1 #pragma once
2 
3 #ifndef FUNCTIONTREEMODEL_H
4 #define FUNCTIONTREEMODEL_H
5 
6 // TnzCore includes
7 #include "tcommon.h"
8 #include "tdoubleparam.h"
9 
10 // TnzQt includes
11 #include "treemodel.h"
12 
13 // Qt includes
14 #include <QScrollBar>
15 
16 #undef DVAPI
17 #undef DVVAR
18 #ifdef TOONZQT_EXPORTS
19 #define DVAPI DV_EXPORT_API
20 #define DVVAR DV_EXPORT_VAR
21 #else
22 #define DVAPI DV_IMPORT_API
23 #define DVVAR DV_IMPORT_VAR
24 #endif
25 
26 //=================================================================
27 
28 //    Forward declarations
29 
30 class TStageObject;
31 class TFx;
32 class TDoubleParam;
33 class TXsheet;
34 class TParamContainer;
35 class TFxHandle;
36 class TObjectHandle;
37 class TXsheetHandle;
38 
39 class FunctionTreeView;
40 class FunctionViewer;
41 
42 //=================================================================
43 
44 //*****************************************************************************************
45 //    FunctionTreeModel  declaration
46 //*****************************************************************************************
47 
48 /*!
49   \brief    The Function Editor's (tree-like) \a model, as in the
50   <I>model-view</I> architecture.
51 
52   \details  This class represents the data associated to Toonz's Function Editor
53   panels in a
54             view-independent way. The model's purpose is that of representing
55   all \a channels of the
56             objects in a scene. A \a channel is here intended as an
57   <I>animatable parameter</I>
58             represented by a <I>single real-valued function</I>.
59 
60             Animatable objects are currently subdivided in two main types:
61   <I>stage objects</I>
62             (which consist roughly all the objects represented in the \a stage
63   schematic view,
64             including cameras, spline curves and pegbars), and \a fxs. Stage
65   objects typically
66             feature a uniform channels group structure, whereas each fx type
67   have a different set
68             of parameters (and thus channels). Recently, \a column objects can
69   sport an additional
70             group of channels, related to Plastic skeleton animations (see
71   TnzExt library).
72 */
73 
74 class DVAPI FunctionTreeModel final : public TreeModel, public TParamObserver {
75   Q_OBJECT
76 
77 public:
78   /*!
79 \brief    FunctionTreeModel's abstract base item class, adding the requirement
80 to
81         return features visibility data.
82 */
83   class Item : public TreeModel::Item {
84   public:
Item()85     Item() {}
86 
87     virtual bool isActive() const   = 0;
88     virtual bool isAnimated() const = 0;
89     virtual bool isIgnored() const  = 0;
90   };
91 
92   //----------------------------------------------------------------------------------
93 
94   //! The model item representing a channels group.
95   class ChannelGroup : public Item {
96   public:
97     enum ShowFilter { ShowAllChannels, ShowAnimatedChannels };
98 
99   private:
100     QString m_name;
101     ShowFilter m_showFilter;
102 
103   public:
104     ChannelGroup(const QString &name = "");
105     ~ChannelGroup();
106 
107     bool isActive() const override;
108     bool isAnimated() const override;
109     bool isIgnored() const override;
110 
getShortName()111     virtual QString getShortName() const { return m_name; }
getLongName()112     virtual QString getLongName() const { return m_name; }
113 
114     virtual QString getIdName() const;
115 
116     void setShowFilter(ShowFilter showFilter);
getShowFilter()117     ShowFilter getShowFilter() const { return m_showFilter; }
118 
119     void applyShowFilter();  // call this method when a channel changes
120                              // its animation status
121     QVariant data(int role) const override;
122 
123     // used in FunctionTreeView::onActivated
124     void setChildrenAllActive(bool active);
125 
126     void displayAnimatedChannels();
127   };
128 
129   //----------------------------------------------------------------------------------
130 
131   /*!
132 \brief    The common class representing a \a parameter in the model.
133 
134 \remark   This class's concept is different from that of a Channel, as a \a
135 parameter could
136         be composed of <I>multiple channels</I>, e.g. like an animated \p RGBA
137 color, which
138         has 4 channels.
139 */
140   class ParamWrapper {
141   protected:
142     TParamP m_param;      //!< The wrapped parameter.
143     std::wstring m_fxId;  //!< Fx identifier for m_param's owner, if any.
144 
145   public:
ParamWrapper(const TParamP & param,const std::wstring & fxId)146     ParamWrapper(const TParamP &param, const std::wstring &fxId)
147         : m_param(param), m_fxId(fxId) {}
~ParamWrapper()148     virtual ~ParamWrapper() {}
149 
getFxId()150     const std::wstring &getFxId() const { return m_fxId; }
151 
getParam()152     TParamP getParam() const { return m_param; }
setParam(const TParamP & param)153     virtual void setParam(const TParamP &param) { m_param = param; }
154   };
155 
156   //----------------------------------------------------------------------------------
157 
158   //! The model item representing a channel (i.e. a real-valued function).
159   class DVAPI Channel final : public ParamWrapper,
160                               public Item,
161                               public TParamObserver {
162     FunctionTreeModel *m_model;  //!< (\p not \p owned) Reference to the model
163     ChannelGroup
164         *m_group;  //!< (\p not \p owned) Reference to the enclosing group
165 
166     std::string m_paramNamePref;
167 
168     bool m_isActive;  //!< Whether the channels is active, ie visible
169                       //!< as a curve and numeric column
170   public:
171     Channel(FunctionTreeModel *model, TDoubleParam *param,
172             std::string paramNamePrefix = "", std::wstring fxId = L"");
173     ~Channel();
174 
getParam()175     TDoubleParam *getParam() const {
176       return (TDoubleParam *)m_param.getPointer();
177     }
178     void setParam(const TParamP &param) override;
179 
180     QString getShortName() const;
181     QString getLongName() const;
182 
183     // in order to show the expression name in the tooltip
184     QString getExprRefName() const;
185 
getChannelGroup()186     ChannelGroup *getChannelGroup() const { return m_group; }
setChannelGroup(ChannelGroup * group)187     void setChannelGroup(ChannelGroup *group) { m_group = group; }
188 
189     QVariant data(int role) const override;
190 
isActive()191     bool isActive() const override { return m_isActive; }
192     void setIsActive(bool active);
193 
194     bool isAnimated() const override;
195     bool isIgnored() const override;
196 
197     bool isCurrent() const;
198     void setIsCurrent(bool current);
199 
200     bool isHidden() const;  // the channel is hidden if it is filtered out
201                             // by its channelgroup
202     void onChange(const TParamChange &) override;
203 
204     void *getInternalPointer() const override;
205   };
206 
207 private:
208   ChannelGroup
209       *m_stageObjects,  //!< Predefined group for stage object channels.
210       *m_fxs;           //!< Predefined group for fx parameters.
211 
212   std::vector<Channel *> m_activeChannels;
213 
214   Channel *m_currentChannel;  //!< (\p not \p owned) Current channel.
215   TStageObject
216       *m_currentStageObject;  //!< (\p not \p owned) Current stage object.
217   TFx *m_currentFx;           //!< (\p not \p owned) Current fx.
218 
219   bool m_paramsChanged;
220 
221   TFxHandle *m_fxHandle;
222   TObjectHandle *m_objectHandle;
223 
224 public:
225   FunctionTreeModel(
226       FunctionTreeView *parent = 0);  // BUT! Should be view-independent! :o
227   ~FunctionTreeModel();
228 
getCurrentChannel()229   Channel *getCurrentChannel() const { return m_currentChannel; }
230 
231   Channel *getActiveChannel(int index) const;
getActiveChannelCount()232   int getActiveChannelCount() const { return m_activeChannels.size(); }
233 
234   int getColumnIndexByCurve(TDoubleParam *param) const;
235 
236   double getValue(Channel *channel, double frame) const;
237   int getClosestKeyframe(Channel *channel,
238                          double frame) const;  // -1 if not found
239   Channel *getClosestChannel(double frame, double value) const;
240 
241   void refreshActiveChannels();
242   void refreshData(TXsheet *xsh);  // call this method when the stageObject/Fx
243                                    // structure has been modified
244   void resetAll();
245 
246   void applyShowFilters();
247 
setCurrentStageObject(TStageObject * obj)248   void setCurrentStageObject(TStageObject *obj) { m_currentStageObject = obj; }
getCurrentStageObject()249   TStageObject *getCurrentStageObject() const { return m_currentStageObject; }
250 
251   void setCurrentFx(TFx *fx);
getCurrentFx()252   TFx *getCurrentFx() const { return m_currentFx; }
253 
254   void addParameter(
255       TParam *parameter,
256       const TFilePath
257           &folder);  //!< See function FunctionViewer::addParameter().
258 
getFxHandle()259   TFxHandle *getFxHandle() { return m_fxHandle; }
setFxHandle(TFxHandle * fxHandle)260   void setFxHandle(TFxHandle *fxHandle) { m_fxHandle = fxHandle; }
261 
getObjectHandle()262   TObjectHandle *getObjectHandle() { return m_objectHandle; }
setObjectHandle(TObjectHandle * objectHandle)263   void setObjectHandle(TObjectHandle *objectHandle) {
264     m_objectHandle = objectHandle;
265   }
266 
267 signals:
268 
269   void activeChannelsChanged();
270   void curveSelected(TDoubleParam *);
271   void curveChanged(bool isDragging);
272   void currentChannelChanged(FunctionTreeModel::Channel *);
273 
274 private:
275   void addParameter(ChannelGroup *group, const std::string &prefixString,
276                     const std::wstring &fxId, TParam *param);
277 
278   //! remove channel from m_activeChannels and m_currentChannel
279   void onChannelDestroyed(Channel *channel);
280 
281   //! called when channel status (active/current) has been modified
emitDataChanged(Channel * channel)282   void emitDataChanged(Channel *channel) {
283     QModelIndex index = channel->createIndex();
284     emit dataChanged(index, index);
285     emit activeChannelsChanged();
286   }
287 
emitCurveSelected(TDoubleParam * curve)288   void emitCurveSelected(TDoubleParam *curve) { emit curveSelected(curve); }
289 
emitCurrentChannelChanged(FunctionTreeModel::Channel * channel)290   void emitCurrentChannelChanged(FunctionTreeModel::Channel *channel) {
291     emit currentChannelChanged(channel);
292   }
293 
294   void addChannels(TFx *fx, ChannelGroup *fxItem, TParamContainer *params);
295 
296   // Observers notification functions
297 
298   void onChange(
299       const TParamChange &) override;   // Multiple param notifications ...
300   void onParamChange(bool isDragging);  // ... that get compressed into one
301 
302   // Update functions
303 
304   void refreshStageObjects(TXsheet *xsh);
305   void refreshFxs(TXsheet *xsh);
306   void refreshPlasticDeformations();
307   void addActiveChannels(TreeModel::Item *item);
308 
309 public:
310   ChannelGroup *getStageObjectChannel(int index) const;
311   ChannelGroup *getFxChannel(int index) const;
getStageObjectsChannelCount()312   int getStageObjectsChannelCount() const {
313     return m_stageObjects->getChildCount();
314   }
getFxsChannelCount()315   int getFxsChannelCount() const { return m_fxs->getChildCount(); }
316 };
317 
318 //=============================================================================
319 
320 class DVAPI FxChannelGroup final : public FunctionTreeModel::ChannelGroup {
321 public:
322   TFx *m_fx;
323 
324 public:
325   FxChannelGroup(TFx *fx);
326   ~FxChannelGroup();
327 
328   QString getShortName() const override;
329   QString getLongName() const override;
330 
331   QString getIdName() const override;
332 
getInternalPointer()333   void *getInternalPointer() const override {
334     return static_cast<void *>(m_fx);
335   }
getFx()336   TFx *getFx() const { return m_fx; }
337   QVariant data(int role) const override;
338 
339   void refresh() override;
340 };
341 
342 //=============================================================================
343 
344 class DVAPI StageObjectChannelGroup final
345     : public FunctionTreeModel::ChannelGroup {
346 public:
347   TStageObject *m_stageObject;  //!< (not owned) Referenced stage object
348   FunctionTreeModel::ChannelGroup
349       *m_plasticGroup;  //!< (not owned) Eventual plastic channels group
350 
351 public:
352   StageObjectChannelGroup(TStageObject *pegbar);
353   ~StageObjectChannelGroup();
354 
355   QString getShortName() const override;
356   QString getLongName() const override;
357 
358   QString getIdName() const override;
359 
getInternalPointer()360   void *getInternalPointer() const override {
361     return static_cast<void *>(m_stageObject);
362   }
363 
getStageObject()364   TStageObject *getStageObject() const { return m_stageObject; }
365   QVariant data(int role) const override;
366 };
367 
368 //*****************************************************************************************
369 //    FunctionTreeView  declaration
370 //*****************************************************************************************
371 
372 //! TreeView with stage object and fx channels. controls channel visibility and
373 //! current channel
374 class FunctionTreeView final : public TreeView {
375   Q_OBJECT
376 
377   TFilePath m_scenePath;
378   FunctionTreeModel::Channel *m_clickedItem;
379 
380   FunctionTreeModel::Channel *m_draggingChannel;
381   QPoint m_dragStartPosition;
382   FunctionViewer *m_viewer;
383   //---
384 
385   // set color by using style sheet
386   QColor m_textColor;  // text color (black)
387   Q_PROPERTY(QColor TextColor READ getTextColor WRITE setTextColor)
388 
389   TXsheetHandle *m_xshHandle;
390 
391 public:
392   FunctionTreeView(FunctionViewer *parent);
393 
setCurrentScenePath(TFilePath scenePath)394   void setCurrentScenePath(TFilePath scenePath) { m_scenePath = scenePath; }
395 
396   void openContextMenu(TreeModel::Item *item, const QPoint &globalPos) override;
397 
setTextColor(const QColor & color)398   void setTextColor(const QColor &color) { m_textColor = color; }
getTextColor()399   QColor getTextColor() const { return m_textColor; }
getViewer()400   FunctionViewer *getViewer() { return m_viewer; }
401 
setXsheetHandle(TXsheetHandle * xshHandle)402   void setXsheetHandle(TXsheetHandle *xshHandle) { m_xshHandle = xshHandle; }
getXsheetHandle()403   TXsheetHandle *getXsheetHandle() { return m_xshHandle; }
404 
405 protected:
406   void onClick(TreeModel::Item *item, const QPoint &itemPos,
407                QMouseEvent *e) override;
408 
409   void onMidClick(TreeModel::Item *item, const QPoint &itemPos,
410                   QMouseEvent *e) override;
411 
412   void onDrag(TreeModel::Item *item, const QPoint &itemPos,
413               QMouseEvent *e) override;
414   void onRelease() override;
415 
416   void openContextMenu(FunctionTreeModel::Channel *channel,
417                        const QPoint &globalPos);
418   void openContextMenu(FunctionTreeModel::ChannelGroup *group,
419                        const QPoint &globalPos);
420 
421 public slots:
422 
423   void onActivated(const QModelIndex &index);
424   void updateAll();
425 
426   // show all the animated channels when the scene switched
427   void displayAnimatedChannels();
428 
429 signals:
430 
431   void switchCurrentObject(TStageObject *obj);
432   void switchCurrentFx(TFx *fx);
433 };
434 
435 #endif  // FUNCTIONTREEMODEL_H
436