Perspective Grid Tool

This commit is contained in:
manongjohn 2021-11-03 10:05:17 -04:00
parent 3d97c97faf
commit ee8fc57567
28 changed files with 2382 additions and 986 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).

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

@ -67,6 +67,7 @@ class MeasuredValueField;
class PaletteController;
class ClickableLabel;
class StyleIndexFieldAndChip;
class ColorChipCombo;
class QLabel;
class QPushButton;
@ -164,6 +165,7 @@ private:
void visit(TEnumProperty *p) override;
void visit(TStyleIndexProperty *p) override;
void visit(TPointerProperty *p) override;
void visit(TColorChipProperty *p) override;
};
//***********************************************************************************************
@ -739,6 +741,37 @@ 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_presetCombo;
QPushButton *m_addPresetButton;
QPushButton *m_removePresetButton;
private:
class PresetNamePopup;
PresetNamePopup *m_presetNamePopup;
public:
PerspectiveGridToolOptionBox(QWidget *parent, TTool *tool,
TPaletteHandle *pltHandle,
ToolHandle *toolHandle);
protected slots:
void onAddPreset();
void onRemovePreset();
};
//=============================================================================
//
// 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

@ -32,6 +32,7 @@ set(HEADERS
stylepickertool.h
toonzvectorbrushtool.h
vectorselectiontool.h
perspectivetool.h
../include/tools/RGBpicker.h
../include/tools/cursormanager.h
../include/tools/cursors.h
@ -103,6 +104,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
@ -327,43 +329,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;
@ -425,10 +390,6 @@ void FullColorBrushTool::leftButtonDown(const TPointD &pos,
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);
@ -454,7 +415,22 @@ 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) {
TPointD pointToUse = TPointD(0.0, 0.0);
PerspectiveTool *perspectiveTool = dynamic_cast<PerspectiveTool *>(
TTool::getTool("T_PerspectiveGrid", TTool::RasterImage));
if (perspectiveTool) {
TPointD dpiScale = getViewer()->getDpiScale();
TPointD refPoint = m_firstPoint;
refPoint.x *= dpiScale.x;
refPoint.y *= dpiScale.y;
std::vector<PerspectiveObject *> perspectiveObjs =
perspectiveTool->getPerspectiveObjects();
for (auto data : perspectiveObjs) {
TPointD point = data->getReferencePoint(refPoint);
point.x /= dpiScale.x;
point.y /= dpiScale.y;
double newDenominator = point.x - m_firstPoint.x;
double newNumerator = point.y - m_firstPoint.y;
if (areAlmostEqual(newDenominator, 0.0, 0.0001)) {
@ -470,13 +446,17 @@ void FullColorBrushTool::leftButtonDrag(const TPointD &pos,
}
// figure out which angle is closer
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) {
if (newDifference < difference ||
(180 - newDifference) < difference) {
difference = std::min(newDifference, (180 - newDifference));
pointToUse = m_assistantPoints.at(i);
pointToUse = perspectiveObjs.at(i)->getReferencePoint(refPoint);
pointToUse.x /= dpiScale.x;
pointToUse.y /= dpiScale.y;
}
}
}
@ -614,12 +594,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;
@ -744,35 +718,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 +728,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 +806,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();
}
}
}
//------------------------------------------------------------------

View file

@ -126,11 +126,8 @@ 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;
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,489 @@
#pragma once
#ifndef PERSPECTIVETOOL_H
#define PERSPECTIVETOOL_H
#include "tproperty.h"
#include "tpersist.h"
#include "tundo.h"
#include "historytypes.h"
#include "toonzqt/selection.h"
#include "tools/tool.h"
#include "tools/tooloptions.h"
#include <QCoreApplication>
class SceneViewer;
class PerspectiveTool;
//--------------------------------------------------------------
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;
m_spacing = std::min(m_spacing, m_maxSpacing);
m_spacing = std::max(m_spacing, m_minSpacing);
}
virtual double getSpacing() { return m_spacing; }
void setMinSpacing(int minSpace) { m_minSpacing = minSpace; }
void setMaxSpacing(int maxSpace) { m_maxSpacing = maxSpace; }
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 = 250.0;
bool m_horizon;
double m_opacity;
TPixel32 m_color;
};
//************************************************************************
// Perspective Controls declaration
//************************************************************************
class PerspectiveControls {
PerspectiveData *m_perspective;
TPointD m_cursorPos;
bool m_active;
int m_handleRadius = 7;
// 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) {}
~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 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 areAlmostEqual(centerPoint.x, m_cursorPos.x, m_handleRadius) &&
areAlmostEqual(centerPoint.y, m_cursorPos.y, m_handleRadius);
}
bool isOverRotation() {
return areAlmostEqual(m_rotationPos.x, m_cursorPos.x, m_handleRadius) &&
areAlmostEqual(m_rotationPos.y, m_cursorPos.y, m_handleRadius);
}
bool isOverSpacing() {
if (!m_perspective || (m_perspective->getType() == PerspectiveType::Line &&
!m_perspective->isParallel()))
return false;
return areAlmostEqual(m_spacingPos.x, m_cursorPos.x, m_handleRadius) &&
areAlmostEqual(m_spacingPos.y, m_cursorPos.y, m_handleRadius);
}
bool isOverLeftPivot() {
if (!m_perspective ||
m_perspective->getType() != PerspectiveType::VanishingPoint)
return false;
return areAlmostEqual(m_leftPivotPos.x, m_cursorPos.x, m_handleRadius) &&
areAlmostEqual(m_leftPivotPos.y, m_cursorPos.y, m_handleRadius);
}
bool isOverLeftHandle() {
if (!m_perspective ||
m_perspective->getType() != PerspectiveType::VanishingPoint)
return false;
return areAlmostEqual(m_leftHandlePos.x, m_cursorPos.x, m_handleRadius) &&
areAlmostEqual(m_leftHandlePos.y, m_cursorPos.y, m_handleRadius);
}
bool isOverRightPivot() {
if (!m_perspective ||
m_perspective->getType() != PerspectiveType::VanishingPoint)
return false;
return areAlmostEqual(m_rightPivotPos.x, m_cursorPos.x, m_handleRadius) &&
areAlmostEqual(m_rightPivotPos.y, m_cursorPos.y, m_handleRadius);
}
bool isOverRightHandle() {
if (!m_perspective ||
m_perspective->getType() != PerspectiveType::VanishingPoint)
return false;
return areAlmostEqual(m_rightHandlePos.x, m_cursorPos.x, m_handleRadius) &&
areAlmostEqual(m_rightHandlePos.y, m_cursorPos.y, m_handleRadius);
}
bool isOverControl() {
return isOverCenterPoint() | isOverRotation() | isOverSpacing() |
isOverLeftPivot() | isOverLeftHandle() | isOverRightPivot() |
isOverRightHandle();
}
TRectD getCenterPointRect() {
TPointD centerPoint = m_perspective->getCenterPoint();
return TRectD(
centerPoint.x - m_handleRadius, centerPoint.y - m_handleRadius,
centerPoint.x + m_handleRadius, centerPoint.x + m_handleRadius);
}
TRectD getRotationRect() {
return TRectD(
m_rotationPos.x - m_handleRadius, m_rotationPos.y - m_handleRadius,
m_rotationPos.x + m_handleRadius, m_rotationPos.x + m_handleRadius);
}
TRectD getSpacingRect() {
return TRectD(
m_spacingPos.x - m_handleRadius, m_spacingPos.y - m_handleRadius,
m_spacingPos.x + m_handleRadius, m_spacingPos.x + m_handleRadius);
}
TRectD getLeftPivotRect() {
return TRectD(
m_leftPivotPos.x - m_handleRadius, m_leftPivotPos.y - m_handleRadius,
m_leftPivotPos.x + m_handleRadius, m_leftPivotPos.x + m_handleRadius);
}
TRectD getLeftHandleRect() {
return TRectD(
m_leftHandlePos.x - m_handleRadius, m_leftHandlePos.y - m_handleRadius,
m_leftHandlePos.x + m_handleRadius, m_leftHandlePos.x + m_handleRadius);
}
TRectD getRightPivotRect() {
return TRectD(
m_rightPivotPos.x - m_handleRadius, m_rightPivotPos.y - m_handleRadius,
m_rightPivotPos.x + m_handleRadius, m_rightPivotPos.x + m_handleRadius);
}
TRectD getRightHandleRect() {
return TRectD(m_rightHandlePos.x - m_handleRadius,
m_rightHandlePos.y - m_handleRadius,
m_rightHandlePos.x + m_handleRadius,
m_rightHandlePos.x + m_handleRadius);
}
};
//=============================================================================
// 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)
: 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;
PerspectivePreset() {}
PerspectivePreset(std::wstring presetName) : m_presetName(presetName) {}
PerspectivePreset(std::wstring presetName,
std::vector<PerspectiveObject *> perspectiveSet)
: m_presetName(presetName), m_perspectiveSet(perspectiveSet) {}
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 {
TFilePath m_fp; //!< Presets file path
std::set<PerspectivePreset> m_presets; //!< Current presets container
public:
PerspectivePresetManager() {}
void load(const TFilePath &fp);
void save();
const TFilePath &path() { return m_fp; };
const std::set<PerspectivePreset> &presets() const { return m_presets; }
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, TPointD(0, 0), 0.0,
10, false, 30, TPixel::Magenta, false) {
setMaxSpacing(180);
setRotationPos(TPointD(40, -20));
};
~VanishingPointPerspective(){};
void draw(SceneViewer *viewer, TRectD cameraRect) override;
double getSpacing() override {
if (isHorizon()) return std::min(m_spacing, 90.0);
return m_spacing;
}
TPointD getReferencePoint(TPointD firstPoint) override {
return getCenterPoint();
}
};
//=============================================================================
// LinePerspective
//-----------------------------------------------------------------------------
class LinePerspective final : public PerspectiveObject {
public:
LinePerspective() : PerspectiveObject(PerspectiveType::Line){};
~LinePerspective(){};
void draw(SceneViewer *viewer, TRectD cameraRect) override;
TPointD getReferencePoint(TPointD firstPoint) override;
};
//=============================================================================
// PerspectiveTool
//-----------------------------------------------------------------------------
class PerspectiveTool final : public TTool {
Q_DECLARE_TR_FUNCTIONS(PerspectiveTool)
public:
PerspectiveTool();
ToolType getToolType() const override { return TTool::GenericTool; }
void updateTranslation();
void draw(SceneViewer *viewer) override;
void mouseMove(const TPointD &pos, const TMouseEvent &e) 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 onPropertyChanged(std::string propertyName) override;
int getCursorId() const override { return ToolCursor::StrokeSelectCursor; };
TPropertyGroup *getProperties(int targetType) override;
void deleteSelectedObjects();
void setPerspectiveObjects(std::vector<PerspectiveObject *> objs) {
m_perspectiveObjs = objs;
m_selection.selectNone();
}
std::vector<PerspectiveObject *> getPerspectiveObjects() {
return m_perspectiveObjs;
}
std::vector<PerspectiveObject *> copyPerspectiveSet(
std::vector<PerspectiveObject *> perspectiveSet);
void invalidateControl(int controlIndex);
void initPresets();
void loadPreset();
void addPreset(QString name);
void removePreset();
void loadLastPreset();
protected:
TPropertyGroup m_prop;
TEnumProperty m_type;
TDoubleProperty m_opacity;
TColorChipProperty m_color;
TBoolProperty m_horizon;
TBoolProperty m_parallel;
TEnumProperty m_preset;
std::vector<PerspectiveObject *> m_perspectiveObjs;
std::vector<PerspectiveObject *> m_lastPreset;
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;
int m_mainControlIndex;
bool m_propertyUpdating = false;
PerspectivePresetManager m_presetsManager;
bool m_presetsLoaded;
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"
@ -337,6 +338,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
@ -2893,6 +2904,99 @@ void ShiftTraceToolOptionBox::onAfterRadioBtnClicked() {
stTool->setCurrentGhostIndex(1);
}
//=============================================================================
//
// PerspectiveGridToolOptionBox classes
//
//=============================================================================
class PerspectiveGridToolOptionBox::PresetNamePopup final
: public DVGui::Dialog {
DVGui::LineEdit *m_nameFld;
public:
PresetNamePopup() : Dialog(0, true) {
setWindowTitle(tr("Preset Name"));
m_nameFld = new DVGui::LineEdit();
addWidget(m_nameFld);
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(); }
void removeName() { m_nameFld->setText(QString("")); }
};
//=============================================================================
// 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);
ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle);
if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder);
m_presetCombo = dynamic_cast<ToolOptionCombo *>(m_controls.value("Preset:"));
// Preset +/- buttons
m_addPresetButton = new QPushButton(QString("+"));
m_removePresetButton = new QPushButton(QString("-"));
m_addPresetButton->setFixedSize(QSize(20, 20));
m_removePresetButton->setFixedSize(QSize(20, 20));
hLayout()->addWidget(m_addPresetButton);
hLayout()->addWidget(m_removePresetButton);
connect(m_addPresetButton, SIGNAL(clicked()), this, SLOT(onAddPreset()));
connect(m_removePresetButton, SIGNAL(clicked()), this,
SLOT(onRemovePreset()));
m_layout->addStretch(1);
}
//-----------------------------------------------------------------------------
void PerspectiveGridToolOptionBox::onAddPreset() {
// Initialize preset name popup
if (!m_presetNamePopup) m_presetNamePopup = new PresetNamePopup;
if (!m_presetNamePopup->getName().isEmpty()) m_presetNamePopup->removeName();
// Retrieve the preset name
bool ret = m_presetNamePopup->exec();
if (!ret) return;
QString name(m_presetNamePopup->getName());
m_presetNamePopup->removeName();
static_cast<PerspectiveTool *>(m_tool)->addPreset(name);
m_presetCombo->loadEntries();
}
//-----------------------------------------------------------------------------
void PerspectiveGridToolOptionBox::onRemovePreset() {
static_cast<PerspectiveTool *>(m_tool)->removePreset();
m_presetCombo->loadEntries();
}
//=============================================================================
// ZoomToolOptionBox
//-----------------------------------------------------------------------------
@ -3083,7 +3187,10 @@ void ToolOptions::onToolSwitched() {
panel = p;
RulerTool *rt = dynamic_cast<RulerTool *>(tool);
if (rt) rt->setToolOptionsBox(p);
} else if (tool->getName() == T_StylePicker)
} else if (tool->getName() == T_PerspectiveGrid)
panel =
new PerspectiveGridToolOptionBox(this, tool, currPalette, currTool);
else if (tool->getName() == T_StylePicker)
panel = new StylePickerToolOptionsBox(0, tool, currPalette, currTool,
app->getPaletteController());
else if (tool->getName() == "T_ShiftTrace")

