Add brush snap to Grid toolbar option
This commit is contained in:
parent
ee8fc57567
commit
fa61b14844
7 changed files with 424 additions and 366 deletions
|
@ -60,6 +60,7 @@ TEnv::DoubleVar FullcolorModifierOpacity("FullcolorModifierOpacity", 100);
|
|||
TEnv::IntVar FullcolorModifierEraser("FullcolorModifierEraser", 0);
|
||||
TEnv::IntVar FullcolorModifierLockAlpha("FullcolorModifierLockAlpha", 0);
|
||||
TEnv::StringVar FullcolorBrushPreset("FullcolorBrushPreset", "<custom>");
|
||||
TEnv::IntVar FullcolorBrushSnapGrid("FullcolorBrushSnapGrid", 0);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
|
@ -135,7 +136,8 @@ FullColorBrushTool::FullColorBrushTool(std::string name)
|
|||
, m_tileSaver(0)
|
||||
, m_notifier(0)
|
||||
, m_presetsLoaded(false)
|
||||
, m_firstTime(true) {
|
||||
, m_firstTime(true)
|
||||
, m_snapGrid("Grid", false) {
|
||||
bind(TTool::RasterImage | TTool::EmptyTarget);
|
||||
|
||||
m_thickness.setNonLinearSlider();
|
||||
|
@ -148,12 +150,14 @@ FullColorBrushTool::FullColorBrushTool(std::string name)
|
|||
m_prop.bind(m_modifierEraser);
|
||||
m_prop.bind(m_modifierLockAlpha);
|
||||
m_prop.bind(m_pressure);
|
||||
m_prop.bind(m_snapGrid);
|
||||
m_prop.bind(m_preset);
|
||||
|
||||
m_preset.setId("BrushPreset");
|
||||
m_modifierEraser.setId("RasterEraser");
|
||||
m_modifierLockAlpha.setId("LockAlpha");
|
||||
m_pressure.setId("PressureSensitivity");
|
||||
m_snapGrid.setId("SnapGrid");
|
||||
|
||||
m_brushTimer.start();
|
||||
}
|
||||
|
@ -192,6 +196,7 @@ void FullColorBrushTool::updateTranslation() {
|
|||
m_modifierOpacity.setQStringName(tr("Opacity"));
|
||||
m_modifierEraser.setQStringName(tr("Eraser"));
|
||||
m_modifierLockAlpha.setQStringName(tr("Lock Alpha"));
|
||||
m_snapGrid.setQStringName(tr("Grid"));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
@ -336,12 +341,16 @@ void FullColorBrushTool::leftButtonDown(const TPointD &pos,
|
|||
}
|
||||
|
||||
if (e.isAltPressed()) {
|
||||
m_snapAssistant = true;
|
||||
m_isStraight = true;
|
||||
m_firstPoint = pos;
|
||||
m_lastPoint = pos;
|
||||
}
|
||||
|
||||
if (m_snapGrid.getValue()) {
|
||||
m_firstPoint = pos;
|
||||
m_lastPoint = pos;
|
||||
}
|
||||
|
||||
/* update color here since the current style might be switched with numpad
|
||||
* shortcut keys */
|
||||
updateCurrentStyle();
|
||||
|
@ -384,6 +393,7 @@ void FullColorBrushTool::leftButtonDown(const TPointD &pos,
|
|||
invalidateRect +=
|
||||
TRectD(previousBrushPos - thickOffset, previousBrushPos + thickOffset);
|
||||
invalidate(invalidateRect.enlarge(2.0));
|
||||
m_perspectiveIndex = -1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
|
@ -391,16 +401,27 @@ void FullColorBrushTool::leftButtonDown(const TPointD &pos,
|
|||
void FullColorBrushTool::leftButtonDrag(const TPointD &pos,
|
||||
const TMouseEvent &e) {
|
||||
TRectD invalidateRect;
|
||||
if (m_isStraight) {
|
||||
invalidateRect = TRectD(m_firstPoint, m_lastPoint).enlarge(2);
|
||||
m_lastPoint = pos;
|
||||
if (e.isAltPressed()) {
|
||||
double distance = (m_brushPos.x - m_maxCursorThick + 1) * 0.5;
|
||||
TRectD brushRect =
|
||||
TRectD(TPointD(m_brushPos.x - distance, m_brushPos.y - distance),
|
||||
TPointD(m_brushPos.x + distance, m_brushPos.y + distance));
|
||||
invalidateRect += (brushRect);
|
||||
invalidateRect = TRectD(m_firstPoint, m_lastPoint).enlarge(2);
|
||||
m_lastPoint = pos;
|
||||
TPointD usePos = pos;
|
||||
|
||||
if (e.isAltPressed() || m_snapGrid.getValue()) {
|
||||
double distance = (m_brushPos.x - m_maxCursorThick + 1) * 0.5;
|
||||
TRectD brushRect =
|
||||
TRectD(TPointD(m_brushPos.x - distance, m_brushPos.y - distance),
|
||||
TPointD(m_brushPos.x + distance, m_brushPos.y + distance));
|
||||
invalidateRect += (brushRect);
|
||||
|
||||
PerspectiveTool *perspectiveTool = dynamic_cast<PerspectiveTool *>(
|
||||
TTool::getTool("T_PerspectiveGrid", TTool::RasterImage));
|
||||
std::vector<PerspectiveObject *> perspectiveObjs =
|
||||
perspectiveTool->getPerspectiveObjects();
|
||||
TPointD pointToUse = TPointD(0.0, 0.0);
|
||||
TPointD dpiScale = getViewer()->getDpiScale();
|
||||
TPointD refPoint = m_firstPoint;
|
||||
refPoint.x *= dpiScale.x;
|
||||
refPoint.y *= dpiScale.y;
|
||||
if (e.isAltPressed() || m_perspectiveIndex < 0) {
|
||||
// let's get info about our current location
|
||||
double denominator = m_lastPoint.x - m_firstPoint.x;
|
||||
double numerator = m_lastPoint.y - m_firstPoint.y;
|
||||
|
@ -415,140 +436,134 @@ void FullColorBrushTool::leftButtonDrag(const TPointD &pos,
|
|||
|
||||
// now let's get the angle of each of the assistant points
|
||||
std::vector<double> anglesToAssistants;
|
||||
TPointD pointToUse = TPointD(0.0, 0.0);
|
||||
|
||||
PerspectiveTool *perspectiveTool = dynamic_cast<PerspectiveTool *>(
|
||||
TTool::getTool("T_PerspectiveGrid", TTool::RasterImage));
|
||||
if (perspectiveTool) {
|
||||
TPointD dpiScale = getViewer()->getDpiScale();
|
||||
TPointD refPoint = m_firstPoint;
|
||||
refPoint.x *= dpiScale.x;
|
||||
refPoint.y *= dpiScale.y;
|
||||
|
||||
std::vector<PerspectiveObject *> perspectiveObjs =
|
||||
perspectiveTool->getPerspectiveObjects();
|
||||
for (auto data : perspectiveObjs) {
|
||||
TPointD point = data->getReferencePoint(refPoint);
|
||||
point.x /= dpiScale.x;
|
||||
point.y /= dpiScale.y;
|
||||
double newDenominator = point.x - m_firstPoint.x;
|
||||
double newNumerator = point.y - m_firstPoint.y;
|
||||
if (areAlmostEqual(newDenominator, 0.0, 0.0001)) {
|
||||
newDenominator = newDenominator < 0 ? -0.0001 : 0.0001;
|
||||
}
|
||||
if (areAlmostEqual(newNumerator, 0.0, 0.0001)) {
|
||||
newNumerator = newNumerator < 0 ? -0.0001 : 0.0001;
|
||||
}
|
||||
|
||||
double newSlope = (newNumerator / newDenominator);
|
||||
double newAngle = std::atan(newSlope) * (180 / 3.14159);
|
||||
anglesToAssistants.push_back(newAngle);
|
||||
for (auto data : perspectiveObjs) {
|
||||
TPointD point = data->getReferencePoint(refPoint);
|
||||
point.x /= dpiScale.x;
|
||||
point.y /= dpiScale.y;
|
||||
double newDenominator = point.x - m_firstPoint.x;
|
||||
double newNumerator = point.y - m_firstPoint.y;
|
||||
if (areAlmostEqual(newDenominator, 0.0, 0.0001)) {
|
||||
newDenominator = newDenominator < 0 ? -0.0001 : 0.0001;
|
||||
}
|
||||
if (areAlmostEqual(newNumerator, 0.0, 0.0001)) {
|
||||
newNumerator = newNumerator < 0 ? -0.0001 : 0.0001;
|
||||
}
|
||||
|
||||
// figure out which angle is closer
|
||||
double difference = 360;
|
||||
|
||||
for (int i = 0; i < anglesToAssistants.size(); i++) {
|
||||
double newDifference = abs(angle - anglesToAssistants.at(i));
|
||||
if (newDifference < difference ||
|
||||
(180 - newDifference) < difference) {
|
||||
difference = std::min(newDifference, (180 - newDifference));
|
||||
pointToUse = perspectiveObjs.at(i)->getReferencePoint(refPoint);
|
||||
pointToUse.x /= dpiScale.x;
|
||||
pointToUse.y /= dpiScale.y;
|
||||
}
|
||||
}
|
||||
double newSlope = (newNumerator / newDenominator);
|
||||
double newAngle = std::atan(newSlope) * (180 / 3.14159);
|
||||
anglesToAssistants.push_back(newAngle);
|
||||
}
|
||||
|
||||
double distanceFirstToLast =
|
||||
std::sqrt(std::pow((m_lastPoint.x - m_firstPoint.x), 2) +
|
||||
std::pow((m_lastPoint.y - m_firstPoint.y), 2));
|
||||
double distanceLastToAssistant =
|
||||
std::sqrt(std::pow((pointToUse.x - m_lastPoint.x), 2) +
|
||||
std::pow((pointToUse.y - m_lastPoint.y), 2));
|
||||
double distanceFirstToAssistant =
|
||||
std::sqrt(std::pow((pointToUse.x - m_firstPoint.x), 2) +
|
||||
std::pow((pointToUse.y - m_firstPoint.y), 2));
|
||||
// figure out which angle is closer
|
||||
double difference = 360;
|
||||
|
||||
if (distanceFirstToAssistant == 0.0) distanceFirstToAssistant = 0.001;
|
||||
|
||||
double ratio = distanceFirstToLast / distanceFirstToAssistant;
|
||||
|
||||
double newX;
|
||||
double newY;
|
||||
|
||||
// flip the direction if the last point is farther than the first point
|
||||
if (distanceFirstToAssistant < distanceLastToAssistant &&
|
||||
distanceFirstToLast < distanceLastToAssistant) {
|
||||
newX = ((1 + ratio) * m_firstPoint.x) - (ratio * pointToUse.x);
|
||||
newY = ((1 + ratio) * m_firstPoint.y) - (ratio * pointToUse.y);
|
||||
} else {
|
||||
newX = ((1 - ratio) * m_firstPoint.x) + (ratio * pointToUse.x);
|
||||
newY = ((1 - ratio) * m_firstPoint.y) + (ratio * pointToUse.y);
|
||||
}
|
||||
|
||||
m_lastPoint = TPointD(newX, newY);
|
||||
invalidateRect += TRectD(m_firstPoint, m_lastPoint).enlarge(2);
|
||||
} else if (e.isCtrlPressed()) {
|
||||
double distance = (m_brushPos.x - m_maxCursorThick + 1) * 0.5;
|
||||
TRectD brushRect =
|
||||
TRectD(TPointD(m_brushPos.x - distance, m_brushPos.y - distance),
|
||||
TPointD(m_brushPos.x + distance, m_brushPos.y + distance));
|
||||
invalidateRect += (brushRect);
|
||||
double denominator = m_lastPoint.x - m_firstPoint.x;
|
||||
if (denominator == 0) denominator == 0.001;
|
||||
double slope = ((m_lastPoint.y - m_firstPoint.y) / denominator);
|
||||
double radAngle = std::atan(abs(slope));
|
||||
double angle = radAngle * (180 / 3.14159);
|
||||
if (abs(angle) >= 82.5)
|
||||
m_lastPoint.x = m_firstPoint.x;
|
||||
else if (abs(angle) < 7.5)
|
||||
m_lastPoint.y = m_firstPoint.y;
|
||||
else {
|
||||
double xDistance = m_lastPoint.x - m_firstPoint.x;
|
||||
double yDistance = m_lastPoint.y - m_firstPoint.y;
|
||||
|
||||
double totalDistance =
|
||||
std::sqrt(std::pow(xDistance, 2) + std::pow(yDistance, 2));
|
||||
double xLength = 0.0;
|
||||
double yLength = 0.0;
|
||||
if (angle >= 7.5 && angle < 22.5) {
|
||||
yLength = std::sin(15 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(15 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 22.5 && angle < 37.5) {
|
||||
yLength = std::sin(30 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(30 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 37.5 && angle < 52.5) {
|
||||
yLength = std::sin(45 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(45 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 52.5 && angle < 67.5) {
|
||||
yLength = std::sin(60 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(60 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 67.5 && angle < 82.5) {
|
||||
yLength = std::sin(75 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(75 * (3.14159 / 180)) * totalDistance;
|
||||
}
|
||||
|
||||
if (yDistance == abs(yDistance)) {
|
||||
m_lastPoint.y = m_firstPoint.y + yLength;
|
||||
} else {
|
||||
m_lastPoint.y = m_firstPoint.y - yLength;
|
||||
}
|
||||
if (xDistance == abs(xDistance)) {
|
||||
m_lastPoint.x = m_firstPoint.x + xLength;
|
||||
} else {
|
||||
m_lastPoint.x = m_firstPoint.x - xLength;
|
||||
for (int i = 0; i < anglesToAssistants.size(); i++) {
|
||||
double newDifference = abs(angle - anglesToAssistants.at(i));
|
||||
if (newDifference < difference || (180 - newDifference) < difference) {
|
||||
difference = std::min(newDifference, (180 - newDifference));
|
||||
pointToUse = perspectiveObjs.at(i)->getReferencePoint(refPoint);
|
||||
pointToUse.x /= dpiScale.x;
|
||||
pointToUse.y /= dpiScale.y;
|
||||
m_perspectiveIndex = i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pointToUse =
|
||||
perspectiveObjs.at(m_perspectiveIndex)->getReferencePoint(refPoint);
|
||||
pointToUse.x /= dpiScale.x;
|
||||
pointToUse.y /= dpiScale.y;
|
||||
}
|
||||
|
||||
// keep this here for possible eventual variable width
|
||||
// if (getApplication()->getCurrentLevelStyle()->getTagId() ==
|
||||
// 4001) // mypaint brush case
|
||||
// m_oldPressure = m_enabledPressure && e.isTablet() ? e.m_pressure : 0.5;
|
||||
// else
|
||||
// m_oldPressure = m_enabledPressure ? e.m_pressure : 1.0;
|
||||
double distanceFirstToLast =
|
||||
std::sqrt(std::pow((m_lastPoint.x - m_firstPoint.x), 2) +
|
||||
std::pow((m_lastPoint.y - m_firstPoint.y), 2));
|
||||
double distanceLastToAssistant =
|
||||
std::sqrt(std::pow((pointToUse.x - m_lastPoint.x), 2) +
|
||||
std::pow((pointToUse.y - m_lastPoint.y), 2));
|
||||
double distanceFirstToAssistant =
|
||||
std::sqrt(std::pow((pointToUse.x - m_firstPoint.x), 2) +
|
||||
std::pow((pointToUse.y - m_firstPoint.y), 2));
|
||||
|
||||
if (distanceFirstToAssistant == 0.0) distanceFirstToAssistant = 0.001;
|
||||
|
||||
double ratio = distanceFirstToLast / distanceFirstToAssistant;
|
||||
|
||||
double newX;
|
||||
double newY;
|
||||
|
||||
// flip the direction if the last point is farther than the first point
|
||||
if (distanceFirstToAssistant < distanceLastToAssistant &&
|
||||
distanceFirstToLast < distanceLastToAssistant) {
|
||||
newX = ((1 + ratio) * m_firstPoint.x) - (ratio * pointToUse.x);
|
||||
newY = ((1 + ratio) * m_firstPoint.y) - (ratio * pointToUse.y);
|
||||
} else {
|
||||
newX = ((1 - ratio) * m_firstPoint.x) + (ratio * pointToUse.x);
|
||||
newY = ((1 - ratio) * m_firstPoint.y) + (ratio * pointToUse.y);
|
||||
}
|
||||
|
||||
usePos = m_lastPoint = TPointD(newX, newY);
|
||||
invalidateRect += TRectD(m_firstPoint, m_lastPoint).enlarge(2);
|
||||
} else if (e.isCtrlPressed()) {
|
||||
double distance = (m_brushPos.x - m_maxCursorThick + 1) * 0.5;
|
||||
TRectD brushRect =
|
||||
TRectD(TPointD(m_brushPos.x - distance, m_brushPos.y - distance),
|
||||
TPointD(m_brushPos.x + distance, m_brushPos.y + distance));
|
||||
invalidateRect += (brushRect);
|
||||
double denominator = m_lastPoint.x - m_firstPoint.x;
|
||||
if (denominator == 0) denominator == 0.001;
|
||||
double slope = ((m_lastPoint.y - m_firstPoint.y) / denominator);
|
||||
double radAngle = std::atan(abs(slope));
|
||||
double angle = radAngle * (180 / 3.14159);
|
||||
if (abs(angle) >= 82.5)
|
||||
m_lastPoint.x = m_firstPoint.x;
|
||||
else if (abs(angle) < 7.5)
|
||||
m_lastPoint.y = m_firstPoint.y;
|
||||
else {
|
||||
double xDistance = m_lastPoint.x - m_firstPoint.x;
|
||||
double yDistance = m_lastPoint.y - m_firstPoint.y;
|
||||
|
||||
double totalDistance =
|
||||
std::sqrt(std::pow(xDistance, 2) + std::pow(yDistance, 2));
|
||||
double xLength = 0.0;
|
||||
double yLength = 0.0;
|
||||
if (angle >= 7.5 && angle < 22.5) {
|
||||
yLength = std::sin(15 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(15 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 22.5 && angle < 37.5) {
|
||||
yLength = std::sin(30 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(30 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 37.5 && angle < 52.5) {
|
||||
yLength = std::sin(45 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(45 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 52.5 && angle < 67.5) {
|
||||
yLength = std::sin(60 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(60 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 67.5 && angle < 82.5) {
|
||||
yLength = std::sin(75 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(75 * (3.14159 / 180)) * totalDistance;
|
||||
}
|
||||
|
||||
if (yDistance == abs(yDistance)) {
|
||||
m_lastPoint.y = m_firstPoint.y + yLength;
|
||||
} else {
|
||||
m_lastPoint.y = m_firstPoint.y - yLength;
|
||||
}
|
||||
if (xDistance == abs(xDistance)) {
|
||||
m_lastPoint.x = m_firstPoint.x + xLength;
|
||||
} else {
|
||||
m_lastPoint.x = m_firstPoint.x - xLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// keep this here for possible eventual variable width
|
||||
// if (getApplication()->getCurrentLevelStyle()->getTagId() ==
|
||||
// 4001) // mypaint brush case
|
||||
// m_oldPressure = m_enabledPressure && e.isTablet() ? e.m_pressure : 0.5;
|
||||
// else
|
||||
// m_oldPressure = m_enabledPressure ? e.m_pressure : 1.0;
|
||||
|
||||
if (m_isStraight) {
|
||||
m_mousePos = pos;
|
||||
m_brushPos = pos;
|
||||
invalidate(invalidateRect);
|
||||
|
@ -565,7 +580,7 @@ void FullColorBrushTool::leftButtonDrag(const TPointD &pos,
|
|||
|
||||
TRasterP ras = ri->getRaster();
|
||||
TPointD rasCenter = ras->getCenterD();
|
||||
TPointD point(pos + rasCenter);
|
||||
TPointD point(usePos + rasCenter);
|
||||
double pressure;
|
||||
if (getApplication()->getCurrentLevelStyle()->getTagId() ==
|
||||
4001) // mypaint brush case
|
||||
|
@ -602,7 +617,7 @@ void FullColorBrushTool::leftButtonUp(const TPointD &pos,
|
|||
TRasterP ras = ri->getRaster();
|
||||
TPointD rasCenter = ras->getCenterD();
|
||||
TPointD point;
|
||||
if (e.isCtrlPressed() || m_snapAssistant || e.isAltPressed())
|
||||
if (e.isCtrlPressed() || m_snapGrid.getValue() || e.isAltPressed())
|
||||
point = TPointD(m_lastPoint + rasCenter);
|
||||
else
|
||||
point = TPointD(pos + rasCenter);
|
||||
|
@ -655,8 +670,8 @@ void FullColorBrushTool::leftButtonUp(const TPointD &pos,
|
|||
m_strokeRect.empty();
|
||||
m_mousePressed = false;
|
||||
m_isStraight = false;
|
||||
m_snapAssistant = false;
|
||||
m_oldPressure = -1.0;
|
||||
m_perspectiveIndex = -1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
|
@ -838,6 +853,7 @@ bool FullColorBrushTool::onPropertyChanged(std::string propertyName) {
|
|||
FullcolorModifierOpacity = m_modifierOpacity.getValue();
|
||||
FullcolorModifierEraser = m_modifierEraser.getValue() ? 1 : 0;
|
||||
FullcolorModifierLockAlpha = m_modifierLockAlpha.getValue() ? 1 : 0;
|
||||
FullcolorBrushSnapGrid = m_snapGrid.getValue() ? 1 : 0;
|
||||
|
||||
if (m_preset.getValue() != CUSTOM_WSTR) {
|
||||
m_preset.setValue(CUSTOM_WSTR);
|
||||
|
@ -952,6 +968,7 @@ void FullColorBrushTool::loadLastBrush() {
|
|||
m_modifierOpacity.setValue(FullcolorModifierOpacity);
|
||||
m_modifierEraser.setValue(FullcolorModifierEraser ? true : false);
|
||||
m_modifierLockAlpha.setValue(FullcolorModifierLockAlpha ? true : false);
|
||||
m_snapGrid.setValue(FullcolorBrushSnapGrid ? true : false);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -95,6 +95,7 @@ protected:
|
|||
TBoolProperty m_modifierEraser;
|
||||
TBoolProperty m_modifierLockAlpha;
|
||||
TEnumProperty m_preset;
|
||||
TBoolProperty m_snapGrid;
|
||||
|
||||
TPixel32 m_currentColor;
|
||||
bool m_enabledPressure;
|
||||
|
@ -126,10 +127,11 @@ protected:
|
|||
bool m_isStraight = false;
|
||||
TPointD m_firstPoint;
|
||||
TPointD m_lastPoint;
|
||||
bool m_snapAssistant = false;
|
||||
double m_oldPressure = -1.0;
|
||||
|
||||
bool m_propertyUpdating = false;
|
||||
|
||||
int m_perspectiveIndex = -1;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
|
|
@ -2114,7 +2114,7 @@ void BrushToolOptionsBox::filterControls() {
|
|||
it != m_labels.end(); it++) {
|
||||
bool isModifier = (it.key().substr(0, 8) == "Modifier");
|
||||
bool isCommon = (it.key() == "Lock Alpha" || it.key() == "Pressure" ||
|
||||
it.key() == "Preset:");
|
||||
it.key() == "Preset:" || it.key() == "Grid");
|
||||
bool visible = isCommon || (isModifier == showModifiers);
|
||||
it.value()->setVisible(visible);
|
||||
}
|
||||
|
@ -2123,7 +2123,7 @@ void BrushToolOptionsBox::filterControls() {
|
|||
it != m_controls.end(); it++) {
|
||||
bool isModifier = (it.key().substr(0, 8) == "Modifier");
|
||||
bool isCommon = (it.key() == "Lock Alpha" || it.key() == "Pressure" ||
|
||||
it.key() == "Preset:");
|
||||
it.key() == "Preset:" || it.key() == "Grid");
|
||||
bool visible = isCommon || (isModifier == showModifiers);
|
||||
if (QWidget *widget = dynamic_cast<QWidget *>(it.value()))
|
||||
widget->setVisible(visible);
|
||||
|
|
|
@ -61,6 +61,7 @@ TEnv::DoubleVar RasterBrushHardness("RasterBrushHardness", 100);
|
|||
TEnv::DoubleVar RasterBrushModifierSize("RasterBrushModifierSize", 0);
|
||||
TEnv::StringVar RasterBrushPreset("RasterBrushPreset", "<custom>");
|
||||
TEnv::IntVar BrushLockAlpha("InknpaintBrushLockAlpha", 0);
|
||||
TEnv::IntVar BrushSnapGrid("InknpaintBrushSnapGrid", 0);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
#define CUSTOM_WSTR L"<custom>"
|
||||
|
@ -890,7 +891,8 @@ ToonzRasterBrushTool::ToonzRasterBrushTool(std::string name, int targetType)
|
|||
, m_targetType(targetType)
|
||||
, m_workingFrameId(TFrameId())
|
||||
, m_notifier(0)
|
||||
, m_modifierLockAlpha("Lock Alpha", false) {
|
||||
, m_modifierLockAlpha("Lock Alpha", false)
|
||||
, m_snapGrid("Grid", false) {
|
||||
bind(targetType);
|
||||
|
||||
m_rasThickness.setNonLinearSlider();
|
||||
|
@ -911,6 +913,9 @@ ToonzRasterBrushTool::ToonzRasterBrushTool(std::string name, int targetType)
|
|||
|
||||
m_prop[0].bind(m_pressure);
|
||||
|
||||
m_prop[0].bind(m_snapGrid);
|
||||
m_snapGrid.setId("SnapGrid");
|
||||
|
||||
m_prop[0].bind(m_preset);
|
||||
m_preset.setId("BrushPreset");
|
||||
m_preset.addValue(CUSTOM_WSTR);
|
||||
|
@ -1110,6 +1115,7 @@ void ToonzRasterBrushTool::updateTranslation() {
|
|||
m_pencil.setQStringName(tr("Pencil"));
|
||||
m_pressure.setQStringName(tr("Pressure"));
|
||||
m_modifierLockAlpha.setQStringName(tr("Lock Alpha"));
|
||||
m_snapGrid.setQStringName(tr("Grid"));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
@ -1301,12 +1307,16 @@ void ToonzRasterBrushTool::leftButtonDown(const TPointD &pos,
|
|||
}
|
||||
|
||||
if (e.isAltPressed()) {
|
||||
m_snapAssistant = true;
|
||||
m_isStraight = true;
|
||||
m_firstPoint = pos;
|
||||
m_lastPoint = pos;
|
||||
}
|
||||
|
||||
if (m_snapGrid.getValue()) {
|
||||
m_firstPoint = pos;
|
||||
m_lastPoint = pos;
|
||||
}
|
||||
|
||||
// assert(0<=m_styleId && m_styleId<2);
|
||||
TImageP img = getImage(true);
|
||||
TToonzImageP ri(img);
|
||||
|
@ -1442,6 +1452,7 @@ void ToonzRasterBrushTool::leftButtonDown(const TPointD &pos,
|
|||
// updating m_brushPos is needed to refresh viewer properly
|
||||
m_mousePos = pos;
|
||||
m_brushPos = getCenteredCursorPos(pos);
|
||||
m_perspectiveIndex = -1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
|
@ -1455,16 +1466,27 @@ void ToonzRasterBrushTool::leftButtonDrag(const TPointD &pos,
|
|||
}
|
||||
|
||||
TRectD invalidateRect;
|
||||
if (m_isStraight) {
|
||||
invalidateRect = TRectD(m_firstPoint, m_lastPoint).enlarge(2);
|
||||
m_lastPoint = pos;
|
||||
if (e.isAltPressed()) {
|
||||
double distance = (m_brushPos.x - m_maxCursorThick + 1) * 0.5;
|
||||
TRectD brushRect =
|
||||
TRectD(TPointD(m_brushPos.x - distance, m_brushPos.y - distance),
|
||||
TPointD(m_brushPos.x + distance, m_brushPos.y + distance));
|
||||
invalidateRect += (brushRect);
|
||||
invalidateRect = TRectD(m_firstPoint, m_lastPoint).enlarge(2);
|
||||
m_lastPoint = pos;
|
||||
TPointD usePos = pos;
|
||||
|
||||
if (e.isAltPressed() || m_snapGrid.getValue()) {
|
||||
double distance = (m_brushPos.x - m_maxCursorThick + 1) * 0.5;
|
||||
TRectD brushRect =
|
||||
TRectD(TPointD(m_brushPos.x - distance, m_brushPos.y - distance),
|
||||
TPointD(m_brushPos.x + distance, m_brushPos.y + distance));
|
||||
invalidateRect += (brushRect);
|
||||
|
||||
PerspectiveTool *perspectiveTool = dynamic_cast<PerspectiveTool *>(
|
||||
TTool::getTool("T_PerspectiveGrid", TTool::ToonzImage));
|
||||
std::vector<PerspectiveObject *> perspectiveObjs =
|
||||
perspectiveTool->getPerspectiveObjects();
|
||||
TPointD pointToUse = TPointD(0.0, 0.0);
|
||||
TPointD dpiScale = getViewer()->getDpiScale();
|
||||
TPointD refPoint = m_firstPoint;
|
||||
refPoint.x *= dpiScale.x;
|
||||
refPoint.y *= dpiScale.y;
|
||||
if (e.isAltPressed() || m_perspectiveIndex < 0) {
|
||||
// let's get info about our current location
|
||||
double denominator = m_lastPoint.x - m_firstPoint.x;
|
||||
double numerator = m_lastPoint.y - m_firstPoint.y;
|
||||
|
@ -1479,210 +1501,201 @@ void ToonzRasterBrushTool::leftButtonDrag(const TPointD &pos,
|
|||
|
||||
// now let's get the angle of each of the assistant points
|
||||
std::vector<double> anglesToAssistants;
|
||||
TPointD pointToUse = TPointD(0.0, 0.0);
|
||||
|
||||
PerspectiveTool *perspectiveTool = dynamic_cast<PerspectiveTool *>(
|
||||
TTool::getTool("T_PerspectiveGrid", TTool::ToonzImage));
|
||||
if (perspectiveTool) {
|
||||
TPointD dpiScale = getViewer()->getDpiScale();
|
||||
TPointD refPoint = m_firstPoint;
|
||||
refPoint.x *= dpiScale.x;
|
||||
refPoint.y *= dpiScale.y;
|
||||
|
||||
std::vector<PerspectiveObject *> perspectiveObjs =
|
||||
perspectiveTool->getPerspectiveObjects();
|
||||
for (auto data : perspectiveObjs) {
|
||||
TPointD point = data->getReferencePoint(refPoint);
|
||||
point.x /= dpiScale.x;
|
||||
point.y /= dpiScale.y;
|
||||
double newDenominator = point.x - m_firstPoint.x;
|
||||
double newNumerator = point.y - m_firstPoint.y;
|
||||
if (areAlmostEqual(newDenominator, 0.0, 0.0001)) {
|
||||
newDenominator = newDenominator < 0 ? -0.0001 : 0.0001;
|
||||
}
|
||||
if (areAlmostEqual(newNumerator, 0.0, 0.0001)) {
|
||||
newNumerator = newNumerator < 0 ? -0.0001 : 0.0001;
|
||||
}
|
||||
|
||||
double newSlope = (newNumerator / newDenominator);
|
||||
double newAngle = std::atan(newSlope) * (180 / 3.14159);
|
||||
anglesToAssistants.push_back(newAngle);
|
||||
for (auto data : perspectiveObjs) {
|
||||
TPointD point = data->getReferencePoint(refPoint);
|
||||
point.x /= dpiScale.x;
|
||||
point.y /= dpiScale.y;
|
||||
double newDenominator = point.x - m_firstPoint.x;
|
||||
double newNumerator = point.y - m_firstPoint.y;
|
||||
if (areAlmostEqual(newDenominator, 0.0, 0.0001)) {
|
||||
newDenominator = newDenominator < 0 ? -0.0001 : 0.0001;
|
||||
}
|
||||
if (areAlmostEqual(newNumerator, 0.0, 0.0001)) {
|
||||
newNumerator = newNumerator < 0 ? -0.0001 : 0.0001;
|
||||
}
|
||||
|
||||
// figure out which angle is closer
|
||||
double difference = 360;
|
||||
|
||||
for (int i = 0; i < anglesToAssistants.size(); i++) {
|
||||
double newDifference = abs(angle - anglesToAssistants.at(i));
|
||||
if (newDifference < difference ||
|
||||
(180 - newDifference) < difference) {
|
||||
difference = std::min(newDifference, (180 - newDifference));
|
||||
pointToUse = perspectiveObjs.at(i)->getReferencePoint(refPoint);
|
||||
pointToUse.x /= dpiScale.x;
|
||||
pointToUse.y /= dpiScale.y;
|
||||
}
|
||||
}
|
||||
double newSlope = (newNumerator / newDenominator);
|
||||
double newAngle = std::atan(newSlope) * (180 / 3.14159);
|
||||
anglesToAssistants.push_back(newAngle);
|
||||
}
|
||||
|
||||
double distanceFirstToLast =
|
||||
std::sqrt(std::pow((m_lastPoint.x - m_firstPoint.x), 2) +
|
||||
std::pow((m_lastPoint.y - m_firstPoint.y), 2));
|
||||
double distanceLastToAssistant =
|
||||
std::sqrt(std::pow((pointToUse.x - m_lastPoint.x), 2) +
|
||||
std::pow((pointToUse.y - m_lastPoint.y), 2));
|
||||
double distanceFirstToAssistant =
|
||||
std::sqrt(std::pow((pointToUse.x - m_firstPoint.x), 2) +
|
||||
std::pow((pointToUse.y - m_firstPoint.y), 2));
|
||||
// figure out which angle is closer
|
||||
double difference = 360;
|
||||
|
||||
if (distanceFirstToAssistant == 0.0) distanceFirstToAssistant = 0.001;
|
||||
|
||||
double ratio = distanceFirstToLast / distanceFirstToAssistant;
|
||||
|
||||
double newX;
|
||||
double newY;
|
||||
|
||||
// flip the direction if the last point is farther than the first point
|
||||
if (distanceFirstToAssistant < distanceLastToAssistant &&
|
||||
distanceFirstToLast < distanceLastToAssistant) {
|
||||
newX = ((1 + ratio) * m_firstPoint.x) - (ratio * pointToUse.x);
|
||||
newY = ((1 + ratio) * m_firstPoint.y) - (ratio * pointToUse.y);
|
||||
} else {
|
||||
newX = ((1 - ratio) * m_firstPoint.x) + (ratio * pointToUse.x);
|
||||
newY = ((1 - ratio) * m_firstPoint.y) + (ratio * pointToUse.y);
|
||||
}
|
||||
|
||||
m_lastPoint = TPointD(newX, newY);
|
||||
invalidateRect += TRectD(m_firstPoint, m_lastPoint).enlarge(2);
|
||||
} else if (e.isCtrlPressed()) {
|
||||
double distance = (m_brushPos.x - m_maxCursorThick + 1) * 0.5;
|
||||
TRectD brushRect =
|
||||
TRectD(TPointD(m_brushPos.x - distance, m_brushPos.y - distance),
|
||||
TPointD(m_brushPos.x + distance, m_brushPos.y + distance));
|
||||
invalidateRect += (brushRect);
|
||||
|
||||
double denominator = m_lastPoint.x - m_firstPoint.x;
|
||||
if (denominator == 0) denominator == 0.001;
|
||||
double slope = ((m_lastPoint.y - m_firstPoint.y) / denominator);
|
||||
double radAngle = std::atan(abs(slope));
|
||||
double angle = radAngle * (180 / 3.14159);
|
||||
if (abs(angle) >= 82.5) {
|
||||
// make it vertical
|
||||
m_lastPoint.x = m_firstPoint.x;
|
||||
} else if (abs(angle) < 7.5) {
|
||||
// make it horizontal
|
||||
m_lastPoint.y = m_firstPoint.y;
|
||||
} else {
|
||||
double xDistance = m_lastPoint.x - m_firstPoint.x;
|
||||
double yDistance = m_lastPoint.y - m_firstPoint.y;
|
||||
|
||||
double totalDistance =
|
||||
std::sqrt(std::pow(xDistance, 2) + std::pow(yDistance, 2));
|
||||
double xLength = 0.0;
|
||||
double yLength = 0.0;
|
||||
if (angle >= 7.5 && angle < 22.5) {
|
||||
yLength = std::sin(15 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(15 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 22.5 && angle < 37.5) {
|
||||
yLength = std::sin(30 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(30 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 37.5 && angle < 52.5) {
|
||||
yLength = std::sin(45 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(45 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 52.5 && angle < 67.5) {
|
||||
yLength = std::sin(60 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(60 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 67.5 && angle < 82.5) {
|
||||
yLength = std::sin(75 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(75 * (3.14159 / 180)) * totalDistance;
|
||||
}
|
||||
|
||||
if (yDistance == abs(yDistance)) {
|
||||
m_lastPoint.y = m_firstPoint.y + yLength;
|
||||
} else {
|
||||
m_lastPoint.y = m_firstPoint.y - yLength;
|
||||
}
|
||||
if (xDistance == abs(xDistance)) {
|
||||
m_lastPoint.x = m_firstPoint.x + xLength;
|
||||
} else {
|
||||
m_lastPoint.x = m_firstPoint.x - xLength;
|
||||
for (int i = 0; i < anglesToAssistants.size(); i++) {
|
||||
double newDifference = abs(angle - anglesToAssistants.at(i));
|
||||
if (newDifference < difference || (180 - newDifference) < difference) {
|
||||
difference = std::min(newDifference, (180 - newDifference));
|
||||
pointToUse = perspectiveObjs.at(i)->getReferencePoint(refPoint);
|
||||
pointToUse.x /= dpiScale.x;
|
||||
pointToUse.y /= dpiScale.y;
|
||||
m_perspectiveIndex = i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pointToUse =
|
||||
perspectiveObjs.at(m_perspectiveIndex)->getReferencePoint(refPoint);
|
||||
pointToUse.x /= dpiScale.x;
|
||||
pointToUse.y /= dpiScale.y;
|
||||
}
|
||||
|
||||
int maxThickness = m_rasThickness.getValue().second;
|
||||
double thickness = (m_pressure.getValue())
|
||||
? computeThickness(e.m_pressure, m_rasThickness) * 2
|
||||
: maxThickness;
|
||||
// if (m_dragCount < 3 && !m_isMyPaintStyleSelected && thickness > 0.0) {
|
||||
// if (m_hardness.getValue() == 100 || m_pencil.getValue()) {
|
||||
// std::vector<TThickPoint> sequence =
|
||||
// m_rasterTrack->getPointsSequence();
|
||||
// if (sequence.size() > 0) sequence[0].thick = thickness;
|
||||
// m_rasterTrack->setPointsSequence(sequence);
|
||||
// } else if (m_points.size() > 0) {
|
||||
// m_points[0].thick == thickness;
|
||||
// // below is code to allow variable thickess
|
||||
// // but it causes artifacting at the start of the stroke.
|
||||
// TToonzImageP ti = TImageP(getImage(true));
|
||||
// TPointD rasCenter = ti->getRaster()->getCenterD();
|
||||
// TThickPoint point(getCenteredCursorPos(m_firstPoint) + rasCenter,
|
||||
// thickness);
|
||||
// m_points.push_back(point);
|
||||
// m_bluredBrush->addPoint(point, 1);
|
||||
// DrawOrder drawOrder = (DrawOrder)m_drawOrder.getIndex();
|
||||
double distanceFirstToLast =
|
||||
std::sqrt(std::pow((m_lastPoint.x - m_firstPoint.x), 2) +
|
||||
std::pow((m_lastPoint.y - m_firstPoint.y), 2));
|
||||
double distanceLastToAssistant =
|
||||
std::sqrt(std::pow((pointToUse.x - m_lastPoint.x), 2) +
|
||||
std::pow((pointToUse.y - m_lastPoint.y), 2));
|
||||
double distanceFirstToAssistant =
|
||||
std::sqrt(std::pow((pointToUse.x - m_firstPoint.x), 2) +
|
||||
std::pow((pointToUse.y - m_firstPoint.y), 2));
|
||||
|
||||
// TImageP img = getImage(true);
|
||||
// TToonzImageP ri(img);
|
||||
// m_strokeRect = m_bluredBrush->getBoundFromPoints(m_points);
|
||||
// updateWorkAndBackupRasters(m_strokeRect);
|
||||
// m_tileSaver->save(m_strokeRect);
|
||||
// m_bluredBrush->updateDrawing(ri->getRaster(), m_backupRas,
|
||||
// m_strokeRect,
|
||||
// m_styleId, drawOrder);
|
||||
// m_points.erase(m_points.begin());
|
||||
// }
|
||||
//}
|
||||
if (distanceFirstToAssistant == 0.0) distanceFirstToAssistant = 0.001;
|
||||
|
||||
// if (m_dragCount < 3 && m_isMyPaintStyleSelected) {
|
||||
// TToonzImageP ti = TImageP(getImage(true));
|
||||
// TRasterP ras = ti->getRaster();
|
||||
// TPointD rasCenter = ti->getRaster()->getCenterD();
|
||||
// TPointD point(getCenteredCursorPos(m_firstPoint) + rasCenter);
|
||||
// double pressure =
|
||||
// m_pressure.getValue() && e.isTablet() ? e.m_pressure : 0.5;
|
||||
double ratio = distanceFirstToLast / distanceFirstToAssistant;
|
||||
|
||||
// m_strokeSegmentRect.empty();
|
||||
// m_toonz_brush->strokeTo(point, pressure, restartBrushTimer());
|
||||
// TRect updateRect = m_strokeSegmentRect * ras->getBounds();
|
||||
// if (!updateRect.isEmpty()) {
|
||||
// m_toonz_brush->updateDrawing(ras, m_backupRas, m_strokeSegmentRect,
|
||||
// m_styleId);
|
||||
// }
|
||||
// m_lastRect = m_strokeRect;
|
||||
double newX;
|
||||
double newY;
|
||||
|
||||
// TPointD thickOffset(m_maxCursorThick * 0.5, m_maxCursorThick * 0.5);
|
||||
// invalidateRect = convert(m_strokeSegmentRect) - rasCenter;
|
||||
// invalidateRect +=
|
||||
// TRectD(getCenteredCursorPos(m_firstPoint) - thickOffset,
|
||||
// getCenteredCursorPos(m_firstPoint) + thickOffset);
|
||||
// invalidateRect +=
|
||||
// TRectD(m_brushPos - thickOffset, m_brushPos + thickOffset);
|
||||
//}
|
||||
// flip the direction if the last point is farther than the first point
|
||||
if (distanceFirstToAssistant < distanceLastToAssistant &&
|
||||
distanceFirstToLast < distanceLastToAssistant) {
|
||||
newX = ((1 + ratio) * m_firstPoint.x) - (ratio * pointToUse.x);
|
||||
newY = ((1 + ratio) * m_firstPoint.y) - (ratio * pointToUse.y);
|
||||
} else {
|
||||
newX = ((1 - ratio) * m_firstPoint.x) + (ratio * pointToUse.x);
|
||||
newY = ((1 - ratio) * m_firstPoint.y) + (ratio * pointToUse.y);
|
||||
}
|
||||
|
||||
// m_oldThickness = thickness;
|
||||
// double pressure =
|
||||
// m_pressure.getValue() && e.isTablet() ? e.m_pressure : 0.5;
|
||||
// m_oldPressure = pressure;
|
||||
usePos = m_lastPoint = TPointD(newX, newY);
|
||||
invalidateRect += TRectD(m_firstPoint, m_lastPoint).enlarge(2);
|
||||
} else if (e.isCtrlPressed()) {
|
||||
double distance = (m_brushPos.x - m_maxCursorThick + 1) * 0.5;
|
||||
TRectD brushRect =
|
||||
TRectD(TPointD(m_brushPos.x - distance, m_brushPos.y - distance),
|
||||
TPointD(m_brushPos.x + distance, m_brushPos.y + distance));
|
||||
invalidateRect += (brushRect);
|
||||
|
||||
// m_dragCount++;
|
||||
double denominator = m_lastPoint.x - m_firstPoint.x;
|
||||
if (denominator == 0) denominator == 0.001;
|
||||
double slope = ((m_lastPoint.y - m_firstPoint.y) / denominator);
|
||||
double radAngle = std::atan(abs(slope));
|
||||
double angle = radAngle * (180 / 3.14159);
|
||||
if (abs(angle) >= 82.5) {
|
||||
// make it vertical
|
||||
m_lastPoint.x = m_firstPoint.x;
|
||||
} else if (abs(angle) < 7.5) {
|
||||
// make it horizontal
|
||||
m_lastPoint.y = m_firstPoint.y;
|
||||
} else {
|
||||
double xDistance = m_lastPoint.x - m_firstPoint.x;
|
||||
double yDistance = m_lastPoint.y - m_firstPoint.y;
|
||||
|
||||
double totalDistance =
|
||||
std::sqrt(std::pow(xDistance, 2) + std::pow(yDistance, 2));
|
||||
double xLength = 0.0;
|
||||
double yLength = 0.0;
|
||||
if (angle >= 7.5 && angle < 22.5) {
|
||||
yLength = std::sin(15 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(15 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 22.5 && angle < 37.5) {
|
||||
yLength = std::sin(30 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(30 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 37.5 && angle < 52.5) {
|
||||
yLength = std::sin(45 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(45 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 52.5 && angle < 67.5) {
|
||||
yLength = std::sin(60 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(60 * (3.14159 / 180)) * totalDistance;
|
||||
} else if (angle >= 67.5 && angle < 82.5) {
|
||||
yLength = std::sin(75 * (3.14159 / 180)) * totalDistance;
|
||||
xLength = std::cos(75 * (3.14159 / 180)) * totalDistance;
|
||||
}
|
||||
|
||||
if (yDistance == abs(yDistance)) {
|
||||
m_lastPoint.y = m_firstPoint.y + yLength;
|
||||
} else {
|
||||
m_lastPoint.y = m_firstPoint.y - yLength;
|
||||
}
|
||||
if (xDistance == abs(xDistance)) {
|
||||
m_lastPoint.x = m_firstPoint.x + xLength;
|
||||
} else {
|
||||
m_lastPoint.x = m_firstPoint.x - xLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (m_dragCount < 3 && !m_isMyPaintStyleSelected && thickness > 0.0) {
|
||||
// if (m_hardness.getValue() == 100 || m_pencil.getValue()) {
|
||||
// std::vector<TThickPoint> sequence =
|
||||
// m_rasterTrack->getPointsSequence();
|
||||
// if (sequence.size() > 0) sequence[0].thick = thickness;
|
||||
// m_rasterTrack->setPointsSequence(sequence);
|
||||
// } else if (m_points.size() > 0) {
|
||||
// m_points[0].thick == thickness;
|
||||
// // below is code to allow variable thickess
|
||||
// // but it causes artifacting at the start of the stroke.
|
||||
// TToonzImageP ti = TImageP(getImage(true));
|
||||
// TPointD rasCenter = ti->getRaster()->getCenterD();
|
||||
// TThickPoint point(getCenteredCursorPos(m_firstPoint) + rasCenter,
|
||||
// thickness);
|
||||
// m_points.push_back(point);
|
||||
// m_bluredBrush->addPoint(point, 1);
|
||||
// DrawOrder drawOrder = (DrawOrder)m_drawOrder.getIndex();
|
||||
|
||||
// TImageP img = getImage(true);
|
||||
// TToonzImageP ri(img);
|
||||
// m_strokeRect = m_bluredBrush->getBoundFromPoints(m_points);
|
||||
// updateWorkAndBackupRasters(m_strokeRect);
|
||||
// m_tileSaver->save(m_strokeRect);
|
||||
// m_bluredBrush->updateDrawing(ri->getRaster(), m_backupRas,
|
||||
// m_strokeRect,
|
||||
// m_styleId, drawOrder);
|
||||
// m_points.erase(m_points.begin());
|
||||
// }
|
||||
//}
|
||||
|
||||
// if (m_dragCount < 3 && m_isMyPaintStyleSelected) {
|
||||
// TToonzImageP ti = TImageP(getImage(true));
|
||||
// TRasterP ras = ti->getRaster();
|
||||
// TPointD rasCenter = ti->getRaster()->getCenterD();
|
||||
// TPointD point(getCenteredCursorPos(m_firstPoint) + rasCenter);
|
||||
// double pressure =
|
||||
// m_pressure.getValue() && e.isTablet() ? e.m_pressure : 0.5;
|
||||
|
||||
// m_strokeSegmentRect.empty();
|
||||
// m_toonz_brush->strokeTo(point, pressure, restartBrushTimer());
|
||||
// TRect updateRect = m_strokeSegmentRect * ras->getBounds();
|
||||
// if (!updateRect.isEmpty()) {
|
||||
// m_toonz_brush->updateDrawing(ras, m_backupRas, m_strokeSegmentRect,
|
||||
// m_styleId);
|
||||
// }
|
||||
// m_lastRect = m_strokeRect;
|
||||
|
||||
// TPointD thickOffset(m_maxCursorThick * 0.5, m_maxCursorThick * 0.5);
|
||||
// invalidateRect = convert(m_strokeSegmentRect) - rasCenter;
|
||||
// invalidateRect +=
|
||||
// TRectD(getCenteredCursorPos(m_firstPoint) - thickOffset,
|
||||
// getCenteredCursorPos(m_firstPoint) + thickOffset);
|
||||
// invalidateRect +=
|
||||
// TRectD(m_brushPos - thickOffset, m_brushPos + thickOffset);
|
||||
//}
|
||||
|
||||
// m_oldThickness = thickness;
|
||||
// double pressure =
|
||||
// m_pressure.getValue() && e.isTablet() ? e.m_pressure : 0.5;
|
||||
// m_oldPressure = pressure;
|
||||
|
||||
// m_dragCount++;
|
||||
|
||||
if (m_isStraight) {
|
||||
m_mousePos = pos;
|
||||
m_brushPos = getCenteredCursorPos(pos);
|
||||
invalidate(invalidateRect);
|
||||
return;
|
||||
}
|
||||
|
||||
TPointD centeredPos = getCenteredCursorPos(pos);
|
||||
TPointD centeredPos = getCenteredCursorPos(usePos);
|
||||
|
||||
TToonzImageP ti = TImageP(getImage(true));
|
||||
TPointD rasCenter = ti->getRaster()->getCenterD();
|
||||
|
@ -1819,7 +1832,7 @@ void ToonzRasterBrushTool::leftButtonUp(const TPointD &pos,
|
|||
return;
|
||||
}
|
||||
TPointD centeredPos = getCenteredCursorPos(pos);
|
||||
if (e.isCtrlPressed() || m_snapAssistant || e.isAltPressed())
|
||||
if (e.isCtrlPressed() || m_snapGrid.getValue() || e.isAltPressed())
|
||||
centeredPos = getCenteredCursorPos(m_lastPoint);
|
||||
double pressure = m_pressure.getValue() && e.isTablet() ? e.m_pressure : 0.5;
|
||||
// if (!e.isTablet()) m_oldThickness = -1.0;
|
||||
|
@ -1828,6 +1841,7 @@ void ToonzRasterBrushTool::leftButtonUp(const TPointD &pos,
|
|||
finishRasterBrush(centeredPos, pressure);
|
||||
int tc = ToonzCheck::instance()->getChecks();
|
||||
if (tc & ToonzCheck::eGap || tc & ToonzCheck::eAutoclose) invalidate();
|
||||
m_perspectiveIndex = -1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
|
@ -2069,7 +2083,6 @@ void ToonzRasterBrushTool::finishRasterBrush(const TPointD &pos,
|
|||
}
|
||||
delete m_tileSaver;
|
||||
m_isStraight = false;
|
||||
m_snapAssistant = false;
|
||||
m_oldPressure = -1.0;
|
||||
// m_oldThickness = -1.0;
|
||||
// m_dragCount = 0;
|
||||
|
@ -2321,6 +2334,7 @@ bool ToonzRasterBrushTool::onPropertyChanged(std::string propertyName) {
|
|||
RasterBrushHardness = m_hardness.getValue();
|
||||
RasterBrushModifierSize = m_modifierSize.getValue();
|
||||
BrushLockAlpha = m_modifierLockAlpha.getValue();
|
||||
BrushSnapGrid = m_snapGrid.getValue();
|
||||
|
||||
// Recalculate/reset based on changed settings
|
||||
if (propertyName == m_rasThickness.getName()) {
|
||||
|
@ -2459,6 +2473,7 @@ void ToonzRasterBrushTool::loadLastBrush() {
|
|||
m_smooth.setValue(BrushSmooth);
|
||||
m_modifierSize.setValue(RasterBrushModifierSize);
|
||||
m_modifierLockAlpha.setValue(BrushLockAlpha ? 1 : 0);
|
||||
m_snapGrid.setValue(BrushSnapGrid ? 1 : 0);
|
||||
|
||||
// Recalculate based on prior values
|
||||
m_minThick = m_rasThickness.getValue().first;
|
||||
|
|
|
@ -183,6 +183,7 @@ protected:
|
|||
TBoolProperty m_pressure;
|
||||
TDoubleProperty m_modifierSize;
|
||||
TBoolProperty m_modifierLockAlpha;
|
||||
TBoolProperty m_snapGrid;
|
||||
|
||||
RasterStrokeGenerator *m_rasterTrack;
|
||||
TTileSetCM32 *m_tileSet;
|
||||
|
@ -230,13 +231,14 @@ protected:
|
|||
bool m_propertyUpdating = false;
|
||||
|
||||
bool m_isStraight = false;
|
||||
bool m_snapAssistant = false;
|
||||
TPointD m_firstPoint;
|
||||
TPointD m_lastPoint;
|
||||
double m_oldPressure = -1.0;
|
||||
// double m_oldThickness = -1.0;
|
||||
// int m_dragCount = 0;
|
||||
|
||||
int m_perspectiveIndex = -1;
|
||||
|
||||
protected:
|
||||
static void drawLine(const TPointD &point, const TPointD ¢re,
|
||||
bool horizontal, bool isDecimal);
|
||||
|
|
|
@ -71,6 +71,7 @@ TEnv::IntVar V_VectorBrushAutoClose("VectorBrushAutoClose", 0);
|
|||
TEnv::IntVar V_VectorBrushAutoFill("VectorBrushAutoFill", 0);
|
||||
TEnv::IntVar V_VectorBrushAutoGroup("VectorBrushAutoGroup", 0);
|
||||
TEnv::StringVar V_VectorBrushPreset("VectorBrushPreset", "<custom>");
|
||||
TEnv::IntVar V_VectorBrushSnapGrid("VectorBrushSnapGrid", 0);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
|
@ -535,7 +536,8 @@ ToonzVectorBrushTool::ToonzVectorBrushTool(std::string name, int targetType)
|
|||
, m_autoGroup("Auto Group", false)
|
||||
, m_autoFill("Auto Fill", false)
|
||||
, m_targetType(targetType)
|
||||
, m_workingFrameId(TFrameId()) {
|
||||
, m_workingFrameId(TFrameId())
|
||||
, m_snapGrid("Grid", false) {
|
||||
bind(targetType);
|
||||
|
||||
m_thickness.setNonLinearSlider();
|
||||
|
@ -572,6 +574,8 @@ ToonzVectorBrushTool::ToonzVectorBrushTool(std::string name, int targetType)
|
|||
m_snapSensitivity.addValue(MEDIUM_WSTR);
|
||||
m_snapSensitivity.addValue(HIGH_WSTR);
|
||||
|
||||
m_prop[0].bind(m_snapGrid);
|
||||
|
||||
m_prop[0].bind(m_preset);
|
||||
m_preset.addValue(CUSTOM_WSTR);
|
||||
|
||||
|
@ -597,6 +601,7 @@ ToonzVectorBrushTool::ToonzVectorBrushTool(std::string name, int targetType)
|
|||
m_capStyle.setId("Cap");
|
||||
m_joinStyle.setId("Join");
|
||||
m_miterJoinLimit.setId("Miter");
|
||||
m_snapGrid.setId("SnapGrid");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
|
@ -777,6 +782,7 @@ void ToonzVectorBrushTool::leftButtonDown(const TPointD &pos,
|
|||
|
||||
// updating m_brushPos is needed to refresh viewer properly
|
||||
m_brushPos = m_mousePos = pos;
|
||||
m_perspectiveIndex = -1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
|
@ -792,42 +798,44 @@ void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos,
|
|||
|
||||
m_lastPoint = pos;
|
||||
bool nonShiftStraight = false;
|
||||
TPointD usePos = pos;
|
||||
|
||||
if (!m_isPath &&
|
||||
(e.isAltPressed() && !e.isCtrlPressed() && !e.isShiftPressed())) {
|
||||
((e.isAltPressed() && !e.isCtrlPressed() && !e.isShiftPressed()) ||
|
||||
m_snapGrid.getValue())) {
|
||||
invalidateRect = TRectD(m_firstPoint, m_lastPoint).enlarge(2);
|
||||
nonShiftStraight = true;
|
||||
if (!m_snapGrid.getValue()) nonShiftStraight = true;
|
||||
double distance = (m_brushPos.x) * 0.5;
|
||||
TRectD brushRect =
|
||||
TRectD(TPointD(m_brushPos.x - distance, m_brushPos.y - distance),
|
||||
TPointD(m_brushPos.x + distance, m_brushPos.y + distance));
|
||||
invalidateRect += (brushRect);
|
||||
|
||||
// let's get info about our current location
|
||||
double denominator = m_lastPoint.x - m_firstPoint.x;
|
||||
double numerator = m_lastPoint.y - m_firstPoint.y;
|
||||
if (areAlmostEqual(denominator, 0.0, 0.0001)) {
|
||||
denominator = denominator < 0 ? -0.0001 : 0.0001;
|
||||
}
|
||||
if (areAlmostEqual(numerator, 0.0, 0.0001)) {
|
||||
numerator = numerator < 0 ? -0.0001 : 0.0001;
|
||||
}
|
||||
double slope = (numerator / denominator);
|
||||
double angle = std::atan(slope) * (180 / 3.14159);
|
||||
|
||||
// now let's get the angle of each of the assistant points
|
||||
std::vector<double> anglesToAssistants;
|
||||
TPointD pointToUse = TPointD(0.0, 0.0);
|
||||
|
||||
PerspectiveTool *perspectiveTool = dynamic_cast<PerspectiveTool *>(
|
||||
TTool::getTool("T_PerspectiveGrid", TTool::VectorImage));
|
||||
if (perspectiveTool) {
|
||||
TPointD dpiScale = getViewer()->getDpiScale();
|
||||
TPointD refPoint = m_firstPoint;
|
||||
refPoint.x *= dpiScale.x;
|
||||
refPoint.y *= dpiScale.y;
|
||||
std::vector<PerspectiveObject *> perspectiveObjs =
|
||||
perspectiveTool->getPerspectiveObjects();
|
||||
TPointD pointToUse = TPointD(0.0, 0.0);
|
||||
TPointD dpiScale = getViewer()->getDpiScale();
|
||||
TPointD refPoint = m_firstPoint;
|
||||
refPoint.x *= dpiScale.x;
|
||||
refPoint.y *= dpiScale.y;
|
||||
if ((e.isAltPressed() && !e.isCtrlPressed() && !e.isShiftPressed()) ||
|
||||
m_perspectiveIndex < 0) {
|
||||
// let's get info about our current location
|
||||
double denominator = m_lastPoint.x - m_firstPoint.x;
|
||||
double numerator = m_lastPoint.y - m_firstPoint.y;
|
||||
if (areAlmostEqual(denominator, 0.0, 0.0001)) {
|
||||
denominator = denominator < 0 ? -0.0001 : 0.0001;
|
||||
}
|
||||
if (areAlmostEqual(numerator, 0.0, 0.0001)) {
|
||||
numerator = numerator < 0 ? -0.0001 : 0.0001;
|
||||
}
|
||||
double slope = (numerator / denominator);
|
||||
double angle = std::atan(slope) * (180 / 3.14159);
|
||||
|
||||
std::vector<PerspectiveObject *> perspectiveObjs =
|
||||
perspectiveTool->getPerspectiveObjects();
|
||||
// now let's get the angle of each of the assistant points
|
||||
std::vector<double> anglesToAssistants;
|
||||
for (auto data : perspectiveObjs) {
|
||||
TPointD point = data->getReferencePoint(refPoint);
|
||||
point.x /= dpiScale.x;
|
||||
|
@ -856,8 +864,14 @@ void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos,
|
|||
pointToUse = perspectiveObjs.at(i)->getReferencePoint(refPoint);
|
||||
pointToUse.x /= dpiScale.x;
|
||||
pointToUse.y /= dpiScale.y;
|
||||
m_perspectiveIndex = i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pointToUse =
|
||||
perspectiveObjs.at(m_perspectiveIndex)->getReferencePoint(refPoint);
|
||||
pointToUse.x /= dpiScale.x;
|
||||
pointToUse.y /= dpiScale.y;
|
||||
}
|
||||
|
||||
double distanceFirstToLast =
|
||||
|
@ -887,7 +901,7 @@ void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos,
|
|||
newY = ((1 - ratio) * m_firstPoint.y) + (ratio * pointToUse.y);
|
||||
}
|
||||
|
||||
m_lastPoint = TPointD(newX, newY);
|
||||
usePos = m_lastPoint = TPointD(newX, newY);
|
||||
invalidateRect += TRectD(m_firstPoint, m_lastPoint).enlarge(2);
|
||||
} else if (e.isCtrlPressed() && !e.isAltPressed() && !e.isShiftPressed()) {
|
||||
invalidateRect = TRectD(m_firstPoint, m_lastPoint).enlarge(2);
|
||||
|
@ -947,7 +961,7 @@ void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos,
|
|||
}
|
||||
}
|
||||
|
||||
m_lastDragPos = pos;
|
||||
m_lastDragPos = usePos;
|
||||
m_lastDragEvent = e;
|
||||
|
||||
double thickness = (m_pressure.getValue() || m_isPath)
|
||||
|
@ -994,7 +1008,8 @@ void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos,
|
|||
m_track.removeMiddlePoints();
|
||||
invalidateRect += m_track.getModifiedRegion();
|
||||
} else if (m_dragDraw) {
|
||||
addTrackPoint(TThickPoint(pos, thickness), getPixelSize() * getPixelSize());
|
||||
addTrackPoint(TThickPoint(usePos, thickness),
|
||||
getPixelSize() * getPixelSize());
|
||||
invalidateRect += m_track.getLastModifiedRegion();
|
||||
}
|
||||
|
||||
|
@ -1076,6 +1091,7 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos,
|
|||
notifyImageChanged();
|
||||
TUndoManager::manager()->add(undo);
|
||||
|
||||
m_perspectiveIndex = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1083,7 +1099,7 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos,
|
|||
if (m_track.isEmpty()) {
|
||||
m_styleId = 0;
|
||||
m_track.clear();
|
||||
|
||||
m_perspectiveIndex = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1237,6 +1253,7 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos,
|
|||
assert(stroke);
|
||||
m_track.clear();
|
||||
m_toggleSnap = false;
|
||||
m_perspectiveIndex = -1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -1891,6 +1908,7 @@ bool ToonzVectorBrushTool::onPropertyChanged(std::string propertyName) {
|
|||
V_VectorBrushSnap = m_snap.getValue();
|
||||
int snapSensitivityIndex = m_snapSensitivity.getIndex();
|
||||
V_VectorBrushSnapSensitivity = snapSensitivityIndex;
|
||||
V_VectorBrushSnapGrid = m_snapGrid.getValue();
|
||||
|
||||
// Recalculate/reset based on changed settings
|
||||
m_minThick = m_thickness.getValue().first;
|
||||
|
@ -2067,6 +2085,7 @@ void ToonzVectorBrushTool::loadLastBrush() {
|
|||
m_autoGroup.setValue(V_VectorBrushAutoGroup);
|
||||
m_autoClose.setValue(V_VectorBrushAutoClose);
|
||||
m_autoFill.setValue(V_VectorBrushAutoFill);
|
||||
m_snapGrid.setValue(V_VectorBrushSnapGrid);
|
||||
|
||||
// Recalculate based on prior values
|
||||
m_minThick = m_thickness.getValue().first;
|
||||
|
|
|
@ -163,6 +163,7 @@ protected:
|
|||
TEnumProperty m_capStyle;
|
||||
TEnumProperty m_joinStyle;
|
||||
TIntProperty m_miterJoinLimit;
|
||||
TBoolProperty m_snapGrid;
|
||||
|
||||
StrokeGenerator m_track;
|
||||
StrokeGenerator m_rangeTrack;
|
||||
|
@ -215,6 +216,8 @@ protected:
|
|||
|
||||
TPointD m_firstPoint;
|
||||
TPointD m_lastPoint;
|
||||
|
||||
int m_perspectiveIndex = -1;
|
||||
};
|
||||
|
||||
#endif // TOONZVECTORBRUSHTOOL_H
|
||||
|
|
Loading…
Reference in a new issue