1 #pragma once
2 
3 #ifndef TFX_INCLUDED
4 #define TFX_INCLUDED
5 
6 #include <memory>
7 
8 // TnzCore includes
9 #include "tsmartpointer.h"
10 #include "tpersist.h"
11 #include "texception.h"
12 #include "ttile.h"
13 #include "tgeometry.h"
14 
15 // TnzBase includes
16 #include "tparamchange.h"
17 
18 #undef DVAPI
19 #undef DVVAR
20 #ifdef TFX_EXPORTS
21 #define DVAPI DV_EXPORT_API
22 #define DVVAR DV_EXPORT_VAR
23 #else
24 #define DVAPI DV_IMPORT_API
25 #define DVVAR DV_IMPORT_VAR
26 #endif
27 
28 //===================================================================
29 
30 //    Forward declarations
31 
32 class TFxImp;
33 class TFx;
34 class TParam;
35 class TFxAttributes;
36 class TParamContainer;
37 class TParamVar;
38 class TRenderSettings;
39 class TParamUIConcept;
40 
41 //===================================================================
42 
43 class DVAPI TFxPort {
44   friend class TFx;
45 
46 protected:
47   TFx *m_owner;    //!< This is an input port of m_owner
48   int m_groupIdx;  //!< Dynamic group index this belongs to in m_owner (-1 if
49                    //! none)
50   bool m_isControl;
51 
52 public:
TFxPort(bool isControl)53   TFxPort(bool isControl)
54       : m_owner(0), m_groupIdx(-1), m_isControl(isControl) {}
~TFxPort()55   virtual ~TFxPort() {}
56 
57   virtual TFx *getFx() const = 0;
58   virtual void setFx(TFx *)  = 0;
59 
isConnected()60   bool isConnected() const { return getFx() != 0; }
isaControlPort()61   bool isaControlPort() const { return m_isControl; }
62 
getGroupIndex()63   int getGroupIndex() const { return m_groupIdx; }
64 
getOwnerFx()65   TFx *getOwnerFx() const { return m_owner; }
setOwnerFx(TFx * fx)66   void setOwnerFx(TFx *fx) { m_owner = fx; }
67 
68 private:
69   // Not copiable
70   TFxPort(const TFxPort &);
71   TFxPort &operator=(const TFxPort &);
72 };
73 
74 //-------------------------------------------------------------------
75 
76 template <class T>
77 class TFxPortT : public TFxPort {
78   friend class TFx;
79 
80 protected:
81   T *m_fx;
82 
83 public:
TFxPort(isControl)84   TFxPortT(bool isControl = false) : TFxPort(isControl), m_fx(0) {}
~TFxPortT()85   ~TFxPortT() {
86     if (m_fx) {
87       m_fx->removeOutputConnection(this);
88       m_fx->release();
89     }
90   }
91 
getFx()92   TFx *getFx() const override { return m_fx; }
93 
setFx(TFx * fx)94   void setFx(TFx *fx) override {
95     if (m_fx) m_fx->removeOutputConnection(this);
96 
97     if (fx == 0) {
98       if (m_fx) m_fx->release();
99       m_fx = 0;
100     } else {
101       T *fxt = dynamic_cast<T *>(fx);
102       if (!fxt) throw TException("Fx: port type mismatch");
103 
104       fxt->addRef();
105       if (m_fx) m_fx->release();
106 
107       m_fx = fxt;
108       m_fx->addOutputConnection(this);
109     }
110   }
111 
112   T *operator->() {
113     assert(m_fx);
114     return m_fx;
115   }
116 };
117 
118 //===================================================================
119 
120 /*
121   \brief A TFxPortDynamicGroup represents a group of fx ports with the
122   same name prefix whose ports that are added or removed dynamically by
123   Toonz on user request.
124 
125   \sa The TFx::dynamicPortsGroup() method.
126 */
127 class DVAPI TFxPortDynamicGroup {
128 public:
129   typedef std::vector<TFxPort *> PortsContainer;
130 
131 public:
132   TFxPortDynamicGroup(const std::string &portsPrefix, int minPortsCount = 1);
133   ~TFxPortDynamicGroup();
134 
135   //! Returns the group's displayed ports prefix (ports added to the group \b
136   //! must
137   //! have this prefix).
portsPrefix()138   const std::string &portsPrefix() const { return m_portsPrefix; }
139 
140   //! Returns the minimal number of ports to be displayed in the group. The
141   //! group
142   //! <B> must not <\B> be initialized in an fx implementation with more ports
143   //! than
144   //! this number.
minPortsCount()145   int minPortsCount() const { return m_minPortsCount; }
146 
147   //! Returns the list of ports currently in the group (may contain empty
148   //! ports).
ports()149   const PortsContainer &ports() const { return m_ports; }
150 
151   //! Equivalent to checking the portName prefix against the stored one.
contains(const std::string & portName)152   bool contains(const std::string &portName) const {
153     return (strncmp(m_portsPrefix.c_str(), portName.c_str(),
154                     m_portsPrefix.size()) == 0);
155   }
156 
157 private:
158   std::string m_portsPrefix;  //!< Name prefix of each stored port
159   int m_minPortsCount;        //!< Ports count \a should not be smaller
160 
161   std::vector<TFxPort *> m_ports;  //!< \b Owned ports (deleted on destruction)
162 
163 private:
164   friend class TFx;
165 
166   // Not copyable
167   TFxPortDynamicGroup(const TFxPortDynamicGroup &);
168   TFxPortDynamicGroup &operator=(const TFxPortDynamicGroup &);
169 
170   void addPort(TFxPort *port);
171   void removePort(
172       TFxPort *port);  //!< Removes <I> and deletes <\I> the specified port
173   void clear();
174 };
175 
176 typedef TFxPortDynamicGroup TFxPortDG;
177 
178 //===================================================================
179 
180 class DVAPI TFxTimeRegion {
181 public:
182   TFxTimeRegion();
183   TFxTimeRegion(double start, double end);
184 
185   static TFxTimeRegion createUnlimited();
186 
187   TFxTimeRegion &operator+=(const TFxTimeRegion &rhs) {
188     m_start = std::min(m_start, rhs.m_start);
189     m_end   = std::max(m_end, rhs.m_end);
190     return *this;
191   }
192 
193   TFxTimeRegion &operator+=(double shift) {
194     m_start += shift;
195     m_end += shift;
196     return *this;
197   }
198 
199   TFxTimeRegion &operator-=(double shift) { return operator+=(-shift); }
200 
201   bool contains(double time) const;
202   bool isUnlimited() const;
203   bool isEmpty() const;
204 
205   bool getFrameCount(int &count) const;
206   int getFirstFrame() const;
207   int getLastFrame() const;
208 
209   double m_start;
210   double m_end;
211 };
212 
213 inline TFxTimeRegion operator+(const TFxTimeRegion &tr1,
214                                const TFxTimeRegion &tr2) {
215   return TFxTimeRegion(tr1) += tr2;
216 }
217 
218 inline TFxTimeRegion operator+(const TFxTimeRegion &tr1, double shift) {
219   return TFxTimeRegion(tr1) += shift;
220 }
221 
222 inline TFxTimeRegion operator-(const TFxTimeRegion &tr1, double shift) {
223   return TFxTimeRegion(tr1) -= shift;
224 }
225 
226 //===================================================================
227 
228 class DVAPI TFxChange {
229 public:
230   TFx *m_fx;
231 
232   double m_firstAffectedFrame;
233   double m_lastAffectedFrame;
234   bool m_dragging;
235 
236   static double m_minFrame;
237   static double m_maxFrame;
238 
239 public:
TFxChange(TFx * fx,double firstAffectedFrame,double lastAffectedFrame,bool dragging)240   TFxChange(TFx *fx, double firstAffectedFrame, double lastAffectedFrame,
241             bool dragging)
242       : m_fx(fx)
243       , m_firstAffectedFrame(firstAffectedFrame)
244       , m_lastAffectedFrame(lastAffectedFrame)
245       , m_dragging(dragging) {}
246 
247 private:
248   TFxChange();
249 };
250 
251 //------------------------------------------------------------------------------
252 
253 class TFxParamChange final : public TFxChange {
254 public:
255   TFxParamChange(TFx *fx, double firstAffectedFrame, double lastAffectedFrame,
256                  bool dragging);
257   TFxParamChange(TFx *fx, const TParamChange &src);
258 };
259 
260 //------------------------------------------------------------------------------
261 
262 class TFxPortAdded final : public TFxChange {
263 public:
TFxPortAdded(TFx * fx)264   TFxPortAdded(TFx *fx) : TFxChange(fx, m_minFrame, m_maxFrame, false) {}
~TFxPortAdded()265   ~TFxPortAdded() {}
266 };
267 
268 //------------------------------------------------------------------------------
269 
270 class TFxPortRemoved final : public TFxChange {
271 public:
TFxPortRemoved(TFx * fx)272   TFxPortRemoved(TFx *fx) : TFxChange(fx, m_minFrame, m_maxFrame, false) {}
~TFxPortRemoved()273   ~TFxPortRemoved() {}
274 };
275 
276 //------------------------------------------------------------------------------
277 
278 class TFxParamAdded final : public TFxChange {
279 public:
TFxParamAdded(TFx * fx)280   TFxParamAdded(TFx *fx) : TFxChange(fx, m_minFrame, m_maxFrame, false) {}
~TFxParamAdded()281   ~TFxParamAdded() {}
282 };
283 
284 //------------------------------------------------------------------------------
285 
286 class TFxParamRemoved final : public TFxChange {
287 public:
TFxParamRemoved(TFx * fx)288   TFxParamRemoved(TFx *fx) : TFxChange(fx, m_minFrame, m_maxFrame, false) {}
~TFxParamRemoved()289   ~TFxParamRemoved() {}
290 };
291 
292 //------------------------------------------------------------------------------
293 
294 class TFxParamsUnlinked final : public TFxChange {
295 public:
TFxParamsUnlinked(TFx * fx)296   TFxParamsUnlinked(TFx *fx) : TFxChange(fx, m_minFrame, m_maxFrame, false) {}
~TFxParamsUnlinked()297   ~TFxParamsUnlinked() {}
298 };
299 
300 //===================================================================
301 
302 class DVAPI TFxObserver {
303 public:
TFxObserver()304   TFxObserver() {}
~TFxObserver()305   virtual ~TFxObserver() {}
306 
307   virtual void onChange(const TFxChange &change) = 0;
308 
onChange(const TFxPortAdded & change)309   virtual void onChange(const TFxPortAdded &change) {
310     onChange(static_cast<const TFxChange &>(change));
311   }
312 
onChange(const TFxPortRemoved & change)313   virtual void onChange(const TFxPortRemoved &change) {
314     onChange(static_cast<const TFxChange &>(change));
315   }
316 
onChange(const TFxParamAdded & change)317   virtual void onChange(const TFxParamAdded &change) {
318     onChange(static_cast<const TFxChange &>(change));
319   }
320 
onChange(const TFxParamRemoved & change)321   virtual void onChange(const TFxParamRemoved &change) {
322     onChange(static_cast<const TFxChange &>(change));
323   }
324 
onChange(const TFxParamsUnlinked & change)325   virtual void onChange(const TFxParamsUnlinked &change) {
326     onChange(static_cast<const TFxChange &>(change));
327   }
328 };
329 
330 //===================================================================
331 
332 class TFxInfo {
333 public:
334   std::string m_name;
335   bool m_isHidden;
336 
337 public:
TFxInfo()338   TFxInfo() {}
TFxInfo(const std::string & name,bool isHidden)339   TFxInfo(const std::string &name, bool isHidden)
340       : m_name(name), m_isHidden(isHidden) {}
341 };
342 
343 //===================================================================
344 
345 #ifdef _WIN32
346 template class DVAPI TSmartPointerT<TFx>;
347 #endif
348 typedef TSmartPointerT<TFx> TFxP;
349 
350 //===================================================================
351 
352 class DVAPI TFx : public TSmartObject, public TPersist, public TParamObserver {
353   DECLARE_CLASS_CODE
354 
355   TFxImp *m_imp;
356 
357 public:
358   typedef TFx *CreateProc();
359 
360   TFx();
361   virtual ~TFx();
362 
363   virtual std::wstring getName() const;
364   void setName(std::wstring name);
365   std::wstring getFxId() const;
366   void setFxId(std::wstring id);
367 
368   TParamContainer *getParams();
369   const TParamContainer *getParams() const;
370   void addParamVar(TParamVar *var);
371 
372   virtual TFx *clone(bool recursive = true) const;
373   TFx *clone(TFx *fx, bool recursive) const;
374 
375   void unlinkParams();
376   virtual void linkParams(TFx *src);
377 
378   TFx *getLinkedFx() const;
379 
380   bool addInputPort(const std::string &name, TFxPort &p);  //!< Adds a port with
381                                                            //! given name,
382   //! returns false on
383   //! duplicate names.
384   //!  Ownership of the port belongs to derived implementations of TFx.
385   bool addInputPort(const std::string &name, TFxPort *p,
386                     int groupIndex);  //!< Adds a port with given name to the
387                                       //! specified dynamic group,
388   //!  returns false on duplicate names. Ownership is transferred to the group.
389   bool removeInputPort(const std::string &name);  //!< Removes the port with
390                                                   //! given name, returns false
391   //! if not found.
392 
393   bool renamePort(const std::string &oldName, const std::string &newName);
394 
395   bool connect(
396       const std::string &name,
397       TFx *other);  //!< Equivalent to getInputPort(name)->setFx(other).
398   bool disconnect(const std::string
399                       &name);  //!< Equivalent to getInputPort(name)->setFx(0).
400 
401   int getInputPortCount() const;
402   TFxPort *getInputPort(int index) const;
403   TFxPort *getInputPort(const std::string &name) const;
404   std::string getInputPortName(int index) const;
405 
dynamicPortGroupsCount()406   virtual int dynamicPortGroupsCount() const { return 0; }
dynamicPortGroup(int g)407   virtual const TFxPortDG *dynamicPortGroup(int g) const { return 0; }
hasDynamicPortGroups()408   bool hasDynamicPortGroups() const { return (dynamicPortGroupsCount() > 0); }
409   void clearDynamicPortGroup(
410       int g);  //!< \warning Users must ensure that the group's minimal
411                //!  ports count is respected - this method does \b not.
412   bool addOutputConnection(TFxPort *port);
413   bool removeOutputConnection(TFxPort *port);
414 
415   static void listFxs(std::vector<TFxInfo> &fxInfos);
416   static TFxInfo getFxInfo(const std::string &fxIdentifier);  //!< Returns info
417                                                               //! associated to
418   //! an fx
419   //! identifier, or
420   //! an
421   //!  unnamed one if none was found.
isZerary()422   virtual bool isZerary() const { return getInputPortCount() == 0; }
423 
424   // returns the column index that provides reference frame for the FX.
425   // (TColumnFx and Zerary fxs return their column indexes, n-ary FXs return
426   // the reference column index of their first argument)
427   // note: it returns -1 if the column is undefined (e.g. a n-ary FX with
428   // arguments undefined yet)
429   virtual int getReferenceColumnIndex() const;
430 
431   // se getXsheetPort() != 0 e la porta non e' connessa la si considera connessa
432   // a tutte le colonne precedenti a quella corrente.
433   // cfr. AddFx
getXsheetPort()434   virtual TFxPort *getXsheetPort() const { return 0; }
435 
436   int getOutputConnectionCount() const;
437   TFxPort *getOutputConnection(int i) const;
438 
439   virtual TFxTimeRegion getTimeRegion() const;
440 
441   void setActiveTimeRegion(const TFxTimeRegion &tr);
442   TFxTimeRegion getActiveTimeRegion() const;
443 
checkActiveTimeRegion()444   virtual bool checkActiveTimeRegion() const { return true; }
445 
446   void disconnectAll();
447 
448   //! Returns a list of User Interface Concepts to be displayed when editing the
449   //! fx parameters.
450   //! \note Ownership of the returned array allocated with new[] is passed to
451   //! callers.
getParamUIs(TParamUIConcept * & params,int & length)452   virtual void getParamUIs(TParamUIConcept *&params, int &length) {
453     params = 0, length = 0;
454   }
455 
456   inline std::string getFxType() const;
457   virtual std::string getPluginId() const = 0;
458 
459   static TFx *create(std::string name);
460 
461   // TParamObserver-related methods
462   void onChange(const TParamChange &c) override;
463 
464   void addObserver(TFxObserver *);
465   void removeObserver(TFxObserver *);
466   void notify(const TFxChange &change);
467   void notify(const TFxPortAdded &change);
468   void notify(const TFxPortRemoved &change);
469   void notify(const TFxParamAdded &change);
470   void notify(const TFxParamRemoved &change);
471 
472   void loadData(TIStream &is) override;
473   void saveData(TOStream &os) override;
474 
475   void loadPreset(TIStream &is);  // solleva un eccezione se il preset non
476                                   // corrisponde all'effetto
477   void savePreset(TOStream &os);
478 
479   TFxAttributes *getAttributes() const;
480 
getAlias(double frame,const TRenderSettings & info)481   virtual std::string getAlias(double frame,
482                                const TRenderSettings &info) const {
483     return "";
484   }
485 
486   //! Compatibility function - used to translate a port name from older Toonz
487   //! versions into its current form.
compatibilityTranslatePort(int majorVersion,int minorVersion,std::string & portName)488   virtual void compatibilityTranslatePort(int majorVersion, int minorVersion,
489                                           std::string &portName) {}
490 
491   /*-- Rendering(目玉)ボタンがOFFのときに使用されるInputPort --*/
getPreferredInputPort()492   virtual int getPreferredInputPort() { return 0; }
493 
494   /* RasterFxPluginHost 用の仮想関数 */
callStartRenderHandler()495   virtual void callStartRenderHandler() {}
callEndRenderHandler()496   virtual void callEndRenderHandler() {}
callStartRenderFrameHandler(const TRenderSettings * rs,double frame)497   virtual void callStartRenderFrameHandler(const TRenderSettings *rs,
498                                            double frame) {}
callEndRenderFrameHandler(const TRenderSettings * rs,double frame)499   virtual void callEndRenderFrameHandler(const TRenderSettings *rs,
500                                          double frame) {}
501 
502   // This function will be called in TFx::loadData whenever the obsolete
503   // parameter is loaded. Do nothing by default.
onObsoleteParamLoaded(const std::string & paramName)504   virtual void onObsoleteParamLoaded(const std::string &paramName) {}
505 
506   void setFxVersion(int);
507   int getFxVersion() const;
508 
509 public:
510   // Id-related functions
511 
512   unsigned long getIdentifier() const;
513   void setIdentifier(unsigned long id);
514   void setNewIdentifier();
515 
516 private:
517   // not implemented
518   TFx(const TFx &);
519   TFx &operator=(const TFx &);
520 };
521 
522 //===================================================================
523 
524 DVAPI TIStream &operator>>(TIStream &in, TFxP &p);
525 
526 //===================================================================
527 
528 //===================================================================
529 
530 class DVAPI TFxDeclaration : public TPersistDeclaration {
531 public:
532   TFxDeclaration(const TFxInfo &info);
533 };
534 
535 template <class T>
536 class TFxDeclarationT final : public TFxDeclaration {
537 public:
TFxDeclarationT(const TFxInfo & info)538   TFxDeclarationT(const TFxInfo &info) : TFxDeclaration(info) {}
create()539   TPersist *create() const override { return new T; }
540 };
541 
542 //-------------------------------------------------------------------
543 
getFxType()544 inline std::string TFx::getFxType() const { return getDeclaration()->getId(); }
545 
546 //-------------------------------------------------------------------
547 
548 #define FX_DECLARATION(T)                                                      \
549                                                                                \
550 public:                                                                        \
551   const TPersistDeclaration *getDeclaration() const override;
552 
553 #define FX_IDENTIFIER(T, I)                                                    \
554   namespace {                                                                  \
555   TFxDeclarationT<T> info##T(TFxInfo(I, false));                               \
556   }                                                                            \
557   const TPersistDeclaration *T::getDeclaration() const { return &info##T; }
558 
559 #define FX_IDENTIFIER_IS_HIDDEN(T, I)                                          \
560   namespace {                                                                  \
561   TFxDeclarationT<T> info##T(TFxInfo(I, true));                                \
562   }                                                                            \
563   const TPersistDeclaration *T::getDeclaration() const { return &info##T; }
564 
565 //===================================================================
566 
567 #endif
568