View file

@ -564,6 +564,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()

View file

@ -275,6 +275,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>
@ -1291,42 +1293,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;
@ -1488,10 +1454,6 @@ 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);
@ -1517,7 +1479,22 @@ 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) {
TPointD pointToUse = TPointD(0.0, 0.0);
PerspectiveTool *perspectiveTool = dynamic_cast<PerspectiveTool *>(
TTool::getTool("T_PerspectiveGrid", TTool::ToonzImage));
if (perspectiveTool) {
TPointD dpiScale = getViewer()->getDpiScale();
TPointD refPoint = m_firstPoint;
refPoint.x *= dpiScale.x;
refPoint.y *= dpiScale.y;
std::vector<PerspectiveObject *> perspectiveObjs =
perspectiveTool->getPerspectiveObjects();
for (auto data : perspectiveObjs) {
TPointD point = data->getReferencePoint(refPoint);
point.x /= dpiScale.x;
point.y /= dpiScale.y;
double newDenominator = point.x - m_firstPoint.x;
double newNumerator = point.y - m_firstPoint.y;
if (areAlmostEqual(newDenominator, 0.0, 0.0001)) {
@ -1533,14 +1510,17 @@ void ToonzRasterBrushTool::leftButtonDrag(const TPointD &pos,
}
// figure out which angle is closer
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) {
if (newDifference < difference ||
(180 - newDifference) < difference) {
difference = std::min(newDifference, (180 - newDifference));
pointToUse = m_assistantPoints.at(i);
pointToUse = perspectiveObjs.at(i)->getReferencePoint(refPoint);
pointToUse.x /= dpiScale.x;
pointToUse.y /= dpiScale.y;
}
}
}
@ -1832,11 +1812,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;
@ -2193,34 +2168,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 +2176,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 +2292,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();
}
}
}
//------------------------------------------------------------------

View file

@ -230,10 +230,7 @@ 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;

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
@ -661,15 +663,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 +688,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 +751,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;
@ -831,11 +788,6 @@ void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos,
return;
}
if (!m_isPath &&
((e.isCtrlPressed() && e.isAltPressed() && !e.isShiftPressed()) ||
m_addingAssistant)) {
return;
}
TRectD invalidateRect;
m_lastPoint = pos;
@ -864,7 +816,22 @@ void ToonzVectorBrushTool::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) {
TPointD pointToUse = TPointD(0.0, 0.0);
PerspectiveTool *perspectiveTool = dynamic_cast<PerspectiveTool *>(
TTool::getTool("T_PerspectiveGrid", TTool::VectorImage));
if (perspectiveTool) {
TPointD dpiScale = getViewer()->getDpiScale();
TPointD refPoint = m_firstPoint;
refPoint.x *= dpiScale.x;
refPoint.y *= dpiScale.y;
std::vector<PerspectiveObject *> perspectiveObjs =
perspectiveTool->getPerspectiveObjects();
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)) {
@ -880,14 +847,16 @@ void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos,
}
// figure out which angle is closer
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);
pointToUse = perspectiveObjs.at(i)->getReferencePoint(refPoint);
pointToUse.x /= dpiScale.x;
pointToUse.y /= dpiScale.y;
}
}
}
@ -1058,13 +1027,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 +1076,6 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos,
notifyImageChanged();
TUndoManager::manager()->add(undo);
m_addingAssistant = false;
return;
}
@ -1124,7 +1084,6 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos,
m_styleId = 0;
m_track.clear();
m_addingAssistant = false;
return;
}
@ -1278,7 +1237,6 @@ void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos,
assert(stroke);
m_track.clear();
m_toggleSnap = false;
m_addingAssistant = false;
}
//--------------------------------------------------------------------------------------------------
@ -1609,34 +1567,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 +1745,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 +1802,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();
}
}
}
//----------------------------------------------------------------------------------------------------------

