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