diff --git a/stuff/config/current.txt b/stuff/config/current.txt
index 9810bda..d88e4b1 100644
--- a/stuff/config/current.txt
+++ b/stuff/config/current.txt
@@ -1327,30 +1327,40 @@
- "STD_iwa_BokehAdvancedFx.hardness1" "Source1 Hardness"
- "STD_iwa_BokehAdvancedFx.depth_ref1" "Depth Image"
- "STD_iwa_BokehAdvancedFx.depthRange1" "Source1 Depth Range"
+ - "STD_iwa_BokehAdvancedFx.fillGap1" "Fill Gap"
+ - "STD_iwa_BokehAdvancedFx.doMedian1" "Use Median"
- "STD_iwa_BokehAdvancedFx.distance2" "Source2 Distance"
- "STD_iwa_BokehAdvancedFx.bokeh_adjustment2" "Source2 Bokeh Adjustment"
- "STD_iwa_BokehAdvancedFx.hardness2" "Source2 Hardness"
- "STD_iwa_BokehAdvancedFx.depth_ref2" "Depth Image"
- "STD_iwa_BokehAdvancedFx.depthRange2" "Source2 Depth Range"
+ - "STD_iwa_BokehAdvancedFx.fillGap2" "Fill Gap"
+ - "STD_iwa_BokehAdvancedFx.doMedian2" "Use Median"
- "STD_iwa_BokehAdvancedFx.distance3" "Source3 Distance"
- "STD_iwa_BokehAdvancedFx.bokeh_adjustment3" "Source3 Bokeh Adjustment"
- "STD_iwa_BokehAdvancedFx.hardness3" "Source3 Hardness"
- "STD_iwa_BokehAdvancedFx.depth_ref3" "Depth Image"
- "STD_iwa_BokehAdvancedFx.depthRange3" "Source3 Depth Range"
+ - "STD_iwa_BokehAdvancedFx.fillGap3" "Fill Gap"
+ - "STD_iwa_BokehAdvancedFx.doMedian3" "Use Median"
- "STD_iwa_BokehAdvancedFx.distance4" "Source4 Distance"
- "STD_iwa_BokehAdvancedFx.bokeh_adjustment4" "Source4 Bokeh Adjustment"
- "STD_iwa_BokehAdvancedFx.hardness4" "Source4 Hardness"
- "STD_iwa_BokehAdvancedFx.depth_ref4" "Depth Image"
- "STD_iwa_BokehAdvancedFx.depthRange4" "Source4 Depth Range"
+ - "STD_iwa_BokehAdvancedFx.fillGap4" "Fill Gap"
+ - "STD_iwa_BokehAdvancedFx.doMedian4" "Use Median"
- "STD_iwa_BokehAdvancedFx.distance5" "Source5 Distance"
- "STD_iwa_BokehAdvancedFx.bokeh_adjustment5" "Source5 Bokeh Adjustment"
- "STD_iwa_BokehAdvancedFx.hardness5" "Source5 Hardness"
- "STD_iwa_BokehAdvancedFx.depth_ref5" "Depth Image"
- "STD_iwa_BokehAdvancedFx.depthRange5" "Source5 Depth Range"
+ - "STD_iwa_BokehAdvancedFx.fillGap5" "Fill Gap"
+ - "STD_iwa_BokehAdvancedFx.doMedian5" "Use Median"
- "STD_iwa_TimeCodeFx" "TimeCode Iwa"
- "STD_iwa_TimeCodeFx.displayType" "Display Type"
diff --git a/stuff/profiles/layouts/fxs/STD_iwa_BokehAdvancedFx.xml b/stuff/profiles/layouts/fxs/STD_iwa_BokehAdvancedFx.xml
index cb4f562..b12f23e 100644
--- a/stuff/profiles/layouts/fxs/STD_iwa_BokehAdvancedFx.xml
+++ b/stuff/profiles/layouts/fxs/STD_iwa_BokehAdvancedFx.xml
@@ -11,7 +11,11 @@
distance1
bokeh_adjustment1
hardness1
- depth_ref1
+
+ depth_ref1
+ fillGap1
+ doMedian1
+
depthRange1
@@ -19,7 +23,11 @@
distance2
bokeh_adjustment2
hardness2
- depth_ref2
+
+ depth_ref2
+ fillGap2
+ doMedian2
+
depthRange2
@@ -27,7 +35,11 @@
distance3
bokeh_adjustment3
hardness3
- depth_ref3
+
+ depth_ref3
+ fillGap3
+ doMedian3
+
depthRange3
@@ -35,7 +47,11 @@
distance4
bokeh_adjustment4
hardness4
- depth_ref4
+
+ depth_ref4
+ fillGap4
+ doMedian4
+
depthRange4
@@ -43,7 +59,11 @@
distance5
bokeh_adjustment5
hardness5
- depth_ref5
+
+ depth_ref5
+ fillGap5
+ doMedian5
+
depthRange5
@@ -55,6 +75,27 @@
hardness4
hardness5
+
+ fillGap1
+ doMedian1
+
+
+ fillGap2
+ doMedian2
+
+
+ fillGap3
+ doMedian3
+
+
+ fillGap4
+ doMedian4
+
+
+ fillGap5
+ doMedian5
+
+
diff --git a/toonz/sources/stdfx/igs_rotate_blur.cpp b/toonz/sources/stdfx/igs_rotate_blur.cpp
index 3a4b51b..4e0684a 100644
--- a/toonz/sources/stdfx/igs_rotate_blur.cpp
+++ b/toonz/sources/stdfx/igs_rotate_blur.cpp
@@ -362,8 +362,8 @@ int igs::rotate_blur::reference_margin(
const double blur_radius, /* ぼかしの始まる半径 */
const double spin_radius, /* ゼロ以上でspin指定となり、
かつぼかし強弱の一定になる半径となる */
- const int type // 0: Accelerator, 1: Uniform Angle, 2: Uniform Length
-) {
+ const int type, // 0: Accelerator, 1: Uniform Angle, 2: Uniform Length
+ const double ellipse_aspect_ratio) {
/* 強度のないとき、なにもしない */
if (degree <= 0.0) {
return 0;
@@ -402,5 +402,13 @@ int igs::rotate_blur::reference_margin(
margin1 = margin2;
}
+ // Consider ellipse deformation.
+ // Instead of precise computing, return the maximum possible value.
+ if (ellipse_aspect_ratio != 1.0) {
+ double axis_x = 2.0 * ellipse_aspect_ratio / (ellipse_aspect_ratio + 1.0);
+ double axis_y = axis_x / ellipse_aspect_ratio;
+ margin1 *= std::max(axis_x, axis_y);
+ }
+
return static_cast(ceil(margin1));
}
diff --git a/toonz/sources/stdfx/igs_rotate_blur.h b/toonz/sources/stdfx/igs_rotate_blur.h
index 4bb1d1b..37e4c8f 100644
--- a/toonz/sources/stdfx/igs_rotate_blur.h
+++ b/toonz/sources/stdfx/igs_rotate_blur.h
@@ -44,8 +44,8 @@ IGS_ROTATE_BLUR_EXPORT int reference_margin(
const double blur_radius, /* ぼかしの始まる半径 */
const double spin_radius, /* ゼロ以上でspin指定となり、
かつぼかし強弱の一定になる半径となる */
- const int type // 0: Accelerator, 1: Uniform Angle, 2: Uniform Length
-);
+ const int type, // 0: Accelerator, 1: Uniform Angle, 2: Uniform Length
+ const double ellipse_aspect_ratio = 1.0);
} // namespace rotate_blur
} // namespace igs
diff --git a/toonz/sources/stdfx/ino_spin_blur.cpp b/toonz/sources/stdfx/ino_spin_blur.cpp
index dc59acd..74027b1 100644
--- a/toonz/sources/stdfx/ino_spin_blur.cpp
+++ b/toonz/sources/stdfx/ino_spin_blur.cpp
@@ -86,8 +86,8 @@ public:
static_cast(ceil(bBox.getLy())),
static_cast(ceil(bBox.getLx())), center,
this->m_blur->getValue(frame), this->m_radius->getValue(frame) * scale,
- ((0 < this->m_type->getValue()) ? 0.0 : (bBox.getLy() / 2.0)),
- this->m_type->getValue());
+ bBox.getLy() / 2.0, this->m_type->getValue(),
+ this->m_ellipse_aspect_ratio->getValue(frame));
}
void get_render_enlarge(const double frame, const TAffine affine,
TRectD &bBox) {
diff --git a/toonz/sources/stdfx/iwa_bokeh_advancedfx.cpp b/toonz/sources/stdfx/iwa_bokeh_advancedfx.cpp
index 7fd6e43..f3c4b39 100644
--- a/toonz/sources/stdfx/iwa_bokeh_advancedfx.cpp
+++ b/toonz/sources/stdfx/iwa_bokeh_advancedfx.cpp
@@ -144,6 +144,8 @@ Iwa_BokehAdvancedFx::Iwa_BokehAdvancedFx()
m_layerParams[layer].m_hardness = TDoubleParamP(0.3);
m_layerParams[layer].m_depth_ref = TIntParamP(0);
m_layerParams[layer].m_depthRange = TDoubleParamP(1.0);
+ m_layerParams[layer].m_fillGap = TBoolParamP(true);
+ m_layerParams[layer].m_doMedian = TBoolParamP(false);
std::string str = QString("Source%1").arg(layer + 1).toStdString();
addInputPort(str, m_layerParams[layer].m_source);
@@ -158,6 +160,10 @@ Iwa_BokehAdvancedFx::Iwa_BokehAdvancedFx()
m_layerParams[layer].m_depth_ref);
bindParam(this, QString("depthRange%1").arg(layer + 1).toStdString(),
m_layerParams[layer].m_depthRange);
+ bindParam(this, QString("fillGap%1").arg(layer + 1).toStdString(),
+ m_layerParams[layer].m_fillGap);
+ bindParam(this, QString("doMedian%1").arg(layer + 1).toStdString(),
+ m_layerParams[layer].m_doMedian);
m_layerParams[layer].m_distance->setValueRange(0.0, 1.0);
m_layerParams[layer].m_bokehAdjustment->setValueRange(0.0, 2.0);
@@ -303,8 +309,8 @@ void Iwa_BokehAdvancedFx::doCompute(TTile& tile, double frame,
m_layerParams[index].m_bokehAdjustment->getValue(frame);
layerValue.depthRange = m_layerParams[index].m_depthRange->getValue(frame);
layerValue.distancePrecision = 10;
- layerValue.fillGap = true;
- layerValue.doMedian = false;
+ layerValue.fillGap = m_layerParams[index].m_fillGap->getValue();
+ layerValue.doMedian = m_layerParams[index].m_doMedian->getValue();
layerValues.append(layerValue);
}
diff --git a/toonz/sources/stdfx/iwa_bokeh_advancedfx.h b/toonz/sources/stdfx/iwa_bokeh_advancedfx.h
index 06d03c8..fa29d7d 100644
--- a/toonz/sources/stdfx/iwa_bokeh_advancedfx.h
+++ b/toonz/sources/stdfx/iwa_bokeh_advancedfx.h
@@ -41,6 +41,8 @@ protected:
TIntParamP m_depth_ref; // port index of depth reference image
TDoubleParamP m_depthRange; // distance range varies depends on the
// brightness of the reference image (0-1)
+ TBoolParamP m_fillGap;
+ TBoolParamP m_doMedian;
};
std::array m_layerParams;
diff --git a/toonz/sources/toonzlib/outputproperties.cpp b/toonz/sources/toonzlib/outputproperties.cpp
index a0a3473..6568f8f 100644
--- a/toonz/sources/toonzlib/outputproperties.cpp
+++ b/toonz/sources/toonzlib/outputproperties.cpp
@@ -164,6 +164,8 @@ TPropertyGroup *TOutputProperties::getFileFormatProperties(std::string ext) {
TPropertyGroup *ret = Tiio::makeWriterProperties(ext);
m_formatProperties[ext] = ret;
return ret;
+ } else if (ext == "mov" || ext == "3gp") {
+ return it->second;
} else {
// Try to merge settings instead of overriding them
TPropertyGroup *ret = Tiio::makeWriterProperties(ext);
diff --git a/toonz/sources/toonzqt/fxsettings.cpp b/toonz/sources/toonzqt/fxsettings.cpp
index 7a00ba2..40bc869 100644
--- a/toonz/sources/toonzqt/fxsettings.cpp
+++ b/toonz/sources/toonzqt/fxsettings.cpp
@@ -102,6 +102,36 @@ inputFx);
}
}
*/
+
+// find the field by parameter name and register the field and its label widget
+bool findItemByParamName(QLayout *layout, std::string name,
+ QList &ret) {
+ for (int i = 0; i < layout->count(); i++) {
+ QLayoutItem *item = layout->itemAt(i);
+ if (!item) continue;
+ if (item->widget()) {
+ ParamField *pf = dynamic_cast(item->widget());
+ if (pf && pf->getParamName().toStdString() == name) {
+ ret.push_back(pf);
+ if (i > 0 && layout->itemAt(i - 1)->widget()) {
+ QLabel *label =
+ dynamic_cast(layout->itemAt(i - 1)->widget());
+ if (label) ret.push_back(label);
+ }
+ return true;
+ }
+ // the widget may be a container of another layout
+ else if (item->widget()->layout()) {
+ if (findItemByParamName(item->widget()->layout(), name, ret))
+ return true;
+ }
+ } else if (item->layout()) {
+ if (findItemByParamName(item->layout(), name, ret)) return true;
+ }
+ }
+ return false;
+};
+
} // namespace
//=============================================================================
@@ -369,52 +399,15 @@ void ParamsPage::setPageField(TIStream &is, const TFxP &fx, bool isVertical) {
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(w);
- if (pf) {
- if (pf->getParamName().toStdString() == name) {
- if (tagName == "controller")
- controller_bpf = dynamic_cast(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も1段階探す --*/
- else {
- QGridLayout *gridLay = dynamic_cast(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(li_s->widget());
- if (pf_s) {
- if (pf_s->getParamName().toStdString() == name) {
- if (tagName == "controller")
- controller_bpf = dynamic_cast(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());
- }
- }
- }
- }
- }
+
+ QList widgets;
+ if (findItemByParamName(m_mainLayout, name, widgets)) {
+ if (tagName == "controller") {
+ controller_bpf = dynamic_cast(widgets[0]);
+ } else if (tagName == "on")
+ on_items.append(widgets);
+ else if (tagName == "off")
+ off_items.append(widgets);
}
} else
throw TException("unexpected tag " + tagName);
@@ -866,8 +859,8 @@ 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は上下左右のマージン --*/
+ pagePreferredSize + QSize(m_tabBarContainer->height() + 2,
+ 2)); /*-- 2は上下左右のマージン --*/
QScrollArea *pane = new QScrollArea(this);
pane->setWidgetResizable(true);
@@ -970,8 +963,8 @@ void ParamsPageSet::createPage(TIStream &is, const TFxP &fx, int index) {
/*-- このFxで最大サイズのページに合わせてダイアログをリサイズ --*/
QSize pagePreferredSize = paramsPage->getPreferredSize();
m_preferredSize = m_preferredSize.expandedTo(
- pagePreferredSize + QSize(m_tabBarContainer->height() + 2,
- 2)); /*-- 2は上下左右のマージン --*/
+ pagePreferredSize + QSize(m_tabBarContainer->height() + 2,
+ 2)); /*-- 2は上下左右のマージン --*/
QScrollArea *scrollAreaPage = new QScrollArea(this);
scrollAreaPage->setWidgetResizable(true);
@@ -996,7 +989,7 @@ void ParamsPageSet::recomputePreferredSize() {
if (!page) continue;
QSize pagePreferredSize = page->getPreferredSize();
newSize = newSize.expandedTo(pagePreferredSize +
- QSize(m_tabBarContainer->height() + 2, 2));
+ QSize(m_tabBarContainer->height() + 2, 2));
}
if (!newSize.isEmpty()) {
m_preferredSize = newSize;
@@ -1235,7 +1228,7 @@ FxSettings::FxSettings(QWidget *parent, const TPixel32 &checkCol1,
//---signal-slot connections
bool ret = true;
ret = ret && connect(m_paramViewer, SIGNAL(currentFxParamChanged()),
- SLOT(updateViewer()));
+ SLOT(updateViewer()));
ret = ret &&
connect(m_viewer, SIGNAL(pointPositionChanged(int, const TPointD &)),
SLOT(onPointChanged(int, const TPointD &)));