NAP
sequencecurvetrackview_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 #pragma once
6 
7 // Internal includes
8 #include "sequencecurvetrackview_guiactions.h"
9 #include "sequenceguiutils.h"
10 
11 // External includes
12 #include <imguiutils.h>
13 
14 namespace nap
15 {
16  template<typename T>
18  {
19  auto *action = mState.mAction->getDerived<sequenceguiactions::CurvePointActionPopup<T>>();
20  assert(action!= nullptr);
21 
22  if(!action->mOpened)
23  {
24  ImGui::OpenPopup("Curve Point Actions");
25  action->mOpened = true;
26  }
27 
28  if(ImGui::BeginPopup("Curve Point Actions"))
29  {
30  int curveIndex = action->mCurveIndex;
31 
32  float value = action->mValue * (action->mMaximum[curveIndex] - action->mMinimum[curveIndex]) +
33  action->mMinimum[curveIndex];
34  if(ImGui::InputFloat("value", &value))
35  {
36  auto &curve_controller = getEditor().getController<SequenceControllerCurve>();
37  curve_controller.changeCurvePoint(
38  action->mTrackID,
39  action->mSegmentID,
40  action->mControlPointIndex,
41  action->mCurveIndex,
42  action->mTime,
43  value);
44  updateSegmentInClipboard(action->mTrackID, action->mSegmentID);
45 
46  mState.mDirty = true;
47  }
48 
54  // obtain segment
55  auto &curve_controller = getEditor().getController<SequenceControllerCurve>();
56  const auto *segment = curve_controller.getSegment(action->mTrackID, action->mSegmentID);
57  assert(segment != nullptr);
58 
59  double time = action->mTime * segment->mDuration + segment->mStartTime;
60  double min_time = segment->mStartTime;
61  double max_time = segment->mStartTime + segment->mDuration;
62 
63  std::vector<int> time_array = convertTimeToMMSSMSArray(time);
64 
65  bool edit_time = false;
66 
67  ImGui::Separator();
68  ImGui::PushItemWidth(100.0f * mState.mScale);
69 
70  edit_time = ImGui::InputInt3("Time (mm:ss:ms)", &time_array[0]);
71  time_array[0] = math::clamp<int>(time_array[0], 0, 99999);
72  time_array[1] = math::clamp<int>(time_array[1], 0, 59);
73  time_array[2] = math::clamp<int>(time_array[2], 0, 99);
74 
75  if(edit_time)
76  {
77  double new_time = convertMMSSMSArrayToTime(time_array);
78  new_time = math::clamp(new_time, min_time, max_time);
79 
80  float perc = (new_time - segment->mStartTime) / segment->mDuration;
81  action->mTime = perc;
82  curve_controller.changeCurvePoint(
83  action->mTrackID,
84  action->mSegmentID,
85  action->mControlPointIndex,
86  action->mCurveIndex,
87  perc,
88  action->mValue);
89  updateSegmentInClipboard(action->mTrackID, action->mSegmentID);
90  mState.mDirty = true;
91  }
92 
94  {
95  auto &curve_controller = getEditor().getController<SequenceControllerCurve>();
96  curve_controller.deleteCurvePoint(
97  action->mTrackID,
98  action->mSegmentID,
99  action->mControlPointIndex,
100  action->mCurveIndex);
101  updateSegmentInClipboard(action->mTrackID, action->mSegmentID);
102  mCurveCache.clear();
103 
104  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::None>();
105  mState.mDirty = true;
106 
107  ImGui::CloseCurrentPopup();
108  }
109 
110  ImGui::SameLine();
111 
113  {
114  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::None>();
115  ImGui::CloseCurrentPopup();
116  }
117 
118  ImGui::EndPopup();
119  } else
120  {
121  // click outside popup so cancel action
122  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::None>();
123  }
124  }
125 
126 
127  template<typename T>
129  {
130  auto *action = mState.mAction->getDerived<sequenceguiactions::EditingSegmentCurveValue<T>>();
131  assert(action!= nullptr);
132 
133  if(!action->mOpened)
134  {
135  ImGui::OpenPopup("Segment Value Actions");
136  action->mOpened = true;
137  }
138 
139  if(ImGui::BeginPopup("Segment Value Actions"))
140  {
141  int curveIndex = action->mCurveIndex;
142 
143  float value =
144  action->mValue[curveIndex] * (action->mMaximum[curveIndex] - action->mMinimum[curveIndex]) +
145  action->mMinimum[curveIndex];
146  if(ImGui::InputFloat("value", &value))
147  {
148  float translated_value = (value - action->mMinimum[curveIndex]) /
149  (action->mMaximum[curveIndex] - action->mMinimum[curveIndex]);
150  auto &curve_controller = getEditor().getController<SequenceControllerCurve>();
151  curve_controller.changeCurveSegmentValue(
152  action->mTrackID,
153  action->mSegmentID,
154  translated_value,
155  curveIndex,
156  action->mType);
157  updateSegmentInClipboard(action->mTrackID, action->mSegmentID);
158 
159  mState.mDirty = true;
160  }
161 
163  {
164  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::None>();
165 
166  ImGui::CloseCurrentPopup();
167  }
168 
169  ImGui::EndPopup();
170  } else
171  {
172  // click outside popup so cancel action
173  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::None>();
174  }
175  }
176 
177 
178  template<typename T>
180  const SequenceTrack& track,
181  const SequenceTrackSegment& segmentBase,
182  const ImVec2& trackTopLeft,
183  const float previousSegmentX,
184  const float segmentWidth,
185  const float segmentX,
186  ImDrawList* drawList)
187  {
188  const auto &segment = static_cast<const SequenceTrackSegmentCurve<T> &>(segmentBase);
189  const float points_per_pixel = 0.5f * mState.mScale;
190  const float track_height = track.mTrackHeight * mState.mScale;
191  bool needs_drawing = ImGui::IsRectVisible({trackTopLeft.x + previousSegmentX, trackTopLeft.y}, {
192  trackTopLeft.x + previousSegmentX + segmentWidth, trackTopLeft.y + track_height});
193 
194  if(needs_drawing)
195  {
196  // if no cache present, create new curve
197  if(mCurveCache.find(segment.mID) == mCurveCache.end())
198  {
199  const long point_num = (int) (points_per_pixel * segmentWidth);
200  std::vector<std::vector<ImVec2>> curves;
201  for(int v = 0; v < segment.mCurves.size(); v++)
202  {
203  std::vector<ImVec2> curve;
204  if(point_num > 0)
205  {
206  auto start_x = math::max<float>(trackTopLeft.x, 0);
207  float end_x = start_x + mState.mWindowSize.x + mState.mWindowPos.x;
208 
209  // start drawing at window pos
210  {
211  long i = 0;
212  for(; i <= point_num; i++)
213  {
214  float p = (float) i / (float) point_num;
215  float x = trackTopLeft.x + previousSegmentX + segmentWidth * p;
216  if(x > start_x)
217  {
218  float value = 1.0f - segment.mCurves[v]->evaluate(p);
219  value = math::clamp(value, 0.0f, 1.0f);
220  ImVec2 point =
221  {
222  x,
223  trackTopLeft.y + value * track_height
224  };
225  curve.emplace_back(point);
226  }
227 
228  if(x > end_x)
229  {
230  break; // no longer visible on right side, continuation of this loop is not necessary
231  }
232  }
233  }
234  }
235 
236  curves.emplace_back(std::move(curve));
237  }
238  mCurveCache.emplace(segment.mID, std::move(curves));
239  }
240  }
241 
242  int selected_curve = -1;
244  {
245  // determine if mouse is hovering curve
246  if((mState.mAction->isAction<sequenceguiactions::None>() ||
248  && ImGui::IsMouseHoveringRect(
249  {trackTopLeft.x + segmentX - segmentWidth, trackTopLeft.y}, // top left
250  {trackTopLeft.x + segmentX, trackTopLeft.y + track_height})) // bottom right
251  {
252  // translate mouse position to position in curve
253  ImVec2 mouse_pos = ImGui::GetMousePos();
254  float x_in_segment =
255  ((mouse_pos.x - (trackTopLeft.x + segmentX - segmentWidth)) / mState.mStepSize) / segment.mDuration;
256  float y_in_segment = 1.0f - ((mouse_pos.y - trackTopLeft.y) / track_height);
257 
258  for(int i = 0; i < segment.mCurves.size(); i++)
259  {
260  // evaluate curve at x position
261  float y_in_curve = segment.mCurves[i]->evaluate(x_in_segment);
262 
263  // insert curve point on click
264  const float maxDist = 0.1f;
265  if(std::abs(y_in_curve - y_in_segment) < maxDist)
266  {
267  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::HoveringCurve>(
268  track.mID,
269  segment.mID,
270  i);
271 
272  if(ImGui::IsMouseClicked(1))
273  {
274  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::InsertingCurvePoint>(
275  track.mID,
276  segment.mID,
277  i, x_in_segment);
278  }
279  selected_curve = i;
280  }
281  }
282 
283  if(selected_curve == -1)
284  {
285  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::None>();
286  } else
287  {
288  showValue<T>(
289  track,
290  segment, x_in_segment,
291  mState.mMouseCursorTime, selected_curve);
292  }
293  } else
294  {
296  {
297  auto *action = mState.mAction->getDerived<sequenceguiactions::HoveringCurve>();
298 
299  if(action->mSegmentID == segment.mID)
300  {
301  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::None>();
302  }
303  }
304  }
305  }
306 
307  if(needs_drawing)
308  {
309  for(int i = 0; i < segment.mCurves.size(); i++)
310  {
311  if(mCurveCache[segment.mID][i].size() > 0)
312  {
313  float thickness = selected_curve == i ? 3.0f : 1.0f;
314  thickness *= mState.mScale;
315  drawList->AddPolyline
316  (
317  &*mCurveCache[segment.mID][i].begin(), // points array
318  mCurveCache[segment.mID][i].size(), // size of points array
319  mService.getColors().mCurveColors[i], // color
320  false, // closed
321  thickness // thickness
322  );
323  }
324  }
325  }
326  }
327 
328 
329  template<typename T>
331  const SequenceTrack& track,
332  const SequenceTrackSegment& segment,
333  const ImVec2& trackTopLeft,
334  float previousSegmentX,
335  float segmentWidth,
336  float segmentX,
337  ImDrawList* drawList,
338  bool drawStartValue)
339  {
340  // TODO : do this without the elif statement
344  bool draw_selection_background = false;
346  {
347  auto *action = mState.mAction->getDerived<sequenceguiactions::HoveringSegmentValue>();
348  draw_selection_background = action->mSegmentID == segment.mID;
350  {
351  auto *action = mState.mAction->getDerived<sequenceguiactions::EditingCurveSegment>();
352  draw_selection_background = action->mSegmentID == segment.mID;
353  } else if(mState.mAction->isAction<sequenceguiactions::HoveringSegment>())
354  {
355  auto *action = mState.mAction->getDerived<sequenceguiactions::HoveringSegment>();
356  draw_selection_background = action->mSegmentID == segment.mID;
357  } else if(mState.mAction->isAction<sequenceguiactions::DraggingSegment>())
358  {
359  auto *action = mState.mAction->getDerived<sequenceguiactions::DraggingSegment>();
360  draw_selection_background = action->mSegmentID == segment.mID;
362  {
363  auto *action = mState.mAction->getDerived<sequenceguiactions::DraggingSegmentValue>();
364  draw_selection_background = action->mSegmentID == segment.mID;
365  }
366 
367  const float track_height = track.mTrackHeight * mState.mScale;
368 
369  if(draw_selection_background)
370  {
371  drawList->AddRectFilled(
372  {trackTopLeft.x + segmentX - segmentWidth, trackTopLeft.y}, // top left
373  {trackTopLeft.x + segmentX, trackTopLeft.y + track_height}, // top right
374  ImGui::ColorConvertFloat4ToU32(ImVec4(1, 1, 1, 0.25f))); // color
375  } else
376  {
377  // is this segment currently serialized in the clipboard
379  {
380  // get derived clipboard
381  auto *curve_segment_clipboard = mState.mClipboard->getDerived<sequenceguiclipboard::CurveSegmentClipboard>();
382 
383  // does it contain this segment ?
384  if(curve_segment_clipboard->containsObject(segment.mID, getPlayer().getSequenceFilename()))
385  {
386  ImVec4 red = ImGui::ColorConvertU32ToFloat4(mService.getColors().mHigh1);
387  red.w = 0.25f;
388  drawList->AddRectFilled
389  (
390  {trackTopLeft.x + segmentX - segmentWidth, trackTopLeft.y}, // top left
391  {trackTopLeft.x + segmentX, trackTopLeft.y + track_height}, // top right
392  ImGui::ColorConvertFloat4ToU32(red) // color
393  );
394  }
395  }
396  }
397 
398  // draw curve(s)
399  drawCurves<T>(
400  track,
401  segment,
402  trackTopLeft,
403  previousSegmentX,
404  segmentWidth,
405  segmentX,
406  drawList);
407 
408 
409  // draw control points
410  drawControlPoints<T>(
411  track,
412  segment,
413  trackTopLeft,
414  segmentX,
415  segmentWidth,
416  drawList);
417 
418  // if this is the first segment of the track
419  // also draw a handler for the start value
420  if(drawStartValue)
421  {
422  // draw segment value handler
423  drawSegmentValue<T>(
424  track,
425  segment,
426  trackTopLeft,
427  segmentX,
428  segmentWidth,
429  sequencecurveenums::ESegmentValueTypes::BEGIN,
430  drawList);
431  }
432 
433  // draw segment value handler
434  drawSegmentValue<T>(
435  track,
436  segment,
437  trackTopLeft,
438  segmentX,
439  segmentWidth,
440  sequencecurveenums::ESegmentValueTypes::END,
441  drawList);
442  }
443 
444 
445  template<typename T>
447  {
448  const auto &curve_track = static_cast<const SequenceTrackCurve<T> &>(track);
449 
450  T min = curve_track.mMinimum;
451  T max = curve_track.mMaximum;
452 
453  //
454  ImGui::PushID(track.mID.c_str());
455  float offset = 5.0f * mState.mScale;
456  float drag_float_x = ImGui::GetCursorPosX() + (40.0f * mState.mScale);
457  ImGui::SetCursorPos({ImGui::GetCursorPosX() + offset, ImGui::GetCursorPosY() + offset});
458  ImGui::Text("Min:");
459  ImGui::SameLine();
460  ImGui::PushID("min");
461  ImGui::SetCursorPosX(drag_float_x);
462  if(inputFloat<T>(min, 3))
463  {
464  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::ChangeMinMaxCurve<T>>(track.mID, min, max);
465  }
466  ImGui::PopID();
467  ImGui::PopItemWidth();
468  ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offset);
469  ImGui::Text("Max:");
470  ImGui::SameLine();
471  ImGui::PushID("max");
472  ImGui::SetCursorPosX(drag_float_x);
473  if(inputFloat<T>(max, 3))
474  {
475  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::ChangeMinMaxCurve<T>>(track.mID, min, max);
476  }
477  ImGui::PopID();
478  ImGui::PopItemWidth();
479  ImGui::PopID();
480  }
481 
482 
483  template<typename T>
485  const SequenceTrack& track,
486  const SequenceTrackSegment& segmentBase,
487  const ImVec2& trackTopLeft,
488  const float segmentX,
489  const float segmentWidth,
490  const sequencecurveenums::ESegmentValueTypes segmentType,
491  ImDrawList* drawList)
492  {
493  static std::unordered_map<rttr::type, std::function<float(const SequenceTrackSegment &, int, sequencecurveenums::ESegmentValueTypes)>> get_value_map
494  {
495  {RTTI_OF(float), [](const SequenceTrackSegment &segment, int curveIndex, sequencecurveenums::ESegmentValueTypes segmentType) -> float
496  {
497  return static_cast<const SequenceTrackSegmentCurve<float> *>(&segment)->getValue(
498  segmentType == sequencecurveenums::BEGIN ? 0.0f : 1.0f);
499  }},
500  {RTTI_OF(glm::vec2), [](const SequenceTrackSegment &segment, int curveIndex, sequencecurveenums::ESegmentValueTypes segmentType) -> float
501  {
502  return static_cast<const SequenceTrackSegmentCurve<glm::vec2> *>(&segment)->getValue(
503  segmentType == sequencecurveenums::BEGIN ? 0.0f : 1.0f)[curveIndex];
504  }},
505  {RTTI_OF(glm::vec3), [](const SequenceTrackSegment &segment, int curveIndex, sequencecurveenums::ESegmentValueTypes segmentType) -> float
506  {
507  return static_cast<const SequenceTrackSegmentCurve<glm::vec3> *>(&segment)->getValue(
508  segmentType == sequencecurveenums::BEGIN ? 0.0f : 1.0f)[curveIndex];
509  }},
510  {RTTI_OF(glm::vec4), [](const SequenceTrackSegment &segment, int curveIndex, sequencecurveenums::ESegmentValueTypes segmentType) -> float
511  {
512  return static_cast<const SequenceTrackSegmentCurve<glm::vec4> *>(&segment)->getValue(
513  segmentType == sequencecurveenums::BEGIN ? 0.0f : 1.0f)[curveIndex];
514  }}
515  };
516  const float track_height = track.mTrackHeight * mState.mScale;
517 
518  assert(segmentBase.get_type().template is_derived_from<SequenceTrackSegmentCurve<T>>());
519  const auto &segment = static_cast<const SequenceTrackSegmentCurve<T> &>(segmentBase);
520 
521  for(int v = 0; v < segment.mCurves.size(); v++)
522  {
523  // calculate point of this value in the window
524  ImVec2 segment_value_pos =
525  {
526  trackTopLeft.x + segmentX - (segmentType == sequencecurveenums::BEGIN ? segmentWidth : 0.0f),
527  trackTopLeft.y + track_height * (1.0f - ((segmentType == sequencecurveenums::BEGIN ?
528  (float) segment.mCurves[v]->mPoints[0].mPos.mValue :
529  (float) segment.mCurves[v]->mPoints[
530  segment.mCurves[v]->mPoints.size() - 1].mPos.mValue) /
531  1.0f))
532  };
533 
534  bool hovered = false;
535 
537  {
538  // check if we are hovering this value
539  if((mState.mAction->isAction<sequenceguiactions::None>() ||
543  ImGui::IsMouseHoveringRect(
544  {segment_value_pos.x - (12.0f * mState.mScale),
545  segment_value_pos.y - (12.0f * mState.mScale)}, // top left
546  {segment_value_pos.x + (12.0f * mState.mScale),
547  segment_value_pos.y + (12.0f * mState.mScale)})) // bottom right
548  {
549  hovered = true;
550  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::HoveringSegmentValue>(
551  track.mID,
552  segment.mID,
553  segmentType,
554  v);
555 
556  if(ImGui::IsMouseDown(0))
557  {
558  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::DraggingSegmentValue>(
559  track.mID,
560  segment.mID,
561  segmentType,
562  v,
563  get_value_map[RTTI_OF(T)](segment, v, segmentType));
564  } else if(ImGui::IsMouseDown(1))
565  {
566  const auto &curve_segment = static_cast<const SequenceTrackSegmentCurve<T> &>(segment);
567  const auto &curve_track = static_cast<const SequenceTrackCurve<T> &>(track);
568 
569  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::EditingSegmentCurveValue<T>>(
570  track.mID,
571  segment.mID,
572  segmentType,
573  v,
574  (segmentType == sequencecurveenums::ESegmentValueTypes::BEGIN)
575  ? curve_segment.getStartValue() : curve_segment.getEndValue(),
576  curve_track.mMinimum,
577  curve_track.mMaximum);
578  }
579 
580  showValue<T>(
581  track,
582  segment,
583  segmentType == sequencecurveenums::BEGIN ? 0.0f : 1.0f,
584  segmentType == sequencecurveenums::BEGIN ? segment.mStartTime : segment.mStartTime +
585  segment.mDuration,
586  v);
588  {
590  {
591  auto *action = mState.mAction->getDerived<sequenceguiactions::HoveringSegmentValue>();
592 
593  if(action->mType == segmentType &&
594  action->mSegmentID == segment.mID &&
595  action->mCurveIndex == v)
596  {
597  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::None>();
598 
599  showValue<T>(
600  track,
601  segment,
602  segmentType == sequencecurveenums::BEGIN ? 0.0f : 1.0f,
603  segmentType == sequencecurveenums::BEGIN ? segment.mStartTime : segment.mStartTime +
604  segment.mDuration,
605  v);
606  }
607  }
608  }
609 
610  // handle dragging segment value
612  {
613  auto *action = mState.mAction->getDerived<sequenceguiactions::DraggingSegmentValue>();
614  if(action->mSegmentID == segment.mID)
615  {
616  if(action->mType == segmentType && action->mCurveIndex == v)
617  {
618  hovered = true;
619  showValue<T>(
620  track,
621  segment,
622  segmentType == sequencecurveenums::BEGIN ? 0.0f : 1.0f,
623  segmentType == sequencecurveenums::BEGIN ? segment.mStartTime : segment.mStartTime +
624  segment.mDuration,
625  v);
626 
627  float drag_amount = (mState.mMouseDelta.y / track_height) * -1.0f;
628  float value = get_value_map[RTTI_OF(T)](segment, v, segmentType) + drag_amount;
629 
630  action->mNewValue = value;
631  }
632  }
633  }
634  }
635 
636  float circle_radius = 5.0f * mState.mScale;
637  if(hovered)
638  drawList->AddCircleFilled(segment_value_pos, circle_radius, mService.getColors().mCurveColors[v]);
639  else
640  drawList->AddCircle(segment_value_pos, circle_radius, mService.getColors().mCurveColors[v]);
641  }
642  }
643 
644 
645  template<typename T>
647  const SequenceTrack& track,
648  const SequenceTrackSegment& segmentBase,
649  const ImVec2& trackTopLeft,
650  const float segmentX,
651  const float segmentWidth,
652  ImDrawList* drawList)
653  {
654 
655  const auto &segment = static_cast<const SequenceTrackSegmentCurve<T> &>(segmentBase);
656  const float track_height = track.mTrackHeight * mState.mScale;
657 
658  // draw first control point(s) handlers IF this is the first segment of the track
659  if(track.mSegments[0]->mID == segment.mID)
660  {
661  for(int v = 0; v < segment.mCurves.size(); v++)
662  {
663  const auto &curve_point = segment.mCurves[v]->mPoints[0];
664  std::ostringstream string_stream;
665  string_stream << segment.mID << "_point_" << 0 << "_curve_" << v;
666 
667  ImVec2 circle_point =
668  {(trackTopLeft.x + segmentX - segmentWidth) + segmentWidth * curve_point.mPos.mTime,
669  trackTopLeft.y + track_height * (1.0f - (float) curve_point.mPos.mValue)};
670 
671  // only draw tan handlers when we have a bezier
672  if(segment.mCurveTypes[v] == math::ECurveInterp::Bezier)
673  {
674  drawTanHandler<T>(
675  track,
676  segment, string_stream,
677  segmentWidth, curve_point, circle_point,
678  0,
679  v,
680  sequencecurveenums::ETanPointTypes::IN,
681  drawList);
682 
683  drawTanHandler<T>(
684  track,
685  segment, string_stream,
686  segmentWidth, curve_point, circle_point,
687  0,
688  v,
689  sequencecurveenums::ETanPointTypes::OUT,
690  drawList);
691  }
692  }
693  }
694 
695  // draw control points of curves
696  // we ignore the first and last because they are controlled by the start & end value of the segment
697  for(int v = 0; v < segment.mCurves.size(); v++)
698  {
699  for(int i = 1; i < segment.mCurves[v]->mPoints.size() - 1; i++)
700  {
701  // get the curvepoint and generate a unique ID for the control point
702  const auto &curve_point = segment.mCurves[v]->mPoints[i];
703  std::ostringstream string_stream;
704  string_stream << segment.mID << "_point_" << i << "_curve_" << v;
705  std::string point_id = string_stream.str();
706 
707  // determine the point at where to draw the control point
708  ImVec2 circle_point =
709  {(trackTopLeft.x + segmentX - segmentWidth) + segmentWidth * curve_point.mPos.mTime,
710  trackTopLeft.y + track_height * (1.0f - (float) curve_point.mPos.mValue)};
711 
712  // handle mouse hovering
713  bool hovered = false;
714  float offset = 5.0f * mState.mScale;
716  {
717  if((mState.mAction->isAction<sequenceguiactions::None>() ||
720  && ImGui::IsMouseHoveringRect({circle_point.x - offset, circle_point.y - offset},
721  {circle_point.x + offset, circle_point.y + offset}))
722  {
723  hovered = true;
724  }
725  }
726 
727  if(hovered)
728  {
729  // if we are hovering this point, store ID
730  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::HoveringControlPoint>(
731  track.mID,
732  segment.mID,
733  i,
734  v);
735 
736  // show value of current control point as tooltip
737  showValue<T>(
738  track,
739  segment, curve_point.mPos.mTime,
740  curve_point.mPos.mTime * segment.mDuration + segment.mStartTime,
741  v);
742 
743  // is the mouse held down, then we are dragging
744  if(ImGui::IsMouseDown(0))
745  {
746  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::DraggingControlPoint>(
747  track.mID,
748  segment.mID,
749  i,
750  v,
751  curve_point.mPos.mTime,
752  curve_point.mPos.mValue);
753  }
754  // if we clicked right mouse button, open curve action popup
755  else if(ImGui::IsMouseClicked(1))
756  {
757  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::CurvePointActionPopup<T>>(
758  track.mID,
759  segment.mID,
760  i,
761  v,
762  curve_point.mPos.mValue,
763  curve_point.mPos.mTime,
764  static_cast<const SequenceTrackCurve<T> &>(track).mMinimum,
765  static_cast<const SequenceTrackCurve<T> &>(track).mMaximum);
766  }
767  } else
768  {
769  // otherwise, if we where hovering but not anymore, stop hovering
771  {
772  auto *action = mState.mAction->getDerived<sequenceguiactions::HoveringControlPoint>();
773  if(action->mControlPointIndex == i && track.mID == action->mTrackID &&
774  segment.mID == action->mSegmentID && v == action->mCurveIndex)
775  {
776  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::None>();
777  }
778  }
779  }
780 
782  {
783  // handle dragging of control point
785  {
786  auto *action = mState.mAction->getDerived<sequenceguiactions::DraggingControlPoint>();
787 
788  if(action->mSegmentID == segment.mID)
789  {
790  if(action->mControlPointIndex == i && action->mCurveIndex == v)
791  {
792  float time_adjust = mState.mMouseDelta.x / segmentWidth;
793  float value_adjust = (mState.mMouseDelta.y / track_height) * -1.0f;
794 
795  hovered = true;
796 
797  showValue<T>(
798  track,
799  segment, curve_point.mPos.mTime,
800  curve_point.mPos.mTime * segment.mDuration + segment.mStartTime,
801  v);
802 
803  action->mNewValue += value_adjust;
804  action->mNewTime += time_adjust;
805  }
806  }
807  }
808  }
809 
810  // draw the control point
811  drawList->AddCircleFilled
812  (
813  circle_point, 4.0f * mState.mScale,
815  );
816 
817  if(segment.mCurveTypes[v] == math::ECurveInterp::Bezier)
818  {
819  // draw the handlers
820  drawTanHandler<T>(
821  track,
822  segment, string_stream,
823  segmentWidth, curve_point, circle_point,
824  i,
825  v,
826  sequencecurveenums::ETanPointTypes::IN,
827  drawList);
828 
829  drawTanHandler<T>(
830  track,
831  segment, string_stream,
832  segmentWidth, curve_point, circle_point,
833  i,
834  v,
835  sequencecurveenums::ETanPointTypes::OUT,
836  drawList);
837  }
838  }
839  }
840 
841  for(int v = 0; v < segment.mCurves.size(); v++)
842  {
843  // handle last control point
844  // overlaps with endvalue so only draw tan handlers
845  const int control_point_index = segment.mCurves[v]->mPoints.size() - 1;
846  const auto &curve_point = segment.mCurves[v]->mPoints[control_point_index];
847 
848  std::ostringstream string_stream;
849  string_stream << segment.mID << "_point_" << control_point_index << "_curve_" << v;
850  std::string point_id = string_stream.str();
851 
852  ImVec2 circle_point =
853  {(trackTopLeft.x + segmentX - segmentWidth) + segmentWidth * curve_point.mPos.mTime,
854  trackTopLeft.y + track_height * (1.0f - (float) curve_point.mPos.mValue)};
855 
856  if(segment.mCurveTypes[v] == math::ECurveInterp::Bezier)
857  {
858  drawTanHandler<T>(
859  track,
860  segment, string_stream,
861  segmentWidth, curve_point, circle_point, control_point_index,
862  v,
863  sequencecurveenums::ETanPointTypes::IN,
864  drawList);
865 
866  drawTanHandler<T>(
867  track,
868  segment, string_stream,
869  segmentWidth, curve_point, circle_point, control_point_index,
870  v,
871  sequencecurveenums::ETanPointTypes::OUT,
872  drawList);
873  }
874  }
875 
876  //
877  ImGui::SetCursorPosY(ImGui::GetCursorPosY() - track_height);
878  }
879 
880 
881  template<typename T>
883  const SequenceTrack& track,
884  const SequenceTrackSegment& segment,
885  std::ostringstream& stringStream,
886  const float segmentWidth,
887  const math::FCurvePoint<float, float>& curvePoint,
888  const ImVec2& circlePoint,
889  const int controlPointIndex,
890  const int curveIndex,
892  ImDrawList* drawList)
893  {
894  const float track_height = track.mTrackHeight * mState.mScale;
895 
896  // draw tan handlers
897  {
898  // create a string stream to create identifier of this object
899  std::ostringstream tan_stream;
900  tan_stream << stringStream.str() << ((type == sequencecurveenums::ETanPointTypes::IN) ? "inTan" : "outTan");
901 
902  //
903  const math::FComplex<float, float> &tan_complex = (type == sequencecurveenums::ETanPointTypes::IN)
904  ? curvePoint.mInTan : curvePoint.mOutTan;
905 
906  // get the offset from the tan
907  const float tan_constant_size = 100.0f * mState.mScale;
908  ImVec2 offset = {tan_complex.mTime * tan_constant_size,
909  static_cast<float>(tan_complex.mValue) * -1.0f * tan_constant_size};
910  ImVec2 tan_point = {circlePoint.x + offset.x, circlePoint.y + offset.y};
911 
912  // set if we are hoverting this point with the mouse
913  bool tan_point_hovered = false;
914  float tan_bounds = mState.mScale * 5.0f;
915 
917  {
918  // check if hovered
919  if((mState.mAction->template isAction<sequenceguiactions::None>() ||
920  mState.mAction->template isAction<sequenceguiactions::HoveringCurve>() ||
921  mState.mAction->template isAction<sequenceguiactions::HoveringSegment>())
922  && ImGui::IsMouseHoveringRect
923  (
924  {tan_point.x - tan_bounds, tan_point.y - tan_bounds},
925  {tan_point.x + tan_bounds, tan_point.y + tan_bounds})
926  )
927  {
928  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::HoveringTanPoint>(track.mID, tan_stream.str());
929  tan_point_hovered = true;
930  } else if(mState.mAction->isAction<sequenceguiactions::HoveringTanPoint>())
931  {
932  auto *action = mState.mAction->getDerived<sequenceguiactions::HoveringTanPoint>();
933 
934  // if we hare already hovering, check if its this point
935  if(action->mTanPointID == tan_stream.str())
936  {
937  if(ImGui::IsMouseHoveringRect(
938  {tan_point.x - tan_bounds, tan_point.y - tan_bounds},
939  {tan_point.x + tan_bounds, tan_point.y + tan_bounds}))
940  {
941  // still hovering
942  tan_point_hovered = true;
943 
944  // start dragging if mouse down
945  if(ImGui::IsMouseDown(0))
946  {
947  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::DraggingTanPoint>(
948  track.mID,
949  segment.mID,
950  controlPointIndex,
951  curveIndex,
952  type);
953  } else if(ImGui::IsMouseDown(1)) // open edit popup
954  {
955  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::EditingTanPointPopup>(
956  track.mID,
957  segment.mID,
958  controlPointIndex,
959  curveIndex,
960  type,
961  (float) tan_complex.mValue,
962  tan_complex.mTime);
963  }
964  } else
965  {
966  // otherwise, release!
967  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::None>();
968  }
969  }
970  }
971 
972  // handle dragging of tan point
974  {
975  auto *action = mState.mAction->getDerived<sequenceguiactions::DraggingTanPoint>();
976 
977  if(action->mSegmentID == segment.mID &&
978  action->mControlPointIndex == controlPointIndex &&
979  action->mType == type &&
980  action->mCurveIndex == curveIndex)
981  {
982  tan_point_hovered = true;
983 
984  float delta_time = mState.mMouseDelta.x / tan_constant_size;
985  float delta_value = (mState.mMouseDelta.y / tan_constant_size) * -1.0f;
986 
987  const auto &curve_segment = static_cast<const SequenceTrackSegmentCurve<T> &>(segment);
988 
989  float new_time;
990  float new_value;
991  if(type == sequencecurveenums::ETanPointTypes::IN)
992  {
993  new_time =
994  curve_segment.mCurves[curveIndex]->mPoints[controlPointIndex].mInTan.mTime + delta_time;
995  new_value = curve_segment.mCurves[curveIndex]->mPoints[controlPointIndex].mInTan.mValue +
996  delta_value;
997  } else
998  {
999  new_time = curve_segment.mCurves[curveIndex]->mPoints[controlPointIndex].mOutTan.mTime +
1000  delta_time;
1001  new_value = curve_segment.mCurves[curveIndex]->mPoints[controlPointIndex].mOutTan.mValue +
1002  delta_value;
1003  }
1004 
1005  action->mNewTime = new_time;
1006  action->mNewValue = new_value;
1007  }
1008  }
1009  }
1010 
1011  // draw line
1012  drawList->AddLine(circlePoint, tan_point, tan_point_hovered ? mService.getColors().mFro4
1013  : mService.getColors().mFro1,
1014  1.0f * mState.mScale);
1015 
1016  // draw handler
1017  drawList->AddCircleFilled(tan_point, 3.0f * mState.mScale, tan_point_hovered ? mService.getColors().mFro4
1018  : mService.getColors().mFro1);
1019  }
1020  }
1021 
1022 
1023  template<typename T>
1024  bool SequenceCurveTrackView::pasteClipboardSegments(const std::string &trackId, double time, utility::ErrorState &errorState)
1025  {
1026  // get clipboard action
1027  auto *curve_segment_clipboard = mState.mClipboard->getDerived<sequenceguiclipboard::CurveSegmentClipboard>();
1028 
1029  // create vector & object ptr to be filled by de-serialization
1030  std::vector<std::unique_ptr<rtti::Object>> read_objects;
1031 
1032  // continue upon succesfull de-serialization
1033  std::vector<T *> curve_segments = curve_segment_clipboard->deserialize<T>(read_objects, errorState);
1034 
1035  if(errorState.hasErrors())
1036  {
1037  nap::Logger::error(errorState.toString());
1038  return false;
1039  } else
1040  {
1041  assert(curve_segments.size() > 0); // no curve segments deserialized
1042 
1043  // sort curve segments by start time
1044  std::sort(curve_segments.begin(), curve_segments.end(), [](T *a, T *b)
1045  {
1046  return a->mStartTime < b->mStartTime;
1047  });
1048 
1049  // adjust start times by duration and start from 0.0
1050  if(curve_segments.size() > 0)
1051  {
1052  curve_segments[0]->mStartTime = 0.0;
1053  }
1054  for(int i = 1; i < curve_segments.size(); i++)
1055  {
1056  curve_segments[i]->mStartTime = curve_segments[i - 1]->mStartTime + curve_segments[i - 1]->mDuration;
1057  }
1058 
1059  //
1060  for(auto curve_segment: curve_segments)
1061  {
1062  // obtain controller
1063  auto *base_controller = getEditor().getControllerWithTrackID(trackId);
1064 
1065  // controller for track id not found
1066  assert(base_controller != nullptr);
1067 
1068  // upcast
1069  assert(base_controller->get_type().template is_derived_from<SequenceControllerCurve>());
1070  auto *curve_controller = static_cast<SequenceControllerCurve *>(base_controller);
1071 
1072  // insert new segment
1073  const auto *new_segment = curve_controller->insertSegment(trackId, time + curve_segment->mStartTime);
1074 
1075  // copy label
1076  curve_controller->changeSegmentLabel(trackId, new_segment->mID, curve_segment->mLabel);
1077 
1078  // change duration
1079  curve_controller->segmentDurationChange(trackId, new_segment->mID, curve_segment->mDuration);
1080 
1081  // update any segments that could be changed
1082  updateSegmentsInClipboard(trackId);
1083 
1084  // copy curve points & curve type
1085  for(int c = 0; c < curve_segment->mCurves.size(); c++)
1086  {
1087  for(int i = 1; i < curve_segment->mCurves[c]->mPoints.size() - 1; i++)
1088  {
1089  curve_controller->insertCurvePoint(trackId, new_segment->mID, curve_segment->mCurves[c]->mPoints[i].mPos.mTime, c);
1090  }
1091 
1092  curve_controller->changeCurveType(trackId, new_segment->mID, curve_segment->mCurveTypes[c], c);
1093  }
1094 
1095  // change all curvepoints to match the copied clipboard curve segment
1096  // note that the first point is always determined by the previous segment
1097  for(int c = 0; c < curve_segment->mCurves.size(); c++)
1098  {
1099  for(int i = 0; i < curve_segment->mCurves[c]->mPoints.size(); i++)
1100  {
1101  curve_controller->changeCurvePoint(trackId, new_segment->mID, i, c,
1102  curve_segment->mCurves[c]->mPoints[i].mPos.mTime,
1103  curve_segment->mCurves[c]->mPoints[i].mPos.mValue);
1104 
1105  curve_controller->changeTanPoint(trackId, new_segment->mID, i, c, sequencecurveenums::IN,
1106  curve_segment->mCurves[c]->mPoints[i].mInTan.mTime,
1107  curve_segment->mCurves[c]->mPoints[i].mInTan.mValue);
1108  }
1109  }
1110 
1111  // make the controller re-align start & end points of segments
1112  curve_controller->updateCurveSegments(trackId);
1113 
1114  // update any segments we have in the clipboard
1115  updateSegmentsInClipboard(trackId);
1116  }
1117  }
1118 
1119  return true;
1120  }
1121 
1122 
1123  template<typename T>
1124  void SequenceCurveTrackView::pasteClipboardSegmentInto(const std::string& trackId, const std::string& segmentId)
1125  {
1126  // get clipboard action
1127  auto *curve_segment_clipboard = mState.mClipboard->getDerived<sequenceguiclipboard::CurveSegmentClipboard>();
1128 
1129  // expect 1 object
1130  assert(curve_segment_clipboard->getObjectCount() == 1);
1131 
1132  // create vector & object ptr to be filled by de-serialization
1133  std::vector<std::unique_ptr<rtti::Object>> read_objects;
1134  std::vector<T *> curve_segments;
1135 
1136  // continue upon successful de-serialization
1137  utility::ErrorState errorState;
1138  curve_segments = curve_segment_clipboard->deserialize<T>(read_objects, errorState);
1139 
1140  if(!errorState.hasErrors())
1141  {
1142  T *curve_segment = curve_segments[0];
1143 
1144  assert(curve_segment != nullptr); // curve segment cannot be null here
1145 
1146  // obtain controller
1147  auto &curve_controller = getEditor().getController<SequenceControllerCurve>();
1148 
1149  // insert new segment
1150  const auto *target_segment = curve_controller.getSegment(trackId, segmentId);
1151 
1152  // upcast target segment to type of T
1153  assert(target_segment->get_type().template is_derived_from<T>()); // cannot upcast
1154  const T *target_segment_upcast = static_cast<const T *>(target_segment);
1155 
1156  // delete all points except the first and last one
1157  for(size_t c = 0; c < target_segment_upcast->mCurves.size(); c++)
1158  {
1159  for(size_t p = 1; p < target_segment_upcast->mCurves[c]->mPoints.size() - 1; p++)
1160  {
1161  curve_controller.deleteCurvePoint(trackId, segmentId, p, c);
1162  }
1163  }
1164 
1165  // change duration
1166  curve_controller.segmentDurationChange(trackId, target_segment_upcast->mID, curve_segment->mDuration);
1167 
1168  // copy curve points & curve type
1169  for(int c = 0; c < curve_segment->mCurves.size(); c++)
1170  {
1171  for(int i = 1; i < curve_segment->mCurves[c]->mPoints.size() - 1; i++)
1172  {
1173  curve_controller.insertCurvePoint(trackId, target_segment_upcast->mID, curve_segment->mCurves[c]->mPoints[i].mPos.mTime, c);
1174  }
1175 
1176  curve_controller.changeCurveType(trackId, target_segment_upcast->mID, curve_segment->mCurveTypes[c], c);
1177  }
1178 
1179  // change all curvepoints to match the copied clipboard curve segment
1180  // note that the first point is always determined by the previous segment
1181  for(int c = 0; c < curve_segment->mCurves.size(); c++)
1182  {
1183  for(int i = 0; i < curve_segment->mCurves[c]->mPoints.size(); i++)
1184  {
1185  curve_controller.changeCurvePoint(trackId, target_segment_upcast->mID, i, c,
1186  curve_segment->mCurves[c]->mPoints[i].mPos.mTime,
1187  curve_segment->mCurves[c]->mPoints[i].mPos.mValue);
1188 
1189  curve_controller.changeTanPoint(trackId, target_segment_upcast->mID, i, c, sequencecurveenums::IN,
1190  curve_segment->mCurves[c]->mPoints[i].mInTan.mTime,
1191  curve_segment->mCurves[c]->mPoints[i].mInTan.mValue);
1192  }
1193  }
1194 
1195  // make the controller re-align start & end points of segments
1196  curve_controller.updateCurveSegments(trackId);
1197 
1198  // update any segments we have in the clipboard
1199  updateSegmentsInClipboard(trackId);
1200  } else
1201  {
1202  nap::Logger::error(errorState.toString());
1203  }
1204  }
1205 
1206 
1207  template<typename T>
1208  void SequenceCurveTrackView::handleChangeMinMaxCurve()
1209  {
1210  auto *action = mState.mAction->template getDerived<sequenceguiactions::ChangeMinMaxCurve<T>>();
1211  auto &controller = getEditor().template getController<SequenceControllerCurve>();
1212  controller.template changeMinMaxCurveTrack<T>(action->mTrackID, action->mNewMin, action->mNewMax);
1213 
1214  mState.mDirty = true;
1215  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::None>();
1216  }
1217 }
nap::SequenceEditor::getController
T & getController()
Definition: sequenceeditor.h:87
nap::rtti::Object::mID
std::string mID
Property: 'mID' unique name of the object. Used as an identifier by the system.
Definition: object.h:82
nap::sequenceguiactions::HoveringSegment
Definition: sequenceeditorguiactions.h:194
nap::sequenceguiactions::HoveringTanPoint
Definition: sequencecurvetrackview_guiactions.h:67
nap::SequenceController::getSegment
const SequenceTrackSegment * getSegment(const std::string &trackID, const std::string &segmentID) const
nap::SequenceGUIService::Colors::mFro4
ImU32 mFro4
Text.
Definition: sequenceguiservice.h:86
nap::SequenceGUIService::getColors
const Colors & getColors() const
Definition: sequenceguiservice.h:201
nap::SequenceCurveTrackView::handleCurvePointActionPopup
void handleCurvePointActionPopup()
Definition: sequencecurvetrackview_template.h:17
nap::sequencecurveenums::ETanPointTypes
ETanPointTypes
Definition: sequencecurveenums.h:13
nap::sequenceguiactions::HoveringSegment::mSegmentID
std::string mSegmentID
Definition: sequenceeditorguiactions.h:208
nap::SequenceTrackView::mState
SequenceEditorGUIState & mState
Definition: sequencetrackview.h:127
nap::IMGuiService::getIcon
nap::Icon & getIcon(std::string &&name)
nap::SequenceCurveTrackView::drawTanHandler
void drawTanHandler(const SequenceTrack &track, const SequenceTrackSegment &segment, std::ostringstream &stringStream, float segmentWidth, const math::FCurvePoint< float, float > &curvePoint, const ImVec2 &circlePoint, int controlPointIndex, int curveIndex, sequencecurveenums::ETanPointTypes type, ImDrawList *drawList)
Definition: sequencecurvetrackview_template.h:882
nap::SequenceGUIService::Colors::mCurveColors
ImU32 mCurveColors[4]
Definition: sequenceguiservice.h:88
nap::sequenceguiactions::DraggingTanPoint
Definition: sequencecurvetrackview_guiactions.h:198
nap::SequenceCurveTrackView::drawSegmentValue
void drawSegmentValue(const SequenceTrack &track, const SequenceTrackSegment &segment, const ImVec2 &trackTopLeft, float segmentX, float segmentWidth, sequencecurveenums::ESegmentValueTypes segmentType, ImDrawList *drawList)
Definition: sequencecurvetrackview_template.h:484
nap::SequenceEditorGUIState::mWindowSize
ImVec2 mWindowSize
Definition: sequenceeditorguistate.h:48
nap::SequenceControllerCurve::changeCurvePoint
void changeCurvePoint(const std::string &trackID, const std::string &segmentID, int pointIndex, int curveIndex, float time, float value)
nap::SequenceEditorGUIState::mMouseCursorTime
double mMouseCursorTime
Definition: sequenceeditorguistate.h:75
nap::SequenceGUIService::getGui
nap::IMGuiService & getGui()
nap::math::FComplex
Definition: fcurve.h:35
nap::SequenceTrackSegmentCurve
Definition: sequencetracksegmentcurve.h:19
nap::SequenceCurveTrackView::drawSegmentContent
void drawSegmentContent(const SequenceTrack &track, const SequenceTrackSegment &segment, const ImVec2 &trackTopLeft, float previousSegmentX, float segmentWidth, float segmentX, ImDrawList *drawList, bool drawStartValue)
Definition: sequencecurvetrackview_template.h:330
nap::sequenceguiactions::EditingCurveSegment::mSegmentID
std::string mSegmentID
Definition: sequencecurvetrackview_guiactions.h:277
nap::convertMMSSMSArrayToTime
double NAPAPI convertMMSSMSArrayToTime(const std::vector< int > &timeArray)
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::SequenceGUIService::Colors::mFro2
ImU32 mFro2
Dark Foreground.
Definition: sequenceguiservice.h:84
nap::SequenceTrackView::getPlayer
const SequencePlayer & getPlayer()
ImGui::ImageButton
bool IMGUI_API ImageButton(const nap::Texture2D &texture, const ImVec2 &size, const ImVec2 &uv0=ImVec2(0, 1), const ImVec2 &uv1=ImVec2(1, 0), int frame_padding=-1, const ImVec4 &bg_col=ImVec4(0, 0, 0, 0), const ImVec4 &tint_col=ImVec4(1, 1, 1, 1))
nap::SequenceCurveTrackView::updateSegmentInClipboard
void updateSegmentInClipboard(const std::string &trackID, const std::string &segmentID)
nap::math::FComplex::mValue
V mValue
Value mapped to the y axis.
Definition: fcurve.h:50
nap::sequenceguiactions::DraggingSegment
Definition: sequenceeditorguiactions.h:101
nap::SequenceCurveTrackView::drawCurves
void drawCurves(const SequenceTrack &track, const SequenceTrackSegment &segment, const ImVec2 &trackTopLeft, float previousSegmentX, float segmentWidth, float segmentX, ImDrawList *drawList)
Definition: sequencecurvetrackview_template.h:179
nap::utility::ErrorState
Definition: errorstate.h:19
nap::SequenceTrackView::getEditor
SequenceEditor & getEditor()
nap::SequenceGUIService::Colors::mHigh1
ImU32 mHigh1
First highlight color.
Definition: sequenceguiservice.h:77
nap::SequenceTrackSegment
Definition: sequencetracksegment.h:19
nap::SequenceTrackView::mService
SequenceGUIService & mService
Definition: sequencetrackview.h:131
nap::SequenceEditorGUIState::mDirty
bool mDirty
Definition: sequenceeditorguistate.h:33
nap::sequenceguiactions::DraggingSegmentValue::mSegmentID
std::string mSegmentID
Definition: sequencecurvetrackview_guiactions.h:385
nap::SequenceCurveTrackView::mCurveCache
std::unordered_map< std::string, std::vector< std::vector< ImVec2 > > > mCurveCache
Definition: sequencecurvetrackview.h:280
nap::sequenceguiactions::EditingSegmentCurveValue
Definition: sequencecurvetrackview_guiactions.h:290
nap::sequenceguiactions::HoveringControlPoint
Definition: sequencecurvetrackview_guiactions.h:14
nap::sequenceguiactions::HoveringSegmentValue
Definition: sequencecurvetrackview_guiactions.h:344
nap::SequenceTrackSegmentCurve::mCurves
std::vector< ResourcePtr< math::FCurve< float, float > > > mCurves
Property: 'Curves' vector holding curves.
Definition: sequencetracksegmentcurve.h:24
nap::SequenceCurveTrackView::drawInspectorRange
void drawInspectorRange(const SequenceTrack &track)
Definition: sequencecurvetrackview_template.h:446
nap::SequenceEditorGUIState::mStepSize
float mStepSize
Definition: sequenceeditorguistate.h:60
nap::icon::ok
constexpr const char * ok
Definition: imguiservice.h:45
nap::SequenceEditorGUIState::mClipboard
sequenceguiclipboard::SequenceClipboardPtr mClipboard
Definition: sequenceeditorguistate.h:30
nap::sequenceguiactions::HoveringCurve
Definition: sequencecurvetrackview_guiactions.h:87
nap::SequenceTrack
Definition: sequencetrack.h:22
nap::SequenceControllerCurve
Definition: sequencecontrollercurve.h:24
nap::sequenceguiclipboard::Clipboard::deserialize
std::vector< T * > deserialize(std::vector< std::unique_ptr< rtti::Object >> &createdObjects, utility::ErrorState &errorState)
Definition: sequenceeditorguiclipboard.h:181
nap::SequenceTrackCurve
Definition: sequencetrackcurve.h:33
nap::utility::ErrorState::toString
const std::string toString() const
nap::SequenceEditorGUIState::mAction
sequenceguiactions::SequenceActionPtr mAction
Definition: sequenceeditorguistate.h:27
nap::SequenceEditorGUIState::mWindowPos
ImVec2 mWindowPos
Definition: sequenceeditorguistate.h:45
nap::SequenceTrackCurve::mMaximum
T mMaximum
Property: 'Maximum' maximum value of track.
Definition: sequencetrackcurve.h:44
nap::SequenceTrack::mSegments
std::vector< ResourcePtr< SequenceTrackSegment > > mSegments
Property: 'Segments' Vector holding track segments.
Definition: sequencetrack.h:33
nap::math::FCurvePoint::mInTan
FComplex< T, V > mInTan
Left tangent position, relative to mPos.
Definition: fcurve.h:92
nap::SequenceControllerCurve::insertSegment
const SequenceTrackSegment * insertSegment(const std::string &trackID, double time) override
nap::SequenceCurveTrackView::drawControlPoints
void drawControlPoints(const SequenceTrack &track, const SequenceTrackSegment &segment, const ImVec2 &trackTopLeft, float segmentX, float segmentWidth, ImDrawList *drawList)
Definition: sequencecurvetrackview_template.h:646
nap::SequenceEditorGUIState::mMouseDelta
ImVec2 mMouseDelta
Definition: sequenceeditorguistate.h:39
nap::SequencePlayer::getSequenceFilename
const std::string & getSequenceFilename() const
nap::SequenceControllerCurve::changeCurveSegmentValue
void changeCurveSegmentValue(const std::string &trackID, const std::string &segmentID, float newValue, int curveIndex, sequencecurveenums::ESegmentValueTypes valueType)
nap::convertTimeToMMSSMSArray
std::vector< int > NAPAPI convertTimeToMMSSMSArray(double time)
nap::math::ECurveInterp::Bezier
@ Bezier
Bezier style interpolation.
nap::utility::ErrorState::hasErrors
bool hasErrors() const
Definition: errorstate.h:104
nap::sequenceguiactions::CurvePointActionPopup
Definition: sequencecurvetrackview_guiactions.h:137
nap::icon::del
constexpr const char * del
Definition: imguiservice.h:46
nap::SequenceEditorGUIState::mScale
float mScale
Definition: sequenceeditorguistate.h:84
nap::SequenceCurveTrackView::handleSegmentValueActionPopup
void handleSegmentValueActionPopup()
Definition: sequencecurvetrackview_template.h:128
nap::sequenceguiactions::EditingCurveSegment
Definition: sequencecurvetrackview_guiactions.h:259
nap::sequenceguiclipboard::CurveSegmentClipboard
Definition: sequencecurvetrackview.h:298
nap
Definition: templateapp.h:17
nap::SequenceEditorGUIState::mIsWindowFocused
bool mIsWindowFocused
Definition: sequenceeditorguistate.h:36
nap::sequenceguiactions::DraggingControlPoint
Definition: sequencecurvetrackview_guiactions.h:38
nap::math::FCurvePoint::mOutTan
FComplex< T, V > mOutTan
Right tangent position, relative to mPos.
Definition: fcurve.h:93
nap::sequenceguiactions::DraggingSegment::mSegmentID
std::string mSegmentID
Definition: sequenceeditorguiactions.h:116
nap::sequencecurveenums::BEGIN
@ BEGIN
Definition: sequencecurveenums.h:20
nap::SequenceGUIService::Colors::mFro1
ImU32 mFro1
Darker Foreground.
Definition: sequenceguiservice.h:83
nap::sequenceguiactions::HoveringSegmentValue::mSegmentID
std::string mSegmentID
Definition: sequencecurvetrackview_guiactions.h:360
nap::sequenceguiactions::DraggingSegmentValue
Definition: sequencecurvetrackview_guiactions.h:368
nap::math::FCurvePoint
Definition: fcurve.h:75
nap::sequenceguiactions::None
Definition: sequenceeditorguiactions.h:65
nap::math::clamp
T clamp(T value, T min, T max)
Definition: mathutils.h:325
nap::math::FComplex::mTime
T mTime
Time mapped to the x axis.
Definition: fcurve.h:49
nap::SequenceTrack::mTrackHeight
float mTrackHeight
Property: 'TrackHeight' holds track height as shown in gui.
Definition: sequencetrack.h:34