Merge pull request #2878 from shun-iwasawa/g/linear_gradient_fx_revised
Linear Gradient Fx Revised
This commit is contained in:
commit
98a68d5c9b
10 changed files with 440 additions and 4 deletions
|
@ -1294,6 +1294,16 @@
|
|||
<item>"STD_iwa_SpinGradientFx.endAngle" "End Angle" </item>
|
||||
<item>"STD_iwa_SpinGradientFx.endColor" "End Color" </item>
|
||||
|
||||
<item>"STD_iwa_LinearGradientFx" "Linear Gradient" </item>
|
||||
<item>"STD_iwa_LinearGradientFx.curveType" "Type" </item>
|
||||
<item>"STD_iwa_LinearGradientFx.startPoint" "Start Point" </item>
|
||||
<item>"STD_iwa_LinearGradientFx.startColor" "Start Color" </item>
|
||||
<item>"STD_iwa_LinearGradientFx.endPoint" "End Point" </item>
|
||||
<item>"STD_iwa_LinearGradientFx.endColor" "End Color" </item>
|
||||
<item>"STD_iwa_LinearGradientFx.wave_amplitude" "Amplitude" </item>
|
||||
<item>"STD_iwa_LinearGradientFx.wave_frequency" "Frequency" </item>
|
||||
<item>"STD_iwa_LinearGradientFx.wave_phase" "Phase" </item>
|
||||
|
||||
<!------------------------------ Tiled Particles Iwa ------------------------------------------->
|
||||
|
||||
<item>STD_iwa_TiledParticlesFx "Tiled Particles Iwa" </item>
|
||||
|
|
14
stuff/profiles/layouts/fxs/STD_iwa_LinearGradientFx.xml
Normal file
14
stuff/profiles/layouts/fxs/STD_iwa_LinearGradientFx.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<fxlayout>
|
||||
<page name="Linear Gradient">
|
||||
<control>startPoint</control>
|
||||
<control>endPoint</control>
|
||||
<control>startColor</control>
|
||||
<control>endColor</control>
|
||||
<rgb_link_button>startColor endColor</rgb_link_button>
|
||||
<control>curveType</control>
|
||||
<separator label="Distortion Wave"/>
|
||||
<control>wave_amplitude</control>
|
||||
<control>wave_frequency</control>
|
||||
<control>wave_phase</control>
|
||||
</page>
|
||||
</fxlayout>
|
|
@ -1,5 +1,5 @@
|
|||
<fxlayout>
|
||||
<page name="Linear Gradient">
|
||||
<page name="Linear Gradient (Classic)">
|
||||
<control>period</control>
|
||||
<control>color1</control>
|
||||
<control>color2</control>
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
<Gradient>
|
||||
STD_diamondGradientFx
|
||||
STD_fourPointsGradientFx
|
||||
STD_linearGradientFx
|
||||
STD_iwa_LinearGradientFx
|
||||
STD_multiLinearGradientFx
|
||||
STD_multiRadialGradientFx
|
||||
STD_radialGradientFx
|
||||
|
|
|
@ -61,8 +61,10 @@ public:
|
|||
RECT, // A Rect, with width, height and center. { [2
|
||||
// TDoubleParamP], TPointParamP }
|
||||
|
||||
DIAMOND, // A diagonally laid square. {
|
||||
// [TDoubleParamP] }
|
||||
DIAMOND, // A diagonally laid square. {
|
||||
// [TDoubleParamP] }
|
||||
LINEAR_RANGE, // A band-like range between two points.
|
||||
// { [2 TPointParamP] }
|
||||
|
||||
TYPESCOUNT
|
||||
};
|
||||
|
|
|
@ -78,6 +78,7 @@ set(HEADERS
|
|||
iwa_textfx.h
|
||||
iwa_corridorgradientfx.h
|
||||
iwa_spingradientfx.h
|
||||
iwa_lineargradientfx.h
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
|
@ -262,6 +263,7 @@ set(SOURCES
|
|||
iwa_textfx.cpp
|
||||
iwa_corridorgradientfx.cpp
|
||||
iwa_spingradientfx.cpp
|
||||
iwa_lineargradientfx.cpp
|
||||
)
|
||||
|
||||
set(OBJCSOURCES
|
||||
|
|
178
toonz/sources/stdfx/iwa_lineargradientfx.cpp
Normal file
178
toonz/sources/stdfx/iwa_lineargradientfx.cpp
Normal file
|
@ -0,0 +1,178 @@
|
|||
#include "iwa_lineargradientfx.h"
|
||||
|
||||
#include "tspectrumparam.h"
|
||||
#include "gradients.h"
|
||||
#include "tparamuiconcept.h"
|
||||
#include "traster.h"
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
||||
Iwa_LinearGradientFx::Iwa_LinearGradientFx()
|
||||
: m_startPoint(TPointD(-50.0, 0.0))
|
||||
, m_endPoint(TPointD(50.0, 0.0))
|
||||
, m_startColor(TPixel32::Black)
|
||||
, m_endColor(TPixel32::White)
|
||||
, m_curveType(new TIntEnumParam(EaseInOut, "Ease In-Out"))
|
||||
, m_wave_amplitude(0.0)
|
||||
, m_wave_freq(0.0)
|
||||
, m_wave_phase(0.0) {
|
||||
m_startPoint->getX()->setMeasureName("fxLength");
|
||||
m_startPoint->getY()->setMeasureName("fxLength");
|
||||
m_endPoint->getX()->setMeasureName("fxLength");
|
||||
m_endPoint->getY()->setMeasureName("fxLength");
|
||||
bindParam(this, "startPoint", m_startPoint);
|
||||
bindParam(this, "endPoint", m_endPoint);
|
||||
|
||||
m_curveType->addItem(Linear, "Linear");
|
||||
m_curveType->addItem(EaseIn, "Ease In");
|
||||
m_curveType->addItem(EaseOut, "Ease Out");
|
||||
bindParam(this, "curveType", m_curveType);
|
||||
|
||||
m_wave_amplitude->setValueRange(0, std::numeric_limits<double>::max());
|
||||
m_wave_amplitude->setMeasureName("fxLength");
|
||||
bindParam(this, "wave_amplitude", m_wave_amplitude);
|
||||
bindParam(this, "wave_frequency", m_wave_freq);
|
||||
bindParam(this, "wave_phase", m_wave_phase);
|
||||
|
||||
bindParam(this, "startColor", m_startColor);
|
||||
bindParam(this, "endColor", m_endColor);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
||||
bool Iwa_LinearGradientFx::doGetBBox(double frame, TRectD &bBox,
|
||||
const TRenderSettings &ri) {
|
||||
bBox = TConsts::infiniteRectD;
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
template <typename RASTER, typename PIXEL>
|
||||
void doLinearGradientT(RASTER ras, TDimensionI dim, TPointD startPos,
|
||||
TPointD endPos, const TSpectrumT<PIXEL> &spectrum,
|
||||
GradientCurveType type, double w_amplitude,
|
||||
double w_freq, double w_phase, const TAffine &affInv) {
|
||||
auto getFactor = [&](double t) {
|
||||
if (t > 1.0)
|
||||
t = 1.0;
|
||||
else if (t < 0.0)
|
||||
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;
|
||||
};
|
||||
startPos = affInv * startPos;
|
||||
endPos = affInv * endPos;
|
||||
TPointD seVec = endPos - startPos;
|
||||
|
||||
if (seVec == TPointD()) {
|
||||
ras->fill(spectrum.getPremultipliedValue(0.0));
|
||||
return;
|
||||
}
|
||||
|
||||
TPointD posTrasf = -startPos;
|
||||
double seVecLen2 = seVec.x * seVec.x + seVec.y * seVec.y;
|
||||
double seVecLen = sqrt(seVecLen2);
|
||||
double amplitude = w_amplitude / seVecLen;
|
||||
TPointD auxVec(-seVec.y / seVecLen, seVec.x / seVecLen);
|
||||
|
||||
ras->lock();
|
||||
for (int j = 0; j < ras->getLy(); j++) {
|
||||
TPointD posAux = posTrasf;
|
||||
|
||||
PIXEL *pix = ras->pixels(j);
|
||||
PIXEL *endPix = pix + ras->getLx();
|
||||
|
||||
while (pix < endPix) {
|
||||
double t = (seVec.x * posAux.x + seVec.y * posAux.y) / seVecLen2;
|
||||
if (amplitude) {
|
||||
double distance = posAux.x * auxVec.x + posAux.y * auxVec.y;
|
||||
t += amplitude * sin(w_freq * distance + w_phase);
|
||||
}
|
||||
double factor = getFactor(t);
|
||||
*pix++ = spectrum.getPremultipliedValue(factor);
|
||||
|
||||
posAux.x += affInv.a11;
|
||||
posAux.y += affInv.a21;
|
||||
}
|
||||
posTrasf.x += affInv.a12;
|
||||
posTrasf.y += affInv.a22;
|
||||
}
|
||||
ras->unlock();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
||||
void Iwa_LinearGradientFx::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 startPos = aff * m_startPoint->getValue(frame) -
|
||||
(tile.m_pos + tile.getRaster()->getCenterD()) + dimOffset;
|
||||
TPointD endPos = aff * m_endPoint->getValue(frame) -
|
||||
(tile.m_pos + tile.getRaster()->getCenterD()) + dimOffset;
|
||||
|
||||
double w_amplitude = m_wave_amplitude->getValue(frame) / ri.m_shrinkX;
|
||||
double w_freq = m_wave_freq->getValue(frame) * ri.m_shrinkX;
|
||||
double w_phase = m_wave_phase->getValue(frame);
|
||||
w_freq *= 0.01 * M_PI_180;
|
||||
|
||||
std::vector<TSpectrum::ColorKey> colors = {
|
||||
TSpectrum::ColorKey(0, m_startColor->getValue(frame)),
|
||||
TSpectrum::ColorKey(1, m_endColor->getValue(frame))};
|
||||
TSpectrumParamP m_colors = TSpectrumParamP(colors);
|
||||
|
||||
tile.getRaster()->clear();
|
||||
TRaster32P outRas32 = (TRaster32P)tile.getRaster();
|
||||
TRaster64P outRas64 = (TRaster64P)tile.getRaster();
|
||||
if (outRas32)
|
||||
doLinearGradientT<TRaster32P, TPixel32>(
|
||||
outRas32, dimOut, startPos, endPos, m_colors->getValue(frame),
|
||||
(GradientCurveType)m_curveType->getValue(), w_amplitude, w_freq,
|
||||
w_phase, aff.inv());
|
||||
else if (outRas64)
|
||||
doLinearGradientT<TRaster64P, TPixel64>(
|
||||
outRas64, dimOut, startPos, endPos, m_colors->getValue64(frame),
|
||||
(GradientCurveType)m_curveType->getValue(), w_amplitude, w_freq,
|
||||
w_phase, aff.inv());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
||||
void Iwa_LinearGradientFx::getParamUIs(TParamUIConcept *&concepts,
|
||||
int &length) {
|
||||
concepts = new TParamUIConcept[length = 1];
|
||||
|
||||
concepts[0].m_type = TParamUIConcept::LINEAR_RANGE;
|
||||
concepts[0].m_label = "";
|
||||
concepts[0].m_params.push_back(m_startPoint);
|
||||
concepts[0].m_params.push_back(m_endPoint);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
||||
FX_PLUGIN_IDENTIFIER(Iwa_LinearGradientFx, "iwa_LinearGradientFx");
|
32
toonz/sources/stdfx/iwa_lineargradientfx.h
Normal file
32
toonz/sources/stdfx/iwa_lineargradientfx.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
#ifndef IWA_LINEARGRADIENTFX_H
|
||||
#define IWA_LINEARGRADIENTFX_H
|
||||
|
||||
#include "tfxparam.h"
|
||||
#include "stdfx.h"
|
||||
#include "tparamset.h"
|
||||
|
||||
class Iwa_LinearGradientFx final : public TStandardZeraryFx {
|
||||
FX_PLUGIN_DECLARATION(Iwa_LinearGradientFx)
|
||||
|
||||
TIntEnumParamP m_curveType;
|
||||
TPointParamP m_startPoint, m_endPoint;
|
||||
TPixelParamP m_startColor, m_endColor;
|
||||
|
||||
TDoubleParamP m_wave_amplitude;
|
||||
TDoubleParamP m_wave_freq;
|
||||
TDoubleParamP m_wave_phase;
|
||||
|
||||
public:
|
||||
Iwa_LinearGradientFx();
|
||||
|
||||
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
|
|
@ -236,6 +236,11 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// From V1.4 LinearGradientFx becomes obsolete and was replaced by
|
||||
// Iwa_LinearGradientFx which has more flexibility. (iwa_lineargradientfx.cpp)
|
||||
// This code is kept in order to load the fx made with older OT versions.
|
||||
// Nov 14, 2019
|
||||
|
||||
class LinearGradientFx final : public TStandardZeraryFx {
|
||||
FX_PLUGIN_DECLARATION(LinearGradientFx)
|
||||
TDoubleParamP m_period;
|
||||
|
|
|
@ -1342,6 +1342,192 @@ void QuadFxGadget::leftButtonUp(const TPointD &pos, const TMouseEvent &) {
|
|||
m_handle = None;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
class LinearRangeFxGadget final : public FxGadget {
|
||||
TPointParamP m_start, m_end;
|
||||
|
||||
enum HANDLE { Body = 0, Start, End, None } m_handle = None;
|
||||
|
||||
TPointD m_clickedPos;
|
||||
TPointD m_targetPos, m_anotherPos;
|
||||
|
||||
public:
|
||||
LinearRangeFxGadget(FxGadgetController *controller,
|
||||
const TPointParamP &startPoint,
|
||||
const TPointParamP &endPoint);
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
LinearRangeFxGadget::LinearRangeFxGadget(FxGadgetController *controller,
|
||||
const TPointParamP &startPoint,
|
||||
const TPointParamP &endPoint)
|
||||
: FxGadget(controller, 3), m_start(startPoint), m_end(endPoint) {
|
||||
addParam(startPoint->getX());
|
||||
addParam(startPoint->getY());
|
||||
addParam(endPoint->getX());
|
||||
addParam(endPoint->getY());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void LinearRangeFxGadget::draw(bool picking) {
|
||||
auto setColorById = [&](int id) {
|
||||
if (isSelected(id))
|
||||
glColor3dv(m_selectedColor);
|
||||
else
|
||||
glColor3d(0, 0, 1);
|
||||
};
|
||||
|
||||
auto drawPoint = [&]() {
|
||||
double r = getPixelSize() * 3;
|
||||
double d = getPixelSize() * 6;
|
||||
glBegin(GL_LINES);
|
||||
glVertex2d(-d, 0);
|
||||
glVertex2d(-r, 0);
|
||||
glVertex2d(d, 0);
|
||||
glVertex2d(r, 0);
|
||||
glVertex2d(0, -d);
|
||||
glVertex2d(0, -r);
|
||||
glVertex2d(0, d);
|
||||
glVertex2d(0, r);
|
||||
glEnd();
|
||||
tglDrawRect(-r, -r, r, r);
|
||||
};
|
||||
|
||||
setPixelSize();
|
||||
double r = getPixelSize() * 200;
|
||||
double a = getPixelSize() * 5;
|
||||
|
||||
TPointD start = getValue(m_start);
|
||||
TPointD end = getValue(m_end);
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
if (start != end) {
|
||||
// draw lines perpendicular to the line between ends
|
||||
double angle = std::atan2(start.x - end.x, end.y - start.y) * M_180_PI;
|
||||
// start
|
||||
setColorById(Start);
|
||||
glPushMatrix();
|
||||
glTranslated(start.x, start.y, 0);
|
||||
glRotated(angle, 0, 0, 1);
|
||||
if (m_handle == Start) glScaled(5.0, 1.0, 1.0);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2d(-r, 0);
|
||||
glVertex2d(r, 0);
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
// end
|
||||
setColorById(End);
|
||||
glPushMatrix();
|
||||
glTranslated(end.x, end.y, 0);
|
||||
glRotated(angle, 0, 0, 1);
|
||||
if (m_handle == End) glScaled(5.0, 1.0, 1.0);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex2d(-r, 0);
|
||||
glVertex2d(r, 0);
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
|
||||
// line body
|
||||
setColorById(Body);
|
||||
glPushName(getId() + Body);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2d(start.x, start.y);
|
||||
glVertex2d(end.x, end.y);
|
||||
glEnd();
|
||||
// small dash at the center
|
||||
glPushMatrix();
|
||||
glTranslated((start.x + end.x) / 2.0, (start.y + end.y) / 2.0, 0);
|
||||
glRotated(angle, 0, 0, 1);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2d(-a, 0);
|
||||
glVertex2d(a, 0);
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
glPopName();
|
||||
}
|
||||
|
||||
// start point
|
||||
setColorById(Start);
|
||||
glPushName(getId() + Start);
|
||||
glPushMatrix();
|
||||
glTranslated(start.x, start.y, 0);
|
||||
drawPoint();
|
||||
glPopMatrix();
|
||||
glPopName();
|
||||
drawTooltip(start + TPointD(7, 3) * getPixelSize(), "Start");
|
||||
|
||||
// end point
|
||||
setColorById(End);
|
||||
glPushName(getId() + End);
|
||||
glPushMatrix();
|
||||
glTranslated(end.x, end.y, 0);
|
||||
drawPoint();
|
||||
glPopMatrix();
|
||||
glPopName();
|
||||
drawTooltip(end + TPointD(7, 3) * getPixelSize(), "End");
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void LinearRangeFxGadget::leftButtonDown(const TPointD &pos,
|
||||
const TMouseEvent &) {
|
||||
m_handle = (HANDLE)m_selected;
|
||||
if (m_handle == None) return;
|
||||
m_clickedPos = pos;
|
||||
m_targetPos = (m_handle == Start || m_handle == Body) ? getValue(m_start)
|
||||
: getValue(m_end);
|
||||
m_anotherPos = (m_handle == Start || m_handle == Body) ? getValue(m_end)
|
||||
: getValue(m_start);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void LinearRangeFxGadget::leftButtonDrag(const TPointD &pos,
|
||||
const TMouseEvent &e) {
|
||||
if (m_handle == None) return;
|
||||
TPointD d = pos - m_clickedPos;
|
||||
|
||||
if (m_handle == Body) {
|
||||
setValue(m_start, m_targetPos + d);
|
||||
setValue(m_end, m_anotherPos + d);
|
||||
return;
|
||||
}
|
||||
|
||||
TPointParamP target = (m_handle == Start) ? m_start : m_end;
|
||||
|
||||
if (m_targetPos != m_anotherPos && e.isShiftPressed()) {
|
||||
TPointD vecA = m_targetPos - m_anotherPos;
|
||||
TPointD vecB = m_targetPos + d - m_anotherPos;
|
||||
double ratio = std::min(vecB.x / vecA.x, vecB.y / vecA.y);
|
||||
d = vecA * (ratio - 1.0);
|
||||
}
|
||||
|
||||
setValue(target, m_targetPos + d);
|
||||
|
||||
if (e.isCtrlPressed()) {
|
||||
TPointParamP another = (m_handle == Start) ? m_end : m_start;
|
||||
setValue(another, m_anotherPos - d);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void LinearRangeFxGadget::leftButtonUp(const TPointD &pos,
|
||||
const TMouseEvent &) {
|
||||
m_handle = None;
|
||||
}
|
||||
//*************************************************************************************
|
||||
// FxGadgetController implementation
|
||||
//*************************************************************************************
|
||||
|
@ -1519,6 +1705,13 @@ FxGadget *FxGadgetController::allocateGadget(const TParamUIConcept &uiConcept) {
|
|||
gadget = new DiamondFxGadget(this, uiConcept.m_params[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
case TParamUIConcept::LINEAR_RANGE: {
|
||||
assert(uiConcept.m_params.size() == 2);
|
||||
gadget = new LinearRangeFxGadget(this, uiConcept.m_params[0],
|
||||
uiConcept.m_params[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gadget) gadget->setLabel(uiConcept.m_label);
|
||||
|
|
Loading…
Reference in a new issue