Merge pull request #911 from manongjohn/ot_patches_20220220

OpenToonz patches thru 2/20/22
This commit is contained in:
manongjohn 2022-02-27 08:46:26 -05:00 committed by GitHub
commit 59a90d83a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 865 additions and 300 deletions

View file

@ -1706,6 +1706,15 @@ ProjectPopup QLabel {
padding-left: 5px; padding-left: 5px;
padding-right: 5px; padding-right: 5px;
} }
/* -----------------------------------------------------------------------------
Frame format settings box in FormatSettingsPopup
----------------------------------------------------------------------------- */
#FrameFormatBoxInput {
border-color: rgba(124, 10, 10, 0.82);
}
#FrameFormatBoxOutput {
border-color: rgba(10, 10, 124, 0.82);
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Schematic Viewer Schematic Viewer
----------------------------------------------------------------------------- */ ----------------------------------------------------------------------------- */

View file

@ -1706,6 +1706,15 @@ ProjectPopup QLabel {
padding-left: 5px; padding-left: 5px;
padding-right: 5px; padding-right: 5px;
} }
/* -----------------------------------------------------------------------------
Frame format settings box in FormatSettingsPopup
----------------------------------------------------------------------------- */
#FrameFormatBoxInput {
border-color: rgba(118, 4, 4, 0.82);
}
#FrameFormatBoxOutput {
border-color: rgba(4, 4, 118, 0.82);
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Schematic Viewer Schematic Viewer
----------------------------------------------------------------------------- */ ----------------------------------------------------------------------------- */

View file

@ -1706,6 +1706,15 @@ ProjectPopup QLabel {
padding-left: 5px; padding-left: 5px;
padding-right: 5px; padding-right: 5px;
} }
/* -----------------------------------------------------------------------------
Frame format settings box in FormatSettingsPopup
----------------------------------------------------------------------------- */
#FrameFormatBoxInput {
border-color: rgba(207, 93, 93, 0.82);
}
#FrameFormatBoxOutput {
border-color: rgba(93, 93, 207, 0.82);
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Schematic Viewer Schematic Viewer
----------------------------------------------------------------------------- */ ----------------------------------------------------------------------------- */

View file

@ -1706,6 +1706,15 @@ ProjectPopup QLabel {
padding-left: 5px; padding-left: 5px;
padding-right: 5px; padding-right: 5px;
} }
/* -----------------------------------------------------------------------------
Frame format settings box in FormatSettingsPopup
----------------------------------------------------------------------------- */
#FrameFormatBoxInput {
border-color: rgba(138, 24, 24, 0.82);
}
#FrameFormatBoxOutput {
border-color: rgba(24, 24, 138, 0.82);
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Schematic Viewer Schematic Viewer
----------------------------------------------------------------------------- */ ----------------------------------------------------------------------------- */

View file

@ -118,3 +118,13 @@ ProjectPopup {
padding-left: 5px; padding-left: 5px;
padding-right: 5px; padding-right: 5px;
} }
/* -----------------------------------------------------------------------------
Frame format settings box in FormatSettingsPopup
----------------------------------------------------------------------------- */
#FrameFormatBoxInput {
border-color: mix(@accent, rgba(255, 0, 0, 0.7), 40);
}
#FrameFormatBoxOutput {
border-color: mix(@accent, rgba(0, 0, 255, 0.7), 40);
}

View file

@ -1706,6 +1706,15 @@ ProjectPopup QLabel {
padding-left: 5px; padding-left: 5px;
padding-right: 5px; padding-right: 5px;
} }
/* -----------------------------------------------------------------------------
Frame format settings box in FormatSettingsPopup
----------------------------------------------------------------------------- */
#FrameFormatBoxInput {
border-color: rgba(164, 50, 50, 0.82);
}
#FrameFormatBoxOutput {
border-color: rgba(50, 50, 164, 0.82);
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Schematic Viewer Schematic Viewer
----------------------------------------------------------------------------- */ ----------------------------------------------------------------------------- */

View file

