Resolve conflicts with master

This commit is contained in:
manongjohn 2019-10-14 15:42:58 -04:00
commit bd4e8aa598
47 changed files with 1259 additions and 336 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -703,11 +703,18 @@ void TFx::setNewIdentifier() { m_imp->m_id = ++m_imp->m_nextId; }
void TFx::loadData(TIStream &is) {
std::string tagName;
VersionNumber tnzVersion = is.getVersion();
// Prevent to load "params" tag under "super" tag on saving macro fx.
// For now "params" tag is no longer saved under "super" tag.
// This is for keeping compatibility with older versions.
bool isInSuperTag = (is.getCurrentTagName() == "super");
QList<int> groupIds;
QList<std::wstring> groupNames;
while (is.openChild(tagName)) {
if (tagName == "params") {
if (isInSuperTag) { // skip loading "params" tag under "super" tag
is.skipCurrentTag();
continue;
}
while (!is.eos()) {
std::string paramName;
while (is.openChild(paramName)) {
@ -829,29 +836,36 @@ void TFx::loadData(TIStream &is) {
//--------------------------------------------------
void TFx::saveData(TOStream &os) {
// Prevent to save "params" tag under "super" tag on saving macro fx.
// Parameters for macro fx are saved in "nodes" tag and corrected upon
// loading. Therefore, "params" tag is not needed and even causes crash if
// macrofx contains CurveFx (See the issue #2424)
bool isInSuperTag = (os.getCurrentTagName() == "super");
TFx *linkedSetRoot = this;
if (m_imp->m_next != m_imp) {
TFxImp *imp = m_imp->m_next;
int guard = 0;
while (guard++ < 1000 && imp != m_imp) {
if (imp->m_fx < linkedSetRoot) linkedSetRoot = imp->m_fx;
imp = imp->m_next;
imp = imp->m_next;
}
assert(imp == m_imp);
assert(linkedSetRoot);
}
if (linkedSetRoot == this) {
os.openChild("params");
for (int i = 0; i < getParams()->getParamCount(); i++) {
std::string paramName = getParams()->getParamName(i);
const TParamVar *paramVar = getParams()->getParamVar(i);
// skip saving for the obsolete parameters
if (paramVar->isObsolete()) continue;
os.openChild(paramName);
paramVar->getParam()->saveData(os);
if (!isInSuperTag) { // skip saving "params" tag under "super" tag
os.openChild("params");
for (int i = 0; i < getParams()->getParamCount(); i++) {
std::string paramName = getParams()->getParamName(i);
const TParamVar *paramVar = getParams()->getParamVar(i);
// skip saving for the obsolete parameters
if (paramVar->isObsolete()) continue;
os.openChild(paramName);
paramVar->getParam()->saveData(os);
os.closeChild();
}
os.closeChild();
}
os.closeChild();
} else {
os.openChild("paramsLinkedTo");
os << linkedSetRoot;

View file

@ -470,7 +470,7 @@ TOStream &TOStream::operator<<(const TPixel64 &v) {
void TOStream::cr() {
*(m_imp->m_os) << endl;
for (int i = 0; i < m_imp->m_tab; i++) *(m_imp->m_os) << " ";
for (int i = 0; i < m_imp->m_tab; i++) *(m_imp->m_os) << " ";
m_imp->m_justStarted = false;
}
@ -587,6 +587,10 @@ bool TOStream::checkStatus() const {
return m_imp->m_os->rdstate() == ios_base::goodbit;
}
std::string TOStream::getCurrentTagName() {
return (m_imp->m_tagStack.empty()) ? "" : m_imp->m_tagStack.back();
}
//===============================================================
/*!
This class contains TIStream's attributes.
@ -1118,8 +1122,8 @@ TIStream &TIStream::operator>>(TPersist *&v) {
m_imp->m_currentTag = StreamTag();
string tagName = tag.m_name;
std::map<std::string, string>::iterator it;
int id = -1;
it = tag.m_attributes.find("id");
int id = -1;
it = tag.m_attributes.find("id");
if (it != tag.m_attributes.end()) id = atoi(it->second.c_str());
// cout << "tagname = " << tagName << " id = " << id << endl;
@ -1277,3 +1281,7 @@ void TIStream::setVersion(const VersionNumber &version) {
//---------------------------------------------------------------
void TIStream::skipCurrentTag() { m_imp->skipCurrentTag(); }
//---------------------------------------------------------------
std::string TIStream::getCurrentTagName() { return m_imp->m_tagStack.back(); }

View file

@ -32,6 +32,7 @@ enum {
MagnetCursor,
PanCursor,
PickerCursor,
PointingHandCursor,
PumpCursor,
RotCursor,
RotTopLeft,

View file

@ -391,13 +391,13 @@ public:
cells will be inserted by shifting the other down.
*/
void stepCells(int r0, int c0, int r1, int c1, int type);
/*! For each sequenze of frame with same number, contained in rect delimited
/*! For each sequence of frame with same number, contained in rect delimited
by first row \b \e r0, last row \b \e r1 and
first column \b \e c0, a frame with same number is inserted.
*/
void increaseStepCells(int r0, int c0, int &r1, int c1);
/*!
For each sequenze of frame with same number, contained in rect delimited by
For each sequence of frame with same number, contained in rect delimited by
first row \b \e r0, last row \b \e r1 and
first column \b \e c0, a frame with same number is removed.
*/
@ -405,7 +405,7 @@ first row \b \e r0, last row \b \e r1 and
/*!
The cells, contained in rect delimited by first row \b \e r0, last row \b \e r1
and
first column \b \e c0, are resetted in order to have no sequential
first column \b \e c0, are reset in order to have no sequential
frame duplication.
*/
void resetStepCells(int r0, int c0, int r1, int c1);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -86,7 +86,7 @@ public:
/*!Returns the number of milliseconds that have elapsed in all the
start()-stop() intervals since
the stopWatch was resetted up to the getTotalTime() call. The method can be
the stopWatch was reset up to the getTotalTime() call. The method can be
called during a start()-stop() interval */
TUINT32 getTotalTime();

View file

@ -155,6 +155,8 @@ reimplementation of the TPersist::loadData() function.
void skipCurrentTag(); //!< Silently ignores the content of currently opened
//! tag up to its end.
std::string getCurrentTagName();
private:
// Not copyable
TIStream(const TIStream &); //!< Not implemented
@ -266,6 +268,8 @@ checking the status.
*/
bool checkStatus() const; //!< \b Flushes the stream and checks its validity.
std::string getCurrentTagName();
private:
// Not copyable
TOStream(const TOStream &) = delete; //!< Not implemented

View file

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

View file

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

View file

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

View file

@ -0,0 +1,31 @@
#pragma once
#ifndef IWA_CORRIDORGRADIENTFX_H
#define IWA_CORRIDORGRADIENTFX_H
#include "tfxparam.h"
#include "stdfx.h"
#include "tparamset.h"
class Iwa_CorridorGradientFx final : public TStandardZeraryFx {
FX_PLUGIN_DECLARATION(Iwa_CorridorGradientFx)
TIntEnumParamP m_shape;
TIntEnumParamP m_curveType;
TPointParamP m_points[2][4]; // [in/out][Qt::Corner]
TPixelParamP m_innerColor;
TPixelParamP m_outerColor;
public:
Iwa_CorridorGradientFx();
bool canHandle(const TRenderSettings &info, double frame) override {
return true;
}
bool doGetBBox(double frame, TRectD &bBox,
const TRenderSettings &ri) override;
void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override;
void getParamUIs(TParamUIConcept *&concepts, int &length) override;
};
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

View file

@ -54,6 +54,8 @@ const struct {
{ToolCursor::PickerCursorAreaBase, "picker_style", 7, 22, true},
{ToolCursor::PickerCursor, "picker_style", 7, 22, true},
{ToolCursor::PointingHandCursor, "pointing_hand", 13, 4, true},
{ToolCursor::PumpCursor, "pump", 16, 23, false},
{ToolCursor::RotCursor, "rot", 15, 15, false},
{ToolCursor::RotTopLeft, "rot_top_left", 15, 15, false},

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1023,7 +1023,8 @@ void SelectionTool::updateAction(TPointD pos, const TMouseEvent &e) {
}
if (!isLevelType() && !isSelectedFramesType() &&
tdistance2(getCenter(), pos) < maxDist2) {
m_what = MOVE_CENTER;
m_what = MOVE_CENTER;
m_cursorId = ToolCursor::PointingHandCursor;
return;
}
TPointD hpos = bbox.getP10() - TPointD(14 * pixelSize, 15 * pixelSize);
@ -1214,7 +1215,8 @@ void SelectionTool::drawRectSelection(const TImage *image) {
void SelectionTool::drawCommandHandle(const TImage *image) {
const TVectorImage *vi = dynamic_cast<const TVectorImage *>(image);
TPixel32 frameColor(127, 127, 127);
TPixel32 frameColor(210, 210, 210);
TPixel32 frameColor2(0, 0, 0);
FourPoints rect = getBBox();
drawFourPoints(rect, frameColor, 0xffff, true);
@ -1224,13 +1226,37 @@ void SelectionTool::drawCommandHandle(const TImage *image) {
if (m_dragTool) m_dragTool->draw();
double pixelSize = getPixelSize();
if (!isLevelType() && !isSelectedFramesType())
tglDrawCircle(getCenter(), pixelSize * 4);
if (!isLevelType() && !isSelectedFramesType()) {
TPointD c = getCenter() + TPointD(-pixelSize, +pixelSize);
drawSquare(rect.getP00(), pixelSize * 4, frameColor);
drawSquare(rect.getP01(), pixelSize * 4, frameColor);
drawSquare(rect.getP10(), pixelSize * 4, frameColor);
drawSquare(rect.getP11(), pixelSize * 4, frameColor);
tglColor(frameColor);
tglDrawCircle(c, pixelSize * 5);
tglDrawSegment(c - TPointD(pixelSize * 15, 0),
c + TPointD(pixelSize * 15, 0));
tglDrawSegment(c - TPointD(0, pixelSize * 15),
c + TPointD(0, pixelSize * 15));
tglColor(frameColor2);
tglDrawCircle(getCenter(), pixelSize * 5);
tglDrawSegment(getCenter() - TPointD(pixelSize * 15, 0),
getCenter() + TPointD(pixelSize * 15, 0));
tglDrawSegment(getCenter() - TPointD(0, pixelSize * 15),
getCenter() + TPointD(0, pixelSize * 15));
}
TPointD bl(rect.getP00().x - pixelSize, rect.getP00().y + pixelSize);
TPointD tl(rect.getP01().x - pixelSize, rect.getP01().y + pixelSize);
TPointD br(rect.getP10().x - pixelSize, rect.getP10().y + pixelSize);
TPointD tr(rect.getP11().x - pixelSize, rect.getP11().y + pixelSize);
drawSquare(bl, pixelSize * 4, frameColor);
drawSquare(tl, pixelSize * 4, frameColor);
drawSquare(br, pixelSize * 4, frameColor);
drawSquare(tr, pixelSize * 4, frameColor);
drawSquare(rect.getP00(), pixelSize * 4, frameColor2);
drawSquare(rect.getP01(), pixelSize * 4, frameColor2);
drawSquare(rect.getP10(), pixelSize * 4, frameColor2);
drawSquare(rect.getP11(), pixelSize * 4, frameColor2);
if (vi && !m_deformValues.m_isSelectionModified) {
TPointD thickCommandPos =
@ -1238,10 +1264,15 @@ void SelectionTool::drawCommandHandle(const TImage *image) {
drawRectWhitArrow(thickCommandPos, pixelSize);
}
drawSquare(0.5 * (rect.getP10() + rect.getP11()), pixelSize * 4, frameColor);
drawSquare(0.5 * (rect.getP01() + rect.getP11()), pixelSize * 4, frameColor);
drawSquare(0.5 * (rect.getP10() + rect.getP00()), pixelSize * 4, frameColor);
drawSquare(0.5 * (rect.getP01() + rect.getP00()), pixelSize * 4, frameColor);
drawSquare(0.5 * (br + tr), pixelSize * 4, frameColor);
drawSquare(0.5 * (tl + tr), pixelSize * 4, frameColor);
drawSquare(0.5 * (br + bl), pixelSize * 4, frameColor);
drawSquare(0.5 * (tl + bl), pixelSize * 4, frameColor);
drawSquare(0.5 * (rect.getP10() + rect.getP11()), pixelSize * 4, frameColor2);
drawSquare(0.5 * (rect.getP01() + rect.getP11()), pixelSize * 4, frameColor2);
drawSquare(0.5 * (rect.getP10() + rect.getP00()), pixelSize * 4, frameColor2);
drawSquare(0.5 * (rect.getP01() + rect.getP00()), pixelSize * 4, frameColor2);
}
//-----------------------------------------------------------------------------

View file

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

View file

@ -47,6 +47,7 @@
<file>Resources/picker_style_organize.png</file>
<file>Resources/picker_rgb.png</file>
<file>Resources/picker_rgb_white.png</file>
<file>Resources/pointing_hand.png</file>
<file>Resources/karasu.png</file>
<file>Resources/ruler_modify.png</file>
<file>Resources/ruler_new.png</file>

View file

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

View file

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

View file

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

View file

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

View file

@ -82,6 +82,10 @@
#include <QLibraryInfo>
#include <QHash>
#ifdef _WIN32
#include <QtPlatformHeaders/QWindowsWindowFunctions>
#endif
using namespace DVGui;
#if defined LINETEST
const char *applicationName = "Toonz LineTest";
@ -229,7 +233,7 @@ project->setUseScenePath(TProject::Extras, false);
// Imposto la rootDir per ImageCache
/*-- TOONZCACHEROOTの設定 --*/
TFilePath cacheDir = ToonzFolder::getCacheRootFolder();
TFilePath cacheDir = ToonzFolder::getCacheRootFolder();
if (cacheDir.isEmpty()) cacheDir = TEnv::getStuffDir() + "cache";
TImageCache::instance()->setRootDir(cacheDir);
}
@ -315,10 +319,10 @@ int main(int argc, char *argv[]) {
QApplication a(argc, argv);
#ifdef MACOSX
// This workaround is to avoid missing left button problem on Qt5.6.0.
// To invalidate m_rightButtonClicked in Qt/qnsview.mm, sending
// NSLeftButtonDown event before NSLeftMouseDragged event propagated to
// QApplication. See more details in ../mousedragfilter/mousedragfilter.mm.
// This workaround is to avoid missing left button problem on Qt5.6.0.
// To invalidate m_rightButtonClicked in Qt/qnsview.mm, sending
// NSLeftButtonDown event before NSLeftMouseDragged event propagated to
// QApplication. See more details in ../mousedragfilter/mousedragfilter.mm.
#include "mousedragfilter.h"
@ -616,6 +620,11 @@ int main(int argc, char *argv[]) {
/*-- Layoutファイル名をMainWindowのctorに渡す --*/
MainWindow w(argumentLayoutFileName);
#ifdef _WIN32
// http://doc.qt.io/qt-5/windows-issues.html#fullscreen-opengl-based-windows
QWindowsWindowFunctions::setHasBorderInFullScreen(w.windowHandle(), true);
#endif
splash.showMessage(offsetStr + "Loading style sheet ...", Qt::AlignCenter,
Qt::white);
a.processEvents();

View file

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

View file

@ -425,7 +425,7 @@ bool SequenceConverter::parametrize(unsigned int a, unsigned int b) {
//==========================================================================
//------------------------
// CP construcion
// CP construction
//------------------------
// NOTE: Check my thesis for variable meanings (int_ stands for 'integral').

View file

@ -194,7 +194,7 @@ public:
//=========================================================================
//! Birghtness/Contrast color transform data
//! Brightness/Contrast color transform data
#define MAX_N_PENCILS 8
@ -207,7 +207,7 @@ TPixelRGBM32 Paper = TPixel32::White;
//=========================================================================
//! Birghtness/Contrast color transform structure
//! Brightness/Contrast color transform structure
class TransfFunction {
USHORT TransfFun[(MAX_N_PENCILS + 1) << 8];

View file

@ -824,7 +824,7 @@ void Region::removeItem(DockWidget *item) {
//! Undocks \b item and updates geometry.
//!\b NOTE: Window flags are resetted to floating appearance (thus hiding the
//!\b NOTE: Window flags are reset to floating appearance (thus hiding the
//! widget). Since the geometry
//! reference changes a geometry() update may be needed - so item's show() is
//! not forced here. You should

View file

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

View file

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

View file

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

View file

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