NAP
sequenceeventtrackview.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 #include "sequencetrackview.h"
8 #include "sequencecontrollerevent.h"
9 #include "sequencetracksegment.h"
10 #include "sequenceeditorguiclipboard.h"
11 #include "sequenceeventtrackview_guiactions.h"
12 #include "sequenceguiutils.h"
13 
14 #include <utility>
15 #include <imguiutils.h>
16 
17 namespace nap
18 {
20 
21  // forward declares
22  class SequenceEventTrackView;
23  class SequenceGUIService;
24 
30  class NAPAPI SequenceEventTrackSegmentViewBase
31  {
32  RTTI_ENABLE()
33  public:
37  SequenceEventTrackSegmentViewBase() = default;
38 
42  virtual ~SequenceEventTrackSegmentViewBase() = default;
43 
50  virtual bool handleEditPopupContent(sequenceguiactions::Action& action) = 0;
51 
61  virtual void drawEvent(const SequenceTrackSegment& segment, ImDrawList* drawList, const ImVec2& topLeft, float x, ImU32 color) = 0;
62 
70  virtual void insertSegment(SequenceControllerEvent& controller, const std::string& trackID, double time) = 0;
71 
80  virtual std::unique_ptr<sequenceguiactions::Action> createEditAction(const SequenceTrackSegmentEventBase* segment, const std::string& trackID, const std::string& segmentID) = 0;
81  };
82 
91  template<typename T>
93  {
95  public:
100  {}
101 
102 
109  bool handleEditPopupContent(sequenceguiactions::Action& action) override;
110 
120  void drawEvent(const SequenceTrackSegment& segment, ImDrawList* drawList, const ImVec2& topLeft, float x, ImU32 color) override;
121 
129  void insertSegment(SequenceControllerEvent& controller, const std::string& trackID, double time) override;
130 
139  std::unique_ptr<sequenceguiactions::Action>
140  createEditAction(const SequenceTrackSegmentEventBase* segment, const std::string& trackID, const std::string& segmentID) override;
141  };
142 
146  class NAPAPI SequenceEventTrackView final : public SequenceTrackView
147  {
148  friend class SequenceGUIService;
149 
150  RTTI_ENABLE(SequenceTrackView)
151  public:
159 
160  // make this class explicitly non-copyable
162  SequenceEventTrackView& operator=(const SequenceEventTrackView&) = delete;
163 
164  protected:
169  void showInspectorContent(const SequenceTrack& track) override;
170 
176  void showTrackContent(const SequenceTrack& track, const ImVec2& trackTopLeft) override;
177 
181  void handleInsertEventSegmentPopup();
182 
186  template<typename T>
187  void handleEditEventSegmentPopup();
188 
197  bool pasteEventsFromClipboard(const std::string& trackID, double time, utility::ErrorState& errorState);
198 
206  template<typename T>
207  void pasteEvent(const std::string& trackID, const SequenceTrackSegmentEventBase& baseEvent, double time);
208 
218  void
219  drawSegmentHandler(const SequenceTrack& track, const SequenceTrackSegment& segment, const ImVec2& trackTopLeft, float segmentX, float segmentWidth, ImDrawList* drawList);
220 
224  void handleEditSegmentValuePopup();
225 
231  void updateSegmentInClipboard(const std::string& trackID, const std::string& segmentID);
232 
236  void handleAssignOutputIDToTrack();
237 
241  void handleSegmentDrag();
242 
246  void handleLoadPresetPopup();
247 
248  private:
249  // map of segment views for different event views
250  std::unordered_map<rtti::TypeInfo, std::unique_ptr<SequenceEventTrackSegmentViewBase>> mSegmentViews;
251  };
252 
253 
255  // Event Clipboards
257 
258  namespace sequenceguiclipboard
259  {
261  public Clipboard
262  {
263  RTTI_ENABLE(Clipboard)
264  public:
265  EventSegmentClipboard(const rttr::type& type, std::string sequenceName)
266  : Clipboard(type), mSequenceName(std::move(sequenceName))
267  {};
268 
269 
270  const std::string &getSequenceName() const{ return mSequenceName; }
271 
272  private:
273  std::string mSequenceName;
274  };
275  }
276 
278  // Template definitions
280 
281  template<typename T>
283  {
284  if(mState.mAction->isAction<sequenceguiactions::OpenEditEventSegmentPopup<T>>())
285  {
286  // invoke insert sequence popup
287  ImGui::OpenPopup("Edit Event");
288 
289  auto *action = mState.mAction->getDerived<sequenceguiactions::OpenEditEventSegmentPopup<T>>();
290  ImGui::SetNextWindowPos(action->mWindowPos);
291 
292  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::EditingEventSegment<T>>(action->mTrackID, action->mSegmentID, action->mWindowPos, action->mValue, action->mStartTime);
293  }
294 
295  // handle insert segment popup
296  if(mState.mAction->isAction<sequenceguiactions::EditingEventSegment<T>>())
297  {
298  auto *action = mState.mAction->getDerived<sequenceguiactions::EditingEventSegment<T>>();
299 
300  auto take_snapshot = [this, action]()
301  {
302  if(action->mTakeSnapshot)
303  action->mTakeSnapshot = false;
304 
305  getEditor().takeSnapshot(action->get_type());
306  };
307 
308  if(ImGui::BeginPopup("Edit Event"))
309  {
310  // draw the registered popup content for this event
311  auto it = mSegmentViews.find(RTTI_OF(SequenceTrackSegmentEvent<T>));
312  assert(it != mSegmentViews.end()); // type not found
313  if(it->second->handleEditPopupContent(*action))
314  take_snapshot();
315 
316  // time
317  std::vector<int> time_array = convertTimeToMMSSMSArray(action->mStartTime);
318 
319  bool edit_time = false;
320 
321  ImGui::Separator();
322  ImGui::PushItemWidth(100.0f * mState.mScale);
323 
324  edit_time = ImGui::InputInt3("Time (mm:ss:ms)", &time_array[0]);
325  time_array[0] = math::clamp<int>(time_array[0], 0, 99999);
326  time_array[1] = math::clamp<int>(time_array[1], 0, 59);
327  time_array[2] = math::clamp<int>(time_array[2], 0, 99);
328 
329  ImGui::PopItemWidth();
330 
331  ImGui::Separator();
332 
333  if(edit_time)
334  {
335  take_snapshot();
336 
337  auto &event_controller = getEditor().getController<SequenceControllerEvent>();
338  double new_time = convertMMSSMSArrayToTime(time_array);
339  double time = event_controller.segmentEventStartTimeChange(action->mTrackID, action->mSegmentID, new_time);
340  updateSegmentInClipboard(action->mTrackID, action->mSegmentID);
341  action->mStartTime = time;
342  mState.mDirty = true;
343  }
344  if(ImGui::ImageButton(mService.getGui().getIcon(icon::ok)))
345  {
346  auto &event_controller = getEditor().getController<SequenceControllerEvent>();
347  event_controller.editEventSegment<T>(action->mTrackID, action->mSegmentID, action->mValue);
348  updateSegmentInClipboard(action->mTrackID, action->mSegmentID);
349  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::None>();
350  ImGui::CloseCurrentPopup();
351  }
352  ImGui::SameLine();
353  if(ImGui::ImageButton(mService.getGui().getIcon(icon::cancel)))
354  {
355  ImGui::CloseCurrentPopup();
356  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::None>();
357  }
358 
359  action->mWindowPos = ImGui::GetWindowPos();
360 
361  ImGui::EndPopup();
362  } else
363  {
364  // click outside popup so cancel action
365  mState.mAction = sequenceguiactions::createAction<sequenceguiactions::None>();
366  }
367  }
368  }
369 
370 
371  template<typename T>
372  void SequenceEventTrackView::pasteEvent(const std::string& trackID, const SequenceTrackSegmentEventBase& baseEvent, double time)
373  {
374  // obtain controller
375  auto &controller = getEditor().getController<SequenceControllerEvent>();
376 
377  // insert new segment
378  const auto *new_segment = dynamic_cast<const T *>(controller.insertEventSegment<T>(trackID,
379  baseEvent.mStartTime +
380  time));
381  assert(new_segment != nullptr); // cast failed
382 
383  // upcast de-serialized event
384  const auto *event_upcast = dynamic_cast<const T *>(&baseEvent);
385  assert(event_upcast != nullptr); // cast failed
386 
387  // copy values from deserialized event segment
388  controller.editEventSegment(trackID, new_segment->mID, event_upcast->mValue);
389  }
390 
391 
392  template<typename T>
393  void SequenceEventTrackSegmentView<T>::insertSegment(SequenceControllerEvent& controller, const std::string& trackID, double time)
394  {
395  controller.insertEventSegment<SequenceTrackSegmentEvent<T>>(trackID, time);
396  }
397 
398 
399  template<typename T>
400  std::unique_ptr<sequenceguiactions::Action> SequenceEventTrackSegmentView<T>::createEditAction(const SequenceTrackSegmentEventBase* segment, const std::string& trackID, const std::string& segmentID)
401  {
402  const auto* event = static_cast<const SequenceTrackSegmentEvent<T>*>(segment);
403  return sequenceguiactions::createAction<sequenceguiactions::OpenEditEventSegmentPopup<T>>(trackID, segmentID, ImGui::GetWindowPos(), event->mValue, segment->mStartTime);
404  }
405 }
nap::SequenceEventTrackView::pasteEvent
void pasteEvent(const std::string &trackID, const SequenceTrackSegmentEventBase &baseEvent, double time)
Definition: sequenceeventtrackview.h:372
nap::SequenceEventTrackView::handleEditEventSegmentPopup
void handleEditEventSegmentPopup()
Definition: sequenceeventtrackview.h:282
nap::SequenceEventTrackSegmentView::insertSegment
void insertSegment(SequenceControllerEvent &controller, const std::string &trackID, double time) override
Definition: sequenceeventtrackview.h:393
nap::SequenceEditorGUIState
Definition: sequenceeditorguistate.h:23
nap::convertMMSSMSArrayToTime
double NAPAPI convertMMSSMSArrayToTime(const std::vector< int > &timeArray)
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::sequenceguiclipboard::EventSegmentClipboard::getSequenceName
const std::string & getSequenceName() const
Definition: sequenceeventtrackview.h:270
nap::SequenceControllerEvent::insertEventSegment
const SequenceTrackSegment * insertEventSegment(const std::string &trackID, double time)
Definition: sequencecontrollerevent.h:90
nap::utility::ErrorState
Definition: errorstate.h:19
nap::sequenceguiactions::Action::mTakeSnapshot
bool mTakeSnapshot
Definition: sequenceeditorguiactions.h:49
nap::SequenceTrackSegment
Definition: sequencetracksegment.h:19
nap::icon::cancel
constexpr const char * cancel
Definition: imguiservice.h:44
nap::icon::ok
constexpr const char * ok
Definition: imguiservice.h:45
nap::SequenceGUIService
Definition: sequenceguiservice.h:63
nap::SequenceEventTrackView
Definition: sequenceeventtrackview.h:146
nap::SequenceTrack
Definition: sequencetrack.h:22
nap::SequenceTrackSegment::mStartTime
double mStartTime
Property: 'Start time' start time of segment in track.
Definition: sequencetracksegment.h:38
nap::SequenceTrackSegmentEvent
Definition: sequencetracksegmentevent.h:39
nap::SequenceEventTrackSegmentView
Definition: sequenceeventtrackview.h:92
nap::sequenceguiclipboard::Clipboard
Definition: sequenceeditorguiclipboard.h:28
nap::sequenceguiactions::Action
Definition: sequenceeditorguiactions.h:26
nap::SequenceTrackView
Definition: sequencetrackview.h:30
nap::SequenceEditorGUIView
Definition: sequenceeditorgui.h:80
nap::SequenceEventTrackSegmentView::SequenceEventTrackSegmentView
SequenceEventTrackSegmentView()
Definition: sequenceeventtrackview.h:99
nap::convertTimeToMMSSMSArray
std::vector< int > NAPAPI convertTimeToMMSSMSArray(double time)
nap::sequenceguiactions::OpenEditEventSegmentPopup
Definition: sequenceeventtrackview_guiactions.h:40
nap::sequenceguiclipboard::EventSegmentClipboard
Definition: sequenceeventtrackview.h:260
nap::SequenceTrackSegmentEventBase
Definition: sequencetracksegmentevent.h:21
nap::SequenceControllerEvent::editEventSegment
void editEventSegment(const std::string &trackID, const std::string &segmentID, const T &value)
Definition: sequencecontrollerevent.h:120
nap
Definition: templateapp.h:17
nap::SequenceControllerEvent
Definition: sequencecontrollerevent.h:21
nap::sequenceguiclipboard::EventSegmentClipboard::EventSegmentClipboard
EventSegmentClipboard(const rttr::type &type, std::string sequenceName)
Definition: sequenceeventtrackview.h:265
nap::sequenceguiactions::EditingEventSegment
Definition: sequenceeventtrackview_guiactions.h:67
nap::SequenceEventTrackSegmentViewBase
Definition: sequenceeventtracksegmentviewbase.h:18
nap::SequenceEventTrackSegmentView::createEditAction
std::unique_ptr< sequenceguiactions::Action > createEditAction(const SequenceTrackSegmentEventBase *segment, const std::string &trackID, const std::string &segmentID) override
Definition: sequenceeventtrackview.h:400