score-plugin-engine/Engine/Node/Layer.hpp
1 #pragma once
2 
3 #include <Process/Focus/FocusDispatcher.hpp>
4 #include <Process/LayerPresenter.hpp>
5 #include <Process/LayerView.hpp>
6 #include <Process/Style/ScenarioStyle.hpp>
7 
8 #include <Control/Widgets.hpp>
9 #include <Effect/EffectLayer.hpp>
10 #include <Effect/EffectLayout.hpp>
11 #include <Engine/Node/Process.hpp>
12 
13 #include <score/application/GUIApplicationContext.hpp>
14 #include <score/graphics/RectItem.hpp>
15 #include <score/graphics/TextItem.hpp>
16 
17 #include <tuplet/tuple.hpp>
18 
19 #include <type_traits>
20 
21 namespace Control
22 {
23 template <typename T, typename = void>
24 struct HasCustomUI : std::false_type
25 {
26 };
27 template <typename T>
28 struct HasCustomUI<T, std::void_t<decltype(&T::item)>> : std::true_type
29 {
30 };
31 template <typename T, typename = void>
32 struct HasCustomLayer : std::false_type
33 {
34 };
35 template <typename T>
36 struct HasCustomLayer<T, std::void_t<typename T::Layer>> : std::true_type
37 {
38 };
39 
40 template <typename Info>
42 {
43  const Process::Inlets& inlets;
44  const Process::Outlets& outlets;
45  const Process::ProcessModel& process;
46  QGraphicsItem& parent;
47  QObject& context;
48  const Process::Context& doc;
49 
50  template <std::size_t N>
51  auto& getControl() noexcept
52  {
53  using namespace std;
54  using namespace tuplet;
55 
56  constexpr int i = ossia::safe_nodes::info_functions<Info>::control_start + N;
57  constexpr const auto& ctrl = get<N>(Info::Metadata::controls);
58  using port_type = decltype(*ctrl.create_inlet(Id<Process::Port>{}, nullptr));
59  return static_cast<port_type&>(*inlets[i]);
60  }
61 
62  template <std::size_t N>
63  auto& getControlOut() noexcept
64  {
65  using namespace std;
66  using namespace tuplet;
67 
68  constexpr int i = ossia::safe_nodes::info_functions<Info>::control_out_start + N;
69  constexpr const auto& ctrl = get<N>(Info::Metadata::control_outs);
70  using port_type = decltype(*ctrl.create_outlet(Id<Process::Port>{}, nullptr));
71  return static_cast<port_type&>(*outlets[i]);
72  }
73 
74  template <std::size_t... CI, std::size_t... CO>
75  void make(std::index_sequence<CI...>, std::index_sequence<CO...>) noexcept
76  {
77  Info::item(
78  getControl<CI>()..., getControlOut<CO>()..., process, parent, context, doc);
79  }
80 
82  const Process::Inlets& inlets, const Process::Outlets& outlets,
83  const Process::ProcessModel& process, QGraphicsItem& parent, QObject& context,
84  const Process::Context& doc)
85  : inlets{inlets}
86  , outlets{outlets}
87  , process{process}
88  , parent{parent}
89  , context{context}
90  , doc{doc}
91  {
92  make(
93  std::make_index_sequence<
94  ossia::safe_nodes::info_functions<Info>::control_count>{},
95  std::make_index_sequence<
96  ossia::safe_nodes::info_functions<Info>::control_out_count>{});
97  }
98 };
99 
100 template <typename Info>
101 requires(
103  || HasCustomUI<Info>::value) class ControlLayerFactory final
104  : public Process::LayerFactory
105 {
106 public:
107  virtual ~ControlLayerFactory() = default;
108 
109 private:
110  std::optional<double> recommendedHeight() const noexcept override
111  {
112  if constexpr(Info::Metadata::recommended_height > 0)
113  {
114  return Info::Metadata::recommended_height;
115  }
116  return LayerFactory::recommendedHeight();
117  }
118 
119  UuidKey<Process::ProcessModel> concreteKey() const noexcept override
120  {
122  }
123 
124  bool matches(const UuidKey<Process::ProcessModel>& p) const override
125  {
127  }
128 
129  Process::LayerView* makeLayerView(
130  const Process::ProcessModel& proc, const Process::Context& context,
131  QGraphicsItem* parent) const final override
132  {
133  if constexpr(HasCustomLayer<Info>::value)
134  return new typename Info::Layer{proc, context, parent};
135  else
136  return new Process::EffectLayerView{parent};
137  }
138 
139  Process::LayerPresenter* makeLayerPresenter(
141  const Process::Context& context, QObject* parent) const final override
142  {
143  if constexpr(HasCustomLayer<Info>::value)
144  {
145  auto view = static_cast<typename Info::Layer*>(v);
146  return new Process::EffectLayerPresenter{lm, view, context, parent};
147  }
148  else if constexpr(HasCustomUI<Info>::value)
149  {
150  auto view = safe_cast<Process::EffectLayerView*>(v);
151  auto pres = new Process::EffectLayerPresenter{lm, view, context, parent};
152 
153  Control::CustomUISetup<Info>{lm.inlets(), lm.outlets(), lm, *view, *view, context};
154  return pres;
155  }
156  }
157 
158  score::ResizeableItem* makeItem(
159  const Process::ProcessModel& proc, const Process::Context& ctx,
160  QGraphicsItem* parent) const final override
161  {
162  if constexpr(HasCustomLayer<Info>::value)
163  {
164  // We want to go through the makeLayerPresenter case here
165  return nullptr;
166  }
167  else if constexpr(HasCustomUI<Info>::value)
168  {
169  auto rootItem = new score::EmptyRectItem{parent};
170  Control::CustomUISetup<Info>{proc.inlets(), proc.outlets(), proc,
171  *rootItem, *rootItem, ctx};
172 
173  rootItem->fitChildrenRect();
174 
175  QObject::connect(
176  rootItem, &score::ResizeableItem::childrenSizeChanged, rootItem,
177  &score::EmptyRectItem::fitChildrenRect);
178  return rootItem;
179  }
180  }
181 };
182 }
Definition: EffectLayer.hpp:27
Definition: EffectLayer.hpp:16
Definition: score-lib-process/Process/ProcessFactory.hpp:58
Definition: LayerPresenter.hpp:34
Definition: LayerView.hpp:21
The Process class.
Definition: score-lib-process/Process/Process.hpp:61
The id_base_t class.
Definition: Identifier.hpp:57
Definition: RectItem.hpp:64
Definition: RectItem.hpp:12
Definition: score-plugin-engine/Engine/Node/Layer.hpp:42
Definition: score-plugin-engine/Engine/Node/Layer.hpp:33
Definition: score-plugin-engine/Engine/Node/Layer.hpp:25
Static metadata implementation.
Definition: lib/score/tools/Metadata.hpp:36
Definition: ProcessContext.hpp:12
Definition: PortForward.hpp:23
Definition: PortForward.hpp:27
Definition: ObjectMatches.hpp:6