time_period_editor.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /* time_period_editor.cpp - time period editing widget
  2. * Copyright (C) 2017-2018 caryoscelus
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <QGraphicsRectItem>
  18. #include <core/action_stack.h>
  19. #include <core/actions/change_value.h>
  20. #include <generic/node_editor.h>
  21. #include <generic/timeline_editor.h>
  22. #include <widgets/timeline_area.h>
  23. #include "time_item.h"
  24. namespace rainynite::studio {
  25. class TimePeriodEditor;
  26. class TimePeriodItem : public TimeItem {
  27. public:
  28. using Setter = void (core::TimePeriod::*)(core::Time);
  29. TimePeriodItem(TimePeriodEditor* parent, Setter setter_) :
  30. p(parent),
  31. setter(setter_)
  32. {}
  33. protected:
  34. void position_changed(core::Time time) override;
  35. private:
  36. observer_ptr<TimePeriodEditor> p;
  37. Setter setter;
  38. };
  39. class TimePeriodEditor :
  40. public TimelineEditor,
  41. public NodeEditor
  42. {
  43. public:
  44. void setup_canvas() override {
  45. first_item = make_unique<TimePeriodItem>(this, &core::TimePeriod::set_first);
  46. last_item = make_unique<TimePeriodItem>(this, &core::TimePeriod::set_last);
  47. get_scene()->addItem(first_item.get());
  48. get_scene()->addItem(last_item.get());
  49. node_update();
  50. }
  51. void set_position_hint(int y, int height) override {
  52. first_item->set_pos_height(y, height);
  53. last_item->set_pos_height(y, height);
  54. }
  55. void node_update() override {
  56. update_position();
  57. auto node = get_node_as<core::TimePeriod>();
  58. bool editable = node && node->can_set_any_at();
  59. for (auto item : {first_item.get(), last_item.get()}) {
  60. item->set_readonly(!editable);
  61. item->setFlag(QGraphicsItem::ItemIsSelectable, editable);
  62. }
  63. }
  64. void time_changed(core::Time time) override {
  65. ContextListener::time_changed(time);
  66. update_position();
  67. }
  68. void item_moved(core::Time time, TimePeriodItem::Setter setter) {
  69. if (auto node = get_node_as<core::TimePeriod>()) {
  70. ignore_time_change = true;
  71. if (node->can_set_any_at()) {
  72. if (auto action_stack = get_context()->action_stack()) {
  73. using core::actions::ChangeValueAt;
  74. auto value = node->mod();
  75. (value.*setter)(time);
  76. action_stack->emplace<ChangeValueAt>(
  77. node,
  78. value,
  79. get_core_context()
  80. );
  81. }
  82. }
  83. ignore_time_change = false;
  84. }
  85. }
  86. private:
  87. void update_position() {
  88. if (first_item && !ignore_time_change) {
  89. if (auto maybe_value = get_value<core::TimePeriod>()) {
  90. auto value = *maybe_value;
  91. first_item->set_fps(value.get_fps());
  92. first_item->move_to(value.get_first());
  93. last_item->set_fps(value.get_fps());
  94. last_item->move_to(value.get_last());
  95. }
  96. }
  97. }
  98. private:
  99. unique_ptr<TimePeriodItem> first_item;
  100. unique_ptr<TimePeriodItem> last_item;
  101. bool ignore_time_change = false;
  102. };
  103. void TimePeriodItem::position_changed(core::Time time) {
  104. p->item_moved(time, setter);
  105. }
  106. REGISTER_CANVAS_EDITOR(TimelineArea, TimePeriodEditor, core::TimePeriod);
  107. REGISTER_NODE_EDITOR_SHOW_CHILDREN(CompositeTimePeriod, true);
  108. }