Merge branch 'master' of https://github.com/opentoonz/opentoonz into update_korean_translations

This commit is contained in:
manongjohn 2019-10-13 22:57:25 -04:00
commit 16e741e04e
33 changed files with 1150 additions and 297 deletions

View file

@ -19,4 +19,4 @@ matrix:
- os: linux
compiler: clang
- os: osx
osx_image: xcode8.3
osx_image: xcode10.1

View file

@ -1,6 +1,6 @@
#!/bin/bash
pushd thirdparty/tiff-4.0.3
./configure && make
./configure --disable-lzma && make
popd
cd toonz && mkdir build && cd build
QTVERSION=`ls /usr/local/Cellar/qt`

View file

@ -1272,6 +1272,20 @@
<item>"STD_iwa_TextFx.boxColor" "Box Color"</item>
<item>"STD_iwa_TextFx.showBorder" "Show Border"</item>
<item>"STD_iwa_CorridorGradientFx" "Corridor Gradient Iwa" </item>
<item>"STD_iwa_CorridorGradientFx.shape" "Shape" </item>
<item>"STD_iwa_CorridorGradientFx.curveType" "Type" </item>
<item>"STD_iwa_CorridorGradientFx.bottom_left_in" "Bottom Left In" </item>
<item>"STD_iwa_CorridorGradientFx.bottom_left_out" "Bottom Left Out" </item>
<item>"STD_iwa_CorridorGradientFx.bottom_right_in" "Bottom Right In" </item>
<item>"STD_iwa_CorridorGradientFx.bottom_right_out" "Bottom Right Out" </item>
<item>"STD_iwa_CorridorGradientFx.top_right_in" "Top Right In" </item>
<item>"STD_iwa_CorridorGradientFx.top_right_out" "Top Right Out" </item>
<item>"STD_iwa_CorridorGradientFx.top_left_in" "Top Left In" </item>
<item>"STD_iwa_CorridorGradientFx.top_left_out" "Top Left Out" </item>
<item>"STD_iwa_CorridorGradientFx.inner_color" "Inner Color" </item>
<item>"STD_iwa_CorridorGradientFx.outer_color" "Outer Color" </item>
<!------------------------------ Tiled Particles Iwa ------------------------------------------->
<item>STD_iwa_TiledParticlesFx "Tiled Particles Iwa" </item>

View file

@ -0,0 +1,18 @@
<fxlayout>
<page name="Corridor Gradient Iwa">
<control>shape</control>
<control>curveType</control>
<separator label="Inner Shape"/>
<control>bottom_left_in</control>
<control>bottom_right_in</control>
<control>top_left_in</control>
<control>top_right_in</control>
<control>inner_color</control>
<separator label="Outer Shape"/>
<control>bottom_left_out</control>
<control>bottom_right_out</control>
<control>top_left_out</control>
<control>top_right_out</control>
<control>outer_color</control>
</page>
</fxlayout>

View file

@ -44,6 +44,7 @@
STD_radialGradientFx
STD_spiralFx
STD_squareGradientFx
STD_iwa_CorridorGradientFx
</Gradient>
<Image_Adjust>
STD_iwa_AdjustExposureFx

View file

@ -102,12 +102,20 @@ onSliderChanged(int value),
class DVAPI DoubleValueField : public QWidget {
Q_OBJECT
bool m_isLinearSlider;
protected:
RollerField *m_roller;
DoubleValueLineEdit *m_lineEdit;
QSlider *m_slider;
QWidget *m_spaceWidget;
void setLinearSlider(bool linear) { m_isLinearSlider = linear; }
private:
double pos2value(int x) const;
int value2pos(double v) const;
public:
DoubleValueField(QWidget *parent, DoubleValueLineEdit *lineEdit);
~DoubleValueField() {}
@ -158,7 +166,7 @@ signals:
void valueChanged(bool);
/*! This signal is emitted only when users edited the value by hand
*/
*/
void valueEditedByHand();
};

View file

