NAP
sequencecontrollercurve_template.h
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4 
5 namespace nap
6 {
7  template<typename T>
9  {
10  performEditAction([this]()
11  {
12  // create sequence track
13  std::unique_ptr<SequenceTrackCurve<T>> sequence_track = std::make_unique<SequenceTrackCurve<T>>();
14  sequence_track->mID = mService.generateUniqueID(getPlayerReadObjectIDs());
15 
16  // name is ID
17  sequence_track->mName = sequence_track->mID;
18 
19  // create the resource pointer
20  getSequence().mTracks.emplace_back(ResourcePtr<SequenceTrackCurve<T>>(sequence_track.get()));
21 
22  // move ownership
23  getPlayerOwnedObjects().emplace_back(std::move(sequence_track));
24  });
25  }
26 
27 
28  template<typename T>
30  const std::string& trackID, double time)
31  {
32  static std::unordered_map<rttr::type, int> s_curve_count_map
33  {
34  {RTTI_OF(float), 1},
35  {RTTI_OF(glm::vec2), 2},
36  {RTTI_OF(glm::vec3), 3},
37  {RTTI_OF(glm::vec4), 4}
38  };
39 
40  SequenceTrackSegment *return_ptr;
41 
42  performEditAction([this, trackID, time, &return_ptr]() mutable
43  {
44  auto it = s_curve_count_map.find(RTTI_OF(T));
45  assert(it != s_curve_count_map.end()); // type not found
46 
47  int curve_count = it->second;
48 
49  assert(curve_count > 0); // invalid curvecount
50 
51  Sequence &sequence = getSequence();
52 
53  // find the right track
54  for(auto &track: sequence.mTracks)
55  {
56  if(track->mID == trackID)
57  {
58  // track found
59 
60  // find the segment the new segment in inserted after
61  int segment_count = 1;
62  for(auto &segment: track->mSegments)
63  {
64  if(segment->mStartTime < time &&
65  segment->mStartTime + segment->mDuration > time)
66  {
67  // segment found
68 
69  // create new segment & set parameters
70  std::unique_ptr<SequenceTrackSegmentCurve<T>> new_segment = std::make_unique<SequenceTrackSegmentCurve<T>>();
71  new_segment->mStartTime = time;
72  new_segment->mDuration = segment->mStartTime + segment->mDuration - time;
73  new_segment->mCurves.resize(curve_count);
74  new_segment->mCurveTypes.resize(curve_count);
75  for(int i = 0; i < curve_count; i++)
76  {
77  std::unique_ptr<math::FCurve<float, float>> segment_curve = std::make_unique<math::FCurve<float, float>>();
78  segment_curve->mPoints[1].mInTan.mTime = -0.4f;
79  segment_curve->mPoints[1].mOutTan.mTime = 0.4f;
80  segment_curve->mID = mService.generateUniqueID(getPlayerReadObjectIDs());
81 
82  // assign curve
83  new_segment->mCurves[i] = nap::ResourcePtr<math::FCurve<float, float>>(segment_curve.get());
84 
85  new_segment->mCurveTypes[i] = math::ECurveInterp::Bezier;
86 
87  // move ownership
88  getPlayerOwnedObjects().emplace_back(std::move(segment_curve));
89  }
90 
91  //
92  auto &segment_curve_2 = *static_cast<SequenceTrackSegmentCurve<T> *>(segment.get());
93 
94  // set the value by evaluation curve
95  new_segment->setStartValue(segment_curve_2.getValue(
96  (segment->mStartTime + segment->mDuration - time) /
97  segment->mDuration));
98 
99  // check if there is a next segment
100  if(segment_count < track->mSegments.size())
101  {
102  // if there is a next segment, the new segments end value is the start value of the next segment ...
103  auto &next_segment_curve = *static_cast<SequenceTrackSegmentCurve<T> *>(track->mSegments[segment_count].get());
104 
105  new_segment->setEndValue(next_segment_curve.getEndValue());
106  } else
107  {
108  // ... otherwise it just gets this segments end value
109  new_segment->setEndValue(segment_curve_2.getEndValue());
110  }
111 
112  // the segment's end value gets the start value the newly inserted segment
113  segment_curve_2.setEndValue(new_segment->getStartValue());
114 
115  // change duration of segment before inserted segment
116  segment->mDuration = new_segment->mStartTime - segment->mStartTime;
117 
118  // generate unique id
119  new_segment->mID = mService.generateUniqueID(getPlayerReadObjectIDs());
120 
121  // wrap it in a resource ptr and insert it into the track
122  ResourcePtr<SequenceTrackSegment> new_segment_resource_ptr(new_segment.get());
123  track->mSegments.insert(
124  track->mSegments.begin() + segment_count, new_segment_resource_ptr);
125 
126  return_ptr = new_segment.get();
127 
128  // move ownership to sequence player
129  getPlayerOwnedObjects().emplace_back(std::move(new_segment));
130 
131  //
132  updateCurveSegments<T>(*(track.get()));
133 
134  break;
135  } else if(segment_count == track->mSegments.size())
136  {
137  // insert segment at the end of the list
138 
139  // create new segment & set parameters
140  std::unique_ptr<SequenceTrackSegmentCurve<T>> new_segment = std::make_unique<SequenceTrackSegmentCurve<T>>();
141  new_segment->mStartTime = segment->mStartTime + segment->mDuration;
142  new_segment->mDuration = time - new_segment->mStartTime;
143  new_segment->mCurves.resize(curve_count);
144  new_segment->mCurveTypes.resize(curve_count);
145  for(int v = 0; v < curve_count; v++)
146  {
147  std::unique_ptr<math::FCurve<float, float>> new_curve = std::make_unique<math::FCurve<float, float>>();
149  new_curve->mPoints[1].mInTan.mTime = -0.4f;
150  new_curve->mPoints[1].mOutTan.mTime = 0.4f;
151  new_segment->mCurves[v] = ResourcePtr<math::FCurve<float, float>>(new_curve.get());
152  new_segment->mCurveTypes[v] = math::ECurveInterp::Bezier;
153  getPlayerOwnedObjects().emplace_back(std::move(new_curve));
154  }
155 
156  // generate unique id
157  new_segment->mID = mService.generateUniqueID(getPlayerReadObjectIDs());
158 
159  // wrap it in a resource ptr and insert it into the track
160  ResourcePtr<SequenceTrackSegment> new_segment_resource_ptr(new_segment.get());
161  track->mSegments.emplace_back(new_segment_resource_ptr);
162 
163  return_ptr = new_segment.get();
164 
165  // move ownership to sequence player
166  getPlayerOwnedObjects().emplace_back(std::move(new_segment));
167 
168  //
169  updateCurveSegments<T>(*(track.get()));
170 
171  break;
172  }
173 
174  segment_count++;
175  }
176 
177  //
178  if(track->mSegments.empty())
179  {
180  // create new segment & set parameters
181  std::unique_ptr<SequenceTrackSegmentCurve<T>> new_segment = std::make_unique<SequenceTrackSegmentCurve<T>>();
182  new_segment->mStartTime = 0.0;
183  new_segment->mDuration = time - new_segment->mStartTime;
184 
185  // make new curve of segment
186  new_segment->mCurves.resize(curve_count);
187  new_segment->mCurveTypes.resize(curve_count);
188  for(int v = 0; v < curve_count; v++)
189  {
190  std::unique_ptr<math::FCurve<float, float>> new_curve = std::make_unique<math::FCurve<float, float>>();
192  new_curve->mPoints[1].mInTan.mTime = -0.4f;
193  new_curve->mPoints[1].mOutTan.mTime = 0.4f;
194  new_segment->mCurves[v] = ResourcePtr<math::FCurve<float, float>>(new_curve.get());
195  new_segment->mCurveTypes[v] = math::ECurveInterp::Bezier;
196  getPlayerOwnedObjects().emplace_back(std::move(new_curve));
197  }
198 
199  // generate unique id
200  new_segment->mID = mService.generateUniqueID(getPlayerReadObjectIDs());
201 
202  // wrap it in a resource ptr and insert it into the track
203  ResourcePtr<SequenceTrackSegment> new_segment_resource_ptr(new_segment.get());
204  track->mSegments.emplace_back(new_segment_resource_ptr);
205 
206  //
207  return_ptr = new_segment.get();
208 
209  // move ownership to sequence player
210  getPlayerOwnedObjects().emplace_back(std::move(new_segment));
211 
212  //
213  updateCurveSegments<T>(*(track.get()));
214 
215  break;
216  }
217  break;
218  }
219  }
220  });
221 
222  return return_ptr;
223  }
224 
225 
226  template<typename T>
228  math::ECurveInterp type, int curveIndex)
229  {
230  assert(segment.get_type().is_derived_from<SequenceTrackSegmentCurve<T>>()); // type mismatch
231  auto &curve_segment = static_cast<SequenceTrackSegmentCurve<T> &>(segment);
232  assert(curve_segment.mCurveTypes.size() > curveIndex); // curveIndex invalid
233 
234  curve_segment.mCurveTypes[curveIndex] = type;
235  for(int j = 0; j < curve_segment.mCurves[curveIndex]->mPoints.size(); j++)
236  {
237  curve_segment.mCurves[curveIndex]->mPoints[j].mInterp = type;
238  }
239  }
240 
241 
242  template<typename T>
244  SequenceTrackSegment& segment, float newValue, int curveIndex,
246  {
247  assert(segment.get_type().is_derived_from<SequenceTrackSegmentCurve<T>>()); // type mismatch
248  auto &curve_segment = static_cast<SequenceTrackSegmentCurve<T> &>(segment);
249 
250  switch(valueType)
251  {
253  {
254  curve_segment.mCurves[curveIndex]->mPoints[0].mPos.mValue = newValue;
255  curve_segment.mCurves[curveIndex]->mPoints[0].mPos.mValue = math::clamp(curve_segment.mCurves[curveIndex]->mPoints[0].mPos.mValue, 0.0f, 1.0f);
256  }
257  break;
259  {
260  int lastPoint = curve_segment.mCurves[curveIndex]->mPoints.size() - 1;
261  curve_segment.mCurves[curveIndex]->mPoints[lastPoint].mPos.mValue = newValue;
262  curve_segment.mCurves[curveIndex]->mPoints[lastPoint].mPos.mValue = math::clamp(curve_segment.mCurves[curveIndex]->mPoints[lastPoint].mPos.mValue, 0.0f, 1.0f);
263  }
264  break;
265  }
266 
267  //
268  updateCurveSegments<T>(track);
269  }
270 
271 
272  template<typename T>
273  void SequenceControllerCurve::insertCurvePoint(SequenceTrackSegment& segment, float pos, int curveIndex)
274  {
275  assert(segment.get_type().is_derived_from<SequenceTrackSegmentCurve<T>>()); // type mismatch
276 
277  auto &curve_segment = static_cast<SequenceTrackSegmentCurve<T> &>(segment);
278  assert(curveIndex < curve_segment.mCurves.size()); // invalid curve index
279 
280  // iterate trough points of curve
281  for(int i = 0; i < curve_segment.mCurves[curveIndex]->mPoints.size() - 1; i++)
282  {
283  // find the point the new point needs to get inserted after
284  if(curve_segment.mCurves[curveIndex]->mPoints[i].mPos.mTime <= pos &&
285  curve_segment.mCurves[curveIndex]->mPoints[i + 1].mPos.mTime > pos)
286  {
287  // create point
289  p.mPos.mTime = pos;
290  p.mPos.mValue = curve_segment.mCurves[curveIndex]->evaluate(pos);
291  p.mInTan.mTime = -0.1f;
292  p.mOutTan.mTime = 0.1f;
293  p.mInTan.mValue = 0.0f;
294  p.mOutTan.mValue = 0.0f;
295  p.mTangentsAligned = true;
296  p.mInterp = curve_segment.mCurveTypes[curveIndex];
297 
298  // insert point
299  curve_segment.mCurves[curveIndex]->mPoints.insert(
300  curve_segment.mCurves[curveIndex]->mPoints.begin() + i + 1, p);
301  curve_segment.mCurves[curveIndex]->invalidate();
302  break;
303  }
304  }
305  }
306 
307 
308  template<typename T>
310  int curveIndex)
311  {
312  assert(segment.get_type().is_derived_from<SequenceTrackSegmentCurve<T>>()); // type mismatch
313 
314  auto &curve_segment = static_cast<SequenceTrackSegmentCurve<T> &>(segment);
315  assert(curveIndex < curve_segment.mCurves.size()); // invalid curve index
316 
317  if(index < curve_segment.mCurves[curveIndex]->mPoints.size())
318  {
319  curve_segment.mCurves[curveIndex]->mPoints.erase(
320  curve_segment.mCurves[curveIndex]->mPoints.begin() + index);
321  curve_segment.mCurves[curveIndex]->invalidate();
322  }
323  }
324 
325 
326  template<typename T>
328  const int pointIndex, const int curveIndex, float time, float value)
329  {
330  // obtain curve segment
331  assert(segment.get_type().is_derived_from<SequenceTrackSegmentCurve<T>>()); // type mismatch
332  auto &curve_segment = static_cast<SequenceTrackSegmentCurve<T> &>(segment);
333  assert(curveIndex < curve_segment.mCurves.size()); // invalid curve index
334  assert(pointIndex < curve_segment.mCurves[curveIndex]->mPoints.size()); // invalid point index
335 
336  // obtain curve point and set values
337  math::FCurvePoint<float, float> &curve_point = curve_segment.mCurves[curveIndex]->mPoints[pointIndex];
338  curve_point.mPos.mTime = time;
339  curve_point.mPos.mValue = value;
340  curve_point.mPos.mValue = math::clamp(curve_point.mPos.mValue, 0.0f, 1.0f);
341  curve_segment.mCurves[curveIndex]->invalidate();
342  }
343 
344 
345  template<typename T>
347  const int curveIndex, float time, float value)
348  {
349 
350  // obtain curve segment
351  assert(segment.get_type().is_derived_from<SequenceTrackSegmentCurve<T>>()); // type mismatch
352  auto &curve_segment = static_cast<SequenceTrackSegmentCurve<T> &>(segment);
353  assert(curveIndex < curve_segment.mCurves.size()); // invalid curve index
354 
355  int point_index = curve_segment.mCurves[curveIndex]->mPoints.size() - 1;
356 
357  // obtain curve point and set values
358  math::FCurvePoint<float, float> &curve_point = curve_segment.mCurves[curveIndex]->mPoints[point_index];
359  curve_point.mPos.mTime = time;
360  curve_point.mPos.mValue = value;
361  curve_point.mPos.mValue = math::clamp(curve_point.mPos.mValue, 0.0f, 1.0f);
362  curve_segment.mCurves[curveIndex]->invalidate();
363  }
364 
365 
366  template<typename T>
368  const std::string& trackID, const int pointIndex, const int curveIndex,
369  sequencecurveenums::ETanPointTypes tanType, float time, float value)
370  {
371  assert(segment.get_type().is_derived_from<SequenceTrackSegmentCurve<T>>()); // type mismatch
372  auto &curve_segment = static_cast<SequenceTrackSegmentCurve<T> &>(segment);
373  assert(curveIndex < curve_segment.mCurves.size()); // invalid curve index
374  assert(pointIndex < curve_segment.mCurves[curveIndex]->mPoints.size()); // invalid point index
375 
376  // if tangents are flipped, set this to true
377  bool flipped = false;
378 
379  // get reference to curve point
380  auto &curve_point = curve_segment.mCurves[curveIndex]->mPoints[pointIndex];
381  switch(tanType)
382  {
383  case sequencecurveenums::ETanPointTypes::IN:
384  {
385  // if we have aligned tangents, check if IN and OUT can be flipped
386  if(curve_point.mTangentsAligned && time > 0.0f)
387  {
388  time = -time;
389  value = -value;
390  flipped = true;
391  }
392 
393  curve_point.mInTan.mTime = time;
394  curve_point.mInTan.mValue = value;
395 
396  if(curve_point.mTangentsAligned)
397  {
398  curve_point.mOutTan.mTime = -curve_point.mInTan.mTime;
399  curve_point.mOutTan.mValue = -curve_point.mInTan.mValue;
400  }
401  }
402  break;
403  case sequencecurveenums::ETanPointTypes::OUT:
404  {
405  if(curve_point.mTangentsAligned && time < 0.0f)
406  {
407  time = -time;
408  value = -value;
409  flipped = true;
410  }
411 
412  curve_point.mOutTan.mTime = time;
413  curve_point.mOutTan.mValue = value;
414 
415  if(curve_point.mTangentsAligned)
416  {
417  curve_point.mInTan.mTime = -curve_point.mOutTan.mTime;
418  curve_point.mInTan.mValue = -curve_point.mOutTan.mValue;
419  }
420  }
421  break;
422  }
423 
424  // is this the last control point ?
425  // then also change the first control point of the next segment accordinly
426  if(pointIndex == curve_segment.mCurves[curveIndex]->mPoints.size() - 1)
427  {
428  SequenceTrack *track = findTrack(trackID);
429  assert(track != nullptr); // track not found
430 
431  for(int i = 0; i < track->mSegments.size(); i++)
432  {
433  if(track->mSegments[i].get() == &segment && i + 1 < track->mSegments.size())
434  {
435  auto &next_segment_curve_point = static_cast<SequenceTrackSegmentCurve<T> &>(*track->mSegments[i +
436  1]).mCurves[curveIndex]->mPoints[0];
437 
438  next_segment_curve_point.mInTan.mTime = curve_point.mInTan.mTime;
439  next_segment_curve_point.mInTan.mValue = curve_point.mInTan.mValue;
440  next_segment_curve_point.mOutTan.mTime = curve_point.mOutTan.mTime;
441  next_segment_curve_point.mOutTan.mValue = curve_point.mOutTan.mValue;
442  }
443  }
444  }
445 
446  curve_segment.mCurves[curveIndex]->invalidate();
447 
448  return flipped;
449  }
450 
451 
452  template<typename T>
454  {
455  // update start time and duration of all segments
456  ResourcePtr<SequenceTrackSegmentCurve<T>> prev_segment = nullptr;
457  for(auto track_segment: track.mSegments)
458  {
459  if(prev_segment == nullptr)
460  {
461  track_segment->mStartTime = 0.0;
462  } else
463  {
464  track_segment->mStartTime = prev_segment->mStartTime + prev_segment->mDuration;
465  prev_segment->mDuration = track_segment->mStartTime - prev_segment->mStartTime;
466  }
467  prev_segment = static_cast<ResourcePtr<SequenceTrackSegmentCurve<T>>>(track_segment);
468  }
469 
470  //
471  prev_segment = nullptr;
472  for(auto track_segment: track.mSegments)
473  {
474  auto &segment_curve = static_cast<SequenceTrackSegmentCurve<T> &>(*track_segment.get());
475 
476  if(prev_segment != nullptr)
477  {
478  // if we have a previous segment, the curve gets the value of the start value of the current segment
479  segment_curve.setStartValue(prev_segment->getEndValue());
480  }
481  prev_segment = &segment_curve;
482  }
483  }
484 
485 
486  template<typename T>
487  void SequenceControllerCurve::changeMinMaxCurveTrack(const std::string& trackID, T minimum, T maximum)
488  {
489  performEditAction([this, trackID, minimum, maximum]()
490  {
491  SequenceTrack *track = findTrack(trackID);
492  assert(track != nullptr); // track not found
493 
494  auto *track_curve = static_cast<SequenceTrackCurve<T> *>(track);
495 
496  for(auto &segment: track_curve->mSegments)
497  {
498  auto &curve_segment = static_cast<SequenceTrackSegmentCurve<T> &>(*segment.get());
499  int curve_count = 0;
500  for(auto &curve: curve_segment.mCurves)
501  {
502  for(auto &point: curve->mPoints)
503  {
504  if(minimum[curve_count]!=maximum[curve_count])
505  {
506  float value = point.mPos.mValue * (track_curve->mMaximum[curve_count] -
507  track_curve->mMinimum[curve_count]) +
508  track_curve->mMinimum[curve_count];
509 
510  point.mPos.mValue = (value - minimum[curve_count]) /
511  (maximum[curve_count] - minimum[curve_count]);
512  point.mPos.mValue = math::clamp<float>(point.mPos.mValue, 0, 1);
513  }else
514  {
515  point.mPos.mValue = 0.0f;
516  }
517  }
518  curve_count++;
519  }
520  }
521 
522  track_curve->mMinimum = minimum;
523  track_curve->mMaximum = maximum;
524  });
525  }
526 }
nap::SequenceControllerCurve::updateCurveSegments
void updateCurveSegments(const std::string &trackID)
nap::SequenceController::findTrack
SequenceTrack * findTrack(const std::string &trackID)
nap::sequencecurveenums::ETanPointTypes
ETanPointTypes
Definition: sequencecurveenums.h:13
nap::SequenceControllerCurve::changeCurvePoint
void changeCurvePoint(const std::string &trackID, const std::string &segmentID, int pointIndex, int curveIndex, float time, float value)
nap::math::ECurveInterp
ECurveInterp
Definition: fcurve.h:20
nap::SequenceControllerCurve::insertCurveSegment
const SequenceTrackSegment * insertCurveSegment(const std::string &trackID, double time)
Definition: sequencecontrollercurve_template.h:29
nap::SequenceTrackSegmentCurve
Definition: sequencetracksegmentcurve.h:19
nap::sequencecurveenums::ESegmentValueTypes
ESegmentValueTypes
Definition: sequencecurveenums.h:18
nap::SequenceControllerCurve::deleteCurvePoint
void deleteCurvePoint(const std::string &trackID, const std::string &segmentID, int index, int curveIndex)
nap::rtti::ObjectPtr
Definition: objectptr.h:154
nap::SequenceTrackSegmentCurve::setStartValue
void setStartValue(T value)
nap::SequenceTrackSegment
Definition: sequencetracksegment.h:19
nap::SequenceControllerCurve::changeCurveType
void changeCurveType(SequenceTrackSegment &segment, math::ECurveInterp type, int curveIndex)
Definition: sequencecontrollercurve_template.h:227
nap::SequenceTrackSegmentCurve::mCurves
std::vector< ResourcePtr< math::FCurve< float, float > > > mCurves
Property: 'Curves' vector holding curves.
Definition: sequencetracksegmentcurve.h:24
nap::Sequence::mTracks
std::vector< ResourcePtr< SequenceTrack > > mTracks
Property: 'Sequence Tracks' Vector holding resourceptrs to the SequenceTracks.
Definition: sequence.h:26
nap::SequenceControllerCurve::changeLastCurvePoint
void changeLastCurvePoint(SequenceTrackSegment &segment, int curveIndex, float time, float value)
Definition: sequencecontrollercurve_template.h:346
nap::SequenceTrack
Definition: sequencetrack.h:22
nap::SequenceController::getSequence
Sequence & getSequence()
Definition: sequencecontroller.h:131
nap::SequenceControllerCurve::insertCurvePoint
void insertCurvePoint(const std::string &trackID, const std::string &segmentID, float pos, int curveIndex)
nap::SequenceTrackCurve
Definition: sequencetrackcurve.h:33
nap::SequenceController::mService
SequenceService & mService
Definition: sequencecontroller.h:181
nap::SequenceController::performEditAction
void performEditAction(std::function< void()> action)
nap::SequenceTrack::mSegments
std::vector< ResourcePtr< SequenceTrackSegment > > mSegments
Property: 'Segments' Vector holding track segments.
Definition: sequencetrack.h:33
nap::SequenceControllerCurve::addNewCurveTrack
void addNewCurveTrack()
Definition: sequencecontrollercurve_template.h:8
nap::math::FCurvePoint::mInTan
FComplex< T, V > mInTan
Left tangent position, relative to mPos.
Definition: fcurve.h:92
nap::SequenceController::getPlayerReadObjectIDs
std::unordered_set< std::string > & getPlayerReadObjectIDs()
Definition: sequencecontroller.h:172
nap::SequenceControllerCurve::changeCurveSegmentValue
void changeCurveSegmentValue(const std::string &trackID, const std::string &segmentID, float newValue, int curveIndex, sequencecurveenums::ESegmentValueTypes valueType)
nap::SequenceController::getPlayerOwnedObjects
std::vector< std::unique_ptr< rtti::Object > > & getPlayerOwnedObjects()
Definition: sequencecontroller.h:168
nap::math::ECurveInterp::Bezier
@ Bezier
Bezier style interpolation.
nap
Definition: templateapp.h:17
nap::SequenceTrackSegmentCurve::setEndValue
void setEndValue(T value)
nap::sequencecurveenums::END
@ END
Definition: sequencecurveenums.h:20
nap::SequenceService::generateUniqueID
std::string generateUniqueID(std::unordered_set< std::string > &objectIDs, const std::string &baseID="Generated")
nap::math::FCurvePoint::mOutTan
FComplex< T, V > mOutTan
Right tangent position, relative to mPos.
Definition: fcurve.h:93
nap::Sequence
Definition: sequence.h:22
nap::sequencecurveenums::BEGIN
@ BEGIN
Definition: sequencecurveenums.h:20
nap::math::FCurvePoint::mInterp
ECurveInterp mInterp
Definition: fcurve.h:94
nap::math::FCurvePoint
Definition: fcurve.h:75
nap::math::clamp
T clamp(T value, T min, T max)
Definition: mathutils.h:325
nap::math::FCurvePoint::mTangentsAligned
bool mTangentsAligned
Non-essential to functionality, but necessary for editing.
Definition: fcurve.h:96
nap::math::FCurvePoint::mPos
FComplex< T, V > mPos
Position of the handle.
Definition: fcurve.h:91
nap::SequenceControllerCurve::changeTanPoint
bool changeTanPoint(const std::string &trackID, const std::string &segmentID, int pointIndex, int curveIndex, sequencecurveenums::ETanPointTypes tanType, float time, float value)
nap::SequenceControllerCurve::changeMinMaxCurveTrack
void changeMinMaxCurveTrack(const std::string &trackID, T minimum, T maximum)
Definition: sequencecontrollercurve_template.h:487