tahoma2d/toonz/sources/toonzqt/fxsettings.cpp
Jeremy Bullock af90cdedbe
UI update and Icons from Konero (#126)
* add multi arc mockup

* implement mutli arc

* add join and smooth option

* reset multiarc and arc when deactivated

* create self loop if the last point is the same as the first

* make join option in multiarc consistent with tape tool

* fix a bug where thickness don't affect mutliarc in vector level

* remove join option in geometric tool

* stop mutliarc after closing shape

* double click can also end multi arc

* fix a bug where multiArc will produce buggy stroke

* fix a bug where geometric tools is not deactivated

* add multiArc shortcut

* rewrite multiArc

* revert changes to tvectorimage

* add undo data for multiArc

* Paste as Copy Command for XSheet

* Remove unneeded code

* Bug fix

* prevent guide lines from jumping around in MultiArc

* make stroke color consistent in MultiArc

* remove color in MultiArc's undo data

* make color consistent in MultiArc with previous version

* Fix single image raster levels

* fix compilation error

* fix a bug where multiArc might generate bugged stroke

* Remove ICONV dep (#3304)

* fix crash on saving studio palette

* Move to Paste Special Menu

* Don't Set Fixed Width if Docking a Floating Panel

* Update how_to_build_win.md

New draft of pr for requested changes to windows build instructions.

* fix geometric tool multiarc smooth option

* fix level saving failure

* fix wrong warning after saving palette

* fix a bug where moving a control point while holding alt has unintended result

* fix travis-install (#3389)

* Fix assert debug crash in flipconsole.cpp

Fix crash when using the viewer controls in the console (debug)

* Redraw Audio Waveform

Fills the waveform rather than outlines it.

* Update .gitignore

* fix undo data when drawing arc and mutliarc

* fix overwriting raster drawing palette (#3387)

* mode sensitive fx settings

* Create New Style Command Button (#3394)

* Create New Style Command Button

This PR creates a new button in the pallette editor that creates a new style.  Button is large and easy access for a faster and easier workflow.  Original code developed by Turtletooth for Tahoma.  Given permission to develop within Openoonz.

Co-Authored-By: Jeremy Bullock <turtletooth@users.noreply.github.com>

* Update paletteviewergui.cpp

Made changes to the PR per request by Shun.

* Fixed a space within the code that wasn't suppose to be there.

Co-authored-by: Jeremy Bullock <turtletooth@users.noreply.github.com>

* tahoma license (#3396)

* new style button optional

* fix loading pegbars (removing updateKeyframes)

* periodic random expression

* add fx in linear color space
this commit is based on source for the ComposeAdd plugin fx by DWANGO Co., Ltd.
in dwango_opentoonz_plugins and opentoonz_plugin_utility repositories.

* fractal noise iwa fx

* skip unnecessary icon invalidation

* fix frame range fill with tablet

* stop function editor to open by dbl clicking key

* Expanding the radius of the rotation handle.

This just changes when the cursor transforms into the rotation tool.

(cherry picked from commit 7722ae989bbdc6aa5cb48df7a4c08bae1fe6ea39)

* fix vector img patern stroke style

* Update Stylesheets

- Support the new icon sizes
- XSheet and Timeline significantly redesigned
- Lots of margin fixes and refactoring
- Remove deprecated icons, as some icons are moved into binary
- New Light theme

* New Icons

- Redesigns almost every icon as symbolic
- Adds icons for most commands

* Add Option for Icon Themes

- Adds option for icon themes
- Removes useless label from Preferences category list

* Update Icon Functions

- Adds themePath() boolean
- Adds function for recoloring black pixels in pixmaps to any color
- Rebuilds createQIcon to use fromTheme() and recolorPixmap()
- Removes createQIconOnOff as it seemed to be a rarely used duplicate of createQIcon
- Removes a grey horizontal line drawn above the console play bar in the viewer

* Set Default Icon Theme and Paths

- Sets search paths for icons for use with QIcon::fromTheme()
- Sets default start icon theme on first install
- Sets flag for displaying icons in menus, so we can selectively hide them

* Set Icons for Commands

- Sets icons for the commands
- Hides icons being displayed in menus as most icons are 20x20, they will look blurry when shrunk to 16x16
- Selectively allows icons to display for Tools in menus

* Change Icon Sizes, General Fixes and Stylesheet Additions

- Change icon sizes to new size
- Remove margin around FX Editor window
- Remove white line under color sliders in Style Editor
- Make keyframe icons uniform and color stylable in the stylesheets
- Removes deprecated stylesheet strings
- Redesign GUI for palette list view
- Make tree list header sort row stylable
- Remove black lines from scrollbars in New Project window
- Remove margin around combobox in Level Strip
- Alter how some lines are drawn in the Timeline to fix some alpha issues
- Make conditional fixed onion skin and normal onion skin dots contrast more against a light background area to make sure they have good visibility
- Make text always viewable in the FPS field in console bar
- Increase size of radio buttons in Cleanup Settings
- Increase size of switches in motion path nodes
- Remove unessesary "Layer" label in Timeline and other rects
- Various colors made stylable in the stylesheets; palette numpad and selection frame, cleanup settings border, scene cast folder path, schematic lines, ruler, xsheet lines, keyframes, cell input box and more
- Moves some external stylesheet icons into binary

* Make TPanelTitleBar Icon States Stylable

- Makes icon states for TPanelTitleBar buttons stylable in stylesheets

* Travis Fixes

* Swap Startup Popup Logos

They were in the wrong folders

* Revert "Swap Startup Popup Logos"

This reverts commit 815908a9f3e725f48507dab8a2270bdfa045649d.

* Fix Startup Popup Logo

It wasn't switching

* Feedback Changes

- Change render visualization to clapboard
- Fix text contrast on levels in XSheet

* Make Cell Selection More Clear

* Darken Light Theme and Tint Empty Cell Selection

* Fix missing icons

* Fix memo button

* Bring back colors

* Hide Motion Tab

* Fix Play Range Area (Light)

Make play range area more visible

* Vector Column Color

Co-authored-by: pojienie <pojienie@gmail.com>
Co-authored-by: rim <11380091+rozhuk-im@users.noreply.github.com>
Co-authored-by: shun-iwasawa <shun.iwasawa@ghibli.jp>
Co-authored-by: Rodney <rodney.baker@gmail.com>
Co-authored-by: DoctorRyan <65507211+DoctorRyan@users.noreply.github.com>
Co-authored-by: shun-iwasawa <shun-iwasawa@users.noreply.github.com>
Co-authored-by: Kite <konero@users.noreply.github.com>
Co-authored-by: Jeremy Bullock <turtletooth@users.noreply.github.com>
Co-authored-by: DoctorRyan <doctorryan1969.gmail.com>
2020-08-31 12:51:22 -06:00

1637 lines
57 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "toonzqt/fxsettings.h"
#include "toonzqt/gutil.h"
#include "toonzqt/keyframenavigator.h"
#include "toonzqt/dvdialog.h"
#include "toonzqt/fxhistogramrender.h"
#include "toonzqt/histogram.h"
#include "tmacrofx.h"
#include "tstream.h"
#include "tparamcontainer.h"
#include "tspectrumparam.h"
#include "tfxattributes.h"
#include "toutputproperties.h"
#include "pluginhost.h"
#include "tenv.h"
#include "tsystem.h"
#include "docklayout.h"
#include "toonz/tcamera.h"
#include "toonz/toonzfolders.h"
#include "toonz/tcolumnfx.h"
#include "toonz/tscenehandle.h"
#include "toonz/txshlevelhandle.h"
#include "toonz/tobjecthandle.h"
#include "toonz/scenefx.h"
#include "toonz/toonzscene.h"
#include "toonz/sceneproperties.h"
#include "toonz/preferences.h"
#include "tw/stringtable.h"
#include <QVBoxLayout>
#include <QToolBar>
#include <QIcon>
#include <QAction>
#include <QStackedWidget>
#include <QLabel>
#include <QMap>
#include <QPainter>
#include <QCheckBox>
#include <QPushButton>
#include <QDesktopServices>
#include <QUrl>
using namespace DVGui;
namespace {
TFxP getCurrentFx(const TFxP &currentFx, std::wstring actualId) {
if (currentFx->getFxId() == actualId) return currentFx;
int i;
for (i = 0; i < currentFx->getInputPortCount(); i++) {
TFxP fx = getCurrentFx(currentFx->getInputPort(i)->getFx(), actualId);
if (fx.getPointer()) return fx;
}
return 0;
}
bool hasEmptyInputPort(const TFxP &currentFx) {
if (!currentFx.getPointer()) return true;
if (currentFx->getInputPortCount() == 0) return false;
return hasEmptyInputPort(currentFx->getInputPort(0)->getFx());
}
/*
TFxP cloneInputPort(const TFxP &currentFx)
{
int i;
for (i=0; i<getInputPortCount(); ++i)
{
TFx *inputFx = sceneFx->getInputPort(i)->getFx();
if(inputFx)
{
if(TLevelColumnFx* affFx = dynamic_cast<TLevelColumnFx*
>(inputFx))
currentFx->getInputPort(i)->setFx(inputFx);
else
currentFx->getInputPort(i)->setFx(cloneInputPort());
}
TFxPort *port = getInputPort(i);
if (port->getFx())
fx->connect(getInputPortName(i),
cloneInputPort(port->getFx()));
}
void setLevelFxInputPort(const TFxP &currentFx, const TFxP &sceneFx)
{
for (int i=0; i<sceneFx->getInputPortCount(); ++i)
{
TFx *inputFx = sceneFx->getInputPort(i)->getFx();
if(inputFx)
{
if(TLevelColumnFx* affFx = dynamic_cast<TLevelColumnFx*
>(inputFx))
currentFx->getInputPort(i)->setFx(inputFx);
else
setLevelFxInputPort(currentFx->getInputPort(i)->getFx(),
inputFx);
}
}
}
*/
} // namespace
//=============================================================================
// ParamViewer
//-----------------------------------------------------------------------------
ParamsPage::ParamsPage(QWidget *parent, ParamViewer *paramViewer)
: QFrame(parent)
, m_paramViewer(paramViewer)
, m_horizontalLayout(NULL)
, m_groupLayout(NULL) {
m_fxHistogramRender = new FxHistogramRender();
setFrameStyle(QFrame::StyledPanel);
m_mainLayout = new QGridLayout(this);
m_mainLayout->setMargin(12);
m_mainLayout->setVerticalSpacing(10);
m_mainLayout->setHorizontalSpacing(5);
m_mainLayout->setColumnStretch(0, 0);
m_mainLayout->setColumnStretch(1, 1);
setLayout(m_mainLayout);
}
//-----------------------------------------------------------------------------
ParamsPage::~ParamsPage() {}
//-----------------------------------------------------------------------------
void ParamsPage::setPageField(TIStream &is, const TFxP &fx, bool isVertical) {
// m_horizontalLayout dovrebbe essere stato inizializzato prima di entrare nel
// metodo, per sicurezza verifico.
if (isVertical == false && !m_horizontalLayout) {
m_horizontalLayout = new QHBoxLayout();
m_horizontalLayout->setMargin(0);
m_horizontalLayout->setSpacing(5);
}
/*--
* HBoxLayoutを挿入するとき、最初のパラメータ名はGridlayoutのColumn0に入れるため
* --*/
bool isFirstParamInRow = true;
while (!is.matchEndTag()) {
std::string tagName;
if (!is.matchTag(tagName)) throw TException("expected tag");
if (tagName == "control") {
/*--- 設定ファイルからインタフェースの桁数を決める (PairSliderのみ実装。)
* ---*/
int decimals = 0;
std::string decimalsStr = is.getTagAttribute("decimals");
if (decimalsStr != "") {
decimals = QString::fromStdString(decimalsStr).toInt();
}
std::string name;
is >> name;
is.matchEndTag();
/*-- Layout設定名とFxParameterの名前が一致するものを取得 --*/
TParamP param = fx->getParams()->getParam(name);
if (param) {
std::string paramName = fx->getFxType() + "." + name;
QString str =
QString::fromStdWString(TStringTable::translate(paramName));
ParamField *field = ParamField::create(this, str, param);
if (field) {
if (decimals) field->setPrecision(decimals);
m_fields.push_back(field);
/*-- hboxタグに挟まれているとき --*/
if (isVertical == false) {
assert(m_horizontalLayout);
QLabel *label = new QLabel(str, this);
label->setObjectName("FxSettingsLabel");
if (isFirstParamInRow) {
int currentRow = m_mainLayout->rowCount();
m_mainLayout->addWidget(label, currentRow, 0,
Qt::AlignRight | Qt::AlignVCenter);
isFirstParamInRow = false;
} else
m_horizontalLayout->addWidget(label, 0,
Qt::AlignRight | Qt::AlignVCenter);
m_horizontalLayout->addWidget(field);
m_horizontalLayout->addSpacing(10);
} else {
int currentRow = m_mainLayout->rowCount();
QLabel *label = new QLabel(str, this);
label->setObjectName("FxSettingsLabel");
m_mainLayout->addWidget(label, currentRow, 0,
Qt::AlignRight | Qt::AlignVCenter);
m_mainLayout->addWidget(field, currentRow, 1);
}
connect(field, SIGNAL(currentParamChanged()), m_paramViewer,
SIGNAL(currentFxParamChanged()));
connect(field, SIGNAL(actualParamChanged()), m_paramViewer,
SIGNAL(actualFxParamChanged()));
connect(field, SIGNAL(paramKeyToggle()), m_paramViewer,
SIGNAL(paramKeyChanged()));
}
}
} else if (tagName == "label") {
std::string name;
is >> name;
is.matchEndTag();
QString str;
if (isVertical == false) {
assert(m_horizontalLayout);
m_horizontalLayout->addWidget(new QLabel(str.fromStdString(name)));
} else {
int currentRow = m_mainLayout->rowCount();
m_mainLayout->addWidget(new QLabel(str.fromStdString(name)), currentRow,
0, 1, 2);
}
} else if (tagName == "separator") {
// <separator/> o <separator label="xxx"/>
std::string label = is.getTagAttribute("label");
QString str;
Separator *sep = new Separator(str.fromStdString(label), this);
int currentRow = m_mainLayout->rowCount();
m_mainLayout->addWidget(sep, currentRow, 0, 1, 2);
m_mainLayout->setRowStretch(currentRow, 0);
} else if (tagName == "histogram") {
Histogram *histogram = new Histogram();
m_fxHistogramRender->setHistograms(histogram->getHistograms());
if (isVertical == false) {
assert(m_horizontalLayout);
m_horizontalLayout->addWidget(histogram);
} else {
int currentRow = m_mainLayout->rowCount();
m_mainLayout->addWidget(histogram, currentRow, 0, 1, 2);
}
} else if (tagName == "test") {
// <test/>
// box->add(new WidgetBox(new TestSeparator(page)));
} else if (tagName == "hbox") {
int currentRow = m_mainLayout->rowCount();
m_horizontalLayout = new QHBoxLayout();
m_horizontalLayout->setMargin(0);
m_horizontalLayout->setSpacing(5);
setPageField(is, fx, false);
m_mainLayout->addLayout(m_horizontalLayout, currentRow, 1, 1, 2);
} else if (tagName == "vbox") {
int shrink = 0;
std::string shrinkStr = is.getTagAttribute("shrink");
std::string modeSensitiveStr = is.getTagAttribute("modeSensitive");
if (shrinkStr != "" || modeSensitiveStr != "") {
QWidget *tmpWidget;
if (shrinkStr != "") {
tmpWidget = new QWidget(this);
shrink = QString::fromStdString(shrinkStr).toInt();
std::string label = is.getTagAttribute("label");
QCheckBox *checkBox = new QCheckBox(this);
QHBoxLayout *sepLay = new QHBoxLayout();
sepLay->setMargin(0);
sepLay->setSpacing(5);
sepLay->addWidget(checkBox, 0);
sepLay->addWidget(new Separator(QString::fromStdString(label), this),
1);
int currentRow = m_mainLayout->rowCount();
m_mainLayout->addLayout(sepLay, currentRow, 0, 1, 2);
m_mainLayout->setRowStretch(currentRow, 0);
//--- signal-slot connection
connect(checkBox, SIGNAL(toggled(bool)), tmpWidget,
SLOT(setVisible(bool)));
checkBox->setChecked(shrink == 1);
tmpWidget->setVisible(shrink == 1);
} else { // modeSensitiveStr != ""
QList<int> modes;
QStringList modeListStr =
QString::fromStdString(is.getTagAttribute("mode"))
.split(',', QString::SkipEmptyParts);
for (QString modeNum : modeListStr) modes.push_back(modeNum.toInt());
// find the mode combobox
ModeChangerParamField *modeChanger = nullptr;
for (int r = 0; r < m_mainLayout->rowCount(); r++) {
QLayoutItem *li = m_mainLayout->itemAtPosition(r, 1);
if (!li || !li->widget()) continue;
ModeChangerParamField *field =
dynamic_cast<ModeChangerParamField *>(li->widget());
if (!field ||
field->getParamName().toStdString() != modeSensitiveStr)
continue;
modeChanger = field;
break;
}
assert(modeChanger);
tmpWidget = new ModeSensitiveBox(this, modeChanger, modes);
}
int currentRow = m_mainLayout->rowCount();
QGridLayout *keepMainLay = m_mainLayout;
// temporary switch the layout
m_mainLayout = new QGridLayout();
m_mainLayout->setMargin(0);
m_mainLayout->setVerticalSpacing(10);
m_mainLayout->setHorizontalSpacing(5);
m_mainLayout->setColumnStretch(0, 0);
m_mainLayout->setColumnStretch(1, 1);
setPageField(is, fx, true);
tmpWidget->setLayout(m_mainLayout);
// turn back the layout
m_mainLayout = keepMainLay;
m_mainLayout->addWidget(tmpWidget, currentRow, 0, 1, 2);
} else
setPageField(is, fx, true);
}
/*-- PixelParamFieldがつあるとき、一方のRGB値を他方にコピーするボタン --*/
else if (tagName == "rgb_link_button") {
/*-- リンクさせたいパラメータを2つ得る --*/
std::string name1, name2;
is >> name1;
is >> name2;
is.matchEndTag();
/*-- 既に作ってあるGUIを探索し、対応するつを得て格納 --*/
PixelParamField *ppf1 = 0;
PixelParamField *ppf2 = 0;
for (int r = 0; r < m_mainLayout->rowCount(); r++) {
QLayoutItem *li = m_mainLayout->itemAtPosition(r, 1);
if (!li) continue;
QWidget *w = li->widget();
if (!w) continue;
ParamField *pf = dynamic_cast<ParamField *>(w);
if (pf) {
PixelParamField *ppf = dynamic_cast<PixelParamField *>(pf);
if (ppf) {
if (ppf1 == 0 && ppf->getParamName().toStdString() == name1)
ppf1 = ppf;
if (ppf2 == 0 && ppf->getParamName().toStdString() == name2)
ppf2 = ppf;
}
}
}
if (ppf1 == 0 || ppf2 == 0) continue;
/*-- ボタンのラベルのため 翻訳する --*/
std::string paramName1 = fx->getFxType() + "." + name1;
std::string paramName2 = fx->getFxType() + "." + name2;
QString str1 =
QString::fromStdWString(TStringTable::translate(paramName1));
QString str2 =
QString::fromStdWString(TStringTable::translate(paramName2));
RgbLinkButtons *linkBut =
new RgbLinkButtons(str1, str2, this, ppf1, ppf2);
int currentRow = m_mainLayout->rowCount();
m_mainLayout->addWidget(linkBut, currentRow, 1,
Qt::AlignLeft | Qt::AlignVCenter);
}
/*-- チェックボックスによって他のインタフェースを表示/非表示させる ---*/
else if (tagName == "visibleToggle") {
BoolParamField *controller_bpf = 0;
QList<QWidget *> on_items;
QList<QWidget *> off_items;
while (!is.matchEndTag()) {
std::string tagName;
if (!is.matchTag(tagName)) throw TException("expected tag");
if (tagName ==
"controller" || /*-- 表示をコントロールするチェックボックス --*/
tagName == "on" || /*-- ONのとき表示されるインタフェース --*/
tagName == "off") /*-- OFFのとき表示されるインタフェース --*/
{
std::string name;
is >> name;
is.matchEndTag();
for (int r = 0; r < m_mainLayout->rowCount(); r++) {
QLayoutItem *li = m_mainLayout->itemAtPosition(r, 1);
if (!li) continue;
QWidget *w = li->widget();
if (!w) continue;
ParamField *pf = dynamic_cast<ParamField *>(w);
if (pf) {
if (pf->getParamName().toStdString() == name) {
if (tagName == "controller")
controller_bpf = dynamic_cast<BoolParamField *>(pf);
else if (tagName == "on") {
on_items.push_back(w);
on_items.push_back(
m_mainLayout->itemAtPosition(r, 0)->widget());
} else if (tagName == "off") {
off_items.push_back(w);
off_items.push_back(
m_mainLayout->itemAtPosition(r, 0)->widget());
}
}
}
/*-- 入れ子のLayoutも段階探す --*/
else {
QGridLayout *gridLay = dynamic_cast<QGridLayout *>(w->layout());
if (!gridLay) continue;
for (int r_s = 0; r_s < gridLay->rowCount(); r_s++) {
QLayoutItem *li_s = gridLay->itemAtPosition(r_s, 1);
if (!li_s) continue;
ParamField *pf_s = dynamic_cast<ParamField *>(li_s->widget());
if (pf_s) {
if (pf_s->getParamName().toStdString() == name) {
if (tagName == "controller")
controller_bpf = dynamic_cast<BoolParamField *>(pf_s);
else if (tagName == "on") {
on_items.push_back(pf_s);
on_items.push_back(
gridLay->itemAtPosition(r_s, 0)->widget());
} else if (tagName == "off") {
off_items.push_back(pf_s);
off_items.push_back(
gridLay->itemAtPosition(r_s, 0)->widget());
}
}
}
}
}
}
} else
throw TException("unexpected tag " + tagName);
}
/*-- 表示コントロールをconnect --*/
if (controller_bpf) {
/*-- ラベルとWidgetを両方表示/非表示 --*/
for (int i = 0; i < on_items.size(); i++) {
connect(controller_bpf, SIGNAL(toggled(bool)), on_items[i],
SLOT(setVisible(bool)));
on_items[i]->hide();
}
for (int i = 0; i < off_items.size(); i++) {
connect(controller_bpf, SIGNAL(toggled(bool)), off_items[i],
SLOT(setHidden(bool)));
off_items[i]->show();
}
} else
std::cout << "controller_bpf NOT found!" << std::endl;
} else
throw TException("unexpected tag " + tagName);
}
if (isVertical == false && m_horizontalLayout) {
m_horizontalLayout->addStretch(1);
}
}
//-----------------------------------------------------------------------------
void ParamsPage::setPageSpace() {
if (m_fields.count() != 0) {
QWidget *spaceWidget = new QWidget();
int currentRow = m_mainLayout->rowCount();
m_mainLayout->addWidget(spaceWidget, currentRow, 0, 1, 2);
for (int i = 0; i < currentRow; i++) m_mainLayout->setRowStretch(i, 0);
m_mainLayout->setRowStretch(currentRow, 1);
}
}
//-----------------------------------------------------------------------------
void ParamsPage::beginGroup(const char *name) {
m_groupLayout = new QGridLayout();
QGroupBox *group = new QGroupBox(QString::fromUtf8(name), this);
group->setLayout(m_groupLayout);
m_mainLayout->addWidget(group, m_mainLayout->rowCount(), 0, 1, 2);
}
void ParamsPage::endGroup() { m_groupLayout = NULL; }
void ParamsPage::addWidget(QWidget *field, bool isVertical) {
QLabel *label = NULL;
ParamField *pf = qobject_cast<ParamField *>(field);
if (pf) {
label = new QLabel(pf->getUIName(), this);
label->setObjectName("FxSettingsLabel");
if (!pf->getDescription().isEmpty())
label->setToolTip(pf->getDescription());
}
if (isVertical) {
if (m_groupLayout) {
int row = m_groupLayout->rowCount();
if (label)
m_groupLayout->addWidget(label, row, 0,
Qt::AlignRight | Qt::AlignVCenter);
m_groupLayout->addWidget(field, row, 1);
} else {
int row = m_mainLayout->rowCount();
if (label)
m_mainLayout->addWidget(label, row, 0,
Qt::AlignRight | Qt::AlignVCenter);
m_mainLayout->addWidget(field, row, 1);
}
} else {
if (!m_horizontalLayout) {
m_horizontalLayout = new QHBoxLayout();
m_horizontalLayout->setMargin(0);
m_horizontalLayout->setSpacing(5);
}
m_horizontalLayout->addWidget(field);
}
}
#define TOONZ_DEFINE_NEW_COMPONENT(NAME, MAKE) \
QWidget *ParamsPage::NAME(TFx *fx, const char *name) { \
TParamP param = fx->getParams()->getParam(name); \
if (!param) return NULL; \
QString const paramName = \
QString::fromStdString(fx->getFxType() + "." + name); \
ParamField *field = MAKE(this, paramName, param); \
if (!field) return NULL; \
m_fields.push_back(field); \
connect(field, SIGNAL(currentParamChanged()), m_paramViewer, \
SIGNAL(currentFxParamChanged())); \
connect(field, SIGNAL(actualParamChanged()), m_paramViewer, \
SIGNAL(actualFxParamChanged())); \
connect(field, SIGNAL(paramKeyToggle()), m_paramViewer, \
SIGNAL(paramKeyChanged())); \
return field; \
}
TOONZ_DEFINE_NEW_COMPONENT(newParamField, ParamField::create);
TOONZ_DEFINE_NEW_COMPONENT(newLineEdit, make_lineedit);
TOONZ_DEFINE_NEW_COMPONENT(newSlider, make_slider);
TOONZ_DEFINE_NEW_COMPONENT(newSpinBox, make_spinbox);
TOONZ_DEFINE_NEW_COMPONENT(newCheckBox, make_checkbox);
TOONZ_DEFINE_NEW_COMPONENT(newRadioButton, make_radiobutton);
TOONZ_DEFINE_NEW_COMPONENT(newComboBox, make_combobox);
#undef TOONZ_DEFINE_NEW_COMPONENT
//-----------------------------------------------------------------------------
void ParamsPage::setFx(const TFxP &currentFx, const TFxP &actualFx, int frame) {
assert(currentFx);
assert(actualFx);
for (int i = 0; i < (int)m_fields.size(); i++) {
ParamField *field = m_fields[i];
QString fieldName = field->getParamName();
TFxP fx = getCurrentFx(currentFx, actualFx->getFxId());
assert(fx.getPointer());
TParamP currentParam =
currentFx->getParams()->getParam(fieldName.toStdString());
TParamP actualParam =
actualFx->getParams()->getParam(fieldName.toStdString());
assert(currentParam);
assert(actualParam);
field->setParam(currentParam, actualParam, frame);
}
if (actualFx->getInputPortCount() > 0)
m_fxHistogramRender->computeHistogram(actualFx->getInputPort(0)->getFx(),
frame);
}
//-----------------------------------------------------------------------------
void ParamsPage::setPointValue(int index, const TPointD &p) {
if (0 <= index && index < (int)m_fields.size())
m_fields[index]->setPointValue(p);
}
//-----------------------------------------------------------------------------
void ParamsPage::update(int frame) {
int i;
for (i = 0; i < (int)m_fields.size(); i++) {
ParamField *field = m_fields[i];
field->update(frame);
}
}
//-----------------------------------------------------------------------------
namespace {
QSize getItemSize(QLayoutItem *item) {
// layout case
QHBoxLayout *hLay = dynamic_cast<QHBoxLayout *>(item->layout());
if (hLay) {
int tmpWidth = 0, tmpHeight = 0;
for (int c = 0; c < hLay->count(); c++) {
QLayoutItem *subItem = hLay->itemAt(c);
if (!subItem) continue;
QSize subItemSize = getItemSize(subItem);
tmpWidth += subItemSize.width();
if (tmpHeight < subItemSize.height()) tmpHeight = subItemSize.height();
}
tmpWidth += (hLay->count() - 1) * 5;
return QSize(tmpWidth, tmpHeight);
}
ParamField *pF = dynamic_cast<ParamField *>(item->widget());
if (pF) return pF->getPreferedSize();
Separator *sep = dynamic_cast<Separator *>(item->widget());
if (sep) return QSize(0, 16);
Histogram *histo = dynamic_cast<Histogram *>(item->widget());
if (histo) return QSize(278, 162);
RgbLinkButtons *linkBut = dynamic_cast<RgbLinkButtons *>(item->widget());
if (linkBut) return QSize(0, 21);
return QSize();
}
void updateMaximumPageSize(QGridLayout *layout, int &maxLabelWidth,
int &maxWidgetWidth, int &fieldsHeight) {
/*-- Label側の横幅の最大値を得る --*/
for (int r = 0; r < layout->rowCount(); r++) {
/*-- アイテムが無ければ次の行へ --*/
if (!layout->itemAtPosition(r, 0)) continue;
/*-- ラベルの横幅を得て、最大値を更新していく --*/
QLabel *label =
dynamic_cast<QLabel *>(layout->itemAtPosition(r, 0)->widget());
QGroupBox *gBox =
dynamic_cast<QGroupBox *>(layout->itemAtPosition(r, 0)->widget());
if (label) {
int tmpWidth = label->fontMetrics().width(label->text());
if (maxLabelWidth < tmpWidth) maxLabelWidth = tmpWidth;
}
/*-- PlugInFxのGroupパラメータのサイズ --*/
else if (gBox) {
QGridLayout *gridLay = dynamic_cast<QGridLayout *>(gBox->layout());
if (gridLay) {
updateMaximumPageSize(gridLay, maxLabelWidth, maxWidgetWidth,
fieldsHeight);
/*-- GroupBoxのマージン --*/
maxLabelWidth += 10;
maxWidgetWidth += 10;
fieldsHeight += 20;
}
}
}
/*-- Widget側の最適な縦サイズおよび横幅の最大値を得る --*/
QMap<int, int> heightsByMode;
int maxModeHeight = 0;
for (int r = 0; r < layout->rowCount(); r++) {
/*-- Column1にある可能性のあるものParamField, Histogram, Layout,
* RgbLinkButtons --*/
QLayoutItem *item = layout->itemAtPosition(r, 1);
if (!item) continue;
ModeSensitiveBox *box = dynamic_cast<ModeSensitiveBox *>(item->widget());
if (box) {
// if (box->isHidden()) continue;
QGridLayout *innerLay = dynamic_cast<QGridLayout *>(box->layout());
if (!innerLay) continue;
int tmpHeight = 0;
updateMaximumPageSize(innerLay, maxLabelWidth, maxWidgetWidth, tmpHeight);
for (int mode : box->modes()) {
heightsByMode[mode] += tmpHeight;
maxModeHeight = std::max(maxModeHeight, heightsByMode[mode]);
}
// attempt to align the label column
innerLay->setColumnMinimumWidth(0, maxLabelWidth);
continue;
}
QSize itemSize = getItemSize(item);
if (maxWidgetWidth < itemSize.width()) maxWidgetWidth = itemSize.width();
fieldsHeight += itemSize.height();
}
if (maxModeHeight > 0) fieldsHeight += maxModeHeight;
if (layout->rowCount() > 1) fieldsHeight += (layout->rowCount() - 1) * 10;
}
}; // namespace
QSize ParamsPage::getPreferredSize() {
int maxLabelWidth = 0;
int maxWidgetWidth = 0;
int fieldsHeight = 0;
updateMaximumPageSize(m_mainLayout, maxLabelWidth, maxWidgetWidth,
fieldsHeight);
return QSize(maxLabelWidth + maxWidgetWidth +
m_mainLayout->horizontalSpacing() +
2 * m_mainLayout->margin(),
fieldsHeight + 2 * m_mainLayout->margin() +
31 /* spacing for the swatch */);
}
//=============================================================================
// ParamsPageSet
//-----------------------------------------------------------------------------
#if QT_VERSION >= 0x050500
ParamsPageSet::ParamsPageSet(QWidget *parent, Qt::WindowFlags flags)
#else
ParamsPageSet::ParamsPageSet(QWidget *parent, Qt::WFlags flags)
#endif
: QWidget(parent, flags)
, m_preferredSize(0, 0)
, m_helpFilePath("")
, m_helpCommand("") {
// TabBar
m_tabBar = new TabBar(this);
// This widget is used to set the background color of the tabBar
// using the styleSheet and to draw the two lines on the bottom size.
m_tabBarContainer = new TabBarContainter(this);
m_pagesList = new QStackedWidget(this);
m_helpButton = new QPushButton(tr(""), this);
m_helpButton->setIconSize(QSize(20, 20));
m_helpButton->setIcon(createQIcon("help"));
m_helpButton->setFixedWidth(28);
m_helpButton->setToolTip(tr("View help page"));
m_parent = dynamic_cast<ParamViewer *>(parent);
m_pageFxIndexTable.clear();
m_tabBar->setDrawBase(false);
m_tabBar->setObjectName("FxSettingsTabBar");
m_helpButton->setFixedHeight(20);
m_helpButton->setObjectName("FxSettingsHelpButton");
m_helpButton->setFocusPolicy(Qt::NoFocus);
//----layout
QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->setMargin(0);
mainLayout->setSpacing(0);
{
QHBoxLayout *hLayout = new QHBoxLayout();
hLayout->setMargin(0);
hLayout->addSpacing(0);
{
hLayout->addWidget(m_tabBar);
hLayout->addStretch(1);
hLayout->addWidget(m_helpButton);
}
m_tabBarContainer->setLayout(hLayout);
mainLayout->addWidget(m_tabBarContainer);
mainLayout->addWidget(m_pagesList);
mainLayout->addWidget(new Separator("", this), 0);
}
setLayout(mainLayout);
connect(m_tabBar, SIGNAL(currentChanged(int)), this, SLOT(setPage(int)));
m_helpButton->hide();
}
//-----------------------------------------------------------------------------
ParamsPageSet::~ParamsPageSet() {}
//-----------------------------------------------------------------------------
void ParamsPageSet::setPage(int index) {
if (m_tabBar->count() == 0 || m_pagesList->count() == 0) return;
assert(index >= 0 && index < m_pagesList->count());
m_pagesList->setCurrentIndex(index);
}
//-----------------------------------------------------------------------------
void ParamsPageSet::setFx(const TFxP &currentFx, const TFxP &actualFx,
int frame) {
TMacroFx *currentFxMacro = dynamic_cast<TMacroFx *>(currentFx.getPointer());
if (currentFxMacro) {
TMacroFx *actualFxMacro = dynamic_cast<TMacroFx *>(actualFx.getPointer());
assert(actualFxMacro);
const std::vector<TFxP> &currentFxMacroFxs = currentFxMacro->getFxs();
const std::vector<TFxP> &actualFxMacroFxs = actualFxMacro->getFxs();
assert(currentFxMacroFxs.size() == actualFxMacroFxs.size());
for (int i = 0; i < m_pagesList->count(); i++) {
ParamsPage *page = getParamsPage(i);
if (!page || !m_pageFxIndexTable.contains(page)) continue;
int index = m_pageFxIndexTable[page];
page->setFx(currentFxMacroFxs[index], actualFxMacroFxs[index], frame);
}
} else {
for (int i = 0; i < m_pagesList->count(); i++) {
ParamsPage *page = getParamsPage(i);
if (!page) continue;
page->setFx(currentFx, actualFx, frame);
}
}
}
//-----------------------------------------------------------------------------
void ParamsPageSet::updatePage(int frame, bool onlyParam) {
if (!m_pagesList) return;
int i;
for (i = 0; i < m_pagesList->count(); i++) {
ParamsPage *page = getParamsPage(i);
if (!page) continue;
page->update(frame);
if (!onlyParam) page->getFxHistogramRender()->invalidateFrame(frame);
}
}
//-----------------------------------------------------------------------------
void ParamsPageSet::setScene(ToonzScene *scene) {
if (!m_pagesList) return;
int i;
for (i = 0; i < m_pagesList->count(); i++) {
ParamsPage *page = getParamsPage(i);
if (!page) continue;
page->getFxHistogramRender()->setScene(scene);
}
}
//-----------------------------------------------------------------------------
void ParamsPageSet::setIsCameraViewMode(bool isCameraViewMode) {
if (!m_pagesList) return;
int i;
for (i = 0; i < m_pagesList->count(); i++) {
ParamsPage *page = getParamsPage(i);
if (!page) continue;
page->getFxHistogramRender()->setIsCameraViewMode(isCameraViewMode);
}
}
//-----------------------------------------------------------------------------
ParamsPage *ParamsPageSet::createParamsPage() {
return new ParamsPage(this, m_parent);
}
void ParamsPageSet::addParamsPage(ParamsPage *page, const char *name) {
/*-- このFxで最大サイズのページに合わせてダイアログをリサイズ --*/
QSize pagePreferredSize = page->getPreferredSize();
m_preferredSize = m_preferredSize.expandedTo(
pagePreferredSize + QSize(m_tabBarContainer->height() + 2,
2)); /*-- 2は上下左右のマージン --*/
QScrollArea *pane = new QScrollArea(this);
pane->setWidgetResizable(true);
pane->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
pane->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
pane->setWidget(page);
m_tabBar->addSimpleTab(QString::fromUtf8(name));
m_pagesList->addWidget(pane);
}
//-----------------------------------------------------------------------------
void ParamsPageSet::createControls(const TFxP &fx, int index) {
if (TMacroFx *macroFx = dynamic_cast<TMacroFx *>(fx.getPointer())) {
const std::vector<TFxP> &fxs = macroFx->getFxs();
for (int i = 0; i < (int)fxs.size(); i++) createControls(fxs[i], i);
return;
}
if (RasterFxPluginHost *plugin =
dynamic_cast<RasterFxPluginHost *>(fx.getPointer())) {
plugin->build(this);
std::string url = plugin->getUrl();
if (!url.empty()) {
connect(m_helpButton, SIGNAL(pressed()), this, SLOT(openHelpUrl()));
m_helpButton->show();
m_helpUrl = url;
}
return;
}
TFilePath fp = ToonzFolder::getProfileFolder() + "layouts" + "fxs" +
(fx->getFxType() + ".xml");
TIStream is(fp);
if (!is) return;
if (fx->getParams()->getParamCount()) {
try {
std::string tagName;
if (!is.matchTag(tagName) || tagName != "fxlayout")
throw TException("expected <fxlayout>");
m_helpFilePath = is.getTagAttribute("help_file");
if (m_helpFilePath != "") {
connect(m_helpButton, SIGNAL(pressed()), this, SLOT(openHelpFile()));
m_helpButton->show();
/*-- pdfファイルのページ指定など、引数が必要な場合の追加fragmentを取得
* --*/
m_helpCommand = is.getTagAttribute("help_command");
}
while (!is.matchEndTag()) createPage(is, fx, index);
} catch (TException const &) {
}
}
// else createEmptyPage();
}
//-----------------------------------------------------------------------------
ParamsPage *ParamsPageSet::getCurrentParamsPage() const {
QScrollArea *scrollAreaPage =
dynamic_cast<QScrollArea *>(m_pagesList->currentWidget());
assert(scrollAreaPage);
return dynamic_cast<ParamsPage *>(scrollAreaPage->widget());
}
//-----------------------------------------------------------------------------
ParamsPage *ParamsPageSet::getParamsPage(int index) const {
QScrollArea *scrollAreaPage =
dynamic_cast<QScrollArea *>(m_pagesList->widget(index));
assert(scrollAreaPage);
return dynamic_cast<ParamsPage *>(scrollAreaPage->widget());
}
//-----------------------------------------------------------------------------
void ParamsPageSet::createPage(TIStream &is, const TFxP &fx, int index) {
std::string tagName;
if (!is.matchTag(tagName) || tagName != "page")
throw TException("expected <page>");
std::string pageName = is.getTagAttribute("name");
if (pageName == "") pageName = "page";
ParamsPage *paramsPage = new ParamsPage(this, m_parent);
paramsPage->setPage(is, fx);
connect(paramsPage, SIGNAL(preferredPageSizeChanged()), this,
SLOT(recomputePreferredSize()));
/*-- このFxで最大サイズのページに合わせてダイアログをリサイズ --*/
QSize pagePreferredSize = paramsPage->getPreferredSize();
m_preferredSize = m_preferredSize.expandedTo(
pagePreferredSize + QSize(m_tabBarContainer->height() + 2,
2)); /*-- 2は上下左右のマージン --*/
QScrollArea *scrollAreaPage = new QScrollArea(this);
scrollAreaPage->setWidgetResizable(true);
scrollAreaPage->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollAreaPage->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollAreaPage->setWidget(paramsPage);
QString str;
m_tabBar->addSimpleTab(str.fromStdString(pageName));
m_pagesList->addWidget(scrollAreaPage);
if (index >= 0) m_pageFxIndexTable[paramsPage] = index;
}
//-----------------------------------------------------------------------------
void ParamsPageSet::recomputePreferredSize() {
QSize newSize(0, 0);
for (int i = 0; i < m_pagesList->count(); i++) {
QScrollArea *area = dynamic_cast<QScrollArea *>(m_pagesList->widget(i));
if (!area) continue;
ParamsPage *page = dynamic_cast<ParamsPage *>(area->widget());
if (!page) continue;
QSize pagePreferredSize = page->getPreferredSize();
newSize = newSize.expandedTo(pagePreferredSize +
QSize(m_tabBarContainer->height() + 2, 2));
}
if (!newSize.isEmpty()) {
m_preferredSize = newSize;
// resize the parent FxSettings
m_parent->notifyPreferredSizeChanged(m_preferredSize + QSize(2, 50));
}
}
//-----------------------------------------------------------------------------
/* TODO: Webサイト内のヘルプに対応すべきか検討 2016.02.01 shun_iwasawa */
void ParamsPageSet::openHelpFile() {
if (m_helpFilePath == "") return;
// if (m_helpCommand != "")
// commandString += m_helpCommand + " ";
// Get UI language as set in "Preferences"
QString currentLanguage = Preferences::instance()->getCurrentLanguage();
std::string helpDocLang = currentLanguage.toStdString();
// Assume associated language subdir exists
TFilePath helpFp = TEnv::getStuffDir() + "doc" + helpDocLang + m_helpFilePath;
// Verify subdir exists; if not, default to standard doc dir
if (!TFileStatus(helpFp).doesExist()) {
helpFp = TEnv::getStuffDir() + "doc" + m_helpFilePath;
}
// commandString +=
// QString::fromStdWString(helpFp.getWideString()).toStdString();
// QString command = QString::fromStdString(m_helpFilePath);
// system(commandString.c_str());
// QProcess process;
// process.start(command);
QDesktopServices::openUrl(
QUrl::fromLocalFile(QString::fromStdWString(helpFp.getWideString())));
}
void ParamsPageSet::openHelpUrl() {
QDesktopServices::openUrl(QUrl(QString(m_helpUrl.c_str())));
}
//=============================================================================
// ParamViewer
//-----------------------------------------------------------------------------
#if QT_VERSION >= 0x050500
ParamViewer::ParamViewer(QWidget *parent, Qt::WindowFlags flags)
#else
ParamViewer::ParamViewer(QWidget *parent, Qt::WFlags flags)
#endif
: QFrame(parent, flags), m_fx(0) {
m_tablePageSet = new QStackedWidget(this);
m_tablePageSet->addWidget(new QWidget());
/*-- SwatchViewerを表示/非表示するボタン --*/
QPushButton *showSwatchButton = new QPushButton("", this);
QLabel *swatchLabel = new QLabel(tr("Swatch Viewer"), this);
swatchLabel->setObjectName("TitleTxtLabel");
showSwatchButton->setObjectName("menuToggleButton");
showSwatchButton->setFixedSize(15, 15);
showSwatchButton->setIcon(createQIcon("menu_toggle"));
showSwatchButton->setCheckable(true);
showSwatchButton->setChecked(false);
showSwatchButton->setFocusPolicy(Qt::NoFocus);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->setMargin(0);
mainLayout->setSpacing(0);
{
mainLayout->addWidget(m_tablePageSet, 1);
QHBoxLayout *showPreviewButtonLayout = new QHBoxLayout(this);
showPreviewButtonLayout->setMargin(3);
showPreviewButtonLayout->setSpacing(3);
{
showPreviewButtonLayout->addWidget(showSwatchButton, 0);
showPreviewButtonLayout->addWidget(swatchLabel, 0);
showPreviewButtonLayout->addStretch(1);
}
mainLayout->addLayout(showPreviewButtonLayout, 0);
}
setLayout(mainLayout);
connect(showSwatchButton, SIGNAL(toggled(bool)), this,
SIGNAL(showSwatchButtonToggled(bool)));
}
//-----------------------------------------------------------------------------
ParamViewer::~ParamViewer() {}
//-----------------------------------------------------------------------------
void ParamViewer::setFx(const TFxP &currentFx, const TFxP &actualFx, int frame,
ToonzScene *scene) {
if (!actualFx) {
m_tablePageSet->setCurrentIndex(0);
return;
}
std::string name = actualFx->getFxType();
if (name == "macroFx") {
TMacroFx *macroFx = dynamic_cast<TMacroFx *>(currentFx.getPointer());
if (macroFx) name = macroFx->getMacroFxType();
}
int currentIndex = -1;
QMap<std::string, int>::iterator it;
it = m_tableFxIndex.find(name);
if (it == m_tableFxIndex.end()) {
ParamsPageSet *pageSet = new ParamsPageSet(this);
currentIndex = m_tablePageSet->addWidget(pageSet);
m_tableFxIndex[name] = currentIndex;
pageSet->createControls(actualFx);
} else
currentIndex = it.value();
assert(currentIndex >= 0);
m_tablePageSet->setCurrentIndex(currentIndex);
getCurrentPageSet()->setScene(scene);
if (m_fx != currentFx) {
getCurrentPageSet()->setFx(currentFx, actualFx, frame);
if (m_actualFx != actualFx) {
m_actualFx = actualFx;
QSize pageViewerPreferredSize =
getCurrentPageSet()->getPreferredSize() + QSize(2, 50);
emit preferredSizeChanged(pageViewerPreferredSize);
}
}
}
//-----------------------------------------------------------------------------
void ParamViewer::setScene(ToonzScene *scene) {
ParamsPageSet *paramsPageSet = getCurrentPageSet();
if (!paramsPageSet) return;
paramsPageSet->setScene(scene);
}
//-----------------------------------------------------------------------------
void ParamViewer::setIsCameraViewMode(bool isCameraViewMode) {
ParamsPageSet *paramsPageSet = getCurrentPageSet();
if (!paramsPageSet) return;
paramsPageSet->setIsCameraViewMode(isCameraViewMode);
}
//-----------------------------------------------------------------------------
void ParamViewer::update(int frame, bool onlyParam) {
ParamsPageSet *paramsPageSet = getCurrentPageSet();
if (!paramsPageSet) return;
paramsPageSet->updatePage(frame, onlyParam);
}
//-----------------------------------------------------------------------------
void ParamViewer::setPointValue(int index, const TPointD &p) {
// Search the index-th param among all pages
ParamsPageSet *pageSet = getCurrentPageSet();
ParamsPage *page = 0;
for (int i = 0; i < pageSet->getParamsPageCount(); ++i) {
page = pageSet->getParamsPage(i);
int paramsCount = page->m_fields.count();
if (index <= paramsCount) break;
index -= paramsCount;
}
if (page) page->setPointValue(index, p);
}
//-----------------------------------------------------------------------------
ParamsPageSet *ParamViewer::getCurrentPageSet() const {
return dynamic_cast<ParamsPageSet *>(m_tablePageSet->currentWidget());
}
//=============================================================================
// FxSettings
//-----------------------------------------------------------------------------
FxSettings::FxSettings(QWidget *parent, const TPixel32 &checkCol1,
const TPixel32 &checkCol2)
: QSplitter(Qt::Vertical, parent)
, m_frameHandle(0)
, m_fxHandle(0)
, m_xsheetHandle(0)
, m_sceneHandle(0)
, m_levelHandle(0)
, m_objectHandle(0)
, m_checkCol1(checkCol1)
, m_checkCol2(checkCol2)
, m_isCameraModeView(false)
, m_container_height(184)
, m_container_width(390) {
// param viewer
m_paramViewer = new ParamViewer(this);
// swatch
QWidget *swatchContainer = new QWidget(this);
m_viewer = new SwatchViewer(swatchContainer);
setWhiteBg();
createToolBar();
m_paramViewer->setMinimumHeight(50);
swatchContainer->setSizePolicy(QSizePolicy::MinimumExpanding,
QSizePolicy::MinimumExpanding);
//---layout
addWidget(m_paramViewer);
QVBoxLayout *swatchLayout = new QVBoxLayout(swatchContainer);
swatchLayout->setMargin(0);
swatchLayout->setSpacing(0);
{
swatchLayout->addWidget(m_viewer, 0, Qt::AlignHCenter);
QHBoxLayout *toolBarLayout = new QHBoxLayout(swatchContainer);
{
toolBarLayout->addWidget(m_toolBar, 0,
Qt::AlignHCenter | Qt::AlignBottom);
}
swatchLayout->addLayout(toolBarLayout);
}
swatchContainer->setLayout(swatchLayout);
addWidget(swatchContainer);
//---signal-slot connections
bool ret = true;
ret = ret && connect(m_paramViewer, SIGNAL(currentFxParamChanged()),
SLOT(updateViewer()));
ret = ret &&
connect(m_viewer, SIGNAL(pointPositionChanged(int, const TPointD &)),
SLOT(onPointChanged(int, const TPointD &)));
ret = ret && connect(m_paramViewer, SIGNAL(preferredSizeChanged(QSize)), this,
SLOT(onPreferredSizeChanged(QSize)));
ret = ret && connect(m_paramViewer, SIGNAL(showSwatchButtonToggled(bool)),
this, SLOT(onShowSwatchButtonToggled(bool)));
assert(ret);
swatchContainer->hide();
// Swatch updates should happen only at the end of a separator resize op.
setStretchFactor(0, 1);
setStretchFactor(1, 0);
setOpaqueResize(false);
}
//-----------------------------------------------------------------------------
FxSettings::~FxSettings() {}
//-----------------------------------------------------------------------------
void FxSettings::setFxHandle(TFxHandle *fxHandle) {
m_fxHandle = fxHandle;
m_keyframeNavigator->setFxHandle(m_fxHandle);
ParamField::setFxHandle(m_fxHandle);
}
//-----------------------------------------------------------------------------
void FxSettings::setFrameHandle(TFrameHandle *frameHandle) {
m_frameHandle = frameHandle;
m_keyframeNavigator->setFrameHandle(m_frameHandle);
m_frameNavigator->setFrameHandle(m_frameHandle);
}
//-----------------------------------------------------------------------------
void FxSettings::setXsheetHandle(TXsheetHandle *xsheetHandle) {
m_xsheetHandle = xsheetHandle;
}
//-----------------------------------------------------------------------------
void FxSettings::setSceneHandle(TSceneHandle *sceneHandle) {
m_sceneHandle = sceneHandle;
setCurrentScene();
}
//-----------------------------------------------------------------------------
void FxSettings::setLevelHandle(TXshLevelHandle *levelHandle) {
m_levelHandle = levelHandle;
}
//-----------------------------------------------------------------------------
void FxSettings::setObjectHandle(TObjectHandle *objectHandle) {
m_objectHandle = objectHandle;
}
//-----------------------------------------------------------------------------
void FxSettings::createToolBar() {
m_toolBar = new QToolBar(this);
m_toolBar->setMovable(false);
m_toolBar->setFixedHeight(24);
m_toolBar->setIconSize(QSize(20, 20));
m_toolBar->setObjectName("MediumPaddingToolBar");
// m_toolBar->setSizePolicy(QSizePolicy::MinimumExpanding,
// QSizePolicy::MinimumExpanding);
// View mode
QActionGroup *viewModeActGroup = new QActionGroup(m_toolBar);
viewModeActGroup->setExclusive(false);
// camera
QIcon camera = createQIcon("camera");
QAction *cameraAct = new QAction(camera, tr("&Camera Preview"), m_toolBar);
cameraAct->setCheckable(true);
viewModeActGroup->addAction(cameraAct);
m_toolBar->addAction(cameraAct);
// preview
QIcon preview = createQIcon("preview");
QAction *previewAct = new QAction(preview, tr("&Preview"), m_toolBar);
previewAct->setCheckable(true);
viewModeActGroup->addAction(previewAct);
m_toolBar->addAction(previewAct);
connect(viewModeActGroup, SIGNAL(triggered(QAction *)),
SLOT(onViewModeChanged(QAction *)));
m_toolBar->addSeparator();
QActionGroup *viewModeGroup = new QActionGroup(m_toolBar);
viewModeGroup->setExclusive(true);
QAction *whiteBg = new QAction(createQIcon("preview_white"),
tr("&White Background"), m_toolBar);
whiteBg->setCheckable(true);
whiteBg->setChecked(true);
viewModeGroup->addAction(whiteBg);
connect(whiteBg, SIGNAL(triggered()), this, SLOT(setWhiteBg()));
m_toolBar->addAction(whiteBg);
QAction *blackBg = new QAction(createQIcon("preview_black"),
tr("&Black Background"), m_toolBar);
blackBg->setCheckable(true);
viewModeGroup->addAction(blackBg);
connect(blackBg, SIGNAL(triggered()), this, SLOT(setBlackBg()));
m_toolBar->addAction(blackBg);
m_checkboardBg = new QAction(createQIcon("preview_checkboard"),
tr("&Checkered Background"), m_toolBar);
m_checkboardBg->setCheckable(true);
viewModeGroup->addAction(m_checkboardBg);
connect(m_checkboardBg, SIGNAL(triggered()), this, SLOT(setCheckboardBg()));
m_toolBar->addAction(m_checkboardBg);
m_toolBar->addSeparator();
m_keyframeNavigator = new FxKeyframeNavigator(m_toolBar);
m_toolBar->addWidget(m_keyframeNavigator);
m_toolBar->addSeparator();
m_frameNavigator = new FrameNavigator(m_toolBar);
m_frameNavigator->setFrameHandle(m_frameHandle);
m_toolBar->addWidget(m_frameNavigator);
}
//-----------------------------------------------------------------------------
void FxSettings::setFx(const TFxP &currentFx, const TFxP &actualFx) {
// disconnecting from the fxChanged() signals avoid useless and dangerous
// updates!!!
if (m_fxHandle)
disconnect(m_fxHandle, SIGNAL(fxChanged()), this,
SLOT(updateParamViewer()));
TFxP currentFxWithoutCamera = 0;
if (currentFx && actualFx)
currentFxWithoutCamera = getCurrentFx(currentFx, actualFx->getFxId());
if (currentFxWithoutCamera)
TFxUtil::setKeyframe(currentFxWithoutCamera, m_frameHandle->getFrameIndex(),
actualFx, m_frameHandle->getFrameIndex());
ToonzScene *scene = 0;
if (m_sceneHandle) scene = m_sceneHandle->getScene();
int frameIndex = 0;
if (m_frameHandle) frameIndex = m_frameHandle->getFrameIndex();
m_paramViewer->setFx(currentFxWithoutCamera, actualFx, frameIndex, scene);
m_paramViewer->setIsCameraViewMode(m_isCameraModeView);
m_viewer->setCameraMode(m_isCameraModeView);
TDimension cameraSize = TDimension(-1, -1);
if (scene) cameraSize = scene->getCurrentCamera()->getRes();
m_viewer->setCameraSize(cameraSize);
m_viewer->setFx(currentFx, actualFx, frameIndex);
if (m_fxHandle)
connect(m_fxHandle, SIGNAL(fxChanged()), this, SLOT(updateParamViewer()));
}
//-----------------------------------------------------------------------------
void FxSettings::setCurrentFrame() {
int frame = m_frameHandle->getFrameIndex();
m_paramViewer->update(frame, false);
// if(m_isCameraModeView)
setCurrentFx();
m_viewer->updateFrame(frame);
}
//-----------------------------------------------------------------------------
void FxSettings::changeTitleBar(TFx *fx) {
DockWidget *popup = dynamic_cast<DockWidget *>(parentWidget());
if (!popup) return;
QString titleText(tr("Fx Settings"));
if (fx) {
titleText += tr(" : ");
titleText += QString::fromStdWString(fx->getName());
}
popup->setWindowTitle(titleText);
}
//-----------------------------------------------------------------------------
void FxSettings::setCurrentFx() {
TFx *currFx = m_fxHandle->getFx();
TFxP actualFx, currentFx;
if (!currFx || 0 != dynamic_cast<TXsheetFx *>(currFx)) {
actualFx = currentFx = TFxP();
setFx(actualFx, currentFx);
changeTitleBar(currentFx.getPointer());
return;
}
TFxP fx(currFx);
bool hasEmptyInput = false;
if (TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(fx.getPointer()))
fx = zfx->getZeraryFx();
else
hasEmptyInput = hasEmptyInputPort(fx);
int frame = m_frameHandle->getFrame();
ToonzScene *scene = m_sceneHandle->getScene();
actualFx = fx;
bool isEnabled = actualFx->getAttributes()->isEnabled();
actualFx->getAttributes()->enable(true);
if (hasEmptyInput)
currentFx = actualFx;
else if (m_viewer->isEnabled()) {
if (!m_isCameraModeView)
currentFx = buildSceneFx(scene, frame, actualFx, false);
else {
const TRenderSettings rs =
scene->getProperties()->getPreviewProperties()->getRenderSettings();
currentFx = buildPartialSceneFx(scene, (double)frame, actualFx, 1, false);
}
} else
currentFx = TFxP();
if (currentFx) currentFx = currentFx->clone(true);
// se al frame corrente non c'e' il livello a cui e' applicato l'effetto:
// current=0, actual!=0
if (!currentFx) currentFx = actualFx->clone(false);
actualFx->getAttributes()->enable(isEnabled);
setFx(currentFx, actualFx);
changeTitleBar(currentFx.getPointer());
}
//-----------------------------------------------------------------------------
void FxSettings::setCurrentScene() {
ToonzScene *scene = m_sceneHandle->getScene();
m_paramViewer->setScene(scene);
}
//-----------------------------------------------------------------------------
void FxSettings::notifySceneChanged() {
TPixel32 col1, col2;
Preferences::instance()->getChessboardColors(col1, col2);
setCheckboardColors(col1, col2);
}
//-----------------------------------------------------------------------------
void FxSettings::showEvent(QShowEvent *event) {
setCurrentFx();
setCurrentFrame();
connect(m_frameHandle, SIGNAL(frameSwitched()), SLOT(setCurrentFrame()));
if (m_fxHandle) {
connect(m_paramViewer, SIGNAL(actualFxParamChanged()), m_fxHandle,
SIGNAL(fxChanged()));
connect(m_fxHandle, SIGNAL(fxChanged()), SLOT(updateParamViewer()));
connect(m_fxHandle, SIGNAL(fxSettingsShouldBeSwitched()),
SLOT(setCurrentFx()));
}
if (m_sceneHandle) {
connect(m_sceneHandle, SIGNAL(sceneChanged()), this,
SLOT(notifySceneChanged()));
connect(m_sceneHandle, SIGNAL(sceneSwitched()), this,
SLOT(setCurrentScene()));
}
if (m_xsheetHandle)
connect(m_xsheetHandle, SIGNAL(xsheetChanged()), SLOT(setCurrentFx()));
if (m_levelHandle)
connect(m_levelHandle, SIGNAL(xshLevelChanged()), SLOT(setCurrentFx()));
if (m_objectHandle)
connect(m_objectHandle, SIGNAL(objectChanged(bool)), SLOT(setCurrentFx()));
}
//-----------------------------------------------------------------------------
void FxSettings::hideEvent(QHideEvent *) {
setFx(0, 0);
disconnect(m_frameHandle, SIGNAL(frameSwitched()), this,
SLOT(setCurrentFrame()));
if (m_fxHandle) {
disconnect(m_fxHandle, SIGNAL(fxChanged()), this, SLOT(setCurrentFx()));
disconnect(m_fxHandle, SIGNAL(fxChanged()), this,
SLOT(updateParamViewer()));
disconnect(m_fxHandle, SIGNAL(fxSettingsShouldBeSwitched()), this,
SLOT(setCurrentFx()));
}
if (m_sceneHandle) {
disconnect(m_sceneHandle, SIGNAL(sceneChanged()), this,
SLOT(notifySceneChanged()));
disconnect(m_sceneHandle, SIGNAL(sceneSwitched()), this,
SLOT(setCurrentScene()));
}
if (m_xsheetHandle)
disconnect(m_xsheetHandle, SIGNAL(xsheetChanged()), this,
SLOT(setCurrentFx()));
if (m_levelHandle)
disconnect(m_levelHandle, SIGNAL(xshLevelChanged()), this,
SLOT(setCurrentFx()));
if (m_objectHandle)
disconnect(m_objectHandle, SIGNAL(objectChanged(bool)), this,
SLOT(setCurrentFx()));
}
//-----------------------------------------------------------------------------
void FxSettings::setCheckboardColors(const TPixel32 &col1,
const TPixel32 &col2) {
m_checkCol1 = col1;
m_checkCol2 = col2;
if (m_checkboardBg->isChecked())
m_viewer->setBgPainter(m_checkCol1, m_checkCol2);
}
//-----------------------------------------------------------------------------
void FxSettings::setWhiteBg() { m_viewer->setBgPainter(TPixel32::White); }
//-----------------------------------------------------------------------------
void FxSettings::setBlackBg() { m_viewer->setBgPainter(TPixel32::Black); }
//-----------------------------------------------------------------------------
void FxSettings::setCheckboardBg() {
m_viewer->setBgPainter(m_checkCol1, m_checkCol2);
}
//-----------------------------------------------------------------------------
void FxSettings::updateViewer() {
if (m_viewer->isEnabled())
m_viewer->updateFrame(m_frameHandle->getFrameIndex());
}
//-----------------------------------------------------------------------------
void FxSettings::updateParamViewer() {
if (!m_paramViewer || !m_frameHandle) return;
m_paramViewer->update(m_frameHandle->getFrameIndex(), true);
}
//-----------------------------------------------------------------------------
void FxSettings::onPointChanged(int index, const TPointD &p) {
m_paramViewer->setPointValue(index, p);
}
//-----------------------------------------------------------------------------
void FxSettings::onViewModeChanged(QAction *triggeredAct) {
setFocus();
QString name = triggeredAct->text();
bool actIsChecked = triggeredAct->isChecked();
QList<QAction *> actions = m_toolBar->actions();
QAction *cameraAct = actions[0];
QAction *previewAct = actions[1];
if (name == previewAct->text()) {
if (cameraAct->isChecked()) cameraAct->setChecked(false);
if (actIsChecked) {
m_isCameraModeView = false;
m_paramViewer->setIsCameraViewMode(false);
setCurrentFx();
}
m_viewer->setEnable(actIsChecked);
} else if (name == cameraAct->text()) {
if (previewAct->isChecked()) previewAct->setChecked(false);
if (actIsChecked) {
m_isCameraModeView = true;
m_paramViewer->setIsCameraViewMode(true);
setCurrentFx();
}
m_viewer->setEnable(actIsChecked);
}
}
//-----------------------------------------------------------------------------
void FxSettings::onPreferredSizeChanged(QSize pvBestSize) {
QSize popupBestSize = pvBestSize;
// Set minimum size, just in case
popupBestSize.setHeight(std::max(popupBestSize.height(), 85));
popupBestSize.setWidth(std::max(popupBestSize.width(), 390));
if (m_toolBar->isVisible()) {
popupBestSize += QSize(0, m_viewer->height() + m_toolBar->height() + 4);
popupBestSize.setWidth(
std::max(popupBestSize.width(), m_viewer->width() + 13));
}
DockWidget *popup = dynamic_cast<DockWidget *>(parentWidget());
if (popup && popup->isFloating()) {
QRect geom = popup->geometry();
geom.setSize(popupBestSize);
popup->setGeometry(geom);
popup->update();
}
}
//-----------------------------------------------------------------------------
void FxSettings::onShowSwatchButtonToggled(bool on) {
QWidget *bottomContainer = widget(1);
if (!on) {
m_container_height =
bottomContainer->height() + handleWidth() /* ハンドル幅 */;
m_container_width = m_viewer->width() + 13;
}
bottomContainer->setVisible(on);
DockWidget *popup = dynamic_cast<DockWidget *>(parentWidget());
if (popup && popup->isFloating()) {
QRect geom = popup->geometry();
int height_change = (on) ? m_container_height : -m_container_height;
int width_change = 0;
if (on && m_container_width > geom.width())
width_change = m_container_width - geom.width();
geom.setSize(geom.size() + QSize(width_change, height_change));
popup->setGeometry(geom);
popup->update();
}
}
//-----------------------------------------------------------------------------