Merge pull request #848 from manongjohn/ot_patches_20211222
OpenToonz patches thru 12/22
This commit is contained in:
commit
119de0256f
97 changed files with 4021 additions and 1119 deletions
|
@ -73,7 +73,7 @@ inline QString blanks(const QString &str, int count = 15) {
|
|||
//--------------------------------------------------------------------
|
||||
|
||||
inline QString getStr(const TFrameId &id) {
|
||||
if (id.getLetter() != 0)
|
||||
if (!id.getLetter().isEmpty())
|
||||
return QString::number(id.getNumber()) + id.getLetter();
|
||||
else
|
||||
return QString::number(id.getNumber());
|
||||
|
@ -159,7 +159,7 @@ const QString TContentHistory::currentToString() const {
|
|||
dateSorted.insert(pair<QDateTime, TFrameId>(it->second, it->first));
|
||||
|
||||
std::multimap<QDateTime, TFrameId>::const_iterator it1 = dateSorted.begin();
|
||||
QDateTime currDate = it1->first;
|
||||
QDateTime currDate = it1->first;
|
||||
|
||||
while (it1 != dateSorted.end()) {
|
||||
set<TFrameId> frames;
|
||||
|
|
|
@ -132,6 +132,9 @@ TLevelP TLevelReader::loadInfo() {
|
|||
if (!data.empty()) {
|
||||
std::vector<TFilePath>::iterator it =
|
||||
std::min_element(data.begin(), data.end(), myLess);
|
||||
|
||||
m_frameFormat = (*it).getFrame().getCurrentFormat();
|
||||
/*
|
||||
TFilePath fr = (*it).withoutParentDir().withName("").withType("");
|
||||
wstring ws = fr.getWideString();
|
||||
if (ws.length() == 5) {
|
||||
|
@ -150,7 +153,7 @@ TLevelP TLevelReader::loadInfo() {
|
|||
else
|
||||
m_frameFormat = TFrameId::UNDERSCORE_NO_PAD;
|
||||
}
|
||||
|
||||
*/
|
||||
} else
|
||||
m_frameFormat = TFrameId::FOUR_ZEROS;
|
||||
|
||||
|
|
|
@ -27,9 +27,16 @@ const char wauxslash = '\\';
|
|||
|
||||
// QT
|
||||
#include <QObject>
|
||||
#include <QRegExp>
|
||||
|
||||
bool TFilePath::m_underscoreFormatAllowed = true;
|
||||
|
||||
// specifies file path condition for sequential image for each project.
|
||||
// See filepathproperties.h
|
||||
bool TFilePath::m_useStandard = true;
|
||||
bool TFilePath::m_acceptNonAlphabetSuffix = false;
|
||||
int TFilePath::m_letterCountForSuffix = 1;
|
||||
|
||||
namespace {
|
||||
|
||||
/*-- fromSeg位置 と
|
||||
|
@ -102,23 +109,27 @@ std::string TFrameId::expand(FrameFormat format) const {
|
|||
} else {
|
||||
o_buff << m_frame;
|
||||
}
|
||||
if (m_letter != '\0') o_buff << m_letter;
|
||||
return o_buff.str();
|
||||
if (m_letter.isEmpty())
|
||||
return o_buff.str();
|
||||
else
|
||||
return o_buff.str() + m_letter.toStdString();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
const TFrameId &TFrameId::operator++() {
|
||||
++m_frame;
|
||||
m_letter = 0;
|
||||
m_letter = "";
|
||||
// m_letter = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
const TFrameId &TFrameId::operator--() {
|
||||
if (m_letter > 0)
|
||||
m_letter = 0;
|
||||
if (!m_letter.isEmpty()) m_letter = "";
|
||||
// if (m_letter > 0)
|
||||
// m_letter = 0;
|
||||
else
|
||||
--m_frame;
|
||||
return *this;
|
||||
|
@ -245,9 +256,9 @@ void TFilePath::setPath(std::wstring path) {
|
|||
}
|
||||
// se si tratta di un path in formato UNC e' del tipo "\\\\MachineName"
|
||||
else if ((path.length() >= 3 && path[0] == L'\\' && path[1] == L'\\' &&
|
||||
iswalnum(path[2])) ||
|
||||
iswalnum(path[2])) ||
|
||||
(path.length() >= 3 && path[0] == L'/' && path[1] == L'/' &&
|
||||
iswalnum(path[2]))) {
|
||||
iswalnum(path[2]))) {
|
||||
isUncName = true;
|
||||
m_path.append(2, L'\\');
|
||||
m_path.append(1, path[2]);
|
||||
|
@ -283,14 +294,13 @@ void TFilePath::setPath(std::wstring path) {
|
|||
// oppure sia UNC (Windows only) )
|
||||
if (!((m_path.length() == 1 && m_path[0] == wslash) ||
|
||||
(m_path.length() == 3 && iswalpha(m_path[0]) && m_path[1] == L':' &&
|
||||
m_path[2] == wslash)) &&
|
||||
m_path[2] == wslash)) &&
|
||||
(m_path.length() > 1 && m_path[m_path.length() - 1] == wslash))
|
||||
m_path.erase(m_path.length() - 1, 1);
|
||||
|
||||
if (isUncName &&
|
||||
!(m_path.find_last_of(L'\\') > 1 ||
|
||||
m_path.find_last_of(L'/') >
|
||||
1)) // e' indicato solo il nome della macchina...
|
||||
if (isUncName && !(m_path.find_last_of(L'\\') > 1 ||
|
||||
m_path.find_last_of(L'/') >
|
||||
1)) // e' indicato solo il nome della macchina...
|
||||
m_path.append(1, wslash);
|
||||
}
|
||||
|
||||
|
@ -520,10 +530,10 @@ bool TFilePath::isAbsolute() const {
|
|||
bool TFilePath::isRoot() const {
|
||||
return ((m_path.length() == 1 && m_path[0] == slash) ||
|
||||
(m_path.length() == 3 && iswalpha(m_path[0]) && m_path[1] == ':' &&
|
||||
m_path[2] == slash) ||
|
||||
m_path[2] == slash) ||
|
||||
((m_path.length() > 2 && m_path[0] == slash && m_path[1] == slash) &&
|
||||
(std::string::npos == m_path.find(slash, 2) ||
|
||||
m_path.find(slash, 2) == (m_path.size() - 1))));
|
||||
(std::string::npos == m_path.find(slash, 2) ||
|
||||
m_path.find(slash, 2) == (m_path.size() - 1))));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -531,6 +541,15 @@ bool TFilePath::isRoot() const {
|
|||
// ritorna ""(niente tipo, niente punto), "." (file con tipo) o ".." (file con
|
||||
// tipo e frame)
|
||||
std::string TFilePath::getDots() const {
|
||||
if (!TFilePath::m_useStandard) {
|
||||
TFilePathInfo info = analyzePath();
|
||||
if (info.extension.isEmpty()) return "";
|
||||
if (info.sepChar.isNull()) return ".";
|
||||
// return ".." regardless of sepChar type (either "_" or ".")
|
||||
return "..";
|
||||
}
|
||||
//-----
|
||||
|
||||
QString type = QString::fromStdString(getType()).toLower();
|
||||
if (isFfmpegType()) return ".";
|
||||
int i = getLastSlash(m_path);
|
||||
|
@ -555,6 +574,12 @@ std::string TFilePath::getDots() const {
|
|||
std::string TFilePath::getDottedType()
|
||||
const // ritorna l'estensione con PUNTO (se c'e')
|
||||
{
|
||||
if (!TFilePath::m_useStandard) {
|
||||
QString ext = analyzePath().extension;
|
||||
if (ext.isEmpty()) return "";
|
||||
return "." + ext.toLower().toStdString();
|
||||
}
|
||||
|
||||
int i = getLastSlash(m_path);
|
||||
std::wstring str = m_path.substr(i + 1);
|
||||
i = str.rfind(L".");
|
||||
|
@ -568,6 +593,15 @@ std::string TFilePath::getDottedType()
|
|||
std::string TFilePath::getUndottedType()
|
||||
const // ritorna l'estensione senza PUNTO
|
||||
{
|
||||
if (!TFilePath::m_useStandard) {
|
||||
QString ext = analyzePath().extension;
|
||||
if (ext.isEmpty())
|
||||
return "";
|
||||
else
|
||||
return ext.toLower().toStdString();
|
||||
}
|
||||
|
||||
//-----
|
||||
size_t i = getLastSlash(m_path);
|
||||
std::wstring str = m_path.substr(i + 1);
|
||||
i = str.rfind(L".");
|
||||
|
@ -579,6 +613,11 @@ std::string TFilePath::getUndottedType()
|
|||
|
||||
std::wstring TFilePath::getWideName() const // noDot! noSlash!
|
||||
{
|
||||
if (!TFilePath::m_useStandard) {
|
||||
return analyzePath().levelName.toStdWString();
|
||||
}
|
||||
//-----
|
||||
|
||||
QString type = QString::fromStdString(getType()).toLower();
|
||||
int i = getLastSlash(m_path); // cerco l'ultimo slash
|
||||
std::wstring str = m_path.substr(i + 1);
|
||||
|
@ -613,6 +652,16 @@ std::string TFilePath::getLevelName() const {
|
|||
// es. TFilePath("/pippo/pluto.0001.gif").getLevelName() == "pluto..gif"
|
||||
|
||||
std::wstring TFilePath::getLevelNameW() const {
|
||||
if (!TFilePath::m_useStandard) {
|
||||
TFilePathInfo info = analyzePath();
|
||||
if (info.extension.isEmpty()) return info.levelName.toStdWString();
|
||||
QString name = info.levelName;
|
||||
if (!info.sepChar.isNull()) name += info.sepChar;
|
||||
name += "." + info.extension;
|
||||
return name.toStdWString();
|
||||
}
|
||||
//-----
|
||||
|
||||
int i = getLastSlash(m_path); // cerco l'ultimo slash
|
||||
std::wstring str = m_path.substr(i + 1); // str e' m_path senza directory
|
||||
QString type = QString::fromStdString(getType()).toLower();
|
||||
|
@ -627,7 +676,8 @@ std::wstring TFilePath::getLevelNameW() const {
|
|||
return str;
|
||||
|
||||
if (!checkForSeqNum(type) || !isNumbers(str, i, j) ||
|
||||
i == (int)std::wstring::npos) return str;
|
||||
i == (int)std::wstring::npos)
|
||||
return str;
|
||||
// prova.0001.tif
|
||||
return str.erase(i + 1, j - i - 1);
|
||||
}
|
||||
|
@ -638,8 +688,9 @@ TFilePath TFilePath::getParentDir() const // noSlash!
|
|||
{
|
||||
int i = getLastSlash(m_path); // cerco l'ultimo slash
|
||||
if (i < 0) {
|
||||
if (m_path.length() >= 2 && (('a' <= m_path[0] && m_path[0] <= 'z') ||
|
||||
('A' <= m_path[0] && m_path[0] <= 'Z')) &&
|
||||
if (m_path.length() >= 2 &&
|
||||
(('a' <= m_path[0] && m_path[0] <= 'z') ||
|
||||
('A' <= m_path[0] && m_path[0] <= 'Z')) &&
|
||||
m_path[1] == ':')
|
||||
return TFilePath(m_path.substr(0, 2));
|
||||
else
|
||||
|
@ -651,8 +702,13 @@ TFilePath TFilePath::getParentDir() const // noSlash!
|
|||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// return true if the fID is EMPTY_FRAME
|
||||
bool TFilePath::isLevelName() const {
|
||||
if (!TFilePath::m_useStandard) {
|
||||
return analyzePath().fId.getNumber() == TFrameId::EMPTY_FRAME;
|
||||
}
|
||||
//-----
|
||||
|
||||
QString type = QString::fromStdString(getType()).toLower();
|
||||
if (isFfmpegType() || !checkForSeqNum(type)) return false;
|
||||
try {
|
||||
|
@ -665,6 +721,11 @@ bool TFilePath::isLevelName() const {
|
|||
}
|
||||
|
||||
TFrameId TFilePath::getFrame() const {
|
||||
if (!TFilePath::m_useStandard) {
|
||||
return analyzePath().fId;
|
||||
}
|
||||
|
||||
//-----
|
||||
int i = getLastSlash(m_path); // cerco l'ultimo slash
|
||||
std::wstring str = m_path.substr(i + 1); // str e' il path senza parentdir
|
||||
QString type = QString::fromStdString(getType()).toLower();
|
||||
|
@ -680,8 +741,7 @@ TFrameId TFilePath::getFrame() const {
|
|||
if (j == (int)std::wstring::npos) return TFrameId(TFrameId::NO_FRAME);
|
||||
if (i == j + 1) return TFrameId(TFrameId::EMPTY_FRAME);
|
||||
|
||||
/*-- 間が数字でない場合(ファイル名にまぎれた"_" や "."がある場合)を除外する
|
||||
* --*/
|
||||
// 間が数字でない場合(ファイル名にまぎれた"_" や "."がある場合)を除外する
|
||||
if (!checkForSeqNum(type) || !isNumbers(str, j, i))
|
||||
return TFrameId(TFrameId::NO_FRAME);
|
||||
|
||||
|
@ -690,14 +750,13 @@ TFrameId TFilePath::getFrame() const {
|
|||
digits++;
|
||||
number = number * 10 + str[k] - L'0';
|
||||
}
|
||||
char letter = '\0';
|
||||
char letter = '\0';
|
||||
if (iswalpha(str[k])) letter = str[k++] + ('a' - L'a');
|
||||
/*
|
||||
if (number == 0 || k < i) // || letter!='\0')
|
||||
throw TMalformedFrameException(
|
||||
*this,
|
||||
str + L": " + QObject::tr("Malformed frame name").toStdWString());
|
||||
*/
|
||||
|
||||
// if (number == 0 || k < i) // || letter!='\0')
|
||||
// throw TMalformedFrameException(
|
||||
// *this,
|
||||
// str + L": " + QObject::tr("Malformed frame name").toStdWString());
|
||||
int padding = 0;
|
||||
|
||||
if (str[j + 1] == '0') padding = digits;
|
||||
|
@ -751,6 +810,20 @@ TFilePath TFilePath::withName(const std::string &name) const {
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
TFilePath TFilePath::withName(const std::wstring &name) const {
|
||||
if (!TFilePath::m_useStandard) {
|
||||
TFilePathInfo info = analyzePath();
|
||||
|
||||
QString ret = info.parentDir + QString::fromStdWString(name);
|
||||
if (info.fId.getNumber() != TFrameId::NO_FRAME) {
|
||||
QString sepChar = (info.sepChar.isNull()) ? "." : QString(info.sepChar);
|
||||
ret += sepChar + QString::fromStdString(
|
||||
info.fId.expand(info.fId.getCurrentFormat()));
|
||||
}
|
||||
if (!info.extension.isEmpty()) ret += "." + info.extension;
|
||||
|
||||
return TFilePath(ret);
|
||||
}
|
||||
|
||||
int i = getLastSlash(m_path); // cerco l'ultimo slash
|
||||
std::wstring str = m_path.substr(i + 1); // str e' il path senza parentdir
|
||||
QString type = QString::fromStdString(getType()).toLower();
|
||||
|
@ -790,6 +863,31 @@ TFilePath TFilePath::withParentDir(const TFilePath &dir) const {
|
|||
|
||||
TFilePath TFilePath::withFrame(const TFrameId &frame,
|
||||
TFrameId::FrameFormat format) const {
|
||||
if (!TFilePath::m_useStandard) {
|
||||
TFilePathInfo info = analyzePath();
|
||||
// Override format input because it may be wrong.
|
||||
if (checkForSeqNum(info.extension)) format = frame.getCurrentFormat();
|
||||
// override format if the original fid is available
|
||||
else if (info.fId.getNumber() != TFrameId::NO_FRAME)
|
||||
format = info.fId.getCurrentFormat();
|
||||
|
||||
if (info.extension.isEmpty()) {
|
||||
if (frame.isEmptyFrame() || frame.isNoFrame()) return *this;
|
||||
|
||||
return TFilePath(m_path + L"." + ::to_wstring(frame.expand(format)));
|
||||
}
|
||||
if (frame.isNoFrame()) {
|
||||
return TFilePath(info.parentDir + info.levelName + "." + info.extension);
|
||||
}
|
||||
QString sepChar = (info.sepChar.isNull()) ? "." : QString(info.sepChar);
|
||||
|
||||
return TFilePath(info.parentDir + info.levelName + sepChar +
|
||||
QString::fromStdString(frame.expand(format)) + "." +
|
||||
info.extension);
|
||||
}
|
||||
|
||||
//-----------------
|
||||
|
||||
const std::wstring dot = L".", dotDot = L"..";
|
||||
int i = getLastSlash(m_path); // cerco l'ultimo slash
|
||||
std::wstring str = m_path.substr(i + 1); // str e' il path senza parentdir
|
||||
|
@ -804,6 +902,8 @@ TFilePath TFilePath::withFrame(const TFrameId &frame,
|
|||
format == TFrameId::UNDERSCORE_NO_PAD ||
|
||||
format == TFrameId::UNDERSCORE_CUSTOM_PAD))
|
||||
ch = "_";
|
||||
|
||||
// no extension case
|
||||
if (j == (int)std::wstring::npos) {
|
||||
if (frame.isEmptyFrame() || frame.isNoFrame())
|
||||
return *this;
|
||||
|
@ -842,7 +942,7 @@ TFilePath TFilePath::withFrame(const TFrameId &frame,
|
|||
(k == j - 1 ||
|
||||
(checkForSeqNum(type) &&
|
||||
isNumbers(str, k,
|
||||
j)))) /*-- "_." の並びか、"_[数字]."の並びのとき --*/
|
||||
j)))) //-- "_." の並びか、"_[数字]."の並びのとき --
|
||||
return TFilePath(m_path.substr(0, k + i + 1) +
|
||||
((frame.isNoFrame())
|
||||
? L""
|
||||
|
@ -893,6 +993,16 @@ TFilePath TFilePath::operator-(const TFilePath &fp) const {
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool TFilePath::match(const TFilePath &fp) const {
|
||||
if (!TFilePath::m_useStandard) {
|
||||
if (getParentDir() != fp.getParentDir()) return false;
|
||||
|
||||
TFilePathInfo info = analyzePath();
|
||||
TFilePathInfo info_ext = fp.analyzePath();
|
||||
|
||||
return (info.levelName == info_ext.levelName && info.fId == info_ext.fId &&
|
||||
info.extension == info_ext.extension);
|
||||
}
|
||||
|
||||
return getParentDir() == fp.getParentDir() && getName() == fp.getName() &&
|
||||
getFrame() == fp.getFrame() && getType() == fp.getType();
|
||||
}
|
||||
|
@ -915,3 +1025,118 @@ void TFilePath::split(std::wstring &head, TFilePath &tail) const {
|
|||
head = ancestor.getWideString();
|
||||
tail = *this - ancestor;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
QString TFilePath::fidRegExpStr() {
|
||||
if (m_useStandard) return QString("(\\d+)([a-zA-Z]?)");
|
||||
QString suffixLetter = (m_acceptNonAlphabetSuffix)
|
||||
? "[^\\._ \\\\/:,;*?\"<>|0123456789]"
|
||||
: "[a-zA-Z]";
|
||||
QString countLetter = (m_letterCountForSuffix == 0)
|
||||
? "{0,}"
|
||||
: (QString("{0,%1}").arg(m_letterCountForSuffix));
|
||||
return QString("(\\d+)(%1%2)").arg(suffixLetter).arg(countLetter);
|
||||
// const QString fIdRegExp("(\\d+)([a-zA-Z]?)");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
TFilePath::TFilePathInfo TFilePath::analyzePath() const {
|
||||
assert(!TFilePath::m_useStandard);
|
||||
|
||||
TFilePath::TFilePathInfo info;
|
||||
|
||||
int i = getLastSlash(m_path);
|
||||
std::wstring str = m_path.substr(i + 1);
|
||||
|
||||
if (i >= 0) info.parentDir = QString::fromStdWString(m_path.substr(0, i + 1));
|
||||
|
||||
QString fileName = QString::fromStdWString(str);
|
||||
|
||||
// Level Name : letters other than \/:,;*?"<>|
|
||||
const QString levelNameRegExp("([^\\\\/:,;*?\"<>|]+)");
|
||||
// Sep Char : period or underscore
|
||||
const QString sepCharRegExp("([\\._])");
|
||||
// Frame Number and Suffix
|
||||
QString fIdRegExp = TFilePath::fidRegExpStr();
|
||||
|
||||
// Extension:letters other than "._" or \/:,;*?"<>| or " "(space)
|
||||
const QString extensionRegExp("([^\\._ \\\\/:,;*?\"<>|]+)");
|
||||
|
||||
// ignore frame numbers on non-sequential (i.e. movie) extension case :
|
||||
// hoge_0001.mp4
|
||||
// QRegExp rx_mf("^" + levelNameRegExp + "\\." + extensionRegExp + "$");
|
||||
// if (rx_mf.indexIn(levelName) != -1) {
|
||||
// QString ext = rx_mf.cap(2);
|
||||
// if (!checkForSeqNum(ext)) {
|
||||
// info.levelName = rx_mf.cap(1);
|
||||
// info.sepChar = QChar();
|
||||
// info.fId = TFrameId(TFrameId::NO_FRAME, 0, 0); //NO_PADで初期化する
|
||||
// info.extension = ext;
|
||||
// return info;
|
||||
// }
|
||||
//}
|
||||
|
||||
// hogehoge.0001a.jpg
|
||||
// empty frame case : hogehoge..jpg
|
||||
QRegExp rx("^" + levelNameRegExp + sepCharRegExp + "(?:" + fIdRegExp + ")?" +
|
||||
"\\." + extensionRegExp + "$");
|
||||
if (rx.indexIn(fileName) != -1) {
|
||||
assert(rx.captureCount() == 5);
|
||||
info.levelName = rx.cap(1);
|
||||
info.sepChar = rx.cap(2)[0];
|
||||
info.extension = rx.cap(5);
|
||||
// ignore frame numbers on non-sequential (i.e. movie) extension case :
|
||||
// hoge_0001.mp4
|
||||
if (!checkForSeqNum(info.extension)) {
|
||||
info.levelName = rx.cap(1) + rx.cap(2);
|
||||
if (!rx.cap(3).isEmpty()) info.levelName += rx.cap(3);
|
||||
if (!rx.cap(4).isEmpty()) info.levelName += rx.cap(4);
|
||||
info.sepChar = QChar();
|
||||
info.fId = TFrameId(TFrameId::NO_FRAME, 0, 0); // initialize with NO_PAD
|
||||
} else {
|
||||
QString numberStr = rx.cap(3);
|
||||
if (numberStr.isEmpty()) // empty frame case : hogehoge..jpg
|
||||
info.fId =
|
||||
TFrameId(TFrameId::EMPTY_FRAME, 0, 4, info.sepChar.toLatin1());
|
||||
else {
|
||||
int number = numberStr.toInt();
|
||||
int padding = 0;
|
||||
if (numberStr[0] == "0") // with padding
|
||||
padding = numberStr.count();
|
||||
QString suffix;
|
||||
if (!rx.cap(4).isEmpty()) suffix = rx.cap(4);
|
||||
info.fId = TFrameId(number, suffix, padding, info.sepChar.toLatin1());
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
// QRegExp rx_ef("^" + levelNameRegExp + sepCharRegExp + "\\." +
|
||||
// extensionRegExp + "$"); if (rx_ef.indexIn(levelName) != -1) {
|
||||
// info.levelName = rx_ef.cap(1);
|
||||
// info.sepChar = rx_ef.cap(2)[0];
|
||||
// info.fId = TFrameId(TFrameId::EMPTY_FRAME, 0, 4, info.sepChar.toLatin1());
|
||||
// info.extension = rx_ef.cap(3);
|
||||
// return info;
|
||||
//}
|
||||
|
||||
// no frame case : hogehoge.jpg
|
||||
// no level name case : .jpg
|
||||
QRegExp rx_nf("^(?:" + levelNameRegExp + ")?\\." + extensionRegExp + "$");
|
||||
if (rx_nf.indexIn(fileName) != -1) {
|
||||
if (!rx_nf.cap(1).isEmpty()) info.levelName = rx_nf.cap(1);
|
||||
info.sepChar = QChar();
|
||||
info.fId = TFrameId(TFrameId::NO_FRAME, 0, 0); // initialize with NO_PAD
|
||||
info.extension = rx_nf.cap(2);
|
||||
return info;
|
||||
}
|
||||
|
||||
// no periods
|
||||
info.levelName = fileName;
|
||||
info.sepChar = QChar();
|
||||
info.fId = TFrameId(TFrameId::NO_FRAME, 0, 0); // initialize with NO_PAD
|
||||
info.extension = QString();
|
||||
return info;
|
||||
}
|
|
@ -332,7 +332,7 @@ void TLevelWriterAvi::createBitmap(int lx, int ly) {
|
|||
TImageWriterP TLevelWriterAvi::getFrameWriter(TFrameId fid) {
|
||||
if (IOError != 0)
|
||||
throw TImageException(m_path, buildAVIExceptionString(IOError));
|
||||
if (fid.getLetter() != 0) return TImageWriterP(0);
|
||||
if (!fid.getLetter().isEmpty()) return TImageWriterP(0);
|
||||
int index = fid.getNumber() - 1;
|
||||
TImageWriterAvi *iwa = new TImageWriterAvi(m_path, index, this);
|
||||
return TImageWriterP(iwa);
|
||||
|
@ -879,7 +879,7 @@ TLevelP TLevelReaderAvi::loadInfo() {
|
|||
TImageReaderP TLevelReaderAvi::getFrameReader(TFrameId fid) {
|
||||
if (IOError != 0)
|
||||
throw TImageException(m_path, buildAVIExceptionString(IOError));
|
||||
if (fid.getLetter() != 0) return TImageReaderP(0);
|
||||
if (!fid.getLetter().isEmpty()) return TImageReaderP(0);
|
||||
int index = fid.getNumber() - 1;
|
||||
|
||||
TImageReaderAvi *ira = new TImageReaderAvi(m_path, index, this);
|
||||
|
|
|
@ -119,7 +119,7 @@ TLevelWriterGif::~TLevelWriterGif() {
|
|||
TImageWriterP TLevelWriterGif::getFrameWriter(TFrameId fid) {
|
||||
// if (IOError != 0)
|
||||
// throw TImageException(m_path, buildGifExceptionString(IOError));
|
||||
if (fid.getLetter() != 0) return TImageWriterP(0);
|
||||
if (!fid.getLetter().isEmpty()) return TImageWriterP(0);
|
||||
int index = fid.getNumber();
|
||||
TImageWriterGif *iwg = new TImageWriterGif(m_path, index, this);
|
||||
return TImageWriterP(iwg);
|
||||
|
@ -224,7 +224,7 @@ TLevelP TLevelReaderGif::loadInfo() {
|
|||
TImageReaderP TLevelReaderGif::getFrameReader(TFrameId fid) {
|
||||
// if (IOError != 0)
|
||||
// throw TImageException(m_path, buildAVIExceptionString(IOError));
|
||||
if (fid.getLetter() != 0) return TImageReaderP(0);
|
||||
if (!fid.getLetter().isEmpty()) return TImageReaderP(0);
|
||||
int index = fid.getNumber();
|
||||
TImageReaderGif *irm = new TImageReaderGif(m_path, index, this, m_info);
|
||||
return TImageReaderP(irm);
|
||||
|
|
|
@ -104,7 +104,7 @@ TLevelWriterMov::~TLevelWriterMov() {
|
|||
TImageWriterP TLevelWriterMov::getFrameWriter(TFrameId fid) {
|
||||
// if (IOError != 0)
|
||||
// throw TImageException(m_path, buildMovExceptionString(IOError));
|
||||
if (fid.getLetter() != 0) return TImageWriterP(0);
|
||||
if (!fid.getLetter().isEmpty()) return TImageWriterP(0);
|
||||
int index = fid.getNumber();
|
||||
TImageWriterMov *iwg = new TImageWriterMov(m_path, index, this);
|
||||
return TImageWriterP(iwg);
|
||||
|
@ -207,7 +207,7 @@ TLevelP TLevelReaderMov::loadInfo() {
|
|||
TImageReaderP TLevelReaderMov::getFrameReader(TFrameId fid) {
|
||||
// if (IOError != 0)
|
||||
// throw TImageException(m_path, buildAVIExceptionString(IOError));
|
||||
if (fid.getLetter() != 0) return TImageReaderP(0);
|
||||
if (!fid.getLetter().isEmpty()) return TImageReaderP(0);
|
||||
int index = fid.getNumber();
|
||||
|
||||
TImageReaderMov *irm = new TImageReaderMov(m_path, index, this, m_info);
|
||||
|
|
|
@ -100,7 +100,7 @@ TLevelWriterMp4::~TLevelWriterMp4() {
|
|||
TImageWriterP TLevelWriterMp4::getFrameWriter(TFrameId fid) {
|
||||
// if (IOError != 0)
|
||||
// throw TImageException(m_path, buildMp4ExceptionString(IOError));
|
||||
if (fid.getLetter() != 0) return TImageWriterP(0);
|
||||
if (!fid.getLetter().isEmpty()) return TImageWriterP(0);
|
||||
int index = fid.getNumber();
|
||||
TImageWriterMp4 *iwg = new TImageWriterMp4(m_path, index, this);
|
||||
return TImageWriterP(iwg);
|
||||
|
@ -203,7 +203,7 @@ TLevelP TLevelReaderMp4::loadInfo() {
|
|||
TImageReaderP TLevelReaderMp4::getFrameReader(TFrameId fid) {
|
||||
// if (IOError != 0)
|
||||
// throw TImageException(m_path, buildAVIExceptionString(IOError));
|
||||
if (fid.getLetter() != 0) return TImageReaderP(0);
|
||||
if (!fid.getLetter().isEmpty()) return TImageReaderP(0);
|
||||
int index = fid.getNumber();
|
||||
|
||||
TImageReaderMp4 *irm = new TImageReaderMp4(m_path, index, this, m_info);
|
||||
|
|
|
@ -101,7 +101,7 @@ TLevelWriterWebm::~TLevelWriterWebm() {
|
|||
TImageWriterP TLevelWriterWebm::getFrameWriter(TFrameId fid) {
|
||||
// if (IOError != 0)
|
||||
// throw TImageException(m_path, buildGifExceptionString(IOError));
|
||||
if (fid.getLetter() != 0) return TImageWriterP(0);
|
||||
if (!fid.getLetter().isEmpty()) return TImageWriterP(0);
|
||||
int index = fid.getNumber();
|
||||
TImageWriterWebm *iwg = new TImageWriterWebm(m_path, index, this);
|
||||
return TImageWriterP(iwg);
|
||||
|
@ -204,7 +204,7 @@ TLevelP TLevelReaderWebm::loadInfo() {
|
|||
TImageReaderP TLevelReaderWebm::getFrameReader(TFrameId fid) {
|
||||
// if (IOError != 0)
|
||||
// throw TImageException(m_path, buildAVIExceptionString(IOError));
|
||||
if (fid.getLetter() != 0) return TImageReaderP(0);
|
||||
if (!fid.getLetter().isEmpty()) return TImageReaderP(0);
|
||||
int index = fid.getNumber();
|
||||
|
||||
TImageReaderWebm *irm = new TImageReaderWebm(m_path, index, this, m_info);
|
||||
|
|
|
@ -29,7 +29,7 @@ typedef TVectorImage::IntersectionBranch IntersectionBranch;
|
|||
TNZ_LITTLE_ENDIAN undefined !!
|
||||
#endif
|
||||
|
||||
static const int c_majorVersionNumber = 120;
|
||||
static const int c_majorVersionNumber = 150;
|
||||
static const int c_minorVersionNumber = 0;
|
||||
|
||||
/*=====================================================================*/
|
||||
|
@ -58,8 +58,8 @@ inline double doubleFromUlong1(TUINT32 hi, TUINT32 lo) {
|
|||
l[1] = hi;
|
||||
l[0] = lo;
|
||||
#else
|
||||
l[0] = hi;
|
||||
l[1] = lo;
|
||||
l[0] = hi;
|
||||
l[1] = lo;
|
||||
#endif
|
||||
|
||||
return *(double *)l; // - 1;
|
||||
|
@ -84,8 +84,8 @@ public:
|
|||
#if TNZ_LITTLE_ENDIAN
|
||||
app = n;
|
||||
#else
|
||||
UCHAR *uc = (UCHAR *)&n;
|
||||
app = *(uc) | (*(uc + 1)) << 8 | (*(uc + 2)) << 16 | (*(uc + 3)) << 24;
|
||||
UCHAR *uc = (UCHAR *)&n;
|
||||
app = *(uc) | (*(uc + 1)) << 8 | (*(uc + 2)) << 16 | (*(uc + 3)) << 24;
|
||||
#endif
|
||||
write((char *)&app, sizeof(TUINT32));
|
||||
return *this;
|
||||
|
@ -669,15 +669,27 @@ void ParsedPliImp::loadInfo(bool readPlt, TPalette *&palette,
|
|||
USHORT frame;
|
||||
m_iChan >> frame;
|
||||
|
||||
char letter = 0;
|
||||
if (m_majorVersionNumber > 6 ||
|
||||
(m_majorVersionNumber == 6 && m_minorVersionNumber >= 6))
|
||||
m_iChan >> letter;
|
||||
QByteArray suffix;
|
||||
if (m_majorVersionNumber >= 150) {
|
||||
TUINT32 suffixLength;
|
||||
m_iChan >> suffixLength;
|
||||
if ((int)suffixLength > 0) {
|
||||
suffix.resize(suffixLength);
|
||||
m_iChan.read(suffix.data(), suffixLength);
|
||||
}
|
||||
} else {
|
||||
char letter = 0;
|
||||
if (m_majorVersionNumber > 6 ||
|
||||
(m_majorVersionNumber == 6 && m_minorVersionNumber >= 6))
|
||||
m_iChan >> letter;
|
||||
if (letter > 0) suffix = QByteArray(&letter, 1);
|
||||
}
|
||||
|
||||
m_frameOffsInFile[TFrameId(frame, letter)] = m_iChan.tellg();
|
||||
m_frameOffsInFile[TFrameId(frame, QString::fromUtf8(suffix))] =
|
||||
m_iChan.tellg();
|
||||
|
||||
// m_iChan.seekg(m_tagLength, ios::cur);
|
||||
m_iChan.seekg(m_tagLength - 2, ios::cur);
|
||||
if (m_majorVersionNumber < 150) m_iChan.seekg(m_tagLength - 2, ios::cur);
|
||||
} else if (type == PliTag::STYLE_NGOBJ) {
|
||||
m_iChan.seekg(pos, ios::beg);
|
||||
TagElem *tagElem = readTag();
|
||||
|
@ -798,7 +810,7 @@ ImageTag *ParsedPliImp::loadFrame(const TFrameId &frameNumber) {
|
|||
// PliTag *tag;
|
||||
USHORT type = PliTag::IMAGE_BEGIN_GOBJ;
|
||||
USHORT frame;
|
||||
char letter;
|
||||
QByteArray suffix;
|
||||
TFrameId frameId;
|
||||
|
||||
// cerco il frame
|
||||
|
@ -813,13 +825,21 @@ ImageTag *ParsedPliImp::loadFrame(const TFrameId &frameNumber) {
|
|||
while ((type = readTagHeader()) != PliTag::END_CNTRL) {
|
||||
if (type == PliTag::IMAGE_BEGIN_GOBJ) {
|
||||
m_iChan >> frame;
|
||||
if (m_majorVersionNumber > 6 ||
|
||||
(m_majorVersionNumber == 6 && m_minorVersionNumber >= 6))
|
||||
m_iChan >> letter;
|
||||
else
|
||||
letter = 0;
|
||||
if (m_majorVersionNumber >= 150) {
|
||||
TUINT32 suffixLength;
|
||||
m_iChan >> suffixLength;
|
||||
suffix.resize(suffixLength);
|
||||
m_iChan.read(suffix.data(), suffixLength);
|
||||
} else {
|
||||
char letter = 0;
|
||||
if (m_majorVersionNumber > 6 ||
|
||||
(m_majorVersionNumber == 6 && m_minorVersionNumber >= 6)) {
|
||||
m_iChan >> letter;
|
||||
if (letter > 0) suffix = QByteArray(&letter, 1);
|
||||
}
|
||||
}
|
||||
|
||||
frameId = TFrameId(frame, letter);
|
||||
frameId = TFrameId(frame, QString::fromUtf8(suffix));
|
||||
m_frameOffsInFile[frameId] = m_iChan.tellg();
|
||||
if (frameId == frameNumber) break;
|
||||
} else
|
||||
|
@ -1056,15 +1076,16 @@ inline bool ParsedPliImp::readDynamicData(TINT32 &val, TUINT32 &bufOffs) {
|
|||
case 4:
|
||||
if (m_isIrixEndian) {
|
||||
val = (m_buf[bufOffs + 3] | (m_buf[bufOffs + 2] << 8) |
|
||||
(m_buf[bufOffs + 1] << 16) | (m_buf[bufOffs] << 24)) & 0x7fffffff;
|
||||
(m_buf[bufOffs + 1] << 16) | (m_buf[bufOffs] << 24)) &
|
||||
0x7fffffff;
|
||||
if (m_buf[bufOffs] & 0x80) {
|
||||
val = -val;
|
||||
isNegative = true;
|
||||
}
|
||||
} else {
|
||||
val = (m_buf[bufOffs] | (m_buf[bufOffs + 1] << 8) |
|
||||
(m_buf[bufOffs + 2] << 16) |
|
||||
(m_buf[bufOffs + 3] << 24)) & 0x7fffffff;
|
||||
(m_buf[bufOffs + 2] << 16) | (m_buf[bufOffs + 3] << 24)) &
|
||||
0x7fffffff;
|
||||
if (m_buf[bufOffs + 3] & 0x80) {
|
||||
val = -val;
|
||||
isNegative = true;
|
||||
|
@ -1466,7 +1487,7 @@ UINT ParsedPliImp::readRasterData(TRaster32P &r, TUINT32 &bufOffs) {
|
|||
/*=====================================================================*/
|
||||
|
||||
inline void getLongValFromFloat(double val, TINT32 &intVal, TUINT32 &decVal) {
|
||||
intVal = (TINT32)val;
|
||||
intVal = (TINT32)val;
|
||||
if (val < 0) decVal = (TUINT32)((double)((-val) - (-intVal)) * 65536.0);
|
||||
/*if (intVal<(0x1<<7))
|
||||
intVal|=(0x1<<7);
|
||||
|
@ -1614,11 +1635,25 @@ PliTag *ParsedPliImp::readImageTag() {
|
|||
bufOffs += 2;
|
||||
|
||||
int headerLength = 2;
|
||||
char letter = 0;
|
||||
if (m_majorVersionNumber > 6 ||
|
||||
(m_majorVersionNumber == 6 && m_minorVersionNumber >= 6)) {
|
||||
letter = (char)m_buf[bufOffs++];
|
||||
++headerLength;
|
||||
|
||||
QByteArray suffix;
|
||||
if (m_majorVersionNumber >= 150) {
|
||||
TUINT32 suffixLength;
|
||||
readTUINT32Data(suffixLength, bufOffs);
|
||||
headerLength += 4;
|
||||
if (suffixLength > 0) {
|
||||
suffix = QByteArray((char *)m_buf.get() + bufOffs, suffixLength);
|
||||
bufOffs += suffixLength;
|
||||
headerLength += suffixLength;
|
||||
}
|
||||
} else {
|
||||
char letter = 0;
|
||||
if (m_majorVersionNumber > 6 ||
|
||||
(m_majorVersionNumber == 6 && m_minorVersionNumber >= 6)) {
|
||||
letter = (char)m_buf[bufOffs++];
|
||||
++headerLength;
|
||||
if (letter > 0) suffix = QByteArray(&letter, 1);
|
||||
}
|
||||
}
|
||||
|
||||
TUINT32 numObjects = (m_tagLength - headerLength) / m_currDynamicTypeBytesNum;
|
||||
|
@ -1638,7 +1673,8 @@ PliTag *ParsedPliImp::readImageTag() {
|
|||
assert(false);
|
||||
|
||||
std::unique_ptr<ImageTag[]> tag(
|
||||
new ImageTag(TFrameId(frame, letter), numObjects, std::move(object)));
|
||||
new ImageTag(TFrameId(frame, QString::fromUtf8(suffix)), numObjects,
|
||||
std::move(object)));
|
||||
return tag.release();
|
||||
}
|
||||
|
||||
|
@ -1655,8 +1691,8 @@ inline double doubleFromUlong(TUINT32 q) {
|
|||
l[1] = 0x3FF00000 | (q >> 12);
|
||||
l[0] = (q & 0xFFE) << 20;
|
||||
#else
|
||||
l[0] = 0x3FF00000 | (q >> 12);
|
||||
l[1] = (q & 0xFFE) << 20;
|
||||
l[0] = 0x3FF00000 | (q >> 12);
|
||||
l[1] = (q & 0xFFE) << 20;
|
||||
#endif
|
||||
|
||||
return *(double *)l - 1;
|
||||
|
@ -1700,7 +1736,7 @@ PliTag *ParsedPliImp::readIntersectionDataTag() {
|
|||
readUShortData(style, bufOffs);
|
||||
branchArray[i].m_style = style;
|
||||
/*
|
||||
*/
|
||||
*/
|
||||
if (m_buf[bufOffs] & 0x80) // in un numero double tra 0 e 1, il bit piu'
|
||||
// significativo e' sempre 0
|
||||
// sfrutto questo bit; se e' 1, vuol dire che il valore e' 0.0 o 1.0 in un
|
||||
|
@ -1981,7 +2017,7 @@ TUINT32 ParsedPliImp::writePaletteWithAlphaTag(PaletteWithAlphaTag *tag) {
|
|||
|
||||
inline void ParsedPliImp::WRITE_UCHAR_FROM_DOUBLE(double dval) {
|
||||
assert(m_oChan);
|
||||
int ival = tround(dval);
|
||||
int ival = tround(dval);
|
||||
if (ival > 255) ival = 255;
|
||||
assert(ival >= 0);
|
||||
*m_oChan << (UCHAR)ival;
|
||||
|
@ -2128,10 +2164,24 @@ TUINT32 ParsedPliImp::writeImageTag(ImageTag *tag) {
|
|||
TUINT32 *objectOffset, offset, tagLength;
|
||||
int maxval = 0, minval = 100000;
|
||||
|
||||
writeTagHeader((UCHAR)PliTag::IMAGE_BEGIN_GOBJ, 3);
|
||||
*m_oChan << (USHORT)tag->m_numFrame.getNumber();
|
||||
*m_oChan << tag->m_numFrame.getLetter();
|
||||
|
||||
QByteArray suffix = tag->m_numFrame.getLetter().toUtf8();
|
||||
TUINT32 suffixLength = suffix.size();
|
||||
UINT fIdTagLength;
|
||||
if (m_majorVersionNumber >= 150) { // write the suffix length before data
|
||||
fIdTagLength = 2 + 4 + suffixLength;
|
||||
writeTagHeader((UCHAR)PliTag::IMAGE_BEGIN_GOBJ, fIdTagLength);
|
||||
*m_oChan << (USHORT)tag->m_numFrame.getNumber();
|
||||
*m_oChan << suffixLength;
|
||||
if (suffixLength > 0) m_oChan->writeBuf(suffix.data(), suffixLength);
|
||||
} else { // write only the first byte
|
||||
fIdTagLength = 3;
|
||||
writeTagHeader((UCHAR)PliTag::IMAGE_BEGIN_GOBJ, fIdTagLength);
|
||||
*m_oChan << (USHORT)tag->m_numFrame.getNumber();
|
||||
if (suffixLength > 0)
|
||||
m_oChan->writeBuf(suffix.data(), 1);
|
||||
else
|
||||
*m_oChan << (UCHAR)0;
|
||||
}
|
||||
m_currDynamicTypeBytesNum = 3;
|
||||
|
||||
objectOffset = new TUINT32[tag->m_numObjects];
|
||||
|
@ -2155,12 +2205,23 @@ TUINT32 ParsedPliImp::writeImageTag(ImageTag *tag) {
|
|||
|
||||
setDynamicTypeBytesNum(minval, maxval);
|
||||
|
||||
tagLength = tag->m_numObjects * m_currDynamicTypeBytesNum + 3;
|
||||
tagLength = tag->m_numObjects * m_currDynamicTypeBytesNum + fIdTagLength;
|
||||
// tagLength = tag->m_numObjects * m_currDynamicTypeBytesNum + 3;
|
||||
|
||||
offset = writeTagHeader((UCHAR)PliTag::IMAGE_GOBJ, tagLength);
|
||||
|
||||
suffix = tag->m_numFrame.getLetter().toUtf8();
|
||||
*m_oChan << (USHORT)tag->m_numFrame.getNumber();
|
||||
*m_oChan << tag->m_numFrame.getLetter();
|
||||
|
||||
if (m_majorVersionNumber >= 150) { // write the suffix length before data
|
||||
*m_oChan << suffixLength;
|
||||
if (suffixLength > 0) m_oChan->writeBuf(suffix.data(), suffixLength);
|
||||
} else { // write only the first byte
|
||||
if (suffixLength > 0)
|
||||
m_oChan->writeBuf(suffix.data(), 1);
|
||||
else
|
||||
*m_oChan << (UCHAR)0;
|
||||
}
|
||||
|
||||
for (i = 0; i < tag->m_numObjects; i++) writeDynamicData(objectOffset[i]);
|
||||
|
||||
|
@ -2420,29 +2481,29 @@ TUINT32 ParsedPliImp::writeGeometricTransformationTag(
|
|||
if (objectOffset > (unsigned int)maxval) maxval = (int)objectOffset;
|
||||
|
||||
getLongValFromFloat(tag->m_affine.a11, intVal[0], decVal[0]);
|
||||
if (intVal[0] < minval) minval = (int)intVal[0];
|
||||
if (intVal[0] > maxval) maxval = (int)intVal[0];
|
||||
if (intVal[0] < minval) minval = (int)intVal[0];
|
||||
if (intVal[0] > maxval) maxval = (int)intVal[0];
|
||||
if (decVal[0] > (unsigned int)maxval) maxval = (int)decVal[0];
|
||||
getLongValFromFloat(tag->m_affine.a12, intVal[1], decVal[1]);
|
||||
if (decVal[1] > (unsigned int)maxval) maxval = (int)decVal[1];
|
||||
if (intVal[1] < minval) minval = (int)intVal[1];
|
||||
if (intVal[1] > maxval) maxval = (int)intVal[1];
|
||||
if (intVal[1] < minval) minval = (int)intVal[1];
|
||||
if (intVal[1] > maxval) maxval = (int)intVal[1];
|
||||
getLongValFromFloat(tag->m_affine.a13, intVal[2], decVal[2]);
|
||||
if (decVal[2] > (unsigned int)maxval) maxval = (int)decVal[2];
|
||||
if (intVal[2] < minval) minval = (int)intVal[2];
|
||||
if (intVal[2] > maxval) maxval = (int)intVal[2];
|
||||
if (intVal[2] < minval) minval = (int)intVal[2];
|
||||
if (intVal[2] > maxval) maxval = (int)intVal[2];
|
||||
getLongValFromFloat(tag->m_affine.a21, intVal[3], decVal[3]);
|
||||
if (decVal[3] > (unsigned int)maxval) maxval = (int)decVal[3];
|
||||
if (intVal[3] < minval) minval = (int)intVal[3];
|
||||
if (intVal[3] > maxval) maxval = (int)intVal[3];
|
||||
if (intVal[3] < minval) minval = (int)intVal[3];
|
||||
if (intVal[3] > maxval) maxval = (int)intVal[3];
|
||||
getLongValFromFloat(tag->m_affine.a22, intVal[4], decVal[4]);
|
||||
if (decVal[4] > (unsigned int)maxval) maxval = (int)decVal[4];
|
||||
if (intVal[4] < minval) minval = (int)intVal[4];
|
||||
if (intVal[4] > maxval) maxval = (int)intVal[4];
|
||||
if (intVal[4] < minval) minval = (int)intVal[4];
|
||||
if (intVal[4] > maxval) maxval = (int)intVal[4];
|
||||
getLongValFromFloat(tag->m_affine.a23, intVal[5], decVal[5]);
|
||||
if (decVal[5] > (unsigned int)maxval) maxval = (int)decVal[5];
|
||||
if (intVal[5] < minval) minval = (int)intVal[5];
|
||||
if (intVal[5] > maxval) maxval = (int)intVal[5];
|
||||
if (intVal[5] < minval) minval = (int)intVal[5];
|
||||
if (intVal[5] > maxval) maxval = (int)intVal[5];
|
||||
|
||||
setDynamicTypeBytesNum(minval, maxval);
|
||||
|
||||
|
@ -2479,11 +2540,11 @@ TUINT32 ParsedPliImp::writeDoublePairTag(DoublePairTag *tag) {
|
|||
|
||||
getLongValFromFloat(tag->m_first, xIntVal, xDecVal);
|
||||
getLongValFromFloat(tag->m_second, yIntVal, yDecVal);
|
||||
if (xIntVal < minval) minval = (int)xIntVal;
|
||||
if (xIntVal > maxval) maxval = (int)xIntVal;
|
||||
if (xIntVal < minval) minval = (int)xIntVal;
|
||||
if (xIntVal > maxval) maxval = (int)xIntVal;
|
||||
if ((int)xDecVal > maxval) maxval = (int)xDecVal;
|
||||
if (yIntVal < minval) minval = (int)yIntVal;
|
||||
if (yIntVal > maxval) maxval = (int)yIntVal;
|
||||
if (yIntVal < minval) minval = (int)yIntVal;
|
||||
if (yIntVal > maxval) maxval = (int)yIntVal;
|
||||
if ((int)yDecVal > maxval) maxval = (int)yDecVal;
|
||||
|
||||
setDynamicTypeBytesNum(minval, maxval);
|
||||
|
@ -2635,10 +2696,16 @@ void ParsedPli::getVersion(UINT &majorVersionNumber,
|
|||
/*=====================================================================*/
|
||||
|
||||
void ParsedPli::setVersion(UINT majorVersionNumber, UINT minorVersionNumber) {
|
||||
if (imp->m_versionLocked) return;
|
||||
if (imp->m_versionLocked) {
|
||||
// accept only when settings higher versions
|
||||
if ((imp->m_majorVersionNumber > majorVersionNumber) ||
|
||||
(imp->m_majorVersionNumber == majorVersionNumber &&
|
||||
imp->m_minorVersionNumber >= minorVersionNumber))
|
||||
return;
|
||||
}
|
||||
if (majorVersionNumber >= 120) imp->m_versionLocked = true;
|
||||
imp->m_majorVersionNumber = majorVersionNumber;
|
||||
imp->m_minorVersionNumber = minorVersionNumber;
|
||||
imp->m_majorVersionNumber = majorVersionNumber;
|
||||
imp->m_minorVersionNumber = minorVersionNumber;
|
||||
}
|
||||
|
||||
/*=====================================================================*/
|
||||
|
|
|
@ -160,7 +160,7 @@ void buildPalette(ParsedPli *pli, const TImageP img) {
|
|||
assert(vPalette->getPageCount());
|
||||
|
||||
std::vector<TStyleParam> pageNames(vPalette->getPageCount());
|
||||
for (i = 0; i < pageNames.size(); i++)
|
||||
for (i = 0; i < pageNames.size(); i++)
|
||||
pageNames[i] = TStyleParam(::to_string(vPalette->getPage(i)->getName()));
|
||||
StyleTag *pageNamesTag =
|
||||
new StyleTag(0, 0, pageNames.size(), pageNames.data());
|
||||
|
@ -414,18 +414,18 @@ TImageP TImageReaderPli::doLoad() {
|
|||
} // switch(groupTag->m_object[j]->m_type)
|
||||
} // for (i=0; i<imageTag->m_numObjects; i++)
|
||||
|
||||
//} // try
|
||||
//} // try
|
||||
|
||||
// catch(...) // cosi' e' inutile o raccolgo qualcosa prima di rilanciare o lo
|
||||
// elimino
|
||||
//{
|
||||
// throw;
|
||||
// }
|
||||
// catch(...) // cosi' e' inutile o raccolgo qualcosa prima di rilanciare o lo
|
||||
// elimino
|
||||
//{
|
||||
// throw;
|
||||
// }
|
||||
|
||||
// if (regionsComputed) //WARNING !!! la seedFill mette il flag a ValidRegion a
|
||||
// TRUE
|
||||
// outVectImage->seedFill(); //le vecchie immagini hanno il seed
|
||||
// (version<3.1)
|
||||
// if (regionsComputed) //WARNING !!! la seedFill mette il flag a ValidRegion
|
||||
// a TRUE
|
||||
// outVectImage->seedFill(); //le vecchie immagini hanno il seed
|
||||
// (version<3.1)
|
||||
|
||||
#ifdef _DEBUG
|
||||
outVectImage->checkIntersections();
|
||||
|
@ -564,6 +564,9 @@ solo nel costruttore)
|
|||
PliTag *tag = new PrecisionScaleTag(precisionScale);
|
||||
tags.push_back((PliObjectTag *)tag);
|
||||
}
|
||||
|
||||
// update the format version if multiple suffixes is supported0
|
||||
if (!TFilePath::useStandard()) pli->setVersion(150, 0);
|
||||
// Store the auto close tolerance
|
||||
double pliTolerance = m_lwp->m_pli->getAutocloseTolerance();
|
||||
// write the tag if the frame's tolerance has been changed or
|
||||
|
@ -744,7 +747,7 @@ TPalette *readPalette(GroupTag *paletteTag, int majorVersion,
|
|||
// caricarli!
|
||||
|
||||
std::vector<TStyleParam> params(styleTag->m_numParams);
|
||||
for (int j = 0; j < styleTag->m_numParams; j++)
|
||||
for (int j = 0; j < styleTag->m_numParams; j++)
|
||||
params[j] = styleTag->m_param[j];
|
||||
|
||||
PliInputStream chan(¶ms, majorVersion, minorVersion);
|
||||
|
|
|
@ -190,7 +190,7 @@ TLevelWriterSprite::~TLevelWriterSprite() {
|
|||
//-----------------------------------------------------------
|
||||
|
||||
TImageWriterP TLevelWriterSprite::getFrameWriter(TFrameId fid) {
|
||||
if (fid.getLetter() != 0) return TImageWriterP(0);
|
||||
if (!fid.getLetter().isEmpty()) return TImageWriterP(0);
|
||||
int index = fid.getNumber();
|
||||
TImageWriterSprite *iwg = new TImageWriterSprite(m_path, index, this);
|
||||
return TImageWriterP(iwg);
|
||||
|
@ -265,9 +265,9 @@ void TLevelWriterSprite::save(const TImageP &img, int frameIndex) {
|
|||
m_top = t;
|
||||
m_bottom = b;
|
||||
} else {
|
||||
if (l < m_left) m_left = l;
|
||||
if (r > m_right) m_right = r;
|
||||
if (t < m_top) m_top = t;
|
||||
if (l < m_left) m_left = l;
|
||||
if (r > m_right) m_right = r;
|
||||
if (t < m_top) m_top = t;
|
||||
if (b > m_bottom) m_bottom = b;
|
||||
}
|
||||
QImage *newQi = new QImage(m_lx, m_ly, QImage::Format_ARGB32_Premultiplied);
|
||||
|
|
|
@ -25,8 +25,7 @@
|
|||
TNZ_LITTLE_ENDIAN undefined !!
|
||||
#endif
|
||||
|
||||
const int CURRENT_VERSION = 14;
|
||||
const int CREATOR_LENGTH = 40;
|
||||
const int CREATOR_LENGTH = 40;
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -40,6 +39,13 @@ char *reverse(char *buffer, int size) {
|
|||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// switch the saving version according to the file path property
|
||||
int currentVersion() {
|
||||
if (TFilePath::useStandard()) return 14;
|
||||
return 15;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
static int tfwrite(const char *data, const unsigned int count, FILE *f) {
|
||||
|
@ -138,6 +144,8 @@ bool readVersion(FILE *chan, int &version) {
|
|||
version = 13;
|
||||
} else if (memcmp(magic, "TLV14", 5) == 0) {
|
||||
version = 14;
|
||||
} else if (memcmp(magic, "TLV15", 5) == 0) {
|
||||
version = 15;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -162,7 +170,7 @@ bool readHeaderAndOffsets(FILE *chan, TzlOffsetMap &frameOffsTable,
|
|||
if (!readVersion(chan, version)) return false;
|
||||
|
||||
// read creator
|
||||
if (version == 14) {
|
||||
if (version >= 14) {
|
||||
char buffer[CREATOR_LENGTH + 1];
|
||||
memset(buffer, 0, sizeof buffer);
|
||||
fread(&buffer, sizeof(char), CREATOR_LENGTH, chan);
|
||||
|
@ -201,9 +209,18 @@ bool readHeaderAndOffsets(FILE *chan, TzlOffsetMap &frameOffsTable,
|
|||
TFrameId oldFid(TFrameId::EMPTY_FRAME);
|
||||
for (int i = 0; i < (int)frameCount; i++) {
|
||||
TINT32 number, offs, length;
|
||||
char letter;
|
||||
QByteArray suffix;
|
||||
fread(&number, sizeof(TINT32), 1, chan);
|
||||
fread(&letter, sizeof(char), 1, chan);
|
||||
if (version >= 15) {
|
||||
TINT32 suffixLength;
|
||||
fread(&suffixLength, sizeof(TINT32), 1, chan);
|
||||
suffix.resize(suffixLength);
|
||||
fread(suffix.data(), sizeof(char), suffixLength, chan);
|
||||
} else {
|
||||
char letter;
|
||||
fread(&letter, sizeof(char), 1, chan);
|
||||
suffix = QByteArray(&letter, 1);
|
||||
}
|
||||
fread(&offs, sizeof(TINT32), 1, chan);
|
||||
if (version >= 12) fread(&length, sizeof(TINT32), 1, chan);
|
||||
|
||||
|
@ -215,7 +232,7 @@ bool readHeaderAndOffsets(FILE *chan, TzlOffsetMap &frameOffsTable,
|
|||
// std::cout << "#" << i << std::hex << " n 0x" << number
|
||||
//<< " l 0x" << letter << " o 0x" << offs << std::dec << std::endl;
|
||||
|
||||
TFrameId fid(number, letter);
|
||||
TFrameId fid(number, QString::fromUtf8(suffix));
|
||||
// assert(i==0 || oldFid<fid);
|
||||
|
||||
if (version >= 12) {
|
||||
|
@ -241,9 +258,18 @@ bool readHeaderAndOffsets(FILE *chan, TzlOffsetMap &frameOffsTable,
|
|||
|
||||
for (int i = 0; i < (int)frameCount; i++) {
|
||||
TINT32 number, thumbnailOffs, thumbnailLength;
|
||||
char letter;
|
||||
QByteArray suffix;
|
||||
fread(&number, sizeof(TINT32), 1, chan);
|
||||
fread(&letter, sizeof(char), 1, chan);
|
||||
if (version >= 15) {
|
||||
TINT32 suffixLength;
|
||||
fread(&suffixLength, sizeof(TINT32), 1, chan);
|
||||
suffix.resize(suffixLength);
|
||||
fread(suffix.data(), sizeof(char), suffixLength, chan);
|
||||
} else {
|
||||
char letter;
|
||||
fread(&letter, sizeof(char), 1, chan);
|
||||
suffix = QByteArray(&letter, 1);
|
||||
}
|
||||
fread(&thumbnailOffs, sizeof(TINT32), 1, chan);
|
||||
fread(&thumbnailLength, sizeof(TINT32), 1, chan);
|
||||
|
||||
|
@ -252,7 +278,7 @@ bool readHeaderAndOffsets(FILE *chan, TzlOffsetMap &frameOffsTable,
|
|||
thumbnailOffs = swapTINT32(thumbnailOffs);
|
||||
thumbnailLength = swapTINT32(thumbnailLength);
|
||||
#endif
|
||||
TFrameId fid(number, letter);
|
||||
TFrameId fid(number, QString::fromUtf8(suffix));
|
||||
iconOffsTable[fid] = TzlChunk(thumbnailOffs, thumbnailLength);
|
||||
}
|
||||
}
|
||||
|
@ -460,7 +486,7 @@ void TLevelWriterTzl::buildFreeChunksTable() {
|
|||
// dati relativi alle immagini
|
||||
if (m_version == 13)
|
||||
curPos = 6 * sizeof(TINT32) + 4 * sizeof(char) + 8 * sizeof(char);
|
||||
else if (m_version == 14)
|
||||
else if (m_version >= 14)
|
||||
curPos = 6 * sizeof(TINT32) + 4 * sizeof(char) + 8 * sizeof(char) +
|
||||
CREATOR_LENGTH * sizeof(char);
|
||||
else
|
||||
|
@ -495,7 +521,7 @@ TLevelWriterTzl::TLevelWriterTzl(const TFilePath &path, TPropertyGroup *info)
|
|||
, m_palette(0)
|
||||
, m_res(0, 0)
|
||||
, m_exists(false)
|
||||
, m_version(CURRENT_VERSION)
|
||||
, m_version(currentVersion())
|
||||
, m_updatedIconsSize(false)
|
||||
, m_currentIconSize(0, 0)
|
||||
, m_iconSize(TDimension(80, 60))
|
||||
|
@ -506,13 +532,14 @@ TLevelWriterTzl::TLevelWriterTzl(const TFilePath &path, TPropertyGroup *info)
|
|||
m_path = path;
|
||||
m_palettePath = path.withNoFrame().withType("tpl");
|
||||
TFileStatus fs(path);
|
||||
m_magic = "TLV14B1a"; // actual version
|
||||
m_magic = (m_version == 14) ? "TLV14B1a" : "TLV15B1a"; // actual version
|
||||
erasedFrame = false;
|
||||
// version TLV10B1a: first version
|
||||
// version TLV11B1a: added frameIds
|
||||
// version TLV12B1a: incremental writings
|
||||
// version TLV13B1a: added thumbnails
|
||||
// version TLV15B1a: add creator string (fixed size = CREATOR_LENGTH char)
|
||||
// version TLV14B1a: add creator string (fixed size = CREATOR_LENGTH char)
|
||||
// version TLV15B1a: support multiple suffixes
|
||||
|
||||
if (fs.doesExist()) {
|
||||
// if (!fs.isWritable())
|
||||
|
@ -530,7 +557,7 @@ TLevelWriterTzl::TLevelWriterTzl(const TFilePath &path, TPropertyGroup *info)
|
|||
if (m_version >= 12) buildFreeChunksTable();
|
||||
m_headerWritten = true;
|
||||
m_exists = true;
|
||||
if (m_version == 14)
|
||||
if (m_version >= 14)
|
||||
m_frameCountPos = 8 + CREATOR_LENGTH + 3 * sizeof(TINT32);
|
||||
else
|
||||
m_frameCountPos = 8 + 3 * sizeof(TINT32);
|
||||
|
@ -555,9 +582,9 @@ TLevelWriterTzl::TLevelWriterTzl(const TFilePath &path, TPropertyGroup *info)
|
|||
//-------------------------------------------------------------------
|
||||
|
||||
TLevelWriterTzl::~TLevelWriterTzl() {
|
||||
if (m_version < CURRENT_VERSION) {
|
||||
if (m_version < currentVersion()) {
|
||||
if (!convertToLatestVersion()) return;
|
||||
assert(m_version == CURRENT_VERSION);
|
||||
assert(m_version == currentVersion());
|
||||
}
|
||||
delete m_codec;
|
||||
|
||||
|
@ -573,13 +600,18 @@ TLevelWriterTzl::~TLevelWriterTzl() {
|
|||
|
||||
TzlOffsetMap::iterator it = m_frameOffsTable.begin();
|
||||
for (; it != m_frameOffsTable.end(); ++it) {
|
||||
TFrameId fid = it->first;
|
||||
TINT32 num = fid.getNumber();
|
||||
char letter = fid.getLetter();
|
||||
TINT32 offs = it->second.m_offs;
|
||||
TINT32 length = it->second.m_length;
|
||||
TFrameId fid = it->first;
|
||||
TINT32 num = fid.getNumber();
|
||||
QByteArray suffix = fid.getLetter().toUtf8();
|
||||
TINT32 offs = it->second.m_offs;
|
||||
TINT32 length = it->second.m_length;
|
||||
tfwrite(&num, 1, m_chan);
|
||||
tfwrite(&letter, 1, m_chan);
|
||||
if (m_version >= 15) { // write the suffix length before data
|
||||
TINT32 suffixLength = suffix.size();
|
||||
tfwrite(&suffixLength, 1, m_chan);
|
||||
tfwrite(suffix.constData(), suffixLength, m_chan);
|
||||
} else // write only the first byte
|
||||
tfwrite(suffix.constData(), 1, m_chan);
|
||||
tfwrite(&offs, 1, m_chan);
|
||||
tfwrite(&length, 1, m_chan);
|
||||
}
|
||||
|
@ -593,11 +625,16 @@ TLevelWriterTzl::~TLevelWriterTzl() {
|
|||
for (; iconIt != m_iconOffsTable.end(); ++iconIt) {
|
||||
TFrameId fid = iconIt->first;
|
||||
TINT32 num = fid.getNumber();
|
||||
char letter = fid.getLetter();
|
||||
QByteArray suffix = fid.getLetter().toUtf8();
|
||||
TINT32 thumbnailOffs = iconIt->second.m_offs;
|
||||
TINT32 thumbnailLength = iconIt->second.m_length;
|
||||
tfwrite(&num, 1, m_chan);
|
||||
tfwrite(&letter, 1, m_chan);
|
||||
if (m_version >= 15) { // write the suffix length before data
|
||||
TINT32 suffixLength = suffix.size();
|
||||
tfwrite(&suffixLength, 1, m_chan);
|
||||
tfwrite(suffix.constData(), suffixLength, m_chan);
|
||||
} else // write only the first byte
|
||||
tfwrite(suffix.constData(), 1, m_chan);
|
||||
tfwrite(&thumbnailOffs, 1, m_chan);
|
||||
tfwrite(&thumbnailLength, 1, m_chan);
|
||||
}
|
||||
|
@ -774,7 +811,7 @@ bool TLevelWriterTzl::convertToLatestVersion() {
|
|||
if (!m_chan) return false;
|
||||
if (!writeVersionAndCreator(m_chan, m_magic, m_creator)) return false;
|
||||
m_creatorWritten = true;
|
||||
m_version = CURRENT_VERSION;
|
||||
m_version = currentVersion();
|
||||
TLevelReaderP lr(tempPath);
|
||||
if (!lr) return false;
|
||||
TLevelP level = lr->loadInfo();
|
||||
|
@ -798,13 +835,18 @@ bool TLevelWriterTzl::convertToLatestVersion() {
|
|||
|
||||
TzlOffsetMap::iterator it2 = m_frameOffsTable.begin();
|
||||
for (; it2 != m_frameOffsTable.end(); ++it2) {
|
||||
TFrameId fid = it2->first;
|
||||
TINT32 num = fid.getNumber();
|
||||
char letter = fid.getLetter();
|
||||
TINT32 offs = it2->second.m_offs;
|
||||
TINT32 length = it2->second.m_length;
|
||||
TFrameId fid = it2->first;
|
||||
TINT32 num = fid.getNumber();
|
||||
QByteArray suffix = fid.getLetter().toUtf8();
|
||||
TINT32 offs = it2->second.m_offs;
|
||||
TINT32 length = it2->second.m_length;
|
||||
tfwrite(&num, 1, m_chan);
|
||||
tfwrite(&letter, 1, m_chan);
|
||||
if (m_version >= 15) { // write the suffix length before data
|
||||
TINT32 suffixLength = suffix.size();
|
||||
tfwrite(&suffixLength, 1, m_chan);
|
||||
tfwrite(suffix.constData(), suffixLength, m_chan);
|
||||
} else // write only the first byte
|
||||
tfwrite(suffix.constData(), 1, m_chan);
|
||||
tfwrite(&offs, 1, m_chan);
|
||||
tfwrite(&length, 1, m_chan);
|
||||
}
|
||||
|
@ -816,11 +858,16 @@ bool TLevelWriterTzl::convertToLatestVersion() {
|
|||
for (; iconIt != m_iconOffsTable.end(); ++iconIt) {
|
||||
TFrameId fid = iconIt->first;
|
||||
TINT32 num = fid.getNumber();
|
||||
char letter = fid.getLetter();
|
||||
QByteArray suffix = fid.getLetter().toUtf8();
|
||||
TINT32 thumbnailOffs = iconIt->second.m_offs;
|
||||
TINT32 thumbnailLength = iconIt->second.m_length;
|
||||
tfwrite(&num, 1, m_chan);
|
||||
tfwrite(&letter, 1, m_chan);
|
||||
if (m_version >= 15) { // write the suffix length before data
|
||||
TINT32 suffixLength = suffix.size();
|
||||
tfwrite(&suffixLength, 1, m_chan);
|
||||
tfwrite(suffix.constData(), suffixLength, m_chan);
|
||||
} else // write only the first byte
|
||||
tfwrite(suffix.constData(), 1, m_chan);
|
||||
tfwrite(&thumbnailOffs, 1, m_chan);
|
||||
tfwrite(&thumbnailLength, 1, m_chan);
|
||||
}
|
||||
|
@ -856,7 +903,7 @@ bool TLevelWriterTzl::convertToLatestVersion() {
|
|||
m_headerWritten = true;
|
||||
m_exists = true;
|
||||
m_frameCountPos = 8 + CREATOR_LENGTH + 3 * sizeof(TINT32);
|
||||
assert(m_version == CURRENT_VERSION);
|
||||
assert(m_version == currentVersion());
|
||||
if (!m_renumberTable.empty()) renumberFids(m_renumberTable);
|
||||
return true;
|
||||
}
|
||||
|
@ -867,9 +914,9 @@ void TLevelWriterTzl::saveImage(const TImageP &img, const TFrameId &_fid,
|
|||
if (!m_chan) return;
|
||||
|
||||
// se il file è di una versione precedente allora lo converto prima
|
||||
if (m_version < CURRENT_VERSION) {
|
||||
if (m_version < currentVersion()) {
|
||||
if (!convertToLatestVersion()) return;
|
||||
assert(m_version == CURRENT_VERSION);
|
||||
assert(m_version == currentVersion());
|
||||
}
|
||||
|
||||
if (!m_updatedIconsSize && m_exists)
|
||||
|
@ -1348,7 +1395,7 @@ float TLevelWriterTzl::getFreeSpace() {
|
|||
if (m_version == 13)
|
||||
totalSpace = m_offsetTablePos - 6 * sizeof(TINT32) - 4 * sizeof(char) -
|
||||
8 * sizeof(char);
|
||||
else if (m_version == 14)
|
||||
else if (m_version >= 14)
|
||||
totalSpace = m_offsetTablePos - 6 * sizeof(TINT32) - 4 * sizeof(char) -
|
||||
8 * sizeof(char) - CREATOR_LENGTH * sizeof(char);
|
||||
assert(totalSpace > 0);
|
||||
|
@ -2285,6 +2332,10 @@ TImageP TImageReaderTzl::load() {
|
|||
if (!m_lrp->m_frameOffsTable.empty() && !m_lrp->m_iconOffsTable.empty())
|
||||
image = load14();
|
||||
break;
|
||||
case 15: // same as v14
|
||||
if (!m_lrp->m_frameOffsTable.empty() && !m_lrp->m_iconOffsTable.empty())
|
||||
image = load14();
|
||||
break;
|
||||
default:
|
||||
image = load10();
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ enum class PredefinedRect {
|
|||
BEGIN_EXTENDER, //! top / left extender
|
||||
KEYFRAME_AREA, //! part of cell dedicated to key frames
|
||||
DRAG_AREA, //! draggable side bar
|
||||
CELL_MARK_AREA, //! cell mark
|
||||
SOUND_TRACK, //! area dedicated to waveform display
|
||||
PREVIEW_TRACK, //! sound preview area
|
||||
BEGIN_SOUND_EDIT, //! top sound resize
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
// tcg includes
|
||||
#include "macros.h"
|
||||
#include <algorithm>
|
||||
|
||||
/*!
|
||||
\file tcg_poly_ops.h
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#define DVVAR DV_IMPORT_VAR
|
||||
#endif
|
||||
|
||||
class QString;
|
||||
#include <QString>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
|
@ -28,8 +28,8 @@ class QString;
|
|||
//! figures and, in case, by a character (necessary for added frames)
|
||||
class DVAPI TFrameId {
|
||||
int m_frame;
|
||||
char m_letter; // serve per i frame "aggiunti" del tipo pippo.0001a.tzp =>
|
||||
// f=1 c='a'
|
||||
QString m_letter; // serve per i frame "aggiunti" del tipo pippo.0001a.tzp =>
|
||||
// f=1 c='a'
|
||||
int m_zeroPadding;
|
||||
char m_startSeqInd;
|
||||
|
||||
|
@ -50,13 +50,13 @@ public:
|
|||
}; // pippo_1.tif
|
||||
|
||||
TFrameId(int f = EMPTY_FRAME)
|
||||
: m_frame(f), m_letter(0), m_zeroPadding(4), m_startSeqInd('.') {}
|
||||
TFrameId(int f, char c)
|
||||
: m_frame(f), m_letter(c), m_zeroPadding(4), m_startSeqInd('.') {}
|
||||
TFrameId(int f, char c, int p)
|
||||
: m_frame(f), m_letter(c), m_zeroPadding(p), m_startSeqInd('.') {}
|
||||
TFrameId(int f, char c, int p, char s)
|
||||
: m_frame(f), m_letter(c), m_zeroPadding(p), m_startSeqInd(s) {}
|
||||
: m_frame(f), m_letter(""), m_zeroPadding(4), m_startSeqInd('.') {}
|
||||
TFrameId(int f, char c, int p = 4, char s = '.')
|
||||
: m_frame(f), m_zeroPadding(p), m_startSeqInd(s) {
|
||||
m_letter = (c == '\0') ? "" : QString(c);
|
||||
}
|
||||
TFrameId(int f, QString str, int p = 4, char s = '.')
|
||||
: m_frame(f), m_letter(str), m_zeroPadding(p), m_startSeqInd(s) {}
|
||||
|
||||
inline bool operator==(const TFrameId &f) const {
|
||||
return f.m_frame == m_frame && f.m_letter == m_letter;
|
||||
|
@ -66,7 +66,8 @@ public:
|
|||
}
|
||||
inline bool operator<(const TFrameId &f) const {
|
||||
return (m_frame < f.m_frame ||
|
||||
(m_frame == f.m_frame && m_letter < f.m_letter));
|
||||
(m_frame == f.m_frame &&
|
||||
QString::localeAwareCompare(m_letter, f.m_letter) < 0));
|
||||
}
|
||||
inline bool operator>(const TFrameId &f) const { return f < *this; }
|
||||
inline bool operator>=(const TFrameId &f) const { return !operator<(f); }
|
||||
|
@ -89,7 +90,7 @@ public:
|
|||
// operator string() const;
|
||||
std::string expand(FrameFormat format = FOUR_ZEROS) const;
|
||||
int getNumber() const { return m_frame; }
|
||||
char getLetter() const { return m_letter; }
|
||||
QString getLetter() const { return m_letter; }
|
||||
|
||||
void setZeroPadding(int p) { m_zeroPadding = p; }
|
||||
int getZeroPadding() const { return m_zeroPadding; }
|
||||
|
@ -132,7 +133,23 @@ inline std::ostream &operator<<(std::ostream &out, const TFrameId &f) {
|
|||
constructor.*/
|
||||
class DVAPI TFilePath {
|
||||
static bool m_underscoreFormatAllowed;
|
||||
|
||||
// specifies file path condition for sequential image for each project.
|
||||
// See filepathproperties.h
|
||||
static bool m_useStandard;
|
||||
static bool m_acceptNonAlphabetSuffix;
|
||||
static int m_letterCountForSuffix;
|
||||
|
||||
std::wstring m_path;
|
||||
|
||||
struct TFilePathInfo {
|
||||
QString parentDir; // with slash
|
||||
QString levelName;
|
||||
QChar sepChar; // either "." or "_"
|
||||
TFrameId fId;
|
||||
QString extension;
|
||||
};
|
||||
|
||||
void setPath(std::wstring path);
|
||||
|
||||
public:
|
||||
|
@ -142,6 +159,23 @@ public:
|
|||
m_underscoreFormatAllowed = state;
|
||||
}
|
||||
|
||||
// called from TProjectManager::getCurrentProject() and
|
||||
// ProjectPopup::updateProjectFromFields
|
||||
// returns true if something changed
|
||||
static bool setFilePathProperties(bool useStandard, bool acceptNonAlphaSuffix,
|
||||
int letterCountForSuffix) {
|
||||
if (m_useStandard == useStandard &&
|
||||
m_acceptNonAlphabetSuffix == acceptNonAlphaSuffix &&
|
||||
m_letterCountForSuffix == letterCountForSuffix)
|
||||
return false;
|
||||
m_useStandard = useStandard;
|
||||
m_acceptNonAlphabetSuffix = acceptNonAlphaSuffix;
|
||||
m_letterCountForSuffix = letterCountForSuffix;
|
||||
return true;
|
||||
}
|
||||
static bool useStandard() { return m_useStandard; }
|
||||
static QString fidRegExpStr();
|
||||
|
||||
/*!This constructor creates a string removing redundances ('//', './',etc.)
|
||||
and final slashes,
|
||||
correcting (redressing) the "twisted" slashes.
|
||||
|
@ -191,6 +225,7 @@ If the path is "<alpha>:" a slash will be added*/
|
|||
std::string getType() const {
|
||||
return getUndottedType();
|
||||
} // ritorna l'estensione SENZA PUNTO
|
||||
|
||||
/*!Returns the base filename (no extension, no dots, no slash)*/
|
||||
std::string getName() const; // noDot! noSlash!
|
||||
std::wstring getWideName() const; // noDot! noSlash!
|
||||
|
@ -274,6 +309,8 @@ type is a string that indicate the filename extension(ex:. bmp or .bmp)*/
|
|||
|
||||
// '/a/b/c.txt' => head='a' tail='b/c.txt'
|
||||
void split(std::wstring &head, TFilePath &tail) const;
|
||||
|
||||
TFilePathInfo analyzePath() const;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -160,6 +160,12 @@ public:
|
|||
/*--- オフセットを軸ごとにロックする ---*/
|
||||
bool m_offx_lock, m_offy_lock;
|
||||
|
||||
// hold brightness and contrast values for each line processing modes (grey
|
||||
// and color).
|
||||
double m_altBrightness, m_altContrast;
|
||||
// exporting file format when Line Processing = None
|
||||
std::string m_lpNoneFormat;
|
||||
|
||||
public:
|
||||
CleanupParameters();
|
||||
CleanupParameters(const CleanupParameters &p) { assign(&p); }
|
||||
|
|
49
toonz/sources/include/toonz/filepathproperties.h
Normal file
49
toonz/sources/include/toonz/filepathproperties.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef FILEPATHPROPERTIES_H
|
||||
#define FILEPATHPROPERTIES_H
|
||||
|
||||
#include "tcommon.h"
|
||||
|
||||
#undef DVAPI
|
||||
#undef DVVAR
|
||||
#ifdef TOONZLIB_EXPORTS
|
||||
#define DVAPI DV_EXPORT_API
|
||||
#define DVVAR DV_EXPORT_VAR
|
||||
#else
|
||||
#define DVAPI DV_IMPORT_API
|
||||
#define DVVAR DV_IMPORT_VAR
|
||||
#endif
|
||||
//=============================================================================
|
||||
// forward declarations
|
||||
class TIStream;
|
||||
class TOStream;
|
||||
|
||||
//=============================================================================
|
||||
// FilePathProperties
|
||||
// This class defines file path condition for sequential image level
|
||||
|
||||
class DVAPI FilePathProperties {
|
||||
bool m_useStandard;
|
||||
bool m_acceptNonAlphabetSuffix;
|
||||
int m_letterCountForSuffix;
|
||||
|
||||
public:
|
||||
FilePathProperties();
|
||||
|
||||
bool useStandard() { return m_useStandard; }
|
||||
void setUseStandard(bool on) { m_useStandard = on; }
|
||||
|
||||
bool acceptNonAlphabetSuffix() { return m_acceptNonAlphabetSuffix; }
|
||||
void setAcceptNonAlphabetSuffix(bool on) { m_acceptNonAlphabetSuffix = on; }
|
||||
|
||||
int letterCountForSuffix() { return m_letterCountForSuffix; }
|
||||
void setLetterCountForSuffix(int val) { m_letterCountForSuffix = val; }
|
||||
|
||||
void saveData(TOStream& os) const;
|
||||
void loadData(TIStream& is);
|
||||
|
||||
bool isDefault();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -49,6 +49,11 @@ class DVAPI TSceneProperties {
|
|||
public:
|
||||
typedef std::vector<double> Guides;
|
||||
|
||||
struct CellMark {
|
||||
QString name;
|
||||
TPixel32 color;
|
||||
};
|
||||
|
||||
private:
|
||||
Guides m_hGuides, m_vGuides;
|
||||
|
||||
|
@ -73,6 +78,9 @@ private:
|
|||
//! Xsheet Note Color, color number = 7.
|
||||
QList<TPixel32> m_notesColor;
|
||||
|
||||
// Cell Mark colors and names
|
||||
QList<CellMark> m_cellMarks;
|
||||
|
||||
bool m_columnColorFilterOnRender;
|
||||
TFilePath m_camCapSaveInPath;
|
||||
|
||||
|
@ -274,6 +282,12 @@ and height.
|
|||
TPixel32 getNoteColor(int colorIndex) const;
|
||||
void setNoteColor(TPixel32 color, int colorIndex);
|
||||
|
||||
QList<CellMark> getCellMarks() const;
|
||||
CellMark getCellMark(int index) const;
|
||||
void setCellMark(const CellMark &mark, int index);
|
||||
bool hasDefaultCellMarks()
|
||||
const; // check if the cell mark settings are modified
|
||||
|
||||
private:
|
||||
// not implemented
|
||||
TSceneProperties(const TSceneProperties &);
|
||||
|
|
|
@ -89,10 +89,11 @@ time, to unlock a possibly useful memory block.
|
|||
*/
|
||||
CleanupPreprocessedImage *process(TRasterImageP &image, bool first_image,
|
||||
TRasterImageP &onlyResampledImage,
|
||||
bool isCameraTest = false,
|
||||
bool returnResampled = false,
|
||||
bool onlyForSwatch = false,
|
||||
TAffine *aff = 0);
|
||||
bool isCameraTest = false,
|
||||
bool returnResampled = false,
|
||||
bool onlyForSwatch = false,
|
||||
TAffine *aff = 0,
|
||||
TRasterP templateForResampled = 0);
|
||||
|
||||
void finalize(const TRaster32P &dst, CleanupPreprocessedImage *src);
|
||||
TToonzImageP finalize(CleanupPreprocessedImage *src,
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
class ToonzScene;
|
||||
class TSceneProperties;
|
||||
class FilePathProperties;
|
||||
|
||||
#undef DVAPI
|
||||
#undef DVVAR
|
||||
|
@ -28,6 +29,8 @@ class DVAPI TProject final : public TSmartObject {
|
|||
bool m_useSubScenePath;
|
||||
TSceneProperties *m_sprop;
|
||||
|
||||
FilePathProperties *m_fpProp;
|
||||
|
||||
public:
|
||||
// default folders names
|
||||
static const std::string Inputs;
|
||||
|
@ -70,6 +73,8 @@ public:
|
|||
void setSceneProperties(const TSceneProperties &sprop);
|
||||
const TSceneProperties &getSceneProperties() const { return *m_sprop; }
|
||||
|
||||
FilePathProperties *getFilePathProperties() const { return m_fpProp; }
|
||||
|
||||
//?????????????????????????????????????????????
|
||||
void setUseScenePath(std::string folderName, bool on);
|
||||
//?????????????????????????????????????????????
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <QPair>
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
|
||||
#undef DVAPI
|
||||
#undef DVVAR
|
||||
|
@ -304,6 +305,9 @@ protected:
|
|||
std::vector<TXshCell> m_cells;
|
||||
int m_first;
|
||||
|
||||
// cell marks information key:frame value:id
|
||||
QMap<int, int> m_cellMarkIds;
|
||||
|
||||
public:
|
||||
/*!
|
||||
Constructs a TXshCellColumn with default value.
|
||||
|
@ -398,6 +402,13 @@ last row with not empty cell of same level.
|
|||
bool getLevelRange(int row, int &r0, int &r1) const override;
|
||||
|
||||
// virtual void updateIcon() = 0;
|
||||
|
||||
void saveCellMarks(TOStream &os);
|
||||
bool loadCellMarks(std::string tagName, TIStream &is);
|
||||
void setCellMark(int frame, int id);
|
||||
int getCellMark(int frame) const;
|
||||
QMap<int, int> getCellMarks() const;
|
||||
void clearCellMarks();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -442,8 +442,9 @@ frame duplication.
|
|||
|
||||
// cutomized exposseLevel used from LoadLevel command
|
||||
int exposeLevel(int row, int col, TXshLevel *xl, std::vector<TFrameId> &fIds_,
|
||||
int xFrom = -1, int xTo = -1, int step = -1, int inc = -1,
|
||||
int frameCount = -1, bool doesFileActuallyExist = true);
|
||||
TFrameId xFrom = TFrameId(), TFrameId xTo = TFrameId(),
|
||||
int step = -1, int inc = -1, int frameCount = -1,
|
||||
bool doesFileActuallyExist = true);
|
||||
|
||||
/*! Exposes level \b \e xl \b \e fids in xsheet starting from cell identified
|
||||
* by \b \e row and \b \e col.
|
||||
|
|
|
@ -202,7 +202,8 @@ table) it returns the proper insertion index
|
|||
// load icon (and image) data of all frames into cache
|
||||
void loadAllIconsAndPutInCache(bool cacheImagesAsWell);
|
||||
|
||||
TRasterImageP getFrameToCleanup(const TFrameId &fid) const;
|
||||
TRasterImageP getFrameToCleanup(const TFrameId &fid,
|
||||
bool toBeLineProcessed) const;
|
||||
|
||||
std::string getImageId(const TFrameId &fid, int frameStatus = -1) const;
|
||||
std::string getIconId(const TFrameId &fid, int frameStatus = -1) const;
|
||||
|
|
|
@ -65,7 +65,8 @@ enum CommandType {
|
|||
MiscCommandType,
|
||||
MenuCommandType,
|
||||
VisualizationButtonCommandType,
|
||||
StopMotionCommandType
|
||||
StopMotionCommandType,
|
||||
CellMarkCommandType
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -160,19 +160,24 @@ QString fidsToString(const std::vector<TFrameId> &fids,
|
|||
} else {
|
||||
bool beginBlock = true;
|
||||
for (int f = 0; f < fids.size() - 1; f++) {
|
||||
int num = fids[f].getNumber();
|
||||
int next_num = fids[f + 1].getNumber();
|
||||
if (num + 1 == next_num) {
|
||||
int num = fids[f].getNumber();
|
||||
QString letter = fids[f].getLetter();
|
||||
int next_num = fids[f + 1].getNumber();
|
||||
QString next_letter = fids[f + 1].getLetter();
|
||||
|
||||
if (num + 1 == next_num && letter.isEmpty() && next_letter.isEmpty()) {
|
||||
if (beginBlock) {
|
||||
retStr += QString::number(num) + " - ";
|
||||
beginBlock = false;
|
||||
}
|
||||
} else {
|
||||
retStr += QString::number(num) + ", ";
|
||||
retStr += QString::number(num);
|
||||
if (!letter.isEmpty()) retStr += letter;
|
||||
retStr += ", ";
|
||||
beginBlock = true;
|
||||
}
|
||||
}
|
||||
retStr += QString::number(fids.back().getNumber());
|
||||
if (!fids.back().getLetter().isEmpty()) retStr += fids.back().getLetter();
|
||||
}
|
||||
return retStr;
|
||||
}
|
||||
|
|
|
@ -666,42 +666,46 @@ void StopMotionSaveInFolderPopup::updateParentFolder() {
|
|||
|
||||
//=============================================================================
|
||||
|
||||
FrameNumberLineEdit::FrameNumberLineEdit(QWidget *parent, int value)
|
||||
FrameNumberLineEdit::FrameNumberLineEdit(QWidget* parent, TFrameId fId,
|
||||
bool acceptLetter)
|
||||
: LineEdit(parent) {
|
||||
setFixedWidth(54);
|
||||
m_intValidator = new QIntValidator(this);
|
||||
setValue(value);
|
||||
m_intValidator->setRange(1, 9999);
|
||||
setFixedWidth(60);
|
||||
if (acceptLetter) {
|
||||
QString regExpStr = QString("^%1$").arg(TFilePath::fidRegExpStr());
|
||||
m_regexpValidator = new QRegExpValidator(QRegExp(regExpStr), this);
|
||||
TProjectManager* pm = TProjectManager::instance();
|
||||
pm->addListener(this);
|
||||
} else
|
||||
m_regexpValidator = new QRegExpValidator(QRegExp("^\\d{1,4}$"), this);
|
||||
|
||||
QRegExp rx("^[0-9]{1,4}[A-Ia-i]?$");
|
||||
m_regexpValidator = new QRegExpValidator(rx, this);
|
||||
m_regexpValidator_alt =
|
||||
new QRegExpValidator(QRegExp("^\\d{1,3}[A-Ia-i]?$"), this);
|
||||
|
||||
updateValidator();
|
||||
|
||||
setValue(fId);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FrameNumberLineEdit::updateValidator() {
|
||||
if (Preferences::instance()->isShowFrameNumberWithLettersEnabled())
|
||||
setValidator(m_regexpValidator);
|
||||
setValidator(m_regexpValidator_alt);
|
||||
else
|
||||
setValidator(m_intValidator);
|
||||
setValidator(m_regexpValidator);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FrameNumberLineEdit::setValue(int value) {
|
||||
if (value <= 0)
|
||||
value = 1;
|
||||
else if (value > 9999)
|
||||
value = 9999;
|
||||
|
||||
void FrameNumberLineEdit::setValue(TFrameId fId) {
|
||||
QString str;
|
||||
if (Preferences::instance()->isShowFrameNumberWithLettersEnabled()) {
|
||||
str = convertToFrameWithLetter(value, 3);
|
||||
if (!fId.getLetter().isEmpty()) {
|
||||
// need some warning?
|
||||
}
|
||||
str = convertToFrameWithLetter(fId.getNumber(), 3);
|
||||
} else {
|
||||
str.setNum(value);
|
||||
while (str.length() < 4) str.push_front("0");
|
||||
str = QString::fromStdString(fId.expand());
|
||||
}
|
||||
setText(str);
|
||||
setCursorPosition(0);
|
||||
|
@ -709,22 +713,44 @@ void FrameNumberLineEdit::setValue(int value) {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int FrameNumberLineEdit::getValue() {
|
||||
TFrameId FrameNumberLineEdit::getValue() {
|
||||
if (Preferences::instance()->isShowFrameNumberWithLettersEnabled()) {
|
||||
QString str = text();
|
||||
int f;
|
||||
// if no letters added
|
||||
if (str.at(str.size() - 1).isDigit())
|
||||
return str.toInt() * 10;
|
||||
f = str.toInt() * 10;
|
||||
else {
|
||||
return str.left(str.size() - 1).toInt() * 10 +
|
||||
letterToNum(str.at(str.size() - 1));
|
||||
f = str.left(str.size() - 1).toInt() * 10 +
|
||||
letterToNum(str.at(str.size() - 1));
|
||||
}
|
||||
} else
|
||||
return text().toInt();
|
||||
return TFrameId(f);
|
||||
} else {
|
||||
QString regExpStr = QString("^%1$").arg(TFilePath::fidRegExpStr());
|
||||
QRegExp rx(regExpStr);
|
||||
int pos = rx.indexIn(text());
|
||||
if (pos < 0) return TFrameId();
|
||||
if (rx.cap(2).isEmpty())
|
||||
return TFrameId(rx.cap(1).toInt());
|
||||
else
|
||||
return TFrameId(rx.cap(1).toInt(), rx.cap(2));
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FrameNumberLineEdit::onProjectSwitched() {
|
||||
QRegExpValidator* oldValidator = m_regexpValidator;
|
||||
QString regExpStr = QString("^%1$").arg(TFilePath::fidRegExpStr());
|
||||
m_regexpValidator = new QRegExpValidator(QRegExp(regExpStr), this);
|
||||
updateValidator();
|
||||
if (oldValidator) delete oldValidator;
|
||||
}
|
||||
|
||||
void FrameNumberLineEdit::onProjectChanged() { onProjectSwitched(); }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FrameNumberLineEdit::focusInEvent(QFocusEvent *e) {
|
||||
m_textOnFocusIn = text();
|
||||
}
|
||||
|
@ -3578,7 +3604,7 @@ void StopMotionController::onFileTypeActivated() {
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
void StopMotionController::onFrameNumberChanged() {
|
||||
m_stopMotion->setFrameNumber(m_frameNumberEdit->getValue());
|
||||
m_stopMotion->setFrameNumber(m_frameNumberEdit->getValue().getNumber());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
#include "toonzqt/dvdialog.h"
|
||||
#include "toonzqt/lineedit.h"
|
||||
|
||||
#include "tfilepath.h"
|
||||
#include "toonz/tproject.h"
|
||||
|
||||
// TnzQt includes
|
||||
#include "toonzqt/tabbar.h"
|
||||
#include "toonzqt/gutil.h"
|
||||
|
@ -69,23 +72,28 @@ class IntLineEdit;
|
|||
// "Show ABC Appendix to the Frame Number in Xsheet Cell" is active.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class FrameNumberLineEdit : public DVGui::LineEdit {
|
||||
class FrameNumberLineEdit : public DVGui::LineEdit,
|
||||
public TProjectManager::Listener {
|
||||
Q_OBJECT
|
||||
/* having two validators and switch them according to the preferences*/
|
||||
QIntValidator *m_intValidator;
|
||||
QRegExpValidator *m_regexpValidator;
|
||||
QRegExpValidator *m_regexpValidator, *m_regexpValidator_alt;
|
||||
|
||||
void updateValidator();
|
||||
QString m_textOnFocusIn;
|
||||
|
||||
public:
|
||||
FrameNumberLineEdit(QWidget *parent = 0, int value = 1);
|
||||
FrameNumberLineEdit(QWidget* parent = 0, TFrameId fId = TFrameId(1),
|
||||
bool acceptLetter = true);
|
||||
~FrameNumberLineEdit() {}
|
||||
|
||||
/*! Set text in field to \b value. */
|
||||
void setValue(int value);
|
||||
void setValue(TFrameId fId);
|
||||
/*! Return an integer with text field value. */
|
||||
int getValue();
|
||||
TFrameId getValue();
|
||||
|
||||
// TProjectManager::Listener
|
||||
void onProjectSwitched() override;
|
||||
void onProjectChanged() override;
|
||||
|
||||
protected:
|
||||
/*! If focus is lost and current text value is out of range emit signal
|
||||
|
|
|
@ -411,7 +411,10 @@ static void cleanupLevel(TXshSimpleLevel *xl, std::set<TFrameId> fidsInXsheet,
|
|||
QString::fromStdString(fid.expand()));
|
||||
continue;
|
||||
}
|
||||
TRasterImageP original = xl->getFrameToCleanup(fid);
|
||||
CleanupParameters *params = scene->getProperties()->getCleanupParameters();
|
||||
// if lines are not processed, obtain the original sampled image
|
||||
bool toBeLineProcessed = params->m_lineProcessingMode != lpNone;
|
||||
TRasterImageP original = xl->getFrameToCleanup(fid, toBeLineProcessed);
|
||||
if (!original) {
|
||||
string err = " *error* missed frame";
|
||||
m_userLog.error(err);
|
||||
|
@ -419,11 +422,9 @@ static void cleanupLevel(TXshSimpleLevel *xl, std::set<TFrameId> fidsInXsheet,
|
|||
continue;
|
||||
}
|
||||
|
||||
CleanupParameters *params = scene->getProperties()->getCleanupParameters();
|
||||
|
||||
if (params->m_lineProcessingMode == lpNone) {
|
||||
TRasterImageP ri;
|
||||
if (params->m_autocenterType == CleanupTypes::AUTOCENTER_NONE)
|
||||
TRasterImageP ri(original);
|
||||
/*if (params->m_autocenterType == CleanupTypes::AUTOCENTER_NONE)
|
||||
ri = original;
|
||||
else {
|
||||
bool autocentered;
|
||||
|
@ -432,7 +433,9 @@ static void cleanupLevel(TXshSimpleLevel *xl, std::set<TFrameId> fidsInXsheet,
|
|||
m_userLog.error("The autocentering failed on the current drawing.");
|
||||
cout << "The autocentering failed on the current drawing." << endl;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
cl->process(original, false, ri, false, true, true, nullptr,
|
||||
ri->getRaster());
|
||||
updater.update(fid, ri);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -102,8 +102,8 @@ TFrameId getNewFrameId(TXshSimpleLevel *sl, int row) {
|
|||
TFrameId fid(row + 1);
|
||||
if (sl->isFid(fid)) {
|
||||
fid = TFrameId(fid.getNumber(), 'a');
|
||||
while (fid.getLetter() < 'z' && sl->isFid(fid))
|
||||
fid = TFrameId(fid.getNumber(), fid.getLetter() + 1);
|
||||
while (fid.getLetter().toUtf8().at(0) < 'z' && sl->isFid(fid))
|
||||
fid = TFrameId(fid.getNumber(), fid.getLetter().toUtf8().at(0) + 1);
|
||||
}
|
||||
return fid;
|
||||
}
|
||||
|
@ -123,9 +123,15 @@ TFrameId getDesiredFId(TXshCellColumn *column, int r0, TXshSimpleLevel *sl,
|
|||
if (neighborFId.isEmptyFrame()) neighborFId = tmpFId;
|
||||
if (maxFId < tmpFId) maxFId = tmpFId;
|
||||
}
|
||||
if (maxFId.getLetter() && maxFId.getLetter() < 'z' && maxFId == neighborFId)
|
||||
return TFrameId(maxFId.getNumber(), maxFId.getLetter() + 1);
|
||||
else
|
||||
|
||||
QByteArray suffix = maxFId.getLetter().toUtf8();
|
||||
// increment letter
|
||||
if (suffix.size() == 1 &&
|
||||
((suffix.at(0) >= 'A' && suffix.at(0) < 'Z') ||
|
||||
(suffix.at(0) >= 'a' && suffix.at(0) < 'z')) &&
|
||||
maxFId == neighborFId) {
|
||||
return TFrameId(maxFId.getNumber(), suffix.at(0) + 1);
|
||||
} else
|
||||
return TFrameId(maxFId.getNumber() + 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -1827,6 +1827,15 @@ bool ToolUtils::doUpdateXSheet(TXshSimpleLevel *sl,
|
|||
|
||||
bool ToolUtils::renumberForInsertFId(TXshSimpleLevel *sl, const TFrameId &fid,
|
||||
const TFrameId &maxFid, TXsheet *xsh) {
|
||||
auto getNextLetter = [](const QString &letter) {
|
||||
if (letter.isEmpty()) return QString('a');
|
||||
if (letter == 'z' || letter == 'Z') return QString();
|
||||
QByteArray byteArray = letter.toUtf8();
|
||||
// return incrementing the last letter
|
||||
byteArray.data()[byteArray.size() - 1]++;
|
||||
return QString::fromUtf8(byteArray);
|
||||
};
|
||||
|
||||
std::vector<TFrameId> fids;
|
||||
std::vector<TFrameId> oldFrames;
|
||||
sl->getFids(oldFrames);
|
||||
|
@ -1840,10 +1849,10 @@ bool ToolUtils::renumberForInsertFId(TXshSimpleLevel *sl, const TFrameId &fid,
|
|||
for (auto itr = fidsSet.upper_bound(maxFid); itr != fidsSet.end(); ++itr) {
|
||||
if (*itr > tmpFid) break;
|
||||
fIdsToBeShifted.push_back(*itr);
|
||||
if (fid.getLetter()) {
|
||||
if ((*itr).getLetter() < 'z')
|
||||
tmpFid = TFrameId((*itr).getNumber(),
|
||||
((*itr).getLetter()) ? (*itr).getLetter() + 1 : 'a');
|
||||
if (!fid.getLetter().isEmpty()) {
|
||||
QString nextLetter = getNextLetter((*itr).getLetter());
|
||||
if (!nextLetter.isEmpty())
|
||||
tmpFid = TFrameId((*itr).getNumber(), nextLetter);
|
||||
else
|
||||
tmpFid = TFrameId((*itr).getNumber() + 1);
|
||||
} else
|
||||
|
@ -1854,11 +1863,10 @@ bool ToolUtils::renumberForInsertFId(TXshSimpleLevel *sl, const TFrameId &fid,
|
|||
|
||||
for (TFrameId &tmpFid : fids) {
|
||||
if (fIdsToBeShifted.contains(tmpFid)) {
|
||||
if (fid.getLetter()) {
|
||||
if (tmpFid.getLetter() < 'z')
|
||||
tmpFid =
|
||||
TFrameId(tmpFid.getNumber(),
|
||||
(tmpFid.getLetter()) ? tmpFid.getLetter() + 1 : 'a');
|
||||
if (!fid.getLetter().isEmpty()) {
|
||||
QString nextLetter = getNextLetter(tmpFid.getLetter());
|
||||
if (!nextLetter.isEmpty())
|
||||
tmpFid = TFrameId(tmpFid.getNumber(), nextLetter);
|
||||
else
|
||||
tmpFid = TFrameId(tmpFid.getNumber() + 1);
|
||||
} else
|
||||
|
|
|
@ -66,29 +66,46 @@ AudioRecordingPopup::AudioRecordingPopup()
|
|||
m_saveButton = new QPushButton(tr("Save and Insert"));
|
||||
m_pauseRecordingButton = new QPushButton(this);
|
||||
m_pausePlaybackButton = new QPushButton(this);
|
||||
// m_refreshDevicesButton = new QPushButton(tr("Refresh"));
|
||||
m_duration = new QLabel("00:00");
|
||||
m_playDuration = new QLabel("00:00");
|
||||
m_refreshDevicesButton = new QPushButton(this);
|
||||
m_duration = new QLabel("00:00.000");
|
||||
m_playDuration = new QLabel("00:00.000");
|
||||
m_deviceListCB = new QComboBox();
|
||||
m_audioLevelsDisplay = new AudioLevelsDisplay(this);
|
||||
m_playXSheetCB = new QCheckBox(tr("Sync with Scene"), this);
|
||||
m_playXSheetCB = new QCheckBox(tr("Sync with XSheet/Timeline"), this);
|
||||
m_timer = new QElapsedTimer();
|
||||
m_recordedLevels = QMap<qint64, double>();
|
||||
m_oldElapsed = 0;
|
||||
m_probe = new QAudioProbe;
|
||||
m_player = new QMediaPlayer(this);
|
||||
m_console = FlipConsole::getCurrent();
|
||||
m_audioRecorder = new QAudioRecorder;
|
||||
|
||||
m_recordButton->setMaximumWidth(25);
|
||||
m_playButton->setMaximumWidth(25);
|
||||
m_pauseRecordingButton->setMaximumWidth(25);
|
||||
m_pausePlaybackButton->setMaximumWidth(25);
|
||||
m_labelDevice = new QLabel(tr("Device: "));
|
||||
m_labelSamplerate = new QLabel(tr("Sample rate: "));
|
||||
m_labelSamplefmt = new QLabel(tr("Sample format: "));
|
||||
m_comboSamplerate = new QComboBox();
|
||||
m_comboSamplefmt = new QComboBox();
|
||||
m_comboSamplerate->addItem(tr("8000 Hz"), QVariant::fromValue(8000));
|
||||
m_comboSamplerate->addItem(tr("11025 Hz"), QVariant::fromValue(11025));
|
||||
m_comboSamplerate->addItem(tr("22050 Hz"), QVariant::fromValue(22050));
|
||||
m_comboSamplerate->addItem(tr("44100 Hz"), QVariant::fromValue(44100));
|
||||
m_comboSamplerate->addItem(tr("48000 Hz"), QVariant::fromValue(48000));
|
||||
m_comboSamplerate->addItem(tr("96000 Hz"), QVariant::fromValue(96000));
|
||||
m_comboSamplerate->setCurrentIndex(3); // 44.1KHz
|
||||
m_comboSamplefmt->addItem(tr("Mono 8-Bits"), QVariant::fromValue(9));
|
||||
m_comboSamplefmt->addItem(tr("Stereo 8-Bits"), QVariant::fromValue(10));
|
||||
m_comboSamplefmt->addItem(tr("Mono 16-Bits"), QVariant::fromValue(17));
|
||||
m_comboSamplefmt->addItem(tr("Stereo 16-Bits"), QVariant::fromValue(18));
|
||||
m_comboSamplefmt->setCurrentIndex(2); // Mono 16-Bits
|
||||
|
||||
m_recordButton->setMaximumWidth(32);
|
||||
m_playButton->setMaximumWidth(32);
|
||||
m_pauseRecordingButton->setMaximumWidth(32);
|
||||
m_pausePlaybackButton->setMaximumWidth(32);
|
||||
m_refreshDevicesButton->setMaximumWidth(25);
|
||||
|
||||
QString playDisabled = QString(":Resources/play_disabled.svg");
|
||||
QString pauseDisabled = QString(":Resources/pause_disabled.svg");
|
||||
QString stopDisabled = QString(":Resources/stop_disabled.svg");
|
||||
QString recordDisabled = QString(":Resources/record_disabled.svg");
|
||||
QString refreshDisabled = QString(":Resources/repeat_icon.svg");
|
||||
|
||||
m_pauseIcon = createQIcon("pause");
|
||||
m_pauseIcon.addFile(pauseDisabled, QSize(), QIcon::Disabled);
|
||||
|
@ -98,6 +115,9 @@ AudioRecordingPopup::AudioRecordingPopup()
|
|||
m_recordIcon.addFile(recordDisabled, QSize(), QIcon::Disabled);
|
||||
m_stopIcon = createQIcon("stop");
|
||||
m_stopIcon.addFile(stopDisabled, QSize(), QIcon::Disabled);
|
||||
m_refreshIcon = createQIcon("repeat");
|
||||
m_refreshIcon.addFile(refreshDisabled, QSize(), QIcon::Disabled);
|
||||
|
||||
m_pauseRecordingButton->setIcon(m_pauseIcon);
|
||||
m_pauseRecordingButton->setIconSize(QSize(17, 17));
|
||||
m_playButton->setIcon(m_playIcon);
|
||||
|
@ -106,12 +126,32 @@ AudioRecordingPopup::AudioRecordingPopup()
|
|||
m_recordButton->setIconSize(QSize(17, 17));
|
||||
m_pausePlaybackButton->setIcon(m_pauseIcon);
|
||||
m_pausePlaybackButton->setIconSize(QSize(17, 17));
|
||||
m_refreshDevicesButton->setIcon(m_refreshIcon);
|
||||
m_refreshDevicesButton->setIconSize(QSize(17, 17));
|
||||
|
||||
QStringList inputs = m_audioRecorder->audioInputs();
|
||||
m_deviceListCB->addItems(inputs);
|
||||
QString selectedInput = m_audioRecorder->defaultAudioInput();
|
||||
m_deviceListCB->setCurrentText(selectedInput);
|
||||
m_audioRecorder->setAudioInput(selectedInput);
|
||||
// Enumerate devices and initialize default device
|
||||
enumerateAudioDevices("");
|
||||
QAudioDeviceInfo m_audioDeviceInfo = QAudioDeviceInfo::defaultInputDevice();
|
||||
QAudioFormat format;
|
||||
format.setSampleRate(44100);
|
||||
format.setChannelCount(1);
|
||||
format.setSampleSize(16);
|
||||
format.setSampleType(QAudioFormat::SignedInt);
|
||||
format.setByteOrder(QAudioFormat::LittleEndian);
|
||||
format.setCodec("audio/pcm");
|
||||
if (!m_audioDeviceInfo.isFormatSupported(format)) {
|
||||
format = m_audioDeviceInfo.nearestFormat(format);
|
||||
}
|
||||
m_audioInput = new QAudioInput(m_audioDeviceInfo, format);
|
||||
m_audioWriterWAV = new AudioWriterWAV(format);
|
||||
|
||||
// Tool tips to provide additional info to the user
|
||||
m_deviceListCB->setToolTip(tr("Audio input device to record"));
|
||||
m_comboSamplerate->setToolTip(tr("Number of samples per second, 44.1KHz = CD Quality"));
|
||||
m_comboSamplefmt->setToolTip(tr("Number of channels and bits per sample, 16-bits recommended"));
|
||||
m_playXSheetCB->setToolTip(tr("Play animation from current frame while recording/playback"));
|
||||
m_saveButton->setToolTip(tr("Save recording and insert into new column"));
|
||||
m_refreshDevicesButton->setToolTip(tr("Refresh list of connected audio input devices"));
|
||||
|
||||
m_topLayout->setMargin(5);
|
||||
m_topLayout->setSpacing(8);
|
||||
|
@ -124,11 +164,19 @@ AudioRecordingPopup::AudioRecordingPopup()
|
|||
recordGridLay->setHorizontalSpacing(2);
|
||||
recordGridLay->setVerticalSpacing(3);
|
||||
{
|
||||
recordGridLay->addWidget(m_deviceListCB, 0, 0, 1, 4, Qt::AlignCenter);
|
||||
// recordGridLay->addWidget(m_refreshDevicesButton, 0, 3, Qt::AlignLeft);
|
||||
recordGridLay->addWidget(new QLabel(tr(" ")), 1, 0, Qt::AlignCenter);
|
||||
recordGridLay->addWidget(m_audioLevelsDisplay, 2, 0, 1, 4,
|
||||
recordGridLay->addWidget(m_labelDevice, 0, 0, 1, 2, Qt::AlignRight);
|
||||
recordGridLay->addWidget(m_deviceListCB, 0, 2, 1, 2, Qt::AlignLeft);
|
||||
|
||||
recordGridLay->addWidget(m_labelSamplerate, 1, 0, 1, 2, Qt::AlignRight);
|
||||
recordGridLay->addWidget(m_comboSamplerate, 1, 2, 1, 1, Qt::AlignLeft);
|
||||
recordGridLay->addWidget(m_refreshDevicesButton, 1, 3, Qt::AlignRight);
|
||||
|
||||
recordGridLay->addWidget(m_labelSamplefmt, 2, 0, 1, 2, Qt::AlignRight);
|
||||
recordGridLay->addWidget(m_comboSamplefmt, 2, 2, 1, 2, Qt::AlignLeft);
|
||||
|
||||
recordGridLay->addWidget(m_audioLevelsDisplay, 3, 0, 1, 4,
|
||||
Qt::AlignCenter);
|
||||
recordGridLay->addWidget(m_playXSheetCB, 4, 0, 1, 5, Qt::AlignCenter);
|
||||
QHBoxLayout *recordLay = new QHBoxLayout();
|
||||
recordLay->setSpacing(4);
|
||||
recordLay->setContentsMargins(0, 0, 0, 0);
|
||||
|
@ -139,7 +187,7 @@ AudioRecordingPopup::AudioRecordingPopup()
|
|||
recordLay->addWidget(m_duration);
|
||||
recordLay->addStretch();
|
||||
}
|
||||
recordGridLay->addLayout(recordLay, 3, 0, 1, 4, Qt::AlignCenter);
|
||||
recordGridLay->addLayout(recordLay, 5, 0, 1, 4, Qt::AlignCenter);
|
||||
QHBoxLayout *playLay = new QHBoxLayout();
|
||||
playLay->setSpacing(4);
|
||||
playLay->setContentsMargins(0, 0, 0, 0);
|
||||
|
@ -150,11 +198,9 @@ AudioRecordingPopup::AudioRecordingPopup()
|
|||
playLay->addWidget(m_playDuration);
|
||||
playLay->addStretch();
|
||||
}
|
||||
recordGridLay->addLayout(playLay, 4, 0, 1, 4, Qt::AlignCenter);
|
||||
recordGridLay->addWidget(new QLabel(tr(" ")), 5, 0, Qt::AlignCenter);
|
||||
recordGridLay->addWidget(m_saveButton, 6, 0, 1, 4,
|
||||
Qt::AlignCenter | Qt::AlignVCenter);
|
||||
recordGridLay->addWidget(m_playXSheetCB, 7, 0, 1, 4,
|
||||
recordGridLay->addLayout(playLay, 6, 0, 1, 4, Qt::AlignCenter);
|
||||
recordGridLay->addWidget(new QLabel(tr(" ")), 7, 0, Qt::AlignCenter);
|
||||
recordGridLay->addWidget(m_saveButton, 8, 0, 1, 4,
|
||||
Qt::AlignCenter | Qt::AlignVCenter);
|
||||
}
|
||||
recordGridLay->setColumnStretch(0, 0);
|
||||
|
@ -172,23 +218,6 @@ AudioRecordingPopup::AudioRecordingPopup()
|
|||
|
||||
m_playXSheetCB->setChecked(true);
|
||||
|
||||
m_probe->setSource(m_audioRecorder);
|
||||
QAudioEncoderSettings audioSettings;
|
||||
audioSettings.setCodec("audio/PCM");
|
||||
// setting the sample rate to some value (like 44100)
|
||||
// may cause divide-by-zero crash in QAudioDeviceInfo::nearestFormat()
|
||||
// so here we set the value to -1, as the documentation says;
|
||||
// "A value of -1 indicates the encoder should make an optimal choice"
|
||||
audioSettings.setSampleRate(-1);
|
||||
audioSettings.setChannelCount(1);
|
||||
audioSettings.setBitRate(16);
|
||||
audioSettings.setEncodingMode(QMultimedia::ConstantBitRateEncoding);
|
||||
audioSettings.setQuality(QMultimedia::HighQuality);
|
||||
m_audioRecorder->setContainerFormat("wav");
|
||||
m_audioRecorder->setEncodingSettings(audioSettings);
|
||||
|
||||
connect(m_probe, SIGNAL(audioBufferProbed(QAudioBuffer)), this,
|
||||
SLOT(processBuffer(QAudioBuffer)));
|
||||
connect(m_playXSheetCB, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(onPlayXSheetCBChanged(int)));
|
||||
connect(m_saveButton, SIGNAL(clicked()), this, SLOT(onSaveButtonPressed()));
|
||||
|
@ -199,16 +228,18 @@ AudioRecordingPopup::AudioRecordingPopup()
|
|||
SLOT(onPauseRecordingButtonPressed()));
|
||||
connect(m_pausePlaybackButton, SIGNAL(clicked()), this,
|
||||
SLOT(onPausePlaybackButtonPressed()));
|
||||
connect(m_audioRecorder, SIGNAL(durationChanged(qint64)), this,
|
||||
connect(m_audioWriterWAV, SIGNAL(update(qint64)), this,
|
||||
SLOT(updateRecordDuration(qint64)));
|
||||
connect(m_console, SIGNAL(playStateChanged(bool)), this,
|
||||
if (m_console) connect(m_console, SIGNAL(playStateChanged(bool)), this,
|
||||
SLOT(onPlayStateChanged(bool)));
|
||||
connect(m_deviceListCB, SIGNAL(currentTextChanged(const QString)), this,
|
||||
SLOT(onInputDeviceChanged()));
|
||||
// connect(m_refreshDevicesButton, SIGNAL(clicked()), this,
|
||||
// SLOT(onRefreshButtonPressed()));
|
||||
// connect(m_audioRecorder, SIGNAL(availableAudioInputsChanged()), this,
|
||||
// SLOT(onRefreshButtonPressed()));
|
||||
connect(m_refreshDevicesButton, SIGNAL(clicked()), this,
|
||||
SLOT(onRefreshButtonPressed()));
|
||||
connect(m_comboSamplerate, SIGNAL(currentTextChanged(const QString)), this,
|
||||
SLOT(onAudioSettingChanged()));
|
||||
connect(m_comboSamplefmt, SIGNAL(currentTextChanged(const QString)), this,
|
||||
SLOT(onAudioSettingChanged()));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -218,11 +249,24 @@ AudioRecordingPopup::~AudioRecordingPopup() {}
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AudioRecordingPopup::onRecordButtonPressed() {
|
||||
if (m_audioRecorder->state() == QAudioRecorder::StoppedState) {
|
||||
if (m_audioRecorder->status() == QMediaRecorder::UnavailableStatus) {
|
||||
#if QT_VERSION >= 0x051000
|
||||
if (m_audioInput->state() == QAudio::InterruptedState) {
|
||||
DVGui::warning(
|
||||
tr("The microphone is not available: "
|
||||
"\nPlease select a different device or check the microphone."));
|
||||
return;
|
||||
} else if (m_audioInput->state() == QAudio::StoppedState) {
|
||||
if (!m_console) {
|
||||
DVGui::warning(
|
||||
tr("Record failed: "
|
||||
"\nMake sure there's XSheet or Timeline in the room."));
|
||||
#else
|
||||
if (m_audioInput->state() == QAudio::StoppedState) {
|
||||
if (!m_console) {
|
||||
DVGui::warning(
|
||||
tr("The microphone is not available: "
|
||||
"\nPlease select a different device or check the microphone."));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
// clear the player in case the file is open there
|
||||
|
@ -236,25 +280,36 @@ void AudioRecordingPopup::onRecordButtonPressed() {
|
|||
// (rarely)
|
||||
// could cause a crash. I think OT tried to import the level before the
|
||||
// final file was fully copied to the new location
|
||||
m_audioRecorder->setOutputLocation(
|
||||
QUrl::fromLocalFile(m_filePath.getQString()));
|
||||
if (TSystem::doesExistFileOrLevel(m_filePath)) {
|
||||
TSystem::removeFileOrLevel(m_filePath);
|
||||
}
|
||||
// The audio writer support either writing to buffer or directly to disk
|
||||
// each method have their own pros and cons
|
||||
// For now using false to mimic previous QAudioRecorder behaviour
|
||||
m_audioWriterWAV->restart(m_audioInput->format());
|
||||
if (!m_audioWriterWAV->start(m_filePath.getQString(), false)) {
|
||||
DVGui::warning(
|
||||
tr("Failed to save WAV file:\nMake sure you have write permissions "
|
||||
"in folder."));
|
||||
return;
|
||||
}
|
||||
m_recordButton->setIcon(m_stopIcon);
|
||||
m_saveButton->setDisabled(true);
|
||||
m_playButton->setDisabled(true);
|
||||
m_pausePlaybackButton->setDisabled(true);
|
||||
m_pauseRecordingButton->setEnabled(true);
|
||||
m_deviceListCB->setDisabled(true);
|
||||
m_refreshDevicesButton->setDisabled(true);
|
||||
m_comboSamplerate->setDisabled(true);
|
||||
m_comboSamplefmt->setDisabled(true);
|
||||
m_recordedLevels.clear();
|
||||
m_oldElapsed = 0;
|
||||
m_pausedTime = 0;
|
||||
m_startPause = 0;
|
||||
m_endPause = 0;
|
||||
m_stoppedAtEnd = false;
|
||||
m_playDuration->setText("00:00");
|
||||
m_playDuration->setText("00:00.000");
|
||||
m_timer->restart();
|
||||
m_audioRecorder->record();
|
||||
m_audioInput->start(m_audioWriterWAV);
|
||||
// this sometimes sets to one frame off, so + 1.
|
||||
m_currentFrame = TApp::instance()->getCurrentFrame()->getFrame() + 1;
|
||||
if (m_syncPlayback && !m_isPlaying) {
|
||||
|
@ -264,13 +319,20 @@ void AudioRecordingPopup::onRecordButtonPressed() {
|
|||
}
|
||||
|
||||
} else {
|
||||
m_audioRecorder->stop();
|
||||
m_audioLevelsDisplay->setLevel(0);
|
||||
m_audioInput->stop();
|
||||
bool success = m_audioWriterWAV->stop();
|
||||
if (success) {
|
||||
m_saveButton->setEnabled(true);
|
||||
m_playButton->setEnabled(true);
|
||||
}
|
||||
m_audioLevelsDisplay->setLevel(-1, -1);
|
||||
m_recordButton->setIcon(m_recordIcon);
|
||||
m_saveButton->setEnabled(true);
|
||||
m_playButton->setEnabled(true);
|
||||
m_pauseRecordingButton->setDisabled(true);
|
||||
m_pauseRecordingButton->setIcon(m_pauseIcon);
|
||||
m_deviceListCB->setEnabled(true);
|
||||
m_refreshDevicesButton->setEnabled(true);
|
||||
m_comboSamplerate->setEnabled(true);
|
||||
m_comboSamplefmt->setEnabled(true);
|
||||
if (m_syncPlayback) {
|
||||
if (m_isPlaying) {
|
||||
m_console->pressButton(FlipConsole::ePause);
|
||||
|
@ -279,21 +341,29 @@ void AudioRecordingPopup::onRecordButtonPressed() {
|
|||
TApp::instance()->getCurrentFrame()->setCurrentFrame(m_currentFrame);
|
||||
}
|
||||
m_isPlaying = false;
|
||||
if (!success) {
|
||||
DVGui::warning(tr(
|
||||
"Failed to save WAV file:\nMake sure you have write permissions in folder."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AudioRecordingPopup::updateRecordDuration(qint64 duration) {
|
||||
// this is only called every second or so - sometimes duration ~= 950
|
||||
// this gives some padding so it doesn't take two seconds to show one second
|
||||
// has passed
|
||||
if (duration % 1000 > 850) duration += 150;
|
||||
int minutes = duration / 60000;
|
||||
int seconds = (duration / 1000) % 60;
|
||||
int milis = duration % 1000;
|
||||
QString strMinutes = QString::number(minutes).rightJustified(2, '0');
|
||||
QString strSeconds = QString::number(seconds).rightJustified(2, '0');
|
||||
m_duration->setText(strMinutes + ":" + strSeconds);
|
||||
QString strMilis = QString::number(milis).rightJustified(3, '0');
|
||||
m_duration->setText(strMinutes + ":" + strSeconds + "." + strMilis);
|
||||
|
||||
// Show and record amplitude
|
||||
qreal level = m_audioWriterWAV->level();
|
||||
qreal peakL = m_audioWriterWAV->peakLevel();
|
||||
m_audioLevelsDisplay->setLevel(level, peakL);
|
||||
m_recordedLevels[duration / 20] = level;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -301,15 +371,17 @@ void AudioRecordingPopup::updateRecordDuration(qint64 duration) {
|
|||
void AudioRecordingPopup::updatePlaybackDuration(qint64 duration) {
|
||||
int minutes = duration / 60000;
|
||||
int seconds = (duration / 1000) % 60;
|
||||
int milis = duration % 1000;
|
||||
QString strMinutes = QString::number(minutes).rightJustified(2, '0');
|
||||
QString strSeconds = QString::number(seconds).rightJustified(2, '0');
|
||||
m_playDuration->setText(strMinutes + ":" + strSeconds);
|
||||
QString strMilis = QString::number(milis).rightJustified(3, '0');
|
||||
m_playDuration->setText(strMinutes + ":" + strSeconds + "." + strMilis);
|
||||
|
||||
// the qmediaplayer probe doesn't work on all platforms, so we fake it by
|
||||
// using
|
||||
// a map that is made during recording
|
||||
if (m_recordedLevels.contains(duration / 20)) {
|
||||
m_audioLevelsDisplay->setLevel(m_recordedLevels.value(duration / 20));
|
||||
m_audioLevelsDisplay->setLevel(m_recordedLevels.value(duration / 20), -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,6 +400,10 @@ void AudioRecordingPopup::onPlayButtonPressed() {
|
|||
m_recordButton->setDisabled(true);
|
||||
m_saveButton->setDisabled(true);
|
||||
m_pausePlaybackButton->setEnabled(true);
|
||||
m_deviceListCB->setDisabled(true);
|
||||
m_refreshDevicesButton->setDisabled(true);
|
||||
m_comboSamplerate->setDisabled(true);
|
||||
m_comboSamplefmt->setDisabled(true);
|
||||
m_stoppedAtEnd = false;
|
||||
m_player->play();
|
||||
// this sometimes sets to one frame off, so + 1.
|
||||
|
@ -343,25 +419,29 @@ void AudioRecordingPopup::onPlayButtonPressed() {
|
|||
m_playButton->setIcon(m_playIcon);
|
||||
m_pausePlaybackButton->setDisabled(true);
|
||||
m_pausePlaybackButton->setIcon(m_pauseIcon);
|
||||
m_deviceListCB->setEnabled(true);
|
||||
m_refreshDevicesButton->setEnabled(true);
|
||||
m_comboSamplerate->setEnabled(true);
|
||||
m_comboSamplefmt->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AudioRecordingPopup::onPauseRecordingButtonPressed() {
|
||||
if (m_audioRecorder->state() == QAudioRecorder::StoppedState) {
|
||||
if (m_audioInput->state() == QAudio::StoppedState) {
|
||||
return;
|
||||
} else if (m_audioRecorder->state() == QAudioRecorder::PausedState) {
|
||||
} else if (m_audioInput->state() == QAudio::SuspendedState) {
|
||||
m_endPause = m_timer->elapsed();
|
||||
m_pausedTime += m_endPause - m_startPause;
|
||||
m_audioRecorder->record();
|
||||
m_audioInput->resume();
|
||||
m_pauseRecordingButton->setIcon(m_pauseIcon);
|
||||
if (m_syncPlayback && !m_isPlaying && !m_stoppedAtEnd) {
|
||||
m_console->pressButton(FlipConsole::ePlay);
|
||||
m_isPlaying = true;
|
||||
}
|
||||
} else {
|
||||
m_audioRecorder->pause();
|
||||
m_audioInput->suspend();
|
||||
m_pauseRecordingButton->setIcon(m_recordIcon);
|
||||
m_startPause = m_timer->elapsed();
|
||||
if (m_syncPlayback && m_isPlaying) {
|
||||
|
@ -398,7 +478,7 @@ void AudioRecordingPopup::onPausePlaybackButtonPressed() {
|
|||
void AudioRecordingPopup::onMediaStateChanged(QMediaPlayer::State state) {
|
||||
// stopping can happen through the stop button or the file ending
|
||||
if (state == QMediaPlayer::StoppedState) {
|
||||
m_audioLevelsDisplay->setLevel(0);
|
||||
m_audioLevelsDisplay->setLevel(-1, -1);
|
||||
if (m_syncPlayback) {
|
||||
if (m_isPlaying) {
|
||||
m_console->pressButton(FlipConsole::ePause);
|
||||
|
@ -410,6 +490,10 @@ void AudioRecordingPopup::onMediaStateChanged(QMediaPlayer::State state) {
|
|||
m_pausePlaybackButton->setIcon(m_pauseIcon);
|
||||
m_pausePlaybackButton->setDisabled(true);
|
||||
m_recordButton->setEnabled(true);
|
||||
m_deviceListCB->setEnabled(true);
|
||||
m_refreshDevicesButton->setEnabled(true);
|
||||
m_comboSamplerate->setEnabled(true);
|
||||
m_comboSamplefmt->setEnabled(true);
|
||||
m_saveButton->setEnabled(true);
|
||||
m_isPlaying = false;
|
||||
}
|
||||
|
@ -426,36 +510,36 @@ void AudioRecordingPopup::onPlayXSheetCBChanged(int status) {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Refresh isn't working right now, but I'm leaving the code in case a future
|
||||
// change
|
||||
// makes it work
|
||||
void AudioRecordingPopup::onRefreshButtonPressed() {
|
||||
QAudioDeviceInfo m_audioDeviceInfo =
|
||||
m_deviceListCB->itemData(m_deviceListCB->currentIndex())
|
||||
.value<QAudioDeviceInfo>();
|
||||
|
||||
// void AudioRecordingPopup::onRefreshButtonPressed() {
|
||||
// m_deviceListCB->clear();
|
||||
// QStringList inputs = m_audioRecorder->audioInputs();
|
||||
// int count = inputs.count();
|
||||
// m_deviceListCB->addItems(inputs);
|
||||
// QString selectedInput = m_audioRecorder->defaultAudioInput();
|
||||
// m_deviceListCB->setCurrentText(selectedInput);
|
||||
//
|
||||
//}
|
||||
enumerateAudioDevices(m_audioDeviceInfo.deviceName());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AudioRecordingPopup::onInputDeviceChanged() {
|
||||
m_audioRecorder->setAudioInput(m_deviceListCB->currentText());
|
||||
reinitAudioInput();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AudioRecordingPopup::onAudioSettingChanged() {
|
||||
reinitAudioInput();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AudioRecordingPopup::onSaveButtonPressed() {
|
||||
if (m_audioRecorder->state() != QAudioRecorder::StoppedState) {
|
||||
m_audioRecorder->stop();
|
||||
m_audioLevelsDisplay->setLevel(0);
|
||||
if (m_audioInput->state() != QAudio::StoppedState) {
|
||||
m_audioInput->stop();
|
||||
m_audioLevelsDisplay->setLevel(-1, -1);
|
||||
}
|
||||
if (m_player->state() != QMediaPlayer::StoppedState) {
|
||||
m_player->stop();
|
||||
m_audioLevelsDisplay->setLevel(0);
|
||||
m_audioLevelsDisplay->setLevel(-1, -1);
|
||||
}
|
||||
if (!TSystem::doesExistFileOrLevel(m_filePath)) return;
|
||||
|
||||
|
@ -499,31 +583,6 @@ void AudioRecordingPopup::makePaths() {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AudioRecordingPopup::processBuffer(const QAudioBuffer &buffer) {
|
||||
// keep from processing too many times
|
||||
// get 50 signals per second
|
||||
if (m_timer->elapsed() < m_oldElapsed + 20) return;
|
||||
m_oldElapsed = m_timer->elapsed() - m_pausedTime;
|
||||
qint16 value = 0;
|
||||
|
||||
if (!buffer.format().isValid() ||
|
||||
buffer.format().byteOrder() != QAudioFormat::LittleEndian)
|
||||
return;
|
||||
|
||||
if (buffer.format().codec() != "audio/pcm") return;
|
||||
|
||||
const qint16 *data = buffer.constData<qint16>();
|
||||
qreal maxValue = 0;
|
||||
qreal tempValue = 0;
|
||||
for (int i = 0; i < buffer.frameCount(); ++i) {
|
||||
tempValue = qAbs(qreal(data[i]));
|
||||
if (tempValue > maxValue) maxValue = tempValue;
|
||||
}
|
||||
maxValue /= SHRT_MAX;
|
||||
m_audioLevelsDisplay->setLevel(maxValue);
|
||||
m_recordedLevels[m_oldElapsed / 20] = maxValue;
|
||||
}
|
||||
|
||||
void AudioRecordingPopup::onPlayStateChanged(bool playing) {
|
||||
// m_isPlaying = playing;
|
||||
if (!playing && m_isPlaying) m_stoppedAtEnd = true;
|
||||
|
@ -545,28 +604,254 @@ void AudioRecordingPopup::resetEverything() {
|
|||
m_pauseRecordingButton->setIcon(m_pauseIcon);
|
||||
m_pauseRecordingButton->setDisabled(true);
|
||||
m_pausePlaybackButton->setDisabled(true);
|
||||
m_deviceListCB->setEnabled(true);
|
||||
m_refreshDevicesButton->setEnabled(true);
|
||||
m_comboSamplerate->setEnabled(true);
|
||||
m_comboSamplefmt->setEnabled(true);
|
||||
m_recordedLevels.clear();
|
||||
m_duration->setText("00:00");
|
||||
m_playDuration->setText("00:00");
|
||||
m_audioLevelsDisplay->setLevel(0);
|
||||
m_duration->setText("00:00.000");
|
||||
m_playDuration->setText("00:00.000");
|
||||
m_audioLevelsDisplay->setLevel(-1, -1);
|
||||
if (!m_console) {
|
||||
m_console = FlipConsole::getCurrent();
|
||||
if (m_console)
|
||||
connect(m_console, SIGNAL(playStateChanged(bool)), this,
|
||||
SLOT(onPlayStateChanged(bool)));
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AudioRecordingPopup::hideEvent(QHideEvent *event) {
|
||||
if (m_audioRecorder->state() != QAudioRecorder::StoppedState) {
|
||||
m_audioRecorder->stop();
|
||||
if (m_audioInput->state() != QAudio::StoppedState) {
|
||||
m_audioInput->stop();
|
||||
m_audioWriterWAV->stop();
|
||||
}
|
||||
if (m_player->state() != QMediaPlayer::StoppedState) {
|
||||
m_player->stop();
|
||||
}
|
||||
// make sure the file is freed before deleting
|
||||
delete m_player;
|
||||
m_player = new QMediaPlayer(this);
|
||||
// this should only remove files that haven't been used in the scene
|
||||
// make paths checks to only create path names that don't exist yet.
|
||||
if (TSystem::doesExistFileOrLevel(TFilePath(m_filePath.getQString()))) {
|
||||
TSystem::removeFileOrLevel(TFilePath(m_filePath.getQString()));
|
||||
}
|
||||
// Free up memory used in recording
|
||||
m_recordedLevels.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AudioRecordingPopup::enumerateAudioDevices(const QString &selectedDeviceName) {
|
||||
const QAudioDeviceInfo &defaultDeviceInfo =
|
||||
QAudioDeviceInfo::defaultInputDevice();
|
||||
|
||||
m_blockAudioSettings = true;
|
||||
m_deviceListCB->clear();
|
||||
m_deviceListCB->addItem(defaultDeviceInfo.deviceName(),
|
||||
QVariant::fromValue(defaultDeviceInfo));
|
||||
|
||||
for (auto &deviceInfo :
|
||||
QAudioDeviceInfo::availableDevices(QAudio::AudioInput)) {
|
||||
if (deviceInfo != defaultDeviceInfo &&
|
||||
m_deviceListCB->findText(deviceInfo.deviceName()) == -1) {
|
||||
m_deviceListCB->addItem(deviceInfo.deviceName(),
|
||||
QVariant::fromValue(deviceInfo));
|
||||
}
|
||||
}
|
||||
|
||||
int deviceIndex = m_deviceListCB->findText(selectedDeviceName);
|
||||
if (deviceIndex != -1) m_deviceListCB->setCurrentIndex(deviceIndex);
|
||||
m_blockAudioSettings = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AudioRecordingPopup::reinitAudioInput() {
|
||||
if (m_blockAudioSettings) return;
|
||||
|
||||
QAudioDeviceInfo m_audioDeviceInfo =
|
||||
m_deviceListCB->itemData(m_deviceListCB->currentIndex())
|
||||
.value<QAudioDeviceInfo>();
|
||||
int samplerate =
|
||||
m_comboSamplerate->itemData(m_comboSamplerate->currentIndex())
|
||||
.value<int>();
|
||||
int sampletype =
|
||||
m_comboSamplefmt->itemData(m_comboSamplefmt->currentIndex()).value<int>();
|
||||
int bitdepth = sampletype & 56;
|
||||
int channels = sampletype & 7;
|
||||
|
||||
QAudioFormat format;
|
||||
format.setSampleRate(samplerate);
|
||||
format.setChannelCount(channels);
|
||||
format.setSampleSize(bitdepth);
|
||||
format.setSampleType(bitdepth == 8 ? QAudioFormat::UnSignedInt
|
||||
: QAudioFormat::SignedInt);
|
||||
format.setByteOrder(QAudioFormat::LittleEndian);
|
||||
format.setCodec("audio/pcm");
|
||||
if (!m_audioDeviceInfo.isFormatSupported(format)) {
|
||||
DVGui::warning(tr(
|
||||
"Audio format unsupported:\nNearest format will be internally used."));
|
||||
format = m_audioDeviceInfo.nearestFormat(format);
|
||||
}
|
||||
|
||||
// Recreate input
|
||||
delete m_audioInput;
|
||||
m_audioInput = new QAudioInput(m_audioDeviceInfo, format);
|
||||
m_audioWriterWAV->restart(format);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// AudioWriterWAV Class
|
||||
//-----------------------------------------------------------------------------
|
||||
// IODevice to write standard WAV files, performs peak level calc
|
||||
//
|
||||
// 8-bits audio must be unsigned
|
||||
// 16-bits audio must be signed
|
||||
// 32-bits isn't supported
|
||||
|
||||
AudioWriterWAV::AudioWriterWAV(const QAudioFormat &format)
|
||||
: m_level(0.0)
|
||||
, m_peakL(0.0)
|
||||
, m_maxAmp(0.0)
|
||||
, m_wrRawB(0)
|
||||
, m_wavFile(NULL)
|
||||
, m_wavBuff(NULL) {
|
||||
restart(format);
|
||||
}
|
||||
|
||||
bool AudioWriterWAV::restart(const QAudioFormat &format) {
|
||||
m_format = format;
|
||||
if (m_format.sampleSize() == 8) {
|
||||
m_rbytesms = 1000.0 / (m_format.sampleRate() * m_format.channelCount());
|
||||
m_maxAmp = 127.0;
|
||||
} else if (m_format.sampleSize() == 16) {
|
||||
m_rbytesms = 500.0 / (m_format.sampleRate() * m_format.channelCount());
|
||||
m_maxAmp = 32767.0;
|
||||
} else {
|
||||
// 32-bits isn't supported
|
||||
m_rbytesms = 250.0 / (m_format.sampleRate() * m_format.channelCount());
|
||||
m_maxAmp = 1.0;
|
||||
}
|
||||
m_wrRawB = 0;
|
||||
m_peakL = 0.0;
|
||||
if (m_wavBuff) m_wavBuff->clear();
|
||||
return this->reset();
|
||||
}
|
||||
|
||||
// Just a tiny define to avoid a magic number
|
||||
// this is the size of a WAV header with PCM format
|
||||
#define AWWAV_HEADER_SIZE 44
|
||||
|
||||
bool AudioWriterWAV::start(const QString &filename, bool useMem) {
|
||||
open(QIODevice::WriteOnly);
|
||||
m_filename = filename;
|
||||
|
||||
if (useMem) {
|
||||
m_wavBuff = new QByteArray();
|
||||
} else {
|
||||
m_wavFile = new QFile(m_filename);
|
||||
if (!m_wavFile->open(QIODevice::WriteOnly | QIODevice::Truncate))
|
||||
return false;
|
||||
m_wavFile->seek(AWWAV_HEADER_SIZE); // skip header
|
||||
}
|
||||
|
||||
m_wrRawB = 0;
|
||||
m_peakL = 0.0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioWriterWAV::stop() {
|
||||
close();
|
||||
|
||||
if (m_wavBuff) {
|
||||
// Using memory
|
||||
QFile file;
|
||||
file.setFileName(m_filename);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) return false;
|
||||
writeWAVHeader(file);
|
||||
file.write(m_wavBuff->constData(), m_wavBuff->size());
|
||||
delete m_wavBuff;
|
||||
m_wavBuff = NULL;
|
||||
} else {
|
||||
// Using disk directly
|
||||
writeWAVHeader(*m_wavFile);
|
||||
m_wavFile->close();
|
||||
delete m_wavFile;
|
||||
m_wavFile = NULL;
|
||||
}
|
||||
|
||||
m_wrRawB = 0;
|
||||
m_peakL = 0.0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AudioWriterWAV::writeWAVHeader(QFile &file) {
|
||||
quint16 channels = m_format.channelCount();
|
||||
quint32 samplerate = m_format.sampleRate();
|
||||
quint16 bitrate = m_format.sampleSize();
|
||||
|
||||
qint64 pos = file.pos();
|
||||
file.seek(0);
|
||||
|
||||
QDataStream out(&file);
|
||||
out.setByteOrder(QDataStream::LittleEndian);
|
||||
out.writeRawData("RIFF", 4);
|
||||
out << (quint32)(m_wrRawB + AWWAV_HEADER_SIZE);
|
||||
out.writeRawData("WAVEfmt ", 8);
|
||||
out << (quint32)16 << (quint16)1; // magic numbers!
|
||||
out << channels << samplerate;
|
||||
out << quint32(samplerate * channels * bitrate / 8);
|
||||
out << quint16(channels * bitrate / 8);
|
||||
out << bitrate;
|
||||
out.writeRawData("data", 4);
|
||||
out << (quint32)m_wrRawB;
|
||||
}
|
||||
|
||||
qint64 AudioWriterWAV::readData(char *data, qint64 maxlen) {
|
||||
Q_UNUSED(data)
|
||||
Q_UNUSED(maxlen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
qint64 AudioWriterWAV::writeData(const char *data, qint64 len) {
|
||||
int tmp, peak = 0.0;
|
||||
|
||||
// Measure peak
|
||||
if (m_format.sampleSize() == 8) {
|
||||
const quint8 *sdata = (const quint8 *)data;
|
||||
int slen = len;
|
||||
for (int i = 0; i < slen; ++i) {
|
||||
tmp = qAbs<int>(sdata[i] - 128);
|
||||
if (tmp > peak) peak = tmp;
|
||||
}
|
||||
} else if (m_format.sampleSize() == 16) {
|
||||
const qint16 *sdata = (const qint16 *)data;
|
||||
int slen = len / 2;
|
||||
for (int i = 0; i < slen; ++i) {
|
||||
tmp = qAbs<int>(sdata[i]);
|
||||
if (tmp > peak) peak = tmp;
|
||||
}
|
||||
} else {
|
||||
// 32-bits isn't supported
|
||||
peak = -1;
|
||||
}
|
||||
m_level = qreal(peak) / m_maxAmp;
|
||||
if (m_level > m_peakL) m_peakL = m_level;
|
||||
|
||||
// Write to memory or disk
|
||||
if (m_wavBuff) {
|
||||
m_wavBuff->append(data, len);
|
||||
} else {
|
||||
m_wavFile->write(data, len);
|
||||
}
|
||||
m_wrRawB += len;
|
||||
|
||||
// Emit an update
|
||||
emit update(qreal(m_wrRawB) * m_rbytesms);
|
||||
return len;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -574,14 +859,15 @@ void AudioRecordingPopup::hideEvent(QHideEvent *event) {
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
AudioLevelsDisplay::AudioLevelsDisplay(QWidget *parent)
|
||||
: QWidget(parent), m_level(0.0) {
|
||||
: QWidget(parent), m_level(0.0), m_peakL(0.0) {
|
||||
setFixedHeight(20);
|
||||
setFixedWidth(300);
|
||||
}
|
||||
|
||||
void AudioLevelsDisplay::setLevel(qreal level) {
|
||||
if (m_level != level) {
|
||||
void AudioLevelsDisplay::setLevel(qreal level, qreal peakLevel) {
|
||||
if (m_level != level || m_peakL != peakLevel) {
|
||||
m_level = level;
|
||||
m_peakL = peakLevel;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
@ -591,20 +877,29 @@ void AudioLevelsDisplay::paintEvent(QPaintEvent *event) {
|
|||
|
||||
QPainter painter(this);
|
||||
QColor color;
|
||||
if (m_level < 0.5) {
|
||||
if (m_level < 0.0) {
|
||||
return; // draw nothing...
|
||||
} else if (m_level < 0.5) {
|
||||
color = Qt::green;
|
||||
}
|
||||
|
||||
else if (m_level < 0.75) {
|
||||
} else if (m_level < 0.75) {
|
||||
color = QColor(204, 205, 0); // yellow
|
||||
} else if (m_level < 0.95) {
|
||||
color = QColor(255, 115, 0); // orange
|
||||
} else
|
||||
color = Qt::red;
|
||||
|
||||
qreal widthLevel = m_level * width();
|
||||
painter.fillRect(0, 0, widthLevel, height(), color);
|
||||
int widthLevel = m_level * width();
|
||||
int widthPeakL = m_peakL * width();
|
||||
painter.fillRect(widthLevel, 0, width(), height(), Qt::black);
|
||||
if (widthPeakL >= 0) {
|
||||
if (m_peakL >= 0.995) {
|
||||
painter.fillRect(width() - 4, 0, 4, height(), Qt::red);
|
||||
} else {
|
||||
painter.setPen(QColor(64, 64, 64)); // very dark gray
|
||||
painter.drawLine(widthPeakL, 0, widthPeakL, height());
|
||||
}
|
||||
}
|
||||
painter.fillRect(0, 0, widthLevel, height(), color);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -15,14 +15,13 @@
|
|||
class QComboBox;
|
||||
class QCheckBox;
|
||||
class QPushButton;
|
||||
class QAudioRecorder;
|
||||
class QLabel;
|
||||
class AudioLevelsDisplay;
|
||||
class FlipConsole;
|
||||
class QAudioProbe;
|
||||
class QAudioBuffer;
|
||||
class QMediaPlayer;
|
||||
class QElapsedTimer;
|
||||
class AudioWriterWAV;
|
||||
|
||||
//=============================================================================
|
||||
// AudioRecordingPopup
|
||||
|
@ -31,24 +30,22 @@ class QElapsedTimer;
|
|||
class AudioRecordingPopup : public DVGui::Dialog {
|
||||
Q_OBJECT
|
||||
|
||||
QString m_deviceName;
|
||||
QPushButton
|
||||
*m_recordButton, // *m_refreshDevicesButton, -refresh not working for now
|
||||
*m_recordButton, *m_refreshDevicesButton,
|
||||
*m_playButton,
|
||||
*m_pauseRecordingButton, *m_pausePlaybackButton, *m_saveButton;
|
||||
QComboBox *m_deviceListCB;
|
||||
QAudioRecorder *m_audioRecorder;
|
||||
QAudioInput *m_audioInput;
|
||||
AudioWriterWAV *m_audioWriterWAV;
|
||||
QLabel *m_duration, *m_playDuration;
|
||||
QCheckBox *m_playXSheetCB;
|
||||
int m_currentFrame;
|
||||
AudioLevelsDisplay *m_audioLevelsDisplay;
|
||||
QAudioProbe *m_probe;
|
||||
QMediaPlayer *m_player;
|
||||
TFilePath m_filePath;
|
||||
FlipConsole *m_console;
|
||||
QElapsedTimer *m_timer;
|
||||
QMap<qint64, double> m_recordedLevels;
|
||||
qint64 m_oldElapsed;
|
||||
qint64 m_startPause = 0;
|
||||
qint64 m_endPause = 0;
|
||||
qint64 m_pausedTime = 0;
|
||||
|
@ -56,7 +53,11 @@ class AudioRecordingPopup : public DVGui::Dialog {
|
|||
QIcon m_pauseIcon;
|
||||
QIcon m_recordIcon;
|
||||
QIcon m_stopIcon;
|
||||
QIcon m_refreshIcon;
|
||||
bool m_isPlaying, m_syncPlayback, m_stoppedAtEnd;
|
||||
QLabel *m_labelDevice, *m_labelSamplerate, *m_labelSamplefmt;
|
||||
QComboBox *m_comboSamplerate, *m_comboSamplefmt;
|
||||
bool m_blockAudioSettings;
|
||||
|
||||
public:
|
||||
AudioRecordingPopup();
|
||||
|
@ -67,6 +68,8 @@ protected:
|
|||
void hideEvent(QHideEvent *event);
|
||||
void makePaths();
|
||||
void resetEverything();
|
||||
void enumerateAudioDevices(const QString &deviceName);
|
||||
void reinitAudioInput();
|
||||
|
||||
private slots:
|
||||
void onRecordButtonPressed();
|
||||
|
@ -76,12 +79,47 @@ private slots:
|
|||
void onSaveButtonPressed();
|
||||
void onPauseRecordingButtonPressed();
|
||||
void onPausePlaybackButtonPressed();
|
||||
void processBuffer(const QAudioBuffer &buffer);
|
||||
void onPlayStateChanged(bool playing);
|
||||
void onPlayXSheetCBChanged(int status);
|
||||
void onMediaStateChanged(QMediaPlayer::State state);
|
||||
void onInputDeviceChanged();
|
||||
// void onRefreshButtonPressed();
|
||||
void onRefreshButtonPressed();
|
||||
void onAudioSettingChanged();
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// AudioWriterWAV
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class AudioWriterWAV : public QIODevice {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioWriterWAV(const QAudioFormat &format);
|
||||
bool restart(const QAudioFormat &format);
|
||||
|
||||
bool start(const QString &filename, bool useMem);
|
||||
bool stop();
|
||||
|
||||
qint64 readData(char *data, qint64 maxlen) override;
|
||||
qint64 writeData(const char *data, qint64 len) override;
|
||||
|
||||
qreal level() const { return m_level; }
|
||||
qreal peakLevel() const { return m_peakL; }
|
||||
|
||||
private:
|
||||
QString m_filename;
|
||||
QFile *m_wavFile;
|
||||
QByteArray *m_wavBuff; // if not null then use memory
|
||||
QAudioFormat m_format;
|
||||
quint64 m_wrRawB; // Written raw bytes
|
||||
qreal m_rbytesms;
|
||||
qreal m_maxAmp;
|
||||
qreal m_level, m_peakL;
|
||||
|
||||
void writeWAVHeader(QFile &file);
|
||||
|
||||
signals:
|
||||
void update(qint64 duration);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
@ -94,12 +132,13 @@ public:
|
|||
explicit AudioLevelsDisplay(QWidget *parent = 0);
|
||||
|
||||
// Using [0; 1.0] range
|
||||
void setLevel(qreal level);
|
||||
void setLevel(qreal level, qreal peak);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
|
||||
private:
|
||||
qreal m_level;
|
||||
qreal m_peakL;
|
||||
};
|
||||
#endif
|
|
@ -196,9 +196,9 @@ AutoInputCellNumberPopup::AutoInputCellNumberPopup()
|
|||
"AutoInputCellNumberPopup") {
|
||||
setWindowTitle(tr("Auto Input Cell Number"));
|
||||
|
||||
m_from = new FrameNumberLineEdit(this);
|
||||
m_from = new FrameNumberLineEdit(this, TFrameId(1), false);
|
||||
m_increment = new DVGui::IntLineEdit(this, 0, 0);
|
||||
m_to = new FrameNumberLineEdit(this);
|
||||
m_to = new FrameNumberLineEdit(this, TFrameId(1), false);
|
||||
m_interval = new DVGui::IntLineEdit(this, 0, 0);
|
||||
m_step = new DVGui::IntLineEdit(this, 1, 1);
|
||||
m_repeat = new DVGui::IntLineEdit(this, 1, 1);
|
||||
|
@ -301,8 +301,8 @@ void AutoInputCellNumberPopup::doExecute(bool overwrite) {
|
|||
}
|
||||
AutoInputCellNumberUndo *undo = new AutoInputCellNumberUndo(
|
||||
m_increment->getValue(), m_interval->getValue(), m_step->getValue(),
|
||||
m_repeat->getValue(), m_from->getValue(), m_to->getValue(), r0, r1,
|
||||
overwrite, columnIndices, levels);
|
||||
m_repeat->getValue(), m_from->getValue().getNumber(),
|
||||
m_to->getValue().getNumber(), r0, r1, overwrite, columnIndices, levels);
|
||||
// if no cells will be arranged, then return
|
||||
if (undo->rowsCount() == 0) {
|
||||
DVGui::MsgBox(DVGui::WARNING,
|
||||
|
|
|
@ -3013,6 +3013,13 @@ static void dRenumberCells(int col, int r0, int r1) {
|
|||
levelsTable[sl].push_back(std::make_pair(oldFid, newFid));
|
||||
}
|
||||
}
|
||||
auto getNextLetter = [](const QString &letter) {
|
||||
if (letter.isEmpty()) return QString('a');
|
||||
QByteArray byteArray = letter.toUtf8();
|
||||
// return incrementing the last letter
|
||||
byteArray.data()[byteArray.size() - 1]++;
|
||||
return QString::fromUtf8(byteArray);
|
||||
};
|
||||
|
||||
// Ensure renumber consistency in case some destination fid would overwrite
|
||||
// some unrenumbered fid in the level
|
||||
|
@ -3022,8 +3029,7 @@ static void dRenumberCells(int col, int r0, int r1) {
|
|||
if (cellsMap.find(it->second) == cellsMap.end() &&
|
||||
it->first.getSimpleLevel()->isFid(it->second.getFrameId())) {
|
||||
TFrameId &fid = it->second.m_frameId;
|
||||
fid = TFrameId(fid.getNumber(),
|
||||
fid.getLetter() ? fid.getLetter() + 1 : 'a',
|
||||
fid = TFrameId(fid.getNumber(), getNextLetter(fid.getLetter()),
|
||||
fid.getZeroPadding(), fid.getStartSeqInd());
|
||||
}
|
||||
}
|
||||
|
@ -3218,8 +3224,8 @@ static void createNewDrawing(TXsheet *xsh, int row, int col,
|
|||
TFrameId fid(row + 1);
|
||||
if (sl->isFid(fid)) {
|
||||
fid = TFrameId(fid.getNumber(), 'a');
|
||||
while (fid.getLetter() < 'z' && sl->isFid(fid))
|
||||
fid = TFrameId(fid.getNumber(), fid.getLetter() + 1);
|
||||
while (fid.getLetter().toUtf8().at(0) < 'z' && sl->isFid(fid))
|
||||
fid = TFrameId(fid.getNumber(), fid.getLetter().toUtf8().at(0) + 1);
|
||||
}
|
||||
// add the new frame
|
||||
sl->setFrame(fid, sl->createEmptyFrame());
|
||||
|
|
|
@ -565,6 +565,8 @@ bool CleanupPopup::analyzeCleanupList() {
|
|||
m_overwriteDialog->reset();
|
||||
}
|
||||
|
||||
m_overwriteDialog->enableOptions(inputPath == outputPath);
|
||||
|
||||
// Prompt user for file conflict resolution
|
||||
clt.m_resolution =
|
||||
Resolution(m_overwriteDialog->execute(&clt.m_outputPath));
|
||||
|
@ -634,7 +636,7 @@ bool CleanupPopup::analyzeCleanupList() {
|
|||
TPointD outDpi;
|
||||
m_params->getOutputImageInfo(outRes, outDpi.x, outDpi.y);
|
||||
|
||||
if (oldRes != outRes) {
|
||||
if (oldRes != outRes && inputPath != outputPath) {
|
||||
DVGui::warning(
|
||||
tr("The resulting resolution of level \"%1\"\ndoes not match "
|
||||
"with that of previously cleaned up level drawings.\n\nPlease "
|
||||
|
@ -789,7 +791,13 @@ TImageP CleanupPopup::currentImage() const {
|
|||
if (!isValidPosition(m_idx)) return TImageP();
|
||||
|
||||
const CleanupLevel &cl = m_cleanupLevels[m_idx.first];
|
||||
return cl.m_sl->getFrameToCleanup(cl.m_frames[m_idx.second]);
|
||||
|
||||
// if lines are not processed, obtain the original sampled image
|
||||
bool toBeLineProcessed =
|
||||
TCleanupper::instance()->getParameters()->m_lineProcessingMode != lpNone;
|
||||
|
||||
return cl.m_sl->getFrameToCleanup(cl.m_frames[m_idx.second],
|
||||
toBeLineProcessed);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1195,19 +1203,35 @@ void CleanupPopup::cleanupFrame() {
|
|||
TCleanupper *cl = TCleanupper::instance();
|
||||
const CleanupParameters *params = cl->getParameters();
|
||||
|
||||
// Obtain the source dpi. Changed it to be done once at the first frame of
|
||||
// each level in order to avoid the following problem:
|
||||
// If the original raster level has no dpi (such as TGA images), obtaining
|
||||
// dpi in every frame causes dpi mismatch between the first frame and the
|
||||
// following frames, since the value
|
||||
// TXshSimpleLevel::m_properties->getDpi() will be changed to the
|
||||
// dpi of cleanup camera (= TLV's dpi) after finishing the first frame.
|
||||
if (m_firstLevelFrame) {
|
||||
TPointD dpi;
|
||||
original->getDpi(dpi.x, dpi.y);
|
||||
if (dpi.x == 0 && dpi.y == 0) dpi = sl->getProperties()->getDpi();
|
||||
cl->setSourceDpi(dpi);
|
||||
}
|
||||
|
||||
if (params->m_lineProcessingMode == lpNone) {
|
||||
// No line processing
|
||||
|
||||
TRasterImageP ri(original);
|
||||
if (params->m_autocenterType != CleanupTypes::AUTOCENTER_NONE) {
|
||||
/*if (params->m_autocenterType != CleanupTypes::AUTOCENTER_NONE) {
|
||||
bool autocentered;
|
||||
ri = cl->autocenterOnly(original, false, autocentered);
|
||||
if (!autocentered)
|
||||
DVGui::warning(
|
||||
QObject::tr("The autocentering failed on the current drawing."));
|
||||
}
|
||||
}*/
|
||||
cl->process(original, false, ri, false, true, true, nullptr,
|
||||
ri->getRaster());
|
||||
|
||||
sl->setFrame(fid, ri);
|
||||
if (TRaster32P(ri->getRaster())) sl->setFrame(fid, ri);
|
||||
|
||||
// Update the associated file. In case the operation throws, oh well the
|
||||
// image gets skipped.
|
||||
|
@ -1220,20 +1244,6 @@ void CleanupPopup::cleanupFrame() {
|
|||
} else {
|
||||
// Perform main processing
|
||||
|
||||
// Obtain the source dpi. Changed it to be done once at the first frame of
|
||||
// each level in order to avoid the following problem:
|
||||
// If the original raster level has no dpi (such as TGA images), obtaining
|
||||
// dpi in every frame causes dpi mismatch between the first frame and the
|
||||
// following frames, since the value
|
||||
// TXshSimpleLevel::m_properties->getDpi() will be changed to the
|
||||
// dpi of cleanup camera (= TLV's dpi) after finishing the first frame.
|
||||
if (m_firstLevelFrame) {
|
||||
TPointD dpi;
|
||||
original->getDpi(dpi.x, dpi.y);
|
||||
if (dpi.x == 0 && dpi.y == 0) dpi = sl->getProperties()->getDpi();
|
||||
cl->setSourceDpi(dpi);
|
||||
}
|
||||
|
||||
CleanupPreprocessedImage *cpi;
|
||||
{
|
||||
TRasterImageP resampledRaster;
|
||||
|
@ -1503,6 +1513,14 @@ void CleanupPopup::OverwriteDialog::reset() {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CleanupPopup::OverwriteDialog::enableOptions(bool writingOnSource) {
|
||||
if (writingOnSource && m_buttonGroup->button(REPLACE)->isChecked())
|
||||
m_buttonGroup->button(OVERWRITE)->setChecked(true);
|
||||
m_buttonGroup->button(REPLACE)->setDisabled(writingOnSource);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
QString CleanupPopup::OverwriteDialog::acceptResolution(void *obj,
|
||||
int resolution,
|
||||
bool applyToAll) {
|
||||
|
|
|
@ -144,6 +144,7 @@ public:
|
|||
OverwriteDialog();
|
||||
|
||||
void reset() override;
|
||||
void enableOptions(bool writingOnSource);
|
||||
|
||||
private:
|
||||
DVGui::LineEdit *m_suffix;
|
||||
|
|
|
@ -405,7 +405,7 @@ void CleanupSettingsModel::rebuildPreview() {
|
|||
void CleanupSettingsModel::processFrame(TXshSimpleLevel *sl, TFrameId fid) {
|
||||
assert(sl);
|
||||
|
||||
TRasterImageP imageToCleanup = sl->getFrameToCleanup(fid);
|
||||
TRasterImageP imageToCleanup = sl->getFrameToCleanup(fid, true);
|
||||
if (!imageToCleanup) return;
|
||||
|
||||
// Store the original image
|
||||
|
@ -741,5 +741,6 @@ TFilePath CleanupSettingsModel::getOutputPath(TXshSimpleLevel *sl,
|
|||
const TFilePath &outDir = params->getPath(scene);
|
||||
|
||||
return lineProcessing ? (outDir + inPath.getWideName()).withType("tlv")
|
||||
: (outDir + inPath.getLevelNameW()).withType("tif");
|
||||
: (outDir + inPath.getLevelNameW())
|
||||
.withType(params->m_lpNoneFormat);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "toonz/tscenehandle.h"
|
||||
#include "toonz/toonzscene.h"
|
||||
#include "toonz/toonzfolders.h"
|
||||
#include "toonz/cleanupcolorstyles.h"
|
||||
|
||||
// ToonzQt includes
|
||||
#include "toonzqt/gutil.h"
|
||||
|
@ -101,6 +102,8 @@ CleanupSettingsPane::CleanupSettingsPane(QWidget *parent)
|
|||
m_aaValueLabel = new QLabel(tr("MLAA Intensity:"));
|
||||
m_aaValue = new IntField(this);
|
||||
m_lineProcessing = new QComboBox(this);
|
||||
m_lpNoneFormatLabel = new QLabel(tr("Format:"));
|
||||
m_lpNoneFormat = new QComboBox(this);
|
||||
m_paletteViewer = new CleanupPaletteViewer(this);
|
||||
m_pathField = new CleanupSaveInField(this, QString(""));
|
||||
|
||||
|
@ -143,6 +146,13 @@ CleanupSettingsPane::CleanupSettingsPane(QWidget *parent)
|
|||
items << tr("None") << tr("Greyscale") << tr("Color");
|
||||
m_lineProcessing->addItems(items);
|
||||
|
||||
items.clear();
|
||||
items << "tif"
|
||||
<< "png"
|
||||
<< "jpg"
|
||||
<< "tga";
|
||||
m_lpNoneFormat->addItems(items);
|
||||
|
||||
m_sharpness->setValues(90, 0, 100);
|
||||
m_despeckling->setValues(2, 0, 20);
|
||||
m_aaValue->setValues(70, 0, 100);
|
||||
|
@ -223,15 +233,15 @@ CleanupSettingsPane::CleanupSettingsPane(QWidget *parent)
|
|||
lineProcLay->addWidget(m_aaValueLabel, 4, 0,
|
||||
Qt::AlignRight | Qt::AlignVCenter);
|
||||
lineProcLay->addWidget(m_aaValue, 4, 1);
|
||||
lineProcLay->addWidget(m_lpNoneFormatLabel, 5, 0,
|
||||
Qt::AlignRight | Qt::AlignVCenter);
|
||||
lineProcLay->addWidget(m_lpNoneFormat, 5, 1,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
|
||||
lineProcLay->addWidget(m_paletteViewer, 5, 0, 1, 2);
|
||||
lineProcLay->addWidget(m_paletteViewer, 6, 0, 1, 2);
|
||||
}
|
||||
lineProcLay->setRowStretch(0, 0);
|
||||
lineProcLay->setRowStretch(1, 0);
|
||||
lineProcLay->setRowStretch(2, 0);
|
||||
lineProcLay->setRowStretch(3, 0);
|
||||
lineProcLay->setRowStretch(4, 0);
|
||||
lineProcLay->setRowStretch(5, 1);
|
||||
for (int r = 0; r <= 5; r++) lineProcLay->setRowStretch(r, 0);
|
||||
lineProcLay->setRowStretch(6, 1);
|
||||
lineProcLay->setColumnStretch(0, 0);
|
||||
lineProcLay->setColumnStretch(1, 1);
|
||||
|
||||
|
@ -286,6 +296,8 @@ CleanupSettingsPane::CleanupSettingsPane(QWidget *parent)
|
|||
SLOT(onGenericSettingsChange()));
|
||||
ret = ret && connect(m_lineProcessing, SIGNAL(activated(int)),
|
||||
SLOT(onGenericSettingsChange()));
|
||||
ret = ret && connect(m_lpNoneFormat, SIGNAL(activated(int)),
|
||||
SLOT(onGenericSettingsChange()));
|
||||
ret = ret && connect(m_despeckling, SIGNAL(valueChanged(bool)),
|
||||
SLOT(onGenericSettingsChange()));
|
||||
ret = ret && connect(m_aaValue, SIGNAL(valueChanged(bool)),
|
||||
|
@ -404,6 +416,8 @@ void CleanupSettingsPane::updateGui(CleanupParameters *params,
|
|||
m_sharpness->setValue(params->m_sharpness);
|
||||
m_despeckling->setValue(params->m_despeckling);
|
||||
m_aaValue->setValue(params->m_aaValue);
|
||||
m_lpNoneFormat->setCurrentText(
|
||||
QString::fromStdString(params->m_lpNoneFormat));
|
||||
|
||||
updateVisibility();
|
||||
|
||||
|
@ -462,6 +476,8 @@ void CleanupSettingsPane::updateVisibility() {
|
|||
for (QWidget *w : m_lpWidgets) w->setVisible(lp);
|
||||
m_aaValueLabel->setVisible(MLAA);
|
||||
m_aaValue->setVisible(MLAA);
|
||||
m_lpNoneFormatLabel->setVisible(!lp);
|
||||
m_lpNoneFormat->setVisible(!lp);
|
||||
|
||||
m_paletteViewer->setMode(lpGrey);
|
||||
m_paletteViewer->setContrastEnabled(m_antialias->currentIndex() == 0);
|
||||
|
@ -525,15 +541,30 @@ void CleanupSettingsPane::onGenericSettingsChange() {
|
|||
params->m_flipy = m_flipY->isChecked();
|
||||
|
||||
//------
|
||||
|
||||
params->m_lineProcessingMode = m_lineProcessing->currentIndex();
|
||||
params->m_noAntialias = (m_antialias->currentIndex() > 0);
|
||||
params->m_postAntialias = (m_antialias->currentIndex() == 2);
|
||||
params->m_despeckling = m_despeckling->getValue();
|
||||
params->m_aaValue = m_aaValue->getValue();
|
||||
|
||||
if (params->m_lineProcessingMode == lpNone)
|
||||
params->m_transparencyCheckEnabled = false;
|
||||
if (params->m_lineProcessingMode != m_lineProcessing->currentIndex()) {
|
||||
int oldMode = params->m_lineProcessingMode;
|
||||
params->m_lineProcessingMode = m_lineProcessing->currentIndex();
|
||||
if (params->m_lineProcessingMode == lpNone) {
|
||||
params->m_transparencyCheckEnabled = false;
|
||||
}
|
||||
// When switching from/to Greyscale processing, replace the brightness and
|
||||
// contrast values by the registered ones.
|
||||
if (oldMode == lpGrey || params->m_lineProcessingMode == lpGrey) {
|
||||
TCleanupStyle *blackStyle =
|
||||
dynamic_cast<TCleanupStyle *>(params->m_cleanupPalette->getStyle(1));
|
||||
double b = params->m_altBrightness;
|
||||
double c = params->m_altContrast;
|
||||
params->m_altBrightness = blackStyle->getBrightness();
|
||||
params->m_altContrast = blackStyle->getContrast();
|
||||
blackStyle->setBrightness(b);
|
||||
blackStyle->setContrast(c);
|
||||
}
|
||||
}
|
||||
params->m_noAntialias = (m_antialias->currentIndex() > 0);
|
||||
params->m_postAntialias = (m_antialias->currentIndex() == 2);
|
||||
params->m_despeckling = m_despeckling->getValue();
|
||||
params->m_aaValue = m_aaValue->getValue();
|
||||
params->m_lpNoneFormat = m_lpNoneFormat->currentText().toStdString();
|
||||
//------
|
||||
|
||||
m_cameraWidget->getFields(model->getCurrentParameters());
|
||||
|
|
|
@ -62,6 +62,8 @@ private:
|
|||
QLabel *m_aaValueLabel;
|
||||
DVGui::IntField *m_aaValue;
|
||||
QComboBox *m_lineProcessing;
|
||||
QLabel *m_lpNoneFormatLabel;
|
||||
QComboBox *m_lpNoneFormat;
|
||||
//----Cleanup Palette
|
||||
CleanupPaletteViewer *m_paletteViewer;
|
||||
//----Bottom Parts
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
// TnzBase includes
|
||||
#include "tfx.h"
|
||||
#include "tfxattributes.h"
|
||||
#include "tparamcontainer.h"
|
||||
#include "tparamset.h"
|
||||
|
||||
// TnzCore includes
|
||||
#include "tstroke.h"
|
||||
|
@ -100,9 +102,24 @@ void getColumnLinkedFxs(TFx *startFx, TFx *newStartFx,
|
|||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
template <typename ParamCont>
|
||||
void setGrammerToParams(const ParamCont *cont,
|
||||
const TSyntax::Grammar *grammer) {
|
||||
for (int p = 0; p != cont->getParamCount(); ++p) {
|
||||
TParam ¶m = *cont->getParam(p);
|
||||
if (TDoubleParam *dp = dynamic_cast<TDoubleParam *>(¶m))
|
||||
dp->setGrammar(grammer);
|
||||
else if (TParamSet *paramSet = dynamic_cast<TParamSet *>(¶m))
|
||||
setGrammerToParams(paramSet, grammer);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void cloneNotColumnLinkedFxsAndOutputsFx(TXsheet *xsh, TXsheet *newXsh) {
|
||||
void cloneNotColumnLinkedFxsAndOutputsFx(
|
||||
TXsheet *xsh, TXsheet *newXsh, QMap<TFx *, TFx *> *fxTable = nullptr) {
|
||||
int columnCount = xsh->getColumnCount();
|
||||
assert(newXsh->getColumnCount() == columnCount);
|
||||
|
||||
|
@ -136,6 +153,9 @@ void cloneNotColumnLinkedFxsAndOutputsFx(TXsheet *xsh, TXsheet *newXsh) {
|
|||
newFxDag->getInternalFxs()->addFx(newFx);
|
||||
if (fxDag->getTerminalFxs()->containsFx(fx))
|
||||
newFxDag->getTerminalFxs()->addFx(newFx);
|
||||
// if the fx has not unique name then let assignUniqueId() set the default
|
||||
// name
|
||||
if (newFx->getName() == newFx->getFxId()) newFx->setName(L"");
|
||||
newFxDag->assignUniqueId(newFx);
|
||||
clonedFxs[fx] = newFx;
|
||||
notColumnLinkedClonedFxs.append(newFx);
|
||||
|
@ -203,6 +223,17 @@ void cloneNotColumnLinkedFxsAndOutputsFx(TXsheet *xsh, TXsheet *newXsh) {
|
|||
newOutputFx->getInputPort(0)->setFx(newInputFx);
|
||||
}
|
||||
}
|
||||
|
||||
// reset grammers for all parameters of cloned fxs
|
||||
// or they fails to refer to other parameters via expression
|
||||
TSyntax::Grammar *grammer = newXsh->getStageObjectTree()->getGrammar();
|
||||
QMap<TFx *, TFx *>::const_iterator it;
|
||||
for (it = clonedFxs.constBegin(); it != clonedFxs.constEnd(); ++it) {
|
||||
setGrammerToParams(it.value()->getParams(), grammer);
|
||||
|
||||
// register to the fx table for expression management
|
||||
if (fxTable) fxTable->insert(it.key(), it.value());
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1077,11 +1108,13 @@ void ColumnCmd::cloneChild(int index) {
|
|||
data->storeColumns(indices, childXsh, 0);
|
||||
data->storeColumnFxs(indices, childXsh, 0);
|
||||
std::list<int> restoredSplineIds;
|
||||
QMap<TStageObjectId, TStageObjectId> idTable;
|
||||
QMap<TFx *, TFx *> fxTable;
|
||||
data->restoreObjects(indices, restoredSplineIds, newChildXsh,
|
||||
StageObjectsData::eDoClone);
|
||||
StageObjectsData::eDoClone, idTable, fxTable);
|
||||
delete data;
|
||||
|
||||
cloneNotColumnLinkedFxsAndOutputsFx(childXsh, newChildXsh);
|
||||
cloneNotColumnLinkedFxsAndOutputsFx(childXsh, newChildXsh, &fxTable);
|
||||
cloneXsheetTStageObjectTree(childXsh, newChildXsh);
|
||||
/*--以下は、Clone SubXsheet
|
||||
するときに、SubXsheet内にある子SubXsheetをクローンする関数
|
||||
|
@ -1094,6 +1127,10 @@ void ColumnCmd::cloneChild(int index) {
|
|||
newChildXsh->getFxDag()->getXsheetFx()->getAttributes()->setDagNodePos(
|
||||
childXsh->getFxDag()->getXsheetFx()->getAttributes()->getDagNodePos());
|
||||
|
||||
ExpressionReferenceManager::instance()->refreshXsheetRefInfo(newChildXsh);
|
||||
ExpressionReferenceManager::instance()->transferReference(
|
||||
childXsh, newChildXsh, idTable, fxTable);
|
||||
|
||||
newChildXsh->updateFrameCount();
|
||||
|
||||
/*-- TXshChildLevel作成時にsetCellした1つ目のセルを消去 --*/
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "toonz/tstageobject.h"
|
||||
#include "toonz/preferences.h"
|
||||
#include "toonz/toonzfolders.h"
|
||||
#include "toonz/txshsoundtextcolumn.h"
|
||||
#include "toonz/txshsoundtextlevel.h"
|
||||
|
||||
// TnzCore includes
|
||||
#include "tsystem.h"
|
||||
|
@ -74,6 +76,8 @@ TEnv::IntVar XShPdfExportPrintSoundtrack("XShPdfExportPrintSoundtrack", 0);
|
|||
TEnv::IntVar XShPdfExportSerialFrameNumber("XShPdfExportSerialFrameNumber", 0);
|
||||
// print level name on the bottom
|
||||
TEnv::IntVar XShPdfExportLevelNameOnBottom("XShPdfExportLevelNameOnBottom", 0);
|
||||
// print dialogue
|
||||
TEnv::IntVar XShPdfExportPrintDialogue("XShPdfExportPrintDialogue", 0);
|
||||
// print scene name
|
||||
TEnv::IntVar XShPdfExportPrintSceneName("XShPdfExportPrintSceneName", 0);
|
||||
// template font
|
||||
|
@ -90,6 +94,12 @@ TEnv::StringVar XShPdfExportImgPath("XShPdfExportImgPath", "");
|
|||
TEnv::IntVar XShPdfExportContinuousLineThres("XShPdfExportContinuousLineThres",
|
||||
0);
|
||||
|
||||
TEnv::IntVar XShPdfExportTick1Id("XShPdfExportTick1Id", -1);
|
||||
TEnv::IntVar XShPdfExportTick2Id("XShPdfExportTick2Id", -1);
|
||||
TEnv::IntVar XShPdfExportKeyId("XShPdfExportKeyId", -1);
|
||||
TEnv::IntVar XShPdfExportTick1Type("XShPdfExportTick1Type", TickMark_Dot);
|
||||
TEnv::IntVar XShPdfExportTick2Type("XShPdfExportTick2Type", TickMark_Dot);
|
||||
|
||||
using namespace XSheetPDFTemplateParamIDs;
|
||||
|
||||
namespace {
|
||||
|
@ -287,6 +297,86 @@ XSheetPDFDataType dataStr2Type(const QString& str) {
|
|||
return map.value(str, Data_Invalid);
|
||||
}
|
||||
|
||||
QIcon getColorChipIcon(TPixel32 color) {
|
||||
QPixmap pm(15, 15);
|
||||
pm.fill(QColor(color.r, color.g, color.b));
|
||||
return QIcon(pm);
|
||||
}
|
||||
|
||||
void refreshCellMarkComboItems(QComboBox* combo) {
|
||||
int current = -1;
|
||||
if (combo->count()) current = combo->currentData().toInt();
|
||||
|
||||
combo->clear();
|
||||
QList<TSceneProperties::CellMark> marks = TApp::instance()
|
||||
->getCurrentScene()
|
||||
->getScene()
|
||||
->getProperties()
|
||||
->getCellMarks();
|
||||
combo->addItem(QObject::tr("None", "XSheetPDF CellMark"), -1);
|
||||
int curId = 0;
|
||||
for (auto mark : marks) {
|
||||
QString label = QString("%1: %2").arg(curId).arg(mark.name);
|
||||
combo->addItem(getColorChipIcon(mark.color), label, curId);
|
||||
curId++;
|
||||
}
|
||||
|
||||
if (current >= 0) combo->setCurrentIndex(combo->findData(current));
|
||||
}
|
||||
|
||||
QPixmap tickMarkPm(TickMarkType type, int size, bool withBG = false) {
|
||||
QPixmap pm(size, size);
|
||||
QPointF center(double(size) * 0.5, double(size) * 0.5);
|
||||
|
||||
pm.fill((withBG) ? Qt::white : Qt::transparent);
|
||||
QPainter p(&pm);
|
||||
QPen pen(Qt::black);
|
||||
pen.setWidthF(double(size) / 15.0);
|
||||
p.setPen(pen);
|
||||
switch (type) {
|
||||
case TickMark_Dot: {
|
||||
p.setBrush(Qt::black);
|
||||
double dotR = double(size) * 0.1;
|
||||
p.drawEllipse(center, dotR, dotR);
|
||||
break;
|
||||
}
|
||||
case TickMark_Circle: {
|
||||
double circleR = double(size) * 0.4;
|
||||
p.drawEllipse(center, circleR, circleR);
|
||||
break;
|
||||
}
|
||||
case TickMark_Filled: {
|
||||
p.setBrush(Qt::black);
|
||||
double circleR = double(size) * 0.4;
|
||||
p.drawEllipse(center, circleR, circleR);
|
||||
break;
|
||||
}
|
||||
case TickMark_Asterisk: {
|
||||
QFont font = p.font();
|
||||
font.setPixelSize(size);
|
||||
p.setFont(font);
|
||||
p.drawText(0, 0, size, size, Qt::AlignCenter, "*");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pm;
|
||||
}
|
||||
|
||||
QComboBox* createTickMarkCombo(QWidget* parent) {
|
||||
QComboBox* combo = new QComboBox(parent);
|
||||
combo->addItem(QIcon(tickMarkPm(TickMark_Dot, 15, true)),
|
||||
QObject::tr("Dot", "XSheetPDF CellMark"), TickMark_Dot);
|
||||
combo->addItem(QIcon(tickMarkPm(TickMark_Circle, 15, true)),
|
||||
QObject::tr("Circle", "XSheetPDF CellMark"), TickMark_Circle);
|
||||
combo->addItem(QIcon(tickMarkPm(TickMark_Filled, 15, true)),
|
||||
QObject::tr("Filled circle", "XSheetPDF CellMark"),
|
||||
TickMark_Filled);
|
||||
combo->addItem(QIcon(tickMarkPm(TickMark_Asterisk, 15, true)),
|
||||
QObject::tr("Asterisk", "XSheetPDF CellMark"),
|
||||
TickMark_Asterisk);
|
||||
return combo;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
//---------------------------------------------------------
|
||||
|
||||
|
@ -652,7 +742,7 @@ void XSheetPDFTemplate::drawDialogBlock(QPainter& painter, const int framePage,
|
|||
painter.restore();
|
||||
|
||||
// register sound cells
|
||||
if (m_info.drawSound)
|
||||
if (m_info.drawSound || m_noteColumn)
|
||||
registerSoundRects(painter, param(DialogColWidth), bodyId);
|
||||
}
|
||||
painter.restore();
|
||||
|
@ -859,7 +949,7 @@ void XSheetPDFTemplate::drawContinuousLine(QPainter& painter, QRect rect,
|
|||
}
|
||||
|
||||
void XSheetPDFTemplate::drawCellNumber(QPainter& painter, QRect rect,
|
||||
TXshCell& cell) {
|
||||
TXshCell& cell, bool isKey) {
|
||||
QFont font = painter.font();
|
||||
font.setPixelSize(param(RowHeight) - mm2px(1));
|
||||
font.setLetterSpacing(QFont::PercentageSpacing, 100);
|
||||
|
@ -874,12 +964,38 @@ void XSheetPDFTemplate::drawCellNumber(QPainter& painter, QRect rect,
|
|||
str = getFrameNumberWithLetters(cell.m_frameId.getNumber());
|
||||
} else {
|
||||
str = QString::number(cell.m_frameId.getNumber());
|
||||
if (cell.m_frameId.getLetter() != '\0') str += cell.m_frameId.getLetter();
|
||||
if (!cell.m_frameId.getLetter().isEmpty())
|
||||
str += cell.m_frameId.getLetter();
|
||||
}
|
||||
painter.drawText(rect, Qt::AlignCenter, str);
|
||||
if (isKey) {
|
||||
QPen keep(painter.pen());
|
||||
QPen circlePen(keep);
|
||||
circlePen.setWidth(mm2px(0.3));
|
||||
painter.setPen(circlePen);
|
||||
QFontMetrics fm(font);
|
||||
#if QT_VERSION >= 0x051100
|
||||
int keyR_width =
|
||||
std::max(param(RowHeight), fm.horizontalAdvance(str) + mm2px(1));
|
||||
#else
|
||||
int keyR_width =
|
||||
std::max(param(RowHeight), fm.boundingRect(str).width() + mm2px(1));
|
||||
#endif
|
||||
QRect keyR(0, 0, keyR_width, param(RowHeight));
|
||||
keyR.moveCenter(rect.center());
|
||||
painter.drawEllipse(keyR);
|
||||
painter.setPen(keep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XSheetPDFTemplate::drawTickMark(QPainter& painter, QRect rect,
|
||||
TickMarkType type) {
|
||||
QRect tickR(0, 0, rect.height(), rect.height());
|
||||
tickR.moveCenter(rect.center());
|
||||
painter.drawPixmap(tickR, tickMarkPm(type, rect.height()));
|
||||
}
|
||||
|
||||
void XSheetPDFTemplate::drawEndMark(QPainter& painter, QRect upperRect) {
|
||||
QRect rect = upperRect.translated(0, upperRect.height());
|
||||
|
||||
|
@ -1024,6 +1140,153 @@ void XSheetPDFTemplate::drawSound(QPainter& painter, int framePage) {
|
|||
}
|
||||
}
|
||||
|
||||
void XSheetPDFTemplate::drawDialogue(QPainter& painter, int framePage) {
|
||||
if (!m_noteColumn || m_soundCellRects.isEmpty()) return;
|
||||
|
||||
QFont font = painter.font();
|
||||
font.setPixelSize(m_soundCellRects[0].height());
|
||||
painter.setFont(font);
|
||||
|
||||
QFont smallFont(font);
|
||||
smallFont.setPixelSize(font.pixelSize() * 2 / 3);
|
||||
|
||||
QFont largeFont(font);
|
||||
largeFont.setPixelSize(font.pixelSize() * 13 / 10);
|
||||
int heightThres = QFontMetrics(largeFont).height();
|
||||
|
||||
int r0, r1;
|
||||
m_noteColumn->getRange(r0, r1);
|
||||
|
||||
// obtain frame range to be printed in the current page
|
||||
int printFrameR0 = framePage * param(FrameLength);
|
||||
int printFrameR1 = printFrameR0 + param(FrameLength) - 1;
|
||||
|
||||
// compute for each body
|
||||
int framesPerBody = 72;
|
||||
int bodyFrameR0 = printFrameR0;
|
||||
int bodyFrameR1 = bodyFrameR0 + framesPerBody - 1;
|
||||
while (bodyFrameR1 <= printFrameR1) {
|
||||
// move to next body if the current body is out of range
|
||||
if (r1 < bodyFrameR0 || bodyFrameR1 < r0) {
|
||||
// to next body
|
||||
bodyFrameR0 = bodyFrameR1 + 1;
|
||||
bodyFrameR1 = bodyFrameR0 + framesPerBody - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// frame range to be printed
|
||||
int drawStart = std::max(r0, bodyFrameR0);
|
||||
int drawEnd = std::min(r1, std::min(bodyFrameR1, printFrameR1));
|
||||
|
||||
int rStart = drawStart;
|
||||
int rEnd = drawEnd;
|
||||
// obtain top row of the fist note block
|
||||
if (!m_noteColumn->getCell(drawStart).isEmpty()) {
|
||||
while (rStart > 0 && m_noteColumn->getCell(rStart - 1) ==
|
||||
m_noteColumn->getCell(drawStart)) {
|
||||
rStart--;
|
||||
}
|
||||
}
|
||||
// obtain bottom row of the last note block
|
||||
if (!m_noteColumn->getCell(drawEnd).isEmpty()) {
|
||||
while (m_noteColumn->getCell(rEnd + 1) ==
|
||||
m_noteColumn->getCell(drawEnd)) {
|
||||
rEnd++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int row = rStart; row <= drawEnd; row++) {
|
||||
TXshCell cell = m_noteColumn->getCell(row);
|
||||
if (cell.isEmpty()) continue;
|
||||
|
||||
// check how long the same content continues
|
||||
int rowTo = row;
|
||||
while (m_noteColumn->getCell(rowTo + 1) == cell) {
|
||||
rowTo++;
|
||||
}
|
||||
int blockLength = rowTo - row + 1;
|
||||
|
||||
QString text = cell.getSoundTextLevel()->getFrameText(
|
||||
cell.m_frameId.getNumber() - 1);
|
||||
int textCount = text.count();
|
||||
// separate text if it overflows the body
|
||||
if (row < drawStart) {
|
||||
int partialBlockLength = rowTo - drawStart + 1;
|
||||
int partialTextCount = (int)std::round(
|
||||
(double)(textCount * partialBlockLength) / (double)blockLength);
|
||||
text = text.mid(textCount - partialTextCount);
|
||||
textCount = partialTextCount;
|
||||
row = drawStart;
|
||||
blockLength = partialBlockLength;
|
||||
}
|
||||
// draw start mark
|
||||
else {
|
||||
int topRectId = row - printFrameR0;
|
||||
QRect rect = m_soundCellRects.at(topRectId);
|
||||
painter.drawLine(rect.topLeft(), rect.topRight());
|
||||
}
|
||||
|
||||
if (rowTo > drawEnd) {
|
||||
int partialBlockLength = drawEnd - row + 1;
|
||||
int partialTextCount = (int)std::round(
|
||||
(double)(textCount * partialBlockLength) / (double)blockLength);
|
||||
text = text.mid(0, partialTextCount);
|
||||
textCount = partialTextCount;
|
||||
rowTo = drawEnd;
|
||||
}
|
||||
// draw end mark
|
||||
else if (m_noteColumn->getCell(rowTo + 1).isEmpty()) {
|
||||
int bottomRectId = rowTo - printFrameR0;
|
||||
QRect rect = m_soundCellRects.at(bottomRectId);
|
||||
drawEndMark(painter, rect);
|
||||
}
|
||||
if (text.isEmpty()) {
|
||||
row = rowTo;
|
||||
continue;
|
||||
}
|
||||
|
||||
int normalLettersPerChunk = textCount * m_soundCellRects[0].width() /
|
||||
QFontMetrics(font).boundingRect(text).width();
|
||||
int maxLettersPerChunk =
|
||||
textCount * m_soundCellRects[0].width() /
|
||||
QFontMetrics(smallFont).boundingRect(text).width();
|
||||
|
||||
int lettersPerChunk =
|
||||
(int)std::ceil((double)textCount / ((double)blockLength));
|
||||
lettersPerChunk = std::min(lettersPerChunk, maxLettersPerChunk);
|
||||
int chunkCount =
|
||||
(int)std::ceil((double)textCount / (double)(lettersPerChunk));
|
||||
chunkCount = std::min(chunkCount, (int)((double)(blockLength)*1.5));
|
||||
|
||||
int topRectId = row - printFrameR0;
|
||||
int bottomRectId = rowTo - printFrameR0;
|
||||
// unite the cell rects and divide by the amount of chunks
|
||||
QRect unitedRect = m_soundCellRects.at(topRectId).united(
|
||||
m_soundCellRects.at(bottomRectId));
|
||||
// check if the large font is available
|
||||
if (lettersPerChunk == 1 && unitedRect.height() / textCount > heightThres)
|
||||
painter.setFont(largeFont);
|
||||
else if (lettersPerChunk > normalLettersPerChunk)
|
||||
painter.setFont(smallFont);
|
||||
else
|
||||
painter.setFont(font);
|
||||
// draw text
|
||||
for (int c = 0; c < chunkCount; c++) {
|
||||
int y0 = unitedRect.top() + unitedRect.height() * c / chunkCount;
|
||||
int y1 = unitedRect.top() + unitedRect.height() * (c + 1) / chunkCount;
|
||||
QRect tmpRect(unitedRect.left(), y0, unitedRect.width(), y1 - y0 + 1);
|
||||
painter.drawText(tmpRect, Qt::AlignCenter,
|
||||
text.mid(c * lettersPerChunk, lettersPerChunk));
|
||||
}
|
||||
|
||||
row = rowTo;
|
||||
}
|
||||
// to next body
|
||||
bodyFrameR0 = bodyFrameR1 + 1;
|
||||
bodyFrameR1 = bodyFrameR0 + framesPerBody - 1;
|
||||
}
|
||||
}
|
||||
|
||||
XSheetPDFTemplate::XSheetPDFTemplate(
|
||||
const QList<QPair<TXshLevelColumn*, QString>>& columns, const int duration)
|
||||
: m_columns(columns), m_duration(duration), m_useExtraColumns(false) {}
|
||||
|
@ -1101,6 +1364,10 @@ void XSheetPDFTemplate::drawXsheetContents(QPainter& painter, int framePage,
|
|||
painter.setPen(
|
||||
QPen(Qt::black, mm2px(0.5), Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
|
||||
painter.setFont(m_info.contentsFontFamily);
|
||||
|
||||
// draw dialogue
|
||||
drawDialogue(painter, framePage);
|
||||
|
||||
int colsInPage = columnsInPage();
|
||||
int startColId = colsInPage * parallelPage;
|
||||
int startFrame = param(FrameLength) * framePage;
|
||||
|
@ -1135,14 +1402,23 @@ void XSheetPDFTemplate::drawXsheetContents(QPainter& painter, int framePage,
|
|||
TXshCell cell = column->getCell(f);
|
||||
if (cell.m_level != level) cell.m_level = nullptr;
|
||||
|
||||
int markId = column->getCellMark(r);
|
||||
|
||||
// cotinuous line
|
||||
if (r != 0 && r != 72 && prevCell == cell) {
|
||||
if (drawCLFlag)
|
||||
// draw tick mark
|
||||
if (markId >= 0 && m_info.tick1MarkId == markId)
|
||||
drawTickMark(painter, m_cellRects[c][r], m_info.tick1MarkType);
|
||||
else if (markId >= 0 && m_info.tick2MarkId == markId)
|
||||
drawTickMark(painter, m_cellRects[c][r], m_info.tick2MarkType);
|
||||
|
||||
else if (drawCLFlag)
|
||||
drawContinuousLine(painter, m_cellRects[c][r], cell.isEmpty());
|
||||
}
|
||||
// draw cell
|
||||
else {
|
||||
drawCellNumber(painter, m_cellRects[c][r], cell);
|
||||
bool drawKeyMark = (markId >= 0 && m_info.keyMarkId == markId);
|
||||
drawCellNumber(painter, m_cellRects[c][r], cell, drawKeyMark);
|
||||
drawCLFlag = (m_info.continuousLineMode == Line_Always)
|
||||
? true
|
||||
: (m_info.continuousLineMode == Line_None)
|
||||
|
@ -1602,8 +1878,10 @@ ExportXsheetPdfPopup::ExportXsheetPdfPopup()
|
|||
new QCheckBox(tr("Put Serial Frame Numbers Over Pages"), this);
|
||||
m_levelNameOnBottomCB =
|
||||
new QCheckBox(tr("Print Level Names On The Bottom"), this);
|
||||
m_sceneNameEdit = new QLineEdit(this);
|
||||
m_memoEdit = new QTextEdit(this);
|
||||
m_drawDialogueCB = new QCheckBox(tr("Print Dialogue"), this);
|
||||
m_dialogueColCombo = new QComboBox();
|
||||
m_sceneNameEdit = new QLineEdit(this);
|
||||
m_memoEdit = new QTextEdit(this);
|
||||
|
||||
m_logoTxtRB = new QRadioButton(tr("Text"), this);
|
||||
m_logoImgRB = new QRadioButton(tr("Image"), this);
|
||||
|
@ -1620,6 +1898,15 @@ ExportXsheetPdfPopup::ExportXsheetPdfPopup()
|
|||
QPushButton* exportPngBtn = new QPushButton(tr("Export PNG"), this);
|
||||
QPushButton* cancelBtn = new QPushButton(tr("Cancel"), this);
|
||||
|
||||
m_tick1IdCombo = new QComboBox(this);
|
||||
m_tick2IdCombo = new QComboBox(this);
|
||||
m_keyIdCombo = new QComboBox(this);
|
||||
refreshCellMarkComboItems(m_tick1IdCombo);
|
||||
refreshCellMarkComboItems(m_tick2IdCombo);
|
||||
refreshCellMarkComboItems(m_keyIdCombo);
|
||||
m_tick1MarkCombo = createTickMarkCombo(this);
|
||||
m_tick2MarkCombo = createTickMarkCombo(this);
|
||||
|
||||
//------
|
||||
QStringList pdfFileTypes = {"pdf"};
|
||||
m_pathFld->setFilters(pdfFileTypes);
|
||||
|
@ -1636,6 +1923,7 @@ ExportXsheetPdfPopup::ExportXsheetPdfPopup()
|
|||
m_memoEdit->setStyleSheet(
|
||||
"background:white;\ncolor:black;\nborder:1 solid black;");
|
||||
m_memoEdit->setFixedHeight(150);
|
||||
m_dialogueColCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
m_sceneNameEdit->setFixedWidth(100);
|
||||
|
||||
m_continuousLineCombo->addItem(tr("Always"), Line_Always);
|
||||
|
@ -1747,22 +2035,44 @@ ExportXsheetPdfPopup::ExportXsheetPdfPopup()
|
|||
exportLay->addWidget(m_continuousLineCombo, 2, 1, 1, 2,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
|
||||
exportLay->addWidget(m_addDateTimeCB, 3, 0, 1, 3,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
exportLay->addWidget(m_addScenePathCB, 4, 0, 1, 3,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
exportLay->addWidget(m_drawSoundCB, 5, 0, 1, 3,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
exportLay->addWidget(m_addSceneNameCB, 6, 0, 1, 2,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
exportLay->addWidget(m_sceneNameEdit, 6, 2,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
exportLay->addWidget(m_levelNameOnBottomCB, 7, 0, 1, 3,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
QGridLayout* checksLay = new QGridLayout();
|
||||
checksLay->setMargin(0);
|
||||
checksLay->setHorizontalSpacing(10);
|
||||
checksLay->setVerticalSpacing(10);
|
||||
{
|
||||
checksLay->addWidget(m_addDateTimeCB, 0, 0);
|
||||
checksLay->addWidget(m_addScenePathCB, 0, 1, 1, 2);
|
||||
checksLay->addWidget(m_drawSoundCB, 1, 0);
|
||||
checksLay->addWidget(m_addSceneNameCB, 1, 1);
|
||||
checksLay->addWidget(m_sceneNameEdit, 1, 2,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
checksLay->addWidget(m_levelNameOnBottomCB, 2, 0);
|
||||
checksLay->addWidget(m_drawDialogueCB, 2, 1);
|
||||
checksLay->addWidget(m_dialogueColCombo, 2, 2,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
}
|
||||
checksLay->setColumnStretch(0, 2);
|
||||
checksLay->setColumnStretch(1, 1);
|
||||
checksLay->setColumnStretch(2, 1);
|
||||
exportLay->addLayout(checksLay, 3, 0, 1, 3);
|
||||
|
||||
exportLay->addWidget(new QLabel(tr("Memo:"), this), 8, 0,
|
||||
exportLay->addWidget(new QLabel(tr("Inbetween mark:"), this), 4, 0,
|
||||
Qt::AlignRight | Qt::AlignVCenter);
|
||||
exportLay->addWidget(m_tick1IdCombo, 4, 1);
|
||||
exportLay->addWidget(m_tick1MarkCombo, 4, 2,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
exportLay->addWidget(new QLabel(tr("Reverse sheet mark:"), this), 5,
|
||||
0, Qt::AlignRight | Qt::AlignVCenter);
|
||||
exportLay->addWidget(m_tick2IdCombo, 5, 1);
|
||||
exportLay->addWidget(m_tick2MarkCombo, 5, 2,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
exportLay->addWidget(new QLabel(tr("Keyframe mark:"), this), 6, 0,
|
||||
Qt::AlignRight | Qt::AlignVCenter);
|
||||
exportLay->addWidget(m_keyIdCombo, 6, 1);
|
||||
|
||||
exportLay->addWidget(new QLabel(tr("Memo:"), this), 7, 0,
|
||||
Qt::AlignRight | Qt::AlignTop);
|
||||
exportLay->addWidget(m_memoEdit, 8, 1, 1, 2);
|
||||
exportLay->addWidget(m_memoEdit, 7, 1, 1, 2);
|
||||
}
|
||||
exportLay->setColumnStretch(2, 1);
|
||||
exportGBox->setLayout(exportLay);
|
||||
|
@ -1831,6 +2141,11 @@ ExportXsheetPdfPopup::ExportXsheetPdfPopup()
|
|||
SLOT(updatePreview()));
|
||||
connect(m_levelNameOnBottomCB, SIGNAL(clicked(bool)), this,
|
||||
SLOT(updatePreview()));
|
||||
connect(m_drawDialogueCB, SIGNAL(clicked(bool)), this, SLOT(updatePreview()));
|
||||
connect(m_drawDialogueCB, SIGNAL(clicked(bool)), m_dialogueColCombo,
|
||||
SLOT(setEnabled(bool)));
|
||||
connect(m_dialogueColCombo, SIGNAL(activated(int)), this,
|
||||
SLOT(updatePreview()));
|
||||
connect(m_addSceneNameCB, SIGNAL(clicked(bool)), this, SLOT(updatePreview()));
|
||||
connect(m_addSceneNameCB, SIGNAL(clicked(bool)), m_sceneNameEdit,
|
||||
SLOT(setEnabled(bool)));
|
||||
|
@ -1849,6 +2164,16 @@ ExportXsheetPdfPopup::ExportXsheetPdfPopup()
|
|||
connect(m_prev, SIGNAL(clicked(bool)), this, SLOT(onPrev()));
|
||||
connect(m_next, SIGNAL(clicked(bool)), this, SLOT(onNext()));
|
||||
|
||||
connect(m_tick1IdCombo, SIGNAL(activated(int)), this,
|
||||
SLOT(onTickIdComboActivated()));
|
||||
connect(m_tick2IdCombo, SIGNAL(activated(int)), this,
|
||||
SLOT(onTickIdComboActivated()));
|
||||
connect(m_keyIdCombo, SIGNAL(activated(int)), this, SLOT(updatePreview()));
|
||||
connect(m_tick1MarkCombo, SIGNAL(activated(int)), this,
|
||||
SLOT(updatePreview()));
|
||||
connect(m_tick2MarkCombo, SIGNAL(activated(int)), this,
|
||||
SLOT(updatePreview()));
|
||||
|
||||
// The following lines are "translation word book" listing the words which may
|
||||
// appear in the template
|
||||
|
||||
|
@ -1932,6 +2257,7 @@ void ExportXsheetPdfPopup::initialize() {
|
|||
|
||||
m_columns.clear();
|
||||
m_soundColumns.clear();
|
||||
m_noteColumns.clear();
|
||||
for (int col = 0; col < xsheet->getColumnCount(); col++) {
|
||||
if (xsheet->isColumnEmpty(col)) continue;
|
||||
|
||||
|
@ -1941,6 +2267,13 @@ void ExportXsheetPdfPopup::initialize() {
|
|||
continue;
|
||||
}
|
||||
|
||||
TXshSoundTextColumn* noteColumn =
|
||||
xsheet->getColumn(col)->getSoundTextColumn();
|
||||
if (noteColumn) {
|
||||
m_noteColumns.insert(col, noteColumn);
|
||||
continue;
|
||||
}
|
||||
|
||||
TXshLevelColumn* column = xsheet->getColumn(col)->getLevelColumn();
|
||||
if (!column) continue;
|
||||
// do not export if the "eye" (render) button is off
|
||||
|
@ -1964,10 +2297,20 @@ void ExportXsheetPdfPopup::initialize() {
|
|||
m_sceneNameEdit->setText(
|
||||
(scene->isUntitled()) ? ""
|
||||
: QString::fromStdWString(scene->getSceneName()));
|
||||
m_drawDialogueCB->setDisabled(m_noteColumns.isEmpty());
|
||||
m_dialogueColCombo->setEnabled(!m_noteColumns.isEmpty() &&
|
||||
m_drawDialogueCB->isChecked());
|
||||
m_dialogueColCombo->clear();
|
||||
for (auto colId : m_noteColumns.keys())
|
||||
m_dialogueColCombo->addItem(tr("Col%1").arg(colId + 1), colId);
|
||||
|
||||
initTemplate();
|
||||
|
||||
m_previewPane->fitScaleTo(m_previewArea->size());
|
||||
|
||||
refreshCellMarkComboItems(m_tick1IdCombo);
|
||||
refreshCellMarkComboItems(m_tick2IdCombo);
|
||||
refreshCellMarkComboItems(m_keyIdCombo);
|
||||
}
|
||||
|
||||
// register settings to the user env file on close
|
||||
|
@ -1983,6 +2326,7 @@ void ExportXsheetPdfPopup::saveSettings() {
|
|||
XShPdfExportPrintSceneName = (m_addSceneNameCB->isChecked()) ? 1 : 0;
|
||||
XShPdfExportSerialFrameNumber = (m_serialFrameNumberCB->isChecked()) ? 1 : 0;
|
||||
XShPdfExportLevelNameOnBottom = (m_levelNameOnBottomCB->isChecked()) ? 1 : 0;
|
||||
XShPdfExportPrintDialogue = (m_drawDialogueCB->isChecked()) ? 1 : 0;
|
||||
XShPdfExportTemplateFont =
|
||||
m_templateFontCB->currentFont().family().toStdString();
|
||||
XShPdfExportOutputFont =
|
||||
|
@ -1995,6 +2339,12 @@ void ExportXsheetPdfPopup::saveSettings() {
|
|||
(ContinuousLineMode)(m_continuousLineCombo->currentData().toInt());
|
||||
XShPdfExportContinuousLineThres =
|
||||
(clMode == Line_Always) ? 0 : (clMode == Line_None) ? -1 : 3;
|
||||
|
||||
XShPdfExportTick1Id = m_tick1IdCombo->currentData().toInt();
|
||||
XShPdfExportTick2Id = m_tick2IdCombo->currentData().toInt();
|
||||
XShPdfExportKeyId = m_keyIdCombo->currentData().toInt();
|
||||
XShPdfExportTick1Type = m_tick1MarkCombo->currentData().toInt();
|
||||
XShPdfExportTick2Type = m_tick2MarkCombo->currentData().toInt();
|
||||
}
|
||||
|
||||
// load settings from the user env file on ctor
|
||||
|
@ -2013,6 +2363,7 @@ void ExportXsheetPdfPopup::loadSettings() {
|
|||
m_addSceneNameCB->setChecked(XShPdfExportPrintSceneName != 0);
|
||||
m_serialFrameNumberCB->setChecked(XShPdfExportSerialFrameNumber != 0);
|
||||
m_levelNameOnBottomCB->setChecked(XShPdfExportLevelNameOnBottom != 0);
|
||||
m_drawDialogueCB->setChecked(XShPdfExportPrintDialogue != 0);
|
||||
|
||||
QString tmplFont = QString::fromStdString(XShPdfExportTemplateFont);
|
||||
if (!tmplFont.isEmpty()) m_templateFontCB->setCurrentFont(QFont(tmplFont));
|
||||
|
@ -2035,6 +2386,21 @@ void ExportXsheetPdfPopup::loadSettings() {
|
|||
m_logoTextEdit->setEnabled(m_logoTxtRB->isChecked());
|
||||
m_logoImgPathField->setEnabled(m_logoImgRB->isChecked());
|
||||
m_sceneNameEdit->setEnabled(m_addSceneNameCB->isChecked());
|
||||
m_dialogueColCombo->setEnabled(m_drawDialogueCB->isChecked() &&
|
||||
m_drawDialogueCB->isEnabled());
|
||||
|
||||
int id = XShPdfExportTick1Id;
|
||||
m_tick1IdCombo->setCurrentIndex(m_tick1IdCombo->findData(id));
|
||||
m_tick1MarkCombo->setEnabled(id != -1);
|
||||
id = XShPdfExportTick2Id;
|
||||
m_tick2IdCombo->setCurrentIndex(m_tick2IdCombo->findData(id));
|
||||
m_tick2MarkCombo->setEnabled(id != -1);
|
||||
id = XShPdfExportKeyId;
|
||||
m_keyIdCombo->setCurrentIndex(m_keyIdCombo->findData(id));
|
||||
int type = XShPdfExportTick1Type;
|
||||
m_tick1MarkCombo->setCurrentIndex(m_tick1MarkCombo->findData(type));
|
||||
type = XShPdfExportTick2Type;
|
||||
m_tick2MarkCombo->setCurrentIndex(m_tick2MarkCombo->findData(type));
|
||||
}
|
||||
|
||||
void ExportXsheetPdfPopup::initTemplate() {
|
||||
|
@ -2095,8 +2461,20 @@ void ExportXsheetPdfPopup::setInfo() {
|
|||
info.serialFrameNumber = m_serialFrameNumberCB->isChecked();
|
||||
info.drawLevelNameOnBottom = m_levelNameOnBottomCB->isChecked();
|
||||
|
||||
info.tick1MarkId = m_tick1IdCombo->currentData().toInt();
|
||||
info.tick2MarkId = m_tick2IdCombo->currentData().toInt();
|
||||
info.keyMarkId = m_keyIdCombo->currentData().toInt();
|
||||
info.tick1MarkType = (TickMarkType)(m_tick1MarkCombo->currentData().toInt());
|
||||
info.tick2MarkType = (TickMarkType)(m_tick2MarkCombo->currentData().toInt());
|
||||
|
||||
m_currentTmpl->setInfo(info);
|
||||
|
||||
if (m_drawDialogueCB->isChecked() && m_drawDialogueCB->isEnabled())
|
||||
m_currentTmpl->setNoteColumn(m_noteColumns.value(
|
||||
m_dialogueColCombo->currentData().toInt(), nullptr));
|
||||
else
|
||||
m_currentTmpl->setNoteColumn(nullptr);
|
||||
|
||||
if (!m_logoImgRB->isChecked()) return;
|
||||
|
||||
// prepare logo image
|
||||
|
@ -2364,6 +2742,15 @@ void ExportXsheetPdfPopup::onNext() {
|
|||
updatePreview();
|
||||
}
|
||||
|
||||
void ExportXsheetPdfPopup::onTickIdComboActivated() {
|
||||
QComboBox* combo = qobject_cast<QComboBox*>(sender());
|
||||
if (combo == m_tick1IdCombo)
|
||||
m_tick1MarkCombo->setEnabled(m_tick1IdCombo->currentData().toInt() != -1);
|
||||
else if (combo == m_tick2IdCombo)
|
||||
m_tick2MarkCombo->setEnabled(m_tick2IdCombo->currentData().toInt() != -1);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
OpenPopupCommandHandler<ExportXsheetPdfPopup> openExportXsheetPdfPopup(
|
||||
|
|
|
@ -21,6 +21,7 @@ class QComboBox;
|
|||
class QCheckBox;
|
||||
class TXshLevelColumn;
|
||||
class TXshSoundColumn;
|
||||
class TXshSoundTextColumn;
|
||||
namespace DVGui {
|
||||
class FileField;
|
||||
class ColorField;
|
||||
|
@ -85,6 +86,12 @@ typedef void (*DecoFunc)(QPainter&, QRect, QMap<XSheetPDFDataType, QRect>&,
|
|||
|
||||
enum ExportArea { Area_Actions = 0, Area_Cells };
|
||||
enum ContinuousLineMode { Line_Always = 0, Line_MoreThan3s, Line_None };
|
||||
enum TickMarkType {
|
||||
TickMark_Dot = 0,
|
||||
TickMark_Circle,
|
||||
TickMark_Filled,
|
||||
TickMark_Asterisk
|
||||
};
|
||||
|
||||
struct XSheetPDFFormatInfo {
|
||||
QColor lineColor;
|
||||
|
@ -101,6 +108,11 @@ struct XSheetPDFFormatInfo {
|
|||
bool serialFrameNumber;
|
||||
bool drawLevelNameOnBottom;
|
||||
ContinuousLineMode continuousLineMode;
|
||||
int tick1MarkId;
|
||||
int tick2MarkId;
|
||||
int keyMarkId;
|
||||
TickMarkType tick1MarkType;
|
||||
TickMarkType tick2MarkType;
|
||||
};
|
||||
|
||||
class XSheetPDFTemplate {
|
||||
|
@ -138,6 +150,7 @@ protected:
|
|||
// column and column name (if manually specified)
|
||||
QList<QPair<TXshLevelColumn*, QString>> m_columns;
|
||||
QList<TXshSoundColumn*> m_soundColumns;
|
||||
TXshSoundTextColumn* m_noteColumn;
|
||||
|
||||
int m_duration;
|
||||
bool m_useExtraColumns;
|
||||
|
@ -172,12 +185,15 @@ protected:
|
|||
void addInfo(int w, QString lbl, DecoFunc f = nullptr);
|
||||
|
||||
void drawContinuousLine(QPainter& painter, QRect rect, bool isEmpty);
|
||||
void drawCellNumber(QPainter& painter, QRect rect, TXshCell& cell);
|
||||
void drawCellNumber(QPainter& painter, QRect rect, TXshCell& cell,
|
||||
bool isKey);
|
||||
void drawTickMark(QPainter& painter, QRect rect, TickMarkType type);
|
||||
void drawEndMark(QPainter& painter, QRect upperRect);
|
||||
void drawLevelName(QPainter& painter, QRect rect, QString name,
|
||||
bool isBottom = false);
|
||||
void drawLogo(QPainter& painter);
|
||||
void drawSound(QPainter& painter, int framePage);
|
||||
void drawDialogue(QPainter& painter, int framePage);
|
||||
|
||||
int param(const std::string& id, int defaultValue = 0) {
|
||||
if (!m_params.contains(id)) std::cout << id << std::endl;
|
||||
|
@ -201,6 +217,9 @@ public:
|
|||
void setSoundColumns(const QList<TXshSoundColumn*>& soundColumns) {
|
||||
m_soundColumns = soundColumns;
|
||||
}
|
||||
void setNoteColumn(TXshSoundTextColumn* noteColumn) {
|
||||
m_noteColumn = noteColumn;
|
||||
}
|
||||
void setInfo(const XSheetPDFFormatInfo& info);
|
||||
};
|
||||
|
||||
|
@ -262,11 +281,13 @@ class ExportXsheetPdfPopup final : public DVGui::Dialog {
|
|||
XsheetPdfPreviewArea* m_previewArea;
|
||||
DVGui::FileField* m_pathFld;
|
||||
QLineEdit* m_fileNameFld;
|
||||
QComboBox *m_templateCombo, *m_exportAreaCombo, *m_continuousLineCombo;
|
||||
QComboBox *m_templateCombo, *m_exportAreaCombo, *m_continuousLineCombo,
|
||||
*m_dialogueColCombo;
|
||||
DVGui::ColorField* m_lineColorFld;
|
||||
|
||||
QCheckBox *m_addDateTimeCB, *m_addScenePathCB, *m_drawSoundCB,
|
||||
*m_addSceneNameCB, *m_serialFrameNumberCB, *m_levelNameOnBottomCB;
|
||||
*m_addSceneNameCB, *m_serialFrameNumberCB, *m_levelNameOnBottomCB,
|
||||
*m_drawDialogueCB;
|
||||
|
||||
QFontComboBox *m_templateFontCB, *m_contentsFontCB;
|
||||
QTextEdit* m_memoEdit;
|
||||
|
@ -281,9 +302,13 @@ class ExportXsheetPdfPopup final : public DVGui::Dialog {
|
|||
int m_totalPageCount;
|
||||
QPushButton *m_prev, *m_next;
|
||||
|
||||
QComboBox *m_tick1IdCombo, *m_tick2IdCombo, *m_keyIdCombo;
|
||||
QComboBox *m_tick1MarkCombo, *m_tick2MarkCombo;
|
||||
|
||||
// column and column name (if manually specified)
|
||||
QList<QPair<TXshLevelColumn*, QString>> m_columns;
|
||||
QList<TXshSoundColumn*> m_soundColumns;
|
||||
QMap<int, TXshSoundTextColumn*> m_noteColumns;
|
||||
int m_duration;
|
||||
|
||||
XSheetPDFTemplate* m_currentTmpl;
|
||||
|
@ -315,6 +340,8 @@ protected slots:
|
|||
void onLogoImgPathChanged();
|
||||
void onPrev();
|
||||
void onNext();
|
||||
|
||||
void onTickIdComboActivated();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -310,6 +310,21 @@ void ExpressionReferenceManager::onSceneSwitched() {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ExpressionReferenceManager::refreshXsheetRefInfo(TXsheet* xsh) {
|
||||
xsh->setObserver(this);
|
||||
m_model->refreshData(xsh);
|
||||
xsh->getExpRefMonitor()->clearAll();
|
||||
for (int i = 0; i < m_model->getStageObjectsChannelCount(); i++) {
|
||||
checkRef(m_model->getStageObjectChannel(i), xsh);
|
||||
}
|
||||
for (int i = 0; i < m_model->getFxsChannelCount(); i++) {
|
||||
checkRef(m_model->getFxChannel(i), xsh);
|
||||
}
|
||||
onXsheetSwitched();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ExpressionReferenceManager::onXsheetSwitched() {
|
||||
TXsheet* xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
|
||||
xsh->setObserver(this);
|
||||
|
@ -772,7 +787,8 @@ void ExpressionReferenceManager::transferReference(
|
|||
|
||||
// 1. create 3 tables for replacing; column indices, parameter pointers, and
|
||||
// expression texts. Note that moving columns in the same xsheet does not need
|
||||
// to replace the parameter pointers since they are swapped along with columns.
|
||||
// to replace the parameter pointers since they are swapped along with
|
||||
// columns.
|
||||
QMap<int, int> colIdReplaceTable;
|
||||
QMap<TDoubleParam*, TDoubleParam*> curveReplaceTable;
|
||||
std::map<std::string, std::string> exprReplaceTable;
|
||||
|
|
|
@ -79,6 +79,7 @@ public:
|
|||
|
||||
bool askIfParamIsIgnoredOnSave(bool saveSubXsheet);
|
||||
|
||||
void refreshXsheetRefInfo(TXsheet* xsh);
|
||||
protected slots:
|
||||
void onSceneSwitched();
|
||||
void onXsheetSwitched();
|
||||
|
|
|
@ -1193,7 +1193,9 @@ QMenu *FileBrowser::getContextMenu(QWidget *parent, int index) {
|
|||
}
|
||||
|
||||
for (i = 0; i < files.size(); i++)
|
||||
if (!TFileType::isViewable(TFileType::getInfo(files[i]))) break;
|
||||
if (!TFileType::isViewable(TFileType::getInfo(files[i])) &&
|
||||
files[i].getType() != "tpl")
|
||||
break;
|
||||
if (i == files.size()) {
|
||||
std::string type = files[0].getType();
|
||||
for (j = 0; j < files.size(); j++)
|
||||
|
|
|
@ -15,6 +15,12 @@
|
|||
#include "convertpopup.h"
|
||||
#include "matchline.h"
|
||||
#include "colormodelbehaviorpopup.h"
|
||||
//#if defined(x64)
|
||||
//#include "penciltestpopup.h" // FrameNumberLineEdit
|
||||
//#else
|
||||
//#include "penciltestpopup_qt.h"
|
||||
//#endif
|
||||
#include "../stopmotion/stopmotioncontroller.h" // FrameNumberLineEdit
|
||||
|
||||
// TnzQt includes
|
||||
#include "toonzqt/gutil.h"
|
||||
|
@ -473,8 +479,9 @@ TFilePath GenericLoadFilePopup::getPath() {
|
|||
// GenericSaveFilePopup implementation
|
||||
//***********************************************************************************
|
||||
|
||||
GenericSaveFilePopup::GenericSaveFilePopup(const QString &title)
|
||||
: FileBrowserPopup(title, Options(FOR_SAVING)) {
|
||||
GenericSaveFilePopup::GenericSaveFilePopup(const QString &title,
|
||||
QWidget *customWidget)
|
||||
: FileBrowserPopup(title, Options(FOR_SAVING), "", customWidget) {
|
||||
connect(m_nameField, SIGNAL(returnPressedNow()), m_okButton,
|
||||
SLOT(animateClick()));
|
||||
}
|
||||
|
@ -707,8 +714,8 @@ LoadLevelPopup::LoadLevelPopup()
|
|||
QPushButton *showSubsequenceButton = createShowButton(this);
|
||||
QLabel *subsequenceLabel = new QLabel(tr("Load Subsequence Level"), this);
|
||||
m_subsequenceFrame = new QFrame(this);
|
||||
m_fromFrame = new DVGui::IntLineEdit(this, 1, 1);
|
||||
m_toFrame = new DVGui::IntLineEdit(this, 1, 1);
|
||||
m_fromFrame = new FrameNumberLineEdit(this, TFrameId(1));
|
||||
m_toFrame = new FrameNumberLineEdit(this, TFrameId(1));
|
||||
|
||||
//----Arrangement in Xsheet
|
||||
m_arrLvlPropWidget = new QWidget(this);
|
||||
|
@ -716,8 +723,8 @@ LoadLevelPopup::LoadLevelPopup()
|
|||
QLabel *arrangementLabel =
|
||||
new QLabel(tr("Level Settings & Arrangement in Scene"), this);
|
||||
m_arrangementFrame = new QFrame(this);
|
||||
m_xFrom = new DVGui::IntLineEdit(this, 1, 1);
|
||||
m_xTo = new DVGui::IntLineEdit(this, 1, 1);
|
||||
m_xFrom = new FrameNumberLineEdit(this, TFrameId(1));
|
||||
m_xTo = new FrameNumberLineEdit(this, TFrameId(1));
|
||||
m_stepCombo = new QComboBox(this);
|
||||
m_incCombo = new QComboBox(this);
|
||||
m_posFrom = new DVGui::IntLineEdit(this, 1, 1);
|
||||
|
@ -968,12 +975,12 @@ void LoadLevelPopup::onNameSetEditted() {
|
|||
} else {
|
||||
m_notExistLabel->show();
|
||||
|
||||
m_fromFrame->setText("1");
|
||||
m_toFrame->setText("1");
|
||||
m_fromFrame->setValue(TFrameId(1));
|
||||
m_toFrame->setValue(TFrameId(1));
|
||||
m_subsequenceFrame->setEnabled(true);
|
||||
|
||||
m_xFrom->setText("1");
|
||||
m_xTo->setText("1");
|
||||
m_xFrom->setValue(TFrameId(1));
|
||||
m_xTo->setValue(TFrameId(1));
|
||||
|
||||
m_levelName->setText(QString::fromStdString(path.getName()));
|
||||
|
||||
|
@ -998,26 +1005,39 @@ void LoadLevelPopup::updatePosTo() {
|
|||
return;
|
||||
}
|
||||
|
||||
int xFrom = m_xFrom->text().toInt();
|
||||
int xTo = m_xTo->text().toInt();
|
||||
TFrameId xFrom = m_xFrom->getValue();
|
||||
TFrameId xTo = m_xTo->getValue();
|
||||
|
||||
int frameLength;
|
||||
|
||||
bool isScene = (QString::fromStdString(fp.getType()) == "tnz");
|
||||
|
||||
if (isScene) { // scene does not consider frame suffixes
|
||||
xFrom = TFrameId(xFrom.getNumber());
|
||||
xTo = TFrameId(xTo.getNumber());
|
||||
}
|
||||
|
||||
auto frameLengthBetweenFIds = [&]() {
|
||||
if (xFrom > xTo) return 0;
|
||||
int ret = xTo.getNumber() - xFrom.getNumber() + 1;
|
||||
if (!xTo.getLetter().isEmpty()) ret++;
|
||||
return ret;
|
||||
};
|
||||
|
||||
//--- if loading the "missing" level
|
||||
if (m_notExistLabel->isVisible()) {
|
||||
int inc = m_incCombo->currentIndex();
|
||||
if (inc == 0) // Inc = Auto
|
||||
{
|
||||
frameLength = (xTo - xFrom + 1) * ((m_stepCombo->currentIndex() == 0)
|
||||
? 1
|
||||
: m_stepCombo->currentIndex());
|
||||
frameLength =
|
||||
frameLengthBetweenFIds() * ((m_stepCombo->currentIndex() == 0)
|
||||
? 1
|
||||
: m_stepCombo->currentIndex());
|
||||
|
||||
} else // Inc =! Auto
|
||||
{
|
||||
int loopAmount;
|
||||
loopAmount = tceil((double)(xTo - xFrom + 1) / (double)inc);
|
||||
loopAmount = tceil((double)(frameLengthBetweenFIds()) / (double)inc);
|
||||
frameLength = loopAmount * ((m_stepCombo->currentIndex() == 0)
|
||||
? inc
|
||||
: m_stepCombo->currentIndex());
|
||||
|
@ -1028,7 +1048,7 @@ void LoadLevelPopup::updatePosTo() {
|
|||
else if (m_incCombo->currentIndex() == 0) // Inc = Auto
|
||||
{
|
||||
if (isScene) {
|
||||
frameLength = xTo - xFrom + 1;
|
||||
frameLength = frameLengthBetweenFIds();
|
||||
} else {
|
||||
std::vector<TFrameId> fIds = getCurrentFIds();
|
||||
//--- If loading the level with sequential files, reuse the list of
|
||||
|
@ -1036,32 +1056,23 @@ void LoadLevelPopup::updatePosTo() {
|
|||
if (fIds.size() != 0) {
|
||||
if (m_stepCombo->currentIndex() == 0) // Step = Auto
|
||||
{
|
||||
frameLength = 0;
|
||||
std::vector<TFrameId>::iterator it;
|
||||
int firstFrame = 0;
|
||||
int lastFrame = 0;
|
||||
for (it = fIds.begin(); it != fIds.end(); it++) {
|
||||
if (xFrom <= it->getNumber()) {
|
||||
firstFrame = it->getNumber();
|
||||
if (xFrom <= *it && *it <= xTo)
|
||||
frameLength++;
|
||||
else if (xTo < *it)
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (it = fIds.begin(); it != fIds.end(); it++) {
|
||||
if (it->getNumber() <= xTo) {
|
||||
lastFrame = it->getNumber();
|
||||
}
|
||||
}
|
||||
frameLength = lastFrame - firstFrame + 1;
|
||||
} else // Step != Auto
|
||||
{
|
||||
std::vector<TFrameId>::iterator it;
|
||||
int loopAmount = 0;
|
||||
for (it = fIds.begin(); it != fIds.end(); it++) {
|
||||
if (xFrom <= it->getNumber() && it->getNumber() <= xTo)
|
||||
loopAmount++;
|
||||
if (xFrom <= *it && *it <= xTo) loopAmount++;
|
||||
}
|
||||
frameLength = loopAmount * m_stepCombo->currentIndex();
|
||||
}
|
||||
|
||||
}
|
||||
// loading another type of level such as tlv
|
||||
else {
|
||||
|
@ -1074,29 +1085,20 @@ void LoadLevelPopup::updatePosTo() {
|
|||
|
||||
if (m_stepCombo->currentIndex() == 0) // Step = Auto
|
||||
{
|
||||
frameLength = 0;
|
||||
TLevel::Iterator it;
|
||||
int firstFrame = 0;
|
||||
int lastFrame = 0;
|
||||
for (it = level->begin(); it != level->end(); it++) {
|
||||
if (xFrom <= it->first.getNumber()) {
|
||||
firstFrame = it->first.getNumber();
|
||||
if (xFrom <= it->first && it->first <= xTo)
|
||||
frameLength++;
|
||||
else if (xTo < it->first)
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (it = level->begin(); it != level->end(); it++) {
|
||||
if (it->first.getNumber() <= xTo) {
|
||||
lastFrame = it->first.getNumber();
|
||||
}
|
||||
}
|
||||
frameLength = lastFrame - firstFrame + 1;
|
||||
} else // Step != Auto
|
||||
{
|
||||
TLevel::Iterator it;
|
||||
int loopAmount = 0;
|
||||
for (it = level->begin(); it != level->end(); it++) {
|
||||
if (xFrom <= it->first.getNumber() &&
|
||||
it->first.getNumber() <= xTo)
|
||||
loopAmount++;
|
||||
if (xFrom <= it->first && it->first <= xTo) loopAmount++;
|
||||
}
|
||||
frameLength = loopAmount * m_stepCombo->currentIndex();
|
||||
}
|
||||
|
@ -1110,7 +1112,7 @@ void LoadLevelPopup::updatePosTo() {
|
|||
else {
|
||||
int inc = m_incCombo->currentIndex();
|
||||
int loopAmount;
|
||||
loopAmount = tceil((double)(xTo - xFrom + 1) / (double)inc);
|
||||
loopAmount = tceil((double)(frameLengthBetweenFIds()) / (double)inc);
|
||||
frameLength = loopAmount * ((m_stepCombo->currentIndex() == 0)
|
||||
? inc
|
||||
: m_stepCombo->currentIndex());
|
||||
|
@ -1123,8 +1125,8 @@ void LoadLevelPopup::updatePosTo() {
|
|||
/*! if the from / to values in the subsequent box, update m_xFrom and m_xTo
|
||||
*/
|
||||
void LoadLevelPopup::onSubsequentFrameChanged() {
|
||||
m_xFrom->setText(m_fromFrame->text());
|
||||
m_xTo->setText(m_toFrame->text());
|
||||
m_xFrom->setValue(m_fromFrame->getValue());
|
||||
m_xTo->setValue(m_toFrame->getValue());
|
||||
updatePosTo();
|
||||
}
|
||||
|
||||
|
@ -1192,9 +1194,9 @@ bool LoadLevelPopup::execute() {
|
|||
//---- SubSequent load
|
||||
// if loading the "missing" level
|
||||
if (m_notExistLabel->isVisible()) {
|
||||
int firstFrameNumber = m_fromFrame->text().toInt();
|
||||
int lastFrameNumber = m_toFrame->text().toInt();
|
||||
setLoadingLevelRange(firstFrameNumber, lastFrameNumber);
|
||||
TFrameId firstLoadingFId = m_fromFrame->getValue();
|
||||
TFrameId lastLoadingFId = m_toFrame->getValue();
|
||||
setLoadingLevelRange(firstLoadingFId, lastLoadingFId);
|
||||
} else if (m_subsequenceFrame->isEnabled() &&
|
||||
m_subsequenceFrame->isVisible()) {
|
||||
std::vector<TFrameId> fIds = getCurrentFIds();
|
||||
|
@ -1220,11 +1222,10 @@ bool LoadLevelPopup::execute() {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
int firstFrameNumber = m_fromFrame->text().toInt();
|
||||
int lastFrameNumber = m_toFrame->text().toInt();
|
||||
if (firstFrame.getNumber() != firstFrameNumber ||
|
||||
lastFrame.getNumber() != lastFrameNumber)
|
||||
setLoadingLevelRange(firstFrameNumber, lastFrameNumber);
|
||||
TFrameId firstLoadingFId = m_fromFrame->getValue();
|
||||
TFrameId lastLoadingFId = m_toFrame->getValue();
|
||||
if (firstFrame != firstLoadingFId || lastFrame != lastLoadingFId)
|
||||
setLoadingLevelRange(firstLoadingFId, lastLoadingFId);
|
||||
}
|
||||
|
||||
IoCmd::LoadResourceArguments args(fp);
|
||||
|
@ -1237,20 +1238,27 @@ bool LoadLevelPopup::execute() {
|
|||
args.frameIdsSet.push_back(*getCurrentFIdsSet().begin());
|
||||
|
||||
else if (m_notExistLabel->isVisible()) {
|
||||
int firstFrameNumber = m_fromFrame->text().toInt();
|
||||
int lastFrameNumber = m_toFrame->text().toInt();
|
||||
TFrameId firstLoadingFId = m_fromFrame->getValue();
|
||||
TFrameId lastLoadingFId = m_toFrame->getValue();
|
||||
// putting the Fids in order to avoid LoadInfo later
|
||||
std::vector<TFrameId> tmp_fids;
|
||||
for (int i = firstFrameNumber; i <= lastFrameNumber; i++) {
|
||||
int i = firstLoadingFId.getNumber();
|
||||
if (!firstLoadingFId.getLetter().isEmpty()) {
|
||||
tmp_fids.push_back(firstLoadingFId);
|
||||
i++;
|
||||
}
|
||||
for (; i <= lastLoadingFId.getNumber(); i++) {
|
||||
tmp_fids.push_back(TFrameId(i));
|
||||
}
|
||||
if (!lastLoadingFId.getLetter().isEmpty())
|
||||
tmp_fids.push_back(lastLoadingFId);
|
||||
args.frameIdsSet.push_back(tmp_fids);
|
||||
}
|
||||
|
||||
int xFrom = m_xFrom->text().toInt();
|
||||
if (xFrom) args.xFrom = xFrom;
|
||||
int xTo = m_xTo->text().toInt();
|
||||
if (xTo) args.xTo = xTo;
|
||||
TFrameId xFrom = m_xFrom->getValue();
|
||||
if (!xFrom.isEmptyFrame()) args.xFrom = xFrom;
|
||||
TFrameId xTo = m_xTo->getValue();
|
||||
if (!xTo.isEmptyFrame()) args.xTo = xTo;
|
||||
|
||||
args.levelName = m_levelName->text().toStdWString();
|
||||
args.step = m_stepCombo->currentIndex();
|
||||
|
@ -1372,9 +1380,8 @@ void LoadLevelPopup::updateBottomGUI() {
|
|||
disableAll();
|
||||
return;
|
||||
} else if (ext == "tpl") {
|
||||
QString str;
|
||||
m_fromFrame->setText(str.number(1));
|
||||
m_toFrame->setText(str.number(1));
|
||||
m_fromFrame->setText("1");
|
||||
m_toFrame->setText("1");
|
||||
m_subsequenceFrame->setEnabled(false);
|
||||
|
||||
m_xFrom->setText("1");
|
||||
|
@ -1420,13 +1427,12 @@ void LoadLevelPopup::updateBottomGUI() {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_fromFrame->setText(QString().number(firstFrame.getNumber()));
|
||||
m_toFrame->setText(QString().number(lastFrame.getNumber()));
|
||||
m_fromFrame->setValue(firstFrame);
|
||||
m_toFrame->setValue(lastFrame);
|
||||
m_subsequenceFrame->setEnabled(true);
|
||||
|
||||
m_xFrom->setText(m_fromFrame->text());
|
||||
m_xTo->setText(m_toFrame->text());
|
||||
m_xFrom->setValue(firstFrame);
|
||||
m_xTo->setValue(lastFrame);
|
||||
|
||||
// if some option in the preferences is selected, load the level with
|
||||
// removing
|
||||
|
|
|
@ -32,6 +32,7 @@ class QPushButton;
|
|||
class QComboBox;
|
||||
class QGroupBox;
|
||||
class QCheckBox;
|
||||
class FrameNumberLineEdit;
|
||||
|
||||
namespace DVGui {
|
||||
class ColorField;
|
||||
|
@ -184,7 +185,7 @@ protected:
|
|||
//! asks the user for a \a single file path to save something to.
|
||||
class GenericSaveFilePopup : public FileBrowserPopup {
|
||||
public:
|
||||
GenericSaveFilePopup(const QString &title);
|
||||
GenericSaveFilePopup(const QString &title, QWidget *customWidget = nullptr);
|
||||
|
||||
/*!
|
||||
This function shows the popup and blocks until a suitable
|
||||
|
@ -266,11 +267,11 @@ class LoadLevelPopup final : public FileBrowserPopup {
|
|||
Q_OBJECT
|
||||
|
||||
QFrame *m_subsequenceFrame;
|
||||
DVGui::IntLineEdit *m_fromFrame, *m_toFrame;
|
||||
FrameNumberLineEdit *m_fromFrame, *m_toFrame;
|
||||
|
||||
QWidget *m_arrLvlPropWidget;
|
||||
QFrame *m_arrangementFrame;
|
||||
DVGui::IntLineEdit *m_xFrom, *m_xTo;
|
||||
FrameNumberLineEdit *m_xFrom, *m_xTo;
|
||||
QComboBox *m_stepCombo, *m_incCombo;
|
||||
DVGui::IntLineEdit *m_posFrom, *m_posTo;
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "toonzqt/icongenerator.h"
|
||||
#include "toonzqt/gutil.h"
|
||||
#include "historytypes.h"
|
||||
#include "toonzqt/menubarcommand.h"
|
||||
|
||||
// TnzLib includes
|
||||
#include "toonz/tproject.h"
|
||||
|
@ -30,6 +31,9 @@
|
|||
#include "toonz/sceneresources.h"
|
||||
#include "toonz/preferences.h"
|
||||
#include "toonz/tscenehandle.h"
|
||||
#include "toonz/studiopalette.h"
|
||||
#include "toonz/palettecontroller.h"
|
||||
#include "toonz/tpalettehandle.h"
|
||||
|
||||
// TnzCore includes
|
||||
#include "tfiletype.h"
|
||||
|
@ -185,6 +189,8 @@ public:
|
|||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
TPaletteP viewedPalette;
|
||||
//-----------------------------------------------------------------------------
|
||||
} // namespace
|
||||
|
||||
|
@ -372,12 +378,21 @@ void FileSelection::viewFile() {
|
|||
getSelectedFiles(files);
|
||||
int i = 0;
|
||||
for (i = 0; i < files.size(); i++) {
|
||||
if (!TFileType::isViewable(TFileType::getInfo(files[0]))) continue;
|
||||
if (!TFileType::isViewable(TFileType::getInfo(files[i])) &&
|
||||
files[i].getType() != "tpl")
|
||||
continue;
|
||||
|
||||
if (Preferences::instance()->isDefaultViewerEnabled() &&
|
||||
(files[i].getType() == "avi"))
|
||||
QDesktopServices::openUrl(QUrl("file:///" + toQString(files[i])));
|
||||
else {
|
||||
else if (files[i].getType() == "tpl") {
|
||||
viewedPalette = StudioPalette::instance()->getPalette(files[i], false);
|
||||
TApp::instance()
|
||||
->getPaletteController()
|
||||
->getCurrentLevelPalette()
|
||||
->setPalette(viewedPalette.getPointer());
|
||||
CommandManager::instance()->execute("MI_OpenPalette");
|
||||
} else {
|
||||
FlipBook *fb = ::viewFile(files[i]);
|
||||
if (fb) {
|
||||
FileBrowserPopup::setModalBrowserToParent(fb->parentWidget());
|
||||
|
|
|
@ -711,9 +711,9 @@ void FilmstripFrames::paintEvent(QPaintEvent *evt) {
|
|||
}
|
||||
// for sequential frame
|
||||
else {
|
||||
char letter = fid.getLetter();
|
||||
text = QString::number(fid.getNumber()).rightJustified(4, '0') +
|
||||
(letter != '\0' ? QString(letter) : "");
|
||||
QString letter = fid.getLetter();
|
||||
text = QString::number(fid.getNumber()).rightJustified(4, '0') +
|
||||
(!letter.isEmpty() ? letter : "");
|
||||
}
|
||||
p.drawText(tmp_frameRect.adjusted(0, 0, -3, 2), text,
|
||||
QTextOption(Qt::AlignRight | Qt::AlignBottom));
|
||||
|
|
|
@ -51,7 +51,8 @@
|
|||
//=============================================================================
|
||||
|
||||
TFrameId operator+(const TFrameId &fid, int d) {
|
||||
return TFrameId(fid.getNumber() + d, fid.getLetter());
|
||||
return TFrameId(fid.getNumber() + d, fid.getLetter(), fid.getZeroPadding(),
|
||||
fid.getStartSeqInd());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1341,6 +1342,17 @@ public:
|
|||
int getHistoryType() override { return HistoryType::FilmStrip; }
|
||||
};
|
||||
|
||||
QString getNextLetter(const QString &letter) {
|
||||
// 空なら a を返す
|
||||
if (letter.isEmpty()) return QString('a');
|
||||
// 1文字かつ z または Z ならEmptyを返す
|
||||
if (letter == 'z' || letter == 'Z') return QString();
|
||||
QByteArray byteArray = letter.toUtf8();
|
||||
// それ以外の場合、最後の文字をとにかく1進めて返す
|
||||
byteArray.data()[byteArray.size() - 1]++;
|
||||
return QString::fromUtf8(byteArray);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
//=============================================================================
|
||||
|
@ -1356,10 +1368,14 @@ void FilmstripCmd::addFrames(TXshSimpleLevel *sl, int start, int end,
|
|||
std::vector<TFrameId> oldFids;
|
||||
sl->getFids(oldFids);
|
||||
|
||||
TFrameId tmplFid;
|
||||
if (!oldFids.empty()) tmplFid = oldFids.front();
|
||||
|
||||
std::set<TFrameId> fidsToInsert;
|
||||
int frame = 0;
|
||||
for (frame = start; frame <= end; frame += step)
|
||||
fidsToInsert.insert(TFrameId(frame));
|
||||
fidsToInsert.insert(TFrameId(frame, "", tmplFid.getZeroPadding(),
|
||||
tmplFid.getStartSeqInd()));
|
||||
|
||||
makeSpaceForFids(sl, fidsToInsert);
|
||||
|
||||
|
@ -1487,10 +1503,11 @@ void FilmstripCmd::renumber(
|
|||
// make sure that srcFid has not been used. add a letter if this is needed
|
||||
if (tmp.count(tarFid) > 0) {
|
||||
do {
|
||||
char letter = tarFid.getLetter();
|
||||
tarFid = TFrameId(tarFid.getNumber(), letter == 0 ? 'a' : letter + 1);
|
||||
} while (tarFid.getLetter() <= 'z' && tmp.count(tarFid) > 0);
|
||||
if (tarFid.getLetter() > 'z') {
|
||||
tarFid =
|
||||
TFrameId(tarFid.getNumber(), getNextLetter(tarFid.getLetter()),
|
||||
tarFid.getZeroPadding(), tarFid.getStartSeqInd());
|
||||
} while (!tarFid.getLetter().isEmpty() && tmp.count(tarFid) > 0);
|
||||
if (tarFid.getLetter().isEmpty()) {
|
||||
// todo: error message
|
||||
return;
|
||||
}
|
||||
|
@ -1546,7 +1563,8 @@ void FilmstripCmd::renumber(TXshSimpleLevel *sl, std::set<TFrameId> &frames,
|
|||
std::vector<TFrameId>::iterator j = fids.begin();
|
||||
for (it = frames.begin(); it != frames.end(); ++it) {
|
||||
TFrameId srcFid(*it);
|
||||
TFrameId dstFid(frame);
|
||||
TFrameId dstFid(frame, "", srcFid.getZeroPadding(),
|
||||
srcFid.getStartSeqInd());
|
||||
frame += stepFrame;
|
||||
// faccio il controllo su tmp e non su fids. considera:
|
||||
// fids = [1,2,3,4], renumber = [2->3,3->5]
|
||||
|
@ -1579,7 +1597,8 @@ void FilmstripCmd::renumber(TXshSimpleLevel *sl, std::set<TFrameId> &frames,
|
|||
it2 = frames.begin();
|
||||
std::set<TFrameId> newFrames;
|
||||
for (i = 0; i < frames.size(); i++, it2++)
|
||||
newFrames.insert(TFrameId(startFrame + (i * stepFrame), it2->getLetter()));
|
||||
newFrames.insert(TFrameId(startFrame + (i * stepFrame), it2->getLetter(),
|
||||
it2->getZeroPadding(), it2->getStartSeqInd()));
|
||||
assert(frames.size() == newFrames.size());
|
||||
frames.swap(newFrames);
|
||||
|
||||
|
@ -2763,13 +2782,9 @@ void FilmstripCmd::renumberDrawing(TXshSimpleLevel *sl, const TFrameId &oldFid,
|
|||
if (it == fids.end()) return;
|
||||
TFrameId newFid = desiredNewFid;
|
||||
while (std::find(fids.begin(), fids.end(), newFid) != fids.end()) {
|
||||
char letter = newFid.getLetter();
|
||||
if (letter == 'z') return;
|
||||
if (letter == 0)
|
||||
letter = 'a';
|
||||
else
|
||||
letter++;
|
||||
newFid = TFrameId(newFid.getNumber(), letter);
|
||||
QString nextLetter = getNextLetter(newFid.getLetter());
|
||||
if (nextLetter.isEmpty()) return;
|
||||
newFid = TFrameId(newFid.getNumber(), nextLetter);
|
||||
}
|
||||
*it = newFid;
|
||||
if (Preferences::instance()->isSyncLevelRenumberWithXsheetEnabled()) {
|
||||
|
|
|
@ -88,52 +88,51 @@ TFx *createPresetFxByName(TFilePath path) {
|
|||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// same as createMacroFxByPath() in addfxcontextmenu.cpp
|
||||
|
||||
TFx *createMacroFxByPath(TFilePath path) {
|
||||
TIStream is(path);
|
||||
TPersist *p = 0;
|
||||
is >> p;
|
||||
TMacroFx *fx = dynamic_cast<TMacroFx *>(p);
|
||||
if (!fx) return 0;
|
||||
fx->setName(path.getWideName());
|
||||
// Assign a unic ID to each fx in the macro!
|
||||
TApp *app = TApp::instance();
|
||||
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
|
||||
if (!xsh) return fx;
|
||||
FxDag *fxDag = xsh->getFxDag();
|
||||
if (!fxDag) return fx;
|
||||
std::vector<TFxP> fxs;
|
||||
fxs = fx->getFxs();
|
||||
QMap<std::wstring, std::wstring> oldNewId;
|
||||
int i;
|
||||
for (i = 0; i < fxs.size(); i++) {
|
||||
std::wstring oldId = fxs[i]->getFxId();
|
||||
fxDag->assignUniqueId(fxs[i].getPointer());
|
||||
oldNewId[oldId] = fxs[i]->getFxId();
|
||||
}
|
||||
try {
|
||||
TIStream is(path);
|
||||
TPersist *p = 0;
|
||||
is >> p;
|
||||
TMacroFx *fx = dynamic_cast<TMacroFx *>(p);
|
||||
if (!fx) return 0;
|
||||
fx->setName(path.getWideName());
|
||||
// Assign a unic ID to each fx in the macro!
|
||||
TApp *app = TApp::instance();
|
||||
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
|
||||
if (!xsh) return fx;
|
||||
FxDag *fxDag = xsh->getFxDag();
|
||||
if (!fxDag) return fx;
|
||||
std::vector<TFxP> fxs;
|
||||
fxs = fx->getFxs();
|
||||
QMap<std::wstring, std::wstring> oldNewId;
|
||||
int i;
|
||||
for (i = 0; i < fxs.size(); i++) {
|
||||
std::wstring oldId = fxs[i]->getFxId();
|
||||
fxDag->assignUniqueId(fxs[i].getPointer());
|
||||
std::wstring newId = fxs[i]->getFxId();
|
||||
oldNewId[oldId] = newId;
|
||||
|
||||
QStack<QPair<std::string, TFxPort *>> newPortNames;
|
||||
// changing the id of the internal effects of a macro breaks the links
|
||||
// between the name of the port and the port to which it is linked :
|
||||
// I have to change the names of the ports and remap them within the macro
|
||||
int j;
|
||||
for (j = 0; j < fx->getInputPortCount(); j++) {
|
||||
QString inputName = QString::fromStdString(fx->getInputPortName(j));
|
||||
if (inputName.endsWith(QString::fromStdWString(oldId))) {
|
||||
QString newInputName = inputName;
|
||||
newInputName.replace(QString::fromStdWString(oldId),
|
||||
QString::fromStdWString(newId));
|
||||
fx->renamePort(inputName.toStdString(), newInputName.toStdString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Devo cambiare il nome alle porte: contengono l'id dei vecchi effetti
|
||||
for (i = fx->getInputPortCount() - 1; i >= 0; i--) {
|
||||
std::string oldPortName = fx->getInputPortName(i);
|
||||
std::string inFxOldId = oldPortName;
|
||||
inFxOldId.erase(0, inFxOldId.find_last_of("_") + 1);
|
||||
assert(oldNewId.contains(::to_wstring(inFxOldId)));
|
||||
std::string inFxNewId = ::to_string(oldNewId[ ::to_wstring(inFxOldId)]);
|
||||
std::string newPortName = oldPortName;
|
||||
newPortName.erase(newPortName.find_last_of("_") + 1,
|
||||
newPortName.size() - 1);
|
||||
newPortName.append(inFxNewId);
|
||||
TFxPort *fxPort = fx->getInputPort(i);
|
||||
newPortNames.append(QPair<std::string, TFxPort *>(newPortName, fxPort));
|
||||
fx->removeInputPort(oldPortName);
|
||||
return fx;
|
||||
} catch (...) {
|
||||
return 0;
|
||||
}
|
||||
while (!newPortNames.isEmpty()) {
|
||||
QPair<std::string, TFxPort *> newPort = newPortNames.pop();
|
||||
fx->addInputPort(newPort.first, *newPort.second);
|
||||
}
|
||||
return fx;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
|
|
@ -324,7 +324,8 @@ bool beforeCellsInsert(TXsheet *xsh, int row, int &col, int rowCount,
|
|||
|
||||
for (i = 0; i < rowCount && xsh->getCell(row + i, col).isEmpty(); i++) {
|
||||
}
|
||||
int type = column ? column->getColumnType() : newLevelColumnType;
|
||||
int type = (column && !column->isEmpty()) ? column->getColumnType()
|
||||
: newLevelColumnType;
|
||||
// If some used cells in range or column type mismatch must insert a column.
|
||||
if (col < 0 || i < rowCount || newLevelColumnType != type) {
|
||||
col += 1;
|
||||
|
@ -891,9 +892,9 @@ TXshLevel *loadLevel(ToonzScene *scene,
|
|||
const IoCmd::LoadResourceArguments::ResourceData &rd,
|
||||
const TFilePath &castFolder, int row0, int &col0, int row1,
|
||||
int &col1, bool expose, std::vector<TFrameId> &fIds,
|
||||
int xFrom = -1, int xTo = -1, std::wstring levelName = L"",
|
||||
int step = -1, int inc = -1, int frameCount = -1,
|
||||
bool doesFileActuallyExist = true) {
|
||||
TFrameId xFrom = TFrameId(), TFrameId xTo = TFrameId(),
|
||||
std::wstring levelName = L"", int step = -1, int inc = -1,
|
||||
int frameCount = -1, bool doesFileActuallyExist = true) {
|
||||
TFilePath actualPath = scene->decodeFilePath(rd.m_path);
|
||||
|
||||
LoadLevelUndo *undo = 0;
|
||||
|
@ -1022,12 +1023,15 @@ TXshLevel *loadLevel(ToonzScene *scene,
|
|||
// loadResource(scene, path, castFolder, row, col, expose)
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
TXshLevel *loadResource(
|
||||
ToonzScene *scene, const IoCmd::LoadResourceArguments::ResourceData &rd,
|
||||
const TFilePath &castFolder, int row0, int &col0, int row1, int &col1,
|
||||
bool expose, std::vector<TFrameId> fIds = std::vector<TFrameId>(),
|
||||
int xFrom = -1, int xTo = -1, std::wstring levelName = L"", int step = -1,
|
||||
int inc = -1, int frameCount = -1, bool doesFileActuallyExist = true) {
|
||||
TXshLevel *loadResource(ToonzScene *scene,
|
||||
const IoCmd::LoadResourceArguments::ResourceData &rd,
|
||||
const TFilePath &castFolder, int row0, int &col0,
|
||||
int row1, int &col1, bool expose,
|
||||
std::vector<TFrameId> fIds = std::vector<TFrameId>(),
|
||||
TFrameId xFrom = TFrameId(), TFrameId xTo = TFrameId(),
|
||||
std::wstring levelName = L"", int step = -1,
|
||||
int inc = -1, int frameCount = -1,
|
||||
bool doesFileActuallyExist = true) {
|
||||
IoCmd::LoadResourceArguments::ResourceData actualRd(rd);
|
||||
actualRd.m_path = scene->decodeFilePath(rd.m_path);
|
||||
|
||||
|
@ -2253,7 +2257,7 @@ static int loadPSDResource(IoCmd::LoadResourceArguments &args,
|
|||
assert(childLevel);
|
||||
childXsh = childLevel->getXsheet();
|
||||
}
|
||||
int subCol0 = args.col0;
|
||||
int subCol0 = 0;
|
||||
loadedPsdLevelIndex.clear();
|
||||
// for each layer in psd
|
||||
for (int i = 0; i < popup->getPsdLevelCount(); i++) {
|
||||
|
@ -2265,7 +2269,7 @@ static int loadPSDResource(IoCmd::LoadResourceArguments &args,
|
|||
count +=
|
||||
createSubXSheetFromPSDFolder(args, childXsh, subCol0, i, popup);
|
||||
else
|
||||
count += createSubXSheetFromPSDFolder(args, xsh, subCol0, i, popup);
|
||||
count += createSubXSheetFromPSDFolder(args, xsh, col0, i, popup);
|
||||
} else {
|
||||
TFilePath psdpath = popup->getPsdPath(i);
|
||||
TXshLevel *xl = 0;
|
||||
|
@ -2280,14 +2284,14 @@ static int loadPSDResource(IoCmd::LoadResourceArguments &args,
|
|||
// lo importo nell'xsheet
|
||||
if (popup->subxsheet() && childXsh) {
|
||||
childXsh->exposeLevel(0, subCol0, xl);
|
||||
subCol0++;
|
||||
} else {
|
||||
// move the current column to the right
|
||||
col0++;
|
||||
app->getCurrentColumn()->setColumnIndex(col0);
|
||||
}
|
||||
args.loadedLevels.push_back(xl);
|
||||
subCol0++;
|
||||
count++;
|
||||
|
||||
// move the current column to the right
|
||||
col0++;
|
||||
app->getCurrentColumn()->setColumnIndex(col0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ public:
|
|||
std::vector<TXshLevel *> loadedLevels; //!< [\p Out] Levels loaded by
|
||||
//! resource loading procedures.
|
||||
|
||||
int xFrom, xTo;
|
||||
TFrameId xFrom, xTo;
|
||||
std::wstring levelName;
|
||||
int step, inc, frameCount;
|
||||
bool doesFileActuallyExist;
|
||||
|
|
|
@ -512,6 +512,14 @@ void LevelCmd::addMissingLevelsToCast(const QList<TXshColumnP> &columns) {
|
|||
}
|
||||
|
||||
void LevelCmd::addMissingLevelsToCast(std::set<TXshLevel *> &levels) {
|
||||
// remove zerary fx levels which are not registered in the cast
|
||||
for (auto it = levels.begin(); it != levels.end();) {
|
||||
if ((*it)->getZeraryFxLevel())
|
||||
it = levels.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
if (levels.empty()) return;
|
||||
TUndoManager::manager()->beginBlock();
|
||||
TLevelSet *levelSet =
|
||||
|
|
|
@ -3066,6 +3066,16 @@ void MainWindow::defineActions() {
|
|||
"");
|
||||
createStopMotionAction(MI_StopMotionToggleUseLiveViewImages,
|
||||
QT_TR_NOOP("Show original live view images."), "");
|
||||
|
||||
// create cell mark actions
|
||||
for (int markId = 0; markId < 12; markId++) {
|
||||
std::string cmdId = (std::string)MI_SetCellMark + std::to_string(markId);
|
||||
std::string labelStr =
|
||||
QT_TR_NOOP("Set Cell Mark ") + std::to_string(markId);
|
||||
QAction *action =
|
||||
createAction(cmdId.c_str(), labelStr.c_str(), "", "", CellMarkCommandType);
|
||||
action->setData(markId);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -471,6 +471,9 @@
|
|||
#define MI_ExportTvpJson "MI_ExportTvpJson"
|
||||
#define MI_ExportXsheetPDF "MI_ExportXsheetPDF"
|
||||
|
||||
// mark id is added for each actual command (i.g. MI_SetCellMark1)
|
||||
#define MI_SetCellMark "MI_SetCellMark"
|
||||
|
||||
#define MI_ToggleAutoCreate "MI_ToggleAutoCreate"
|
||||
#define MI_ToggleCreationInHoldCells "MI_ToggleCreationInHoldCells"
|
||||
#define MI_ToggleAutoStretch "MI_ToggleAutoStretch"
|
||||
|
|
|
@ -19,10 +19,15 @@
|
|||
#include "toonzqt/checkbox.h"
|
||||
#include "toonzqt/gutil.h"
|
||||
|
||||
// TnzLib
|
||||
#include "toonz/filepathproperties.h"
|
||||
|
||||
// TnzCore includes
|
||||
#include "tsystem.h"
|
||||
#include "tenv.h"
|
||||
#include "tapp.h"
|
||||
#include "tfilepath.h"
|
||||
|
||||
#include "toonz/tscenehandle.h"
|
||||
#include "toonz/toonzscene.h"
|
||||
#include "toonz/preferences.h"
|
||||
|
@ -35,9 +40,19 @@
|
|||
#include <QComboBox>
|
||||
#include <QStandardPaths>
|
||||
#include <QGroupBox>
|
||||
#include <QTabWidget>
|
||||
#include <QStackedWidget>
|
||||
#include <QButtonGroup>
|
||||
#include <QRadioButton>
|
||||
|
||||
using namespace DVGui;
|
||||
|
||||
namespace {
|
||||
|
||||
enum { Rule_Standard = 0, Rule_Custom };
|
||||
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
|
||||
TFilePath getDocumentsPath() {
|
||||
|
@ -85,6 +100,33 @@ ProjectPopup::ProjectPopup(bool isModal)
|
|||
new CheckBox("*Separate assets into scene sub-folders");
|
||||
m_useSubSceneCbs->setMaximumHeight(WidgetHeight);
|
||||
|
||||
m_rulePreferenceBG = new QButtonGroup(this);
|
||||
QRadioButton *standardRB = new QRadioButton(tr("Standard"), this);
|
||||
QRadioButton *customRB =
|
||||
new QRadioButton(QString("[Experimental] ") + tr("Custom"), this);
|
||||
m_acceptNonAlphabetSuffixCB =
|
||||
new CheckBox(tr("Accept Non-alphabet Suffix"), this);
|
||||
m_letterCountCombo = new QComboBox(this);
|
||||
|
||||
//-----
|
||||
|
||||
m_rulePreferenceBG->addButton(standardRB, Rule_Standard);
|
||||
m_rulePreferenceBG->addButton(customRB, Rule_Custom);
|
||||
m_rulePreferenceBG->setExclusive(true);
|
||||
standardRB->setToolTip(tr(
|
||||
"In the standard mode files with the following file name are handled as sequencial images:\n\
|
||||
[LEVEL_NAME][\".\"or\"_\"][FRAME_NUMBER][SUFFIX].[EXTENSION]\n\
|
||||
For [SUFFIX] zero or one occurrences of alphabet (a-z, A-Z) can be used in the standard mode."));
|
||||
customRB->setToolTip(
|
||||
tr("In the custom mode you can customize the file path rules.\n\
|
||||
Note that this mode uses regular expression for file name validation and may slow the operation."));
|
||||
|
||||
m_letterCountCombo->addItem(tr("1"), 1);
|
||||
m_letterCountCombo->addItem(tr("2"), 2);
|
||||
m_letterCountCombo->addItem(tr("3"), 3);
|
||||
m_letterCountCombo->addItem(tr("5"), 5);
|
||||
m_letterCountCombo->addItem(tr("Unlimited"), 0);
|
||||
|
||||
m_settingsLabel = new QLabel(tr("Settings"), this);
|
||||
m_settingsBox = createSettingsBox();
|
||||
|
||||
|
@ -127,7 +169,12 @@ ProjectPopup::ProjectPopup(bool isModal)
|
|||
SLOT(setVisible(bool)));
|
||||
|
||||
pm->addListener(this);
|
||||
|
||||
//---------
|
||||
connect(m_rulePreferenceBG, SIGNAL(buttonClicked(int)), this,
|
||||
SLOT(onRulePreferenceToggled(int)));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
QFrame *ProjectPopup::createSettingsBox() {
|
||||
|
@ -136,49 +183,72 @@ QFrame *ProjectPopup::createSettingsBox() {
|
|||
|
||||
TProjectManager *pm = TProjectManager::instance();
|
||||
|
||||
QGridLayout *lay = new QGridLayout();
|
||||
lay->setMargin(5);
|
||||
lay->setHorizontalSpacing(5);
|
||||
lay->setVerticalSpacing(10);
|
||||
{
|
||||
std::vector<std::string> folderNames;
|
||||
pm->getFolderNames(folderNames);
|
||||
int i;
|
||||
for (i = 0; i < (int)folderNames.size(); i++) {
|
||||
std::string name = folderNames[i];
|
||||
QString qName = QString::fromStdString(name);
|
||||
FileField *ff = new FileField(0, qName);
|
||||
m_folderFlds.append(qMakePair(name, ff));
|
||||
bool assetFolder = false;
|
||||
if (qName == "drawings" || qName == "extras" || qName == "inputs")
|
||||
assetFolder = true;
|
||||
QLabel *label = new QLabel("+" + qName + (assetFolder ? "*" : ""), this);
|
||||
lay->addWidget(label, i + 4, 0, Qt::AlignRight | Qt::AlignVCenter);
|
||||
lay->addWidget(ff, i + 4, 1);
|
||||
}
|
||||
/*
|
||||
std::vector<std::tuple<QString, std::string>> cbs = {
|
||||
std::make_tuple(tr("Append $scenepath to +drawings"),
|
||||
TProject::Drawings),
|
||||
std::make_tuple(tr("Append $scenepath to +inputs"), TProject::Inputs),
|
||||
std::make_tuple(tr("Append $scenepath to +extras"), TProject::Extras) };
|
||||
int currentRow = lay->rowCount();
|
||||
QTabWidget *tabWidget = new QTabWidget(this);
|
||||
|
||||
for (int i = 0; i < cbs.size(); ++i) {
|
||||
auto const &name = std::get<0>(cbs[i]);
|
||||
auto const &folderName = std::get<1>(cbs[i]);
|
||||
CheckBox *cb = new CheckBox(name);
|
||||
cb->setMaximumHeight(WidgetHeight);
|
||||
lay->addWidget(cb, currentRow + i, 1);
|
||||
m_useScenePathCbs.append(qMakePair(folderName, cb));
|
||||
cb->hide();
|
||||
QVBoxLayout *settingsLayout = new QVBoxLayout();
|
||||
settingsLayout->setMargin(5);
|
||||
settingsLayout->setSpacing(10);
|
||||
{
|
||||
settingsLayout->addWidget(tabWidget, 1);
|
||||
|
||||
// project folder settings
|
||||
QWidget *projectFolderPanel = new QWidget(this);
|
||||
QGridLayout *folderLayout = new QGridLayout();
|
||||
folderLayout->setMargin(5);
|
||||
folderLayout->setHorizontalSpacing(5);
|
||||
folderLayout->setVerticalSpacing(10);
|
||||
{
|
||||
std::vector<std::string> folderNames;
|
||||
pm->getFolderNames(folderNames);
|
||||
int i;
|
||||
for (i = 0; i < (int)folderNames.size(); i++) {
|
||||
std::string name = folderNames[i];
|
||||
QString qName = QString::fromStdString(name);
|
||||
FileField *ff = new FileField(0, qName);
|
||||
m_folderFlds.append(qMakePair(name, ff));
|
||||
bool assetFolder = false;
|
||||
if (qName == "drawings" || qName == "extras" || qName == "inputs")
|
||||
assetFolder = true;
|
||||
QLabel *label = new QLabel("+" + qName + (assetFolder ? "*" : ""), this);
|
||||
folderLayout->addWidget(label, i + 4, 0, Qt::AlignRight | Qt::AlignVCenter);
|
||||
folderLayout->addWidget(ff, i + 4, 1);
|
||||
}
|
||||
int currentRow = folderLayout->rowCount();
|
||||
folderLayout->addWidget(m_useSubSceneCbs, currentRow, 1);
|
||||
}
|
||||
*/
|
||||
int currentRow = lay->rowCount();
|
||||
lay->addWidget(m_useSubSceneCbs, currentRow, 1);
|
||||
projectFolderPanel->setLayout(folderLayout);
|
||||
tabWidget->addTab(projectFolderPanel, tr("Project Folder"));
|
||||
|
||||
|
||||
// file path settings
|
||||
QWidget *filePathPanel = new QWidget(this);
|
||||
QVBoxLayout *fpLayout = new QVBoxLayout();
|
||||
fpLayout->setMargin(5);
|
||||
fpLayout->setSpacing(10);
|
||||
{
|
||||
fpLayout->addWidget(m_rulePreferenceBG->buttons()[0], 0); // standardRB
|
||||
fpLayout->addWidget(m_rulePreferenceBG->buttons()[1], 0); // customRB
|
||||
|
||||
// add some indent
|
||||
QGridLayout *customLay = new QGridLayout();
|
||||
customLay->setMargin(10);
|
||||
customLay->setHorizontalSpacing(10);
|
||||
customLay->setVerticalSpacing(10);
|
||||
{
|
||||
customLay->addWidget(m_acceptNonAlphabetSuffixCB, 0, 0, 1, 2);
|
||||
customLay->addWidget(
|
||||
new QLabel(tr("Maximum Letter Count For Suffix"), this), 1, 0);
|
||||
customLay->addWidget(m_letterCountCombo, 1, 1);
|
||||
}
|
||||
customLay->setColumnStretch(2, 1);
|
||||
fpLayout->addLayout(customLay, 0);
|
||||
fpLayout->addStretch(1);
|
||||
}
|
||||
filePathPanel->setLayout(fpLayout);
|
||||
tabWidget->addTab(filePathPanel, tr("File Path Rules"));
|
||||
}
|
||||
|
||||
projectSettingsBox->setLayout(lay);
|
||||
projectSettingsBox->setLayout(settingsLayout);
|
||||
|
||||
return projectSettingsBox;
|
||||
}
|
||||
|
@ -208,6 +278,18 @@ void ProjectPopup::updateFieldsFromProject(TProject *project) {
|
|||
m_useSubSceneCbs->blockSignals(true);
|
||||
m_useSubSceneCbs->setChecked(project->getUseSubScenePath());
|
||||
m_useSubSceneCbs->blockSignals(false);
|
||||
|
||||
// file path
|
||||
FilePathProperties *fpProp = project->getFilePathProperties();
|
||||
bool useStandard = fpProp->useStandard();
|
||||
bool acceptNonAlphabet = fpProp->acceptNonAlphabetSuffix();
|
||||
int letterCount = fpProp->letterCountForSuffix();
|
||||
m_rulePreferenceBG->button((useStandard) ? Rule_Standard : Rule_Custom)
|
||||
->setChecked(true);
|
||||
onRulePreferenceToggled((useStandard) ? Rule_Standard : Rule_Custom);
|
||||
m_acceptNonAlphabetSuffixCB->setChecked(acceptNonAlphabet);
|
||||
m_letterCountCombo->setCurrentIndex(
|
||||
m_letterCountCombo->findData(letterCount));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -229,6 +311,20 @@ void ProjectPopup::updateProjectFromFields(TProject *project) {
|
|||
*/
|
||||
bool useScenePath = m_useSubSceneCbs->isChecked();
|
||||
project->setUseSubScenePath(useScenePath);
|
||||
|
||||
// file path
|
||||
FilePathProperties *fpProp = project->getFilePathProperties();
|
||||
bool useStandard = m_rulePreferenceBG->checkedId() == Rule_Standard;
|
||||
bool acceptNonAlphabet = m_acceptNonAlphabetSuffixCB->isChecked();
|
||||
int letterCount = m_letterCountCombo->currentData().toInt();
|
||||
fpProp->setUseStandard(useStandard);
|
||||
fpProp->setAcceptNonAlphabetSuffix(acceptNonAlphabet);
|
||||
fpProp->setLetterCountForSuffix(letterCount);
|
||||
|
||||
if (TFilePath::setFilePathProperties(useStandard, acceptNonAlphabet,
|
||||
letterCount))
|
||||
DvDirModel::instance()->refreshFolderChild(QModelIndex()); // refresh all
|
||||
|
||||
TProjectManager::instance()->notifyProjectChanged();
|
||||
}
|
||||
|
||||
|
@ -246,6 +342,13 @@ void ProjectPopup::showEvent(QShowEvent *) {
|
|||
updateFieldsFromProject(currentProject.getPointer());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ProjectPopup::onRulePreferenceToggled(int id) {
|
||||
m_acceptNonAlphabetSuffixCB->setEnabled((id == Rule_Custom));
|
||||
m_letterCountCombo->setEnabled((id == Rule_Custom));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
/*! \class ProjectSettingsPopup
|
||||
\brief The ProjectSettingsPopup class provides a dialog to
|
||||
|
@ -269,7 +372,7 @@ ProjectSettingsPopup::ProjectSettingsPopup() : ProjectPopup(false) {
|
|||
int i;
|
||||
for (i = 0; i < m_folderFlds.size(); i++) {
|
||||
FileField *ff = m_folderFlds[i].second;
|
||||
connect(ff, SIGNAL(pathChanged()), this, SLOT(onFolderChanged()));
|
||||
connect(ff, SIGNAL(pathChanged()), this, SLOT(onSomethingChanged()));
|
||||
}
|
||||
/*
|
||||
for (i = 0; i < m_useScenePathCbs.size(); i++) {
|
||||
|
@ -278,8 +381,16 @@ ProjectSettingsPopup::ProjectSettingsPopup() : ProjectPopup(false) {
|
|||
SLOT(onUseSceneChekboxChanged(int)));
|
||||
}
|
||||
*/
|
||||
connect(m_useSubSceneCbs, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(onUseSceneChekboxChanged(int)));
|
||||
|
||||
connect(m_useSubSceneCbs, SIGNAL(stateChanged(int)), this, SLOT(onSomethingChanged()));
|
||||
|
||||
// file path settings
|
||||
connect(m_rulePreferenceBG, SIGNAL(buttonClicked(int)), this,
|
||||
SLOT(onSomethingChanged()));
|
||||
connect(m_acceptNonAlphabetSuffixCB, SIGNAL(clicked(bool)), this,
|
||||
SLOT(onSomethingChanged()));
|
||||
connect(m_letterCountCombo, SIGNAL(activated(int)), this,
|
||||
SLOT(onSomethingChanged()));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -374,21 +485,7 @@ void ProjectSettingsPopup::onProjectChanged() {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ProjectSettingsPopup::onFolderChanged() {
|
||||
TProjectP project = TProjectManager::instance()->getCurrentProject();
|
||||
updateProjectFromFields(project.getPointer());
|
||||
try {
|
||||
project->save();
|
||||
} catch (TSystemException se) {
|
||||
DVGui::warning(QString::fromStdWString(se.getMessage()));
|
||||
return;
|
||||
}
|
||||
DvDirModel::instance()->refreshFolder(project->getProjectFolder());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ProjectSettingsPopup::onUseSceneChekboxChanged(int) {
|
||||
void ProjectSettingsPopup::onSomethingChanged() {
|
||||
TProjectP project = TProjectManager::instance()->getCurrentProject();
|
||||
updateProjectFromFields(project.getPointer());
|
||||
try {
|
||||
|
@ -556,6 +653,12 @@ void ProjectCreatePopup::showEvent(QShowEvent *) {
|
|||
setSizePolicy(sizePolicy);
|
||||
setFixedSize(width(), height());
|
||||
setSizeGripEnabled(false);
|
||||
|
||||
// default file path settings
|
||||
m_rulePreferenceBG->button(Rule_Standard)->setChecked(true);
|
||||
onRulePreferenceToggled(Rule_Standard);
|
||||
m_acceptNonAlphabetSuffixCB->setChecked(false);
|
||||
m_letterCountCombo->setCurrentIndex(m_letterCountCombo->findData(1));
|
||||
}
|
||||
|
||||
void ProjectCreatePopup::setPath(QString path) {
|
||||
|
|
|
@ -16,11 +16,12 @@ namespace DVGui {
|
|||
class FileField;
|
||||
class LineEdit;
|
||||
class CheckBox;
|
||||
}
|
||||
} // namespace DVGui
|
||||
|
||||
class QComboBox;
|
||||
class QGridLayout;
|
||||
class QGroupBox;
|
||||
class QButtonGroup;
|
||||
|
||||
//=============================================================================
|
||||
// ProjectPopup
|
||||
|
@ -46,6 +47,11 @@ protected:
|
|||
QFrame *m_settingsBox;
|
||||
QPushButton *m_showSettingsButton;
|
||||
|
||||
// file path settings
|
||||
QButtonGroup *m_rulePreferenceBG;
|
||||
DVGui::CheckBox *m_acceptNonAlphabetSuffixCB;
|
||||
QComboBox *m_letterCountCombo;
|
||||
|
||||
public:
|
||||
ProjectPopup(bool isModal);
|
||||
// da TProjectManager::Listener
|
||||
|
@ -60,6 +66,9 @@ public:
|
|||
|
||||
protected:
|
||||
void showEvent(QShowEvent *) override;
|
||||
|
||||
protected slots:
|
||||
void onRulePreferenceToggled(int);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
@ -75,8 +84,7 @@ public:
|
|||
ProjectSettingsPopup();
|
||||
|
||||
public slots:
|
||||
void onFolderChanged();
|
||||
void onUseSceneChekboxChanged(int);
|
||||
void onSomethingChanged();
|
||||
void projectChanged();
|
||||
void onProjectChanged() override;
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QPainter>
|
||||
#include <QPushButton>
|
||||
|
||||
using namespace DVGui;
|
||||
|
||||
|
@ -43,6 +44,46 @@ const int labelSize = 110;
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class EditCellMarkUndo final : public TUndo {
|
||||
int m_id;
|
||||
TSceneProperties::CellMark m_markBefore, m_markAfter;
|
||||
|
||||
EditCellMarkUndo(int id) : m_id(id) {
|
||||
m_markBefore = TApp::instance()
|
||||
->getCurrentScene()
|
||||
->getScene()
|
||||
->getProperties()
|
||||
->getCellMark(id);
|
||||
}
|
||||
|
||||
public:
|
||||
EditCellMarkUndo(int id, TPixel32 color) : EditCellMarkUndo(id) {
|
||||
m_markAfter = {m_markBefore.name, color};
|
||||
}
|
||||
EditCellMarkUndo(int id, QString name) : EditCellMarkUndo(id) {
|
||||
m_markAfter = {name, m_markBefore.color};
|
||||
}
|
||||
|
||||
void set(const TSceneProperties::CellMark &mark) const {
|
||||
TApp::instance()
|
||||
->getCurrentScene()
|
||||
->getScene()
|
||||
->getProperties()
|
||||
->setCellMark(mark, m_id);
|
||||
TApp::instance()->getCurrentScene()->notifySceneChanged();
|
||||
}
|
||||
|
||||
void undo() const override { set(m_markBefore); }
|
||||
|
||||
void redo() const override { set(m_markAfter); }
|
||||
|
||||
int getSize() const override { return sizeof *this; }
|
||||
|
||||
QString getHistoryString() override {
|
||||
return QObject::tr("Edit Cell Mark #%1").arg(QString::number(m_id));
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
} // namespace
|
||||
|
@ -77,12 +118,129 @@ QImage::Format_ARGB32);
|
|||
};
|
||||
*/
|
||||
|
||||
//=============================================================================
|
||||
// CellMarksPopup
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CellMarksPopup::CellMarksPopup(QWidget *parent) : QDialog(parent) {
|
||||
setWindowTitle(tr("Cell Marks Settings"));
|
||||
|
||||
QList<TSceneProperties::CellMark> marks = TApp::instance()
|
||||
->getCurrentScene()
|
||||
->getScene()
|
||||
->getProperties()
|
||||
->getCellMarks();
|
||||
|
||||
QGridLayout *layout = new QGridLayout();
|
||||
layout->setMargin(10);
|
||||
layout->setHorizontalSpacing(5);
|
||||
layout->setVerticalSpacing(10);
|
||||
{
|
||||
int id = 0;
|
||||
for (auto mark : marks) {
|
||||
ColorField *colorF = new ColorField(this, false, mark.color, 20);
|
||||
colorF->hideChannelsFields(true);
|
||||
QLineEdit *nameF = new QLineEdit(mark.name, this);
|
||||
m_fields.append({id, colorF, nameF});
|
||||
|
||||
int row = layout->rowCount();
|
||||
|
||||
layout->addWidget(new QLabel(QString("%1:").arg(id), this), row, 0,
|
||||
Qt::AlignRight | Qt::AlignVCenter);
|
||||
|
||||
layout->addWidget(colorF, row, 1);
|
||||
layout->addWidget(nameF, row, 2);
|
||||
|
||||
connect(colorF, SIGNAL(colorChanged(const TPixel32 &, bool)), this,
|
||||
SLOT(onColorChanged(const TPixel32 &, bool)));
|
||||
connect(nameF, SIGNAL(editingFinished()), this, SLOT(onNameChanged()));
|
||||
id++;
|
||||
}
|
||||
}
|
||||
layout->setColumnStretch(2, 1);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void CellMarksPopup::update() {
|
||||
QList<TSceneProperties::CellMark> marks = TApp::instance()
|
||||
->getCurrentScene()
|
||||
->getScene()
|
||||
->getProperties()
|
||||
->getCellMarks();
|
||||
assert(marks.count() == m_fields.count());
|
||||
int id = 0;
|
||||
for (auto mark : marks) {
|
||||
assert(m_fields[id].id == id);
|
||||
m_fields[id].colorField->setColor(mark.color);
|
||||
m_fields[id].nameField->setText(mark.name);
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
void CellMarksPopup::onColorChanged(const TPixel32 &color, bool isDragging) {
|
||||
if (isDragging) return;
|
||||
// obtain id
|
||||
int id = -1;
|
||||
ColorField *colorF = qobject_cast<ColorField *>(sender());
|
||||
for (auto field : m_fields) {
|
||||
if (field.colorField == colorF) {
|
||||
id = field.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (id < 0) return;
|
||||
|
||||
// return if the value is unchanged
|
||||
TPixel32 oldColor = TApp::instance()
|
||||
->getCurrentScene()
|
||||
->getScene()
|
||||
->getProperties()
|
||||
->getCellMark(id)
|
||||
.color;
|
||||
if (color == oldColor) return;
|
||||
|
||||
EditCellMarkUndo *undo = new EditCellMarkUndo(id, color);
|
||||
undo->redo();
|
||||
TUndoManager::manager()->add(undo);
|
||||
}
|
||||
|
||||
void CellMarksPopup::onNameChanged() {
|
||||
// obtain id
|
||||
int id = -1;
|
||||
QLineEdit *nameF = qobject_cast<QLineEdit *>(sender());
|
||||
for (auto field : m_fields) {
|
||||
if (field.nameField == nameF) {
|
||||
id = field.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (id < 0) return;
|
||||
|
||||
// return if the value is unchanged
|
||||
QString oldName = TApp::instance()
|
||||
->getCurrentScene()
|
||||
->getScene()
|
||||
->getProperties()
|
||||
->getCellMark(id)
|
||||
.name;
|
||||
if (nameF->text() == oldName) return;
|
||||
// reject empty string
|
||||
if (nameF->text().isEmpty()) {
|
||||
nameF->setText(oldName);
|
||||
return;
|
||||
}
|
||||
|
||||
EditCellMarkUndo *undo = new EditCellMarkUndo(id, nameF->text());
|
||||
undo->redo();
|
||||
TUndoManager::manager()->add(undo);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// SceneSettingsPopup
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
SceneSettingsPopup::SceneSettingsPopup()
|
||||
: QDialog(TApp::instance()->getMainWindow()) {
|
||||
: QDialog(TApp::instance()->getMainWindow()), m_cellMarksPopup(nullptr) {
|
||||
setWindowTitle(tr("Scene Settings"));
|
||||
setObjectName("SceneSettings");
|
||||
TSceneProperties *sprop = getProperties();
|
||||
|
@ -124,6 +282,9 @@ SceneSettingsPopup::SceneSettingsPopup()
|
|||
m_colorFilterOnRenderCB->setChecked(
|
||||
sprop->isColumnColorFilterOnRenderEnabled());
|
||||
|
||||
QPushButton *editCellMarksButton =
|
||||
new QPushButton(tr("Edit Cell Marks"), this);
|
||||
|
||||
// layout
|
||||
QGridLayout *mainLayout = new QGridLayout();
|
||||
mainLayout->setMargin(10);
|
||||
|
@ -164,6 +325,12 @@ SceneSettingsPopup::SceneSettingsPopup()
|
|||
|
||||
// Use Color Filter and Transparency for Rendering
|
||||
mainLayout->addWidget(m_colorFilterOnRenderCB, 6, 0, 1, 4);
|
||||
|
||||
// cell marks
|
||||
mainLayout->addWidget(new QLabel(tr("Cell Marks:"), this), 7, 0,
|
||||
Qt::AlignRight | Qt::AlignVCenter);
|
||||
mainLayout->addWidget(editCellMarksButton, 7, 1, 1, 4,
|
||||
Qt::AlignLeft | Qt::AlignVCenter);
|
||||
}
|
||||
mainLayout->setColumnStretch(0, 0);
|
||||
mainLayout->setColumnStretch(1, 0);
|
||||
|
@ -201,6 +368,9 @@ SceneSettingsPopup::SceneSettingsPopup()
|
|||
// Use Color Filter and Transparency for Rendering
|
||||
ret = ret && connect(m_colorFilterOnRenderCB, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(onColorFilterOnRenderChanged()));
|
||||
// Cell Marks
|
||||
ret = ret && connect(editCellMarksButton, SIGNAL(clicked()), this,
|
||||
SLOT(onEditCellMarksButtonClicked()));
|
||||
assert(ret);
|
||||
}
|
||||
|
||||
|
@ -254,6 +424,8 @@ void SceneSettingsPopup::update() {
|
|||
m_startFrameFld->setValue(markerOffset + 1);
|
||||
m_colorFilterOnRenderCB->setChecked(
|
||||
sprop->isColumnColorFilterOnRenderEnabled());
|
||||
|
||||
if (m_cellMarksPopup) m_cellMarksPopup->update();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -368,6 +540,14 @@ void SceneSettingsPopup::onColorFilterOnRenderChanged() {
|
|||
TApp::instance()->getCurrentScene()->notifySceneChanged();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SceneSettingsPopup::onEditCellMarksButtonClicked() {
|
||||
if (!m_cellMarksPopup) m_cellMarksPopup = new CellMarksPopup(this);
|
||||
m_cellMarksPopup->show();
|
||||
m_cellMarksPopup->raise();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
OpenPopupCommandHandler<SceneSettingsPopup> openSceneSettingsPopup(
|
||||
|
|
|
@ -13,6 +13,25 @@
|
|||
// forward declaration
|
||||
class TSceneProperties;
|
||||
class QComboBox;
|
||||
class QLineEdit;
|
||||
|
||||
class CellMarksPopup final : public QDialog {
|
||||
Q_OBJECT
|
||||
struct MarkerField {
|
||||
int id;
|
||||
DVGui::ColorField *colorField;
|
||||
QLineEdit *nameField;
|
||||
};
|
||||
|
||||
QList<MarkerField> m_fields;
|
||||
|
||||
public:
|
||||
CellMarksPopup(QWidget *parent);
|
||||
void update();
|
||||
protected slots:
|
||||
void onColorChanged(const TPixel32 &, bool);
|
||||
void onNameChanged();
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// SceneSettingsPopup
|
||||
|
@ -37,6 +56,8 @@ class SceneSettingsPopup final : public QDialog {
|
|||
|
||||
TSceneProperties *getProperties() const;
|
||||
|
||||
CellMarksPopup *m_cellMarksPopup;
|
||||
|
||||
public:
|
||||
SceneSettingsPopup();
|
||||
void configureNotify();
|
||||
|
@ -61,6 +82,8 @@ public slots:
|
|||
void setBgColor(const TPixel32 &value, bool isDragging);
|
||||
|
||||
void onColorFilterOnRenderChanged();
|
||||
|
||||
void onEditCellMarksButtonClicked();
|
||||
};
|
||||
|
||||
#endif // SCENESETTINGSPOPUP_H
|
||||
|
|
|
@ -223,6 +223,8 @@ ShortcutTree::ShortcutTree(QWidget *parent) : QTreeWidget(parent) {
|
|||
addFolder(tr("Help"), MenuHelpCommandType, menuCommandFolder);
|
||||
|
||||
addFolder(tr("Right-click Menu Commands"), RightClickMenuCommandType);
|
||||
QTreeWidgetItem *rcmSubFolder = m_folders.back();
|
||||
addFolder(tr("Cell Mark"), CellMarkCommandType, rcmSubFolder);
|
||||
|
||||
addFolder(tr("Tools"), ToolCommandType);
|
||||
addFolder(tr("Tool Modifiers"), ToolModifierCommandType);
|
||||
|
@ -470,7 +472,7 @@ ShortcutPopup::ShortcutPopup()
|
|||
connect(searchEdit, SIGNAL(textChanged(const QString &)), this,
|
||||
SLOT(onSearchTextChanged(const QString &)));
|
||||
connect(m_presetChoiceCB, SIGNAL(currentIndexChanged(int)),
|
||||
SLOT(onPresetChanged(int)));
|
||||
SLOT(onPresetChanged()));
|
||||
connect(m_exportButton, SIGNAL(clicked()), SLOT(onExportButton()));
|
||||
connect(m_deletePresetButton, SIGNAL(clicked()), SLOT(onDeletePreset()));
|
||||
connect(m_savePresetButton, SIGNAL(clicked()), SLOT(onSavePreset()));
|
||||
|
@ -495,8 +497,8 @@ void ShortcutPopup::onSearchTextChanged(const QString &text) {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ShortcutPopup::onPresetChanged(int index) {
|
||||
if (m_presetChoiceCB->currentText() == "Load from file...") {
|
||||
void ShortcutPopup::onPresetChanged() {
|
||||
if (m_presetChoiceCB->currentData().toString() == QString("LoadFromFile")) {
|
||||
importPreset();
|
||||
}
|
||||
}
|
||||
|
@ -607,7 +609,10 @@ void ShortcutPopup::onExportButton(TFilePath fp) {
|
|||
if (fp == TFilePath()) return;
|
||||
}
|
||||
showDialog(tr("Saving Shortcuts"));
|
||||
QString shortcutString = "[shortcuts]\n";
|
||||
|
||||
QSettings preset(toQString(fp), QSettings::IniFormat);
|
||||
preset.beginGroup("shortcuts");
|
||||
|
||||
for (int commandType = UndefinedCommandType; commandType <= MenuCommandType;
|
||||
commandType++) {
|
||||
std::vector<QAction *> actions;
|
||||
|
@ -618,24 +623,22 @@ void ShortcutPopup::onExportButton(TFilePath fp) {
|
|||
std::string shortcut =
|
||||
CommandManager::instance()->getShortcutFromAction(action);
|
||||
if (shortcut != "") {
|
||||
shortcutString = shortcutString + QString::fromStdString(id) + "=" +
|
||||
QString::fromStdString(shortcut) + "\n";
|
||||
preset.setValue(QString::fromStdString(id),
|
||||
QString::fromStdString(shortcut));
|
||||
}
|
||||
}
|
||||
}
|
||||
QFile file(fp.getQString());
|
||||
file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
QTextStream out(&file);
|
||||
out << shortcutString;
|
||||
file.close();
|
||||
|
||||
preset.endGroup();
|
||||
|
||||
m_dialog->hide();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ShortcutPopup::onDeletePreset() {
|
||||
// change this to 4 once RETAS shortcuts are updated
|
||||
if (m_presetChoiceCB->currentIndex() <= 3) {
|
||||
// change this to 5 once RETAS shortcuts are updated
|
||||
if (m_presetChoiceCB->currentIndex() <= 4) {
|
||||
DVGui::MsgBox(DVGui::CRITICAL, tr("Included presets cannot be deleted."));
|
||||
return;
|
||||
}
|
||||
|
@ -649,7 +652,7 @@ void ShortcutPopup::onDeletePreset() {
|
|||
}
|
||||
TFilePath presetDir =
|
||||
ToonzFolder::getMyModuleDir() + TFilePath("shortcutpresets");
|
||||
QString presetName = m_presetChoiceCB->currentText();
|
||||
QString presetName = m_presetChoiceCB->currentData().toString();
|
||||
if (TSystem::doesExistFileOrLevel(presetDir +
|
||||
TFilePath(presetName + ".ini"))) {
|
||||
TSystem::deleteFile(presetDir + TFilePath(presetName + ".ini"));
|
||||
|
@ -693,48 +696,26 @@ void ShortcutPopup::importPreset() {
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ShortcutPopup::onLoadPreset() {
|
||||
QString preset = m_presetChoiceCB->currentText();
|
||||
TFilePath presetDir =
|
||||
ToonzFolder::getMyModuleDir() + TFilePath("shortcutpresets");
|
||||
TFilePath defaultPresetDir =
|
||||
ToonzFolder::getProfileFolder() + TFilePath("layouts/shortcuts");
|
||||
if (preset == "") return;
|
||||
if (preset == "Load from file...") {
|
||||
QString preset = m_presetChoiceCB->currentData().toString();
|
||||
TFilePath presetDir;
|
||||
if (m_presetChoiceCB->currentIndex() <= 4)
|
||||
presetDir =
|
||||
ToonzFolder::getProfileFolder() + TFilePath("layouts/shortcuts");
|
||||
else
|
||||
presetDir = ToonzFolder::getMyModuleDir() + TFilePath("shortcutpresets");
|
||||
|
||||
if (preset.isEmpty()) return;
|
||||
if (preset == QString("LoadFromFile")) {
|
||||
importPreset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!showConfirmDialog()) return;
|
||||
showDialog(tr("Setting Shortcuts"));
|
||||
if (preset == "Tahoma2D") {
|
||||
TFilePath presetFilePath(preset + ".ini");
|
||||
if (TSystem::doesExistFileOrLevel(presetDir + presetFilePath)) {
|
||||
clearAllShortcuts(false);
|
||||
TFilePath fp = defaultPresetDir + TFilePath("deftahoma2d.ini");
|
||||
setPresetShortcuts(fp);
|
||||
return;
|
||||
} else if (preset == "Toon Boom Harmony") {
|
||||
clearAllShortcuts(false);
|
||||
TFilePath fp = defaultPresetDir + TFilePath("otharmony.ini");
|
||||
setPresetShortcuts(fp);
|
||||
return;
|
||||
} else if (preset == "Adobe Animate") {
|
||||
clearAllShortcuts(false);
|
||||
TFilePath fp = defaultPresetDir + TFilePath("otanimate.ini");
|
||||
setPresetShortcuts(fp);
|
||||
return;
|
||||
} else if (preset == "Adobe Flash Pro") {
|
||||
clearAllShortcuts(false);
|
||||
TFilePath fp = defaultPresetDir + TFilePath("otadobe.ini");
|
||||
setPresetShortcuts(fp);
|
||||
return;
|
||||
} else if (preset == "RETAS PaintMan") {
|
||||
clearAllShortcuts(false);
|
||||
TFilePath fp = defaultPresetDir + TFilePath("otretas.ini");
|
||||
setPresetShortcuts(fp);
|
||||
return;
|
||||
} else if (TSystem::doesExistFileOrLevel(presetDir +
|
||||
TFilePath(preset + ".ini"))) {
|
||||
clearAllShortcuts(false);
|
||||
TFilePath fp = presetDir + TFilePath(preset + ".ini");
|
||||
TFilePath fp = presetDir + presetFilePath;
|
||||
setPresetShortcuts(fp);
|
||||
return;
|
||||
}
|
||||
|
@ -743,14 +724,16 @@ void ShortcutPopup::onLoadPreset() {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
QStringList ShortcutPopup::buildPresets() {
|
||||
QStringList presets;
|
||||
presets << ""
|
||||
<< "Tahoma2D"
|
||||
//<< "RETAS PaintMan"
|
||||
<< "Toon Boom Harmony"
|
||||
<< "Adobe Animate"
|
||||
<< "Adobe Flash Pro";
|
||||
void ShortcutPopup::buildPresets() {
|
||||
m_presetChoiceCB->clear();
|
||||
|
||||
m_presetChoiceCB->addItem("", QString(""));
|
||||
m_presetChoiceCB->addItem("Tahoma2D", QString("deftahoma2d"));
|
||||
// m_presetChoiceCB->addItem("RETAS PaintMan", QString("otretas"));
|
||||
m_presetChoiceCB->addItem("Toon Boom Harmony", QString("otharmony"));
|
||||
m_presetChoiceCB->addItem("Adobe Animate", QString("otanimate"));
|
||||
m_presetChoiceCB->addItem("Adobe Flash Pro", QString("otadobe"));
|
||||
|
||||
TFilePath presetDir =
|
||||
ToonzFolder::getMyModuleDir() + TFilePath("shortcutpresets");
|
||||
if (TSystem::doesExistFileOrLevel(presetDir)) {
|
||||
|
@ -763,12 +746,10 @@ QStringList ShortcutPopup::buildPresets() {
|
|||
}
|
||||
}
|
||||
customPresets.sort();
|
||||
presets = presets + customPresets;
|
||||
for (auto customPreset : customPresets)
|
||||
m_presetChoiceCB->addItem(customPreset, customPreset);
|
||||
}
|
||||
presets << tr("Load from file...");
|
||||
m_presetChoiceCB->clear();
|
||||
m_presetChoiceCB->addItems(presets);
|
||||
return presets;
|
||||
m_presetChoiceCB->addItem(tr("Load from file..."), QString("LoadFromFile"));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -808,19 +789,9 @@ void ShortcutPopup::setCurrentPresetPref(QString name) {
|
|||
|
||||
void ShortcutPopup::getCurrentPresetPref() {
|
||||
QString name = Preferences::instance()->getShortcutPreset();
|
||||
if (name == "DELETED")
|
||||
m_presetChoiceCB->setCurrentText("");
|
||||
else if (name == "deftahoma2d")
|
||||
m_presetChoiceCB->setCurrentText("Tahoma2D");
|
||||
else if (name == "otharmony")
|
||||
m_presetChoiceCB->setCurrentText("Toon Boom Harmony");
|
||||
else if (name == "otadobe")
|
||||
m_presetChoiceCB->setCurrentText("Adobe Animate(Flash)");
|
||||
else if (name == "otretas")
|
||||
m_presetChoiceCB->setCurrentText("RETAS PaintMan");
|
||||
if (name == "DELETED") name = "";
|
||||
|
||||
else
|
||||
m_presetChoiceCB->setCurrentText(name);
|
||||
m_presetChoiceCB->setCurrentIndex(m_presetChoiceCB->findData(name));
|
||||
}
|
||||
|
||||
OpenPopupCommandHandler<ShortcutPopup> openShortcutPopup(MI_ShortcutPopup);
|
||||
|
|
|
@ -115,7 +115,7 @@ private:
|
|||
bool showConfirmDialog();
|
||||
bool showOverwriteDialog(QString name);
|
||||
void importPreset();
|
||||
QStringList buildPresets();
|
||||
void buildPresets();
|
||||
void showEvent(QShowEvent *se) override;
|
||||
void setCurrentPresetPref(QString preset);
|
||||
void getCurrentPresetPref();
|
||||
|
@ -123,7 +123,7 @@ private:
|
|||
protected slots:
|
||||
void clearAllShortcuts(bool warning = true);
|
||||
void onSearchTextChanged(const QString &text);
|
||||
void onPresetChanged(int index);
|
||||
void onPresetChanged();
|
||||
void onExportButton(TFilePath fp = TFilePath());
|
||||
void onDeletePreset();
|
||||
void onSavePreset();
|
||||
|
|
|
@ -1297,7 +1297,7 @@ void collapseColumns(std::set<int> indices, bool columnsOnly) {
|
|||
data->storeColumns(indices, xsh, StageObjectsData::eDoClone);
|
||||
data->storeColumnFxs(indices, xsh, StageObjectsData::eDoClone);
|
||||
|
||||
ExpressionReferenceMonitor *monitor = xsh->getExpRefMonitor()->clone();
|
||||
// ExpressionReferenceMonitor *monitor = xsh->getExpRefMonitor()->clone();
|
||||
|
||||
ToonzScene *scene = app->getCurrentScene()->getScene();
|
||||
TXshLevel *xl = scene->createNewLevel(CHILD_XSHLEVEL);
|
||||
|
@ -1320,6 +1320,7 @@ void collapseColumns(std::set<int> indices, bool columnsOnly) {
|
|||
if (!columnsOnly)
|
||||
bringPegbarsInsideChildXsheet(xsh, childXsh, indices, newIndices, idTable);
|
||||
|
||||
ExpressionReferenceManager::instance()->refreshXsheetRefInfo(childXsh);
|
||||
ExpressionReferenceManager::instance()->transferReference(xsh, childXsh,
|
||||
idTable, fxTable);
|
||||
|
||||
|
@ -1408,7 +1409,7 @@ void collapseColumns(std::set<int> indices,
|
|||
StageObjectsData::eDoClone);
|
||||
data->storeColumnFxs(indices, xsh, StageObjectsData::eDoClone);
|
||||
|
||||
ExpressionReferenceMonitor *monitor = xsh->getExpRefMonitor()->clone();
|
||||
// ExpressionReferenceMonitor *monitor = xsh->getExpRefMonitor()->clone();
|
||||
|
||||
ToonzScene *scene = app->getCurrentScene()->getScene();
|
||||
TXshLevel *xl = scene->createNewLevel(CHILD_XSHLEVEL);
|
||||
|
@ -1427,6 +1428,7 @@ void collapseColumns(std::set<int> indices,
|
|||
fxTable);
|
||||
childXsh->updateFrameCount();
|
||||
|
||||
ExpressionReferenceManager::instance()->refreshXsheetRefInfo(childXsh);
|
||||
ExpressionReferenceManager::instance()->transferReference(xsh, childXsh,
|
||||
idTable, fxTable);
|
||||
|
||||
|
@ -1472,7 +1474,7 @@ void collapseColumns(std::set<int> indices, const std::set<TFx *> &fxs,
|
|||
data->storeColumns(indices, xsh, StageObjectsData::eDoClone);
|
||||
data->storeFxs(fxs, xsh, StageObjectsData::eDoClone);
|
||||
|
||||
ExpressionReferenceMonitor *monitor = xsh->getExpRefMonitor()->clone();
|
||||
// ExpressionReferenceMonitor *monitor = xsh->getExpRefMonitor()->clone();
|
||||
|
||||
ToonzScene *scene = app->getCurrentScene()->getScene();
|
||||
TXshLevel *xl = scene->createNewLevel(CHILD_XSHLEVEL);
|
||||
|
@ -1491,6 +1493,7 @@ void collapseColumns(std::set<int> indices, const std::set<TFx *> &fxs,
|
|||
if (!columnsOnly)
|
||||
bringPegbarsInsideChildXsheet(xsh, childXsh, indices, newIndices, idTable);
|
||||
|
||||
ExpressionReferenceManager::instance()->refreshXsheetRefInfo(childXsh);
|
||||
ExpressionReferenceManager::instance()->transferReference(xsh, childXsh,
|
||||
idTable, fxTable);
|
||||
|
||||
|
|
|
@ -574,6 +574,7 @@ void PaletteViewerPanel::onFreezeButtonToggled(bool frozen) {
|
|||
|
||||
// Cambio il livello corrente
|
||||
if (!frozen) {
|
||||
m_frozenPalette = nullptr;
|
||||
std::set<TXshSimpleLevel *> levels;
|
||||
TXsheet *xsheet = app->getCurrentXsheet()->getXsheet();
|
||||
int row, column;
|
||||
|
@ -605,6 +606,7 @@ void PaletteViewerPanel::onFreezeButtonToggled(bool frozen) {
|
|||
app->getCurrentLevel()->setLevel(level);
|
||||
m_paletteViewer->setPaletteHandle(ph);
|
||||
} else {
|
||||
m_frozenPalette = ph->getPalette();
|
||||
m_paletteHandle->setPalette(ph->getPalette());
|
||||
m_paletteViewer->setPaletteHandle(m_paletteHandle);
|
||||
}
|
||||
|
@ -796,30 +798,31 @@ void ColorFieldEditorController::edit(DVGui::ColorField *colorField) {
|
|||
connect(m_currentColorField, SIGNAL(colorChanged(const TPixel32 &, bool)),
|
||||
SLOT(onColorChanged(const TPixel32 &, bool)));
|
||||
connect(m_colorFieldHandle, SIGNAL(colorStyleChanged(bool)),
|
||||
SLOT(onColorStyleChanged()));
|
||||
SLOT(onColorStyleChanged(bool)));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ColorFieldEditorController::hide() {
|
||||
disconnect(m_colorFieldHandle, SIGNAL(colorStyleChanged(bool)), this,
|
||||
SLOT(onColorStyleChanged()));
|
||||
SLOT(onColorStyleChanged(bool)));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ColorFieldEditorController::onColorStyleChanged() {
|
||||
void ColorFieldEditorController::onColorStyleChanged(bool isDragging) {
|
||||
if (!m_currentColorField) return;
|
||||
assert(!!m_palette);
|
||||
TPixel32 color = m_palette->getStyle(1)->getMainColor();
|
||||
if (m_currentColorField->getColor() == color) return;
|
||||
if (m_currentColorField->getColor() == color && isDragging) return;
|
||||
m_currentColorField->setColor(color);
|
||||
m_currentColorField->notifyColorChanged(color, false);
|
||||
m_currentColorField->notifyColorChanged(color, isDragging);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ColorFieldEditorController::onColorChanged(const TPixel32 &color, bool) {
|
||||
void ColorFieldEditorController::onColorChanged(const TPixel32 &color,
|
||||
bool isDragging) {
|
||||
if (!m_currentColorField) return;
|
||||
TColorStyle *style = m_palette->getStyle(1);
|
||||
if (style->getMainColor() == color) return;
|
||||
|
@ -827,7 +830,7 @@ void ColorFieldEditorController::onColorChanged(const TPixel32 &color, bool) {
|
|||
TApp::instance()
|
||||
->getPaletteController()
|
||||
->getCurrentPalette()
|
||||
->notifyColorStyleChanged();
|
||||
->notifyColorStyleChanged(isDragging);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
|
|
@ -44,6 +44,7 @@ class PaletteViewerPanel final : public StyleShortcutSwitchablePanel {
|
|||
PaletteViewer *m_paletteViewer;
|
||||
|
||||
bool m_isFrozen;
|
||||
TPaletteP m_frozenPalette;
|
||||
|
||||
public:
|
||||
PaletteViewerPanel(QWidget *parent);
|
||||
|
@ -133,7 +134,7 @@ public:
|
|||
void hide() override;
|
||||
|
||||
protected slots:
|
||||
void onColorStyleChanged();
|
||||
void onColorStyleChanged(bool);
|
||||
void onColorChanged(const TPixel32 &color, bool);
|
||||
};
|
||||
|
||||
|
|
|
@ -250,12 +250,13 @@ void TvpJsonLayer::build(int index, ToonzScene* scene, TXshCellColumn* column) {
|
|||
if (Preferences::instance()->isShowFrameNumberWithLettersEnabled())
|
||||
instance_name = getFrameNumberWithLetters(fid.getNumber());
|
||||
else {
|
||||
std::string frameNumber("");
|
||||
QString frameNumber("");
|
||||
// set number
|
||||
if (fid.getNumber() >= 0) frameNumber = std::to_string(fid.getNumber());
|
||||
if (fid.getNumber() >= 0)
|
||||
frameNumber = QString::number(fid.getNumber());
|
||||
// add letter
|
||||
if (fid.getLetter() != 0) frameNumber.append(1, fid.getLetter());
|
||||
instance_name = QString::fromStdString(frameNumber);
|
||||
if (!fid.getLetter().isEmpty()) frameNumber += fid.getLetter();
|
||||
instance_name = frameNumber;
|
||||
}
|
||||
|
||||
fid.setZeroPadding(frameFormats[cell.m_level.getPointer()].first);
|
||||
|
@ -365,7 +366,7 @@ void TvpJsonClip::build(ToonzScene* scene, TXsheet* xsheet) {
|
|||
continue;
|
||||
}
|
||||
TvpJsonLayer layer;
|
||||
layer.build(col, scene, column);
|
||||
layer.build(m_layers.size(), scene, column);
|
||||
if (!layer.isEmpty()) m_layers.append(layer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "tsystem.h"
|
||||
#include "toonzqt/filefield.h"
|
||||
#include "toonz/toonzscene.h"
|
||||
#include "toonz/tscenehandle.h"
|
||||
#include "toonz/sceneproperties.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QTableView>
|
||||
|
@ -11,9 +13,20 @@
|
|||
#include <QScrollArea>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QComboBox>
|
||||
|
||||
using namespace DVGui;
|
||||
|
||||
namespace {
|
||||
QIcon getColorChipIcon(TPixel32 color) {
|
||||
QPixmap pm(15, 15);
|
||||
pm.fill(QColor(color.r, color.g, color.b));
|
||||
return QIcon(pm);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//=============================================================================
|
||||
|
||||
XDTSImportPopup::XDTSImportPopup(QStringList levelNames, ToonzScene* scene,
|
||||
TFilePath scenePath)
|
||||
: m_scene(scene)
|
||||
|
@ -24,6 +37,26 @@ XDTSImportPopup::XDTSImportPopup(QStringList levelNames, ToonzScene* scene,
|
|||
QPushButton* loadButton = new QPushButton(tr("Load"), this);
|
||||
QPushButton* cancelButton = new QPushButton(tr("Cancel"), this);
|
||||
|
||||
m_tick1Combo = new QComboBox(this);
|
||||
m_tick2Combo = new QComboBox(this);
|
||||
QList<TSceneProperties::CellMark> marks = TApp::instance()
|
||||
->getCurrentScene()
|
||||
->getScene()
|
||||
->getProperties()
|
||||
->getCellMarks();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
QComboBox* combo = (i == 0) ? m_tick1Combo : m_tick2Combo;
|
||||
combo->addItem(tr("None"), -1);
|
||||
int curId = 0;
|
||||
for (auto mark : marks) {
|
||||
QString label = QString("%1: %2").arg(curId).arg(mark.name);
|
||||
combo->addItem(getColorChipIcon(mark.color), label, curId);
|
||||
curId++;
|
||||
}
|
||||
}
|
||||
m_tick1Combo->setCurrentIndex(m_tick1Combo->findData(0));
|
||||
m_tick2Combo->setCurrentIndex(m_tick2Combo->findData(1));
|
||||
|
||||
QString description =
|
||||
tr("Please specify the level locations. Suggested paths "
|
||||
"are input in the fields with blue border.");
|
||||
|
@ -62,6 +95,24 @@ XDTSImportPopup::XDTSImportPopup(QStringList levelNames, ToonzScene* scene,
|
|||
fieldsArea->setWidget(fieldsWidget);
|
||||
m_topLayout->addWidget(fieldsArea, 1);
|
||||
|
||||
// cell mark area
|
||||
QGridLayout* markLay = new QGridLayout();
|
||||
markLay->setMargin(0);
|
||||
markLay->setHorizontalSpacing(10);
|
||||
markLay->setVerticalSpacing(10);
|
||||
{
|
||||
markLay->addWidget(new QLabel(tr("Inbetween symbol mark"), this), 0, 0,
|
||||
Qt::AlignRight | Qt::AlignVCenter);
|
||||
markLay->addWidget(m_tick1Combo, 0, 1);
|
||||
|
||||
markLay->addWidget(new QLabel(tr("Reverse sheet symbol mark"), this), 1, 0,
|
||||
Qt::AlignRight | Qt::AlignVCenter);
|
||||
markLay->addWidget(m_tick2Combo, 1, 1);
|
||||
}
|
||||
markLay->setColumnStretch(2, 1);
|
||||
m_topLayout->addLayout(markLay, 0);
|
||||
|
||||
|
||||
connect(loadButton, SIGNAL(clicked()), this, SLOT(accept()));
|
||||
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
|
||||
|
||||
|
@ -174,8 +225,17 @@ void XDTSImportPopup::updateSuggestions(const QString samplePath) {
|
|||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
QString XDTSImportPopup::getLevelPath(QString levelName) {
|
||||
FileField* field = m_fields.value(levelName);
|
||||
if (!field) return QString();
|
||||
return field->getPath();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void XDTSImportPopup::getMarkerIds(int& tick1Id, int& tick2Id) {
|
||||
tick1Id = m_tick1Combo->currentData().toInt();
|
||||
tick2Id = m_tick2Combo->currentData().toInt();
|
||||
}
|
||||
|
|
|
@ -10,19 +10,23 @@ namespace DVGui {
|
|||
class FileField;
|
||||
}
|
||||
class ToonzScene;
|
||||
class QComboBox;
|
||||
|
||||
class XDTSImportPopup : public DVGui::Dialog {
|
||||
Q_OBJECT
|
||||
QMap<QString, DVGui::FileField *> m_fields;
|
||||
QMap<QString, DVGui::FileField*> m_fields;
|
||||
QStringList m_pathSuggestedLevels;
|
||||
ToonzScene *m_scene;
|
||||
ToonzScene* m_scene;
|
||||
|
||||
QComboBox *m_tick1Combo, *m_tick2Combo;
|
||||
|
||||
void updateSuggestions(const QString samplePath);
|
||||
|
||||
public:
|
||||
XDTSImportPopup(QStringList levelNames, ToonzScene *scene,
|
||||
XDTSImportPopup(QStringList levelNames, ToonzScene* scene,
|
||||
TFilePath scenePath);
|
||||
QString getLevelPath(QString levelName);
|
||||
void getMarkerIds(int& tick1Id, int& tick2Id);
|
||||
protected slots:
|
||||
void onPathChanged();
|
||||
};
|
||||
|
|
|
@ -32,10 +32,22 @@
|
|||
#include <QApplication>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
#include <QComboBox>
|
||||
#include <QLabel>
|
||||
using namespace XdtsIo;
|
||||
namespace {
|
||||
static QByteArray identifierStr("exchangeDigitalTimeSheet Save Data");
|
||||
|
||||
QIcon getColorChipIcon(TPixel32 color) {
|
||||
QPixmap pm(15, 15);
|
||||
pm.fill(QColor(color.r, color.g, color.b));
|
||||
return QIcon(pm);
|
||||
}
|
||||
|
||||
int _tick1Id = -1;
|
||||
int _tick2Id = -1;
|
||||
bool _exportAllColumn = true;
|
||||
} // namespace
|
||||
//-----------------------------------------------------------------------------
|
||||
void XdtsHeader::read(const QJsonObject &json) {
|
||||
QRegExp rx("\\d{1,4}");
|
||||
|
@ -60,21 +72,30 @@ void XdtsHeader::write(QJsonObject &json) const {
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
TFrameId XdtsFrameDataItem::str2Fid(const QString &str) const {
|
||||
if (str.isEmpty()) return TFrameId::EMPTY_FRAME;
|
||||
bool ok;
|
||||
int frame = str.toInt(&ok);
|
||||
if (ok) return TFrameId(frame);
|
||||
// separate the last word as suffix
|
||||
frame = str.left(str.size() - 1).toInt(&ok);
|
||||
if (!ok) return TFrameId(-1); // EMPTY
|
||||
if (!str[str.size() - 1].isLetter()) return TFrameId(-1); // EMPTY
|
||||
char c = str[str.size() - 1].toLatin1();
|
||||
|
||||
return TFrameId(frame, c);
|
||||
QString regExpStr = QString("^%1$").arg(TFilePath::fidRegExpStr());
|
||||
QRegExp rx(regExpStr);
|
||||
int pos = rx.indexIn(str);
|
||||
if (pos < 0) return TFrameId();
|
||||
if (rx.cap(2).isEmpty())
|
||||
return TFrameId(rx.cap(1).toInt());
|
||||
else
|
||||
return TFrameId(rx.cap(1).toInt(), rx.cap(2));
|
||||
}
|
||||
|
||||
QString XdtsFrameDataItem::fid2Str(const TFrameId &fid) const {
|
||||
if (fid.getLetter() == 0) return QString::number(fid.getNumber());
|
||||
return QString::number(fid.getNumber()) + QString(fid.getLetter());
|
||||
if (fid.getNumber() == -1)
|
||||
return QString("SYMBOL_NULL_CELL");
|
||||
else if (fid.getNumber() == SYMBOL_TICK_1)
|
||||
return QString("SYMBOL_TICK_1");
|
||||
else if (fid.getNumber() == SYMBOL_TICK_2)
|
||||
return QString("SYMBOL_TICK_2");
|
||||
else if (fid.getLetter().isEmpty())
|
||||
return QString::number(fid.getNumber());
|
||||
return QString::number(fid.getNumber()) + fid.getLetter();
|
||||
}
|
||||
|
||||
void XdtsFrameDataItem::read(const QJsonObject &json) {
|
||||
|
@ -101,11 +122,13 @@ TFrameId XdtsFrameDataItem::getFrameId() const {
|
|||
if (val == "SYMBOL_NULL_CELL")
|
||||
return TFrameId(-1); // EMPTY
|
||||
// ignore sheet symbols for now
|
||||
else if (val == "SYMBOL_HYPHEN" || val == "SYMBOL_TICK_1" ||
|
||||
val == "SYMBOL_TICK_2")
|
||||
else if (val == "SYMBOL_HYPHEN")
|
||||
return TFrameId(-2); // IGNORE
|
||||
// return -1;
|
||||
// return cell number
|
||||
else if (val == "SYMBOL_TICK_1")
|
||||
return TFrameId(SYMBOL_TICK_1);
|
||||
else if (val == "SYMBOL_TICK_2")
|
||||
return TFrameId(SYMBOL_TICK_2);
|
||||
// return cell number
|
||||
return str2Fid(m_values.at(0));
|
||||
}
|
||||
|
||||
|
@ -169,7 +192,8 @@ static bool frameLessThan(const QPair<int, TFrameId> &v1,
|
|||
return v1.first < v2.first;
|
||||
}
|
||||
|
||||
QVector<TFrameId> XdtsFieldTrackItem::getCellFrameIdTrack() const {
|
||||
QVector<TFrameId> XdtsFieldTrackItem::getCellFrameIdTrack(
|
||||
QList<int> &tick1, QList<int> &tick2) const {
|
||||
QList<QPair<int, TFrameId>> frameFids;
|
||||
for (const XdtsTrackFrameItem &frame : m_frames)
|
||||
frameFids.append(frame.frameFid());
|
||||
|
@ -193,7 +217,15 @@ QVector<TFrameId> XdtsFieldTrackItem::getCellFrameIdTrack() const {
|
|||
TFrameId cellFid = frameFid.second;
|
||||
if (cellFid.getNumber() == -2) // IGNORE case
|
||||
cells.append((cells.isEmpty()) ? TFrameId(-1) : cells.last());
|
||||
else
|
||||
else if (cellFid.getNumber() ==
|
||||
XdtsFrameDataItem::SYMBOL_TICK_1) { // SYMBOL_TICK_1
|
||||
cells.append((cells.isEmpty()) ? TFrameId(-1) : cells.last());
|
||||
tick1.append(currentFrame);
|
||||
} else if (cellFid.getNumber() ==
|
||||
XdtsFrameDataItem::SYMBOL_TICK_2) { // SYMBOL_TICK_2
|
||||
cells.append((cells.isEmpty()) ? TFrameId(-1) : cells.last());
|
||||
tick2.append(currentFrame);
|
||||
} else
|
||||
cells.append(cellFid);
|
||||
currentFrame++;
|
||||
}
|
||||
|
@ -217,7 +249,14 @@ QString XdtsFieldTrackItem::build(TXshCellColumn *column) {
|
|||
// handle as the empty cell
|
||||
if (!level || cell.m_level != level) cell = TXshCell();
|
||||
// continue if the cell is continuous
|
||||
if (prevCell == cell) continue;
|
||||
if (prevCell == cell) {
|
||||
// cell mark to ticks
|
||||
if (_tick1Id >= 0 && column->getCellMark(row) == _tick1Id)
|
||||
addFrame(row, TFrameId(XdtsFrameDataItem::SYMBOL_TICK_1));
|
||||
else if (_tick2Id >= 0 && column->getCellMark(row) == _tick2Id)
|
||||
addFrame(row, TFrameId(XdtsFrameDataItem::SYMBOL_TICK_2));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cell.isEmpty())
|
||||
addFrame(row, TFrameId(-1));
|
||||
|
@ -266,29 +305,37 @@ QList<int> XdtsTimeTableFieldItem::getOccupiedColumns() const {
|
|||
return ret;
|
||||
}
|
||||
|
||||
QVector<TFrameId> XdtsTimeTableFieldItem::getColumnTrack(int col) const {
|
||||
QVector<TFrameId> XdtsTimeTableFieldItem::getColumnTrack(
|
||||
int col, QList<int> &tick1, QList<int> &tick2) const {
|
||||
for (const XdtsFieldTrackItem &track : m_tracks) {
|
||||
if (track.getTrackNo() != col) continue;
|
||||
return track.getCellFrameIdTrack();
|
||||
return track.getCellFrameIdTrack(tick1, tick2);
|
||||
}
|
||||
return QVector<TFrameId>();
|
||||
}
|
||||
|
||||
void XdtsTimeTableFieldItem::build(TXsheet *xsheet, QStringList &columnLabels) {
|
||||
m_fieldId = CELL;
|
||||
m_fieldId = CELL;
|
||||
int exportCol = 0;
|
||||
for (int col = 0; col < xsheet->getFirstFreeColumnIndex(); col++) {
|
||||
if (xsheet->isColumnEmpty(col)) {
|
||||
columnLabels.append("");
|
||||
exportCol++;
|
||||
continue;
|
||||
}
|
||||
TXshCellColumn *column = xsheet->getColumn(col)->getCellColumn();
|
||||
// skip non-cell column
|
||||
if (!column) {
|
||||
columnLabels.append("");
|
||||
continue;
|
||||
}
|
||||
XdtsFieldTrackItem track(col);
|
||||
// skip inactive column
|
||||
if (!_exportAllColumn && !column->isPreviewVisible()) {
|
||||
continue;
|
||||
}
|
||||
XdtsFieldTrackItem track(exportCol);
|
||||
columnLabels.append(track.build(column));
|
||||
if (!track.isEmpty()) m_tracks.append(track);
|
||||
exportCol++;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -501,6 +548,9 @@ bool XdtsIo::loadXdtsScene(ToonzScene *scene, const TFilePath &scenePath) {
|
|||
return false;
|
||||
}
|
||||
|
||||
int tick1Id, tick2Id;
|
||||
popup.getMarkerIds(tick1Id, tick2Id);
|
||||
|
||||
TXsheet *xsh = scene->getXsheet();
|
||||
XdtsTimeTableFieldItem cellField = xdtsData.timeTable().getCellField();
|
||||
XdtsTimeTableHeaderItem cellHeader = xdtsData.timeTable().getCellHeader();
|
||||
|
@ -508,9 +558,10 @@ 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);
|
||||
QVector<TFrameId> track = cellField.getColumnTrack(column);
|
||||
QString levelName = layerNames.at(column);
|
||||
TXshLevel *level = levels.value(levelName);
|
||||
QList<int> tick1, tick2;
|
||||
QVector<TFrameId> track = cellField.getColumnTrack(column, tick1, tick2);
|
||||
|
||||
int row = 0;
|
||||
std::vector<TFrameId>::iterator it;
|
||||
|
@ -528,6 +579,15 @@ bool XdtsIo::loadXdtsScene(ToonzScene *scene, const TFilePath &scenePath) {
|
|||
xsh->setCell(row, column, TXshCell(level, TFrameId(lastFid)));
|
||||
}
|
||||
|
||||
// set cell marks
|
||||
TXshCellColumn *cellColumn = xsh->getColumn(column)->getCellColumn();
|
||||
if (tick1Id >= 0) {
|
||||
for (auto tick1f : tick1) cellColumn->setCellMark(tick1f, tick1Id);
|
||||
}
|
||||
if (tick2Id >= 0) {
|
||||
for (auto tick2f : tick2) cellColumn->setCellMark(tick2f, tick2Id);
|
||||
}
|
||||
|
||||
TStageObject *pegbar =
|
||||
xsh->getStageObject(TStageObjectId::ColumnId(column));
|
||||
if (pegbar) pegbar->setName(levelName.toStdString());
|
||||
|
@ -569,18 +629,80 @@ void ExportXDTSCommand::execute() {
|
|||
else
|
||||
duration = xsheet->getFrameCount();
|
||||
|
||||
XdtsData xdtsData;
|
||||
xdtsData.build(xsheet, QString::fromStdString(fp.getName()), duration);
|
||||
if (xdtsData.isEmpty()) {
|
||||
DVGui::error(QObject::tr("No columns can be exported."));
|
||||
return;
|
||||
{
|
||||
_tick1Id = -1;
|
||||
_tick2Id = -1;
|
||||
_exportAllColumn = true;
|
||||
XdtsData pre_xdtsData;
|
||||
pre_xdtsData.build(xsheet, QString::fromStdString(fp.getName()), duration);
|
||||
if (pre_xdtsData.isEmpty()) {
|
||||
DVGui::error(QObject::tr("No columns can be exported."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static GenericSaveFilePopup *savePopup = 0;
|
||||
static QComboBox *tick1Id = nullptr;
|
||||
static QComboBox *tick2Id = nullptr;
|
||||
static QComboBox *targetColumnCombo = nullptr;
|
||||
|
||||
auto refreshCellMarkComboItems = [](QComboBox *combo) {
|
||||
int current = -1;
|
||||
if (combo->count()) current = combo->currentData().toInt();
|
||||
|
||||
combo->clear();
|
||||
QList<TSceneProperties::CellMark> marks = TApp::instance()
|
||||
->getCurrentScene()
|
||||
->getScene()
|
||||
->getProperties()
|
||||
->getCellMarks();
|
||||
combo->addItem(tr("None"), -1);
|
||||
int curId = 0;
|
||||
for (auto mark : marks) {
|
||||
QString label = QString("%1: %2").arg(curId).arg(mark.name);
|
||||
combo->addItem(getColorChipIcon(mark.color), label, curId);
|
||||
curId++;
|
||||
}
|
||||
if (current >= 0) combo->setCurrentIndex(combo->findData(current));
|
||||
};
|
||||
|
||||
if (!savePopup) {
|
||||
// create custom widget
|
||||
QWidget *custonWidget = new QWidget();
|
||||
tick1Id = new QComboBox();
|
||||
tick2Id = new QComboBox();
|
||||
refreshCellMarkComboItems(tick1Id);
|
||||
refreshCellMarkComboItems(tick2Id);
|
||||
tick1Id->setCurrentIndex(tick1Id->findData(0));
|
||||
tick2Id->setCurrentIndex(tick2Id->findData(1));
|
||||
targetColumnCombo = new QComboBox();
|
||||
targetColumnCombo->addItem(tr("All columns"), true);
|
||||
targetColumnCombo->addItem(tr("Only active columns"), false);
|
||||
targetColumnCombo->setCurrentIndex(targetColumnCombo->findData(true));
|
||||
|
||||
QGridLayout *customLay = new QGridLayout();
|
||||
customLay->setMargin(0);
|
||||
customLay->setSpacing(10);
|
||||
{
|
||||
customLay->addWidget(new QLabel(tr("Inbetween symbol mark")), 0, 0,
|
||||
Qt::AlignRight | Qt::AlignVCenter);
|
||||
customLay->addWidget(tick1Id, 0, 1);
|
||||
customLay->addWidget(new QLabel(tr("Reverse sheet symbol mark")), 1, 0,
|
||||
Qt::AlignRight | Qt::AlignVCenter);
|
||||
customLay->addWidget(tick2Id, 1, 1);
|
||||
customLay->addWidget(new QLabel(tr("Target column")), 2, 0,
|
||||
Qt::AlignRight | Qt::AlignVCenter);
|
||||
customLay->addWidget(targetColumnCombo, 2, 1);
|
||||
}
|
||||
customLay->setColumnStretch(0, 1);
|
||||
custonWidget->setLayout(customLay);
|
||||
|
||||
savePopup = new GenericSaveFilePopup(
|
||||
QObject::tr("Export Exchange Digital Time Sheet (XDTS)"));
|
||||
QObject::tr("Export Exchange Digital Time Sheet (XDTS)"), custonWidget);
|
||||
savePopup->addFilterType("xdts");
|
||||
} else {
|
||||
refreshCellMarkComboItems(tick1Id);
|
||||
refreshCellMarkComboItems(tick2Id);
|
||||
}
|
||||
if (!scene->isUntitled())
|
||||
savePopup->setFolder(fp.getParentDir());
|
||||
|
@ -598,6 +720,16 @@ void ExportXDTSCommand::execute() {
|
|||
return;
|
||||
}
|
||||
|
||||
_tick1Id = tick1Id->currentData().toInt();
|
||||
_tick2Id = tick2Id->currentData().toInt();
|
||||
_exportAllColumn = targetColumnCombo->currentData().toBool();
|
||||
XdtsData xdtsData;
|
||||
xdtsData.build(xsheet, QString::fromStdString(fp.getName()), duration);
|
||||
if (xdtsData.isEmpty()) {
|
||||
DVGui::error(QObject::tr("No columns can be exported."));
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonObject xdtsObject;
|
||||
xdtsData.write(xdtsObject);
|
||||
QJsonDocument saveDoc(xdtsObject);
|
||||
|
|
|
@ -83,10 +83,11 @@ class XdtsFrameDataItem {
|
|||
QString fid2Str(const TFrameId &) const;
|
||||
|
||||
public:
|
||||
enum { SYMBOL_TICK_1 = -100, SYMBOL_TICK_2 = -200 };
|
||||
|
||||
XdtsFrameDataItem() : m_id(Default) {}
|
||||
XdtsFrameDataItem(TFrameId fId) : m_id(Default) {
|
||||
m_values.append((fId.getNumber() == -1) ? QString("SYMBOL_NULL_CELL")
|
||||
: fid2Str(fId));
|
||||
m_values.append(fid2Str(fId));
|
||||
}
|
||||
void read(const QJsonObject &json);
|
||||
void write(QJsonObject &json) const;
|
||||
|
@ -132,7 +133,8 @@ public:
|
|||
void write(QJsonObject &json) const;
|
||||
bool isEmpty() const { return m_frames.isEmpty(); }
|
||||
int getTrackNo() const { return m_trackNo; }
|
||||
QVector<TFrameId> getCellFrameIdTrack() const;
|
||||
QVector<TFrameId> getCellFrameIdTrack(QList<int> &tick1,
|
||||
QList<int> &tick2) const;
|
||||
|
||||
QString build(TXshCellColumn *);
|
||||
void addFrame(int frame, TFrameId fId) {
|
||||
|
@ -154,7 +156,8 @@ public:
|
|||
void write(QJsonObject &json) const;
|
||||
bool isCellField() { return m_fieldId == CELL; }
|
||||
QList<int> getOccupiedColumns() const;
|
||||
QVector<TFrameId> getColumnTrack(int col) const;
|
||||
QVector<TFrameId> getColumnTrack(int col, QList<int> &tick1,
|
||||
QList<int> &tick2) const;
|
||||
|
||||
void build(TXsheet *, QStringList &);
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -8,6 +8,7 @@
|
|||
#include "orientation.h"
|
||||
|
||||
#include "toonz/txshcell.h"
|
||||
#include "tundo.h"
|
||||
|
||||
// forward declaration
|
||||
class XsheetViewer;
|
||||
|
@ -17,6 +18,20 @@ class TXshSoundTextColumn;
|
|||
|
||||
namespace XsheetGUI {
|
||||
|
||||
class SetCellMarkUndo final : public TUndo {
|
||||
int m_row, m_col;
|
||||
int m_idBefore, m_idAfter;
|
||||
|
||||
public:
|
||||
SetCellMarkUndo(int row, int col, int idAfter);
|
||||
void setId(int id) const;
|
||||
void undo() const override;
|
||||
void redo() const override;
|
||||
int getSize() const override;
|
||||
QString getHistoryString() override;
|
||||
int getHistoryType() override;
|
||||
};
|
||||
|
||||
class NoteWidget;
|
||||
class DragTool;
|
||||
|
||||
|
@ -103,6 +118,7 @@ class CellArea final : public QWidget {
|
|||
bool showLevelName = true);
|
||||
void drawSoundTextCell(QPainter &p, int row, int col);
|
||||
void drawSoundCell(QPainter &p, int row, int col, bool isReference = false);
|
||||
void drawSoundTextColumn(QPainter &p, int r0, int r1, int col);
|
||||
void drawPaletteCell(QPainter &p, int row, int col, bool isReference = false);
|
||||
|
||||
void drawKeyframe(QPainter &p, const QRect toBeUpdated);
|
||||
|
@ -166,7 +182,8 @@ protected:
|
|||
/*!Crea il menu' del tasto destro che si visualizza quando si clicca sulla
|
||||
cella,
|
||||
distinguendo i due casi: cella piena, cella vuota.*/
|
||||
void createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell);
|
||||
void createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell, int row,
|
||||
int col);
|
||||
//! Crea il menu' del tasto destro che si visualizza si clicca su un key
|
||||
//! frame.
|
||||
void createKeyMenu(QMenu &menu);
|
||||
|
@ -182,6 +199,7 @@ protected slots:
|
|||
void onStepChanged(QAction *);
|
||||
// replace level with another level in the cast
|
||||
void onReplaceByCastedLevel(QAction *action);
|
||||
void onSetCellMark();
|
||||
};
|
||||
|
||||
} // namespace XsheetGUI
|
||||
|
|
|
@ -1043,7 +1043,7 @@ void ColumnArea::DrawHeader::drawColumnName() const {
|
|||
|
||||
// ZeraryFx columns store name elsewhere
|
||||
TXshZeraryFxColumn *zColumn = dynamic_cast<TXshZeraryFxColumn *>(column);
|
||||
if (zColumn)
|
||||
if (zColumn && !isEmpty)
|
||||
name = ::to_string(zColumn->getZeraryColumnFx()->getZeraryFx()->getName());
|
||||
|
||||
QRect columnName = o->rect((col < 0) ? PredefinedRect::CAMERA_LAYER_NAME
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "duplicatepopup.h"
|
||||
#include "menubarcommandids.h"
|
||||
#include "columncommand.h"
|
||||
#include "xshcellviewer.h" // SetCellMarkUndo
|
||||
|
||||
// Qt includes
|
||||
#include <QClipboard>
|
||||
|
@ -2199,6 +2200,43 @@ public:
|
|||
|
||||
} ToggleXsheetCameraColumnCommand;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class SetCellMarkCommand final : public MenuItemHandler {
|
||||
int m_markId;
|
||||
|
||||
public:
|
||||
SetCellMarkCommand(int markId)
|
||||
: MenuItemHandler(
|
||||
((std::string)MI_SetCellMark + std::to_string(markId)).c_str())
|
||||
, m_markId(markId) {}
|
||||
|
||||
void execute() override {
|
||||
TApp *app = TApp::instance();
|
||||
TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
|
||||
int currentRow = app->getCurrentFrame()->getFrame();
|
||||
int currentColumn = app->getCurrentColumn()->getColumnIndex();
|
||||
if (!xsh->getColumn(currentColumn)) return;
|
||||
TXshCellColumn *cellColumn = xsh->getColumn(currentColumn)->getCellColumn();
|
||||
if (!cellColumn) return;
|
||||
XsheetGUI::SetCellMarkUndo *undo =
|
||||
new XsheetGUI::SetCellMarkUndo(currentRow, currentColumn, m_markId);
|
||||
undo->redo();
|
||||
TUndoManager::manager()->add(undo);
|
||||
}
|
||||
};
|
||||
SetCellMarkCommand CellMarkCommand0(0);
|
||||
SetCellMarkCommand CellMarkCommand1(1);
|
||||
SetCellMarkCommand CellMarkCommand2(2);
|
||||
SetCellMarkCommand CellMarkCommand3(3);
|
||||
SetCellMarkCommand CellMarkCommand4(4);
|
||||
SetCellMarkCommand CellMarkCommand5(5);
|
||||
SetCellMarkCommand CellMarkCommand6(6);
|
||||
SetCellMarkCommand CellMarkCommand7(7);
|
||||
SetCellMarkCommand CellMarkCommand8(8);
|
||||
SetCellMarkCommand CellMarkCommand9(9);
|
||||
SetCellMarkCommand CellMarkCommand10(10);
|
||||
SetCellMarkCommand CellMarkCommand11(11);
|
||||
|
||||
//============================================================
|
||||
|
||||
|
|
|
@ -551,7 +551,7 @@ public:
|
|||
int i;
|
||||
for (i = 1; i < count; i++)
|
||||
if (m_sourceCells[i].m_level != cell.m_level ||
|
||||
m_sourceCells[i].m_frameId.getLetter() != 0)
|
||||
!m_sourceCells[i].m_frameId.getLetter().isEmpty())
|
||||
return;
|
||||
|
||||
// check if all the selected cells have the same frame number
|
||||
|
|
|
@ -162,6 +162,7 @@ set(HEADERS
|
|||
../include/toonz/preferencesitemids.h
|
||||
../include/toonz/txsheetcolumnchange.h
|
||||
../include/toonz/expressionreferencemonitor.h
|
||||
../include/toonz/filepathproperties.h
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
|
@ -320,6 +321,7 @@ set(SOURCES
|
|||
txshmeshcolumn.cpp
|
||||
textureutils.cpp
|
||||
boardsettings.cpp
|
||||
filepathproperties.cpp
|
||||
)
|
||||
|
||||
if(BUILD_TARGET_WIN)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "toonz/toonzscene.h"
|
||||
#include "toonz/sceneproperties.h"
|
||||
#include "toonz/txshleveltypes.h"
|
||||
#include "toonz/cleanupcolorstyles.h"
|
||||
#include "tsystem.h"
|
||||
#include "tenv.h"
|
||||
#include "tconvert.h"
|
||||
|
@ -193,7 +194,10 @@ CleanupParameters::CleanupParameters()
|
|||
, m_dirtyFlag(false)
|
||||
//, m_resName("")
|
||||
, m_offx_lock(false)
|
||||
, m_offy_lock(false) {}
|
||||
, m_offy_lock(false)
|
||||
, m_altBrightness(0)
|
||||
, m_altContrast(50)
|
||||
, m_lpNoneFormat("tif") {}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
|
@ -300,8 +304,11 @@ void CleanupParameters::assign(const CleanupParameters *param,
|
|||
if (clonePalette && param->m_cleanupPalette)
|
||||
m_cleanupPalette = param->m_cleanupPalette->clone();
|
||||
|
||||
m_offx_lock = param->m_offx_lock;
|
||||
m_offy_lock = param->m_offy_lock;
|
||||
m_offx_lock = param->m_offx_lock;
|
||||
m_offy_lock = param->m_offy_lock;
|
||||
m_altBrightness = param->m_altBrightness;
|
||||
m_altContrast = param->m_altContrast;
|
||||
m_lpNoneFormat = param->m_lpNoneFormat;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
@ -330,10 +337,10 @@ void CleanupParameters::saveData(TOStream &os) const {
|
|||
attr.clear();
|
||||
std::string flip =
|
||||
std::string(m_flipx ? "x" : "") + std::string(m_flipy ? "y" : "");
|
||||
if (flip != "") attr["flip"] = flip;
|
||||
if (flip != "") attr["flip"] = flip;
|
||||
if (m_rotate != 0) attr["rotate"] = std::to_string(m_rotate);
|
||||
if (m_offx != 0.0) attr["xoff"] = std::to_string(m_offx);
|
||||
if (m_offy != 0.0) attr["yoff"] = std::to_string(m_offy);
|
||||
if (m_offx != 0.0) attr["xoff"] = std::to_string(m_offx);
|
||||
if (m_offy != 0.0) attr["yoff"] = std::to_string(m_offy);
|
||||
os.openCloseChild("transform", attr);
|
||||
}
|
||||
|
||||
|
@ -366,6 +373,8 @@ void CleanupParameters::saveData(TOStream &os) const {
|
|||
os.openCloseChild("fdg", attr);
|
||||
attr.clear();
|
||||
if (m_path != TFilePath()) os.child("path") << m_path;
|
||||
os.child("altBrightnessContrast") << m_altBrightness << m_altContrast;
|
||||
os.child("lpNoneFormat") << m_lpNoneFormat;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
@ -380,6 +389,9 @@ void CleanupParameters::loadData(TIStream &is, bool globalParams) {
|
|||
m_lineProcessingMode = lpNone;
|
||||
m_noAntialias = false;
|
||||
m_postAntialias = false;
|
||||
// hold brightness and contrast values of another processing mode
|
||||
m_altBrightness = -1.0;
|
||||
m_altContrast = -1.0;
|
||||
|
||||
while (is.matchTag(tagName)) {
|
||||
if (tagName == "cleanupPalette") {
|
||||
|
@ -390,42 +402,42 @@ void CleanupParameters::loadData(TIStream &is, bool globalParams) {
|
|||
m_camera.loadData(is);
|
||||
is.closeChild();
|
||||
} else if (tagName == "autoCenter") {
|
||||
m_autocenterType = AUTOCENTER_FDG;
|
||||
std::string s = is.getTagAttribute("type");
|
||||
m_autocenterType = AUTOCENTER_FDG;
|
||||
std::string s = is.getTagAttribute("type");
|
||||
if (s != "" && isInt(s)) m_autocenterType = (AUTOCENTER_TYPE)std::stoi(s);
|
||||
s = is.getTagAttribute("pegHoles");
|
||||
s = is.getTagAttribute("pegHoles");
|
||||
if (s != "" && isInt(s)) m_pegSide = (PEGS_SIDE)std::stoi(s);
|
||||
} else if (tagName == "transform") {
|
||||
std::string s = is.getTagAttribute("flip");
|
||||
m_flipx = (s.find("x") != std::string::npos);
|
||||
m_flipy = (s.find("y") != std::string::npos);
|
||||
s = is.getTagAttribute("rotate");
|
||||
if (s != "" && isInt(s)) m_rotate = std::stoi(s);
|
||||
s = is.getTagAttribute("xoff");
|
||||
std::string s = is.getTagAttribute("flip");
|
||||
m_flipx = (s.find("x") != std::string::npos);
|
||||
m_flipy = (s.find("y") != std::string::npos);
|
||||
s = is.getTagAttribute("rotate");
|
||||
if (s != "" && isInt(s)) m_rotate = std::stoi(s);
|
||||
s = is.getTagAttribute("xoff");
|
||||
if (s != "" && isDouble(s)) m_offx = std::stod(s);
|
||||
s = is.getTagAttribute("yoff");
|
||||
s = is.getTagAttribute("yoff");
|
||||
if (s != "" && isDouble(s)) m_offy = std::stod(s);
|
||||
} else if (tagName == "lineProcessing") {
|
||||
m_lineProcessingMode = lpGrey;
|
||||
std::string s = is.getTagAttribute("sharpness");
|
||||
m_lineProcessingMode = lpGrey;
|
||||
std::string s = is.getTagAttribute("sharpness");
|
||||
if (s != "" && isDouble(s)) m_sharpness = std::stod(s);
|
||||
s = is.getTagAttribute("autoAdjust");
|
||||
if (s != "" && isDouble(s))
|
||||
m_autoAdjustMode = (CleanupTypes::AUTO_ADJ_MODE)std::stoi(s);
|
||||
s = is.getTagAttribute("mode");
|
||||
s = is.getTagAttribute("mode");
|
||||
if (s != "" && s == "color") m_lineProcessingMode = lpColor;
|
||||
} else if (tagName == "despeckling") {
|
||||
std::string s = is.getTagAttribute("value");
|
||||
std::string s = is.getTagAttribute("value");
|
||||
if (s != "" && isInt(s)) m_despeckling = std::stoi(s);
|
||||
} else if (tagName == "aaValue") {
|
||||
std::string s = is.getTagAttribute("value");
|
||||
std::string s = is.getTagAttribute("value");
|
||||
if (s != "" && isInt(s)) m_aaValue = std::stoi(s);
|
||||
} else if (tagName == "noAntialias")
|
||||
m_noAntialias = true;
|
||||
else if (tagName == "MLAA")
|
||||
m_postAntialias = true;
|
||||
else if (tagName == "closestField") {
|
||||
std::string s = is.getTagAttribute("value");
|
||||
std::string s = is.getTagAttribute("value");
|
||||
if (s != "" && isDouble(s)) m_closestField = std::stod(s);
|
||||
} else if (tagName == "fdg") {
|
||||
std::string s = is.getTagAttribute("name");
|
||||
|
@ -433,10 +445,26 @@ void CleanupParameters::loadData(TIStream &is, bool globalParams) {
|
|||
} else if (tagName == "path") {
|
||||
is >> m_path;
|
||||
is.closeChild();
|
||||
} else if (tagName == "altBrightnessContrast") {
|
||||
is >> m_altBrightness >> m_altContrast;
|
||||
is.closeChild();
|
||||
} else if (tagName == "lpNoneFormat") {
|
||||
is >> m_lpNoneFormat;
|
||||
is.closeChild();
|
||||
} else
|
||||
is.skipCurrentTag();
|
||||
}
|
||||
|
||||
if ((m_altBrightness < 0.0 || m_altContrast < 0.0) && m_cleanupPalette &&
|
||||
m_cleanupPalette->getStyleCount() >= 2) {
|
||||
TCleanupStyle *blackStyle =
|
||||
dynamic_cast<TCleanupStyle *>(m_cleanupPalette->getStyle(1));
|
||||
if (blackStyle) {
|
||||
m_altBrightness = blackStyle->getBrightness();
|
||||
m_altContrast = blackStyle->getContrast();
|
||||
}
|
||||
}
|
||||
|
||||
CleanupParameters::LastSavedParameters.assign(this);
|
||||
if (globalParams) CleanupParameters::GlobalParameters.assign(this);
|
||||
}
|
||||
|
|
38
toonz/sources/toonzlib/filepathproperties.cpp
Normal file
38
toonz/sources/toonzlib/filepathproperties.cpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#include "toonz/filepathproperties.h"
|
||||
|
||||
// TnzCore includes
|
||||
#include "tstream.h"
|
||||
|
||||
FilePathProperties::FilePathProperties()
|
||||
: m_useStandard(true)
|
||||
, m_acceptNonAlphabetSuffix(false)
|
||||
, m_letterCountForSuffix(1) {}
|
||||
|
||||
bool FilePathProperties::isDefault() {
|
||||
return (m_useStandard == true && m_acceptNonAlphabetSuffix == false &&
|
||||
m_letterCountForSuffix == 1);
|
||||
}
|
||||
|
||||
void FilePathProperties::saveData(TOStream& os) const {
|
||||
os.child("useStandard") << ((m_useStandard) ? 1 : 0);
|
||||
os.child("acceptNonAlphabetSuffix") << ((m_acceptNonAlphabetSuffix) ? 1 : 0);
|
||||
os.child("letterCountForSuffix") << m_letterCountForSuffix;
|
||||
}
|
||||
|
||||
// make sure to let TFilePath to know the new properties!
|
||||
void FilePathProperties::loadData(TIStream& is) {
|
||||
int val;
|
||||
std::string tagName;
|
||||
while (is.matchTag(tagName)) {
|
||||
if (tagName == "useStandard") {
|
||||
is >> val;
|
||||
m_useStandard = (val == 1);
|
||||
} else if (tagName == "acceptNonAlphabetSuffix") {
|
||||
is >> val;
|
||||
m_acceptNonAlphabetSuffix = (val == 1);
|
||||
} else if (tagName == "letterCountForSuffix") {
|
||||
is >> m_letterCountForSuffix;
|
||||
}
|
||||
is.closeChild();
|
||||
}
|
||||
}
|
|
@ -129,6 +129,9 @@ inline void setFxParamToCurrentScene(TFx *fx, TXsheet *xsh) {
|
|||
void initializeFx(TXsheet *xsh, TFx *fx) {
|
||||
if (TZeraryColumnFx *zcfx = dynamic_cast<TZeraryColumnFx *>(fx))
|
||||
fx = zcfx->getZeraryFx();
|
||||
// if the fx has not unique name then let assignUniqueId() set the default
|
||||
// name
|
||||
if (fx->getName() != L"" && fx->getName() == fx->getFxId()) fx->setName(L"");
|
||||
|
||||
xsh->getFxDag()->assignUniqueId(fx);
|
||||
setFxParamToCurrentScene(fx, xsh);
|
||||
|
|
|
@ -335,6 +335,9 @@ TopToBottomOrientation::TopToBottomOrientation() {
|
|||
addRect(PredefinedRect::KEYFRAME_AREA,
|
||||
QRect(CELL_WIDTH - KEY_ICON_WIDTH, 0, KEY_ICON_WIDTH, CELL_HEIGHT));
|
||||
addRect(PredefinedRect::DRAG_AREA, QRect(0, 0, CELL_DRAG_WIDTH, CELL_HEIGHT));
|
||||
int markSize = CELL_HEIGHT * 8 / 10; // 80% size
|
||||
addRect(PredefinedRect::CELL_MARK_AREA,
|
||||
QRect(CELL_DRAG_WIDTH - 3, 2, markSize, markSize));
|
||||
QRect soundRect(CELL_DRAG_WIDTH, 0,
|
||||
CELL_WIDTH - CELL_DRAG_WIDTH - SOUND_PREVIEW_WIDTH,
|
||||
CELL_HEIGHT);
|
||||
|
@ -1111,6 +1114,9 @@ LeftToRightOrientation::LeftToRightOrientation() {
|
|||
EXTENDER_HEIGHT));
|
||||
addRect(PredefinedRect::KEYFRAME_AREA, keyRect);
|
||||
addRect(PredefinedRect::DRAG_AREA, QRect(0, 0, CELL_WIDTH, CELL_DRAG_HEIGHT));
|
||||
int markSize = CELL_HEIGHT / 2; // 50% size (12px)
|
||||
addRect(PredefinedRect::CELL_MARK_AREA,
|
||||
QRect(1, CELL_DRAG_HEIGHT + 1, markSize, markSize));
|
||||
QRect soundRect(0, CELL_DRAG_HEIGHT, CELL_WIDTH,
|
||||
CELL_HEIGHT - CELL_DRAG_HEIGHT - SOUND_PREVIEW_HEIGHT);
|
||||
addRect(PredefinedRect::SOUND_TRACK, soundRect);
|
||||
|
|
|
@ -94,7 +94,7 @@ inline bool formatLess(const Preferences::LevelFormat &a,
|
|||
//=================================================================
|
||||
|
||||
void getDefaultLevelFormats(LevelFormatVector &lfv) {
|
||||
lfv.resize(3);
|
||||
lfv.resize(2);
|
||||
{
|
||||
LevelFormat &lf = lfv[0];
|
||||
|
||||
|
@ -215,6 +215,13 @@ void getValue(QSettings &settings,
|
|||
++it;
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
// remove the "empty" condition which may inserted due to the previous bug
|
||||
else if ((*it).m_name.isEmpty() &&
|
||||
(*it).m_pathFormat == QRegExp(".*", Qt::CaseInsensitive) &&
|
||||
(*it).m_priority == 1 && (*it).m_options == LevelOptions()) {
|
||||
it = lfv.erase(it);
|
||||
changed = true;
|
||||
} else
|
||||
++it;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,23 @@
|
|||
#include "tproperty.h"
|
||||
#include "tiio.h"
|
||||
|
||||
namespace {
|
||||
const TSceneProperties::CellMark cellMarkDefault[12] = {
|
||||
{QObject::tr("Red"), TPixel32(167, 55, 55)},
|
||||
{QObject::tr("Orange"), TPixel32(195, 115, 40)},
|
||||
{QObject::tr("Yellow"), TPixel32(214, 183, 22)},
|
||||
{QObject::tr("Light Green"), TPixel32(165, 179, 57)},
|
||||
{QObject::tr("Green"), TPixel32(82, 157, 79)},
|
||||
{QObject::tr("Light Blue"), TPixel32(71, 142, 165)},
|
||||
{QObject::tr("Blue"), TPixel32(64, 103, 172)},
|
||||
{QObject::tr("Dark Blue"), TPixel32(60, 49, 187)},
|
||||
{QObject::tr("Purple"), TPixel32(108, 66, 170)},
|
||||
{QObject::tr("Pink"), TPixel32(161, 75, 140)},
|
||||
{QObject::tr("Dark Pink"), TPixel32(111, 29, 108)},
|
||||
{QObject::tr("White"), TPixel32(255, 255, 255)}};
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
TSceneProperties::TSceneProperties()
|
||||
|
@ -47,6 +64,9 @@ TSceneProperties::TSceneProperties()
|
|||
m_notesColor.push_back(TPixel32(145, 240, 145));
|
||||
m_notesColor.push_back(TPixel32(130, 255, 210));
|
||||
m_notesColor.push_back(TPixel32(150, 245, 255));
|
||||
|
||||
// Default Cell Marks
|
||||
for (int i = 0; i < 12; i++) m_cellMarks.push_back(cellMarkDefault[i]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -77,7 +97,7 @@ void TSceneProperties::assign(const TSceneProperties *sprop) {
|
|||
|
||||
if (sprop != this) {
|
||||
m_cameras = sprop->m_cameras;
|
||||
for (int i = 0; i < (int)m_cameras.size(); i++)
|
||||
for (int i = 0; i < (int)m_cameras.size(); i++)
|
||||
m_cameras[i] = new TCamera(*m_cameras[i]);
|
||||
}
|
||||
m_bgColor = sprop->m_bgColor;
|
||||
|
@ -142,7 +162,7 @@ void TSceneProperties::setFieldGuideSize(int size) {
|
|||
|
||||
void TSceneProperties::setFieldGuideAspectRatio(double ar) {
|
||||
assert(ar >= 0);
|
||||
if (ar <= 0) ar = 1;
|
||||
if (ar <= 0) ar = 1;
|
||||
m_fieldGuideAspectRatio = ar;
|
||||
}
|
||||
|
||||
|
@ -196,8 +216,8 @@ void TSceneProperties::saveData(TOStream &os) const {
|
|||
os.child("threadsIndex") << out.getThreadIndex();
|
||||
os.child("maxTileSizeIndex") << out.getMaxTileSizeIndex();
|
||||
os.child("subcameraPrev") << (out.isSubcameraPreview() ? 1 : 0);
|
||||
os.child("stereoscopic") << (rs.m_stereoscopic ? 1 : 0)
|
||||
<< rs.m_stereoscopicShift;
|
||||
os.child("stereoscopic")
|
||||
<< (rs.m_stereoscopic ? 1 : 0) << rs.m_stereoscopicShift;
|
||||
|
||||
switch (rs.m_quality) {
|
||||
case TRenderSettings::StandardResampleQuality:
|
||||
|
@ -313,6 +333,12 @@ void TSceneProperties::saveData(TOStream &os) const {
|
|||
os.openChild("noteColors");
|
||||
for (i = 0; i < m_notesColor.size(); i++) os << m_notesColor.at(i);
|
||||
os.closeChild();
|
||||
|
||||
if (!hasDefaultCellMarks()) {
|
||||
os.openChild("cellMarks");
|
||||
for (auto mark : m_cellMarks) os << mark.name.toStdString() << mark.color;
|
||||
os.closeChild();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -413,7 +439,7 @@ void TSceneProperties::loadData(TIStream &is, bool isLoadingProject) {
|
|||
if (name == "preview")
|
||||
outPtr = m_previewProp;
|
||||
else if (name == "main")
|
||||
outPtr = m_outputProp;
|
||||
outPtr = m_outputProp;
|
||||
TOutputProperties &out = *outPtr;
|
||||
TRenderSettings renderSettings;
|
||||
if (globFrom != -1)
|
||||
|
@ -697,6 +723,15 @@ void TSceneProperties::loadData(TIStream &is, bool isLoadingProject) {
|
|||
assert(i == 7);
|
||||
} else if (tagName == "cameraCaputureSaveInPath") {
|
||||
is >> m_camCapSaveInPath;
|
||||
} else if (tagName == "cellMarks") {
|
||||
int i = 0;
|
||||
while (!is.eos()) {
|
||||
TPixel32 color;
|
||||
std::string name;
|
||||
is >> name >> color;
|
||||
m_cellMarks.replace(i, {QString::fromStdString(name), color});
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
throw TException("unexpected property tag: " + tagName);
|
||||
}
|
||||
|
@ -770,3 +805,34 @@ TPixel32 TSceneProperties::getNoteColor(int colorIndex) const {
|
|||
void TSceneProperties::setNoteColor(TPixel32 color, int colorIndex) {
|
||||
m_notesColor[colorIndex] = color;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
QList<TSceneProperties::CellMark> TSceneProperties::getCellMarks() const {
|
||||
return m_cellMarks;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
TSceneProperties::CellMark TSceneProperties::getCellMark(int index) const {
|
||||
return m_cellMarks[index];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void TSceneProperties::setCellMark(const TSceneProperties::CellMark &mark,
|
||||
int index) {
|
||||
m_cellMarks[index] = mark;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// check if the cell mark settings are modified
|
||||
bool TSceneProperties::hasDefaultCellMarks() const {
|
||||
if (m_cellMarks.size() != 12) return false;
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (m_cellMarks.at(i).name != cellMarkDefault[i].name ||
|
||||
m_cellMarks.at(i).color != cellMarkDefault[i].color)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -206,10 +206,10 @@ QScriptValue Scene::getCell(int row, int col) {
|
|||
if (sl) {
|
||||
QScriptValue level = create(engine(), new Level(sl));
|
||||
QScriptValue fid;
|
||||
if (cell.m_frameId.getLetter() == 0)
|
||||
if (cell.m_frameId.getLetter().isEmpty())
|
||||
fid = cell.m_frameId.getNumber();
|
||||
else
|
||||
fid = QString::fromStdString(cell.m_frameId.expand());
|
||||
fid = QString::fromStdString(cell.m_frameId.expand());
|
||||
QScriptValue result = engine()->newObject();
|
||||
result.setProperty("level", level);
|
||||
result.setProperty("fid", fid);
|
||||
|
|
|
@ -160,7 +160,7 @@ HSVColor HSVColor::fromRGB(double r, double g, double b) {
|
|||
h = 2.0 + (b - r) / delta;
|
||||
else if (b == max)
|
||||
h = 4.0 + (r - g) / delta;
|
||||
h = h * 60.0;
|
||||
h = h * 60.0;
|
||||
if (h < 0) h += 360.0;
|
||||
}
|
||||
|
||||
|
@ -569,7 +569,7 @@ TRasterP TCleanupper::processColors(const TRasterP &rin) {
|
|||
CleanupPreprocessedImage *TCleanupper::process(
|
||||
TRasterImageP &image, bool first_image, TRasterImageP &onlyResampledImage,
|
||||
bool isCameraTest, bool returnResampled, bool onlyForSwatch,
|
||||
TAffine *resampleAff) {
|
||||
TAffine *resampleAff, TRasterP templateForResampled) {
|
||||
TAffine aff;
|
||||
double blur;
|
||||
TDimension outDim(0, 0);
|
||||
|
@ -682,7 +682,9 @@ CleanupPreprocessedImage *TCleanupper::process(
|
|||
TRasterP tmp_ras;
|
||||
|
||||
if (returnResampled || (fromGr8 && toGr8)) {
|
||||
if (fromGr8 && toGr8)
|
||||
if (templateForResampled)
|
||||
tmp_ras = templateForResampled->create(outDim.lx, outDim.ly);
|
||||
else if (fromGr8 && toGr8)
|
||||
tmp_ras = TRasterGR8P(outDim);
|
||||
else
|
||||
tmp_ras = TRaster32P(outDim);
|
||||
|
@ -709,7 +711,7 @@ CleanupPreprocessedImage *TCleanupper::process(
|
|||
flt_type = TRop::Hann2;
|
||||
TRop::resample(tmp_ras, image->getRaster(), aff, flt_type, blur);
|
||||
|
||||
if ((TRaster32P)tmp_ras)
|
||||
if ((TRaster32P)tmp_ras && !templateForResampled)
|
||||
// Add white background to deal with semitransparent pixels
|
||||
TRop::addBackground(tmp_ras, TPixel32::White);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "toonz/toonzfolders.h"
|
||||
#include "toonz/cleanupparameters.h"
|
||||
#include "toonz/preferences.h"
|
||||
#include "toonz/filepathproperties.h"
|
||||
|
||||
// TnzBase includes
|
||||
#include "tenv.h"
|
||||
|
@ -17,6 +18,7 @@
|
|||
// TnzCore includes
|
||||
#include "tsystem.h"
|
||||
#include "tstream.h"
|
||||
#include "tfilepath.h"
|
||||
#include "tfilepath_io.h"
|
||||
#include "tconvert.h"
|
||||
|
||||
|
@ -321,11 +323,18 @@ TFilePath getDesktopPath() {
|
|||
\see TProjectManager and TOStream.
|
||||
*/
|
||||
|
||||
TProject::TProject() : m_name(), m_path(), m_sprop(new TSceneProperties()) {}
|
||||
TProject::TProject()
|
||||
: m_name()
|
||||
, m_path()
|
||||
, m_sprop(new TSceneProperties())
|
||||
, m_fpProp(new FilePathProperties()) {}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
TProject::~TProject() { delete m_sprop; }
|
||||
TProject::~TProject() {
|
||||
delete m_sprop;
|
||||
delete m_fpProp;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
/*! Associates the \b name to the specified \b path.
|
||||
|
@ -615,6 +624,13 @@ bool TProject::save(const TFilePath &projectPath) {
|
|||
os.openChild("sceneProperties");
|
||||
getSceneProperties().saveData(os);
|
||||
os.closeChild();
|
||||
|
||||
if (!getFilePathProperties()->isDefault()) {
|
||||
os.openChild("filePathProperties");
|
||||
getFilePathProperties()->saveData(os);
|
||||
os.closeChild();
|
||||
}
|
||||
|
||||
os.closeChild();
|
||||
|
||||
// crea (se necessario) le directory relative ai vari folder
|
||||
|
@ -725,6 +741,9 @@ void TProject::load(const TFilePath &projectPath) {
|
|||
}
|
||||
setSceneProperties(sprop);
|
||||
is.matchEndTag();
|
||||
} else if (tagName == "filePathProperties") {
|
||||
m_fpProp->loadData(is);
|
||||
is.matchEndTag();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1038,6 +1057,12 @@ TProjectP TProjectManager::getCurrentProject() {
|
|||
assert(TProject::isAProjectPath(fp));
|
||||
currentProject = new TProject();
|
||||
currentProject->load(fp);
|
||||
|
||||
// update TFilePath condition on loading the current project
|
||||
FilePathProperties *fpProp = currentProject->getFilePathProperties();
|
||||
TFilePath::setFilePathProperties(fpProp->useStandard(),
|
||||
fpProp->acceptNonAlphabetSuffix(),
|
||||
fpProp->letterCountForSuffix());
|
||||
}
|
||||
return currentProject;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "toonz/txshleveltypes.h"
|
||||
|
||||
#include <QMap>
|
||||
#include "tstream.h"
|
||||
|
||||
namespace {
|
||||
QMap<int, QPair<QString, TPixel32>> filterColors;
|
||||
|
@ -144,12 +145,12 @@ void TXshCellColumn::getCells(int row, int rowCount, TXshCell cells[]) {
|
|||
}
|
||||
if (n + src > cellCount) n = cellCount - src;
|
||||
|
||||
TXshCell *dstCell = cells;
|
||||
TXshCell *endDstCell = dstCell + dst;
|
||||
TXshCell *dstCell = cells;
|
||||
TXshCell *endDstCell = dstCell + dst;
|
||||
while (dstCell < endDstCell) *dstCell++ = emptyCell;
|
||||
endDstCell += n;
|
||||
while (dstCell < endDstCell) *dstCell++ = m_cells[src++];
|
||||
endDstCell = cells + rowCount;
|
||||
endDstCell = cells + rowCount;
|
||||
while (dstCell < endDstCell) *dstCell++ = emptyCell;
|
||||
}
|
||||
|
||||
|
@ -243,7 +244,7 @@ bool TXshCellColumn::setCells(int row, int rowCount, const TXshCell cells[]) {
|
|||
if (row > c_rb) // sono oltre l'ultima riga
|
||||
{
|
||||
if (oldCellCount == 0) m_first = row; // row 'e la nuova firstrow
|
||||
int newCellCount = row - m_first + rowCount;
|
||||
int newCellCount = row - m_first + rowCount;
|
||||
m_cells.resize(newCellCount);
|
||||
} else if (row < m_first) {
|
||||
int delta = m_first - row;
|
||||
|
@ -278,8 +279,9 @@ bool TXshCellColumn::setCells(int row, int rowCount, const TXshCell cells[]) {
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
void TXshCellColumn::insertEmptyCells(int row, int rowCount) {
|
||||
if (m_cells.empty()) return; // se la colonna e' vuota non devo inserire
|
||||
// celle
|
||||
if (m_cells.empty())
|
||||
return; // se la colonna e' vuota non devo inserire
|
||||
// celle
|
||||
|
||||
if (row >= m_first + (int)m_cells.size()) return; // dopo:non inserisco nulla
|
||||
if (row <= m_first) // prima
|
||||
|
@ -426,6 +428,70 @@ bool TXshCellColumn::getLevelRange(int row, int &r0, int &r1) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void TXshCellColumn::saveCellMarks(TOStream &os) {
|
||||
if (m_cellMarkIds.isEmpty()) return;
|
||||
// gather frame numbers with the same id
|
||||
QMap<int, QString> idStrMap;
|
||||
QMap<int, int>::const_iterator i = m_cellMarkIds.constBegin();
|
||||
while (i != m_cellMarkIds.constEnd()) {
|
||||
if (!idStrMap.contains(i.value()))
|
||||
idStrMap.insert(i.value(), QString::number(i.key()));
|
||||
else
|
||||
idStrMap[i.value()] += " " + QString::number(i.key());
|
||||
++i;
|
||||
}
|
||||
os.openChild("cellMarks");
|
||||
QMap<int, QString>::const_iterator j = idStrMap.constBegin();
|
||||
while (j != idStrMap.constEnd()) {
|
||||
std::map<std::string, std::string> attr;
|
||||
attr["id"] = std::to_string(j.key());
|
||||
os.openChild("cellMark", attr);
|
||||
os << j.value();
|
||||
os.closeChild();
|
||||
++j;
|
||||
}
|
||||
os.closeChild();
|
||||
}
|
||||
|
||||
bool TXshCellColumn::loadCellMarks(std::string tagName, TIStream &is) {
|
||||
if (tagName != "cellMarks") return false;
|
||||
m_cellMarkIds.clear();
|
||||
while (is.openChild(tagName)) {
|
||||
if (tagName == "cellMark") {
|
||||
int id;
|
||||
QString frameStr;
|
||||
if (is.getTagParam("id", id)) {
|
||||
is >> frameStr;
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
QStringList frameStrList = frameStr.split(" ", Qt::SkipEmptyParts);
|
||||
#else
|
||||
QStringList frameStrList = frameStr.split(" ", QString::SkipEmptyParts);
|
||||
#endif
|
||||
for (auto fStr : frameStrList) m_cellMarkIds.insert(fStr.toInt(), id);
|
||||
}
|
||||
}
|
||||
is.closeChild();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TXshCellColumn::setCellMark(int frame, int id) {
|
||||
if (id < 0)
|
||||
m_cellMarkIds.remove(frame);
|
||||
else
|
||||
m_cellMarkIds.insert(frame, id);
|
||||
}
|
||||
|
||||
int TXshCellColumn::getCellMark(int frame) const {
|
||||
return m_cellMarkIds.value(frame, -1);
|
||||
}
|
||||
|
||||
QMap<int, int> TXshCellColumn::getCellMarks() const { return m_cellMarkIds; }
|
||||
|
||||
void TXshCellColumn::clearCellMarks() { m_cellMarkIds.clear(); }
|
||||
|
||||
//=============================================================================
|
||||
// TXshColumn
|
||||
|
||||
|
|
|
@ -1061,8 +1061,8 @@ int TXsheet::exposeLevel(int row, int col, TXshLevel *xl, bool overwrite) {
|
|||
//-----------------------------------------------------------------------------
|
||||
// customized version for load level popup
|
||||
int TXsheet::exposeLevel(int row, int col, TXshLevel *xl,
|
||||
std::vector<TFrameId> &fIds_, int xFrom, int xTo,
|
||||
int step, int inc, int frameCount,
|
||||
std::vector<TFrameId> &fIds_, TFrameId xFrom,
|
||||
TFrameId xTo, int step, int inc, int frameCount,
|
||||
bool doesFileActuallyExist) {
|
||||
if (!xl) return 0;
|
||||
std::vector<TFrameId> fids;
|
||||
|
@ -1104,7 +1104,7 @@ int TXsheet::exposeLevel(int row, int col, TXshLevel *xl,
|
|||
{
|
||||
std::vector<TFrameId>::iterator it;
|
||||
it = fids.begin();
|
||||
while (it->getNumber() < xFrom) it++;
|
||||
while (*it < xFrom) it++;
|
||||
|
||||
if (step == 0) // Step = Auto
|
||||
{
|
||||
|
@ -1112,14 +1112,12 @@ int TXsheet::exposeLevel(int row, int col, TXshLevel *xl,
|
|||
next_it = it;
|
||||
next_it++;
|
||||
|
||||
int startFrame = it->getNumber();
|
||||
|
||||
for (int f = startFrame; f < startFrame + frameCount; f++) {
|
||||
if (next_it != fids.end() && f >= next_it->getNumber()) {
|
||||
for (int f = 0; f < frameCount; f++) {
|
||||
setCell(row++, col, TXshCell(xl, *it));
|
||||
if (next_it != fids.end()) {
|
||||
it++;
|
||||
next_it++;
|
||||
}
|
||||
setCell(row++, col, TXshCell(xl, *it));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1143,7 +1141,7 @@ int TXsheet::exposeLevel(int row, int col, TXshLevel *xl,
|
|||
loopCount = frameCount / step;
|
||||
|
||||
for (int loop = 0; loop < loopCount; loop++) {
|
||||
TFrameId id(xFrom + loop * inc, fids.begin()->getLetter());
|
||||
TFrameId id(xFrom.getNumber() + loop * inc, xFrom.getLetter());
|
||||
for (int s = 0; s < step; s++) {
|
||||
setCell(row++, col, TXshCell(xl, id));
|
||||
}
|
||||
|
@ -1224,6 +1222,12 @@ void TXsheet::loadData(TIStream &is) {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (tagName == "cameraColumn") {
|
||||
while (is.openChild(tagName)) {
|
||||
if (!m_cameraColumn->getCellColumn()->loadCellMarks(tagName, is))
|
||||
throw TException("Camera Column, unknown tag: " + tagName);
|
||||
is.closeChild();
|
||||
}
|
||||
} else if (tagName == "pegbars") {
|
||||
TPersist *p = m_imp->m_pegTree;
|
||||
m_imp->m_pegTree->loadData(is, this);
|
||||
|
@ -1280,6 +1284,14 @@ void TXsheet::saveData(TOStream &os) {
|
|||
if (column && c < getFirstFreeColumnIndex()) os << column.getPointer();
|
||||
}
|
||||
os.closeChild();
|
||||
|
||||
// save cell marks in the camera column
|
||||
if (!m_cameraColumn->getCellColumn()->getCellMarks().isEmpty()) {
|
||||
os.openChild("cameraColumn");
|
||||
m_cameraColumn->getCellColumn()->saveCellMarks(os);
|
||||
os.closeChild();
|
||||
}
|
||||
|
||||
os.openChild("pegbars");
|
||||
m_imp->m_pegTree->saveData(os, getFirstFreeColumnIndex(), this);
|
||||
// os << *(m_imp->m_pegTree);
|
||||
|
|
|
@ -17,24 +17,17 @@ TFrameId qstringToFrameId(QString str) {
|
|||
return TFrameId::EMPTY_FRAME;
|
||||
else if (str == "-" || str == "-2")
|
||||
return TFrameId::NO_FRAME;
|
||||
TFrameId fid;
|
||||
int s = 0;
|
||||
QString number;
|
||||
char letter(0);
|
||||
for (s = 0; s < str.size(); s++) {
|
||||
QChar c = str.at(s);
|
||||
if (c.isNumber()) number.append(c);
|
||||
#if QT_VERSION >= 0x050500
|
||||
else
|
||||
letter = c.toLatin1();
|
||||
#else
|
||||
else
|
||||
letter = c.toAscii();
|
||||
#endif
|
||||
}
|
||||
return TFrameId(number.toInt(), letter);
|
||||
}
|
||||
|
||||
QString regExpStr = QString("^%1$").arg(TFilePath::fidRegExpStr());
|
||||
QRegExp rx(regExpStr);
|
||||
int pos = rx.indexIn(str);
|
||||
if (pos < 0) return TFrameId();
|
||||
if (rx.cap(2).isEmpty())
|
||||
return TFrameId(rx.cap(1).toInt());
|
||||
else
|
||||
return TFrameId(rx.cap(1).toInt(), rx.cap(2));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
@ -123,13 +116,13 @@ void TXshLevelColumn::loadData(TIStream &is) {
|
|||
while (is.openChild(tagName)) {
|
||||
if (tagName == "cell") {
|
||||
TPersist *p = 0;
|
||||
QString str;
|
||||
std::string str;
|
||||
int row = 1, rowCount = 1, increment = 0;
|
||||
TFilePath path;
|
||||
is >> row >> rowCount >> p >> str >> increment;
|
||||
TFrameId fid = qstringToFrameId(str);
|
||||
assert((fid.getLetter() == 0 && rowCount >= 0) ||
|
||||
(fid.getLetter() != 0 && rowCount == 1));
|
||||
TFrameId fid = qstringToFrameId(QString::fromStdString(str));
|
||||
assert((fid.getLetter().isEmpty() && rowCount >= 0) ||
|
||||
(!fid.getLetter().isEmpty() && rowCount == 1));
|
||||
TXshLevel *xshLevel = dynamic_cast<TXshLevel *>(p);
|
||||
if (xshLevel) {
|
||||
int fidNumber = fid.getNumber();
|
||||
|
@ -158,9 +151,10 @@ void TXshLevelColumn::loadData(TIStream &is) {
|
|||
{
|
||||
TFxSet fxSet;
|
||||
fxSet.loadData(is);
|
||||
} else {
|
||||
} else if (loadCellMarks(tagName, is)) {
|
||||
// do nothing
|
||||
} else
|
||||
throw TException("TXshLevelColumn, unknown tag: " + tagName);
|
||||
}
|
||||
is.closeChild();
|
||||
}
|
||||
}
|
||||
|
@ -182,11 +176,11 @@ void TXshLevelColumn::saveData(TOStream &os) {
|
|||
int n = 1, inc = 0, dr = fid.getNumber();
|
||||
// If fid has not letter save more than one cell and its incrementation;
|
||||
// otherwise save one cell.
|
||||
if (r < r1 && fid.getLetter() == 0) {
|
||||
if (r < r1 && fid.getLetter().isEmpty()) {
|
||||
TXshCell cell2 = getCell(r + 1);
|
||||
TFrameId fid2 = cell2.m_frameId;
|
||||
if (cell2.m_level.getPointer() == cell.m_level.getPointer() &&
|
||||
fid2.getLetter() == 0) {
|
||||
fid2.getLetter().isEmpty()) {
|
||||
inc = cell2.m_frameId.getNumber() - dr;
|
||||
n++;
|
||||
for (;;) {
|
||||
|
@ -194,7 +188,7 @@ void TXshLevelColumn::saveData(TOStream &os) {
|
|||
cell2 = getCell(r + n);
|
||||
TFrameId fid2 = cell2.m_frameId;
|
||||
if (cell2.m_level.getPointer() != cell.m_level.getPointer() ||
|
||||
fid2.getLetter() != 0)
|
||||
!fid2.getLetter().isEmpty())
|
||||
break;
|
||||
if (fid2.getNumber() != dr + n * inc) break;
|
||||
n++;
|
||||
|
@ -208,6 +202,9 @@ void TXshLevelColumn::saveData(TOStream &os) {
|
|||
os.closeChild();
|
||||
}
|
||||
os.child("fx") << m_fx;
|
||||
|
||||
// cell marks
|
||||
saveCellMarks(os);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -24,28 +24,16 @@ TFrameId qstringToFrameId(QString str) {
|
|||
else if (str == "-" || str == "-2")
|
||||
return TFrameId::NO_FRAME;
|
||||
|
||||
TFrameId fid;
|
||||
|
||||
QString number;
|
||||
char letter(0);
|
||||
|
||||
int s, strSize = str.size();
|
||||
for (s = 0; s < strSize; ++s) {
|
||||
QChar c = str.at(s);
|
||||
|
||||
if (c.isNumber())
|
||||
number.append(c);
|
||||
else
|
||||
#if QT_VERSION >= 0x050500
|
||||
letter = c.toLatin1();
|
||||
#else
|
||||
letter = c.toAscii();
|
||||
#endif
|
||||
}
|
||||
|
||||
return TFrameId(number.toInt(), letter);
|
||||
}
|
||||
QString regExpStr = QString("^%1$").arg(TFilePath::fidRegExpStr());
|
||||
QRegExp rx(regExpStr);
|
||||
int pos = rx.indexIn(str);
|
||||
if (pos < 0) return TFrameId();
|
||||
if (rx.cap(2).isEmpty())
|
||||
return TFrameId(rx.cap(1).toInt());
|
||||
else
|
||||
return TFrameId(rx.cap(1).toInt(), rx.cap(2));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//*******************************************************************************
|
||||
// TXshMeshColumn implementation
|
||||
|
@ -94,12 +82,12 @@ void TXshMeshColumn::saveData(TOStream &os) {
|
|||
|
||||
// If fid has no letter save more than one cell and its increment -
|
||||
// otherwise save just one cell
|
||||
if (r < r1 && fid.getLetter() == 0) {
|
||||
if (r < r1 && fid.getLetter().isEmpty()) {
|
||||
TXshCell cell2 = getCell(r + 1);
|
||||
TFrameId fid2 = cell2.m_frameId;
|
||||
|
||||
if (cell2.m_level.getPointer() == cell.m_level.getPointer() &&
|
||||
fid2.getLetter() == 0) {
|
||||
fid2.getLetter().isEmpty()) {
|
||||
inc = cell2.m_frameId.getNumber() - dr;
|
||||
for (++n;; ++n) {
|
||||
if (r + n > r1) break;
|
||||
|
@ -108,7 +96,7 @@ void TXshMeshColumn::saveData(TOStream &os) {
|
|||
TFrameId fid2 = cell2.m_frameId;
|
||||
|
||||
if (cell2.m_level.getPointer() != cell.m_level.getPointer() ||
|
||||
fid2.getLetter() != 0)
|
||||
!fid2.getLetter().isEmpty())
|
||||
break;
|
||||
|
||||
if (fid2.getNumber() != dr + n * inc) break;
|
||||
|
@ -123,6 +111,8 @@ void TXshMeshColumn::saveData(TOStream &os) {
|
|||
}
|
||||
os.closeChild();
|
||||
}
|
||||
// cell marks
|
||||
saveCellMarks(os);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -150,16 +140,16 @@ void TXshMeshColumn::loadData(TIStream &is) {
|
|||
while (is.openChild(tagName)) {
|
||||
if (tagName == "cell") {
|
||||
TPersist *p = 0;
|
||||
QString str;
|
||||
std::string str;
|
||||
|
||||
int row = 1, rowCount = 1, increment = 0;
|
||||
TFilePath path;
|
||||
|
||||
is >> row >> rowCount >> p >> str >> increment;
|
||||
|
||||
TFrameId fid = qstringToFrameId(str);
|
||||
assert((fid.getLetter() == 0 && rowCount >= 0) ||
|
||||
(fid.getLetter() != 0 && rowCount == 1));
|
||||
TFrameId fid = qstringToFrameId(QString::fromStdString(str));
|
||||
assert((fid.getLetter().isEmpty() && rowCount >= 0) ||
|
||||
(!fid.getLetter().isEmpty() && rowCount == 1));
|
||||
|
||||
TXshLevel *xshLevel = dynamic_cast<TXshLevel *>(p);
|
||||
if (xshLevel) {
|
||||
|
@ -179,6 +169,8 @@ void TXshMeshColumn::loadData(TIStream &is) {
|
|||
is.skipCurrentTag();
|
||||
}
|
||||
|
||||
is.closeChild();
|
||||
} else if (loadCellMarks(tagName, is)) {
|
||||
is.closeChild();
|
||||
} else
|
||||
is.skipCurrentTag();
|
||||
|
|
|
@ -73,6 +73,8 @@ void TXshPaletteColumn::loadData(TIStream &is) {
|
|||
TPersist *p = 0;
|
||||
is >> p;
|
||||
if (TFx *fx = dynamic_cast<TFx *>(p)) setFx(fx);
|
||||
} else if (loadCellMarks(tagName, is)) {
|
||||
// do nothing
|
||||
} else {
|
||||
throw TException("TXshLevelColumn, unknown tag: " + tagName);
|
||||
}
|
||||
|
@ -107,6 +109,9 @@ void TXshPaletteColumn::saveData(TOStream &os) {
|
|||
os.closeChild();
|
||||
}
|
||||
os.child("fx") << m_fx;
|
||||
|
||||
// cell marks
|
||||
saveCellMarks(os);
|
||||
}
|
||||
|
||||
PERSIST_IDENTIFIER(TXshPaletteColumn, "paletteColumn")
|
||||
|
|
|
@ -485,7 +485,8 @@ int TXshSimpleLevel::guessStep() const {
|
|||
|
||||
TFrameId firstFid = *ft++, secondFid = *ft++;
|
||||
|
||||
if (firstFid.getLetter() != 0 || secondFid.getLetter() != 0) return 1;
|
||||
if (!firstFid.getLetter().isEmpty() || !secondFid.getLetter().isEmpty())
|
||||
return 1;
|
||||
|
||||
int step = secondFid.getNumber() - firstFid.getNumber();
|
||||
if (step == 1) return 1;
|
||||
|
@ -494,7 +495,7 @@ int TXshSimpleLevel::guessStep() const {
|
|||
// (cerco di limitare il numero di volte in cui devo controllare tutta la
|
||||
// lista)
|
||||
TFrameId lastFid = *m_frames.rbegin();
|
||||
if (lastFid.getLetter() != 0) return 1;
|
||||
if (!lastFid.getLetter().isEmpty()) return 1;
|
||||
|
||||
if (lastFid.getNumber() != firstFid.getNumber() + step * (frameCount - 1))
|
||||
return 1;
|
||||
|
@ -502,7 +503,7 @@ int TXshSimpleLevel::guessStep() const {
|
|||
for (int i = 2; ft != m_frames.end(); ++ft, ++i) {
|
||||
const TFrameId &fid = *ft;
|
||||
|
||||
if (fid.getLetter() != 0) return 1;
|
||||
if (!fid.getLetter().isEmpty()) return 1;
|
||||
|
||||
if (fid.getNumber() != firstFid.getNumber() + step * i) return 1;
|
||||
}
|
||||
|
@ -642,7 +643,8 @@ void TXshSimpleLevel::loadAllIconsAndPutInCache(bool cacheImagesAsWell) {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
TRasterImageP TXshSimpleLevel::getFrameToCleanup(const TFrameId &fid) const {
|
||||
TRasterImageP TXshSimpleLevel::getFrameToCleanup(const TFrameId &fid,
|
||||
bool toBeLineProcessed) const {
|
||||
assert(m_type != UNKNOWN_XSHLEVEL);
|
||||
|
||||
FramesSet::const_iterator ft = m_frames.find(fid);
|
||||
|
@ -652,8 +654,12 @@ TRasterImageP TXshSimpleLevel::getFrameToCleanup(const TFrameId &fid) const {
|
|||
std::string imageId = getImageId(fid, flag ? Scanned : 0);
|
||||
|
||||
ImageLoader::BuildExtData extData(this, fid, 1);
|
||||
TRasterImageP img = ImageManager::instance()->getImage(
|
||||
imageId, ImageManager::dontPutInCache, &extData);
|
||||
|
||||
UCHAR imFlags = ImageManager::dontPutInCache;
|
||||
// if lines are not processed, obtain the original sampled image
|
||||
if (!toBeLineProcessed) imFlags |= ImageManager::is64bitEnabled;
|
||||
TRasterImageP img =
|
||||
ImageManager::instance()->getImage(imageId, imFlags, &extData);
|
||||
if (!img) return img;
|
||||
|
||||
double x_dpi, y_dpi;
|
||||
|
|
|
@ -262,6 +262,13 @@ void TXshSoundColumn::loadData(TIStream &is) {
|
|||
is >> status;
|
||||
setStatusWord(status);
|
||||
}
|
||||
|
||||
std::string tagName;
|
||||
while (is.openChild(tagName)) {
|
||||
if (!loadCellMarks(tagName, is))
|
||||
throw TException("TXshLevelColumn, unknown tag: " + tagName);
|
||||
is.closeChild();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -274,6 +281,8 @@ void TXshSoundColumn::saveData(TOStream &os) {
|
|||
int i;
|
||||
for (i = 0; i < levelsCount; i++) m_levels.at(i)->saveData(os);
|
||||
os << getStatusWord();
|
||||
// cell marks
|
||||
saveCellMarks(os);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -68,18 +68,28 @@ void TXshSoundTextColumn::loadData(TIStream &is) {
|
|||
if (tagName == "cells") {
|
||||
while (is.openChild(tagName)) {
|
||||
if (tagName == "cell") {
|
||||
TPersist *p = 0;
|
||||
int row = 1;
|
||||
int fidNumber = 1;
|
||||
TPersist *p = 0;
|
||||
std::string rowRangeStr = "1";
|
||||
int fidNumber = 1;
|
||||
TFilePath path;
|
||||
is >> row >> fidNumber >> p;
|
||||
is >> rowRangeStr >> fidNumber >> p;
|
||||
TXshLevel *xshLevel = dynamic_cast<TXshLevel *>(p);
|
||||
TXshCell cell(xshLevel, TFrameId(fidNumber));
|
||||
setCell(row, cell);
|
||||
|
||||
QString _rowRangeStr = QString::fromStdString(rowRangeStr);
|
||||
QStringList rows = _rowRangeStr.split('-');
|
||||
if (rows.size() == 1)
|
||||
setCell(rows[0].toInt(), cell);
|
||||
else if (rows.size() == 2) {
|
||||
for (int r = rows[0].toInt(); r <= rows[1].toInt(); r++)
|
||||
setCell(r, cell);
|
||||
}
|
||||
} else
|
||||
throw TException("TXshLevelColumn, unknown tag(2): " + tagName);
|
||||
is.closeChild();
|
||||
}
|
||||
} else if (loadCellMarks(tagName, is)) {
|
||||
// do nothing
|
||||
} else
|
||||
throw TException("TXshLevelColumn, unknown tag: " + tagName);
|
||||
is.closeChild();
|
||||
|
@ -92,14 +102,47 @@ void TXshSoundTextColumn::saveData(TOStream &os) {
|
|||
int r0, r1;
|
||||
if (getRange(r0, r1)) {
|
||||
os.openChild("cells");
|
||||
TXshCell prevCell;
|
||||
int fromR = r0;
|
||||
for (int r = r0; r <= r1; r++) {
|
||||
TXshCell cell = getCell(r);
|
||||
if (cell.isEmpty()) continue;
|
||||
TFrameId fid = cell.m_frameId;
|
||||
os.child("cell") << r << fid.getNumber() << cell.m_level.getPointer();
|
||||
|
||||
if (cell != prevCell) {
|
||||
if (!prevCell.isEmpty()) {
|
||||
int toR = r - 1;
|
||||
TFrameId fid = prevCell.m_frameId;
|
||||
if (fromR == toR)
|
||||
os.child("cell")
|
||||
<< toR << fid.getNumber() << prevCell.m_level.getPointer();
|
||||
else {
|
||||
QString rangeStr = QString("%1-%2").arg(fromR).arg(toR);
|
||||
os.child("cell") << rangeStr.toStdString() << fid.getNumber()
|
||||
<< prevCell.m_level.getPointer();
|
||||
}
|
||||
}
|
||||
prevCell = cell;
|
||||
fromR = r;
|
||||
}
|
||||
assert(cell == prevCell);
|
||||
if (r == r1) {
|
||||
if (!cell.isEmpty()) {
|
||||
int toR = r;
|
||||
TFrameId fid = cell.m_frameId;
|
||||
if (fromR == toR)
|
||||
os.child("cell")
|
||||
<< toR << fid.getNumber() << cell.m_level.getPointer();
|
||||
else {
|
||||
QString rangeStr = QString("%1-%2").arg(fromR).arg(toR);
|
||||
os.child("cell") << rangeStr.toStdString() << fid.getNumber()
|
||||
<< cell.m_level.getPointer();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
os.closeChild();
|
||||
}
|
||||
// cell marks
|
||||
saveCellMarks(os);
|
||||
}
|
||||
|
||||
PERSIST_IDENTIFIER(TXshSoundTextColumn, "soundTextColumn")
|
||||
|
|
|
@ -29,7 +29,8 @@ TXshZeraryFxColumn::TXshZeraryFxColumn(int frameCount)
|
|||
|
||||
TXshZeraryFxColumn::TXshZeraryFxColumn(const TXshZeraryFxColumn &src)
|
||||
: m_zeraryColumnFx(new TZeraryColumnFx())
|
||||
, m_zeraryFxLevel(new TXshZeraryFxLevel()) {
|
||||
, m_zeraryFxLevel(new TXshZeraryFxLevel())
|
||||
, m_iconVisible(false) {
|
||||
m_zeraryColumnFx->addRef();
|
||||
m_zeraryColumnFx->setColumn(this);
|
||||
m_zeraryFxLevel->addRef();
|
||||
|
@ -161,6 +162,8 @@ void TXshZeraryFxColumn::loadData(TIStream &is) {
|
|||
throw TException("expected <cell>");
|
||||
is.closeChild();
|
||||
}
|
||||
} else if (loadCellMarks(tagName, is)) {
|
||||
// do nothing
|
||||
} else
|
||||
throw TException("expected <status> or <cells>");
|
||||
is.closeChild();
|
||||
|
@ -185,6 +188,8 @@ void TXshZeraryFxColumn::saveData(TOStream &os) {
|
|||
}
|
||||
os.closeChild();
|
||||
}
|
||||
// cell marks
|
||||
saveCellMarks(os);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -129,7 +129,8 @@ void CommandManager::define(CommandId id, CommandType type,
|
|||
(node->m_enabled &&
|
||||
(node->m_handler || node->m_qaction->actionGroup() != 0)) ||
|
||||
node->m_type == MiscCommandType ||
|
||||
node->m_type == ToolModifierCommandType);
|
||||
node->m_type == ToolModifierCommandType ||
|
||||
node->m_type == CellMarkCommandType);
|
||||
|
||||
m_qactionTable[qaction] = node;
|
||||
qaction->setShortcutContext(Qt::ApplicationShortcut);
|
||||
|
@ -371,7 +372,7 @@ QAction *CommandManager::createAction(CommandId id, QObject *parent,
|
|||
if (!refAction) return 0;
|
||||
QString text = refAction->text();
|
||||
if (node->m_onText != "" && node->m_offText != "")
|
||||
text = state ? node->m_onText : node->m_offText;
|
||||
text = state ? node->m_onText : node->m_offText;
|
||||
QAction *action = new QAction(text, parent);
|
||||
action->setShortcut(refAction->shortcut());
|
||||
return action;
|
||||
|
@ -533,24 +534,24 @@ void DVMenuAction::setActions(QList<QString> actions) {
|
|||
|
||||
namespace {
|
||||
QString changeStringNumber(QString str, int index) {
|
||||
QString newStr = str;
|
||||
int n = 3;
|
||||
QString newStr = str;
|
||||
int n = 3;
|
||||
if (index >= 10) n = 4;
|
||||
QString number;
|
||||
newStr.replace(0, n, number.number(index + 1) + QString(". "));
|
||||
return newStr;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void DVMenuAction::onTriggered(QAction *action) {
|
||||
QVariant data = action->data();
|
||||
QVariant data = action->data();
|
||||
if (data.isValid()) m_triggeredActionIndex = data.toInt();
|
||||
CommandManager::instance()->execute(action, menuAction());
|
||||
int oldIndex = m_triggeredActionIndex;
|
||||
if (m_triggeredActionIndex != -1) m_triggeredActionIndex = -1;
|
||||
QString str = data.toString();
|
||||
QString str = data.toString();
|
||||
QAction *tableAction =
|
||||
CommandManager::instance()->getAction(str.toStdString().c_str());
|
||||
if (tableAction || oldIndex == 0) return;
|
||||
|
|
|
@ -990,10 +990,20 @@ std::vector<TStageObjectId> StageObjectsData::restoreObjects(
|
|||
dynamic_cast<TXshZeraryFxColumn *>(pastedColumn)) {
|
||||
TZeraryColumnFx *zfx = zc->getZeraryColumnFx();
|
||||
TFx *zeraryFx = zfx->getZeraryFx();
|
||||
if (zeraryFx && doClone) {
|
||||
std::wstring app = zeraryFx->getName();
|
||||
fxDag->assignUniqueId(zeraryFx);
|
||||
zeraryFx->setName(app);
|
||||
if (zeraryFx) {
|
||||
if (doClone) {
|
||||
// if the fx has not unique name then let assignUniqueId() set the
|
||||
// default name
|
||||
if (zeraryFx->getName() == zeraryFx->getFxId())
|
||||
zeraryFx->setName(L"");
|
||||
fxDag->assignUniqueId(zeraryFx);
|
||||
} else
|
||||
fxDag->updateFxIdTable(zeraryFx);
|
||||
if (TXshZeraryFxColumn *orig_zc =
|
||||
dynamic_cast<TXshZeraryFxColumn *>(column)) {
|
||||
if (TFx *origZeraryFx = orig_zc->getZeraryColumnFx()->getZeraryFx())
|
||||
fxTable[origZeraryFx] = zeraryFx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1038,8 +1048,9 @@ std::vector<TStageObjectId> StageObjectsData::restoreObjects(
|
|||
|
||||
if (doClone) {
|
||||
fx = fxOrig->clone(false);
|
||||
|
||||
fx->setName(fxOrig->getName());
|
||||
// if the fx has not unique name then let assignUniqueId() set the default
|
||||
// name
|
||||
if (fx->getName() == fx->getFxId()) fx->setName(L"");
|
||||
fx->getAttributes()->setId(fxOrig->getAttributes()->getId());
|
||||
fx->getAttributes()->passiveCacheDataIdx() = -1;
|
||||
|
||||
|
@ -1084,7 +1095,10 @@ std::vector<TStageObjectId> StageObjectsData::restoreObjects(
|
|||
linkedFx = fx->clone(false);
|
||||
linkedFx->linkParams(fx);
|
||||
|
||||
linkedFx->setName(oldLinkedFx->getName());
|
||||
// if the fx has not unique name then let assignUniqueId() set the
|
||||
// default name
|
||||
if (linkedFx->getName() == linkedFx->getFxId())
|
||||
linkedFx->setName(L"");
|
||||
linkedFx->getAttributes()->setId(
|
||||
oldLinkedFx->getAttributes()->getId());
|
||||
linkedFx->getAttributes()->passiveCacheDataIdx() = -1;
|
||||
|
|
|
@ -1020,8 +1020,8 @@ SplineAimChanger::~SplineAimChanger() {}
|
|||
|
||||
void SplineAimChanger::mouseMoveEvent(QGraphicsSceneMouseEvent *me) {
|
||||
if (m_buttonState == Qt::LeftButton) {
|
||||
bool increase = false;
|
||||
int delta = me->screenPos().y() - me->lastScreenPos().y();
|
||||
bool increase = false;
|
||||
int delta = me->screenPos().y() - me->lastScreenPos().y();
|
||||
if (delta < 0) increase = true;
|
||||
m_delta += abs(delta);
|
||||
if (m_delta > 15) {
|
||||
|
@ -2250,10 +2250,9 @@ StageSchematicGroupNode::StageSchematicGroupNode(
|
|||
, m_root(root)
|
||||
, m_groupedObj(groupedObj) {
|
||||
SchematicViewer *viewer = scene->getSchematicViewer();
|
||||
|
||||
int i;
|
||||
for (i = 0; i < m_groupedObj.size(); i++) m_groupedObj[i]->addRef();
|
||||
bool ret = true;
|
||||
for (i = 0; i < m_groupedObj.size(); i++) m_groupedObj[i]->addRef();
|
||||
bool ret = true;
|
||||
std::wstring name = m_stageObject->getGroupName(false);
|
||||
m_name = QString::fromStdWString(name);
|
||||
|
||||
|
|
Loading…
Reference in a new issue