Vuo  2.0.3
VuoCommandCommon.cc
Go to the documentation of this file.
1 
10 #include "VuoCommandCommon.hh"
12 #include "VuoCompilerNode.hh"
13 #include "VuoCompilerPort.hh"
14 #include "VuoCompilerPortClass.hh"
16 #include "VuoEditor.hh"
17 #include "VuoEditorComposition.hh"
18 #include "VuoEditorWindow.hh"
19 #include "VuoNodeClass.hh"
20 #include "VuoRendererCable.hh"
22 #include "VuoPublishedPort.hh"
23 
28 void VuoCommandCommon::addCable(VuoRendererCable *rc, VuoPort *fromPortAfterAdding, VuoPort *toPortAfterAdding,
29  VuoEditorComposition *composition)
30 {
31  // Case: The cable had already been disconnected from its 'To' port at the time it was deleted.
32  if (! toPortAfterAdding)
33  toPortAfterAdding = rc->getFloatingEndpointPreviousToPort();
34 
35  bool willBePublishedInputCable = dynamic_cast<VuoPublishedPort *>(fromPortAfterAdding);
36  bool willBePublishedOutputCable = dynamic_cast<VuoPublishedPort *>(toPortAfterAdding);
37 
38  VuoNode *fromNode = (willBePublishedInputCable?
39  composition->getPublishedInputNode() :
40  fromPortAfterAdding->getRenderer()->getUnderlyingParentNode()->getBase()
41  );
42  VuoNode *toNode = (willBePublishedOutputCable?
43  composition->getPublishedOutputNode() :
44  toPortAfterAdding->getRenderer()->getUnderlyingParentNode()->getBase()
45  );
46 
47  rc->setFrom(fromNode, fromPortAfterAdding);
48  rc->setTo(toNode, toPortAfterAdding);
49 
50  composition->addCable(rc->getBase());
51 }
52 
58 {
59  if (rc->scene() != composition)
60  return;
61 
62  composition->removeCable(rc);
63 }
64 
75 void VuoCommandCommon::updateCable(VuoRendererCable *rc, VuoPort *updatedFromPort, VuoPort *updatedToPort,
76  VuoEditorComposition *composition, bool preserveDanglingCables)
77 {
78  VuoNode *updatedFromNode = (updatedFromPort? composition->getUnderlyingParentNodeForPort(updatedFromPort, composition):NULL);
79  VuoNode *updatedToNode = (updatedToPort? composition->getUnderlyingParentNodeForPort(updatedToPort, composition):NULL);
80 
81  // Perform port updates
82  rc->setFrom(updatedFromNode, updatedFromPort);
83  rc->setTo(updatedToNode, updatedToPort);
84 
85  // Add cable to composition if appropriate
86  if (updatedFromPort && updatedToPort &&
87  compositionContainsNode(composition, updatedFromNode) &&
88  compositionContainsNode(composition, updatedToNode) &&
89  (rc->scene() != composition))
90  {
91  composition->addCable(rc->getBase());
92  }
93 
94  // Remove cable from composition if appropriate
95  else if ((! (preserveDanglingCables ||
96  (updatedFromPort && updatedToPort &&
97  compositionContainsNode(composition, updatedFromNode) &&
98  compositionContainsNode(composition, updatedToNode)))
99  )
100  && (rc->scene() == composition))
101  {
102  composition->removeCable(rc);
103  }
104 }
105 
109 bool VuoCommandCommon::compositionContainsNode(VuoEditorComposition *composition, VuoNode *node)
110 {
111  if (node->hasRenderer() && node->getRenderer()->scene() == composition)
112  return true;
113 
115  return true;
116 
118  return true;
119 
120  return false;
121 }
122 
137 VuoPublishedPort * VuoCommandCommon::publishInternalPort(VuoPort *internalPort, bool forceEventOnlyPublication, string publishedPortName, VuoEditorComposition *composition, bool attemptMerge)
138 {
139  internalPort->getRenderer()->updateGeometry();
140  VuoType *publishedPortType = (forceEventOnlyPublication? NULL : ((VuoCompilerPortClass *)(internalPort->getClass()->getCompiler()))->getDataVuoType());
141 
142  bool mergePerformed = false;
143  VuoRendererPublishedPort *externalPort = composition->publishInternalPort(internalPort,
144  forceEventOnlyPublication,
145  publishedPortName,
146  publishedPortType,
147  attemptMerge,
148  &mergePerformed);
149  if (!mergePerformed)
150  composition->emitPublishedPortNameEditorRequested(externalPort);
151 
152  return dynamic_cast<VuoPublishedPort *>(externalPort->getBase());
153 }
154 
161 VuoPublishedPort * VuoCommandCommon::publishInternalExternalPortCombination(VuoPort *internalPort, VuoPublishedPort *externalPort, bool forceEventOnlyPublication, VuoEditorComposition *composition)
162 {
163  bool isInput = internalPort->getRenderer()->getInput();
164  composition->addPublishedPort(externalPort, isInput);
165 
166  // @todo Make use of retrieved mergePerformed value? https://b33p.net/node/7659
167  bool mergePerformed;
168  VuoPublishedPort *actualExternalPort = dynamic_cast<VuoPublishedPort *>(composition->publishInternalPort(internalPort, forceEventOnlyPublication,
169  externalPort->getClass()->getName(),
170  static_cast<VuoCompilerPortClass *>(externalPort->getClass()->getCompiler())->getDataVuoType(),
171  true, &mergePerformed)->getBase());
172 
173  return actualExternalPort;
174 }
175 
182 void VuoCommandCommon::unpublishInternalExternalPortCombination(VuoPort *internalPort, VuoPublishedPort *externalPort, VuoEditorComposition *composition, bool unpublishIsolatedExternalPorts)
183 {
184  bool isInput = internalPort->getRenderer()->getInput();
185  internalPort->getRenderer()->updateGeometry();
186 
187  // Remove the published cable associated with this internal-external port combination, if it has not been
188  // removed already.
189  VuoCable *publishedCable = internalPort->getCableConnecting(externalPort);
190  if (!publishedCable)
191  {
192  // The cable might have been disconnected by dragging. Look for a dangling cable that fits the description.
193  if (isInput)
194  {
195  VuoCable *danglingCable = externalPort->getCableConnecting(NULL);
196  if (danglingCable && (danglingCable->getRenderer()->getFloatingEndpointPreviousToPort() == internalPort))
197  publishedCable = danglingCable;
198  }
199  else // if (!isInput)
200  {
201  VuoCable *danglingCable = internalPort->getCableConnecting(NULL);
202  if (danglingCable && (danglingCable->getRenderer()->getFloatingEndpointPreviousToPort() == externalPort))
203  publishedCable = danglingCable;
204  }
205  }
206 
207  if (publishedCable)
208  composition->removeCable(publishedCable->getRenderer());
209 
210  bool noConnectedPorts = externalPort->getConnectedCables().empty();
211  if (unpublishIsolatedExternalPorts && noConnectedPorts)
212  composition->removePublishedPort(externalPort, isInput);
213 }
214 
222  VuoRendererNode *oldNode, VuoRendererNode *newNode,
223  map<VuoPort *, VuoPort *> updatedPortForOriginalPort,
224  VuoEditorComposition *composition)
225 {
226  if (!oldNode->getBase()->hasCompiler() || !newNode->getBase()->hasCompiler())
227  return diffInfo;
228 
229  // Tell VuoCompositionDiff about the node replacements, since some information can't be inferred from the composition snapshot:
230  // - the fact that a node was replaced if its node class hasn't changed
231  // - for `Calculate` nodes, the mapping from old to new ports on the `Make List` node that holds the variable values
232  map<string, string> oldAndNewPortIdentifiers;
233  for (VuoPort *oldPort : oldNode->getBase()->getInputPorts())
234  {
235  VuoPort *newPort = updatedPortForOriginalPort[oldPort];
236  if (newPort)
237  {
238  string oldPortIdentifier = static_cast<VuoCompilerPort *>(oldPort->getCompiler())->getIdentifier();
239  string newPortIdentifier = static_cast<VuoCompilerPort *>(newPort->getCompiler())->getIdentifier();
240  oldAndNewPortIdentifiers[oldPortIdentifier] = newPortIdentifier;
241  }
242  }
243 
244  string oldNodeIdentifier = oldNode->getBase()->getCompiler()->getIdentifier();
245  string newNodeIdentifier = newNode->getBase()->getCompiler()->getIdentifier();
246 
247  string compositionIdentifier = static_cast<VuoEditor *>(qApp)->getSubcompositionRouter()->getCompositionIdentifier(composition);
248  diffInfo->addNodeReplacement(compositionIdentifier, oldNodeIdentifier, newNodeIdentifier, oldAndNewPortIdentifiers);
249 
250  return diffInfo;
251 }
252 
257 {
258  this->window = window;
259  this->description = nullptr;
260 }
261 
266 {
267  free(description);
268 }
269 
273 void VuoCommandCommon::setDescription(const char *formatString, ...)
274 {
275  va_list args;
276  va_start(args, formatString);
277  vasprintf(&description, formatString, args);
278  va_end(args);
279 }