397 lines
11 KiB
C++
397 lines
11 KiB
C++
|
|
|
|
#ifndef FUNCTIONTREEMODEL_H
|
|
#define FUNCTIONTREEMODEL_H
|
|
|
|
// TnzCore includes
|
|
#include "tcommon.h"
|
|
#include "tdoubleparam.h"
|
|
|
|
// TnzQt includes
|
|
#include "treemodel.h"
|
|
|
|
// Qt includes
|
|
#include <QScrollBar>
|
|
|
|
#undef DVAPI
|
|
#undef DVVAR
|
|
#ifdef TOONZQT_EXPORTS
|
|
#define DVAPI DV_EXPORT_API
|
|
#define DVVAR DV_EXPORT_VAR
|
|
#else
|
|
#define DVAPI DV_IMPORT_API
|
|
#define DVVAR DV_IMPORT_VAR
|
|
#endif
|
|
|
|
//=================================================================
|
|
|
|
// Forward declarations
|
|
|
|
class TStageObject;
|
|
class TFx;
|
|
class TDoubleParam;
|
|
class TXsheet;
|
|
class TParamContainer;
|
|
class TFxHandle;
|
|
class TObjectHandle;
|
|
|
|
class FunctionTreeView;
|
|
class FunctionViewer;
|
|
|
|
//=================================================================
|
|
|
|
//*****************************************************************************************
|
|
// FunctionTreeModel declaration
|
|
//*****************************************************************************************
|
|
|
|
/*!
|
|
\brief The Function Editor's (tree-like) \a model, as in the <I>model-view</I> architecture.
|
|
|
|
\details This class represents the data associated to Toonz's Function Editor panels in a
|
|
view-independent way. The model's purpose is that of representing all \a channels of the
|
|
objects in a scene. A \a channel is here intended as an <I>animatable parameter</I>
|
|
represented by a <I>single real-valued function</I>.
|
|
|
|
Animatable objects are currently subdivided in two main types: <I>stage objects</I>
|
|
(which consist roughly all the objects represented in the \a stage schematic view,
|
|
including cameras, spline curves and pegbars), and \a fxs. Stage objects typically
|
|
feature a uniform channels group structure, whereas each fx type have a different set
|
|
of parameters (and thus channels). Recently, \a column objects can sport an additional
|
|
group of channels, related to Plastic skeleton animations (see TnzExt library).
|
|
*/
|
|
|
|
class FunctionTreeModel : public TreeModel, public TParamObserver
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
/*!
|
|
\brief FunctionTreeModel's abstract base item class, adding the requirement to
|
|
return features visibility data.
|
|
*/
|
|
class Item : public TreeModel::Item
|
|
{
|
|
public:
|
|
Item() {}
|
|
|
|
virtual bool isActive() const = 0;
|
|
virtual bool isAnimated() const = 0;
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
//! The model item representing a channels group.
|
|
class ChannelGroup : public Item
|
|
{
|
|
public:
|
|
enum ShowFilter {
|
|
ShowAllChannels,
|
|
ShowAnimatedChannels
|
|
};
|
|
|
|
private:
|
|
QString m_name;
|
|
ShowFilter m_showFilter;
|
|
|
|
public:
|
|
ChannelGroup(const QString &name = "");
|
|
~ChannelGroup();
|
|
|
|
bool isActive() const;
|
|
bool isAnimated() const;
|
|
|
|
virtual QString getShortName() const { return m_name; }
|
|
virtual QString getLongName() const { return m_name; }
|
|
|
|
virtual QString getIdName() const;
|
|
|
|
void setShowFilter(ShowFilter showFilter);
|
|
ShowFilter getShowFilter() const { return m_showFilter; }
|
|
|
|
void applyShowFilter(); // call this method when a channel changes
|
|
// its animation status
|
|
QVariant data(int role) const;
|
|
|
|
//used in FunctionTreeView::onActivated
|
|
void setChildrenAllActive(bool active);
|
|
|
|
void displayAnimatedChannels();
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
/*!
|
|
\brief The common class representing a \a parameter in the model.
|
|
|
|
\remark This class's concept is different from that of a Channel, as a \a parameter could
|
|
be composed of <I>multiple channels</I>, e.g. like an animated \p RGBA color, which
|
|
has 4 channels.
|
|
*/
|
|
class ParamWrapper
|
|
{
|
|
protected:
|
|
TParamP m_param; //!< The wrapped parameter.
|
|
wstring m_fxId; //!< Fx identifier for m_param's owner, if any.
|
|
|
|
public:
|
|
ParamWrapper(const TParamP ¶m, const wstring &fxId) : m_param(param), m_fxId(fxId) {}
|
|
virtual ~ParamWrapper() {}
|
|
|
|
const wstring &getFxId() const { return m_fxId; }
|
|
|
|
TParamP getParam() const { return m_param; }
|
|
virtual void setParam(const TParamP ¶m) { m_param = param; }
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
//! The model item representing a channel (i.e. a real-valued function).
|
|
class Channel : public ParamWrapper, public Item, public TParamObserver
|
|
{
|
|
FunctionTreeModel *m_model; //!< (\p not \p owned) Reference to the model
|
|
ChannelGroup *m_group; //!< (\p not \p owned) Reference to the enclosing group
|
|
|
|
string m_paramNamePref;
|
|
|
|
bool m_isActive; //!< Whether the channels is active, ie visible
|
|
//!< as a curve and numeric column
|
|
public:
|
|
Channel(FunctionTreeModel *model, TDoubleParam *param,
|
|
string paramNamePrefix = "", wstring fxId = L"");
|
|
~Channel();
|
|
|
|
TDoubleParam *getParam() const { return (TDoubleParam *)m_param.getPointer(); }
|
|
void setParam(const TParamP ¶m);
|
|
|
|
QString getShortName() const;
|
|
QString getLongName() const;
|
|
|
|
//in order to show the expression name in the tooltip
|
|
QString getExprRefName() const;
|
|
|
|
ChannelGroup *getChannelGroup() const { return m_group; }
|
|
void setChannelGroup(ChannelGroup *group) { m_group = group; }
|
|
|
|
QVariant data(int role) const;
|
|
|
|
bool isActive() const { return m_isActive; }
|
|
void setIsActive(bool active);
|
|
|
|
bool isAnimated() const;
|
|
|
|
bool isCurrent() const;
|
|
void setIsCurrent(bool current);
|
|
|
|
bool isHidden() const; // the channel is hidden if it is filtered out
|
|
// by its channelgroup
|
|
void onChange(const TParamChange &);
|
|
|
|
void *getInternalPointer() const;
|
|
};
|
|
|
|
private:
|
|
ChannelGroup *m_stageObjects, //!< Predefined group for stage object channels.
|
|
*m_fxs; //!< Predefined group for fx parameters.
|
|
|
|
std::vector<Channel *> m_activeChannels;
|
|
|
|
Channel *m_currentChannel; //!< (\p not \p owned) Current channel.
|
|
TStageObject *m_currentStageObject; //!< (\p not \p owned) Current stage object.
|
|
TFx *m_currentFx; //!< (\p not \p owned) Current fx.
|
|
|
|
bool m_paramsChanged;
|
|
|
|
TFxHandle *m_fxHandle;
|
|
TObjectHandle *m_objectHandle;
|
|
|
|
public:
|
|
FunctionTreeModel(FunctionTreeView *parent = 0); // BUT! Should be view-independent! :o
|
|
~FunctionTreeModel();
|
|
|
|
Channel *getCurrentChannel() const
|
|
{
|
|
return m_currentChannel;
|
|
}
|
|
|
|
Channel *getActiveChannel(int index) const;
|
|
int getActiveChannelCount() const
|
|
{
|
|
return m_activeChannels.size();
|
|
}
|
|
|
|
int getColumnIndexByCurve(TDoubleParam *param) const;
|
|
|
|
double getValue(Channel *channel, double frame) const;
|
|
int getClosestKeyframe(Channel *channel, double frame) const; // -1 if not found
|
|
Channel *getClosestChannel(double frame, double value) const;
|
|
|
|
void refreshActiveChannels();
|
|
void refreshData(TXsheet *xsh); // call this method when the stageObject/Fx structure
|
|
// has been modified
|
|
void resetAll();
|
|
|
|
void applyShowFilters();
|
|
|
|
void setCurrentStageObject(TStageObject *obj)
|
|
{
|
|
m_currentStageObject = obj;
|
|
}
|
|
TStageObject *getCurrentStageObject() const
|
|
{
|
|
return m_currentStageObject;
|
|
}
|
|
|
|
void setCurrentFx(TFx *fx);
|
|
TFx *getCurrentFx() const
|
|
{
|
|
return m_currentFx;
|
|
}
|
|
|
|
void addParameter(TParam *parameter,
|
|
const TFilePath &folder); //!< See function FunctionViewer::addParameter().
|
|
|
|
TFxHandle *getFxHandle() { return m_fxHandle; }
|
|
void setFxHandle(TFxHandle *fxHandle) { m_fxHandle = fxHandle; }
|
|
|
|
TObjectHandle *getObjectHandle() { return m_objectHandle; }
|
|
void setObjectHandle(TObjectHandle *objectHandle) { m_objectHandle = objectHandle; }
|
|
|
|
signals:
|
|
|
|
void activeChannelsChanged();
|
|
void curveSelected(TDoubleParam *);
|
|
void curveChanged(bool isDragging);
|
|
void currentChannelChanged(FunctionTreeModel::Channel *);
|
|
|
|
private:
|
|
void addParameter(ChannelGroup *group,
|
|
const std::string &prefixString,
|
|
const std::wstring &fxId,
|
|
TParam *param);
|
|
|
|
//! remove channel from m_activeChannels and m_currentChannel
|
|
void onChannelDestroyed(Channel *channel);
|
|
|
|
//! called when channel status (active/current) has been modified
|
|
void emitDataChanged(Channel *channel)
|
|
{
|
|
QModelIndex index = channel->createIndex();
|
|
emit dataChanged(index, index);
|
|
emit activeChannelsChanged();
|
|
}
|
|
|
|
void emitCurveSelected(TDoubleParam *curve)
|
|
{
|
|
emit curveSelected(curve);
|
|
}
|
|
|
|
void emitCurrentChannelChanged(FunctionTreeModel::Channel *channel)
|
|
{
|
|
emit currentChannelChanged(channel);
|
|
}
|
|
|
|
void addChannels(TFx *fx, ChannelGroup *fxItem, TParamContainer *params);
|
|
|
|
// Observers notification functions
|
|
|
|
void onChange(const TParamChange &); // Multiple param notifications ...
|
|
void onParamChange(bool isDragging); // ... that get compressed into one
|
|
|
|
// Update functions
|
|
|
|
void refreshStageObjects(TXsheet *xsh);
|
|
void refreshFxs(TXsheet *xsh);
|
|
void refreshPlasticDeformations();
|
|
void addActiveChannels(TreeModel::Item *item);
|
|
|
|
public:
|
|
ChannelGroup *getStageObjectChannel(int index) const;
|
|
ChannelGroup *getFxChannel(int index) const;
|
|
int getStageObjectsChannelCount() const { return m_stageObjects->getChildCount(); }
|
|
int getFxsChannelCount() const { return m_fxs->getChildCount(); }
|
|
};
|
|
|
|
//=============================================================================
|
|
|
|
class FxChannelGroup : public FunctionTreeModel::ChannelGroup
|
|
{
|
|
public:
|
|
TFx *m_fx;
|
|
|
|
public:
|
|
FxChannelGroup(TFx *fx);
|
|
~FxChannelGroup();
|
|
|
|
QString getShortName() const;
|
|
QString getLongName() const;
|
|
|
|
QString getIdName() const;
|
|
|
|
void *getInternalPointer() const { return static_cast<void *>(m_fx); }
|
|
TFx *getFx() const { return m_fx; }
|
|
QVariant data(int role) const;
|
|
|
|
void refresh();
|
|
};
|
|
|
|
//*****************************************************************************************
|
|
// FunctionTreeView declaration
|
|
//*****************************************************************************************
|
|
|
|
//! TreeView with stage object and fx channels. controls channel visibility and
|
|
//! current channel
|
|
class FunctionTreeView : public TreeView
|
|
{
|
|
Q_OBJECT
|
|
|
|
TFilePath m_scenePath;
|
|
FunctionTreeModel::Channel *m_clickedItem;
|
|
|
|
FunctionTreeModel::Channel *m_draggingChannel;
|
|
QPoint m_dragStartPosition;
|
|
//---
|
|
|
|
//set color by using style sheet
|
|
QColor m_textColor; //text color (black)
|
|
QColor m_currentTextColor; //current item text color (red)
|
|
Q_PROPERTY(QColor TextColor READ getTextColor WRITE setTextColor)
|
|
Q_PROPERTY(QColor CurrentTextColor READ getCurrentTextColor WRITE setCurrentTextColor)
|
|
|
|
public:
|
|
FunctionTreeView(FunctionViewer *parent);
|
|
|
|
void setCurrentScenePath(TFilePath scenePath) { m_scenePath = scenePath; }
|
|
|
|
void openContextMenu(TreeModel::Item *item, const QPoint &globalPos);
|
|
|
|
void setTextColor(const QColor &color) { m_textColor = color; }
|
|
QColor getTextColor() const { return m_textColor; }
|
|
void setCurrentTextColor(const QColor &color) { m_currentTextColor = color; }
|
|
QColor getCurrentTextColor() const { return m_currentTextColor; }
|
|
|
|
protected:
|
|
void onClick(TreeModel::Item *item, const QPoint &itemPos, QMouseEvent *e);
|
|
|
|
void onMidClick(TreeModel::Item *item, const QPoint &itemPos, QMouseEvent *e);
|
|
|
|
void onDrag(TreeModel::Item *item, const QPoint &itemPos, QMouseEvent *e);
|
|
void onRelease();
|
|
|
|
void openContextMenu(FunctionTreeModel::Channel *channel, const QPoint &globalPos);
|
|
void openContextMenu(FunctionTreeModel::ChannelGroup *group, const QPoint &globalPos);
|
|
|
|
public slots:
|
|
|
|
void onActivated(const QModelIndex &index);
|
|
void updateAll();
|
|
|
|
//show all the animated channels when the scene switched
|
|
void displayAnimatedChannels();
|
|
|
|
signals:
|
|
|
|
void switchCurrentObject(TStageObject *obj);
|
|
void switchCurrentFx(TFx *fx);
|
|
};
|
|
|
|
#endif // FUNCTIONTREEMODEL_H
|