Guided Drawing Feature (#1297)

* Guided Drawing Feature
This commit is contained in:
Jeremy Bullock 2017-09-24 23:29:38 -06:00 committed by shun-iwasawa
parent feed0d22f3
commit 1e17edb69a
15 changed files with 411 additions and 68 deletions

View file

@ -16,6 +16,7 @@
#include "tconvert.h"
#include "tcurves.h"
#include "tstrokeoutline.h"
#include <QTime>
#ifndef _WIN32
#define CALLBACK
@ -132,6 +133,108 @@ void drawControlPoints(const TVectorRenderData &rd, TStroke *stroke,
#endif
//-----------------------------------------------------------------------------
void drawArrows(TStroke *stroke, bool onlyFirstPoint) {
double length = stroke->getLength(0.0, 1.0);
int points = length / 20;
if (points < 2) points += 1;
double currentPosition = 0.0;
TPointD prePoint, point, postPoint;
glColor3d(1.0, 0.0, 0.0);
for (int i = 0; i <= points; i++) {
currentPosition = i / (double)points;
point = stroke->getPointAtLength(length * currentPosition);
prePoint = (i == 0) ? point : stroke->getPointAtLength(
length * (currentPosition - 0.02));
postPoint = (i == points) ? point : stroke->getPointAtLength(
length * (currentPosition + 0.02));
if (prePoint == postPoint) continue;
double radian =
std::atan2(postPoint.y - prePoint.y, postPoint.x - prePoint.x);
double degree = radian * 180.0 / 3.14159265;
glPushMatrix();
glTranslated(point.x, point.y, 0);
glRotated(degree, 0, 0, 1);
glBegin(GL_LINES);
glVertex2d(0, 0);
glVertex2d(-3, -3);
glVertex2d(0, 0);
glVertex2d(-3, 3);
glEnd();
glPopMatrix();
if (onlyFirstPoint) break;
// make the arrow blue from the second one
glColor3d(0.0, 0.0, 1.0);
}
}
//-----------------------------------------------------------------------------
// Used for Guided Drawing
void drawFirstControlPoint(const TVectorRenderData &rd, TStroke *stroke) {
TPointD p = stroke->getPoint(0.0);
double length = stroke->getLength(0.0, 1.0);
int msecs = QTime::currentTime().msec();
double modifier = (msecs / 100) * 0.1;
TPointD startPoint = stroke->getPointAtLength(length * modifier);
TPointD endPoint = stroke->getPointAtLength(length * 0.10);
double j = 0.025;
glPushMatrix();
tglMultMatrix(rd.m_aff);
if (!rd.m_animatedGuidedDrawing) glLineWidth(2.0f);
glColor3d(0.0, 1.0, 0.0);
if (!rd.m_animatedGuidedDrawing) {
drawArrows(stroke, false);
}
if (rd.m_animatedGuidedDrawing) {
drawArrows(stroke, true);
glColor3d(0.0, 1.0, 0.0);
j = 0.025 + modifier;
glBegin(GL_LINES);
// draw the first animated section
for (int i = 0; i < 8; i++) {
endPoint = stroke->getPointAtLength(length * j);
glVertex2d(startPoint.x, startPoint.y);
glVertex2d(endPoint.x, endPoint.y);
startPoint = endPoint;
j += 0.025;
if (j > 1) {
j -= 1;
startPoint = stroke->getPointAtLength(length * j);
}
}
modifier = modifier + 0.5;
if (modifier >= 1) modifier -= 1;
startPoint = stroke->getPointAtLength(length * modifier);
j = 0.025 + modifier;
// draw another animated section
for (int i = 0; i < 8; i++) {
endPoint = stroke->getPointAtLength(length * j);
glVertex2d(startPoint.x, startPoint.y);
glVertex2d(endPoint.x, endPoint.y);
startPoint = endPoint;
j += 0.025;
if (j > 1) {
j -= 1;
startPoint = stroke->getPointAtLength(length * j);
}
}
glEnd();
}
glLineWidth(1.0f);
glPopMatrix();
}
//=============================================================================
/*TPixel TransparencyCheckBlackBgInk = TPixel(255,255,255);
@ -483,11 +586,20 @@ static void tglDoDraw(const TVectorRenderData &rd, const TStroke *s) {
if (color.m != 0) visible = true;
}
}
#if DISEGNO_OUTLINE == 0
if (visible)
#endif
tglDraw(rd, s, false);
if (visible) {
// Change stroke color to blue if guided drawing
if (rd.m_showGuidedDrawing && rd.m_highLightNow) {
TVectorRenderData *newRd = new TVectorRenderData(
rd, rd.m_aff, rd.m_clippingRect, rd.m_palette, rd.m_guidedCf);
tglDraw(*newRd, s, false);
delete newRd;
TStroke *new_s = (TStroke *)s;
drawFirstControlPoint(rd, new_s);
} else {
tglDraw(rd, s, false);
}
}
#ifdef _DEBUG
// drawControlPoints(rd, vim->getStroke(i), sqrt(tglGetPixelSize2()), true);
// assert(checkQuadraticDistance(vim->getStroke(i),true));
@ -542,6 +654,11 @@ rdRegions.m_alphaChannel = rdRegions.m_antiAliasing = false;*/
tglDoDraw(rdRegions, vim->getRegion(regionIndex));
while (strokeIndex < vim->getStrokeCount() &&
vim->sameGroup(strokeIndex, currStrokeIndex)) {
if (rd.m_indexToHighlight != strokeIndex) {
rd.m_highLightNow = false;
} else {
rd.m_highLightNow = true;
}
#if DISEGNO_OUTLINE == 1
CurrStrokeIndex = strokeIndex;
CurrVimg = vim;

View file

@ -329,6 +329,11 @@ public:
return m_useNumpadForSwitchingStyles;
}
void setGuidedDrawing(int status);
int getGuidedDrawing() { return m_guidedDrawingType; }
void setAnimatedGuidedDrawing(bool status);
bool getAnimatedGuidedDrawing() const { return m_animatedGuidedDrawing; }
void enableNewLevelSizeToCameraSize(bool on);
bool isNewLevelSizeToCameraSizeEnabled() const {
return m_newLevelSizeToCameraSizeEnabled;
@ -519,7 +524,7 @@ private:
m_chunkSize, m_blanksCount, m_onionPaperThickness, m_step, m_shrink,
m_textureSize, m_autocreationType, m_keyframeType, m_animationStep,
m_ffmpegTimeout; // seconds
int m_projectRoot, m_importPolicy, m_interfaceFontWeight;
int m_projectRoot, m_importPolicy, m_interfaceFontWeight, m_guidedDrawingType;
QString m_currentLanguage, m_currentStyleSheet;
int m_undoMemorySize, // in megabytes
m_dragCellsBehaviour, m_lineTestFpsCapture, m_defLevelType, m_xsheetStep,
@ -531,7 +536,7 @@ private:
m_rewindAfterPlaybackEnabled, m_fitToFlipbookEnabled, m_autosaveEnabled,
m_autosaveSceneEnabled, m_autosaveOtherFilesEnabled,
m_defaultViewerEnabled, m_pixelsOnly, m_showXSheetToolbar,
m_expandFunctionHeader, m_showColumnNumbers;
m_expandFunctionHeader, m_showColumnNumbers, m_animatedGuidedDrawing;
bool m_rasterOptimizedMemory, m_saveUnpaintedInCleanup,
m_askForOverrideRender, m_automaticSVNFolderRefreshEnabled, m_SVNEnabled,
m_levelsBackupEnabled, m_minimizeSaveboxAfterEditing,

View file

@ -65,12 +65,14 @@ DVAPI void visit(Visitor &visitor, ToonzScene *scene, TXsheet *xsh, int row);
//-----------------------------------------------------------------------------
DVAPI void visit(Visitor &visitor, TXshSimpleLevel *level, const TFrameId &fid,
const OnionSkinMask &osm, bool isPlaying);
const OnionSkinMask &osm, bool isPlaying,
int isGuidedDrawingEnabled = 0);
//-----------------------------------------------------------------------------
DVAPI void visit(Visitor &visitor, TXshLevel *level, const TFrameId &fid,
const OnionSkinMask &osm, bool isPlaying);
const OnionSkinMask &osm, bool isPlaying,
double isGuidedDrawingEnabled = 0.0);
//-----------------------------------------------------------------------------
} // namespace Stage

