tahoma2d/toonz/sources/include/toonzqt/functiontreeviewer.h

438 lines
13 KiB
C
Raw Normal View History

2016-05-17 03:04:11 +12:00
#pragma once
2016-03-19 06:57:51 +13:00
#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;
2020-04-17 19:02:53 +12:00
class TXsheetHandle;
2016-03-19 06:57:51 +13:00
class FunctionTreeView;
class FunctionViewer;
//=================================================================
//*****************************************************************************************
// FunctionTreeModel declaration
//*****************************************************************************************
/*!
2016-06-15 18:43:10 +12:00
\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>
2016-03-19 06:57:51 +13:00
represented by a <I>single real-valued function</I>.
2016-06-15 18:43:10 +12:00
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).
2016-03-19 06:57:51 +13:00
*/
2020-04-17 19:02:53 +12:00
class DVAPI FunctionTreeModel final : public TreeModel, public TParamObserver {
2016-06-15 18:43:10 +12:00
Q_OBJECT
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
/*!
\brief FunctionTreeModel's abstract base item class, adding the requirement
to
return features visibility data.
*/
class Item : public TreeModel::Item {
public:
Item() {}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
virtual bool isActive() const = 0;
virtual bool isAnimated() const = 0;
2020-04-17 19:02:53 +12:00
virtual bool isIgnored() const = 0;
2016-06-15 18:43:10 +12:00
};
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//----------------------------------------------------------------------------------
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//! The model item representing a channels group.
class ChannelGroup : public Item {
public:
enum ShowFilter { ShowAllChannels, ShowAnimatedChannels };
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
private:
QString m_name;
ShowFilter m_showFilter;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
public:
ChannelGroup(const QString &name = "");
~ChannelGroup();
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
bool isActive() const override;
bool isAnimated() const override;
2020-04-17 19:02:53 +12:00
bool isIgnored() const override;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
virtual QString getShortName() const { return m_name; }
virtual QString getLongName() const { return m_name; }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
virtual QString getIdName() const;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void setShowFilter(ShowFilter showFilter);
ShowFilter getShowFilter() const { return m_showFilter; }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void applyShowFilter(); // call this method when a channel changes
// its animation status
2016-06-19 20:06:29 +12:00
QVariant data(int role) const override;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// used in FunctionTreeView::onActivated
void setChildrenAllActive(bool active);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void displayAnimatedChannels();
};
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//----------------------------------------------------------------------------------
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
/*!
\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.
std::wstring m_fxId; //!< Fx identifier for m_param's owner, if any.
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
public:
ParamWrapper(const TParamP &param, const std::wstring &fxId)
: m_param(param), m_fxId(fxId) {}
virtual ~ParamWrapper() {}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
const std::wstring &getFxId() const { return m_fxId; }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TParamP getParam() const { return m_param; }
virtual void setParam(const TParamP &param) { m_param = param; }
};
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//----------------------------------------------------------------------------------
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//! The model item representing a channel (i.e. a real-valued function).
2020-04-17 19:02:53 +12:00
class DVAPI Channel final : public ParamWrapper,
public Item,
public TParamObserver {
2016-06-15 18:43:10 +12:00
FunctionTreeModel *m_model; //!< (\p not \p owned) Reference to the model
ChannelGroup
*m_group; //!< (\p not \p owned) Reference to the enclosing group
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
std::string m_paramNamePref;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
bool m_isActive; //!< Whether the channels is active, ie visible
//!< as a curve and numeric column
public:
Channel(FunctionTreeModel *model, TDoubleParam *param,
std::string paramNamePrefix = "", std::wstring fxId = L"");
~Channel();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TDoubleParam *getParam() const {
return (TDoubleParam *)m_param.getPointer();
}
2016-06-19 20:06:29 +12:00
void setParam(const TParamP &param) override;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
QString getShortName() const;
QString getLongName() const;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// in order to show the expression name in the tooltip
QString getExprRefName() const;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
ChannelGroup *getChannelGroup() const { return m_group; }
void setChannelGroup(ChannelGroup *group) { m_group = group; }
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
QVariant data(int role) const override;
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
bool isActive() const override { return m_isActive; }
2016-06-15 18:43:10 +12:00
void setIsActive(bool active);
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
bool isAnimated() const override;
2020-04-17 19:02:53 +12:00
bool isIgnored() const override;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
bool isCurrent() const;
void setIsCurrent(bool current);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
bool isHidden() const; // the channel is hidden if it is filtered out
// by its channelgroup
2016-06-19 20:06:29 +12:00
void onChange(const TParamChange &) override;
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void *getInternalPointer() const override;
2016-06-15 18:43:10 +12:00
};
2016-03-19 06:57:51 +13:00
private:
2016-06-15 18:43:10 +12:00
ChannelGroup
*m_stageObjects, //!< Predefined group for stage object channels.
*m_fxs; //!< Predefined group for fx parameters.
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
std::vector<Channel *> m_activeChannels;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
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.
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
bool m_paramsChanged;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TFxHandle *m_fxHandle;
TObjectHandle *m_objectHandle;
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
FunctionTreeModel(
FunctionTreeView *parent = 0); // BUT! Should be view-independent! :o
~FunctionTreeModel();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
Channel *getCurrentChannel() const { return m_currentChannel; }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
Channel *getActiveChannel(int index) const;
int getActiveChannelCount() const { return m_activeChannels.size(); }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int getColumnIndexByCurve(TDoubleParam *param) const;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
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;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void refreshActiveChannels();
void refreshData(TXsheet *xsh); // call this method when the stageObject/Fx
// structure has been modified
2016-06-15 18:43:10 +12:00
void resetAll();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void applyShowFilters();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void setCurrentStageObject(TStageObject *obj) { m_currentStageObject = obj; }
TStageObject *getCurrentStageObject() const { return m_currentStageObject; }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void setCurrentFx(TFx *fx);
TFx *getCurrentFx() const { return m_currentFx; }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void addParameter(
TParam *parameter,
const TFilePath
&folder); //!< See function FunctionViewer::addParameter().
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TFxHandle *getFxHandle() { return m_fxHandle; }
void setFxHandle(TFxHandle *fxHandle) { m_fxHandle = fxHandle; }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TObjectHandle *getObjectHandle() { return m_objectHandle; }
void setObjectHandle(TObjectHandle *objectHandle) {
m_objectHandle = objectHandle;
}
2016-03-19 06:57:51 +13:00
signals:
2016-06-15 18:43:10 +12:00
void activeChannelsChanged();
void curveSelected(TDoubleParam *);
void curveChanged(bool isDragging);
void currentChannelChanged(FunctionTreeModel::Channel *);
2016-03-19 06:57:51 +13:00
private:
2016-06-15 18:43:10 +12:00
void addParameter(ChannelGroup *group, const std::string &prefixString,
const std::wstring &fxId, TParam *param);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//! remove channel from m_activeChannels and m_currentChannel
void onChannelDestroyed(Channel *channel);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//! called when channel status (active/current) has been modified
void emitDataChanged(Channel *channel) {
QModelIndex index = channel->createIndex();
emit dataChanged(index, index);
emit activeChannelsChanged();
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void emitCurveSelected(TDoubleParam *curve) { emit curveSelected(curve); }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void emitCurrentChannelChanged(FunctionTreeModel::Channel *channel) {
emit currentChannelChanged(channel);
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void addChannels(TFx *fx, ChannelGroup *fxItem, TParamContainer *params);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Observers notification functions
2016-03-19 06:57:51 +13:00
2016-06-20 14:23:05 +12:00
void onChange(
const TParamChange &) override; // Multiple param notifications ...
2016-06-15 18:43:10 +12:00
void onParamChange(bool isDragging); // ... that get compressed into one
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Update functions
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void refreshStageObjects(TXsheet *xsh);
void refreshFxs(TXsheet *xsh);
void refreshPlasticDeformations();
void addActiveChannels(TreeModel::Item *item);
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
ChannelGroup *getStageObjectChannel(int index) const;
ChannelGroup *getFxChannel(int index) const;
int getStageObjectsChannelCount() const {
return m_stageObjects->getChildCount();
}
int getFxsChannelCount() const { return m_fxs->getChildCount(); }
2016-03-19 06:57:51 +13:00
};
//=============================================================================
2020-04-17 19:02:53 +12:00
class DVAPI FxChannelGroup final : public FunctionTreeModel::ChannelGroup{
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
TFx *m_fx;
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
FxChannelGroup(TFx *fx);
~FxChannelGroup();
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
QString getShortName() const override;
QString getLongName() const override;
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
QString getIdName() const override;
2016-03-19 06:57:51 +13:00
2016-06-20 14:23:05 +12:00
void *getInternalPointer() const override {
return static_cast<void *>(m_fx);
}
2016-06-15 18:43:10 +12:00
TFx *getFx() const { return m_fx; }
2016-06-19 20:06:29 +12:00
QVariant data(int role) const override;
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void refresh() override;
2016-03-19 06:57:51 +13:00
};
2019-07-01 19:42:08 +12:00
//=============================================================================
2020-04-17 19:02:53 +12:00
class DVAPI StageObjectChannelGroup final
: public FunctionTreeModel::ChannelGroup {
2019-07-01 19:42:08 +12:00
public:
TStageObject *m_stageObject; //!< (not owned) Referenced stage object
FunctionTreeModel::ChannelGroup
*m_plasticGroup; //!< (not owned) Eventual plastic channels group
public:
StageObjectChannelGroup(TStageObject *pegbar);
~StageObjectChannelGroup();
QString getShortName() const override;
QString getLongName() const override;
QString getIdName() const override;
void *getInternalPointer() const override {
return static_cast<void *>(m_stageObject);
}
TStageObject *getStageObject() const { return m_stageObject; }
QVariant data(int role) const override;
};
2016-03-19 06:57:51 +13:00
//*****************************************************************************************
// FunctionTreeView declaration
//*****************************************************************************************
//! TreeView with stage object and fx channels. controls channel visibility and
//! current channel
class FunctionTreeView final : public TreeView {
2016-06-15 18:43:10 +12:00
Q_OBJECT
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TFilePath m_scenePath;
FunctionTreeModel::Channel *m_clickedItem;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
FunctionTreeModel::Channel *m_draggingChannel;
QPoint m_dragStartPosition;
FunctionViewer *m_viewer;
2016-06-15 18:43:10 +12:00
//---
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// set color by using style sheet
QColor m_textColor; // text color (black)
2016-06-15 18:43:10 +12:00
Q_PROPERTY(QColor TextColor READ getTextColor WRITE setTextColor)
2016-03-19 06:57:51 +13:00
2020-04-17 19:02:53 +12:00
TXsheetHandle *m_xshHandle;
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
FunctionTreeView(FunctionViewer *parent);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void setCurrentScenePath(TFilePath scenePath) { m_scenePath = scenePath; }
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void openContextMenu(TreeModel::Item *item, const QPoint &globalPos) override;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void setTextColor(const QColor &color) { m_textColor = color; }
QColor getTextColor() const { return m_textColor; }
FunctionViewer *getViewer() { return m_viewer; }
2016-03-19 06:57:51 +13:00
2020-04-17 19:02:53 +12:00
void setXsheetHandle(TXsheetHandle *xshHandle) { m_xshHandle = xshHandle; }
TXsheetHandle *getXsheetHandle() { return m_xshHandle; }
2016-03-19 06:57:51 +13:00
protected:
2016-06-20 14:23:05 +12:00
void onClick(TreeModel::Item *item, const QPoint &itemPos,
QMouseEvent *e) override;
2016-03-19 06:57:51 +13:00
2016-06-20 14:23:05 +12:00
void onMidClick(TreeModel::Item *item, const QPoint &itemPos,
QMouseEvent *e) override;
2016-03-19 06:57:51 +13:00
2016-06-20 14:23:05 +12:00
void onDrag(TreeModel::Item *item, const QPoint &itemPos,
QMouseEvent *e) override;
2016-06-19 20:06:29 +12:00
void onRelease() override;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void openContextMenu(FunctionTreeModel::Channel *channel,
const QPoint &globalPos);
void openContextMenu(FunctionTreeModel::ChannelGroup *group,
const QPoint &globalPos);
2020-05-23 09:31:30 +12:00
void mouseDoubleClickEvent(QMouseEvent *) override;
2016-03-19 06:57:51 +13:00
public slots:
2016-06-15 18:43:10 +12:00
void onActivated(const QModelIndex &index);
void updateAll();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// show all the animated channels when the scene switched
void displayAnimatedChannels();
2016-03-19 06:57:51 +13:00
signals:
2016-06-15 18:43:10 +12:00
void switchCurrentObject(TStageObject *obj);
void switchCurrentFx(TFx *fx);
2020-05-23 09:31:30 +12:00
void fit();
2016-03-19 06:57:51 +13:00
};
2016-06-15 18:43:10 +12:00
#endif // FUNCTIONTREEMODEL_H