View file

@ -213,11 +213,8 @@ protected:
bool m_propertyUpdating = false;
std::vector<TPointD> m_assistantPoints;
bool m_addingAssistant = false;
TPointD m_firstPoint;
TPointD m_lastPoint;
int m_highlightAssistant = -1;
};
#endif // TOONZVECTORBRUSHTOOL_H

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

@ -2557,6 +2557,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;
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));
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();
});
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

@ -1671,6 +1671,17 @@ void SceneViewer::drawOverlay() {
glPopMatrix();
}
TTool *perspectiveTool =
TTool::getTool(T_PerspectiveGrid, TTool::VectorImage);
if (perspectiveTool &&
((fieldGuideToggle.getStatus() && ShowPerspectiveGrids) ||
app->getCurrentTool()->getTool() == perspectiveTool)) {
glPushMatrix();
tglMultMatrix(m_drawTableAff);
perspectiveTool->draw(this);
glPopMatrix();
}
#ifdef WITH_CANON
if (m_stopMotion->m_liveViewStatus == StopMotion::LiveViewOpen &&
app->getCurrentFrame()->getFrame() ==
@ -1782,22 +1793,7 @@ 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();
}
}
}
// 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

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,15 @@ 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 Perspective Objects")
.arg(trModKey("Shift"))
.arg(cmdTextSeparator) +
spacer +
tr("%1%2Select multiple Perspective Objects")
.arg(trModKey("Ctrl+Click/Drag"))
.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,11 @@
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);
TEnv::IntVar ShowPerspectiveGuides("ShowPerspectiveGuides", 0);
/* TODO, move to include */
void getSafeAreaSizeList(QList<QList<double>> &_sizeList);
@ -400,81 +383,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 +639,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);