Merge pull request #835 from manongjohn/perspective_grid_tool

Perspective Grid Tool
This commit is contained in:
manongjohn 2021-12-03 07:49:46 -05:00 committed by GitHub
commit ed5ae868ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 3896 additions and 1257 deletions

View file

@ -94,6 +94,7 @@ public:
void visit(TIntPairProperty *dst) override { assign(dst, m_src); }
void visit(TStyleIndexProperty *dst) override { assign(dst, m_src); }
void visit(TPointerProperty *dst) override { assign(dst, m_src); }
void visit(TColorChipProperty *dst) override { assign(dst, m_src); }
};
void TPropertyGroup::setProperties(TPropertyGroup *g) {
@ -208,6 +209,14 @@ public:
attr["value"] = p->getValueAsString();
m_os.openCloseChild("property", attr);
}
void visit(TColorChipProperty *p) override {
std::map<std::string, std::string> attr;
attr["type"] = "string";
attr["name"] = p->getName();
attr["value"] = ::to_string(p->getValue());
m_os.openCloseChild("property", attr);
}
};
void TPropertyGroup::loadData(TIStream &is) {
@ -306,3 +315,14 @@ void TEnumProperty::assignUIName(TProperty *refP) {
if (0 <= refIndex) m_items[i].UIName = refItems[refIndex].UIName;
}
}
void TColorChipProperty::assignUIName(TProperty *refP) {
setQStringName(refP->getQStringName());
TColorChipProperty *colorChipRefP = dynamic_cast<TColorChipProperty *>(refP);
if (!colorChipRefP) return;
ColorChips refChips = colorChipRefP->getColorChips();
for (int i = 0; i < m_chips.size(); i++) {
int refIndex = colorChipRefP->indexOf(m_chips[i].UIName.toStdWString());
if (0 <= refIndex) m_chips[i].UIName = refChips[refIndex].UIName;
}
}

View file

@ -20,7 +20,8 @@ enum {
Schematic,
Palette,
Xsheet,
FilmStrip
FilmStrip,
PerspectiveGridTool
};
}

View file

@ -58,6 +58,8 @@ class TFxHandle;
class ToolOptionsBox;
class SceneViewer;
class QMenu;
class QKeyEvent;
@ -415,6 +417,10 @@ return true if the method execution can have changed the current tool
virtual void draw() {} //!< Draws the tool on the viewer.
// Needed in case the tool wants the current SceneViewer
// as in the case of the PerspectiveTool
virtual void draw(SceneViewer *viewer) {}
bool isActive() const {
return m_active;
} //!< Used to know if a tool is active, (used in TextTool only).
@ -532,6 +538,9 @@ transformation.
virtual bool isMyPaintStyleSelected() { return false; }
virtual void saveTool(){};
virtual void loadTool(){};
public:
struct CellOps {
int r0;

View file

@ -29,6 +29,7 @@
#define T_Rotate "T_Rotate"
#define T_Hand "T_Hand"
#define T_Ruler "T_Ruler"
#define T_PerspectiveGrid "T_PerspectiveGrid"
#define T_Finger "T_Finger"
#endif // TOOL_COMMAND_IDS_H

View file

@ -12,6 +12,7 @@
// TnzCore includes
#include "tcommon.h"
#include "tproperty.h"
#include "tunit.h"
// Qt includes
#include <QFrame>
@ -67,6 +68,7 @@ class MeasuredValueField;
class PaletteController;
class ClickableLabel;
class StyleIndexFieldAndChip;
class ColorChipCombo;
class QLabel;
class QPushButton;
@ -164,6 +166,7 @@ private:
void visit(TEnumProperty *p) override;
void visit(TStyleIndexProperty *p) override;
void visit(TPointerProperty *p) override;
void visit(TColorChipProperty *p) override;
};
//***********************************************************************************************
@ -739,6 +742,53 @@ protected slots:
void updateColors();
};
//=============================================================================
//
// PerspectiveToolOptionBox
// shown only when "Edit Perspective" mode is active
//
//=============================================================================
class PerspectiveGridToolOptionBox final : public ToolOptionsBox {
Q_OBJECT
TTool *m_tool;
ToolOptionCombo *m_perspectiveType;
ToolOptionSlider *m_opacity;
ColorChipCombo *m_color;
ToolOptionCheckbox *m_horizon, *m_parallel, *m_advancedControls;
ClickableLabel *m_rotationLabel, *m_spacingLabel;
MeasuredValueField *m_rotation, *m_spacing;
ToolOptionCombo *m_presetCombo;
QPushButton *m_addPresetButton, *m_removePresetButton, *m_leftRotateButton,
*m_rightRotateButton;
private:
class PresetNamePopup;
PresetNamePopup *m_presetNamePopup;
void filterControls();
public:
PerspectiveGridToolOptionBox(QWidget *parent, TTool *tool,
TPaletteHandle *pltHandle,
ToolHandle *toolHandle);
void updateStatus();
void updateMeasuredValues(double spacing, double rotation);
void reloadPresetCombo();
protected slots:
void onAddPreset();
void onRemovePreset();
void onPerspectiveTypeChanged(int);
void onSpacingChange(TMeasuredValue *fld);
void onRotationChange(TMeasuredValue *fld);
void onRotateLeft();
void onRotateRight();
};
//=============================================================================
//
// ZoomToolOptionsBox

View file

@ -4,6 +4,7 @@
#define TPROPERTY_INCLUDED
#include "tconvert.h"
#include "tpixel.h"
#include <cstdint>
@ -36,6 +37,7 @@ class DVAPI TDoublePairProperty;
class DVAPI TIntPairProperty;
class DVAPI TStyleIndexProperty;
class DVAPI TPointerProperty;
class DVAPI TColorChipProperty;
class TIStream;
class TOStream;
@ -55,6 +57,7 @@ public:
virtual void visit(TIntPairProperty *p) = 0;
virtual void visit(TStyleIndexProperty *p) = 0;
virtual void visit(TPointerProperty *p) = 0;
virtual void visit(TColorChipProperty *p) = 0;
virtual ~Visitor() {}
};
@ -428,6 +431,102 @@ private:
//---------------------------------------------------------
class DVAPI TColorChipProperty final : public TProperty {
public:
struct ColorChip {
QString UIName;
TPixel32 pixelColor;
ColorChip(const QString &name = QString(),
const TPixel32 &color = TPixel32(0, 0, 0))
: UIName(name), pixelColor(color) {}
};
typedef std::vector<ColorChip> ColorChips;
TColorChipProperty(const std::string &name) : TProperty(name), m_index(-1) {}
TProperty *clone() const override { return new TColorChipProperty(*this); }
int indexOf(const std::wstring &value) {
ColorChips::const_iterator it;
for (it = m_chips.begin(); it != m_chips.end(); it++) {
ColorChip chip = *it;
if (chip.UIName == QString::fromStdWString(value)) break;
}
return (it == m_chips.end()) ? -1 : it - m_chips.begin();
}
int indexOf(TPixel32 color) {
ColorChips::const_iterator it;
for (it = m_chips.begin(); it != m_chips.end(); it++) {
ColorChip chip = *it;
if (chip.pixelColor == color) break;
}
return (it == m_chips.end()) ? -1 : it - m_chips.begin();
}
bool isValue(const std::wstring &value) { return (indexOf(value) != -1); }
void addValue(std::wstring value, const TPixel32 &color) {
if (m_index == -1) m_index = 0;
m_chips.push_back(ColorChip(QString::fromStdWString(value), color));
}
void setItemUIName(std::wstring value, const QString &name) {
int index = indexOf(value);
if (index < 0 || index >= (int)m_chips.size()) throw RangeError();
m_chips[index].UIName = name;
}
void deleteAllValues() {
m_chips.clear();
m_index = -1;
}
void setIndex(int index) {
if (index < 0 || index >= (int)m_chips.size()) throw RangeError();
m_index = index;
}
void setValue(const std::wstring &value) {
int idx = indexOf(value);
if (idx < 0) throw RangeError();
m_index = idx;
}
void setColor(TPixel32 color) {
int idx = indexOf(color);
if (idx < 0) throw RangeError();
m_index = idx;
}
int getCount() const { return (int)m_chips.size(); }
const ColorChips &getColorChips() const { return m_chips; }
std::wstring getValue() const {
return (m_index < 0) ? L"" : m_chips[m_index].UIName.toStdWString();
}
std::string getValueAsString() override {
return (m_index < 0) ? "" : m_chips[m_index].UIName.toStdString();
}
TPixel32 getColorValue() const {
return (m_index < 0) ? TPixel32(0, 0, 0) : m_chips[m_index].pixelColor;
}
int getIndex() const { return m_index; }
void accept(Visitor &v) override { v.visit(this); }
void assignUIName(TProperty *refP) override;
private:
ColorChips m_chips;
int m_index;
};
//---------------------------------------------------------
class DVAPI TPropertyGroup {
public:
typedef std::vector<std::pair<TProperty *, bool>> PropertyVector;

View file

@ -33,6 +33,7 @@ set(HEADERS
stylepickertool.h
toonzvectorbrushtool.h
vectorselectiontool.h
perspectivetool.h
../include/tools/RGBpicker.h
../include/tools/cursormanager.h
../include/tools/cursors.h
@ -104,6 +105,7 @@ set(SOURCES
rulertool.cpp
mypainttoonzbrush.cpp
shifttracetool.cpp
perspectivetool.cpp
toonzrasterbrushtool.cpp
toonzvectorbrushtool.cpp
)

View file

@ -42,6 +42,8 @@
#include "tpixelutils.h"
#include "tsystem.h"
#include "perspectivetool.h"
// Qt includes
#include <QCoreApplication> // Qt translation support
@ -58,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);
//----------------------------------------------------------------------------------
@ -133,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();
@ -146,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();
}
@ -190,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"));
}
//---------------------------------------------------------------------------------------------------
@ -327,43 +334,6 @@ void FullColorBrushTool::leftButtonDown(const TPointD &pos,
return;
}
TXshSimpleLevelP simLevel = level->getSimpleLevel();
m_assistantPoints = simLevel->getProperties()->getVanishingPoints();
if (e.isAltPressed() && e.isCtrlPressed() && !e.isShiftPressed()) {
m_addingAssistant = true;
bool deletedPoint = false;
for (int i = 0; i < m_assistantPoints.size(); i++) {
if (areAlmostEqual(m_assistantPoints.at(i).x, pos.x, 12) &&
areAlmostEqual(m_assistantPoints.at(i).y, pos.y, 12)) {
TRectD pointRect = TRectD(
m_assistantPoints.at(i).x - 15, m_assistantPoints.at(i).y - 15,
m_assistantPoints.at(i).x + 15, m_assistantPoints.at(i).x + 15);
m_assistantPoints.erase(m_assistantPoints.begin() + i);
deletedPoint = true;
invalidate(pointRect);
break;
}
}
if (!deletedPoint) m_assistantPoints.push_back(pos);
simLevel->getProperties()->setVanishingPoints(m_assistantPoints);
level->setDirtyFlag(true);
invalidate();
return;
}
if (e.isAltPressed() && e.isShiftPressed() && !e.isCtrlPressed()) {
m_addingAssistant = true;
std::vector<TPointD> pointsToClear = m_assistantPoints;
m_assistantPoints.clear();
for (auto point : pointsToClear) {
TRectD pointRect =
TRectD(point.x - 3, point.y - 3, point.x + 3, point.y + 3);
invalidate(pointRect);
}
return;
}
if ((e.isShiftPressed() || e.isCtrlPressed()) && !e.isAltPressed()) {
m_isStraight = true;
m_firstPoint = pos;
@ -371,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();
@ -419,27 +393,35 @@ void FullColorBrushTool::leftButtonDown(const TPointD &pos,
invalidateRect +=
TRectD(previousBrushPos - thickOffset, previousBrushPos + thickOffset);
invalidate(invalidateRect.enlarge(2.0));
m_perspectiveIndex = -1;
}
//-------------------------------------------------------------------------------------------------------------
void FullColorBrushTool::leftButtonDrag(const TPointD &pos,
const TMouseEvent &e) {
if ((e.isCtrlPressed() && e.isAltPressed()) ||
(e.isShiftPressed() && e.isAltPressed()) || m_addingAssistant) {
return;
}
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;
@ -454,7 +436,10 @@ void FullColorBrushTool::leftButtonDrag(const TPointD &pos,
// now let's get the angle of each of the assistant points
std::vector<double> anglesToAssistants;
for (auto point : m_assistantPoints) {
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)) {
@ -470,105 +455,115 @@ void FullColorBrushTool::leftButtonDrag(const TPointD &pos,
}
// figure out which angle is closer
TPointD pointToUse = TPointD(0.0, 0.0);
double difference = 360;
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 = m_assistantPoints.at(i);
}
}
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);
}
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;
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);
@ -585,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
@ -614,12 +609,6 @@ void FullColorBrushTool::leftButtonUp(const TPointD &pos,
TPointD previousBrushPos = m_brushPos;
m_brushPos = m_mousePos = pos;
if ((e.isAltPressed() && e.isCtrlPressed()) ||
(e.isShiftPressed() && e.isAltPressed()) || m_addingAssistant) {
m_addingAssistant = false;
return;
}
TRasterImageP ri = (TRasterImageP)getImage(true);
if (!ri) return;
@ -628,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);
@ -681,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;
}
//---------------------------------------------------------------------------------------------------------------
@ -744,35 +733,6 @@ void FullColorBrushTool::mouseMove(const TPointD &pos, const TMouseEvent &e) {
m_mousePos = pos;
if (e.isAltPressed() && e.isCtrlPressed() && !e.isShiftPressed()) {
if (m_highlightAssistant != -1 &&
m_highlightAssistant < m_assistantPoints.size()) {
TRectD pointRect =
TRectD(m_assistantPoints.at(m_highlightAssistant).x - 15,
m_assistantPoints.at(m_highlightAssistant).y - 15,
m_assistantPoints.at(m_highlightAssistant).x + 15,
m_assistantPoints.at(m_highlightAssistant).x + 15);
invalidate(pointRect);
}
m_highlightAssistant = -1;
for (int i = 0; i < m_assistantPoints.size(); i++) {
if (areAlmostEqual(m_assistantPoints.at(i).x, pos.x, 12) &&
areAlmostEqual(m_assistantPoints.at(i).y, pos.y, 12)) {
m_highlightAssistant = i;
break;
}
}
} else if (m_highlightAssistant != -1 &&
m_highlightAssistant < m_assistantPoints.size()) {
TRectD pointRect =
TRectD(m_assistantPoints.at(m_highlightAssistant).x - 15,
m_assistantPoints.at(m_highlightAssistant).y - 15,
m_assistantPoints.at(m_highlightAssistant).x + 15,
m_assistantPoints.at(m_highlightAssistant).x + 15);
invalidate(pointRect);
m_highlightAssistant = -1;
}
invalidate();
}
@ -783,21 +743,6 @@ void FullColorBrushTool::draw() {
if (m_isStraight) {
tglDrawSegment(m_firstPoint, m_lastPoint);
}
if (m_assistantPoints.size() > 0) {
for (int i = 0; i < m_assistantPoints.size(); i++) {
if (m_highlightAssistant == i) {
glColor3d(1.0, 0.0, 0.0);
tglDrawDisk(m_assistantPoints.at(i), 15.0);
} else {
glColor3d(0.0, 1.0, 0.0);
tglDrawCircle(m_assistantPoints.at(i), 5.0);
glColor3d(1.0, 1.0, 0.0);
tglDrawCircle(m_assistantPoints.at(i), 8.0);
}
}
}
// If toggled off, don't draw brush outline
if (!Preferences::instance()->isCursorOutlineEnabled()) return;
@ -876,16 +821,6 @@ void FullColorBrushTool::setWorkAndBackupImages() {
m_strokeRect.empty();
m_lastRect.empty();
TXshLevelHandle *level = getApplication()->getCurrentLevel();
TXshSimpleLevel *sl;
if (level) sl = level->getSimpleLevel();
if (sl) {
if (sl->getProperties()->getVanishingPoints() != m_assistantPoints) {
m_assistantPoints = sl->getProperties()->getVanishingPoints();
invalidate();
}
}
}
//------------------------------------------------------------------
@ -918,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);
@ -1032,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);
}
//------------------------------------------------------------------

View file

@ -95,6 +95,7 @@ protected:
TBoolProperty m_modifierEraser;
TBoolProperty m_modifierLockAlpha;
TEnumProperty m_preset;
TBoolProperty m_snapGrid;
TPixel32 m_currentColor;
bool m_enabledPressure;
@ -126,13 +127,11 @@ protected:
bool m_isStraight = false;
TPointD m_firstPoint;
TPointD m_lastPoint;
std::vector<TPointD> m_assistantPoints;
bool m_addingAssistant = false;
bool m_snapAssistant = false;
double m_oldPressure = -1.0;
int m_highlightAssistant = -1;
bool m_propertyUpdating = false;
int m_perspectiveIndex = -1;
};
//------------------------------------------------------------

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,529 @@
#pragma once
#ifndef PERSPECTIVETOOL_H
#define PERSPECTIVETOOL_H
#include "tproperty.h"
#include "tpersist.h"
#include "tundo.h"
#include "historytypes.h"
#include "toonz/tproject.h"
#include "toonzqt/selection.h"
#include "tools/tool.h"
#include "tools/tooloptions.h"
#include <QCoreApplication>
class SceneViewer;
class PerspectiveTool;
//--------------------------------------------------------------
#define CUSTOM_WSTR L"<custom>"
//--------------------------------------------------------------
enum PerspectiveType { Undefined, VanishingPoint, Line };
//************************************************************************
// Perspective Data declaration
//************************************************************************
class PerspectiveData {
public:
PerspectiveData(PerspectiveType perspectiveType, TPointD centerPoint,
double rotation, int spacing, bool horizon, double opacity,
TPixel32 color, bool parallel)
: m_type(perspectiveType)
, m_centerPoint(centerPoint)
, m_rotation(rotation)
, m_spacing(spacing)
, m_horizon(horizon)
, m_opacity(opacity)
, m_color(color)
, m_parallel(parallel){};
~PerspectiveData(){};
virtual void draw(SceneViewer *viewer, TRectD cameraRect){};
void setType(PerspectiveType pType) { m_type = pType; }
PerspectiveType getType() { return m_type; }
void setCenterPoint(TPointD point) { m_centerPoint = point; }
TPointD getCenterPoint() { return m_centerPoint; }
void setRotation(double angle) { m_rotation = angle; }
virtual double getRotation() { return m_rotation; }
void setParallel(bool isParallel) { m_parallel = isParallel; }
bool isParallel() { return m_parallel; }
void setSpacing(double space) { m_spacing = space; }
virtual double getSpacing() { return m_spacing; }
void setMinSpacing(int minSpace) { m_minSpacing = minSpace; }
virtual double getMinSpacing() { return m_minSpacing; }
void setMaxSpacing(int maxSpace) { m_maxSpacing = maxSpace; }
virtual double getMaxSpacing() { return m_maxSpacing; }
void setHorizon(bool isHorizon) { m_horizon = isHorizon; }
bool isHorizon() { return m_horizon; }
void setOpacity(double opacity) { m_opacity = opacity; }
double getOpacity() { return m_opacity; }
void setColor(TPixel32 color) { m_color = color; }
TPixel32 getColor() { return m_color; }
protected:
PerspectiveType m_type;
TPointD m_centerPoint;
double m_rotation;
bool m_parallel;
double m_spacing, m_minSpacing = 1.0, m_maxSpacing = UINT_MAX;
bool m_horizon;
double m_opacity;
TPixel32 m_color;
};
//************************************************************************
// Perspective Controls declaration
//************************************************************************
class PerspectiveControls {
PerspectiveData *m_perspective;
TPointD m_cursorPos;
bool m_active;
bool m_showAdvanced;
double m_unit = 1;
double m_handleRadius = 10;
// Common Controls
TPointD m_rotationPos = TPointD(40, 0);
TPointD m_spacingPos = TPointD(0, -40);
// Vanishing Point Controls
TPointD m_leftPivotPos = TPointD(-40, 0);
TPointD m_leftHandlePos = TPointD(-80, 0);
TPointD m_rightPivotPos = TPointD(40, 0);
TPointD m_rightHandlePos = TPointD(80, 0);
public:
PerspectiveControls(PerspectiveData *perspective)
: m_perspective(perspective), m_active(false), m_showAdvanced(false) {}
~PerspectiveControls() {}
void setCursorPos(TPointD pos) { m_cursorPos = pos; }
TPointD getCursorPos() { return m_cursorPos; }
void setActive(bool active) { m_active = active; }
bool isActive() { return m_active; }
void setShowAdvancedControls(bool show) { m_showAdvanced = show; }
bool showAdvancedControls() { return m_showAdvanced; }
void setRotationPos(TPointD pos) { m_rotationPos = pos; }
TPointD getRotationPos() { return m_rotationPos; }
void setSpacingPos(TPointD pos) { m_spacingPos = pos; }
TPointD getSpacingPos() { return m_spacingPos; }
void setLeftPivotPos(TPointD pos) { m_leftPivotPos = pos; }
TPointD getLeftPivotPos() { return m_leftPivotPos; }
void setLeftHandlePos(TPointD pos) { m_leftHandlePos = pos; }
TPointD getLeftHandlePos() { return m_leftHandlePos; }
void setRightPivotPos(TPointD pos) { m_rightPivotPos = pos; }
TPointD getRightPivotPos() { return m_rightPivotPos; }
void setRightHandlePos(TPointD pos) { m_rightHandlePos = pos; }
TPointD getRightHandlePos() { return m_rightHandlePos; }
void shiftPerspectiveObject(TPointD delta);
void drawControls();
bool isOverCenterPoint() {
TPointD centerPoint = m_perspective->getCenterPoint();
return checkOver(centerPoint, m_cursorPos);
}
bool isOverRotation() { return checkOver(m_rotationPos, m_cursorPos); }
bool isOverSpacing() {
if (!m_perspective || (m_perspective->getType() == PerspectiveType::Line &&
!m_perspective->isParallel()))
return false;
return checkOver(m_spacingPos, m_cursorPos);
}
bool isOverLeftPivot() {
if (!m_showAdvanced || !m_perspective ||
m_perspective->getType() != PerspectiveType::VanishingPoint)
return false;
return checkOver(m_leftPivotPos, m_cursorPos);
}
bool isOverLeftHandle() {
if (!m_showAdvanced || !m_perspective ||
m_perspective->getType() != PerspectiveType::VanishingPoint)
return false;
return checkOver(m_leftHandlePos, m_cursorPos);
}
bool isOverRightPivot() {
if (!m_showAdvanced || !m_perspective ||
m_perspective->getType() != PerspectiveType::VanishingPoint)
return false;
return checkOver(m_rightPivotPos, m_cursorPos);
}
bool isOverRightHandle() {
if (!m_showAdvanced || !m_perspective ||
m_perspective->getType() != PerspectiveType::VanishingPoint)
return false;
return checkOver(m_rightHandlePos, m_cursorPos);
}
bool isOverControl() {
return isOverCenterPoint() | isOverRotation() | isOverSpacing() |
isOverLeftPivot() | isOverLeftHandle() | isOverRightPivot() |
isOverRightHandle();
}
TRectD getCenterPointRect() {
TPointD centerPoint = m_perspective->getCenterPoint();
return getControlRect(centerPoint);
}
TRectD getRotationRect() { return getControlRect(m_rotationPos); }
TRectD getSpacingRect() { return getControlRect(m_spacingPos); }
TRectD getLeftPivotRect() { return getControlRect(m_leftPivotPos); }
TRectD getLeftHandleRect() { return getControlRect(m_leftHandlePos); }
TRectD getRightPivotRect() { return getControlRect(m_rightPivotPos); }
TRectD getRightHandleRect() { return getControlRect(m_rightHandlePos); }
private:
TRectD getControlRect(TPointD controlPos) {
return TRectD(controlPos.x - m_handleRadius * m_unit,
controlPos.y + m_handleRadius * m_unit,
controlPos.x + m_handleRadius * m_unit,
controlPos.y - m_handleRadius * m_unit);
}
bool checkOver(TPointD controlPos, TPointD mousePos) {
return areAlmostEqual(controlPos.x, mousePos.x, m_handleRadius * m_unit) &&
areAlmostEqual(controlPos.y, mousePos.y, m_handleRadius * m_unit);
}
};
//=============================================================================
// PerspectiveObject
//-----------------------------------------------------------------------------
class PerspectiveObject : public PerspectiveData, public PerspectiveControls {
public:
PerspectiveObject(PerspectiveType perspectiveType,
TPointD centerPoint = TPointD(0, 0), double rotation = 0.0,
double spacing = 100.0, bool horizon = false,
double opacity = 30.0, TPixel32 color = TPixel::Magenta,
bool parallel = true, bool showAdvanced = false)
: PerspectiveData(perspectiveType, centerPoint, rotation, spacing,
horizon, opacity, color, parallel)
, PerspectiveControls(this){};
~PerspectiveObject(){};
virtual TPointD getReferencePoint(TPointD firstPoint) { return firstPoint; }
};
//=============================================================================
// PerspectiveObjectUndo
//-----------------------------------------------------------------------------
class PerspectiveObjectUndo final : public TUndo {
std::vector<PerspectiveObject *> m_undoData;
std::vector<PerspectiveObject *> m_redoData;
PerspectiveTool *m_tool;
public:
PerspectiveObjectUndo(std::vector<PerspectiveObject *> objs,
PerspectiveTool *tool);
~PerspectiveObjectUndo() {}
void undo() const override;
void redo() const override;
void setRedoData(std::vector<PerspectiveObject *> objs);
int getSize() const override { return sizeof(this); }
QString getToolName() { return QString("Perspective Grid Tool"); }
int getHistoryType() override { return HistoryType::PerspectiveGridTool; }
QString getHistoryString() override { return getToolName(); }
};
//=============================================================================
// PerspectivePreset
//-----------------------------------------------------------------------------
struct PerspectivePreset final : public TPersist {
PERSIST_DECLARATION(PerspectivePreset)
std::wstring m_presetName;
std::vector<PerspectiveObject *> m_perspectiveSet;
TFilePath m_path;
PerspectivePreset() {}
PerspectivePreset(std::wstring presetName, TFilePath path = TFilePath())
: m_presetName(presetName), m_path(path) {}
PerspectivePreset(std::wstring presetName,
std::vector<PerspectiveObject *> perspectiveSet,
TFilePath path = TFilePath())
: m_presetName(presetName)
, m_perspectiveSet(perspectiveSet)
, m_path(path) {}
void setPath(TFilePath path) { m_path = path; }
TFilePath getPath() { return m_path; }
bool operator<(const PerspectivePreset &other) const {
return m_presetName < other.m_presetName;
}
void saveData(TOStream &os) override;
void loadData(TIStream &is) override;
};
//************************************************************************
// Perspective Preset Manager declaration
//************************************************************************
class PerspectivePresetManager {
std::set<PerspectivePreset> m_presets; //!< Current presets container
bool m_presetsLoaded = false;
PerspectivePreset m_customPreset;
public:
PerspectivePresetManager() {}
void setIsLoaded(bool isLoaded) { m_presetsLoaded = isLoaded; }
bool isLoaded() { return m_presetsLoaded; }
void clearPresets() {
m_presetsLoaded = false;
m_presets.clear();
}
void loadPresets(const TFilePath &presetFolder);
void savePreset(std::wstring presetName);
void deletePreset(TFilePath presetPath);
const std::set<PerspectivePreset> &presets() const { return m_presets; }
PerspectivePreset getCustomPreset() { return m_customPreset; }
void setCustomPreset(PerspectivePreset custom) { m_customPreset = custom; }
void addPreset(PerspectivePreset perspectiveSet);
void removePreset(const std::wstring &name);
};
//=============================================================================
// PerspectiveSelection
//-----------------------------------------------------------------------------
class PerspectiveSelection final : public TSelection {
private:
std::set<int> m_selectedObjects;
PerspectiveTool *m_tool;
public:
PerspectiveSelection() : m_tool(0) {}
void enableCommands() override;
void setTool(PerspectiveTool *tool) { m_tool = tool; }
bool isEmpty() const override { return m_selectedObjects.empty(); }
void selectNone() override { m_selectedObjects.clear(); }
bool isSelected(int index) {
return m_selectedObjects.find(index) != m_selectedObjects.end();
}
void select(int index) { m_selectedObjects.insert(index); }
void unselect(int index) { m_selectedObjects.erase(index); }
int count() { return m_selectedObjects.size(); }
std::set<int> getSelectedObjects() { return m_selectedObjects; }
};
//=============================================================================
// VanishingPointPerspective
//-----------------------------------------------------------------------------
class VanishingPointPerspective final : public PerspectiveObject {
public:
VanishingPointPerspective()
: PerspectiveObject(PerspectiveType::VanishingPoint) {
setSpacing(27);
setParallel(false);
setMaxSpacing(180);
setRotationPos(TPointD(0, -40));
setSpacingPos(TPointD(20, -40));
};
~VanishingPointPerspective(){};
void draw(SceneViewer *viewer, TRectD cameraRect) override;
double getMaxSpacing() override {
if (isHorizon()) return 90.0;
return m_maxSpacing;
}
TPointD getReferencePoint(TPointD firstPoint) override {
return getCenterPoint();
}
};
//=============================================================================
// LinePerspective
//-----------------------------------------------------------------------------
class LinePerspective final : public PerspectiveObject {
public:
LinePerspective() : PerspectiveObject(PerspectiveType::Line) {
setSpacing(40);
};
~LinePerspective(){};
void draw(SceneViewer *viewer, TRectD cameraRect) override;
TPointD getReferencePoint(TPointD firstPoint) override;
};
//=============================================================================
// PerspectiveTool
//-----------------------------------------------------------------------------
class PerspectiveTool final : public TTool, public TProjectManager::Listener {
Q_DECLARE_TR_FUNCTIONS(PerspectiveTool)
public:
PerspectiveTool();
~PerspectiveTool();
ToolType getToolType() const override { return TTool::GenericTool; }
void updateTranslation();
void draw(SceneViewer *viewer) override;
void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override;
void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override;
void leftButtonUp(const TPointD &pos, const TMouseEvent &) override;
bool keyDown(QKeyEvent *event) override;
void onActivate() override;
bool onPropertyChanged(std::string propertyName) override;
int getCursorId() const override { return ToolCursor::StrokeSelectCursor; };
TPropertyGroup *getProperties(int targetType) override;
void setToolOptionsBox(PerspectiveGridToolOptionBox *toolOptionsBox);
void deleteSelectedObjects();
void selectAllObjects();
void setPerspectiveObjects(std::vector<PerspectiveObject *> objs);
std::vector<PerspectiveObject *> getPerspectiveObjects() {
return m_perspectiveObjs;
}
PerspectiveObject *getMainPerspectiveObject() {
if (m_mainControlIndex < 0 ||
m_mainControlIndex >= m_perspectiveObjs.size())
return 0;
return m_perspectiveObjs[m_mainControlIndex];
}
std::vector<PerspectiveObject *> copyPerspectiveSet(
std::vector<PerspectiveObject *> perspectiveSet, bool keepStatus = true);
void invalidateControl(int controlIndex);
void onEnter() override;
void onDeactivate() override;
void initPresets();
void loadPreset();
void addPreset(QString name, bool isLibrary = false);
void removePreset();
void loadLastPreset();
void updateSpacing(double space);
void updateRotation(double rotation);
void updateMeasuredValueToolOptions();
void updateToolOptionValues();
void saveTool() override;
void loadTool() override;
/*! Overridden from TProjectManager::Listener. */
void onProjectSwitched() override;
void onProjectChanged() override;
protected:
TPropertyGroup m_prop;
std::vector<PerspectiveGridToolOptionBox *> m_toolOptionsBox;
TEnumProperty m_type;
TDoubleProperty m_opacity;
TColorChipProperty m_color;
TBoolProperty m_horizon;
TBoolProperty m_parallel;
TEnumProperty m_preset;
TBoolProperty m_advancedControls;
std::vector<PerspectiveObject *> m_perspectiveObjs;
std::vector<PerspectiveObject *> m_lastPreset;
bool m_firstTime;
PerspectiveSelection m_selection;
bool m_selecting;
TRectD m_selectingRect;
bool m_modified;
bool m_isShifting;
bool m_isCenterMoving;
bool m_isRotating;
bool m_isSpacing;
bool m_isLeftPivoting;
bool m_isLeftMoving;
bool m_isRightPivoting;
bool m_isRightMoving;
TPointD m_mousePos, m_firstPos;
double m_totalChange;
int m_mainControlIndex;
bool m_propertyUpdating = false;
PerspectivePresetManager m_presetsManager;
PerspectiveObjectUndo *m_undo;
};
#endif

View file

@ -19,6 +19,7 @@
//#include "rgbpickertool.h"
#include "rulertool.h"
#include "shifttracetool.h"
#include "perspectivetool.h"
// TnzQt includes
#include "toonzqt/dvdialog.h"
@ -61,6 +62,8 @@
#include <QEasingCurve>
#include <QStackedWidget>
using namespace ToolOptionsControls;
TEnv::IntVar ArrowGlobalKeyFrame("EditToolGlobalKeyFrame", 0);
//=============================================================================
@ -337,6 +340,16 @@ void ToolOptionControlBuilder::visit(TPointerProperty *p) {
assert(!"not implemented");
}
//-----------------------------------------------------------------------------
void ToolOptionControlBuilder::visit(TColorChipProperty *p) {
QLabel *label = addLabel(p);
m_panel->addLabel(p->getName(), label);
ColorChipCombo *chipCombo = new ColorChipCombo(m_tool, p);
hLayout()->addWidget(chipCombo, 0);
m_panel->addControl(chipCombo);
}
//=============================================================================
// GenericToolOptionsBox
@ -2103,7 +2116,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);
}
@ -2112,7 +2125,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);
@ -2893,6 +2906,349 @@ void ShiftTraceToolOptionBox::onAfterRadioBtnClicked() {
stTool->setCurrentGhostIndex(1);
}
//=============================================================================
//
// PerspectiveGridToolOptionBox classes
//
//=============================================================================
class PerspectiveGridToolOptionBox::PresetNamePopup final
: public DVGui::Dialog {
DVGui::LineEdit *m_nameFld;
DVGui::CheckBox *m_saveInLibrary;
public:
PresetNamePopup() : Dialog(0, true) {
setWindowTitle(tr("Preset Name"));
m_nameFld = new DVGui::LineEdit();
addWidget(m_nameFld);
m_saveInLibrary = new DVGui::CheckBox(tr("Save As Library Preset"));
addWidget(m_saveInLibrary);
QPushButton *okBtn = new QPushButton(tr("OK"), this);
okBtn->setDefault(true);
QPushButton *cancelBtn = new QPushButton(tr("Cancel"), this);
connect(okBtn, SIGNAL(clicked()), this, SLOT(accept()));
connect(cancelBtn, SIGNAL(clicked()), this, SLOT(reject()));
addButtonBarWidget(okBtn, cancelBtn);
}
QString getName() { return m_nameFld->text(); }
bool isSaveInLibrary() { return m_saveInLibrary->isChecked(); }
void resetDialog() {
m_nameFld->setText(QString(""));
m_saveInLibrary->setChecked(false);
}
};
//=============================================================================
// PerspectiveGridToolOptionBox
//-----------------------------------------------------------------------------
PerspectiveGridToolOptionBox::PerspectiveGridToolOptionBox(
QWidget *parent, TTool *tool, TPaletteHandle *pltHandle,
ToolHandle *toolHandle)
: ToolOptionsBox(parent), m_tool(tool), m_presetNamePopup(0) {
setFrameStyle(QFrame::StyledPanel);
setFixedHeight(26);
TPropertyGroup *props = tool->getProperties(0);
assert(props->getPropertyCount() > 0);
TEnumProperty *perspectiveType =
dynamic_cast<TEnumProperty *>(props->getProperty("Type:"));
m_perspectiveType = new ToolOptionCombo(tool, perspectiveType, toolHandle);
TDoubleProperty *opacity =
dynamic_cast<TDoubleProperty *>(props->getProperty("Opacity:"));
m_opacity = new ToolOptionSlider(tool, opacity, toolHandle);
int fieldMaxWidth;
m_spacingLabel = new ClickableLabel(tr("Spacing:"), this);
m_spacing = new MeasuredValueField(this);
m_spacing->setMeasure("");
m_spacing->setMaximumWidth(getMaximumWidthForMeasuredValueField(m_spacing));
m_rotationLabel = new ClickableLabel(tr("Rotation:"), this);
m_rotation = new MeasuredValueField(this);
m_rotation->setMeasure("angle");
m_rotation->setMaximumWidth(getMaximumWidthForMeasuredValueField(m_rotation));
m_leftRotateButton = new QPushButton(this);
m_rightRotateButton = new QPushButton(this);
m_leftRotateButton->setFixedSize(QSize(20, 20));
m_rightRotateButton->setFixedSize(QSize(20, 20));
m_leftRotateButton->setIcon(createQIcon("rotateleft"));
m_leftRotateButton->setIconSize(QSize(20, 20));
m_rightRotateButton->setIcon(createQIcon("rotateright"));
m_rightRotateButton->setIconSize(QSize(20, 20));
m_leftRotateButton->setToolTip(tr("Rotate Perspective Left"));
m_rightRotateButton->setToolTip(tr("Rotate Perspective Right"));
TColorChipProperty *color =
dynamic_cast<TColorChipProperty *>(props->getProperty("Color:"));
m_color = new ColorChipCombo(tool, color);
TBoolProperty *horizon =
dynamic_cast<TBoolProperty *>(props->getProperty("Horizon"));
m_horizon = new ToolOptionCheckbox(tool, horizon, toolHandle);
TBoolProperty *parallel =
dynamic_cast<TBoolProperty *>(props->getProperty("Parallel"));
m_parallel = new ToolOptionCheckbox(tool, parallel, toolHandle);
TBoolProperty *advancedControls =
dynamic_cast<TBoolProperty *>(props->getProperty("Advanced Controls"));
m_advancedControls =
new ToolOptionCheckbox(tool, advancedControls, toolHandle);
TEnumProperty *preset =
dynamic_cast<TEnumProperty *>(props->getProperty("Preset:"));
m_presetCombo = new ToolOptionCombo(tool, preset, toolHandle);
// Preset +/- buttons
m_addPresetButton = new QPushButton(QString("+"));
m_removePresetButton = new QPushButton(QString("-"));
m_addPresetButton->setFixedSize(QSize(20, 20));
m_removePresetButton->setFixedSize(QSize(20, 20));
/* --- Layout --- */
QHBoxLayout *mainLay = m_layout;
{
mainLay->addWidget(new QLabel(tr("Type:"), this), 0);
mainLay->addWidget(m_perspectiveType, 0);
mainLay->addSpacing(5);
mainLay->addWidget(new QLabel(tr("Opacity:"), this), 0);
mainLay->addWidget(m_opacity, 100);
mainLay->addSpacing(5);
mainLay->addWidget(m_spacingLabel, 0);
mainLay->addWidget(m_spacing, 10);
mainLay->addSpacing(5);
mainLay->addWidget(m_rotationLabel, 0);
mainLay->addWidget(m_rotation, 10);
mainLay->addWidget(m_leftRotateButton, 0);
mainLay->addWidget(m_rightRotateButton, 0);
mainLay->addSpacing(5);
mainLay->addWidget(new QLabel(tr("Color:"), this), 0);
mainLay->addWidget(m_color, 0);
mainLay->addSpacing(5);
mainLay->addWidget(m_horizon, 0);
mainLay->addSpacing(5);
mainLay->addWidget(m_parallel, 0);
mainLay->addSpacing(5);
mainLay->addWidget(m_advancedControls, 0);
mainLay->addSpacing(5);
mainLay->addWidget(new QLabel(tr("Preset:"), this), 0);
mainLay->addWidget(m_presetCombo, 0);
mainLay->addWidget(m_addPresetButton);
mainLay->addWidget(m_removePresetButton);
}
m_layout->addStretch(1);
connect(m_perspectiveType, SIGNAL(currentIndexChanged(int)), this,
SLOT(onPerspectiveTypeChanged(int)));
connect(m_spacing, SIGNAL(measuredValueChanged(TMeasuredValue *, bool)),
SLOT(onSpacingChange(TMeasuredValue *)));
connect(m_spacingLabel, SIGNAL(onMousePress(QMouseEvent *)), m_spacing,
SLOT(receiveMousePress(QMouseEvent *)));
connect(m_spacingLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_spacing,
SLOT(receiveMouseMove(QMouseEvent *)));
connect(m_spacingLabel, SIGNAL(onMouseRelease(QMouseEvent *)), m_spacing,
SLOT(receiveMouseRelease(QMouseEvent *)));
connect(m_rotation, SIGNAL(measuredValueChanged(TMeasuredValue *, bool)),
SLOT(onRotationChange(TMeasuredValue *)));
connect(m_rotationLabel, SIGNAL(onMousePress(QMouseEvent *)), m_rotation,
SLOT(receiveMousePress(QMouseEvent *)));
connect(m_rotationLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_rotation,
SLOT(receiveMouseMove(QMouseEvent *)));
connect(m_rotationLabel, SIGNAL(onMouseRelease(QMouseEvent *)), m_rotation,
SLOT(receiveMouseRelease(QMouseEvent *)));
connect(m_leftRotateButton, SIGNAL(clicked()), SLOT(onRotateLeft()));
connect(m_rightRotateButton, SIGNAL(clicked()), SLOT(onRotateRight()));
connect(m_addPresetButton, SIGNAL(clicked()), this, SLOT(onAddPreset()));
connect(m_removePresetButton, SIGNAL(clicked()), this,
SLOT(onRemovePreset()));
filterControls();
}
//-----------------------------------------------------------------------------
void PerspectiveGridToolOptionBox::filterControls() {
PerspectiveTool *perspectiveTool = dynamic_cast<PerspectiveTool *>(m_tool);
PerspectiveObject *mainObj = perspectiveTool->getMainPerspectiveObject();
std::vector<PerspectiveObject *> objs =
perspectiveTool->getPerspectiveObjects();
bool isVanishingSelected =
m_perspectiveType->getProperty()->getValue() == L"Vanishing Point";
bool isLineSelected = m_perspectiveType->getProperty()->getValue() == L"Line";
int selected = 0;
for (int i = 0; i < objs.size(); i++) {
if (!objs[i]->isActive()) continue;
if (objs[i]->getType() == PerspectiveType::VanishingPoint)
isVanishingSelected = true;
else if (objs[i]->getType() == PerspectiveType::Line)
isLineSelected = true;
selected++;
}
m_parallel->setEnabled(isLineSelected);
m_horizon->setEnabled(isVanishingSelected || m_parallel->isChecked());
m_advancedControls->setEnabled(isVanishingSelected);
m_spacingLabel->setEnabled(selected &&
(isVanishingSelected || m_parallel->isChecked()));
m_spacing->setEnabled(selected &&
(isVanishingSelected || m_parallel->isChecked()));
if (!m_spacing->isEnabled())
m_spacing->setValue(0);
else if (mainObj)
m_spacing->setValue(mainObj->getSpacing());
m_rotationLabel->setEnabled(selected);
m_rotation->setEnabled(selected);
if (!m_rotation->isEnabled())
m_rotation->setValue(0);
else if (mainObj)
m_rotation->setValue(mainObj->getRotation());
m_leftRotateButton->setEnabled(selected);
m_rightRotateButton->setEnabled(selected);
}
//-----------------------------------------------------------------------------
void PerspectiveGridToolOptionBox::updateStatus() {
m_opacity->updateStatus();
m_color->updateStatus();
m_horizon->updateStatus();
m_parallel->updateStatus();
m_presetCombo->updateStatus();
filterControls();
}
//-----------------------------------------------------------------------------
void PerspectiveGridToolOptionBox::updateMeasuredValues(double spacing,
double rotation) {
filterControls();
if (m_spacing->isEnabled()) m_spacing->setValue(spacing);
m_rotation->setValue(rotation);
repaint();
}
//-----------------------------------------------------------------------------
void PerspectiveGridToolOptionBox::reloadPresetCombo() {
m_presetCombo->loadEntries();
}
//-----------------------------------------------------------------------------
void PerspectiveGridToolOptionBox::onAddPreset() {
// Initialize preset name popup
if (!m_presetNamePopup) m_presetNamePopup = new PresetNamePopup;
if (!m_presetNamePopup->getName().isEmpty()) m_presetNamePopup->resetDialog();
// Retrieve the preset name
bool ret = m_presetNamePopup->exec();
if (!ret) return;
QString name(m_presetNamePopup->getName());
bool saveInLibrary(m_presetNamePopup->isSaveInLibrary());
m_presetNamePopup->resetDialog();
static_cast<PerspectiveTool *>(m_tool)->addPreset(name, saveInLibrary);
m_presetCombo->loadEntries();
}
//-----------------------------------------------------------------------------
void PerspectiveGridToolOptionBox::onRemovePreset() {
static_cast<PerspectiveTool *>(m_tool)->removePreset();
m_presetCombo->loadEntries();
}
//-----------------------------------------------------------------------------
void PerspectiveGridToolOptionBox::onPerspectiveTypeChanged(int index) {
filterControls();
}
//-----------------------------------------------------------------------------
void PerspectiveGridToolOptionBox::onSpacingChange(TMeasuredValue *fld) {
double value = fld->getValue(TMeasuredValue::CurrentUnit);
PerspectiveTool *perspectiveTool = dynamic_cast<PerspectiveTool *>(m_tool);
PerspectiveObject *mainObj = perspectiveTool->getMainPerspectiveObject();
if (mainObj) {
value = std::min(value, mainObj->getMaxSpacing());
value = std::max(value, mainObj->getMinSpacing());
m_spacing->setValue(value);
repaint();
}
perspectiveTool->updateSpacing(value);
}
//-----------------------------------------------------------------------------
void PerspectiveGridToolOptionBox::onRotationChange(TMeasuredValue *fld) {
double value = fld->getValue(TMeasuredValue::CurrentUnit);
PerspectiveTool *perspectiveTool = dynamic_cast<PerspectiveTool *>(m_tool);
perspectiveTool->updateRotation(value);
}
//-----------------------------------------------------------------------------
void PerspectiveGridToolOptionBox::onRotateLeft() {
m_rotation->setValue(m_rotation->getValue() + 90);
emit m_rotation->measuredValueChanged(m_rotation->getMeasuredValue());
}
//-----------------------------------------------------------------------------
void PerspectiveGridToolOptionBox::onRotateRight() {
m_rotation->setValue(m_rotation->getValue() - 90);
emit m_rotation->measuredValueChanged(m_rotation->getMeasuredValue());
}
//=============================================================================
// ZoomToolOptionBox
//-----------------------------------------------------------------------------
@ -3083,6 +3439,12 @@ void ToolOptions::onToolSwitched() {
panel = p;
RulerTool *rt = dynamic_cast<RulerTool *>(tool);
if (rt) rt->setToolOptionsBox(p);
} else if (tool->getName() == T_PerspectiveGrid) {
PerspectiveGridToolOptionBox *p =
new PerspectiveGridToolOptionBox(this, tool, currPalette, currTool);
panel = p;
PerspectiveTool *pt = dynamic_cast<PerspectiveTool *>(tool);
if (pt) pt->setToolOptionsBox(p);
} else if (tool->getName() == T_StylePicker)
panel = new StylePickerToolOptionsBox(0, tool, currPalette, currTool,
app->getPaletteController());

View file

@ -42,6 +42,12 @@
#include "tooloptionscontrols.h"
using namespace DVGui;
using namespace ToolOptionsControls;
int ToolOptionsControls::getMaximumWidthForMeasuredValueField(QWidget *widget) {
static int fieldMaxWidth = widget->fontMetrics().width("-0000.00 field") + 10;
return fieldMaxWidth;
}
//***********************************************************************************
// ToolOptionControl implementation
@ -564,6 +570,53 @@ void StyleIndexFieldAndChip::updateColor() { repaint(); }
//=============================================================================
ColorChipCombo::ColorChipCombo(TTool *tool, TColorChipProperty *property)
: QComboBox()
, ToolOptionControl(tool, property->getName())
, m_property(property) {
setObjectName(QString::fromStdString(property->getName()));
setFixedHeight(20);
setSizeAdjustPolicy(QComboBox::AdjustToContents);
m_property->addListener(this);
const TColorChipProperty::ColorChips &chips = m_property->getColorChips();
for (int i = 0; i < chips.size(); ++i) {
TPixel32 color = chips[i].pixelColor;
QPixmap pixmap(10, 10);
pixmap.fill(QColor(color.r, color.g, color.b));
addItem(QIcon(pixmap), chips[i].UIName);
}
setCurrentIndex(0);
updateStatus();
connect(this, SIGNAL(activated(int)), this, SLOT(onActivated(int)));
}
//-----------------------------------------------------------------------------
void ColorChipCombo::updateStatus() {
int index = m_property->getIndex();
if (index >= 0 && index != currentIndex()) setCurrentIndex(index);
}
//-----------------------------------------------------------------------------
void ColorChipCombo::onActivated(int index) {
const TColorChipProperty::ColorChips &chips = m_property->getColorChips();
if (index < 0 || index >= (int)chips.size()) return;
std::wstring item = chips[index].UIName.toStdWString();
m_property->setValue(item);
notifyTool();
}
//-----------------------------------------------------------------------------
void ColorChipCombo::doSetCurrentIndex(int index) {
if (isVisible()) setCurrentIndex(index);
}
//=============================================================================
ToolOptionParamRelayField::ToolOptionParamRelayField(
TTool *tool, TDoubleParamRelayProperty *property, int decimals)
: MeasuredDoubleLineEdit()
@ -894,14 +947,6 @@ void MeasuredValueField::receiveMouseRelease(QMouseEvent *e) {
//=============================================================================
namespace {
// calculate maximum field size (once) with 10 pixels margin
int getMaximumWidthForEditToolField(QWidget *widget) {
static int fieldMaxWidth = widget->fontMetrics().width("-0000.00 field") + 10;
return fieldMaxWidth;
}
} // namespace
PegbarChannelField::PegbarChannelField(TTool *tool,
enum TStageObject::Channel actionId,
QString name, TFrameHandle *frameHandle,
@ -949,7 +994,7 @@ PegbarChannelField::PegbarChannelField(TTool *tool,
break;
}
setMaximumWidth(getMaximumWidthForEditToolField(this));
setMaximumWidth(getMaximumWidthForMeasuredValueField(this));
updateStatus();
}
@ -1069,7 +1114,7 @@ PegbarCenterField::PegbarCenterField(TTool *tool, int index, QString name,
connect(this, SIGNAL(measuredValueChanged(TMeasuredValue *, bool)),
SLOT(onChange(TMeasuredValue *, bool)));
updateStatus();
setMaximumWidth(getMaximumWidthForEditToolField(this));
setMaximumWidth(getMaximumWidthForMeasuredValueField(this));
}
//-----------------------------------------------------------------------------
@ -1127,7 +1172,7 @@ NoScaleField::NoScaleField(TTool *tool, QString name)
connect(this, SIGNAL(measuredValueChanged(TMeasuredValue *, bool)),
SLOT(onChange(TMeasuredValue *, bool)));
updateStatus();
setMaximumWidth(getMaximumWidthForEditToolField(this));
setMaximumWidth(getMaximumWidthForMeasuredValueField(this));
}
//-----------------------------------------------------------------------------
@ -1231,13 +1276,6 @@ void PropertyMenuButton::onActionTriggered(QAction *action) {
}
//=============================================================================
namespace {
// calculate maximum field size (once) with 10 pixels margin
int getMaximumWidthForSelectionToolField(QWidget *widget) {
static int fieldMaxWidth = widget->fontMetrics().width("-000.00 %") + 10;
return fieldMaxWidth;
}
} // namespace
// id == 0 Scale X
// id == 0 Scale Y
@ -1250,7 +1288,7 @@ SelectionScaleField::SelectionScaleField(SelectionTool *tool, int id,
setMeasure("scale");
updateStatus();
setMaximumWidth(getMaximumWidthForSelectionToolField(this));
setMaximumWidth(getMaximumWidthForMeasuredValueField(this));
}
//-----------------------------------------------------------------------------
@ -1338,7 +1376,7 @@ SelectionRotationField::SelectionRotationField(SelectionTool *tool,
setMeasure("angle");
updateStatus();
setMaximumWidth(getMaximumWidthForSelectionToolField(this));
setMaximumWidth(getMaximumWidthForMeasuredValueField(this));
}
//-----------------------------------------------------------------------------
@ -1404,7 +1442,7 @@ SelectionMoveField::SelectionMoveField(SelectionTool *tool, int id,
// for translation value field, use size for the Edit Tool as it needs more
// estate
setMaximumWidth(getMaximumWidthForEditToolField(this));
setMaximumWidth(getMaximumWidthForMeasuredValueField(this));
}
//-----------------------------------------------------------------------------
@ -1464,7 +1502,7 @@ ThickChangeField::ThickChangeField(SelectionTool *tool, QString name)
setMeasure("");
updateStatus();
setMaximumWidth(getMaximumWidthForSelectionToolField(this));
setMaximumWidth(getMaximumWidthForMeasuredValueField(this));
}
//-----------------------------------------------------------------------------

View file

@ -51,6 +51,11 @@ class TXsheetHandle;
class SelectionTool;
class ToolHandle;
namespace ToolOptionsControls {
// calculate maximum field size (once) with 10 pixels margin
int getMaximumWidthForMeasuredValueField(QWidget *widget);
} // namespace
//***********************************************************************************
// ToolOptionControl declaration
//***********************************************************************************
@ -275,6 +280,23 @@ public slots:
//-----------------------------------------------------------------------------
class ColorChipCombo final : public QComboBox, public ToolOptionControl {
Q_OBJECT
protected:
TColorChipProperty *m_property;
public:
ColorChipCombo(TTool *tool, TColorChipProperty *property);
void updateStatus() override;
public slots:
void onActivated(int index);
void doSetCurrentIndex(int);
};
//-----------------------------------------------------------------------------
//! The ToolOptionMeasuredDoubleField class implements toolbar controls for
//! double properties that need to be displayed with a measure.
/*!

View file

@ -44,6 +44,8 @@
#include "tgl.h"
#include "trop.h"
#include "perspectivetool.h"
// Qt includes
#include <QPainter>
@ -59,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>"
@ -888,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();
@ -909,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);
@ -1108,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"));
}
//---------------------------------------------------------------------------------------------------
@ -1291,42 +1299,6 @@ void ToonzRasterBrushTool::leftButtonDown(const TPointD &pos,
m_active = false;
return;
}
TXshSimpleLevelP simLevel = level->getSimpleLevel();
m_assistantPoints = simLevel->getProperties()->getVanishingPoints();
if (e.isAltPressed() && e.isCtrlPressed() && !e.isShiftPressed()) {
m_addingAssistant = true;
bool deletedPoint = false;
for (int i = 0; i < m_assistantPoints.size(); i++) {
if (areAlmostEqual(m_assistantPoints.at(i).x, pos.x, 12) &&
areAlmostEqual(m_assistantPoints.at(i).y, pos.y, 12)) {
TRectD pointRect = TRectD(
m_assistantPoints.at(i).x - 15, m_assistantPoints.at(i).y - 15,
m_assistantPoints.at(i).x + 15, m_assistantPoints.at(i).x + 15);
m_assistantPoints.erase(m_assistantPoints.begin() + i);
deletedPoint = true;
invalidate(pointRect);
break;
}
}
if (!deletedPoint) m_assistantPoints.push_back(pos);
simLevel->getProperties()->setVanishingPoints(m_assistantPoints);
level->setDirtyFlag(true);
invalidate();
return;
}
if (e.isAltPressed() && e.isShiftPressed() && !e.isCtrlPressed()) {
m_addingAssistant = true;
std::vector<TPointD> pointsToClear = m_assistantPoints;
m_assistantPoints.clear();
for (auto point : pointsToClear) {
TRectD pointRect =
TRectD(point.x - 3, point.y - 3, point.x + 3, point.y + 3);
invalidate(pointRect);
}
return;
}
if ((e.isShiftPressed() || e.isCtrlPressed()) && !e.isAltPressed()) {
m_isStraight = true;
@ -1335,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);
@ -1476,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;
}
//-------------------------------------------------------------------------------------------------------------
@ -1488,21 +1465,28 @@ void ToonzRasterBrushTool::leftButtonDrag(const TPointD &pos,
return;
}
if ((e.isCtrlPressed() && e.isAltPressed()) ||
(e.isShiftPressed() && e.isAltPressed()) || m_addingAssistant) {
return;
}
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;
@ -1517,7 +1501,11 @@ void ToonzRasterBrushTool::leftButtonDrag(const TPointD &pos,
// now let's get the angle of each of the assistant points
std::vector<double> anglesToAssistants;
for (auto point : m_assistantPoints) {
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)) {
@ -1533,176 +1521,181 @@ void ToonzRasterBrushTool::leftButtonDrag(const TPointD &pos,
}
// figure out which angle is closer
TPointD pointToUse = TPointD(0.0, 0.0);
double difference = 360;
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 = m_assistantPoints.at(i);
}
}
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);
}
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;
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();
@ -1832,11 +1825,6 @@ void ToonzRasterBrushTool::leftButtonDrag(const TPointD &pos,
void ToonzRasterBrushTool::leftButtonUp(const TPointD &pos,
const TMouseEvent &e) {
if ((e.isAltPressed() && e.isCtrlPressed()) ||
(e.isShiftPressed() && e.isAltPressed()) || m_addingAssistant) {
m_addingAssistant = false;
return;
}
bool isValid = m_enabled && m_active;
m_enabled = false;
m_active = false;
@ -1844,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;
@ -1853,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;
}
//---------------------------------------------------------------------------------------------------------------
@ -2094,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;
@ -2193,34 +2181,6 @@ void ToonzRasterBrushTool::mouseMove(const TPointD &pos, const TMouseEvent &e) {
m_minThick = m_rasThickness.getValue().first;
m_maxThick = m_rasThickness.getValue().second;
}
if (e.isAltPressed() && e.isCtrlPressed() && !e.isShiftPressed()) {
if (m_highlightAssistant != -1 &&
m_highlightAssistant < m_assistantPoints.size()) {
TRectD pointRect =
TRectD(m_assistantPoints.at(m_highlightAssistant).x - 15,
m_assistantPoints.at(m_highlightAssistant).y - 15,
m_assistantPoints.at(m_highlightAssistant).x + 15,
m_assistantPoints.at(m_highlightAssistant).x + 15);
invalidate(pointRect);
}
m_highlightAssistant = -1;
for (int i = 0; i < m_assistantPoints.size(); i++) {
if (areAlmostEqual(m_assistantPoints.at(i).x, pos.x, 12) &&
areAlmostEqual(m_assistantPoints.at(i).y, pos.y, 12)) {
m_highlightAssistant = i;
break;
}
}
} else if (m_highlightAssistant != -1 &&
m_highlightAssistant < m_assistantPoints.size()) {
TRectD pointRect =
TRectD(m_assistantPoints.at(m_highlightAssistant).x - 15,
m_assistantPoints.at(m_highlightAssistant).y - 15,
m_assistantPoints.at(m_highlightAssistant).x + 15,
m_assistantPoints.at(m_highlightAssistant).x + 15);
invalidate(pointRect);
m_highlightAssistant = -1;
}
}
//-------------------------------------------------------------------------------------------------------------
@ -2229,21 +2189,6 @@ void ToonzRasterBrushTool::draw() {
if (m_isStraight) {
tglDrawSegment(m_firstPoint, m_lastPoint);
}
if (m_assistantPoints.size() > 0) {
for (int i = 0; i < m_assistantPoints.size(); i++) {
if (m_highlightAssistant == i) {
glColor3d(1.0, 0.0, 0.0);
tglDrawDisk(m_assistantPoints.at(i), 15.0);
} else {
glColor3d(0.0, 1.0, 0.0);
tglDrawCircle(m_assistantPoints.at(i), 5.0);
glColor3d(1.0, 1.0, 0.0);
tglDrawCircle(m_assistantPoints.at(i), 8.0);
}
}
}
if (m_minThick == 0 && m_maxThick == 0 &&
!Preferences::instance()->getShow0ThickLines())
return;
@ -2360,16 +2305,6 @@ void ToonzRasterBrushTool::setWorkAndBackupImages() {
m_strokeRect.empty();
m_lastRect.empty();
}
TXshLevelHandle *level = getApplication()->getCurrentLevel();
TXshSimpleLevel *sl;
if (level) sl = level->getSimpleLevel();
if (sl) {
if (sl->getProperties()->getVanishingPoints() != m_assistantPoints) {
m_assistantPoints = sl->getProperties()->getVanishingPoints();
invalidate();
}
}
}
//------------------------------------------------------------------
@ -2399,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()) {
@ -2537,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;

View file

@ -183,6 +183,7 @@ protected:
TBoolProperty m_pressure;
TDoubleProperty m_modifierSize;
TBoolProperty m_modifierLockAlpha;
TBoolProperty m_snapGrid;
RasterStrokeGenerator *m_rasterTrack;
TTileSetCM32 *m_tileSet;
@ -230,16 +231,14 @@ protected:
bool m_propertyUpdating = false;
bool m_isStraight = false;
std::vector<TPointD> m_assistantPoints;
bool m_addingAssistant = false;
bool m_snapAssistant = false;
int m_highlightAssistant = -1;
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 &centre,
bool horizontal, bool isDecimal);

View file

@ -43,6 +43,8 @@
#include "tgl.h"
#include "trop.h"
#include "perspectivetool.h"
#ifdef Q_OS_WIN
#include <WinUser.h> // for Sleep
#endif
@ -69,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);
//-------------------------------------------------------------------
@ -533,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();
@ -570,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);
@ -595,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");
}
//-------------------------------------------------------------------------------------------------------
@ -661,15 +668,6 @@ void ToonzVectorBrushTool::onActivate() {
}
resetFrameRange();
// TODO:app->editImageOrSpline();
TXshLevelHandle *level = getApplication()->getCurrentLevel();
TXshSimpleLevel *sl;
if (level) sl = level->getSimpleLevel();
if (sl) {
if (sl->getProperties()->getVanishingPoints() != m_assistantPoints) {
m_assistantPoints = sl->getProperties()->getVanishingPoints();
invalidate();
}
}
}
//--------------------------------------------------------------------------------------------------
@ -695,15 +693,6 @@ void ToonzVectorBrushTool::onDeactivate() {
//--------------------------------------------------------------------------------------------------
bool ToonzVectorBrushTool::preLeftButtonDown() {
TXshLevelHandle *level = getApplication()->getCurrentLevel();
TXshSimpleLevel *sl;
if (level) sl = level->getSimpleLevel();
if (sl) {
if (sl->getProperties()->getVanishingPoints() != m_assistantPoints) {
m_assistantPoints = sl->getProperties()->getVanishingPoints();
invalidate();
}
}
if (getViewer() && getViewer()->getGuidedStrokePickerMode()) return false;
touchImage();
@ -767,33 +756,6 @@ void ToonzVectorBrushTool::leftButtonDown(const TPointD &pos,
m_active = false;
return;
}
TXshSimpleLevelP simLevel;
if (!m_isPath && level) simLevel = level->getSimpleLevel();
if (!m_isPath && simLevel) {
m_assistantPoints = simLevel->getProperties()->getVanishingPoints();
if (e.isAltPressed() && e.isCtrlPressed() && !e.isShiftPressed()) {
m_addingAssistant = true;
bool deletedPoint = false;
for (int i = 0; i < m_assistantPoints.size(); i++) {
if (areAlmostEqual(m_assistantPoints.at(i).x, pos.x, 6) &&
areAlmostEqual(m_assistantPoints.at(i).y, pos.y, 6)) {
TRectD pointRect = TRectD(
m_assistantPoints.at(i).x - 15, m_assistantPoints.at(i).y - 15,
m_assistantPoints.at(i).x + 15, m_assistantPoints.at(i).x + 15);
m_assistantPoints.erase(m_assistantPoints.begin() + i);
deletedPoint = true;
invalidate(pointRect);
break;
}
}
if (!deletedPoint) m_assistantPoints.push_back(pos);
simLevel->getProperties()->setVanishingPoints(m_assistantPoints);
level->setDirtyFlag(true);
invalidate();
return;
}
}
m_firstPoint = pos;
m_lastPoint = pos;
@ -820,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;
}
//-------------------------------------------------------------------------------------------------------------
@ -831,64 +794,84 @@ void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos,
return;
}
if (!m_isPath &&
((e.isCtrlPressed() && e.isAltPressed() && !e.isShiftPressed()) ||
m_addingAssistant)) {
return;
}
TRectD invalidateRect;
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;
for (auto point : m_assistantPoints) {
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);
}
// figure out which angle is closer
PerspectiveTool *perspectiveTool = dynamic_cast<PerspectiveTool *>(
TTool::getTool("T_PerspectiveGrid", TTool::VectorImage));
std::vector<PerspectiveObject *> perspectiveObjs =
perspectiveTool->getPerspectiveObjects();
TPointD pointToUse = TPointD(0.0, 0.0);
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 = m_assistantPoints.at(i);
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);
// 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;
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);
}
// 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;
m_perspectiveIndex = i;
}
}
} else {
pointToUse =
perspectiveObjs.at(m_perspectiveIndex)->getReferencePoint(refPoint);
pointToUse.x /= dpiScale.x;
pointToUse.y /= dpiScale.y;
}
double distanceFirstToLast =
@ -918,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);
@ -930,7 +913,7 @@ void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos,
invalidateRect += (brushRect);
double denominator = m_lastPoint.x - m_firstPoint.x;
if (denominator == 0) denominator == 0.001;
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);
@ -978,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)
@ -1025,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();
}
@ -1058,13 +1042,6 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos,
return;
}
if (!m_isPath &&
((e.isAltPressed() && e.isCtrlPressed() && !e.isShiftPressed()) ||
m_addingAssistant)) {
m_addingAssistant = false;
return;
}
bool nonShiftStraight = false;
if ((e.isAltPressed() && !e.isCtrlPressed() && !e.isShiftPressed()) ||
(!e.isAltPressed() && e.isCtrlPressed() && !e.isShiftPressed())) {
@ -1114,8 +1091,7 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos,
notifyImageChanged();
TUndoManager::manager()->add(undo);
m_addingAssistant = false;
m_perspectiveIndex = -1;
return;
}
@ -1123,8 +1099,7 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos,
if (m_track.isEmpty()) {
m_styleId = 0;
m_track.clear();
m_addingAssistant = false;
m_perspectiveIndex = -1;
return;
}
@ -1278,7 +1253,7 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos,
assert(stroke);
m_track.clear();
m_toggleSnap = false;
m_addingAssistant = false;
m_perspectiveIndex = -1;
}
//--------------------------------------------------------------------------------------------------
@ -1609,34 +1584,6 @@ void ToonzVectorBrushTool::mouseMove(const TPointD &pos, const TMouseEvent &e) {
m_minThick = m_thickness.getValue().first;
m_maxThick = m_thickness.getValue().second;
}
if (e.isAltPressed() && e.isCtrlPressed() && !e.isShiftPressed()) {
if (m_highlightAssistant != -1 &&
m_highlightAssistant < m_assistantPoints.size()) {
TRectD pointRect =
TRectD(m_assistantPoints.at(m_highlightAssistant).x - 15,
m_assistantPoints.at(m_highlightAssistant).y - 15,
m_assistantPoints.at(m_highlightAssistant).x + 15,
m_assistantPoints.at(m_highlightAssistant).x + 15);
invalidate(pointRect);
}
m_highlightAssistant = -1;
for (int i = 0; i < m_assistantPoints.size(); i++) {
if (areAlmostEqual(m_assistantPoints.at(i).x, pos.x, 6) &&
areAlmostEqual(m_assistantPoints.at(i).y, pos.y, 6)) {
m_highlightAssistant = i;
break;
}
}
} else if (m_highlightAssistant != -1 &&
m_highlightAssistant < m_assistantPoints.size()) {
TRectD pointRect =
TRectD(m_assistantPoints.at(m_highlightAssistant).x - 15,
m_assistantPoints.at(m_highlightAssistant).y - 15,
m_assistantPoints.at(m_highlightAssistant).x + 15,
m_assistantPoints.at(m_highlightAssistant).x + 15);
invalidate(pointRect);
m_highlightAssistant = -1;
}
}
//-------------------------------------------------------------------------------------------------------------
@ -1815,20 +1762,6 @@ void ToonzVectorBrushTool::draw() {
}
}
if (m_assistantPoints.size() > 0) {
for (int i = 0; i < m_assistantPoints.size(); i++) {
if (m_highlightAssistant == i) {
glColor3d(1.0, 0.0, 0.0);
tglDrawDisk(m_assistantPoints.at(i), 8.0);
} else {
glColor3d(0.0, 1.0, 0.0);
tglDrawCircle(m_assistantPoints.at(i), 3.0);
glColor3d(1.0, 1.0, 0.0);
tglDrawCircle(m_assistantPoints.at(i), 5.0);
}
}
}
// frame range
if (m_firstStroke) {
glColor3d(1.0, 0.0, 0.0);
@ -1886,16 +1819,6 @@ void ToonzVectorBrushTool::onEnter() {
m_currentColor = TPixel32::Black;
}
m_active = img;
TXshLevelHandle *level = getApplication()->getCurrentLevel();
TXshSimpleLevel *sl;
if (level) sl = level->getSimpleLevel();
if (sl) {
if (sl->getProperties()->getVanishingPoints() != m_assistantPoints) {
m_assistantPoints = sl->getProperties()->getVanishingPoints();
invalidate();
}
}
}
//----------------------------------------------------------------------------------------------------------
@ -1985,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;
@ -2161,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;

View file

@ -163,6 +163,7 @@ protected:
TEnumProperty m_capStyle;
TEnumProperty m_joinStyle;
TIntProperty m_miterJoinLimit;
TBoolProperty m_snapGrid;
StrokeGenerator m_track;
StrokeGenerator m_rangeTrack;
@ -213,11 +214,10 @@ protected:
bool m_propertyUpdating = false;
std::vector<TPointD> m_assistantPoints;
bool m_addingAssistant = false;
TPointD m_firstPoint;
TPointD m_lastPoint;
int m_highlightAssistant = -1;
int m_perspectiveIndex = -1;
};
#endif // TOONZVECTORBRUSHTOOL_H

View file

@ -599,6 +599,7 @@ void FileBrowser::refreshCurrentFolderItems() {
it->getType() != "tnzbat" && it->getType() != "mpath" &&
it->getType() != "curve" && it->getType() != "tpl" &&
it->getType() != "macrofx" && it->getType() != "plugin" &&
it->getType() != "grid" &&
TFileType::getInfo(*it) == TFileType::UNKNOW_FILE)
continue;
} else if (!m_filter.contains(QString::fromStdString(it->getType())))

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<rect x="0" y="0" width="20" height="20" style="fill-opacity:0;"/>
<path d="M13.5,4.5L1.5,1.5L1.5,18L13.5,10.5L13.5,4.5Z" style="fill-opacity:0.2;"/>
<path d="M1,2.257L1,18C1,18.552 1.448,19 2,19C5.476,19 16.961,19 19.5,19C19.776,19 20,18.776 20,18.5C20,18.367 19.947,18.24 19.854,18.146C19.76,18.053 19.633,18 19.5,18C16.654,18 2.625,18 2.625,18L5.875,16L18.5,16C18.633,16 18.76,15.947 18.854,15.854C18.947,15.76 19,15.633 19,15.5C19,15.367 18.947,15.24 18.854,15.146C18.76,15.053 18.633,15 18.5,15C16.289,15 7.5,15 7.5,15L10.75,13L17.5,13C17.776,13 18,12.776 18,12.5C18,12.224 17.776,12 17.5,12C16.123,12 12.375,12 12.375,12L14,11L16.5,11C16.633,11 16.76,10.947 16.854,10.854C16.947,10.76 17,10.633 17,10.5C17,10.367 16.947,10.24 16.854,10.146C16.76,10.053 16.633,10 16.5,10C15.647,10 14,10 14,10L14,4.796C14,4.33 13.679,3.926 13.225,3.821C11.049,3.319 4.869,1.893 2.225,1.283C1.928,1.214 1.616,1.285 1.377,1.474C1.139,1.664 1,1.952 1,2.257ZM6,14.749L6,9.257L2,9.924L2,17.21L6,14.749ZM7,9.09L7,14.134L10,12.287L10,8.59L7,9.09ZM13,8.09L11,8.424L11,11.672L13,10.441L13,8.09ZM2,8.91L6,8.243L6,3.18L2,2.257L2,8.91ZM7,8.076L10,7.576L10,4.103L7,3.411L7,8.076ZM11,4.334L11,7.41L13,7.076L13,4.796L11,4.334Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -756,6 +756,15 @@ int main(int argc, char *argv[]) {
QString currentStyle = Preferences::instance()->getCurrentStyleSheetPath();
a.setStyleSheet(currentStyle);
// Perspective grid tool - custom grid
splash.showMessage(offsetStr + "Loading Perspective Grid...",
Qt::AlignRight | Qt::AlignBottom, Qt::black);
a.processEvents();
TTool *perspectiveTool =
TTool::getTool(T_PerspectiveGrid, TTool::VectorImage);
if (perspectiveTool) perspectiveTool->loadTool();
w.setWindowTitle(QString::fromStdString(TEnv::getApplicationFullName()));
if (TEnv::getIsPortable()) {
splash.showMessage(offsetStr + "Starting Tahoma2D...",

View file

@ -703,6 +703,11 @@ void MainWindow::writeSettings() {
Tofstream os(ToonzFolder::getMyRoomsDir() + currentRoomFileName);
os << getCurrentRoom()->getName().toStdString();
// Perspective grid tool - custom grid
TTool *perspectiveTool =
TTool::getTool(T_PerspectiveGrid, TTool::VectorImage);
if (perspectiveTool) perspectiveTool->saveTool();
// Main window settings
TFilePath fp = ToonzFolder::getMyModuleDir() + TFilePath("mainwindow.ini");
QSettings settings(toQString(fp), QSettings::IniFormat);
@ -2557,6 +2562,9 @@ void MainWindow::defineActions() {
"animate a level"));
createToolAction(T_Ruler, "ruler", QT_TR_NOOP("Ruler Tool"), "",
tr("Ruler Tool: Measure distances on the canvas"));
createToolAction(T_PerspectiveGrid, "perspective_grid",
QT_TR_NOOP("Perspective Grid Tool"), "",
tr("Perspective Grid Tool: Set up perspective grids"));
createToolAction(T_Finger, "finger", QT_TR_NOOP("Finger Tool"), "",
tr("Finger Tool: Smudges small areas to cover with line"));

View file

@ -9,12 +9,15 @@
#include "saveloadqsettings.h"
#include "toonzqt/gutil.h"
#include "toonzqt/dvdialog.h"
// TnzLib includes
#include "toonz/preferences.h"
#include "toonz/toonzfolders.h"
#include "toonz/tscenehandle.h"
#include "tools/toolhandle.h"
// TnzCore includes
#include "tsystem.h"
@ -40,29 +43,11 @@
extern TEnv::StringVar EnvSafeAreaName;
extern TEnv::IntVar CameraViewTransparency;
extern TEnv::IntVar IsometricLeftAngle;
extern TEnv::IntVar IsometricRightAngle;
extern TEnv::IntVar IsometricLeftStep;
extern TEnv::IntVar IsometricRightStep;
extern TEnv::IntVar ShowRuleOfThirds;
extern TEnv::IntVar ShowGoldenRatio;
extern TEnv::IntVar ShowIsometricGrid;
extern TEnv::IntVar ShowHorizontalGrid;
extern TEnv::IntVar ShowVerticalGrid;
extern TEnv::IntVar VerticalSpacing;
extern TEnv::IntVar HorizontalSpacing;
extern TEnv::IntVar ShowFieldGuide;
extern TEnv::IntVar GuideOpacity;
extern TEnv::IntVar HorizontalOffset;
extern TEnv::IntVar VerticalOffset;
extern TEnv::IntVar ShowHorizon;
extern TEnv::IntVar HorizonAngle;
extern TEnv::IntVar HorizonStep;
extern TEnv::IntVar HorizonOffset;
extern TEnv::IntVar ShowVanishingPointRays;
extern TEnv::IntVar VanishingPointRayAngles;
extern TEnv::IntVar VanishingPointRayOpacity;
extern TEnv::IntVar ShowPerspectiveGrids;
//=============================================================================
// TPanel
//-----------------------------------------------------------------------------
@ -452,309 +437,18 @@ TPanelTitleBarButtonForGrids::TPanelTitleBarButtonForGrids(
emit updateViewer();
});
QGroupBox* vanishingCheckbox = new QGroupBox(tr("Vanishing Point Rays"), this);
vanishingCheckbox->setCheckable(true);
vanishingCheckbox->setChecked(ShowVanishingPointRays != 0);
connect(vanishingCheckbox, &QGroupBox::toggled, [=](bool value) {
ShowVanishingPointRays = value == true ? 1 : 0;
emit updateViewer();
});
QSlider* vanishingAngleSlider = new QSlider(this);
vanishingAngleSlider->setRange(5, 90);
vanishingAngleSlider->setValue(VanishingPointRayAngles);
vanishingAngleSlider->setOrientation(Qt::Horizontal);
vanishingAngleSlider->setMinimumWidth(300);
QLabel* vanishingAngleLabel = new QLabel(this);
vanishingAngleLabel->setText(tr("Angle: ") +
QString::number(VanishingPointRayAngles));
connect(vanishingAngleSlider, &QSlider::valueChanged, [=](int value) {
VanishingPointRayAngles = value;
vanishingAngleLabel->setText(tr("Angle: ") +
QString::number(VanishingPointRayAngles));
emit updateViewer();
});
QSlider* vanishingOpacitySlider = new QSlider(this);
vanishingOpacitySlider->setRange(1, 100);
vanishingOpacitySlider->setValue(VanishingPointRayOpacity);
vanishingOpacitySlider->setOrientation(Qt::Horizontal);
QLabel* vanishingOpacityLabel = new QLabel(this);
vanishingOpacityLabel->setText(tr("Opacity: ") +
QString::number(VanishingPointRayOpacity));
connect(vanishingOpacitySlider, &QSlider::valueChanged, [=](int value) {
VanishingPointRayOpacity = value;
vanishingOpacityLabel->setText(tr("Opacity: ") +
QString::number(VanishingPointRayOpacity));
emit updateViewer();
});
QGridLayout* vanishingLayout = new QGridLayout(this);
vanishingLayout->addWidget(vanishingAngleLabel, 0, 0, Qt::AlignRight);
vanishingAngleLabel->setFixedWidth(110);
vanishingAngleLabel->setAlignment(Qt::AlignRight);
vanishingLayout->addWidget(vanishingAngleSlider, 0, 1);
vanishingLayout->addWidget(vanishingOpacityLabel, 1, 0, Qt::AlignRight);
vanishingLayout->addWidget(vanishingOpacitySlider, 1, 1);
vanishingCheckbox->setLayout(vanishingLayout);
QGroupBox *horizontalCheckbox = new QGroupBox(tr("Horizontal Grid"), this);
horizontalCheckbox->setCheckable(true);
horizontalCheckbox->setChecked(ShowHorizontalGrid != 0);
connect(horizontalCheckbox, &QGroupBox::toggled, [=](bool value) {
ShowHorizontalGrid = value == true ? 1 : 0;
QCheckBox *perspectiveCheckbox = new QCheckBox(tr("Perspective Grids"), this);
perspectiveCheckbox->setChecked(ShowPerspectiveGrids != 0);
connect(perspectiveCheckbox, &QCheckBox::stateChanged, [=](int value) {
ShowPerspectiveGrids = value > 0 ? 1 : 0;
emit updateViewer();
});
QSlider *horizontalSpacingSlider = new QSlider(this);
horizontalSpacingSlider->setRange(10, 250);
horizontalSpacingSlider->setValue(HorizontalSpacing);
horizontalSpacingSlider->setOrientation(Qt::Horizontal);
QLabel *horizontalSpacingLabel = new QLabel(this);
horizontalSpacingLabel->setText(tr("Spacing: ") +
QString::number(HorizontalSpacing));
connect(horizontalSpacingSlider, &QSlider::valueChanged, [=](int value) {
HorizontalSpacing = value;
horizontalSpacingLabel->setText(tr("Spacing: ") +
QString::number(HorizontalSpacing));
emit updateViewer();
});
QSlider *horizontalOffsetSlider = new QSlider(this);
horizontalOffsetSlider->setRange(-100, 100);
horizontalOffsetSlider->setValue(HorizontalOffset);
horizontalOffsetSlider->setOrientation(Qt::Horizontal);
QLabel *horizontalOffsetLabel = new QLabel(this);
horizontalOffsetLabel->setText(tr("Offset: ") +
QString::number(HorizontalOffset));
connect(horizontalOffsetSlider, &QSlider::valueChanged, [=](int value) {
HorizontalOffset = value;
horizontalOffsetLabel->setText(tr("Offset: ") +
QString::number(HorizontalOffset));
emit updateViewer();
});
QGridLayout *horizontalLayout = new QGridLayout(this);
horizontalLayout->addWidget(horizontalSpacingLabel, 0, 0, Qt::AlignRight);
horizontalSpacingLabel->setFixedWidth(110);
horizontalSpacingLabel->setAlignment(Qt::AlignRight);
horizontalLayout->addWidget(horizontalSpacingSlider, 0, 1);
horizontalLayout->addWidget(horizontalOffsetLabel, 1, 0, Qt::AlignRight);
horizontalLayout->addWidget(horizontalOffsetSlider, 1, 1);
horizontalCheckbox->setLayout(horizontalLayout);
QGroupBox *verticalCheckbox = new QGroupBox(tr("Vertical Grid"), this);
verticalCheckbox->setCheckable(true);
verticalCheckbox->setChecked(ShowVerticalGrid != 0);
connect(verticalCheckbox, &QGroupBox::toggled, [=](bool value) {
ShowVerticalGrid = value == true ? 1 : 0;
emit updateViewer();
});
QSlider *verticalSpacingSlider = new QSlider(this);
verticalSpacingSlider->setRange(10, 250);
verticalSpacingSlider->setValue(VerticalSpacing);
verticalSpacingSlider->setOrientation(Qt::Horizontal);
verticalSpacingSlider->setMinimumWidth(300);
QLabel *verticalSpacingLabel = new QLabel(this);
verticalSpacingLabel->setText(tr("Spacing: ") +
QString::number(VerticalSpacing));
connect(verticalSpacingSlider, &QSlider::valueChanged, [=](int value) {
VerticalSpacing = value;
verticalSpacingLabel->setText(tr("Spacing: ") +
QString::number(VerticalSpacing));
emit updateViewer();
});
QSlider *verticalOffsetSlider = new QSlider(this);
verticalOffsetSlider->setRange(-100, 100);
verticalOffsetSlider->setValue(VerticalOffset);
verticalOffsetSlider->setOrientation(Qt::Horizontal);
QLabel *verticalOffsetLabel = new QLabel(this);
verticalOffsetLabel->setText(tr("Offset: ") +
QString::number(VerticalOffset));
connect(verticalOffsetSlider, &QSlider::valueChanged, [=](int value) {
VerticalOffset = value;
verticalOffsetLabel->setText(tr("Offset: ") +
QString::number(VerticalOffset));
emit updateViewer();
});
QGridLayout *verticalLayout = new QGridLayout(this);
verticalLayout->addWidget(verticalSpacingLabel, 0, 0, Qt::AlignRight);
verticalSpacingLabel->setFixedWidth(110);
verticalSpacingLabel->setAlignment(Qt::AlignRight);
verticalLayout->addWidget(verticalSpacingSlider, 0, 1);
verticalLayout->addWidget(verticalOffsetLabel, 1, 0, Qt::AlignRight);
verticalLayout->addWidget(verticalOffsetSlider, 1, 1);
verticalCheckbox->setLayout(verticalLayout);
QGroupBox* horizonCheckbox = new QGroupBox(tr("Horizon"), this);
horizonCheckbox->setCheckable(true);
horizonCheckbox->setChecked(ShowHorizon != 0);
connect(horizonCheckbox, &QGroupBox::toggled, [=](bool value) {
ShowHorizon = value == true ? 1 : 0;
emit updateViewer();
});
QSlider* horizonAngleSlider = new QSlider(this);
horizonAngleSlider->setRange(-90, 90);
horizonAngleSlider->setValue(HorizonAngle);
horizonAngleSlider->setOrientation(Qt::Horizontal);
horizonAngleSlider->setMinimumWidth(300);
QLabel* horizonAngleLabel = new QLabel(this);
horizonAngleLabel->setText(tr("Angle: ") +
QString::number(HorizonAngle));
connect(horizonAngleSlider, &QSlider::valueChanged, [=](int value) {
HorizonAngle = value;
horizonAngleLabel->setText(tr("Angle: ") +
QString::number(HorizonAngle));
emit updateViewer();
});
QSlider* horizonStepSlider = new QSlider(this);
horizonStepSlider->setRange(2, 100);
horizonStepSlider->setValue(HorizonStep);
horizonStepSlider->setOrientation(Qt::Horizontal);
QLabel* horizonStepLabel = new QLabel(this);
horizonStepLabel->setText(tr("Step: ") +
QString::number(HorizonStep));
connect(horizonStepSlider, &QSlider::valueChanged, [=](int value) {
HorizonStep = value;
horizonStepLabel->setText(tr("Step: ") +
QString::number(HorizonStep));
emit updateViewer();
});
QSlider* horizonOffsetSlider = new QSlider(this);
horizonOffsetSlider->setRange(-1000, 1000);
horizonOffsetSlider->setValue(HorizonOffset);
horizonOffsetSlider->setOrientation(Qt::Horizontal);
QLabel* horizonOffsetLabel = new QLabel(this);
horizonOffsetLabel->setText(tr("Offset: ") +
QString::number(HorizonOffset));
connect(horizonOffsetSlider, &QSlider::valueChanged, [=](int value) {
HorizonOffset = value;
horizonOffsetLabel->setText(tr("Offset: ") +
QString::number(HorizonOffset));
emit updateViewer();
});
QGridLayout* horizonLayout = new QGridLayout(this);
horizonLayout->addWidget(horizonAngleLabel, 0, 0, Qt::AlignRight);
horizonAngleLabel->setFixedWidth(110);
horizonAngleLabel->setAlignment(Qt::AlignRight);
horizonLayout->addWidget(horizonAngleSlider, 0, 1);
horizonLayout->addWidget(horizonStepLabel, 1, 0, Qt::AlignRight);
horizonLayout->addWidget(horizonStepSlider, 1, 1);
horizonLayout->addWidget(horizonOffsetLabel, 2, 0, Qt::AlignRight);
horizonLayout->addWidget(horizonOffsetSlider, 2, 1);
horizonCheckbox->setLayout(horizonLayout);
QGroupBox *isometricCheckbox = new QGroupBox(tr("Isometric Grid"), this);
isometricCheckbox->setCheckable(true);
isometricCheckbox->setChecked(ShowIsometricGrid != 0);
connect(isometricCheckbox, &QGroupBox::toggled, [=](int value) {
ShowIsometricGrid = value == true ? 1 : 0;
emit updateViewer();
});
QSlider *leftAngleSlider = new QSlider(this);
leftAngleSlider->setRange(10, 89);
leftAngleSlider->setValue(IsometricLeftAngle);
leftAngleSlider->setOrientation(Qt::Horizontal);
QLabel *leftAngleLabel = new QLabel(this);
leftAngleLabel->setText(tr("Left Angle: ") +
QString::number(IsometricLeftAngle));
connect(leftAngleSlider, &QSlider::valueChanged, [=](int value) {
IsometricLeftAngle = value;
leftAngleLabel->setText(tr("Left Angle: ") +
QString::number(IsometricLeftAngle));
emit updateViewer();
});
QSlider *rightAngleSlider = new QSlider(this);
rightAngleSlider->setRange(10, 89);
rightAngleSlider->setValue(IsometricRightAngle);
rightAngleSlider->setOrientation(Qt::Horizontal);
QLabel *rightAngleLabel = new QLabel(this);
rightAngleLabel->setText(tr("Right Angle: ") +
QString::number(IsometricRightAngle));
connect(rightAngleSlider, &QSlider::valueChanged, [=](int value) {
IsometricRightAngle = value;
rightAngleLabel->setText(tr("Right Angle: ") +
QString::number(IsometricRightAngle));
emit updateViewer();
});
QSlider *leftStepSlider = new QSlider(this);
leftStepSlider->setRange(1, 100);
leftStepSlider->setValue(IsometricLeftStep / 5);
leftStepSlider->setOrientation(Qt::Horizontal);
QLabel *leftStepLabel = new QLabel(this);
leftStepLabel->setText(tr("Left Spacing: ") +
QString::number(IsometricLeftStep));
connect(leftStepSlider, &QSlider::valueChanged, [=](int value) {
IsometricLeftStep = value * 5;
leftStepLabel->setText(tr("Left Spacing: ") +
QString::number(IsometricLeftStep));
emit updateViewer();
});
QSlider *rightStepSlider = new QSlider(this);
rightStepSlider->setRange(1, 100);
rightStepSlider->setValue(IsometricRightStep / 5);
rightStepSlider->setOrientation(Qt::Horizontal);
QLabel *rightStepLabel = new QLabel(this);
rightStepLabel->setText(tr("Right Spacing: ") +
QString::number(IsometricRightStep));
connect(rightStepSlider, &QSlider::valueChanged, [=](int value) {
IsometricRightStep = value * 5;
rightStepLabel->setText(tr("Right Spacing: ") +
QString::number(IsometricRightStep));
emit updateViewer();
});
QGridLayout *isometricLayout = new QGridLayout(this);
leftAngleLabel->setFixedWidth(110);
leftAngleLabel->setAlignment(Qt::AlignRight);
isometricLayout->addWidget(leftAngleLabel, 0, 0, Qt::AlignRight);
isometricLayout->addWidget(leftAngleSlider, 0, 1);
isometricLayout->addWidget(leftStepLabel, 1, 0, Qt::AlignRight);
isometricLayout->addWidget(leftStepSlider, 1, 1);
isometricLayout->addWidget(rightAngleLabel, 2, 0, Qt::AlignRight);
isometricLayout->addWidget(rightAngleSlider, 2, 1);
isometricLayout->addWidget(rightStepLabel, 3, 0, Qt::AlignRight);
isometricLayout->addWidget(rightStepSlider, 3, 1);
isometricCheckbox->setLayout(isometricLayout);
QSlider *guideOpacitySlider = new QSlider(this);
guideOpacitySlider->setRange(10, 100);
guideOpacitySlider->setValue(GuideOpacity);
guideOpacitySlider->setOrientation(Qt::Horizontal);
QLabel *guideOpacityLabel = new QLabel(this);
guideOpacityLabel->setText(tr("Opacity: ") + QString::number(GuideOpacity));
connect(guideOpacitySlider, &QSlider::valueChanged, [=](int value) {
GuideOpacity = value;
guideOpacityLabel->setText(tr("Opacity: ") + QString::number(GuideOpacity));
emit updateViewer();
});
});
gridLayout->addWidget(thirdsCheckbox, 0, 0, 1, 2);
gridLayout->addWidget(goldenRationCheckbox, 1, 0, 1, 2);
gridLayout->addWidget(fieldGuideCheckbox, 2, 0, 1, 2);
gridLayout->addWidget(horizontalCheckbox, 3, 0, 1, 2);
gridLayout->addWidget(verticalCheckbox, 4, 0, 1, 2);
gridLayout->addWidget(perspectiveCheckbox, 3, 0, 1, 2);
gridLayout->addWidget(horizonCheckbox, 5, 0, 1, 2);
gridLayout->addWidget(isometricCheckbox, 6, 0, 1, 2);
gridLayout->addWidget(guideOpacityLabel, 7, 0);
gridLayout->addWidget(guideOpacitySlider, 7, 1);
gridLayout->addWidget(vanishingCheckbox, 8, 0, 1, 2);
gridWidget->setLayout(gridLayout);
gridsAction->setDefaultWidget(gridWidget);
m_menu->addAction(gridsAction);

View file

@ -1782,22 +1782,22 @@ void SceneViewer::drawOverlay() {
// draw tool gadgets
TTool *tool = app->getCurrentTool()->getTool();
TXshSimpleLevel *sl = app->getCurrentLevel()->getSimpleLevel();
if (sl) {
std::vector<TPointD> assistantPoints =
sl->getProperties()->getVanishingPoints();
if (!m_draw3DMode && assistantPoints.size() > 0) {
if (tool->getToolType() & TTool::LevelTool &&
!app->getCurrentObject()->isSpline() &&
(tool->getName() == "T_Brush" || tool->getName() == "T_Geometric")) {
glPushMatrix();
tglMultMatrix(getViewMatrix() * tool->getMatrix());
glScaled(m_dpiScale.x, m_dpiScale.y, 1);
ViewerDraw::drawPerspectiveGuides(this, m_viewAff[m_viewMode].det(),
assistantPoints);
glPopMatrix();
}
}
TTool *perspectiveTool =
TTool::getTool(T_PerspectiveGrid, TTool::VectorImage);
if (tool && perspectiveTool &&
((fieldGuideToggle.getStatus() && ShowPerspectiveGrids) ||
tool == perspectiveTool)) {
glPushMatrix();
if (m_draw3DMode) {
mult3DMatrix();
tglMultMatrix(tool->getCurrentColumnMatrix());
} else
tglMultMatrix(getViewMatrix() * tool->getCurrentColumnMatrix());
perspectiveTool->draw(this);
glPopMatrix();
}
// Call tool->draw() even if the level is read only (i.e. to show hooks)
if (tool && (tool->isEnabled() || (sl && sl->isReadOnly()))) {
// tool->setViewer(this); // Moved at
@ -1808,6 +1808,7 @@ void SceneViewer::drawOverlay() {
tglMultMatrix(tool->getMatrix());
} else
tglMultMatrix(getViewMatrix() * tool->getMatrix());
if (tool->getToolType() & TTool::LevelTool &&
!app->getCurrentObject()->isSpline())
glScaled(m_dpiScale.x, m_dpiScale.y, 1);

View file

@ -191,11 +191,7 @@ std::unordered_map<std::string, QString> StatusBar::makeMap(
.arg(trModKey("Ctrl"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Add / Remove Vanishing Point")
.arg(trModKey("Ctrl+Alt"))
.arg(cmdTextSeparator) +
spacer +
tr("%1%2Draw to Vanishing Point")
tr("%1%2Snap to Perspective Grid")
.arg(trModKey("Alt"))
.arg(cmd2TextSeparator) +
spacer +
@ -212,11 +208,7 @@ std::unordered_map<std::string, QString> StatusBar::makeMap(
.arg(trModKey("Ctrl"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Add / Remove Vanishing Point")
.arg(trModKey("Ctrl+Alt"))
.arg(cmdTextSeparator) +
spacer +
tr("%1%2Draw to Vanishing Point")
tr("%1%2Snap to Perspective Grid")
.arg(trModKey("Alt"))
.arg(cmd2TextSeparator)});
lMap.insert({"T_BrushRaster",
@ -229,11 +221,7 @@ std::unordered_map<std::string, QString> StatusBar::makeMap(
.arg(trModKey("Ctrl"))
.arg(cmd2TextSeparator) +
spacer +
tr("%1%2Add / Remove Vanishing Point")
.arg(trModKey("Ctrl+Alt"))
.arg(cmdTextSeparator) +
spacer +
tr("%1%2Draw to Vanishing Point")
tr("%1%2Snap to Perspective Grid")
.arg(trModKey("Alt"))
.arg(cmd2TextSeparator)});
lMap.insert({"T_Geometric", tr("Geometry Tool: Draws geometric shapes")});
@ -356,6 +344,23 @@ std::unordered_map<std::string, QString> StatusBar::makeMap(
lMap.insert({"T_Zoom", tr("Zoom Tool: Zooms viewer")});
lMap.insert({"T_Rotate", tr("Rotate Tool: Rotate the workspace")});
lMap.insert({"T_Ruler", tr("Ruler Tool: Measures distances on the canvas")});
lMap.insert({"T_PerspectiveGrid",
tr("Perspective Grid Tool: Set up perspective grids") + spacer +
tr("%1%2Move entire object")
.arg(trModKey("Shift"))
.arg(cmdTextSeparator) +
spacer +
tr("%1%2Select/Deselect multiple")
.arg(trModKey("Ctrl"))
.arg(cmdTextSeparator) +
spacer +
tr("%1%2Snap rotation/spacing")
.arg(trModKey("Alt"))
.arg(cmdTextSeparator) +
spacer +
tr("%1%2Move object along horizon")
.arg(trModKey("Shift+Alt"))
.arg(cmdTextSeparator)});
lMap.insert(
{"T_Finger", tr("Finger Tool: Smudges small areas to cover with line")});
lMap.insert({"T_Dummy", tr("This tool doesn't work on this layer type.")});

View file

@ -23,7 +23,7 @@ class Toolbar final : public QToolBar {
bool isSeparator;
bool collapsible;
QAction *action;
} m_buttonLayout[33] = {
} m_buttonLayout[34] = {
{T_Edit, false, false, 0}, {T_Selection, false, false, 0},
{"Separator_1", true, false, 0}, {T_Brush, false, false, 0},
{T_Geometric, false, false, 0}, {T_Type, false, true, 0},
@ -31,7 +31,8 @@ class Toolbar final : public QToolBar {
{"Separator_2", true, false, 0}, {T_Eraser, false, false, 0},
{T_Tape, false, false, 0}, //{T_Finger, false, false, 0},
{"Separator_3", true, false, 0}, {T_StylePicker, false, false, 0},
{T_RGBPicker, false, false, 0}, {T_Ruler, false, false, 0},
{T_RGBPicker, false, false, 0}, {T_PerspectiveGrid, false, false, 0},
{T_Ruler, false, false, 0},
{"Separator_4", true, false, 0}, {T_ControlPointEditor, false, false, 0},
{T_Pinch, false, true, 0}, {T_Pump, false, true, 0},
{T_Magnet, false, true, 0}, {T_Bender, false, true, 0},

View file

@ -32,6 +32,7 @@ private:
void visit(TEnumProperty* p) override;
void visit(TStyleIndexProperty* p) override {}
void visit(TPointerProperty* p) override {}
void visit(TColorChipProperty* p) override {}
};
//=============================================================================

View file

@ -26,6 +26,7 @@
<file>icons/dark/tools/20/plastic.svg</file>
<file>icons/dark/tools/20/pump.svg</file>
<file>icons/dark/tools/20/ruler.svg</file>
<file>icons/dark/tools/20/perspective_grid.svg</file>
<file>icons/dark/tools/20/selection.svg</file>
<file>icons/dark/tools/20/skeleton.svg</file>
<file>icons/dark/tools/20/type.svg</file>

View file

@ -37,28 +37,10 @@
TEnv::StringVar EnvSafeAreaName("SafeAreaName", "PR_safe");
TEnv::IntVar CameraViewTransparency("CameraViewTransparency", 100);
TEnv::IntVar IsometricLeftAngle("IsometricLeftAngle", 30);
TEnv::IntVar IsometricRightAngle("IsometricRightAngle", 30);
TEnv::IntVar IsometricLeftStep("IsometricLeftStep", 100);
TEnv::IntVar IsometricRightStep("IsometricRightStep", 100);
TEnv::IntVar ShowRuleOfThirds("ShowRuleOfThirds", 1);
TEnv::IntVar ShowGoldenRatio("ShowGoldenRatio", 0);
TEnv::IntVar ShowIsometricGrid("ShowIsometricGrid", 0);
TEnv::IntVar ShowVerticalGrid("ShowVerticalGrid", 0);
TEnv::IntVar ShowHorizontalGrid("ShowHorizontalGrid", 0);
TEnv::IntVar VerticalSpacing("VerticalSpacing", 100);
TEnv::IntVar HorizontalSpacing("HorizontalSpacing", 100);
TEnv::IntVar HorizontalOffset("HorizontalOffset", 0);
TEnv::IntVar VerticalOffset("VerticalOffset", 0);
TEnv::IntVar ShowFieldGuide("ShowFieldGuide", 0);
TEnv::IntVar GuideOpacity("GuideOpacity", 70);
TEnv::IntVar ShowHorizon("ShowHorizon", 0);
TEnv::IntVar HorizonAngle("HorizonAngle", 0);
TEnv::IntVar HorizonStep("HorizonStep", 5);
TEnv::IntVar HorizonOffset("HorizonOffset", 0);
TEnv::IntVar ShowVanishingPointRays("ShowVanishingPointRays", 1);
TEnv::IntVar VanishingPointRayAngles("VanishingPointRayAngles", 10);
TEnv::IntVar VanishingPointRayOpacity("VanishingPointRayOpacity", 35);
/* TODO, move to include */
void getSafeAreaSizeList(QList<QList<double>> &_sizeList);
@ -400,81 +382,6 @@ void ViewerDraw::drawGridAndGuides(SceneViewer *viewer, double sc, Ruler *vr,
//-----------------------------------------------------------------------------
void ViewerDraw::drawPerspectiveGuides(SceneViewer *viewer, double sc,
std::vector<TPointD> assistantPoints) {
if (ShowVanishingPointRays == 0) return;
int x1, x2, y1, y2;
viewer->rect().getCoords(&x1, &y1, &x2, &y2);
TRect clipRect = TRect(x1, y1, x2 + 1, y2 + 1);
GLfloat modelView[16];
glGetFloatv(GL_MODELVIEW_MATRIX, modelView);
TAffine modelViewAff(modelView[0], modelView[4], modelView[12], modelView[1],
modelView[5], modelView[13]);
TRectD cameraRect = getCameraRect();
TPointD clipCorner[] = {
modelViewAff.inv() * TPointD(clipRect.x0, clipRect.y0),
modelViewAff.inv() * TPointD(clipRect.x1, clipRect.y0),
modelViewAff.inv() * TPointD(clipRect.x1, clipRect.y1),
modelViewAff.inv() * TPointD(clipRect.x0, clipRect.y1)};
TRectD bounds;
bounds.x0 = bounds.x1 = clipCorner[0].x;
bounds.y0 = bounds.y1 = clipCorner[0].y;
int i;
for (i = 1; i < 4; i++) {
const TPointD &p = clipCorner[i];
if (p.x < bounds.x0)
bounds.x0 = p.x;
else if (p.x > bounds.x1)
bounds.x1 = p.x;
if (p.y < bounds.y0)
bounds.y0 = p.y;
else if (p.y > bounds.y1)
bounds.y1 = p.y;
}
double interval = 150;
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
std::vector<double> reds{0.0, 0.7, 1.0, 0.0, 0.3};
std::vector<double> greens{0.0, 0.0, 0.0, 0.4, 0.3};
std::vector<double> blues{1.0, 0.7, 0.0, 0.0, 0.3};
for (int j = 0; j < assistantPoints.size(); j++) {
TPointD p = assistantPoints.at(j);
if (j < 5)
glColor4d(reds.at(j), greens.at(j), blues.at(j),
(double)VanishingPointRayOpacity / 100.0);
TPointD end;
double distanceToLeft = std::abs(p.x - bounds.x0);
double distanceToRight = std::abs(p.x - bounds.x1);
double distanceToTop = std::abs(p.y - bounds.y1);
double distanceToBottom = std::abs(p.y - bounds.y0);
double xDistance = std::max(distanceToLeft, distanceToRight);
double yDistance = std::max(distanceToTop, distanceToBottom);
double totalDistance =
std::sqrt(std::pow(xDistance, 2) + std::pow(yDistance, 2));
for (int i = 0; i < 360; i += VanishingPointRayAngles) {
double yLength = std::sin(i * (3.14159 / 180)) * totalDistance;
double xLength = std::cos(i * (3.14159 / 180)) * totalDistance;
end.x = p.x + xLength;
end.y = p.y + yLength;
tglDrawSegment(p, end);
}
}
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
}
//-----------------------------------------------------------------------------
void ViewerDraw::drawColorcard(UCHAR channel) {
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
TRectD rect = getCameraRect();
@ -731,158 +638,6 @@ void ViewerDraw::drawGridsAndOverlays(SceneViewer *viewer, double pixelSize) {
double phiX = (rect.x1 - rect.x0) / 1.618;
double phiY = (rect.y1 - rect.y0) / 1.618;
if (ShowVerticalGrid) {
tglDrawSegment(TPointD(rect.x0 + halfX + (VerticalOffset /
Stage::standardDpi * Stage::inch),
bounds.y0),
TPointD(rect.x0 + halfX + (VerticalOffset /
Stage::standardDpi * Stage::inch),
bounds.y1));
int step = std::max(1, (int)VerticalSpacing);
double currentX = rect.x0 + halfX;
for (int i = 1; currentX > bounds.x0; i++) {
currentX = (rect.x0 + halfX) - ((step * i - VerticalOffset) /
Stage::standardDpi * Stage::inch);
glBegin(GL_LINES);
glVertex2d(currentX, bounds.y0);
glVertex2d(currentX, bounds.y1);
glEnd();
}
currentX = rect.x0 + halfX;
for (int i = 1; currentX < bounds.x1; i++) {
currentX = (rect.x0 + halfX) + ((step * i + VerticalOffset) /
Stage::standardDpi * Stage::inch);
glBegin(GL_LINES);
glVertex2d(currentX, bounds.y0);
glVertex2d(currentX, bounds.y1);
glEnd();
}
}
if (ShowHorizontalGrid) {
tglDrawSegment(
TPointD(bounds.x0,
rect.y0 + halfY +
(HorizontalOffset / Stage::standardDpi * Stage::inch)),
TPointD(bounds.x1,
rect.y0 + halfY +
(HorizontalOffset / Stage::standardDpi * Stage::inch)));
int step = std::max(1, (int)HorizontalSpacing);
double currentY = rect.y0 + halfY;
for (int i = 1; currentY > bounds.y0; i++) {
currentY = rect.y0 + halfY - ((step * i - HorizontalOffset) /
Stage::standardDpi * Stage::inch);
// double xInPixels =
glBegin(GL_LINES);
glVertex2d(bounds.x0, currentY);
glVertex2d(bounds.x1, currentY);
glEnd();
}
currentY = rect.y0 + halfY;
for (int i = 1; currentY < bounds.y1; i++) {
currentY = rect.y0 + halfY + ((step * i + HorizontalOffset) /
Stage::standardDpi * Stage::inch);
glBegin(GL_LINES);
glVertex2d(bounds.x0, currentY);
glVertex2d(bounds.x1, currentY);
glEnd();
}
}
if (ShowHorizon) {
double theta = (double)HorizonAngle * (3.14159 / 180);
double step = HorizonStep;
double run = std::cos(theta) * step;
double rise = std::sin(theta) * step;
double slope = rise / run;
double distance = step;
{
// find the first y value
double startY = (slope * bounds.x0) + (HorizonOffset / Stage::standardDpi * Stage::inch);
double endY = (slope * bounds.x1) + (HorizonOffset / Stage::standardDpi * Stage::inch);
if (slope == 0.0) {
startY = (rect.y0 + ((rect.y1 - rect.y0) / 2)) + (HorizonOffset / Stage::standardDpi * Stage::inch);
endY = startY;
}
double i = 1.5;
while (endY > bounds.y0 || startY > bounds.y0) {
glBegin(GL_LINES);
glVertex2d(bounds.x0, startY);
glVertex2d(bounds.x1, endY);
glEnd();
endY -= distance / Stage::standardDpi * Stage::inch;
startY -= distance / Stage::standardDpi * Stage::inch;
distance += step * i;
step = step * i;
}
}
}
if (ShowIsometricGrid) {
double rightTheta = (double)IsometricRightAngle * (3.14159 / 180);
double rightStep = IsometricRightStep;
double rightRun = std::cos(rightTheta) * rightStep;
double rightRise = std::sin(rightTheta) * rightStep;
double rightSlope = rightRise / rightRun;
{
double topRightX = bounds.y1 / rightSlope;
double bottomRightX = bounds.y0 / rightSlope;
TPointD startRight = TPointD(topRightX, bounds.y1);
TPointD endRight = TPointD(bottomRightX, bounds.y0);
while (startRight.x > bounds.x0) {
glBegin(GL_LINES);
glVertex2d(startRight.x, startRight.y);
glVertex2d(endRight.x, endRight.y);
glEnd();
startRight.x -= rightStep / Stage::standardDpi * Stage::inch;
endRight.x -= rightStep / Stage::standardDpi * Stage::inch;
}
startRight = TPointD(topRightX, bounds.y1);
endRight = TPointD(bottomRightX, bounds.y0);
while (endRight.x < bounds.x1) {
startRight.x += rightStep / Stage::standardDpi * Stage::inch;
endRight.x += rightStep / Stage::standardDpi * Stage::inch;
glBegin(GL_LINES);
glVertex2d(startRight.x + 0.25, startRight.y);
glVertex2d(endRight.x + 0.25, endRight.y);
glEnd();
}
}
double leftTheta = (double)IsometricLeftAngle * (3.14159 / 180);
double leftStep = IsometricLeftStep;
double leftRun = std::cos(leftTheta) * leftStep;
double leftRise = std::sin(leftTheta) * leftStep;
double leftSlope = leftRise / leftRun;
{
double topLeftX = bounds.y1 / -leftSlope;
double bottomLeftX = bounds.y0 / -leftSlope;
TPointD startLeft = TPointD(topLeftX, bounds.y1);
TPointD endLeft = TPointD(bottomLeftX, bounds.y0);
while (startLeft.x < bounds.x1) {
glBegin(GL_LINES);
glVertex2d(startLeft.x, startLeft.y);
glVertex2d(endLeft.x, endLeft.y);
glEnd();
startLeft.x += leftStep / Stage::standardDpi * Stage::inch;
endLeft.x += leftStep / Stage::standardDpi * Stage::inch;
}
startLeft = TPointD(topLeftX, bounds.y1);
endLeft = TPointD(bottomLeftX, bounds.y0);
while (endLeft.x > bounds.x0) {
startLeft.x -= leftStep / Stage::standardDpi * Stage::inch;
endLeft.x -= leftStep / Stage::standardDpi * Stage::inch;
glBegin(GL_LINES);
glVertex2d(startLeft.x, startLeft.y);
glVertex2d(endLeft.x, endLeft.y);
glEnd();
}
}
}
glLineWidth(1.0f);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);

View file

@ -35,9 +35,6 @@ TRectD getCameraRect();
void drawCameraMask(SceneViewer *viewer);
void drawGridAndGuides(SceneViewer *viewer, double viewerScale, Ruler *vRuler,
Ruler *hRuler, bool gridEnabled);
void drawPerspectiveGuides(SceneViewer *viewer, double viewerScale,
std::vector<TPointD> assistantPoints);
void draw3DCamera(unsigned long flags, double zmin, double phi);
void drawCamera(unsigned long flags, double pixelSize);
void drawGridsAndOverlays(SceneViewer *viewer, double pixelSize);

View file

@ -642,7 +642,8 @@ bool isResource(const QString &path) {
return (TFileType::isViewable(type) || type & TFileType::MESH_IMAGE ||
type == TFileType::AUDIO_LEVEL || type == TFileType::TABSCENE ||
type == TFileType::TOONZSCENE || fp.getType() == "tpl" ||
fp.getType() == "macrofx" || fp.getType() == "plugin");
fp.getType() == "macrofx" || fp.getType() == "plugin" ||
fp.getType() == "grid");
}
//-----------------------------------------------------------------------------