parent
feed0d22f3
commit
1e17edb69a
15 changed files with 411 additions and 68 deletions
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -83,12 +83,15 @@ 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
|
||||
|
||||
TXsheet *m_xsh; //!< (not owned) The player's xsheet
|
||||
int m_column; //!< The player's xsheet column
|
||||
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
|
||||
//! onion skin?)
|
||||
|
||||
|
@ -101,6 +104,8 @@ public:
|
|||
|
||||
static double m_onionSkinFrontSize;
|
||||
static double m_onionSkinBackSize;
|
||||
static double m_firstBackOnionSkin;
|
||||
static double m_lastBackVisibleSkin;
|
||||
|
||||
TPixel32 m_filterColor;
|
||||
|
||||
|
|
|
@ -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) {}
|
||||
};
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
@ -61,8 +62,9 @@ public:
|
|||
TPixel m_tCheckInk; //!< Color to be used for <I>ink check</I> mode.
|
||||
TPixel m_tCheckPaint; //!< Color to be used for <I>paint check</I> mode.
|
||||
|
||||
int m_colorCheckIndex; //!< Color index to be highlighted in <I>color
|
||||
//! check</I> mode.
|
||||
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.
|
||||
};
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -31,6 +31,10 @@ public slots:
|
|||
|
||||
void enterVectorImageGroup();
|
||||
void exitVectorImageGroup();
|
||||
void setGuidedDrawingOff();
|
||||
void setGuidedDrawingClosest();
|
||||
void setGuidedDrawingFarthest();
|
||||
void setGuidedDrawingAll();
|
||||
|
||||
void onShowHide();
|
||||
void onSetCurrent();
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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_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;
|
||||
|
@ -356,11 +371,13 @@ void StageBuilder::addCell(PlayerSet &players, ToonzScene *scene, TXsheet *xsh,
|
|||
// Build and store a player
|
||||
|
||||
Player player;
|
||||
player.m_sl = sl;
|
||||
player.m_fid = cell.m_frameId;
|
||||
player.m_xsh = xsh;
|
||||
player.m_column = col;
|
||||
player.m_frame = row;
|
||||
player.m_sl = sl;
|
||||
player.m_fid = cell.m_frameId;
|
||||
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);
|
||||
|
@ -632,12 +649,16 @@ void StageBuilder::addSimpleLevelFrame(PlayerSet &players,
|
|||
const TFrameId &fid2 = level->index2fid(rows[i]);
|
||||
if (fid2 == fid) continue;
|
||||
players.push_back(Player());
|
||||
Player &player = players.back();
|
||||
player.m_sl = level;
|
||||
player.m_frame = level->guessIndex(fid);
|
||||
player.m_fid = fid2;
|
||||
player.m_isCurrentColumn = true;
|
||||
player.m_isCurrentXsheetLevel = true;
|
||||
Player &player = players.back();
|
||||
player.m_sl = level;
|
||||
player.m_frame = level->guessIndex(fid);
|
||||
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);
|
||||
}
|
||||
|
@ -713,18 +735,22 @@ void Stage::visit(Visitor &visitor, const VisitArgs &args) {
|
|||
bool isPlaying = args.m_isPlaying;
|
||||
|
||||
StageBuilder sb;
|
||||
sb.m_vs = &visitor.m_vs;
|
||||
TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId();
|
||||
TStageObject *camera = xsh->getStageObject(cameraId);
|
||||
TAffine cameraAff = camera->getPlacement(row);
|
||||
double z = camera->getZ(row);
|
||||
sb.m_cameraPlacement = ZPlacement(cameraAff, z);
|
||||
sb.m_camera3d = camera3d;
|
||||
sb.m_currentColumnIndex = col;
|
||||
sb.m_xsheetLevel = xsheetLevel;
|
||||
sb.m_onionSkinMask = *osm;
|
||||
Player::m_onionSkinFrontSize = 0;
|
||||
Player::m_onionSkinBackSize = 0;
|
||||
sb.m_vs = &visitor.m_vs;
|
||||
TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId();
|
||||
TStageObject *camera = xsh->getStageObject(cameraId);
|
||||
TAffine cameraAff = camera->getPlacement(row);
|
||||
double z = camera->getZ(row);
|
||||
sb.m_cameraPlacement = ZPlacement(cameraAff, z);
|
||||
sb.m_camera3d = camera3d;
|
||||
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;
|
||||
Player::m_onionSkinFrontSize = 0;
|
||||
Player::m_onionSkinBackSize = 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;
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -19,8 +19,10 @@ using namespace Stage;
|
|||
// Stage::Player implementation
|
||||
//*****************************************************************************************
|
||||
|
||||
double Player::m_onionSkinFrontSize = 0;
|
||||
double Player::m_onionSkinBackSize = 0;
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -833,13 +834,55 @@ void RasterPainter::onVectorImage(TVectorImage *vi,
|
|||
true // alpha enabled
|
||||
);
|
||||
|
||||
rd.m_drawRegions = !inksOnly;
|
||||
rd.m_inkCheckEnabled = tc & ToonzCheck::eInk;
|
||||
rd.m_paintCheckEnabled = tc & ToonzCheck::ePaint;
|
||||
rd.m_blackBgEnabled = tc & ToonzCheck::eBlackBg;
|
||||
rd.m_colorCheckIndex = ToonzCheck::instance()->getColorIndex();
|
||||
rd.m_show0ThickStrokes = prefs.getShow0ThickLines();
|
||||
rd.m_regionAntialias = prefs.getRegionAntialias();
|
||||
rd.m_drawRegions = !inksOnly;
|
||||
rd.m_inkCheckEnabled = tc & ToonzCheck::eInk;
|
||||
rd.m_paintCheckEnabled = tc & ToonzCheck::ePaint;
|
||||
rd.m_blackBgEnabled = tc & ToonzCheck::eBlackBg;
|
||||
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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue