Nonlinear Slider for the Brush Size Options (#2824)
* nonlinear slider for tool size * nonlinear slider for finger magnet and pinch tools
This commit is contained in:
parent
6817df33ac
commit
76d093f2f4
20 changed files with 386 additions and 184 deletions
|
@ -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() {}
|
||||
|
|
|
@ -102,6 +102,8 @@ protected:
|
|||
|
||||
bool m_isMaxRangeLimited;
|
||||
|
||||
bool m_isLinear;
|
||||
|
||||
public:
|
||||
DoubleValuePairField(QWidget *parent, bool isMaxRangeLimited,
|
||||
DoubleValueLineEdit *leftLineEdit,
|
||||
|
@ -174,6 +176,7 @@ protected:
|
|||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
|
||||
void setLinearSlider(bool linear) { m_isLinear = linear; }
|
||||
protected slots:
|
||||
/*! Set current left value to value in left text field; if necessary, if left
|
||||
value is greater than right, change also current right value.
|
||||
|
|
|
@ -167,6 +167,7 @@ class DVAPI IntField : public QWidget {
|
|||
IntLineEdit *m_lineEdit;
|
||||
QSlider *m_slider;
|
||||
bool m_isMaxRangeLimited;
|
||||
bool m_isLinearSlider;
|
||||
|
||||
public:
|
||||
IntField(QWidget *parent = 0, bool isMaxRangeLimited = true,
|
||||
|
@ -205,6 +206,13 @@ public:
|
|||
|
||||
void setLineEditBackgroundColor(QColor color);
|
||||
|
||||
protected:
|
||||
void setLinearSlider(bool linear) { m_isLinearSlider = linear; }
|
||||
|
||||
private:
|
||||
int pos2value(int x) const;
|
||||
int value2pos(int v) const;
|
||||
|
||||
protected slots:
|
||||
/*! Set to value the text field. If text field value is different from \b
|
||||
value
|
||||
|
|
|
@ -112,6 +112,8 @@ class DVAPI IntPairField : public QWidget {
|
|||
|
||||
bool m_isMaxRangeLimited;
|
||||
|
||||
bool m_isLinear;
|
||||
|
||||
public:
|
||||
IntPairField(QWidget *parent = 0, bool isMaxRangeLimited = true);
|
||||
~IntPairField() {}
|
||||
|
@ -166,9 +168,9 @@ public:
|
|||
|
||||
protected:
|
||||
/*! Return value corresponding \b x position. */
|
||||
double pos2value(int x) const;
|
||||
int pos2value(int x) const;
|
||||
/*! Return x position corresponding \b value. */
|
||||
int value2pos(double v) const;
|
||||
int value2pos(int v) const;
|
||||
|
||||
/*! Set current value to \b value.
|
||||
Set left or right value, or both, to value depending on
|
||||
|
@ -182,6 +184,7 @@ protected:
|
|||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
|
||||
void setLinearSlider(bool linear) { m_isLinear = linear; }
|
||||
protected slots:
|
||||
/*! Set current left value to value in left text field; if necessary, if left
|
||||
value is greater than right, change also current right value.
|
||||
|
|
|
@ -112,7 +112,8 @@ public:
|
|||
: TProperty(name)
|
||||
, m_range(minValue, maxValue)
|
||||
, m_value(minValue)
|
||||
, m_isMaxRangeLimited(isMaxRangeLimited) {
|
||||
, m_isMaxRangeLimited(isMaxRangeLimited)
|
||||
, m_isLinearSlider(true) {
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
|
@ -138,10 +139,14 @@ public:
|
|||
|
||||
bool isMaxRangeLimited() const { return m_isMaxRangeLimited; }
|
||||
|
||||
void setNonLinearSlider() { m_isLinearSlider = false; }
|
||||
bool isLinearSlider() { return m_isLinearSlider; }
|
||||
|
||||
private:
|
||||
Range m_range;
|
||||
T m_value;
|
||||
bool m_isMaxRangeLimited;
|
||||
bool m_isLinearSlider;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
@ -160,7 +165,8 @@ public:
|
|||
double v0, double v1, bool isMaxRangeLimited = true)
|
||||
: TProperty(name)
|
||||
, m_range(Range(minValue, maxValue))
|
||||
, m_isMaxRangeLimited(isMaxRangeLimited) {
|
||||
, m_isMaxRangeLimited(isMaxRangeLimited)
|
||||
, m_isLinearSlider(true) {
|
||||
setValue(Value(v0, v1));
|
||||
}
|
||||
|
||||
|
@ -184,10 +190,14 @@ public:
|
|||
}
|
||||
void accept(Visitor &v) override { v.visit(this); };
|
||||
|
||||
void setNonLinearSlider() { m_isLinearSlider = false; }
|
||||
bool isLinearSlider() { return m_isLinearSlider; }
|
||||
|
||||
private:
|
||||
Range m_range;
|
||||
Value m_value;
|
||||
bool m_isMaxRangeLimited;
|
||||
bool m_isLinearSlider;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
@ -201,7 +211,8 @@ public:
|
|||
bool isMaxRangeLimited = true)
|
||||
: TProperty(name)
|
||||
, m_range(minValue, maxValue)
|
||||
, m_isMaxRangeLimited(isMaxRangeLimited) {
|
||||
, m_isMaxRangeLimited(isMaxRangeLimited)
|
||||
, m_isLinearSlider(true) {
|
||||
setValue(Value(v0, v1));
|
||||
}
|
||||
|
||||
|
@ -225,10 +236,14 @@ public:
|
|||
}
|
||||
void accept(Visitor &v) override { v.visit(this); };
|
||||
|
||||
void setNonLinearSlider() { m_isLinearSlider = false; }
|
||||
bool isLinearSlider() { return m_isLinearSlider; }
|
||||
|
||||
private:
|
||||
Range m_range;
|
||||
Value m_value;
|
||||
bool m_isMaxRangeLimited;
|
||||
bool m_isLinearSlider;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -576,8 +578,7 @@ void FingerTool::pick(const TPointD &pos) {
|
|||
/*---
|
||||
* pickLineモードのとき、PurePaintの部分をクリックしてもカレントStyleを変えない
|
||||
* ---*/
|
||||
if (ti &&
|
||||
picker.pickTone(TScale(1.0 / subsampling) * pos +
|
||||
if (ti && picker.pickTone(TScale(1.0 / subsampling) * pos +
|
||||
TPointD(-0.5, -0.5)) == 255)
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ public:
|
|||
|
||||
FullColorBrushTool::FullColorBrushTool(std::string name)
|
||||
: TTool(name)
|
||||
, m_thickness("Size", 1, 100, 1, 5, false)
|
||||
, m_thickness("Size", 1, 1000, 1, 5, false)
|
||||
, m_pressure("Pressure", true)
|
||||
, m_opacity("Opacity", 0, 100, 100, 100, true)
|
||||
, m_hardness("Hardness:", 0, 100, 100)
|
||||
|
@ -133,6 +133,8 @@ FullColorBrushTool::FullColorBrushTool(std::string name)
|
|||
, m_firstTime(true) {
|
||||
bind(TTool::RasterImage | TTool::EmptyTarget);
|
||||
|
||||
m_thickness.setNonLinearSlider();
|
||||
|
||||
m_prop.bind(m_thickness);
|
||||
m_prop.bind(m_hardness);
|
||||
m_prop.bind(m_opacity);
|
||||
|
@ -318,7 +320,13 @@ void FullColorBrushTool::leftButtonDown(const TPointD &pos,
|
|||
|
||||
TPointD rasCenter = ras->getCenterD();
|
||||
TPointD point(pos + rasCenter);
|
||||
double pressure = m_enabledPressure && e.isTablet() ? e.m_pressure : 0.5;
|
||||
|
||||
double pressure;
|
||||
if (getApplication()->getCurrentLevelStyle()->getTagId() ==
|
||||
4001) // mypaint brush case
|
||||
pressure = m_enabledPressure && e.isTablet() ? e.m_pressure : 0.5;
|
||||
else
|
||||
pressure = m_enabledPressure ? e.m_pressure : 1.0;
|
||||
|
||||
m_tileSet = new TTileSetFullColor(ras->getSize());
|
||||
m_tileSaver = new TTileSaverFullColor(ras, m_tileSet);
|
||||
|
@ -358,7 +366,12 @@ void FullColorBrushTool::leftButtonDrag(const TPointD &pos,
|
|||
TRasterP ras = ri->getRaster();
|
||||
TPointD rasCenter = ras->getCenterD();
|
||||
TPointD point(pos + rasCenter);
|
||||
double pressure = m_enabledPressure && e.isTablet() ? e.m_pressure : 0.5;
|
||||
double pressure;
|
||||
if (getApplication()->getCurrentLevelStyle()->getTagId() ==
|
||||
4001) // mypaint brush case
|
||||
pressure = m_enabledPressure && e.isTablet() ? e.m_pressure : 0.5;
|
||||
else
|
||||
pressure = m_enabledPressure ? e.m_pressure : 1.0;
|
||||
|
||||
m_strokeSegmentRect.empty();
|
||||
m_toonz_brush->strokeTo(point, pressure, restartBrushTimer());
|
||||
|
@ -389,7 +402,12 @@ void FullColorBrushTool::leftButtonUp(const TPointD &pos,
|
|||
TRasterP ras = ri->getRaster();
|
||||
TPointD rasCenter = ras->getCenterD();
|
||||
TPointD point(pos + rasCenter);
|
||||
double pressure = m_enabledPressure && e.isTablet() ? e.m_pressure : 0.5;
|
||||
double pressure;
|
||||
if (getApplication()->getCurrentLevelStyle()->getTagId() ==
|
||||
4001) // mypaint brush case
|
||||
pressure = m_enabledPressure && e.isTablet() ? e.m_pressure : 0.5;
|
||||
else
|
||||
pressure = m_enabledPressure ? e.m_pressure : 1.0;
|
||||
|
||||
m_strokeSegmentRect.empty();
|
||||
m_toonz_brush->strokeTo(point, pressure, restartBrushTimer());
|
||||
|
@ -747,13 +765,7 @@ void FullColorBrushTool::updateCurrentStyle() {
|
|||
m_minCursorThick = std::max(m_thickness.getValue().first, 1);
|
||||
m_maxCursorThick =
|
||||
std::max(m_thickness.getValue().second, m_minCursorThick);
|
||||
if (!m_enabledPressure) {
|
||||
double minRadiusLog = log(0.5 * m_minCursorThick);
|
||||
double maxRadiusLog = log(0.5 * m_maxCursorThick);
|
||||
double avgRadiusLog = 0.5 * (minRadiusLog + maxRadiusLog);
|
||||
double avgRadius = exp(avgRadiusLog);
|
||||
m_minCursorThick = m_maxCursorThick = (int)round(2.0 * avgRadius);
|
||||
}
|
||||
if (!m_enabledPressure) m_minCursorThick = m_maxCursorThick;
|
||||
}
|
||||
|
||||
// if this function is called from onEnter(), the clipping rect will not be
|
||||
|
|
|
@ -368,7 +368,7 @@ private:
|
|||
|
||||
FullColorEraserTool::FullColorEraserTool(std::string name)
|
||||
: TTool(name)
|
||||
, m_size("Size:", 1, 100, 5, false)
|
||||
, m_size("Size:", 1, 1000, 5, false)
|
||||
, m_opacity("Opacity:", 0, 100, 100)
|
||||
, m_hardness("Hardness:", 0, 100, 100)
|
||||
, m_eraseType("Type:")
|
||||
|
@ -385,6 +385,8 @@ FullColorEraserTool::FullColorEraserTool(std::string name)
|
|||
, m_isXsheetCell(false) {
|
||||
bind(TTool::RasterImage);
|
||||
|
||||
m_size.setNonLinearSlider();
|
||||
|
||||
m_prop.bind(m_size);
|
||||
m_prop.bind(m_hardness);
|
||||
m_prop.bind(m_opacity);
|
||||
|
|
|
@ -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>;
|
||||
|
@ -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) {
|
||||
double pointSize = m_toolSize.getValue();
|
||||
|
||||
tglColor(TPixel32::Red);
|
||||
tglDrawCircle(m_pointAtMove, m_pointSize);
|
||||
}
|
||||
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
|
||||
{
|
||||
bool onPropertyChanged(std::string propertyName) override {
|
||||
if (propertyName == m_toolSize.getName()) {
|
||||
updatePointSize();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Update point size based on property.
|
||||
void updatePointSize()
|
||||
{
|
||||
double x = m_toolSize.getValue();
|
||||
|
||||
double minRange = 1;
|
||||
double maxRange = 100;
|
||||
|
||||
double minSize = 10;
|
||||
double maxSize = 100;
|
||||
|
||||
m_pointSize =
|
||||
(x - minRange) / (maxRange - minRange) * (maxSize - minSize) + minSize;
|
||||
}
|
||||
} magnetTool;
|
||||
|
||||
// TTool *getMagnetTool() {return &magnetTool;}
|
||||
|
|
|
@ -318,11 +318,13 @@ PaintBrushTool::PaintBrushTool()
|
|||
, m_tileSaver(0)
|
||||
, m_cursor(ToolCursor::EraserCursor)
|
||||
// sostituire i nomi con quelli del current, tipo W_ToolOptions...
|
||||
, m_toolSize("Size:", 1, 100, 10, false) // W_ToolOptions_BrushToolSize
|
||||
, m_toolSize("Size:", 1, 1000, 10, false) // W_ToolOptions_BrushToolSize
|
||||
, m_colorType("Mode:") // W_ToolOptions_InkOrPaint
|
||||
, m_onlyEmptyAreas("Selective", false) // W_ToolOptions_Selective
|
||||
, m_firstTime(true)
|
||||
, m_workingFrameId(TFrameId()) {
|
||||
m_toolSize.setNonLinearSlider();
|
||||
|
||||
m_colorType.addValue(LINES);
|
||||
m_colorType.addValue(AREAS);
|
||||
m_colorType.addValue(ALL);
|
||||
|
|
|
@ -81,6 +81,8 @@ PinchTool::PinchTool()
|
|||
, m_selector(500, 10, 1000) {
|
||||
bind(TTool::Vectors);
|
||||
|
||||
m_toolRange.setNonLinearSlider();
|
||||
|
||||
m_prop.bind(m_toolCornerSize);
|
||||
m_prop.bind(m_autoOrManual);
|
||||
m_prop.bind(m_toolRange);
|
||||
|
|
|
@ -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);
|
||||
|
@ -1657,7 +1659,8 @@ void EraserTool::storeUndoAndRefresh() {
|
|||
TUndoManager::manager()->add(new RasterBluredEraserUndo(
|
||||
m_tileSet, m_points,
|
||||
TTool::getApplication()->getCurrentLevelStyleIndex(),
|
||||
m_currentStyle.getValue(), TTool::getApplication()
|
||||
m_currentStyle.getValue(),
|
||||
TTool::getApplication()
|
||||
->getCurrentLevel()
|
||||
->getLevel()
|
||||
->getSimpleLevel(),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -251,7 +251,8 @@ 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 -
|
||||
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);
|
||||
|
||||
|
@ -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);
|
||||
|
|
|
@ -273,7 +273,8 @@ 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 -
|
||||
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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -358,7 +358,7 @@ private:
|
|||
EraserTool::EraserTool()
|
||||
: TTool("T_Eraser")
|
||||
, m_eraseType("Type:") // "W_ToolOptions_Erasetype"
|
||||
, m_toolSize("Size:", 1, 100, 10) // "W_ToolOptions_EraserToolSize"
|
||||
, 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"
|
||||
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
@ -239,14 +278,13 @@ 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));
|
||||
|
||||
// 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
|
||||
|
|
|
@ -76,16 +76,45 @@ DoubleValuePairField::DoubleValuePairField(QWidget *parent,
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
double DoubleValuePairField::pos2value(int x) const {
|
||||
int xMin = m_leftMargin, xMax = width() - m_rightMargin;
|
||||
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));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
@ -309,7 +314,11 @@ void IntField::setRange(int minValue, int maxValue) {
|
|||
m_lineEdit->setRange(minValue, m_isMaxRangeLimited
|
||||
? maxValue
|
||||
: (std::numeric_limits<int>::max)());
|
||||
if (m_isLinearSlider)
|
||||
m_slider->setRange(minValue, maxValue);
|
||||
else
|
||||
m_slider->setRange(minValue * pow(10., NonLinearSliderPrecision),
|
||||
maxValue * pow(10., NonLinearSliderPrecision));
|
||||
m_roller->setRange(minValue, maxValue);
|
||||
}
|
||||
|
||||
|
@ -318,7 +327,7 @@ void IntField::setRange(int minValue, int maxValue) {
|
|||
void IntField::setValue(int value) {
|
||||
if (m_lineEdit->getValue() == value) return;
|
||||
m_lineEdit->setValue(value);
|
||||
m_slider->setSliderPosition(value);
|
||||
m_slider->setSliderPosition(value2pos(value));
|
||||
m_roller->setValue((double)value);
|
||||
}
|
||||
|
||||
|
@ -369,7 +378,50 @@ void IntField::setLineEditBackgroundColor(QColor color) {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void IntField::onSliderChanged(int value) {
|
||||
int IntField::pos2value(int x) const {
|
||||
if (m_isLinearSlider) return x;
|
||||
|
||||
// nonlinear slider case
|
||||
double rangeSize = (double)(m_slider->maximum() - m_slider->minimum());
|
||||
double posRatio = (double)(x - m_slider->minimum()) / rangeSize;
|
||||
double t;
|
||||
if (posRatio <= 0.5)
|
||||
t = 0.04 * posRatio;
|
||||
else if (posRatio <= 0.75)
|
||||
t = -0.02 + 0.08 * posRatio;
|
||||
else if (posRatio <= 0.9)
|
||||
t = -0.26 + 0.4 * posRatio;
|
||||
else
|
||||
t = -8.0 + 9.0 * posRatio;
|
||||
double sliderVal = (double)m_slider->minimum() + rangeSize * t;
|
||||
return (int)round(sliderVal * pow(0.1, NonLinearSliderPrecision));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int IntField::value2pos(int v) const {
|
||||
if (m_isLinearSlider) return v;
|
||||
|
||||
// nonlinear slider case
|
||||
double sliderVal = (double)v * pow(10., NonLinearSliderPrecision);
|
||||
double rangeSize = (double)(m_slider->maximum() - m_slider->minimum());
|
||||
double valueRatio = (double)(sliderVal - m_slider->minimum()) / rangeSize;
|
||||
double t;
|
||||
if (valueRatio <= 0.02)
|
||||
t = valueRatio / 0.04;
|
||||
else if (valueRatio <= 0.04)
|
||||
t = (valueRatio + 0.02) / 0.08;
|
||||
else if (valueRatio <= 0.1)
|
||||
t = (valueRatio + 0.26) / 0.4;
|
||||
else
|
||||
t = (valueRatio + 8.0) / 9.0;
|
||||
return m_slider->minimum() + (int)(t * rangeSize);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void IntField::onSliderChanged(int sliderPos) {
|
||||
int value = pos2value(sliderPos);
|
||||
// Controllo necessario per evitare che il segnale di cambiamento venga emesso
|
||||
// piu' volte.
|
||||
if (m_lineEdit->getValue() == value ||
|
||||
|
@ -390,10 +442,10 @@ void IntField::onEditingFinished() {
|
|||
double value = m_lineEdit->getValue();
|
||||
// Controllo necessario per evitare che il segnale di cambiamento venga emesso
|
||||
// piu' volte.
|
||||
if ((m_slider->value() == value && m_slider->isVisible()) ||
|
||||
if ((pos2value(m_slider->value()) == value && m_slider->isVisible()) ||
|
||||
(int)m_roller->getValue() == value && m_roller->isVisible())
|
||||
return;
|
||||
m_slider->setValue(value);
|
||||
m_slider->setValue(value2pos(value));
|
||||
m_roller->setValue((double)value);
|
||||
emit valueChanged(false);
|
||||
}
|
||||
|
@ -403,13 +455,13 @@ void IntField::onEditingFinished() {
|
|||
void IntField::onRollerValueChanged(bool isDragging) {
|
||||
int value = m_roller->getValue();
|
||||
if (value == m_lineEdit->getValue()) {
|
||||
assert(m_slider->value() == value || !m_slider->isVisible());
|
||||
assert(pos2value(m_slider->value()) == value || !m_slider->isVisible());
|
||||
// Se isDragging e' falso e' giusto che venga emessa la notifica di
|
||||
// cambiamento.
|
||||
if (!isDragging) emit valueChanged(isDragging);
|
||||
return;
|
||||
}
|
||||
m_slider->setValue(value);
|
||||
m_slider->setValue(value2pos(value));
|
||||
m_lineEdit->setValue(value);
|
||||
|
||||
// Faccio in modo che il cursore sia sulla prima cifra, cosi' se la stringa
|
||||
|
|
|
@ -33,7 +33,8 @@ IntPairField::IntPairField(QWidget *parent, bool isMaxRangeLimited)
|
|||
, m_grabIndex(-1)
|
||||
, m_leftMargin(52)
|
||||
, m_rightMargin(52)
|
||||
, m_isMaxRangeLimited(isMaxRangeLimited) {
|
||||
, m_isMaxRangeLimited(isMaxRangeLimited)
|
||||
, m_isLinear(true) {
|
||||
setObjectName("IntPairField");
|
||||
setFixedHeight(WidgetHeight);
|
||||
|
||||
|
@ -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;
|
||||
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;
|
||||
if (m_isLinear)
|
||||
return xMin +
|
||||
(int)(((xMax - xMin) * (v - m_minValue)) / (m_maxValue - m_minValue));
|
||||
((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));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue