Merge branch 'master' into blender2.8
This commit is contained in:
@@ -96,7 +96,7 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg,
|
||||
sd->P = triangle_refine(kg, sd, isect, ray);
|
||||
sd->Ng = Ng;
|
||||
sd->N = Ng;
|
||||
|
||||
|
||||
/* smooth normal */
|
||||
if(sd->shader & SHADER_SMOOTH_NORMAL)
|
||||
sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v);
|
||||
@@ -419,7 +419,7 @@ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *s
|
||||
{
|
||||
/* vectors */
|
||||
sd->P = ray->P;
|
||||
sd->N = -ray->D;
|
||||
sd->N = -ray->D;
|
||||
sd->Ng = -ray->D;
|
||||
sd->I = -ray->D;
|
||||
sd->shader = SHADER_NONE;
|
||||
@@ -428,36 +428,36 @@ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *s
|
||||
sd->time = ray->time;
|
||||
sd->ray_length = 0.0f; /* todo: can we set this to some useful value? */
|
||||
|
||||
#ifdef __INSTANCING__
|
||||
# ifdef __INSTANCING__
|
||||
sd->object = PRIM_NONE; /* todo: fill this for texture coordinates */
|
||||
#endif
|
||||
# endif
|
||||
sd->prim = PRIM_NONE;
|
||||
sd->type = PRIMITIVE_NONE;
|
||||
|
||||
#ifdef __UV__
|
||||
# ifdef __UV__
|
||||
sd->u = 0.0f;
|
||||
sd->v = 0.0f;
|
||||
#endif
|
||||
# endif
|
||||
|
||||
#ifdef __DPDU__
|
||||
# ifdef __DPDU__
|
||||
/* dPdu/dPdv */
|
||||
sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
|
||||
sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
|
||||
#endif
|
||||
# endif
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
# ifdef __RAY_DIFFERENTIALS__
|
||||
/* differentials */
|
||||
sd->dP = ray->dD;
|
||||
differential_incoming(&sd->dI, sd->dP);
|
||||
sd->du = differential_zero();
|
||||
sd->dv = differential_zero();
|
||||
#endif
|
||||
# endif
|
||||
|
||||
/* for NDC coordinates */
|
||||
sd->ray_P = ray->P;
|
||||
sd->ray_dP = ray->dP;
|
||||
}
|
||||
#endif
|
||||
#endif /* __VOLUME__ */
|
||||
|
||||
/* Merging */
|
||||
|
||||
@@ -492,7 +492,7 @@ ccl_device_inline void shader_merge_closures(ShaderData *sd)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* __BRANCHED_PATH__ || __VOLUME__ */
|
||||
|
||||
/* Defensive sampling. */
|
||||
|
||||
@@ -571,7 +571,7 @@ ccl_device_inline void _shader_bsdf_multi_eval_branched(KernelGlobals *kg,
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
|
||||
|
||||
#ifndef __KERNEL_CUDA__
|
||||
@@ -797,7 +797,7 @@ ccl_device float3 shader_bsdf_alpha(KernelGlobals *kg, ShaderData *sd)
|
||||
|
||||
alpha = max(alpha, make_float3(0.0f, 0.0f, 0.0f));
|
||||
alpha = min(alpha, make_float3(1.0f, 1.0f, 1.0f));
|
||||
|
||||
|
||||
return alpha;
|
||||
}
|
||||
|
||||
@@ -919,10 +919,10 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b
|
||||
|
||||
if(texture_blur_)
|
||||
*texture_blur_ = safe_divide(texture_blur, weight_sum);
|
||||
|
||||
|
||||
return eval;
|
||||
}
|
||||
#endif
|
||||
#endif /* __SUBSURFACE__ */
|
||||
|
||||
/* Emission */
|
||||
|
||||
@@ -1001,12 +1001,12 @@ ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd,
|
||||
sd->num_closure_extra = 0;
|
||||
|
||||
#ifdef __SVM__
|
||||
#ifdef __OSL__
|
||||
# ifdef __OSL__
|
||||
if(kg->osl) {
|
||||
OSLShader::eval_background(kg, sd, state, path_flag);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
# endif /* __OSL__ */
|
||||
{
|
||||
svm_eval_nodes(kg, sd, state, SHADER_TYPE_SURFACE, path_flag);
|
||||
}
|
||||
@@ -1021,9 +1021,9 @@ ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd,
|
||||
}
|
||||
|
||||
return eval;
|
||||
#else
|
||||
#else /* __SVM__ */
|
||||
return make_float3(0.8f, 0.8f, 0.8f);
|
||||
#endif
|
||||
#endif /* __SVM__ */
|
||||
}
|
||||
|
||||
/* Volume */
|
||||
@@ -1075,7 +1075,7 @@ ccl_device int shader_volume_phase_sample(KernelGlobals *kg, const ShaderData *s
|
||||
|
||||
for(sampled = 0; sampled < sd->num_closure; sampled++) {
|
||||
const ShaderClosure *sc = &sd->closure[sampled];
|
||||
|
||||
|
||||
if(CLOSURE_IS_PHASE(sc->type))
|
||||
sum += sc->sample_weight;
|
||||
}
|
||||
@@ -1085,7 +1085,7 @@ ccl_device int shader_volume_phase_sample(KernelGlobals *kg, const ShaderData *s
|
||||
|
||||
for(sampled = 0; sampled < sd->num_closure; sampled++) {
|
||||
const ShaderClosure *sc = &sd->closure[sampled];
|
||||
|
||||
|
||||
if(CLOSURE_IS_PHASE(sc->type)) {
|
||||
float next_sum = partial_sum + sc->sample_weight;
|
||||
|
||||
@@ -1191,7 +1191,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* __VOLUME__ */
|
||||
|
||||
/* Displacement Evaluation */
|
||||
|
||||
@@ -1236,7 +1236,6 @@ ccl_device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect
|
||||
|
||||
return (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
|
||||
}
|
||||
#endif
|
||||
#endif /* __TRANSPARENT_SHADOWS__ */
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -476,6 +476,8 @@ typedef enum ClosureType {
|
||||
#define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_BURLEY_ID)
|
||||
#define CLOSURE_IS_BSSRDF(type) (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_BURLEY_ID)
|
||||
#define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
|
||||
#define CLOSURE_IS_VOLUME_SCATTER(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
|
||||
#define CLOSURE_IS_VOLUME_ABSORPTION(type) (type == CLOSURE_VOLUME_ABSORPTION_ID)
|
||||
#define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID)
|
||||
#define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
|
||||
#define CLOSURE_IS_BACKGROUND(type) (type == CLOSURE_BACKGROUND_ID)
|
||||
|
||||
@@ -193,13 +193,8 @@ class BONE_PT_curved(BoneButtonsPanel, Panel):
|
||||
|
||||
sub = row.column(align=True)
|
||||
sub.label("Easing:")
|
||||
if pchan:
|
||||
# XXX: have these also be an overlay?
|
||||
sub.prop(bbone.bone, "bbone_in", text="Ease In")
|
||||
sub.prop(bbone.bone, "bbone_out", text="Ease Out")
|
||||
else:
|
||||
sub.prop(bone, "bbone_in", text="Ease In")
|
||||
sub.prop(bone, "bbone_out", text="Ease Out")
|
||||
sub.prop(bbone, "bbone_easein", text="Ease In")
|
||||
sub.prop(bbone, "bbone_easeout", text="Ease Out")
|
||||
|
||||
if pchan:
|
||||
layout.separator()
|
||||
|
||||
@@ -54,7 +54,7 @@ AbcMBallWriter::AbcMBallWriter(
|
||||
m_is_animated = isAnimated();
|
||||
|
||||
m_mesh_ob = BKE_object_copy(bmain, ob);
|
||||
m_mesh_ob->curve_cache = (CurveCache*)MEM_callocN(
|
||||
m_mesh_ob->curve_cache = (CurveCache *)MEM_callocN(
|
||||
sizeof(CurveCache),
|
||||
"CurveCache for AbcMBallWriter");
|
||||
|
||||
|
||||
@@ -204,10 +204,12 @@ void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, struct BPoint *bp, float r_nor
|
||||
void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, struct BPoint *bp, float r_plane[3]);
|
||||
|
||||
void BKE_nurb_handle_calc(struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next,
|
||||
const bool is_fcurve);
|
||||
const bool is_fcurve, const char smoothing);
|
||||
void BKE_nurb_handle_calc_simple(struct Nurb *nu, struct BezTriple *bezt);
|
||||
void BKE_nurb_handle_calc_simple_auto(struct Nurb *nu, struct BezTriple *bezt);
|
||||
|
||||
void BKE_nurb_handle_smooth_fcurve(struct BezTriple *bezt, int total, bool cyclic);
|
||||
|
||||
void BKE_nurb_handles_calc(struct Nurb *nu);
|
||||
void BKE_nurb_handles_autocalc(struct Nurb *nu, int flag);
|
||||
void BKE_nurb_bezt_handle_test(struct BezTriple *bezt, const bool use_handle);
|
||||
|
||||
@@ -876,6 +876,8 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan
|
||||
pchan->curveInY = chan->curveInY;
|
||||
pchan->curveOutX = chan->curveOutX;
|
||||
pchan->curveOutY = chan->curveOutY;
|
||||
pchan->ease1 = chan->ease1;
|
||||
pchan->ease2 = chan->ease2;
|
||||
pchan->scaleIn = chan->scaleIn;
|
||||
pchan->scaleOut = chan->scaleOut;
|
||||
|
||||
@@ -1367,6 +1369,7 @@ void BKE_pose_rest(bPose *pose)
|
||||
pchan->roll1 = pchan->roll2 = 0.0f;
|
||||
pchan->curveInX = pchan->curveInY = 0.0f;
|
||||
pchan->curveOutX = pchan->curveOutY = 0.0f;
|
||||
pchan->ease1 = pchan->ease2 = 0.0f;
|
||||
pchan->scaleIn = pchan->scaleOut = 1.0f;
|
||||
|
||||
pchan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE | POSE_BBONE_SHAPE);
|
||||
@@ -1410,6 +1413,8 @@ bool BKE_pose_copy_result(bPose *to, bPose *from)
|
||||
pchanto->curveInY = pchanfrom->curveInY;
|
||||
pchanto->curveOutX = pchanfrom->curveOutX;
|
||||
pchanto->curveOutY = pchanfrom->curveOutY;
|
||||
pchanto->ease1 = pchanfrom->ease1;
|
||||
pchanto->ease2 = pchanfrom->ease2;
|
||||
pchanto->scaleIn = pchanfrom->scaleIn;
|
||||
pchanto->scaleOut = pchanfrom->scaleOut;
|
||||
|
||||
|
||||
@@ -613,8 +613,10 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
|
||||
{
|
||||
const float circle_factor = length * (cubic_tangent_factor_circle_v3(h1, h2) / 0.75f);
|
||||
|
||||
const float hlength1 = bone->ease1 * circle_factor;
|
||||
const float hlength2 = bone->ease2 * circle_factor;
|
||||
const float combined_ease1 = bone->ease1 + (!rest ? pchan->ease1 : 0.0f);
|
||||
const float combined_ease2 = bone->ease2 + (!rest ? pchan->ease2 : 0.0f);
|
||||
const float hlength1 = combined_ease1 * circle_factor;
|
||||
const float hlength2 = combined_ease2 * circle_factor;
|
||||
|
||||
/* and only now negate h2 */
|
||||
mul_v3_fl(h1, hlength1);
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_ghash.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
|
||||
@@ -1241,8 +1242,9 @@ void BKE_nurb_makeFaces(Nurb *nu, float *coord_array, int rowstride, int resolu,
|
||||
basis += KNOTSV(nu);
|
||||
}
|
||||
u += ustep;
|
||||
if (rowstride != 0)
|
||||
in = (float *) (((unsigned char *) in) + (rowstride - 3 * totv * sizeof(*in)));
|
||||
if (rowstride != 0) {
|
||||
in = (float *)(((unsigned char *)in) + (rowstride - 3 * totv * sizeof(*in)));
|
||||
}
|
||||
}
|
||||
|
||||
/* free */
|
||||
@@ -1685,7 +1687,7 @@ float *BKE_curve_make_orco(const EvaluationContext *eval_ctx, Scene *scene, Obje
|
||||
if (dl->flag & DL_CYCL_V)
|
||||
sizev++;
|
||||
}
|
||||
else if (dl->flag & DL_CYCL_V) {
|
||||
else if (dl->flag & DL_CYCL_V) {
|
||||
sizev++;
|
||||
}
|
||||
|
||||
@@ -1802,7 +1804,7 @@ void BKE_curve_bevel_make(
|
||||
fp[3] = fp[4] = 0.0;
|
||||
fp[5] = cu->ext1;
|
||||
}
|
||||
else if ( (cu->flag & (CU_FRONT | CU_BACK)) == 0 && cu->ext1 == 0.0f) { // we make a full round bevel in that case
|
||||
else if ((cu->flag & (CU_FRONT | CU_BACK)) == 0 && cu->ext1 == 0.0f) { /* we make a full round bevel in that case */
|
||||
nr = 4 + 2 * cu->bevresol;
|
||||
|
||||
dl = MEM_callocN(sizeof(DispList), "makebevelcurve p1");
|
||||
@@ -1834,9 +1836,9 @@ void BKE_curve_bevel_make(
|
||||
|
||||
if ((cu->flag & CU_BACK) || !(cu->flag & CU_FRONT)) {
|
||||
dnr = nr = 2 + cu->bevresol;
|
||||
if ( (cu->flag & (CU_FRONT | CU_BACK)) == 0)
|
||||
if ((cu->flag & (CU_FRONT | CU_BACK)) == 0) {
|
||||
nr = 3 + 2 * cu->bevresol;
|
||||
|
||||
}
|
||||
dl = MEM_callocN(sizeof(DispList), "makebevelcurve p1");
|
||||
dl->verts = MEM_mallocN(nr * sizeof(float[3]), "makebevelcurve p1");
|
||||
BLI_addtail(disp, dl);
|
||||
@@ -1876,7 +1878,7 @@ void BKE_curve_bevel_make(
|
||||
fp[4] = cu->ext2;
|
||||
fp[5] = cu->ext1;
|
||||
|
||||
if ( (cu->flag & (CU_FRONT | CU_BACK)) == 0) {
|
||||
if ((cu->flag & (CU_FRONT | CU_BACK)) == 0) {
|
||||
dl = MEM_dupallocN(dl);
|
||||
dl->verts = MEM_dupallocN(dl->verts);
|
||||
BLI_addtail(disp, dl);
|
||||
@@ -1892,9 +1894,9 @@ void BKE_curve_bevel_make(
|
||||
/* part 3, front */
|
||||
if ((cu->flag & CU_FRONT) || !(cu->flag & CU_BACK)) {
|
||||
dnr = nr = 2 + cu->bevresol;
|
||||
if ( (cu->flag & (CU_FRONT | CU_BACK)) == 0)
|
||||
if ((cu->flag & (CU_FRONT | CU_BACK)) == 0) {
|
||||
nr = 3 + 2 * cu->bevresol;
|
||||
|
||||
}
|
||||
dl = MEM_callocN(sizeof(DispList), "makebevelcurve p3");
|
||||
dl->verts = MEM_mallocN(nr * sizeof(float[3]), "makebevelcurve p3");
|
||||
BLI_addtail(disp, dl);
|
||||
@@ -2112,7 +2114,7 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *
|
||||
if (tilt_array) {
|
||||
if (nu->tilt_interp == KEY_CU_EASE) { /* May as well support for tilt also 2.47 ease interp */
|
||||
*tilt_array = prevbezt->alfa +
|
||||
(bezt->alfa - prevbezt->alfa) * (3.0f * fac * fac - 2.0f * fac * fac * fac);
|
||||
(bezt->alfa - prevbezt->alfa) * (3.0f * fac * fac - 2.0f * fac * fac * fac);
|
||||
}
|
||||
else {
|
||||
key_curve_position_weights(fac, t, nu->tilt_interp);
|
||||
@@ -2128,7 +2130,7 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *
|
||||
* Note! - this only takes the 2 points into account,
|
||||
* giving much more localized results to changes in radius, sometimes you want that */
|
||||
*radius_array = prevbezt->radius +
|
||||
(bezt->radius - prevbezt->radius) * (3.0f * fac * fac - 2.0f * fac * fac * fac);
|
||||
(bezt->radius - prevbezt->radius) * (3.0f * fac * fac - 2.0f * fac * fac * fac);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -2136,8 +2138,9 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *
|
||||
if (tilt_array == NULL || nu->tilt_interp != nu->radius_interp) {
|
||||
key_curve_position_weights(fac, t, nu->radius_interp);
|
||||
}
|
||||
*radius_array = t[0] * pprev->radius + t[1] * prevbezt->radius +
|
||||
t[2] * bezt->radius + t[3] * next->radius;
|
||||
*radius_array =
|
||||
t[0] * pprev->radius + t[1] * prevbezt->radius +
|
||||
t[2] * bezt->radius + t[3] * next->radius;
|
||||
}
|
||||
|
||||
radius_array = POINTER_OFFSET(radius_array, stride);
|
||||
@@ -2145,8 +2148,9 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *
|
||||
|
||||
if (weight_array) {
|
||||
/* basic interpolation for now, could copy tilt interp too */
|
||||
*weight_array = prevbezt->weight +
|
||||
(bezt->weight - prevbezt->weight) * (3.0f * fac * fac - 2.0f * fac * fac * fac);
|
||||
*weight_array =
|
||||
prevbezt->weight +
|
||||
(bezt->weight - prevbezt->weight) * (3.0f * fac * fac - 2.0f * fac * fac * fac);
|
||||
|
||||
weight_array = POINTER_OFFSET(weight_array, stride);
|
||||
}
|
||||
@@ -3139,7 +3143,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
|
||||
|
||||
static void calchandleNurb_intern(
|
||||
BezTriple *bezt, const BezTriple *prev, const BezTriple *next,
|
||||
bool is_fcurve, bool skip_align)
|
||||
bool is_fcurve, bool skip_align, char fcurve_smoothing)
|
||||
{
|
||||
/* defines to avoid confusion */
|
||||
#define p2_h1 ((p2) - 3)
|
||||
@@ -3153,6 +3157,9 @@ static void calchandleNurb_intern(
|
||||
float len_ratio;
|
||||
const float eps = 1e-5;
|
||||
|
||||
/* assume normal handle until we check */
|
||||
bezt->f5 = HD_AUTOTYPE_NORMAL;
|
||||
|
||||
if (bezt->h1 == 0 && bezt->h2 == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -3204,7 +3211,14 @@ static void calchandleNurb_intern(
|
||||
tvec[2] = dvec_b[2] / len_b + dvec_a[2] / len_a;
|
||||
|
||||
if (is_fcurve) {
|
||||
len = tvec[0];
|
||||
if (fcurve_smoothing != FCURVE_SMOOTH_NONE) {
|
||||
/* force the horizontal handle size to be 1/3 of the key interval so that
|
||||
* the X component of the parametric bezier curve is a linear spline */
|
||||
len = 6.0f / 2.5614f;
|
||||
}
|
||||
else {
|
||||
len = tvec[0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
len = len_v3(tvec);
|
||||
@@ -3215,10 +3229,12 @@ static void calchandleNurb_intern(
|
||||
/* only for fcurves */
|
||||
bool leftviolate = false, rightviolate = false;
|
||||
|
||||
if (len_a > 5.0f * len_b)
|
||||
len_a = 5.0f * len_b;
|
||||
if (len_b > 5.0f * len_a)
|
||||
len_b = 5.0f * len_a;
|
||||
if (!is_fcurve || fcurve_smoothing == FCURVE_SMOOTH_NONE) {
|
||||
if (len_a > 5.0f * len_b)
|
||||
len_a = 5.0f * len_b;
|
||||
if (len_b > 5.0f * len_a)
|
||||
len_b = 5.0f * len_a;
|
||||
}
|
||||
|
||||
if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) {
|
||||
len_a /= len;
|
||||
@@ -3229,6 +3245,7 @@ static void calchandleNurb_intern(
|
||||
float ydiff2 = next->vec[1][1] - bezt->vec[1][1];
|
||||
if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f)) {
|
||||
bezt->vec[0][1] = bezt->vec[1][1];
|
||||
bezt->f5 = HD_AUTOTYPE_SPECIAL;
|
||||
}
|
||||
else { /* handles should not be beyond y coord of two others */
|
||||
if (ydiff1 <= 0.0f) {
|
||||
@@ -3253,8 +3270,9 @@ static void calchandleNurb_intern(
|
||||
if ((bezt->h2 == HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */
|
||||
float ydiff1 = prev->vec[1][1] - bezt->vec[1][1];
|
||||
float ydiff2 = next->vec[1][1] - bezt->vec[1][1];
|
||||
if ( (ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f) ) {
|
||||
if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f)) {
|
||||
bezt->vec[2][1] = bezt->vec[1][1];
|
||||
bezt->f5 = HD_AUTOTYPE_SPECIAL;
|
||||
}
|
||||
else { /* handles should not be beyond y coord of two others */
|
||||
if (ydiff1 <= 0.0f) {
|
||||
@@ -3402,7 +3420,7 @@ static void calchandlesNurb_intern(Nurb *nu, bool skip_align)
|
||||
next = bezt + 1;
|
||||
|
||||
while (a--) {
|
||||
calchandleNurb_intern(bezt, prev, next, 0, skip_align);
|
||||
calchandleNurb_intern(bezt, prev, next, 0, skip_align, 0);
|
||||
prev = bezt;
|
||||
if (a == 1) {
|
||||
if (nu->flagu & CU_NURB_CYCLIC)
|
||||
@@ -3417,9 +3435,540 @@ static void calchandlesNurb_intern(Nurb *nu, bool skip_align)
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_nurb_handle_calc(BezTriple *bezt, BezTriple *prev, BezTriple *next, const bool is_fcurve)
|
||||
/* A utility function for allocating a number of arrays of the same length
|
||||
* with easy error checking and deallocation, and an easy way to add or remove
|
||||
* arrays that are processed in this way when changing code.
|
||||
*
|
||||
* floats, chars: NULL-terminated arrays of pointers to array pointers that need to be allocated.
|
||||
*
|
||||
* Returns: pointer to the buffer that contains all of the arrays.
|
||||
*/
|
||||
static void *allocate_arrays(int count, float ***floats, char ***chars, const char *name)
|
||||
{
|
||||
calchandleNurb_intern(bezt, prev, next, is_fcurve, false);
|
||||
int num_floats = 0, num_chars = 0;
|
||||
|
||||
while (floats && floats[num_floats]) {
|
||||
num_floats++;
|
||||
}
|
||||
|
||||
while (chars && chars[num_chars]) {
|
||||
num_chars++;
|
||||
}
|
||||
|
||||
void *buffer = (float *)MEM_mallocN(count * (sizeof(float) * num_floats + num_chars), name);
|
||||
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
float *fptr = buffer;
|
||||
|
||||
for (int i = 0; i < num_floats; i++, fptr += count) {
|
||||
*floats[i] = fptr;
|
||||
}
|
||||
|
||||
char *cptr = (char *)fptr;
|
||||
|
||||
for (int i = 0; i < num_chars; i++, cptr += count) {
|
||||
*chars[i] = cptr;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void free_arrays(void *buffer)
|
||||
{
|
||||
MEM_freeN(buffer);
|
||||
}
|
||||
|
||||
/* computes in which direction to change h[i] to satisfy conditions better */
|
||||
static float bezier_relax_direction(float *a, float *b, float *c, float *d, float *h, int i, int count)
|
||||
{
|
||||
/* current deviation between sides of the equation */
|
||||
float state = a[i] * h[(i + count - 1) % count] +
|
||||
b[i] * h[i] +
|
||||
c[i] * h[(i + 1) % count] -
|
||||
d[i];
|
||||
|
||||
/* only the sign is meaningful */
|
||||
return -state * b[i];
|
||||
}
|
||||
|
||||
static void bezier_lock_unknown(float *a, float *b, float *c, float *d, int i, float value)
|
||||
{
|
||||
a[i] = c[i] = 0.0f;
|
||||
b[i] = 1.0f;
|
||||
d[i] = value;
|
||||
}
|
||||
|
||||
static void bezier_restore_equation(float *a, float *b, float *c, float *d, float *a0, float *b0, float *c0, float *d0, int i)
|
||||
{
|
||||
a[i] = a0[i];
|
||||
b[i] = b0[i];
|
||||
c[i] = c0[i];
|
||||
d[i] = d0[i];
|
||||
}
|
||||
|
||||
static bool tridiagonal_solve_with_limits(float *a, float *b, float *c, float *d, float *h, float *hmin, float *hmax, int solve_count)
|
||||
{
|
||||
float *a0, *b0, *c0, *d0;
|
||||
float **arrays[] = { &a0, &b0, &c0, &d0, NULL };
|
||||
char *is_locked, *num_unlocks;
|
||||
char **flagarrays[] = { &is_locked, &num_unlocks, NULL };
|
||||
|
||||
void *tmps = allocate_arrays(solve_count, arrays, flagarrays, "tridiagonal_solve_with_limits");
|
||||
if (!tmps)
|
||||
return false;
|
||||
|
||||
memcpy(a0, a, sizeof(float) * solve_count);
|
||||
memcpy(b0, b, sizeof(float) * solve_count);
|
||||
memcpy(c0, c, sizeof(float) * solve_count);
|
||||
memcpy(d0, d, sizeof(float) * solve_count);
|
||||
|
||||
memset(is_locked, 0, solve_count);
|
||||
memset(num_unlocks, 0, solve_count);
|
||||
|
||||
bool overshoot, unlocked;
|
||||
|
||||
do {
|
||||
if (!BLI_tridiagonal_solve_cyclic(a, b, c, d, h, solve_count)) {
|
||||
free_arrays(tmps);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* first check if any handles overshoot the limits, and lock them */
|
||||
bool all = false, locked = false;
|
||||
|
||||
overshoot = unlocked = false;
|
||||
|
||||
do {
|
||||
for (int i = 0; i < solve_count; i++) {
|
||||
if (h[i] >= hmin[i] && h[i] <= hmax[i])
|
||||
continue;
|
||||
|
||||
overshoot = true;
|
||||
|
||||
float target = h[i] > hmax[i] ? hmax[i] : hmin[i];
|
||||
|
||||
/* heuristically only lock handles that go in the right direction if there are such ones */
|
||||
if (target != 0.0f || all) {
|
||||
/* mark item locked */
|
||||
is_locked[i] = 1;
|
||||
|
||||
bezier_lock_unknown(a, b, c, d, i, target);
|
||||
locked = true;
|
||||
}
|
||||
}
|
||||
|
||||
all = true;
|
||||
} while (overshoot && !locked);
|
||||
|
||||
/* if no handles overshot and were locked, see if it may be a good idea to unlock some handles */
|
||||
if (!locked) {
|
||||
for (int i = 0; i < solve_count; i++) {
|
||||
// to definitely avoid infinite loops limit this to 2 times
|
||||
if (!is_locked[i] || num_unlocks[i] >= 2)
|
||||
continue;
|
||||
|
||||
/* if the handle wants to move in allowable direction, release it */
|
||||
float relax = bezier_relax_direction(a0, b0, c0, d0, h, i, solve_count);
|
||||
|
||||
if ((relax > 0 && h[i] < hmax[i]) || (relax < 0 && h[i] > hmin[i])) {
|
||||
bezier_restore_equation(a, b, c, d, a0, b0, c0, d0, i);
|
||||
|
||||
is_locked[i] = 0;
|
||||
num_unlocks[i]++;
|
||||
unlocked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (overshoot || unlocked);
|
||||
|
||||
free_arrays(tmps);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function computes the handles of a series of auto bezier points
|
||||
* on the basis of 'no acceleration discontinuities' at the points.
|
||||
* The first and last bezier points are considered 'fixed' (their handles are not touched)
|
||||
* The result is the smoothest possible trajectory going through intemediate points.
|
||||
* The difficulty is that the handles depends on their neighbours.
|
||||
*
|
||||
* The exact solution is found by solving a tridiagonal matrix equation formed
|
||||
* by the continuity and boundary conditions. Although theoretically handle position
|
||||
* is affected by all other points of the curve segment, in practice the influence
|
||||
* decreases exponentially with distance.
|
||||
*
|
||||
* Note: this algorithm assumes that the handle horizontal size if always 1/3 of the
|
||||
* of the interval to the next point. This rule ensures linear interpolation of time.
|
||||
*
|
||||
* ^ height (co 1)
|
||||
* | yN
|
||||
* | yN-1 |
|
||||
* | y2 | |
|
||||
* | y1 | | |
|
||||
* | y0 | | | |
|
||||
* | | | | | |
|
||||
* | | | | | |
|
||||
* | | | | | |
|
||||
* |-------t1---------t2--------- ~ --------tN-------------------> time (co 0)
|
||||
*
|
||||
*
|
||||
* Mathematical basis:
|
||||
*
|
||||
* 1. Handle lengths on either side of each point are connected by a factor
|
||||
* ensuring continuity of the first derivative:
|
||||
*
|
||||
* l[i] = t[i+1]/t[i]
|
||||
*
|
||||
* 2. The tridiagonal system is formed by the following equation, which is derived
|
||||
* by differentiating the bezier curve and specifies second derivative continuity
|
||||
* at every point:
|
||||
*
|
||||
* l[i]^2 * h[i-1] + (2*l[i]+2) * h[i] + 1/l[i+1] * h[i+1] = (y[i]-y[i-1])*l[i]^2 + y[i+1]-y[i]
|
||||
*
|
||||
* 3. If this point is adjacent to a manually set handle with X size not equal to 1/3
|
||||
* of the horizontal interval, this equation becomes slightly more complex:
|
||||
*
|
||||
* l[i]^2 * h[i-1] + (3*(1-R[i-1])*l[i] + 3*(1-L[i+1])) * h[i] + 1/l[i+1] * h[i+1] = (y[i]-y[i-1])*l[i]^2 + y[i+1]-y[i]
|
||||
*
|
||||
* The difference between equations amounts to this, and it's obvious that when R[i-1]
|
||||
* and L[i+1] are both 1/3, it becomes zero:
|
||||
*
|
||||
* ( (1-3*R[i-1])*l[i] + (1-3*L[i+1]) ) * h[i]
|
||||
*
|
||||
* 4. The equations for zero acceleration border conditions are basically the above
|
||||
* equation with parts omitted, so the handle size correction also applies.
|
||||
*/
|
||||
|
||||
|
||||
static void bezier_eq_continuous(float *a, float *b, float *c, float *d, float *dy, float *l, int i)
|
||||
{
|
||||
a[i] = l[i] * l[i];
|
||||
b[i] = 2.0f * (l[i] + 1);
|
||||
c[i] = 1.0f / l[i + 1];
|
||||
d[i] = dy[i] * l[i] * l[i] + dy[i + 1];
|
||||
}
|
||||
|
||||
static void bezier_eq_noaccel_right(float *a, float *b, float *c, float *d, float *dy, float *l, int i)
|
||||
{
|
||||
a[i] = 0.0f;
|
||||
b[i] = 2.0f;
|
||||
c[i] = 1.0f / l[i + 1];
|
||||
d[i] = dy[i + 1];
|
||||
}
|
||||
|
||||
static void bezier_eq_noaccel_left(float *a, float *b, float *c, float *d, float *dy, float *l, int i)
|
||||
{
|
||||
a[i] = l[i] * l[i];
|
||||
b[i] = 2.0f * l[i];
|
||||
c[i] = 0.0f;
|
||||
d[i] = dy[i] * l[i] * l[i];
|
||||
}
|
||||
|
||||
/* auto clamp prevents its own point going the wrong way, and adjacent handles overshooting */
|
||||
static void bezier_clamp(float *hmax, float *hmin, int i, float dy, bool no_reverse, bool no_overshoot)
|
||||
{
|
||||
if (dy > 0) {
|
||||
if (no_overshoot)
|
||||
hmax[i] = min_ff(hmax[i], dy);
|
||||
if (no_reverse)
|
||||
hmin[i] = 0.0f;
|
||||
}
|
||||
else if (dy < 0) {
|
||||
if (no_reverse)
|
||||
hmax[i] = 0.0f;
|
||||
if (no_overshoot)
|
||||
hmin[i] = max_ff(hmin[i], dy);
|
||||
}
|
||||
else if (no_reverse || no_overshoot) {
|
||||
hmax[i] = hmin[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* write changes to a bezier handle */
|
||||
static void bezier_output_handle_inner(BezTriple *bezt, bool right, float newval[3], bool endpoint)
|
||||
{
|
||||
float tmp[3];
|
||||
|
||||
int idx = right ? 2 : 0;
|
||||
char hr = right ? bezt->h2 : bezt->h1;
|
||||
char hm = right ? bezt->h1 : bezt->h2;
|
||||
|
||||
/* only assign Auto/Vector handles */
|
||||
if (!ELEM(hr, HD_AUTO, HD_AUTO_ANIM, HD_VECT))
|
||||
return;
|
||||
|
||||
copy_v3_v3(bezt->vec[idx], newval);
|
||||
|
||||
/* fix up the Align handle if any */
|
||||
if (ELEM(hm, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) {
|
||||
float hlen = len_v3v3(bezt->vec[1], bezt->vec[2 - idx]);
|
||||
float h2len = len_v3v3(bezt->vec[1], bezt->vec[idx]);
|
||||
|
||||
sub_v3_v3v3(tmp, bezt->vec[1], bezt->vec[idx]);
|
||||
madd_v3_v3v3fl(bezt->vec[2 - idx], bezt->vec[1], tmp, hlen / h2len);
|
||||
}
|
||||
/* at end points of the curve, mirror handle to the other side */
|
||||
else if (endpoint && ELEM(hm, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) {
|
||||
sub_v3_v3v3(tmp, bezt->vec[1], bezt->vec[idx]);
|
||||
add_v3_v3v3(bezt->vec[2 - idx], bezt->vec[1], tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static void bezier_output_handle(BezTriple *bezt, bool right, float dy, bool endpoint)
|
||||
{
|
||||
float tmp[3];
|
||||
|
||||
copy_v3_v3(tmp, bezt->vec[right ? 2 : 0]);
|
||||
|
||||
tmp[1] = bezt->vec[1][1] + dy;
|
||||
|
||||
bezier_output_handle_inner(bezt, right, tmp, endpoint);
|
||||
}
|
||||
|
||||
static bool bezier_check_solve_end_handle(BezTriple *bezt, char htype, bool end)
|
||||
{
|
||||
return (htype == HD_VECT) || (end && ELEM(htype, HD_AUTO, HD_AUTO_ANIM) && bezt->f5 == HD_AUTOTYPE_NORMAL);
|
||||
}
|
||||
|
||||
static float bezier_calc_handle_adj(float hsize[2], float dx)
|
||||
{
|
||||
/* if handles intersect in x direction, they are scaled to fit */
|
||||
float fac = dx / (hsize[0] + dx / 3.0f);
|
||||
if (fac < 1.0f) {
|
||||
mul_v2_fl(hsize, fac);
|
||||
}
|
||||
return 1.0f - 3.0f * hsize[0] / dx;
|
||||
}
|
||||
|
||||
static void bezier_handle_calc_smooth_fcurve(BezTriple *bezt, int total, int start, int count, bool cycle)
|
||||
{
|
||||
float *dx, *dy, *l, *a, *b, *c, *d, *h, *hmax, *hmin;
|
||||
float **arrays[] = { &dx, &dy, &l, &a, &b, &c, &d, &h, &hmax, &hmin, NULL };
|
||||
|
||||
int solve_count = count;
|
||||
|
||||
/* verify index ranges */
|
||||
|
||||
if (count < 2)
|
||||
return;
|
||||
|
||||
BLI_assert(start < total - 1 && count <= total);
|
||||
BLI_assert(start + count <= total || cycle);
|
||||
|
||||
bool full_cycle = (start == 0 && count == total && cycle);
|
||||
|
||||
BezTriple *bezt_first = &bezt[start];
|
||||
BezTriple *bezt_last = &bezt[(start + count > total) ? start + count - total : start + count - 1];
|
||||
|
||||
bool solve_first = bezier_check_solve_end_handle(bezt_first, bezt_first->h2, start == 0);
|
||||
bool solve_last = bezier_check_solve_end_handle(bezt_last, bezt_last->h1, start + count == total);
|
||||
|
||||
if (count == 2 && !full_cycle && solve_first == solve_last) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* allocate all */
|
||||
|
||||
void *tmp_buffer = allocate_arrays(count, arrays, NULL, "bezier_calc_smooth_tmp");
|
||||
if (!tmp_buffer)
|
||||
return;
|
||||
|
||||
/* point locations */
|
||||
|
||||
dx[0] = dy[0] = NAN_FLT;
|
||||
|
||||
for (int i = 1, j = start + 1; i < count; i++, j++) {
|
||||
dx[i] = bezt[j].vec[1][0] - bezt[j - 1].vec[1][0];
|
||||
dy[i] = bezt[j].vec[1][1] - bezt[j - 1].vec[1][1];
|
||||
|
||||
/* when cyclic, jump from last point to first */
|
||||
if (cycle && j == total - 1)
|
||||
j = 0;
|
||||
}
|
||||
|
||||
/* ratio of x intervals */
|
||||
|
||||
l[0] = l[count - 1] = 1.0f;
|
||||
|
||||
for (int i = 1; i < count - 1; i++) {
|
||||
l[i] = dx[i + 1] / dx[i];
|
||||
}
|
||||
|
||||
/* compute handle clamp ranges */
|
||||
|
||||
bool clamped_prev = false, clamped_cur = ELEM(HD_AUTO_ANIM, bezt_first->h1, bezt_first->h2);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
hmax[i] = FLT_MAX;
|
||||
hmin[i] = -FLT_MAX;
|
||||
}
|
||||
|
||||
for (int i = 1, j = start + 1; i < count; i++, j++) {
|
||||
clamped_prev = clamped_cur;
|
||||
clamped_cur = ELEM(HD_AUTO_ANIM, bezt[j].h1, bezt[j].h2);
|
||||
|
||||
if (cycle && j == total - 1) {
|
||||
j = 0;
|
||||
clamped_cur = clamped_cur || ELEM(HD_AUTO_ANIM, bezt[j].h1, bezt[j].h2);
|
||||
}
|
||||
|
||||
bezier_clamp(hmax, hmin, i - 1, dy[i], clamped_prev, clamped_prev);
|
||||
bezier_clamp(hmax, hmin, i, dy[i] * l[i], clamped_cur, clamped_cur);
|
||||
}
|
||||
|
||||
/* full cycle merges first and last points into continuous loop */
|
||||
|
||||
float first_handle_adj = 0.0f, last_handle_adj = 0.0f;
|
||||
|
||||
if (full_cycle) {
|
||||
/* reduce the number of uknowns by one */
|
||||
int i = solve_count = count - 1;
|
||||
|
||||
dx[0] = dx[i];
|
||||
dy[0] = dy[i];
|
||||
|
||||
l[0] = l[i] = dx[1] / dx[0];
|
||||
|
||||
hmin[0] = max_ff(hmin[0], hmin[i]);
|
||||
hmax[0] = min_ff(hmax[0], hmax[i]);
|
||||
|
||||
solve_first = solve_last = true;
|
||||
|
||||
bezier_eq_continuous(a, b, c, d, dy, l, 0);
|
||||
}
|
||||
else {
|
||||
float tmp[2];
|
||||
|
||||
/* boundary condition: fixed handles or zero curvature */
|
||||
if (!solve_first) {
|
||||
sub_v2_v2v2(tmp, bezt_first->vec[2], bezt_first->vec[1]);
|
||||
first_handle_adj = bezier_calc_handle_adj(tmp, dx[1]);
|
||||
|
||||
bezier_lock_unknown(a, b, c, d, 0, tmp[1]);
|
||||
}
|
||||
else {
|
||||
bezier_eq_noaccel_right(a, b, c, d, dy, l, 0);
|
||||
}
|
||||
|
||||
if (!solve_last) {
|
||||
sub_v2_v2v2(tmp, bezt_last->vec[1], bezt_last->vec[0]);
|
||||
last_handle_adj = bezier_calc_handle_adj(tmp, dx[count - 1]);
|
||||
|
||||
bezier_lock_unknown(a, b, c, d, count - 1, tmp[1]);
|
||||
}
|
||||
else {
|
||||
bezier_eq_noaccel_left(a, b, c, d, dy, l, count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* main tridiagonal system of equations */
|
||||
|
||||
for (int i = 1; i < count - 1; i++) {
|
||||
bezier_eq_continuous(a, b, c, d, dy, l, i);
|
||||
}
|
||||
|
||||
/* apply correction for user-defined handles with nonstandard x positions */
|
||||
|
||||
if (!full_cycle) {
|
||||
if (count > 2 || solve_last) {
|
||||
b[1] += l[1] * first_handle_adj;
|
||||
}
|
||||
|
||||
if (count > 2 || solve_first) {
|
||||
b[count - 2] += last_handle_adj;
|
||||
}
|
||||
}
|
||||
|
||||
/* solve and output results */
|
||||
|
||||
if (tridiagonal_solve_with_limits(a, b, c, d, h, hmin, hmax, solve_count)) {
|
||||
if (full_cycle) {
|
||||
h[count - 1] = h[0];
|
||||
}
|
||||
|
||||
for (int i = 1, j = start + 1; i < count - 1; i++, j++) {
|
||||
bool end = (j == total - 1);
|
||||
|
||||
bezier_output_handle(&bezt[j], false, -h[i] / l[i], end);
|
||||
|
||||
if (end)
|
||||
j = 0;
|
||||
|
||||
bezier_output_handle(&bezt[j], true, h[i], end);
|
||||
}
|
||||
|
||||
if (solve_first) {
|
||||
bezier_output_handle(bezt_first, true, h[0], start == 0);
|
||||
}
|
||||
|
||||
if (solve_last) {
|
||||
bezier_output_handle(bezt_last, false, -h[count - 1] / l[count - 1], start + count == total);
|
||||
}
|
||||
}
|
||||
|
||||
/* free all */
|
||||
|
||||
free_arrays(tmp_buffer);
|
||||
}
|
||||
|
||||
static bool is_free_auto_point(BezTriple *bezt)
|
||||
{
|
||||
return BEZT_IS_AUTOH(bezt) && bezt->f5 == HD_AUTOTYPE_NORMAL;
|
||||
}
|
||||
|
||||
void BKE_nurb_handle_smooth_fcurve(BezTriple *bezt, int total, bool cycle)
|
||||
{
|
||||
/* ignore cyclic extrapolation if end points are locked */
|
||||
cycle = cycle && is_free_auto_point(&bezt[0]) && is_free_auto_point(&bezt[total - 1]);
|
||||
|
||||
/* if cyclic, try to find a sequence break point */
|
||||
int search_base = 0;
|
||||
|
||||
if (cycle) {
|
||||
for (int i = 1; i < total - 1; i++) {
|
||||
if (!is_free_auto_point(&bezt[i])) {
|
||||
search_base = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* all points of the curve are freely changeable auto handles - solve as full cycle */
|
||||
if (search_base == 0) {
|
||||
bezier_handle_calc_smooth_fcurve(bezt, total, 0, total, cycle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find continuous subsequences of free auto handles and smooth them, starting at
|
||||
* search_base. In cyclic mode these subsequences can span the cycle boundary. */
|
||||
int start = search_base, count = 1;
|
||||
|
||||
for (int i = 1, j = start + 1; i < total; i++, j++) {
|
||||
/* in cyclic mode: jump from last to first point when necessary */
|
||||
if (j == total - 1 && cycle)
|
||||
j = 0;
|
||||
|
||||
/* non auto handle closes the list (we come here at least for the last handle, see above) */
|
||||
if (!is_free_auto_point(&bezt[j])) {
|
||||
bezier_handle_calc_smooth_fcurve(bezt, total, start, count + 1, cycle);
|
||||
start = j;
|
||||
count = 1;
|
||||
}
|
||||
else {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 1) {
|
||||
bezier_handle_calc_smooth_fcurve(bezt, total, start, count, cycle);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_nurb_handle_calc(BezTriple *bezt, BezTriple *prev, BezTriple *next, const bool is_fcurve, const char smoothing)
|
||||
{
|
||||
calchandleNurb_intern(bezt, prev, next, is_fcurve, false, smoothing);
|
||||
}
|
||||
|
||||
void BKE_nurb_handles_calc(Nurb *nu) /* first, if needed, set handle flags */
|
||||
@@ -3459,7 +4008,7 @@ void BKE_nurb_handle_calc_simple(Nurb *nu, BezTriple *bezt)
|
||||
if (nu->pntsu > 1) {
|
||||
BezTriple *prev = BKE_nurb_bezt_get_prev(nu, bezt);
|
||||
BezTriple *next = BKE_nurb_bezt_get_next(nu, bezt);
|
||||
BKE_nurb_handle_calc(bezt, prev, next, 0);
|
||||
BKE_nurb_handle_calc(bezt, prev, next, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3566,7 +4115,7 @@ void BKE_nurb_handles_autocalc(Nurb *nu, int flag)
|
||||
bool align = false, leftsmall = false, rightsmall = false;
|
||||
|
||||
/* left handle: */
|
||||
if (flag == 0 || (bezt1->f1 & flag) ) {
|
||||
if (flag == 0 || (bezt1->f1 & flag)) {
|
||||
bezt1->h1 = HD_FREE;
|
||||
/* distance too short: vectorhandle */
|
||||
if (len_squared_v3v3(bezt1->vec[1], bezt0->vec[1]) < eps_sq) {
|
||||
@@ -3585,7 +4134,7 @@ void BKE_nurb_handles_autocalc(Nurb *nu, int flag)
|
||||
}
|
||||
}
|
||||
/* right handle: */
|
||||
if (flag == 0 || (bezt1->f3 & flag) ) {
|
||||
if (flag == 0 || (bezt1->f3 & flag)) {
|
||||
bezt1->h2 = HD_FREE;
|
||||
/* distance too short: vectorhandle */
|
||||
if (len_squared_v3v3(bezt1->vec[1], bezt2->vec[1]) < eps_sq) {
|
||||
|
||||
@@ -896,7 +896,7 @@ bool BKE_fcurve_is_cyclic(FCurve *fcu)
|
||||
if (fcm->flag & (FMODIFIER_FLAG_RANGERESTRICT | FMODIFIER_FLAG_USEINFLUENCE))
|
||||
return false;
|
||||
|
||||
FMod_Cycles *data = (FMod_Cycles*)fcm->data;
|
||||
FMod_Cycles *data = (FMod_Cycles *)fcm->data;
|
||||
|
||||
return data && data->after_cycles == 0 && data->before_cycles == 0 &&
|
||||
ELEM(data->before_mode, FCM_EXTRAPOLATE_CYCLIC, FCM_EXTRAPOLATE_CYCLIC_OFFSET) &&
|
||||
@@ -939,14 +939,14 @@ void calchandles_fcurve(FCurve *fcu)
|
||||
return;
|
||||
|
||||
/* if the first modifier is Cycles, smooth the curve through the cycle */
|
||||
BezTriple *first = &fcu->bezt[0], *last = &fcu->bezt[fcu->totvert-1];
|
||||
BezTriple *first = &fcu->bezt[0], *last = &fcu->bezt[fcu->totvert - 1];
|
||||
BezTriple tmp;
|
||||
|
||||
bool cycle = BKE_fcurve_is_cyclic(fcu) && BEZT_IS_AUTOH(first) && BEZT_IS_AUTOH(last);
|
||||
|
||||
/* get initial pointers */
|
||||
bezt = fcu->bezt;
|
||||
prev = cycle_offset_triple(cycle, &tmp, &fcu->bezt[fcu->totvert-2], last, first);
|
||||
prev = cycle_offset_triple(cycle, &tmp, &fcu->bezt[fcu->totvert - 2], last, first);
|
||||
next = (bezt + 1);
|
||||
|
||||
/* loop over all beztriples, adjusting handles */
|
||||
@@ -956,7 +956,7 @@ void calchandles_fcurve(FCurve *fcu)
|
||||
if (bezt->vec[2][0] < bezt->vec[1][0]) bezt->vec[2][0] = bezt->vec[1][0];
|
||||
|
||||
/* calculate auto-handles */
|
||||
BKE_nurb_handle_calc(bezt, prev, next, true);
|
||||
BKE_nurb_handle_calc(bezt, prev, next, true, fcu->auto_smoothing);
|
||||
|
||||
/* for automatic ease in and out */
|
||||
if (BEZT_IS_AUTOH(bezt) && !cycle) {
|
||||
@@ -965,9 +965,16 @@ void calchandles_fcurve(FCurve *fcu)
|
||||
/* set both handles to have same horizontal value as keyframe */
|
||||
if (fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) {
|
||||
bezt->vec[0][1] = bezt->vec[2][1] = bezt->vec[1][1];
|
||||
/* remember that these keyframes are special, they don't need to be adjusted */
|
||||
bezt->f5 = HD_AUTOTYPE_SPECIAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* avoid total smoothing failure on duplicate keyframes (can happen during grab) */
|
||||
if (prev && prev->vec[1][0] >= bezt->vec[1][0]) {
|
||||
prev->f5 = bezt->f5 = HD_AUTOTYPE_SPECIAL;
|
||||
}
|
||||
|
||||
/* advance pointers for next iteration */
|
||||
prev = bezt;
|
||||
@@ -981,6 +988,18 @@ void calchandles_fcurve(FCurve *fcu)
|
||||
|
||||
bezt++;
|
||||
}
|
||||
|
||||
/* if cyclic extrapolation and Auto Clamp has triggered, ensure it is symmetric */
|
||||
if (cycle && (first->f5 != HD_AUTOTYPE_NORMAL || last->f5 != HD_AUTOTYPE_NORMAL)) {
|
||||
first->vec[0][1] = first->vec[2][1] = first->vec[1][1];
|
||||
last->vec[0][1] = last->vec[2][1] = last->vec[1][1];
|
||||
first->f5 = last->f5 = HD_AUTOTYPE_SPECIAL;
|
||||
}
|
||||
|
||||
/* do a second pass for auto handle: compute the handle to have 0 accelaration step */
|
||||
if (fcu->auto_smoothing != FCURVE_SMOOTH_NONE) {
|
||||
BKE_nurb_handle_smooth_fcurve(fcu->bezt, fcu->totvert, cycle);
|
||||
}
|
||||
}
|
||||
|
||||
void testhandles_fcurve(FCurve *fcu, const bool use_handle)
|
||||
|
||||
@@ -1197,14 +1197,14 @@ static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *poin
|
||||
|
||||
#if 1
|
||||
if (bezt_prev || bezt_next) {
|
||||
BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, 0);
|
||||
BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, 0, 0);
|
||||
}
|
||||
#else
|
||||
if (handle_type == HD_VECT) {
|
||||
BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, 0);
|
||||
BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, 0, 0);
|
||||
}
|
||||
else if (handle_type == HD_AUTO) {
|
||||
BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, 0);
|
||||
BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, 0, 0);
|
||||
}
|
||||
else if (handle_type == HD_ALIGN || handle_type == HD_ALIGN_DOUBLESIDE) {
|
||||
float v1[3], v2[3];
|
||||
|
||||
@@ -1387,6 +1387,7 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
|
||||
|
||||
/* set default flags */
|
||||
fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
|
||||
fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
|
||||
|
||||
/* store path - make copy, and store that */
|
||||
fcu->rna_path = BLI_strdupn("influence", 9);
|
||||
@@ -1408,6 +1409,7 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
|
||||
|
||||
/* set default flags */
|
||||
fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
|
||||
fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
|
||||
|
||||
/* store path - make copy, and store that */
|
||||
fcu->rna_path = BLI_strdupn("strip_time", 10);
|
||||
|
||||
@@ -48,6 +48,11 @@ bool BLI_eigen_solve_selfadjoint_m3(const float m3[3][3], float r_eigen_values[3
|
||||
|
||||
void BLI_svd_m3(const float m3[3][3], float r_U[3][3], float r_S[], float r_V[3][3]);
|
||||
|
||||
/***************************** Simple Solvers ************************************/
|
||||
|
||||
bool BLI_tridiagonal_solve(const float *a, const float *b, const float *c, const float *d, float *r_x, const int count);
|
||||
bool BLI_tridiagonal_solve_cyclic(const float *a, const float *b, const float *c, const float *d, float *r_x, const int count);
|
||||
|
||||
/**************************** Inline Definitions ******************************/
|
||||
#if 0 /* None so far. */
|
||||
# if BLI_MATH_DO_INLINE
|
||||
|
||||
@@ -72,3 +72,111 @@ void BLI_svd_m3(const float m3[3][3], float r_U[3][3], float r_S[3], float r_V[3
|
||||
{
|
||||
EIG_svd_square_matrix(3, (const float *)m3, (float *)r_U, (float *)r_S, (float *)r_V);
|
||||
}
|
||||
|
||||
/***************************** Simple Solvers ************************************/
|
||||
|
||||
/**
|
||||
* \brief Solve a tridiagonal system of equations:
|
||||
*
|
||||
* a[i] * r_x[i-1] + b[i] * r_x[i] + c[i] * r_x[i+1] = d[i]
|
||||
*
|
||||
* Ignores a[0] and c[count-1]. Uses the Thomas algorithm, e.g. see wiki.
|
||||
*
|
||||
* \param r_x output vector, may be shared with any of the input ones
|
||||
* \return true if success
|
||||
*/
|
||||
bool BLI_tridiagonal_solve(const float *a, const float *b, const float *c, const float *d, float *r_x, const int count)
|
||||
{
|
||||
if (count < 1)
|
||||
return false;
|
||||
|
||||
size_t bytes = sizeof(double) * (unsigned)count;
|
||||
double *c1 = (double *)MEM_mallocN(bytes * 2, "tridiagonal_c1d1");
|
||||
double *d1 = c1 + count;
|
||||
|
||||
if (!c1)
|
||||
return false;
|
||||
|
||||
int i;
|
||||
double c_prev, d_prev, x_prev;
|
||||
|
||||
/* forward pass */
|
||||
|
||||
c1[0] = c_prev = ((double)c[0]) / b[0];
|
||||
d1[0] = d_prev = ((double)d[0]) / b[0];
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
double denum = b[i] - a[i] * c_prev;
|
||||
|
||||
c1[i] = c_prev = c[i] / denum;
|
||||
d1[i] = d_prev = (d[i] - a[i] * d_prev) / denum;
|
||||
}
|
||||
|
||||
/* back pass */
|
||||
|
||||
x_prev = d_prev;
|
||||
r_x[--i] = ((float)x_prev);
|
||||
|
||||
while (--i >= 0) {
|
||||
x_prev = d1[i] - c1[i] * x_prev;
|
||||
r_x[i] = ((float)x_prev);
|
||||
}
|
||||
|
||||
MEM_freeN(c1);
|
||||
|
||||
return isfinite(x_prev);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Solve a possibly cyclic tridiagonal system using the Sherman-Morrison formula.
|
||||
*
|
||||
* \param r_x output vector, may be shared with any of the input ones
|
||||
* \return true if success
|
||||
*/
|
||||
bool BLI_tridiagonal_solve_cyclic(const float *a, const float *b, const float *c, const float *d, float *r_x, const int count)
|
||||
{
|
||||
if (count < 1)
|
||||
return false;
|
||||
|
||||
float a0 = a[0], cN = c[count - 1];
|
||||
|
||||
/* if not really cyclic, fall back to the simple solver */
|
||||
if (a0 == 0.0f && cN == 0.0f) {
|
||||
return BLI_tridiagonal_solve(a, b, c, d, r_x, count);
|
||||
}
|
||||
|
||||
size_t bytes = sizeof(float) * (unsigned)count;
|
||||
float *tmp = (float *)MEM_mallocN(bytes * 2, "tridiagonal_ex");
|
||||
float *b2 = tmp + count;
|
||||
|
||||
if (!tmp)
|
||||
return false;
|
||||
|
||||
/* prepare the noncyclic system; relies on tridiagonal_solve ignoring values */
|
||||
memcpy(b2, b, bytes);
|
||||
b2[0] -= a0;
|
||||
b2[count - 1] -= cN;
|
||||
|
||||
memset(tmp, 0, bytes);
|
||||
tmp[0] = a0;
|
||||
tmp[count - 1] = cN;
|
||||
|
||||
/* solve for partial solution and adjustment vector */
|
||||
bool success =
|
||||
BLI_tridiagonal_solve(a, b2, c, tmp, tmp, count) &&
|
||||
BLI_tridiagonal_solve(a, b2, c, d, r_x, count);
|
||||
|
||||
/* apply adjustment */
|
||||
if (success) {
|
||||
float coeff = (r_x[0] + r_x[count - 1]) / (1.0f + tmp[0] + tmp[count - 1]);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
r_x[i] -= coeff * tmp[i];
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(tmp);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
@@ -168,8 +168,8 @@ int BM_mesh_edgeloops_find(
|
||||
|
||||
/* add both directions */
|
||||
if (bm_loop_build(el_store, e->v1, e->v2, 1) &&
|
||||
bm_loop_build(el_store, e->v2, e->v1, -1) &&
|
||||
el_store->len > 1)
|
||||
bm_loop_build(el_store, e->v2, e->v1, -1) &&
|
||||
el_store->len > 1)
|
||||
{
|
||||
BLI_addtail(r_eloops, el_store);
|
||||
count++;
|
||||
|
||||
@@ -104,6 +104,7 @@ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_inde
|
||||
fcu = MEM_callocN(sizeof(FCurve), "FCurve");
|
||||
|
||||
fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
|
||||
fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
|
||||
|
||||
/* store path - make copy, and store that */
|
||||
fcu->rna_path = BLI_strdup(rna_path);
|
||||
|
||||
@@ -188,6 +188,7 @@ FCurve *verify_fcurve(bAction *act, const char group[], PointerRNA *ptr,
|
||||
fcu = MEM_callocN(sizeof(FCurve), "FCurve");
|
||||
|
||||
fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
|
||||
fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
|
||||
if (BLI_listbase_is_empty(&act->curves))
|
||||
fcu->flag |= FCURVE_ACTIVE; /* first one added active */
|
||||
|
||||
|
||||
@@ -77,19 +77,20 @@ EditBone *ED_armature_edit_bone_add(bArmature *arm, const char *name)
|
||||
bone->dist = 0.25f;
|
||||
bone->xwidth = 0.1f;
|
||||
bone->zwidth = 0.1f;
|
||||
bone->ease1 = 1.0f;
|
||||
bone->ease2 = 1.0f;
|
||||
bone->rad_head = 0.10f;
|
||||
bone->rad_tail = 0.05f;
|
||||
bone->segments = 1;
|
||||
bone->layer = arm->layer;
|
||||
|
||||
/* Bendy-Bone parameters */
|
||||
bone->roll1 = 0.0f;
|
||||
bone->roll2 = 0.0f;
|
||||
bone->curveInX = 0.0f;
|
||||
bone->curveInY = 0.0f;
|
||||
bone->curveOutX = 0.0f;
|
||||
bone->curveOutY = 0.0f;
|
||||
bone->ease1 = 1.0f;
|
||||
bone->ease2 = 1.0f;
|
||||
bone->scaleIn = 1.0f;
|
||||
bone->scaleOut = 1.0f;
|
||||
|
||||
@@ -899,19 +900,20 @@ static int armature_extrude_exec(bContext *C, wmOperator *op)
|
||||
newbone->dist = ebone->dist;
|
||||
newbone->xwidth = ebone->xwidth;
|
||||
newbone->zwidth = ebone->zwidth;
|
||||
newbone->ease1 = ebone->ease1;
|
||||
newbone->ease2 = ebone->ease2;
|
||||
newbone->rad_head = ebone->rad_tail; // don't copy entire bone...
|
||||
newbone->rad_tail = ebone->rad_tail;
|
||||
newbone->segments = 1;
|
||||
newbone->layer = ebone->layer;
|
||||
|
||||
/* Bendy-Bone parameters */
|
||||
newbone->roll1 = ebone->roll1;
|
||||
newbone->roll2 = ebone->roll2;
|
||||
newbone->curveInX = ebone->curveInX;
|
||||
newbone->curveInY = ebone->curveInY;
|
||||
newbone->curveOutX = ebone->curveOutX;
|
||||
newbone->curveOutY = ebone->curveOutY;
|
||||
newbone->ease1 = ebone->ease1;
|
||||
newbone->ease2 = ebone->ease2;
|
||||
newbone->scaleIn = ebone->scaleIn;
|
||||
newbone->scaleOut = ebone->scaleOut;
|
||||
|
||||
|
||||
@@ -173,6 +173,7 @@ typedef struct tPChanFCurveLink {
|
||||
float roll1, roll2; /* old bbone values (to be restored along with the transform properties) */
|
||||
float curveInX, curveInY; /* (NOTE: we haven't renamed these this time, as their names are already long enough) */
|
||||
float curveOutX, curveOutY;
|
||||
float ease1, ease2;
|
||||
float scaleIn, scaleOut;
|
||||
|
||||
struct IDProperty *oldprops; /* copy of custom properties at start of operator (to be restored before each modal step) */
|
||||
|
||||
@@ -463,19 +463,20 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
|
||||
eBone->weight = curBone->weight;
|
||||
eBone->xwidth = curBone->xwidth;
|
||||
eBone->zwidth = curBone->zwidth;
|
||||
eBone->ease1 = curBone->ease1;
|
||||
eBone->ease2 = curBone->ease2;
|
||||
eBone->rad_head = curBone->rad_head;
|
||||
eBone->rad_tail = curBone->rad_tail;
|
||||
eBone->segments = curBone->segments;
|
||||
eBone->layer = curBone->layer;
|
||||
|
||||
/* Bendy-Bone parameters */
|
||||
eBone->roll1 = curBone->roll1;
|
||||
eBone->roll2 = curBone->roll2;
|
||||
eBone->curveInX = curBone->curveInX;
|
||||
eBone->curveInY = curBone->curveInY;
|
||||
eBone->curveOutX = curBone->curveOutX;
|
||||
eBone->curveOutY = curBone->curveOutY;
|
||||
eBone->ease1 = curBone->ease1;
|
||||
eBone->ease2 = curBone->ease2;
|
||||
eBone->scaleIn = curBone->scaleIn;
|
||||
eBone->scaleOut = curBone->scaleOut;
|
||||
|
||||
@@ -627,19 +628,20 @@ void ED_armature_from_edit(bArmature *arm)
|
||||
|
||||
newBone->xwidth = eBone->xwidth;
|
||||
newBone->zwidth = eBone->zwidth;
|
||||
newBone->ease1 = eBone->ease1;
|
||||
newBone->ease2 = eBone->ease2;
|
||||
newBone->rad_head = eBone->rad_head;
|
||||
newBone->rad_tail = eBone->rad_tail;
|
||||
newBone->segments = eBone->segments;
|
||||
newBone->layer = eBone->layer;
|
||||
|
||||
/* Bendy-Bone parameters */
|
||||
newBone->roll1 = eBone->roll1;
|
||||
newBone->roll2 = eBone->roll2;
|
||||
newBone->curveInX = eBone->curveInX;
|
||||
newBone->curveInY = eBone->curveInY;
|
||||
newBone->curveOutX = eBone->curveOutX;
|
||||
newBone->curveOutY = eBone->curveOutY;
|
||||
newBone->ease1 = eBone->ease1;
|
||||
newBone->ease2 = eBone->ease2;
|
||||
newBone->scaleIn = eBone->scaleIn;
|
||||
newBone->scaleOut = eBone->scaleOut;
|
||||
|
||||
|
||||
@@ -1444,19 +1444,20 @@ static EditBone *add_editbonetolist(char *name, ListBase *list)
|
||||
bone->dist = 0.25F;
|
||||
bone->xwidth = 0.1;
|
||||
bone->zwidth = 0.1;
|
||||
bone->ease1 = 1.0;
|
||||
bone->ease2 = 1.0;
|
||||
bone->rad_head = 0.10;
|
||||
bone->rad_tail = 0.05;
|
||||
bone->segments = 1;
|
||||
bone->layer = 1; //arm->layer;
|
||||
|
||||
/* Bendy-Bone parameters */
|
||||
bone->roll1 = 0.0f;
|
||||
bone->roll2 = 0.0f;
|
||||
bone->curveInX = 0.0f;
|
||||
bone->curveInY = 0.0f;
|
||||
bone->curveOutX = 0.0f;
|
||||
bone->curveOutY = 0.0f;
|
||||
bone->ease1 = 1.0f;
|
||||
bone->ease2 = 1.0f;
|
||||
bone->scaleIn = 1.0f;
|
||||
bone->scaleOut = 1.0f;
|
||||
|
||||
|
||||
@@ -362,6 +362,8 @@ static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bo
|
||||
|
||||
pchan->roll1 = chan->roll1;
|
||||
pchan->roll2 = chan->roll2;
|
||||
pchan->ease1 = chan->ease1;
|
||||
pchan->ease2 = chan->ease2;
|
||||
pchan->scaleIn = chan->scaleIn;
|
||||
pchan->scaleOut = chan->scaleOut;
|
||||
|
||||
@@ -584,6 +586,8 @@ static void pchan_clear_scale(bPoseChannel *pchan)
|
||||
if ((pchan->protectflag & OB_LOCK_SCALEZ) == 0)
|
||||
pchan->size[2] = 1.0f;
|
||||
|
||||
pchan->ease1 = 0.0f;
|
||||
pchan->ease2 = 0.0f;
|
||||
pchan->scaleIn = 1.0f;
|
||||
pchan->scaleOut = 1.0f;
|
||||
}
|
||||
@@ -742,7 +746,7 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
|
||||
/* clear any unkeyed tags */
|
||||
if (pchan->bone)
|
||||
pchan->bone->flag &= ~BONE_UNKEYED;
|
||||
|
||||
|
||||
/* tag for autokeying later */
|
||||
autokey = 1;
|
||||
}
|
||||
|
||||
@@ -115,6 +115,8 @@ static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *a
|
||||
pfl->curveInY = pchan->curveInY;
|
||||
pfl->curveOutX = pchan->curveOutX;
|
||||
pfl->curveOutY = pchan->curveOutY;
|
||||
pfl->ease1 = pchan->ease1;
|
||||
pfl->ease2 = pchan->ease2;
|
||||
pfl->scaleIn = pchan->scaleIn;
|
||||
pfl->scaleOut = pchan->scaleOut;
|
||||
|
||||
@@ -223,6 +225,8 @@ void poseAnim_mapping_reset(ListBase *pfLinks)
|
||||
pchan->curveInY = pfl->curveInY;
|
||||
pchan->curveOutX = pfl->curveOutX;
|
||||
pchan->curveOutY = pfl->curveOutY;
|
||||
pchan->ease1 = pfl->ease1;
|
||||
pchan->ease2 = pfl->ease2;
|
||||
pchan->scaleIn = pfl->scaleIn;
|
||||
pchan->scaleOut = pfl->scaleOut;
|
||||
|
||||
|
||||
@@ -595,7 +595,7 @@ static void calc_keyHandles(ListBase *nurb, float *key)
|
||||
if (nextp) key_to_bezt(nextfp, nextp, &next);
|
||||
if (prevp) key_to_bezt(prevfp, prevp, &prev);
|
||||
|
||||
BKE_nurb_handle_calc(&cur, prevp ? &prev : NULL, nextp ? &next : NULL, 0);
|
||||
BKE_nurb_handle_calc(&cur, prevp ? &prev : NULL, nextp ? &next : NULL, 0, 0);
|
||||
bezt_to_key(&cur, fp);
|
||||
|
||||
prevp = bezt;
|
||||
|
||||
@@ -75,12 +75,15 @@ typedef struct EditBone {
|
||||
|
||||
float dist, weight;
|
||||
float xwidth, length, zwidth; /* put them in order! transform uses this as scale */
|
||||
float ease1, ease2;
|
||||
float rad_head, rad_tail;
|
||||
|
||||
/* Bendy-Bone parameters */
|
||||
float roll1, roll2;
|
||||
float curveOutX, curveOutY;
|
||||
float curveInX, curveInY;
|
||||
float ease1, ease2;
|
||||
float scaleIn, scaleOut;
|
||||
|
||||
float oldlength; /* for envelope scaling */
|
||||
|
||||
short segments;
|
||||
|
||||
@@ -136,6 +136,7 @@ enum {
|
||||
|
||||
/* block->flag bits 14-17 are identical to but->drawflag bits */
|
||||
|
||||
#define UI_BLOCK_POPUP_HOLD (1 << 18)
|
||||
#define UI_BLOCK_LIST_ITEM (1 << 19)
|
||||
#define UI_BLOCK_RADIAL (1 << 20)
|
||||
|
||||
@@ -359,6 +360,7 @@ typedef struct uiSearchItems uiSearchItems;
|
||||
typedef void (*uiButHandleFunc)(struct bContext *C, void *arg1, void *arg2);
|
||||
typedef void (*uiButHandleRenameFunc)(struct bContext *C, void *arg, char *origstr);
|
||||
typedef void (*uiButHandleNFunc)(struct bContext *C, void *argN, void *arg2);
|
||||
typedef void (*uiButHandleHoldFunc)(struct bContext *C, struct ARegion *butregion, uiBut *but);
|
||||
typedef int (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg);
|
||||
typedef struct ARegion *(*uiButSearchCreateFunc)(struct bContext *C, struct ARegion *butregion, uiBut *but);
|
||||
typedef void (*uiButSearchFunc)(const struct bContext *C, void *arg, const char *str, uiSearchItems *items);
|
||||
@@ -400,6 +402,7 @@ void UI_popup_menu_reports(struct bContext *C, struct ReportList *reports) ATTR_
|
||||
int UI_popup_menu_invoke(struct bContext *C, const char *idname, struct ReportList *reports) ATTR_NONNULL(1, 2);
|
||||
|
||||
void UI_popup_menu_retval_set(const uiBlock *block, const int retval, const bool enable);
|
||||
void UI_popup_menu_but_set(uiPopupMenu *pup, struct ARegion *butregion, uiBut *but);
|
||||
|
||||
/* Pie menus */
|
||||
typedef struct uiPieMenu uiPieMenu;
|
||||
@@ -731,6 +734,8 @@ bool UI_textbutton_activate_but(const struct bContext *C, uiBut *but);
|
||||
|
||||
void UI_but_focus_on_enter_event(struct wmWindow *win, uiBut *but);
|
||||
|
||||
void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN);
|
||||
|
||||
/* Autocomplete
|
||||
*
|
||||
* Tab complete helper functions, for use in uiButCompleteFunc callbacks.
|
||||
@@ -831,6 +836,7 @@ void UI_exit(void);
|
||||
#define UI_ITEM_R_FULL_EVENT (1 << 6)
|
||||
#define UI_ITEM_R_NO_BG (1 << 7)
|
||||
#define UI_ITEM_R_IMMEDIATE (1 << 8)
|
||||
#define UI_ITEM_O_DEPRESS (1 << 9)
|
||||
|
||||
/* uiTemplateOperatorPropertyButs flags */
|
||||
#define UI_TEMPLATE_OP_PROPS_SHOW_TITLE 1
|
||||
@@ -1005,6 +1011,11 @@ void uiItemFullO(
|
||||
uiLayout *layout, const char *idname, const char *name, int icon,
|
||||
struct IDProperty *properties, int context, int flag,
|
||||
PointerRNA *r_opptr);
|
||||
void uiItemFullOMenuHold_ptr(
|
||||
uiLayout *layout, struct wmOperatorType *ot, const char *name, int icon,
|
||||
struct IDProperty *properties, int context, int flag,
|
||||
const char *menu_id, /* extra menu arg. */
|
||||
PointerRNA *r_opptr);
|
||||
|
||||
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon);
|
||||
void uiItemFullR(uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int flag, const char *name, int icon);
|
||||
|
||||
@@ -2678,6 +2678,10 @@ static void ui_but_free(const bContext *C, uiBut *but)
|
||||
MEM_freeN(but->tip_argN);
|
||||
}
|
||||
|
||||
if (but->hold_argN) {
|
||||
MEM_freeN(but->hold_argN);
|
||||
}
|
||||
|
||||
if (!but->editstr && but->free_search_arg) {
|
||||
MEM_SAFE_FREE(but->search_arg);
|
||||
}
|
||||
@@ -4532,6 +4536,12 @@ void UI_but_focus_on_enter_event(wmWindow *win, uiBut *but)
|
||||
wm_event_add(win, &event);
|
||||
}
|
||||
|
||||
void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN)
|
||||
{
|
||||
but->hold_func = func;
|
||||
but->hold_argN = argN;
|
||||
}
|
||||
|
||||
void UI_but_string_info_get(bContext *C, uiBut *but, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
@@ -305,6 +305,9 @@ typedef struct uiHandleButtonData {
|
||||
bool used_mouse;
|
||||
wmTimer *autoopentimer;
|
||||
|
||||
/* auto open (hold) */
|
||||
wmTimer *hold_action_timer;
|
||||
|
||||
/* text selection/editing */
|
||||
/* size of 'str' (including terminator) */
|
||||
int maxlen;
|
||||
@@ -7809,6 +7812,15 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
|
||||
data->flashtimer = NULL;
|
||||
}
|
||||
|
||||
/* add hold timer if it's used */
|
||||
if (state == BUTTON_STATE_WAIT_RELEASE && (but->hold_func != NULL)) {
|
||||
data->hold_action_timer = WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_AUTO_OPEN_THRESH);
|
||||
}
|
||||
else if (data->hold_action_timer) {
|
||||
WM_event_remove_timer(data->wm, data->window, data->hold_action_timer);
|
||||
data->hold_action_timer = NULL;
|
||||
}
|
||||
|
||||
/* add a blocking ui handler at the window handler for blocking, modal states
|
||||
* but not for popups, because we already have a window level handler*/
|
||||
if (!(but->block->handle && but->block->handle->popup)) {
|
||||
@@ -8423,6 +8435,25 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
|
||||
button_activate_state(C, but, BUTTON_STATE_EXIT);
|
||||
break;
|
||||
|
||||
case TIMER:
|
||||
{
|
||||
if (event->customdata == data->hold_action_timer) {
|
||||
if (true) {
|
||||
data->cancel = true;
|
||||
button_activate_state(C, but, BUTTON_STATE_EXIT);
|
||||
}
|
||||
else {
|
||||
/* Do this so we can still mouse-up, closing the menu and running the button.
|
||||
* This is nice to support but there are times when the button gets left pressed.
|
||||
* Keep disavled for now. */
|
||||
WM_event_remove_timer(data->wm, data->window, data->hold_action_timer);
|
||||
data->hold_action_timer = NULL;
|
||||
}
|
||||
retval = WM_UI_HANDLER_CONTINUE;
|
||||
but->hold_func(C, data->region, but);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MOUSEMOVE:
|
||||
if (ELEM(but->type, UI_BTYPE_LINK, UI_BTYPE_INLINK)) {
|
||||
but->flag |= UI_SELECT;
|
||||
@@ -9349,21 +9380,29 @@ static int ui_handle_menu_event(
|
||||
if (inside == 0) {
|
||||
uiSafetyRct *saferct = block->saferct.first;
|
||||
|
||||
if (ELEM(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) &&
|
||||
ELEM(event->val, KM_PRESS, KM_DBL_CLICK))
|
||||
{
|
||||
if ((is_parent_menu == false) && (U.uiflag & USER_MENUOPENAUTO) == 0) {
|
||||
/* for root menus, allow clicking to close */
|
||||
if (block->flag & (UI_BLOCK_OUT_1))
|
||||
menu->menuretval = UI_RETURN_OK;
|
||||
else
|
||||
menu->menuretval = UI_RETURN_OUT;
|
||||
if (ELEM(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE)) {
|
||||
if (ELEM(event->val, KM_PRESS, KM_DBL_CLICK)) {
|
||||
if ((is_parent_menu == false) && (U.uiflag & USER_MENUOPENAUTO) == 0) {
|
||||
/* for root menus, allow clicking to close */
|
||||
if (block->flag & (UI_BLOCK_OUT_1))
|
||||
menu->menuretval = UI_RETURN_OK;
|
||||
else
|
||||
menu->menuretval = UI_RETURN_OUT;
|
||||
}
|
||||
else if (saferct && !BLI_rctf_isect_pt(&saferct->parent, event->x, event->y)) {
|
||||
if (block->flag & (UI_BLOCK_OUT_1))
|
||||
menu->menuretval = UI_RETURN_OK;
|
||||
else
|
||||
menu->menuretval = UI_RETURN_OUT;
|
||||
}
|
||||
}
|
||||
else if (saferct && !BLI_rctf_isect_pt(&saferct->parent, event->x, event->y)) {
|
||||
if (block->flag & (UI_BLOCK_OUT_1))
|
||||
menu->menuretval = UI_RETURN_OK;
|
||||
else
|
||||
menu->menuretval = UI_RETURN_OUT;
|
||||
else if (ELEM(event->val, KM_RELEASE, KM_CLICK)) {
|
||||
/* For buttons that use a hold function, exit when mouse-up outside the menu. */
|
||||
if (block->flag & UI_BLOCK_POPUP_HOLD) {
|
||||
/* Note, we could check the cursor is over the parent button. */
|
||||
menu->menuretval = UI_RETURN_CANCEL;
|
||||
retval = WM_UI_HANDLER_CONTINUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,6 +266,10 @@ struct uiBut {
|
||||
void *rename_arg1;
|
||||
void *rename_orig;
|
||||
|
||||
/* Run an action when holding the button down. */
|
||||
uiButHandleHoldFunc hold_func;
|
||||
void *hold_argN;
|
||||
|
||||
uiLink *link;
|
||||
short linkto[2]; /* region relative coords */
|
||||
|
||||
|
||||
@@ -795,7 +795,7 @@ static void ui_item_disabled(uiLayout *layout, const char *name)
|
||||
* \param r_opptr: Optional, initialize with operator properties when not NULL.
|
||||
* Will always be written to even in the case of errors.
|
||||
*/
|
||||
void uiItemFullO_ptr(
|
||||
static uiBut *uiItemFullO_ptr_ex(
|
||||
uiLayout *layout, wmOperatorType *ot,
|
||||
const char *name, int icon, IDProperty *properties, int context, int flag,
|
||||
PointerRNA *r_opptr)
|
||||
@@ -845,6 +845,10 @@ void uiItemFullO_ptr(
|
||||
if (flag & UI_ITEM_R_NO_BG)
|
||||
UI_block_emboss_set(block, UI_EMBOSS);
|
||||
|
||||
if (flag & UI_ITEM_O_DEPRESS) {
|
||||
but->flag |= UI_SELECT;
|
||||
}
|
||||
|
||||
if (layout->redalert)
|
||||
UI_but_flag_enable(but, UI_BUT_REDALERT);
|
||||
|
||||
@@ -862,6 +866,50 @@ void uiItemFullO_ptr(
|
||||
*r_opptr = *opptr;
|
||||
}
|
||||
}
|
||||
|
||||
return but;
|
||||
}
|
||||
|
||||
static void ui_item_hold_menu(struct bContext *C, ARegion *butregion, uiBut *but)
|
||||
{
|
||||
uiPopupMenu *pup = UI_popup_menu_begin(C, "", ICON_NONE);
|
||||
uiLayout *layout = UI_popup_menu_layout(pup);
|
||||
uiBlock *block = layout->root->block;
|
||||
UI_popup_menu_but_set(pup, butregion, but);
|
||||
|
||||
block->flag |= UI_BLOCK_POPUP_HOLD;
|
||||
|
||||
const char *menu_id = but->hold_argN;
|
||||
MenuType *mt = WM_menutype_find(menu_id, true);
|
||||
if (mt) {
|
||||
Menu menu = {NULL};
|
||||
menu.layout = layout;
|
||||
menu.type = mt;
|
||||
mt->draw(C, &menu);
|
||||
}
|
||||
else {
|
||||
uiItemL(layout, "Menu Missing:", ICON_NONE);
|
||||
uiItemL(layout, menu_id, ICON_NONE);
|
||||
}
|
||||
UI_popup_menu_end(C, pup);
|
||||
}
|
||||
|
||||
void uiItemFullO_ptr(
|
||||
uiLayout *layout, wmOperatorType *ot,
|
||||
const char *name, int icon, IDProperty *properties, int context, int flag,
|
||||
PointerRNA *r_opptr)
|
||||
{
|
||||
uiItemFullO_ptr_ex(layout, ot, name, icon, properties, context, flag, r_opptr);
|
||||
}
|
||||
|
||||
void uiItemFullOMenuHold_ptr(
|
||||
uiLayout *layout, wmOperatorType *ot,
|
||||
const char *name, int icon, IDProperty *properties, int context, int flag,
|
||||
const char *menu_id,
|
||||
PointerRNA *r_opptr)
|
||||
{
|
||||
uiBut *but = uiItemFullO_ptr_ex(layout, ot, name, icon, properties, context, flag, r_opptr);
|
||||
UI_but_func_hold_set(but, ui_item_hold_menu, BLI_strdup(menu_id));
|
||||
}
|
||||
|
||||
void uiItemFullO(
|
||||
@@ -875,7 +923,7 @@ void uiItemFullO(
|
||||
ot, opname, {
|
||||
if (r_opptr) {
|
||||
*r_opptr = PointerRNA_NULL;
|
||||
};
|
||||
}
|
||||
return;
|
||||
});
|
||||
|
||||
|
||||
@@ -2635,6 +2635,7 @@ struct uiPopupMenu {
|
||||
uiBlock *block;
|
||||
uiLayout *layout;
|
||||
uiBut *but;
|
||||
ARegion *butregion;
|
||||
|
||||
int mx, my;
|
||||
bool popup, slideout;
|
||||
@@ -2881,17 +2882,33 @@ uiPopupMenu *UI_popup_menu_begin(bContext *C, const char *title, int icon)
|
||||
return UI_popup_menu_begin_ex(C, title, __func__, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting the button makes the popup open from the button instead of the cursor.
|
||||
*/
|
||||
void UI_popup_menu_but_set(uiPopupMenu *pup, struct ARegion *butregion, uiBut *but)
|
||||
{
|
||||
pup->but = but;
|
||||
pup->butregion = butregion;
|
||||
}
|
||||
|
||||
/* set the whole structure to work */
|
||||
void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
|
||||
{
|
||||
wmWindow *window = CTX_wm_window(C);
|
||||
uiPopupBlockHandle *menu;
|
||||
uiBut *but = NULL;
|
||||
ARegion *butregion = NULL;
|
||||
|
||||
pup->popup = true;
|
||||
pup->mx = window->eventstate->x;
|
||||
pup->my = window->eventstate->y;
|
||||
|
||||
menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPUP, pup);
|
||||
|
||||
if (pup->but) {
|
||||
but = pup->but;
|
||||
butregion = pup->butregion;
|
||||
}
|
||||
|
||||
menu = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup);
|
||||
menu->popup = true;
|
||||
|
||||
UI_popup_handlers_add(C, &window->modalhandlers, menu, 0);
|
||||
|
||||
@@ -66,6 +66,15 @@
|
||||
/* icons are 80% of height of button (16 pixels inside 20 height) */
|
||||
#define ICON_SIZE_FROM_BUTRECT(rect) (0.8f * BLI_rcti_size_y(rect))
|
||||
|
||||
#define UI_BUT_FLAGS_PUBLIC \
|
||||
(UI_SELECT | UI_SCROLLED | UI_ACTIVE | UI_HAS_ICON | UI_TEXTINPUT | UI_HIDDEN)
|
||||
|
||||
/* Bits 0..5 are from UI_SELECT .. etc */
|
||||
enum {
|
||||
/* Show that holding the button opens a menu. */
|
||||
UI_STATE_HOLD_ACTION = (1 << 6),
|
||||
};
|
||||
|
||||
/* ************** widget base functions ************** */
|
||||
/**
|
||||
* - in: roundbox codes for corner types and radius
|
||||
@@ -145,45 +154,54 @@ static const float jit[WIDGET_AA_JITTER][2] = {
|
||||
{-0.272855, 0.269918}, { 0.095909, 0.388710}
|
||||
};
|
||||
|
||||
static const float num_tria_vert[3][2] = {
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Shape Preset Data
|
||||
* \{ */
|
||||
|
||||
static const float g_shape_preset_number_arrow_vert[3][2] = {
|
||||
{-0.352077, 0.532607}, {-0.352077, -0.549313}, {0.330000, -0.008353}
|
||||
};
|
||||
|
||||
static const unsigned int num_tria_face[1][3] = {
|
||||
static const uint g_shape_preset_number_arrow_face[1][3] = {
|
||||
{0, 1, 2}
|
||||
};
|
||||
|
||||
static const float scroll_circle_vert[16][2] = {
|
||||
static const float g_shape_preset_scroll_circle_vert[16][2] = {
|
||||
{0.382684, 0.923879}, {0.000001, 1.000000}, {-0.382683, 0.923880}, {-0.707107, 0.707107},
|
||||
{-0.923879, 0.382684}, {-1.000000, 0.000000}, {-0.923880, -0.382684}, {-0.707107, -0.707107},
|
||||
{-0.382683, -0.923880}, {0.000000, -1.000000}, {0.382684, -0.923880}, {0.707107, -0.707107},
|
||||
{0.923880, -0.382684}, {1.000000, -0.000000}, {0.923880, 0.382683}, {0.707107, 0.707107}
|
||||
};
|
||||
|
||||
static const unsigned int scroll_circle_face[14][3] = {
|
||||
static const uint g_shape_preset_scroll_circle_face[14][3] = {
|
||||
{0, 1, 2}, {2, 0, 3}, {3, 0, 15}, {3, 15, 4}, {4, 15, 14}, {4, 14, 5}, {5, 14, 13}, {5, 13, 6},
|
||||
{6, 13, 12}, {6, 12, 7}, {7, 12, 11}, {7, 11, 8}, {8, 11, 10}, {8, 10, 9}
|
||||
};
|
||||
|
||||
|
||||
static const float menu_tria_vert[6][2] = {
|
||||
static const float g_shape_preset_menu_arrow_vert[6][2] = {
|
||||
{-0.33, 0.16}, {0.33, 0.16}, {0, 0.82},
|
||||
{0, -0.82}, {-0.33, -0.16}, {0.33, -0.16}
|
||||
};
|
||||
static const uint g_shape_preset_menu_arrow_face[2][3] = {{2, 0, 1}, {3, 5, 4}};
|
||||
|
||||
|
||||
|
||||
static const unsigned int menu_tria_face[2][3] = {{2, 0, 1}, {3, 5, 4}};
|
||||
|
||||
static const float check_tria_vert[6][2] = {
|
||||
static const float g_shape_preset_checkmark_vert[6][2] = {
|
||||
{-0.578579, 0.253369}, {-0.392773, 0.412794}, {-0.004241, -0.328551},
|
||||
{-0.003001, 0.034320}, {1.055313, 0.864744}, {0.866408, 1.026895}
|
||||
};
|
||||
|
||||
static const unsigned int check_tria_face[4][3] = {
|
||||
static const uint g_shape_preset_checkmark_face[4][3] = {
|
||||
{3, 2, 4}, {3, 4, 5}, {1, 0, 3}, {0, 2, 3}
|
||||
};
|
||||
|
||||
#define OY -0.2
|
||||
#define SC 0.35
|
||||
static const float g_shape_preset_hold_action_vert[6][2] = {
|
||||
{-0.5 + SC, 1.0 + OY}, {0.5, 1.0 + OY}, {0.5, 0.0 + OY + SC},
|
||||
};
|
||||
static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}};
|
||||
#undef OY
|
||||
#undef SC
|
||||
|
||||
/** \} */
|
||||
|
||||
/* ************************************************* */
|
||||
|
||||
void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3,
|
||||
@@ -490,9 +508,12 @@ static void round_box_edges(uiWidgetBase *wt, int roundboxalign, const rcti *rec
|
||||
round_box__edges(wt, roundboxalign, rect, rad, rad - U.pixelsize);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Shape Preset Mini API
|
||||
* \{ */
|
||||
|
||||
/* based on button rect, return scaled array of triangles */
|
||||
static void widget_draw_tria_ex(
|
||||
static void shape_preset_init_trias_ex(
|
||||
uiWidgetTrias *tria, const rcti *rect, float triasize, char where,
|
||||
/* input data */
|
||||
const float verts[][2], const int verts_tot,
|
||||
@@ -531,23 +552,31 @@ static void widget_draw_tria_ex(
|
||||
tria->index = tris;
|
||||
}
|
||||
|
||||
static void widget_num_tria(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
|
||||
static void shape_preset_init_number_arrows(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
|
||||
{
|
||||
widget_draw_tria_ex(
|
||||
shape_preset_init_trias_ex(
|
||||
tria, rect, triasize, where,
|
||||
num_tria_vert, ARRAY_SIZE(num_tria_vert),
|
||||
num_tria_face, ARRAY_SIZE(num_tria_face));
|
||||
g_shape_preset_number_arrow_vert, ARRAY_SIZE(g_shape_preset_number_arrow_vert),
|
||||
g_shape_preset_number_arrow_face, ARRAY_SIZE(g_shape_preset_number_arrow_face));
|
||||
}
|
||||
|
||||
static void widget_scroll_circle(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
|
||||
static void shape_preset_init_hold_action(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
|
||||
{
|
||||
widget_draw_tria_ex(
|
||||
shape_preset_init_trias_ex(
|
||||
tria, rect, triasize, where,
|
||||
scroll_circle_vert, ARRAY_SIZE(scroll_circle_vert),
|
||||
scroll_circle_face, ARRAY_SIZE(scroll_circle_face));
|
||||
g_shape_preset_hold_action_vert, ARRAY_SIZE(g_shape_preset_hold_action_vert),
|
||||
g_shape_preset_hold_action_face, ARRAY_SIZE(g_shape_preset_hold_action_face));
|
||||
}
|
||||
|
||||
static void widget_trias_draw(uiWidgetTrias *tria, unsigned int pos)
|
||||
static void shape_preset_init_scroll_circle(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
|
||||
{
|
||||
shape_preset_init_trias_ex(
|
||||
tria, rect, triasize, where,
|
||||
g_shape_preset_scroll_circle_vert, ARRAY_SIZE(g_shape_preset_scroll_circle_vert),
|
||||
g_shape_preset_scroll_circle_face, ARRAY_SIZE(g_shape_preset_scroll_circle_face));
|
||||
}
|
||||
|
||||
static void shape_preset_draw_trias(uiWidgetTrias *tria, uint pos)
|
||||
{
|
||||
immBegin(GWN_PRIM_TRIS, tria->tot * 3);
|
||||
for (int i = 0; i < tria->tot; ++i)
|
||||
@@ -570,7 +599,7 @@ static void widget_draw_vertex_buffer(unsigned int pos, unsigned int col, int mo
|
||||
immEnd();
|
||||
}
|
||||
|
||||
static void widget_menu_trias(uiWidgetTrias *tria, const rcti *rect)
|
||||
static void shape_preset_trias_from_rect_menu(uiWidgetTrias *tria, const rcti *rect)
|
||||
{
|
||||
float centx, centy, size;
|
||||
int a;
|
||||
@@ -581,15 +610,15 @@ static void widget_menu_trias(uiWidgetTrias *tria, const rcti *rect)
|
||||
size = 0.4f * BLI_rcti_size_y(rect);
|
||||
|
||||
for (a = 0; a < 6; a++) {
|
||||
tria->vec[a][0] = size * menu_tria_vert[a][0] + centx;
|
||||
tria->vec[a][1] = size * menu_tria_vert[a][1] + centy;
|
||||
tria->vec[a][0] = size * g_shape_preset_menu_arrow_vert[a][0] + centx;
|
||||
tria->vec[a][1] = size * g_shape_preset_menu_arrow_vert[a][1] + centy;
|
||||
}
|
||||
|
||||
tria->tot = 2;
|
||||
tria->index = menu_tria_face;
|
||||
tria->index = g_shape_preset_menu_arrow_face;
|
||||
}
|
||||
|
||||
static void widget_check_trias(uiWidgetTrias *tria, const rcti *rect)
|
||||
static void shape_preset_trias_from_rect_checkmark(uiWidgetTrias *tria, const rcti *rect)
|
||||
{
|
||||
float centx, centy, size;
|
||||
int a;
|
||||
@@ -600,14 +629,16 @@ static void widget_check_trias(uiWidgetTrias *tria, const rcti *rect)
|
||||
size = 0.5f * BLI_rcti_size_y(rect);
|
||||
|
||||
for (a = 0; a < 6; a++) {
|
||||
tria->vec[a][0] = size * check_tria_vert[a][0] + centx;
|
||||
tria->vec[a][1] = size * check_tria_vert[a][1] + centy;
|
||||
tria->vec[a][0] = size * g_shape_preset_checkmark_vert[a][0] + centx;
|
||||
tria->vec[a][1] = size * g_shape_preset_checkmark_vert[a][1] + centy;
|
||||
}
|
||||
|
||||
tria->tot = 4;
|
||||
tria->index = check_tria_face;
|
||||
tria->index = g_shape_preset_checkmark_face;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
|
||||
/* prepares shade colors */
|
||||
static void shadecolors4(char coltop[4], char coldown[4], const char *color, short shadetop, short shadedown)
|
||||
@@ -805,11 +836,11 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
|
||||
gpuTranslate2fv(jit[j]);
|
||||
|
||||
if (wtb->tria1.tot)
|
||||
widget_trias_draw(&wtb->tria1, pos);
|
||||
shape_preset_draw_trias(&wtb->tria1, pos);
|
||||
|
||||
if (wtb->tria2.tot)
|
||||
widget_trias_draw(&wtb->tria2, pos);
|
||||
|
||||
shape_preset_draw_trias(&wtb->tria2, pos);
|
||||
|
||||
gpuTranslate2f(-jit[j][0], -jit[j][1]);
|
||||
}
|
||||
|
||||
@@ -2742,8 +2773,8 @@ static void widget_numbut_draw(uiWidgetColors *wcol, rcti *rect, int state, int
|
||||
|
||||
/* decoration */
|
||||
if (!(state & UI_TEXTINPUT)) {
|
||||
widget_num_tria(&wtb.tria1, rect, 0.6f, 'l');
|
||||
widget_num_tria(&wtb.tria2, rect, 0.6f, 'r');
|
||||
shape_preset_init_number_arrows(&wtb.tria1, rect, 0.6f, 'l');
|
||||
shape_preset_init_number_arrows(&wtb.tria2, rect, 0.6f, 'r');
|
||||
}
|
||||
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
@@ -2885,12 +2916,12 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s
|
||||
wcol->item[3] = 255;
|
||||
|
||||
if (horizontal) {
|
||||
widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'l');
|
||||
widget_scroll_circle(&wtb.tria2, slider, 0.6f, 'r');
|
||||
shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'l');
|
||||
shape_preset_init_scroll_circle(&wtb.tria2, slider, 0.6f, 'r');
|
||||
}
|
||||
else {
|
||||
widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
|
||||
widget_scroll_circle(&wtb.tria2, slider, 0.6f, 't');
|
||||
shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
|
||||
shape_preset_init_scroll_circle(&wtb.tria2, slider, 0.6f, 't');
|
||||
}
|
||||
}
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
@@ -3233,7 +3264,7 @@ static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
|
||||
round_box_edges(&wtb, roundboxalign, rect, rad);
|
||||
|
||||
/* decoration */
|
||||
widget_menu_trias(&wtb.tria1, rect);
|
||||
shape_preset_trias_from_rect_menu(&wtb.tria1, rect);
|
||||
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
|
||||
@@ -3372,7 +3403,7 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN
|
||||
|
||||
/* decoration */
|
||||
if (state & UI_SELECT) {
|
||||
widget_check_trias(&wtb.tria1, &recttemp);
|
||||
shape_preset_trias_from_rect_checkmark(&wtb.tria1, &recttemp);
|
||||
}
|
||||
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
@@ -3455,6 +3486,7 @@ static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
|
||||
{
|
||||
uiWidgetBase wtb;
|
||||
@@ -3467,6 +3499,25 @@ static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
|
||||
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void widget_roundbut_exec(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
|
||||
{
|
||||
uiWidgetBase wtb;
|
||||
const float rad = 0.25f * U.widget_unit;
|
||||
|
||||
widget_init(&wtb);
|
||||
|
||||
if (state & UI_STATE_HOLD_ACTION) {
|
||||
/* Show that keeping pressed performs another action (typically a menu). */
|
||||
shape_preset_init_hold_action(&wtb.tria1, rect, 0.75f, 'r');
|
||||
}
|
||||
|
||||
/* half rounded */
|
||||
round_box_edges(&wtb, roundboxalign, rect, rad);
|
||||
|
||||
widgetbase_draw(&wtb, wcol);
|
||||
}
|
||||
|
||||
static void widget_tab(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
|
||||
{
|
||||
@@ -3590,7 +3641,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
|
||||
|
||||
case UI_WTYPE_EXEC:
|
||||
wt.wcol_theme = &btheme->tui.wcol_tool;
|
||||
wt.draw = widget_roundbut;
|
||||
wt.draw = widget_roundbut_exec;
|
||||
break;
|
||||
|
||||
case UI_WTYPE_TAB:
|
||||
@@ -3770,6 +3821,10 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
|
||||
return roundbox;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Public API
|
||||
* \{ */
|
||||
|
||||
/* conversion from old to new buttons, so still messy */
|
||||
void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
|
||||
{
|
||||
@@ -4009,7 +4064,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
|
||||
|
||||
roundboxalign = widget_roundbox_set(but, rect);
|
||||
|
||||
state = but->flag;
|
||||
state = but->flag & UI_BUT_FLAGS_PUBLIC;
|
||||
|
||||
if ((but->editstr) ||
|
||||
(UNLIKELY(but->flag & UI_BUT_DRAG_MULTI) && ui_but_drag_multi_edit_get(but)))
|
||||
@@ -4017,6 +4072,10 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
|
||||
state |= UI_TEXTINPUT;
|
||||
}
|
||||
|
||||
if (but->hold_func) {
|
||||
state |= UI_STATE_HOLD_ACTION;
|
||||
}
|
||||
|
||||
if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
|
||||
if (but->dt != UI_EMBOSS_PULLDOWN)
|
||||
disabled = true;
|
||||
@@ -4343,3 +4402,5 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int
|
||||
UI_fontstyle_draw(fstyle, &trect, drawstr, (unsigned char *)wt->wcol.text);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -208,7 +208,12 @@ static void graph_panel_properties(const bContext *C, Panel *pa)
|
||||
sub = uiLayoutRow(row, true);
|
||||
uiLayoutSetEnabled(sub, (fcu->color_mode == FCURVE_COLOR_CUSTOM));
|
||||
uiItemR(sub, &fcu_ptr, "color", 0, "", ICON_NONE);
|
||||
|
||||
|
||||
/* smoothing setting */
|
||||
col = uiLayoutColumn(layout, true);
|
||||
uiItemL(col, IFACE_("Auto Handle Smoothing:"), ICON_NONE);
|
||||
uiItemR(col, &fcu_ptr, "auto_smoothing", 0, "", ICON_NONE);
|
||||
|
||||
MEM_freeN(ale);
|
||||
}
|
||||
|
||||
|
||||
@@ -2578,7 +2578,11 @@ float schlick_fresnel(float u)
|
||||
|
||||
float GTR1(float NdotH, float a)
|
||||
{
|
||||
if (a >= 1.0) return M_1_PI;
|
||||
if (a >= 1.0) {
|
||||
return M_1_PI;
|
||||
}
|
||||
|
||||
a = max(a, 0.001);
|
||||
float a2 = a*a;
|
||||
float t = 1.0 + (a2 - 1.0) * NdotH*NdotH;
|
||||
return (a2 - 1.0) / (M_PI * log(a2) * t);
|
||||
|
||||
@@ -268,6 +268,7 @@ typedef struct bPoseChannel {
|
||||
float roll1, roll2;
|
||||
float curveInX, curveInY;
|
||||
float curveOutX, curveOutY;
|
||||
float ease1, ease2;
|
||||
float scaleIn, scaleOut;
|
||||
|
||||
struct bPoseChannel *bbone_prev; /* next/prev bones to use as handle references when calculating bbones (optional) */
|
||||
|
||||
@@ -490,7 +490,10 @@ typedef struct FCurve {
|
||||
float curval; /* value stored from last time curve was evaluated (not threadsafe, debug display only!) */
|
||||
short flag; /* user-editable settings for this curve */
|
||||
short extend; /* value-extending mode for this curve (does not cover */
|
||||
char auto_smoothing; /* auto-handle smoothing mode */
|
||||
|
||||
char pad[7];
|
||||
|
||||
/* RNA - data link */
|
||||
int array_index; /* if applicable, the index of the RNA-array item to get */
|
||||
char *rna_path; /* RNA-path to resolve data-access */
|
||||
@@ -545,6 +548,12 @@ typedef enum eFCurve_Coloring {
|
||||
FCURVE_COLOR_CUSTOM = 2, /* custom color */
|
||||
} eFCurve_Coloring;
|
||||
|
||||
/* curve smoothing modes */
|
||||
typedef enum eFCurve_Smoothing {
|
||||
FCURVE_SMOOTH_NONE = 0, /* legacy mode: auto handles only consider adjacent points */
|
||||
FCURVE_SMOOTH_CONT_ACCEL = 1, /* maintain continuity of the acceleration */
|
||||
} eFCurve_Smoothing;
|
||||
|
||||
/* ************************************************ */
|
||||
/* 'Action' Datatypes */
|
||||
|
||||
|
||||
@@ -66,12 +66,12 @@ typedef struct Bone {
|
||||
|
||||
float dist, weight; /* dist, weight: for non-deformgroup deforms */
|
||||
float xwidth, length, zwidth; /* width: for block bones. keep in this order, transform! */
|
||||
float ease1, ease2; /* length of bezier handles */
|
||||
float rad_head, rad_tail; /* radius for head/tail sphere, defining deform as well, parent->rad_tip overrides rad_head */
|
||||
|
||||
float roll1, roll2; /* curved bones settings - these define the "restpose" for a curved bone */
|
||||
float curveInX, curveInY;
|
||||
float curveOutX, curveOutY;
|
||||
float ease1, ease2; /* length of bezier handles */
|
||||
float scaleIn, scaleOut;
|
||||
|
||||
float size[3]; /* patch for upward compat, UNUSED! */
|
||||
|
||||
@@ -124,7 +124,8 @@ typedef struct BezTriple {
|
||||
float back; /* BEZT_IPO_BACK */
|
||||
float amplitude, period; /* BEZT_IPO_ELASTIC */
|
||||
|
||||
char pad[4];
|
||||
char f5; /* f5: used for auto handle to distinguish between normal handle and exception (extrema) */
|
||||
char pad[3];
|
||||
} BezTriple;
|
||||
|
||||
/* note; alfa location in struct is abused by Key system */
|
||||
@@ -396,6 +397,12 @@ typedef enum eBezTriple_Handle {
|
||||
HD_ALIGN_DOUBLESIDE = 5, /* align handles, displayed both of them. used for masks */
|
||||
} eBezTriple_Handle;
|
||||
|
||||
/* f5 (beztriple) */
|
||||
typedef enum eBezTriple_Auto_Type {
|
||||
HD_AUTOTYPE_NORMAL = 0,
|
||||
HD_AUTOTYPE_SPECIAL = 1
|
||||
} eBezTriple_Auto_Type;
|
||||
|
||||
/* interpolation modes (used only for BezTriple->ipo) */
|
||||
typedef enum eBezTriple_Interpolation {
|
||||
/* traditional interpolation */
|
||||
|
||||
@@ -543,7 +543,22 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone)
|
||||
RNA_def_property_range(prop, -5.0f, 5.0f);
|
||||
RNA_def_property_ui_text(prop, "Out Y", "Y-axis handle offset for end of the B-Bone's curve, adjusts curvature");
|
||||
RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
|
||||
|
||||
/* Ease In/Out */
|
||||
prop = RNA_def_property(srna, "bbone_easein", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "ease1");
|
||||
RNA_def_property_range(prop, -5.0f, 5.0f);
|
||||
RNA_def_property_float_default(prop, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "B-Bone Ease In", "Length of first Bezier Handle (for B-Bones only)");
|
||||
RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
|
||||
|
||||
prop = RNA_def_property(srna, "bbone_easeout", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "ease2");
|
||||
RNA_def_property_range(prop, -5.0f, 5.0f);
|
||||
RNA_def_property_float_default(prop, 1.0f);
|
||||
RNA_def_property_ui_text(prop, "B-Bone Ease Out", "Length of second Bezier Handle (for B-Bones only)");
|
||||
RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
|
||||
|
||||
/* Scale In/Out */
|
||||
prop = RNA_def_property(srna, "bbone_scalein", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "scaleIn");
|
||||
@@ -681,18 +696,6 @@ static void rna_def_bone_common(StructRNA *srna, int editbone)
|
||||
RNA_def_property_ui_text(prop, "B-Bone Segments", "Number of subdivisions of bone (for B-Bones only)");
|
||||
RNA_def_property_update(prop, 0, "rna_Armature_update_data");
|
||||
|
||||
prop = RNA_def_property(srna, "bbone_in", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "ease1");
|
||||
RNA_def_property_range(prop, 0.0f, 2.0f);
|
||||
RNA_def_property_ui_text(prop, "B-Bone Ease In", "Length of first Bezier Handle (for B-Bones only)");
|
||||
RNA_def_property_update(prop, 0, "rna_Armature_update_data");
|
||||
|
||||
prop = RNA_def_property(srna, "bbone_out", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "ease2");
|
||||
RNA_def_property_range(prop, 0.0f, 2.0f);
|
||||
RNA_def_property_ui_text(prop, "B-Bone Ease Out", "Length of second Bezier Handle (for B-Bones only)");
|
||||
RNA_def_property_update(prop, 0, "rna_Armature_update_data");
|
||||
|
||||
prop = RNA_def_property(srna, "bbone_x", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "xwidth");
|
||||
RNA_def_property_range(prop, 0.0f, 1000.0f);
|
||||
|
||||
@@ -1897,6 +1897,11 @@ static void rna_def_fcurve(BlenderRNA *brna)
|
||||
"Use custom hand-picked color for F-Curve"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
static EnumPropertyItem prop_mode_smoothing_items[] = {
|
||||
{FCURVE_SMOOTH_NONE, "NONE", 0, "None", "Auto handles only take adjacent keys into account (legacy mode)"},
|
||||
{FCURVE_SMOOTH_CONT_ACCEL, "CONT_ACCEL", 0, "Continuous Acceleration", "Auto handles are placed to avoid jumps in acceleration"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
srna = RNA_def_struct(brna, "FCurve", NULL);
|
||||
RNA_def_struct_ui_text(srna, "F-Curve", "F-Curve defining values of a period of time");
|
||||
@@ -1970,6 +1975,11 @@ static void rna_def_fcurve(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Hide", "F-Curve and its keyframes are hidden in the Graph Editor graphs");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "auto_smoothing", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, prop_mode_smoothing_items);
|
||||
RNA_def_property_ui_text(prop, "Auto Handle Smoothing", "Algorithm used to compute automatic handles");
|
||||
RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FCurve_update_data");
|
||||
|
||||
/* State Info (for Debugging) */
|
||||
prop = RNA_def_property(srna, "is_valid", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", FCURVE_DISABLED);
|
||||
|
||||
@@ -175,11 +175,11 @@ static void rna_uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const c
|
||||
uiItemPointerR(layout, ptr, propname, searchptr, searchpropname, name, icon);
|
||||
}
|
||||
|
||||
static PointerRNA rna_uiItemO(uiLayout *layout, const char *opname, const char *name, const char *text_ctxt,
|
||||
int translate, int icon, int emboss, int icon_value)
|
||||
static PointerRNA rna_uiItemO(
|
||||
uiLayout *layout, const char *opname, const char *name, const char *text_ctxt,
|
||||
int translate, int icon, int emboss, int depress, int icon_value)
|
||||
{
|
||||
wmOperatorType *ot;
|
||||
int flag;
|
||||
|
||||
ot = WM_operatortype_find(opname, 0); /* print error next */
|
||||
if (!ot || !ot->srna) {
|
||||
@@ -193,15 +193,39 @@ static PointerRNA rna_uiItemO(uiLayout *layout, const char *opname, const char *
|
||||
if (icon_value && !icon) {
|
||||
icon = icon_value;
|
||||
}
|
||||
|
||||
flag = 0;
|
||||
flag |= (emboss) ? 0 : UI_ITEM_R_NO_BG;
|
||||
int flag = (emboss) ? 0 : UI_ITEM_R_NO_BG;
|
||||
flag |= (depress) ? UI_ITEM_O_DEPRESS : 0;
|
||||
|
||||
PointerRNA opptr;
|
||||
uiItemFullO_ptr(layout, ot, name, icon, NULL, uiLayoutGetOperatorContext(layout), flag, &opptr);
|
||||
return opptr;
|
||||
}
|
||||
|
||||
static PointerRNA rna_uiItemOMenuHold(
|
||||
uiLayout *layout, const char *opname, const char *name, const char *text_ctxt,
|
||||
int translate, int icon, int emboss, int depress, int icon_value,
|
||||
const char *menu)
|
||||
{
|
||||
wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
|
||||
if (!ot || !ot->srna) {
|
||||
RNA_warning("%s '%s'", ot ? "unknown operator" : "operator missing srna", opname);
|
||||
return PointerRNA_NULL;
|
||||
}
|
||||
|
||||
/* Get translated name (label). */
|
||||
name = rna_translate_ui_text(name, text_ctxt, ot->srna, NULL, translate);
|
||||
if (icon_value && !icon) {
|
||||
icon = icon_value;
|
||||
}
|
||||
int flag = (emboss) ? 0 : UI_ITEM_R_NO_BG;
|
||||
flag |= (depress) ? UI_ITEM_O_DEPRESS : 0;
|
||||
|
||||
PointerRNA opptr;
|
||||
uiItemFullOMenuHold_ptr(layout, ot, name, icon, NULL, uiLayoutGetOperatorContext(layout), flag, menu, &opptr);
|
||||
return opptr;
|
||||
}
|
||||
|
||||
|
||||
static void rna_uiItemMenuEnumO(uiLayout *layout, bContext *C, const char *opname, const char *propname, const char *name,
|
||||
const char *text_ctxt, int translate, int icon)
|
||||
{
|
||||
@@ -553,15 +577,24 @@ void RNA_api_ui_layout(StructRNA *srna)
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
api_ui_item_common(func);
|
||||
|
||||
func = RNA_def_function(srna, "operator", "rna_uiItemO");
|
||||
api_ui_item_op_common(func);
|
||||
RNA_def_boolean(func, "emboss", true, "", "Draw the button itself, just the icon/text");
|
||||
parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_ui_text(parm, "Icon Value", "Override automatic icon of the item");
|
||||
parm = RNA_def_pointer(func, "properties", "OperatorProperties", "", "Operator properties to fill in");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR);
|
||||
RNA_def_function_return(func, parm);
|
||||
RNA_def_function_ui_description(func, "Item. Places a button into the layout to call an Operator");
|
||||
for (int is_menu_hold = 0; is_menu_hold < 2; is_menu_hold++) {
|
||||
func = (is_menu_hold) ?
|
||||
RNA_def_function(srna, "operator_menu_hold", "rna_uiItemOMenuHold") :
|
||||
RNA_def_function(srna, "operator", "rna_uiItemO");
|
||||
api_ui_item_op_common(func);
|
||||
RNA_def_boolean(func, "emboss", true, "", "Draw the button itself, just the icon/text");
|
||||
RNA_def_boolean(func, "depress", false, "", "Draw pressed in");
|
||||
parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_ui_text(parm, "Icon Value", "Override automatic icon of the item");
|
||||
if (is_menu_hold) {
|
||||
parm = RNA_def_string(func, "menu", NULL, 0, "", "Identifier of the menu");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
}
|
||||
parm = RNA_def_pointer(func, "properties", "OperatorProperties", "", "Operator properties to fill in");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR);
|
||||
RNA_def_function_return(func, parm);
|
||||
RNA_def_function_ui_description(func, "Item. Places a button into the layout to call an Operator");
|
||||
}
|
||||
|
||||
func = RNA_def_function(srna, "operator_enum", "uiItemsEnumO");
|
||||
parm = RNA_def_string(func, "operator", NULL, 0, "", "Identifier of the operator");
|
||||
|
||||
Reference in New Issue
Block a user