View file

@ -83,10 +83,13 @@ public:
//! of) the current column
bool m_isCurrentXsheetLevel; //!< Whether the player's xsheet is the \a
//! current one
bool m_isEditingLevel;
bool m_isVisibleinOSM; // Whether the current frame is in the onion skin
int m_isGuidedDrawingEnabled = 0;
TXshSimpleLevel *m_sl; //!< (not owned) The player's simple level
TFrameId m_fid; //!< The player's frame in m_sl
TFrameId
m_currentFrameId; // The current frame selected in the level or xsheet
TXsheet *m_xsh; //!< (not owned) The player's xsheet
int m_column; //!< The player's xsheet column
int m_frame; //!< The player's xhseet row (could be not the current, due to
@ -101,6 +104,8 @@ public:
static double m_onionSkinFrontSize;
static double m_onionSkinBackSize;
static double m_firstBackOnionSkin;
static double m_lastBackVisibleSkin;
TPixel32 m_filterColor;

View file

@ -126,12 +126,13 @@ struct DVAPI VisitArgs {
const OnionSkinMask *m_osm;
int m_xsheetLevel;
TFrameId m_currentFrameId;
bool m_camera3d;
bool m_isPlaying;
bool m_onlyVisible;
bool m_checkPreviewVisibility;
bool m_rasterizePli;
int m_isGuidedDrawingEnabled;
public:
VisitArgs()
@ -145,6 +146,7 @@ public:
, m_isPlaying(false)
, m_onlyVisible(false)
, m_checkPreviewVisibility(false)
, m_isGuidedDrawingEnabled(0)
, m_rasterizePli(false) {}
};

