Merge branch 'master' of https://github.com/opentoonz/opentoonz into update_korean_translations
This commit is contained in:
commit
16e741e04e
33 changed files with 1150 additions and 297 deletions
|
@ -19,4 +19,4 @@ matrix:
|
|||
- os: linux
|
||||
compiler: clang
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
osx_image: xcode10.1
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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>
|
||||
|
|
18
stuff/profiles/layouts/fxs/STD_iwa_CorridorGradientFx.xml
Normal file
18
stuff/profiles/layouts/fxs/STD_iwa_CorridorGradientFx.xml
Normal 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>
|
|
@ -44,6 +44,7 @@
|
|||
STD_radialGradientFx
|
||||
STD_spiralFx
|
||||
STD_squareGradientFx
|
||||
STD_iwa_CorridorGradientFx
|
||||
</Gradient>
|
||||
<Image_Adjust>
|
||||
STD_iwa_AdjustExposureFx
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
|
|
378
toonz/sources/stdfx/iwa_corridorgradientfx.cpp
Normal file
378
toonz/sources/stdfx/iwa_corridorgradientfx.cpp
Normal 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 ¶m,
|
||||
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");
|
31
toonz/sources/stdfx/iwa_corridorgradientfx.h
Normal file
31
toonz/sources/stdfx/iwa_corridorgradientfx.h
Normal 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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
||||
//==========================================================================================================
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue