1
2
3 #include "toonzqt/fxsettings.h"
4 #include "toonzqt/gutil.h"
5 #include "toonzqt/keyframenavigator.h"
6 #include "toonzqt/dvdialog.h"
7 #include "toonzqt/fxhistogramrender.h"
8 #include "toonzqt/histogram.h"
9
10 #include "tmacrofx.h"
11 #include "tstream.h"
12 #include "tparamcontainer.h"
13 #include "tspectrumparam.h"
14 #include "tfxattributes.h"
15 #include "toutputproperties.h"
16 #include "pluginhost.h"
17 #include "tenv.h"
18 #include "tsystem.h"
19 #include "docklayout.h"
20
21 #include "toonz/tcamera.h"
22 #include "toonz/toonzfolders.h"
23 #include "toonz/tcolumnfx.h"
24 #include "toonz/tscenehandle.h"
25 #include "toonz/txshlevelhandle.h"
26 #include "toonz/tobjecthandle.h"
27 #include "toonz/scenefx.h"
28 #include "toonz/toonzscene.h"
29 #include "toonz/sceneproperties.h"
30 #include "toonz/preferences.h"
31 #include "tw/stringtable.h"
32
33 #include <QVBoxLayout>
34 #include <QToolBar>
35 #include <QIcon>
36 #include <QAction>
37 #include <QStackedWidget>
38 #include <QLabel>
39 #include <QMap>
40 #include <QPainter>
41 #include <QCheckBox>
42 #include <QPushButton>
43
44 #include <QDesktopServices>
45 #include <QUrl>
46
47 using namespace DVGui;
48
49 namespace {
50
getCurrentFx(const TFxP & currentFx,std::wstring actualId)51 TFxP getCurrentFx(const TFxP ¤tFx, std::wstring actualId) {
52 if (currentFx->getFxId() == actualId) return currentFx;
53 int i;
54 for (i = 0; i < currentFx->getInputPortCount(); i++) {
55 TFxP fx = getCurrentFx(currentFx->getInputPort(i)->getFx(), actualId);
56 if (fx.getPointer()) return fx;
57 }
58 return 0;
59 }
60
hasEmptyInputPort(const TFxP & currentFx)61 bool hasEmptyInputPort(const TFxP ¤tFx) {
62 if (!currentFx.getPointer()) return true;
63 if (currentFx->getInputPortCount() == 0) return false;
64 return hasEmptyInputPort(currentFx->getInputPort(0)->getFx());
65 }
66 /*
67 TFxP cloneInputPort(const TFxP ¤tFx)
68 {
69 int i;
70 for (i=0; i<getInputPortCount(); ++i)
71 {
72 TFx *inputFx = sceneFx->getInputPort(i)->getFx();
73 if(inputFx)
74 {
75 if(TLevelColumnFx* affFx = dynamic_cast<TLevelColumnFx*
76 >(inputFx))
77 currentFx->getInputPort(i)->setFx(inputFx);
78 else
79 currentFx->getInputPort(i)->setFx(cloneInputPort());
80 }
81 TFxPort *port = getInputPort(i);
82 if (port->getFx())
83 fx->connect(getInputPortName(i),
84 cloneInputPort(port->getFx()));
85 }
86 void setLevelFxInputPort(const TFxP ¤tFx, const TFxP &sceneFx)
87 {
88 for (int i=0; i<sceneFx->getInputPortCount(); ++i)
89 {
90 TFx *inputFx = sceneFx->getInputPort(i)->getFx();
91 if(inputFx)
92 {
93 if(TLevelColumnFx* affFx = dynamic_cast<TLevelColumnFx*
94 >(inputFx))
95 currentFx->getInputPort(i)->setFx(inputFx);
96 else
97 setLevelFxInputPort(currentFx->getInputPort(i)->getFx(),
98 inputFx);
99 }
100 }
101 }
102 */
103 } // namespace
104
105 //=============================================================================
106 // ParamViewer
107 //-----------------------------------------------------------------------------
108
ParamsPage(QWidget * parent,ParamViewer * paramViewer)109 ParamsPage::ParamsPage(QWidget *parent, ParamViewer *paramViewer)
110 : QFrame(parent)
111 , m_paramViewer(paramViewer)
112 , m_horizontalLayout(NULL)
113 , m_groupLayout(NULL) {
114 m_fxHistogramRender = new FxHistogramRender();
115 setFrameStyle(QFrame::StyledPanel);
116
117 m_mainLayout = new QGridLayout(this);
118 m_mainLayout->setMargin(12);
119 m_mainLayout->setVerticalSpacing(10);
120 m_mainLayout->setHorizontalSpacing(5);
121
122 m_mainLayout->setColumnStretch(0, 0);
123 m_mainLayout->setColumnStretch(1, 1);
124
125 setLayout(m_mainLayout);
126 }
127
128 //-----------------------------------------------------------------------------
129
~ParamsPage()130 ParamsPage::~ParamsPage() {}
131
132 //-----------------------------------------------------------------------------
133
setPageField(TIStream & is,const TFxP & fx,bool isVertical)134 void ParamsPage::setPageField(TIStream &is, const TFxP &fx, bool isVertical) {
135 // m_horizontalLayout dovrebbe essere stato inizializzato prima di entrare nel
136 // metodo, per sicurezza verifico.
137 if (isVertical == false && !m_horizontalLayout) {
138 m_horizontalLayout = new QHBoxLayout();
139 m_horizontalLayout->setMargin(0);
140 m_horizontalLayout->setSpacing(5);
141 }
142
143 /*--
144 * HBoxLayoutを挿入するとき、最初のパラメータ名はGridlayoutのColumn0に入れるため
145 * --*/
146 bool isFirstParamInRow = true;
147
148 while (!is.matchEndTag()) {
149 std::string tagName;
150 if (!is.matchTag(tagName)) throw TException("expected tag");
151 if (tagName == "control") {
152 /*--- 設定ファイルからインタフェースの桁数を決める (PairSliderのみ実装。)
153 * ---*/
154 int decimals = 0;
155 std::string decimalsStr = is.getTagAttribute("decimals");
156 if (decimalsStr != "") {
157 decimals = QString::fromStdString(decimalsStr).toInt();
158 }
159
160 std::string name;
161 is >> name;
162 is.matchEndTag();
163 /*-- Layout設定名とFxParameterの名前が一致するものを取得 --*/
164 TParamP param = fx->getParams()->getParam(name);
165 if (param) {
166 std::string paramName = fx->getFxType() + "." + name;
167 QString str =
168 QString::fromStdWString(TStringTable::translate(paramName));
169 ParamField *field = ParamField::create(this, str, param);
170 if (field) {
171 if (decimals) field->setPrecision(decimals);
172 m_fields.push_back(field);
173 /*-- hboxタグに挟まれているとき --*/
174 if (isVertical == false) {
175 assert(m_horizontalLayout);
176 QLabel *label = new QLabel(str, this);
177 label->setObjectName("FxSettingsLabel");
178 if (isFirstParamInRow) {
179 int currentRow = m_mainLayout->rowCount();
180 m_mainLayout->addWidget(label, currentRow, 0,
181 Qt::AlignRight | Qt::AlignVCenter);
182 isFirstParamInRow = false;
183 } else
184 m_horizontalLayout->addWidget(label, 0,
185 Qt::AlignRight | Qt::AlignVCenter);
186 m_horizontalLayout->addWidget(field);
187 m_horizontalLayout->addSpacing(10);
188 } else {
189 int currentRow = m_mainLayout->rowCount();
190 QLabel *label = new QLabel(str, this);
191 label->setObjectName("FxSettingsLabel");
192 m_mainLayout->addWidget(label, currentRow, 0,
193 Qt::AlignRight | Qt::AlignVCenter);
194 m_mainLayout->addWidget(field, currentRow, 1);
195 }
196 connect(field, SIGNAL(currentParamChanged()), m_paramViewer,
197 SIGNAL(currentFxParamChanged()));
198 connect(field, SIGNAL(actualParamChanged()), m_paramViewer,
199 SIGNAL(actualFxParamChanged()));
200 connect(field, SIGNAL(paramKeyToggle()), m_paramViewer,
201 SIGNAL(paramKeyChanged()));
202 }
203 }
204 } else if (tagName == "label") {
205 std::string name;
206 is >> name;
207 is.matchEndTag();
208 QString str;
209 if (isVertical == false) {
210 assert(m_horizontalLayout);
211 m_horizontalLayout->addWidget(new QLabel(str.fromStdString(name)));
212 } else {
213 int currentRow = m_mainLayout->rowCount();
214 m_mainLayout->addWidget(new QLabel(str.fromStdString(name)), currentRow,
215 0, 1, 2);
216 }
217 } else if (tagName == "separator") {
218 // <separator/> o <separator label="xxx"/>
219 std::string label = is.getTagAttribute("label");
220 QString str;
221 Separator *sep = new Separator(str.fromStdString(label), this);
222 int currentRow = m_mainLayout->rowCount();
223 m_mainLayout->addWidget(sep, currentRow, 0, 1, 2);
224 m_mainLayout->setRowStretch(currentRow, 0);
225 } else if (tagName == "histogram") {
226 Histogram *histogram = new Histogram();
227 m_fxHistogramRender->setHistograms(histogram->getHistograms());
228 if (isVertical == false) {
229 assert(m_horizontalLayout);
230 m_horizontalLayout->addWidget(histogram);
231 } else {
232 int currentRow = m_mainLayout->rowCount();
233 m_mainLayout->addWidget(histogram, currentRow, 0, 1, 2);
234 }
235 } else if (tagName == "test") {
236 // <test/>
237 // box->add(new WidgetBox(new TestSeparator(page)));
238 } else if (tagName == "hbox") {
239 int currentRow = m_mainLayout->rowCount();
240 m_horizontalLayout = new QHBoxLayout();
241 m_horizontalLayout->setMargin(0);
242 m_horizontalLayout->setSpacing(5);
243 setPageField(is, fx, false);
244 m_mainLayout->addLayout(m_horizontalLayout, currentRow, 1, 1, 2);
245 } else if (tagName == "vbox") {
246 int shrink = 0;
247 std::string shrinkStr = is.getTagAttribute("shrink");
248 std::string modeSensitiveStr = is.getTagAttribute("modeSensitive");
249 if (shrinkStr != "" || modeSensitiveStr != "") {
250 QWidget *tmpWidget;
251 if (shrinkStr != "") {
252 tmpWidget = new QWidget(this);
253 shrink = QString::fromStdString(shrinkStr).toInt();
254 std::string label = is.getTagAttribute("label");
255 QCheckBox *checkBox = new QCheckBox(this);
256 QHBoxLayout *sepLay = new QHBoxLayout();
257 sepLay->setMargin(0);
258 sepLay->setSpacing(5);
259 sepLay->addWidget(checkBox, 0);
260 sepLay->addWidget(new Separator(QString::fromStdString(label), this),
261 1);
262 int currentRow = m_mainLayout->rowCount();
263 m_mainLayout->addLayout(sepLay, currentRow, 0, 1, 2);
264 m_mainLayout->setRowStretch(currentRow, 0);
265 //--- signal-slot connection
266 connect(checkBox, SIGNAL(toggled(bool)), tmpWidget,
267 SLOT(setVisible(bool)));
268 checkBox->setChecked(shrink == 1);
269 tmpWidget->setVisible(shrink == 1);
270 } else { // modeSensitiveStr != ""
271 QList<int> modes;
272 QStringList modeListStr =
273 QString::fromStdString(is.getTagAttribute("mode"))
274 .split(',', QString::SkipEmptyParts);
275 for (QString modeNum : modeListStr) modes.push_back(modeNum.toInt());
276 // find the mode combobox
277 ModeChangerParamField *modeChanger = nullptr;
278 for (int r = 0; r < m_mainLayout->rowCount(); r++) {
279 QLayoutItem *li = m_mainLayout->itemAtPosition(r, 1);
280 if (!li || !li->widget()) continue;
281 ModeChangerParamField *field =
282 dynamic_cast<ModeChangerParamField *>(li->widget());
283 if (!field ||
284 field->getParamName().toStdString() != modeSensitiveStr)
285 continue;
286 modeChanger = field;
287 break;
288 }
289 assert(modeChanger);
290 tmpWidget = new ModeSensitiveBox(this, modeChanger, modes);
291 }
292
293 int currentRow = m_mainLayout->rowCount();
294 QGridLayout *keepMainLay = m_mainLayout;
295 // temporary switch the layout
296 m_mainLayout = new QGridLayout();
297 m_mainLayout->setMargin(0);
298 m_mainLayout->setVerticalSpacing(10);
299 m_mainLayout->setHorizontalSpacing(5);
300 m_mainLayout->setColumnStretch(0, 0);
301 m_mainLayout->setColumnStretch(1, 1);
302 setPageField(is, fx, true);
303 tmpWidget->setLayout(m_mainLayout);
304 // turn back the layout
305 m_mainLayout = keepMainLay;
306 m_mainLayout->addWidget(tmpWidget, currentRow, 0, 1, 2);
307 } else
308 setPageField(is, fx, true);
309 }
310 /*-- PixelParamFieldが2つあるとき、一方のRGB値を他方にコピーするボタン --*/
311 else if (tagName == "rgb_link_button") {
312 /*-- リンクさせたいパラメータを2つ得る --*/
313 std::string name1, name2;
314 is >> name1;
315 is >> name2;
316 is.matchEndTag();
317
318 /*-- 既に作ってあるGUIを探索し、対応する2つを得て格納 --*/
319 PixelParamField *ppf1 = 0;
320 PixelParamField *ppf2 = 0;
321 for (int r = 0; r < m_mainLayout->rowCount(); r++) {
322 QLayoutItem *li = m_mainLayout->itemAtPosition(r, 1);
323 if (!li) continue;
324 QWidget *w = li->widget();
325 if (!w) continue;
326
327 ParamField *pf = dynamic_cast<ParamField *>(w);
328 if (pf) {
329 PixelParamField *ppf = dynamic_cast<PixelParamField *>(pf);
330 if (ppf) {
331 if (ppf1 == 0 && ppf->getParamName().toStdString() == name1)
332 ppf1 = ppf;
333
334 if (ppf2 == 0 && ppf->getParamName().toStdString() == name2)
335 ppf2 = ppf;
336 }
337 }
338 }
339 if (ppf1 == 0 || ppf2 == 0) continue;
340
341 /*-- ボタンのラベルのため 翻訳する --*/
342 std::string paramName1 = fx->getFxType() + "." + name1;
343 std::string paramName2 = fx->getFxType() + "." + name2;
344 QString str1 =
345 QString::fromStdWString(TStringTable::translate(paramName1));
346 QString str2 =
347 QString::fromStdWString(TStringTable::translate(paramName2));
348
349 RgbLinkButtons *linkBut =
350 new RgbLinkButtons(str1, str2, this, ppf1, ppf2);
351
352 int currentRow = m_mainLayout->rowCount();
353 m_mainLayout->addWidget(linkBut, currentRow, 1,
354 Qt::AlignLeft | Qt::AlignVCenter);
355 }
356 /*-- チェックボックスによって他のインタフェースを表示/非表示させる ---*/
357 else if (tagName == "visibleToggle") {
358 BoolParamField *controller_bpf = 0;
359 QList<QWidget *> on_items;
360 QList<QWidget *> off_items;
361 while (!is.matchEndTag()) {
362 std::string tagName;
363 if (!is.matchTag(tagName)) throw TException("expected tag");
364
365 if (tagName ==
366 "controller" || /*-- 表示をコントロールするチェックボックス --*/
367 tagName == "on" || /*-- ONのとき表示されるインタフェース --*/
368 tagName == "off") /*-- OFFのとき表示されるインタフェース --*/
369 {
370 std::string name;
371 is >> name;
372 is.matchEndTag();
373 for (int r = 0; r < m_mainLayout->rowCount(); r++) {
374 QLayoutItem *li = m_mainLayout->itemAtPosition(r, 1);
375 if (!li) continue;
376 QWidget *w = li->widget();
377 if (!w) continue;
378 ParamField *pf = dynamic_cast<ParamField *>(w);
379 if (pf) {
380 if (pf->getParamName().toStdString() == name) {
381 if (tagName == "controller")
382 controller_bpf = dynamic_cast<BoolParamField *>(pf);
383 else if (tagName == "on") {
384 on_items.push_back(w);
385 on_items.push_back(
386 m_mainLayout->itemAtPosition(r, 0)->widget());
387 } else if (tagName == "off") {
388 off_items.push_back(w);
389 off_items.push_back(
390 m_mainLayout->itemAtPosition(r, 0)->widget());
391 }
392 }
393 }
394 /*-- 入れ子のLayoutも1段階探す --*/
395 else {
396 QGridLayout *gridLay = dynamic_cast<QGridLayout *>(w->layout());
397 if (!gridLay) continue;
398 for (int r_s = 0; r_s < gridLay->rowCount(); r_s++) {
399 QLayoutItem *li_s = gridLay->itemAtPosition(r_s, 1);
400 if (!li_s) continue;
401 ParamField *pf_s = dynamic_cast<ParamField *>(li_s->widget());
402 if (pf_s) {
403 if (pf_s->getParamName().toStdString() == name) {
404 if (tagName == "controller")
405 controller_bpf = dynamic_cast<BoolParamField *>(pf_s);
406 else if (tagName == "on") {
407 on_items.push_back(pf_s);
408 on_items.push_back(
409 gridLay->itemAtPosition(r_s, 0)->widget());
410 } else if (tagName == "off") {
411 off_items.push_back(pf_s);
412 off_items.push_back(
413 gridLay->itemAtPosition(r_s, 0)->widget());
414 }
415 }
416 }
417 }
418 }
419 }
420 } else
421 throw TException("unexpected tag " + tagName);
422 }
423 /*-- 表示コントロールをconnect --*/
424 if (controller_bpf) {
425 /*-- ラベルとWidgetを両方表示/非表示 --*/
426 for (int i = 0; i < on_items.size(); i++) {
427 connect(controller_bpf, SIGNAL(toggled(bool)), on_items[i],
428 SLOT(setVisible(bool)));
429 on_items[i]->hide();
430 }
431 for (int i = 0; i < off_items.size(); i++) {
432 connect(controller_bpf, SIGNAL(toggled(bool)), off_items[i],
433 SLOT(setHidden(bool)));
434 off_items[i]->show();
435 }
436 } else
437 std::cout << "controller_bpf NOT found!" << std::endl;
438 } else
439 throw TException("unexpected tag " + tagName);
440 }
441
442 if (isVertical == false && m_horizontalLayout) {
443 m_horizontalLayout->addStretch(1);
444 }
445 }
446
447 //-----------------------------------------------------------------------------
448
setPageSpace()449 void ParamsPage::setPageSpace() {
450 if (m_fields.count() != 0) {
451 QWidget *spaceWidget = new QWidget();
452
453 int currentRow = m_mainLayout->rowCount();
454 m_mainLayout->addWidget(spaceWidget, currentRow, 0, 1, 2);
455
456 for (int i = 0; i < currentRow; i++) m_mainLayout->setRowStretch(i, 0);
457 m_mainLayout->setRowStretch(currentRow, 1);
458 }
459 }
460
461 //-----------------------------------------------------------------------------
beginGroup(const char * name)462 void ParamsPage::beginGroup(const char *name) {
463 m_groupLayout = new QGridLayout();
464
465 QGroupBox *group = new QGroupBox(QString::fromUtf8(name), this);
466 group->setLayout(m_groupLayout);
467 m_mainLayout->addWidget(group, m_mainLayout->rowCount(), 0, 1, 2);
468 }
469
endGroup()470 void ParamsPage::endGroup() { m_groupLayout = NULL; }
471
addWidget(QWidget * field,bool isVertical)472 void ParamsPage::addWidget(QWidget *field, bool isVertical) {
473 QLabel *label = NULL;
474 ParamField *pf = qobject_cast<ParamField *>(field);
475 if (pf) {
476 label = new QLabel(pf->getUIName(), this);
477 label->setObjectName("FxSettingsLabel");
478 if (!pf->getDescription().isEmpty())
479 label->setToolTip(pf->getDescription());
480 }
481
482 if (isVertical) {
483 if (m_groupLayout) {
484 int row = m_groupLayout->rowCount();
485 if (label)
486 m_groupLayout->addWidget(label, row, 0,
487 Qt::AlignRight | Qt::AlignVCenter);
488 m_groupLayout->addWidget(field, row, 1);
489 } else {
490 int row = m_mainLayout->rowCount();
491 if (label)
492 m_mainLayout->addWidget(label, row, 0,
493 Qt::AlignRight | Qt::AlignVCenter);
494 m_mainLayout->addWidget(field, row, 1);
495 }
496 } else {
497 if (!m_horizontalLayout) {
498 m_horizontalLayout = new QHBoxLayout();
499 m_horizontalLayout->setMargin(0);
500 m_horizontalLayout->setSpacing(5);
501 }
502 m_horizontalLayout->addWidget(field);
503 }
504 }
505
506 #define TOONZ_DEFINE_NEW_COMPONENT(NAME, MAKE) \
507 QWidget *ParamsPage::NAME(TFx *fx, const char *name) { \
508 TParamP param = fx->getParams()->getParam(name); \
509 if (!param) return NULL; \
510 QString const paramName = \
511 QString::fromStdString(fx->getFxType() + "." + name); \
512 ParamField *field = MAKE(this, paramName, param); \
513 if (!field) return NULL; \
514 m_fields.push_back(field); \
515 connect(field, SIGNAL(currentParamChanged()), m_paramViewer, \
516 SIGNAL(currentFxParamChanged())); \
517 connect(field, SIGNAL(actualParamChanged()), m_paramViewer, \
518 SIGNAL(actualFxParamChanged())); \
519 connect(field, SIGNAL(paramKeyToggle()), m_paramViewer, \
520 SIGNAL(paramKeyChanged())); \
521 return field; \
522 }
523
524 TOONZ_DEFINE_NEW_COMPONENT(newParamField, ParamField::create);
525 TOONZ_DEFINE_NEW_COMPONENT(newLineEdit, make_lineedit);
526 TOONZ_DEFINE_NEW_COMPONENT(newSlider, make_slider);
527 TOONZ_DEFINE_NEW_COMPONENT(newSpinBox, make_spinbox);
528 TOONZ_DEFINE_NEW_COMPONENT(newCheckBox, make_checkbox);
529 TOONZ_DEFINE_NEW_COMPONENT(newRadioButton, make_radiobutton);
530 TOONZ_DEFINE_NEW_COMPONENT(newComboBox, make_combobox);
531
532 #undef TOONZ_DEFINE_NEW_COMPONENT
533
534 //-----------------------------------------------------------------------------
535
setFx(const TFxP & currentFx,const TFxP & actualFx,int frame)536 void ParamsPage::setFx(const TFxP ¤tFx, const TFxP &actualFx, int frame) {
537 assert(currentFx);
538 assert(actualFx);
539 for (int i = 0; i < (int)m_fields.size(); i++) {
540 ParamField *field = m_fields[i];
541 QString fieldName = field->getParamName();
542
543 TFxP fx = getCurrentFx(currentFx, actualFx->getFxId());
544 assert(fx.getPointer());
545 TParamP currentParam =
546 currentFx->getParams()->getParam(fieldName.toStdString());
547 TParamP actualParam =
548 actualFx->getParams()->getParam(fieldName.toStdString());
549 assert(currentParam);
550 assert(actualParam);
551 field->setParam(currentParam, actualParam, frame);
552 }
553 if (actualFx->getInputPortCount() > 0)
554 m_fxHistogramRender->computeHistogram(actualFx->getInputPort(0)->getFx(),
555 frame);
556 }
557
558 //-----------------------------------------------------------------------------
559
setPointValue(int index,const TPointD & p)560 void ParamsPage::setPointValue(int index, const TPointD &p) {
561 if (0 <= index && index < (int)m_fields.size())
562 m_fields[index]->setPointValue(p);
563 }
564
565 //-----------------------------------------------------------------------------
566
update(int frame)567 void ParamsPage::update(int frame) {
568 int i;
569 for (i = 0; i < (int)m_fields.size(); i++) {
570 ParamField *field = m_fields[i];
571 field->update(frame);
572 }
573 }
574
575 //-----------------------------------------------------------------------------
576
577 namespace {
578
getItemSize(QLayoutItem * item)579 QSize getItemSize(QLayoutItem *item) {
580 // layout case
581 QHBoxLayout *hLay = dynamic_cast<QHBoxLayout *>(item->layout());
582 if (hLay) {
583 int tmpWidth = 0, tmpHeight = 0;
584 for (int c = 0; c < hLay->count(); c++) {
585 QLayoutItem *subItem = hLay->itemAt(c);
586 if (!subItem) continue;
587 QSize subItemSize = getItemSize(subItem);
588 tmpWidth += subItemSize.width();
589 if (tmpHeight < subItemSize.height()) tmpHeight = subItemSize.height();
590 }
591 tmpWidth += (hLay->count() - 1) * 5;
592 return QSize(tmpWidth, tmpHeight);
593 }
594
595 ParamField *pF = dynamic_cast<ParamField *>(item->widget());
596 if (pF) return pF->getPreferedSize();
597
598 Separator *sep = dynamic_cast<Separator *>(item->widget());
599 if (sep) return QSize(0, 16);
600
601 Histogram *histo = dynamic_cast<Histogram *>(item->widget());
602 if (histo) return QSize(278, 162);
603
604 RgbLinkButtons *linkBut = dynamic_cast<RgbLinkButtons *>(item->widget());
605 if (linkBut) return QSize(0, 21);
606
607 return QSize();
608 }
609
updateMaximumPageSize(QGridLayout * layout,int & maxLabelWidth,int & maxWidgetWidth,int & fieldsHeight)610 void updateMaximumPageSize(QGridLayout *layout, int &maxLabelWidth,
611 int &maxWidgetWidth, int &fieldsHeight) {
612 /*-- Label側の横幅の最大値を得る --*/
613 for (int r = 0; r < layout->rowCount(); r++) {
614 /*-- アイテムが無ければ次の行へ --*/
615 if (!layout->itemAtPosition(r, 0)) continue;
616 /*-- ラベルの横幅を得て、最大値を更新していく --*/
617 QLabel *label =
618 dynamic_cast<QLabel *>(layout->itemAtPosition(r, 0)->widget());
619 QGroupBox *gBox =
620 dynamic_cast<QGroupBox *>(layout->itemAtPosition(r, 0)->widget());
621 if (label) {
622 int tmpWidth = label->fontMetrics().width(label->text());
623 if (maxLabelWidth < tmpWidth) maxLabelWidth = tmpWidth;
624 }
625 /*-- PlugInFxのGroupパラメータのサイズ --*/
626 else if (gBox) {
627 QGridLayout *gridLay = dynamic_cast<QGridLayout *>(gBox->layout());
628 if (gridLay) {
629 updateMaximumPageSize(gridLay, maxLabelWidth, maxWidgetWidth,
630 fieldsHeight);
631 /*-- GroupBoxのマージン --*/
632 maxLabelWidth += 10;
633 maxWidgetWidth += 10;
634 fieldsHeight += 20;
635 }
636 }
637 }
638
639 /*-- Widget側の最適な縦サイズおよび横幅の最大値を得る --*/
640 QMap<int, int> heightsByMode;
641 int maxModeHeight = 0;
642 for (int r = 0; r < layout->rowCount(); r++) {
643 /*-- Column1にある可能性のあるもの:ParamField, Histogram, Layout,
644 * RgbLinkButtons --*/
645
646 QLayoutItem *item = layout->itemAtPosition(r, 1);
647 if (!item) continue;
648
649 ModeSensitiveBox *box = dynamic_cast<ModeSensitiveBox *>(item->widget());
650 if (box) {
651 // if (box->isHidden()) continue;
652 QGridLayout *innerLay = dynamic_cast<QGridLayout *>(box->layout());
653 if (!innerLay) continue;
654 int tmpHeight = 0;
655 updateMaximumPageSize(innerLay, maxLabelWidth, maxWidgetWidth, tmpHeight);
656 for (int mode : box->modes()) {
657 heightsByMode[mode] += tmpHeight;
658 maxModeHeight = std::max(maxModeHeight, heightsByMode[mode]);
659 }
660
661 // attempt to align the label column
662 innerLay->setColumnMinimumWidth(0, maxLabelWidth);
663 continue;
664 }
665
666 QSize itemSize = getItemSize(item);
667 if (maxWidgetWidth < itemSize.width()) maxWidgetWidth = itemSize.width();
668 fieldsHeight += itemSize.height();
669 }
670 if (maxModeHeight > 0) fieldsHeight += maxModeHeight;
671
672 if (layout->rowCount() > 1) fieldsHeight += (layout->rowCount() - 1) * 10;
673 }
674 }; // namespace
675
getPreferredSize()676 QSize ParamsPage::getPreferredSize() {
677 int maxLabelWidth = 0;
678 int maxWidgetWidth = 0;
679 int fieldsHeight = 0;
680
681 updateMaximumPageSize(m_mainLayout, maxLabelWidth, maxWidgetWidth,
682 fieldsHeight);
683 return QSize(maxLabelWidth + maxWidgetWidth +
684 m_mainLayout->horizontalSpacing() +
685 2 * m_mainLayout->margin(),
686 fieldsHeight + 2 * m_mainLayout->margin() +
687 31 /* spacing for the swatch */);
688 }
689
690 //=============================================================================
691 // ParamsPageSet
692 //-----------------------------------------------------------------------------
693
694 #if QT_VERSION >= 0x050500
ParamsPageSet(QWidget * parent,Qt::WindowFlags flags)695 ParamsPageSet::ParamsPageSet(QWidget *parent, Qt::WindowFlags flags)
696 #else
697 ParamsPageSet::ParamsPageSet(QWidget *parent, Qt::WFlags flags)
698 #endif
699 : QWidget(parent, flags)
700 , m_preferredSize(0, 0)
701 , m_helpFilePath("")
702 , m_helpCommand("") {
703 // TabBar
704 m_tabBar = new TabBar(this);
705 // This widget is used to set the background color of the tabBar
706 // using the styleSheet and to draw the two lines on the bottom size.
707 m_tabBarContainer = new TabBarContainter(this);
708 m_pagesList = new QStackedWidget(this);
709
710 m_helpButton = new QPushButton(tr(""), this);
711 m_helpButton->setIconSize(QSize(20, 20));
712 m_helpButton->setIcon(createQIcon("help"));
713 m_helpButton->setFixedWidth(28);
714 m_helpButton->setToolTip(tr("View help page"));
715
716 m_parent = dynamic_cast<ParamViewer *>(parent);
717 m_pageFxIndexTable.clear();
718 m_tabBar->setDrawBase(false);
719 m_tabBar->setObjectName("FxSettingsTabBar");
720 m_helpButton->setFixedHeight(20);
721 m_helpButton->setObjectName("FxSettingsHelpButton");
722 m_helpButton->setFocusPolicy(Qt::NoFocus);
723
724 //----layout
725 QVBoxLayout *mainLayout = new QVBoxLayout();
726 mainLayout->setMargin(0);
727 mainLayout->setSpacing(0);
728 {
729 QHBoxLayout *hLayout = new QHBoxLayout();
730 hLayout->setMargin(0);
731 hLayout->addSpacing(0);
732 {
733 hLayout->addWidget(m_tabBar);
734 hLayout->addStretch(1);
735 hLayout->addWidget(m_helpButton);
736 }
737 m_tabBarContainer->setLayout(hLayout);
738
739 mainLayout->addWidget(m_tabBarContainer);
740
741 mainLayout->addWidget(m_pagesList);
742
743 mainLayout->addWidget(new Separator("", this), 0);
744 }
745 setLayout(mainLayout);
746
747 connect(m_tabBar, SIGNAL(currentChanged(int)), this, SLOT(setPage(int)));
748
749 m_helpButton->hide();
750 }
751
752 //-----------------------------------------------------------------------------
753
~ParamsPageSet()754 ParamsPageSet::~ParamsPageSet() {}
755
756 //-----------------------------------------------------------------------------
757
setPage(int index)758 void ParamsPageSet::setPage(int index) {
759 if (m_tabBar->count() == 0 || m_pagesList->count() == 0) return;
760 assert(index >= 0 && index < m_pagesList->count());
761 m_pagesList->setCurrentIndex(index);
762 }
763
764 //-----------------------------------------------------------------------------
765
setFx(const TFxP & currentFx,const TFxP & actualFx,int frame)766 void ParamsPageSet::setFx(const TFxP ¤tFx, const TFxP &actualFx,
767 int frame) {
768 TMacroFx *currentFxMacro = dynamic_cast<TMacroFx *>(currentFx.getPointer());
769 if (currentFxMacro) {
770 TMacroFx *actualFxMacro = dynamic_cast<TMacroFx *>(actualFx.getPointer());
771 assert(actualFxMacro);
772 const std::vector<TFxP> ¤tFxMacroFxs = currentFxMacro->getFxs();
773 const std::vector<TFxP> &actualFxMacroFxs = actualFxMacro->getFxs();
774 assert(currentFxMacroFxs.size() == actualFxMacroFxs.size());
775 for (int i = 0; i < m_pagesList->count(); i++) {
776 ParamsPage *page = getParamsPage(i);
777 if (!page || !m_pageFxIndexTable.contains(page)) continue;
778 int index = m_pageFxIndexTable[page];
779 page->setFx(currentFxMacroFxs[index], actualFxMacroFxs[index], frame);
780 }
781 } else {
782 for (int i = 0; i < m_pagesList->count(); i++) {
783 ParamsPage *page = getParamsPage(i);
784 if (!page) continue;
785 page->setFx(currentFx, actualFx, frame);
786 }
787 }
788 }
789
790 //-----------------------------------------------------------------------------
791
updatePage(int frame,bool onlyParam)792 void ParamsPageSet::updatePage(int frame, bool onlyParam) {
793 if (!m_pagesList) return;
794 int i;
795 for (i = 0; i < m_pagesList->count(); i++) {
796 ParamsPage *page = getParamsPage(i);
797 if (!page) continue;
798 page->update(frame);
799 if (!onlyParam) page->getFxHistogramRender()->invalidateFrame(frame);
800 }
801 }
802
803 //-----------------------------------------------------------------------------
804
setScene(ToonzScene * scene)805 void ParamsPageSet::setScene(ToonzScene *scene) {
806 if (!m_pagesList) return;
807 int i;
808 for (i = 0; i < m_pagesList->count(); i++) {
809 ParamsPage *page = getParamsPage(i);
810 if (!page) continue;
811 page->getFxHistogramRender()->setScene(scene);
812 }
813 }
814
815 //-----------------------------------------------------------------------------
816
setIsCameraViewMode(bool isCameraViewMode)817 void ParamsPageSet::setIsCameraViewMode(bool isCameraViewMode) {
818 if (!m_pagesList) return;
819 int i;
820 for (i = 0; i < m_pagesList->count(); i++) {
821 ParamsPage *page = getParamsPage(i);
822 if (!page) continue;
823 page->getFxHistogramRender()->setIsCameraViewMode(isCameraViewMode);
824 }
825 }
826
827 //-----------------------------------------------------------------------------
828
createParamsPage()829 ParamsPage *ParamsPageSet::createParamsPage() {
830 return new ParamsPage(this, m_parent);
831 }
832
addParamsPage(ParamsPage * page,const char * name)833 void ParamsPageSet::addParamsPage(ParamsPage *page, const char *name) {
834 /*-- このFxで最大サイズのページに合わせてダイアログをリサイズ --*/
835 QSize pagePreferredSize = page->getPreferredSize();
836 m_preferredSize = m_preferredSize.expandedTo(
837 pagePreferredSize + QSize(m_tabBarContainer->height() + 2,
838 2)); /*-- 2は上下左右のマージン --*/
839
840 QScrollArea *pane = new QScrollArea(this);
841 pane->setWidgetResizable(true);
842 pane->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
843 pane->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
844 pane->setWidget(page);
845
846 m_tabBar->addSimpleTab(QString::fromUtf8(name));
847 m_pagesList->addWidget(pane);
848 }
849
850 //-----------------------------------------------------------------------------
851
createControls(const TFxP & fx,int index)852 void ParamsPageSet::createControls(const TFxP &fx, int index) {
853 if (TMacroFx *macroFx = dynamic_cast<TMacroFx *>(fx.getPointer())) {
854 const std::vector<TFxP> &fxs = macroFx->getFxs();
855 for (int i = 0; i < (int)fxs.size(); i++) createControls(fxs[i], i);
856 return;
857 }
858 if (RasterFxPluginHost *plugin =
859 dynamic_cast<RasterFxPluginHost *>(fx.getPointer())) {
860 plugin->build(this);
861 std::string url = plugin->getUrl();
862 if (!url.empty()) {
863 connect(m_helpButton, SIGNAL(pressed()), this, SLOT(openHelpUrl()));
864 m_helpButton->show();
865 m_helpUrl = url;
866 }
867 return;
868 }
869
870 TFilePath fp = ToonzFolder::getProfileFolder() + "layouts" + "fxs" +
871 (fx->getFxType() + ".xml");
872
873 TIStream is(fp);
874 if (!is) return;
875
876 if (fx->getParams()->getParamCount()) {
877 try {
878 std::string tagName;
879 if (!is.matchTag(tagName) || tagName != "fxlayout")
880 throw TException("expected <fxlayout>");
881
882 m_helpFilePath = is.getTagAttribute("help_file");
883 if (m_helpFilePath != "") {
884 connect(m_helpButton, SIGNAL(pressed()), this, SLOT(openHelpFile()));
885 m_helpButton->show();
886 /*-- pdfファイルのページ指定など、引数が必要な場合の追加fragmentを取得
887 * --*/
888 m_helpCommand = is.getTagAttribute("help_command");
889 }
890
891 while (!is.matchEndTag()) createPage(is, fx, index);
892 } catch (TException const &) {
893 }
894 }
895 // else createEmptyPage();
896 }
897
898 //-----------------------------------------------------------------------------
899
getCurrentParamsPage() const900 ParamsPage *ParamsPageSet::getCurrentParamsPage() const {
901 QScrollArea *scrollAreaPage =
902 dynamic_cast<QScrollArea *>(m_pagesList->currentWidget());
903 assert(scrollAreaPage);
904 return dynamic_cast<ParamsPage *>(scrollAreaPage->widget());
905 }
906
907 //-----------------------------------------------------------------------------
908
getParamsPage(int index) const909 ParamsPage *ParamsPageSet::getParamsPage(int index) const {
910 QScrollArea *scrollAreaPage =
911 dynamic_cast<QScrollArea *>(m_pagesList->widget(index));
912 assert(scrollAreaPage);
913 return dynamic_cast<ParamsPage *>(scrollAreaPage->widget());
914 }
915
916 //-----------------------------------------------------------------------------
917
createPage(TIStream & is,const TFxP & fx,int index)918 void ParamsPageSet::createPage(TIStream &is, const TFxP &fx, int index) {
919 std::string tagName;
920 if (!is.matchTag(tagName) || tagName != "page")
921 throw TException("expected <page>");
922 std::string pageName = is.getTagAttribute("name");
923 if (pageName == "") pageName = "page";
924
925 ParamsPage *paramsPage = new ParamsPage(this, m_parent);
926 paramsPage->setPage(is, fx);
927
928 connect(paramsPage, SIGNAL(preferredPageSizeChanged()), this,
929 SLOT(recomputePreferredSize()));
930
931 /*-- このFxで最大サイズのページに合わせてダイアログをリサイズ --*/
932 QSize pagePreferredSize = paramsPage->getPreferredSize();
933 m_preferredSize = m_preferredSize.expandedTo(
934 pagePreferredSize + QSize(m_tabBarContainer->height() + 2,
935 2)); /*-- 2は上下左右のマージン --*/
936
937 QScrollArea *scrollAreaPage = new QScrollArea(this);
938 scrollAreaPage->setWidgetResizable(true);
939 scrollAreaPage->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
940 scrollAreaPage->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
941 scrollAreaPage->setWidget(paramsPage);
942
943 QString str;
944 m_tabBar->addSimpleTab(str.fromStdString(pageName));
945 m_pagesList->addWidget(scrollAreaPage);
946 if (index >= 0) m_pageFxIndexTable[paramsPage] = index;
947 }
948
949 //-----------------------------------------------------------------------------
950
recomputePreferredSize()951 void ParamsPageSet::recomputePreferredSize() {
952 QSize newSize(0, 0);
953 for (int i = 0; i < m_pagesList->count(); i++) {
954 QScrollArea *area = dynamic_cast<QScrollArea *>(m_pagesList->widget(i));
955 if (!area) continue;
956 ParamsPage *page = dynamic_cast<ParamsPage *>(area->widget());
957 if (!page) continue;
958 QSize pagePreferredSize = page->getPreferredSize();
959 newSize = newSize.expandedTo(pagePreferredSize +
960 QSize(m_tabBarContainer->height() + 2, 2));
961 }
962 if (!newSize.isEmpty()) {
963 m_preferredSize = newSize;
964 // resize the parent FxSettings
965 m_parent->notifyPreferredSizeChanged(m_preferredSize + QSize(2, 50));
966 }
967 }
968
969 //-----------------------------------------------------------------------------
970
971 /* TODO: Webサイト内のヘルプに対応すべきか検討 2016.02.01 shun_iwasawa */
openHelpFile()972 void ParamsPageSet::openHelpFile() {
973 if (m_helpFilePath == "") return;
974
975 // if (m_helpCommand != "")
976 // commandString += m_helpCommand + " ";
977
978 // Get UI language as set in "Preferences"
979 QString currentLanguage = Preferences::instance()->getCurrentLanguage();
980 std::string helpDocLang = currentLanguage.toStdString();
981
982 // Assume associated language subdir exists
983 TFilePath helpFp = TEnv::getStuffDir() + "doc" + helpDocLang + m_helpFilePath;
984
985 // Verify subdir exists; if not, default to standard doc dir
986 if (!TFileStatus(helpFp).doesExist()) {
987 helpFp = TEnv::getStuffDir() + "doc" + m_helpFilePath;
988 }
989
990 // commandString +=
991 // QString::fromStdWString(helpFp.getWideString()).toStdString();
992 // QString command = QString::fromStdString(m_helpFilePath);
993 // system(commandString.c_str());
994 // QProcess process;
995 // process.start(command);
996 QDesktopServices::openUrl(
997 QUrl::fromLocalFile(QString::fromStdWString(helpFp.getWideString())));
998 }
999
openHelpUrl()1000 void ParamsPageSet::openHelpUrl() {
1001 QDesktopServices::openUrl(QUrl(QString(m_helpUrl.c_str())));
1002 }
1003
1004 //=============================================================================
1005 // ParamViewer
1006 //-----------------------------------------------------------------------------
1007
1008 #if QT_VERSION >= 0x050500
ParamViewer(QWidget * parent,Qt::WindowFlags flags)1009 ParamViewer::ParamViewer(QWidget *parent, Qt::WindowFlags flags)
1010 #else
1011 ParamViewer::ParamViewer(QWidget *parent, Qt::WFlags flags)
1012 #endif
1013 : QFrame(parent, flags), m_fx(0) {
1014 m_tablePageSet = new QStackedWidget(this);
1015 m_tablePageSet->addWidget(new QWidget());
1016
1017 /*-- SwatchViewerを表示/非表示するボタン --*/
1018 QPushButton *showSwatchButton = new QPushButton("", this);
1019 QLabel *swatchLabel = new QLabel(tr("Swatch Viewer"), this);
1020
1021 swatchLabel->setObjectName("TitleTxtLabel");
1022 showSwatchButton->setObjectName("menuToggleButton");
1023 showSwatchButton->setFixedSize(15, 15);
1024 showSwatchButton->setIcon(createQIcon("menu_toggle"));
1025 showSwatchButton->setCheckable(true);
1026 showSwatchButton->setChecked(false);
1027 showSwatchButton->setFocusPolicy(Qt::NoFocus);
1028
1029 QVBoxLayout *mainLayout = new QVBoxLayout(this);
1030 mainLayout->setMargin(0);
1031 mainLayout->setSpacing(0);
1032 {
1033 mainLayout->addWidget(m_tablePageSet, 1);
1034
1035 QHBoxLayout *showPreviewButtonLayout = new QHBoxLayout(this);
1036 showPreviewButtonLayout->setMargin(3);
1037 showPreviewButtonLayout->setSpacing(3);
1038 {
1039 showPreviewButtonLayout->addWidget(showSwatchButton, 0);
1040 showPreviewButtonLayout->addWidget(swatchLabel, 0);
1041 showPreviewButtonLayout->addStretch(1);
1042 }
1043 mainLayout->addLayout(showPreviewButtonLayout, 0);
1044 }
1045 setLayout(mainLayout);
1046
1047 connect(showSwatchButton, SIGNAL(toggled(bool)), this,
1048 SIGNAL(showSwatchButtonToggled(bool)));
1049 }
1050
1051 //-----------------------------------------------------------------------------
1052
~ParamViewer()1053 ParamViewer::~ParamViewer() {}
1054
1055 //-----------------------------------------------------------------------------
1056
setFx(const TFxP & currentFx,const TFxP & actualFx,int frame,ToonzScene * scene)1057 void ParamViewer::setFx(const TFxP ¤tFx, const TFxP &actualFx, int frame,
1058 ToonzScene *scene) {
1059 if (!actualFx) {
1060 m_tablePageSet->setCurrentIndex(0);
1061 return;
1062 }
1063 std::string name = actualFx->getFxType();
1064 if (name == "macroFx") {
1065 TMacroFx *macroFx = dynamic_cast<TMacroFx *>(currentFx.getPointer());
1066 if (macroFx) name = macroFx->getMacroFxType();
1067 }
1068
1069 int currentIndex = -1;
1070
1071 QMap<std::string, int>::iterator it;
1072 it = m_tableFxIndex.find(name);
1073 if (it == m_tableFxIndex.end()) {
1074 ParamsPageSet *pageSet = new ParamsPageSet(this);
1075 currentIndex = m_tablePageSet->addWidget(pageSet);
1076 m_tableFxIndex[name] = currentIndex;
1077 pageSet->createControls(actualFx);
1078 } else
1079 currentIndex = it.value();
1080
1081 assert(currentIndex >= 0);
1082
1083 m_tablePageSet->setCurrentIndex(currentIndex);
1084
1085 getCurrentPageSet()->setScene(scene);
1086
1087 if (m_fx != currentFx) {
1088 getCurrentPageSet()->setFx(currentFx, actualFx, frame);
1089 if (m_actualFx != actualFx) {
1090 m_actualFx = actualFx;
1091 QSize pageViewerPreferredSize =
1092 getCurrentPageSet()->getPreferredSize() + QSize(2, 50);
1093 emit preferredSizeChanged(pageViewerPreferredSize);
1094 }
1095 }
1096 }
1097
1098 //-----------------------------------------------------------------------------
1099
setScene(ToonzScene * scene)1100 void ParamViewer::setScene(ToonzScene *scene) {
1101 ParamsPageSet *paramsPageSet = getCurrentPageSet();
1102 if (!paramsPageSet) return;
1103 paramsPageSet->setScene(scene);
1104 }
1105
1106 //-----------------------------------------------------------------------------
1107
setIsCameraViewMode(bool isCameraViewMode)1108 void ParamViewer::setIsCameraViewMode(bool isCameraViewMode) {
1109 ParamsPageSet *paramsPageSet = getCurrentPageSet();
1110 if (!paramsPageSet) return;
1111 paramsPageSet->setIsCameraViewMode(isCameraViewMode);
1112 }
1113
1114 //-----------------------------------------------------------------------------
1115
update(int frame,bool onlyParam)1116 void ParamViewer::update(int frame, bool onlyParam) {
1117 ParamsPageSet *paramsPageSet = getCurrentPageSet();
1118 if (!paramsPageSet) return;
1119 paramsPageSet->updatePage(frame, onlyParam);
1120 }
1121
1122 //-----------------------------------------------------------------------------
1123
setPointValue(int index,const TPointD & p)1124 void ParamViewer::setPointValue(int index, const TPointD &p) {
1125 // Search the index-th param among all pages
1126 ParamsPageSet *pageSet = getCurrentPageSet();
1127 ParamsPage *page = 0;
1128
1129 for (int i = 0; i < pageSet->getParamsPageCount(); ++i) {
1130 page = pageSet->getParamsPage(i);
1131 int paramsCount = page->m_fields.count();
1132
1133 if (index <= paramsCount) break;
1134 index -= paramsCount;
1135 }
1136
1137 if (page) page->setPointValue(index, p);
1138 }
1139
1140 //-----------------------------------------------------------------------------
1141
getCurrentPageSet() const1142 ParamsPageSet *ParamViewer::getCurrentPageSet() const {
1143 return dynamic_cast<ParamsPageSet *>(m_tablePageSet->currentWidget());
1144 }
1145
1146 //=============================================================================
1147 // FxSettings
1148 //-----------------------------------------------------------------------------
1149
FxSettings(QWidget * parent,const TPixel32 & checkCol1,const TPixel32 & checkCol2)1150 FxSettings::FxSettings(QWidget *parent, const TPixel32 &checkCol1,
1151 const TPixel32 &checkCol2)
1152 : QSplitter(Qt::Vertical, parent)
1153 , m_frameHandle(0)
1154 , m_fxHandle(0)
1155 , m_xsheetHandle(0)
1156 , m_sceneHandle(0)
1157 , m_levelHandle(0)
1158 , m_objectHandle(0)
1159 , m_checkCol1(checkCol1)
1160 , m_checkCol2(checkCol2)
1161 , m_isCameraModeView(false)
1162 , m_container_height(184)
1163 , m_container_width(390) {
1164 // param viewer
1165 m_paramViewer = new ParamViewer(this);
1166 // swatch
1167 QWidget *swatchContainer = new QWidget(this);
1168 m_viewer = new SwatchViewer(swatchContainer);
1169 setWhiteBg();
1170 createToolBar();
1171
1172 m_paramViewer->setMinimumHeight(50);
1173 swatchContainer->setSizePolicy(QSizePolicy::MinimumExpanding,
1174 QSizePolicy::MinimumExpanding);
1175
1176 //---layout
1177 addWidget(m_paramViewer);
1178
1179 QVBoxLayout *swatchLayout = new QVBoxLayout(swatchContainer);
1180 swatchLayout->setMargin(0);
1181 swatchLayout->setSpacing(0);
1182 {
1183 swatchLayout->addWidget(m_viewer, 0, Qt::AlignHCenter);
1184
1185 QHBoxLayout *toolBarLayout = new QHBoxLayout(swatchContainer);
1186 {
1187 toolBarLayout->addWidget(m_toolBar, 0,
1188 Qt::AlignHCenter | Qt::AlignBottom);
1189 }
1190 swatchLayout->addLayout(toolBarLayout);
1191 }
1192 swatchContainer->setLayout(swatchLayout);
1193
1194 addWidget(swatchContainer);
1195
1196 //---signal-slot connections
1197 bool ret = true;
1198 ret = ret && connect(m_paramViewer, SIGNAL(currentFxParamChanged()),
1199 SLOT(updateViewer()));
1200 ret = ret &&
1201 connect(m_viewer, SIGNAL(pointPositionChanged(int, const TPointD &)),
1202 SLOT(onPointChanged(int, const TPointD &)));
1203 ret = ret && connect(m_paramViewer, SIGNAL(preferredSizeChanged(QSize)), this,
1204 SLOT(onPreferredSizeChanged(QSize)));
1205 ret = ret && connect(m_paramViewer, SIGNAL(showSwatchButtonToggled(bool)),
1206 this, SLOT(onShowSwatchButtonToggled(bool)));
1207 assert(ret);
1208
1209 swatchContainer->hide();
1210
1211 // Swatch updates should happen only at the end of a separator resize op.
1212 setStretchFactor(0, 1);
1213 setStretchFactor(1, 0);
1214 setOpaqueResize(false);
1215 }
1216
1217 //-----------------------------------------------------------------------------
1218
~FxSettings()1219 FxSettings::~FxSettings() {}
1220
1221 //-----------------------------------------------------------------------------
1222
setFxHandle(TFxHandle * fxHandle)1223 void FxSettings::setFxHandle(TFxHandle *fxHandle) {
1224 m_fxHandle = fxHandle;
1225 m_keyframeNavigator->setFxHandle(m_fxHandle);
1226
1227 ParamField::setFxHandle(m_fxHandle);
1228 }
1229
1230 //-----------------------------------------------------------------------------
1231
setFrameHandle(TFrameHandle * frameHandle)1232 void FxSettings::setFrameHandle(TFrameHandle *frameHandle) {
1233 m_frameHandle = frameHandle;
1234 m_keyframeNavigator->setFrameHandle(m_frameHandle);
1235 m_frameNavigator->setFrameHandle(m_frameHandle);
1236 }
1237
1238 //-----------------------------------------------------------------------------
1239
setXsheetHandle(TXsheetHandle * xsheetHandle)1240 void FxSettings::setXsheetHandle(TXsheetHandle *xsheetHandle) {
1241 m_xsheetHandle = xsheetHandle;
1242 }
1243
1244 //-----------------------------------------------------------------------------
1245
setSceneHandle(TSceneHandle * sceneHandle)1246 void FxSettings::setSceneHandle(TSceneHandle *sceneHandle) {
1247 m_sceneHandle = sceneHandle;
1248 setCurrentScene();
1249 }
1250
1251 //-----------------------------------------------------------------------------
1252
setLevelHandle(TXshLevelHandle * levelHandle)1253 void FxSettings::setLevelHandle(TXshLevelHandle *levelHandle) {
1254 m_levelHandle = levelHandle;
1255 }
1256
1257 //-----------------------------------------------------------------------------
1258
setObjectHandle(TObjectHandle * objectHandle)1259 void FxSettings::setObjectHandle(TObjectHandle *objectHandle) {
1260 m_objectHandle = objectHandle;
1261 }
1262
1263 //-----------------------------------------------------------------------------
1264
createToolBar()1265 void FxSettings::createToolBar() {
1266 m_toolBar = new QToolBar(this);
1267 m_toolBar->setMovable(false);
1268 m_toolBar->setFixedHeight(24);
1269 m_toolBar->setIconSize(QSize(20, 20));
1270 m_toolBar->setObjectName("MediumPaddingToolBar");
1271 // m_toolBar->setSizePolicy(QSizePolicy::MinimumExpanding,
1272 // QSizePolicy::MinimumExpanding);
1273
1274 // View mode
1275 QActionGroup *viewModeActGroup = new QActionGroup(m_toolBar);
1276 viewModeActGroup->setExclusive(false);
1277 // camera
1278 QIcon camera = createQIcon("camera");
1279 QAction *cameraAct = new QAction(camera, tr("&Camera Preview"), m_toolBar);
1280 cameraAct->setCheckable(true);
1281 viewModeActGroup->addAction(cameraAct);
1282 m_toolBar->addAction(cameraAct);
1283 // preview
1284 QIcon preview = createQIcon("preview");
1285 QAction *previewAct = new QAction(preview, tr("&Preview"), m_toolBar);
1286 previewAct->setCheckable(true);
1287 viewModeActGroup->addAction(previewAct);
1288 m_toolBar->addAction(previewAct);
1289 connect(viewModeActGroup, SIGNAL(triggered(QAction *)),
1290 SLOT(onViewModeChanged(QAction *)));
1291
1292 m_toolBar->addSeparator();
1293
1294 QActionGroup *viewModeGroup = new QActionGroup(m_toolBar);
1295 viewModeGroup->setExclusive(true);
1296
1297 QAction *whiteBg = new QAction(createQIcon("preview_white"),
1298 tr("&White Background"), m_toolBar);
1299 whiteBg->setCheckable(true);
1300 whiteBg->setChecked(true);
1301 viewModeGroup->addAction(whiteBg);
1302 connect(whiteBg, SIGNAL(triggered()), this, SLOT(setWhiteBg()));
1303 m_toolBar->addAction(whiteBg);
1304
1305 QAction *blackBg = new QAction(createQIcon("preview_black"),
1306 tr("&Black Background"), m_toolBar);
1307 blackBg->setCheckable(true);
1308 viewModeGroup->addAction(blackBg);
1309 connect(blackBg, SIGNAL(triggered()), this, SLOT(setBlackBg()));
1310 m_toolBar->addAction(blackBg);
1311
1312 m_checkboardBg = new QAction(createQIcon("preview_checkboard"),
1313 tr("&Checkered Background"), m_toolBar);
1314 m_checkboardBg->setCheckable(true);
1315 viewModeGroup->addAction(m_checkboardBg);
1316 connect(m_checkboardBg, SIGNAL(triggered()), this, SLOT(setCheckboardBg()));
1317 m_toolBar->addAction(m_checkboardBg);
1318
1319 m_toolBar->addSeparator();
1320
1321 m_keyframeNavigator = new FxKeyframeNavigator(m_toolBar);
1322 m_toolBar->addWidget(m_keyframeNavigator);
1323
1324 m_toolBar->addSeparator();
1325
1326 m_frameNavigator = new FrameNavigator(m_toolBar);
1327 m_frameNavigator->setFrameHandle(m_frameHandle);
1328 m_toolBar->addWidget(m_frameNavigator);
1329 }
1330
1331 //-----------------------------------------------------------------------------
1332
setFx(const TFxP & currentFx,const TFxP & actualFx)1333 void FxSettings::setFx(const TFxP ¤tFx, const TFxP &actualFx) {
1334 // disconnecting from the fxChanged() signals avoid useless and dangerous
1335 // updates!!!
1336 if (m_fxHandle)
1337 disconnect(m_fxHandle, SIGNAL(fxChanged()), this,
1338 SLOT(updateParamViewer()));
1339
1340 TFxP currentFxWithoutCamera = 0;
1341 if (currentFx && actualFx)
1342 currentFxWithoutCamera = getCurrentFx(currentFx, actualFx->getFxId());
1343
1344 if (currentFxWithoutCamera)
1345 TFxUtil::setKeyframe(currentFxWithoutCamera, m_frameHandle->getFrameIndex(),
1346 actualFx, m_frameHandle->getFrameIndex());
1347
1348 ToonzScene *scene = 0;
1349 if (m_sceneHandle) scene = m_sceneHandle->getScene();
1350
1351 int frameIndex = 0;
1352 if (m_frameHandle) frameIndex = m_frameHandle->getFrameIndex();
1353
1354 m_paramViewer->setFx(currentFxWithoutCamera, actualFx, frameIndex, scene);
1355 m_paramViewer->setIsCameraViewMode(m_isCameraModeView);
1356 m_viewer->setCameraMode(m_isCameraModeView);
1357
1358 TDimension cameraSize = TDimension(-1, -1);
1359 if (scene) cameraSize = scene->getCurrentCamera()->getRes();
1360 m_viewer->setCameraSize(cameraSize);
1361
1362 m_viewer->setFx(currentFx, actualFx, frameIndex);
1363
1364 if (m_fxHandle)
1365 connect(m_fxHandle, SIGNAL(fxChanged()), this, SLOT(updateParamViewer()));
1366 }
1367
1368 //-----------------------------------------------------------------------------
1369
setCurrentFrame()1370 void FxSettings::setCurrentFrame() {
1371 int frame = m_frameHandle->getFrameIndex();
1372 m_paramViewer->update(frame, false);
1373
1374 // if(m_isCameraModeView)
1375 setCurrentFx();
1376 m_viewer->updateFrame(frame);
1377 }
1378
1379 //-----------------------------------------------------------------------------
1380
changeTitleBar(TFx * fx)1381 void FxSettings::changeTitleBar(TFx *fx) {
1382 DockWidget *popup = dynamic_cast<DockWidget *>(parentWidget());
1383 if (!popup) return;
1384
1385 QString titleText(tr("Fx Settings"));
1386 if (fx) {
1387 titleText += tr(" : ");
1388 titleText += QString::fromStdWString(fx->getName());
1389 }
1390
1391 popup->setWindowTitle(titleText);
1392 }
1393
1394 //-----------------------------------------------------------------------------
1395
setCurrentFx()1396 void FxSettings::setCurrentFx() {
1397 TFx *currFx = m_fxHandle->getFx();
1398
1399 TFxP actualFx, currentFx;
1400 if (!currFx || 0 != dynamic_cast<TXsheetFx *>(currFx)) {
1401 actualFx = currentFx = TFxP();
1402 setFx(actualFx, currentFx);
1403 changeTitleBar(currentFx.getPointer());
1404 return;
1405 }
1406 TFxP fx(currFx);
1407 bool hasEmptyInput = false;
1408 if (TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(fx.getPointer()))
1409 fx = zfx->getZeraryFx();
1410 else
1411 hasEmptyInput = hasEmptyInputPort(fx);
1412 int frame = m_frameHandle->getFrame();
1413 ToonzScene *scene = m_sceneHandle->getScene();
1414 actualFx = fx;
1415 bool isEnabled = actualFx->getAttributes()->isEnabled();
1416 actualFx->getAttributes()->enable(true);
1417 if (hasEmptyInput)
1418 currentFx = actualFx;
1419 else if (m_viewer->isEnabled()) {
1420 if (!m_isCameraModeView)
1421 currentFx = buildSceneFx(scene, frame, actualFx, false);
1422 else {
1423 const TRenderSettings rs =
1424 scene->getProperties()->getPreviewProperties()->getRenderSettings();
1425 currentFx = buildPartialSceneFx(scene, (double)frame, actualFx, 1, false);
1426 }
1427 } else
1428 currentFx = TFxP();
1429
1430 if (currentFx) currentFx = currentFx->clone(true);
1431
1432 // se al frame corrente non c'e' il livello a cui e' applicato l'effetto:
1433 // current=0, actual!=0
1434 if (!currentFx) currentFx = actualFx->clone(false);
1435
1436 actualFx->getAttributes()->enable(isEnabled);
1437 setFx(currentFx, actualFx);
1438 changeTitleBar(currentFx.getPointer());
1439 }
1440
1441 //-----------------------------------------------------------------------------
1442
setCurrentScene()1443 void FxSettings::setCurrentScene() {
1444 ToonzScene *scene = m_sceneHandle->getScene();
1445 m_paramViewer->setScene(scene);
1446 }
1447
1448 //-----------------------------------------------------------------------------
1449
notifySceneChanged()1450 void FxSettings::notifySceneChanged() {
1451 TPixel32 col1, col2;
1452 Preferences::instance()->getChessboardColors(col1, col2);
1453 setCheckboardColors(col1, col2);
1454 }
1455
1456 //-----------------------------------------------------------------------------
1457
showEvent(QShowEvent * event)1458 void FxSettings::showEvent(QShowEvent *event) {
1459 setCurrentFx();
1460 setCurrentFrame();
1461 connect(m_frameHandle, SIGNAL(frameSwitched()), SLOT(setCurrentFrame()));
1462 if (m_fxHandle) {
1463 connect(m_paramViewer, SIGNAL(actualFxParamChanged()), m_fxHandle,
1464 SIGNAL(fxChanged()));
1465 connect(m_fxHandle, SIGNAL(fxChanged()), SLOT(updateParamViewer()));
1466 connect(m_fxHandle, SIGNAL(fxSettingsShouldBeSwitched()),
1467 SLOT(setCurrentFx()));
1468 }
1469 if (m_sceneHandle) {
1470 connect(m_sceneHandle, SIGNAL(sceneChanged()), this,
1471 SLOT(notifySceneChanged()));
1472 connect(m_sceneHandle, SIGNAL(sceneSwitched()), this,
1473 SLOT(setCurrentScene()));
1474 }
1475 if (m_xsheetHandle)
1476 connect(m_xsheetHandle, SIGNAL(xsheetChanged()), SLOT(setCurrentFx()));
1477 if (m_levelHandle)
1478 connect(m_levelHandle, SIGNAL(xshLevelChanged()), SLOT(setCurrentFx()));
1479 if (m_objectHandle)
1480 connect(m_objectHandle, SIGNAL(objectChanged(bool)), SLOT(setCurrentFx()));
1481 }
1482
1483 //-----------------------------------------------------------------------------
1484
hideEvent(QHideEvent *)1485 void FxSettings::hideEvent(QHideEvent *) {
1486 setFx(0, 0);
1487 disconnect(m_frameHandle, SIGNAL(frameSwitched()), this,
1488 SLOT(setCurrentFrame()));
1489 if (m_fxHandle) {
1490 disconnect(m_fxHandle, SIGNAL(fxChanged()), this, SLOT(setCurrentFx()));
1491 disconnect(m_fxHandle, SIGNAL(fxChanged()), this,
1492 SLOT(updateParamViewer()));
1493 disconnect(m_fxHandle, SIGNAL(fxSettingsShouldBeSwitched()), this,
1494 SLOT(setCurrentFx()));
1495 }
1496 if (m_sceneHandle) {
1497 disconnect(m_sceneHandle, SIGNAL(sceneChanged()), this,
1498 SLOT(notifySceneChanged()));
1499 disconnect(m_sceneHandle, SIGNAL(sceneSwitched()), this,
1500 SLOT(setCurrentScene()));
1501 }
1502 if (m_xsheetHandle)
1503 disconnect(m_xsheetHandle, SIGNAL(xsheetChanged()), this,
1504 SLOT(setCurrentFx()));
1505 if (m_levelHandle)
1506 disconnect(m_levelHandle, SIGNAL(xshLevelChanged()), this,
1507 SLOT(setCurrentFx()));
1508 if (m_objectHandle)
1509 disconnect(m_objectHandle, SIGNAL(objectChanged(bool)), this,
1510 SLOT(setCurrentFx()));
1511 }
1512
1513 //-----------------------------------------------------------------------------
1514
setCheckboardColors(const TPixel32 & col1,const TPixel32 & col2)1515 void FxSettings::setCheckboardColors(const TPixel32 &col1,
1516 const TPixel32 &col2) {
1517 m_checkCol1 = col1;
1518 m_checkCol2 = col2;
1519 if (m_checkboardBg->isChecked())
1520 m_viewer->setBgPainter(m_checkCol1, m_checkCol2);
1521 }
1522
1523 //-----------------------------------------------------------------------------
1524
setWhiteBg()1525 void FxSettings::setWhiteBg() { m_viewer->setBgPainter(TPixel32::White); }
1526
1527 //-----------------------------------------------------------------------------
1528
setBlackBg()1529 void FxSettings::setBlackBg() { m_viewer->setBgPainter(TPixel32::Black); }
1530
1531 //-----------------------------------------------------------------------------
1532
setCheckboardBg()1533 void FxSettings::setCheckboardBg() {
1534 m_viewer->setBgPainter(m_checkCol1, m_checkCol2);
1535 }
1536
1537 //-----------------------------------------------------------------------------
1538
updateViewer()1539 void FxSettings::updateViewer() {
1540 if (m_viewer->isEnabled())
1541 m_viewer->updateFrame(m_frameHandle->getFrameIndex());
1542 }
1543
1544 //-----------------------------------------------------------------------------
1545
updateParamViewer()1546 void FxSettings::updateParamViewer() {
1547 if (!m_paramViewer || !m_frameHandle) return;
1548 m_paramViewer->update(m_frameHandle->getFrameIndex(), true);
1549 }
1550
1551 //-----------------------------------------------------------------------------
1552
onPointChanged(int index,const TPointD & p)1553 void FxSettings::onPointChanged(int index, const TPointD &p) {
1554 m_paramViewer->setPointValue(index, p);
1555 }
1556
1557 //-----------------------------------------------------------------------------
1558
onViewModeChanged(QAction * triggeredAct)1559 void FxSettings::onViewModeChanged(QAction *triggeredAct) {
1560 setFocus();
1561 QString name = triggeredAct->text();
1562 bool actIsChecked = triggeredAct->isChecked();
1563 QList<QAction *> actions = m_toolBar->actions();
1564 QAction *cameraAct = actions[0];
1565 QAction *previewAct = actions[1];
1566 if (name == previewAct->text()) {
1567 if (cameraAct->isChecked()) cameraAct->setChecked(false);
1568 if (actIsChecked) {
1569 m_isCameraModeView = false;
1570 m_paramViewer->setIsCameraViewMode(false);
1571 setCurrentFx();
1572 }
1573 m_viewer->setEnable(actIsChecked);
1574 } else if (name == cameraAct->text()) {
1575 if (previewAct->isChecked()) previewAct->setChecked(false);
1576 if (actIsChecked) {
1577 m_isCameraModeView = true;
1578 m_paramViewer->setIsCameraViewMode(true);
1579 setCurrentFx();
1580 }
1581 m_viewer->setEnable(actIsChecked);
1582 }
1583 }
1584
1585 //-----------------------------------------------------------------------------
1586
onPreferredSizeChanged(QSize pvBestSize)1587 void FxSettings::onPreferredSizeChanged(QSize pvBestSize) {
1588 QSize popupBestSize = pvBestSize;
1589
1590 // Set minimum size, just in case
1591 popupBestSize.setHeight(std::max(popupBestSize.height(), 85));
1592 popupBestSize.setWidth(std::max(popupBestSize.width(), 390));
1593
1594 if (m_toolBar->isVisible()) {
1595 popupBestSize += QSize(0, m_viewer->height() + m_toolBar->height() + 4);
1596 popupBestSize.setWidth(
1597 std::max(popupBestSize.width(), m_viewer->width() + 13));
1598 }
1599
1600 DockWidget *popup = dynamic_cast<DockWidget *>(parentWidget());
1601 if (popup && popup->isFloating()) {
1602 QRect geom = popup->geometry();
1603 geom.setSize(popupBestSize);
1604 popup->setGeometry(geom);
1605 popup->update();
1606 }
1607 }
1608
1609 //-----------------------------------------------------------------------------
1610
onShowSwatchButtonToggled(bool on)1611 void FxSettings::onShowSwatchButtonToggled(bool on) {
1612 QWidget *bottomContainer = widget(1);
1613
1614 if (!on) {
1615 m_container_height =
1616 bottomContainer->height() + handleWidth() /* ハンドル幅 */;
1617 m_container_width = m_viewer->width() + 13;
1618 }
1619 bottomContainer->setVisible(on);
1620
1621 DockWidget *popup = dynamic_cast<DockWidget *>(parentWidget());
1622 if (popup && popup->isFloating()) {
1623 QRect geom = popup->geometry();
1624
1625 int height_change = (on) ? m_container_height : -m_container_height;
1626 int width_change = 0;
1627
1628 if (on && m_container_width > geom.width())
1629 width_change = m_container_width - geom.width();
1630
1631 geom.setSize(geom.size() + QSize(width_change, height_change));
1632 popup->setGeometry(geom);
1633 popup->update();
1634 }
1635 }
1636
1637 //-----------------------------------------------------------------------------
1638