View file

@ -49,6 +49,7 @@ public:
public:
const TColorFunction
*m_cf; //!< [\p not-owned] Transform to be used for drawing RGBM colors.
const TColorFunction *m_guidedCf;
const TPalette *m_palette; //!< [\p not-owned] Palette to be used for
//! translating color indexes to
//! RGBM colors.
@ -63,6 +64,7 @@ public:
int m_colorCheckIndex; //!< Color index to be highlighted in <I>color
//! check</I> mode.
int m_indexToHighlight; // for guided vector drawing
bool m_alphaChannel, //!< Whether alpha channel is enabled.
m_antiAliasing, //!< Whether antialiasing must be applied.
@ -79,8 +81,12 @@ public:
//! rendered anyway.
m_regionAntialias, //!< Whether regions should be rendered with
//! antialiasing at boundaries.
m_isOfflineRender; //!< Whether image rendering is in render or
m_isOfflineRender, //!< Whether image rendering is in render or
//! camera-stand (preview) mode.
m_showGuidedDrawing, // Whether this image is being used for guided
// drawing
m_highLightNow; // Show highlight on active stroke
bool m_animatedGuidedDrawing = false;
//! \deprecated Use the above individual options instead.
//! \todo Remove it ASAP.
public:
@ -111,7 +117,11 @@ public:
, m_regionAntialias(false) // No need for pretty region boundaries,
// typically shadowed by strokes
// This is also related to interference with the directly above param
, m_isOfflineRender(false) {} // By definition
, m_isOfflineRender(false) // By definition
, m_indexToHighlight(-1)
, m_highLightNow(false)
, m_guidedCf(0)
, m_showGuidedDrawing(false) {}
TVectorRenderData(ProductionSettings, const TAffine &aff,
const TRect &clippingRect, const TPalette *palette,
@ -137,7 +147,11 @@ public:
, m_show0ThickStrokes(false) // Invisible strokes must be invisible
, m_regionAntialias(true) // Pretty region boundaries under invisible or
// semitransparent strokes
, m_isOfflineRender(true) {} // By definition
, m_isOfflineRender(true) // By definition
, m_indexToHighlight(-1)
, m_highLightNow(false)
, m_guidedCf(0)
, m_showGuidedDrawing(false) {}
TVectorRenderData(const TVectorRenderData &other, const TAffine &aff,
const TRect &clippingRect, const TPalette *palette,
@ -161,7 +175,11 @@ public:
, m_is3dView(other.m_is3dView)
, m_show0ThickStrokes(other.m_show0ThickStrokes)
, m_regionAntialias(other.m_regionAntialias)
, m_isOfflineRender(other.m_isOfflineRender) {
, m_isOfflineRender(other.m_isOfflineRender)
, m_indexToHighlight(other.m_indexToHighlight)
, m_highLightNow(other.m_highLightNow)
, m_guidedCf(other.m_guidedCf)
, m_showGuidedDrawing(other.m_showGuidedDrawing) {
} //!< Constructs from explicit primary context settings while
//! copying the rest from another instance.
@ -188,7 +206,11 @@ public:
, m_is3dView(is3dView)
, m_show0ThickStrokes(true)
, m_regionAntialias(false)
, m_isOfflineRender(false) {
, m_isOfflineRender(false)
, m_indexToHighlight(-1)
, m_highLightNow(false)
, m_guidedCf(0)
, m_showGuidedDrawing(false) {
} //!< Constructs settings with default ViewerSettings.
//! \deprecated Use constructors with explicit settings type tag.
};

View file

@ -725,6 +725,12 @@ void PreferencesPopup::onOnionSkinDuringPlaybackChanged(int index) {
//-----------------------------------------------------------------------------
void PreferencesPopup::onGuidedDrawingStyleChanged(int index) {
m_pref->setAnimatedGuidedDrawing(index);
}
//-----------------------------------------------------------------------------
void PreferencesPopup::onActualPixelOnSceneModeChanged(int index) {
m_pref->enableActualPixelViewOnSceneEditingMode(index == Qt::Checked);
}
@ -1320,6 +1326,7 @@ PreferencesPopup::PreferencesPopup()
int thickness = m_pref->getOnionPaperThickness();
m_onionPaperThickness = new DVGui::IntLineEdit(this, thickness, 0, 100);
m_guidedDrawingStyle = new QComboBox(this);
//--- Transparency Check ------------------------------
categoryList->addItem(tr("Transparency Check"));
@ -1619,6 +1626,10 @@ PreferencesPopup::PreferencesPopup()
m_frontOnionColor->setEnabled(m_pref->isOnionSkinEnabled());
m_backOnionColor->setEnabled(m_pref->isOnionSkinEnabled());
m_inksOnly->setEnabled(m_pref->isOnionSkinEnabled());
QStringList guidedDrawingStyles;
guidedDrawingStyles << tr("Arrow Markers") << tr("Animated Guide");
m_guidedDrawingStyle->addItems(guidedDrawingStyles);
m_guidedDrawingStyle->setCurrentIndex(m_pref->getAnimatedGuidedDrawing());
//--- Version Control ------------------------------
m_enableVersionControl->setChecked(m_pref->isSVNEnabled());
@ -2167,7 +2178,17 @@ PreferencesPopup::PreferencesPopup()
onionLay->addWidget(m_inksOnly, 0, Qt::AlignLeft | Qt::AlignVCenter);
onionLay->addWidget(m_onionSkinDuringPlayback, 0,
Qt::AlignLeft | Qt::AlignVCenter);
QGridLayout *guidedDrawingLay = new QGridLayout();
{
guidedDrawingLay->addWidget(new QLabel(tr("Vector Guided Style:")), 0,
0, Qt::AlignLeft | Qt::AlignVCenter);
guidedDrawingLay->addWidget(m_guidedDrawingStyle, 0, 1,
Qt::AlignLeft | Qt::AlignVCenter);
guidedDrawingLay->setColumnStretch(0, 0);
guidedDrawingLay->setColumnStretch(1, 0);
guidedDrawingLay->setColumnStretch(2, 1);
}
onionLay->addLayout(guidedDrawingLay, 0);
onionLay->addStretch(1);
}
onionBox->setLayout(onionLay);
@ -2474,7 +2495,8 @@ PreferencesPopup::PreferencesPopup()
SLOT(onOnionSkinDuringPlaybackChanged(int)));
ret = ret && connect(m_onionPaperThickness, SIGNAL(editingFinished()),
SLOT(onOnionPaperThicknessChanged()));
ret = ret && connect(m_guidedDrawingStyle, SIGNAL(currentIndexChanged(int)),
SLOT(onGuidedDrawingStyleChanged(int)));
//--- Transparency Check ----------------------
ret = ret && connect(m_transpCheckBgColor,
SIGNAL(colorChanged(const TPixel32 &, bool)),

View file

@ -54,7 +54,8 @@ private:
QComboBox *m_keyframeType, *m_cellsDragBehaviour, *m_defScanLevelType,
*m_defLevelType, *m_autocreationType, *m_levelFormatNames,
*m_columnIconOm, *m_unitOm, *m_cameraUnitOm, *m_importPolicy,
*m_interfaceFont, *m_interfaceFontWeight, *m_vectorSnappingTargetCB;
*m_interfaceFont, *m_interfaceFontWeight, *m_vectorSnappingTargetCB,
*m_guidedDrawingStyle;
DVGui::MeasuredDoubleLineEdit *m_defLevelWidth, *m_defLevelHeight;
@ -163,6 +164,7 @@ private slots:
void onReplaceAfterSaveLevelAsChanged(int index);
void onOnionSkinVisibilityChanged(int);
void onOnionSkinDuringPlaybackChanged(int);
void onGuidedDrawingStyleChanged(int);
void onActualPixelOnSceneModeChanged(int);
void onMultiLayerStylePickerChanged(int);
void onLevelNameOnEachMarkerChanged(int);

View file

@ -65,6 +65,7 @@
#include "tofflinegl.h"
#include "tstopwatch.h"
#include "trop.h"
#include "tproperty.h"
#include "timagecache.h"
#include "trasterimage.h"
#include "tstroke.h"
@ -1592,6 +1593,9 @@ void SceneViewer::drawScene() {
bool fillFullColorRaster = TXshSimpleLevel::m_fillFullColorRaster;
TXshSimpleLevel::m_fillFullColorRaster = false;
// Guided Drawing Check
int useGuidedDrawing = Preferences::instance()->getGuidedDrawing();
m_minZ = 0;
if (is3DView()) {
Stage::OpenGlPainter painter(getViewMatrix(), clipRect, m_visualSettings,
@ -1615,6 +1619,14 @@ void SceneViewer::drawScene() {
args.m_osm = &osm;
args.m_camera3d = true;
args.m_xsheetLevel = xsheetLevel;
args.m_currentFrameId =
app->getCurrentXsheet()
->getXsheet()
->getCell(app->getCurrentFrame()->getFrame(), args.m_col)
.getFrameId();
args.m_isGuidedDrawingEnabled = useGuidedDrawing;
// args.m_currentFrameId = app->getCurrentFrame()->getFid();
Stage::visit(painter, args);
m_minZ = painter.getMinZ();
@ -1646,7 +1658,7 @@ void SceneViewer::drawScene() {
Stage::visit(painter, app->getCurrentLevel()->getLevel(),
app->getCurrentFrame()->getFid(),
app->getCurrentOnionSkin()->getOnionSkinMask(),
frameHandle->isPlaying());
frameHandle->isPlaying(), useGuidedDrawing);
} else {
std::pair<TXsheet *, int> xr;
int xsheetLevel = 0;
@ -1665,6 +1677,12 @@ void SceneViewer::drawScene() {
args.m_osm = &osm;
args.m_xsheetLevel = xsheetLevel;
args.m_isPlaying = frameHandle->isPlaying();
args.m_currentFrameId =
app->getCurrentXsheet()
->getXsheet()
->getCell(app->getCurrentFrame()->getFrame(), args.m_col)
.getFrameId();
args.m_isGuidedDrawingEnabled = useGuidedDrawing;
Stage::visit(painter, args);
}

View file

@ -176,7 +176,32 @@ SceneViewerContextMenu::SceneViewerContextMenu(SceneViewer *parent)
if (Preferences::instance()->isOnionSkinEnabled() &&
!parent->isPreviewEnabled())
OnioniSkinMaskGUI::addOnionSkinCommand(this);
QMenu *guidedDrawingMenu = addMenu(tr("Vector Guided Drawing"));
int guidedDrawingStatus = Preferences::instance()->getGuidedDrawing();
action = guidedDrawingMenu->addAction(tr("Off"));
action->setCheckable(true);
action->setChecked(guidedDrawingStatus == 0);
ret = ret &&
parent->connect(action, SIGNAL(triggered()), this,
SLOT(setGuidedDrawingOff()));
action = guidedDrawingMenu->addAction(tr("Closest Drawing"));
action->setCheckable(true);
action->setChecked(guidedDrawingStatus == 1);
ret = ret &&
parent->connect(action, SIGNAL(triggered()), this,
SLOT(setGuidedDrawingClosest()));
action = guidedDrawingMenu->addAction(tr("Farthest Drawing"));
action->setCheckable(true);
action->setChecked(guidedDrawingStatus == 2);
ret = ret &&
parent->connect(action, SIGNAL(triggered()), this,
SLOT(setGuidedDrawingFarthest()));
action = guidedDrawingMenu->addAction(tr("All Drawings"));
action->setCheckable(true);
action->setChecked(guidedDrawingStatus == 3);
ret = ret &&
parent->connect(action, SIGNAL(triggered()), this,
SLOT(setGuidedDrawingAll()));
// Zero Thick
if (!parent->isPreviewEnabled())
ZeroThickToggleGui::addZeroThickCommand(this);
@ -385,6 +410,26 @@ void SceneViewerContextMenu::onSetCurrent() {
}
}
//-----------------------------------------------------------------------------
void SceneViewerContextMenu::setGuidedDrawingOff() {
Preferences::instance()->setGuidedDrawing(0);
}
//-----------------------------------------------------------------------------
void SceneViewerContextMenu::setGuidedDrawingClosest() {
Preferences::instance()->setGuidedDrawing(1);
}
//-----------------------------------------------------------------------------
void SceneViewerContextMenu::setGuidedDrawingFarthest() {
Preferences::instance()->setGuidedDrawing(2);
}
//-----------------------------------------------------------------------------
void SceneViewerContextMenu::setGuidedDrawingAll() {
Preferences::instance()->setGuidedDrawing(3);
}
//-----------------------------------------------------------------------------
void SceneViewerContextMenu::savePreviewedFrames() {

View file

@ -31,6 +31,10 @@ public slots:
void enterVectorImageGroup();
void exitVectorImageGroup();
void setGuidedDrawingOff();
void setGuidedDrawingClosest();
void setGuidedDrawingFarthest();
void setGuidedDrawingAll();
void onShowHide();
void onSetCurrent();

View file

@ -322,6 +322,8 @@ Preferences::Preferences()
, m_useArrowKeyToShiftCellSelection(false)
, m_inputCellsWithoutDoubleClickingEnabled(false)
, m_importPolicy(0)
, m_guidedDrawingType(0)
, m_animatedGuidedDrawing(false)
, m_ignoreImageDpi(false)
, m_watchFileSystem(true)
, m_shortcutCommandsWhileRenamingCellEnabled(false) {
@ -612,6 +614,8 @@ Preferences::Preferences()
getValue(*m_settings, "interfaceFontWeight", m_interfaceFontWeight);
getValue(*m_settings, "useNumpadForSwitchingStyles",
m_useNumpadForSwitchingStyles);
getValue(*m_settings, "guidedDrawingType", m_guidedDrawingType);
getValue(*m_settings, "animatedGuidedDrawing", m_animatedGuidedDrawing);
getValue(*m_settings, "newLevelSizeToCameraSizeEnabled",
m_newLevelSizeToCameraSizeEnabled);
getValue(*m_settings, "showXSheetToolbar", m_showXSheetToolbar);
@ -1450,6 +1454,20 @@ void Preferences::enableUseNumpadForSwitchingStyles(bool on) {
//-----------------------------------------------------------------
void Preferences::setGuidedDrawing(int status) {
m_guidedDrawingType = status;
m_settings->setValue("guidedDrawingType", status);
}
//-----------------------------------------------------------------
void Preferences::setAnimatedGuidedDrawing(bool status) {
m_animatedGuidedDrawing = status;
m_settings->setValue("animatedGuidedDrawing", status);
}
//-----------------------------------------------------------------
void Preferences::enableNewLevelSizeToCameraSize(bool on) {
m_newLevelSizeToCameraSizeEnabled = on;
m_settings->setValue("newLevelSizeToCameraSizeEnabled", on ? "1" : "0");

View file

@ -76,7 +76,8 @@ namespace {
void updateOnionSkinSize(const PlayerSet &players) {
assert(Player::m_onionSkinFrontSize == 0 && Player::m_onionSkinBackSize == 0);
int i;
int maxOnionSkinFrontValue = 0, maxOnionSkinBackValue = 0;
int maxOnionSkinFrontValue = 0, maxOnionSkinBackValue = 0,
firstBackOnionSkin = 0, lastBackVisibleSkin = 0;
for (i = 0; i < (int)players.size(); i++) {
Player player = players[i];
if (player.m_onionSkinDistance == c_noOnionSkin) continue;
@ -86,9 +87,20 @@ void updateOnionSkinSize(const PlayerSet &players) {
if (player.m_onionSkinDistance < 0 &&
maxOnionSkinBackValue > player.m_onionSkinDistance)
maxOnionSkinBackValue = player.m_onionSkinDistance;
if (firstBackOnionSkin == 0 && player.m_onionSkinDistance < 0)
firstBackOnionSkin = player.m_onionSkinDistance;
else if (player.m_onionSkinDistance < 0 &&
firstBackOnionSkin < player.m_onionSkinDistance)
firstBackOnionSkin = player.m_onionSkinDistance;
// Level Editing Mode can send players at a depth beyond what is visible.
if (player.m_onionSkinDistance < lastBackVisibleSkin &&
player.m_isVisibleinOSM)
lastBackVisibleSkin = player.m_onionSkinDistance;
}
Player::m_onionSkinFrontSize = maxOnionSkinFrontValue;
Player::m_onionSkinBackSize = maxOnionSkinBackValue;
Player::m_firstBackOnionSkin = firstBackOnionSkin;
Player::m_lastBackVisibleSkin = lastBackVisibleSkin;
}
//-----------------------------------------------------------------------------
@ -184,6 +196,9 @@ public:
int m_currentXsheetLevel; // level of the current xsheet, see: editInPlace
int m_xsheetLevel; // xsheet-level of the column being processed
// for guided drawing
TFrameId m_currentFrameId;
int m_isGuidedDrawingEnabled;
std::vector<TXshColumn *> m_ancestors;
const ImagePainter::VisualSettings *m_vs;
@ -361,6 +376,8 @@ void StageBuilder::addCell(PlayerSet &players, ToonzScene *scene, TXsheet *xsh,
player.m_xsh = xsh;
player.m_column = col;
player.m_frame = row;
player.m_currentFrameId = m_currentFrameId;
player.m_isGuidedDrawingEnabled = m_isGuidedDrawingEnabled;
player.m_dpiAff = sl ? getDpiAffine(sl, cell.m_frameId) : TAffine();
player.m_onionSkinDistance = m_onionSkinDistance;
player.m_isCurrentColumn = (m_currentColumnIndex == col);
@ -638,6 +655,10 @@ void StageBuilder::addSimpleLevelFrame(PlayerSet &players,
player.m_fid = fid2;
player.m_isCurrentColumn = true;
player.m_isCurrentXsheetLevel = true;
player.m_isEditingLevel = true;
player.m_currentFrameId = m_currentFrameId;
player.m_isGuidedDrawingEnabled = m_isGuidedDrawingEnabled;
player.m_isVisibleinOSM = rows[i] >= 0;
#ifdef NUOVO_ONION
player.m_onionSkinDistance = rows[i] - row;
#else
@ -655,6 +676,7 @@ void StageBuilder::addSimpleLevelFrame(PlayerSet &players,
player.m_onionSkinDistance = 0;
player.m_isCurrentColumn = true;
player.m_isCurrentXsheetLevel = true;
player.m_isEditingLevel = true;
player.m_ancestorColumnIndex = -1;
player.m_dpiAff = getDpiAffine(level, fid);
}
@ -723,8 +745,12 @@ void Stage::visit(Visitor &visitor, const VisitArgs &args) {
sb.m_currentColumnIndex = col;
sb.m_xsheetLevel = xsheetLevel;
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;
sb.addFrame(sb.m_players, scene, xsh, row, 0, args.m_onlyVisible,
args.m_checkPreviewVisibility);
@ -753,12 +779,17 @@ void Stage::visit(Visitor &visitor, ToonzScene *scene, TXsheet *xsh, int row) {
and \b StageBuilder::visit().
*/
void Stage::visit(Visitor &visitor, TXshSimpleLevel *level, const TFrameId &fid,
const OnionSkinMask &osm, bool isPlaying) {
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.addSimpleLevelFrame(sb.m_players, level, fid);
updateOnionSkinSize(sb.m_players);
sb.visit(sb.m_players, visitor, isPlaying);
@ -767,7 +798,9 @@ void Stage::visit(Visitor &visitor, TXshSimpleLevel *level, const TFrameId &fid,
//-----------------------------------------------------------------------------
void Stage::visit(Visitor &visitor, TXshLevel *level, const TFrameId &fid,
const OnionSkinMask &osm, bool isPlaying) {
const OnionSkinMask &osm, bool isPlaying,
double isGuidedDrawingEnabled) {
if (level && level->getSimpleLevel())
visit(visitor, level->getSimpleLevel(), fid, osm, isPlaying);
visit(visitor, level->getSimpleLevel(), fid, osm, isPlaying,
(int)isGuidedDrawingEnabled);
}

View file

@ -21,6 +21,8 @@ using namespace Stage;
double Player::m_onionSkinFrontSize = 0;
double Player::m_onionSkinBackSize = 0;
double Player::m_firstBackOnionSkin = 0;
double Player::m_lastBackVisibleSkin = 0;
//-----------------------------------------------------------------------------
@ -32,6 +34,8 @@ Stage::Player::Player()
, m_ancestorColumnIndex(-1)
, m_isCurrentColumn(false)
, m_isCurrentXsheetLevel(false)
, m_isEditingLevel(false)
, m_isVisibleinOSM(false)
, m_sl()
, m_xsh()
, m_column(-1)

View file

@ -48,6 +48,7 @@
#include "toonz/autoclose.h"
#include "toonz/txshleveltypes.h"
#include "imagebuilders.h"
#include "toonz/tframehandle.h"
// Qt includes
#include <QImage>
@ -789,7 +790,7 @@ void RasterPainter::onVectorImage(TVectorImage *vi,
const Preferences &prefs = *Preferences::instance();
TColorFunction *cf = 0;
TColorFunction *cf = 0, *guidedCf = 0;
TPalette *vPalette = vi->getPalette();
TPixel32 bgColor = TPixel32::White;
@ -840,6 +841,48 @@ void RasterPainter::onVectorImage(TVectorImage *vi,
rd.m_colorCheckIndex = ToonzCheck::instance()->getColorIndex();
rd.m_show0ThickStrokes = prefs.getShow0ThickLines();
rd.m_regionAntialias = prefs.getRegionAntialias();
rd.m_animatedGuidedDrawing = prefs.getAnimatedGuidedDrawing();
if (player.m_onionSkinDistance < 0 &&
(player.m_isCurrentColumn || player.m_isCurrentXsheetLevel)) {
if (player.m_isGuidedDrawingEnabled == 3 // show guides on all
|| (player.m_isGuidedDrawingEnabled == 1 && // show guides on closest
player.m_onionSkinDistance == player.m_firstBackOnionSkin) ||
(player.m_isGuidedDrawingEnabled == 2 && // show guides on farthest
player.m_onionSkinDistance == player.m_onionSkinBackSize) ||
(player.m_isEditingLevel && // fix for level editing mode sending extra
// players
player.m_isGuidedDrawingEnabled == 2 &&
player.m_onionSkinDistance == player.m_lastBackVisibleSkin)) {
rd.m_showGuidedDrawing = player.m_isGuidedDrawingEnabled > 0;
int currentStrokeCount = 0;
int totalStrokes = vi->getStrokeCount();
TXshSimpleLevel *sl = player.m_sl;
if (sl) {
TImageP image = sl->getFrame(player.m_currentFrameId, false);
TVectorImageP vecImage = image;
if (vecImage) currentStrokeCount = vecImage->getStrokeCount();
if (currentStrokeCount < totalStrokes)
rd.m_indexToHighlight = currentStrokeCount;
double guidedM[4] = {1.0, 1.0, 1.0, 1.0}, guidedC[4];
TPixel32 bgColor = TPixel32::Blue;
guidedM[3] =
1.0 -
((player.m_onionSkinDistance == 0)
? 0.1
: OnionSkinMask::getOnionSkinFade(player.m_onionSkinDistance));
guidedC[0] = (1.0 - guidedM[3]) * bgColor.r,
guidedC[1] = (1.0 - guidedM[3]) * bgColor.g,
guidedC[2] = (1.0 - guidedM[3]) * bgColor.b;
guidedC[3] = 0.0;
guidedCf = new TGenericColorFunction(guidedM, guidedC);
rd.m_guidedCf = guidedCf;
}
}
}
if (tc & (ToonzCheck::eTransparency | ToonzCheck::eGap)) {
TPixel dummy;
@ -874,6 +917,7 @@ void RasterPainter::onVectorImage(TVectorImage *vi,
vPalette->setFrame(oldFrame);
delete cf;
delete guidedCf;
}
//-----------------------------------------------------