From 87b298cee51d41bad66ce45273a93bf9f2deb624 Mon Sep 17 00:00:00 2001 From: Rodney Date: Nov 12 2019 13:35:39 +0000 Subject: Merge pull request #2873 from shun-iwasawa/g/spin_gradient_iwa New Fx: Spin Gradient Iwa Fx --- diff --git a/stuff/config/current.txt b/stuff/config/current.txt index e8ac97b..7aa6923 100644 --- a/stuff/config/current.txt +++ b/stuff/config/current.txt @@ -1286,6 +1286,14 @@ "STD_iwa_CorridorGradientFx.inner_color" "Inner Color" "STD_iwa_CorridorGradientFx.outer_color" "Outer Color" + "STD_iwa_SpinGradientFx" "Spin Gradient Iwa" + "STD_iwa_SpinGradientFx.center" "Center" + "STD_iwa_SpinGradientFx.curveType" "Type" + "STD_iwa_SpinGradientFx.startAngle" "Start Angle" + "STD_iwa_SpinGradientFx.startColor" "Start Color" + "STD_iwa_SpinGradientFx.endAngle" "End Angle" + "STD_iwa_SpinGradientFx.endColor" "End Color" + STD_iwa_TiledParticlesFx "Tiled Particles Iwa" diff --git a/stuff/profiles/layouts/fxs/STD_iwa_SpinGradientFx.xml b/stuff/profiles/layouts/fxs/STD_iwa_SpinGradientFx.xml new file mode 100644 index 0000000..8ab64c5 --- /dev/null +++ b/stuff/profiles/layouts/fxs/STD_iwa_SpinGradientFx.xml @@ -0,0 +1,12 @@ + + + center + curveType + + startAngle + startColor + + endAngle + endColor + + diff --git a/stuff/profiles/layouts/fxs/fxs.lst b/stuff/profiles/layouts/fxs/fxs.lst index ca26b7c..f2d13c3 100644 --- a/stuff/profiles/layouts/fxs/fxs.lst +++ b/stuff/profiles/layouts/fxs/fxs.lst @@ -45,6 +45,7 @@ STD_spiralFx STD_squareGradientFx STD_iwa_CorridorGradientFx + STD_iwa_SpinGradientFx STD_iwa_AdjustExposureFx diff --git a/toonz/sources/include/tparamuiconcept.h b/toonz/sources/include/tparamuiconcept.h index b764e03..8a62c37 100644 --- a/toonz/sources/include/tparamuiconcept.h +++ b/toonz/sources/include/tparamuiconcept.h @@ -36,12 +36,14 @@ public: enum Type { NONE = 0, - RADIUS, // Distance from a point (radius). Represented by { - // [TDoubleParamP], TPointParamP } - WIDTH, // Width, as distance from a line with given angle. { - // [TDoubleParamP], TDoubleParamP } - ANGLE, // An angle. { - // [TDoubleParamP] } + RADIUS, // Distance from a point (radius). Represented by { + // [TDoubleParamP], TPointParamP } + WIDTH, // Width, as distance from a line with given angle. { + // [TDoubleParamP], TDoubleParamP } + ANGLE, // An angle. { + // [TDoubleParamP] } + ANGLE_2, // An angle range defined with start and end angles. + // { [2 TDoubleParamP], TDoubleParamP } POINT, // A Point. { // [TPointParamP] } diff --git a/toonz/sources/stdfx/CMakeLists.txt b/toonz/sources/stdfx/CMakeLists.txt index 4aa2aaf..e871986 100644 --- a/toonz/sources/stdfx/CMakeLists.txt +++ b/toonz/sources/stdfx/CMakeLists.txt @@ -77,6 +77,7 @@ set(HEADERS iwa_bokehreffx.h iwa_textfx.h iwa_corridorgradientfx.h + iwa_spingradientfx.h ) set(SOURCES @@ -260,6 +261,7 @@ set(SOURCES iwa_barreldistortfx.cpp iwa_textfx.cpp iwa_corridorgradientfx.cpp + iwa_spingradientfx.cpp ) set(OBJCSOURCES diff --git a/toonz/sources/stdfx/iwa_spingradientfx.cpp b/toonz/sources/stdfx/iwa_spingradientfx.cpp new file mode 100644 index 0000000..812be16 --- /dev/null +++ b/toonz/sources/stdfx/iwa_spingradientfx.cpp @@ -0,0 +1,174 @@ +#include "iwa_spingradientfx.h" + +#include "trop.h" +#include "tparamuiconcept.h" +#include "tspectrumparam.h" +#include "gradients.h" + +#include + +#include +#include + +//------------------------------------------------------------ + +Iwa_SpinGradientFx::Iwa_SpinGradientFx() + : m_center(TPointD(0.0, 0.0)) + , m_startAngle(0.0) + , m_endAngle(0.0) + , m_startColor(TPixel32::Black) + , m_endColor(TPixel32::White) + , m_curveType(new TIntEnumParam()) { + m_center->getX()->setMeasureName("fxLength"); + m_center->getY()->setMeasureName("fxLength"); + bindParam(this, "center", m_center); + + m_startAngle->setValueRange(-360, 720); + m_endAngle->setValueRange(-360, 720); + bindParam(this, "startAngle", m_startAngle); + bindParam(this, "endAngle", m_endAngle); + + m_curveType->addItem(EaseInOut, "Ease In-Out"); + m_curveType->addItem(Linear, "Linear"); + m_curveType->addItem(EaseIn, "Ease In"); + m_curveType->addItem(EaseOut, "Ease Out"); + m_curveType->setDefaultValue(Linear); + m_curveType->setValue(Linear); + bindParam(this, "curveType", m_curveType); + + bindParam(this, "startColor", m_startColor); + bindParam(this, "endColor", m_endColor); +} + +//------------------------------------------------------------ + +bool Iwa_SpinGradientFx::doGetBBox(double frame, TRectD &bBox, + const TRenderSettings &ri) { + bBox = TConsts::infiniteRectD; + return true; +} + +//------------------------------------------------------------ +namespace { +template +void doSpinGradientT(RASTER ras, TDimensionI dim, TPointD centerPos, + double startAngle, double endAngle, + const TSpectrumT &spectrum, + GradientCurveType type) { + auto getFactor = [&](double angle) { + double p = angle - startAngle; + if (p < 0) p += 2.0 * M_PI; + double range = endAngle - startAngle; + if (range <= 0) range += 2.0 * M_PI; + + double t; + if (range >= p) + t = p / range; + else if (M_PI + range / 2.0 > p) + t = 1.0; + else + t = 0.0; + + double factor; + switch (type) { + case Linear: + factor = t; + break; + case EaseIn: + factor = t * t; + break; + case EaseOut: + factor = 1.0 - (1.0 - t) * (1.0 - t); + break; + case EaseInOut: + default: + factor = (-2 * t + 3) * (t * t); + break; + } + return factor; + }; + + ras->lock(); + for (int j = 0; j < ras->getLy(); j++) { + PIXEL *pix = ras->pixels(j); + PIXEL *endPix = pix + ras->getLx(); + double dy = (double)j - centerPos.y; + double dx = -centerPos.x; + while (pix < endPix) { + double angle = std::atan2(dy, dx); + double factor = getFactor(angle); + *pix++ = spectrum.getPremultipliedValue(factor); + dx += 1.0; + } + } + ras->unlock(); +} +} // namespace + +//------------------------------------------------------------ + +void Iwa_SpinGradientFx::doCompute(TTile &tile, double frame, + const TRenderSettings &ri) { + if (!((TRaster32P)tile.getRaster()) && !((TRaster64P)tile.getRaster())) { + throw TRopException("unsupported input pixel type"); + } + + // convert shape position to render region coordinate + TAffine aff = ri.m_affine; + TDimensionI dimOut(tile.getRaster()->getLx(), tile.getRaster()->getLy()); + TPointD dimOffset((float)dimOut.lx / 2.0f, (float)dimOut.ly / 2.0f); + TPointD centerPos = aff * m_center->getValue(frame) - + (tile.m_pos + tile.getRaster()->getCenterD()) + dimOffset; + + std::vector colors = { + TSpectrum::ColorKey(0, m_startColor->getValue(frame)), + TSpectrum::ColorKey(1, m_endColor->getValue(frame))}; + TSpectrumParamP m_colors = TSpectrumParamP(colors); + + auto conv2RadianAndClamp = [](double angle) { + double ret = angle * M_PI / 180.0; + while (ret < -M_PI) { + ret += 2.0 * M_PI; + } + while (ret >= M_PI) { + ret -= 2.0 * M_PI; + } + return ret; + }; + + double startAngle = conv2RadianAndClamp(m_startAngle->getValue(frame)); + double endAngle = conv2RadianAndClamp(m_endAngle->getValue(frame)); + + tile.getRaster()->clear(); + TRaster32P outRas32 = (TRaster32P)tile.getRaster(); + TRaster64P outRas64 = (TRaster64P)tile.getRaster(); + if (outRas32) + doSpinGradientT( + outRas32, dimOut, centerPos, startAngle, endAngle, + m_colors->getValue(frame), (GradientCurveType)m_curveType->getValue()); + else if (outRas64) + doSpinGradientT( + outRas64, dimOut, centerPos, startAngle, endAngle, + m_colors->getValue64(frame), + (GradientCurveType)m_curveType->getValue()); +} + +//------------------------------------------------------------ + +void Iwa_SpinGradientFx::getParamUIs(TParamUIConcept *&concepts, int &length) { + concepts = new TParamUIConcept[length = 2]; + + concepts[0].m_type = TParamUIConcept::ANGLE_2; + concepts[0].m_label = "Angle"; + concepts[0].m_params.push_back(m_startAngle); + concepts[0].m_params.push_back(m_endAngle); + concepts[0].m_params.push_back(m_center); + + concepts[1].m_type = TParamUIConcept::POINT; + concepts[1].m_label = "Center"; + concepts[1].m_params.push_back(m_center); +} + +//------------------------------------------------------------ + +FX_PLUGIN_IDENTIFIER(Iwa_SpinGradientFx, "iwa_SpinGradientFx"); diff --git a/toonz/sources/stdfx/iwa_spingradientfx.h b/toonz/sources/stdfx/iwa_spingradientfx.h new file mode 100644 index 0000000..264f7ce --- /dev/null +++ b/toonz/sources/stdfx/iwa_spingradientfx.h @@ -0,0 +1,29 @@ +#pragma once +#ifndef IWA_SPINGRADIENTFX_H +#define IWA_SPINGRADIENTFX_H + +#include "tfxparam.h" +#include "stdfx.h" +#include "tparamset.h" + +class Iwa_SpinGradientFx final : public TStandardZeraryFx { + FX_PLUGIN_DECLARATION(Iwa_SpinGradientFx) + + TIntEnumParamP m_curveType; + TPointParamP m_center; + TDoubleParamP m_startAngle, m_endAngle; + TPixelParamP m_startColor, m_endColor; + +public: + Iwa_SpinGradientFx(); + + bool canHandle(const TRenderSettings &info, double frame) override { + return true; + } + bool doGetBBox(double frame, TRectD &bBox, + const TRenderSettings &ri) override; + void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override; + void getParamUIs(TParamUIConcept *&concepts, int &length) override; +}; + +#endif \ No newline at end of file diff --git a/toonz/sources/tnztools/edittoolgadgets.cpp b/toonz/sources/tnztools/edittoolgadgets.cpp index 489c4d8..2cd9d93 100644 --- a/toonz/sources/tnztools/edittoolgadgets.cpp +++ b/toonz/sources/tnztools/edittoolgadgets.cpp @@ -553,6 +553,171 @@ void AngleFxGadget::leftButtonUp(const TPointD &pos, const TMouseEvent &) {} //============================================================================= +class AngleRangeFxGadget final : public FxGadget { + TDoubleParamP m_startAngle, m_endAngle; + TPointParamP m_center; + + enum HANDLE { StartAngle = 0, EndAngle, None } m_handle = None; + + double m_clickedAngle; + double m_targetAngle, m_anotherAngle; + +public: + AngleRangeFxGadget(FxGadgetController *controller, + const TDoubleParamP &startAngle, + const TDoubleParamP &endAngle, const TPointParamP ¢er); + + void draw(bool picking) override; + + void leftButtonDown(const TPointD &pos, const TMouseEvent &) override; + void leftButtonDrag(const TPointD &pos, const TMouseEvent &) override; + void leftButtonUp(const TPointD &pos, const TMouseEvent &) override; +}; + +//--------------------------------------------------------------------------- + +AngleRangeFxGadget::AngleRangeFxGadget(FxGadgetController *controller, + const TDoubleParamP &startAngle, + const TDoubleParamP &endAngle, + const TPointParamP ¢er) + : FxGadget(controller, 2) + , m_startAngle(startAngle) + , m_endAngle(endAngle) + , m_center(center) { + addParam(startAngle); + addParam(endAngle); + addParam(center->getX()); + addParam(center->getY()); +} + +//--------------------------------------------------------------------------- + +void AngleRangeFxGadget::draw(bool picking) { + auto setColorById = [&](int id) { + if (isSelected(id)) + glColor3dv(m_selectedColor); + else + glColor3d(0, 0, 1); + }; + + double pixelSize = sqrt(tglGetPixelSize2()) * getDevPixRatio(); + double r = pixelSize * 200; + double a = pixelSize * 30; + + TPointD center = getValue(m_center); + double start = getValue(m_startAngle); + double end = getValue(m_endAngle); + + glPushMatrix(); + glTranslated(center.x, center.y, 0); + + setColorById(StartAngle); + glPushMatrix(); + glPushName(getId() + StartAngle); + glRotated(start, 0, 0, 1); + glBegin(GL_LINE_STRIP); + glVertex2d(0, 0); + glVertex2d(r, 0); + // expand handle while dragging + if (m_handle == StartAngle) glVertex2d(r * 5.0, 0); + glEnd(); + glPopName(); + + glPushMatrix(); + glTranslated(r * 1.05, 0, 0.0); + glScaled(pixelSize * 1.6, pixelSize * 1.6, 1); + glRotated(-start, 0, 0, 1); + tglDrawText(TPointD(0, 0), "Start Angle"); + glPopMatrix(); + + glPopMatrix(); + + setColorById(EndAngle); + glPushMatrix(); + glPushName(getId() + EndAngle); + glRotated(end, 0, 0, 1); + glBegin(GL_LINE_STRIP); + glVertex2d(0, 0); + glVertex2d(r, 0); + // expand handle while dragging + if (m_handle == EndAngle) glVertex2d(r * 5.0, 0); + glEnd(); + + glPopName(); + glPushMatrix(); + glTranslated(r * 1.05, 0, 0.0); + glScaled(pixelSize * 1.6, pixelSize * 1.6, 1); + glRotated(-end, 0, 0, 1); + tglDrawText(TPointD(0, 0), "End Angle"); + glPopMatrix(); + + glPopMatrix(); + + // draw arc + while (end <= start) end += 360.0; + + glColor3d(0, 0, 1); + glBegin(GL_LINE_STRIP); + double angle = start; + double dAngle = 5.0; + while (angle <= end) { + double rad = angle / M_180_PI; + glVertex2d(a * std::cos(rad), a * std::sin(rad)); + angle += dAngle; + } + if (angle != end) + glVertex2d(a * std::cos(end / M_180_PI), a * std::sin(end / M_180_PI)); + glEnd(); + + glPopMatrix(); +} + +//--------------------------------------------------------------------------- + +void AngleRangeFxGadget::leftButtonDown(const TPointD &pos, + const TMouseEvent &) { + m_handle = (HANDLE)m_selected; + if (m_handle == None) return; + TPointD d = pos - getValue(m_center); + m_clickedAngle = atan2(d.y, d.x) * M_180_PI; + TDoubleParamP target = (m_handle == StartAngle) ? m_startAngle : m_endAngle; + TDoubleParamP another = (m_handle == StartAngle) ? m_endAngle : m_startAngle; + m_targetAngle = getValue(target); + m_anotherAngle = getValue(another); +} + +//--------------------------------------------------------------------------- + +void AngleRangeFxGadget::leftButtonDrag(const TPointD &pos, + const TMouseEvent &e) { + if (m_handle == None) return; + TDoubleParamP target = (m_handle == StartAngle) ? m_startAngle : m_endAngle; + TPointD d = pos - getValue(m_center); + double angle = atan2(d.y, d.x) * M_180_PI; + double targetAngle = m_targetAngle + angle - m_clickedAngle; + // move every 10 degrees when pressing Shift key + if (e.isShiftPressed()) targetAngle = std::round(targetAngle / 10.0) * 10.0; + setValue(target, targetAngle); + + // move both angles when pressing Ctrl key + if (e.isCtrlPressed()) { + TDoubleParamP another = + (m_handle == StartAngle) ? m_endAngle : m_startAngle; + double anotherAngle = m_anotherAngle + angle - m_clickedAngle; + if (e.isShiftPressed()) + anotherAngle = std::round(anotherAngle / 10.0) * 10.0; + setValue(another, anotherAngle); + } +} + +//--------------------------------------------------------------------------- + +void AngleRangeFxGadget::leftButtonUp(const TPointD &pos, const TMouseEvent &) { + m_handle = None; +} + +//============================================================================= + class DiamondFxGadget final : public FxGadget { TDoubleParamP m_param; @@ -1284,6 +1449,14 @@ FxGadget *FxGadgetController::allocateGadget(const TParamUIConcept &uiConcept) { break; } + case TParamUIConcept::ANGLE_2: { + assert(uiConcept.m_params.size() == 3); + gadget = + new AngleRangeFxGadget(this, uiConcept.m_params[0], + uiConcept.m_params[1], uiConcept.m_params[2]); + break; + } + case TParamUIConcept::POINT: { assert(uiConcept.m_params.size() == 1); gadget = new PointFxGadget(this, uiConcept.m_params[0]);