Merge pull request #911 from manongjohn/ot_patches_20220220
OpenToonz patches thru 2/20/22
This commit is contained in:
commit
59a90d83a8
55 changed files with 865 additions and 300 deletions
|
@ -1706,6 +1706,15 @@ ProjectPopup QLabel {
|
|||
padding-left: 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
|
||||
----------------------------------------------------------------------------- */
|
||||
|
|
|
@ -1706,6 +1706,15 @@ ProjectPopup QLabel {
|
|||
padding-left: 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
|
||||
----------------------------------------------------------------------------- */
|
||||
|
|
|
@ -1706,6 +1706,15 @@ ProjectPopup QLabel {
|
|||
padding-left: 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
|
||||
----------------------------------------------------------------------------- */
|
||||
|
|
|
@ -1706,6 +1706,15 @@ ProjectPopup QLabel {
|
|||
padding-left: 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
|
||||
----------------------------------------------------------------------------- */
|
||||
|
|
|
@ -118,3 +118,13 @@ ProjectPopup {
|
|||
padding-left: 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);
|
||||
}
|
||||
|
|
|
@ -1706,6 +1706,15 @@ ProjectPopup QLabel {
|
|||
padding-left: 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
|
||||
----------------------------------------------------------------------------- */
|
||||
|
|
|
@ -186,7 +186,8 @@ TLevelWriter::TLevelWriter(const TFilePath &path, TPropertyGroup *prop)
|
|||
: TSmartObject(m_classCode)
|
||||
, m_path(path)
|
||||
, m_properties(prop)
|
||||
, m_contentHistory(0) {
|
||||
, m_contentHistory(0)
|
||||
, m_frameFormatTemplateFId(TFrameId::NO_FRAME) {
|
||||
string ext = path.getType();
|
||||
if (!prop) m_properties = Tiio::makeWriterProperties(ext);
|
||||
}
|
||||
|
@ -250,6 +251,12 @@ void TLevelWriter::getSupportedFormats(QStringList &names,
|
|||
//-----------------------------------------------------------
|
||||
|
||||
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));
|
||||
iw->setProperties(m_properties);
|
||||
return iw;
|
||||
|
|
|
@ -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()
|
||||
const // ritorna l'estensione con PUNTO (se c'e')
|
||||
{
|
||||
|
@ -881,7 +911,8 @@ TFilePath TFilePath::withFrame(const TFrameId &frame,
|
|||
if (frame.isNoFrame()) {
|
||||
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 +
|
||||
QString::fromStdString(frame.expand(format)) + "." +
|
||||
|
|
|
@ -176,15 +176,20 @@ TPoint TFont::drawChar(QImage &outImage, TPoint &unused, wchar_t charcode,
|
|||
// alphaMapForGlyph with a space character returns an invalid
|
||||
// QImage for some reason.
|
||||
// Bug 3604: https://github.com/opentoonz/opentoonz/issues/3604
|
||||
#ifdef Q_OS_UNIX
|
||||
if (chars[0] == L' ') {
|
||||
outImage = QImage(raw.averageCharWidth(), raw.ascent() + raw.descent(),
|
||||
QImage::Format_Grayscale8);
|
||||
outImage.fill(255);
|
||||
return getDistance(charcode, nextCharCode);
|
||||
}
|
||||
// (21/1/2022) Use this workaround for all platforms as the crash also occured
|
||||
// in windows when the display is scaled up.
|
||||
if (chars[0].isSpace()) {
|
||||
#if QT_VERSION >= 0x051100
|
||||
int w = QFontMetrics(m_pimpl->m_font).horizontalAdvance(chars[0]);
|
||||
#else
|
||||
int w = raw.averageCharWidth();
|
||||
#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);
|
||||
if (image.format() != QImage::Format_Indexed8 &&
|
||||
image.format() != QImage::Format_Alpha8)
|
||||
|
|
|
@ -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;
|
||||
|
||||
TFilePathInfo analyzePath() const;
|
||||
|
||||
QChar getSepChar() const;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -82,12 +82,11 @@ public:
|
|||
|
||||
static FormatType getFormatType(std::string extension);
|
||||
|
||||
static void define(
|
||||
QString extension, int reader,
|
||||
// nel caso in cui ci siano piu' lettori per lo stesso formato
|
||||
// (es. flash)
|
||||
static void define(QString extension, int reader,
|
||||
// nel caso in cui ci siano piu' lettori per lo stesso
|
||||
// formato (es. flash)
|
||||
|
||||
TLevelReaderCreateProc *proc);
|
||||
TLevelReaderCreateProc *proc);
|
||||
|
||||
static inline void define(QString extension, TLevelReaderCreateProc *proc) {
|
||||
define(extension, 0, proc);
|
||||
|
@ -136,6 +135,9 @@ protected:
|
|||
TContentHistory *m_contentHistory;
|
||||
QString m_creator;
|
||||
|
||||
// if template is not used, frame number is set to TFrameId::NO_FRAME
|
||||
TFrameId m_frameFormatTemplateFId;
|
||||
|
||||
public:
|
||||
TLevelWriter(const TFilePath &path,
|
||||
TPropertyGroup *winfo = 0); // ottiene l'ownership
|
||||
|
@ -203,6 +205,10 @@ public:
|
|||
|
||||
static void define(QString extension, TLevelWriterCreateProc *proc,
|
||||
bool isRenderFormat);
|
||||
|
||||
void setFrameFormatTemplateFId(const TFrameId &tmplFId) {
|
||||
m_frameFormatTemplateFId = tmplFId;
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------
|
||||
|
|
|
@ -124,7 +124,8 @@ class DVAPI LevelUpdater {
|
|||
public:
|
||||
LevelUpdater();
|
||||
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();
|
||||
|
||||
TLevelWriterP getLevelWriter() { return m_lw; }
|
||||
|
@ -142,7 +143,8 @@ public:
|
|||
//! This function may throw in case the specified path has an unrecognized
|
||||
//! extension, or the file could
|
||||
//! 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
|
||||
//! properties are the default in case the level
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "tcommon.h"
|
||||
#include "tgeometry.h"
|
||||
#include "tpixel.h"
|
||||
#include "tfilepath.h"
|
||||
|
||||
// TnzLib includes
|
||||
#include "toonz/levelproperties.h"
|
||||
|
@ -36,7 +37,6 @@
|
|||
|
||||
// Forward declarations
|
||||
|
||||
class TFilePath;
|
||||
class QSettings;
|
||||
|
||||
//==============================================================
|
||||
|
@ -295,7 +295,8 @@ public:
|
|||
int getRhubarbTimeout() { return getIntValue(rhubarbTimeout); }
|
||||
|
||||
// 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); }
|
||||
bool isNewLevelSizeToCameraSizeEnabled() const {
|
||||
return getBoolValue(newLevelSizeToCameraSizeEnabled);
|
||||
|
|
|
@ -82,7 +82,8 @@ enum PreferencesItemId {
|
|||
|
||||
//----------
|
||||
// Drawing
|
||||
scanLevelType,
|
||||
DefRasterFormat,
|
||||
// scanLevelType,// deprecated
|
||||
DefLevelType,
|
||||
newLevelSizeToCameraSizeEnabled,
|
||||
DefLevelWidth,
|
||||
|
|
|
@ -288,6 +288,10 @@ and height.
|
|||
bool hasDefaultCellMarks()
|
||||
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:
|
||||
// not implemented
|
||||
TSceneProperties(const TSceneProperties &);
|
||||
|
|
|
@ -185,6 +185,7 @@ table) it returns the proper insertion index
|
|||
//! from each entry to the next.
|
||||
int guessStep() const;
|
||||
|
||||
void formatFId(TFrameId &fid, TFrameId tmplFId);
|
||||
void setFrame(const TFrameId &fid, const TImageP &img);
|
||||
|
||||
TImageP getFrame(const TFrameId &fid, UCHAR imgManagerParamsMask,
|
||||
|
|
|
@ -98,10 +98,11 @@ void DVAPI convert(
|
|||
const TPixel &bgColor =
|
||||
TPixel::Transparent, //!< Destination Background color.
|
||||
bool removeDotBeforeFrameNumber =
|
||||
false /*-- ConvertPopup
|
||||
での指定に合わせて、[レベル名].[フレーム番号].[拡張子]のうち、
|
||||
[レベル名]と[フレーム番号]の間のドットを消す。 --*/
|
||||
); //!< Converts a saved level to fullcolor, and saves the result.
|
||||
false, /*-- ConvertPopup
|
||||
での指定に合わせて、[レベル名].[フレーム番号].[拡張子]のうち、
|
||||
[レベル名]と[フレーム番号]の間のドットを消す。 --*/
|
||||
const TFrameId &tmplFId = TFrameId() //!< frame format template
|
||||
); //!< Converts a saved level to fullcolor, and saves the result.
|
||||
|
||||
void DVAPI convertNaa2Tlv(
|
||||
const TFilePath &source, //!< Level path to convert from.
|
||||
|
|
|
@ -94,6 +94,10 @@ private:
|
|||
|
||||
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:
|
||||
/*!
|
||||
Constructs TOutputProperties with default value.
|
||||
|
@ -221,6 +225,8 @@ machine's CPU).
|
|||
void setSubcameraPreview(bool enabled) { m_subcameraPreview = enabled; }
|
||||
|
||||
BoardSettings *getBoardSettings() const { return m_boardSettings; }
|
||||
|
||||
TFrameId &formatTemplateFId() { return m_formatTemplateFId; }
|
||||
};
|
||||
|
||||
//--------------------------------------------
|
||||
|
|
|
@ -33,7 +33,7 @@ inline const T &clamp(const T &v, const T &lo, const T &hi) {
|
|||
|
||||
const double turbulentGamma = 2.2;
|
||||
// magic number to offset evolution between generations
|
||||
const double evolutionOffsetStep = 19.82;
|
||||
const double evolutionOffsetStep = 19.82;
|
||||
const double evolutionOffsetStepW = 31.1;
|
||||
} // namespace
|
||||
//------------------------------------------------------------------
|
||||
|
@ -61,11 +61,11 @@ Iwa_FractalNoiseFx::Iwa_FractalNoiseFx()
|
|||
///, m_randomSeed(0)
|
||||
, m_dynamicIntensity(1.0)
|
||||
, m_alphaRendering(false)
|
||||
, m_doConical(false)
|
||||
, m_conicalEvolution(0.0)
|
||||
, m_conicalAngle(60.0)
|
||||
, m_cameraFov(60.0)
|
||||
, m_zScale(2.0) {
|
||||
, m_doConical(false)
|
||||
, m_conicalEvolution(0.0)
|
||||
, m_conicalAngle(60.0)
|
||||
, m_cameraFov(60.0)
|
||||
, m_zScale(2.0) {
|
||||
m_fractalType->addItem(TurbulentSmooth, "Turbulent Smooth");
|
||||
m_fractalType->addItem(TurbulentBasic, "Turbulent Basic");
|
||||
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();
|
||||
|
||||
// affine transformations
|
||||
TAffine globalAff = TTranslation(-tile.m_pos) * ri.m_affine;
|
||||
TAffine globalAff = TTranslation(-tile.m_pos) * ri.m_affine;
|
||||
TAffine parentAff =
|
||||
TScale(param.scale.lx, param.scale.ly) * TRotation(-param.rotation);
|
||||
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++) {
|
||||
// affine transformation for the current generation
|
||||
TAffine currentAff =
|
||||
(globalAff * parentOffsetAff * parentAff * genAff).inv();
|
||||
(globalAff * parentOffsetAff * parentAff * genAff).inv();
|
||||
// scale of the current pattern ( used for the Dynamic / Dynamic Twist
|
||||
// offset )
|
||||
double scale = sqrt(std::abs(currentAff.det()));
|
||||
// for each pixel
|
||||
double* buf_p = work_buf;
|
||||
double *buf_p = work_buf;
|
||||
for (int y = 0; y < outDim.ly; y++) {
|
||||
for (int x = 0; x < outDim.lx; x++, buf_p++) {
|
||||
// obtain sampling position
|
||||
// For Dynamic and Dynamic Twist patterns, the position offsets using
|
||||
// gradient / rotation of the parent pattern
|
||||
TPointD samplePos =
|
||||
getSamplePos(x, y, outDim, out_buf, gen, scale, param);
|
||||
getSamplePos(x, y, outDim, out_buf, gen, scale, param);
|
||||
// multiply affine transformation
|
||||
samplePos = currentAff * samplePos;
|
||||
// adjust position for the block pattern
|
||||
if (param.noiseType == Block)
|
||||
samplePos = TPointD(std::floor(samplePos.x) + 0.5,
|
||||
std::floor(samplePos.y) + 0.5);
|
||||
std::floor(samplePos.y) + 0.5);
|
||||
// calculate the base noise
|
||||
if (param.cycleEvolution)
|
||||
*buf_p = (pn.noise(samplePos.x, samplePos.y, evolution_zw.x,
|
||||
evolution_zw.y) +
|
||||
1.0) *
|
||||
0.5;
|
||||
evolution_zw.y) +
|
||||
1.0) *
|
||||
0.5;
|
||||
else
|
||||
*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(buf_p, param);
|
||||
|
@ -232,17 +232,16 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame,
|
|||
// just copy the values for the first generation
|
||||
if (gen == 0) {
|
||||
memcpy(out_buf, work_buf, outDim.lx * outDim.ly * sizeof(double));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// intensity of the last generation will take the fraction part of
|
||||
// complexity
|
||||
double genIntensity = std::min(1.0, param.complexity - (double)gen);
|
||||
// influence of the current generation
|
||||
double influence =
|
||||
genIntensity * std::pow(param.subInfluence, (double)gen);
|
||||
genIntensity * std::pow(param.subInfluence, (double)gen);
|
||||
// composite the base noise pattern
|
||||
buf_p = work_buf;
|
||||
double* out_p = out_buf;
|
||||
buf_p = work_buf;
|
||||
double *out_p = out_buf;
|
||||
for (int i = 0; i < outDim.lx * outDim.ly; i++, buf_p++, out_p++)
|
||||
composite(out_p, buf_p, influence, param);
|
||||
}
|
||||
|
@ -253,9 +252,9 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame,
|
|||
// according to the sub scale
|
||||
if (param.perspectiveOffset)
|
||||
parentOffsetAff = TScale(param.subScaling) *
|
||||
TRotation(-param.subRotation) * parentOffsetAff *
|
||||
TRotation(param.subRotation) *
|
||||
TScale(1 / param.subScaling);
|
||||
TRotation(-param.subRotation) * parentOffsetAff *
|
||||
TRotation(param.subRotation) *
|
||||
TScale(1 / param.subScaling);
|
||||
|
||||
if (param.cycleEvolution)
|
||||
evolution_zw.x += evolutionOffsetStep;
|
||||
|
@ -269,8 +268,8 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame,
|
|||
// angle of slope of the cone
|
||||
double theta_n = param.conicalAngle * M_PI_180;
|
||||
// half of the vertical fov
|
||||
double phi_2 = param.cameraFov * 0.5 * M_PI_180;
|
||||
double z_scale = std::pow(10.0, param.zScale);
|
||||
double phi_2 = param.cameraFov * 0.5 * M_PI_180;
|
||||
double z_scale = std::pow(10.0, param.zScale);
|
||||
double evolution_w = param.conicalEvolution;
|
||||
|
||||
// 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
|
||||
for (int gen = 0; gen < genCount; gen++) {
|
||||
// affine transformation for the current generation
|
||||
TAffine currentAff =
|
||||
(globalAff * parentAff * genAff).inv();
|
||||
TAffine currentAff = (globalAff * parentAff * genAff).inv();
|
||||
// scale of the current pattern ( used for the Dynamic / Dynamic Twist
|
||||
// offset )
|
||||
double scale = sqrt(std::abs(currentAff.det()));
|
||||
|
||||
// for each pixel
|
||||
double* buf_p = work_buf;
|
||||
double *buf_p = work_buf;
|
||||
for (int y = 0; y < outDim.ly; y++) {
|
||||
for (int x = 0; x < outDim.lx; x++, buf_p++) {
|
||||
|
||||
double dx, dy, dz;
|
||||
if (theta_n == 0.0) {
|
||||
dx = x;
|
||||
dy = y;
|
||||
dz = 0.0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// conical, without offset
|
||||
if (center == TPointD()) {
|
||||
TPointD p = TTranslation(tile.m_pos) * TPointD(x, y);
|
||||
// pixel distance from the screen center
|
||||
double d = tdistance(p, TPointD());
|
||||
// line of sight : d = S * z + T
|
||||
double S = d / D;
|
||||
double T = d;
|
||||
dz = (V - T) / (S - U);
|
||||
double S = d / D;
|
||||
double T = d;
|
||||
dz = (V - T) / (S - U);
|
||||
double dp = S * dz + T;
|
||||
if (d != 0.0) {
|
||||
p.x *= dp / d;
|
||||
p.y *= dp / d;
|
||||
}
|
||||
p += center * (dp / V);
|
||||
p = TTranslation(tile.m_pos).inv() * p;
|
||||
p = TTranslation(tile.m_pos).inv() * p;
|
||||
dx = p.x;
|
||||
dy = p.y;
|
||||
dz /= z_scale;
|
||||
}
|
||||
// conical, with offset
|
||||
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);
|
||||
QVector3D p(_p.x, _p.y, 0.0);
|
||||
QVector3D eye_O(center.x, center.y, -D);
|
||||
QVector3D eye_d = (p - eye_O).normalized();
|
||||
// offset by combination of offsets of A) projection position and
|
||||
// B) eye positon.
|
||||
//
|
||||
// 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_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);
|
||||
|
||||
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 d_a = QVector3D::dotProduct(eye_d, cone_a);
|
||||
float Ca_Oa = QVector3D::dotProduct(cone_C, cone_a) -
|
||||
QVector3D::dotProduct(eye_O, cone_a);
|
||||
|
||||
// A * t^2 + B * t + C = 0
|
||||
float A = d_a * d_a - eye_d.lengthSquared() * cos_ConeT;
|
||||
float B = 2.0 * (QVector3D::dotProduct(eye_d, cone_C) - 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());
|
||||
float A =
|
||||
d_a * d_a - eye_d.lengthSquared() * cos_ConeT * cos_ConeT;
|
||||
float B = 2.0 *
|
||||
(QVector3D::dotProduct(eye_d, cone_C) -
|
||||
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
|
||||
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);
|
||||
if (t1 < 0) t1 = t2;
|
||||
else if (t2 < 0) t2 = t1;
|
||||
if (t1 < 0)
|
||||
t1 = t2;
|
||||
else if (t2 < 0)
|
||||
t2 = t1;
|
||||
double t = std::min(t1, t2);
|
||||
|
||||
// intersecting point
|
||||
QVector3D sampleP = eye_O + eye_d * t;
|
||||
_p.x = sampleP.x();
|
||||
_p.y = sampleP.y();
|
||||
_p = TTranslation(tile.m_pos).inv() * _p;
|
||||
dx = _p.x;
|
||||
dy = _p.y;
|
||||
dz = sampleP.z() / z_scale;
|
||||
_p.x = sampleP.x();
|
||||
_p.y = sampleP.y();
|
||||
_p = TTranslation(tile.m_pos).inv() * _p;
|
||||
dx = _p.x;
|
||||
dy = _p.y;
|
||||
dz = sampleP.z() / z_scale;
|
||||
}
|
||||
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);
|
||||
evolution_zw.x = cycle_d * cos(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
|
||||
// For Dynamic and Dynamic Twist patterns, the position offsets using
|
||||
// gradient / rotation of the parent pattern
|
||||
TPointD samplePosOffset =
|
||||
getSamplePos(x, y, outDim, out_buf, gen, scale, param) -
|
||||
TPointD(x, y);
|
||||
TPointD samplePos =
|
||||
getSamplePos(dx, dy, outDim, out_buf, gen, scale, param);
|
||||
TPointD(dx, dy) + samplePosOffset * (D / (D + dz));
|
||||
// multiply affine transformation
|
||||
samplePos = currentAff * samplePos;
|
||||
// adjust position for the block pattern
|
||||
if (param.noiseType == Block)
|
||||
samplePos = TPointD(std::floor(samplePos.x) + 0.5,
|
||||
std::floor(samplePos.y) + 0.5);
|
||||
std::floor(samplePos.y) + 0.5);
|
||||
// calculate the base noise
|
||||
if (param.cycleEvolution)
|
||||
*buf_p = (pn.noise(samplePos.x, samplePos.y, evolution_zw.x,
|
||||
evolution_zw.y) +
|
||||
1.0) *
|
||||
0.5;
|
||||
evolution_zw.y) +
|
||||
1.0) *
|
||||
0.5;
|
||||
else
|
||||
*buf_p =
|
||||
(pn.noise(samplePos.x, samplePos.y, evolution_z, evolution_w + dz) + 1.0) * 0.5;
|
||||
*buf_p = (pn.noise(samplePos.x, samplePos.y, evolution_z,
|
||||
evolution_w + dz) +
|
||||
1.0) *
|
||||
0.5;
|
||||
|
||||
// convert the noise
|
||||
convert(buf_p, param);
|
||||
|
@ -395,17 +415,16 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame,
|
|||
// just copy the values for the first generation
|
||||
if (gen == 0) {
|
||||
memcpy(out_buf, work_buf, outDim.lx * outDim.ly * sizeof(double));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// intensity of the last generation will take the fraction part of
|
||||
// complexity
|
||||
double genIntensity = std::min(1.0, param.complexity - (double)gen);
|
||||
// influence of the current generation
|
||||
double influence =
|
||||
genIntensity * std::pow(param.subInfluence, (double)gen);
|
||||
genIntensity * std::pow(param.subInfluence, (double)gen);
|
||||
// composite the base noise pattern
|
||||
buf_p = work_buf;
|
||||
double* out_p = out_buf;
|
||||
buf_p = work_buf;
|
||||
double *out_p = out_buf;
|
||||
for (int i = 0; i < outDim.lx * outDim.ly; i++, buf_p++, out_p++)
|
||||
composite(out_p, buf_p, influence, param);
|
||||
}
|
||||
|
@ -422,7 +441,6 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
work_buf_ras->unlock();
|
||||
|
||||
// finalize pattern (converting the color space)
|
||||
|
@ -483,13 +501,13 @@ void Iwa_FractalNoiseFx::obtainParams(FNParam ¶m, const double frame,
|
|||
param.cycleEvolutionRange = m_cycleEvolutionRange->getValue(frame);
|
||||
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.conicalAngle = m_conicalAngle->getValue(frame);
|
||||
param.cameraFov = m_cameraFov->getValue(frame);
|
||||
param.zScale = m_zScale->getValue(frame);
|
||||
param.conicalAngle = m_conicalAngle->getValue(frame);
|
||||
param.cameraFov = m_cameraFov->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 /
|
||||
// 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 scale,
|
||||
const FNParam ¶m) {
|
||||
|
@ -541,43 +560,47 @@ TPointD Iwa_FractalNoiseFx::getSamplePos(double x, double y, const TDimension ou
|
|||
auto clampPos = [&](double x, double y) {
|
||||
if (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);
|
||||
if (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);
|
||||
return TPointD(x, y);
|
||||
};
|
||||
|
||||
auto val = [&](const TPoint& p) {
|
||||
return out_buf[std::min(p.y, outDim.ly - 1) * outDim.lx + std::min(p.x, outDim.lx - 1)];
|
||||
auto val = [&](const TPoint &p) {
|
||||
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) {
|
||||
return (1.0 - ratio) * v0 + ratio * v1;
|
||||
};
|
||||
auto lerpVal = [&](const TPointD &p) {
|
||||
int id_x = (int)std::floor(p.x);
|
||||
auto lerpVal = [&](const TPointD &p) {
|
||||
int id_x = (int)std::floor(p.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;
|
||||
return lerp ( 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);
|
||||
return lerp(
|
||||
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));
|
||||
TPointD left = clampPos(x - range, y);
|
||||
int range = std::max(2, (int)(0.1 / scale));
|
||||
TPointD left = clampPos(x - range, y);
|
||||
TPointD right = clampPos(x + range, y);
|
||||
TPointD down = clampPos(x, y - range);
|
||||
TPointD up = clampPos(x, y + range);
|
||||
|
||||
double dif_x = param.dynamicIntensity * (1 / scale) *
|
||||
(lerpVal(left) - lerpVal(right)) / (left.x - right.x);
|
||||
double dif_y = param.dynamicIntensity * (1 / scale) * (lerpVal(up) - lerpVal(down)) /
|
||||
(up.y - down.y);
|
||||
double dif_y = param.dynamicIntensity * (1 / scale) *
|
||||
(lerpVal(up) - lerpVal(down)) / (up.y - down.y);
|
||||
|
||||
if (param.fractalType == Dynamic)
|
||||
return TPointD(x + dif_x, y + dif_y); // gradient
|
||||
else // Dynamic_twist
|
||||
else // Dynamic_twist
|
||||
return TPointD(x + dif_y, y - dif_x); // rotation
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ protected:
|
|||
// ダイナミックの度合い
|
||||
TDoubleParamP m_dynamicIntensity;
|
||||
|
||||
//- - - Conical Noise - - -
|
||||
//- - - Conical Noise - - -
|
||||
TBoolParamP m_doConical;
|
||||
TDoubleParamP m_conicalEvolution;
|
||||
TDoubleParamP m_conicalAngle;
|
||||
|
@ -126,7 +126,7 @@ protected:
|
|||
public:
|
||||
Iwa_FractalNoiseFx();
|
||||
bool canHandle(const TRenderSettings &info, double frame) override {
|
||||
return true;
|
||||
return !m_doConical->getValue();
|
||||
}
|
||||
bool doGetBBox(double frame, TRectD &bBox,
|
||||
const TRenderSettings &ri) override;
|
||||
|
|
|
@ -413,21 +413,24 @@ void SkeletonTool::leftButtonDown(const TPointD &ppos, const TMouseEvent &e) {
|
|||
|
||||
// lock/unlock: modalita IK
|
||||
if (TD_LockStageObject <= m_device && m_device < TD_LockStageObject + 1000) {
|
||||
Skeleton* skeleton = new Skeleton();
|
||||
buildSkeleton(*skeleton, currentColumnIndex);
|
||||
int columnIndex = m_device - TD_LockStageObject;
|
||||
int frame = app->getCurrentFrame()->getFrame();
|
||||
if (skeleton->getBoneByColumnIndex(columnIndex) == skeleton->getRootBone()) {
|
||||
app->getCurrentColumn()->setColumnIndex(columnIndex);
|
||||
m_device = TD_Translation;
|
||||
int frame = app->getCurrentFrame()->getFrame();
|
||||
if (e.isCtrlPressed() || e.isShiftPressed()) {
|
||||
// ctrl + click : toggle pinned center
|
||||
// shift + click : toggle temporary pin
|
||||
togglePinnedStatus(columnIndex, frame, e.isShiftPressed());
|
||||
invalidate();
|
||||
m_dragTool = 0;
|
||||
return;
|
||||
}
|
||||
else if (e.isShiftPressed()) {
|
||||
togglePinnedStatus(columnIndex, frame, e.isShiftPressed());
|
||||
invalidate();
|
||||
m_dragTool = 0;
|
||||
return;
|
||||
}
|
||||
else return;
|
||||
Skeleton *skeleton = new Skeleton();
|
||||
buildSkeleton(*skeleton, currentColumnIndex);
|
||||
if (skeleton->getBoneByColumnIndex(columnIndex) ==
|
||||
skeleton->getRootBone()) {
|
||||
app->getCurrentColumn()->setColumnIndex(columnIndex);
|
||||
m_device = TD_Translation;
|
||||
} else
|
||||
return;
|
||||
}
|
||||
|
||||
switch (m_device) {
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "toonz/dpiscale.h"
|
||||
#include "toonz/palettecontroller.h"
|
||||
#include "toonz/tonionskinmaskhandle.h"
|
||||
#include "toutputproperties.h"
|
||||
|
||||
// TnzCore includes
|
||||
#include "tvectorimage.h"
|
||||
|
@ -313,6 +314,11 @@ TImage *TTool::touchImage() {
|
|||
TFrameHandle *currentFrame = m_application->getCurrentFrame();
|
||||
TXshLevelHandle *currentLevel = m_application->getCurrentLevel();
|
||||
|
||||
TFrameId tmplFId = m_application->getCurrentScene()
|
||||
->getScene()
|
||||
->getProperties()
|
||||
->formatTemplateFIdForInput();
|
||||
|
||||
if (currentFrame->isEditingLevel()) {
|
||||
// Editing level
|
||||
|
||||
|
@ -331,6 +337,8 @@ TImage *TTool::touchImage() {
|
|||
|
||||
// create a new drawing
|
||||
img = sl->createEmptyFrame();
|
||||
// modify frameId to be with the same frame format as existing frames
|
||||
sl->formatFId(fid, tmplFId);
|
||||
sl->setFrame(fid, img);
|
||||
currentLevel->notifyLevelChange();
|
||||
m_isFrameCreated = true;
|
||||
|
@ -414,6 +422,8 @@ TImage *TTool::touchImage() {
|
|||
// create the new drawing
|
||||
TImageP img = sl->createEmptyFrame();
|
||||
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
|
||||
sl->setFrame(fid, img);
|
||||
// update the cell
|
||||
|
@ -507,6 +517,9 @@ TImage *TTool::touchImage() {
|
|||
// create the new drawing
|
||||
TImageP img = sl->createEmptyFrame();
|
||||
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
|
||||
sl->setFrame(fid, img);
|
||||
// update the cell
|
||||
|
@ -561,6 +574,8 @@ TImage *TTool::touchImage() {
|
|||
TFrameId fid = animationSheetEnabled ? getNewFrameId(sl, row) : TFrameId(1);
|
||||
TImageP img = sl->createEmptyFrame();
|
||||
m_isFrameCreated = true;
|
||||
// modify frameId to be with the same frame format as existing frames
|
||||
sl->formatFId(fid, tmplFId);
|
||||
sl->setFrame(fid, img);
|
||||
cell = TXshCell(sl, fid);
|
||||
xsh->setCell(row, col, cell);
|
||||
|
|
|
@ -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++) {
|
||||
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());
|
||||
unsigned int index = from + i;
|
||||
// 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;
|
||||
|
||||
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,
|
||||
(wchar_t)character,
|
||||
(wchar_t)m_string[index].m_key);
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
#include "vectorizerpopup.h"
|
||||
#include "tools/rasterselection.h"
|
||||
#include "tools/strokeselection.h"
|
||||
#include "toonz/sceneproperties.h"
|
||||
#include "toutputproperties.h"
|
||||
|
||||
// TnzCore includes
|
||||
#include "timagecache.h"
|
||||
|
@ -633,7 +635,9 @@ bool pasteRasterImageInCellWithoutUndo(int row, int col,
|
|||
TXshSimpleLevel *sl = 0;
|
||||
TFrameId fid(1);
|
||||
ToonzScene *scene = app->getCurrentScene()->getScene();
|
||||
TCamera *camera = scene->getCurrentCamera();
|
||||
TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput();
|
||||
|
||||
TCamera *camera = scene->getCurrentCamera();
|
||||
if (cell.isEmpty()) {
|
||||
if (row > 0) cell = xsh->getCell(row - 1, col);
|
||||
sl = cell.getSimpleLevel();
|
||||
|
@ -667,6 +671,10 @@ bool pasteRasterImageInCellWithoutUndo(int row, int col,
|
|||
img = sl->createEmptyFrame();
|
||||
} else
|
||||
return false;
|
||||
|
||||
// modify frameId to be with the same frame format as existing frames
|
||||
sl->formatFId(fid, tmplFId);
|
||||
|
||||
sl->setFrame(fid, img);
|
||||
app->getCurrentLevel()->setLevel(sl);
|
||||
app->getCurrentLevel()->notifyLevelChange();
|
||||
|
@ -679,6 +687,10 @@ bool pasteRasterImageInCellWithoutUndo(int row, int col,
|
|||
std::vector<TFrameId> fids;
|
||||
sl->getFids(fids);
|
||||
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);
|
||||
}
|
||||
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))
|
||||
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
|
||||
sl->setFrame(fid, sl->createEmptyFrame());
|
||||
TApp::instance()->getCurrentLevel()->notifyLevelChange();
|
||||
|
|
|
@ -311,10 +311,9 @@ void ComboViewerPanel::onShowHideActionTriggered(QAction *act) {
|
|||
|
||||
void ComboViewerPanel::onDrawFrame(int frame,
|
||||
const ImagePainter::VisualSettings &settings,
|
||||
QElapsedTimer *timer, qint64 targetInstant) {
|
||||
QElapsedTimer *, qint64) {
|
||||
TApp *app = TApp::instance();
|
||||
m_sceneViewer->setVisual(settings);
|
||||
m_sceneViewer->setTimerAndTargetInstant(timer, targetInstant);
|
||||
|
||||
TFrameHandle *frameHandle = app->getCurrentFrame();
|
||||
|
||||
|
@ -350,10 +349,6 @@ void ComboViewerPanel::onDrawFrame(int frame,
|
|||
|
||||
else if (settings.m_blankColor != TPixel::Transparent)
|
||||
m_sceneViewer->update();
|
||||
|
||||
// make sure to redraw the frame here.
|
||||
// repaint() does NOT immediately redraw the frame for QOpenGLWidget
|
||||
if (frameHandle->isPlaying()) qApp->processEvents();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -228,7 +228,8 @@ void ConvertPopup::Converter::convertLevel(
|
|||
TPixel32 bgColor = m_parent->m_bgColorField->getColor();
|
||||
ImageUtils::convert(sourceFileFullPath, dstFileFullPath, from, to,
|
||||
framerate, prop, m_parent->m_notifier, bgColor,
|
||||
m_parent->m_removeDotBeforeFrameNumber->isChecked());
|
||||
m_parent->m_removeDotBeforeFrameNumber->isChecked(),
|
||||
oprop->formatTemplateFId());
|
||||
}
|
||||
|
||||
popup->m_notifier->notifyLevelCompleted(dstFileFullPath);
|
||||
|
@ -1039,12 +1040,11 @@ TFilePath ConvertPopup::getDestinationFilePath(
|
|||
const TFilePath &sourceFilePath) {
|
||||
// Build the DECODED output folder path
|
||||
TFilePath destFolder = sourceFilePath.getParentDir();
|
||||
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
||||
|
||||
if (!m_saveInFileFld->getPath().isEmpty()) {
|
||||
TFilePath dir(m_saveInFileFld->getPath().toStdWString());
|
||||
|
||||
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
||||
destFolder = scene->decodeFilePath(dir);
|
||||
destFolder = scene->decodeFilePath(dir);
|
||||
}
|
||||
|
||||
// Build the output level name
|
||||
|
@ -1059,10 +1059,11 @@ TFilePath ConvertPopup::getDestinationFilePath(
|
|||
TFilePath destName = TFilePath(name).withType(ext);
|
||||
|
||||
if (TFileType::isLevelFilePath(sourceFilePath) &&
|
||||
!TFileType::isLevelExtension(ext))
|
||||
destName = destName.withFrame(TFrameId::EMPTY_FRAME); // use the '..'
|
||||
// format to denote
|
||||
// an output level
|
||||
!TFileType::isLevelExtension(ext)) {
|
||||
// add ".." or "_." according to the output settings' frame format template.
|
||||
TOutputProperties *prop = scene->getProperties()->getOutputProperties();
|
||||
destName = destName.withFrame(prop->formatTemplateFId());
|
||||
}
|
||||
|
||||
// Merge the two
|
||||
return destFolder + destName;
|
||||
|
@ -1273,8 +1274,12 @@ void ConvertPopup::onOptionsClicked() {
|
|||
std::string ext = m_fileFormat->currentText().toStdString();
|
||||
TPropertyGroup *props = getFormatProperties(ext);
|
||||
|
||||
// use output settings' frame format.
|
||||
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
||||
TOutputProperties *prop = scene->getProperties()->getOutputProperties();
|
||||
|
||||
openFormatSettingsPopup(
|
||||
this, ext, props,
|
||||
this, ext, props, &prop->formatTemplateFId(), false,
|
||||
m_srcFilePaths.size() == 1 ? m_srcFilePaths[0] : TFilePath());
|
||||
}
|
||||
|
||||
|
|
|
@ -442,8 +442,15 @@ bool IoCmd::exportLevel(const TFilePath &path, TXshSimpleLevel *sl,
|
|||
QString::fromStdString(m_sl->index2fid(i).expand()) + "." +
|
||||
QString::fromStdString(m_path.getType());
|
||||
fpout = TFilePath(pathOut.toStdString());
|
||||
} else
|
||||
fpout = TFilePath(m_path.withFrame(m_sl->index2fid(i)));
|
||||
} else {
|
||||
// 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
|
||||
// already exists
|
||||
|
|
|
@ -46,9 +46,9 @@ struct ProgressCallbacks {
|
|||
virtual ~ProgressCallbacks() {}
|
||||
|
||||
virtual void setProcessedName(const QString &name) = 0;
|
||||
virtual void setRange(int min, int max) = 0;
|
||||
virtual void setValue(int val) = 0;
|
||||
virtual bool canceled() const = 0;
|
||||
virtual void setRange(int min, int max) = 0;
|
||||
virtual void setValue(int val) = 0;
|
||||
virtual bool canceled() const = 0;
|
||||
};
|
||||
|
||||
//************************************************************************************
|
||||
|
@ -79,12 +79,15 @@ struct ExportLevelOptions {
|
|||
//! \li Transparent pixels mapped to white
|
||||
bool m_noAntialias; //!< Whether antialias must be removed from images.
|
||||
|
||||
TFrameId m_formatTemplateFId;
|
||||
|
||||
public:
|
||||
ExportLevelOptions()
|
||||
: m_props(0)
|
||||
, m_bgColor(TPixel32::Transparent)
|
||||
, 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[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 TFrameId &fid, //!< Frame of the image in sl.
|
||||
const ExportLevelOptions &opts = ExportLevelOptions() //!< Export options.
|
||||
);
|
||||
);
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
|
@ -142,7 +145,7 @@ bool exportLevel(
|
|||
0, //!< External callbacks to overwrite requests.
|
||||
ProgressCallbacks *progressCB =
|
||||
0 //!< External callbacks to progress notifications.
|
||||
);
|
||||
);
|
||||
|
||||
} // namespace IoCmd
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "toonz/txshlevelhandle.h"
|
||||
#include "toonz/txsheethandle.h"
|
||||
#include "toonz/tscenehandle.h"
|
||||
#include "toutputproperties.h"
|
||||
|
||||
// TnzCore includes
|
||||
#include "tiio.h"
|
||||
|
@ -477,6 +478,10 @@ IoCmd::ExportLevelOptions ExportLevelPopup::getOptions(const std::string &ext) {
|
|||
opts.m_props = getFormatProperties(ext);
|
||||
opts.m_forRetas = (m_retas->checkState() == Qt::Checked);
|
||||
|
||||
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
||||
opts.m_formatTemplateFId =
|
||||
scene->getProperties()->formatTemplateFIdForInput();
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
|
@ -521,14 +526,19 @@ void ExportLevelPopup::checkAlpha() {
|
|||
void ExportLevelPopup::onOptionsClicked() {
|
||||
std::string ext = m_format->currentText().toStdString();
|
||||
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);
|
||||
|
||||
if (DVGui::Dialog *dialog =
|
||||
openFormatSettingsPopup(this, ext, props, m_browser->getFolder())) {
|
||||
bool ret;
|
||||
ret = connect(dialog, SIGNAL(dialogClosed()), SLOT(checkAlpha())),
|
||||
assert(ret);
|
||||
}
|
||||
if (openFormatSettingsPopup(this, ext, props, tmplFId, true,
|
||||
m_browser->getFolder()))
|
||||
checkAlpha();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
|
@ -616,14 +626,19 @@ bool ExportLevelPopup::execute() {
|
|||
const std::string &ext = m_format->currentText().toStdString();
|
||||
const IoCmd::ExportLevelOptions &opts = getOptions(ext);
|
||||
|
||||
TApp *app = TApp::instance();
|
||||
|
||||
ToonzScene *scene = app->getCurrentScene()->getScene();
|
||||
TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput();
|
||||
|
||||
// Retrieve current column selection
|
||||
TApp *app = TApp::instance();
|
||||
|
||||
TSelection *selection = app->getCurrentSelection()->getSelection();
|
||||
TColumnSelection *colSelection = dynamic_cast<TColumnSelection *>(selection);
|
||||
if (colSelection && colSelection->getIndices().size() > 1) {
|
||||
fp = TFilePath(m_browser->getFolder() + TFilePath("a"))
|
||||
.withType(ext)
|
||||
.withFrame();
|
||||
.withFrame(tmplFId);
|
||||
|
||||
bool ret = true;
|
||||
MultiExportOverwriteCB overwriteCB;
|
||||
|
@ -661,7 +676,7 @@ bool ExportLevelPopup::execute() {
|
|||
if (isReservedFileName_message(QString::fromStdString(fp.getName())))
|
||||
return false;
|
||||
|
||||
return IoCmd::exportLevel(fp.withType(ext).withFrame(), 0, opts);
|
||||
return IoCmd::exportLevel(fp.withType(ext).withFrame(tmplFId), 0, opts);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "tlevel_io.h"
|
||||
#include "tproperty.h"
|
||||
#include "timageinfo.h"
|
||||
#include "tfiletype.h"
|
||||
|
||||
// Qt includes
|
||||
#include <QComboBox>
|
||||
|
@ -28,6 +29,17 @@
|
|||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#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
|
||||
|
@ -35,7 +47,8 @@
|
|||
|
||||
FormatSettingsPopup::FormatSettingsPopup(QWidget *parent,
|
||||
const std::string &format,
|
||||
TPropertyGroup *props)
|
||||
TPropertyGroup *props,
|
||||
TFrameId *tmplFrameId, bool forInput)
|
||||
: Dialog(parent)
|
||||
, m_format(format)
|
||||
, m_props(props)
|
||||
|
@ -45,7 +58,9 @@ FormatSettingsPopup::FormatSettingsPopup(QWidget *parent,
|
|||
, m_codecComboBox(0)
|
||||
, m_configureCodec(0)
|
||||
#endif
|
||||
{
|
||||
, m_sepCharCB(nullptr)
|
||||
, m_paddingCB(nullptr)
|
||||
, m_tmplFId(tmplFrameId) {
|
||||
setWindowTitle(tr("File Settings"));
|
||||
|
||||
setWindowFlags(Qt::Dialog | Qt::WindowStaysOnTopHint);
|
||||
|
@ -57,22 +72,24 @@ FormatSettingsPopup::FormatSettingsPopup(QWidget *parent,
|
|||
m_mainLayout->setColumnStretch(0, 0);
|
||||
m_mainLayout->setColumnStretch(1, 1);
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < m_props->getPropertyCount(); i++) {
|
||||
if (dynamic_cast<TEnumProperty *>(m_props->getProperty(i)))
|
||||
buildPropertyComboBox(i, m_props);
|
||||
else if (dynamic_cast<TIntProperty *>(m_props->getProperty(i)))
|
||||
buildValueField(i, m_props);
|
||||
else if (dynamic_cast<TDoubleProperty *>(m_props->getProperty(i)))
|
||||
buildDoubleField(i, m_props);
|
||||
else if (dynamic_cast<TBoolProperty *>(m_props->getProperty(i))) {
|
||||
if (m_props->getProperty(i)->getName() !=
|
||||
"Generate Palette") // Hide. Not using but still needed here
|
||||
if (m_props) {
|
||||
int i = 0;
|
||||
for (i = 0; i < m_props->getPropertyCount(); i++) {
|
||||
if (dynamic_cast<TEnumProperty *>(m_props->getProperty(i)))
|
||||
buildPropertyComboBox(i, m_props);
|
||||
else if (dynamic_cast<TIntProperty *>(m_props->getProperty(i)))
|
||||
buildValueField(i, m_props);
|
||||
else if (dynamic_cast<TDoubleProperty *>(m_props->getProperty(i)))
|
||||
buildDoubleField(i, m_props);
|
||||
else if (dynamic_cast<TBoolProperty*>(m_props->getProperty(i))) {
|
||||
if (m_props->getProperty(i)->getName() !=
|
||||
"Generate Palette") // Hide. Not using but still needed here
|
||||
buildPropertyCheckBox(i, m_props);
|
||||
} else if (dynamic_cast<TStringProperty *>(m_props->getProperty(i)))
|
||||
buildPropertyLineEdit(i, m_props);
|
||||
else
|
||||
assert(false);
|
||||
} else if (dynamic_cast<TStringProperty*>(m_props->getProperty(i)))
|
||||
buildPropertyLineEdit(i, m_props);
|
||||
else
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -92,6 +109,51 @@ FormatSettingsPopup::FormatSettingsPopup(QWidget *parent,
|
|||
}
|
||||
#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"));
|
||||
closeButton->setContentsMargins(4, 4, 4, 4);
|
||||
closeButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
|
@ -319,25 +381,40 @@ void FormatSettingsPopup::showEvent(QShowEvent *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
|
||||
//**********************************************************************************
|
||||
|
||||
FormatSettingsPopup *openFormatSettingsPopup(QWidget *parent,
|
||||
const std::string &format,
|
||||
TPropertyGroup *props,
|
||||
const TFilePath &levelPath) {
|
||||
bool openFormatSettingsPopup(QWidget *parent, const std::string &format,
|
||||
TPropertyGroup *props, TFrameId *tmplFId,
|
||||
bool forInput, 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->setModal(true);
|
||||
|
||||
if (!levelPath.isEmpty()) popup->setLevelPath(levelPath);
|
||||
|
||||
popup->show();
|
||||
popup->raise();
|
||||
popup->exec();
|
||||
|
||||
return popup;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -18,11 +18,12 @@
|
|||
|
||||
class TPropertyGroup;
|
||||
class QLabel;
|
||||
class QComboBox;
|
||||
|
||||
namespace DVGui {
|
||||
class PropertyWidget;
|
||||
class PropertyComboBox;
|
||||
}
|
||||
} // namespace DVGui
|
||||
|
||||
//==============================================================
|
||||
|
||||
|
@ -35,7 +36,8 @@ class FormatSettingsPopup final : public DVGui::Dialog {
|
|||
|
||||
public:
|
||||
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 setFormatProperties(TPropertyGroup *props);
|
||||
|
@ -59,6 +61,9 @@ private:
|
|||
|
||||
#endif
|
||||
|
||||
TFrameId *m_tmplFId;
|
||||
QComboBox *m_sepCharCB, *m_paddingCB;
|
||||
|
||||
private:
|
||||
void buildPropertyComboBox(int index, TPropertyGroup *props);
|
||||
void buildValueField(int index, TPropertyGroup *props);
|
||||
|
@ -70,6 +75,9 @@ private:
|
|||
private Q_SLOTS:
|
||||
void onComboBoxIndexChanged(const QString &);
|
||||
void onAviCodecConfigure();
|
||||
|
||||
void onSepCharCBChanged();
|
||||
void onPaddingCBChanged();
|
||||
};
|
||||
|
||||
//**********************************************************************************
|
||||
|
@ -101,14 +109,18 @@ private Q_SLOTS:
|
|||
format.
|
||||
*/
|
||||
|
||||
FormatSettingsPopup *openFormatSettingsPopup(
|
||||
bool openFormatSettingsPopup(
|
||||
QWidget *parent, //!< Parent for the new format popup.
|
||||
const std::string &format, //!< File extension of the displayed 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 =
|
||||
TFilePath() //!< May be used to choose available codecs
|
||||
//! depending on a level's resolution.
|
||||
); //!< Opens a suitable popup with settings
|
||||
); //!< Opens a suitable popup with settings
|
||||
//! for an input level format.
|
||||
|
||||
#endif // FORMATSETTINGSPOPUPS_H
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "menubarcommandids.h"
|
||||
#include "tapp.h"
|
||||
#include "levelcommand.h"
|
||||
#include "formatsettingspopups.h"
|
||||
|
||||
// TnzTools includes
|
||||
#include "tools/toolhandle.h"
|
||||
|
@ -36,6 +37,7 @@
|
|||
#include "toonz/tproject.h"
|
||||
#include "toonz/namebuilder.h"
|
||||
#include "toonz/childstack.h"
|
||||
#include "toutputproperties.h"
|
||||
|
||||
// TnzCore includes
|
||||
#include "tsystem.h"
|
||||
|
@ -180,6 +182,10 @@ LevelCreatePopup::LevelCreatePopup()
|
|||
m_dpiLabel = new QLabel(tr("DPI:"));
|
||||
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 *cancelBtn = new QPushButton(tr("Cancel"), 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_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);
|
||||
|
||||
//--- layout
|
||||
|
@ -247,15 +258,21 @@ LevelCreatePopup::LevelCreatePopup()
|
|||
Qt::AlignRight | Qt::AlignVCenter);
|
||||
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
|
||||
guiLay->addWidget(m_widthLabel, 5, 0, Qt::AlignRight | Qt::AlignVCenter);
|
||||
guiLay->addWidget(m_widthFld, 5, 1);
|
||||
guiLay->addWidget(m_heightLabel, 5, 2, Qt::AlignRight | Qt::AlignVCenter);
|
||||
guiLay->addWidget(m_heightFld, 5, 3);
|
||||
guiLay->addWidget(m_widthLabel, 6, 0, Qt::AlignRight | Qt::AlignVCenter);
|
||||
guiLay->addWidget(m_widthFld, 6, 1);
|
||||
guiLay->addWidget(m_heightLabel, 6, 2, Qt::AlignRight | Qt::AlignVCenter);
|
||||
guiLay->addWidget(m_heightFld, 6, 3);
|
||||
|
||||
// DPI
|
||||
guiLay->addWidget(m_dpiLabel, 6, 0, Qt::AlignRight | Qt::AlignVCenter);
|
||||
guiLay->addWidget(m_dpiFld, 6, 1, 1, 3);
|
||||
guiLay->addWidget(m_dpiLabel, 7, 0, Qt::AlignRight | Qt::AlignVCenter);
|
||||
guiLay->addWidget(m_dpiFld, 7, 1);
|
||||
}
|
||||
guiLay->setColumnStretch(0, 0);
|
||||
guiLay->setColumnStretch(1, 0);
|
||||
|
@ -280,12 +297,15 @@ LevelCreatePopup::LevelCreatePopup()
|
|||
bool ret = true;
|
||||
ret = ret && connect(m_levelTypeOm, SIGNAL(currentIndexChanged(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(cancelBtn, SIGNAL(clicked()), this, SLOT(reject()));
|
||||
ret =
|
||||
ret && connect(applyBtn, SIGNAL(clicked()), this, SLOT(onApplyButton()));
|
||||
|
||||
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 {
|
||||
return m_levelTypeOm->currentData().toInt();
|
||||
}
|
||||
|
@ -389,6 +418,9 @@ void LevelCreatePopup::onLevelTypeChanged(int index) {
|
|||
setSizeWidgetEnable(true);
|
||||
else
|
||||
setSizeWidgetEnable(false);
|
||||
|
||||
// setRasterWidgetVisible(type == OVL_XSHLEVEL || type == TZI_XSHLEVEL);
|
||||
|
||||
updatePath();
|
||||
|
||||
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() {
|
||||
TApp *app = TApp::instance();
|
||||
int row = app->getCurrentFrame()->getFrame();
|
||||
|
@ -499,6 +542,10 @@ bool LevelCreatePopup::apply() {
|
|||
TFilePath fp =
|
||||
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);
|
||||
bool fileExists = TSystem::doesExistFileOrLevel(actualFp);
|
||||
if (!fileExists) {
|
||||
|
@ -607,7 +654,6 @@ bool LevelCreatePopup::apply() {
|
|||
|
||||
for (i = from; i <= to; i += inc) {
|
||||
TFrameId fid(i);
|
||||
TXshCell cell(sl, fid);
|
||||
if (lType == PLI_XSHLEVEL)
|
||||
sl->setFrame(fid, new TVectorImage());
|
||||
else if (lType == TZP_XSHLEVEL) {
|
||||
|
@ -622,8 +668,12 @@ bool LevelCreatePopup::apply() {
|
|||
raster->clear();
|
||||
TRasterImageP ri(raster);
|
||||
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);
|
||||
}
|
||||
TXshCell cell(sl, fid);
|
||||
for (j = 0; j < step; j++) xsh->setCell(row++, col, cell);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,10 +34,16 @@ class LevelCreatePopup final : public DVGui::Dialog {
|
|||
DVGui::MeasuredDoubleLineEdit *m_heightFld;
|
||||
DVGui::DoubleLineEdit *m_dpiFld;
|
||||
|
||||
QLabel *m_rasterFormatLabel;
|
||||
QComboBox *m_rasterFormatOm;
|
||||
QPushButton *m_frameFormatBtn;
|
||||
|
||||
public:
|
||||
LevelCreatePopup();
|
||||
|
||||
void setSizeWidgetEnable(bool isEnable);
|
||||
void setRasterWidgetVisible(bool isVisible);
|
||||
|
||||
int getLevelType() const;
|
||||
|
||||
void update();
|
||||
|
@ -55,6 +61,7 @@ public slots:
|
|||
void onOkBtn();
|
||||
|
||||
void onApplyButton();
|
||||
void onFrameFormatButton();
|
||||
};
|
||||
|
||||
#endif // LEVELCREATEPOPUP_H
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "tenv.h"
|
||||
#include "tsystem.h"
|
||||
#include "tstream.h"
|
||||
#include "tfiletype.h"
|
||||
|
||||
// Qt includes
|
||||
#include <QLabel>
|
||||
|
@ -145,6 +146,13 @@ enum ThreadsOption {
|
|||
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
@ -1238,10 +1246,10 @@ void OutputSettingsPopup::onNameChanged() {
|
|||
TOutputProperties *prop = getProperties();
|
||||
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(fp);
|
||||
prop->setPath(newFp);
|
||||
|
||||
TApp::instance()->getCurrentScene()->setDirtyFlag(true);
|
||||
|
||||
|
@ -1258,10 +1266,14 @@ void OutputSettingsPopup::onFormatChanged(const QString &str) {
|
|||
ext == "spritesheet";
|
||||
};
|
||||
|
||||
TOutputProperties *prop = getProperties();
|
||||
TOutputProperties *prop = getProperties();
|
||||
bool wasMultiRenderInvalid =
|
||||
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);
|
||||
TApp::instance()->getCurrentScene()->setDirtyFlag(true);
|
||||
m_allowMT = Preferences::instance()->getFfmpegMultiThread();
|
||||
|
@ -1292,9 +1304,25 @@ void OutputSettingsPopup::onFormatChanged(const QString &str) {
|
|||
void OutputSettingsPopup::openSettingsPopup() {
|
||||
TOutputProperties *prop = getProperties();
|
||||
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 (oldTmplFId.getZeroPadding() !=
|
||||
prop->formatTemplateFId().getZeroPadding() ||
|
||||
oldTmplFId.getStartSeqInd() !=
|
||||
prop->formatTemplateFId().getStartSeqInd()) {
|
||||
TFilePath fp =
|
||||
prop->getPath().withNoFrame().withFrame(prop->formatTemplateFId());
|
||||
prop->setPath(fp);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "levelsettingspopup.h"
|
||||
#include "tapp.h"
|
||||
#include "cleanupsettingsmodel.h"
|
||||
#include "formatsettingspopups.h"
|
||||
#include "tenv.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
|
@ -29,6 +30,7 @@
|
|||
#include "toonz/toonzscene.h"
|
||||
#include "toonz/tcamera.h"
|
||||
#include "toonz/levelproperties.h"
|
||||
#include "toonz/sceneproperties.h"
|
||||
#include "toonz/tonionskinmaskhandle.h"
|
||||
#include "toonz/stage.h"
|
||||
#include "toonz/toonzfolders.h"
|
||||
|
@ -785,6 +787,17 @@ void PreferencesPopup::onCheck30bitDisplay() {
|
|||
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() {
|
||||
|
@ -1011,15 +1024,26 @@ void PreferencesPopup::insertUI(PreferencesItemId id, QGridLayout* layout,
|
|||
|
||||
// CheckBox contains label in itself
|
||||
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
|
||||
int row = layout->rowCount();
|
||||
layout->addWidget(new QLabel(getUIString(id), this), row, 0,
|
||||
Qt::AlignRight | Qt::AlignVCenter);
|
||||
if (isFileField)
|
||||
layout->addWidget(widget, row, 1, 1, 2);
|
||||
else
|
||||
layout->addWidget(widget, row, 1, Qt::AlignLeft | Qt::AlignVCenter);
|
||||
else {
|
||||
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(
|
||||
tr("* Changes will take effect the next time you run Tahoma2D"));
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1148,7 +1172,8 @@ QString PreferencesPopup::getUIString(PreferencesItemId id) {
|
|||
{rhubarbTimeout, tr("Analyze Audio Timeout (seconds):")},
|
||||
|
||||
// Drawing
|
||||
{scanLevelType, tr("Scan File Format:")},
|
||||
{DefRasterFormat, tr("Default Raster Level Format:")},
|
||||
//{scanLevelType, tr("Scan File Format:")},
|
||||
{DefLevelType, tr("Default Level Type:")},
|
||||
{newLevelSizeToCameraSizeEnabled,
|
||||
tr("New Levels Default to the Current Camera Size")},
|
||||
|
@ -1229,7 +1254,7 @@ QString PreferencesPopup::getUIString(PreferencesItemId id) {
|
|||
{blanksCount, tr("Blank Frames:")},
|
||||
{blankColor, tr("Blank Frames Color:")},
|
||||
{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")},
|
||||
{fitToFlipbook, tr("Fit to Flipbook")},
|
||||
{generatedMovieViewEnabled, tr("Open Flipbook after Rendering")},
|
||||
|
@ -1316,7 +1341,8 @@ QList<ComboBoxItem> PreferencesPopup::getComboItemList(
|
|||
{columnIconLoadingPolicy,
|
||||
{{tr("At Once"), Preferences::LoadAtOnce},
|
||||
{tr("On Demand"), Preferences::LoadOnDemand}}},
|
||||
{scanLevelType, {{"tif", "tif"}, {"png", "png"}}},
|
||||
{DefRasterFormat, {{"tif", "tif"}, {"png", "png"}}},
|
||||
//{scanLevelType, {{"tif", "tif"}, {"png", "png"}}},
|
||||
{DefLevelType,
|
||||
{{tr("Vector Level"), PLI_XSHLEVEL},
|
||||
{tr("Smart Raster Level"), TZP_XSHLEVEL},
|
||||
|
@ -1574,7 +1600,7 @@ QWidget* PreferencesPopup::createInterfacePage() {
|
|||
|
||||
// lay->addWidget(new QLabel(tr("Pixels Only:"), this), 5, 0,
|
||||
// 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(functionEditorToggle, lay, getComboItemList(functionEditorToggle));
|
||||
|
@ -1593,7 +1619,7 @@ QWidget* PreferencesPopup::createInterfacePage() {
|
|||
#if QT_VERSION >= 0x051000
|
||||
insertUI(displayIn30bit, lay);
|
||||
row = lay->rowCount();
|
||||
lay->addWidget(check30bitBtn, row - 1, 3);
|
||||
lay->addWidget(check30bitBtn, row - 1, 2, Qt::AlignRight);
|
||||
#endif
|
||||
// insertUI(showIconsInMenu, lay);
|
||||
|
||||
|
@ -1760,7 +1786,7 @@ QWidget* PreferencesPopup::createImportExportPage() {
|
|||
insertUI(ffmpegTimeout, ffmpegOptionsLay);
|
||||
|
||||
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:"),
|
||||
ffmpegOptionsLay);
|
||||
insertUI(ffmpegMultiThread, ffmpegOptionsLay);
|
||||
|
@ -1783,10 +1809,15 @@ QWidget* PreferencesPopup::createImportExportPage() {
|
|||
QWidget* PreferencesPopup::createDrawingPage() {
|
||||
QWidget* widget = new QWidget(this);
|
||||
QGridLayout* lay = new QGridLayout();
|
||||
|
||||
QPushButton* frameFormatBtn = new QPushButton(tr("Default Frame Filename Format"));
|
||||
|
||||
setupLayout(lay);
|
||||
|
||||
// insertUI(scanLevelType, lay, getComboItemList(scanLevelType));
|
||||
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);
|
||||
insertDualUIs(DefLevelWidth, DefLevelHeight, lay);
|
||||
// insertUI(DefLevelDpi, lay);
|
||||
|
@ -1829,6 +1860,9 @@ QWidget* PreferencesPopup::createDrawingPage() {
|
|||
getUI<MeasuredDoubleLineEdit*>(DefLevelHeight)->setDecimals(0);
|
||||
//}
|
||||
|
||||
bool ret = ret && connect(frameFormatBtn, SIGNAL(clicked()), this,
|
||||
SLOT(onFrameFormatButton()));
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
|
|
|
@ -179,6 +179,7 @@ private slots:
|
|||
void onInterfaceFontChanged(const QString& text);
|
||||
void onLutPathChanged();
|
||||
void onCheck30bitDisplay();
|
||||
void onFrameFormatButton();
|
||||
|
||||
void onAddLevelFormat();
|
||||
void onRemoveLevelFormat();
|
||||
|
|
|
@ -800,8 +800,7 @@ SceneViewer::SceneViewer(ImageUtils::FullScreenWidget *parent)
|
|||
, m_mousePanning(0)
|
||||
, m_mouseZooming(0)
|
||||
, m_mouseRotating(0)
|
||||
, m_keyAction(0)
|
||||
, m_timer(nullptr) {
|
||||
, m_keyAction(0) {
|
||||
m_visualSettings.m_sceneProperties =
|
||||
TApp::instance()->getCurrentScene()->getScene()->getProperties();
|
||||
m_stopMotion = StopMotion::instance();
|
||||
|
@ -2053,14 +2052,6 @@ void SceneViewer::paintGL() {
|
|||
|
||||
if (!m_isPicking && m_lutCalibrator && m_lutCalibrator->isValid())
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -219,10 +219,6 @@ class SceneViewer final : public GLWidgetForHighDpi,
|
|||
|
||||
QAction *m_keyAction;
|
||||
|
||||
// passed from PlaybackExecutor
|
||||
QElapsedTimer *m_timer;
|
||||
qint64 m_targetInstant;
|
||||
|
||||
public:
|
||||
enum ReferenceMode {
|
||||
NORMAL_REFERENCE = 1,
|
||||
|
@ -331,11 +327,6 @@ public:
|
|||
void setPreviewBGColor(const QColor &color) { m_previewBgColor = color; }
|
||||
QColor getPreviewBGColor() const { return m_previewBgColor; }
|
||||
|
||||
void setTimerAndTargetInstant(QElapsedTimer *timer, qint64 target) {
|
||||
m_timer = timer;
|
||||
m_targetInstant = target;
|
||||
}
|
||||
|
||||
public:
|
||||
// SceneViewer's gadget public functions
|
||||
TPointD winToWorld(const QPointF &pos) const;
|
||||
|
|
|
@ -276,10 +276,9 @@ void SceneViewerPanel::onShowHideActionTriggered(QAction *act) {
|
|||
|
||||
void SceneViewerPanel::onDrawFrame(int frame,
|
||||
const ImagePainter::VisualSettings &settings,
|
||||
QElapsedTimer *timer, qint64 targetInstant) {
|
||||
QElapsedTimer *, qint64) {
|
||||
TApp *app = TApp::instance();
|
||||
m_sceneViewer->setVisual(settings);
|
||||
m_sceneViewer->setTimerAndTargetInstant(timer, targetInstant);
|
||||
|
||||
TFrameHandle *frameHandle = app->getCurrentFrame();
|
||||
|
||||
|
@ -314,10 +313,6 @@ void SceneViewerPanel::onDrawFrame(int frame,
|
|||
|
||||
else if (settings.m_blankColor != TPixel::Transparent)
|
||||
m_sceneViewer->update();
|
||||
|
||||
// make sure to redraw the frame here.
|
||||
// repaint() does NOT immediately redraw the frame for QOpenGLWidget
|
||||
if (frameHandle->isPlaying()) qApp->processEvents();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -551,6 +551,8 @@ bool XdtsIo::loadXdtsScene(ToonzScene *scene, const TFilePath &scenePath) {
|
|||
int tick1Id, tick2Id;
|
||||
popup.getMarkerIds(tick1Id, tick2Id);
|
||||
|
||||
TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput();
|
||||
|
||||
TXsheet *xsh = scene->getXsheet();
|
||||
XdtsTimeTableFieldItem cellField = xdtsData.timeTable().getCellField();
|
||||
XdtsTimeTableHeaderItem cellHeader = xdtsData.timeTable().getCellHeader();
|
||||
|
@ -558,8 +560,9 @@ bool XdtsIo::loadXdtsScene(ToonzScene *scene, const TFilePath &scenePath) {
|
|||
QStringList layerNames = cellHeader.getLayerNames();
|
||||
QList<int> columns = cellField.getOccupiedColumns();
|
||||
for (int column : columns) {
|
||||
QString levelName = layerNames.at(column);
|
||||
TXshLevel *level = levels.value(levelName);
|
||||
QString levelName = layerNames.at(column);
|
||||
TXshLevel *level = levels.value(levelName);
|
||||
TXshSimpleLevel *sl = level->getSimpleLevel();
|
||||
QList<int> 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) {
|
||||
if (fid.getNumber() == -1) // EMPTY cell case
|
||||
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));
|
||||
}
|
||||
}
|
||||
// if the last cell is not "SYMBOL_NULL_CELL", continue the cell
|
||||
// to the end of the sheet
|
||||
TFrameId lastFid = track.last();
|
||||
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++)
|
||||
xsh->setCell(row, column, TXshCell(level, TFrameId(lastFid)));
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
getCells(m_cells, r0, c0);
|
||||
getColumnsData(c0, c1);
|
||||
|
||||
if (m_qualifiers & eInsertCells && !(m_qualifiers & eOverwriteCells))
|
||||
getImplicitCellInfo();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -83,6 +86,46 @@ TXsheet *CellsMover::getXsheet() const {
|
|||
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
|
||||
//
|
||||
|
@ -152,21 +195,25 @@ void CellsMover::moveCells(const TPoint &pos) const {
|
|||
int startCol =
|
||||
(m_orientation->isVerticalTimeline()) ? m_startPos.x : m_startPos.y;
|
||||
if (startCol == c) {
|
||||
int infoId = 0;
|
||||
for (int i = 0; i < m_colCount; i++) {
|
||||
TXshColumn *column = xsh->getColumn(c + i);
|
||||
if (!column || column->getCellColumn() == 0 || column->isLocked())
|
||||
continue;
|
||||
// a cell above inserted cells
|
||||
TXshCell upperCell = xsh->getCell(r - 1, c + i);
|
||||
if (upperCell.isEmpty()) continue;
|
||||
|
||||
QMap<int, TXshCell>::const_iterator itr =
|
||||
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
|
||||
TXshCell bottomCell = xsh->getCell(r + m_rowCount - 1, c + i);
|
||||
if (bottomCell.isEmpty()) continue;
|
||||
int tmp_r = r + m_rowCount;
|
||||
while (xsh->getCell(tmp_r, c + i) == upperCell) {
|
||||
for (int tmp_r = r + m_rowCount; tmp_r <= itr.key() - 1 + m_rowCount;
|
||||
tmp_r++)
|
||||
xsh->setCell(tmp_r, c + i, bottomCell);
|
||||
tmp_r++;
|
||||
}
|
||||
|
||||
infoId++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -180,6 +227,7 @@ void CellsMover::undoMoveCells(const TPoint &pos) const {
|
|||
r = pos.x;
|
||||
c = pos.y;
|
||||
}
|
||||
|
||||
if (m_qualifiers & eInsertCells) {
|
||||
// Act like implicit hold when dragging cells with pressing Shift key
|
||||
// ( and WITHOUT Alt key ) and dragging within the same column.
|
||||
|
@ -187,19 +235,27 @@ void CellsMover::undoMoveCells(const TPoint &pos) const {
|
|||
int startCol =
|
||||
(m_orientation->isVerticalTimeline()) ? m_startPos.x : m_startPos.y;
|
||||
if (startCol == c) {
|
||||
int infoId = 0;
|
||||
for (int i = 0; i < m_colCount; i++) {
|
||||
// a cell above selected cells
|
||||
TXshCell upperCell = xsh->getCell(r - 1, c + i);
|
||||
if (upperCell.isEmpty()) continue;
|
||||
// a cell at the bottom of the selected cells
|
||||
TXshCell bottomCell = xsh->getCell(r + m_rowCount - 1, c + i);
|
||||
if (bottomCell.isEmpty()) continue;
|
||||
int tmp_r = r + m_rowCount;
|
||||
while (xsh->getCell(tmp_r, c + i) == bottomCell) {
|
||||
xsh->setCell(tmp_r, c + i, upperCell);
|
||||
tmp_r++;
|
||||
TXshColumn *column = xsh->getColumn(c + i);
|
||||
if (!column || column->getCellColumn() == 0 || column->isLocked())
|
||||
continue;
|
||||
|
||||
// clear the cells and restore original arrangement
|
||||
TXshCellColumn *cellCol = column->getCellColumn();
|
||||
int r0, r1;
|
||||
cellCol->getRange(r0, r1);
|
||||
cellCol->clearCells(r0, r1 - r0 + 1);
|
||||
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);
|
||||
if (!m_validPos) return;
|
||||
if (m_moved) cellsMover->undoMoveCells();
|
||||
if (m_moved) {
|
||||
cellsMover->undoMoveCells();
|
||||
}
|
||||
m_validPos = canMove(pos);
|
||||
|
||||
if (m_validPos) {
|
||||
|
|
|
@ -33,6 +33,9 @@ class CellsMover {
|
|||
|
||||
const Orientation *m_orientation;
|
||||
|
||||
// keeping the implicit cell arrangement when start shift + dragging
|
||||
QList<QMap<int, TXshCell>> m_implicitCellInfo;
|
||||
|
||||
// helper method
|
||||
TXsheet *getXsheet() const;
|
||||
|
||||
|
@ -45,6 +48,8 @@ class CellsMover {
|
|||
// m_columnsData <- xsheet columns data
|
||||
void getColumnsData(int c0, int c1);
|
||||
|
||||
void getImplicitCellInfo();
|
||||
|
||||
public:
|
||||
enum Qualifier {
|
||||
eCopyCells = 0x1, // leaves a copy of cells block at the starting point
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "toonz/doubleparamcmd.h"
|
||||
#include "toonz/preferences.h"
|
||||
#include "toonz/palettecontroller.h"
|
||||
#include "toutputproperties.h"
|
||||
|
||||
// TnzBase includes
|
||||
#include "tdoublekeyframe.h"
|
||||
|
@ -892,6 +893,9 @@ void RenameCellField::renameCell() {
|
|||
TApp::instance()->getCurrentSelection()->getSelection());
|
||||
if (!cellSelection) return;
|
||||
|
||||
ToonzScene *scene = m_viewer->getXsheet()->getScene();
|
||||
TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput();
|
||||
|
||||
QList<TXshCell> cells;
|
||||
bool hasFrameZero = false;
|
||||
|
||||
|
@ -929,15 +933,20 @@ void RenameCellField::renameCell() {
|
|||
}
|
||||
}
|
||||
|
||||
TXshLevel *xl = cell.m_level.getPointer();
|
||||
if (!xl || (xl->getSimpleLevel() && !xl->getSimpleLevel()->isEmpty() &&
|
||||
xl->getSimpleLevel()->getFirstFid() == TFrameId::NO_FRAME)) {
|
||||
TXshLevel *xl = cell.m_level.getPointer();
|
||||
TXshSimpleLevel *sl = (xl) ? xl->getSimpleLevel() : nullptr;
|
||||
if (!xl ||
|
||||
(sl && !sl->isEmpty() && sl->getFirstFid() == TFrameId::NO_FRAME)) {
|
||||
cells.append(TXshCell());
|
||||
continue;
|
||||
}
|
||||
// if the next upper cell is empty, then make this cell empty too
|
||||
if (fid == TFrameId::NO_FRAME)
|
||||
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));
|
||||
changed = true;
|
||||
hasFrameZero = (fid.getNumber() == 0 && xl->getSimpleLevel() &&
|
||||
|
@ -945,7 +954,6 @@ void RenameCellField::renameCell() {
|
|||
}
|
||||
if (!changed) return;
|
||||
} else {
|
||||
ToonzScene *scene = m_viewer->getXsheet()->getScene();
|
||||
TLevelSet *levelSet = scene->getLevelSet();
|
||||
TXshLevel *xl = levelSet->getLevel(levelName);
|
||||
if (!xl && fid != TFrameId::NO_FRAME) {
|
||||
|
@ -954,8 +962,11 @@ void RenameCellField::renameCell() {
|
|||
int levelType = pref->getDefLevelType();
|
||||
xl = scene->createNewLevel(levelType, levelName);
|
||||
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());
|
||||
}
|
||||
if (levelType == TZP_XSHLEVEL || levelType == PLI_XSHLEVEL) {
|
||||
TPalette *defaultPalette =
|
||||
TApp::instance()->getPaletteController()->getDefaultPalette(
|
||||
|
@ -966,6 +977,10 @@ void RenameCellField::renameCell() {
|
|||
xl = scene->createNewLevel(TZI_XSHLEVEL, levelName);
|
||||
}
|
||||
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));
|
||||
hasFrameZero = (fid.getNumber() == 0 && xl->getSimpleLevel() &&
|
||||
xl->getSimpleLevel()->isFid(fid));
|
||||
|
|
|
@ -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_inputLevel(0)
|
||||
, m_imageInfo(0)
|
||||
, m_currIdx(0)
|
||||
, m_opened(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);
|
||||
|
||||
// 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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -276,7 +276,8 @@ void MovieRenderer::Imp::prepareForStart() {
|
|||
locals::eraseUncompatibleExistingLevel(m_fp, cameraResI);
|
||||
|
||||
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);
|
||||
} else {
|
||||
TFilePath leftFp = m_fp.withName(m_fp.getName() + "_l");
|
||||
|
@ -286,11 +287,13 @@ void MovieRenderer::Imp::prepareForStart() {
|
|||
locals::eraseUncompatibleExistingLevel(rightFp, cameraResI);
|
||||
|
||||
m_levelUpdaterA.reset(new LevelUpdater(
|
||||
leftFp, oprop->getFileFormatProperties(leftFp.getType())));
|
||||
leftFp, oprop->getFileFormatProperties(leftFp.getType()),
|
||||
oprop->formatTemplateFId()));
|
||||
m_levelUpdaterA->getLevelWriter()->setFrameRate(frameRate);
|
||||
|
||||
m_levelUpdaterB.reset(new LevelUpdater(
|
||||
rightFp, oprop->getFileFormatProperties(rightFp.getType())));
|
||||
rightFp, oprop->getFileFormatProperties(rightFp.getType()),
|
||||
oprop->formatTemplateFId()));
|
||||
m_levelUpdaterB->getLevelWriter()->setFrameRate(frameRate);
|
||||
}
|
||||
} 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
|
||||
// prevent another
|
||||
// thread from interfering
|
||||
double frame = ft->first;
|
||||
double frame = ft->first;
|
||||
std::pair<TRasterP, TRasterP> rasters = ft->second;
|
||||
|
||||
++m_nextFrameIdxToSave;
|
||||
|
|
|
@ -41,7 +41,8 @@ TOutputProperties::TOutputProperties()
|
|||
, m_maxTileSizeIndex(0)
|
||||
, m_threadIndex(2)
|
||||
, m_subcameraPreview(false)
|
||||
, m_boardSettings(new BoardSettings()) {
|
||||
, m_boardSettings(new BoardSettings())
|
||||
, m_formatTemplateFId() {
|
||||
m_renderSettings = new TRenderSettings();
|
||||
}
|
||||
|
||||
|
@ -61,7 +62,8 @@ TOutputProperties::TOutputProperties(const TOutputProperties &src)
|
|||
, m_maxTileSizeIndex(src.m_maxTileSizeIndex)
|
||||
, m_threadIndex(src.m_threadIndex)
|
||||
, 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,
|
||||
fEnd = m_formatProperties.end();
|
||||
for (ft = m_formatProperties.begin(); ft != fEnd; ++ft) {
|
||||
|
@ -108,6 +110,8 @@ TOutputProperties &TOutputProperties::operator=(const TOutputProperties &src) {
|
|||
delete m_boardSettings;
|
||||
m_boardSettings = new BoardSettings(*src.m_boardSettings);
|
||||
|
||||
m_formatTemplateFId = src.m_formatTemplateFId;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "tconvert.h"
|
||||
#include "tundo.h"
|
||||
#include "tbigmemorymanager.h"
|
||||
#include "tfilepath.h"
|
||||
#include "timage_io.h"
|
||||
|
||||
// Qt includes
|
||||
|
@ -501,7 +500,8 @@ void Preferences::definePreferenceItems() {
|
|||
std::numeric_limits<int>::max());
|
||||
|
||||
// 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(newLevelSizeToCameraSizeEnabled, "newLevelSizeToCameraSizeEnabled",
|
||||
QMetaType::Bool, true);
|
||||
|
@ -788,6 +788,12 @@ void Preferences::resolveCompatibility() {
|
|||
else // Default (level name on top of each cell block)
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
|
|
@ -313,6 +313,16 @@ void TSceneProperties::saveData(TOStream &os) const {
|
|||
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();
|
||||
|
@ -680,6 +690,20 @@ void TSceneProperties::loadData(TIStream &is, bool isLoadingProject) {
|
|||
} else if (tagName == "clapperboardSettings") {
|
||||
assert(out.getBoardSettings());
|
||||
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 {
|
||||
throw TException("unexpected property tag: " + tagName);
|
||||
}
|
||||
|
@ -835,4 +859,11 @@ bool TSceneProperties::hasDefaultCellMarks() const {
|
|||
return false;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -1376,21 +1376,20 @@ TFilePath ToonzScene::getDefaultLevelPath(int levelType,
|
|||
TProject *project = getProject();
|
||||
assert(project);
|
||||
TFilePath levelPath;
|
||||
QString scanLevelType;
|
||||
switch (levelType) {
|
||||
case TZI_XSHLEVEL:
|
||||
scanLevelType = Preferences::instance()->getScanLevelType();
|
||||
levelPath = TFilePath(levelName + L".." + scanLevelType.toStdWString());
|
||||
break;
|
||||
case OVL_XSHLEVEL: {
|
||||
QString rasterLevelType = Preferences::instance()->getDefRasterFormat();
|
||||
TFrameId tmplFId = getProperties()->formatTemplateFIdForInput();
|
||||
levelPath = TFilePath(levelName + L"." + rasterLevelType.toStdWString())
|
||||
.withFrame(tmplFId);
|
||||
} break;
|
||||
case PLI_XSHLEVEL:
|
||||
levelPath = TFilePath(levelName).withType("pli");
|
||||
break;
|
||||
case TZP_XSHLEVEL:
|
||||
levelPath = TFilePath(levelName).withType("tlv");
|
||||
break;
|
||||
case OVL_XSHLEVEL:
|
||||
levelPath = TFilePath(levelName + L"..tif");
|
||||
break;
|
||||
default:
|
||||
levelPath = TFilePath(levelName + L"..png");
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "tstream.h"
|
||||
#include "tsystem.h"
|
||||
#include "tcontenthistory.h"
|
||||
#include "tfilepath.h"
|
||||
|
||||
// Qt includes
|
||||
#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) {
|
||||
assert(m_type != UNKNOWN_XSHLEVEL);
|
||||
|
||||
|
|
|
@ -490,7 +490,7 @@ ColorField::ColorField(QWidget *parent, bool isAlphaActive, TPixel32 color,
|
|||
*/
|
||||
|
||||
void ColorField::setAlphaActive(bool active) {
|
||||
if (active && !m_alphaChannel->isVisible()) {
|
||||
if (active && !m_alphaChannel->isVisibleTo(this)) {
|
||||
m_alphaChannel->show();
|
||||
connect(m_alphaChannel, SIGNAL(valueChanged(int, bool)),
|
||||
SLOT(onAlphaChannelChanged(int, bool)));
|
||||
|
@ -499,7 +499,7 @@ void ColorField::setAlphaActive(bool active) {
|
|||
m_color.m = 0;
|
||||
m_colorSample->setColor(m_color);
|
||||
emit colorChanged(m_color, false);
|
||||
} else if (!active && m_alphaChannel->isVisible()) {
|
||||
} else if (!active && m_alphaChannel->isVisibleTo(this)) {
|
||||
m_alphaChannel->hide();
|
||||
disconnect(m_alphaChannel, SIGNAL(valueChanged(int, bool)), this,
|
||||
SLOT(onAlphaChannelChanged(int, bool)));
|
||||
|
|
|
@ -220,10 +220,19 @@ void PlaybackExecutor::run() {
|
|||
shortTermDelayAdjuster -= delayAdjust;
|
||||
|
||||
// Show the next frame, telling currently measured fps
|
||||
// The wait time will be inserted at the end of paintGL in order to
|
||||
// achieve precise playback
|
||||
// For the Flipbook, the wait time will be inserted at the end of paintGL
|
||||
// in order to achieve precise playback
|
||||
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) {
|
||||
// In case there are linked consoles, update them too.
|
||||
// Their load time must be included in the fps calculation.
|
||||
|
|
|
@ -592,7 +592,8 @@ static void convertFromVector(const TLevelReaderP &lr, const TLevelWriterP &lw,
|
|||
void convert(const TFilePath &source, const TFilePath &dest,
|
||||
const TFrameId &from, const TFrameId &to, double framerate,
|
||||
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();
|
||||
|
||||
// Load source level structure
|
||||
|
@ -621,6 +622,7 @@ void convert(const TFilePath &source, const TFilePath &dest,
|
|||
// Write the destination level
|
||||
TLevelWriterP lw(dest, prop);
|
||||
lw->setFrameRate(framerate);
|
||||
lw->setFrameFormatTemplateFId(tmplFId);
|
||||
|
||||
if (srcExt == "tlv")
|
||||
convertFromCM(lr, level->getPalette(), lw, frames, TAffine(),
|
||||
|
|
|
@ -4240,6 +4240,10 @@ QFrame *StyleEditor::createBottomWidget() {
|
|||
m_plainColorPage->m_rgbFrame->setVisible(false);
|
||||
|
||||
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);
|
||||
menu->addAction(m_hexEditorAction);
|
||||
|
||||
|
@ -4258,14 +4262,6 @@ QFrame *StyleEditor::createBottomWidget() {
|
|||
|
||||
// QToolBar *displayToolbar = new QToolBar(this);
|
||||
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->setMaximumHeight(22);
|
||||
m_toolBar->setIconSize(QSize(16, 16));
|
||||
|
|
Loading…
Reference in a new issue