1
2
3 // TnzCore includes
4 #include "tconst.h"
5 #include "tutil.h"
6 #include "tstream.h"
7
8 // TnzBase includes
9 #include "tparamcontainer.h"
10 #include "tfxattributes.h"
11 #include "texternfx.h"
12 #include "tpassivecachemanager.h"
13
14 // STD includes
15 #include <set>
16
17 #include "tfx.h"
18
19 //==============================================================================
20
operator >>(TIStream & in,TFxP & p)21 TIStream &operator>>(TIStream &in, TFxP &p) {
22 TPersist *tmp = 0;
23 in >> tmp;
24 p = TFxP(dynamic_cast<TFx *>(tmp));
25 return in;
26 }
27
28 //==============================================================================
29 //
30 // namespace {}
31 //
32 //------------------------------------------------------------------------------
33
34 namespace {
35
36 //------------------------------------------------------------------------------
37
38 typedef std::pair<std::string, TFxPort *> NamePort;
39 typedef std::map<std::string, TFxPort *> PortTable;
40 typedef std::vector<NamePort> PortArray;
41
42 //------------------------------------------------------------------------------
43
44 class PortNameEq {
45 std::string m_name;
46
47 public:
PortNameEq(const std::string & name)48 PortNameEq(const std::string &name) : m_name(name) {}
~PortNameEq()49 ~PortNameEq() {}
operator ()(const NamePort & np)50 bool operator()(const NamePort &np) { return np.first == m_name; }
51 };
52
53 //------------------------------------------------------------------------------
54
skipChild(TIStream & is)55 void skipChild(TIStream &is) {
56 while (!is.eos()) {
57 std::string dummy = is.getString();
58 std::string tagName;
59 while (is.openChild(tagName)) {
60 skipChild(is);
61 if (is.isBeginEndTag()) is.matchTag(tagName);
62 is.closeChild();
63 }
64 if (is.isBeginEndTag()) is.matchTag(tagName);
65 }
66 }
67
68 //------------------------------------------------------------------------------
69
updateDagPosition(const TPointD & pos,const VersionNumber & tnzVersion)70 TPointD updateDagPosition(const TPointD &pos, const VersionNumber &tnzVersion) {
71 if (tnzVersion < VersionNumber(1, 16)) return TConst::nowhere;
72 return pos;
73 }
74
75 } // namespace
76
77 //==============================================================================
78 //
79 // TFxParamChange
80 //
81 //------------------------------------------------------------------------------
82
TFxParamChange(TFx * fx,double firstAffectedFrame,double lastAffectedFrame,bool dragging)83 TFxParamChange::TFxParamChange(TFx *fx, double firstAffectedFrame,
84 double lastAffectedFrame, bool dragging)
85 : TFxChange(fx, firstAffectedFrame, lastAffectedFrame, dragging) {}
86
87 //--------------------------------------------------
88
TFxParamChange(TFx * fx,const TParamChange & src)89 TFxParamChange::TFxParamChange(TFx *fx, const TParamChange &src)
90 : TFxChange(fx, src.m_firstAffectedFrame, src.m_lastAffectedFrame,
91 src.m_dragging) {}
92
93 //==============================================================================
94 //
95 // TFxChange
96 //
97 //------------------------------------------------------------------------------
98
99 double TFxChange::m_minFrame = -(std::numeric_limits<double>::max)();
100 double TFxChange::m_maxFrame = +(std::numeric_limits<double>::max)();
101
102 //==============================================================================
103 //
104 // TFxPortDynamicGroup
105 //
106 //------------------------------------------------------------------------------
107
TFxPortDynamicGroup(const std::string & prefix,int minSize)108 TFxPortDynamicGroup::TFxPortDynamicGroup(const std::string &prefix, int minSize)
109 : m_portsPrefix(prefix), m_minPortsCount(minSize) {}
110
111 //--------------------------------------------------
112
~TFxPortDynamicGroup()113 TFxPortDynamicGroup::~TFxPortDynamicGroup() { clear(); }
114
115 //--------------------------------------------------
116
addPort(TFxPort * port)117 void TFxPortDynamicGroup::addPort(TFxPort *port) { m_ports.push_back(port); }
118
119 //--------------------------------------------------
120
removePort(TFxPort * port)121 void TFxPortDynamicGroup::removePort(TFxPort *port) {
122 m_ports.resize(std::remove(m_ports.begin(), m_ports.end(), port) -
123 m_ports.begin());
124 delete port;
125 }
126
127 //--------------------------------------------------
128
clear()129 void TFxPortDynamicGroup::clear() {
130 std::for_each(m_ports.begin(), m_ports.end(), TDeleteObjectFunctor());
131 m_ports.clear();
132 }
133
134 //==============================================================================
135 //
136 // TFxImp
137 //
138 //------------------------------------------------------------------------------
139
140 class TFxImp {
141 public:
142 TFx *m_fx; //!< Fx back-pointer
143 TFxImp *m_prev, *m_next; //!< Linked fxs
144
145 std::wstring m_name;
146 std::wstring m_fxId;
147
148 PortTable m_portTable; //!< Name -> port map
149 PortArray m_portArray; //!< Ports container
150
151 TParamContainer m_paramContainer;
152
153 std::set<TFxPort *> m_outputPort;
154 TFxTimeRegion m_activeTimeRegion;
155 std::set<TFxObserver *> m_observers;
156
157 TFxAttributes m_attributes;
158
159 static unsigned long m_nextId;
160 unsigned long m_id; //!< Unique fx identifier, per Toonz session.
161 //!< It is intended to be used \b solely to build
162 //!< an internal string description of the fx.
163 public:
TFxImp(TFx * fx)164 TFxImp(TFx *fx)
165 : m_fx(fx), m_activeTimeRegion(TFxTimeRegion::createUnlimited()), m_id() {
166 m_prev = m_next = this;
167 }
168
~TFxImp()169 ~TFxImp() {
170 m_prev->m_next = m_next;
171 m_next->m_prev = m_prev;
172 }
173
checkLinks() const174 bool checkLinks() const {
175 assert(m_prev);
176 assert(m_next);
177 assert(m_prev->m_next == this);
178 assert(m_next->m_prev == this);
179
180 return true;
181 }
182
183 private:
184 // not copyable
185 TFxImp(const TFxImp &);
186 TFxImp &operator=(const TFxImp &);
187 };
188
189 //--------------------------------------------------
190
191 unsigned long TFxImp::m_nextId = 0;
192
193 //==============================================================================
194 //
195 // TFxFactory
196 //
197 //------------------------------------------------------------------------------
198
199 class TFxFactory // singleton
200 {
201 typedef std::map<std::string, std::pair<TFxInfo, TFxDeclaration *>> Table;
202
203 Table m_table;
204 std::vector<std::string> m_map;
205
TFxFactory()206 TFxFactory() {}
207
208 public:
instance()209 static TFxFactory *instance() {
210 static TFxFactory _instance;
211 return &_instance;
212 }
213
add(const TFxInfo & info,TFxDeclaration * decl)214 void add(const TFxInfo &info, TFxDeclaration *decl) {
215 // check for dups ???
216 std::pair<TFxInfo, TFxDeclaration *> p(info, decl);
217 m_table[info.m_name] = p;
218 }
219
create(std::string name)220 TFx *create(std::string name) {
221 Table::iterator it = m_table.find(name);
222 if (it != m_table.end()) {
223 TFxDeclaration *decl = it->second.second;
224
225 TPersist *obj = decl->create();
226 assert(obj);
227
228 return dynamic_cast<TFx *>(obj);
229 } else
230 return TExternFx::create(name);
231 }
232
getFxInfos(std::vector<TFxInfo> & info) const233 void getFxInfos(std::vector<TFxInfo> &info) const {
234 for (Table::const_iterator it = m_table.begin(); it != m_table.end(); ++it)
235 info.push_back(it->second.first);
236 }
237
getFxInfo(const std::string & fxIdentifier) const238 TFxInfo getFxInfo(const std::string &fxIdentifier) const {
239 Table::const_iterator it = m_table.find(fxIdentifier);
240 return (it != m_table.end()) ? it->second.first : TFxInfo();
241 }
242 };
243
244 //==============================================================================
245 //
246 // TFxDeclaration
247 //
248 //------------------------------------------------------------------------------
249
TFxDeclaration(const TFxInfo & info)250 TFxDeclaration::TFxDeclaration(const TFxInfo &info)
251 : TPersistDeclaration(info.m_name) {
252 TFxFactory::instance()->add(info, this);
253 }
254
255 //==============================================================================
256 //
257 // TFx
258 //
259 //------------------------------------------------------------------------------
260
261 DEFINE_CLASS_CODE(TFx, 3)
262
263 //------------------------------------------------------------------------------
264
TFx()265 TFx::TFx()
266 : TSmartObject(m_classCode) // TPersist(TFxImp::m_instances)
267 , m_imp(new TFxImp(this)) {}
268
269 //--------------------------------------------------
270
~TFx()271 TFx::~TFx() {
272 for (std::set<TFxPort *>::iterator it = m_imp->m_outputPort.begin();
273 it != m_imp->m_outputPort.end(); ++it) {
274 TFxPort *port = *it;
275 port->setFx(0);
276 }
277
278 delete m_imp;
279 }
280
281 //--------------------------------------------------
282
getName() const283 std::wstring TFx::getName() const { return m_imp->m_name; }
284
285 //--------------------------------------------------
286
setName(std::wstring name)287 void TFx::setName(std::wstring name) { m_imp->m_name = name; }
288
289 //--------------------------------------------------
290
getFxId() const291 std::wstring TFx::getFxId() const { return m_imp->m_fxId; }
292
293 //--------------------------------------------------
294
setFxId(std::wstring id)295 void TFx::setFxId(std::wstring id) { m_imp->m_fxId = id; }
296
297 //--------------------------------------------------
298
getAttributes() const299 TFxAttributes *TFx::getAttributes() const { return &m_imp->m_attributes; }
300
301 //--------------------------------------------------
302
getParams() const303 const TParamContainer *TFx::getParams() const {
304 return &m_imp->m_paramContainer;
305 }
306
307 //--------------------------------------------------
308
getParams()309 TParamContainer *TFx::getParams() { return &m_imp->m_paramContainer; }
310
311 //--------------------------------------------------
312
clone(bool recursive) const313 TFx *TFx::clone(bool recursive) const {
314 TFx *fx = TFx::create(getFxType());
315 assert(fx);
316 return this->clone(fx, recursive);
317 }
318
clone(TFx * fx,bool recursive) const319 TFx *TFx::clone(TFx *fx, bool recursive) const {
320 // Copy misc stuff
321
322 fx->m_imp->m_activeTimeRegion = m_imp->m_activeTimeRegion;
323 fx->setIdentifier(getIdentifier());
324 fx->getParams()->copy(getParams());
325 fx->setFxId(getFxId());
326 fx->setName(getName());
327
328 // Copy attributes
329 *fx->getAttributes() = *getAttributes();
330
331 // Clone the dynamic ports pool
332 if (hasDynamicPortGroups()) {
333 int p, pCount = m_imp->m_portArray.size();
334 for (p = 0; p != pCount; ++p) {
335 const NamePort &namedPort = m_imp->m_portArray[p];
336
337 int groupIdx = namedPort.second->getGroupIndex();
338 if (groupIdx >= 0 && !fx->getInputPort(namedPort.first))
339 fx->addInputPort(namedPort.first, new TRasterFxPort, groupIdx);
340 }
341
342 assert(pCount == fx->getInputPortCount());
343 }
344
345 // copia ricorsiva sulle porte
346 if (recursive) {
347 int p, pCount = getInputPortCount();
348 for (p = 0; p != pCount; ++p) {
349 TFxPort *port = getInputPort(p);
350 if (port->getFx())
351 fx->connect(getInputPortName(p), port->getFx()->clone(true));
352 }
353 }
354
355 return fx;
356 }
357
358 //--------------------------------------------------
359
linkParams(TFx * fx)360 void TFx::linkParams(TFx *fx) {
361 if (this == fx) return;
362 getParams()->link(fx->getParams());
363 m_imp->m_activeTimeRegion = fx->m_imp->m_activeTimeRegion;
364
365 // aggiorno i link
366 assert(m_imp->checkLinks());
367 assert(fx->m_imp->checkLinks());
368
369 std::swap(m_imp->m_next, fx->m_imp->m_next);
370 std::swap(m_imp->m_next->m_prev, fx->m_imp->m_next->m_prev);
371
372 assert(m_imp->checkLinks());
373 assert(fx->m_imp->checkLinks());
374 }
375
376 //--------------------------------------------------
377
unlinkParams()378 void TFx::unlinkParams() {
379 // clone dei parametri
380 getParams()->unlink();
381
382 assert(m_imp->m_prev);
383 assert(m_imp->m_next);
384 assert(m_imp->m_prev->m_next == m_imp);
385 assert(m_imp->m_next->m_prev == m_imp);
386 m_imp->m_prev->m_next = m_imp->m_next;
387 m_imp->m_next->m_prev = m_imp->m_prev;
388 m_imp->m_next = m_imp->m_prev = m_imp;
389
390 notify(TFxParamsUnlinked(this));
391 }
392
393 //--------------------------------------------------
394
addInputPort(const std::string & name,TFxPort & port)395 bool TFx::addInputPort(const std::string &name, TFxPort &port) {
396 PortTable::iterator it = m_imp->m_portTable.find(name);
397 if (it != m_imp->m_portTable.end()) return false;
398
399 m_imp->m_portTable[name] = &port;
400 m_imp->m_portArray.push_back(NamePort(name, &port));
401 port.setOwnerFx(this); // back pointer to the owner...
402
403 return true;
404 }
405
406 //--------------------------------------------------
407
addInputPort(const std::string & name,TFxPort * port,int groupIndex)408 bool TFx::addInputPort(const std::string &name, TFxPort *port, int groupIndex) {
409 if (!port) {
410 assert(port);
411 return false;
412 }
413
414 if (groupIndex >= dynamicPortGroupsCount()) {
415 assert(groupIndex < dynamicPortGroupsCount());
416 return false;
417 }
418
419 if (!addInputPort(name, *port)) return false;
420
421 // Assign the port to the associated group
422 port->m_groupIdx = groupIndex;
423
424 TFxPortDG *group = const_cast<TFxPortDG *>(dynamicPortGroup(groupIndex));
425 group->addPort(port);
426
427 assert(name.find(group->m_portsPrefix) == 0);
428
429 return true;
430 }
431
432 //--------------------------------------------------
433
removeInputPort(const std::string & name)434 bool TFx::removeInputPort(const std::string &name) {
435 m_imp->m_portTable.erase(name);
436
437 PortArray::iterator it = std::find_if(
438 m_imp->m_portArray.begin(), m_imp->m_portArray.end(), PortNameEq(name));
439 if (it == m_imp->m_portArray.end()) return false;
440
441 TFxPort *port = it->second;
442 port->setOwnerFx(0);
443
444 if (port->m_groupIdx >= 0) {
445 TFxPortDG *group =
446 const_cast<TFxPortDG *>(this->dynamicPortGroup(port->m_groupIdx));
447 group->removePort(port); // The port is DELETED here
448 }
449
450 m_imp->m_portArray.erase(it);
451 return true;
452 }
453
454 //--------------------------------------------------
455
456 namespace {
457 struct IsPrefix {
458 const std::string &m_prefix;
operator ()__anoncc7a1ab10211::IsPrefix459 bool operator()(const NamePort &nameport) {
460 return (strncmp(m_prefix.c_str(), nameport.first.c_str(),
461 m_prefix.size()) == 0);
462 }
463 };
464 } // namespace
465
clearDynamicPortGroup(int g)466 void TFx::clearDynamicPortGroup(int g) {
467 TFxPortDG *dg = const_cast<TFxPortDG *>(this->dynamicPortGroup(g));
468
469 const std::string &prefix = dg->portsPrefix();
470
471 std::string prefixEnd = prefix;
472 ++prefixEnd[prefixEnd.size() - 1];
473
474 {
475 // Delete all associated ports from the ports table
476 PortTable::iterator pBegin(m_imp->m_portTable.lower_bound(prefix));
477 PortTable::iterator pEnd(m_imp->m_portTable.lower_bound(prefixEnd));
478
479 m_imp->m_portTable.erase(pBegin, pEnd);
480
481 // Traverse the ports array and remove all ports in the group
482 IsPrefix func = {prefix};
483 m_imp->m_portArray.resize(std::remove_if(m_imp->m_portArray.begin(),
484 m_imp->m_portArray.end(), func) -
485 m_imp->m_portArray.begin());
486 }
487
488 dg->clear(); // Has ports ownership, so deletes them
489 }
490
491 //--------------------------------------------------
492
addOutputConnection(TFxPort * port)493 bool TFx::addOutputConnection(TFxPort *port) {
494 assert(port->getFx() == this);
495 return m_imp->m_outputPort.insert(port).second;
496 }
497
498 //--------------------------------------------------
499
removeOutputConnection(TFxPort * port)500 bool TFx::removeOutputConnection(TFxPort *port) {
501 std::set<TFxPort *>::iterator it = m_imp->m_outputPort.find(port);
502 if (it == m_imp->m_outputPort.end()) return false;
503
504 m_imp->m_outputPort.erase(it);
505 return true;
506 }
507
508 //--------------------------------------------------
509
getOutputConnectionCount() const510 int TFx::getOutputConnectionCount() const { return m_imp->m_outputPort.size(); }
511
512 //--------------------------------------------------
513
getOutputConnection(int i) const514 TFxPort *TFx::getOutputConnection(int i) const {
515 assert(0 <= i && i <= (int)m_imp->m_outputPort.size());
516 std::set<TFxPort *>::iterator it = m_imp->m_outputPort.begin();
517 std::advance(it, i);
518 if (it == m_imp->m_outputPort.end()) return 0;
519 return *it;
520 }
521
522 //--------------------------------------------------
523
disconnect(const std::string & name)524 bool TFx::disconnect(const std::string &name) {
525 TFxPort *port = getInputPort(name);
526 if (!port) return false;
527
528 port->setFx(0);
529 return true;
530 }
531
532 //--------------------------------------------------
533
connect(const std::string & name,TFx * fx)534 bool TFx::connect(const std::string &name, TFx *fx) {
535 TFxPort *port = getInputPort(name);
536 if (!port) return false;
537
538 port->setFx(fx);
539 return true;
540 }
541
542 //--------------------------------------------------
543
getInputPortCount() const544 int TFx::getInputPortCount() const { return m_imp->m_portArray.size(); }
545
546 //--------------------------------------------------
547
getInputPort(int index) const548 TFxPort *TFx::getInputPort(int index) const {
549 assert(0 <= index && index < (int)m_imp->m_portArray.size());
550 return m_imp->m_portArray[index].second;
551 }
552
553 //--------------------------------------------------
554
getInputPortName(int index) const555 std::string TFx::getInputPortName(int index) const {
556 assert(0 <= index && index < (int)(m_imp->m_portArray.size()));
557 return m_imp->m_portArray[index].first;
558 }
559
560 //--------------------------------------------------
561
renamePort(const std::string & oldName,const std::string & newName)562 bool TFx::renamePort(const std::string &oldName, const std::string &newName) {
563 PortTable::iterator it = m_imp->m_portTable.find(oldName);
564 if (it == m_imp->m_portTable.end()) return false;
565
566 TFxPort *port = it->second;
567 m_imp->m_portTable.erase(it);
568 m_imp->m_portTable[newName] = port;
569
570 PortArray::iterator it2;
571 for (it2 = m_imp->m_portArray.begin(); it2 != m_imp->m_portArray.end();
572 ++it2) {
573 if (it2->first != oldName) continue;
574
575 it2->first = newName;
576 break;
577 }
578
579 return true;
580 }
581
582 //--------------------------------------------------
583
getInputPort(const std::string & name) const584 TFxPort *TFx::getInputPort(const std::string &name) const {
585 PortTable::iterator it = m_imp->m_portTable.find(name);
586 if (it == m_imp->m_portTable.end()) return 0;
587
588 return m_imp->m_portTable[name];
589 }
590
591 //--------------------------------------------------
592
getReferenceColumnIndex() const593 int TFx::getReferenceColumnIndex() const {
594 if (!m_imp->m_portArray.empty()) {
595 TFx *fx = m_imp->m_portArray[0].second->getFx();
596 if (fx) return fx->getReferenceColumnIndex();
597 }
598 return -1;
599 }
600
601 //--------------------------------------------------
602
getTimeRegion() const603 TFxTimeRegion TFx::getTimeRegion() const {
604 if (m_imp->m_portTable.empty()) return TFxTimeRegion::createUnlimited();
605
606 TFxTimeRegion tr((std::numeric_limits<double>::max)(),
607 -(std::numeric_limits<double>::max)());
608
609 PortTable::iterator it = m_imp->m_portTable.begin();
610 for (; it != m_imp->m_portTable.end(); ++it) {
611 TFxPort *port = it->second;
612 if (port && port->isConnected() && !port->isaControlPort()) {
613 TFx *fx = port->getFx();
614 assert(fx);
615 tr += fx->getTimeRegion();
616 }
617 }
618
619 return tr;
620 }
621
622 //--------------------------------------------------
623
setActiveTimeRegion(const TFxTimeRegion & tr)624 void TFx::setActiveTimeRegion(const TFxTimeRegion &tr) {
625 m_imp->m_activeTimeRegion = tr;
626 }
627
628 //--------------------------------------------------
629
getActiveTimeRegion() const630 TFxTimeRegion TFx::getActiveTimeRegion() const {
631 return m_imp->m_activeTimeRegion;
632 }
633
634 //--------------------------------------------------
635
onChange(const TParamChange & c)636 void TFx::onChange(const TParamChange &c) {
637 TFxParamChange change(this, c);
638 notify(change);
639 }
640
641 //--------------------------------------------------
642
addObserver(TFxObserver * obs)643 void TFx::addObserver(TFxObserver *obs) { m_imp->m_observers.insert(obs); }
644
645 //--------------------------------------------------
646
removeObserver(TFxObserver * obs)647 void TFx::removeObserver(TFxObserver *obs) { m_imp->m_observers.erase(obs); }
648
649 //--------------------------------------------------
650
notify(const TFxChange & change)651 void TFx::notify(const TFxChange &change) {
652 for (std::set<TFxObserver *>::iterator it = m_imp->m_observers.begin();
653 it != m_imp->m_observers.end(); ++it)
654 (*it)->onChange(change);
655 }
656
657 //--------------------------------------------------
658
notify(const TFxPortAdded & change)659 void TFx::notify(const TFxPortAdded &change) {
660 for (std::set<TFxObserver *>::iterator it = m_imp->m_observers.begin();
661 it != m_imp->m_observers.end(); ++it)
662 (*it)->onChange(change);
663 }
664
665 //--------------------------------------------------
666
notify(const TFxPortRemoved & change)667 void TFx::notify(const TFxPortRemoved &change) {
668 for (std::set<TFxObserver *>::iterator it = m_imp->m_observers.begin();
669 it != m_imp->m_observers.end(); ++it)
670 (*it)->onChange(change);
671 }
672
673 //--------------------------------------------------
674
notify(const TFxParamAdded & change)675 void TFx::notify(const TFxParamAdded &change) {
676 for (std::set<TFxObserver *>::iterator it = m_imp->m_observers.begin();
677 it != m_imp->m_observers.end(); ++it)
678 (*it)->onChange(change);
679 }
680
681 //--------------------------------------------------
682
notify(const TFxParamRemoved & change)683 void TFx::notify(const TFxParamRemoved &change) {
684 for (std::set<TFxObserver *>::iterator it = m_imp->m_observers.begin();
685 it != m_imp->m_observers.end(); ++it)
686 (*it)->onChange(change);
687 }
688
689 //--------------------------------------------------
690
getIdentifier() const691 unsigned long TFx::getIdentifier() const { return m_imp->m_id; }
692
693 //--------------------------------------------------
694
setIdentifier(unsigned long id)695 void TFx::setIdentifier(unsigned long id) { m_imp->m_id = id; }
696
697 //--------------------------------------------------
698
setNewIdentifier()699 void TFx::setNewIdentifier() { m_imp->m_id = ++m_imp->m_nextId; }
700
701 //--------------------------------------------------
702
loadData(TIStream & is)703 void TFx::loadData(TIStream &is) {
704 // default version of fx is 1
705 setFxVersion(1);
706
707 std::string tagName;
708 VersionNumber tnzVersion = is.getVersion();
709 // Prevent to load "params" tag under "super" tag on saving macro fx.
710 // For now "params" tag is no longer saved under "super" tag.
711 // This is for keeping compatibility with older versions.
712 bool isInSuperTag = (is.getCurrentTagName() == "super");
713 QList<int> groupIds;
714 QList<std::wstring> groupNames;
715 while (is.openChild(tagName)) {
716 if (tagName == "params") {
717 if (isInSuperTag) { // skip loading "params" tag under "super" tag
718 is.skipCurrentTag();
719 continue;
720 }
721 while (!is.eos()) {
722 std::string paramName;
723 while (is.openChild(paramName)) {
724 TParamVar *paramVar = getParams()->getParamVar(paramName);
725 if (paramVar && paramVar->getParam()) {
726 paramVar->getParam()->loadData(is);
727 if (paramVar->isObsolete())
728 onObsoleteParamLoaded(paramVar->getParam()->getName());
729 } else // il parametro non e' presente -> skip
730 skipChild(is);
731
732 is.closeChild();
733 }
734 }
735 } else if (tagName == "paramsLinkedTo") {
736 TPersist *p = 0;
737 is >> p;
738 TFx *fx = dynamic_cast<TFx *>(p);
739 if (fx == 0) throw TException("Missing linkedSetRoot");
740 linkParams(fx);
741 } else if (tagName == "ports") {
742 std::string portName;
743 while (!is.eos()) {
744 while (is.openChild(portName)) {
745 VersionNumber version = is.getVersion();
746 compatibilityTranslatePort(version.first, version.second, portName);
747
748 // Try to find the specified port
749 TFxPort *port = getInputPort(portName);
750 if (!port) {
751 // Scan dynamic port groups for a containing one - add a port there
752 // if found
753 int g, gCount = dynamicPortGroupsCount();
754 for (g = 0; g != gCount; ++g) {
755 TFxPortDG *group = const_cast<TFxPortDG *>(dynamicPortGroup(g));
756
757 if (group->contains(portName)) {
758 addInputPort(portName, port = new TRasterFxPort, g);
759 break;
760 }
761 }
762 }
763
764 // Could not find (or add) a port with the corresponding name - throw
765 if (!port)
766 throw TException(std::string("port '") + portName +
767 "' is not present");
768
769 if (!is.eos()) {
770 TPersist *p = 0;
771 is >> p;
772 TFx *fx = dynamic_cast<TFx *>(p);
773 port->setFx(fx);
774 }
775
776 is.closeChild();
777 }
778 }
779 } else if (tagName == "dagNodePos") {
780 TPointD p;
781 is >> p.x >> p.y;
782 m_imp->m_attributes.setDagNodePos(updateDagPosition(p, tnzVersion));
783 } else if (tagName == "numberId") {
784 int numberId = 0;
785 is >> numberId;
786 m_imp->m_attributes.setId(numberId);
787 } else if (tagName == "passiveCacheId") {
788 int passiveCacheId = 0;
789 is >> passiveCacheId;
790
791 assert(passiveCacheId > 0);
792 TPassiveCacheManager::instance()->declareCached(this, passiveCacheId);
793 } else if (tagName == "name") {
794 // passo attraverso un filepath solo per evitare i problemi di blank
795 // o caratteri strani dentro il nome (sospetto che tfilepath sia gestito
796 // correttamente mentre wstring no
797 TFilePath tmp;
798 is >> tmp;
799 setName(tmp.getWideName());
800 } else if (tagName == "fxId") {
801 TFilePath tmp;
802 is >> tmp;
803 setFxId(tmp.getWideName());
804 } else if (tagName == "enabled") {
805 int flag = 1;
806 is >> flag;
807 m_imp->m_attributes.enable(flag != 0);
808 } else if (tagName == "opened") {
809 int opened = 1;
810 is >> opened;
811 m_imp->m_attributes.setIsOpened(opened);
812 } else if (tagName == "groupIds") {
813 int groupId;
814 while (!is.eos()) {
815 is >> groupId;
816 groupIds.append(groupId);
817 }
818 } else if (tagName == "groupNames") {
819 std::wstring groupName;
820 while (!is.eos()) {
821 is >> groupName;
822 groupNames.append(groupName);
823 }
824 } else if (tagName == "fxVersion") {
825 int version = 1;
826 is >> version;
827 setFxVersion(version);
828 } else {
829 throw TException("Unknown tag!");
830 }
831 is.closeChild();
832 }
833 if (!groupIds.isEmpty()) {
834 assert(groupIds.size() == groupNames.size());
835 int i;
836 for (i = 0; i < groupIds.size(); i++) {
837 m_imp->m_attributes.setGroupId(groupIds[i]);
838 m_imp->m_attributes.setGroupName(groupNames[i]);
839 }
840 }
841 }
842
843 //--------------------------------------------------
844
saveData(TOStream & os)845 void TFx::saveData(TOStream &os) {
846 // Prevent to save "params" tag under "super" tag on saving macro fx.
847 // Parameters for macro fx are saved in "nodes" tag and corrected upon
848 // loading. Therefore, "params" tag is not needed and even causes crash if
849 // macrofx contains CurveFx (See the issue #2424)
850 bool isInSuperTag = (os.getCurrentTagName() == "super");
851 TFx *linkedSetRoot = this;
852 if (m_imp->m_next != m_imp) {
853 TFxImp *imp = m_imp->m_next;
854 int guard = 0;
855 while (guard++ < 1000 && imp != m_imp) {
856 if (imp->m_fx < linkedSetRoot) linkedSetRoot = imp->m_fx;
857 imp = imp->m_next;
858 }
859 assert(imp == m_imp);
860 assert(linkedSetRoot);
861 }
862 if (linkedSetRoot == this) {
863 if (!isInSuperTag) { // skip saving "params" tag under "super" tag
864 os.openChild("params");
865 for (int i = 0; i < getParams()->getParamCount(); i++) {
866 std::string paramName = getParams()->getParamName(i);
867 const TParamVar *paramVar = getParams()->getParamVar(i);
868 // skip saving for the obsolete parameters
869 if (paramVar->isObsolete()) continue;
870 os.openChild(paramName);
871 paramVar->getParam()->saveData(os);
872 os.closeChild();
873 }
874 os.closeChild();
875 }
876 } else {
877 os.openChild("paramsLinkedTo");
878 os << linkedSetRoot;
879 os.closeChild();
880 }
881
882 os.openChild("ports");
883 for (auto &namePort : m_imp->m_portArray) {
884 os.openChild(namePort.first);
885 if (namePort.second->isConnected())
886 os << TFxP(namePort.second->getFx()).getPointer();
887 os.closeChild();
888 }
889 os.closeChild();
890
891 TPointD p = m_imp->m_attributes.getDagNodePos();
892 if (p != TConst::nowhere) os.child("dagNodePos") << p.x << p.y;
893 int numberId = m_imp->m_attributes.getId();
894 os.child("numberId") << numberId;
895 bool cacheEnabled = TPassiveCacheManager::instance()->cacheEnabled(this);
896 if (cacheEnabled)
897 os.child("passiveCacheId")
898 << TPassiveCacheManager::instance()->getPassiveCacheId(this);
899 std::wstring name = getName();
900 if (name != L"") os.child("name") << TFilePath(name);
901 std::wstring fxId = getFxId();
902 os.child("fxId") << fxId;
903 if (!m_imp->m_attributes.isEnabled()) os.child("enabled") << 0;
904 os.child("opened") << (int)m_imp->m_attributes.isOpened();
905 if (m_imp->m_attributes.isGrouped()) {
906 os.openChild("groupIds");
907 QStack<int> groupIdStack = m_imp->m_attributes.getGroupIdStack();
908 int i;
909 for (i = 0; i < groupIdStack.size(); i++) os << groupIdStack[i];
910 os.closeChild();
911 os.openChild("groupNames");
912 QStack<std::wstring> groupNameStack =
913 m_imp->m_attributes.getGroupNameStack();
914 for (i = 0; i < groupNameStack.size(); i++) os << groupNameStack[i];
915 os.closeChild();
916 }
917 if (getFxVersion() != 1) os.child("fxVersion") << getFxVersion();
918 }
919
920 //--------------------------------------------------
921
loadPreset(TIStream & is)922 void TFx::loadPreset(TIStream &is) {
923 std::string tagName;
924 while (is.openChild(tagName)) {
925 if (tagName == "dvpreset") {
926 std::string fxId = is.getTagAttribute("fxId");
927 if (fxId != getFxType())
928 throw TException("Preset doesn't match the fx type");
929 } else if (tagName == "params") {
930 while (!is.eos()) {
931 std::string paramName;
932 while (is.openChild(paramName)) {
933 try {
934 TParamP param = getParams()->getParam(paramName);
935 param->loadData(is);
936 } catch (TException &) { /*skip*/
937 } // il parametro non e' presente
938 is.closeChild();
939 }
940 }
941 } else {
942 throw TException("Fx preset unknown tag!");
943 }
944 }
945 }
946
947 //--------------------------------------------------
948
savePreset(TOStream & os)949 void TFx::savePreset(TOStream &os) {
950 std::map<std::string, std::string> attributes;
951 attributes.insert(std::make_pair(std::string("ver"), std::string("1.0")));
952 attributes.insert(std::make_pair(std::string("fxId"), getFxType()));
953
954 os.openChild("dvpreset", attributes);
955
956 os.openChild("params");
957 for (int i = 0; i < getParams()->getParamCount(); i++) {
958 std::string paramName = getParams()->getParamName(i);
959 TParam *param = getParams()->getParam(i);
960 os.openChild(paramName);
961 param->saveData(os);
962 os.closeChild();
963 }
964 os.closeChild();
965
966 os.closeChild();
967 }
968
969 //--------------------------------------------------
970
disconnectAll()971 void TFx::disconnectAll() {
972 int p, pCount = getInputPortCount();
973 for (p = 0; p != pCount; ++p) getInputPort(p)->setFx(0);
974 }
975
976 //--------------------------------------------------
977
create(std::string name)978 TFx *TFx::create(std::string name) {
979 return TFxFactory::instance()->create(name);
980 }
981
982 //--------------------------------------------------
983
listFxs(std::vector<TFxInfo> & info)984 void TFx::listFxs(std::vector<TFxInfo> &info) {
985 TFxFactory::instance()->getFxInfos(info);
986 }
987
988 //--------------------------------------------------
989
getFxInfo(const std::string & fxIdentifier)990 TFxInfo TFx::getFxInfo(const std::string &fxIdentifier) {
991 return TFxFactory::instance()->getFxInfo(fxIdentifier);
992 }
993
994 //--------------------------------------------------
995
getLinkedFx() const996 TFx *TFx::getLinkedFx() const {
997 assert(m_imp->m_next);
998 assert(m_imp->m_next->m_prev == m_imp);
999 assert(m_imp->m_next->m_fx != 0);
1000 return m_imp->m_next->m_fx;
1001 }
1002
1003 //--------------------------------------------------
1004
setFxVersion(int v)1005 void TFx::setFxVersion(int v) { m_imp->m_attributes.setFxVersion(v); }
1006
1007 //--------------------------------------------------
1008
getFxVersion() const1009 int TFx::getFxVersion() const { return m_imp->m_attributes.getFxVersion(); }
1010
1011 //===================================================
1012 //
1013 // TFxTimeRegion
1014 //
1015 //--------------------------------------------------
1016
1017 //! Creates an unlimited time region.
TFxTimeRegion()1018 TFxTimeRegion::TFxTimeRegion()
1019 : m_start((std::numeric_limits<double>::max)())
1020 , m_end(-(std::numeric_limits<double>::max)()) {}
1021
1022 //--------------------------------------------------
1023
1024 //! Creates a time region with specified start (included) and end (\b excluded).
TFxTimeRegion(double start,double end)1025 TFxTimeRegion::TFxTimeRegion(double start, double end)
1026 : m_start(start), m_end(end) {}
1027
1028 //--------------------------------------------------
1029
createUnlimited()1030 TFxTimeRegion TFxTimeRegion::createUnlimited() {
1031 return TFxTimeRegion(-(std::numeric_limits<double>::max)(),
1032 (std::numeric_limits<double>::max)());
1033 }
1034
1035 //--------------------------------------------------
1036
contains(double time) const1037 bool TFxTimeRegion::contains(double time) const {
1038 return (m_start <= time && time < m_end);
1039 }
1040
1041 //--------------------------------------------------
1042
isUnlimited() const1043 bool TFxTimeRegion::isUnlimited() const {
1044 return (m_start == -(std::numeric_limits<double>::max)() ||
1045 m_end == (std::numeric_limits<double>::max)());
1046 }
1047
1048 //--------------------------------------------------
1049
isEmpty() const1050 bool TFxTimeRegion::isEmpty() const { return (m_end <= m_start); }
1051
1052 //--------------------------------------------------
1053
getFrameCount(int & count) const1054 bool TFxTimeRegion::getFrameCount(int &count) const {
1055 if (isUnlimited()) return false;
1056 count = tfloor(m_end) - tceil(m_start);
1057 return true;
1058 }
1059
1060 //--------------------------------------------------
1061
getFirstFrame() const1062 int TFxTimeRegion::getFirstFrame() const { return tceil(m_start); }
1063
1064 //--------------------------------------------------
1065
getLastFrame() const1066 int TFxTimeRegion::getLastFrame() const {
1067 if (m_end == (std::numeric_limits<double>::max)())
1068 return (std::numeric_limits<int>::max)();
1069 else
1070 return tceil(m_end) - 1;
1071 }
1072
1073 //===================================================
1074