@ -186,7 +186,8 @@ TLevelWriter::TLevelWriter(const TFilePath &path, TPropertyGroup *prop)
: TSmartObject(m_classCode) : TSmartObject(m_classCode)
, m_path(path) , m_path(path)
, m_properties(prop) , m_properties(prop)
, m_contentHistory(0) { , m_contentHistory(0)
, m_frameFormatTemplateFId(TFrameId::NO_FRAME) {
string ext = path.getType(); string ext = path.getType();
if (!prop) m_properties = Tiio::makeWriterProperties(ext); if (!prop) m_properties = Tiio::makeWriterProperties(ext);
} }
@ -250,6 +251,12 @@ void TLevelWriter::getSupportedFormats(QStringList &names,
//----------------------------------------------------------- //-----------------------------------------------------------
TImageWriterP TLevelWriter::getFrameWriter(TFrameId fid) { TImageWriterP TLevelWriter::getFrameWriter(TFrameId fid) {
// change the frame format with the template
if (!m_frameFormatTemplateFId.isNoFrame()) {
fid.setZeroPadding(m_frameFormatTemplateFId.getZeroPadding());
fid.setStartSeqInd(m_frameFormatTemplateFId.getStartSeqInd());
}
TImageWriterP iw(m_path.withFrame(fid)); TImageWriterP iw(m_path.withFrame(fid));
iw->setProperties(m_properties); iw->setProperties(m_properties);
return iw; return iw;

View file

@ -573,6 +573,36 @@ std::string TFilePath::getDots() const {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
QChar TFilePath::getSepChar() const {
if (!TFilePath::m_useStandard) return analyzePath().sepChar;
//-----
QString type = QString::fromStdString(getType()).toLower();
if (isFfmpegType()) return QChar();
int i = getLastSlash(m_path);
std::wstring str = m_path.substr(i + 1);
// potrei anche avere a.b.c.d dove d e' l'estensione
i = str.rfind(L".");
if (i == (int)std::wstring::npos || str == L"..") return QChar();
int j = str.substr(0, i).rfind(L".");
if (j != (int)std::wstring::npos)
return (j == i - 1 || (checkForSeqNum(type) && isNumbers(str, j, i)))
? QChar('.')
: QChar();
if (!m_underscoreFormatAllowed) return QChar();
j = str.substr(0, i).rfind(L"_");
if (j != (int)std::wstring::npos)
return (j == i - 1 || (checkForSeqNum(type) && isNumbers(str, j, i)))
? QChar('_')
: QChar();
else
return QChar();
}
//-----------------------------------------------------------------------------
std::string TFilePath::getDottedType() std::string TFilePath::getDottedType()
const // ritorna l'estensione con PUNTO (se c'e') const // ritorna l'estensione con PUNTO (se c'e')
{ {
@ -881,7 +911,8 @@ TFilePath TFilePath::withFrame(const TFrameId &frame,
if (frame.isNoFrame()) { if (frame.isNoFrame()) {
return TFilePath(info.parentDir + info.levelName + "." + info.extension); return TFilePath(info.parentDir + info.levelName + "." + info.extension);
} }
QString sepChar = (info.sepChar.isNull()) ? "." : QString(info.sepChar); QString sepChar = (info.sepChar.isNull()) ? QString(frame.getStartSeqInd())
: QString(info.sepChar);
return TFilePath(info.parentDir + info.levelName + sepChar + return TFilePath(info.parentDir + info.levelName + sepChar +
QString::fromStdString(frame.expand(format)) + "." + QString::fromStdString(frame.expand(format)) + "." +

View file

@ -176,15 +176,20 @@ TPoint TFont::drawChar(QImage &outImage, TPoint &unused, wchar_t charcode,
// alphaMapForGlyph with a space character returns an invalid // alphaMapForGlyph with a space character returns an invalid
// QImage for some reason. // QImage for some reason.
// Bug 3604: https://github.com/opentoonz/opentoonz/issues/3604 // Bug 3604: https://github.com/opentoonz/opentoonz/issues/3604
#ifdef Q_OS_UNIX // (21/1/2022) Use this workaround for all platforms as the crash also occured
if (chars[0] == L' ') { // in windows when the display is scaled up.
outImage = QImage(raw.averageCharWidth(), raw.ascent() + raw.descent(), if (chars[0].isSpace()) {
QImage::Format_Grayscale8); #if QT_VERSION >= 0x051100
outImage.fill(255); int w = QFontMetrics(m_pimpl->m_font).horizontalAdvance(chars[0]);
return getDistance(charcode, nextCharCode); #else
} int w = raw.averageCharWidth();
#endif #endif
outImage =
QImage(w, raw.ascent() + raw.descent(), QImage::Format_Grayscale8);
outImage.fill(255);
return getDistance(charcode, nextCharCode);
}
QImage image = raw.alphaMapForGlyph(indices[0], QRawFont::PixelAntialiasing); QImage image = raw.alphaMapForGlyph(indices[0], QRawFont::PixelAntialiasing);
if (image.format() != QImage::Format_Indexed8 && if (image.format() != QImage::Format_Indexed8 &&
image.format() != QImage::Format_Alpha8) image.format() != QImage::Format_Alpha8)

View file

@ -316,6 +316,8 @@ type is a string that indicate the filename extension(ex:. bmp or .bmp)*/
void split(std::wstring &head, TFilePath &tail) const; void split(std::wstring &head, TFilePath &tail) const;
TFilePathInfo analyzePath() const; TFilePathInfo analyzePath() const;
QChar getSepChar() const;
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View file

@ -82,12 +82,11 @@ public:
static FormatType getFormatType(std::string extension); static FormatType getFormatType(std::string extension);
static void define( static void define(QString extension, int reader,
QString extension, int reader, // nel caso in cui ci siano piu' lettori per lo stesso
// nel caso in cui ci siano piu' lettori per lo stesso formato // formato (es. flash)
// (es. flash)
TLevelReaderCreateProc *proc); TLevelReaderCreateProc *proc);
static inline void define(QString extension, TLevelReaderCreateProc *proc) { static inline void define(QString extension, TLevelReaderCreateProc *proc) {
define(extension, 0, proc); define(extension, 0, proc);
@ -136,6 +135,9 @@ protected:
TContentHistory *m_contentHistory; TContentHistory *m_contentHistory;
QString m_creator; QString m_creator;
// if template is not used, frame number is set to TFrameId::NO_FRAME
TFrameId m_frameFormatTemplateFId;
public: public:
TLevelWriter(const TFilePath &path, TLevelWriter(const TFilePath &path,
TPropertyGroup *winfo = 0); // ottiene l'ownership TPropertyGroup *winfo = 0); // ottiene l'ownership
@ -203,6 +205,10 @@ public:
static void define(QString extension, TLevelWriterCreateProc *proc, static void define(QString extension, TLevelWriterCreateProc *proc,
bool isRenderFormat); bool isRenderFormat);
void setFrameFormatTemplateFId(const TFrameId &tmplFId) {
m_frameFormatTemplateFId = tmplFId;
}
}; };
//----------------------------------------------------------- //-----------------------------------------------------------

View file

@ -124,7 +124,8 @@ class DVAPI LevelUpdater {
public: public:
LevelUpdater(); LevelUpdater();
LevelUpdater(TXshSimpleLevel *sl); LevelUpdater(TXshSimpleLevel *sl);
LevelUpdater(const TFilePath &path, TPropertyGroup *lwProperties = 0); LevelUpdater(const TFilePath &path, TPropertyGroup *lwProperties = 0,
const TFrameId &tmplFId = TFrameId(TFrameId::NO_FRAME));
~LevelUpdater(); ~LevelUpdater();
TLevelWriterP getLevelWriter() { return m_lw; } TLevelWriterP getLevelWriter() { return m_lw; }
@ -142,7 +143,8 @@ public:
//! This function may throw in case the specified path has an unrecognized //! This function may throw in case the specified path has an unrecognized
//! extension, or the file could //! extension, or the file could
//! not be opened for write. //! not be opened for write.
void open(const TFilePath &src, TPropertyGroup *lwProperties); void open(const TFilePath &src, TPropertyGroup *lwProperties,
const TFrameId &tmplFId);
//! Attaches the updater to the specified simple level instance. Format //! Attaches the updater to the specified simple level instance. Format
//! properties are the default in case the level //! properties are the default in case the level

View file

@ -9,6 +9,7 @@
#include "tcommon.h" #include "tcommon.h"
#include "tgeometry.h" #include "tgeometry.h"
#include "tpixel.h" #include "tpixel.h"
#include "tfilepath.h"
// TnzLib includes // TnzLib includes
#include "toonz/levelproperties.h" #include "toonz/levelproperties.h"
@ -36,7 +37,6 @@
// Forward declarations // Forward declarations
class TFilePath;
class QSettings; class QSettings;
//============================================================== //==============================================================
@ -295,7 +295,8 @@ public:
int getRhubarbTimeout() { return getIntValue(rhubarbTimeout); } int getRhubarbTimeout() { return getIntValue(rhubarbTimeout); }
// Drawing tab // Drawing tab
QString getScanLevelType() const { return getStringValue(scanLevelType); } QString getDefRasterFormat() const { return getStringValue(DefRasterFormat); }
// QString getScanLevelType() const { return getStringValue(scanLevelType); }
int getDefLevelType() const { return getIntValue(DefLevelType); } int getDefLevelType() const { return getIntValue(DefLevelType); }
bool isNewLevelSizeToCameraSizeEnabled() const { bool isNewLevelSizeToCameraSizeEnabled() const {
return getBoolValue(newLevelSizeToCameraSizeEnabled); return getBoolValue(newLevelSizeToCameraSizeEnabled);

View file

@ -82,7 +82,8 @@ enum PreferencesItemId {
//---------- //----------
// Drawing // Drawing
scanLevelType, DefRasterFormat,
// scanLevelType,// deprecated
DefLevelType, DefLevelType,
newLevelSizeToCameraSizeEnabled, newLevelSizeToCameraSizeEnabled,
DefLevelWidth, DefLevelWidth,

View file

@ -288,6 +288,10 @@ and height.
bool hasDefaultCellMarks() bool hasDefaultCellMarks()
const; // check if the cell mark settings are modified const; // check if the cell mark settings are modified
// templateFId in preview settings is used for "input" file format
// such as new raster level, captured images by camera capture feature, etc.
TFrameId &formatTemplateFIdForInput();
private: private:
// not implemented // not implemented
TSceneProperties(const TSceneProperties &); TSceneProperties(const TSceneProperties &);

View file

@ -185,6 +185,7 @@ table) it returns the proper insertion index
//! from each entry to the next. //! from each entry to the next.
int guessStep() const; int guessStep() const;
void formatFId(TFrameId &fid, TFrameId tmplFId);
void setFrame(const TFrameId &fid, const TImageP &img); void setFrame(const TFrameId &fid, const TImageP &img);
TImageP getFrame(const TFrameId &fid, UCHAR imgManagerParamsMask, TImageP getFrame(const TFrameId &fid, UCHAR imgManagerParamsMask,

View file

@ -98,10 +98,11 @@ void DVAPI convert(
const TPixel &bgColor = const TPixel &bgColor =
TPixel::Transparent, //!< Destination Background color. TPixel::Transparent, //!< Destination Background color.
bool removeDotBeforeFrameNumber = bool removeDotBeforeFrameNumber =
false /*-- ConvertPopup false, /*-- ConvertPopup
[].[].[] [].[].[]
[][] --*/ [][] --*/
); //!< Converts a saved level to fullcolor, and saves the result. const TFrameId &tmplFId = TFrameId() //!< frame format template
); //!< Converts a saved level to fullcolor, and saves the result.
void DVAPI convertNaa2Tlv( void DVAPI convertNaa2Tlv(
const TFilePath &source, //!< Level path to convert from. const TFilePath &source, //!< Level path to convert from.

View file

@ -94,6 +94,10 @@ private:
BoardSettings *m_boardSettings; BoardSettings *m_boardSettings;
// templateFId in preview settings is used for "input" file format
// such as new raster level, captured images by camera capture feature, etc.
TFrameId m_formatTemplateFId;
public: public:
/*! /*!
Constructs TOutputProperties with default value. Constructs TOutputProperties with default value.
@ -221,6 +225,8 @@ machine's CPU).
void setSubcameraPreview(bool enabled) { m_subcameraPreview = enabled; } void setSubcameraPreview(bool enabled) { m_subcameraPreview = enabled; }
BoardSettings *getBoardSettings() const { return m_boardSettings; } BoardSettings *getBoardSettings() const { return m_boardSettings; }
TFrameId &formatTemplateFId() { return m_formatTemplateFId; }
}; };
//-------------------------------------------- //--------------------------------------------

View file

@ -33,7 +33,7 @@ inline const T &clamp(const T &v, const T &lo, const T &hi) {
const double turbulentGamma = 2.2; const double turbulentGamma = 2.2;
// magic number to offset evolution between generations // magic number to offset evolution between generations
const double evolutionOffsetStep = 19.82; const double evolutionOffsetStep = 19.82;
const double evolutionOffsetStepW = 31.1; const double evolutionOffsetStepW = 31.1;
} // namespace } // namespace
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -61,11 +61,11 @@ Iwa_FractalNoiseFx::Iwa_FractalNoiseFx()
///, m_randomSeed(0) ///, m_randomSeed(0)
, m_dynamicIntensity(1.0) , m_dynamicIntensity(1.0)
, m_alphaRendering(false) , m_alphaRendering(false)
, m_doConical(false) , m_doConical(false)
, m_conicalEvolution(0.0) , m_conicalEvolution(0.0)
, m_conicalAngle(60.0) , m_conicalAngle(60.0)
, m_cameraFov(60.0) , m_cameraFov(60.0)
, m_zScale(2.0) { , m_zScale(2.0) {
m_fractalType->addItem(TurbulentSmooth, "Turbulent Smooth"); m_fractalType->addItem(TurbulentSmooth, "Turbulent Smooth");
m_fractalType->addItem(TurbulentBasic, "Turbulent Basic"); m_fractalType->addItem(TurbulentBasic, "Turbulent Basic");
m_fractalType->addItem(TurbulentSharp, "Turbulent Sharp"); m_fractalType->addItem(TurbulentSharp, "Turbulent Sharp");
@ -167,7 +167,7 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame,
double *work_buf = (double *)work_buf_ras->getRawData(); double *work_buf = (double *)work_buf_ras->getRawData();
// affine transformations // affine transformations
TAffine globalAff = TTranslation(-tile.m_pos) * ri.m_affine; TAffine globalAff = TTranslation(-tile.m_pos) * ri.m_affine;
TAffine parentAff = TAffine parentAff =
TScale(param.scale.lx, param.scale.ly) * TRotation(-param.rotation); TScale(param.scale.lx, param.scale.ly) * TRotation(-param.rotation);
TAffine subAff = TTranslation(param.subOffset) * TScale(param.subScaling) * TAffine subAff = TTranslation(param.subOffset) * TScale(param.subScaling) *
@ -195,34 +195,34 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame,
for (int gen = 0; gen < genCount; gen++) { for (int gen = 0; gen < genCount; gen++) {
// affine transformation for the current generation // affine transformation for the current generation
TAffine currentAff = TAffine currentAff =
(globalAff * parentOffsetAff * parentAff * genAff).inv(); (globalAff * parentOffsetAff * parentAff * genAff).inv();
// scale of the current pattern ( used for the Dynamic / Dynamic Twist // scale of the current pattern ( used for the Dynamic / Dynamic Twist
// offset ) // offset )
double scale = sqrt(std::abs(currentAff.det())); double scale = sqrt(std::abs(currentAff.det()));
// for each pixel // for each pixel
double* buf_p = work_buf; double *buf_p = work_buf;
for (int y = 0; y < outDim.ly; y++) { for (int y = 0; y < outDim.ly; y++) {
for (int x = 0; x < outDim.lx; x++, buf_p++) { for (int x = 0; x < outDim.lx; x++, buf_p++) {
// obtain sampling position // obtain sampling position
// For Dynamic and Dynamic Twist patterns, the position offsets using // For Dynamic and Dynamic Twist patterns, the position offsets using
// gradient / rotation of the parent pattern // gradient / rotation of the parent pattern
TPointD samplePos = TPointD samplePos =
getSamplePos(x, y, outDim, out_buf, gen, scale, param); getSamplePos(x, y, outDim, out_buf, gen, scale, param);
// multiply affine transformation // multiply affine transformation
samplePos = currentAff * samplePos; samplePos = currentAff * samplePos;
// adjust position for the block pattern // adjust position for the block pattern
if (param.noiseType == Block) if (param.noiseType == Block)
samplePos = TPointD(std::floor(samplePos.x) + 0.5, samplePos = TPointD(std::floor(samplePos.x) + 0.5,
std::floor(samplePos.y) + 0.5); std::floor(samplePos.y) + 0.5);
// calculate the base noise // calculate the base noise
if (param.cycleEvolution) if (param.cycleEvolution)
*buf_p = (pn.noise(samplePos.x, samplePos.y, evolution_zw.x, *buf_p = (pn.noise(samplePos.x, samplePos.y, evolution_zw.x,
evolution_zw.y) + evolution_zw.y) +
1.0) * 1.0) *
0.5; 0.5;
else else
*buf_p = *buf_p =
(pn.noise(samplePos.x, samplePos.y, evolution_z) + 1.0) * 0.5; (pn.noise(samplePos.x, samplePos.y, evolution_z) + 1.0) * 0.5;
// convert the noise // convert the noise
convert(buf_p, param); convert(buf_p, param);
@ -232,17 +232,16 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame,
// just copy the values for the first generation // just copy the values for the first generation
if (gen == 0) { if (gen == 0) {
memcpy(out_buf, work_buf, outDim.lx * outDim.ly * sizeof(double)); memcpy(out_buf, work_buf, outDim.lx * outDim.ly * sizeof(double));
} } else {
else {
// intensity of the last generation will take the fraction part of // intensity of the last generation will take the fraction part of
// complexity // complexity
double genIntensity = std::min(1.0, param.complexity - (double)gen); double genIntensity = std::min(1.0, param.complexity - (double)gen);
// influence of the current generation // influence of the current generation
double influence = double influence =
genIntensity * std::pow(param.subInfluence, (double)gen); genIntensity * std::pow(param.subInfluence, (double)gen);
// composite the base noise pattern // composite the base noise pattern
buf_p = work_buf; buf_p = work_buf;
double* out_p = out_buf; double *out_p = out_buf;
for (int i = 0; i < outDim.lx * outDim.ly; i++, buf_p++, out_p++) for (int i = 0; i < outDim.lx * outDim.ly; i++, buf_p++, out_p++)
composite(out_p, buf_p, influence, param); composite(out_p, buf_p, influence, param);
} }
@ -253,9 +252,9 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame,
// according to the sub scale // according to the sub scale
if (param.perspectiveOffset) if (param.perspectiveOffset)
parentOffsetAff = TScale(param.subScaling) * parentOffsetAff = TScale(param.subScaling) *
TRotation(-param.subRotation) * parentOffsetAff * TRotation(-param.subRotation) * parentOffsetAff *
TRotation(param.subRotation) * TRotation(param.subRotation) *
TScale(1 / param.subScaling); TScale(1 / param.subScaling);
if (param.cycleEvolution) if (param.cycleEvolution)
evolution_zw.x += evolutionOffsetStep; evolution_zw.x += evolutionOffsetStep;
@ -269,8 +268,8 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame,
// angle of slope of the cone // angle of slope of the cone
double theta_n = param.conicalAngle * M_PI_180; double theta_n = param.conicalAngle * M_PI_180;
// half of the vertical fov // half of the vertical fov
double phi_2 = param.cameraFov * 0.5 * M_PI_180; double phi_2 = param.cameraFov * 0.5 * M_PI_180;
double z_scale = std::pow(10.0, param.zScale); double z_scale = std::pow(10.0, param.zScale);
double evolution_w = param.conicalEvolution; double evolution_w = param.conicalEvolution;
// pixel distance between camera and the screen // pixel distance between camera and the screen
@ -284,83 +283,99 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame,
// accumulate base noise pattern for each generation // accumulate base noise pattern for each generation
for (int gen = 0; gen < genCount; gen++) { for (int gen = 0; gen < genCount; gen++) {
// affine transformation for the current generation // affine transformation for the current generation
TAffine currentAff = TAffine currentAff = (globalAff * parentAff * genAff).inv();
(globalAff * parentAff * genAff).inv();
// scale of the current pattern ( used for the Dynamic / Dynamic Twist // scale of the current pattern ( used for the Dynamic / Dynamic Twist
// offset ) // offset )
double scale = sqrt(std::abs(currentAff.det())); double scale = sqrt(std::abs(currentAff.det()));
// for each pixel // for each pixel
double* buf_p = work_buf; double *buf_p = work_buf;
for (int y = 0; y < outDim.ly; y++) { for (int y = 0; y < outDim.ly; y++) {
for (int x = 0; x < outDim.lx; x++, buf_p++) { for (int x = 0; x < outDim.lx; x++, buf_p++) {
double dx, dy, dz; double dx, dy, dz;
if (theta_n == 0.0) { if (theta_n == 0.0) {
dx = x; dx = x;
dy = y; dy = y;
dz = 0.0; dz = 0.0;
} } else {
else {
// conical, without offset // conical, without offset
if (center == TPointD()) { if (center == TPointD()) {
TPointD p = TTranslation(tile.m_pos) * TPointD(x, y); TPointD p = TTranslation(tile.m_pos) * TPointD(x, y);
// pixel distance from the screen center // pixel distance from the screen center
double d = tdistance(p, TPointD()); double d = tdistance(p, TPointD());
// line of sight : d = S * z + T // line of sight : d = S * z + T
double S = d / D; double S = d / D;
double T = d; double T = d;
dz = (V - T) / (S - U); dz = (V - T) / (S - U);
double dp = S * dz + T; double dp = S * dz + T;
if (d != 0.0) { if (d != 0.0) {
p.x *= dp / d; p.x *= dp / d;
p.y *= dp / d; p.y *= dp / d;
} }
p += center * (dp / V); p += center * (dp / V);
p = TTranslation(tile.m_pos).inv() * p; p = TTranslation(tile.m_pos).inv() * p;
dx = p.x; dx = p.x;
dy = p.y; dy = p.y;
dz /= z_scale; dz /= z_scale;
} }
// conical, with offset // conical, with offset
else { else {
// compute the intersecting point between the "noise cone" and the line of sight // compute the intersecting point between the "noise cone" and the
// line of sight
TPointD _p = TTranslation(tile.m_pos) * TPointD(x, y); TPointD _p = TTranslation(tile.m_pos) * TPointD(x, y);
QVector3D p(_p.x, _p.y, 0.0); // offset by combination of offsets of A) projection position and
QVector3D eye_O(center.x, center.y, -D); // B) eye positon.
QVector3D eye_d = (p - eye_O).normalized(); //
// A) 0.5 * projection position offset
QVector3D p(_p.x - center.x * 0.5, _p.y - center.y * 0.5, 0.0);
QVector3D cone_C(0.0, 0.0, V * std::tan(theta_n)); QVector3D cone_C(0.0, 0.0, V * std::tan(theta_n));
QVector3D cone_a(0, 0, -1); QVector3D cone_a(0, 0, -1);
// B) 0.5 * eye position offset
double offsetAdj = 0.5 * (D + cone_C.z()) / cone_C.z();
QVector3D eye_O(center.x * offsetAdj, center.y * offsetAdj, -D);
QVector3D eye_d = (p - eye_O).normalized();
double cos_ConeT = std::sin(theta_n); double cos_ConeT = std::sin(theta_n);
float d_a = QVector3D::dotProduct(eye_d, cone_a); float d_a = QVector3D::dotProduct(eye_d, cone_a);
float Ca_Oa = QVector3D::dotProduct(cone_C, cone_a) - QVector3D::dotProduct(eye_O, cone_a); float Ca_Oa = QVector3D::dotProduct(cone_C, cone_a) -
QVector3D::dotProduct(eye_O, cone_a);
// A * t^2 + B * t + C = 0 // A * t^2 + B * t + C = 0
float A = d_a * d_a - eye_d.lengthSquared() * cos_ConeT; float A =
float B = 2.0 * (QVector3D::dotProduct(eye_d, cone_C) - QVector3D::dotProduct(eye_d, eye_O)) * cos_ConeT * cos_ConeT d_a * d_a - eye_d.lengthSquared() * cos_ConeT * cos_ConeT;
- 2.0 * Ca_Oa * d_a; float B = 2.0 *
float C = Ca_Oa * Ca_Oa (QVector3D::dotProduct(eye_d, cone_C) -
- cos_ConeT * cos_ConeT * (cone_C.lengthSquared() - 2.0 * QVector3D::dotProduct(eye_O, cone_C) + eye_O.lengthSquared()); QVector3D::dotProduct(eye_d, eye_O)) *
cos_ConeT * cos_ConeT -
2.0 * Ca_Oa * d_a;
float C = Ca_Oa * Ca_Oa -
cos_ConeT * cos_ConeT *
(cone_C.lengthSquared() -
2.0 * QVector3D::dotProduct(eye_O, cone_C) +
eye_O.lengthSquared());
// obtain t // obtain t
double t1 = (-B + std::sqrt(B * B - 4.0 * A * C)) / (2.0 * A); double t1 = (-B + std::sqrt(B * B - 4.0 * A * C)) / (2.0 * A);
double t2 = (-B - std::sqrt(B * B - 4.0 * A * C)) / (2.0 * A); double t2 = (-B - std::sqrt(B * B - 4.0 * A * C)) / (2.0 * A);
if (t1 < 0) t1 = t2; if (t1 < 0)
else if (t2 < 0) t2 = t1; t1 = t2;
else if (t2 < 0)
t2 = t1;
double t = std::min(t1, t2); double t = std::min(t1, t2);
// intersecting point // intersecting point
QVector3D sampleP = eye_O + eye_d * t; QVector3D sampleP = eye_O + eye_d * t;
_p.x = sampleP.x(); _p.x = sampleP.x();
_p.y = sampleP.y(); _p.y = sampleP.y();
_p = TTranslation(tile.m_pos).inv() * _p; _p = TTranslation(tile.m_pos).inv() * _p;
dx = _p.x; dx = _p.x;
dy = _p.y; dy = _p.y;
dz = sampleP.z() / z_scale; dz = sampleP.z() / z_scale;
} }
if (param.cycleEvolution) { if (param.cycleEvolution) {
double cycle_theta = 2.0 * M_PI * (param.evolution + param.conicalEvolution + dz) / param.cycleEvolutionRange; double cycle_theta =
2.0 * M_PI * (param.evolution + param.conicalEvolution + dz) /
param.cycleEvolutionRange;
double cycle_d = param.cycleEvolutionRange / (2.0 * M_PI); double cycle_d = param.cycleEvolutionRange / (2.0 * M_PI);
evolution_zw.x = cycle_d * cos(cycle_theta); evolution_zw.x = cycle_d * cos(cycle_theta);
evolution_zw.y = cycle_d * sin(cycle_theta); evolution_zw.y = cycle_d * sin(cycle_theta);
@ -369,23 +384,28 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame,
// obtain sampling position // obtain sampling position
// For Dynamic and Dynamic Twist patterns, the position offsets using // For Dynamic and Dynamic Twist patterns, the position offsets using
// gradient / rotation of the parent pattern // gradient / rotation of the parent pattern
TPointD samplePosOffset =
getSamplePos(x, y, outDim, out_buf, gen, scale, param) -
TPointD(x, y);
TPointD samplePos = TPointD samplePos =
getSamplePos(dx, dy, outDim, out_buf, gen, scale, param); TPointD(dx, dy) + samplePosOffset * (D / (D + dz));
// multiply affine transformation // multiply affine transformation
samplePos = currentAff * samplePos; samplePos = currentAff * samplePos;
// adjust position for the block pattern // adjust position for the block pattern
if (param.noiseType == Block) if (param.noiseType == Block)
samplePos = TPointD(std::floor(samplePos.x) + 0.5, samplePos = TPointD(std::floor(samplePos.x) + 0.5,
std::floor(samplePos.y) + 0.5); std::floor(samplePos.y) + 0.5);
// calculate the base noise // calculate the base noise
if (param.cycleEvolution) if (param.cycleEvolution)
*buf_p = (pn.noise(samplePos.x, samplePos.y, evolution_zw.x, *buf_p = (pn.noise(samplePos.x, samplePos.y, evolution_zw.x,
evolution_zw.y) + evolution_zw.y) +
1.0) * 1.0) *
0.5; 0.5;
else else
*buf_p = *buf_p = (pn.noise(samplePos.x, samplePos.y, evolution_z,
(pn.noise(samplePos.x, samplePos.y, evolution_z, evolution_w + dz) + 1.0) * 0.5; evolution_w + dz) +
1.0) *
0.5;
// convert the noise // convert the noise
convert(buf_p, param); convert(buf_p, param);
@ -395,17 +415,16 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame,
// just copy the values for the first generation // just copy the values for the first generation
if (gen == 0) { if (gen == 0) {
memcpy(out_buf, work_buf, outDim.lx * outDim.ly * sizeof(double)); memcpy(out_buf, work_buf, outDim.lx * outDim.ly * sizeof(double));
} } else {
else {
// intensity of the last generation will take the fraction part of // intensity of the last generation will take the fraction part of
// complexity // complexity
double genIntensity = std::min(1.0, param.complexity - (double)gen); double genIntensity = std::min(1.0, param.complexity - (double)gen);
// influence of the current generation // influence of the current generation
double influence = double influence =
genIntensity * std::pow(param.subInfluence, (double)gen); genIntensity * std::pow(param.subInfluence, (double)gen);
// composite the base noise pattern // composite the base noise pattern
buf_p = work_buf; buf_p = work_buf;
double* out_p = out_buf; double *out_p = out_buf;
for (int i = 0; i < outDim.lx * outDim.ly; i++, buf_p++, out_p++) for (int i = 0; i < outDim.lx * outDim.ly; i++, buf_p++, out_p++)
composite(out_p, buf_p, influence, param); composite(out_p, buf_p, influence, param);
} }
@ -422,7 +441,6 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame,
} }
} }
work_buf_ras->unlock(); work_buf_ras->unlock();
// finalize pattern (converting the color space) // finalize pattern (converting the color space)
@ -483,13 +501,13 @@ void Iwa_FractalNoiseFx::obtainParams(FNParam &param, const double frame,
param.cycleEvolutionRange = m_cycleEvolutionRange->getValue(frame); param.cycleEvolutionRange = m_cycleEvolutionRange->getValue(frame);
param.dynamicIntensity = m_dynamicIntensity->getValue(frame) * 10.0; param.dynamicIntensity = m_dynamicIntensity->getValue(frame) * 10.0;
param.doConical = m_doConical->getValue(); param.doConical = m_doConical->getValue();
param.conicalEvolution = m_conicalEvolution->getValue(frame); param.conicalEvolution = m_conicalEvolution->getValue(frame);
param.conicalAngle = m_conicalAngle->getValue(frame); param.conicalAngle = m_conicalAngle->getValue(frame);
param.cameraFov = m_cameraFov->getValue(frame); param.cameraFov = m_cameraFov->getValue(frame);
param.zScale = m_zScale->getValue(frame); param.zScale = m_zScale->getValue(frame);
param.alphaRendering = m_alphaRendering->getValue(); param.alphaRendering = m_alphaRendering->getValue();
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -529,7 +547,8 @@ void Iwa_FractalNoiseFx::getParamUIs(TParamUIConcept *&concepts, int &length) {
//------------------------------------------------------------------ //------------------------------------------------------------------
// For Dynamic and Dynamic Twist patterns, the position offsets using gradient / // For Dynamic and Dynamic Twist patterns, the position offsets using gradient /
// rotation of the parent pattern // rotation of the parent pattern
TPointD Iwa_FractalNoiseFx::getSamplePos(double x, double y, const TDimension outDim, TPointD Iwa_FractalNoiseFx::getSamplePos(double x, double y,
const TDimension outDim,
const double *out_buf, const int gen, const double *out_buf, const int gen,
const double scale, const double scale,
const FNParam &param) { const FNParam &param) {
@ -541,43 +560,47 @@ TPointD Iwa_FractalNoiseFx::getSamplePos(double x, double y, const TDimension ou
auto clampPos = [&](double x, double y) { auto clampPos = [&](double x, double y) {
if (x < 0.0) if (x < 0.0)
x = 0.0; x = 0.0;
else if (x > (double)(outDim.lx-1)) else if (x > (double)(outDim.lx - 1))
x = (double)(outDim.lx - 1); x = (double)(outDim.lx - 1);
if (y < 0.0) if (y < 0.0)
y = 0.0; y = 0.0;
else if (y > (double)(outDim.ly-1)) else if (y > (double)(outDim.ly - 1))
y = (double)(outDim.ly - 1); y = (double)(outDim.ly - 1);
return TPointD(x, y); return TPointD(x, y);
}; };
auto val = [&](const TPoint& p) { auto val = [&](const TPoint &p) {
return out_buf[std::min(p.y, outDim.ly - 1) * outDim.lx + std::min(p.x, outDim.lx - 1)]; return out_buf[std::min(p.y, outDim.ly - 1) * outDim.lx +
std::min(p.x, outDim.lx - 1)];
}; };
auto lerp = [](double v0, double v1, double ratio) { auto lerp = [](double v0, double v1, double ratio) {
return (1.0 - ratio) * v0 + ratio * v1; return (1.0 - ratio) * v0 + ratio * v1;
}; };
auto lerpVal = [&](const TPointD &p) { auto lerpVal = [&](const TPointD &p) {
int id_x = (int)std::floor(p.x); int id_x = (int)std::floor(p.x);
double ratio_x = p.x - (double)id_x; double ratio_x = p.x - (double)id_x;
int id_y = (int)std::floor(p.y); int id_y = (int)std::floor(p.y);
double ratio_y = p.y - (double)id_y; double ratio_y = p.y - (double)id_y;
return lerp ( lerp(val(TPoint(id_x, id_y)), val(TPoint(id_x+1, id_y)), ratio_x), return lerp(
lerp(val(TPoint(id_x, id_y+1)), val(TPoint(id_x + 1, id_y+1)), ratio_x), ratio_y); lerp(val(TPoint(id_x, id_y)), val(TPoint(id_x + 1, id_y)), ratio_x),
lerp(val(TPoint(id_x, id_y + 1)), val(TPoint(id_x + 1, id_y + 1)),
ratio_x),
ratio_y);
}; };
int range = std::max(2, (int)(0.1 / scale)); int range = std::max(2, (int)(0.1 / scale));
TPointD left = clampPos(x - range, y); TPointD left = clampPos(x - range, y);
TPointD right = clampPos(x + range, y); TPointD right = clampPos(x + range, y);
TPointD down = clampPos(x, y - range); TPointD down = clampPos(x, y - range);
TPointD up = clampPos(x, y + range); TPointD up = clampPos(x, y + range);
double dif_x = param.dynamicIntensity * (1 / scale) * double dif_x = param.dynamicIntensity * (1 / scale) *
(lerpVal(left) - lerpVal(right)) / (left.x - right.x); (lerpVal(left) - lerpVal(right)) / (left.x - right.x);
double dif_y = param.dynamicIntensity * (1 / scale) * (lerpVal(up) - lerpVal(down)) / double dif_y = param.dynamicIntensity * (1 / scale) *
(up.y - down.y); (lerpVal(up) - lerpVal(down)) / (up.y - down.y);
if (param.fractalType == Dynamic) if (param.fractalType == Dynamic)
return TPointD(x + dif_x, y + dif_y); // gradient return TPointD(x + dif_x, y + dif_y); // gradient
else // Dynamic_twist else // Dynamic_twist
return TPointD(x + dif_y, y - dif_x); // rotation return TPointD(x + dif_y, y - dif_x); // rotation
} }

View file

@ -113,7 +113,7 @@ protected:
// ダイナミックの度合い // ダイナミックの度合い
TDoubleParamP m_dynamicIntensity; TDoubleParamP m_dynamicIntensity;
//- - - Conical Noise - - - //- - - Conical Noise - - -
TBoolParamP m_doConical; TBoolParamP m_doConical;
TDoubleParamP m_conicalEvolution; TDoubleParamP m_conicalEvolution;
TDoubleParamP m_conicalAngle; TDoubleParamP m_conicalAngle;
@ -126,7 +126,7 @@ protected:
public: public:
Iwa_FractalNoiseFx(); Iwa_FractalNoiseFx();
bool canHandle(const TRenderSettings &info, double frame) override { bool canHandle(const TRenderSettings &info, double frame) override {
return true; return !m_doConical->getValue();
} }
bool doGetBBox(double frame, TRectD &bBox, bool doGetBBox(double frame, TRectD &bBox,
const TRenderSettings &ri) override; const TRenderSettings &ri) override;

View file

@ -413,21 +413,24 @@ void SkeletonTool::leftButtonDown(const TPointD &ppos, const TMouseEvent &e) {
// lock/unlock: modalita IK // lock/unlock: modalita IK
if (TD_LockStageObject <= m_device && m_device < TD_LockStageObject + 1000) { if (TD_LockStageObject <= m_device && m_device < TD_LockStageObject + 1000) {
Skeleton* skeleton = new Skeleton();
buildSkeleton(*skeleton, currentColumnIndex);
int columnIndex = m_device - TD_LockStageObject; int columnIndex = m_device - TD_LockStageObject;
int frame = app->getCurrentFrame()->getFrame(); int frame = app->getCurrentFrame()->getFrame();
if (skeleton->getBoneByColumnIndex(columnIndex) == skeleton->getRootBone()) { if (e.isCtrlPressed() || e.isShiftPressed()) {
app->getCurrentColumn()->setColumnIndex(columnIndex); // ctrl + click : toggle pinned center
m_device = TD_Translation; // shift + click : toggle temporary pin
togglePinnedStatus(columnIndex, frame, e.isShiftPressed());
invalidate();
m_dragTool = 0;
return;
} }
else if (e.isShiftPressed()) { Skeleton *skeleton = new Skeleton();
togglePinnedStatus(columnIndex, frame, e.isShiftPressed()); buildSkeleton(*skeleton, currentColumnIndex);
invalidate(); if (skeleton->getBoneByColumnIndex(columnIndex) ==
m_dragTool = 0; skeleton->getRootBone()) {
return; app->getCurrentColumn()->setColumnIndex(columnIndex);
} m_device = TD_Translation;
else return; } else
return;
} }
switch (m_device) { switch (m_device) {

View file

@ -34,6 +34,7 @@
#include "toonz/dpiscale.h" #include "toonz/dpiscale.h"
#include "toonz/palettecontroller.h" #include "toonz/palettecontroller.h"
#include "toonz/tonionskinmaskhandle.h" #include "toonz/tonionskinmaskhandle.h"
#include "toutputproperties.h"
// TnzCore includes // TnzCore includes
#include "tvectorimage.h" #include "tvectorimage.h"
@ -313,6 +314,11 @@ TImage *TTool::touchImage() {
TFrameHandle *currentFrame = m_application->getCurrentFrame(); TFrameHandle *currentFrame = m_application->getCurrentFrame();
TXshLevelHandle *currentLevel = m_application->getCurrentLevel(); TXshLevelHandle *currentLevel = m_application->getCurrentLevel();
TFrameId tmplFId = m_application->getCurrentScene()
->getScene()
->getProperties()
->formatTemplateFIdForInput();
if (currentFrame->isEditingLevel()) { if (currentFrame->isEditingLevel()) {
// Editing level // Editing level
@ -331,6 +337,8 @@ TImage *TTool::touchImage() {
// create a new drawing // create a new drawing
img = sl->createEmptyFrame(); img = sl->createEmptyFrame();
// modify frameId to be with the same frame format as existing frames
sl->formatFId(fid, tmplFId);
sl->setFrame(fid, img); sl->setFrame(fid, img);
currentLevel->notifyLevelChange(); currentLevel->notifyLevelChange();
m_isFrameCreated = true; m_isFrameCreated = true;
@ -414,6 +422,8 @@ TImage *TTool::touchImage() {
// create the new drawing // create the new drawing
TImageP img = sl->createEmptyFrame(); TImageP img = sl->createEmptyFrame();
m_isFrameCreated = true; m_isFrameCreated = true;
// modify frameId to be with the same frame format as existing frames
sl->formatFId(fid, tmplFId);
// insert the drawing in the level // insert the drawing in the level
sl->setFrame(fid, img); sl->setFrame(fid, img);
// update the cell // update the cell
@ -507,6 +517,9 @@ TImage *TTool::touchImage() {
// create the new drawing // create the new drawing
TImageP img = sl->createEmptyFrame(); TImageP img = sl->createEmptyFrame();
m_isFrameCreated = true; m_isFrameCreated = true;
// modify frameId to be with the same frame format as existing frames
sl->formatFId(fid, tmplFId);
// insert the drawing in the level // insert the drawing in the level
sl->setFrame(fid, img); sl->setFrame(fid, img);
// update the cell // update the cell
@ -561,6 +574,8 @@ TImage *TTool::touchImage() {
TFrameId fid = animationSheetEnabled ? getNewFrameId(sl, row) : TFrameId(1); TFrameId fid = animationSheetEnabled ? getNewFrameId(sl, row) : TFrameId(1);
TImageP img = sl->createEmptyFrame(); TImageP img = sl->createEmptyFrame();
m_isFrameCreated = true; m_isFrameCreated = true;
// modify frameId to be with the same frame format as existing frames
sl->formatFId(fid, tmplFId);
sl->setFrame(fid, img); sl->setFrame(fid, img);
cell = TXshCell(sl, fid); cell = TXshCell(sl, fid);
xsh->setCell(row, col, cell); xsh->setCell(row, col, cell);

View file

@ -1440,7 +1440,16 @@ void TypeTool::replaceText(std::wstring text, int from, int to) {
for (unsigned int i = 0; i < (unsigned int)text.size(); i++) { for (unsigned int i = 0; i < (unsigned int)text.size(); i++) {
wchar_t character = text[i]; wchar_t character = text[i];
if (vi) { // line break case. This can happen when pasting text including the line
// break
if (character == '\r') {
TVectorImageP vi(new TVectorImage);
unsigned int index = from + i;
m_string.insert(m_string.begin() + index,
StrokeChar(vi, -1., (int)(QChar('\r').unicode()), 0));
}
else if (vi) {
TVectorImageP characterImage(new TVectorImage()); TVectorImageP characterImage(new TVectorImage());
unsigned int index = from + i; unsigned int index = from + i;
// se il font ha kerning bisogna tenere conto del carattere successivo // se il font ha kerning bisogna tenere conto del carattere successivo
@ -1466,7 +1475,7 @@ void TypeTool::replaceText(std::wstring text, int from, int to) {
unsigned int index = from + i; unsigned int index = from + i;
if (instance->hasKerning() && (UINT)m_cursorIndex < m_string.size() && if (instance->hasKerning() && (UINT)m_cursorIndex < m_string.size() &&
!m_string[index].isReturn()) index < m_string.size() - 1 && !m_string[index].isReturn())
adv = instance->drawChar((TRasterCM32P &)newRasterCM, p, styleId, adv = instance->drawChar((TRasterCM32P &)newRasterCM, p, styleId,
(wchar_t)character, (wchar_t)character,
(wchar_t)m_string[index].m_key); (wchar_t)m_string[index].m_key);

View file

@ -58,6 +58,8 @@
#include "vectorizerpopup.h" #include "vectorizerpopup.h"
#include "tools/rasterselection.h" #include "tools/rasterselection.h"
#include "tools/strokeselection.h" #include "tools/strokeselection.h"
#include "toonz/sceneproperties.h"
#include "toutputproperties.h"
// TnzCore includes // TnzCore includes
#include "timagecache.h" #include "timagecache.h"
@ -633,7 +635,9 @@ bool pasteRasterImageInCellWithoutUndo(int row, int col,
TXshSimpleLevel *sl = 0; TXshSimpleLevel *sl = 0;
TFrameId fid(1); TFrameId fid(1);
ToonzScene *scene = app->getCurrentScene()->getScene(); ToonzScene *scene = app->getCurrentScene()->getScene();
TCamera *camera = scene->getCurrentCamera(); TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput();
TCamera *camera = scene->getCurrentCamera();
if (cell.isEmpty()) { if (cell.isEmpty()) {
if (row > 0) cell = xsh->getCell(row - 1, col); if (row > 0) cell = xsh->getCell(row - 1, col);
sl = cell.getSimpleLevel(); sl = cell.getSimpleLevel();
@ -667,6 +671,10 @@ bool pasteRasterImageInCellWithoutUndo(int row, int col,
img = sl->createEmptyFrame(); img = sl->createEmptyFrame();
} else } else
return false; return false;
// modify frameId to be with the same frame format as existing frames
sl->formatFId(fid, tmplFId);
sl->setFrame(fid, img); sl->setFrame(fid, img);
app->getCurrentLevel()->setLevel(sl); app->getCurrentLevel()->setLevel(sl);
app->getCurrentLevel()->notifyLevelChange(); app->getCurrentLevel()->notifyLevelChange();
@ -679,6 +687,10 @@ bool pasteRasterImageInCellWithoutUndo(int row, int col,
std::vector<TFrameId> fids; std::vector<TFrameId> fids;
sl->getFids(fids); sl->getFids(fids);
if (fids.size() > 0) fid = TFrameId(fids.back().getNumber() + 1); if (fids.size() > 0) fid = TFrameId(fids.back().getNumber() + 1);
// modify frameId to be with the same frame format as existing frames
sl->formatFId(fid, tmplFId);
sl->setFrame(fid, img); sl->setFrame(fid, img);
} }
xsh->setCell(row, col, TXshCell(sl, fid)); xsh->setCell(row, col, TXshCell(sl, fid));
@ -3381,6 +3393,10 @@ static void createNewDrawing(TXsheet *xsh, int row, int col,
while (fid.getLetter().toUtf8().at(0) < 'z' && sl->isFid(fid)) while (fid.getLetter().toUtf8().at(0) < 'z' && sl->isFid(fid))
fid = TFrameId(fid.getNumber(), fid.getLetter().toUtf8().at(0) + 1); fid = TFrameId(fid.getNumber(), fid.getLetter().toUtf8().at(0) + 1);
} }
// modify frameId to be with the same frame format as existing frames
TFrameId tmplFId =
xsh->getScene()->getProperties()->formatTemplateFIdForInput();
sl->formatFId(fid, tmplFId);
// add the new frame // add the new frame
sl->setFrame(fid, sl->createEmptyFrame()); sl->setFrame(fid, sl->createEmptyFrame());
TApp::instance()->getCurrentLevel()->notifyLevelChange(); TApp::instance()->getCurrentLevel()->notifyLevelChange();

View file

@ -311,10 +311,9 @@ void ComboViewerPanel::onShowHideActionTriggered(QAction *act) {
void ComboViewerPanel::onDrawFrame(int frame, void ComboViewerPanel::onDrawFrame(int frame,
const ImagePainter::VisualSettings &settings, const ImagePainter::VisualSettings &settings,
QElapsedTimer *timer, qint64 targetInstant) { QElapsedTimer *, qint64) {
TApp *app = TApp::instance(); TApp *app = TApp::instance();
m_sceneViewer->setVisual(settings); m_sceneViewer->setVisual(settings);
m_sceneViewer->setTimerAndTargetInstant(timer, targetInstant);
TFrameHandle *frameHandle = app->getCurrentFrame(); TFrameHandle *frameHandle = app->getCurrentFrame();
@ -350,10 +349,6 @@ void ComboViewerPanel::onDrawFrame(int frame,
else if (settings.m_blankColor != TPixel::Transparent) else if (settings.m_blankColor != TPixel::Transparent)
m_sceneViewer->update(); m_sceneViewer->update();
// make sure to redraw the frame here.
// repaint() does NOT immediately redraw the frame for QOpenGLWidget
if (frameHandle->isPlaying()) qApp->processEvents();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View file

@ -228,7 +228,8 @@ void ConvertPopup::Converter::convertLevel(
TPixel32 bgColor = m_parent->m_bgColorField->getColor(); TPixel32 bgColor = m_parent->m_bgColorField->getColor();
ImageUtils::convert(sourceFileFullPath, dstFileFullPath, from, to, ImageUtils::convert(sourceFileFullPath, dstFileFullPath, from, to,
framerate, prop, m_parent->m_notifier, bgColor, framerate, prop, m_parent->m_notifier, bgColor,
m_parent->m_removeDotBeforeFrameNumber->isChecked()); m_parent->m_removeDotBeforeFrameNumber->isChecked(),
oprop->formatTemplateFId());
} }
popup->m_notifier->notifyLevelCompleted(dstFileFullPath); popup->m_notifier->notifyLevelCompleted(dstFileFullPath);
@ -1039,12 +1040,11 @@ TFilePath ConvertPopup::getDestinationFilePath(
const TFilePath &sourceFilePath) { const TFilePath &sourceFilePath) {
// Build the DECODED output folder path // Build the DECODED output folder path
TFilePath destFolder = sourceFilePath.getParentDir(); TFilePath destFolder = sourceFilePath.getParentDir();
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
if (!m_saveInFileFld->getPath().isEmpty()) { if (!m_saveInFileFld->getPath().isEmpty()) {
TFilePath dir(m_saveInFileFld->getPath().toStdWString()); TFilePath dir(m_saveInFileFld->getPath().toStdWString());
destFolder = scene->decodeFilePath(dir);
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
destFolder = scene->decodeFilePath(dir);
} }
// Build the output level name // Build the output level name
@ -1059,10 +1059,11 @@ TFilePath ConvertPopup::getDestinationFilePath(
TFilePath destName = TFilePath(name).withType(ext); TFilePath destName = TFilePath(name).withType(ext);
if (TFileType::isLevelFilePath(sourceFilePath) && if (TFileType::isLevelFilePath(sourceFilePath) &&
!TFileType::isLevelExtension(ext)) !TFileType::isLevelExtension(ext)) {
destName = destName.withFrame(TFrameId::EMPTY_FRAME); // use the '..' // add ".." or "_." according to the output settings' frame format template.
// format to denote TOutputProperties *prop = scene->getProperties()->getOutputProperties();
// an output level destName = destName.withFrame(prop->formatTemplateFId());
}
// Merge the two // Merge the two
return destFolder + destName; return destFolder + destName;
@ -1273,8 +1274,12 @@ void ConvertPopup::onOptionsClicked() {
std::string ext = m_fileFormat->currentText().toStdString(); std::string ext = m_fileFormat->currentText().toStdString();
TPropertyGroup *props = getFormatProperties(ext); TPropertyGroup *props = getFormatProperties(ext);
// use output settings' frame format.
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
TOutputProperties *prop = scene->getProperties()->getOutputProperties();
openFormatSettingsPopup( openFormatSettingsPopup(
this, ext, props, this, ext, props, &prop->formatTemplateFId(), false,
m_srcFilePaths.size() == 1 ? m_srcFilePaths[0] : TFilePath()); m_srcFilePaths.size() == 1 ? m_srcFilePaths[0] : TFilePath());
} }

View file

@ -442,8 +442,15 @@ bool IoCmd::exportLevel(const TFilePath &path, TXshSimpleLevel *sl,
QString::fromStdString(m_sl->index2fid(i).expand()) + "." + QString::fromStdString(m_sl->index2fid(i).expand()) + "." +
QString::fromStdString(m_path.getType()); QString::fromStdString(m_path.getType());
fpout = TFilePath(pathOut.toStdString()); fpout = TFilePath(pathOut.toStdString());
} else } else {
fpout = TFilePath(m_path.withFrame(m_sl->index2fid(i))); // change frame format for saving
TFrameId formattedFId(m_sl->index2fid(i));
formattedFId.setZeroPadding(
m_opts.m_formatTemplateFId.getZeroPadding());
formattedFId.setStartSeqInd(
m_opts.m_formatTemplateFId.getStartSeqInd());
fpout = TFilePath(m_path.withFrame(formattedFId));
}
// Ask for overwrite permission in case a level with the built path // Ask for overwrite permission in case a level with the built path
// already exists // already exists

View file

@ -46,9 +46,9 @@ struct ProgressCallbacks {
virtual ~ProgressCallbacks() {} virtual ~ProgressCallbacks() {}
virtual void setProcessedName(const QString &name) = 0; virtual void setProcessedName(const QString &name) = 0;
virtual void setRange(int min, int max) = 0; virtual void setRange(int min, int max) = 0;
virtual void setValue(int val) = 0; virtual void setValue(int val) = 0;
virtual bool canceled() const = 0; virtual bool canceled() const = 0;
}; };
//************************************************************************************ //************************************************************************************
@ -79,12 +79,15 @@ struct ExportLevelOptions {
//! \li Transparent pixels mapped to white //! \li Transparent pixels mapped to white
bool m_noAntialias; //!< Whether antialias must be removed from images. bool m_noAntialias; //!< Whether antialias must be removed from images.
TFrameId m_formatTemplateFId;
public: public:
ExportLevelOptions() ExportLevelOptions()
: m_props(0) : m_props(0)
, m_bgColor(TPixel32::Transparent) , m_bgColor(TPixel32::Transparent)
, m_forRetas(false) , m_forRetas(false)
, m_noAntialias(false) { , m_noAntialias(false)
, m_formatTemplateFId() {
m_thicknessTransform[0][0] = 0.0, m_thicknessTransform[0][1] = 1.0; m_thicknessTransform[0][0] = 0.0, m_thicknessTransform[0][1] = 1.0;
m_thicknessTransform[1][0] = 0.0, m_thicknessTransform[1][1] = 1.0; m_thicknessTransform[1][0] = 0.0, m_thicknessTransform[1][1] = 1.0;
} }
@ -111,7 +114,7 @@ TImageP exportedImage(
const TXshSimpleLevel &sl, //!< Level host of the image to be exported. const TXshSimpleLevel &sl, //!< Level host of the image to be exported.
const TFrameId &fid, //!< Frame of the image in sl. const TFrameId &fid, //!< Frame of the image in sl.
const ExportLevelOptions &opts = ExportLevelOptions() //!< Export options. const ExportLevelOptions &opts = ExportLevelOptions() //!< Export options.
); );
//--------------------------------------------------------------------- //---------------------------------------------------------------------
@ -142,7 +145,7 @@ bool exportLevel(
0, //!< External callbacks to overwrite requests. 0, //!< External callbacks to overwrite requests.
ProgressCallbacks *progressCB = ProgressCallbacks *progressCB =
0 //!< External callbacks to progress notifications. 0 //!< External callbacks to progress notifications.
); );
} // namespace IoCmd } // namespace IoCmd

View file

@ -36,6 +36,7 @@
#include "toonz/txshlevelhandle.h" #include "toonz/txshlevelhandle.h"
#include "toonz/txsheethandle.h" #include "toonz/txsheethandle.h"
#include "toonz/tscenehandle.h" #include "toonz/tscenehandle.h"
#include "toutputproperties.h"
// TnzCore includes // TnzCore includes
#include "tiio.h" #include "tiio.h"
@ -477,6 +478,10 @@ IoCmd::ExportLevelOptions ExportLevelPopup::getOptions(const std::string &ext) {
opts.m_props = getFormatProperties(ext); opts.m_props = getFormatProperties(ext);
opts.m_forRetas = (m_retas->checkState() == Qt::Checked); opts.m_forRetas = (m_retas->checkState() == Qt::Checked);
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
opts.m_formatTemplateFId =
scene->getProperties()->formatTemplateFIdForInput();
return opts; return opts;
} }
@ -521,14 +526,19 @@ void ExportLevelPopup::checkAlpha() {
void ExportLevelPopup::onOptionsClicked() { void ExportLevelPopup::onOptionsClicked() {
std::string ext = m_format->currentText().toStdString(); std::string ext = m_format->currentText().toStdString();
TPropertyGroup *props = getFormatProperties(ext); TPropertyGroup *props = getFormatProperties(ext);
// use preview settings' frame format.
// hide options when the Retas option is enabled.
TFrameId *tmplFId = nullptr;
if (!m_retas->isChecked()) {
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
tmplFId = &scene->getProperties()->formatTemplateFIdForInput();
}
setModal(false); setModal(false);
if (DVGui::Dialog *dialog = if (openFormatSettingsPopup(this, ext, props, tmplFId, true,
openFormatSettingsPopup(this, ext, props, m_browser->getFolder())) { m_browser->getFolder()))
bool ret; checkAlpha();
ret = connect(dialog, SIGNAL(dialogClosed()), SLOT(checkAlpha())),
assert(ret);
}
} }
//-------------------------------------------------------------- //--------------------------------------------------------------
@ -616,14 +626,19 @@ bool ExportLevelPopup::execute() {
const std::string &ext = m_format->currentText().toStdString(); const std::string &ext = m_format->currentText().toStdString();
const IoCmd::ExportLevelOptions &opts = getOptions(ext); const IoCmd::ExportLevelOptions &opts = getOptions(ext);
TApp *app = TApp::instance();
ToonzScene *scene = app->getCurrentScene()->getScene();
TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput();
// Retrieve current column selection // Retrieve current column selection
TApp *app = TApp::instance();
TSelection *selection = app->getCurrentSelection()->getSelection(); TSelection *selection = app->getCurrentSelection()->getSelection();
TColumnSelection *colSelection = dynamic_cast<TColumnSelection *>(selection); TColumnSelection *colSelection = dynamic_cast<TColumnSelection *>(selection);
if (colSelection && colSelection->getIndices().size() > 1) { if (colSelection && colSelection->getIndices().size() > 1) {
fp = TFilePath(m_browser->getFolder() + TFilePath("a")) fp = TFilePath(m_browser->getFolder() + TFilePath("a"))
.withType(ext) .withType(ext)
.withFrame(); .withFrame(tmplFId);
bool ret = true; bool ret = true;
MultiExportOverwriteCB overwriteCB; MultiExportOverwriteCB overwriteCB;
@ -661,7 +676,7 @@ bool ExportLevelPopup::execute() {
if (isReservedFileName_message(QString::fromStdString(fp.getName()))) if (isReservedFileName_message(QString::fromStdString(fp.getName())))
return false; return false;
return IoCmd::exportLevel(fp.withType(ext).withFrame(), 0, opts); return IoCmd::exportLevel(fp.withType(ext).withFrame(tmplFId), 0, opts);
} }
} }

View file

@ -21,6 +21,7 @@
#include "tlevel_io.h" #include "tlevel_io.h"
#include "tproperty.h" #include "tproperty.h"
#include "timageinfo.h" #include "timageinfo.h"
#include "tfiletype.h"
// Qt includes // Qt includes
#include <QComboBox> #include <QComboBox>
@ -28,6 +29,17 @@
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QPushButton> #include <QPushButton>
#include <QMainWindow> #include <QMainWindow>
#include <QGroupBox>
namespace {
bool checkForSeqNum(QString type) {
TFileType::Type typeInfo = TFileType::getInfoFromExtension(type);
if ((typeInfo & TFileType::IMAGE) && !(typeInfo & TFileType::LEVEL))
return true;
else
return false;
}
}; // namespace
//********************************************************************************** //**********************************************************************************
// FormatSettingsPopup implementation // FormatSettingsPopup implementation
@ -35,7 +47,8 @@
FormatSettingsPopup::FormatSettingsPopup(QWidget *parent, FormatSettingsPopup::FormatSettingsPopup(QWidget *parent,
const std::string &format, const std::string &format,
TPropertyGroup *props) TPropertyGroup *props,
TFrameId *tmplFrameId, bool forInput)
: Dialog(parent) : Dialog(parent)
, m_format(format) , m_format(format)
, m_props(props) , m_props(props)
@ -45,7 +58,9 @@ FormatSettingsPopup::FormatSettingsPopup(QWidget *parent,
, m_codecComboBox(0) , m_codecComboBox(0)
, m_configureCodec(0) , m_configureCodec(0)
#endif #endif
{ , m_sepCharCB(nullptr)
, m_paddingCB(nullptr)
, m_tmplFId(tmplFrameId) {
setWindowTitle(tr("File Settings")); setWindowTitle(tr("File Settings"));
setWindowFlags(Qt::Dialog | Qt::WindowStaysOnTopHint); setWindowFlags(Qt::Dialog | Qt::WindowStaysOnTopHint);
@ -57,22 +72,24 @@ FormatSettingsPopup::FormatSettingsPopup(QWidget *parent,
m_mainLayout->setColumnStretch(0, 0); m_mainLayout->setColumnStretch(0, 0);
m_mainLayout->setColumnStretch(1, 1); m_mainLayout->setColumnStretch(1, 1);
int i = 0; if (m_props) {
for (i = 0; i < m_props->getPropertyCount(); i++) { int i = 0;
if (dynamic_cast<TEnumProperty *>(m_props->getProperty(i))) for (i = 0; i < m_props->getPropertyCount(); i++) {
buildPropertyComboBox(i, m_props); if (dynamic_cast<TEnumProperty *>(m_props->getProperty(i)))
else if (dynamic_cast<TIntProperty *>(m_props->getProperty(i))) buildPropertyComboBox(i, m_props);
buildValueField(i, m_props); else if (dynamic_cast<TIntProperty *>(m_props->getProperty(i)))
else if (dynamic_cast<TDoubleProperty *>(m_props->getProperty(i))) buildValueField(i, m_props);
buildDoubleField(i, m_props); else if (dynamic_cast<TDoubleProperty *>(m_props->getProperty(i)))
else if (dynamic_cast<TBoolProperty *>(m_props->getProperty(i))) { buildDoubleField(i, m_props);
if (m_props->getProperty(i)->getName() != else if (dynamic_cast<TBoolProperty*>(m_props->getProperty(i))) {
"Generate Palette") // Hide. Not using but still needed here if (m_props->getProperty(i)->getName() !=
"Generate Palette") // Hide. Not using but still needed here
buildPropertyCheckBox(i, m_props); buildPropertyCheckBox(i, m_props);
} else if (dynamic_cast<TStringProperty *>(m_props->getProperty(i))) } else if (dynamic_cast<TStringProperty*>(m_props->getProperty(i)))
buildPropertyLineEdit(i, m_props); buildPropertyLineEdit(i, m_props);
else else
assert(false); assert(false);
}
} }
#ifdef _WIN32 #ifdef _WIN32
@ -92,6 +109,51 @@ FormatSettingsPopup::FormatSettingsPopup(QWidget *parent,
} }
#endif #endif
if (checkForSeqNum(QString::fromStdString(format)) && tmplFrameId) {
m_sepCharCB = new QComboBox(this);
m_paddingCB = new QComboBox(this);
m_sepCharCB->addItem(tr(". (period)"), QChar('.'));
m_sepCharCB->addItem(tr("_ (underscore)"), QChar('_'));
m_sepCharCB->setCurrentIndex(m_sepCharCB->findData(
QChar::fromLatin1(tmplFrameId->getStartSeqInd())));
m_paddingCB->addItem(tr("No padding"), 0);
for (int p = 1; p <= 6; p++) m_paddingCB->addItem(QString::number(p), p);
m_paddingCB->setCurrentIndex(
m_paddingCB->findData(tmplFrameId->getZeroPadding()));
int currentRow = m_mainLayout->rowCount();
if (currentRow > 0)
m_mainLayout->addItem(new QSpacerItem(15, 15), currentRow, 0);
QGroupBox *frameFormatGB = new QGroupBox(tr("Frame Number Format"), this);
frameFormatGB->setObjectName((forInput) ? "FrameFormatBoxInput"
: "FrameFormatBoxOutput");
QGridLayout *frameFormatLay = new QGridLayout();
frameFormatLay->setColumnStretch(0, 0);
frameFormatLay->setColumnStretch(1, 1);
{
frameFormatLay->addWidget(new QLabel(tr("Separate Character:"), this), 0,
0, Qt::AlignRight);
frameFormatLay->addWidget(m_sepCharCB, 0, 1, Qt::AlignLeft);
frameFormatLay->addWidget(new QLabel(tr("Padding:"), this), 1, 0,
Qt::AlignRight);
frameFormatLay->addWidget(m_paddingCB, 1, 1, Qt::AlignLeft);
}
frameFormatGB->setLayout(frameFormatLay);
m_mainLayout->addWidget(frameFormatGB, currentRow + 1, 0, 1, 2);
connect(m_sepCharCB, SIGNAL(activated(int)), this,
SLOT(onSepCharCBChanged()));
connect(m_paddingCB, SIGNAL(activated(int)), this,
SLOT(onPaddingCBChanged()));
}
QPushButton *closeButton = new QPushButton(tr("Close")); QPushButton *closeButton = new QPushButton(tr("Close"));
closeButton->setContentsMargins(4, 4, 4, 4); closeButton->setContentsMargins(4, 4, 4, 4);
closeButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); closeButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
@ -319,25 +381,40 @@ void FormatSettingsPopup::showEvent(QShowEvent *se) {
Dialog::showEvent(se); Dialog::showEvent(se);
} }
//-----------------------------------------------------------------------------
void FormatSettingsPopup::onSepCharCBChanged() {
assert(m_tmplFId);
m_tmplFId->setStartSeqInd(m_sepCharCB->currentData().toChar().toLatin1());
}
//-----------------------------------------------------------------------------
void FormatSettingsPopup::onPaddingCBChanged() {
assert(m_tmplFId);
m_tmplFId->setZeroPadding(m_paddingCB->currentData().toInt());
}
//********************************************************************************** //**********************************************************************************
// API functions // API functions
//********************************************************************************** //**********************************************************************************
FormatSettingsPopup *openFormatSettingsPopup(QWidget *parent, bool openFormatSettingsPopup(QWidget *parent, const std::string &format,
const std::string &format, TPropertyGroup *props, TFrameId *tmplFId,
TPropertyGroup *props, bool forInput, const TFilePath &levelPath) {
const TFilePath &levelPath) {
if (!props || props->getPropertyCount() == 0) return 0; if ((!props || props->getPropertyCount() == 0) &&
!(checkForSeqNum(QString::fromStdString(format)) && tmplFId))
return false;
FormatSettingsPopup *popup = new FormatSettingsPopup(parent, format, props); FormatSettingsPopup *popup =
new FormatSettingsPopup(parent, format, props, tmplFId, forInput);
popup->setAttribute(Qt::WA_DeleteOnClose); popup->setAttribute(Qt::WA_DeleteOnClose);
popup->setModal(true); popup->setModal(true);
if (!levelPath.isEmpty()) popup->setLevelPath(levelPath); if (!levelPath.isEmpty()) popup->setLevelPath(levelPath);
popup->show(); popup->exec();
popup->raise();
return popup; return true;
} }

View file

@ -18,11 +18,12 @@
class TPropertyGroup; class TPropertyGroup;
class QLabel; class QLabel;
class QComboBox;
namespace DVGui { namespace DVGui {
class PropertyWidget; class PropertyWidget;
class PropertyComboBox; class PropertyComboBox;
} } // namespace DVGui
//============================================================== //==============================================================
@ -35,7 +36,8 @@ class FormatSettingsPopup final : public DVGui::Dialog {
public: public:
FormatSettingsPopup(QWidget *parent, const std::string &format, FormatSettingsPopup(QWidget *parent, const std::string &format,
TPropertyGroup *props); TPropertyGroup *props, TFrameId *tmplFrameId = nullptr,
bool forInput = true);
void setLevelPath(const TFilePath &path) { m_levelPath = path; } void setLevelPath(const TFilePath &path) { m_levelPath = path; }
void setFormatProperties(TPropertyGroup *props); void setFormatProperties(TPropertyGroup *props);
@ -59,6 +61,9 @@ private:
#endif #endif
TFrameId *m_tmplFId;
QComboBox *m_sepCharCB, *m_paddingCB;
private: private:
void buildPropertyComboBox(int index, TPropertyGroup *props); void buildPropertyComboBox(int index, TPropertyGroup *props);
void buildValueField(int index, TPropertyGroup *props); void buildValueField(int index, TPropertyGroup *props);
@ -70,6 +75,9 @@ private:
private Q_SLOTS: private Q_SLOTS:
void onComboBoxIndexChanged(const QString &); void onComboBoxIndexChanged(const QString &);
void onAviCodecConfigure(); void onAviCodecConfigure();
void onSepCharCBChanged();
void onPaddingCBChanged();
}; };
//********************************************************************************** //**********************************************************************************
@ -101,14 +109,18 @@ private Q_SLOTS:
format. format.
*/ */
FormatSettingsPopup *openFormatSettingsPopup( bool openFormatSettingsPopup(
QWidget *parent, //!< Parent for the new format popup. QWidget *parent, //!< Parent for the new format popup.
const std::string &format, //!< File extension of the displayed format. const std::string &format, //!< File extension of the displayed format.
TPropertyGroup *props, //!< Properties to be shown for the format. TPropertyGroup *props, //!< Properties to be shown for the format.
TFrameId *tmplFId =
nullptr, //!< Template TFrameId to specify frame number format
bool forInput =
true, // specifies border color for the frame number format box
const TFilePath &levelPath = const TFilePath &levelPath =
TFilePath() //!< May be used to choose available codecs TFilePath() //!< May be used to choose available codecs
//! depending on a level's resolution. //! depending on a level's resolution.
); //!< Opens a suitable popup with settings ); //!< Opens a suitable popup with settings
//! for an input level format. //! for an input level format.
#endif // FORMATSETTINGSPOPUPS_H #endif // FORMATSETTINGSPOPUPS_H

View file

@ -6,6 +6,7 @@
#include "menubarcommandids.h" #include "menubarcommandids.h"
#include "tapp.h" #include "tapp.h"
#include "levelcommand.h" #include "levelcommand.h"
#include "formatsettingspopups.h"
// TnzTools includes // TnzTools includes
#include "tools/toolhandle.h" #include "tools/toolhandle.h"
@ -36,6 +37,7 @@
#include "toonz/tproject.h" #include "toonz/tproject.h"
#include "toonz/namebuilder.h" #include "toonz/namebuilder.h"
#include "toonz/childstack.h" #include "toonz/childstack.h"
#include "toutputproperties.h"
// TnzCore includes // TnzCore includes
#include "tsystem.h" #include "tsystem.h"
@ -180,6 +182,10 @@ LevelCreatePopup::LevelCreatePopup()
m_dpiLabel = new QLabel(tr("DPI:")); m_dpiLabel = new QLabel(tr("DPI:"));
m_dpiFld = new DoubleLineEdit(0, 66.76); m_dpiFld = new DoubleLineEdit(0, 66.76);
m_rasterFormatLabel = new QLabel(tr("Format:"));
m_rasterFormatOm = new QComboBox();
m_frameFormatBtn = new QPushButton(tr("Frame Format"));
QPushButton *okBtn = new QPushButton(tr("OK"), this); QPushButton *okBtn = new QPushButton(tr("OK"), this);
QPushButton *cancelBtn = new QPushButton(tr("Cancel"), this); QPushButton *cancelBtn = new QPushButton(tr("Cancel"), this);
QPushButton *applyBtn = new QPushButton(tr("Apply"), this); QPushButton *applyBtn = new QPushButton(tr("Apply"), this);
@ -205,6 +211,11 @@ LevelCreatePopup::LevelCreatePopup()
m_heightFld->setRange(0.1, (std::numeric_limits<double>::max)()); m_heightFld->setRange(0.1, (std::numeric_limits<double>::max)());
m_dpiFld->setRange(0.1, (std::numeric_limits<double>::max)()); m_dpiFld->setRange(0.1, (std::numeric_limits<double>::max)());
m_rasterFormatOm->addItem("tif", "tif");
m_rasterFormatOm->addItem("png", "png");
m_rasterFormatOm->setCurrentIndex(m_rasterFormatOm->findData(
Preferences::instance()->getDefRasterFormat()));
okBtn->setDefault(true); okBtn->setDefault(true);
//--- layout //--- layout
@ -247,15 +258,21 @@ LevelCreatePopup::LevelCreatePopup()
Qt::AlignRight | Qt::AlignVCenter); Qt::AlignRight | Qt::AlignVCenter);
guiLay->addWidget(m_pathFld, 4, 1, 1, 4); guiLay->addWidget(m_pathFld, 4, 1, 1, 4);
// Format options (for Raster/Scan levels)
guiLay->addWidget(m_rasterFormatLabel, 5, 0,
Qt::AlignRight | Qt::AlignVCenter);
guiLay->addWidget(m_rasterFormatOm, 5, 1, Qt::AlignLeft);
guiLay->addWidget(m_frameFormatBtn, 5, 2, 1, 2, Qt::AlignLeft);
// Width - Height // Width - Height
guiLay->addWidget(m_widthLabel, 5, 0, Qt::AlignRight | Qt::AlignVCenter); guiLay->addWidget(m_widthLabel, 6, 0, Qt::AlignRight | Qt::AlignVCenter);
guiLay->addWidget(m_widthFld, 5, 1); guiLay->addWidget(m_widthFld, 6, 1);
guiLay->addWidget(m_heightLabel, 5, 2, Qt::AlignRight | Qt::AlignVCenter); guiLay->addWidget(m_heightLabel, 6, 2, Qt::AlignRight | Qt::AlignVCenter);
guiLay->addWidget(m_heightFld, 5, 3); guiLay->addWidget(m_heightFld, 6, 3);
// DPI // DPI
guiLay->addWidget(m_dpiLabel, 6, 0, Qt::AlignRight | Qt::AlignVCenter); guiLay->addWidget(m_dpiLabel, 7, 0, Qt::AlignRight | Qt::AlignVCenter);
guiLay->addWidget(m_dpiFld, 6, 1, 1, 3); guiLay->addWidget(m_dpiFld, 7, 1);
} }
guiLay->setColumnStretch(0, 0); guiLay->setColumnStretch(0, 0);
guiLay->setColumnStretch(1, 0); guiLay->setColumnStretch(1, 0);
@ -280,12 +297,15 @@ LevelCreatePopup::LevelCreatePopup()
bool ret = true; bool ret = true;
ret = ret && connect(m_levelTypeOm, SIGNAL(currentIndexChanged(int)), ret = ret && connect(m_levelTypeOm, SIGNAL(currentIndexChanged(int)),
SLOT(onLevelTypeChanged(int))); SLOT(onLevelTypeChanged(int)));
ret = ret && connect(m_frameFormatBtn, SIGNAL(clicked()), this,
SLOT(onFrameFormatButton()));
ret = ret && connect(okBtn, SIGNAL(clicked()), this, SLOT(onOkBtn())); ret = ret && connect(okBtn, SIGNAL(clicked()), this, SLOT(onOkBtn()));
ret = ret && connect(cancelBtn, SIGNAL(clicked()), this, SLOT(reject())); ret = ret && connect(cancelBtn, SIGNAL(clicked()), this, SLOT(reject()));
ret = ret =
ret && connect(applyBtn, SIGNAL(clicked()), this, SLOT(onApplyButton())); ret && connect(applyBtn, SIGNAL(clicked()), this, SLOT(onApplyButton()));
setSizeWidgetEnable(false); setSizeWidgetEnable(false);
setRasterWidgetVisible(false);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -377,6 +397,15 @@ void LevelCreatePopup::setSizeWidgetEnable(bool isEnable) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void LevelCreatePopup::setRasterWidgetVisible(bool isVisible) {
m_rasterFormatLabel->setVisible(isVisible);
m_rasterFormatOm->setVisible(isVisible);
m_frameFormatBtn->setVisible(isVisible);
updateGeometry();
}
//-----------------------------------------------------------------------------
int LevelCreatePopup::getLevelType() const { int LevelCreatePopup::getLevelType() const {
return m_levelTypeOm->currentData().toInt(); return m_levelTypeOm->currentData().toInt();
} }
@ -389,6 +418,9 @@ void LevelCreatePopup::onLevelTypeChanged(int index) {
setSizeWidgetEnable(true); setSizeWidgetEnable(true);
else else
setSizeWidgetEnable(false); setSizeWidgetEnable(false);
// setRasterWidgetVisible(type == OVL_XSHLEVEL || type == TZI_XSHLEVEL);
updatePath(); updatePath();
std::wstring levelName = m_nameFld->text().toStdWString(); std::wstring levelName = m_nameFld->text().toStdWString();
@ -422,6 +454,17 @@ void LevelCreatePopup::onApplyButton() {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void LevelCreatePopup::onFrameFormatButton() {
// Tentatively use the preview output settings
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return;
std::string ext = m_rasterFormatOm->currentData().toString().toStdString();
openFormatSettingsPopup(this, ext, nullptr,
&scene->getProperties()->formatTemplateFIdForInput());
}
//-----------------------------------------------------------------------------
bool LevelCreatePopup::apply() { bool LevelCreatePopup::apply() {
TApp *app = TApp::instance(); TApp *app = TApp::instance();
int row = app->getCurrentFrame()->getFrame(); int row = app->getCurrentFrame()->getFrame();
@ -499,6 +542,10 @@ bool LevelCreatePopup::apply() {
TFilePath fp = TFilePath fp =
scene->getDefaultLevelPath(lType, levelName).withParentDir(parentDir); scene->getDefaultLevelPath(lType, levelName).withParentDir(parentDir);
if (lType == OVL_XSHLEVEL || lType == TZI_XSHLEVEL)
fp = fp.withType(Preferences::instance()->getDefRasterFormat().toStdString());
// fp = fp.withType(m_rasterFormatOm->currentData().toString().toStdString());
TFilePath actualFp = scene->decodeFilePath(fp); TFilePath actualFp = scene->decodeFilePath(fp);
bool fileExists = TSystem::doesExistFileOrLevel(actualFp); bool fileExists = TSystem::doesExistFileOrLevel(actualFp);
if (!fileExists) { if (!fileExists) {
@ -607,7 +654,6 @@ bool LevelCreatePopup::apply() {
for (i = from; i <= to; i += inc) { for (i = from; i <= to; i += inc) {
TFrameId fid(i); TFrameId fid(i);
TXshCell cell(sl, fid);
if (lType == PLI_XSHLEVEL) if (lType == PLI_XSHLEVEL)
sl->setFrame(fid, new TVectorImage()); sl->setFrame(fid, new TVectorImage());
else if (lType == TZP_XSHLEVEL) { else if (lType == TZP_XSHLEVEL) {
@ -622,8 +668,12 @@ bool LevelCreatePopup::apply() {
raster->clear(); raster->clear();
TRasterImageP ri(raster); TRasterImageP ri(raster);
ri->setDpi(dpi, dpi); ri->setDpi(dpi, dpi);
// modify frameId to be with the same frame format as existing frames
TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput();
sl->formatFId(fid, tmplFId);
sl->setFrame(fid, ri); sl->setFrame(fid, ri);
} }
TXshCell cell(sl, fid);
for (j = 0; j < step; j++) xsh->setCell(row++, col, cell); for (j = 0; j < step; j++) xsh->setCell(row++, col, cell);
} }

View file

@ -34,10 +34,16 @@ class LevelCreatePopup final : public DVGui::Dialog {
DVGui::MeasuredDoubleLineEdit *m_heightFld; DVGui::MeasuredDoubleLineEdit *m_heightFld;
DVGui::DoubleLineEdit *m_dpiFld; DVGui::DoubleLineEdit *m_dpiFld;
QLabel *m_rasterFormatLabel;
QComboBox *m_rasterFormatOm;
QPushButton *m_frameFormatBtn;
public: public:
LevelCreatePopup(); LevelCreatePopup();
void setSizeWidgetEnable(bool isEnable); void setSizeWidgetEnable(bool isEnable);
void setRasterWidgetVisible(bool isVisible);
int getLevelType() const; int getLevelType() const;
void update(); void update();
@ -55,6 +61,7 @@ public slots:
void onOkBtn(); void onOkBtn();
void onApplyButton(); void onApplyButton();
void onFrameFormatButton();
}; };
#endif // LEVELCREATEPOPUP_H #endif // LEVELCREATEPOPUP_H

View file

@ -38,6 +38,7 @@
#include "tenv.h" #include "tenv.h"
#include "tsystem.h" #include "tsystem.h"
#include "tstream.h" #include "tstream.h"
#include "tfiletype.h"
// Qt includes // Qt includes
#include <QLabel> #include <QLabel>
@ -145,6 +146,13 @@ enum ThreadsOption {
enum GranularityOption { c_off, c_large, c_medium, c_small }; enum GranularityOption { c_off, c_large, c_medium, c_small };
bool checkForSeqNum(QString type) {
TFileType::Type typeInfo = TFileType::getInfoFromExtension(type);
if ((typeInfo & TFileType::IMAGE) && !(typeInfo & TFileType::LEVEL))
return true;
else
return false;
}
} // anonymous namespace } // anonymous namespace
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1238,10 +1246,10 @@ void OutputSettingsPopup::onNameChanged() {
TOutputProperties *prop = getProperties(); TOutputProperties *prop = getProperties();
TFilePath fp = prop->getPath(); TFilePath fp = prop->getPath();
if (fp.getWideName() == wname) return; // Already had the right name TFilePath newFp = fp.getParentDir() + TFilePath(wname).withType(fp.getType());
if (newFp == fp) return; // Already had the right name
fp = fp.getParentDir() + TFilePath(wname).withType(fp.getType()); prop->setPath(newFp);
prop->setPath(fp);
TApp::instance()->getCurrentScene()->setDirtyFlag(true); TApp::instance()->getCurrentScene()->setDirtyFlag(true);
@ -1258,10 +1266,14 @@ void OutputSettingsPopup::onFormatChanged(const QString &str) {
ext == "spritesheet"; ext == "spritesheet";
}; };
TOutputProperties *prop = getProperties(); TOutputProperties *prop = getProperties();
bool wasMultiRenderInvalid = bool wasMultiRenderInvalid =
isMultiRenderInvalid(prop->getPath().getType(), m_allowMT); isMultiRenderInvalid(prop->getPath().getType(), m_allowMT);
TFilePath fp = prop->getPath().withType(str.toStdString()); // remove sepchar, ..
TFilePath fp = prop->getPath().withNoFrame().withType(str.toStdString());
// .. then add sepchar for sequencial image formats
if (checkForSeqNum(str)) fp = fp.withFrame(prop->formatTemplateFId());
prop->setPath(fp); prop->setPath(fp);
TApp::instance()->getCurrentScene()->setDirtyFlag(true); TApp::instance()->getCurrentScene()->setDirtyFlag(true);
m_allowMT = Preferences::instance()->getFfmpegMultiThread(); m_allowMT = Preferences::instance()->getFfmpegMultiThread();
@ -1292,9 +1304,25 @@ void OutputSettingsPopup::onFormatChanged(const QString &str) {
void OutputSettingsPopup::openSettingsPopup() { void OutputSettingsPopup::openSettingsPopup() {
TOutputProperties *prop = getProperties(); TOutputProperties *prop = getProperties();
std::string ext = prop->getPath().getType(); std::string ext = prop->getPath().getType();
openFormatSettingsPopup(this, ext, prop->getFileFormatProperties(ext));
TFrameId oldTmplFId = prop->formatTemplateFId();
bool ret =
openFormatSettingsPopup(this, ext, prop->getFileFormatProperties(ext),
&prop->formatTemplateFId(), false);
if (!ret) return;
if (m_presetCombo) m_presetCombo->setCurrentIndex(0); if (m_presetCombo) m_presetCombo->setCurrentIndex(0);
if (oldTmplFId.getZeroPadding() !=
prop->formatTemplateFId().getZeroPadding() ||
oldTmplFId.getStartSeqInd() !=
prop->formatTemplateFId().getStartSeqInd()) {
TFilePath fp =
prop->getPath().withNoFrame().withFrame(prop->formatTemplateFId());
prop->setPath(fp);
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View file

@ -8,6 +8,7 @@
#include "levelsettingspopup.h" #include "levelsettingspopup.h"
#include "tapp.h" #include "tapp.h"
#include "cleanupsettingsmodel.h" #include "cleanupsettingsmodel.h"
#include "formatsettingspopups.h"
#include "tenv.h" #include "tenv.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -29,6 +30,7 @@
#include "toonz/toonzscene.h" #include "toonz/toonzscene.h"
#include "toonz/tcamera.h" #include "toonz/tcamera.h"
#include "toonz/levelproperties.h" #include "toonz/levelproperties.h"
#include "toonz/sceneproperties.h"
#include "toonz/tonionskinmaskhandle.h" #include "toonz/tonionskinmaskhandle.h"
#include "toonz/stage.h" #include "toonz/stage.h"
#include "toonz/toonzfolders.h" #include "toonz/toonzfolders.h"
@ -785,6 +787,17 @@ void PreferencesPopup::onCheck30bitDisplay() {
checker.exec(); checker.exec();
} }
//-----------------------------------------------------------------------------
void PreferencesPopup::onFrameFormatButton() {
ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
if (!scene) return;
std::string ext = Preferences::instance()->getDefRasterFormat().toStdString();
openFormatSettingsPopup(this, ext, nullptr,
&scene->getProperties()->formatTemplateFIdForInput());
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void PreferencesPopup::onAddLevelFormat() { void PreferencesPopup::onAddLevelFormat() {
@ -1011,15 +1024,26 @@ void PreferencesPopup::insertUI(PreferencesItemId id, QGridLayout* layout,
// CheckBox contains label in itself // CheckBox contains label in itself
if (item.type == QMetaType::Bool) if (item.type == QMetaType::Bool)
layout->addWidget(widget, layout->rowCount(), 0, 1, 2); layout->addWidget(widget, layout->rowCount(), 0, 1, 3, Qt::AlignLeft);
else { // insert labels for other types else { // insert labels for other types
int row = layout->rowCount(); int row = layout->rowCount();
layout->addWidget(new QLabel(getUIString(id), this), row, 0, layout->addWidget(new QLabel(getUIString(id), this), row, 0,
Qt::AlignRight | Qt::AlignVCenter); Qt::AlignRight | Qt::AlignVCenter);
if (isFileField) if (isFileField)
layout->addWidget(widget, row, 1, 1, 2); layout->addWidget(widget, row, 1, 1, 2);
else else {
layout->addWidget(widget, row, 1, Qt::AlignLeft | Qt::AlignVCenter); bool isWideComboBox = false;
for (auto cbItem : comboItems) {
if (widget->fontMetrics().width(cbItem.first) > 100) {
isWideComboBox = true;
break;
}
}
if (id == interfaceFont) isWideComboBox = true;
layout->addWidget(widget, row, 1, 1, (isWideComboBox) ? 2 : 1,
Qt::AlignLeft | Qt::AlignVCenter);
}
} }
} }
@ -1054,7 +1078,7 @@ void PreferencesPopup::insertFootNote(QGridLayout* layout) {
QLabel* note = new QLabel( QLabel* note = new QLabel(
tr("* Changes will take effect the next time you run Tahoma2D")); tr("* Changes will take effect the next time you run Tahoma2D"));
note->setStyleSheet("font-size: 10px; font: italic;"); note->setStyleSheet("font-size: 10px; font: italic;");
layout->addWidget(note, layout->rowCount(), 0, 1, 2, layout->addWidget(note, layout->rowCount(), 0, 1, 3,
Qt::AlignLeft | Qt::AlignVCenter); Qt::AlignLeft | Qt::AlignVCenter);
} }
@ -1148,7 +1172,8 @@ QString PreferencesPopup::getUIString(PreferencesItemId id) {
{rhubarbTimeout, tr("Analyze Audio Timeout (seconds):")}, {rhubarbTimeout, tr("Analyze Audio Timeout (seconds):")},
// Drawing // Drawing
{scanLevelType, tr("Scan File Format:")}, {DefRasterFormat, tr("Default Raster Level Format:")},
//{scanLevelType, tr("Scan File Format:")},
{DefLevelType, tr("Default Level Type:")}, {DefLevelType, tr("Default Level Type:")},
{newLevelSizeToCameraSizeEnabled, {newLevelSizeToCameraSizeEnabled,
tr("New Levels Default to the Current Camera Size")}, tr("New Levels Default to the Current Camera Size")},
@ -1229,7 +1254,7 @@ QString PreferencesPopup::getUIString(PreferencesItemId id) {
{blanksCount, tr("Blank Frames:")}, {blanksCount, tr("Blank Frames:")},
{blankColor, tr("Blank Frames Color:")}, {blankColor, tr("Blank Frames Color:")},
{rewindAfterPlayback, tr("Rewind after Playback")}, {rewindAfterPlayback, tr("Rewind after Playback")},
{shortPlayFrameCount, tr("Number of Frames to Play for Short Play:")}, {shortPlayFrameCount, tr("Number of Frames to Play \nfor Short Play:")},
{previewAlwaysOpenNewFlip, tr("Display in a New Flipbook Window")}, {previewAlwaysOpenNewFlip, tr("Display in a New Flipbook Window")},
{fitToFlipbook, tr("Fit to Flipbook")}, {fitToFlipbook, tr("Fit to Flipbook")},
{generatedMovieViewEnabled, tr("Open Flipbook after Rendering")}, {generatedMovieViewEnabled, tr("Open Flipbook after Rendering")},
@ -1316,7 +1341,8 @@ QList<ComboBoxItem> PreferencesPopup::getComboItemList(
{columnIconLoadingPolicy, {columnIconLoadingPolicy,
{{tr("At Once"), Preferences::LoadAtOnce}, {{tr("At Once"), Preferences::LoadAtOnce},
{tr("On Demand"), Preferences::LoadOnDemand}}}, {tr("On Demand"), Preferences::LoadOnDemand}}},
{scanLevelType, {{"tif", "tif"}, {"png", "png"}}}, {DefRasterFormat, {{"tif", "tif"}, {"png", "png"}}},
//{scanLevelType, {{"tif", "tif"}, {"png", "png"}}},
{DefLevelType, {DefLevelType,
{{tr("Vector Level"), PLI_XSHLEVEL}, {{tr("Vector Level"), PLI_XSHLEVEL},
{tr("Smart Raster Level"), TZP_XSHLEVEL}, {tr("Smart Raster Level"), TZP_XSHLEVEL},
@ -1574,7 +1600,7 @@ QWidget* PreferencesPopup::createInterfacePage() {
// lay->addWidget(new QLabel(tr("Pixels Only:"), this), 5, 0, // lay->addWidget(new QLabel(tr("Pixels Only:"), this), 5, 0,
// Qt::AlignRight | Qt::AlignVCenter); // Qt::AlignRight | Qt::AlignVCenter);
// lay->addWidget(createUI(pixelsOnly), 5, 1); // lay->addWidget(createUI(pixelsOnly), 5, 1, 1, 2, Qt::AlignLeft);
// insertUI(CurrentRoomChoice, lay, roomItemList); // insertUI(CurrentRoomChoice, lay, roomItemList);
insertUI(functionEditorToggle, lay, getComboItemList(functionEditorToggle)); insertUI(functionEditorToggle, lay, getComboItemList(functionEditorToggle));
@ -1593,7 +1619,7 @@ QWidget* PreferencesPopup::createInterfacePage() {
#if QT_VERSION >= 0x051000 #if QT_VERSION >= 0x051000
insertUI(displayIn30bit, lay); insertUI(displayIn30bit, lay);
row = lay->rowCount(); row = lay->rowCount();
lay->addWidget(check30bitBtn, row - 1, 3); lay->addWidget(check30bitBtn, row - 1, 2, Qt::AlignRight);
#endif #endif
// insertUI(showIconsInMenu, lay); // insertUI(showIconsInMenu, lay);
@ -1760,7 +1786,7 @@ QWidget* PreferencesPopup::createImportExportPage() {
insertUI(ffmpegTimeout, ffmpegOptionsLay); insertUI(ffmpegTimeout, ffmpegOptionsLay);
putLabel( putLabel(
tr("Enabling multi-thread rendering will render significantly faster\n" tr("Enabling multi-thread rendering will render significantly faster \n"
"but a random crash might occur, use at your own risk:"), "but a random crash might occur, use at your own risk:"),
ffmpegOptionsLay); ffmpegOptionsLay);
insertUI(ffmpegMultiThread, ffmpegOptionsLay); insertUI(ffmpegMultiThread, ffmpegOptionsLay);
@ -1783,10 +1809,15 @@ QWidget* PreferencesPopup::createImportExportPage() {
QWidget* PreferencesPopup::createDrawingPage() { QWidget* PreferencesPopup::createDrawingPage() {
QWidget* widget = new QWidget(this); QWidget* widget = new QWidget(this);
QGridLayout* lay = new QGridLayout(); QGridLayout* lay = new QGridLayout();
QPushButton* frameFormatBtn = new QPushButton(tr("Default Frame Filename Format"));
setupLayout(lay); setupLayout(lay);
// insertUI(scanLevelType, lay, getComboItemList(scanLevelType));
insertUI(DefLevelType, lay, getComboItemList(DefLevelType)); insertUI(DefLevelType, lay, getComboItemList(DefLevelType));
insertUI(DefRasterFormat, lay, getComboItemList(DefRasterFormat));
int row = lay->rowCount();
lay->addWidget(frameFormatBtn, row - 1, 2, Qt::AlignLeft);
insertUI(newLevelSizeToCameraSizeEnabled, lay); insertUI(newLevelSizeToCameraSizeEnabled, lay);
insertDualUIs(DefLevelWidth, DefLevelHeight, lay); insertDualUIs(DefLevelWidth, DefLevelHeight, lay);
// insertUI(DefLevelDpi, lay); // insertUI(DefLevelDpi, lay);
@ -1829,6 +1860,9 @@ QWidget* PreferencesPopup::createDrawingPage() {
getUI<MeasuredDoubleLineEdit*>(DefLevelHeight)->setDecimals(0); getUI<MeasuredDoubleLineEdit*>(DefLevelHeight)->setDecimals(0);
//} //}
bool ret = ret && connect(frameFormatBtn, SIGNAL(clicked()), this,
SLOT(onFrameFormatButton()));
return widget; return widget;
} }

View file

@ -179,6 +179,7 @@ private slots:
void onInterfaceFontChanged(const QString& text); void onInterfaceFontChanged(const QString& text);
void onLutPathChanged(); void onLutPathChanged();
void onCheck30bitDisplay(); void onCheck30bitDisplay();
void onFrameFormatButton();
void onAddLevelFormat(); void onAddLevelFormat();
void onRemoveLevelFormat(); void onRemoveLevelFormat();

View file

@ -800,8 +800,7 @@ SceneViewer::SceneViewer(ImageUtils::FullScreenWidget *parent)
, m_mousePanning(0) , m_mousePanning(0)
, m_mouseZooming(0) , m_mouseZooming(0)
, m_mouseRotating(0) , m_mouseRotating(0)
, m_keyAction(0) , m_keyAction(0) {
, m_timer(nullptr) {
m_visualSettings.m_sceneProperties = m_visualSettings.m_sceneProperties =
TApp::instance()->getCurrentScene()->getScene()->getProperties(); TApp::instance()->getCurrentScene()->getScene()->getProperties();
m_stopMotion = StopMotion::instance(); m_stopMotion = StopMotion::instance();
@ -2053,14 +2052,6 @@ void SceneViewer::paintGL() {
if (!m_isPicking && m_lutCalibrator && m_lutCalibrator->isValid()) if (!m_isPicking && m_lutCalibrator && m_lutCalibrator->isValid())
m_lutCalibrator->onEndDraw(m_fbo); m_lutCalibrator->onEndDraw(m_fbo);
// wait to achieve precise fps
if (m_timer && m_timer->isValid()) {
qint64 currentInstant = m_timer->nsecsElapsed();
while (currentInstant < m_targetInstant) {
currentInstant = m_timer->nsecsElapsed();
}
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View file

@ -219,10 +219,6 @@ class SceneViewer final : public GLWidgetForHighDpi,
QAction *m_keyAction; QAction *m_keyAction;
// passed from PlaybackExecutor
QElapsedTimer *m_timer;
qint64 m_targetInstant;
public: public:
enum ReferenceMode { enum ReferenceMode {
NORMAL_REFERENCE = 1, NORMAL_REFERENCE = 1,
@ -331,11 +327,6 @@ public:
void setPreviewBGColor(const QColor &color) { m_previewBgColor = color; } void setPreviewBGColor(const QColor &color) { m_previewBgColor = color; }
QColor getPreviewBGColor() const { return m_previewBgColor; } QColor getPreviewBGColor() const { return m_previewBgColor; }
void setTimerAndTargetInstant(QElapsedTimer *timer, qint64 target) {
m_timer = timer;
m_targetInstant = target;
}
public: public:
// SceneViewer's gadget public functions // SceneViewer's gadget public functions
TPointD winToWorld(const QPointF &pos) const; TPointD winToWorld(const QPointF &pos) const;

View file

@ -276,10 +276,9 @@ void SceneViewerPanel::onShowHideActionTriggered(QAction *act) {
void SceneViewerPanel::onDrawFrame(int frame, void SceneViewerPanel::onDrawFrame(int frame,
const ImagePainter::VisualSettings &settings, const ImagePainter::VisualSettings &settings,
QElapsedTimer *timer, qint64 targetInstant) { QElapsedTimer *, qint64) {
TApp *app = TApp::instance(); TApp *app = TApp::instance();
m_sceneViewer->setVisual(settings); m_sceneViewer->setVisual(settings);
m_sceneViewer->setTimerAndTargetInstant(timer, targetInstant);
TFrameHandle *frameHandle = app->getCurrentFrame(); TFrameHandle *frameHandle = app->getCurrentFrame();
@ -314,10 +313,6 @@ void SceneViewerPanel::onDrawFrame(int frame,
else if (settings.m_blankColor != TPixel::Transparent) else if (settings.m_blankColor != TPixel::Transparent)
m_sceneViewer->update(); m_sceneViewer->update();
// make sure to redraw the frame here.
// repaint() does NOT immediately redraw the frame for QOpenGLWidget
if (frameHandle->isPlaying()) qApp->processEvents();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View file

@ -551,6 +551,8 @@ bool XdtsIo::loadXdtsScene(ToonzScene *scene, const TFilePath &scenePath) {
int tick1Id, tick2Id; int tick1Id, tick2Id;
popup.getMarkerIds(tick1Id, tick2Id); popup.getMarkerIds(tick1Id, tick2Id);
TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput();
TXsheet *xsh = scene->getXsheet(); TXsheet *xsh = scene->getXsheet();
XdtsTimeTableFieldItem cellField = xdtsData.timeTable().getCellField(); XdtsTimeTableFieldItem cellField = xdtsData.timeTable().getCellField();
XdtsTimeTableHeaderItem cellHeader = xdtsData.timeTable().getCellHeader(); XdtsTimeTableHeaderItem cellHeader = xdtsData.timeTable().getCellHeader();
@ -558,8 +560,9 @@ bool XdtsIo::loadXdtsScene(ToonzScene *scene, const TFilePath &scenePath) {
QStringList layerNames = cellHeader.getLayerNames(); QStringList layerNames = cellHeader.getLayerNames();
QList<int> columns = cellField.getOccupiedColumns(); QList<int> columns = cellField.getOccupiedColumns();
for (int column : columns) { for (int column : columns) {
QString levelName = layerNames.at(column); QString levelName = layerNames.at(column);
TXshLevel *level = levels.value(levelName); TXshLevel *level = levels.value(levelName);
TXshSimpleLevel *sl = level->getSimpleLevel();
QList<int> tick1, tick2; QList<int> tick1, tick2;
QVector<TFrameId> track = cellField.getColumnTrack(column, tick1, tick2); QVector<TFrameId> track = cellField.getColumnTrack(column, tick1, tick2);
@ -568,13 +571,18 @@ bool XdtsIo::loadXdtsScene(ToonzScene *scene, const TFilePath &scenePath) {
for (TFrameId fid : track) { for (TFrameId fid : track) {
if (fid.getNumber() == -1) // EMPTY cell case if (fid.getNumber() == -1) // EMPTY cell case
row++; row++;
else else {
// modify frameId to be with the same frame format as existing frames
if (sl) sl->formatFId(fid, tmplFId);
xsh->setCell(row++, column, TXshCell(level, fid)); xsh->setCell(row++, column, TXshCell(level, fid));
}
} }
// if the last cell is not "SYMBOL_NULL_CELL", continue the cell // if the last cell is not "SYMBOL_NULL_CELL", continue the cell
// to the end of the sheet // to the end of the sheet
TFrameId lastFid = track.last(); TFrameId lastFid = track.last();
if (lastFid.getNumber() != -1) { if (lastFid.getNumber() != -1) {
// modify frameId to be with the same frame format as existing frames
if (sl) sl->formatFId(lastFid, tmplFId);
for (; row < duration; row++) for (; row < duration; row++)
xsh->setCell(row, column, TXshCell(level, TFrameId(lastFid))); xsh->setCell(row, column, TXshCell(level, TFrameId(lastFid)));
} }

View file

@ -74,6 +74,9 @@ void CellsMover::start(int r0, int c0, int r1, int c1, int qualifiers,
m_oldCells.resize(m_rowCount * m_colCount, TXshCell()); m_oldCells.resize(m_rowCount * m_colCount, TXshCell());
getCells(m_cells, r0, c0); getCells(m_cells, r0, c0);
getColumnsData(c0, c1); getColumnsData(c0, c1);
if (m_qualifiers & eInsertCells && !(m_qualifiers & eOverwriteCells))
getImplicitCellInfo();
} }
// //
@ -83,6 +86,46 @@ TXsheet *CellsMover::getXsheet() const {
return TApp::instance()->getCurrentXsheet()->getXsheet(); return TApp::instance()->getCurrentXsheet()->getXsheet();
} }
//
// keeping the implicit cell arrangement when start shift + dragging
//
void CellsMover::getImplicitCellInfo() {
int startCol =
(m_orientation->isVerticalTimeline()) ? m_startPos.x : m_startPos.y;
int startRow =
(m_orientation->isVerticalTimeline()) ? m_startPos.y : m_startPos.x;
TXsheet *xsh = getXsheet();
for (int i = 0; i < m_colCount; i++) {
TXshColumn *column = xsh->getColumn(startCol + i);
if (!column || column->getCellColumn() == 0 || column->isLocked()) continue;
TXshCellColumn *cellCol = column->getCellColumn();
QMap<int, TXshCell> cellInfo;
if (!column->isEmpty()) {
int r0, r1;
column->getRange(r0, r1);
TXshCell currentCell;
for (int r = r0; r <= r1 + 1; r++) {
TXshCell tmpCell = cellCol->getCell(r);
if (tmpCell != currentCell) {
if (m_qualifiers & eCopyCells)
cellInfo.insert(r, tmpCell);
else {
if (r < startRow)
cellInfo.insert(r, tmpCell);
else if (r >= startRow + m_rowCount)
cellInfo.insert(r - m_rowCount, tmpCell);
}
currentCell = tmpCell;
}
}
}
m_implicitCellInfo.append(cellInfo);
}
}
// //
// cells <- xsheet // cells <- xsheet
// //
@ -152,21 +195,25 @@ void CellsMover::moveCells(const TPoint &pos) const {
int startCol = int startCol =
(m_orientation->isVerticalTimeline()) ? m_startPos.x : m_startPos.y; (m_orientation->isVerticalTimeline()) ? m_startPos.x : m_startPos.y;
if (startCol == c) { if (startCol == c) {
int infoId = 0;
for (int i = 0; i < m_colCount; i++) { for (int i = 0; i < m_colCount; i++) {
TXshColumn *column = xsh->getColumn(c + i); TXshColumn *column = xsh->getColumn(c + i);
if (!column || column->getCellColumn() == 0 || column->isLocked()) if (!column || column->getCellColumn() == 0 || column->isLocked())
continue; continue;
// a cell above inserted cells
TXshCell upperCell = xsh->getCell(r - 1, c + i); QMap<int, TXshCell>::const_iterator itr =
if (upperCell.isEmpty()) continue; m_implicitCellInfo[infoId].lowerBound(r);
if (itr == m_implicitCellInfo[infoId].end() || itr.key() == r) {
infoId++;
continue;
}
// a cell at the bottom of the inserted cells // a cell at the bottom of the inserted cells
TXshCell bottomCell = xsh->getCell(r + m_rowCount - 1, c + i); TXshCell bottomCell = xsh->getCell(r + m_rowCount - 1, c + i);
if (bottomCell.isEmpty()) continue; for (int tmp_r = r + m_rowCount; tmp_r <= itr.key() - 1 + m_rowCount;
int tmp_r = r + m_rowCount; tmp_r++)
while (xsh->getCell(tmp_r, c + i) == upperCell) {
xsh->setCell(tmp_r, c + i, bottomCell); xsh->setCell(tmp_r, c + i, bottomCell);
tmp_r++;
} infoId++;
} }
} }
} }
@ -180,6 +227,7 @@ void CellsMover::undoMoveCells(const TPoint &pos) const {
r = pos.x; r = pos.x;
c = pos.y; c = pos.y;
} }
if (m_qualifiers & eInsertCells) { if (m_qualifiers & eInsertCells) {
// Act like implicit hold when dragging cells with pressing Shift key // Act like implicit hold when dragging cells with pressing Shift key
// ( and WITHOUT Alt key ) and dragging within the same column. // ( and WITHOUT Alt key ) and dragging within the same column.
@ -187,19 +235,27 @@ void CellsMover::undoMoveCells(const TPoint &pos) const {
int startCol = int startCol =
(m_orientation->isVerticalTimeline()) ? m_startPos.x : m_startPos.y; (m_orientation->isVerticalTimeline()) ? m_startPos.x : m_startPos.y;
if (startCol == c) { if (startCol == c) {
int infoId = 0;
for (int i = 0; i < m_colCount; i++) { for (int i = 0; i < m_colCount; i++) {
// a cell above selected cells TXshColumn *column = xsh->getColumn(c + i);
TXshCell upperCell = xsh->getCell(r - 1, c + i); if (!column || column->getCellColumn() == 0 || column->isLocked())
if (upperCell.isEmpty()) continue; continue;
// a cell at the bottom of the selected cells
TXshCell bottomCell = xsh->getCell(r + m_rowCount - 1, c + i); // clear the cells and restore original arrangement
if (bottomCell.isEmpty()) continue; TXshCellColumn *cellCol = column->getCellColumn();
int tmp_r = r + m_rowCount; int r0, r1;
while (xsh->getCell(tmp_r, c + i) == bottomCell) { cellCol->getRange(r0, r1);
xsh->setCell(tmp_r, c + i, upperCell); cellCol->clearCells(r0, r1 - r0 + 1);
tmp_r++; QList<int> implicitKeys = m_implicitCellInfo[infoId].keys();
for (int k = 0; k < implicitKeys.size() - 1; k++) {
int from = implicitKeys[k];
int to = implicitKeys[k + 1] - 1;
for (int f = from; f <= to; f++)
cellCol->setCell(f, m_implicitCellInfo[infoId].value(from));
} }
infoId++;
} }
return;
} }
} }
@ -589,7 +645,9 @@ void LevelMoverTool::onCellChange(int row, int col) {
m_validPos = canMoveColumns(pos); m_validPos = canMoveColumns(pos);
if (!m_validPos) return; if (!m_validPos) return;
if (m_moved) cellsMover->undoMoveCells(); if (m_moved) {
cellsMover->undoMoveCells();
}
m_validPos = canMove(pos); m_validPos = canMove(pos);
if (m_validPos) { if (m_validPos) {

View file

@ -33,6 +33,9 @@ class CellsMover {
const Orientation *m_orientation; const Orientation *m_orientation;
// keeping the implicit cell arrangement when start shift + dragging
QList<QMap<int, TXshCell>> m_implicitCellInfo;
// helper method // helper method
TXsheet *getXsheet() const; TXsheet *getXsheet() const;
@ -45,6 +48,8 @@ class CellsMover {
// m_columnsData <- xsheet columns data // m_columnsData <- xsheet columns data
void getColumnsData(int c0, int c1); void getColumnsData(int c0, int c1);
void getImplicitCellInfo();
public: public:
enum Qualifier { enum Qualifier {
eCopyCells = 0x1, // leaves a copy of cells block at the starting point eCopyCells = 0x1, // leaves a copy of cells block at the starting point

View file

@ -60,6 +60,7 @@
#include "toonz/doubleparamcmd.h" #include "toonz/doubleparamcmd.h"
#include "toonz/preferences.h" #include "toonz/preferences.h"
#include "toonz/palettecontroller.h" #include "toonz/palettecontroller.h"
#include "toutputproperties.h"
// TnzBase includes // TnzBase includes
#include "tdoublekeyframe.h" #include "tdoublekeyframe.h"
@ -892,6 +893,9 @@ void RenameCellField::renameCell() {
TApp::instance()->getCurrentSelection()->getSelection()); TApp::instance()->getCurrentSelection()->getSelection());
if (!cellSelection) return; if (!cellSelection) return;
ToonzScene *scene = m_viewer->getXsheet()->getScene();
TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput();
QList<TXshCell> cells; QList<TXshCell> cells;
bool hasFrameZero = false; bool hasFrameZero = false;
@ -929,15 +933,20 @@ void RenameCellField::renameCell() {
} }
} }
TXshLevel *xl = cell.m_level.getPointer(); TXshLevel *xl = cell.m_level.getPointer();
if (!xl || (xl->getSimpleLevel() && !xl->getSimpleLevel()->isEmpty() && TXshSimpleLevel *sl = (xl) ? xl->getSimpleLevel() : nullptr;
xl->getSimpleLevel()->getFirstFid() == TFrameId::NO_FRAME)) { if (!xl ||
(sl && !sl->isEmpty() && sl->getFirstFid() == TFrameId::NO_FRAME)) {
cells.append(TXshCell()); cells.append(TXshCell());
continue; continue;
} }
// if the next upper cell is empty, then make this cell empty too // if the next upper cell is empty, then make this cell empty too
if (fid == TFrameId::NO_FRAME) if (fid == TFrameId::NO_FRAME)
fid = (m_row - tmpRow <= 1) ? cell.m_frameId : TFrameId(0); fid = (m_row - tmpRow <= 1) ? cell.m_frameId : TFrameId(0);
// modify frameId to be with the same frame format as existing frames
if (sl) sl->formatFId(fid, tmplFId);
cells.append(TXshCell(xl, fid)); cells.append(TXshCell(xl, fid));
changed = true; changed = true;
hasFrameZero = (fid.getNumber() == 0 && xl->getSimpleLevel() && hasFrameZero = (fid.getNumber() == 0 && xl->getSimpleLevel() &&
@ -945,7 +954,6 @@ void RenameCellField::renameCell() {
} }
if (!changed) return; if (!changed) return;
} else { } else {
ToonzScene *scene = m_viewer->getXsheet()->getScene();
TLevelSet *levelSet = scene->getLevelSet(); TLevelSet *levelSet = scene->getLevelSet();
TXshLevel *xl = levelSet->getLevel(levelName); TXshLevel *xl = levelSet->getLevel(levelName);
if (!xl && fid != TFrameId::NO_FRAME) { if (!xl && fid != TFrameId::NO_FRAME) {
@ -954,8 +962,11 @@ void RenameCellField::renameCell() {
int levelType = pref->getDefLevelType(); int levelType = pref->getDefLevelType();
xl = scene->createNewLevel(levelType, levelName); xl = scene->createNewLevel(levelType, levelName);
TXshSimpleLevel *sl = xl->getSimpleLevel(); TXshSimpleLevel *sl = xl->getSimpleLevel();
if (levelType == TZP_XSHLEVEL || levelType == OVL_XSHLEVEL) if (levelType == TZP_XSHLEVEL || levelType == OVL_XSHLEVEL) {
// modify frameId to be with the same frame format as existing frames
sl->formatFId(fid, tmplFId);
sl->setFrame(fid, sl->createEmptyFrame()); sl->setFrame(fid, sl->createEmptyFrame());
}
if (levelType == TZP_XSHLEVEL || levelType == PLI_XSHLEVEL) { if (levelType == TZP_XSHLEVEL || levelType == PLI_XSHLEVEL) {
TPalette *defaultPalette = TPalette *defaultPalette =
TApp::instance()->getPaletteController()->getDefaultPalette( TApp::instance()->getPaletteController()->getDefaultPalette(
@ -966,6 +977,10 @@ void RenameCellField::renameCell() {
xl = scene->createNewLevel(TZI_XSHLEVEL, levelName); xl = scene->createNewLevel(TZI_XSHLEVEL, levelName);
} }
if (!xl) return; if (!xl) return;
// modify frameId to be with the same frame format as existing frames
if (xl->getSimpleLevel()) xl->getSimpleLevel()->formatFId(fid, tmplFId);
cells.append(TXshCell(xl, fid)); cells.append(TXshCell(xl, fid));
hasFrameZero = (fid.getNumber() == 0 && xl->getSimpleLevel() && hasFrameZero = (fid.getNumber() == 0 && xl->getSimpleLevel() &&
xl->getSimpleLevel()->isFid(fid)); xl->getSimpleLevel()->isFid(fid));

View file

@ -94,14 +94,15 @@ LevelUpdater::LevelUpdater(TXshSimpleLevel *sl)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
LevelUpdater::LevelUpdater(const TFilePath &fp, TPropertyGroup *lwProperties) LevelUpdater::LevelUpdater(const TFilePath &fp, TPropertyGroup *lwProperties,
const TFrameId &tmplFId)
: m_pg(0) : m_pg(0)
, m_inputLevel(0) , m_inputLevel(0)
, m_imageInfo(0) , m_imageInfo(0)
, m_currIdx(0) , m_currIdx(0)
, m_opened(false) , m_opened(false)
, m_usingTemporaryFile(false) { , m_usingTemporaryFile(false) {
open(fp, lwProperties); open(fp, lwProperties, tmplFId);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -203,7 +204,8 @@ void LevelUpdater::buildProperties(const TFilePath &fp) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void LevelUpdater::open(const TFilePath &fp, TPropertyGroup *pg) { void LevelUpdater::open(const TFilePath &fp, TPropertyGroup *pg,
const TFrameId &tmplFId) {
assert(!m_lw); assert(!m_lw);
// Find out if a corresponding level already exists on disk - in that case, // Find out if a corresponding level already exists on disk - in that case,
@ -257,6 +259,10 @@ void LevelUpdater::open(const TFilePath &fp, TPropertyGroup *pg) {
assert(iconSize.lx > 0 && iconSize.ly > 0); assert(iconSize.lx > 0 && iconSize.ly > 0);
m_lw->setIconSize(iconSize); m_lw->setIconSize(iconSize);
// set the frame format template (to be used in
// TLevelWriter::getFrameWriter())
if (!tmplFId.isNoFrame()) m_lw->setFrameFormatTemplateFId(tmplFId);
m_opened = true; m_opened = true;
} }

View file

@ -276,7 +276,8 @@ void MovieRenderer::Imp::prepareForStart() {
locals::eraseUncompatibleExistingLevel(m_fp, cameraResI); locals::eraseUncompatibleExistingLevel(m_fp, cameraResI);
m_levelUpdaterA.reset(new LevelUpdater( m_levelUpdaterA.reset(new LevelUpdater(
m_fp, oprop->getFileFormatProperties(m_fp.getType()))); m_fp, oprop->getFileFormatProperties(m_fp.getType()),
oprop->formatTemplateFId()));
m_levelUpdaterA->getLevelWriter()->setFrameRate(frameRate); m_levelUpdaterA->getLevelWriter()->setFrameRate(frameRate);
} else { } else {
TFilePath leftFp = m_fp.withName(m_fp.getName() + "_l"); TFilePath leftFp = m_fp.withName(m_fp.getName() + "_l");
@ -286,11 +287,13 @@ void MovieRenderer::Imp::prepareForStart() {
locals::eraseUncompatibleExistingLevel(rightFp, cameraResI); locals::eraseUncompatibleExistingLevel(rightFp, cameraResI);
m_levelUpdaterA.reset(new LevelUpdater( m_levelUpdaterA.reset(new LevelUpdater(
leftFp, oprop->getFileFormatProperties(leftFp.getType()))); leftFp, oprop->getFileFormatProperties(leftFp.getType()),
oprop->formatTemplateFId()));
m_levelUpdaterA->getLevelWriter()->setFrameRate(frameRate); m_levelUpdaterA->getLevelWriter()->setFrameRate(frameRate);
m_levelUpdaterB.reset(new LevelUpdater( m_levelUpdaterB.reset(new LevelUpdater(
rightFp, oprop->getFileFormatProperties(rightFp.getType()))); rightFp, oprop->getFileFormatProperties(rightFp.getType()),
oprop->formatTemplateFId()));
m_levelUpdaterB->getLevelWriter()->setFrameRate(frameRate); m_levelUpdaterB->getLevelWriter()->setFrameRate(frameRate);
} }
} catch (...) { } catch (...) {
@ -538,7 +541,7 @@ void MovieRenderer::Imp::doRenderRasterCompleted(const RenderData &renderData) {
// This thread will be the one processing ft - remove it from the map to // This thread will be the one processing ft - remove it from the map to
// prevent another // prevent another
// thread from interfering // thread from interfering
double frame = ft->first; double frame = ft->first;
std::pair<TRasterP, TRasterP> rasters = ft->second; std::pair<TRasterP, TRasterP> rasters = ft->second;
++m_nextFrameIdxToSave; ++m_nextFrameIdxToSave;

View file

@ -41,7 +41,8 @@ TOutputProperties::TOutputProperties()
, m_maxTileSizeIndex(0) , m_maxTileSizeIndex(0)
, m_threadIndex(2) , m_threadIndex(2)
, m_subcameraPreview(false) , m_subcameraPreview(false)
, m_boardSettings(new BoardSettings()) { , m_boardSettings(new BoardSettings())
, m_formatTemplateFId() {
m_renderSettings = new TRenderSettings(); m_renderSettings = new TRenderSettings();
} }
@ -61,7 +62,8 @@ TOutputProperties::TOutputProperties(const TOutputProperties &src)
, m_maxTileSizeIndex(src.m_maxTileSizeIndex) , m_maxTileSizeIndex(src.m_maxTileSizeIndex)
, m_threadIndex(src.m_threadIndex) , m_threadIndex(src.m_threadIndex)
, m_subcameraPreview(src.m_subcameraPreview) , m_subcameraPreview(src.m_subcameraPreview)
, m_boardSettings(new BoardSettings(*src.m_boardSettings)) { , m_boardSettings(new BoardSettings(*src.m_boardSettings))
, m_formatTemplateFId(src.m_formatTemplateFId) {
std::map<std::string, TPropertyGroup *>::iterator ft, std::map<std::string, TPropertyGroup *>::iterator ft,
fEnd = m_formatProperties.end(); fEnd = m_formatProperties.end();
for (ft = m_formatProperties.begin(); ft != fEnd; ++ft) { for (ft = m_formatProperties.begin(); ft != fEnd; ++ft) {
@ -108,6 +110,8 @@ TOutputProperties &TOutputProperties::operator=(const TOutputProperties &src) {
delete m_boardSettings; delete m_boardSettings;
m_boardSettings = new BoardSettings(*src.m_boardSettings); m_boardSettings = new BoardSettings(*src.m_boardSettings);
m_formatTemplateFId = src.m_formatTemplateFId;
return *this; return *this;
} }

View file

@ -18,7 +18,6 @@
#include "tconvert.h" #include "tconvert.h"
#include "tundo.h" #include "tundo.h"
#include "tbigmemorymanager.h" #include "tbigmemorymanager.h"
#include "tfilepath.h"
#include "timage_io.h" #include "timage_io.h"
// Qt includes // Qt includes
@ -501,7 +500,8 @@ void Preferences::definePreferenceItems() {
std::numeric_limits<int>::max()); std::numeric_limits<int>::max());
// Drawing // Drawing
define(scanLevelType, "scanLevelType", QMetaType::QString, "tif"); define(DefRasterFormat, "DefRasterFormat", QMetaType::QString, "png");
// define(scanLevelType, "scanLevelType", QMetaType::QString, "tif");
define(DefLevelType, "DefLevelType", QMetaType::Int, OVL_XSHLEVEL); define(DefLevelType, "DefLevelType", QMetaType::Int, OVL_XSHLEVEL);
define(newLevelSizeToCameraSizeEnabled, "newLevelSizeToCameraSizeEnabled", define(newLevelSizeToCameraSizeEnabled, "newLevelSizeToCameraSizeEnabled",
QMetaType::Bool, true); QMetaType::Bool, true);
@ -788,6 +788,12 @@ void Preferences::resolveCompatibility() {
else // Default (level name on top of each cell block) else // Default (level name on top of each cell block)
setValue(levelNameDisplayType, ShowLevelName_Default); setValue(levelNameDisplayType, ShowLevelName_Default);
} }
// "scanLevelType" is changed to "DefRasterFormat", enabling to specify
// default format for both the Scan and the Raster levels.
if (m_settings->contains("scanLevelType") &&
!m_settings->contains("DefRasterFormat")) {
setValue(DefRasterFormat, m_settings->value("scanLevelType").toString());
}
} }
//----------------------------------------------------------------- //-----------------------------------------------------------------

View file

@ -313,6 +313,16 @@ void TSceneProperties::saveData(TOStream &os) const {
os.closeChild(); os.closeChild();
} }
if (out.formatTemplateFId().getZeroPadding() !=
TFrameId().getZeroPadding() ||
out.formatTemplateFId().getStartSeqInd() !=
TFrameId().getStartSeqInd()) {
os.openChild("frameFormat");
os.child("padding") << (int)out.formatTemplateFId().getZeroPadding();
os.child("sepchar") << QString(out.formatTemplateFId().getStartSeqInd());
os.closeChild();
}
os.closeChild(); // </output> os.closeChild(); // </output>
} }
os.closeChild(); os.closeChild();
@ -680,6 +690,20 @@ void TSceneProperties::loadData(TIStream &is, bool isLoadingProject) {
} else if (tagName == "clapperboardSettings") { } else if (tagName == "clapperboardSettings") {
assert(out.getBoardSettings()); assert(out.getBoardSettings());
out.getBoardSettings()->loadData(is); out.getBoardSettings()->loadData(is);
} else if (tagName == "frameFormat") {
while (is.matchTag(tagName)) {
if (tagName == "padding") {
int padding;
is >> padding;
out.formatTemplateFId().setZeroPadding(padding);
} else if (tagName == "sepchar") {
QString sepChar;
is >> sepChar;
out.formatTemplateFId().setStartSeqInd(sepChar[0].toLatin1());
} else
throw TException("unexpected tag: " + tagName);
is.closeChild();
} // end while
} else { } else {
throw TException("unexpected property tag: " + tagName); throw TException("unexpected property tag: " + tagName);
} }
@ -835,4 +859,11 @@ bool TSceneProperties::hasDefaultCellMarks() const {
return false; return false;
} }
return true; return true;
} }
//-----------------------------------------------------------------------------
// templateFId in preview settings is used for "input" file format
// such as new raster level, captured images by camera capture feature, etc.
TFrameId &TSceneProperties::formatTemplateFIdForInput() {
return m_previewProp->formatTemplateFId();
}

View file

@ -407,7 +407,9 @@ void ScenePalette::rollbackPath() { m_pl->setPath(m_oldPath); }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool ScenePalette::isDirty() { return m_pl->getPalette()->getDirtyFlag(); } bool ScenePalette::isDirty() {
return m_pl->getPalette() && m_pl->getPalette()->getDirtyFlag();
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View file

@ -1376,21 +1376,20 @@ TFilePath ToonzScene::getDefaultLevelPath(int levelType,
TProject *project = getProject(); TProject *project = getProject();
assert(project); assert(project);
TFilePath levelPath; TFilePath levelPath;
QString scanLevelType;
switch (levelType) { switch (levelType) {
case TZI_XSHLEVEL: case TZI_XSHLEVEL:
scanLevelType = Preferences::instance()->getScanLevelType(); case OVL_XSHLEVEL: {
levelPath = TFilePath(levelName + L".." + scanLevelType.toStdWString()); QString rasterLevelType = Preferences::instance()->getDefRasterFormat();
break; TFrameId tmplFId = getProperties()->formatTemplateFIdForInput();
levelPath = TFilePath(levelName + L"." + rasterLevelType.toStdWString())
.withFrame(tmplFId);
} break;
case PLI_XSHLEVEL: case PLI_XSHLEVEL:
levelPath = TFilePath(levelName).withType("pli"); levelPath = TFilePath(levelName).withType("pli");
break; break;
case TZP_XSHLEVEL: case TZP_XSHLEVEL:
levelPath = TFilePath(levelName).withType("tlv"); levelPath = TFilePath(levelName).withType("tlv");
break; break;
case OVL_XSHLEVEL:
levelPath = TFilePath(levelName + L"..tif");
break;
default: default:
levelPath = TFilePath(levelName + L"..png"); levelPath = TFilePath(levelName + L"..png");
} }

View file

@ -34,6 +34,7 @@
#include "tstream.h" #include "tstream.h"
#include "tsystem.h" #include "tsystem.h"
#include "tcontenthistory.h" #include "tcontenthistory.h"
#include "tfilepath.h"
// Qt includes // Qt includes
#include <QDir> #include <QDir>
@ -781,6 +782,27 @@ TImageP buildIcon(const TImageP &img, const TDimension &size) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// modify frameId to be with the same frame format as existing frames
void TXshSimpleLevel::formatFId(TFrameId &fid, TFrameId _tmplFId) {
if (m_type != OVL_XSHLEVEL && m_type != TZI_XSHLEVEL) return;
if (!m_frames.empty()) {
TFrameId tmplFId = *m_frames.begin();
fid.setZeroPadding(tmplFId.getZeroPadding());
fid.setStartSeqInd(tmplFId.getStartSeqInd());
}
// since there is no reference frame, take sepChar from the path
else {
// override sepchar by the path
QChar sepChar = m_path.getSepChar();
if (!sepChar.isNull()) _tmplFId.setStartSeqInd(sepChar.toLatin1());
fid.setZeroPadding(_tmplFId.getZeroPadding());
fid.setStartSeqInd(_tmplFId.getStartSeqInd());
}
}
//-----------------------------------------------------------------------------
void TXshSimpleLevel::setFrame(const TFrameId &fid, const TImageP &img) { void TXshSimpleLevel::setFrame(const TFrameId &fid, const TImageP &img) {
assert(m_type != UNKNOWN_XSHLEVEL); assert(m_type != UNKNOWN_XSHLEVEL);

View file

@ -490,7 +490,7 @@ ColorField::ColorField(QWidget *parent, bool isAlphaActive, TPixel32 color,
*/ */
void ColorField::setAlphaActive(bool active) { void ColorField::setAlphaActive(bool active) {
if (active && !m_alphaChannel->isVisible()) { if (active && !m_alphaChannel->isVisibleTo(this)) {
m_alphaChannel->show(); m_alphaChannel->show();
connect(m_alphaChannel, SIGNAL(valueChanged(int, bool)), connect(m_alphaChannel, SIGNAL(valueChanged(int, bool)),
SLOT(onAlphaChannelChanged(int, bool))); SLOT(onAlphaChannelChanged(int, bool)));
@ -499,7 +499,7 @@ void ColorField::setAlphaActive(bool active) {
m_color.m = 0; m_color.m = 0;
m_colorSample->setColor(m_color); m_colorSample->setColor(m_color);
emit colorChanged(m_color, false); emit colorChanged(m_color, false);
} else if (!active && m_alphaChannel->isVisible()) { } else if (!active && m_alphaChannel->isVisibleTo(this)) {
m_alphaChannel->hide(); m_alphaChannel->hide();
disconnect(m_alphaChannel, SIGNAL(valueChanged(int, bool)), this, disconnect(m_alphaChannel, SIGNAL(valueChanged(int, bool)), this,
SLOT(onAlphaChannelChanged(int, bool))); SLOT(onAlphaChannelChanged(int, bool)));

View file

@ -220,10 +220,19 @@ void PlaybackExecutor::run() {
shortTermDelayAdjuster -= delayAdjust; shortTermDelayAdjuster -= delayAdjust;
// Show the next frame, telling currently measured fps // Show the next frame, telling currently measured fps
// The wait time will be inserted at the end of paintGL in order to // For the Flipbook, the wait time will be inserted at the end of paintGL
// achieve precise playback // in order to achieve precise playback
emit nextFrame(fps, &m_timer, targetInstant); emit nextFrame(fps, &m_timer, targetInstant);
// Playing on Viewer / Combo Viewer will advance the current frame.
// Calling qApp->processEvents() on drawing frame causes repaint of other
// panels which slows playback. Therefore in Viewer / Combo Viewer panels
// it just calls update() and necessary wait will be inserted here.
qint64 currentInstant = m_timer.nsecsElapsed();
while (currentInstant < targetInstant) {
currentInstant = m_timer.nsecsElapsed();
}
if (FlipConsole::m_areLinked) { if (FlipConsole::m_areLinked) {
// In case there are linked consoles, update them too. // In case there are linked consoles, update them too.
// Their load time must be included in the fps calculation. // Their load time must be included in the fps calculation.

View file

@ -592,7 +592,8 @@ static void convertFromVector(const TLevelReaderP &lr, const TLevelWriterP &lw,
void convert(const TFilePath &source, const TFilePath &dest, void convert(const TFilePath &source, const TFilePath &dest,
const TFrameId &from, const TFrameId &to, double framerate, const TFrameId &from, const TFrameId &to, double framerate,
TPropertyGroup *prop, FrameTaskNotifier *frameNotifier, TPropertyGroup *prop, FrameTaskNotifier *frameNotifier,
const TPixel &bgColor, bool removeDotBeforeFrameNumber) { const TPixel &bgColor, bool removeDotBeforeFrameNumber,
const TFrameId &tmplFId) {
std::string dstExt = dest.getType(), srcExt = source.getType(); std::string dstExt = dest.getType(), srcExt = source.getType();
// Load source level structure // Load source level structure
@ -621,6 +622,7 @@ void convert(const TFilePath &source, const TFilePath &dest,
// Write the destination level // Write the destination level
TLevelWriterP lw(dest, prop); TLevelWriterP lw(dest, prop);
lw->setFrameRate(framerate); lw->setFrameRate(framerate);
lw->setFrameFormatTemplateFId(tmplFId);
if (srcExt == "tlv") if (srcExt == "tlv")
convertFromCM(lr, level->getPalette(), lw, frames, TAffine(), convertFromCM(lr, level->getPalette(), lw, frames, TAffine(),

View file

@ -4240,6 +4240,10 @@ QFrame *StyleEditor::createBottomWidget() {
m_plainColorPage->m_rgbFrame->setVisible(false); m_plainColorPage->m_rgbFrame->setVisible(false);
menu->addSeparator(); menu->addSeparator();
m_toggleOrientationAction =
new QAction(createQIcon("orientation_h"), tr("Toggle Orientation"), this);
menu->addAction(m_toggleOrientationAction);
m_hexEditorAction = new QAction(tr("Hex Color Names..."), this); m_hexEditorAction = new QAction(tr("Hex Color Names..."), this);
menu->addAction(m_hexEditorAction); menu->addAction(m_hexEditorAction);
@ -4258,14 +4262,6 @@ QFrame *StyleEditor::createBottomWidget() {
// QToolBar *displayToolbar = new QToolBar(this); // QToolBar *displayToolbar = new QToolBar(this);
m_toolBar->addWidget(m_styleSetsButton); m_toolBar->addWidget(m_styleSetsButton);
m_toggleOrientationAction =
m_toolBar->addAction(createQIcon("orientation_h"), "");
m_toggleOrientationAction->setToolTip(
tr("Toggle orientation of the Color Page."));
QWidget *toggleOrientationButton =
m_toolBar->widgetForAction(m_toggleOrientationAction);
toggleOrientationButton->setFixedSize(22, 22);
toggleOrientationButton->setFocusPolicy(Qt::NoFocus);
m_toolBar->addWidget(toolButton); m_toolBar->addWidget(toolButton);
m_toolBar->setMaximumHeight(22); m_toolBar->setMaximumHeight(22);
m_toolBar->setIconSize(QSize(16, 16)); m_toolBar->setIconSize(QSize(16, 16));