shift and trace improvement (#2240)
This commit is contained in:
parent
e5a0a35b95
commit
1d5937a1fe
25 changed files with 559 additions and 192 deletions
|
@ -607,7 +607,8 @@ public:
|
|||
//! onionskins)
|
||||
//! (window coordinate, pixels, bottom-left origin)
|
||||
virtual int posToRow(const TPointD &p, double distance,
|
||||
bool includeInvisible = true) const = 0;
|
||||
bool includeInvisible = true,
|
||||
bool currentColumnOnly = false) const = 0;
|
||||
|
||||
//! return pos in pixel, bottom-left origin
|
||||
virtual TPointD worldToPos(const TPointD &worldPos) const = 0;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <QToolBar>
|
||||
#include <QMap>
|
||||
#include <QLabel>
|
||||
#include <QRadioButton>
|
||||
|
||||
// STD includes
|
||||
#include <map>
|
||||
|
@ -678,15 +679,25 @@ protected slots:
|
|||
|
||||
class ShiftTraceToolOptionBox final : public ToolOptionsBox {
|
||||
Q_OBJECT
|
||||
QPushButton *m_resetPrevGhostBtn;
|
||||
QPushButton *m_resetAfterGhostBtn;
|
||||
QFrame *m_prevFrame, *m_afterFrame;
|
||||
QRadioButton *m_prevRadioBtn, *m_afterRadioBtn;
|
||||
QPushButton *m_resetPrevGhostBtn, *m_resetAfterGhostBtn;
|
||||
TTool *m_tool;
|
||||
void resetGhost(int index);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *);
|
||||
void hideEvent(QShowEvent *);
|
||||
|
||||
public:
|
||||
ShiftTraceToolOptionBox(QWidget *parent = 0);
|
||||
ShiftTraceToolOptionBox(QWidget *parent = 0, TTool *tool = 0);
|
||||
void updateStatus() override;
|
||||
protected slots:
|
||||
void onResetPrevGhostBtnPressed();
|
||||
void onResetAfterGhostBtnPressed();
|
||||
void onPrevRadioBtnClicked();
|
||||
void onAfterRadioBtnClicked();
|
||||
void updateColors();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -507,6 +507,11 @@ public:
|
|||
}
|
||||
bool getOnionSkinDuringPlayback() { return m_onionSkinDuringPlayback; }
|
||||
void setOnionSkinDuringPlayback(bool on);
|
||||
|
||||
void useOnionColorsForShiftAndTraceGhosts(bool on);
|
||||
bool areOnionColorsUsedForShiftAndTraceGhosts() const {
|
||||
return m_useOnionColorsForShiftAndTraceGhosts;
|
||||
}
|
||||
// Transparency Check tab
|
||||
|
||||
void setTranspCheckData(const TPixel &bg, const TPixel &ink,
|
||||
|
@ -711,7 +716,8 @@ private:
|
|||
|
||||
TPixel32 m_currentColumnColor;
|
||||
|
||||
bool m_enableWinInk = false;
|
||||
bool m_enableWinInk = false;
|
||||
bool m_useOnionColorsForShiftAndTraceGhosts = false;
|
||||
|
||||
private:
|
||||
Preferences();
|
||||
|
|
|
@ -107,6 +107,8 @@ public:
|
|||
static double m_firstBackOnionSkin;
|
||||
static double m_lastBackVisibleSkin;
|
||||
|
||||
static bool m_isShiftAndTraceEnabled;
|
||||
|
||||
TPixel32 m_filterColor;
|
||||
|
||||
public:
|
||||
|
|
|
@ -289,6 +289,8 @@ class DVAPI Picker final : public Visitor {
|
|||
TAffine m_viewAff;
|
||||
double m_minDist2;
|
||||
|
||||
int m_currentColumnIndex = -1;
|
||||
|
||||
public:
|
||||
Picker(const TAffine &viewAff, const TPointD &p,
|
||||
const ImagePainter::VisualSettings &vs);
|
||||
|
@ -304,6 +306,8 @@ public:
|
|||
int getColumnIndex() const;
|
||||
void getColumnIndexes(std::vector<int> &indexes) const;
|
||||
int getRow() const;
|
||||
|
||||
void setCurrentColumnIndex(int index) { m_currentColumnIndex = index; }
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
|
|
@ -36,6 +36,7 @@ set(HEADERS ${MOC_HEADERS}
|
|||
../include/tools/toolutils.h
|
||||
../include/tools/RGBpicker.h
|
||||
mypainttoonzbrush.h
|
||||
shifttracetool.h
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
|
@ -96,6 +97,7 @@ set(SOURCES
|
|||
fingertool.cpp
|
||||
rulertool.cpp
|
||||
mypainttoonzbrush.cpp
|
||||
shifttracetool.cpp
|
||||
)
|
||||
|
||||
set(RESOURCES tnztools.qrc)
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include "toonz/onionskinmask.h"
|
||||
#include "toonz/tonionskinmaskhandle.h"
|
||||
#include "tools/cursors.h"
|
||||
#include "tools/tool.h"
|
||||
#include "timage.h"
|
||||
#include "trasterimage.h"
|
||||
#include "ttoonzimage.h"
|
||||
|
@ -15,10 +14,10 @@
|
|||
#include "toonz/tframehandle.h"
|
||||
#include "toonz/tcolumnhandle.h"
|
||||
#include "toonz/txshlevelhandle.h"
|
||||
#include "tools/toolhandle.h"
|
||||
#include "toonz/txshsimplelevel.h"
|
||||
#include "toonz/dpiscale.h"
|
||||
#include "toonz/stage.h"
|
||||
#include "tapp.h"
|
||||
#include "tpixel.h"
|
||||
#include "toonzqt/menubarcommand.h"
|
||||
|
||||
|
@ -51,97 +50,6 @@ static bool circumCenter(TPointD &out, const TPointD &a, const TPointD &b,
|
|||
|
||||
//=============================================================================
|
||||
|
||||
class ShiftTraceTool final : public TTool {
|
||||
public:
|
||||
enum CurveStatus {
|
||||
NoCurve,
|
||||
TwoPointsCurve, // just during the first click&drag
|
||||
ThreePointsCurve
|
||||
};
|
||||
|
||||
enum GadgetId {
|
||||
NoGadget,
|
||||
NoGadget_InBox,
|
||||
CurveP0Gadget,
|
||||
CurveP1Gadget,
|
||||
CurvePmGadget,
|
||||
MoveCenterGadget,
|
||||
RotateGadget,
|
||||
TranslateGadget,
|
||||
ScaleGadget
|
||||
};
|
||||
inline bool isCurveGadget(GadgetId id) const {
|
||||
return CurveP0Gadget <= id && id <= CurvePmGadget;
|
||||
}
|
||||
|
||||
private:
|
||||
TPointD m_oldPos, m_startPos;
|
||||
int m_ghostIndex;
|
||||
TPointD m_p0, m_p1, m_p2;
|
||||
|
||||
CurveStatus m_curveStatus;
|
||||
GadgetId m_gadget;
|
||||
GadgetId m_highlightedGadget;
|
||||
|
||||
TRectD m_box;
|
||||
TAffine m_dpiAff;
|
||||
int m_row[2];
|
||||
TAffine m_aff[2];
|
||||
TPointD m_center[2];
|
||||
|
||||
TAffine m_oldAff;
|
||||
|
||||
public:
|
||||
ShiftTraceTool();
|
||||
|
||||
ToolType getToolType() const override { return GenericTool; }
|
||||
|
||||
void clearData();
|
||||
void updateData();
|
||||
void updateBox();
|
||||
void updateCurveAffs();
|
||||
void updateGhost();
|
||||
|
||||
void reset() override {
|
||||
int ghostIndex = m_ghostIndex;
|
||||
onActivate();
|
||||
invalidate();
|
||||
m_ghostIndex = ghostIndex;
|
||||
}
|
||||
|
||||
void mouseMove(const TPointD &, const TMouseEvent &e) override;
|
||||
void leftButtonDown(const TPointD &, const TMouseEvent &) override;
|
||||
void leftButtonDrag(const TPointD &, const TMouseEvent &) override;
|
||||
void leftButtonUp(const TPointD &, const TMouseEvent &) override;
|
||||
void draw() override;
|
||||
|
||||
TAffine getGhostAff();
|
||||
GadgetId getGadget(const TPointD &);
|
||||
void drawDot(const TPointD ¢er, double r,
|
||||
const TPixel32 &color = TPixel32::White);
|
||||
void drawControlRect();
|
||||
void drawCurve();
|
||||
|
||||
void onActivate() override {
|
||||
m_ghostIndex = 0;
|
||||
m_curveStatus = NoCurve;
|
||||
clearData();
|
||||
OnionSkinMask osm =
|
||||
TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask();
|
||||
m_aff[0] = osm.getShiftTraceGhostAff(0);
|
||||
m_aff[1] = osm.getShiftTraceGhostAff(1);
|
||||
m_center[0] = osm.getShiftTraceGhostCenter(0);
|
||||
m_center[1] = osm.getShiftTraceGhostCenter(1);
|
||||
}
|
||||
void onDeactivate() override {
|
||||
QAction *action = CommandManager::instance()->getAction("MI_EditShift");
|
||||
action->setChecked(false);
|
||||
}
|
||||
bool isEventAcceptable(QEvent *e) override;
|
||||
|
||||
int getCursorId() const override;
|
||||
};
|
||||
|
||||
ShiftTraceTool::ShiftTraceTool()
|
||||
: TTool("T_ShiftTrace")
|
||||
, m_ghostIndex(0)
|
||||
|
@ -170,7 +78,7 @@ void ShiftTraceTool::updateBox() {
|
|||
|
||||
TImageP img;
|
||||
|
||||
TApp *app = TApp::instance();
|
||||
TApplication *app = TTool::getApplication();
|
||||
if (app->getCurrentFrame()->isEditingScene()) {
|
||||
int col = app->getCurrentColumn()->getColumnIndex();
|
||||
int row = m_row[m_ghostIndex];
|
||||
|
@ -214,10 +122,9 @@ void ShiftTraceTool::updateData() {
|
|||
m_box = TRectD();
|
||||
for (int i = 0; i < 2; i++) m_row[i] = -1;
|
||||
m_dpiAff = TAffine();
|
||||
TApp *app = TApp::instance();
|
||||
TApplication *app = TTool::getApplication();
|
||||
|
||||
OnionSkinMask osm =
|
||||
TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask();
|
||||
OnionSkinMask osm = app->getCurrentOnionSkin()->getOnionSkinMask();
|
||||
int previousOffset = osm.getShiftTraceGhostFrameOffset(0);
|
||||
int forwardOffset = osm.getShiftTraceGhostFrameOffset(1);
|
||||
// we must find the prev (m_row[0]) and next (m_row[1]) reference images
|
||||
|
@ -284,12 +191,23 @@ void ShiftTraceTool::updateCurveAffs() {
|
|||
|
||||
void ShiftTraceTool::updateGhost() {
|
||||
OnionSkinMask osm =
|
||||
TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask();
|
||||
TTool::getApplication()->getCurrentOnionSkin()->getOnionSkinMask();
|
||||
osm.setShiftTraceGhostAff(0, m_aff[0]);
|
||||
osm.setShiftTraceGhostAff(1, m_aff[1]);
|
||||
osm.setShiftTraceGhostCenter(0, m_center[0]);
|
||||
osm.setShiftTraceGhostCenter(1, m_center[1]);
|
||||
TApp::instance()->getCurrentOnionSkin()->setOnionSkinMask(osm);
|
||||
TTool::getApplication()->getCurrentOnionSkin()->setOnionSkinMask(osm);
|
||||
}
|
||||
|
||||
void ShiftTraceTool::reset() {
|
||||
int ghostIndex = m_ghostIndex;
|
||||
onActivate();
|
||||
invalidate();
|
||||
m_ghostIndex = ghostIndex;
|
||||
|
||||
TTool::getApplication()
|
||||
->getCurrentTool()
|
||||
->notifyToolChanged(); // Refreshes toolbar values
|
||||
}
|
||||
|
||||
TAffine ShiftTraceTool::getGhostAff() {
|
||||
|
@ -417,6 +335,23 @@ void ShiftTraceTool::drawCurve() {
|
|||
}
|
||||
}
|
||||
|
||||
void ShiftTraceTool::onActivate() {
|
||||
m_ghostIndex = 0;
|
||||
m_curveStatus = NoCurve;
|
||||
clearData();
|
||||
OnionSkinMask osm =
|
||||
TTool::getApplication()->getCurrentOnionSkin()->getOnionSkinMask();
|
||||
m_aff[0] = osm.getShiftTraceGhostAff(0);
|
||||
m_aff[1] = osm.getShiftTraceGhostAff(1);
|
||||
m_center[0] = osm.getShiftTraceGhostCenter(0);
|
||||
m_center[1] = osm.getShiftTraceGhostCenter(1);
|
||||
}
|
||||
|
||||
void ShiftTraceTool::onDeactivate() {
|
||||
QAction *action = CommandManager::instance()->getAction("MI_EditShift");
|
||||
action->setChecked(false);
|
||||
}
|
||||
|
||||
ShiftTraceTool::GadgetId ShiftTraceTool::getGadget(const TPointD &p) {
|
||||
std::vector<std::pair<TPointD, GadgetId>> gadgets;
|
||||
gadgets.push_back(std::make_pair(m_p0, CurveP0Gadget));
|
||||
|
@ -505,6 +440,8 @@ void ShiftTraceTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
|
|||
m_gadget = m_highlightedGadget;
|
||||
m_oldPos = m_startPos = pos;
|
||||
|
||||
bool notify = false;
|
||||
|
||||
if (m_gadget == NoGadget || m_gadget == NoGadget_InBox) {
|
||||
if (!e.isCtrlPressed()) {
|
||||
if (m_gadget == NoGadget_InBox)
|
||||
|
@ -513,13 +450,13 @@ void ShiftTraceTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
|
|||
m_gadget = RotateGadget;
|
||||
// m_curveStatus = NoCurve;
|
||||
}
|
||||
int row = getViewer()->posToRow(e.m_pos, 5 * getPixelSize(), false);
|
||||
int row = getViewer()->posToRow(e.m_pos, 5 * getPixelSize(), false, true);
|
||||
if (row >= 0) {
|
||||
int index = -1;
|
||||
TApp *app = TApp::instance();
|
||||
int index = -1;
|
||||
TApplication *app = TTool::getApplication();
|
||||
if (app->getCurrentFrame()->isEditingScene()) {
|
||||
int currentRow = getFrame();
|
||||
if (m_row[0] >= 0 && row <= currentRow)
|
||||
if (m_row[0] >= 0 && row < currentRow)
|
||||
index = 0;
|
||||
else if (m_row[1] >= 0 && row > currentRow)
|
||||
index = 1;
|
||||
|
@ -535,12 +472,19 @@ void ShiftTraceTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
|
|||
updateBox();
|
||||
m_gadget = TranslateGadget;
|
||||
m_highlightedGadget = TranslateGadget;
|
||||
notify = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_oldAff = m_aff[m_ghostIndex];
|
||||
invalidate();
|
||||
|
||||
if (notify) {
|
||||
TTool::getApplication()
|
||||
->getCurrentTool()
|
||||
->notifyToolChanged(); // Refreshes toolbar values
|
||||
}
|
||||
}
|
||||
|
||||
void ShiftTraceTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) {
|
||||
|
@ -613,6 +557,10 @@ void ShiftTraceTool::leftButtonUp(const TPointD &pos, const TMouseEvent &) {
|
|||
}
|
||||
m_gadget = NoGadget;
|
||||
invalidate();
|
||||
|
||||
TTool::getApplication()
|
||||
->getCurrentTool()
|
||||
->notifyToolChanged(); // Refreshes toolbar values
|
||||
}
|
||||
|
||||
void ShiftTraceTool::draw() {
|
||||
|
@ -639,4 +587,17 @@ bool ShiftTraceTool::isEventAcceptable(QEvent *e) {
|
|||
return (Qt::Key_F1 <= key && key <= Qt::Key_F3);
|
||||
}
|
||||
|
||||
void ShiftTraceTool::onLeave() {
|
||||
OnionSkinMask osm =
|
||||
TTool::getApplication()->getCurrentOnionSkin()->getOnionSkinMask();
|
||||
osm.clearGhostFlipKey();
|
||||
TTool::getApplication()->getCurrentOnionSkin()->setOnionSkinMask(osm);
|
||||
}
|
||||
|
||||
void ShiftTraceTool::setCurrentGhostIndex(int index) {
|
||||
m_ghostIndex = index;
|
||||
updateBox();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
ShiftTraceTool shiftTraceTool;
|
82
toonz/sources/tnztools/shifttracetool.h
Normal file
82
toonz/sources/tnztools/shifttracetool.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
#pragma once
|
||||
|
||||
#include "tools/tool.h"
|
||||
|
||||
class ShiftTraceTool final : public TTool {
|
||||
public:
|
||||
enum CurveStatus {
|
||||
NoCurve,
|
||||
TwoPointsCurve, // just during the first click&drag
|
||||
ThreePointsCurve
|
||||
};
|
||||
|
||||
enum GadgetId {
|
||||
NoGadget,
|
||||
NoGadget_InBox,
|
||||
CurveP0Gadget,
|
||||
CurveP1Gadget,
|
||||
CurvePmGadget,
|
||||
MoveCenterGadget,
|
||||
RotateGadget,
|
||||
TranslateGadget,
|
||||
ScaleGadget
|
||||
};
|
||||
inline bool isCurveGadget(GadgetId id) const {
|
||||
return CurveP0Gadget <= id && id <= CurvePmGadget;
|
||||
}
|
||||
|
||||
private:
|
||||
TPointD m_oldPos, m_startPos;
|
||||
int m_ghostIndex;
|
||||
TPointD m_p0, m_p1, m_p2;
|
||||
|
||||
CurveStatus m_curveStatus;
|
||||
GadgetId m_gadget;
|
||||
GadgetId m_highlightedGadget;
|
||||
|
||||
TRectD m_box;
|
||||
TAffine m_dpiAff;
|
||||
int m_row[2];
|
||||
TAffine m_aff[2];
|
||||
TPointD m_center[2];
|
||||
|
||||
TAffine m_oldAff;
|
||||
|
||||
public:
|
||||
ShiftTraceTool();
|
||||
|
||||
ToolType getToolType() const override { return GenericTool; }
|
||||
|
||||
void clearData();
|
||||
void updateData();
|
||||
void updateBox();
|
||||
void updateCurveAffs();
|
||||
void updateGhost();
|
||||
|
||||
void reset() override;
|
||||
|
||||
void mouseMove(const TPointD &, const TMouseEvent &e) override;
|
||||
void leftButtonDown(const TPointD &, const TMouseEvent &) override;
|
||||
void leftButtonDrag(const TPointD &, const TMouseEvent &) override;
|
||||
void leftButtonUp(const TPointD &, const TMouseEvent &) override;
|
||||
void draw() override;
|
||||
|
||||
TAffine getGhostAff();
|
||||
GadgetId getGadget(const TPointD &);
|
||||
void drawDot(const TPointD ¢er, double r,
|
||||
const TPixel32 &color = TPixel32::White);
|
||||
void drawControlRect();
|
||||
void drawCurve();
|
||||
|
||||
void onActivate() override;
|
||||
void onDeactivate() override;
|
||||
|
||||
void onLeave() override;
|
||||
|
||||
bool isEventAcceptable(QEvent *e) override;
|
||||
|
||||
int getCursorId() const override;
|
||||
|
||||
int getCurrentGhostIndex() { return m_ghostIndex; }
|
||||
void setCurrentGhostIndex(int index);
|
||||
};
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
//#include "rgbpickertool.h"
|
||||
#include "rulertool.h"
|
||||
#include "shifttracetool.h"
|
||||
|
||||
// TnzQt includes
|
||||
#include "toonzqt/dvdialog.h"
|
||||
|
@ -2501,24 +2502,58 @@ void StylePickerToolOptionsBox::updateRealTimePickLabel(const int ink,
|
|||
// ShiftTraceToolOptionBox
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ShiftTraceToolOptionBox::ShiftTraceToolOptionBox(QWidget *parent)
|
||||
: ToolOptionsBox(parent) {
|
||||
ShiftTraceToolOptionBox::ShiftTraceToolOptionBox(QWidget *parent, TTool *tool)
|
||||
: ToolOptionsBox(parent), m_tool(tool) {
|
||||
setFrameStyle(QFrame::StyledPanel);
|
||||
setFixedHeight(26);
|
||||
|
||||
m_resetPrevGhostBtn =
|
||||
new QPushButton(tr("Reset Shift of Previous Drawing"), this);
|
||||
m_resetAfterGhostBtn =
|
||||
new QPushButton(tr("Reset Shift of Forward Drawing"), this);
|
||||
m_prevFrame = new QFrame(this);
|
||||
m_afterFrame = new QFrame(this);
|
||||
|
||||
m_resetPrevGhostBtn = new QPushButton(tr("Reset Previous"), this);
|
||||
m_resetAfterGhostBtn = new QPushButton(tr("Reset Following"), this);
|
||||
|
||||
m_prevRadioBtn = new QRadioButton(tr("Previous Drawing"), this);
|
||||
m_afterRadioBtn = new QRadioButton(tr("Following Drawing"), this);
|
||||
|
||||
m_prevFrame->setFixedSize(10, 21);
|
||||
m_afterFrame->setFixedSize(10, 21);
|
||||
|
||||
m_layout->addWidget(m_prevFrame, 0);
|
||||
m_layout->addWidget(m_prevRadioBtn, 0);
|
||||
m_layout->addWidget(m_resetPrevGhostBtn, 0);
|
||||
|
||||
m_layout->addWidget(new DVGui::Separator("", this, false));
|
||||
|
||||
m_layout->addWidget(m_afterFrame, 0);
|
||||
m_layout->addWidget(m_afterRadioBtn, 0);
|
||||
m_layout->addWidget(m_resetAfterGhostBtn, 0);
|
||||
|
||||
m_layout->addStretch(1);
|
||||
|
||||
connect(m_resetPrevGhostBtn, SIGNAL(clicked()), this,
|
||||
connect(m_resetPrevGhostBtn, SIGNAL(clicked(bool)), this,
|
||||
SLOT(onResetPrevGhostBtnPressed()));
|
||||
connect(m_resetAfterGhostBtn, SIGNAL(clicked()), this,
|
||||
connect(m_resetAfterGhostBtn, SIGNAL(clicked(bool)), this,
|
||||
SLOT(onResetAfterGhostBtnPressed()));
|
||||
connect(m_prevRadioBtn, SIGNAL(clicked(bool)), this,
|
||||
SLOT(onPrevRadioBtnClicked()));
|
||||
connect(m_afterRadioBtn, SIGNAL(clicked(bool)), this,
|
||||
SLOT(onAfterRadioBtnClicked()));
|
||||
|
||||
updateStatus();
|
||||
}
|
||||
|
||||
void ShiftTraceToolOptionBox::showEvent(QShowEvent *) {
|
||||
TTool::Application *app = TTool::getApplication();
|
||||
connect(app->getCurrentOnionSkin(), SIGNAL(onionSkinMaskChanged()), this,
|
||||
SLOT(updateColors()));
|
||||
updateColors();
|
||||
}
|
||||
|
||||
void ShiftTraceToolOptionBox::hideEvent(QShowEvent *) {
|
||||
TTool::Application *app = TTool::getApplication();
|
||||
disconnect(app->getCurrentOnionSkin(), SIGNAL(onionSkinMaskChanged()), this,
|
||||
SLOT(updateColors()));
|
||||
}
|
||||
|
||||
void ShiftTraceToolOptionBox::resetGhost(int index) {
|
||||
|
@ -2530,12 +2565,68 @@ void ShiftTraceToolOptionBox::resetGhost(int index) {
|
|||
app->getCurrentOnionSkin()->notifyOnionSkinMaskChanged();
|
||||
TTool *tool = app->getCurrentTool()->getTool();
|
||||
if (tool) tool->reset();
|
||||
|
||||
if (index == 0)
|
||||
m_resetPrevGhostBtn->setDisabled(true);
|
||||
else // index == 1
|
||||
m_resetAfterGhostBtn->setDisabled(true);
|
||||
}
|
||||
|
||||
void ShiftTraceToolOptionBox::onResetPrevGhostBtnPressed() { resetGhost(0); }
|
||||
|
||||
void ShiftTraceToolOptionBox::onResetAfterGhostBtnPressed() { resetGhost(1); }
|
||||
|
||||
void ShiftTraceToolOptionBox::updateColors() {
|
||||
TPixel front, back;
|
||||
bool ink;
|
||||
Preferences::instance()->getOnionData(front, back, ink);
|
||||
|
||||
m_prevFrame->setStyleSheet(QString("background:rgb(%1,%2,%3,255);")
|
||||
.arg((int)back.r)
|
||||
.arg((int)back.g)
|
||||
.arg((int)back.b));
|
||||
m_afterFrame->setStyleSheet(QString("background:rgb(%1,%2,%3,255);")
|
||||
.arg((int)front.r)
|
||||
.arg((int)front.g)
|
||||
.arg((int)front.b));
|
||||
}
|
||||
|
||||
void ShiftTraceToolOptionBox::updateStatus() {
|
||||
TTool::Application *app = TTool::getApplication();
|
||||
OnionSkinMask osm = app->getCurrentOnionSkin()->getOnionSkinMask();
|
||||
if (osm.getShiftTraceGhostAff(0).isIdentity() &&
|
||||
osm.getShiftTraceGhostCenter(0) == TPointD())
|
||||
m_resetPrevGhostBtn->setDisabled(true);
|
||||
else
|
||||
m_resetPrevGhostBtn->setEnabled(true);
|
||||
|
||||
if (osm.getShiftTraceGhostAff(1).isIdentity() &&
|
||||
osm.getShiftTraceGhostCenter(1) == TPointD())
|
||||
m_resetAfterGhostBtn->setDisabled(true);
|
||||
else
|
||||
m_resetAfterGhostBtn->setEnabled(true);
|
||||
|
||||
// Check the ghost index
|
||||
ShiftTraceTool *stTool = (ShiftTraceTool *)m_tool;
|
||||
if (!stTool) return;
|
||||
if (stTool->getCurrentGhostIndex() == 0)
|
||||
m_prevRadioBtn->setChecked(true);
|
||||
else // ghostIndex == 1
|
||||
m_afterRadioBtn->setChecked(true);
|
||||
}
|
||||
|
||||
void ShiftTraceToolOptionBox::onPrevRadioBtnClicked() {
|
||||
ShiftTraceTool *stTool = (ShiftTraceTool *)m_tool;
|
||||
if (!stTool) return;
|
||||
stTool->setCurrentGhostIndex(0);
|
||||
}
|
||||
|
||||
void ShiftTraceToolOptionBox::onAfterRadioBtnClicked() {
|
||||
ShiftTraceTool *stTool = (ShiftTraceTool *)m_tool;
|
||||
if (!stTool) return;
|
||||
stTool->setCurrentGhostIndex(1);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// ToolOptions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -2645,7 +2736,7 @@ void ToolOptions::onToolSwitched() {
|
|||
panel = new StylePickerToolOptionsBox(0, tool, currPalette, currTool,
|
||||
app->getPaletteController());
|
||||
else if (tool->getName() == "T_ShiftTrace")
|
||||
panel = new ShiftTraceToolOptionBox(this);
|
||||
panel = new ShiftTraceToolOptionBox(this, tool);
|
||||
else
|
||||
panel = tool->createOptionsBox(); // Only this line should remain out
|
||||
// of that if/else monstrosity
|
||||
|
|
|
@ -107,7 +107,6 @@ set(MOC_HEADERS
|
|||
sceneviewerevents.h
|
||||
scriptconsolepanel.h
|
||||
selectionutils.h
|
||||
shifttracetool.h
|
||||
shortcutpopup.h
|
||||
soundtrackexport.h
|
||||
startuppopup.h
|
||||
|
@ -255,7 +254,6 @@ set(SOURCES
|
|||
sceneviewercontextmenu.cpp
|
||||
scenesettingspopup.cpp
|
||||
scriptconsolepanel.cpp
|
||||
shifttracetool.cpp
|
||||
shortcutpopup.cpp
|
||||
soundtrackexport.cpp
|
||||
startuppopup.cpp
|
||||
|
|
18
toonz/sources/toonz/Resources/shift_and_trace.svg
Normal file
18
toonz/sources/toonz/Resources/shift_and_trace.svg
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||
y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;stroke:#000000;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:#000000;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st3{fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<path class="st0" d="M19.5,9.2c0-4.3-3.4-7.7-7.5-7.7S4.5,4.9,4.5,9.2c0,4.9,4.9,6.3,4.9,10.5c0,2,1.2,2.8,2.6,2.8
|
||||
c1.5,0,2.6-0.8,2.6-2.8C14.6,15.5,19.5,14.1,19.5,9.2z"/>
|
||||
<rect x="10" y="10.5" class="st1" width="4" height="7"/>
|
||||
<g>
|
||||
<line class="st2" x1="8.5" y1="18.5" x2="15.5" y2="18.5"/>
|
||||
<line class="st3" x1="8.5" y1="18.5" x2="15.5" y2="18.5"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1 KiB |
59
toonz/sources/toonz/Resources/shift_and_trace_edit.svg
Normal file
59
toonz/sources/toonz/Resources/shift_and_trace_edit.svg
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||
y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;stroke:#000000;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st3{fill:none;stroke:#000000;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st4{fill:none;stroke:#000000;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||
.st5{fill:#FFFFFF;}
|
||||
.st6{display:none;}
|
||||
.st7{display:inline;fill:none;stroke:#000000;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||
.st8{display:inline;fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M12.5,7c0-3-2.5-5.5-5.5-5.5S1.5,4,1.5,7c0,3.5,3.6,4.5,3.6,7.5c0,1.5,0.9,2,1.9,2c1.1,0,1.9-0.5,1.9-2
|
||||
C8.9,11.5,12.5,10.5,12.5,7z"/>
|
||||
<g>
|
||||
<line class="st1" x1="4.5" y1="13.5" x2="9.5" y2="13.5"/>
|
||||
<line class="st2" x1="4.5" y1="13.5" x2="9.5" y2="13.5"/>
|
||||
</g>
|
||||
<rect x="5.5" y="7.5" class="st3" width="3" height="5"/>
|
||||
<line class="st1" x1="15.5" y1="10.5" x2="15.5" y2="20.5"/>
|
||||
<line class="st1" x1="10.5" y1="15.5" x2="19.5" y2="15.5"/>
|
||||
<polygon class="st4" points="17.5,20 13.5,20 15.5,22.5 "/>
|
||||
<polygon class="st4" points="19.8,13.5 19.8,17.5 22.3,15.5 "/>
|
||||
<polygon class="st4" points="13.5,11 17.5,11 15.5,8.5 "/>
|
||||
<polygon class="st4" points="11,17.5 11,13.5 8.5,15.5 "/>
|
||||
<polygon class="st5" points="19.8,13.5 19.8,17.5 22.3,15.5 "/>
|
||||
<polygon class="st5" points="13.5,11 17.5,11 15.5,8.5 "/>
|
||||
<polygon class="st5" points="11,17.5 11,13.5 8.5,15.5 "/>
|
||||
<polygon class="st5" points="17.5,20 13.5,20 15.5,22.5 "/>
|
||||
<line class="st2" x1="15.5" y1="10.5" x2="15.5" y2="20.5"/>
|
||||
<line class="st2" x1="10.5" y1="15.5" x2="20.5" y2="15.5"/>
|
||||
<g class="st6">
|
||||
<polygon class="st7" points="13.7,9 16.1,9 15.5,12.6 "/>
|
||||
<polygon class="st8" points="13.7,9 16.1,9 15.5,12.6 "/>
|
||||
</g>
|
||||
<g class="st6">
|
||||
<polygon class="st7" points="17.3,22 14.9,22 15.5,18.5 "/>
|
||||
<polygon class="st8" points="17.3,22 14.9,22 15.5,18.5 "/>
|
||||
</g>
|
||||
<g class="st6">
|
||||
<polygon class="st7" points="20.2,10.7 21.4,12.8 18.1,14 "/>
|
||||
<polygon class="st8" points="20.2,10.7 21.4,12.8 18.1,14 "/>
|
||||
</g>
|
||||
<g class="st6">
|
||||
<polygon class="st7" points="10.8,20.3 9.6,18.2 13,17 "/>
|
||||
<polygon class="st8" points="10.8,20.3 9.6,18.2 13,17 "/>
|
||||
</g>
|
||||
<g class="st6">
|
||||
<polygon class="st7" points="9,13.8 10.2,11.8 13,14 "/>
|
||||
<polygon class="st8" points="9,13.8 10.2,11.8 13,14 "/>
|
||||
</g>
|
||||
<g class="st6">
|
||||
<polygon class="st7" points="22,17.2 20.8,19.3 18.1,17 "/>
|
||||
<polygon class="st8" points="22,17.2 20.8,19.3 18.1,17 "/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
56
toonz/sources/toonz/Resources/shift_and_trace_reset.svg
Normal file
56
toonz/sources/toonz/Resources/shift_and_trace_reset.svg
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||
y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;stroke:#000000;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st3{fill:none;stroke:#000000;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st4{display:none;fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st5{display:none;fill:none;stroke:#000000;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||
.st6{display:none;fill:#FFFFFF;}
|
||||
.st7{display:none;fill:none;stroke:#FFFFFF;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st8{fill:none;stroke:#000000;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||
.st9{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M12.5,7c0-3-2.5-5.5-5.5-5.5S1.5,4,1.5,7c0,3.5,3.6,4.5,3.6,7.5c0,1.5,0.9,2,1.9,2c1.1,0,1.9-0.5,1.9-2
|
||||
C8.9,11.5,12.5,10.5,12.5,7z"/>
|
||||
<g>
|
||||
<line class="st1" x1="4.5" y1="13.5" x2="9.5" y2="13.5"/>
|
||||
<line class="st2" x1="4.5" y1="13.5" x2="9.5" y2="13.5"/>
|
||||
</g>
|
||||
<rect x="5.5" y="7.5" class="st3" width="3" height="5"/>
|
||||
<line class="st4" x1="13.5" y1="10.5" x2="13.5" y2="18.5"/>
|
||||
<line class="st4" x1="10.5" y1="15.5" x2="16.5" y2="15.5"/>
|
||||
<polygon class="st5" points="16.8,13.5 16.8,17.5 19.3,15.5 "/>
|
||||
<polygon class="st5" points="11.5,11 15.5,11 13.5,8.5 "/>
|
||||
<polygon class="st6" points="16.8,13.5 16.8,17.5 19.3,15.5 "/>
|
||||
<polygon class="st6" points="11.5,11 15.5,11 13.5,8.5 "/>
|
||||
<line class="st7" x1="13.5" y1="10.5" x2="13.5" y2="18.5"/>
|
||||
<line class="st7" x1="10.5" y1="15.5" x2="17.5" y2="15.5"/>
|
||||
<g>
|
||||
<polygon class="st8" points="13.7,9 16.1,9 15.5,12.6 "/>
|
||||
<polygon class="st9" points="13.7,9 16.1,9 15.5,12.6 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="st8" points="17.3,22 14.9,22 15.5,18.5 "/>
|
||||
<polygon class="st9" points="17.3,22 14.9,22 15.5,18.5 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="st8" points="20.2,10.7 21.4,12.8 18.1,14 "/>
|
||||
<polygon class="st9" points="20.2,10.7 21.4,12.8 18.1,14 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="st8" points="10.8,20.3 9.6,18.2 13,17 "/>
|
||||
<polygon class="st9" points="10.8,20.3 9.6,18.2 13,17 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="st8" points="9,13.8 10.2,11.8 13,14 "/>
|
||||
<polygon class="st9" points="9,13.8 10.2,11.8 13,14 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="st8" points="22,17.2 20.8,19.3 18.1,17 "/>
|
||||
<polygon class="st9" points="22,17.2 20.8,19.3 18.1,17 "/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
|
@ -1956,13 +1956,16 @@ void MainWindow::defineActions() {
|
|||
MenuViewCommandType);
|
||||
createToggle(MI_ACheck, tr("&Gap Check"), "", ACheckToggleAction ? 1 : 0,
|
||||
MenuViewCommandType);
|
||||
createToggle(MI_ShiftTrace, tr("Shift and Trace"), "", false,
|
||||
QAction* shiftTraceAction = createToggle(MI_ShiftTrace, tr("Shift and Trace"), "", false,
|
||||
MenuViewCommandType);
|
||||
createToggle(MI_EditShift, tr("Edit Shift"), "", false, MenuViewCommandType);
|
||||
shiftTraceAction->setIcon(QIcon(":Resources/shift_and_trace.svg"));
|
||||
shiftTraceAction = createToggle(MI_EditShift, tr("Edit Shift"), "", false, MenuViewCommandType);
|
||||
shiftTraceAction->setIcon(QIcon(":Resources/shift_and_trace_edit.svg"));
|
||||
createToggle(MI_NoShift, tr("No Shift"), "", false, MenuViewCommandType);
|
||||
CommandManager::instance()->enable(MI_EditShift, false);
|
||||
CommandManager::instance()->enable(MI_NoShift, false);
|
||||
createAction(MI_ResetShift, tr("Reset Shift"), "", MenuViewCommandType);
|
||||
shiftTraceAction = createAction(MI_ResetShift, tr("Reset Shift"), "", MenuViewCommandType);
|
||||
shiftTraceAction->setIcon(QIcon(":Resources/shift_and_trace_reset.svg"));
|
||||
|
||||
if (QGLPixelBuffer::hasOpenGLPbuffers())
|
||||
createToggle(MI_RasterizePli, tr("&Visualize Vector As Raster"), "",
|
||||
|
|
|
@ -506,6 +506,7 @@ void PreferencesPopup::onOnionDataChanged(const TPixel32 &, bool isDragging) {
|
|||
|
||||
TApp::instance()->getCurrentScene()->notifySceneChanged();
|
||||
TApp::instance()->getCurrentLevel()->notifyLevelViewChange();
|
||||
TApp::instance()->getCurrentOnionSkin()->notifyOnionSkinMaskChanged();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -806,6 +807,12 @@ void PreferencesPopup::onOnionSkinDuringPlaybackChanged(int index) {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void PreferencesPopup::onOnionColorsForShiftAndTraceChanged(int index) {
|
||||
m_pref->useOnionColorsForShiftAndTraceGhosts(index == Qt::Checked);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void PreferencesPopup::onGuidedDrawingStyleChanged(int index) {
|
||||
m_pref->setAnimatedGuidedDrawing(index);
|
||||
}
|
||||
|
@ -1533,9 +1540,11 @@ PreferencesPopup::PreferencesPopup()
|
|||
m_onionSkinVisibility = new CheckBox(tr("Onion Skin ON"));
|
||||
m_onionSkinDuringPlayback =
|
||||
new CheckBox(tr("Show Onion Skin During Playback"));
|
||||
m_frontOnionColor = new ColorField(this, false, frontColor);
|
||||
m_backOnionColor = new ColorField(this, false, backColor);
|
||||
m_inksOnly = new DVGui::CheckBox(tr("Display Lines Only "));
|
||||
m_frontOnionColor = new ColorField(this, false, frontColor);
|
||||
m_backOnionColor = new ColorField(this, false, backColor);
|
||||
m_useOnionColorsForShiftAndTraceCB = new CheckBox(
|
||||
tr("Use Onion Skin Colors for Reference Drawings of Shift and Trace"));
|
||||
m_inksOnly = new DVGui::CheckBox(tr("Display Lines Only "));
|
||||
m_inksOnly->setChecked(onlyInks);
|
||||
|
||||
int thickness = m_pref->getOnionPaperThickness();
|
||||
|
@ -1898,6 +1907,8 @@ PreferencesPopup::PreferencesPopup()
|
|||
m_onionSkinDuringPlayback->setChecked(m_pref->getOnionSkinDuringPlayback());
|
||||
m_frontOnionColor->setEnabled(m_pref->isOnionSkinEnabled());
|
||||
m_backOnionColor->setEnabled(m_pref->isOnionSkinEnabled());
|
||||
m_useOnionColorsForShiftAndTraceCB->setChecked(
|
||||
m_pref->areOnionColorsUsedForShiftAndTraceGhosts());
|
||||
m_inksOnly->setEnabled(m_pref->isOnionSkinEnabled());
|
||||
QStringList guidedDrawingStyles;
|
||||
guidedDrawingStyles << tr("Arrow Markers") << tr("Animated Guide");
|
||||
|
@ -2558,6 +2569,8 @@ PreferencesPopup::PreferencesPopup()
|
|||
onionLay->addWidget(m_inksOnly, 0, Qt::AlignLeft | Qt::AlignVCenter);
|
||||
onionLay->addWidget(m_onionSkinDuringPlayback, 0,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
onionLay->addWidget(m_useOnionColorsForShiftAndTraceCB, 0,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
QGridLayout *guidedDrawingLay = new QGridLayout();
|
||||
{
|
||||
guidedDrawingLay->addWidget(new QLabel(tr("Vector Guided Style:")), 0,
|
||||
|
@ -2952,6 +2965,9 @@ PreferencesPopup::PreferencesPopup()
|
|||
SLOT(onOnionSkinVisibilityChanged(int)));
|
||||
ret = ret && connect(m_onionSkinDuringPlayback, SIGNAL(stateChanged(int)),
|
||||
SLOT(onOnionSkinDuringPlaybackChanged(int)));
|
||||
ret = ret &&
|
||||
connect(m_useOnionColorsForShiftAndTraceCB, SIGNAL(stateChanged(int)),
|
||||
SLOT(onOnionColorsForShiftAndTraceChanged(int)));
|
||||
ret = ret && connect(m_onionPaperThickness, SIGNAL(editingFinished()),
|
||||
SLOT(onOnionPaperThicknessChanged()));
|
||||
ret = ret && connect(m_guidedDrawingStyle, SIGNAL(currentIndexChanged(int)),
|
||||
|
|
|
@ -82,7 +82,8 @@ private:
|
|||
*m_useHigherDpiOnVectorSimplifyCB, *m_keepFillOnVectorSimplifyCB,
|
||||
*m_newLevelToCameraSizeCB, *m_ignoreImageDpiCB,
|
||||
*m_syncLevelRenumberWithXsheet, *m_downArrowInLevelStripCreatesNewFrame,
|
||||
*m_enableAutoStretch, *m_enableWinInk;
|
||||
*m_enableAutoStretch, *m_enableWinInk,
|
||||
*m_useOnionColorsForShiftAndTraceCB;
|
||||
|
||||
DVGui::FileField *m_customProjectRootFileField;
|
||||
|
||||
|
@ -182,6 +183,7 @@ private slots:
|
|||
void onReplaceAfterSaveLevelAsChanged(int index);
|
||||
void onOnionSkinVisibilityChanged(int);
|
||||
void onOnionSkinDuringPlaybackChanged(int);
|
||||
void onOnionColorsForShiftAndTraceChanged(int);
|
||||
void onGuidedDrawingStyleChanged(int);
|
||||
void onActualPixelOnSceneModeChanged(int);
|
||||
void onMultiLayerStylePickerChanged(int);
|
||||
|
|
|
@ -2376,7 +2376,7 @@ includeInvisible);
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
int SceneViewer::posToRow(const TPointD &p, double distance,
|
||||
bool includeInvisible) const {
|
||||
bool includeInvisible, bool currentColumnOnly) const {
|
||||
int oldRasterizePli = TXshSimpleLevel::m_rasterizePli;
|
||||
TApp *app = TApp::instance();
|
||||
OnionSkinMask osm = app->getCurrentOnionSkin()->getOnionSkinMask();
|
||||
|
@ -2405,6 +2405,8 @@ int SceneViewer::posToRow(const TPointD &p, double distance,
|
|||
args.m_osm = &osm;
|
||||
args.m_onlyVisible = includeInvisible;
|
||||
|
||||
if (currentColumnOnly) picker.setCurrentColumnIndex(currentColumnIndex);
|
||||
|
||||
Stage::visit(picker, args);
|
||||
}
|
||||
TXshSimpleLevel::m_rasterizePli = oldRasterizePli;
|
||||
|
|
|
@ -370,8 +370,8 @@ protected:
|
|||
//! return the row of the drawings intersecting point \b p (used with onion
|
||||
//! skins)
|
||||
//! (window coordinate, pixels, bottom-left origin)
|
||||
int posToRow(const TPointD &p, double distance,
|
||||
bool includeInvisible = true) const override;
|
||||
int posToRow(const TPointD &p, double distance, bool includeInvisible = true,
|
||||
bool currentColumnOnly = false) const override;
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
void dropEvent(QDropEvent *event) override;
|
||||
|
|
|
@ -365,6 +365,11 @@ void SceneViewer::onLeave() {
|
|||
if (m_freezedStatus != NO_FREEZED) return;
|
||||
TTool *tool = TApp::instance()->getCurrentTool()->getTool();
|
||||
if (tool && tool->isEnabled()) tool->onLeave();
|
||||
|
||||
// force reset the flipping of shift & trace
|
||||
if (CommandManager::instance()->getAction(MI_ShiftTrace)->isChecked())
|
||||
TTool::getTool("T_ShiftTrace", TTool::ToonzImage)->onLeave();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#pragma once
|
|
@ -465,5 +465,8 @@
|
|||
<file>Resources/colorchiporder_upleft.svg</file>
|
||||
<file>Resources/timeline2xsheet.svg</file>
|
||||
<file>Resources/xsheet2timeline.svg</file>
|
||||
<file>Resources/shift_and_trace.svg</file>
|
||||
<file>Resources/shift_and_trace_edit.svg</file>
|
||||
<file>Resources/shift_and_trace_reset.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -344,7 +344,8 @@ Preferences::Preferences()
|
|||
, m_cursorBrushStyle("Default")
|
||||
, m_cursorOutlineEnabled(true)
|
||||
, m_currentColumnColor(TPixel::Black)
|
||||
, m_enableWinInk(false) {
|
||||
, m_enableWinInk(false)
|
||||
, m_useOnionColorsForShiftAndTraceGhosts(false) {
|
||||
TCamera camera;
|
||||
m_defLevelType = PLI_XSHLEVEL;
|
||||
m_defLevelWidth = camera.getSize().lx;
|
||||
|
@ -620,6 +621,8 @@ Preferences::Preferences()
|
|||
m_moveCurrentFrameByClickCellArea);
|
||||
getValue(*m_settings, "onionSkinEnabled", m_onionSkinEnabled);
|
||||
getValue(*m_settings, "onionSkinDuringPlayback", m_onionSkinDuringPlayback);
|
||||
getValue(*m_settings, "useOnionColorsForShiftAndTraceGhosts",
|
||||
m_useOnionColorsForShiftAndTraceGhosts);
|
||||
getValue(*m_settings, "multiLayerStylePickerEnabled",
|
||||
m_multiLayerStylePickerEnabled);
|
||||
getValue(*m_settings, "showKeyframesOnXsheetCellArea",
|
||||
|
@ -1107,6 +1110,13 @@ void Preferences::setOnionSkinDuringPlayback(bool on) {
|
|||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
void Preferences::useOnionColorsForShiftAndTraceGhosts(bool on) {
|
||||
m_useOnionColorsForShiftAndTraceGhosts = on;
|
||||
m_settings->setValue("useOnionColorsForShiftAndTraceGhosts", on ? "1" : "0");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
void Preferences::setShow0ThickLines(bool on) {
|
||||
m_show0ThickLines = on;
|
||||
m_settings->setValue(s_show0ThickLines, s_bool[on]);
|
||||
|
|
|
@ -418,9 +418,6 @@ void StageBuilder::addCell(PlayerSet &players, ToonzScene *scene, TXsheet *xsh,
|
|||
}
|
||||
|
||||
else {
|
||||
if (m_shiftTraceGhostId != TRACED)
|
||||
player.m_opacity =
|
||||
UCHAR(255.0 * (1.0 - OnionSkinMask::getOnionSkinFade(1)));
|
||||
int opacity = player.m_opacity;
|
||||
player.m_bingoOrder = 10;
|
||||
if (m_onionSkinMask.getShiftTraceStatus() !=
|
||||
|
@ -428,13 +425,15 @@ void StageBuilder::addCell(PlayerSet &players, ToonzScene *scene, TXsheet *xsh,
|
|||
if (m_shiftTraceGhostId == FIRST_GHOST) {
|
||||
player.m_opacity = 30;
|
||||
players.push_back(player);
|
||||
player.m_opacity = opacity;
|
||||
player.m_opacity = opacity;
|
||||
player.m_onionSkinDistance = -1;
|
||||
player.m_placement =
|
||||
m_onionSkinMask.getShiftTraceGhostAff(0) * player.m_placement;
|
||||
} else if (m_shiftTraceGhostId == SECOND_GHOST) {
|
||||
player.m_opacity = 30;
|
||||
players.push_back(player);
|
||||
player.m_opacity = opacity;
|
||||
player.m_opacity = opacity;
|
||||
player.m_onionSkinDistance = 1;
|
||||
player.m_placement =
|
||||
m_onionSkinMask.getShiftTraceGhostAff(1) * player.m_placement;
|
||||
}
|
||||
|
@ -532,32 +531,46 @@ void StageBuilder::addCellWithOnionSkin(PlayerSet &players, ToonzScene *scene,
|
|||
}
|
||||
}; // locals
|
||||
|
||||
if (m_onionSkinMask.isShiftTraceEnabled() && col == m_currentColumnIndex) {
|
||||
TXshCell cell = xsh->getCell(row, col);
|
||||
if (m_onionSkinMask.isShiftTraceEnabled()) {
|
||||
if (col == m_currentColumnIndex) {
|
||||
TXshCell cell = xsh->getCell(row, col);
|
||||
|
||||
// First Ghost
|
||||
int r;
|
||||
r = row + m_onionSkinMask.getShiftTraceGhostFrameOffset(0);
|
||||
if (r >= 0 && xsh->getCell(r, col) != cell &&
|
||||
(cell.getSimpleLevel() == 0 ||
|
||||
xsh->getCell(r, col).getSimpleLevel() == cell.getSimpleLevel())) {
|
||||
m_shiftTraceGhostId = FIRST_GHOST;
|
||||
addCell(players, scene, xsh, r, col, level);
|
||||
// First Ghost
|
||||
int r;
|
||||
r = row + m_onionSkinMask.getShiftTraceGhostFrameOffset(0);
|
||||
if (r >= 0 && xsh->getCell(r, col) != cell &&
|
||||
(cell.getSimpleLevel() == 0 ||
|
||||
xsh->getCell(r, col).getSimpleLevel() == cell.getSimpleLevel())) {
|
||||
m_shiftTraceGhostId = FIRST_GHOST;
|
||||
addCell(players, scene, xsh, r, col, level);
|
||||
}
|
||||
|
||||
r = row + m_onionSkinMask.getShiftTraceGhostFrameOffset(1);
|
||||
if (r >= 0 && xsh->getCell(r, col) != cell &&
|
||||
(cell.getSimpleLevel() == 0 ||
|
||||
xsh->getCell(r, col).getSimpleLevel() == cell.getSimpleLevel())) {
|
||||
m_shiftTraceGhostId = SECOND_GHOST;
|
||||
addCell(players, scene, xsh, r, col, level);
|
||||
}
|
||||
|
||||
// draw current working frame
|
||||
if (!cell.isEmpty()) {
|
||||
m_shiftTraceGhostId = TRACED;
|
||||
addCell(players, scene, xsh, row, col, level);
|
||||
m_shiftTraceGhostId = NO_GHOST;
|
||||
}
|
||||
}
|
||||
|
||||
r = row + m_onionSkinMask.getShiftTraceGhostFrameOffset(1);
|
||||
if (r >= 0 && xsh->getCell(r, col) != cell &&
|
||||
(cell.getSimpleLevel() == 0 ||
|
||||
xsh->getCell(r, col).getSimpleLevel() == cell.getSimpleLevel())) {
|
||||
m_shiftTraceGhostId = SECOND_GHOST;
|
||||
addCell(players, scene, xsh, r, col, level);
|
||||
}
|
||||
|
||||
// draw current working frame
|
||||
if (!cell.isEmpty()) {
|
||||
m_shiftTraceGhostId = TRACED;
|
||||
addCell(players, scene, xsh, row, col, level);
|
||||
m_shiftTraceGhostId = NO_GHOST;
|
||||
// flip non-current columns as well
|
||||
else {
|
||||
int flipKey = m_onionSkinMask.getGhostFlipKey();
|
||||
if (flipKey == Qt::Key_F1) {
|
||||
int r = row + m_onionSkinMask.getShiftTraceGhostFrameOffset(0);
|
||||
addCell(players, scene, xsh, r, col, level);
|
||||
} else if (flipKey == Qt::Key_F3) {
|
||||
int r = row + m_onionSkinMask.getShiftTraceGhostFrameOffset(1);
|
||||
addCell(players, scene, xsh, r, col, level);
|
||||
} else
|
||||
addCell(players, scene, xsh, row, col, level);
|
||||
}
|
||||
} else if (locals::doStandardOnionSkin(this, xsh, level, col)) {
|
||||
std::vector<int> rows;
|
||||
|
@ -674,17 +687,14 @@ void StageBuilder::addSimpleLevelFrame(PlayerSet &players,
|
|||
return;
|
||||
}
|
||||
|
||||
if (m_shiftTraceGhostId != TRACED)
|
||||
player.m_opacity =
|
||||
UCHAR(255.0 * (1.0 - OnionSkinMask::getOnionSkinFade(1)));
|
||||
;
|
||||
int opacity = player.m_opacity;
|
||||
player.m_bingoOrder = 10;
|
||||
if (m_onionSkinMask.getShiftTraceStatus() !=
|
||||
OnionSkinMask::ENABLED_WITHOUT_GHOST_MOVEMENTS) {
|
||||
player.m_opacity = 30;
|
||||
players.push_back(player);
|
||||
player.m_opacity = opacity;
|
||||
player.m_opacity = opacity;
|
||||
player.m_onionSkinDistance = (ghostIndex == 0) ? -1 : 1;
|
||||
player.m_placement = m_onionSkinMask.getShiftTraceGhostAff(ghostIndex) *
|
||||
player.m_placement;
|
||||
}
|
||||
|
@ -832,10 +842,11 @@ void Stage::visit(Visitor &visitor, const VisitArgs &args) {
|
|||
sb.m_onionSkinMask = *osm;
|
||||
sb.m_currentFrameId = args.m_currentFrameId;
|
||||
sb.m_isGuidedDrawingEnabled = args.m_isGuidedDrawingEnabled;
|
||||
Player::m_onionSkinFrontSize = 0;
|
||||
Player::m_onionSkinBackSize = 0;
|
||||
Player::m_firstBackOnionSkin = 0;
|
||||
Player::m_lastBackVisibleSkin = 0;
|
||||
Player::m_onionSkinFrontSize = 0;
|
||||
Player::m_onionSkinBackSize = 0;
|
||||
Player::m_firstBackOnionSkin = 0;
|
||||
Player::m_lastBackVisibleSkin = 0;
|
||||
Player::m_isShiftAndTraceEnabled = osm->isShiftTraceEnabled();
|
||||
sb.addFrame(sb.m_players, scene, xsh, row, 0, args.m_onlyVisible,
|
||||
args.m_checkPreviewVisibility);
|
||||
|
||||
|
@ -867,14 +878,15 @@ void Stage::visit(Visitor &visitor, TXshSimpleLevel *level, const TFrameId &fid,
|
|||
const OnionSkinMask &osm, bool isPlaying,
|
||||
int isGuidedDrawingEnabled) {
|
||||
StageBuilder sb;
|
||||
sb.m_vs = &visitor.m_vs;
|
||||
sb.m_onionSkinMask = osm;
|
||||
sb.m_currentFrameId = fid;
|
||||
sb.m_isGuidedDrawingEnabled = isGuidedDrawingEnabled;
|
||||
Player::m_onionSkinFrontSize = 0;
|
||||
Player::m_onionSkinBackSize = 0;
|
||||
Player::m_firstBackOnionSkin = 0;
|
||||
Player::m_lastBackVisibleSkin = 0;
|
||||
sb.m_vs = &visitor.m_vs;
|
||||
sb.m_onionSkinMask = osm;
|
||||
sb.m_currentFrameId = fid;
|
||||
sb.m_isGuidedDrawingEnabled = isGuidedDrawingEnabled;
|
||||
Player::m_onionSkinFrontSize = 0;
|
||||
Player::m_onionSkinBackSize = 0;
|
||||
Player::m_firstBackOnionSkin = 0;
|
||||
Player::m_lastBackVisibleSkin = 0;
|
||||
Player::m_isShiftAndTraceEnabled = osm.isShiftTraceEnabled();
|
||||
sb.addSimpleLevelFrame(sb.m_players, level, fid);
|
||||
updateOnionSkinSize(sb.m_players);
|
||||
sb.visit(sb.m_players, visitor, isPlaying);
|
||||
|
|
|
@ -19,10 +19,11 @@ using namespace Stage;
|
|||
// Stage::Player implementation
|
||||
//*****************************************************************************************
|
||||
|
||||
double Player::m_onionSkinFrontSize = 0;
|
||||
double Player::m_onionSkinBackSize = 0;
|
||||
double Player::m_firstBackOnionSkin = 0;
|
||||
double Player::m_lastBackVisibleSkin = 0;
|
||||
double Player::m_onionSkinFrontSize = 0;
|
||||
double Player::m_onionSkinBackSize = 0;
|
||||
double Player::m_firstBackOnionSkin = 0;
|
||||
double Player::m_lastBackVisibleSkin = 0;
|
||||
bool Player::m_isShiftAndTraceEnabled = false;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "toonz/txshleveltypes.h"
|
||||
#include "imagebuilders.h"
|
||||
#include "toonz/tframehandle.h"
|
||||
#include "toonz/preferences.h"
|
||||
|
||||
// Qt includes
|
||||
#include <QImage>
|
||||
|
@ -228,6 +229,12 @@ void Picker::setDistance(double d) { m_minDist2 = d * d; }
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
void Picker::onImage(const Stage::Player &player) {
|
||||
// if m_currentColumnIndex is other than the default value (-1),
|
||||
// then pick only the current column.
|
||||
if (m_currentColumnIndex != -1 &&
|
||||
m_currentColumnIndex != player.m_ancestorColumnIndex)
|
||||
return;
|
||||
|
||||
bool picked = false;
|
||||
TAffine aff = m_viewAff * player.m_placement;
|
||||
TPointD point = aff.inv() * m_point;
|
||||
|
@ -815,7 +822,9 @@ void RasterPainter::onVectorImage(TVectorImage *vi,
|
|||
if (player.m_onionSkinDistance != c_noOnionSkin) {
|
||||
TPixel32 frontOnionColor, backOnionColor;
|
||||
|
||||
if (player.m_onionSkinDistance != 0) {
|
||||
if (player.m_onionSkinDistance != 0 &&
|
||||
(!player.m_isShiftAndTraceEnabled ||
|
||||
Preferences::instance()->areOnionColorsUsedForShiftAndTraceGhosts())) {
|
||||
prefs.getOnionData(frontOnionColor, backOnionColor, inksOnly);
|
||||
bgColor =
|
||||
(player.m_onionSkinDistance < 0) ? backOnionColor : frontOnionColor;
|
||||
|
@ -961,11 +970,17 @@ void RasterPainter::onRasterImage(TRasterImage *ri,
|
|||
? 0.9
|
||||
: (1.0 - OnionSkinMask::getOnionSkinFade(
|
||||
player.m_onionSkinDistance));
|
||||
alpha = tcrop(tround(onionSkiFade * 255.0), 0, 255);
|
||||
onionMode = (player.m_onionSkinDistance > 0)
|
||||
? Node::eOnionSkinFront
|
||||
: ((player.m_onionSkinDistance < 0) ? Node::eOnionSkinBack
|
||||
: Node::eOnionSkinNone);
|
||||
alpha = tcrop(tround(onionSkiFade * 255.0), 0, 255);
|
||||
if (player.m_isShiftAndTraceEnabled &&
|
||||
!Preferences::instance()->areOnionColorsUsedForShiftAndTraceGhosts())
|
||||
onionMode = Node::eOnionSkinNone;
|
||||
else {
|
||||
onionMode =
|
||||
(player.m_onionSkinDistance > 0)
|
||||
? Node::eOnionSkinFront
|
||||
: ((player.m_onionSkinDistance < 0) ? Node::eOnionSkinBack
|
||||
: Node::eOnionSkinNone);
|
||||
}
|
||||
} else if (player.m_opacity < 255)
|
||||
alpha = player.m_opacity;
|
||||
TXshSimpleLevel *sl = player.m_sl;
|
||||
|
@ -1018,11 +1033,19 @@ void RasterPainter::onToonzImage(TToonzImage *ti, const Stage::Player &player) {
|
|||
? 0.9
|
||||
: (1.0 - OnionSkinMask::getOnionSkinFade(
|
||||
player.m_onionSkinDistance));
|
||||
alpha = tcrop(tround(onionSkiFade * 255.0), 0, 255);
|
||||
onionMode = (player.m_onionSkinDistance > 0)
|
||||
? Node::eOnionSkinFront
|
||||
: ((player.m_onionSkinDistance < 0) ? Node::eOnionSkinBack
|
||||
: Node::eOnionSkinNone);
|
||||
alpha = tcrop(tround(onionSkiFade * 255.0), 0, 255);
|
||||
|
||||
if (player.m_isShiftAndTraceEnabled &&
|
||||
!Preferences::instance()->areOnionColorsUsedForShiftAndTraceGhosts())
|
||||
onionMode = Node::eOnionSkinNone;
|
||||
else {
|
||||
onionMode =
|
||||
(player.m_onionSkinDistance > 0)
|
||||
? Node::eOnionSkinFront
|
||||
: ((player.m_onionSkinDistance < 0) ? Node::eOnionSkinBack
|
||||
: Node::eOnionSkinNone);
|
||||
}
|
||||
|
||||
} else if (player.m_opacity < 255)
|
||||
alpha = player.m_opacity;
|
||||
|
||||
|
|
Loading…
Reference in a new issue