Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_graph/graph_draw.c')
-rw-r--r--source/blender/editors/space_graph/graph_draw.c139
1 files changed, 102 insertions, 37 deletions
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 4752f62b58c..c5358cdfa5b 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -35,6 +35,7 @@
#include "DNA_userdef_types.h"
#include "DNA_windowmanager_types.h"
+#include "BKE_action.h"
#include "BKE_anim_data.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@@ -579,8 +580,13 @@ static void draw_fcurve_samples(SpaceGraph *sipo, ARegion *region, FCurve *fcu)
/* Helper func - just draw the F-Curve by sampling the visible region
* (for drawing curves with modifiers). */
-static void draw_fcurve_curve(
- bAnimContext *ac, ID *id, FCurve *fcu_, View2D *v2d, uint pos, const bool use_nla_remap)
+static void draw_fcurve_curve(bAnimContext *ac,
+ ID *id,
+ FCurve *fcu_,
+ View2D *v2d,
+ uint pos,
+ const bool use_nla_remap,
+ const bool draw_extrapolation)
{
SpaceGraph *sipo = (SpaceGraph *)ac->sl;
short mapping_flag = ANIM_get_normalization_flags(ac);
@@ -641,40 +647,90 @@ static void draw_fcurve_curve(
/* the start/end times are simply the horizontal extents of the 'cur' rect */
float stime = v2d->cur.xmin;
- float etime = v2d->cur.xmax +
- samplefreq; /* + samplefreq here so that last item gets included... */
+ float etime = v2d->cur.xmax;
- /* at each sampling interval, add a new vertex
- * - apply the unit correction factor to the calculated values so that
- * the displayed values appear correctly in the viewport
- */
+ AnimData *adt = use_nla_remap ? BKE_animdata_from_id(id) : NULL;
+
+ /* If not drawing extrapolation, then change fcurve drawing bounds to its keyframe bounds clamped
+ * by graph editor bounds. */
+ if (!draw_extrapolation) {
+ float fcu_start = 0;
+ float fcu_end = 0;
+ BKE_fcurve_calc_range(fcu_, &fcu_start, &fcu_end, false, false);
- int n = roundf((etime - stime) / samplefreq);
+ fcu_start = BKE_nla_tweakedit_remap(adt, fcu_start, NLATIME_CONVERT_MAP);
+ fcu_end = BKE_nla_tweakedit_remap(adt, fcu_end, NLATIME_CONVERT_MAP);
- if (n > 0) {
- immBegin(GPU_PRIM_LINE_STRIP, (n + 1));
+ /* Account for reversed NLA strip effect. */
+ if (fcu_end < fcu_start) {
+ SWAP(float, fcu_start, fcu_end);
+ }
- AnimData *adt = use_nla_remap ? BKE_animdata_from_id(id) : NULL;
- /* NLA remapping is linear so we don't have to remap per iteration. */
- const float eval_start = BKE_nla_tweakedit_remap(adt, stime, NLATIME_CONVERT_UNMAP);
- const float eval_freq = BKE_nla_tweakedit_remap(
- adt, stime + samplefreq, NLATIME_CONVERT_UNMAP) -
- eval_start;
+ /* Clamp to graph editor rendering bounds. */
+ stime = max_ff(stime, fcu_start);
+ etime = min_ff(etime, fcu_end);
+ }
+
+ const int total_samples = roundf((etime - stime) / samplefreq);
+ if (total_samples <= 0) {
+ return;
+ }
- for (int i = 0; i <= n; i++) {
- float ctime = stime + i * samplefreq;
- const float eval_time = eval_start + i * eval_freq;
- immVertex2f(pos, ctime, (evaluate_fcurve(&fcurve_for_draw, eval_time) + offset) * unitFac);
+ /* NLA remapping is linear so we don't have to remap per iteration. */
+ const float eval_start = BKE_nla_tweakedit_remap(adt, stime, NLATIME_CONVERT_UNMAP);
+ const float eval_freq = BKE_nla_tweakedit_remap(adt, stime + samplefreq, NLATIME_CONVERT_UNMAP) -
+ eval_start;
+ const float eval_end = BKE_nla_tweakedit_remap(adt, etime, NLATIME_CONVERT_UNMAP);
+
+ immBegin(GPU_PRIM_LINE_STRIP, (total_samples + 1));
+
+ /* At each sampling interval, add a new vertex.
+ *
+ * Apply the unit correction factor to the calculated values so that the displayed values appear
+ * correctly in the viewport.
+ */
+ for (int i = 0; i < total_samples; i++) {
+ const float ctime = stime + i * samplefreq;
+ float eval_time = eval_start + i * eval_freq;
+
+ /* Prevent drawing past bounds, due to floating point problems.
+ * User-wise, prevent visual flickering.
+ *
+ * This is to cover the case where:
+ * eval_start + total_samples * eval_freq > eval_end
+ * due to floating point problems.
+ */
+ if (eval_time > eval_end) {
+ eval_time = eval_end;
}
- immEnd();
+ immVertex2f(pos, ctime, (evaluate_fcurve(&fcurve_for_draw, eval_time) + offset) * unitFac);
}
+
+ /* Ensure we include end boundary point.
+ * User-wise, prevent visual flickering.
+ *
+ * This is to cover the case where:
+ * eval_start + total_samples * eval_freq < eval_end
+ * due to floating point problems.
+ */
+ immVertex2f(pos, etime, (evaluate_fcurve(&fcurve_for_draw, eval_end) + offset) * unitFac);
+
+ immEnd();
}
/* helper func - draw a samples-based F-Curve */
-static void draw_fcurve_curve_samples(
- bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, const uint shdr_pos)
+static void draw_fcurve_curve_samples(bAnimContext *ac,
+ ID *id,
+ FCurve *fcu,
+ View2D *v2d,
+ const uint shdr_pos,
+ const bool draw_extrapolation)
{
+ if (!draw_extrapolation && fcu->totvert == 1) {
+ return;
+ }
+
FPoint *prevfpt = fcu->fpt;
FPoint *fpt = prevfpt + 1;
float fac, v[2];
@@ -683,11 +739,13 @@ static void draw_fcurve_curve_samples(
short mapping_flag = ANIM_get_normalization_flags(ac);
int count = fcu->totvert;
- if (prevfpt->vec[0] > v2d->cur.xmin) {
+ const bool extrap_left = draw_extrapolation && prevfpt->vec[0] > v2d->cur.xmin;
+ if (extrap_left) {
count++;
}
- if ((prevfpt + b - 1)->vec[0] < v2d->cur.xmax) {
+ const bool extrap_right = draw_extrapolation && (prevfpt + b - 1)->vec[0] < v2d->cur.xmax;
+ if (extrap_right) {
count++;
}
@@ -700,7 +758,7 @@ static void draw_fcurve_curve_samples(
immBegin(GPU_PRIM_LINE_STRIP, count);
/* extrapolate to left? - left-side of view comes before first keyframe? */
- if (prevfpt->vec[0] > v2d->cur.xmin) {
+ if (extrap_left) {
v[0] = v2d->cur.xmin;
/* y-value depends on the interpolation */
@@ -734,7 +792,7 @@ static void draw_fcurve_curve_samples(
}
/* extrapolate to right? (see code for left-extrapolation above too) */
- if (prevfpt->vec[0] < v2d->cur.xmax) {
+ if (extrap_right) {
v[0] = v2d->cur.xmax;
/* y-value depends on the interpolation */
@@ -779,8 +837,13 @@ static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu)
}
/* helper func - draw one repeat of an F-Curve (using Bezier curve approximations) */
-static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, uint pos)
+static void draw_fcurve_curve_bezts(
+ bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, uint pos, const bool draw_extrapolation)
{
+ if (!draw_extrapolation && fcu->totvert == 1) {
+ return;
+ }
+
BezTriple *prevbezt = fcu->bezt;
BezTriple *bezt = prevbezt + 1;
float v1[2], v2[2], v3[2], v4[2];
@@ -803,7 +866,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
immBeginAtMost(GPU_PRIM_LINE_STRIP, (b * 32 + 3));
/* extrapolate to left? */
- if (prevbezt->vec[1][0] > v2d->cur.xmin) {
+ if (draw_extrapolation && prevbezt->vec[1][0] > v2d->cur.xmin) {
/* left-side of view comes before first keyframe, so need to extend as not cyclic */
v1[0] = v2d->cur.xmin;
@@ -923,7 +986,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
}
/* extrapolate to right? (see code for left-extrapolation above too) */
- if (prevbezt->vec[1][0] < v2d->cur.xmax) {
+ if (draw_extrapolation && prevbezt->vec[1][0] < v2d->cur.xmax) {
v1[0] = v2d->cur.xmax;
/* y-value depends on the interpolation */
@@ -1026,6 +1089,7 @@ static void draw_fcurve(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, bAn
immUniformColor3fvAlpha(fcu->color, fcurve_display_alpha(fcu));
}
+ const bool draw_extrapolation = (sipo->flag & SIPO_NO_DRAW_EXTRAPOLATION) == 0;
/* draw F-Curve */
if ((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) {
/* draw a curve affected by modifiers or only allowed to have integer values
@@ -1039,25 +1103,25 @@ static void draw_fcurve(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, bAn
* curve itself. Afterward, we go back and redo the keyframe remapping so the controls are
* drawn properly. */
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, true, false);
- draw_fcurve_curve(ac, ale->id, fcu, &region->v2d, shdr_pos, true);
+ draw_fcurve_curve(ac, ale->id, fcu, &region->v2d, shdr_pos, true, draw_extrapolation);
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, false, false);
}
else {
- draw_fcurve_curve(ac, ale->id, fcu, &region->v2d, shdr_pos, false);
+ draw_fcurve_curve(ac, ale->id, fcu, &region->v2d, shdr_pos, false, draw_extrapolation);
}
}
else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) {
/* just draw curve based on defined data (i.e. no modifiers) */
if (fcu->bezt) {
if (fcurve_can_use_simple_bezt_drawing(fcu)) {
- draw_fcurve_curve_bezts(ac, ale->id, fcu, &region->v2d, shdr_pos);
+ draw_fcurve_curve_bezts(ac, ale->id, fcu, &region->v2d, shdr_pos, draw_extrapolation);
}
else {
- draw_fcurve_curve(ac, ale->id, fcu, &region->v2d, shdr_pos, false);
+ draw_fcurve_curve(ac, ale->id, fcu, &region->v2d, shdr_pos, false, draw_extrapolation);
}
}
else if (fcu->fpt) {
- draw_fcurve_curve_samples(ac, ale->id, fcu, &region->v2d, shdr_pos);
+ draw_fcurve_curve_samples(ac, ale->id, fcu, &region->v2d, shdr_pos, draw_extrapolation);
}
}
@@ -1278,6 +1342,7 @@ void graph_draw_ghost_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region
immUniform1f("dash_width", 20.0f);
immUniform1f("dash_factor", 0.5f);
+ const bool draw_extrapolation = (sipo->flag & SIPO_NO_DRAW_EXTRAPOLATION) == 0;
/* the ghost curves are simply sampled F-Curves stored in sipo->runtime.ghost_curves */
for (fcu = sipo->runtime.ghost_curves.first; fcu; fcu = fcu->next) {
/* set whatever color the curve has set
@@ -1287,7 +1352,7 @@ void graph_draw_ghost_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region
immUniformColor3fvAlpha(fcu->color, 0.5f);
/* simply draw the stored samples */
- draw_fcurve_curve_samples(ac, NULL, fcu, &region->v2d, shdr_pos);
+ draw_fcurve_curve_samples(ac, NULL, fcu, &region->v2d, shdr_pos, draw_extrapolation);
}
immUnbindProgram();