@ -102,6 +102,8 @@ protected:
bool m_isMaxRangeLimited;
bool m_isLinear;
public:
DoubleValuePairField(QWidget *parent, bool isMaxRangeLimited,
DoubleValueLineEdit *leftLineEdit,
@ -174,6 +176,7 @@ protected:
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void setLinearSlider(bool linear) { m_isLinear = linear; }
protected slots:
/*! Set current left value to value in left text field; if necessary, if left
value is greater than right, change also current right value.

View file

@ -167,6 +167,7 @@ class DVAPI IntField : public QWidget {
IntLineEdit *m_lineEdit;
QSlider *m_slider;
bool m_isMaxRangeLimited;
bool m_isLinearSlider;
public:
IntField(QWidget *parent = 0, bool isMaxRangeLimited = true,
@ -205,6 +206,13 @@ public:
void setLineEditBackgroundColor(QColor color);
protected:
void setLinearSlider(bool linear) { m_isLinearSlider = linear; }
private:
int pos2value(int x) const;
int value2pos(int v) const;
protected slots:
/*! Set to value the text field. If text field value is different from \b
value

View file

@ -112,6 +112,8 @@ class DVAPI IntPairField : public QWidget {
bool m_isMaxRangeLimited;
bool m_isLinear;
public:
IntPairField(QWidget *parent = 0, bool isMaxRangeLimited = true);
~IntPairField() {}
@ -166,9 +168,9 @@ public:
protected:
/*! Return value corresponding \b x position. */
double pos2value(int x) const;
int pos2value(int x) const;
/*! Return x position corresponding \b value. */
int value2pos(double v) const;
int value2pos(int v) const;
/*! Set current value to \b value.
Set left or right value, or both, to value depending on
@ -182,6 +184,7 @@ protected:
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void setLinearSlider(bool linear) { m_isLinear = linear; }
protected slots:
/*! Set current left value to value in left text field; if necessary, if left
value is greater than right, change also current right value.

View file

@ -112,7 +112,8 @@ public:
: TProperty(name)
, m_range(minValue, maxValue)
, m_value(minValue)
, m_isMaxRangeLimited(isMaxRangeLimited) {
, m_isMaxRangeLimited(isMaxRangeLimited)
, m_isLinearSlider(true) {
setValue(value);
}
@ -138,10 +139,14 @@ public:
bool isMaxRangeLimited() const { return m_isMaxRangeLimited; }
void setNonLinearSlider() { m_isLinearSlider = false; }
bool isLinearSlider() { return m_isLinearSlider; }
private:
Range m_range;
T m_value;
bool m_isMaxRangeLimited;
bool m_isLinearSlider;
};
//---------------------------------------------------------
@ -160,7 +165,8 @@ public:
double v0, double v1, bool isMaxRangeLimited = true)
: TProperty(name)
, m_range(Range(minValue, maxValue))
, m_isMaxRangeLimited(isMaxRangeLimited) {
, m_isMaxRangeLimited(isMaxRangeLimited)
, m_isLinearSlider(true) {
setValue(Value(v0, v1));
}
@ -184,10 +190,14 @@ public:
}
void accept(Visitor &v) override { v.visit(this); };
void setNonLinearSlider() { m_isLinearSlider = false; }
bool isLinearSlider() { return m_isLinearSlider; }
private:
Range m_range;
Value m_value;
bool m_isMaxRangeLimited;
bool m_isLinearSlider;
};
//---------------------------------------------------------
@ -201,7 +211,8 @@ public:
bool isMaxRangeLimited = true)
: TProperty(name)
, m_range(minValue, maxValue)
, m_isMaxRangeLimited(isMaxRangeLimited) {
, m_isMaxRangeLimited(isMaxRangeLimited)
, m_isLinearSlider(true) {
setValue(Value(v0, v1));
}
@ -225,10 +236,14 @@ public:
}
void accept(Visitor &v) override { v.visit(this); };
void setNonLinearSlider() { m_isLinearSlider = false; }
bool isLinearSlider() { return m_isLinearSlider; }
private:
Range m_range;
Value m_value;
bool m_isMaxRangeLimited;
bool m_isLinearSlider;
};
//---------------------------------------------------------

View file

@ -76,6 +76,7 @@ set(HEADERS
iwa_timecodefx.h
iwa_bokehreffx.h
iwa_textfx.h
iwa_corridorgradientfx.h
)
set(SOURCES
@ -258,6 +259,7 @@ set(SOURCES
iwa_bokehreffx.cpp
iwa_barreldistortfx.cpp
iwa_textfx.cpp
iwa_corridorgradientfx.cpp
)
set(OBJCSOURCES

View file

@ -19,7 +19,7 @@
namespace {
inline bool myIsEmpty(const TRectD &r) { return r.x0 >= r.x1 || r.y0 >= r.y1; }
}
} // namespace
//==============================================================================
@ -415,19 +415,21 @@ void FreeDistortBaseFx::safeTransform(double frame, int port,
// ------------------------------------------------------------------------
void FreeDistortBaseFx::getParamUIs(TParamUIConcept *&concepts, int &length) {
concepts = new TParamUIConcept[length = 14];
concepts = new TParamUIConcept[length = 6];
concepts[0].m_type = TParamUIConcept::QUAD;
concepts[0].m_params.push_back(m_p00_b);
concepts[0].m_params.push_back(m_p10_b);
concepts[0].m_params.push_back(m_p11_b);
concepts[0].m_params.push_back(m_p01_b);
concepts[0].m_params.push_back(m_p11_b);
concepts[0].m_params.push_back(m_p10_b);
concepts[0].m_params.push_back(m_p00_b);
concepts[0].m_label = " Src";
concepts[1].m_type = TParamUIConcept::QUAD;
concepts[1].m_params.push_back(m_p00_a);
concepts[1].m_params.push_back(m_p10_a);
concepts[1].m_params.push_back(m_p11_a);
concepts[1].m_params.push_back(m_p01_a);
concepts[1].m_params.push_back(m_p11_a);
concepts[1].m_params.push_back(m_p10_a);
concepts[1].m_params.push_back(m_p00_a);
concepts[1].m_label = " Dst";
concepts[2].m_type = TParamUIConcept::VECTOR;
concepts[2].m_params.push_back(m_p00_b);
@ -444,38 +446,6 @@ void FreeDistortBaseFx::getParamUIs(TParamUIConcept *&concepts, int &length) {
concepts[5].m_type = TParamUIConcept::VECTOR;
concepts[5].m_params.push_back(m_p11_b);
concepts[5].m_params.push_back(m_p11_a);
concepts[6].m_type = TParamUIConcept::POINT;
concepts[6].m_label = "Bottom Left Src";
concepts[6].m_params.push_back(m_p00_b);
concepts[7].m_type = TParamUIConcept::POINT;
concepts[7].m_label = "Bottom Right Src";
concepts[7].m_params.push_back(m_p10_b);
concepts[8].m_type = TParamUIConcept::POINT;
concepts[8].m_label = "Top Left Src";
concepts[8].m_params.push_back(m_p01_b);
concepts[9].m_type = TParamUIConcept::POINT;
concepts[9].m_label = "Top Right Src";
concepts[9].m_params.push_back(m_p11_b);
concepts[10].m_type = TParamUIConcept::POINT;
concepts[10].m_label = "Bottom Left Dst";
concepts[10].m_params.push_back(m_p00_a);
concepts[11].m_type = TParamUIConcept::POINT;
concepts[11].m_label = "Bottom Right Dst";
concepts[11].m_params.push_back(m_p10_a);
concepts[12].m_type = TParamUIConcept::POINT;
concepts[12].m_label = "Top Left Dst";
concepts[12].m_params.push_back(m_p01_a);
concepts[13].m_type = TParamUIConcept::POINT;
concepts[13].m_label = "Top Right Dst";
concepts[13].m_params.push_back(m_p11_a);
}
// ------------------------------------------------------------------------
@ -672,7 +642,7 @@ void doBlur(TRasterPT<PIX> &r, double blur0, double blur1, double transp0,
r->unlock();
delete[] row;
}
}
} // namespace
// ------------------------------------------------------------------------

View file

@ -0,0 +1,378 @@
#include "iwa_corridorgradientfx.h"
#include "trop.h"
#include "tparamuiconcept.h"
#include "tspectrumparam.h"
#include "gradients.h"
#include <QPolygonF>
#include <array>
#include <algorithm>
//------------------------------------------------------------
Iwa_CorridorGradientFx::Iwa_CorridorGradientFx()
: m_shape(new TIntEnumParam(0, "Quadrangle"))
, m_innerColor(TPixel32::White)
, m_outerColor(TPixel32::Black)
, m_curveType(new TIntEnumParam()) {
for (int inout = 0; inout < 2; inout++) {
double size = (inout == 0) ? 50. : 400.;
std::string inout_str = (inout == 0) ? "_in" : "_out";
for (int c = 0; c < 4; c++) {
Qt::Corner corner = (Qt::Corner)c;
TPointD basePos(1, 1);
if (corner == Qt::TopLeftCorner || corner == Qt::BottomLeftCorner)
basePos.x *= -1;
if (corner == Qt::BottomLeftCorner || corner == Qt::BottomRightCorner)
basePos.y *= -1;
m_points[inout][corner] = basePos * size;
m_points[inout][corner]->getX()->setMeasureName("fxLength");
m_points[inout][corner]->getY()->setMeasureName("fxLength");
std::string TB_str =
(corner == Qt::TopLeftCorner || corner == Qt::TopRightCorner)
? "top"
: "bottom";
std::string LR_str =
(corner == Qt::TopLeftCorner || corner == Qt::BottomLeftCorner)
? "_left"
: "_right";
bindParam(this, TB_str + LR_str + inout_str, m_points[inout][corner]);
}
}
m_shape->addItem(1, "Circle");
bindParam(this, "shape", m_shape);
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, "inner_color", m_innerColor);
bindParam(this, "outer_color", m_outerColor);
}
//------------------------------------------------------------
bool Iwa_CorridorGradientFx::doGetBBox(double frame, TRectD &bBox,
const TRenderSettings &ri) {
bBox = TConsts::infiniteRectD;
return true;
}
//------------------------------------------------------------
namespace {
QPointF toQPointF(const TPointD &p) { return QPointF(p.x, p.y); }
double WedgeProduct(const TPointD v, const TPointD w) {
return v.x * w.y - v.y * w.x;
}
struct BilinearParam {
TPointD p0, b1, b2, b3;
};
//------------------------------------------------------------
double getFactor(const TPointD &p, const BilinearParam &param,
const GradientCurveType type) {
double t;
TPointD q = p - param.p0;
// Set up quadratic formula
float A = WedgeProduct(param.b2, param.b3);
float B = WedgeProduct(param.b3, q) - WedgeProduct(param.b1, param.b2);
float C = WedgeProduct(param.b1, q);
// Solve for v
if (std::abs(A) < 0.001) {
// Linear form
t = -C / B;
} else {
// Quadratic form
float discrim = B * B - 4 * A * C;
t = 0.5 * (-B - std::sqrt(discrim)) / A;
}
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;
}
//------------------------------------------------------------
template <typename RASTER, typename PIXEL>
void doQuadrangleT(RASTER ras, TDimensionI dim, TPointD pos[2][4],
const TSpectrumT<PIXEL> &spectrum, GradientCurveType type) {
auto buildPolygon = [&](QPolygonF &pol, Qt::Corner c1, Qt::Corner c2) {
pol << toQPointF(pos[0][(int)c1]) << toQPointF(pos[1][(int)c1])
<< toQPointF(pos[1][(int)c2]) << toQPointF(pos[0][(int)c2]);
};
auto buildBilinearParam = [&](BilinearParam &bp, Qt::Corner c1,
Qt::Corner c2) {
bp.p0 = pos[0][(int)c1];
bp.b1 = pos[0][(int)c2] - pos[0][(int)c1];
bp.b2 = pos[1][(int)c1] - pos[0][(int)c1];
bp.b3 =
pos[0][(int)c1] - pos[0][(int)c2] - pos[1][(int)c1] + pos[1][(int)c2];
};
std::array<QPolygonF, 4> polygons;
std::array<BilinearParam, 4> params;
// Top
buildPolygon(polygons[0], Qt::TopLeftCorner, Qt::TopRightCorner);
buildBilinearParam(params[0], Qt::TopLeftCorner, Qt::TopRightCorner);
// Left
buildPolygon(polygons[1], Qt::BottomLeftCorner, Qt::TopLeftCorner);
buildBilinearParam(params[1], Qt::BottomLeftCorner, Qt::TopLeftCorner);
// Bottom
buildPolygon(polygons[2], Qt::BottomRightCorner, Qt::BottomLeftCorner);
buildBilinearParam(params[2], Qt::BottomRightCorner, Qt::BottomLeftCorner);
// Right
buildPolygon(polygons[3], Qt::TopRightCorner, Qt::BottomRightCorner);
buildBilinearParam(params[3], Qt::TopRightCorner, Qt::BottomRightCorner);
QPolygonF innerPolygon;
innerPolygon << toQPointF(pos[0][Qt::TopLeftCorner])
<< toQPointF(pos[0][Qt::TopRightCorner])
<< toQPointF(pos[0][Qt::BottomRightCorner])
<< toQPointF(pos[0][Qt::BottomLeftCorner]);
ras->lock();
for (int j = 0; j < ras->getLy(); j++) {
PIXEL *pix = ras->pixels(j);
PIXEL *endPix = pix + ras->getLx();
int i = 0;
while (pix < endPix) {
QPointF p(i, j);
double factor;
bool found = false;
for (int edge = 0; edge < 4; edge++) {
if (polygons[edge].containsPoint(p, Qt::WindingFill)) {
factor = getFactor(TPointD(i, j), params.at(edge), type);
found = true;
break;
}
}
if (!found) {
if (innerPolygon.containsPoint(p, Qt::WindingFill))
factor = 0.0;
else
factor = 1.0;
}
*pix++ = spectrum.getPremultipliedValue(factor);
i++;
}
}
ras->unlock();
}
//------------------------------------------------------------
template <typename RASTER, typename PIXEL>
void doCircleT(RASTER ras, TDimensionI dim, TPointD pos[2][4],
const TSpectrumT<PIXEL> &spectrum, GradientCurveType type) {
auto lerp = [](TPointD p1, TPointD p2, double f) {
return p1 * (1 - f) + p2 * f;
};
auto bilinearPos = [&](TPointD uv, int inout) {
return lerp(lerp(pos[inout][Qt::BottomLeftCorner],
pos[inout][Qt::BottomRightCorner], uv.x),
lerp(pos[inout][Qt::TopLeftCorner],
pos[inout][Qt::TopRightCorner], uv.x),
uv.y);
};
const int DIVNUM = 36;
std::array<TPointD, DIVNUM> innerPos;
std::array<TPointD, DIVNUM> outerPos;
double tmpRadius = std::sqrt(2.0) / 2.0;
for (int div = 0; div < DIVNUM; div++) {
double angle = 2.0 * M_PI * (double)div / (double)DIVNUM;
// circle position in uv coordinate
TPointD uv(tmpRadius * std::cos(angle) + 0.5,
tmpRadius * std::sin(angle) + 0.5);
// compute inner and outer circle positions by bilinear interpolation
// using uv coordinate values.
innerPos[div] = bilinearPos(uv, 0);
outerPos[div] = bilinearPos(uv, 1);
}
// - - - - - - - -
auto buildPolygon = [&](QPolygonF &pol, int id1, int id2) {
pol << toQPointF(innerPos[id2]) << toQPointF(outerPos[id2])
<< toQPointF(outerPos[id1]) << toQPointF(innerPos[id1]);
};
auto buildBilinearParam = [&](BilinearParam &bp, int id1, int id2) {
bp.p0 = innerPos[id2];
bp.b1 = innerPos[id1] - innerPos[id2];
bp.b2 = outerPos[id2] - innerPos[id2];
bp.b3 = innerPos[id2] - innerPos[id1] - outerPos[id2] + outerPos[id1];
};
std::array<QPolygonF, DIVNUM> polygons;
std::array<BilinearParam, DIVNUM> params;
QPolygonF innerPolygon;
for (int div = 0; div < DIVNUM; div++) {
int next_div = (div == DIVNUM - 1) ? 0 : div + 1;
// create polygon and bilinear parameters for each piece surrounding the
// circle
buildPolygon(polygons[div], div, next_div);
buildBilinearParam(params[div], div, next_div);
// create inner circle polygon
innerPolygon << toQPointF(innerPos[div]);
}
// - - - ok, ready to render
ras->lock();
for (int j = 0; j < ras->getLy(); j++) {
PIXEL *pix = ras->pixels(j);
PIXEL *endPix = pix + ras->getLx();
int i = 0;
while (pix < endPix) {
QPointF p(i, j);
double factor;
bool found = false;
for (int div = 0; div < DIVNUM; div++) {
// check if the point is inside of the surrounding pieces
if (polygons[div].containsPoint(p, Qt::WindingFill)) {
// compute factor by invert bilinear interpolation
factor = getFactor(TPointD(i, j), params.at(div), type);
found = true;
break;
}
}
if (!found) {
if (innerPolygon.containsPoint(p, Qt::WindingFill))
factor = 0.0;
else
factor = 1.0;
}
*pix++ = spectrum.getPremultipliedValue(factor);
i++;
}
}
ras->unlock();
}
}; // namespace
//------------------------------------------------------------
void Iwa_CorridorGradientFx::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
TPointD pos[2][4];
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);
for (int inout = 0; inout < 2; inout++) {
for (int c = 0; c < 4; c++) {
TPointD _point = m_points[inout][c]->getValue(frame);
pos[inout][c] = aff * _point -
(tile.m_pos + tile.getRaster()->getCenterD()) + dimOffset;
}
}
std::vector<TSpectrum::ColorKey> colors = {
TSpectrum::ColorKey(0, m_innerColor->getValue(frame)),
TSpectrum::ColorKey(1, m_outerColor->getValue(frame))};
TSpectrumParamP m_colors = TSpectrumParamP(colors);
tile.getRaster()->clear();
TRaster32P outRas32 = (TRaster32P)tile.getRaster();
TRaster64P outRas64 = (TRaster64P)tile.getRaster();
if (m_shape->getValue() == 0) { // Quadrangle
if (outRas32)
doQuadrangleT<TRaster32P, TPixel32>(
outRas32, dimOut, pos, m_colors->getValue(frame),
(GradientCurveType)m_curveType->getValue());
else if (outRas64)
doQuadrangleT<TRaster64P, TPixel64>(
outRas64, dimOut, pos, m_colors->getValue64(frame),
(GradientCurveType)m_curveType->getValue());
} else { // m_shape == 1 : Circle
if (outRas32)
doCircleT<TRaster32P, TPixel32>(
outRas32, dimOut, pos, m_colors->getValue(frame),
(GradientCurveType)m_curveType->getValue());
else if (outRas64)
doCircleT<TRaster64P, TPixel64>(
outRas64, dimOut, pos, m_colors->getValue64(frame),
(GradientCurveType)m_curveType->getValue());
}
}
//------------------------------------------------------------
void Iwa_CorridorGradientFx::getParamUIs(TParamUIConcept *&concepts,
int &length) {
concepts = new TParamUIConcept[length = 6];
int vectorUiIdOffset = 2;
std::array<Qt::Corner, 4> loopIds{Qt::TopLeftCorner, Qt::TopRightCorner,
Qt::BottomRightCorner,
Qt::BottomLeftCorner};
for (int inout = 0; inout < 2; inout++) {
concepts[inout].m_type = TParamUIConcept::QUAD;
for (int c = 0; c < 4; c++) {
Qt::Corner corner = loopIds[c];
// quad ui
concepts[inout].m_params.push_back(m_points[inout][(int)corner]);
concepts[inout].m_label = (inout == 0) ? " In" : " Out";
// vector ui
if (inout == 0)
concepts[vectorUiIdOffset + (int)corner].m_type =
TParamUIConcept::VECTOR;
concepts[vectorUiIdOffset + (int)corner].m_params.push_back(
m_points[inout][(int)corner]);
}
}
}
//------------------------------------------------------------
FX_PLUGIN_IDENTIFIER(Iwa_CorridorGradientFx, "iwa_CorridorGradientFx");

View file

@ -0,0 +1,31 @@
#pragma once
#ifndef IWA_CORRIDORGRADIENTFX_H
#define IWA_CORRIDORGRADIENTFX_H
#include "tfxparam.h"
#include "stdfx.h"
#include "tparamset.h"
class Iwa_CorridorGradientFx final : public TStandardZeraryFx {
FX_PLUGIN_DECLARATION(Iwa_CorridorGradientFx)
TIntEnumParamP m_shape;
TIntEnumParamP m_curveType;
TPointParamP m_points[2][4]; // [in/out][Qt::Corner]
TPixelParamP m_innerColor;
TPixelParamP m_outerColor;
public:
Iwa_CorridorGradientFx();
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

@ -30,8 +30,13 @@ int getDevPixRatio() {
static int devPixRatio = QApplication::desktop()->devicePixelRatio();
return devPixRatio;
}
TPointD hadamard(const TPointD &v1, const TPointD &v2) {
return TPointD(v1.x * v2.x, v1.y * v2.y);
}
} // namespace
//*************************************************************************************
// FxGadgetUndo definition
//*************************************************************************************
@ -131,13 +136,14 @@ public:
// FxGadget implementation
//*************************************************************************************
FxGadget::FxGadget(FxGadgetController *controller)
FxGadget::FxGadget(FxGadgetController *controller, int handleCount)
: m_id(-1)
, m_selected(false)
, m_selected(-1)
, m_controller(controller)
, m_pixelSize(1)
, m_undo(0)
, m_scaleFactor(1) {
, m_scaleFactor(1)
, m_handleCount(handleCount) {
controller->assignId(this);
}
@ -592,7 +598,7 @@ void DiamondFxGadget::draw(bool picking) {
//---------------------------------------------------------------------------
void DiamondFxGadget::leftButtonDrag(const TPointD &pos, const TMouseEvent &) {
double sz = fabs(pos.x) + fabs(pos.y);
double sz = fabs(pos.x) + fabs(pos.y);
if (sz < 0.1) sz = 0.1;
setValue(m_param, sz);
}
@ -841,12 +847,11 @@ public:
class VectorFxGadget final : public FxGadget {
TPointParamP m_pa, m_pb;
int m_selected;
public:
VectorFxGadget(FxGadgetController *controller, const TPointParamP &pa,
const TPointParamP &pb)
: FxGadget(controller), m_pa(pa), m_pb(pb), m_selected(0) {
: FxGadget(controller), m_pa(pa), m_pb(pb) {
addParam(pa->getX());
addParam(pa->getY());
addParam(pb->getX());
@ -859,7 +864,7 @@ public:
glColor3dv(m_selectedColor);
else
glColor3d(0, 0, 1);
glPushName(getId());
// glPushName(getId());
double pixelSize = getPixelSize();
TPointD pa = getValue(m_pa);
TPointD pb = getValue(m_pb);
@ -882,11 +887,11 @@ public:
}
tglDrawSegment(pbb, pbb - u * a + v * b);
tglDrawSegment(pbb, pbb - u * a - v * b);
drawDot(pa);
drawDot(pb);
} else
drawDot(pa);
glPopName();
// drawDot(pa);
// drawDot(pb);
} // else
// drawDot(pa);
// glPopName();
}
void leftButtonDown(const TPointD &pos, const TMouseEvent &) override {}
@ -897,53 +902,269 @@ public:
//=============================================================================
class QuadFxGadget final : public FxGadget {
TPointParamP m_pa, m_pb, m_pc, m_pd;
TPointParamP m_TL, m_TR, m_BR, m_BL;
enum HANDLE {
Body = 0,
TopLeft,
TopRight,
BottomRight,
BottomLeft,
TopEdge,
RightEdge,
BottomEdge,
LeftEdge,
None
} m_handle = None;
TPointD m_pivot;
TPointD m_dragStartPos;
TPointD m_startTL, m_startTR, m_startBR, m_startBL;
public:
QuadFxGadget(FxGadgetController *controller, const TPointParamP &pa,
const TPointParamP &pb, const TPointParamP &pc,
const TPointParamP &pd)
: FxGadget(controller), m_pa(pa), m_pb(pb), m_pc(pc), m_pd(pd) {
addParam(pa->getX());
addParam(pa->getY());
addParam(pb->getX());
addParam(pb->getY());
addParam(pc->getX());
addParam(pc->getY());
addParam(pd->getX());
addParam(pd->getY());
QuadFxGadget(FxGadgetController *controller, const TPointParamP &topLeft,
const TPointParamP &topRight, const TPointParamP &bottomRight,
const TPointParamP &bottomLeft)
: FxGadget(controller, 9)
, m_TL(topLeft)
, m_TR(topRight)
, m_BR(bottomRight)
, m_BL(bottomLeft) {
addParam(topLeft->getX());
addParam(topLeft->getY());
addParam(topRight->getX());
addParam(topRight->getY());
addParam(bottomRight->getX());
addParam(bottomRight->getY());
addParam(bottomLeft->getX());
addParam(bottomLeft->getY());
}
void draw(bool picking) override {
int idBase = getId();
auto setColorById = [&](int id) {
if (isSelected(id))
glColor3dv(m_selectedColor);
else
glColor3d(0, 0, 1);
};
auto id2Str = [](const HANDLE handleId) -> std::string {
switch (handleId) {
case TopLeft:
return "Top Left";
case TopRight:
return "Top Right";
case BottomRight:
return "Bottom Right";
case BottomLeft:
return "Bottom Left";
default:
return "";
}
};
auto drawPoint = [&](const TPointD &pos, int id) {
setColorById(id);
glPushName(idBase + id);
double unit = getPixelSize();
glPushMatrix();
glTranslated(pos.x, pos.y, 0);
double r = unit * 3;
tglDrawRect(-r, -r, r, r);
glPopMatrix();
glPopName();
if (isSelected(id) && id >= TopLeft && id <= BottomLeft) {
drawTooltip(pos + TPointD(7, 3) * unit,
id2Str((HANDLE)id) + getLabel());
}
};
setPixelSize();
if (isSelected())
glColor3dv(m_selectedColor);
else
glColor3d(0, 0, 1);
// glPushName(getId());
double pixelSize = getPixelSize();
TPointD pa = getValue(m_pa);
TPointD pb = getValue(m_pb);
TPointD pc = getValue(m_pc);
TPointD pd = getValue(m_pd);
// lines for moving all vertices
glPushName(idBase + Body);
setColorById(Body);
double pixelSize = getPixelSize();
TPointD topLeft = getValue(m_TL);
TPointD topRight = getValue(m_TR);
TPointD bottomRight = getValue(m_BR);
TPointD bottomLeft = getValue(m_BL);
glLineStipple(1, 0xCCCC);
glEnable(GL_LINE_STIPPLE);
glBegin(GL_LINE_STRIP);
tglVertex(pa);
tglVertex(pb);
tglVertex(pc);
tglVertex(pd);
tglVertex(pa);
tglVertex(topLeft);
tglVertex(topRight);
tglVertex(bottomRight);
tglVertex(bottomLeft);
tglVertex(topLeft);
glEnd();
glDisable(GL_LINE_STIPPLE);
// glPopName();
glPopName();
// corners
drawPoint(topLeft, TopLeft);
drawPoint(topRight, TopRight);
drawPoint(bottomRight, BottomRight);
drawPoint(bottomLeft, BottomLeft);
// center of the edges
drawPoint((topLeft + topRight) * 0.5, TopEdge);
drawPoint((topRight + bottomRight) * 0.5, RightEdge);
drawPoint((bottomRight + bottomLeft) * 0.5, BottomEdge);
drawPoint((bottomLeft + topLeft) * 0.5, LeftEdge);
}
void leftButtonDown(const TPointD &pos, const TMouseEvent &) override {}
void leftButtonDrag(const TPointD &pos, const TMouseEvent &) override {}
void leftButtonUp(const TPointD &pos, const TMouseEvent &) 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;
};
//---------------------------------------------------------------------------
void QuadFxGadget::leftButtonDown(const TPointD &pos, const TMouseEvent &) {
m_handle = (HANDLE)m_selected;
m_dragStartPos = pos;
m_startTL = getValue(m_TL);
m_startTR = getValue(m_TR);
m_startBR = getValue(m_BR);
m_startBL = getValue(m_BL);
m_pivot = (m_startTL + m_startTR + m_startBR + m_startBL) * 0.25;
}
//---------------------------------------------------------------------------
void QuadFxGadget::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
TPointD offset = pos - m_dragStartPos;
auto scaleShape = [&](const TPointD &start, const TPointD &pivot) {
TPointD startVec = start - pivot;
TPointD endVec = start + offset - pivot;
TPointD scaleFac((startVec.x == 0.0) ? 1.0 : endVec.x / startVec.x,
(startVec.y == 0.0) ? 1.0 : endVec.y / startVec.y);
if (e.isShiftPressed()) {
if (std::abs(scaleFac.x) > std::abs(scaleFac.y))
scaleFac.y = scaleFac.x;
else
scaleFac.x = scaleFac.y;
}
if (m_startTL != pivot)
setValue(m_TL, pivot + hadamard((m_startTL - pivot), scaleFac));
if (m_startTR != pivot)
setValue(m_TR, pivot + hadamard((m_startTR - pivot), scaleFac));
if (m_startBR != pivot)
setValue(m_BR, pivot + hadamard((m_startBR - pivot), scaleFac));
if (m_startBL != pivot)
setValue(m_BL, pivot + hadamard((m_startBL - pivot), scaleFac));
};
auto doCorner = [&](const TPointParamP point, const TPointD &start,
const TPointD &opposite) {
if (e.isCtrlPressed())
setValue(point, start + offset);
else if (e.isAltPressed())
scaleShape(start, m_pivot);
else
scaleShape(start, opposite);
};
auto doEdge = [&](const TPointParamP p1, const TPointParamP p2) {
if (e.isShiftPressed()) {
if (std::abs(offset.x) > std::abs(offset.y))
offset.y = 0;
else
offset.x = 0;
}
if (m_TL == p1 || m_TL == p2)
setValue(m_TL, m_startTL + offset);
else if (e.isAltPressed())
setValue(m_TL, m_startTL - offset);
if (m_TR == p1 || m_TR == p2)
setValue(m_TR, m_startTR + offset);
else if (e.isAltPressed())
setValue(m_TR, m_startTR - offset);
if (m_BR == p1 || m_BR == p2)
setValue(m_BR, m_startBR + offset);
else if (e.isAltPressed())
setValue(m_BR, m_startBR - offset);
if (m_BL == p1 || m_BL == p2)
setValue(m_BL, m_startBL + offset);
else if (e.isAltPressed())
setValue(m_BL, m_startBL - offset);
};
auto pointRotate = [&](const TPointD pos, const double angle) {
TPointD p = pos - m_pivot;
return m_pivot + TPointD(p.x * std::cos(angle) - p.y * std::sin(angle),
p.x * std::sin(angle) + p.y * std::cos(angle));
};
switch (m_handle) {
case Body:
if (e.isCtrlPressed()) { // rotate
TPointD startVec = m_dragStartPos - m_pivot;
TPointD currentVec = pos - m_pivot;
if (currentVec == TPointD()) return;
double angle = std::atan2(currentVec.y, currentVec.x) -
std::atan2(startVec.y, startVec.x);
if (e.isShiftPressed()) {
angle = std::round(angle / (M_PI / 2.0)) * (M_PI / 2.0);
}
setValue(m_TL, pointRotate(m_startTL, angle));
setValue(m_TR, pointRotate(m_startTR, angle));
setValue(m_BR, pointRotate(m_startBR, angle));
setValue(m_BL, pointRotate(m_startBL, angle));
} else { // translate
// move all shapes
if (e.isShiftPressed()) {
if (std::abs(offset.x) > std::abs(offset.y))
offset.y = 0;
else
offset.x = 0;
}
setValue(m_TL, m_startTL + offset);
setValue(m_TR, m_startTR + offset);
setValue(m_BR, m_startBR + offset);
setValue(m_BL, m_startBL + offset);
}
break;
case TopLeft:
doCorner(m_TL, m_startTL, m_startBR);
break;
case TopRight:
doCorner(m_TR, m_startTR, m_startBL);
break;
case BottomRight:
doCorner(m_BR, m_startBR, m_startTL);
break;
case BottomLeft:
doCorner(m_BL, m_startBL, m_startTR);
break;
case TopEdge:
doEdge(m_TL, m_TR);
break;
case RightEdge:
doEdge(m_TR, m_BR);
break;
case BottomEdge:
doEdge(m_BR, m_BL);
break;
case LeftEdge:
doEdge(m_BL, m_TL);
break;
default:
break;
}
}
//---------------------------------------------------------------------------
void QuadFxGadget::leftButtonUp(const TPointD &pos, const TMouseEvent &) {
m_handle = None;
}
//*************************************************************************************
// FxGadgetController implementation
//*************************************************************************************
@ -981,8 +1202,10 @@ void FxGadgetController::clearGadgets() {
void FxGadgetController::assignId(FxGadget *gadget) {
gadget->setId(m_nextId);
m_idTable[m_nextId] = gadget;
++m_nextId;
for (int g = 0; g < gadget->getHandleCount(); g++) {
m_idTable[m_nextId] = gadget;
++m_nextId;
}
}
//---------------------------------------------------------------------------
@ -1009,9 +1232,10 @@ void FxGadgetController::selectById(unsigned int id) {
it = m_idTable.find(id);
FxGadget *selectedGadget = it != m_idTable.end() ? it->second : 0;
if (selectedGadget != m_selectedGadget) {
if (m_selectedGadget) m_selectedGadget->select(false);
if (m_selectedGadget) m_selectedGadget->select(-1);
m_selectedGadget = selectedGadget;
if (m_selectedGadget) m_selectedGadget->select(true);
if (m_selectedGadget)
m_selectedGadget->select(id - m_selectedGadget->getId());
}
}
@ -1144,7 +1368,7 @@ void FxGadgetController::onFxSwitched() {
// before, the levels were considered as nonZeraryFx and the edit tool
// gadget was not displayed! Vinz
{
if (zfx) fx = zfx->getZeraryFx();
if (zfx) fx = zfx->getZeraryFx();
m_editingNonZeraryFx = false;
}

View file

@ -32,7 +32,6 @@ class TParamUIConcept;
class FxGadget : public TParamObserver {
GLuint m_id;
bool m_selected;
std::vector<TDoubleParamP> m_params;
double m_pixelSize;
@ -42,11 +41,14 @@ class FxGadget : public TParamObserver {
protected:
FxGadgetController *m_controller;
int m_handleCount = 1;
// -1 : not selected, 0~ : handle id
int m_selected;
public:
static GLdouble m_selectedColor[3]; // rgb
FxGadget(FxGadgetController *controller);
FxGadget(FxGadgetController *controller, int handleCount = 1);
virtual ~FxGadget();
void setLabel(std::string label) { m_label = label; }
@ -64,8 +66,11 @@ public:
void setId(GLuint id) { m_id = id; }
GLuint getId() const { return m_id; }
void select(bool selected) { m_selected = selected; }
bool isSelected() const { return m_selected; }
int getHandleCount() { return m_handleCount; }
void select(int selected) { m_selected = selected; }
bool isSelected() const { return m_selected >= 0; }
bool isSelected(int id) const { return m_selected == id; }
void setPixelSize(); // uses tglGetPixelSize2()
void setPixelSize(double pixelSize) { m_pixelSize = pixelSize; }
@ -108,7 +113,7 @@ public:
//-----------------------------------------------------------------------------
} // EditToolGadgets namespace
} // namespace EditToolGadgets
class FxGadgetController final : public QObject {
Q_OBJECT

View file

@ -1,6 +1,6 @@
//------------------------------------------------------
/*! Finger Tool : 線のノイズを埋めるツール
*/
*/
#include "tstroke.h"
#include "tools/toolutils.h"
#include "tools/tool.h"
@ -313,12 +313,14 @@ FingerTool::FingerTool()
, m_selecting(false)
, m_tileSaver(0)
, m_cursor(ToolCursor::EraserCursor)
, m_toolSize("Size:", 1, 100, 10, false)
, m_toolSize("Size:", 1, 1000, 10, false)
, m_invert("Invert", false)
, m_firstTime(true)
, m_workingFrameId(TFrameId()) {
bind(TTool::ToonzImage);
m_toolSize.setNonLinearSlider();
m_prop.bind(m_toolSize);
m_prop.bind(m_invert);
@ -504,7 +506,7 @@ void FingerTool::onDeactivate() {
//-----------------------------------------------------------------------------
/*!
* onDeactivateにもMouseReleaseと同じ処理を行う
*/
*/
void FingerTool::finishBrush() {
if (TToonzImageP ti = (TToonzImageP)getImage(true)) {
if (m_rasterTrack) {
@ -576,9 +578,8 @@ void FingerTool::pick(const TPointD &pos) {
/*---
* pickLineモードのときPurePaintの部分をクリックしてもカレントStyleを変えない
* ---*/
if (ti &&
picker.pickTone(TScale(1.0 / subsampling) * pos +
TPointD(-0.5, -0.5)) == 255)
if (ti && picker.pickTone(TScale(1.0 / subsampling) * pos +
TPointD(-0.5, -0.5)) == 255)
return;
}

View file

@ -113,7 +113,7 @@ public:
FullColorBrushTool::FullColorBrushTool(std::string name)
: TTool(name)
, m_thickness("Size", 1, 100, 1, 5, false)
, m_thickness("Size", 1, 1000, 1, 5, false)
, m_pressure("Pressure", true)
, m_opacity("Opacity", 0, 100, 100, 100, true)
, m_hardness("Hardness:", 0, 100, 100)
@ -133,6 +133,8 @@ FullColorBrushTool::FullColorBrushTool(std::string name)
, m_firstTime(true) {
bind(TTool::RasterImage | TTool::EmptyTarget);
m_thickness.setNonLinearSlider();
m_prop.bind(m_thickness);
m_prop.bind(m_hardness);
m_prop.bind(m_opacity);
@ -302,7 +304,7 @@ void FullColorBrushTool::leftButtonDown(const TPointD &pos,
if (!viewer) return;
TRasterImageP ri = (TRasterImageP)getImage(true);
if (!ri) ri = (TRasterImageP)touchImage();
if (!ri) ri = (TRasterImageP)touchImage();
if (!ri) return;
@ -318,7 +320,13 @@ void FullColorBrushTool::leftButtonDown(const TPointD &pos,
TPointD rasCenter = ras->getCenterD();
TPointD point(pos + rasCenter);
double pressure = m_enabledPressure && e.isTablet() ? e.m_pressure : 0.5;
double pressure;
if (getApplication()->getCurrentLevelStyle()->getTagId() ==
4001) // mypaint brush case
pressure = m_enabledPressure && e.isTablet() ? e.m_pressure : 0.5;
else
pressure = m_enabledPressure ? e.m_pressure : 1.0;
m_tileSet = new TTileSetFullColor(ras->getSize());
m_tileSaver = new TTileSaverFullColor(ras, m_tileSet);
@ -358,7 +366,12 @@ void FullColorBrushTool::leftButtonDrag(const TPointD &pos,
TRasterP ras = ri->getRaster();
TPointD rasCenter = ras->getCenterD();
TPointD point(pos + rasCenter);
double pressure = m_enabledPressure && e.isTablet() ? e.m_pressure : 0.5;
double pressure;
if (getApplication()->getCurrentLevelStyle()->getTagId() ==
4001) // mypaint brush case
pressure = m_enabledPressure && e.isTablet() ? e.m_pressure : 0.5;
else
pressure = m_enabledPressure ? e.m_pressure : 1.0;
m_strokeSegmentRect.empty();
m_toonz_brush->strokeTo(point, pressure, restartBrushTimer());
@ -389,7 +402,12 @@ void FullColorBrushTool::leftButtonUp(const TPointD &pos,
TRasterP ras = ri->getRaster();
TPointD rasCenter = ras->getCenterD();
TPointD point(pos + rasCenter);
double pressure = m_enabledPressure && e.isTablet() ? e.m_pressure : 0.5;
double pressure;
if (getApplication()->getCurrentLevelStyle()->getTagId() ==
4001) // mypaint brush case
pressure = m_enabledPressure && e.isTablet() ? e.m_pressure : 0.5;
else
pressure = m_enabledPressure ? e.m_pressure : 1.0;
m_strokeSegmentRect.empty();
m_toonz_brush->strokeTo(point, pressure, restartBrushTimer());
@ -747,13 +765,7 @@ void FullColorBrushTool::updateCurrentStyle() {
m_minCursorThick = std::max(m_thickness.getValue().first, 1);
m_maxCursorThick =
std::max(m_thickness.getValue().second, m_minCursorThick);
if (!m_enabledPressure) {
double minRadiusLog = log(0.5 * m_minCursorThick);
double maxRadiusLog = log(0.5 * m_maxCursorThick);
double avgRadiusLog = 0.5 * (minRadiusLog + maxRadiusLog);
double avgRadius = exp(avgRadiusLog);
m_minCursorThick = m_maxCursorThick = (int)round(2.0 * avgRadius);
}
if (!m_enabledPressure) m_minCursorThick = m_maxCursorThick;
}
// if this function is called from onEnter(), the clipping rect will not be

View file

@ -368,7 +368,7 @@ private:
FullColorEraserTool::FullColorEraserTool(std::string name)
: TTool(name)
, m_size("Size:", 1, 100, 5, false)
, m_size("Size:", 1, 1000, 5, false)
, m_opacity("Opacity:", 0, 100, 100)
, m_hardness("Hardness:", 0, 100, 100)
, m_eraseType("Type:")
@ -385,6 +385,8 @@ FullColorEraserTool::FullColorEraserTool(std::string name)
, m_isXsheetCell(false) {
bind(TTool::RasterImage);
m_size.setNonLinearSlider();
m_prop.bind(m_size);
m_prop.bind(m_hardness);
m_prop.bind(m_opacity);
@ -987,7 +989,7 @@ void FullColorEraserTool::update(const TRasterImageP &ri, TRectD selArea,
tileSet->add(raster, TRasterImageUtils::convertWorldToRaster(selArea, ri));
TUndo *undo;
undo = new RectFullColorUndo(tileSet, selArea, TStroke(),
undo = new RectFullColorUndo(tileSet, selArea, TStroke(),
m_eraseType.getValue(), level.getPointer(),
m_invertOption.getValue(), frameId);
TRect rect = TRasterImageUtils::eraseRect(ri, selArea);

View file

@ -118,7 +118,6 @@ class MagnetTool final : public TTool {
DoublePair m_extremes;
int m_cursorId;
double m_pointSize;
TUndo *m_undo;
typedef struct {
@ -142,11 +141,13 @@ public:
MagnetTool()
: TTool("T_Magnet")
, m_active(false)
, m_pointSize(-1)
, m_oldStrokesArray()
, m_toolSize("Size:", 0, 100, 20) // W_ToolOptions_MagnetTool
, m_toolSize("Size:", 10, 500, 20) // W_ToolOptions_MagnetTool
{
bind(TTool::Vectors);
m_toolSize.setNonLinearSlider();
m_prop.bind(m_toolSize);
}
@ -159,12 +160,8 @@ public:
m_cursorId = ToolCursor::MagnetCursor;
else
m_cursorId = ToolCursor::CURSOR_NO;
updatePointSize();
}
void onLeave() override { m_pointSize = -1; }
void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override {
TPointD p(pos);
@ -190,6 +187,8 @@ public:
m_hitStrokeCorners.clear();
m_strokeToModifyCorners.clear();
double pointSize = m_toolSize.getValue();
UINT i = 0;
for (; i < vi->getStrokeCount(); ++i) {
if (!vi->inCurrentGroup(i)) continue;
@ -198,11 +197,11 @@ public:
ref = stroke;
// calcola le intersezioni
std::vector<double> intersections;
intersect(*ref, p, m_pointSize, intersections);
intersect(*ref, p, pointSize, intersections);
if (intersections.empty()) {
if (increaseControlPoints(*ref,
TStrokePointDeformation(p, m_pointSize))) {
TStrokePointDeformation(p, pointSize))) {
m_changedStrokes.push_back(i);
m_strokeHit.push_back(ref);
@ -225,11 +224,11 @@ public:
splitStroke(*sc.m_parent, intersections, sc.m_splitted);
selectStrokeToMove(sc.m_splitted, p, m_pointSize, sc.m_splittedToMove);
selectStrokeToMove(sc.m_splitted, p, pointSize, sc.m_splittedToMove);
for (UINT ii = 0; ii < sc.m_splittedToMove.size(); ++ii) {
TStroke *temp = sc.m_splittedToMove[ii];
bool test = increaseControlPoints(
*temp, TStrokePointDeformation(p, m_pointSize));
*temp, TStrokePointDeformation(p, pointSize));
assert(test);
std::vector<int> *corners = new std::vector<int>;
@ -245,7 +244,7 @@ public:
}
m_oldStrokesArray.resize(m_changedStrokes.size());
for (i = 0; i < m_changedStrokes.size(); i++)
for (i = 0; i < m_changedStrokes.size(); i++)
m_oldStrokesArray[i] = new TStroke(*(vi->getStroke(m_changedStrokes[i])));
if (!strokeUndo.empty()) {
@ -288,19 +287,21 @@ leftButtonUp(p);
lefrightButtonDown(p);
}
*/
double pointSize = m_toolSize.getValue();
UINT i, j;
for (i = 0; i < m_strokeHit.size(); ++i)
modifyControlPoints(*m_strokeHit[i],
TStrokePointDeformation(offset, m_pointAtMouseDown,
m_pointSize * 0.7));
modifyControlPoints(
*m_strokeHit[i],
TStrokePointDeformation(offset, m_pointAtMouseDown, pointSize * 0.7));
for (i = 0; i < m_strokeToModify.size(); ++i)
for (j = 0; j < m_strokeToModify[i].m_splittedToMove.size(); ++j) {
TStroke *temp = m_strokeToModify[i].m_splittedToMove[j];
modifyControlPoints(*temp,
TStrokePointDeformation(offset, m_pointAtMouseDown,
m_pointSize * 0.7));
pointSize * 0.7));
}
m_pointAtMove = p;
@ -399,10 +400,10 @@ lefrightButtonDown(p);
// glPushMatrix();
// tglMultMatrix(viewMatrix);
if (m_pointSize > 0) {
tglColor(TPixel32::Red);
tglDrawCircle(m_pointAtMove, m_pointSize);
}
double pointSize = m_toolSize.getValue();
tglColor(TPixel32::Red);
tglDrawCircle(m_pointAtMove, pointSize);
if (!m_active) {
// glPopMatrix();
@ -439,31 +440,14 @@ lefrightButtonDown(p);
int getCursorId() const override { return m_cursorId; }
bool onPropertyChanged(std::string propertyName) override
{
if(propertyName == m_toolSize.getName()) {
updatePointSize();
bool onPropertyChanged(std::string propertyName) override {
if (propertyName == m_toolSize.getName()) {
invalidate();
}
return true;
}
private:
/// Update point size based on property.
void updatePointSize()
{
double x = m_toolSize.getValue();
double minRange = 1;
double maxRange = 100;
double minSize = 10;
double maxSize = 100;
m_pointSize =
(x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize;
}
} magnetTool;
// TTool *getMagnetTool() {return &magnetTool;}

View file

@ -318,11 +318,13 @@ PaintBrushTool::PaintBrushTool()
, m_tileSaver(0)
, m_cursor(ToolCursor::EraserCursor)
// sostituire i nomi con quelli del current, tipo W_ToolOptions...
, m_toolSize("Size:", 1, 100, 10, false) // W_ToolOptions_BrushToolSize
, m_colorType("Mode:") // W_ToolOptions_InkOrPaint
, m_onlyEmptyAreas("Selective", false) // W_ToolOptions_Selective
, m_toolSize("Size:", 1, 1000, 10, false) // W_ToolOptions_BrushToolSize
, m_colorType("Mode:") // W_ToolOptions_InkOrPaint
, m_onlyEmptyAreas("Selective", false) // W_ToolOptions_Selective
, m_firstTime(true)
, m_workingFrameId(TFrameId()) {
m_toolSize.setNonLinearSlider();
m_colorType.addValue(LINES);
m_colorType.addValue(AREAS);
m_colorType.addValue(ALL);

View file

@ -81,6 +81,8 @@ PinchTool::PinchTool()
, m_selector(500, 10, 1000) {
bind(TTool::Vectors);
m_toolRange.setNonLinearSlider();
m_prop.bind(m_toolCornerSize);
m_prop.bind(m_autoOrManual);
m_prop.bind(m_toolRange);
@ -138,7 +140,7 @@ void PinchTool::updateInterfaceStatus(const TMouseEvent &event) {
m_status.key_event_ = ContextStatus::NONE;
// mutual exclusive
if (event.isCtrlPressed()) m_status.key_event_ = ContextStatus::CTRL;
if (event.isCtrlPressed()) m_status.key_event_ = ContextStatus::CTRL;
if (event.isShiftPressed()) m_status.key_event_ = ContextStatus::SHIFT;
// TODO: **DEVE** essere fatto dentro la costruzione di TMouseEvent
@ -357,7 +359,7 @@ void PinchTool::onEnter() {
//-----------------------------------------------------------------------------
void PinchTool::onLeave() {
if (!m_active) m_draw = false;
if (!m_active) m_draw = false;
m_status.stroke2change_ = 0;
// Abbiamo dovuto commentarlo perche' stranamente

View file

@ -281,7 +281,7 @@ void eraseStroke(const TToonzImageP &ti, TStroke *stroke,
if (!invert)
area = rasterErasedArea.enlarge(2);
else
area = ras->getBounds();
area = ras->getBounds();
TTileSetCM32 *tileSet = new TTileSetCM32(ras->getSize());
tileSet->add(ras, area);
TUndoManager::manager()->add(new RectRasterUndo(
@ -569,7 +569,7 @@ EraserTool inkPaintEraserTool("T_Eraser");
EraserTool::EraserTool(std::string name)
: TTool(name)
, m_toolSize("Size:", 1, 100, 10, false) // W_ToolOptions_EraserToolSize
, m_toolSize("Size:", 1, 1000, 10, false) // W_ToolOptions_EraserToolSize
, m_hardness("Hardness:", 0, 100, 100)
, m_eraseType("Type:") // W_ToolOptions_Erasetype
, m_colorType("Mode:") // W_ToolOptions_InkOrPaint
@ -592,6 +592,8 @@ EraserTool::EraserTool(std::string name)
, m_isLeftButtonPressed(false) {
bind(TTool::ToonzImage);
m_toolSize.setNonLinearSlider();
m_prop.bind(m_toolSize);
m_prop.bind(m_hardness);
m_prop.bind(m_eraseType);
@ -887,8 +889,8 @@ void EraserTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
int currentStyle = 0;
if (m_currentStyle.getValue())
currentStyle = TTool::getApplication()->getCurrentLevelStyleIndex();
m_tileSet = new TTileSetCM32(raster->getSize());
m_tileSaver = new TTileSaverCM32(raster, m_tileSet);
m_tileSet = new TTileSetCM32(raster->getSize());
m_tileSaver = new TTileSaverCM32(raster, m_tileSet);
TPointD halfThick(m_toolSize.getValue() * 0.5,
m_toolSize.getValue() * 0.5);
invalidateRect = TRectD(pos - halfThick, pos + halfThick);
@ -898,7 +900,7 @@ void EraserTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
m_colorTypeEraser = INK;
}
if (m_colorType.getValue() == AREAS) m_colorTypeEraser = PAINT;
if (m_colorType.getValue() == ALL) m_colorTypeEraser = INKNPAINT;
if (m_colorType.getValue() == ALL) m_colorTypeEraser = INKNPAINT;
m_normalEraser = new RasterStrokeGenerator(
raster, ERASE, m_colorTypeEraser, 0, intPos,
m_currentStyle.getValue(), currentStyle,
@ -1617,7 +1619,7 @@ void EraserTool::doMultiEraser(const TImageP &img, double t,
//--------------------------------------------------------------------------------------------------
/*!ドラッグ中にツールが切り替わった時、終了処理を行う
*/
*/
void EraserTool::onDeactivate() {
if (!m_isLeftButtonPressed || !m_selecting) return;
@ -1657,10 +1659,11 @@ void EraserTool::storeUndoAndRefresh() {
TUndoManager::manager()->add(new RasterBluredEraserUndo(
m_tileSet, m_points,
TTool::getApplication()->getCurrentLevelStyleIndex(),
m_currentStyle.getValue(), TTool::getApplication()
->getCurrentLevel()
->getLevel()
->getSimpleLevel(),
m_currentStyle.getValue(),
TTool::getApplication()
->getCurrentLevel()
->getLevel()
->getSimpleLevel(),
m_workingFrameId.isEmptyFrame() ? getCurrentFid() : m_workingFrameId,
m_toolSize.getValue(), m_hardness.getValue() * 0.01,
m_colorType.getValue()));
@ -1686,7 +1689,7 @@ void EraserTool::storeUndoAndRefresh() {
//--------------------------------------------------------------------------------------------------
/*! Brush、PaintBrush、EraserToolがPencilModeのときにTrueを返す
*/
*/
bool EraserTool::isPencilModeActive() {
return m_eraseType.getValue() == NORMALERASE && m_pencil.getValue();
}

View file

@ -22,6 +22,7 @@
#include "toonz/tobjecthandle.h"
#include "toonz/txshlevelhandle.h"
#include "toonz/tscenehandle.h"
#include "toonz/txsheethandle.h"
#include "toonz/tcenterlinevectorizer.h"
#include "toonz/stage.h"
@ -196,22 +197,18 @@ public:
// PasteStrokesUndo
//-----------------------------------------------------------------------------
class PasteStrokesUndo final : public TUndo {
TXshSimpleLevelP m_level;
TFrameId m_frameId;
class PasteStrokesUndo final : public ToolUtils::TToolUndo {
std::set<int> m_indexes;
TPaletteP m_oldPalette;
QMimeData *m_oldData;
TSceneHandle *m_sceneHandle;
public:
PasteStrokesUndo(TXshSimpleLevel *level, const TFrameId &frameId,
std::set<int> &indexes, TPaletteP oldPalette,
TSceneHandle *sceneHandle)
: m_level(level)
, m_frameId(frameId)
TSceneHandle *sceneHandle, bool createdFrame,
bool createdLevel)
: TToolUndo(level, frameId, createdFrame, createdLevel, oldPalette)
, m_indexes(indexes)
, m_oldPalette(oldPalette)
, m_sceneHandle(sceneHandle) {
QClipboard *clipboard = QApplication::clipboard();
m_oldData = cloneData(clipboard->mimeData());
@ -230,9 +227,16 @@ public:
std::set<int> indexes = m_indexes;
deleteStrokesWithoutUndo(image, indexes);
removeLevelAndFrameIfNeeded();
TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
notifyImageChanged();
}
void redo() const override {
insertLevelAndFrameIfNeeded();
TVectorImageP image = m_level->getFrame(m_frameId, true);
std::set<int> indexes = m_indexes;
@ -245,6 +249,9 @@ public:
TTool::getApplication()->getCurrentTool()->getTool()->notifyImageChanged();
clipboard->setMimeData(data, QClipboard::Clipboard);
TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
notifyImageChanged();
}
int getSize() const override { return sizeof(*this); }
@ -566,7 +573,8 @@ void StrokeSelection::paste() {
TXshSimpleLevel *level =
TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
TUndoManager::manager()->add(new PasteStrokesUndo(
level, tool->getCurrentFid(), m_indexes, oldPalette, m_sceneHandle));
level, tool->getCurrentFid(), m_indexes, oldPalette, m_sceneHandle,
tool->m_isFrameCreated, tool->m_isLevelCreated));
m_updateSelectionBBox = isPaste;
}
tool->notifyImageChanged();

View file

@ -148,6 +148,7 @@ ToolOptionSlider::ToolOptionSlider(TTool *tool, TDoubleProperty *property,
: DoubleField()
, ToolOptionControl(tool, property->getName(), toolHandle)
, m_property(property) {
setLinearSlider(property->isLinearSlider());
m_property->addListener(this);
TDoubleProperty::Range range = property->getRange();
setRange(range.first, range.second);
@ -250,6 +251,7 @@ ToolOptionPairSlider::ToolOptionPairSlider(TTool *tool,
: DoublePairField(0, property->isMaxRangeLimited())
, ToolOptionControl(tool, property->getName(), toolHandle)
, m_property(property) {
setLinearSlider(property->isLinearSlider());
m_property->addListener(this);
TDoublePairProperty::Value value = property->getValue();
TDoublePairProperty::Range range = property->getRange();
@ -377,6 +379,7 @@ ToolOptionIntPairSlider::ToolOptionIntPairSlider(TTool *tool,
: IntPairField(0, property->isMaxRangeLimited())
, ToolOptionControl(tool, property->getName(), toolHandle)
, m_property(property) {
setLinearSlider(property->isLinearSlider());
setLeftText(leftName);
setRightText(rightName);
m_property->addListener(this);
@ -491,6 +494,7 @@ ToolOptionIntSlider::ToolOptionIntSlider(TTool *tool, TIntProperty *property,
: IntField(0, property->isMaxRangeLimited())
, ToolOptionControl(tool, property->getName(), toolHandle)
, m_property(property) {
setLinearSlider(property->isLinearSlider());
m_property->addListener(this);
TIntProperty::Range range = property->getRange();
setRange(range.first, range.second);
@ -621,7 +625,7 @@ void ToolOptionCombo::loadEntries() {
}");
}
}
int tmpWidth = fontMetrics().width(items[i].UIName);
int tmpWidth = fontMetrics().width(items[i].UIName);
if (tmpWidth > maxWidth) maxWidth = tmpWidth;
}
@ -655,8 +659,8 @@ void ToolOptionCombo::onActivated(int index) {
void ToolOptionCombo::doShowPopup() {
if (Preferences::instance()->getDropdownShortcutsCycleOptions()) {
const TEnumProperty::Range &range = m_property->getRange();
int theIndex = currentIndex() + 1;
const TEnumProperty::Range &range = m_property->getRange();
int theIndex = currentIndex() + 1;
if (theIndex >= (int)range.size()) theIndex = 0;
doOnActivated(theIndex);
} else {
@ -738,8 +742,8 @@ void ToolOptionFontCombo::onActivated(int index) {
void ToolOptionFontCombo::doShowPopup() {
if (!isInVisibleViewer(this)) return;
if (Preferences::instance()->getDropdownShortcutsCycleOptions()) {
const TEnumProperty::Range &range = m_property->getRange();
int theIndex = currentIndex() + 1;
const TEnumProperty::Range &range = m_property->getRange();
int theIndex = currentIndex() + 1;
if (theIndex >= (int)range.size()) theIndex = 0;
onActivated(theIndex);
setCurrentIndex(theIndex);
@ -1415,8 +1419,8 @@ void PegbarCenterField::onChange(TMeasuredValue *fld, bool addToUndo) {
TStageObject *obj = xsh->getStageObject(objId);
double v = fld->getValue(TMeasuredValue::MainUnit);
TPointD center = obj->getCenter(frame);
double v = fld->getValue(TMeasuredValue::MainUnit);
TPointD center = obj->getCenter(frame);
if (!m_firstMouseDrag) m_oldCenter = center;
if (m_index == 0)
center.x = v;
@ -1507,7 +1511,7 @@ PropertyMenuButton::PropertyMenuButton(QWidget *parent, TTool *tool,
setIcon(icon);
setToolTip(tooltip);
QMenu *menu = new QMenu(tooltip, this);
QMenu *menu = new QMenu(tooltip, this);
if (!tooltip.isEmpty()) tooltip = tooltip + " ";
QActionGroup *actiongroup = new QActionGroup(this);
@ -1593,13 +1597,13 @@ bool SelectionScaleField::applyChange(bool addToUndo) {
return false;
DragSelectionTool::DragTool *scaleTool = createNewScaleTool(m_tool, 0);
double p = getValue();
if (p == 0) p = 0.00001;
DragSelectionTool::FourPoints points = m_tool->getBBox();
TPointD center = m_tool->getCenter();
TPointD p0M = points.getPoint(7);
TPointD p1M = points.getPoint(5);
TPointD pM1 = points.getPoint(6);
TPointD pM0 = points.getPoint(4);
if (p == 0) p = 0.00001;
DragSelectionTool::FourPoints points = m_tool->getBBox();
TPointD center = m_tool->getCenter();
TPointD p0M = points.getPoint(7);
TPointD p1M = points.getPoint(5);
TPointD pM1 = points.getPoint(6);
TPointD pM0 = points.getPoint(4);
int pointIndex;
TPointD sign(1, 1);
TPointD scaleFactor = m_tool->m_deformValues.m_scaleValue;

View file

@ -251,8 +251,9 @@ static void findMaxCurvPoints(TStroke *stroke, const float &angoloLim,
double estremo_int = 0;
double t = -1;
if (q != TPointD(0, 0)) {
t = 0.25 * (2 * q.x * q.x + 2 * q.y * q.y - q.x * p0.x + q.x * p2.x -
q.y * p0.y + q.y * p2.y) /
t = 0.25 *
(2 * q.x * q.x + 2 * q.y * q.y - q.x * p0.x + q.x * p2.x -
q.y * p0.y + q.y * p2.y) /
(q.x * q.x + q.y * q.y);
dp = -p0 + p2 + 2 * q - 4 * t * q; // First derivate of the curve
@ -286,7 +287,7 @@ static void findMaxCurvPoints(TStroke *stroke, const float &angoloLim,
if (estremo_sx >= estremo_dx)
t_ext = 0;
else
t_ext = 1;
t_ext = 1;
double maxEstremi = std::max(estremo_dx, estremo_sx);
if (maxEstremi > estremo_int) {
t = t_ext;
@ -600,9 +601,9 @@ public:
//=========================================================================================================
double computeThickness(double pressure, const TDoublePairProperty &property) {
double t = pressure * pressure * pressure;
double thick0 = property.getValue().first;
double thick1 = property.getValue().second;
double t = pressure * pressure * pressure;
double thick0 = property.getValue().first;
double thick1 = property.getValue().second;
if (thick1 < 0.0001) thick0 = thick1 = 0.0;
return (thick0 + (thick1 - thick0) * t) * 0.5;
}
@ -821,7 +822,7 @@ void SmoothStroke::generatePoints() {
ToonzRasterBrushTool::ToonzRasterBrushTool(std::string name, int targetType)
: TTool(name)
, m_rasThickness("Size", 1, 100, 1, 5)
, m_rasThickness("Size", 1, 1000, 1, 5)
, m_smooth("Smooth:", 0, 50, 0)
, m_hardness("Hardness:", 0, 100, 100)
, m_preset("Preset:")
@ -842,6 +843,8 @@ ToonzRasterBrushTool::ToonzRasterBrushTool(std::string name, int targetType)
, m_notifier(0) {
bind(targetType);
m_rasThickness.setNonLinearSlider();
m_prop[0].bind(m_rasThickness);
m_prop[0].bind(m_hardness);
m_prop[0].bind(m_smooth);
@ -1244,7 +1247,7 @@ void ToonzRasterBrushTool::leftButtonDown(const TPointD &pos,
: maxThick;
/*--- ストロークの最初にMaxサイズの円が描かれてしまう不具合を防止する
* ---*/
* ---*/
if (m_pressure.getValue() && e.m_pressure == 1.0)
thickness = m_rasThickness.getValue().first;
@ -1305,7 +1308,7 @@ void ToonzRasterBrushTool::leftButtonDown(const TPointD &pos,
TRectD(m_brushPos - thickOffset, m_brushPos + thickOffset);
} else if (m_hardness.getValue() == 100 || m_pencil.getValue()) {
/*-- Pencilモードでなく、Hardness=100 の場合のブラシサイズを1段階下げる
* --*/
* --*/
if (!m_pencil.getValue()) thickness -= 1.0;
TThickPoint thickPoint(centeredPos + convert(ras->getCenter()),
@ -1408,7 +1411,7 @@ void ToonzRasterBrushTool::leftButtonDrag(const TPointD &pos,
} else if (m_rasterTrack &&
(m_hardness.getValue() == 100 || m_pencil.getValue())) {
/*-- Pencilモードでなく、Hardness=100 の場合のブラシサイズを1段階下げる
* --*/
* --*/
if (!m_pencil.getValue()) thickness -= 1.0;
TThickPoint thickPoint(centeredPos + rasCenter, thickness);
@ -1518,7 +1521,7 @@ void ToonzRasterBrushTool::leftButtonUp(const TPointD &pos,
//---------------------------------------------------------------------------------------------------------------
/*!
* onDeactivate時とMouseRelease時にと同じ終了処理を行う
*/
*/
void ToonzRasterBrushTool::finishRasterBrush(const TPointD &pos,
double pressureVal) {
TToonzImageP ti = TImageP(getImage(true));
@ -2096,7 +2099,7 @@ void ToonzRasterBrushTool::loadLastBrush() {
//------------------------------------------------------------------
/*! Brush、PaintBrush、EraserToolがPencilModeのときにTrueを返す
*/
*/
bool ToonzRasterBrushTool::isPencilModeActive() {
return getTargetType() == TTool::ToonzImage && m_pencil.getValue();
}

View file

@ -273,8 +273,9 @@ static void findMaxCurvPoints(TStroke *stroke, const float &angoloLim,
double estremo_int = 0;
double t = -1;
if (q != TPointD(0, 0)) {
t = 0.25 * (2 * q.x * q.x + 2 * q.y * q.y - q.x * p0.x + q.x * p2.x -
q.y * p0.y + q.y * p2.y) /
t = 0.25 *
(2 * q.x * q.x + 2 * q.y * q.y - q.x * p0.x + q.x * p2.x -
q.y * p0.y + q.y * p2.y) /
(q.x * q.x + q.y * q.y);
dp = -p0 + p2 + 2 * q - 4 * t * q; // First derivate of the curve
@ -308,7 +309,7 @@ static void findMaxCurvPoints(TStroke *stroke, const float &angoloLim,
if (estremo_sx >= estremo_dx)
t_ext = 0;
else
t_ext = 1;
t_ext = 1;
double maxEstremi = std::max(estremo_dx, estremo_sx);
if (maxEstremi > estremo_int) {
t = t_ext;
@ -454,9 +455,9 @@ void getAboveStyleIdSet(int styleId, TPaletteP palette,
double computeThickness(double pressure, const TDoublePairProperty &property,
bool isPath) {
if (isPath) return 0.0;
double t = pressure * pressure * pressure;
double thick0 = property.getValue().first;
double thick1 = property.getValue().second;
double t = pressure * pressure * pressure;
double thick0 = property.getValue().first;
double thick1 = property.getValue().second;
if (thick1 < 0.0001) thick0 = thick1 = 0.0;
return (thick0 + (thick1 - thick0) * t) * 0.5;
}
@ -471,7 +472,7 @@ double computeThickness(double pressure, const TDoublePairProperty &property,
ToonzVectorBrushTool::ToonzVectorBrushTool(std::string name, int targetType)
: TTool(name)
, m_thickness("Size", 0, 100, 0, 5)
, m_thickness("Size", 0, 1000, 0, 5)
, m_accuracy("Accuracy:", 1, 100, 20)
, m_smooth("Smooth:", 0, 50, 0)
, m_preset("Preset:")
@ -496,6 +497,9 @@ ToonzVectorBrushTool::ToonzVectorBrushTool(std::string name, int targetType)
, m_targetType(targetType)
, m_workingFrameId(TFrameId()) {
bind(targetType);
m_thickness.setNonLinearSlider();
m_prop[0].bind(m_thickness);
m_prop[0].bind(m_accuracy);
m_prop[0].bind(m_smooth);
@ -607,8 +611,8 @@ void ToonzVectorBrushTool::onActivate() {
void ToonzVectorBrushTool::onDeactivate() {
/*---
* onDeactivateにもMouseReleaseと同じ処理を行う
* ---*/
* onDeactivateにもMouseReleaseと同じ処理を行う
* ---*/
// End current stroke.
if (m_active && m_enabled) {
@ -684,7 +688,7 @@ void ToonzVectorBrushTool::leftButtonDown(const TPointD &pos,
/*--- ストロークの最初にMaxサイズの円が描かれてしまう不具合を防止する ---*/
if (m_pressure.getValue() && e.m_pressure == 1.0)
thickness = m_thickness.getValue().first * 0.5;
thickness = m_thickness.getValue().first * 0.5;
m_currThickness = thickness;
m_smoothStroke.beginStroke(m_smooth.getValue());
@ -1183,7 +1187,7 @@ void ToonzVectorBrushTool::checkStrokeSnapping(bool beforeMousePress,
if (Preferences::instance()->getVectorSnappingTarget() == 1) return;
TVectorImageP vi(getImage(false));
bool checkSnap = m_snap.getValue();
bool checkSnap = m_snap.getValue();
if (invertCheck) checkSnap = !checkSnap;
if (vi && checkSnap) {
m_dragDraw = true;
@ -1233,8 +1237,8 @@ void ToonzVectorBrushTool::checkStrokeSnapping(bool beforeMousePress,
}
}
if (snapFound) {
m_lastSnapPoint = TPointD(point1.x, point1.y);
m_foundLastSnap = true;
m_lastSnapPoint = TPointD(point1.x, point1.y);
m_foundLastSnap = true;
if (distance2 < 2.0) m_dragDraw = false;
}
}
@ -1251,7 +1255,7 @@ void ToonzVectorBrushTool::checkGuideSnapping(bool beforeMousePress,
beforeMousePress ? foundSnap = m_foundFirstSnap : foundSnap = m_foundLastSnap;
beforeMousePress ? snapPoint = m_firstSnapPoint : snapPoint = m_lastSnapPoint;
bool checkSnap = m_snap.getValue();
bool checkSnap = m_snap.getValue();
if (invertCheck) checkSnap = !checkSnap;
if (checkSnap) {
@ -1314,8 +1318,8 @@ void ToonzVectorBrushTool::checkGuideSnapping(bool beforeMousePress,
snapPoint.x = hGuide;
}
beforeMousePress ? m_foundFirstSnap = true : m_foundLastSnap = true;
beforeMousePress ? m_firstSnapPoint = snapPoint : m_lastSnapPoint =
snapPoint;
beforeMousePress ? m_firstSnapPoint = snapPoint
: m_lastSnapPoint = snapPoint;
}
}
}
@ -1638,7 +1642,7 @@ void ToonzVectorBrushTool::loadLastBrush() {
//------------------------------------------------------------------
/*! Brush、PaintBrush、EraserToolがPencilModeのときにTrueを返す
*/
*/
bool ToonzVectorBrushTool::isPencilModeActive() { return false; }
//==========================================================================================================

View file

@ -65,7 +65,7 @@ void mapToVector(const std::map<int, VIStroke *> &theMap,
std::vector<int> &theVect) {
assert(theMap.size() == theVect.size());
std::map<int, VIStroke *>::const_iterator it = theMap.begin();
UINT i = 0;
UINT i = 0;
for (; it != theMap.end(); ++it) {
theVect[i++] = it->first;
}
@ -146,7 +146,7 @@ public:
image->removeStrokes(newStrokeIndex, true, false);
std::map<int, VIStroke *>::const_iterator it = m_originalStrokes.begin();
UINT i = 0;
UINT i = 0;
VIStroke *s;
for (; it != m_originalStrokes.end(); ++it) {
s = cloneVIStroke(it->second);
@ -200,7 +200,7 @@ public:
image->removeStrokes(oldStrokeIndex, true, false);
std::map<int, VIStroke *>::const_iterator it = m_newStrokes.begin();
UINT i = 0;
UINT i = 0;
VIStroke *s;
for (; it != m_newStrokes.end(); ++it) {
s = cloneVIStroke(it->second);
@ -357,11 +357,11 @@ private:
EraserTool::EraserTool()
: TTool("T_Eraser")
, m_eraseType("Type:") // "W_ToolOptions_Erasetype"
, m_toolSize("Size:", 1, 100, 10) // "W_ToolOptions_EraserToolSize"
, m_selective("Selective", false) // "W_ToolOptions_Selective"
, m_invertOption("Invert", false) // "W_ToolOptions_Invert"
, m_multi("Frame Range", false) // "W_ToolOptions_FrameRange"
, m_eraseType("Type:") // "W_ToolOptions_Erasetype"
, m_toolSize("Size:", 1, 1000, 10) // "W_ToolOptions_EraserToolSize"
, m_selective("Selective", false) // "W_ToolOptions_Selective"
, m_invertOption("Invert", false) // "W_ToolOptions_Invert"
, m_multi("Frame Range", false) // "W_ToolOptions_FrameRange"
, m_pointSize(-1)
, m_undo(0)
, m_currCell(-1, -1)
@ -371,6 +371,8 @@ EraserTool::EraserTool()
, m_firstTime(true) {
bind(TTool::VectorImage);
m_toolSize.setNonLinearSlider();
m_prop.bind(m_toolSize);
m_prop.bind(m_eraseType);
m_eraseType.addValue(NORMAL_ERASE);
@ -1380,7 +1382,7 @@ void EraserTool::multiEreserRegion(TStroke *stroke, const TMouseEvent &e) {
//-----------------------------------------------------------------------------
/*! When the tool is switched during dragging, Erase end processing is performed
*/
*/
void EraserTool::onDeactivate() {
if (!m_active) return;

View file

@ -809,17 +809,17 @@ void SceneViewer::onRelease(const TMouseEvent &event) {
quit:
m_mouseButton = Qt::NoButton;
// If m_tabletState is "Touched", we've been called by tabletPress event.
// Don't clear it out table state so the tablePress event will process
// correctly.
if (m_tabletState != Touched) m_tabletState = None;
m_mouseState = None;
m_tabletMove = false;
m_pressure = 0;
// Leave m_tabletEvent as-is in order to check whether the onRelease is called
// from tabletEvent or not in mouseReleaseEvent.
if (m_tabletState == Released) // only clear if tabletRelease event
m_tabletEvent = false;
// If m_tabletState is "Touched", we've been called by tabletPress event.
// Don't clear it out table state so the tablePress event will process
// correctly.
if (m_tabletState != Touched) m_tabletState = None;
m_mouseState = None;
m_tabletMove = false;
m_pressure = 0;
}
//-----------------------------------------------------------------------------

View file

@ -112,11 +112,11 @@ DoubleValueField::DoubleValueField(QWidget *parent,
bool ret = true;
ret = ret && connect(m_lineEdit, SIGNAL(valueChanged()),
SLOT(onLineEditValueChanged()));
ret = ret && connect(m_roller, SIGNAL(valueChanged(bool)),
ret = ret && connect(m_roller, SIGNAL(valueChanged(bool)),
SLOT(onRollerValueChanged(bool)));
ret = ret && connect(m_slider, SIGNAL(valueChanged(int)),
ret = ret && connect(m_slider, SIGNAL(valueChanged(int)),
SLOT(onSliderChanged(int)));
ret = ret &&
ret = ret &&
connect(m_slider, SIGNAL(sliderReleased()), SLOT(onSliderReleased()));
ret = ret && connect(m_lineEdit, SIGNAL(editingFinished()), this,
SIGNAL(valueEditedByHand()));
@ -133,6 +133,50 @@ DoubleValueField::DoubleValueField(QWidget *parent,
//-----------------------------------------------------------------------------
double DoubleValueField::pos2value(int x) const {
int dicimal = m_lineEdit->getDecimals();
if (m_isLinearSlider) return (double)x * pow(0.1, dicimal);
// nonlinear slider case
double rangeSize = (double)(m_slider->maximum() - m_slider->minimum());
double posRatio = (double)(x - m_slider->minimum()) / rangeSize;
double t;
if (posRatio <= 0.5)
t = 0.04 * posRatio;
else if (posRatio <= 0.75)
t = -0.02 + 0.08 * posRatio;
else if (posRatio <= 0.9)
t = -0.26 + 0.4 * posRatio;
else
t = -8.0 + 9.0 * posRatio;
double sliderValue = round((double)m_slider->minimum() + rangeSize * t);
return sliderValue * pow(0.1, dicimal);
}
//-----------------------------------------------------------------------------
int DoubleValueField::value2pos(double v) const {
int dicimal = m_lineEdit->getDecimals();
double sliderValue = round(v * pow(10., dicimal));
if (m_isLinearSlider) return (int)sliderValue;
// nonlinear slider case
double rangeSize = (double)(m_slider->maximum() - m_slider->minimum());
double valueRatio = (sliderValue - (double)m_slider->minimum()) / rangeSize;
double t;
if (valueRatio <= 0.02)
t = valueRatio / 0.04;
else if (valueRatio <= 0.04)
t = (valueRatio + 0.02) / 0.08;
else if (valueRatio <= 0.1)
t = (valueRatio + 0.26) / 0.4;
else
t = (valueRatio + 8.0) / 9.0;
return m_slider->minimum() + (int)(t * rangeSize);
}
//-----------------------------------------------------------------------------
void DoubleValueField::getRange(double &minValue, double &maxValue) {
m_lineEdit->getRange(minValue, maxValue);
}
@ -159,11 +203,7 @@ void DoubleValueField::setValue(double value) {
if (m_lineEdit->getValue() == value) return;
m_lineEdit->setValue(value);
m_roller->setValue(value);
int dicimal = m_lineEdit->getDecimals();
int sliderValue = (int)round(value * pow(10., dicimal));
m_slider->setValue(sliderValue);
m_slider->setValue(value2pos(value));
// forzo il repaint... non sempre si aggiorna e l'update non sembra risolvere
// il ptroblema!!!
m_slider->repaint();
@ -215,9 +255,8 @@ bool DoubleValueField::isRollerEnabled() { return m_roller->isEnabled(); }
//-----------------------------------------------------------------------------
void DoubleValueField::onSliderChanged(int value) {
int dicimal = m_lineEdit->getDecimals();
double val = double(value) * pow(0.1, dicimal);
void DoubleValueField::onSliderChanged(int sliderPos) {
double val = pos2value(sliderPos);
// Controllo necessario per evitare che il segnale di cambiamento venga emesso
// piu' volte.
@ -237,16 +276,15 @@ void DoubleValueField::onSliderChanged(int value) {
//-----------------------------------------------------------------------------
void DoubleValueField::onLineEditValueChanged() {
double value = m_lineEdit->getValue();
int dicimal = m_lineEdit->getDecimals();
int sliderValue = (int)round(value * pow(10., dicimal));
double value = m_lineEdit->getValue();
int dicimal = m_lineEdit->getDecimals();
// Control necessary to prevent the change signal from being emitted more than
// once.
if ((m_slider->value() == sliderValue && m_slider->isVisible()) ||
if ((pos2value(m_slider->value()) == value && m_slider->isVisible()) ||
(m_roller->getValue() == value && m_roller->isVisible()))
return;
m_slider->setValue(sliderValue);
m_slider->setValue(value2pos(value));
m_roller->setValue(value);
emit valueChanged(false);
}
@ -256,17 +294,14 @@ void DoubleValueField::onLineEditValueChanged() {
void DoubleValueField::onRollerValueChanged(bool isDragging) {
double value = m_roller->getValue();
int dicimal = m_lineEdit->getDecimals();
double sliderValue = value * pow(10., dicimal);
if (sliderValue == m_lineEdit->getValue()) {
assert(m_slider->value() == value || !m_slider->isVisible());
if (value == m_lineEdit->getValue()) {
assert(pos2value(m_slider->value()) == value || !m_slider->isVisible());
// Se isDragging e' falso e' giusto che venga emessa la notifica di
// cambiamento.
if (!isDragging) emit valueChanged(isDragging);
return;
}
m_slider->setValue(sliderValue);
m_slider->setValue(value2pos(value));
m_lineEdit->setValue(value);
// Faccio in modo che il cursore sia sulla prima cifra, cosi' se la stringa

View file

@ -68,7 +68,7 @@ DoubleValuePairField::DoubleValuePairField(QWidget *parent,
//---- signal-slot connections
bool ret = connect(m_leftLineEdit, SIGNAL(editingFinished()),
SLOT(onLeftEditingFinished()));
ret = ret && connect(m_rightLineEdit, SIGNAL(editingFinished()),
ret = ret && connect(m_rightLineEdit, SIGNAL(editingFinished()),
SLOT(onRightEditingFinished()));
assert(ret);
}
@ -76,16 +76,45 @@ DoubleValuePairField::DoubleValuePairField(QWidget *parent,
//-----------------------------------------------------------------------------
double DoubleValuePairField::pos2value(int x) const {
int xMin = m_leftMargin, xMax = width() - m_rightMargin;
return m_minValue + (m_maxValue - m_minValue) * (x - xMin) / (xMax - xMin);
int xMin = m_leftMargin, xMax = width() - m_rightMargin - 1;
if (m_isLinear)
return m_minValue + (m_maxValue - m_minValue) * (x - xMin) / (xMax - xMin);
// nonlinear slider case
double posRatio = (double)(x - xMin) / (double)(xMax - xMin);
double t;
if (posRatio <= 0.5)
t = 0.04 * posRatio;
else if (posRatio <= 0.75)
t = -0.02 + 0.08 * posRatio;
else if (posRatio <= 0.9)
t = -0.26 + 0.4 * posRatio;
else
t = -8.0 + 9.0 * posRatio;
return m_minValue + (m_maxValue - m_minValue) * t;
}
//-----------------------------------------------------------------------------
int DoubleValuePairField::value2pos(double v) const {
int xMin = m_leftMargin, xMax = width() - m_rightMargin;
return xMin +
(int)(((xMax - xMin) * (v - m_minValue)) / (m_maxValue - m_minValue));
int xMin = m_leftMargin, xMax = width() - m_rightMargin - 1;
if (m_isLinear)
return xMin + (int)(((xMax - xMin) * (v - m_minValue)) /
(m_maxValue - m_minValue));
// nonlinear slider case
double valueRatio =
(v - (double)m_minValue) / (double)(m_maxValue - m_minValue);
double t;
if (valueRatio <= 0.02)
t = valueRatio / 0.04;
else if (valueRatio <= 0.04)
t = (valueRatio + 0.02) / 0.08;
else if (valueRatio <= 0.1)
t = (valueRatio + 0.26) / 0.4;
else
t = (valueRatio + 8.0) / 9.0;
return xMin + (int)(t * (double)(xMax - xMin));
}
//-----------------------------------------------------------------------------
@ -266,7 +295,7 @@ void DoubleValuePairField::mousePressEvent(QMouseEvent *event) {
void DoubleValuePairField::mouseMoveEvent(QMouseEvent *event) {
if (event->buttons()) {
std::pair<double, double> oldValues = m_values;
int x = event->pos().x() + m_grabOffset;
int x = event->pos().x() + m_grabOffset;
setValue(pos2value(x));
if (oldValues != m_values) {
emit valuesChanged(true);
@ -291,7 +320,7 @@ void DoubleValuePairField::onLeftEditingFinished() {
if (!m_isMaxRangeLimited && value < m_minValue)
value = m_minValue;
else if (m_isMaxRangeLimited)
value = tcrop(value, m_minValue, m_maxValue);
value = tcrop(value, m_minValue, m_maxValue);
m_values.first = value;
if (m_values.first > m_values.second) {
m_values.second = m_values.first;
@ -307,7 +336,7 @@ void DoubleValuePairField::onRightEditingFinished() {
double value = m_rightLineEdit->getValue();
if (value == m_values.second) return;
if (m_isMaxRangeLimited) value = tcrop(value, m_minValue, m_maxValue);
m_values.second = value;
m_values.second = value;
if (m_values.second < m_values.first) {
m_values.first = m_values.second;
m_leftLineEdit->setValue(m_values.first);

View file

@ -11,6 +11,10 @@
#include <QFocusEvent>
#include <QPainter>
namespace {
const int NonLinearSliderPrecision = 2;
}
using namespace DVGui;
//=============================================================================
@ -250,7 +254,8 @@ IntField::IntField(QWidget *parent, bool isMaxRangeLimited, bool isRollerHide)
, m_lineEdit(0)
, m_slider(0)
, m_roller(0)
, m_isMaxRangeLimited(isMaxRangeLimited) {
, m_isMaxRangeLimited(isMaxRangeLimited)
, m_isLinearSlider(true) {
setObjectName("IntField");
QHBoxLayout *layout = new QHBoxLayout(this);
layout->setMargin(0);
@ -279,7 +284,7 @@ IntField::IntField(QWidget *parent, bool isMaxRangeLimited, bool isRollerHide)
m_slider = new QSlider(Qt::Horizontal, this);
ret = ret && connect(m_slider, SIGNAL(valueChanged(int)), this,
SLOT(onSliderChanged(int)));
ret = ret && connect(m_slider, SIGNAL(sliderReleased()), this,
ret = ret && connect(m_slider, SIGNAL(sliderReleased()), this,
SLOT(onSliderReleased()));
ret = ret && connect(m_lineEdit, SIGNAL(editingFinished()), this,
@ -309,7 +314,11 @@ void IntField::setRange(int minValue, int maxValue) {
m_lineEdit->setRange(minValue, m_isMaxRangeLimited
? maxValue
: (std::numeric_limits<int>::max)());
m_slider->setRange(minValue, maxValue);
if (m_isLinearSlider)
m_slider->setRange(minValue, maxValue);
else
m_slider->setRange(minValue * pow(10., NonLinearSliderPrecision),
maxValue * pow(10., NonLinearSliderPrecision));
m_roller->setRange(minValue, maxValue);
}
@ -318,7 +327,7 @@ void IntField::setRange(int minValue, int maxValue) {
void IntField::setValue(int value) {
if (m_lineEdit->getValue() == value) return;
m_lineEdit->setValue(value);
m_slider->setSliderPosition(value);
m_slider->setSliderPosition(value2pos(value));
m_roller->setValue((double)value);
}
@ -369,7 +378,50 @@ void IntField::setLineEditBackgroundColor(QColor color) {
//-----------------------------------------------------------------------------
void IntField::onSliderChanged(int value) {
int IntField::pos2value(int x) const {
if (m_isLinearSlider) return x;
// nonlinear slider case
double rangeSize = (double)(m_slider->maximum() - m_slider->minimum());
double posRatio = (double)(x - m_slider->minimum()) / rangeSize;
double t;
if (posRatio <= 0.5)
t = 0.04 * posRatio;
else if (posRatio <= 0.75)
t = -0.02 + 0.08 * posRatio;
else if (posRatio <= 0.9)
t = -0.26 + 0.4 * posRatio;
else
t = -8.0 + 9.0 * posRatio;
double sliderVal = (double)m_slider->minimum() + rangeSize * t;
return (int)round(sliderVal * pow(0.1, NonLinearSliderPrecision));
}
//-----------------------------------------------------------------------------
int IntField::value2pos(int v) const {
if (m_isLinearSlider) return v;
// nonlinear slider case
double sliderVal = (double)v * pow(10., NonLinearSliderPrecision);
double rangeSize = (double)(m_slider->maximum() - m_slider->minimum());
double valueRatio = (double)(sliderVal - m_slider->minimum()) / rangeSize;
double t;
if (valueRatio <= 0.02)
t = valueRatio / 0.04;
else if (valueRatio <= 0.04)
t = (valueRatio + 0.02) / 0.08;
else if (valueRatio <= 0.1)
t = (valueRatio + 0.26) / 0.4;
else
t = (valueRatio + 8.0) / 9.0;
return m_slider->minimum() + (int)(t * rangeSize);
}
//-----------------------------------------------------------------------------
void IntField::onSliderChanged(int sliderPos) {
int value = pos2value(sliderPos);
// Controllo necessario per evitare che il segnale di cambiamento venga emesso
// piu' volte.
if (m_lineEdit->getValue() == value ||
@ -390,10 +442,10 @@ void IntField::onEditingFinished() {
double value = m_lineEdit->getValue();
// Controllo necessario per evitare che il segnale di cambiamento venga emesso
// piu' volte.
if ((m_slider->value() == value && m_slider->isVisible()) ||
if ((pos2value(m_slider->value()) == value && m_slider->isVisible()) ||
(int)m_roller->getValue() == value && m_roller->isVisible())
return;
m_slider->setValue(value);
m_slider->setValue(value2pos(value));
m_roller->setValue((double)value);
emit valueChanged(false);
}
@ -403,13 +455,13 @@ void IntField::onEditingFinished() {
void IntField::onRollerValueChanged(bool isDragging) {
int value = m_roller->getValue();
if (value == m_lineEdit->getValue()) {
assert(m_slider->value() == value || !m_slider->isVisible());
assert(pos2value(m_slider->value()) == value || !m_slider->isVisible());
// Se isDragging e' falso e' giusto che venga emessa la notifica di
// cambiamento.
if (!isDragging) emit valueChanged(isDragging);
return;
}
m_slider->setValue(value);
m_slider->setValue(value2pos(value));
m_lineEdit->setValue(value);
// Faccio in modo che il cursore sia sulla prima cifra, cosi' se la stringa

View file

@ -33,7 +33,8 @@ IntPairField::IntPairField(QWidget *parent, bool isMaxRangeLimited)
, m_grabIndex(-1)
, m_leftMargin(52)
, m_rightMargin(52)
, m_isMaxRangeLimited(isMaxRangeLimited) {
, m_isMaxRangeLimited(isMaxRangeLimited)
, m_isLinear(true) {
setObjectName("IntPairField");
setFixedHeight(WidgetHeight);
@ -63,7 +64,7 @@ IntPairField::IntPairField(QWidget *parent, bool isMaxRangeLimited)
//---signal-slot connections
bool ret = connect(m_leftLineEdit, SIGNAL(editingFinished()),
SLOT(onLeftEditingFinished()));
ret = ret && connect(m_rightLineEdit, SIGNAL(editingFinished()),
ret = ret && connect(m_rightLineEdit, SIGNAL(editingFinished()),
SLOT(onRightEditingFinished()));
assert(ret);
@ -71,17 +72,46 @@ IntPairField::IntPairField(QWidget *parent, bool isMaxRangeLimited)
//-----------------------------------------------------------------------------
double IntPairField::pos2value(int x) const {
int IntPairField::pos2value(int x) const {
int xMin = m_leftMargin, xMax = width() - m_rightMargin - 1;
return m_minValue + (m_maxValue - m_minValue) * (x - xMin) / (xMax - xMin);
if (m_isLinear)
return m_minValue + (m_maxValue - m_minValue) * (x - xMin) / (xMax - xMin);
// nonlinear slider case
double posRatio = (double)(x - xMin) / (double)(xMax - xMin);
double t;
if (posRatio <= 0.5)
t = 0.04 * posRatio;
else if (posRatio <= 0.75)
t = -0.02 + 0.08 * posRatio;
else if (posRatio <= 0.9)
t = -0.26 + 0.4 * posRatio;
else
t = -8.0 + 9.0 * posRatio;
return m_minValue + (int)((double)(m_maxValue - m_minValue) * t);
}
//-----------------------------------------------------------------------------
int IntPairField::value2pos(double v) const {
int IntPairField::value2pos(int v) const {
int xMin = m_leftMargin, xMax = width() - m_rightMargin - 1;
return xMin +
(int)(((xMax - xMin) * (v - m_minValue)) / (m_maxValue - m_minValue));
if (m_isLinear)
return xMin +
((xMax - xMin) * (v - m_minValue)) / (m_maxValue - m_minValue);
// nonlinear slider case
double valueRatio =
(double)(v - m_minValue) / (double)(m_maxValue - m_minValue);
double t;
if (valueRatio <= 0.02)
t = valueRatio / 0.04;
else if (valueRatio <= 0.04)
t = (valueRatio + 0.02) / 0.08;
else if (valueRatio <= 0.1)
t = (valueRatio + 0.26) / 0.4;
else
t = (valueRatio + 8.0) / 9.0;
return xMin + (int)(t * (double)(xMax - xMin));
}
//-----------------------------------------------------------------------------
@ -258,7 +288,7 @@ void IntPairField::mousePressEvent(QMouseEvent *event) {
void IntPairField::mouseMoveEvent(QMouseEvent *event) {
if (event->buttons()) {
std::pair<int, int> oldValues = m_values;
int x = event->pos().x() + m_grabOffset;
int x = event->pos().x() + m_grabOffset;
setValue(pos2value(x));
if (oldValues == m_values) return;
@ -283,7 +313,7 @@ void IntPairField::onLeftEditingFinished() {
if (!m_isMaxRangeLimited && value < m_minValue)
value = m_minValue;
else if (m_isMaxRangeLimited)
value = tcrop(value, m_minValue, m_maxValue);
value = tcrop(value, m_minValue, m_maxValue);
m_values.first = value;
if (m_values.first > m_values.second) {
m_values.second = m_values.first;
@ -299,7 +329,7 @@ void IntPairField::onRightEditingFinished() {
int value = m_rightLineEdit->getValue();
if (value == m_values.second) return;
if (m_isMaxRangeLimited) value = tcrop(value, m_minValue, m_maxValue);
m_values.second = value;
m_values.second = value;
if (m_values.second < m_values.first) {
m_values.first = m_values.second;
m_leftLineEdit->setValue(m_values.first);