Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tcubicbezier.h"
Toshihiro Shimizu 890ddd
#include "tundo.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tdoublekeyframe.h"
Toshihiro Shimizu 890ddd
#include "tdoubleparamfile.h"
Toshihiro Shimizu 890ddd
#include "texpression.h"
Toshihiro Shimizu 890ddd
#include "tgrammar.h"
Toshihiro Shimizu 890ddd
#include "tparser.h"
Toshihiro Shimizu 890ddd
#include "tunit.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// STD includes
Toshihiro Shimizu 890ddd
#include <set></set>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tdoubleparam.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===============================
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class TActualDoubleKeyframe final : public TDoubleKeyframe {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  mutable TExpression m_expression;
Shinya Kitaoka 120a6e
  mutable TDoubleParamFileData m_fileData;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TActualDoubleKeyframe(double frame = 0, double value = 0)
Shinya Kitaoka 120a6e
      : TDoubleKeyframe(frame, value), m_unit(0) {}
Shinya Kitaoka 120a6e
  explicit TActualDoubleKeyframe(const TDoubleKeyframe &src) : m_unit(0) {
Shinya Kitaoka 120a6e
    TDoubleKeyframe::operator=(src);
Shinya Kitaoka 120a6e
    if (m_type == Expression || m_type == SimilarShape)
Shinya Kitaoka 120a6e
      m_expression.setText(m_expressionText);
Shinya Kitaoka 120a6e
    else if (m_type == File)
Shinya Kitaoka 120a6e
      m_fileData.setParams(m_fileParams);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TActualDoubleKeyframe &operator=(const TDoubleKeyframe &src) {
Shinya Kitaoka 120a6e
    TDoubleKeyframe::operator=(src);
Shinya Kitaoka 120a6e
    m_unit                   = 0;
Shinya Kitaoka 120a6e
    if (m_type == Expression || m_type == SimilarShape) {
Shinya Kitaoka 120a6e
      m_expression.setText(m_expressionText);
Shinya Kitaoka 120a6e
    } else if (m_type == File) {
Shinya Kitaoka 120a6e
      m_fileData.setParams(m_fileParams);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    return *this;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const TUnit *updateUnit(const TMeasure *measure) {
Shinya Kitaoka 120a6e
    if (!measure) {
Shinya Kitaoka 120a6e
      m_unit     = 0;
Shinya Kitaoka 120a6e
      m_unitName = "";
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      if (m_unitName != "")
Shinya Kitaoka 120a6e
        m_unit = measure->getUnit(::to_wstring(m_unitName));
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        m_unit = 0;
Shinya Kitaoka 120a6e
      if (!m_unit) {
Shinya Kitaoka 120a6e
        m_unit = measure->getCurrentUnit();
Shinya Kitaoka 120a6e
        if (m_unit) {
Shinya Kitaoka 120a6e
          QString app = QString::fromStdWString(m_unit->getDefaultExtension());
Shinya Kitaoka 120a6e
          m_unitName  = app.toStdString();
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    assert(measure || m_unit == 0 && m_unitName == "");
Shinya Kitaoka 120a6e
    assert((m_unit == 0) == (m_unitName == ""));
Shinya Kitaoka 120a6e
    QString app = QString::fromStdString(m_unitName);
Shinya Kitaoka 120a6e
    assert(m_unit == 0 || m_unit->isExtension(app.toStdWString()));
Shinya Kitaoka 120a6e
    return m_unit;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double convertFrom(TMeasure *measure, double value) const {
Shinya Kitaoka 120a6e
    if (!m_unit) const_cast<tactualdoublekeyframe *="">(this)->updateUnit(measure);</tactualdoublekeyframe>
Shinya Kitaoka 120a6e
    if (m_unit) value = m_unit->convertFrom(value);
Shinya Kitaoka 120a6e
    return value;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  mutable const TUnit *m_unit;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef vector<tactualdoublekeyframe> DoubleKeyframeVector;</tactualdoublekeyframe>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline double getConstantValue(const TActualDoubleKeyframe &k0,
Shinya Kitaoka 120a6e
                               const TActualDoubleKeyframe &k1, double f) {
Shinya Kitaoka 120a6e
  return (f == k1.m_frame) ? k1.m_value : k0.m_value;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline double getLinearValue(const TActualDoubleKeyframe &k0,
Shinya Kitaoka 120a6e
                             const TActualDoubleKeyframe &k1, double f) {
Shinya Kitaoka 120a6e
  return k0.m_value +
Shinya Kitaoka 120a6e
         (f - k0.m_frame) * (k1.m_value - k0.m_value) /
Shinya Kitaoka 120a6e
             (k1.m_frame - k0.m_frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Campbell Barton 8c6c57
static void truncateSpeeds(double aFrame, double bFrame, TPointD &aSpeedTrunc,
Campbell Barton 8c6c57
                           TPointD &bSpeedTrunc) {
Shinya Kitaoka 120a6e
  double deltaX                        = bFrame - aFrame;
Shinya Kitaoka 120a6e
  if (aSpeedTrunc.x < 0) aSpeedTrunc.x = 0;
Shinya Kitaoka 120a6e
  if (bSpeedTrunc.x > 0) bSpeedTrunc.x = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (aFrame + aSpeedTrunc.x > bFrame) {
Shinya Kitaoka 120a6e
    if (aSpeedTrunc.x != 0) {
Shinya Kitaoka 120a6e
      aSpeedTrunc = aSpeedTrunc * (deltaX / aSpeedTrunc.x);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (bFrame + bSpeedTrunc.x < aFrame) {
Shinya Kitaoka 120a6e
    if (bSpeedTrunc.x != 0) {
Shinya Kitaoka 120a6e
      bSpeedTrunc = -bSpeedTrunc * (deltaX / bSpeedTrunc.x);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline double getSpeedInOutValue(const TActualDoubleKeyframe &k0,
Shinya Kitaoka 120a6e
                                 const TActualDoubleKeyframe &k1,
Shinya Kitaoka 120a6e
                                 const TPointD &speed0, const TPointD &speed1,
Shinya Kitaoka 120a6e
                                 double frame) {
Shinya Kitaoka 120a6e
  double aFrame = k0.m_frame;
Shinya Kitaoka 120a6e
  double bFrame = k1.m_frame;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double aValue = k0.m_value;
Shinya Kitaoka 120a6e
  double bValue = k1.m_value;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (frame <= aFrame)
Shinya Kitaoka 120a6e
    return aValue;
Shinya Kitaoka 120a6e
  else if (frame >= bFrame)
Shinya Kitaoka 120a6e
    return bValue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPointD aSpeedTrunc = speed0;
Shinya Kitaoka 120a6e
  TPointD bSpeedTrunc = speed1;
Shinya Kitaoka 120a6e
  truncateSpeeds(aFrame, bFrame, aSpeedTrunc, bSpeedTrunc);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return getCubicBezierY(frame, TPointD(aFrame, aValue), aSpeedTrunc,
Shinya Kitaoka 120a6e
                         bSpeedTrunc, TPointD(bFrame, bValue));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
DV_EXPORT_API void splitSpeedInOutSegment(TDoubleKeyframe &k,
Shinya Kitaoka 120a6e
                                          TDoubleKeyframe &k0,
Shinya Kitaoka 120a6e
                                          TDoubleKeyframe &k1) {
Shinya Kitaoka 120a6e
  if (k.m_frame <= k0.m_frame) {
Shinya Kitaoka 120a6e
    k = k0;
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  } else if (k.m_frame >= k1.m_frame) {
Shinya Kitaoka 120a6e
    k = k1;
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD aSpeed = k0.m_speedOut;
Shinya Kitaoka 120a6e
  TPointD bSpeed = k1.m_speedIn;
Shinya Kitaoka 120a6e
  truncateSpeeds(k0.m_frame, k1.m_frame, aSpeed, bSpeed);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD p0(k0.m_frame, k0.m_value);
Shinya Kitaoka 120a6e
  TPointD p3(k1.m_frame, k1.m_value);
Shinya Kitaoka 120a6e
  TPointD p1 = p0 + aSpeed;
Shinya Kitaoka 120a6e
  TPointD p2 = p3 + bSpeed;
Shinya Kitaoka 120a6e
  double t   = invCubicBezierX(k.m_frame, p0, aSpeed, bSpeed, p3);
Shinya Kitaoka 120a6e
  t          = tcrop(t, 0.0, 1.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD p01 = (1 - t) * p0 + t * p1;
Shinya Kitaoka 120a6e
  TPointD p12 = (1 - t) * p1 + t * p2;
Shinya Kitaoka 120a6e
  TPointD p23 = (1 - t) * p2 + t * p3;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD p012 = (1 - t) * p01 + t * p12;
Shinya Kitaoka 120a6e
  TPointD p123 = (1 - t) * p12 + t * p23;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD p = (1 - t) * p012 + t * p123;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(fabs(p.x - k.m_frame) < 0.1e-3);
Shinya Kitaoka 120a6e
  k.m_value = p.y;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  k0.m_speedOut = p01 - p0;
Shinya Kitaoka 120a6e
  k.m_speedIn   = p012 - p;
Shinya Kitaoka 120a6e
  k.m_speedOut  = p123 - p;
Shinya Kitaoka 120a6e
  k1.m_speedIn  = p23 - p3;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline double getEaseInOutValue(const TActualDoubleKeyframe &k0,
Shinya Kitaoka 120a6e
                                const TActualDoubleKeyframe &k1, double frame,
Shinya Kitaoka 120a6e
                                bool percentage) {
Shinya Kitaoka 120a6e
  double x3 = k1.m_frame - k0.m_frame;
Shinya Kitaoka 120a6e
  if (x3 <= 0.0) return k0.m_value;
Shinya Kitaoka 120a6e
  double x = frame - k0.m_frame;
Shinya Kitaoka 120a6e
  if (x <= 0)
Shinya Kitaoka 120a6e
    return k0.m_value;
Shinya Kitaoka 120a6e
  else if (x >= x3)
Shinya Kitaoka 120a6e
    return k1.m_value;
Shinya Kitaoka 120a6e
  double e0 = std::max(k0.m_speedOut.x, 0.0);
Shinya Kitaoka 120a6e
  double e1 = std::max(-k1.m_speedIn.x, 0.0);
Shinya Kitaoka 120a6e
  if (percentage) {
Shinya Kitaoka 120a6e
    e0 *= x3 * 0.01;
Shinya Kitaoka 120a6e
    e1 *= x3 * 0.01;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (e0 + e1 >= x3) {
Shinya Kitaoka 120a6e
    double x = tcrop((e0 + x3 - e1) / 2, 0.0, x3);
Shinya Kitaoka 120a6e
    e0       = x;
Shinya Kitaoka 120a6e
    e1       = x3 - x;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  double x1 = e0, x2 = x3 - e1;
Shinya Kitaoka 120a6e
  if (0 < x1 - x2 && x1 - x2 < 0.1e-5)
Shinya Kitaoka 120a6e
    x1 = x2 = (x1 + x2) * 0.5;  // against rounding problems
Shinya Kitaoka 120a6e
  assert(0 <= x1 && x1 <= x2 && x2 <= x3);
Shinya Kitaoka 120a6e
  double v     = 2 / (x3 + x2 - x1);
Shinya Kitaoka 120a6e
  double value = 0;
Shinya Kitaoka 120a6e
  if (x < x1) {
Shinya Kitaoka 120a6e
    double a = v / e0;
Shinya Kitaoka 120a6e
    value    = 0.5 * a * x * x;
Shinya Kitaoka 120a6e
  } else if (x > x2) {
Shinya Kitaoka 120a6e
    double a = v / e1;
Shinya Kitaoka 120a6e
    value    = 1 - 0.5 * a * (x3 - x) * (x3 - x);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    double c = -0.5 * v * e0;
Shinya Kitaoka 120a6e
    value    = x * v + c;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return (1 - value) * k0.m_value + value * k1.m_value;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline double getExponentialValue(const TActualDoubleKeyframe &k0,
Shinya Kitaoka 120a6e
                                  const TActualDoubleKeyframe &k1,
Shinya Kitaoka 120a6e
                                  double frame) {
Shinya Kitaoka 120a6e
  double aFrame = k0.m_frame;
Shinya Kitaoka 120a6e
  double bFrame = k1.m_frame;
Shinya Kitaoka 120a6e
  double deltaX = bFrame - aFrame;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double aValue = k0.m_value;
Shinya Kitaoka 120a6e
  double bValue = k1.m_value;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // if min(aValue,bValue)<=0 => error => linear
Shinya Kitaoka 120a6e
  if (aValue <= 0 || bValue <= 0) return getLinearValue(k0, k1, frame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double t = (frame - aFrame) / deltaX;
Shinya Kitaoka 120a6e
  // if aValue
Shinya Kitaoka 120a6e
  // if bValue
Shinya Kitaoka 120a6e
  if (bValue < aValue) {
Shinya Kitaoka 120a6e
    t = 1 - t;
otakuto ed7dcd
    std::swap(aValue, bValue);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return aValue * exp(t * log(bValue / aValue));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline double getExpressionValue(const TActualDoubleKeyframe &k0,
Shinya Kitaoka 120a6e
                                 const TActualDoubleKeyframe &k1, double frame,
Shinya Kitaoka 120a6e
                                 const TMeasure *measure) {
Shinya Kitaoka 120a6e
  double t = 0, rframe = frame - k0.m_frame;
Shinya Kitaoka 120a6e
  if (k1.m_frame > k0.m_frame) t  = rframe / (k1.m_frame - k0.m_frame);
Shinya Kitaoka 120a6e
  TSyntax::Calculator *calculator = k0.m_expression.getCalculator();
Shinya Kitaoka 120a6e
  if (calculator) {
Shinya Kitaoka 120a6e
    calculator->setUnit(
Shinya Kitaoka 120a6e
        (const_cast<tactualdoublekeyframe &="">(k0)).updateUnit(measure));</tactualdoublekeyframe>
Shinya Kitaoka 120a6e
    return calculator->compute(t, frame + 1, rframe + 1);
Shinya Kitaoka 120a6e
  } else if (measure)
Shinya Kitaoka 120a6e
    return measure->getDefaultValue();
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline double getSimilarShapeValue(const TActualDoubleKeyframe &k0,
Shinya Kitaoka 120a6e
                                   const TActualDoubleKeyframe &k1,
Shinya Kitaoka 120a6e
                                   double frame, const TMeasure *measure) {
Shinya Kitaoka 120a6e
  double offset = k0.m_similarShapeOffset;
Shinya Kitaoka 120a6e
  double rv0    = getExpressionValue(k0, k1, k0.m_frame + offset, measure);
Shinya Kitaoka 120a6e
  double rv1    = getExpressionValue(k0, k1, k1.m_frame + offset, measure);
Shinya Kitaoka 120a6e
  double rv     = getExpressionValue(k0, k1, frame + offset, measure);
Shinya Kitaoka 120a6e
  double v0     = k0.m_value;
Shinya Kitaoka 120a6e
  double v1     = k1.m_value;
Shinya Kitaoka 120a6e
  if (rv1 != rv0)
Shinya Kitaoka 120a6e
    return v0 + (v1 - v0) * (rv - rv0) / (rv1 - rv0);
Shinya Kitaoka 120a6e
  else if (measure)
Shinya Kitaoka 120a6e
    return measure->getDefaultValue();
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TDoubleParam::Imp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  const TSyntax::Grammar *m_grammar;
Shinya Kitaoka 120a6e
  string m_measureName;
Shinya Kitaoka 120a6e
  TMeasure *m_measure;
Shinya Kitaoka 120a6e
  double m_defaultValue, m_minValue, m_maxValue;
Shinya Kitaoka 120a6e
  DoubleKeyframeVector m_keyframes;
Shinya Kitaoka 120a6e
  bool m_cycleEnabled;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::set<tparamobserver *=""> m_observers;</tparamobserver>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Imp(double v = 0.0)
Shinya Kitaoka 120a6e
      : m_grammar(0)
Shinya Kitaoka 120a6e
      , m_measureName()
Shinya Kitaoka 120a6e
      , m_measure(0)
Shinya Kitaoka 120a6e
      , m_defaultValue(v)
Shinya Kitaoka 120a6e
      , m_minValue(-(std::numeric_limits<double>::max)())</double>
Shinya Kitaoka 120a6e
      , m_maxValue((std::numeric_limits<double>::max)())</double>
Shinya Kitaoka 120a6e
      , m_cycleEnabled(false) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~Imp() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void copy(std::unique_ptr<imp> const &src) {</imp>
Shinya Kitaoka 120a6e
    m_grammar      = src->m_grammar;
Shinya Kitaoka 120a6e
    m_measureName  = src->m_measureName;
Shinya Kitaoka 120a6e
    m_measure      = src->m_measure;
Shinya Kitaoka 120a6e
    m_defaultValue = src->m_defaultValue;
Shinya Kitaoka 120a6e
    m_minValue     = src->m_minValue;
Shinya Kitaoka 120a6e
    m_maxValue     = src->m_maxValue;
Shinya Kitaoka 120a6e
    m_keyframes    = src->m_keyframes;
Shinya Kitaoka 120a6e
    m_cycleEnabled = src->m_cycleEnabled;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void notify(const TParamChange &change) {
Shinya Kitaoka 120a6e
    std::set<tparamobserver *="">::iterator it = m_observers.begin();</tparamobserver>
Shinya Kitaoka 120a6e
    for (; it != m_observers.end(); ++it) (*it)->onChange(change);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double getValue(int segmentIndex, double frame);
Shinya Kitaoka 120a6e
  double getSpeed(int segmentIndex, double frame);
Shinya Kitaoka 120a6e
  TPointD getSpeedIn(int kIndex);
Shinya Kitaoka 120a6e
  TPointD getSpeedOut(int kIndex);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
double TDoubleParam::Imp::getValue(int segmentIndex, double frame) {
Shinya Kitaoka 120a6e
  assert(0 <= segmentIndex && segmentIndex + 1 < (int)m_keyframes.size());
Shinya Kitaoka 120a6e
  const TActualDoubleKeyframe &k0 = m_keyframes[segmentIndex];
Shinya Kitaoka 120a6e
  const TActualDoubleKeyframe &k1 = m_keyframes[segmentIndex + 1];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double value     = m_defaultValue;
Shinya Kitaoka 120a6e
  bool convertUnit = false;
Shinya Kitaoka 120a6e
  switch (k0.m_type) {
Shinya Kitaoka 120a6e
  case TDoubleKeyframe::Constant:
Shinya Kitaoka 120a6e
    value = getConstantValue(k0, k1, frame);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TDoubleKeyframe::Linear:
Shinya Kitaoka 120a6e
    value = getLinearValue(k0, k1, frame);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TDoubleKeyframe::SpeedInOut:
Shinya Kitaoka 120a6e
    value = getSpeedInOutValue(k0, k1, getSpeedOut(segmentIndex),
Shinya Kitaoka 120a6e
                               getSpeedIn(segmentIndex + 1), frame);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TDoubleKeyframe::EaseInOut:
Shinya Kitaoka 120a6e
    value = getEaseInOutValue(k0, k1, frame, false);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TDoubleKeyframe::EaseInOutPercentage:
Shinya Kitaoka 120a6e
    value = getEaseInOutValue(k0, k1, frame, true);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TDoubleKeyframe::Exponential:
Shinya Kitaoka 120a6e
    value = getExponentialValue(k0, k1, frame);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TDoubleKeyframe::Expression:
Shinya Kitaoka 120a6e
    value       = getExpressionValue(k0, k1, frame, m_measure);
Shinya Kitaoka 120a6e
    convertUnit = true;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TDoubleKeyframe::File:
Shinya Kitaoka 120a6e
    value       = k0.m_fileData.getValue(frame, m_defaultValue);
Shinya Kitaoka 120a6e
    convertUnit = true;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TDoubleKeyframe::SimilarShape:
Shinya Kitaoka 120a6e
    value = getSimilarShapeValue(k0, k1, frame, m_measure);
Shinya Kitaoka 120a6e
    break;
Rozhuk Ivan 823a31
  default:
Rozhuk Ivan 823a31
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (convertUnit) value = k0.convertFrom(m_measure, value);
Shinya Kitaoka 120a6e
  return value;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
double TDoubleParam::Imp::getSpeed(int segmentIndex, double frame) {
Shinya Kitaoka 120a6e
  const double h = 0.00001;
Shinya Kitaoka 120a6e
  return (getValue(segmentIndex, frame + h) -
Shinya Kitaoka 120a6e
          getValue(segmentIndex, frame - h)) /
Shinya Kitaoka 120a6e
         (2 * h);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPointD TDoubleParam::Imp::getSpeedIn(int kIndex) {
Shinya Kitaoka 120a6e
  assert(1 <= kIndex && kIndex < (int)m_keyframes.size());
Shinya Kitaoka 120a6e
  const TActualDoubleKeyframe &kf0 = m_keyframes[kIndex - 1];
Shinya Kitaoka 120a6e
  const TActualDoubleKeyframe &kf1 = m_keyframes[kIndex];
Shinya Kitaoka 120a6e
  assert(kf0.m_type == TDoubleKeyframe::SpeedInOut);
Shinya Kitaoka 120a6e
  if (!kf1.m_linkedHandles) return kf1.m_speedIn;
Shinya Kitaoka 120a6e
  TPointD speedIn = kf1.m_speedIn;
Shinya Kitaoka 120a6e
  if (kIndex + 1 >= (int)m_keyframes.size()) {
Shinya Kitaoka 120a6e
    // speedIn.y = 0;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (kf1.m_type != TDoubleKeyframe::SpeedInOut &&
Shinya Kitaoka 120a6e
        (kf1.m_type != TDoubleKeyframe::Expression ||
Shinya Kitaoka 120a6e
         !kf1.m_expression.isCycling())) {
Shinya Kitaoka 120a6e
      double speed = getSpeed(kIndex, kf1.m_frame);
Shinya Kitaoka 120a6e
      speedIn.y    = speedIn.x * speed;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return speedIn;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPointD TDoubleParam::Imp::getSpeedOut(int kIndex) {
Shinya Kitaoka 120a6e
  assert(0 <= kIndex && kIndex < (int)m_keyframes.size());
Shinya Kitaoka 120a6e
  const TDoubleKeyframe &kf1 = m_keyframes[kIndex];
Shinya Kitaoka 120a6e
  assert(kf1.m_type == TDoubleKeyframe::SpeedInOut);
Shinya Kitaoka 120a6e
  if (!kf1.m_linkedHandles) return kf1.m_speedOut;
Shinya Kitaoka 120a6e
  TPointD speedOut = kf1.m_speedOut;
Shinya Kitaoka 120a6e
  if (kIndex == 0) {
Shinya Kitaoka 120a6e
    // speedOut.y = 0;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    const TDoubleKeyframe &kf0 = m_keyframes[kIndex - 1];
Shinya Kitaoka 120a6e
    if (kf0.m_type != TDoubleKeyframe::SpeedInOut) {
Shinya Kitaoka 120a6e
      double speed = getSpeed(kIndex - 1, kf1.m_frame);
Shinya Kitaoka 120a6e
      speedOut.y   = speedOut.x * speed;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return speedOut;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPointD TDoubleParam::getSpeedIn(int kIndex) const {
Shinya Kitaoka 120a6e
  return m_imp->getSpeedIn(kIndex);
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
TPointD TDoubleParam::getSpeedOut(int kIndex) const {
Shinya Kitaoka 120a6e
  return m_imp->getSpeedOut(kIndex);
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PERSIST_IDENTIFIER(TDoubleParam, "doubleParam")
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TDoubleParam::TDoubleParam(double v) : m_imp(new TDoubleParam::Imp(v)) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TDoubleParam::TDoubleParam(const TDoubleParam &src)
Shinya Kitaoka 120a6e
    : TParam(src.getName()), m_imp(new TDoubleParam::Imp()) {
Shinya Kitaoka 120a6e
  m_imp->copy(src.m_imp);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TDoubleParam::~TDoubleParam() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TDoubleParam &TDoubleParam::operator=(const TDoubleParam &dp) {
Shinya Kitaoka 120a6e
  setName(dp.getName());
Shinya Kitaoka 120a6e
  m_imp->copy(dp.m_imp);
Shinya Kitaoka 120a6e
  return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::copy(TParam *src) {
Shinya Kitaoka 120a6e
  TDoubleParam *p = dynamic_cast<tdoubleparam *="">(src);</tdoubleparam>
Shinya Kitaoka 120a6e
  if (!p) throw TException("invalid source for copy");
Shinya Kitaoka 120a6e
  setName(src->getName());
Shinya Kitaoka 120a6e
  m_imp->copy(p->m_imp);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->notify(TParamChange(this, 0, 0, true, false, false));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::setValueRange(double min, double max, double step) {
Shinya Kitaoka 120a6e
  if (min > max) min = max;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->m_minValue = min;
Shinya Kitaoka 120a6e
  m_imp->m_maxValue = max;
Shinya Kitaoka 120a6e
  // m_imp->m_valueStep = step;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TDoubleParam::getValueRange(double &min, double &max, double &step) const {
Shinya Kitaoka 120a6e
  min  = m_imp->m_minValue;
Shinya Kitaoka 120a6e
  max  = m_imp->m_maxValue;
Shinya Kitaoka 120a6e
  step = 1;  // m_imp->m_valueStep;
Shinya Kitaoka 120a6e
  return min < max;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
double TDoubleParam::getDefaultValue() const {
Shinya Kitaoka 120a6e
  assert(m_imp);
Shinya Kitaoka 120a6e
  return m_imp->m_defaultValue;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::enableCycle(bool enabled) {
Shinya Kitaoka 120a6e
  m_imp->m_cycleEnabled = enabled;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->notify(TParamChange(this, 0, 0, true, false, false));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TDoubleParam::isCycleEnabled() const { return m_imp->m_cycleEnabled; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
double TDoubleParam::getValue(double frame, bool leftmost) const {
Shinya Kitaoka 120a6e
  double value = 0;
Shinya Kitaoka 120a6e
  assert(m_imp);
Shinya Kitaoka 120a6e
  const DoubleKeyframeVector &keyframes = m_imp->m_keyframes;
Shinya Kitaoka 120a6e
  if (keyframes.empty()) {
Shinya Kitaoka 120a6e
    // no keyframes: return the default value
Shinya Kitaoka 120a6e
    value = m_imp->m_defaultValue;
Shinya Kitaoka 120a6e
  } else if (keyframes.size() == 1) {
Shinya Kitaoka 120a6e
    // a single keyframe. Type must be keyframe based (no expression/file)
Shinya Kitaoka 120a6e
    value = keyframes[0].m_value;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    // keyframes range is [f0,f1]
Shinya Kitaoka 120a6e
    double f0 = keyframes.begin()->m_frame;
Shinya Kitaoka 120a6e
    double f1 = keyframes.back().m_frame;
Shinya Kitaoka 120a6e
    if (frame < f0)
Shinya Kitaoka 120a6e
      frame = f0;
Shinya Kitaoka 120a6e
    else if (frame > f1 && !m_imp->m_cycleEnabled)
Shinya Kitaoka 120a6e
      frame            = f1;
Shinya Kitaoka 120a6e
    double valueOffset = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_imp->m_cycleEnabled) {
Shinya Kitaoka 120a6e
      double dist   = (f1 - f0);
Shinya Kitaoka 120a6e
      double dvalue = keyframes.back().m_value - keyframes.begin()->m_value;
Shinya Kitaoka 120a6e
      while (frame >= f1) {
Shinya Kitaoka 120a6e
        if (frame != f1 || !leftmost) {
Shinya Kitaoka 120a6e
          frame -= dist;
Shinya Kitaoka 120a6e
          valueOffset += dvalue;
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // frame is in [f0,f1]
Shinya Kitaoka 120a6e
    assert(f0 <= frame && frame <= f1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    DoubleKeyframeVector::const_iterator b;
Shinya Kitaoka 120a6e
    b = std::lower_bound(keyframes.begin(), keyframes.end(),
Shinya Kitaoka 120a6e
                         TDoubleKeyframe(frame));
Shinya Kitaoka 120a6e
    assert(b != keyframes.end());
Shinya Kitaoka 120a6e
    DoubleKeyframeVector::const_iterator a;
Shinya Kitaoka 120a6e
    if (b->m_frame == frame && (b + 1) != keyframes.end()) {
Shinya Kitaoka 120a6e
      a = b;
Shinya Kitaoka 120a6e
      b++;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      assert(b != keyframes.begin());
Shinya Kitaoka 120a6e
      a = b - 1;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (leftmost && frame - a->m_frame < 0.00001 && a != keyframes.begin()) {
Shinya Kitaoka 120a6e
      a--;
Shinya Kitaoka 120a6e
      b--;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // segment (a,b) contains frame
Shinya Kitaoka 120a6e
    assert(a != keyframes.end());
Shinya Kitaoka 120a6e
    assert(b != keyframes.end());
Shinya Kitaoka 120a6e
    assert(a->m_frame <= frame);
Shinya Kitaoka 120a6e
    assert(b->m_frame >= frame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int kIndex = std::distance(keyframes.begin(), a);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    vector<tactualdoublekeyframe> tmpKeyframe(3);</tactualdoublekeyframe>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // if segment is keyframe based ....
Shinya Kitaoka 120a6e
    if (TDoubleKeyframe::isKeyframeBased(a->m_type)) {
Shinya Kitaoka 120a6e
      // .. and next segment is not then update the b value
Shinya Kitaoka 120a6e
      if ((b + 1) != keyframes.end() &&
Shinya Kitaoka 120a6e
          !TDoubleKeyframe::isKeyframeBased(b->m_type)) {
Shinya Kitaoka 120a6e
        tmpKeyframe[0] = *b;
Shinya Kitaoka 120a6e
        if (b->m_type != TDoubleKeyframe::Expression ||
Shinya Kitaoka 120a6e
            !b->m_expression.isCycling())
Shinya Kitaoka 120a6e
          tmpKeyframe[0].m_value = getValue(b->m_frame);
Shinya Kitaoka 120a6e
        b                        = tmpKeyframe.begin();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      // .. and/or if prev segment is not then update the a value
Shinya Kitaoka 120a6e
      if (a != keyframes.begin() &&
Shinya Kitaoka 120a6e
          !TDoubleKeyframe::isKeyframeBased(a[-1].m_type)) {
Shinya Kitaoka 120a6e
        tmpKeyframe[1]         = *a;
Shinya Kitaoka 120a6e
        tmpKeyframe[1].m_value = getValue(a->m_frame, true);
Shinya Kitaoka 120a6e
        a                      = tmpKeyframe.begin() + 1;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (a->m_step > 1) {
Shinya Kitaoka 120a6e
      tmpKeyframe[2] = *b;
Shinya Kitaoka 120a6e
      b              = tmpKeyframe.begin() + 2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int relPos = tfloor(b->m_frame - a->m_frame),
Shinya Kitaoka 120a6e
          step   = std::min(a->m_step, relPos);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      tmpKeyframe[2].m_frame        = a->m_frame + tfloor(relPos, step);
Shinya Kitaoka 120a6e
      if (frame > b->m_frame) frame = b->m_frame;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      frame = a->m_frame + tfloor(tfloor(frame - a->m_frame), step);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    assert(0 <= kIndex && kIndex + 1 < (int)m_imp->m_keyframes.size());
Shinya Kitaoka 120a6e
    value            = m_imp->m_defaultValue;
Shinya Kitaoka 120a6e
    bool convertUnit = false;
Shinya Kitaoka 120a6e
    switch (a->m_type) {
Shinya Kitaoka 120a6e
    case TDoubleKeyframe::Constant:
Shinya Kitaoka 120a6e
      value = getConstantValue(*a, *b, frame);
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    case TDoubleKeyframe::Linear:
Shinya Kitaoka 120a6e
      value = getLinearValue(*a, *b, frame);
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    case TDoubleKeyframe::SpeedInOut:
Shinya Kitaoka 120a6e
      value = getSpeedInOutValue(*a, *b, getSpeedOut(kIndex),
Shinya Kitaoka 120a6e
                                 getSpeedIn(kIndex + 1), frame);
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    case TDoubleKeyframe::EaseInOut:
Shinya Kitaoka 120a6e
      value = getEaseInOutValue(*a, *b, frame, false);
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    case TDoubleKeyframe::EaseInOutPercentage:
Shinya Kitaoka 120a6e
      value = getEaseInOutValue(*a, *b, frame, true);
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    case TDoubleKeyframe::Exponential:
Shinya Kitaoka 120a6e
      value = getExponentialValue(*a, *b, frame);
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    case TDoubleKeyframe::Expression:
Shinya Kitaoka 120a6e
      value       = getExpressionValue(*a, *b, frame, m_imp->m_measure);
Shinya Kitaoka 120a6e
      convertUnit = true;
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    case TDoubleKeyframe::File:
Shinya Kitaoka 120a6e
      value       = a->m_fileData.getValue(frame, m_imp->m_defaultValue);
Shinya Kitaoka 120a6e
      convertUnit = true;
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    case TDoubleKeyframe::SimilarShape:
Shinya Kitaoka 120a6e
      value = getSimilarShapeValue(*a, *b, frame, m_imp->m_measure);
Shinya Kitaoka 120a6e
      // convertUnit = true;
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    default:
Shinya Kitaoka 120a6e
      value = 0.0;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    value += valueOffset;
Shinya Kitaoka 120a6e
    if (convertUnit) value = a->convertFrom(m_imp->m_measure, value);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // if (cropped)
Shinya Kitaoka 120a6e
  //  value = tcrop(value, m_imp->m_minValue, m_imp->m_maxValue);
Shinya Kitaoka 120a6e
  return value;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TDoubleParam::setValue(double frame, double value) {
Shinya Kitaoka 120a6e
  assert(m_imp);
Shinya Kitaoka 120a6e
  DoubleKeyframeVector &keyframes = m_imp->m_keyframes;
Shinya Kitaoka 120a6e
  DoubleKeyframeVector::iterator it;
Shinya Kitaoka 120a6e
  TActualDoubleKeyframe k(frame);
Shinya Kitaoka 120a6e
  it           = std::lower_bound(keyframes.begin(), keyframes.end(), k);
Shinya Kitaoka 120a6e
  int index    = 0;
Shinya Kitaoka 120a6e
  bool created = false;
Shinya Kitaoka 120a6e
  /*-- キーフレームが見つかった場合 --*/
Shinya Kitaoka 120a6e
  if (it != keyframes.end() && it->m_frame == frame) {
Shinya Kitaoka 120a6e
    // changing a keyframe value
Shinya Kitaoka 120a6e
    index                             = std::distance(keyframes.begin(), it);
Shinya Kitaoka 120a6e
    TActualDoubleKeyframe oldKeyframe = *it;
Shinya Kitaoka 120a6e
    if (oldKeyframe.m_type == TDoubleKeyframe::Expression ||
Shinya Kitaoka 120a6e
        oldKeyframe.m_type == TDoubleKeyframe::File)
Shinya Kitaoka 120a6e
      return false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    it->m_value = value;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_imp->notify(TParamChange(this, 0, 0, true, false, false));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  /*-- セグメントの部分なので、新たにキーフレームを作る --*/
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    assert(it == keyframes.end() || it->m_frame > frame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // can't change value in a file/expression segment
Shinya Kitaoka 120a6e
    if (it != keyframes.end() && it > keyframes.begin() &&
Shinya Kitaoka 120a6e
        ((it - 1)->m_type == TDoubleKeyframe::Expression ||
Shinya Kitaoka 120a6e
         (it - 1)->m_type == TDoubleKeyframe::File))
Shinya Kitaoka 120a6e
      return false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // inserting a new keyframe
Shinya Kitaoka 120a6e
    k.m_value      = value;
Shinya Kitaoka 120a6e
    k.m_isKeyframe = true;
Shinya Kitaoka 120a6e
    k.m_expression.setGrammar(m_imp->m_grammar);
Shinya Kitaoka 120a6e
    k.m_expression.setOwnerParameter(this);
Shinya Kitaoka 120a6e
    it = keyframes.insert(it, k);
Shinya Kitaoka 120a6e
    if (it == keyframes.begin())
Shinya Kitaoka 120a6e
      it->m_prevType = TDoubleKeyframe::None;
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      it->m_prevType = it[-1].m_type;
Shinya Kitaoka 120a6e
      /*-- FxGuiでSegment内にKeyを打った場合は、Step値も引き継ぐ --*/
Shinya Kitaoka 120a6e
      it->m_step = it[-1].m_step;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (it + 1 != keyframes.end()) it[1].m_prevType = it->m_type;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    index = std::distance(keyframes.begin(), it);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_imp->notify(TParamChange(this, 0, 0, true, false, false));
Shinya Kitaoka 120a6e
    created = true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  assert(0 == index || keyframes[index - 1].m_frame < keyframes[index].m_frame);
Shinya Kitaoka 120a6e
  assert(getKeyframeCount() - 1 == index ||
Shinya Kitaoka 120a6e
         keyframes[index + 1].m_frame > keyframes[index].m_frame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return created;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::setKeyframe(int index, const TDoubleKeyframe &k) {
Shinya Kitaoka 120a6e
  DoubleKeyframeVector &keyframes = m_imp->m_keyframes;
Shinya Kitaoka 120a6e
  assert(0 <= index && index < (int)keyframes.size());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TActualDoubleKeyframe &dst        = keyframes[index];
Shinya Kitaoka 120a6e
  TActualDoubleKeyframe oldKeyframe = dst;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  (TDoubleKeyframe &)dst = k;
Shinya Kitaoka 120a6e
  dst.updateUnit(m_imp->m_measure);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (dst.m_type == TDoubleKeyframe::Expression ||
Shinya Kitaoka 120a6e
      dst.m_type == TDoubleKeyframe::SimilarShape)
Shinya Kitaoka 120a6e
    dst.m_expression.setText(dst.m_expressionText);
Shinya Kitaoka 120a6e
  if (dst.m_type == TDoubleKeyframe::File)
Shinya Kitaoka 120a6e
    dst.m_fileData.setParams(dst.m_fileParams);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->notify(TParamChange(this, 0, 0, true, false, false));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(0 == index || keyframes[index - 1].m_frame < keyframes[index].m_frame);
Shinya Kitaoka 120a6e
  assert(getKeyframeCount() - 1 == index ||
Shinya Kitaoka 120a6e
         keyframes[index + 1].m_frame > keyframes[index].m_frame);
Shinya Kitaoka 120a6e
  if (index == 0)
Shinya Kitaoka 120a6e
    dst.m_prevType = TDoubleKeyframe::None;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    dst.m_prevType = keyframes[index - 1].m_type;
DoctorRyan ac3cab
DoctorRyan ac3cab
 if (getKeyframeCount() - 1 != index)
DoctorRyan ac3cab
    keyframes[index + 1].m_prevType = dst.m_type;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::setKeyframes(const std::map<int, tdoublekeyframe=""> &ks) {</int,>
Shinya Kitaoka 120a6e
  DoubleKeyframeVector &keyframes = m_imp->m_keyframes;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::map<int, tdoublekeyframe="">::const_iterator it;</int,>
Shinya Kitaoka 120a6e
  for (it = ks.begin(); it != ks.end(); ++it) {
Shinya Kitaoka 120a6e
    int index = it->first;
Shinya Kitaoka 120a6e
    assert(0 <= index && index < (int)keyframes.size());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TActualDoubleKeyframe oldKeyframe = keyframes[index];
Shinya Kitaoka 120a6e
    TActualDoubleKeyframe &dst        = keyframes[index];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    (TDoubleKeyframe &)dst = it->second;
Shinya Kitaoka 120a6e
    dst.updateUnit(m_imp->m_measure);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (dst.m_type == TDoubleKeyframe::Expression ||
Shinya Kitaoka 120a6e
        dst.m_type == TDoubleKeyframe::SimilarShape)
Shinya Kitaoka 120a6e
      dst.m_expression.setText(dst.m_expressionText);
Shinya Kitaoka 120a6e
    if (dst.m_type == TDoubleKeyframe::File)
Shinya Kitaoka 120a6e
      dst.m_fileData.setParams(dst.m_fileParams);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (!keyframes.empty()) {
Shinya Kitaoka 120a6e
    keyframes[0].m_prevType = TDoubleKeyframe::None;
Shinya Kitaoka 120a6e
    for (int i                = 1; i < (int)keyframes.size(); i++)
Shinya Kitaoka 120a6e
      keyframes[i].m_prevType = keyframes[i - 1].m_type;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->notify(TParamChange(this, 0, 0, true, false, false));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef NDEBUG
Shinya Kitaoka 120a6e
  for (int i = 0; i + 1 < (int)keyframes.size(); i++) {
Shinya Kitaoka 120a6e
    assert(keyframes[i].m_frame <= keyframes[i + 1].m_frame);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::setKeyframe(const TDoubleKeyframe &k) {
Shinya Kitaoka 120a6e
  DoubleKeyframeVector &keyframes = m_imp->m_keyframes;
Shinya Kitaoka 120a6e
  DoubleKeyframeVector::iterator it;
Shinya Kitaoka 120a6e
  it = std::lower_bound(keyframes.begin(), keyframes.end(), k);
Shinya Kitaoka 120a6e
  if (it != keyframes.end() && it->m_frame == k.m_frame) {
Shinya Kitaoka 120a6e
    // int index = std::distance(keyframes.begin(), it);
Shinya Kitaoka 120a6e
    TActualDoubleKeyframe &dst = *it;
Shinya Kitaoka 120a6e
    (TDoubleKeyframe &)dst     = k;
Shinya Kitaoka 120a6e
    dst.updateUnit(m_imp->m_measure);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    it = keyframes.insert(it, TActualDoubleKeyframe(k));
Shinya Kitaoka 120a6e
    // int index = std::distance(keyframes.begin(), it);
Shinya Kitaoka 120a6e
    // TDoubleKeyframe oldKeyframe = *it;
Shinya Kitaoka 120a6e
    it->m_expression.setGrammar(m_imp->m_grammar);
Shinya Kitaoka 120a6e
    it->m_expression.setOwnerParameter(this);
Shinya Kitaoka 120a6e
    it->updateUnit(m_imp->m_measure);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  it->m_isKeyframe = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (it->m_type == TDoubleKeyframe::Expression)
Shinya Kitaoka 120a6e
    it->m_expression.setText(it->m_expressionText);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (it->m_type == TDoubleKeyframe::File)
Shinya Kitaoka 120a6e
    it->m_fileData.setParams(it->m_fileParams);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (it == keyframes.begin())
Shinya Kitaoka 120a6e
    it->m_prevType = TDoubleKeyframe::None;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    it->m_prevType = it[-1].m_type;
Shinya Kitaoka 120a6e
DoctorRyan ac3cab
  if (it + 1 != keyframes.end()) it[1].m_prevType = it->m_type;
DoctorRyan ac3cab
Shinya Kitaoka 120a6e
  m_imp->notify(TParamChange(this, 0, 0, true, false, false));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(it == keyframes.begin() || (it - 1)->m_frame < it->m_frame);
Shinya Kitaoka 120a6e
  assert(it + 1 == keyframes.end() || (it + 1)->m_frame > it->m_frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::setDefaultValue(double value) {
Shinya Kitaoka 120a6e
  assert(m_imp);
Shinya Kitaoka 120a6e
  if (m_imp->m_defaultValue != value) {
Shinya Kitaoka 120a6e
    m_imp->m_defaultValue = value;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // gmt, 19-6-2010; needed to get a notification in the FxParamsGraphicEditor
Shinya Kitaoka 120a6e
    // (Camera Stand)
Shinya Kitaoka 120a6e
    // when a param (without keyframes) is changed
Shinya Kitaoka 120a6e
    m_imp->notify(TParamChange(this, 0, 0, true, false, false));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TDoubleParam::isDefault() const {
Shinya Kitaoka 120a6e
  return m_imp->m_keyframes.empty() &&
Shinya Kitaoka 120a6e
         // m_imp->m_type == Keyframes &&
Shinya Kitaoka 120a6e
         m_imp->m_defaultValue == 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TDoubleParam::getKeyframeCount() const { return m_imp->m_keyframes.size(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::getKeyframes(std::set<double> &frames) const {</double>
Shinya Kitaoka 120a6e
  for (DoubleKeyframeVector::iterator it = m_imp->m_keyframes.begin();
Shinya Kitaoka 120a6e
       it != m_imp->m_keyframes.end(); ++it)
Shinya Kitaoka 120a6e
    frames.insert(it->m_frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TDoubleParam::hasKeyframes() const { return !m_imp->m_keyframes.empty(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const TDoubleKeyframe &TDoubleParam::getKeyframe(int index) const {
Shinya Kitaoka 120a6e
  assert(0 <= index && index < (int)m_imp->m_keyframes.size());
Shinya Kitaoka 120a6e
  return m_imp->m_keyframes[index];
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const TDoubleKeyframe &TDoubleParam::getKeyframeAt(double frame) const {
Shinya Kitaoka 120a6e
  static TDoubleKeyframe k;
Shinya Kitaoka 120a6e
  k     = TDoubleKeyframe();
Shinya Kitaoka 120a6e
  int i = 0;
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)m_imp->m_keyframes.size(); i++)
Shinya Kitaoka 120a6e
    if (m_imp->m_keyframes[i].m_frame >= frame) break;
Shinya Kitaoka 120a6e
  if (i < (int)m_imp->m_keyframes.size() &&
Shinya Kitaoka 120a6e
      m_imp->m_keyframes[i].m_frame == frame) {
Shinya Kitaoka 120a6e
    k = m_imp->m_keyframes[i];
Shinya Kitaoka 120a6e
    return k;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  k.m_frame      = frame;
Shinya Kitaoka 120a6e
  k.m_value      = getValue(frame);
Shinya Kitaoka 120a6e
  k.m_isKeyframe = false;
Shinya Kitaoka 120a6e
  return k;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TDoubleParam::isKeyframe(double frame) const {
Shinya Kitaoka 120a6e
  return std::binary_search(m_imp->m_keyframes.begin(),
Shinya Kitaoka 120a6e
                            m_imp->m_keyframes.end(), TDoubleKeyframe(frame));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::deleteKeyframe(double frame) {
Shinya Kitaoka 120a6e
  DoubleKeyframeVector &keyframes = m_imp->m_keyframes;
Shinya Kitaoka 120a6e
  DoubleKeyframeVector::iterator it;
Shinya Kitaoka 120a6e
  it = std::lower_bound(keyframes.begin(), keyframes.end(),
Shinya Kitaoka 120a6e
                        TDoubleKeyframe(frame));
Shinya Kitaoka 120a6e
  if (it == keyframes.end() || it->m_frame != frame) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TDoubleKeyframe::Type type                = it->m_prevType;
Shinya Kitaoka 120a6e
  it                                        = m_imp->m_keyframes.erase(it);
Shinya Kitaoka 120a6e
  if (it != keyframes.end()) it->m_prevType = type;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_imp->notify(TParamChange(this, 0, 0, true, false, false));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::clearKeyframes() {
Shinya Kitaoka 120a6e
  m_imp->m_keyframes.clear();
Shinya Kitaoka 120a6e
  m_imp->notify(TParamChange(this, 0, 0, true, false, false));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::assignKeyframe(double frame, const TParamP &src,
Shinya Kitaoka 120a6e
                                  double srcFrame, bool changedOnly) {
Shinya Kitaoka 120a6e
  TDoubleParamP dp = src;
Shinya Kitaoka 120a6e
  if (!dp) return;
Shinya Kitaoka 120a6e
  double value = dp->getValue(srcFrame);
Shinya Kitaoka 120a6e
  if (!changedOnly || getValue(frame) != value) setValue(frame, value);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TDoubleParam::getClosestKeyframe(double frame) const {
Shinya Kitaoka 120a6e
  DoubleKeyframeVector &keyframes = m_imp->m_keyframes;
Shinya Kitaoka 120a6e
  typedef DoubleKeyframeVector::iterator Iterator;
Shinya Kitaoka 120a6e
  Iterator it = std::lower_bound(keyframes.begin(), keyframes.end(),
Shinya Kitaoka 120a6e
                                 TDoubleKeyframe(frame));
Shinya Kitaoka 120a6e
  if (it == keyframes.end()) {
Shinya Kitaoka 120a6e
    // frame > k.m_frame per qualsiasi k.
Shinya Kitaoka 120a6e
    // ritorna l'indice dell'ultimo keyframe (o -1 se l'array e' vuoto)
Shinya Kitaoka 120a6e
    return keyframes.size() - 1;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    int index = std::distance<iterator>(keyframes.begin(), it);</iterator>
Shinya Kitaoka 120a6e
    if (it->m_frame == frame || index == 0)
Shinya Kitaoka 120a6e
      return index;
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      double nextFrame = it->m_frame;
Shinya Kitaoka 120a6e
      double prevFrame = keyframes[index - 1].m_frame;
Shinya Kitaoka 120a6e
      assert(prevFrame < frame && frame < nextFrame);
Shinya Kitaoka 120a6e
      return (nextFrame - frame < frame - prevFrame) ? index : index - 1;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TDoubleParam::getNextKeyframe(double frame) const {
Shinya Kitaoka 120a6e
  TDoubleKeyframe k(frame);
Shinya Kitaoka 120a6e
  typedef DoubleKeyframeVector::const_iterator Iterator;
Shinya Kitaoka 120a6e
  Iterator it =
Shinya Kitaoka 120a6e
      std::upper_bound(m_imp->m_keyframes.begin(), m_imp->m_keyframes.end(), k);
Shinya Kitaoka 120a6e
  if (it == m_imp->m_keyframes.end()) return -1;
Shinya Kitaoka 120a6e
  int index = std::distance<iterator>(m_imp->m_keyframes.begin(), it);</iterator>
Shinya Kitaoka 120a6e
  if (it->m_frame == frame) {
Shinya Kitaoka 120a6e
    ++index;
Shinya Kitaoka 120a6e
    return index < getKeyframeCount() ? index : -1;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return index;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TDoubleParam::getPrevKeyframe(double frame) const {
Shinya Kitaoka 120a6e
  TDoubleKeyframe k(frame);
Shinya Kitaoka 120a6e
  typedef DoubleKeyframeVector::const_iterator Iterator;
Shinya Kitaoka 120a6e
  Iterator it =
Shinya Kitaoka 120a6e
      std::lower_bound(m_imp->m_keyframes.begin(), m_imp->m_keyframes.end(), k);
Shinya Kitaoka 120a6e
  if (it == m_imp->m_keyframes.end()) return m_imp->m_keyframes.size() - 1;
Shinya Kitaoka 120a6e
  int index = std::distance<iterator>(m_imp->m_keyframes.begin(), it);</iterator>
Shinya Kitaoka 120a6e
  return index - 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
double TDoubleParam::keyframeIndexToFrame(int index) const {
Shinya Kitaoka 120a6e
  assert(0 <= index && index < getKeyframeCount());
Shinya Kitaoka 120a6e
  return getKeyframe(index).m_frame;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::addObserver(TParamObserver *observer) {
Shinya Kitaoka 120a6e
  m_imp->m_observers.insert(observer);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::removeObserver(TParamObserver *observer) {
Shinya Kitaoka 120a6e
  m_imp->m_observers.erase(observer);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const std::set<tparamobserver *=""> &TDoubleParam::observers() const {</tparamobserver>
Shinya Kitaoka 120a6e
  return m_imp->m_observers;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::loadData(TIStream &is) {
Shinya Kitaoka 120a6e
  string tagName;
Shinya Kitaoka 120a6e
  /*
Shinya Kitaoka 120a6e
if(is.matchTag(tagName))
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
// nuovo formato (29 agosto 2005)
Shinya Kitaoka 120a6e
if(tagName!="type") throw TException("expected <type>");</type>
Shinya Kitaoka 120a6e
int type = 0;
Shinya Kitaoka 120a6e
is >> type;
Shinya Kitaoka 120a6e
// m_imp->m_type = TDoubleParam::Type(type);
Shinya Kitaoka 120a6e
if(!is.matchEndTag()) throw TException(tagName + " : missing endtag");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//if(!is.matchTag(tagName) || tagName != "default") throw TException("expected
Shinya Kitaoka 120a6e
<default>");</default>
Shinya Kitaoka 120a6e
//is >> m_imp->m_defaultValue;
Shinya Kitaoka 120a6e
//if(!is.matchEndTag()) throw TException(tagName + " : missing endtag");
Shinya Kitaoka 120a6e
//if(!is.matchTag(tagName) || tagName != "default") throw TException("expected
Shinya Kitaoka 120a6e
<default>");</default>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
else
Shinya Kitaoka 120a6e
{
Shinya Kitaoka 120a6e
// vecchio formato
Shinya Kitaoka 120a6e
is >> m_imp->m_defaultValue;
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_imp->m_keyframes.clear();
Shinya Kitaoka 120a6e
  int oldType = -1;
Shinya Kitaoka 120a6e
  while (is.matchTag(tagName)) {
Shinya Kitaoka 120a6e
    if (tagName == "type") {
Shinya Kitaoka 120a6e
      // (old) format 5.2. Since 6.0 param type is no used anymore
Shinya Kitaoka 120a6e
      is >> oldType;
Shinya Kitaoka 120a6e
    } else if (tagName == "default") {
Shinya Kitaoka 120a6e
      is >> m_imp->m_defaultValue;
Shinya Kitaoka 120a6e
    } else if (tagName == "cycle") {
Shinya Kitaoka 120a6e
      string dummy;
Shinya Kitaoka 120a6e
      is >> dummy;
Shinya Kitaoka 120a6e
      m_imp->m_cycleEnabled = true;
Shinya Kitaoka 120a6e
      // setExtrapolationAfter(Loop);
Shinya Kitaoka 120a6e
    } else if (tagName == "k") {
Shinya Kitaoka 120a6e
      // vecchio formato
Shinya Kitaoka 120a6e
      if (oldType != 0) continue;
Shinya Kitaoka 120a6e
      int linkStatus = 0;
Shinya Kitaoka 120a6e
      TActualDoubleKeyframe k;
Shinya Kitaoka 120a6e
      is >> k.m_frame >> k.m_value >> k.m_speedIn.x >> k.m_speedIn.y >>
Shinya Kitaoka 120a6e
          k.m_speedOut.x >> k.m_speedOut.y >> linkStatus;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      k.m_isKeyframe    = true;
Shinya Kitaoka 120a6e
      k.m_linkedHandles = (linkStatus & 1) != 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if ((linkStatus & 1) != 0)
Shinya Kitaoka 120a6e
        k.m_type = TDoubleKeyframe::SpeedInOut;
Shinya Kitaoka 120a6e
      else if ((linkStatus & 2) != 0 || (linkStatus & 4) != 0)
Shinya Kitaoka 120a6e
        k.m_type = TDoubleKeyframe::EaseInOut;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        k.m_type = TDoubleKeyframe::Linear;
Shinya Kitaoka 120a6e
      k.m_expression.setGrammar(m_imp->m_grammar);
Shinya Kitaoka 120a6e
      k.m_expression.setOwnerParameter(this);
Shinya Kitaoka 120a6e
      k.m_prevType = m_imp->m_keyframes.empty()
Shinya Kitaoka 120a6e
                         ? TDoubleKeyframe::None
Shinya Kitaoka 120a6e
                         : m_imp->m_keyframes.back().m_type;
Shinya Kitaoka 120a6e
      m_imp->m_keyframes.push_back(k);
Shinya Kitaoka 120a6e
    } else if (tagName == "expr") {
Shinya Kitaoka 120a6e
      // vecchio formato
Shinya Kitaoka 120a6e
      if (oldType != 1) continue;
Shinya Kitaoka 120a6e
      string text    = is.getTagAttribute("text");
Shinya Kitaoka 120a6e
      string enabled = is.getTagAttribute("enabled");
Shinya Kitaoka 120a6e
      TDoubleKeyframe kk1, kk2;
Shinya Kitaoka 120a6e
      kk1.m_frame          = -1000;
Shinya Kitaoka 120a6e
      kk2.m_frame          = 1000;
Shinya Kitaoka 120a6e
      kk1.m_isKeyframe     = true;
Shinya Kitaoka 120a6e
      kk2.m_isKeyframe     = true;
Shinya Kitaoka 120a6e
      kk1.m_expressionText = text;
Shinya Kitaoka 120a6e
      kk2.m_expressionText = text;
Shinya Kitaoka 120a6e
      kk1.m_type           = TDoubleKeyframe::Expression;
Shinya Kitaoka 120a6e
      kk2.m_type           = TDoubleKeyframe::Expression;
Shinya Kitaoka 120a6e
      TActualDoubleKeyframe k1(kk1);
Shinya Kitaoka 120a6e
      TActualDoubleKeyframe k2(kk2);
Shinya Kitaoka 120a6e
      k1.m_expression.setGrammar(m_imp->m_grammar);
Shinya Kitaoka 120a6e
      k1.m_expression.setOwnerParameter(this);
Shinya Kitaoka 120a6e
      k1.m_prevType = m_imp->m_keyframes.empty()
Shinya Kitaoka 120a6e
                          ? TDoubleKeyframe::None
Shinya Kitaoka 120a6e
                          : m_imp->m_keyframes.back().m_type;
Shinya Kitaoka 120a6e
      k2.m_expression.setGrammar(m_imp->m_grammar);
Shinya Kitaoka 120a6e
      k2.m_expression.setOwnerParameter(this);
Shinya Kitaoka 120a6e
      k2.m_prevType = m_imp->m_keyframes.empty()
Shinya Kitaoka 120a6e
                          ? TDoubleKeyframe::None
Shinya Kitaoka 120a6e
                          : m_imp->m_keyframes.back().m_type;
Shinya Kitaoka 120a6e
      m_imp->m_keyframes.push_back(k1);
Shinya Kitaoka 120a6e
      m_imp->m_keyframes.push_back(k2);
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    } else if (tagName == "file") {
Shinya Kitaoka 120a6e
      // vecchio formato
Shinya Kitaoka 120a6e
      if (oldType != 2) continue;
Shinya Kitaoka 120a6e
      TDoubleKeyframe::FileParams params;
Shinya Kitaoka 120a6e
      params.m_path       = TFilePath(is.getTagAttribute("path"));
Shinya Kitaoka 120a6e
      params.m_fieldIndex = std::stoi(is.getTagAttribute("index"));
Shinya Kitaoka 120a6e
      TActualDoubleKeyframe k1, k2;
Shinya Kitaoka 120a6e
      k1.m_frame      = -1000;
Shinya Kitaoka 120a6e
      k2.m_frame      = 1000;
Shinya Kitaoka 120a6e
      k1.m_isKeyframe = true;
Shinya Kitaoka 120a6e
      k2.m_isKeyframe = true;
Shinya Kitaoka 120a6e
      k1.m_fileData.setParams(params);
Shinya Kitaoka 120a6e
      k2.m_fileData.setParams(params);
Shinya Kitaoka 120a6e
      k1.m_type = TDoubleKeyframe::File;
Shinya Kitaoka 120a6e
      k2.m_type = TDoubleKeyframe::File;
Shinya Kitaoka 120a6e
      k1.m_expression.setGrammar(m_imp->m_grammar);
Shinya Kitaoka 120a6e
      k1.m_expression.setOwnerParameter(this);
Shinya Kitaoka 120a6e
      k1.m_prevType = m_imp->m_keyframes.empty()
Shinya Kitaoka 120a6e
                          ? TDoubleKeyframe::None
Shinya Kitaoka 120a6e
                          : m_imp->m_keyframes.back().m_type;
Shinya Kitaoka 120a6e
      k2.m_expression.setGrammar(m_imp->m_grammar);
Shinya Kitaoka 120a6e
      k2.m_expression.setOwnerParameter(this);
Shinya Kitaoka 120a6e
      k2.m_prevType = m_imp->m_keyframes.empty()
Shinya Kitaoka 120a6e
                          ? TDoubleKeyframe::None
Shinya Kitaoka 120a6e
                          : m_imp->m_keyframes.back().m_type;
Shinya Kitaoka 120a6e
      m_imp->m_keyframes.push_back(k1);
Shinya Kitaoka 120a6e
      m_imp->m_keyframes.push_back(k2);
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    } else if (tagName == "step") {
Shinya Kitaoka 120a6e
      int step = 0;
Shinya Kitaoka 120a6e
      is >> step;
Shinya Kitaoka 120a6e
      // if(step>1)
Shinya Kitaoka 120a6e
      //  m_imp->m_frameStep = step;
Shinya Kitaoka 120a6e
    } else if (tagName == "keyframes") {
Shinya Kitaoka 120a6e
      while (!is.eos()) {
Shinya Kitaoka 120a6e
        TDoubleKeyframe kk;
Shinya Kitaoka 120a6e
        kk.loadData(is);
DoctorRyan ac3cab
         // Throw out invalid interpolation types
DoctorRyan ac3cab
        if (kk.m_type == TDoubleKeyframe::None) continue;
Shinya Kitaoka 120a6e
        TActualDoubleKeyframe k(kk);
Shinya Kitaoka 120a6e
        k.m_expression.setGrammar(m_imp->m_grammar);
Shinya Kitaoka 120a6e
        k.m_expression.setOwnerParameter(this);
Shinya Kitaoka 120a6e
        k.m_prevType = m_imp->m_keyframes.empty()
Shinya Kitaoka 120a6e
                           ? TDoubleKeyframe::None
Shinya Kitaoka 120a6e
                           : m_imp->m_keyframes.back().m_type;
Shinya Kitaoka 120a6e
        m_imp->m_keyframes.push_back(k);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      throw TException(tagName + " : unexpected tag");
Toshihiro Shimizu 890ddd
    }
Shinya Kitaoka 120a6e
    if (!is.matchEndTag()) throw TException(tagName + " : missing endtag");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_imp->m_keyframes.empty() && !is.eos()) {
Shinya Kitaoka 120a6e
    // vecchio sistema (prima 16/1/2003)
Shinya Kitaoka 120a6e
    while (!is.eos()) {
Shinya Kitaoka 120a6e
      double t, v;
Shinya Kitaoka 120a6e
      is >> t >> v;
Shinya Kitaoka 120a6e
      m_imp->m_keyframes.push_back(TActualDoubleKeyframe(t, v));
Toshihiro Shimizu 890ddd
    }
Shinya Kitaoka 120a6e
    if (!m_imp->m_keyframes.empty()) {
Shinya Kitaoka 120a6e
      m_imp->m_keyframes[0].m_prevType = TDoubleKeyframe::None;
Shinya Kitaoka 120a6e
      for (int i = 1; i < (int)m_imp->m_keyframes.size(); i++)
Shinya Kitaoka 120a6e
        m_imp->m_keyframes[i].m_prevType = m_imp->m_keyframes[i - 1].m_type;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_imp->notify(TParamChange(this, 0, 0, true, false, false));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::saveData(TOStream &os) {
Shinya Kitaoka 120a6e
  // os.child("type") << (int)m_imp->m_type;
Shinya Kitaoka 120a6e
  os.child("default") << m_imp->m_defaultValue;
Shinya Kitaoka 120a6e
  if (isCycleEnabled()) os.child("cycle") << std::string("enabled");
Shinya Kitaoka 120a6e
  // if(getExtrapolationAfter() == Loop)
Shinya Kitaoka 120a6e
  //  os.child("cycle") << string("loop");
Shinya Kitaoka 120a6e
  if (!m_imp->m_keyframes.empty()) {
Shinya Kitaoka 120a6e
    os.openChild("keyframes");
Shinya Kitaoka 120a6e
    DoubleKeyframeVector::const_iterator it;
Shinya Kitaoka 120a6e
    for (it = m_imp->m_keyframes.begin(); it != m_imp->m_keyframes.end(); ++it)
Shinya Kitaoka 120a6e
      it->saveData(os);
Shinya Kitaoka 120a6e
    os.closeChild();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
string TDoubleParam::getStreamTag() const { return "doubleParam"; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
string TDoubleParam::getValueAlias(double frame, int precision) {
Shinya Kitaoka 120a6e
  return ::to_string(getValue(frame), precision);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::setGrammar(const TSyntax::Grammar *grammar) {
Shinya Kitaoka 120a6e
  m_imp->m_grammar = grammar;
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)m_imp->m_keyframes.size(); i++)
Shinya Kitaoka 120a6e
    m_imp->m_keyframes[i].m_expression.setGrammar(grammar);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const TSyntax::Grammar *TDoubleParam::getGrammar() const {
Shinya Kitaoka 120a6e
  return m_imp->m_grammar;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::accept(TSyntax::CalculatorNodeVisitor &visitor) {
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)m_imp->m_keyframes.size(); i++)
Shinya Kitaoka 120a6e
    if (m_imp->m_keyframes[i].m_type == TDoubleKeyframe::Expression ||
Shinya Kitaoka 120a6e
        m_imp->m_keyframes[i].m_type == TDoubleKeyframe::SimilarShape)
Shinya Kitaoka 120a6e
      m_imp->m_keyframes[i].m_expression.accept(visitor);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
string TDoubleParam::getMeasureName() const { return m_imp->m_measureName; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TDoubleParam::setMeasureName(string name) {
Shinya Kitaoka 120a6e
  m_imp->m_measureName = name;
Shinya Kitaoka 120a6e
  m_imp->m_measure     = TMeasureManager::instance()->get(name);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TMeasure *TDoubleParam::getMeasure() const { return m_imp->m_measure; }