CableCopy.hpp
1 #pragma once
2 #include <Process/Dataflow/Cable.hpp>
3 #include <Process/Dataflow/Port.hpp>
4 
5 #include <ossia/detail/ptr_set.hpp>
6 
7 namespace Dataflow
8 {
9 using SerializedCables = std::vector<std::pair<Id<Process::Cable>, Process::CableData>>;
10 }
11 namespace Process
12 {
13 
14 inline bool verifyAndUpdateIfChildOf(ObjectPath& path, const ObjectPath& parent)
15 {
16  auto parent_n = parent.vec().size();
17  auto path_n = path.vec().size();
18  if(parent_n >= path_n)
19  return false;
20  for(std::size_t i = 0; i < parent_n; i++)
21  {
22  if(!(path.vec()[i] == parent.vec()[i]))
23  return false;
24  }
25 
26  SCORE_ASSERT(parent_n > 1);
27  path.vec().erase(path.vec().begin(), path.vec().begin() + parent_n - 1);
28  return true;
29 }
30 
31 template <typename T>
32 bool verifyAndUpdateIfChildOf(Process::CableData& path, const std::vector<Path<T>>& vec)
33 {
34  bool source_ok = false;
35  for(const auto& parent : vec)
36  {
37  if(verifyAndUpdateIfChildOf(path.source.unsafePath(), parent.unsafePath()))
38  {
39  source_ok = true;
40  break;
41  }
42  }
43  if(!source_ok)
44  return false;
45 
46  for(const auto& parent : vec)
47  {
48  if(verifyAndUpdateIfChildOf(path.sink.unsafePath(), parent.unsafePath()))
49  {
50  return true;
51  }
52  }
53  // must not happen: the sink is already guaranteed to be a child of an
54  // interval since we look for all the inlets
55  SCORE_ABORT;
56 }
57 
58 template <typename T>
59 Dataflow::SerializedCables cablesToCopy(
60  const std::vector<T*>& array,
61  const std::vector<Path<std::remove_const_t<T>>>& siblings,
62  const score::DocumentContext& ctx)
63 {
64  // For every cable, if both ends are in one of the elements or child elements
65  // currently selected, we copy them.
66  // Note: ids / cable paths have to be updated of course.
67  Dataflow::SerializedCables copiedCables;
68  ossia::ptr_set<Process::Inlet*> ins;
69  for(auto itv : array)
70  {
71  auto child_ins = itv->template findChildren<Process::Inlet*>();
72  ins.insert(child_ins.begin(), child_ins.end());
73  }
74 
75  for(auto inl : ins)
76  {
77  for(const auto& c_inl : inl->cables())
78  {
79  if(Process::Cable* cable = c_inl.try_find(ctx))
80  {
81  auto cd = cable->toCableData();
82  if(verifyAndUpdateIfChildOf(cd, siblings))
83  {
84  copiedCables.push_back({cable->id(), cd});
85  }
86  }
87  }
88  }
89 
90  return copiedCables;
91 }
92 
93 template <typename T>
94 Dataflow::SerializedCables
95 cablesToCopy(const std::vector<T*>& array, const score::DocumentContext& ctx)
96 {
97  std::vector<Path<std::remove_const_t<T>>> siblings;
98  siblings.reserve(array.size());
99  for(auto ptr : array)
100  {
101  siblings.emplace_back(*ptr);
102  }
103  return cablesToCopy(array, siblings, ctx);
104 }
105 }
The ObjectPath class.
Definition: ObjectPath.hpp:37
Definition: Cable.hpp:54
Base classes and tools to implement processes and layers.
Definition: JSONVisitor.hpp:1324
Definition: Cable.hpp:45
Definition: DocumentContext.hpp:18