Merge pull request #911 from manongjohn/ot_patches_20220220

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

View file

@ -1706,6 +1706,15 @@ ProjectPopup QLabel {
padding-left: 5px;
padding-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
----------------------------------------------------------------------------- */

View file

@ -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
----------------------------------------------------------------------------- */

View file

@ -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
----------------------------------------------------------------------------- */

View file

@ -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
----------------------------------------------------------------------------- */

View file

@ -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);
}

View file

@ -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
----------------------------------------------------------------------------- */

View file

@ -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;

View file

@ -573,6 +573,36 @@ std::string TFilePath::getDots() const {
//-----------------------------------------------------------------------------
QChar TFilePath::getSepChar() const {
if (!TFilePath::m_useStandard) return analyzePath().sepChar;
//-----
QString type = QString::fromStdString(getType()).toLower();
if (isFfmpegType()) return QChar();
int i = getLastSlash(m_path);
std::wstring str = m_path.substr(i + 1);
// potrei anche avere a.b.c.d dove d e' l'estensione
i = str.rfind(L".");
if (i == (int)std::wstring::npos || str == L"..") return QChar();
int j = str.substr(0, i).rfind(L".");
if (j != (int)std::wstring::npos)
return (j == i - 1 || (checkForSeqNum(type) && isNumbers(str, j, i)))
? QChar('.')
: QChar();
if (!m_underscoreFormatAllowed) return QChar();
j = str.substr(0, i).rfind(L"_");
if (j != (int)std::wstring::npos)
return (j == i - 1 || (checkForSeqNum(type) && isNumbers(str, j, i)))
? QChar('_')
: QChar();
else
return QChar();
}
//-----------------------------------------------------------------------------
std::string TFilePath::getDottedType()
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)) + "." +

View file

@ -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)

View file

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

View file

@ -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;
}
};
//-----------------------------------------------------------

View file

@ -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

View file

@ -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);

View file

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

View file

@ -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 &);

View file

@ -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,

View file

@ -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.

View file

@ -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; }
};
//--------------------------------------------

View file

@ -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 &param, 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 &param) {
@ -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
}

View file

@ -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;

View file

@ -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) {

View file

@ -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);

View file

@ -1440,7 +1440,16 @@ void TypeTool::replaceText(std::wstring text, int from, int to) {
for (unsigned int i = 0; i < (unsigned int)text.size(); i++) {
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);

View file

@ -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();

View file

@ -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();
}
//-----------------------------------------------------------------------------

View file

@ -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());
}

View file

@ -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

View file

@ -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

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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);
}
}
//-----------------------------------------------------------------------------

View file

@ -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;
}

View file

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

View file

@ -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();
}
}
}
//-----------------------------------------------------------------------------

View file

@ -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;

View file

@ -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();
}
//-----------------------------------------------------------------------------

View file

@ -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)));
}

View file

@ -74,6 +74,9 @@ void CellsMover::start(int r0, int c0, int r1, int c1, int qualifiers,
m_oldCells.resize(m_rowCount * m_colCount, TXshCell());
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) {

View file

@ -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

View file

@ -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));

View file

@ -94,14 +94,15 @@ LevelUpdater::LevelUpdater(TXshSimpleLevel *sl)
//-----------------------------------------------------------------------------
LevelUpdater::LevelUpdater(const TFilePath &fp, TPropertyGroup *lwProperties)
LevelUpdater::LevelUpdater(const TFilePath &fp, TPropertyGroup *lwProperties,
const TFrameId &tmplFId)
: m_pg(0)
, m_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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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());
}
}
//-----------------------------------------------------------------

View file

@ -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();
}

View file

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

View file

@ -1376,21 +1376,20 @@ TFilePath ToonzScene::getDefaultLevelPath(int levelType,
TProject *project = getProject();
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");
}

View file

@ -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);

View file

@ -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)));

View file

@ -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.

View file

@ -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(),

View file

@ -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));