Merge pull request #2878 from shun-iwasawa/g/linear_gradient_fx_revised

Linear Gradient Fx Revised
This commit is contained in:
Rodney 2019-11-15 18:18:25 -07:00 committed by GitHub
commit 98a68d5c9b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 440 additions and 4 deletions

View file

@ -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>

View 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>

View file

@ -1,5 +1,5 @@
<fxlayout>
<page name="Linear Gradient">
<page name="Linear Gradient (Classic)">
<control>period</control>
<control>color1</control>
<control>color2</control>

View file

@ -38,7 +38,7 @@
<Gradient>
STD_diamondGradientFx
STD_fourPointsGradientFx
STD_linearGradientFx
STD_iwa_LinearGradientFx
STD_multiLinearGradientFx
STD_multiRadialGradientFx
STD_radialGradientFx

View file

@ -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
};

View file

@ -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

View 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");

View 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

View file

@ -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;

View file

@ -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);