849 lines
28 KiB
C++
849 lines
28 KiB
C++
|
||
|
||
// TnzFarm includes
|
||
#include "tfarmcontroller.h"
|
||
|
||
// TnzLib includes
|
||
#include "toonz/txshleveltypes.h"
|
||
#include "toonz/tpalettehandle.h"
|
||
#include "toonz/tscenehandle.h"
|
||
#include "toonz/txshlevelhandle.h"
|
||
#include "toonz/sceneproperties.h"
|
||
#include "toonz/levelproperties.h"
|
||
#include "toonz/levelupdater.h"
|
||
#include "toonz/preferences.h"
|
||
#include "toonz/toonzfolders.h"
|
||
#include "toonz/toonzscene.h"
|
||
#include "toonz/txshchildlevel.h"
|
||
#include "toonz/tproject.h"
|
||
#include "toonz/tcleanupper.h"
|
||
#include "toonz/txsheet.h"
|
||
#include "toonz/txshcell.h"
|
||
#include "toonz/txshcolumn.h"
|
||
#include "toonz/tlog.h"
|
||
#include "toonz/imagestyles.h"
|
||
|
||
// TnzBase includes
|
||
#include "tcli.h"
|
||
#include "tenv.h"
|
||
|
||
// TnzCore includes
|
||
#include "tsystem.h"
|
||
#include "tstream.h"
|
||
#include "tstopwatch.h"
|
||
#include "tthread.h"
|
||
#include "tthreadmessage.h"
|
||
#include "timagecache.h"
|
||
#include "tiio_std.h"
|
||
#include "tnzimage.h"
|
||
#include "tmsgcore.h"
|
||
#include "tpluginmanager.h"
|
||
#include "tpalette.h"
|
||
#include "tsimplecolorstyles.h"
|
||
|
||
// Qt includes
|
||
#include <QApplication>
|
||
|
||
using namespace TCli;
|
||
using namespace std;
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
inline ostream &operator<<(ostream &out, const wstring &w) {
|
||
return out << ::to_string(w);
|
||
}
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
inline ostream &operator<<(ostream &out, const TFilePath &fp) {
|
||
return out << fp.getWideString();
|
||
}
|
||
|
||
//------------------------------------------------------------------------
|
||
namespace {
|
||
|
||
const char *rootVarName = "TOONZROOT";
|
||
const char *systemVarPrefix = "TOONZ";
|
||
|
||
namespace {
|
||
|
||
CleanupParameters GlobalParameters;
|
||
TFilePath CurrentSettingsFile = TFilePath();
|
||
|
||
//-----------------------------------------------------------------------------
|
||
|
||
void loadSettings(const TFilePath &settingsFile, CleanupParameters *cp) {
|
||
if (CurrentSettingsFile ==
|
||
TFilePath()) // the parameters were global ...I store them
|
||
GlobalParameters.assign(cp);
|
||
|
||
CurrentSettingsFile = settingsFile;
|
||
|
||
TIStream *is = new TIStream(settingsFile);
|
||
int minor, major;
|
||
string tagName;
|
||
|
||
// Extract file version if any
|
||
is->matchTag(tagName);
|
||
if (tagName == "version") {
|
||
*is >> major >> minor;
|
||
is->matchEndTag();
|
||
is->setVersion(VersionNumber(major, minor));
|
||
} else {
|
||
delete is;
|
||
is = new TIStream(settingsFile);
|
||
}
|
||
|
||
cp->loadData(*is, true);
|
||
|
||
delete is;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------
|
||
|
||
void restoreGlobalSettings(CleanupParameters *cp) {
|
||
if (CurrentSettingsFile == TFilePath()) return; // already global!
|
||
|
||
cp->assign(&GlobalParameters);
|
||
CurrentSettingsFile = TFilePath();
|
||
}
|
||
|
||
} // namespace
|
||
|
||
//========================================================================
|
||
//
|
||
// fatalError
|
||
//
|
||
//------------------------------------------------------------------------
|
||
|
||
void fatalError(string msg) {
|
||
#ifdef _WIN32
|
||
msg = "Application can't start:\n" + msg;
|
||
DVGui::error(QString::fromStdString(msg));
|
||
// MessageBox(0,msg.c_str(),"Fatal error",MB_ICONERROR);
|
||
exit(1);
|
||
#else
|
||
// TODO: Come si fa ad aggiungere un messaggio di errore qui?
|
||
std::cout << msg << std::endl;
|
||
abort();
|
||
#endif
|
||
}
|
||
|
||
} // namespace
|
||
|
||
#ifdef MACOSX
|
||
|
||
inline bool isBlank(char c) { return c == ' ' || c == '\t' || c == '\n'; }
|
||
|
||
//========================================================================
|
||
// setToonzFolder
|
||
//------------------------------------------------------------------------
|
||
|
||
// Ritorna il path della variabile passata come secondo argomento
|
||
// entrambe vengono lette da un file di testo (filename).
|
||
|
||
TFilePath setToonzFolder(const TFilePath &filename, std::string toonzVar) {
|
||
Tifstream is(filename);
|
||
if (!is) return TFilePath();
|
||
|
||
char buffer[1024];
|
||
|
||
while (is.getline(buffer, sizeof(buffer))) {
|
||
// le righe dentro toonzenv.txt sono del tipo
|
||
// export set TOONZPROJECT="....."
|
||
|
||
// devo trovare la linea che contiene toonzVar
|
||
char *s = buffer;
|
||
while (isBlank(*s)) s++;
|
||
// Se la riga vuota, o inizia per # o ! salto alla prossima
|
||
if (*s == '\0' || *s == '#' || *s == '!') continue;
|
||
if (*s == '=') continue; // errore: nome variabile non c'
|
||
char *t = s;
|
||
// Mi prendo la sottoStringa fino all'=
|
||
while (*t && *t != '=') t++;
|
||
if (*t != '=') continue; // errore: manca '='
|
||
char *q = t;
|
||
// Torno indietro fino al primo blank
|
||
while (q > s && !isBlank(*(q - 1))) q--;
|
||
if (q == s)
|
||
continue; // non dovrebbe mai succedere: prima di '=' tutti blanks
|
||
|
||
string toonzVarString(q, t);
|
||
|
||
// Confronto la stringa trovata con toonzVar, se lei vado avanti.
|
||
if (toonzVar != toonzVarString) continue; // errore: stringhe diverse
|
||
s = t + 1;
|
||
// Salto gli spazi
|
||
while (isBlank(*s)) s++;
|
||
if (*s == '\0') continue; // errore: dst vuoto
|
||
t = s;
|
||
while (*t) t++;
|
||
while (t > s && isBlank(*(t - 1))) t--;
|
||
if (t == s) continue;
|
||
// ATTENZIONE : tolgo le virgolette !!
|
||
string pathName(s + 1, t - s - 2);
|
||
return TFilePath(pathName);
|
||
}
|
||
|
||
return TFilePath();
|
||
}
|
||
|
||
#endif
|
||
|
||
//==============================================================================================
|
||
|
||
static void prepareToCleanup(TXshSimpleLevel *xl, TPalette *cleanupPalette) {
|
||
assert(xl->getScene());
|
||
if (xl->getProperties()->getSubsampling() != 1) {
|
||
xl->getProperties()->setSubsampling(1);
|
||
xl->invalidateFrames();
|
||
}
|
||
|
||
/* int ltype = xl->getType();
|
||
if(ltype != TZP_XSHLEVEL)
|
||
xl->makeTlv(xl->getScene()->getDefaultParentDir(TZP_XSHLEVEL));
|
||
if(xl->getPalette()==0)
|
||
{
|
||
//PaletteController* pc = TApp::instance()->getPaletteController();
|
||
xl->setPalette(cleanupPalette);
|
||
//if(xl == TApp::instance()->getCurrentLevel()->getLevel())
|
||
// pc->getCurrentLevelPalette()->setPalette(xl->getPalette());
|
||
}*/
|
||
}
|
||
|
||
//==============================================================================================
|
||
|
||
namespace {
|
||
TStopWatch Sw1;
|
||
TStopWatch Sw2;
|
||
|
||
bool UseRenderFarm = false;
|
||
string FarmControllerName;
|
||
int FarmControllerPort;
|
||
|
||
TFarmController *FarmController = 0;
|
||
|
||
string TaskId;
|
||
} // namespace
|
||
//========================================================================
|
||
//
|
||
// searchLevelsToCleanup
|
||
//
|
||
// Restituisce l'elenco (ordinato per ordine alfabetico di nome)
|
||
// dei livelli TLV(con scannedPath)/TZI/OVL presenti nell'xsheet (o nei
|
||
// sottoxsheet)
|
||
//
|
||
// se selectedOnly = true salta i livelli presenti nelle colonne senza
|
||
// "occhietto"
|
||
//
|
||
//------------------------------------------------------------------------
|
||
|
||
static void searchLevelsToCleanup(
|
||
std::vector<std::pair<TXshSimpleLevel *, std::set<TFrameId>>> &levels,
|
||
TXsheet *xsh, bool selectedOnly) {
|
||
std::map<wstring, TXshSimpleLevel *> levelTable;
|
||
std::map<wstring, std::set<TFrameId>> framesTable;
|
||
|
||
std::set<TXsheet *> visited;
|
||
std::vector<TXsheet *> xsheets;
|
||
xsheets.push_back(xsh);
|
||
visited.insert(xsh);
|
||
while (!xsheets.empty()) {
|
||
TXsheet *xsh = xsheets.back();
|
||
xsheets.pop_back();
|
||
for (int c = 0; c < xsh->getColumnCount(); c++) {
|
||
TXshColumn *column = xsh->getColumn(c);
|
||
if (!column || column->isEmpty()) continue;
|
||
// if(selectedOnly && !column->isPreviewVisible()) continue;
|
||
int r0 = 0, r1 = -1;
|
||
xsh->getCellRange(c, r0, r1);
|
||
for (int r = r0; r <= r1; r++) {
|
||
TXshCell cell = xsh->getCell(r, c);
|
||
if (cell.isEmpty()) continue;
|
||
if (TXshSimpleLevel *sl = cell.m_level->getSimpleLevel()) {
|
||
if (selectedOnly && !column->isPreviewVisible()) // pezza: se questo
|
||
// "if" veniva fatto
|
||
// sopra(riga
|
||
// commentata)
|
||
// quando si fa save della Scene alla fine della cleanuppata,
|
||
// venivano backuppate le tif non processate e cancellati gli
|
||
// originali!
|
||
// Deliri del levelUPdater; evito di mettere le mani in quel pattume.
|
||
// vinz
|
||
{
|
||
sl->setDirtyFlag(false);
|
||
continue;
|
||
}
|
||
int ltype = sl->getType();
|
||
if ((ltype == TZP_XSHLEVEL && sl->getScannedPath() != TFilePath()) ||
|
||
ltype == OVL_XSHLEVEL || ltype == TZI_XSHLEVEL) {
|
||
wstring levelName = sl->getName();
|
||
levelTable[levelName] = sl;
|
||
framesTable[levelName].insert(cell.m_frameId);
|
||
}
|
||
} else if (TXshChildLevel *cl = cell.m_level->getChildLevel()) {
|
||
TXsheet *subXsh = cl->getXsheet();
|
||
if (visited.count(subXsh) == 0) {
|
||
visited.insert(subXsh);
|
||
xsheets.push_back(subXsh);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
assert(levelTable.size() == framesTable.size());
|
||
|
||
for (auto const &level : levelTable) {
|
||
auto const it = framesTable.find(level.first);
|
||
if (it == framesTable.end()) {
|
||
continue;
|
||
}
|
||
levels.push_back(std::make_pair(level.second, (*it).second));
|
||
}
|
||
}
|
||
|
||
//------------------------------------------------------------------------------
|
||
/*- CleanupDefaultパレットを追加する -*/
|
||
static void addCleanupDefaultPalette(TXshSimpleLevel *sl) {
|
||
/*- 元となるパレットはStudioPaletteフォルダに置く -*/
|
||
TFilePath palettePath =
|
||
ToonzFolder::getStudioPaletteFolder() + "cleanup_default.tpl";
|
||
TFileStatus pfs(palettePath);
|
||
|
||
if (!pfs.doesExist() || !pfs.isReadable()) {
|
||
wcout << L"CleanupDefaultPalette file: " << palettePath.getWideString()
|
||
<< L" is not found!" << endl;
|
||
return;
|
||
}
|
||
|
||
TIStream is(palettePath);
|
||
if (!is) {
|
||
cout << "CleanupDefaultPalette file: failed to get TIStream" << endl;
|
||
return;
|
||
}
|
||
|
||
string tagName;
|
||
if (!is.matchTag(tagName) || tagName != "palette") {
|
||
cout << "CleanupDefaultPalette file: This is not palette file" << endl;
|
||
return;
|
||
}
|
||
|
||
string gname;
|
||
is.getTagParam("name", gname);
|
||
TPalette *defaultPalette = new TPalette();
|
||
defaultPalette->loadData(is);
|
||
|
||
sl->getPalette()->setIsCleanupPalette(false);
|
||
|
||
TPalette::Page *dstPage = sl->getPalette()->getPage(0);
|
||
TPalette::Page *srcPage = defaultPalette->getPage(0);
|
||
|
||
for (int srcIndexInPage = 0; srcIndexInPage < srcPage->getStyleCount();
|
||
srcIndexInPage++) {
|
||
int id = srcPage->getStyleId(srcIndexInPage);
|
||
|
||
bool isUsedInCleanupPalette;
|
||
isUsedInCleanupPalette = false;
|
||
|
||
for (int dstIndexInPage = 0; dstIndexInPage < dstPage->getStyleCount();
|
||
dstIndexInPage++) {
|
||
if (dstPage->getStyleId(dstIndexInPage) == id) {
|
||
isUsedInCleanupPalette = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (isUsedInCleanupPalette)
|
||
continue;
|
||
|
||
else {
|
||
int addedId = sl->getPalette()->addStyle(
|
||
srcPage->getStyle(srcIndexInPage)->clone());
|
||
dstPage->addStyle(addedId);
|
||
/*- StudioPalette由来のDefaultPaletteの場合、GrobalNameを消去する -*/
|
||
sl->getPalette()->getStyle(addedId)->setGlobalName(L"");
|
||
sl->getPalette()->getStyle(addedId)->setOriginalName(L"");
|
||
}
|
||
}
|
||
|
||
delete defaultPalette;
|
||
}
|
||
|
||
//========================================================================
|
||
//
|
||
// cleanupLevel
|
||
//
|
||
// effettua il cleanup del livello. Se il livello e' un fullcolor
|
||
// modifica tipo e parametri e crea la palette
|
||
//
|
||
// se overwrite == false non fa il cleanup dei frames gia' cleanuppati
|
||
//
|
||
//------------------------------------------------------------------------
|
||
|
||
static void cleanupLevel(TXshSimpleLevel *xl, std::set<TFrameId> fidsInXsheet,
|
||
ToonzScene *scene, bool overwrite,
|
||
TUserLogAppend &m_userLog) {
|
||
prepareToCleanup(xl, scene->getProperties()
|
||
->getCleanupParameters()
|
||
->m_cleanupPalette.getPointer());
|
||
|
||
TCleanupper *cl = TCleanupper::instance();
|
||
|
||
TFilePath fp = scene->decodeFilePath(xl->getPath());
|
||
TSystem::touchParentDir(fp);
|
||
cout << "cleanupping " << xl->getName() << " path=" << fp << endl;
|
||
string info = "cleanupping " + ::to_string(xl->getPath());
|
||
LevelUpdater updater(xl);
|
||
m_userLog.info(info);
|
||
DVGui::info(QString::fromStdString(info));
|
||
bool firstImage = true;
|
||
for (auto const &fid : fidsInXsheet) {
|
||
cout << " " << fid << endl;
|
||
info = " " + fid.expand();
|
||
m_userLog.info(info);
|
||
int status = xl->getFrameStatus(fid);
|
||
|
||
if (0 != (status & TXshSimpleLevel::Cleanupped) && !overwrite) {
|
||
cout << " skipped" << endl;
|
||
m_userLog.info(" skipped");
|
||
DVGui::info(QString("--skipped frame ") +
|
||
QString::fromStdString(fid.expand()));
|
||
continue;
|
||
}
|
||
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);
|
||
cout << err << endl;
|
||
continue;
|
||
}
|
||
|
||
if (params->m_lineProcessingMode == lpNone) {
|
||
TRasterImageP ri(original);
|
||
/*if (params->m_autocenterType == CleanupTypes::AUTOCENTER_NONE)
|
||
ri = original;
|
||
else {
|
||
bool autocentered;
|
||
ri = cl->autocenterOnly(original, false, autocentered);
|
||
if (!autocentered) {
|
||
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;
|
||
}
|
||
// 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 (firstImage) {
|
||
TPointD dpi;
|
||
original->getDpi(dpi.x, dpi.y);
|
||
if (dpi.x == 0 && dpi.y == 0) dpi = xl->getProperties()->getDpi();
|
||
cl->setSourceDpi(dpi);
|
||
}
|
||
|
||
CleanupPreprocessedImage *cpi;
|
||
{
|
||
TRasterImageP resampledImage;
|
||
cpi = cl->process(original, firstImage, resampledImage);
|
||
}
|
||
|
||
TToonzImageP timage = cl->finalize(cpi, true);
|
||
TPointD dpi(0, 0);
|
||
timage->getDpi(dpi.x, dpi.y);
|
||
if (dpi.x != 0 && dpi.y != 0) xl->getProperties()->setDpi(dpi);
|
||
|
||
if (firstImage) addCleanupDefaultPalette(xl);
|
||
firstImage = false;
|
||
|
||
timage->setPalette(xl->getPalette());
|
||
xl->setFrameStatus(fid, status | TXshSimpleLevel::Cleanupped);
|
||
xl->setFrame(fid, timage);
|
||
|
||
updater.update(fid, timage);
|
||
|
||
/*- 1フレーム終わったら、そのフレームのキャッシュは消す -*/
|
||
xl->invalidateFrame(fid);
|
||
|
||
delete cpi;
|
||
}
|
||
}
|
||
|
||
//========================================================================
|
||
//
|
||
// main
|
||
//
|
||
// usage: tcleanup filename.tnz [-selected][-overwrite]
|
||
//
|
||
//------------------------------------------------------------------------
|
||
|
||
int main(int argc, char *argv[]) {
|
||
QApplication app(argc, argv);
|
||
|
||
// questo definisce la registry root e inizializza TEnv
|
||
TEnv::setRootVarName(rootVarName);
|
||
TEnv::setSystemVarPrefix(systemVarPrefix);
|
||
TEnv::setApplicationFileName(argv[0]);
|
||
|
||
QCoreApplication::setOrganizationName("Tahoma2D");
|
||
QCoreApplication::setOrganizationDomain("");
|
||
QCoreApplication::setApplicationName(
|
||
QString::fromStdString(TEnv::getApplicationName()));
|
||
|
||
TSystem::hasMainLoop(false);
|
||
int i;
|
||
for (i = 0; i < argc; i++) // tmsg must be set as soon as it's possible
|
||
{
|
||
QString str = argv[i];
|
||
if (str == "-tmsg")
|
||
|
||
{
|
||
TMsgCore::instance()->connectTo(argv[i + 1]);
|
||
break;
|
||
}
|
||
}
|
||
if (i == argc) TMsgCore::instance()->connectTo("");
|
||
|
||
TFilePath fproot = TEnv::getStuffDir();
|
||
if (fproot == TFilePath())
|
||
fatalError(string("Undefined: \"") + ::to_string(TEnv::getRootVarPath()) +
|
||
"\"");
|
||
if (!TFileStatus(fproot).isDirectory())
|
||
fatalError(string("Directory \"") + ::to_string(fproot) +
|
||
"\" not found or not readable");
|
||
|
||
TFilePath lRootDir = TEnv::getStuffDir() + "toonzfarm";
|
||
TFilePath logFilePath = lRootDir + "tcleanup.log";
|
||
TUserLogAppend m_userLog(logFilePath);
|
||
|
||
// TFilePathSet fps = ToonzFolder::getProjectsFolders();
|
||
// TFilePathSet::iterator fpIt;
|
||
// for (fpIt = fps.begin(); fpIt != fps.end(); ++fpIt)
|
||
// TProjectManager::instance()->addProjectsRoot(*fpIt);
|
||
|
||
TFilePath libraryFolder = ToonzFolder::getLibraryFolder();
|
||
TRasterImagePatternStrokeStyle::setRootDir(libraryFolder);
|
||
TVectorImagePatternStrokeStyle::setRootDir(libraryFolder);
|
||
TPalette::setRootDir(libraryFolder);
|
||
TImageStyle::setLibraryDir(libraryFolder);
|
||
TFilePath cacheRoot = ToonzFolder::getCacheRootFolder();
|
||
if (cacheRoot.isEmpty()) cacheRoot = TEnv::getStuffDir() + "cache";
|
||
TImageCache::instance()->setRootDir(cacheRoot);
|
||
|
||
FilePathArgument srcName("tnzFile", "Scene file");
|
||
SimpleQualifier selectedOnlyOption("-onlyvisible", "Selected column only");
|
||
|
||
SimpleQualifier overwriteAllOption("-overwriteAll",
|
||
"Overwrite all already cleanupped frames");
|
||
SimpleQualifier overwriteNoPaintOption(
|
||
"-overwriteNoPaint",
|
||
"Overwrite only no-paint levels of already cleanupped frames");
|
||
|
||
StringQualifier farmData("-farm data", "TFarm Controller");
|
||
StringQualifier idq("-id n", "id");
|
||
StringQualifier tmsg("-tmsg n", "Internal use only");
|
||
Usage usage(argv[0]);
|
||
usage.add(srcName + selectedOnlyOption + overwriteAllOption +
|
||
overwriteNoPaintOption + farmData + idq + tmsg);
|
||
if (!usage.parse(argc, argv)) exit(1);
|
||
|
||
TaskId = idq.getValue();
|
||
string fdata = farmData.getValue();
|
||
if (fdata.empty())
|
||
UseRenderFarm = false;
|
||
else {
|
||
UseRenderFarm = true;
|
||
string::size_type pos = fdata.find('@');
|
||
if (pos == string::npos)
|
||
UseRenderFarm = false;
|
||
else {
|
||
FarmControllerPort = std::stoi(fdata.substr(0, pos));
|
||
FarmControllerName = fdata.substr(pos + 1);
|
||
}
|
||
}
|
||
|
||
if (UseRenderFarm) {
|
||
TFarmControllerFactory factory;
|
||
factory.create(QString::fromStdString(FarmControllerName),
|
||
FarmControllerPort, &FarmController);
|
||
}
|
||
|
||
/*- 画像Read/Writeの関数を登録 -*/
|
||
initImageIo();
|
||
Tiio::defineStd();
|
||
|
||
/*- プロジェクトのロード -*/
|
||
TProjectManager *pm = TProjectManager::instance();
|
||
TProjectP project = pm->loadSceneProject(srcName);
|
||
|
||
if (!project) {
|
||
string err = "Couldn't find the project" + project->getName().getName();
|
||
m_userLog.error(err);
|
||
cerr << err << endl;
|
||
return -2;
|
||
}
|
||
|
||
cout << "project:" << project->getName() << endl;
|
||
|
||
TFilePath fp = srcName;
|
||
|
||
/*- CLNファイルを直接指定した場合 -*/
|
||
bool sourceFileIsCleanupSetting = (fp.getType() == "cln");
|
||
|
||
bool selectedOnly = selectedOnlyOption;
|
||
|
||
ToonzScene *scene = new ToonzScene();
|
||
|
||
TImageStyle::setCurrentScene(scene);
|
||
|
||
/*- シーンファイルパスを入力した場合 -*/
|
||
if (!sourceFileIsCleanupSetting) {
|
||
try {
|
||
scene->loadNoResources(fp);
|
||
} catch (...) {
|
||
string err = "can't read " + fp.getName();
|
||
m_userLog.error(err);
|
||
cerr << "can't read " << fp << endl;
|
||
TImageCache::instance()->clear(true);
|
||
return -3;
|
||
}
|
||
}
|
||
/*-- CleanupSettingsファイルパスを直接入力した場合 --*/
|
||
else {
|
||
try {
|
||
TProjectManager *pm = TProjectManager::instance();
|
||
TProjectP sceneProject = pm->loadSceneProject(fp);
|
||
if (!sceneProject) {
|
||
cerr << "can't open project." << endl;
|
||
return -3;
|
||
}
|
||
scene->setProject(sceneProject.getPointer());
|
||
|
||
/*- CleanupSettingsファイルに対応するTIFファイルが有るかチェック -*/
|
||
TFilePath tifImagePath = fp.withType("tif");
|
||
std::wcout << L"tifImagePath : " << tifImagePath.getWideString()
|
||
<< std::endl;
|
||
|
||
/*-
|
||
* 無ければ、連番画像がソースである可能性がある。tifImagePathを連番に差し替える
|
||
* -*/
|
||
if (!TFileStatus(tifImagePath).doesExist()) {
|
||
tifImagePath =
|
||
tifImagePath.getParentDir() + (tifImagePath.getName() + "..tif");
|
||
std::wcout << "change the source path to : "
|
||
<< tifImagePath.getWideString() << std::endl;
|
||
} else
|
||
std::cout << "tif single image found" << std::endl;
|
||
|
||
/*- シーンファイルに対象のTIFファイルをロード -*/
|
||
TXshLevel *xl = scene->loadLevel(tifImagePath);
|
||
if (!xl) {
|
||
std::cout << "failed to load level" << std::endl;
|
||
throw TException("Failed to load level.");
|
||
}
|
||
std::vector<TFrameId> dummy;
|
||
int frameLength = scene->getXsheet()->exposeLevel(0, 0, xl, dummy);
|
||
std::cout << "expose done. frameLength : " << frameLength << std::endl;
|
||
} catch (...) {
|
||
cerr << "can't read Cleanup Settings file " << fp << endl;
|
||
TImageCache::instance()->clear(true);
|
||
return -3;
|
||
}
|
||
}
|
||
|
||
// Levels contiene i livelli e i rispettivi frames prsenti nell'xsheet.
|
||
std::vector<std::pair<TXshSimpleLevel *, std::set<TFrameId>>> levels;
|
||
|
||
/*- XsheetからCleanupするLevelのリストを得る -*/
|
||
searchLevelsToCleanup(levels, scene->getXsheet(), selectedOnly);
|
||
TSceneProperties *sprop = scene->getProperties();
|
||
CleanupParameters *params = scene->getProperties()->getCleanupParameters();
|
||
for (int i = 0; i < (int)levels.size(); i++) {
|
||
bool overwrite = overwriteAllOption;
|
||
|
||
TXshSimpleLevel *xl = levels[i].first->getSimpleLevel();
|
||
if (!xl) continue;
|
||
|
||
/*- CLNファイルパスを取得 -*/
|
||
TFilePath settingsFile =
|
||
xl->getScannedPath().isEmpty() ? xl->getPath() : xl->getScannedPath();
|
||
settingsFile =
|
||
scene->decodeFilePath(settingsFile).withNoFrame().withType("cln");
|
||
|
||
/*- CLNファイルがあればそれを用いる。無ければGlobal設定を読み込む -*/
|
||
// TFilePath settingsFile =
|
||
// scene->decodeFilePath(xl->getPath()).withNoFrame().withType("cln");
|
||
if (TFileStatus(settingsFile).doesExist())
|
||
loadSettings(settingsFile, params);
|
||
else
|
||
restoreGlobalSettings(params);
|
||
|
||
TCleanupper::instance()->setParameters(params);
|
||
|
||
bool lineProcessing = (params->m_lineProcessingMode != lpNone);
|
||
TFilePath tmp = params->getPath(scene);
|
||
int ltype = xl->getType();
|
||
assert(ltype == TZP_XSHLEVEL || ltype == TZI_XSHLEVEL ||
|
||
ltype == OVL_XSHLEVEL);
|
||
|
||
// target path
|
||
TFilePath targetPath = xl->getPath();
|
||
if (ltype != TZP_XSHLEVEL) {
|
||
if (lineProcessing)
|
||
targetPath =
|
||
targetPath
|
||
.withParentDir(params->getPath(
|
||
scene)) // scene->getDefaultParentDir(TZP_XSHLEVEL))
|
||
.withNoFrame()
|
||
.withType("tlv");
|
||
else
|
||
targetPath = targetPath.withParentDir(params->getPath(
|
||
scene)); // scene->getDefaultParentDir(TZP_XSHLEVEL));
|
||
} else {
|
||
targetPath = targetPath.withParentDir(params->getPath(
|
||
scene)); // scene->getDefaultParentDir(TZP_XSHLEVEL));
|
||
}
|
||
|
||
/*- NoPaintを作る設定のとき、NoPaintの方だけにOverwriteするようにする -*/
|
||
bool isReCleanup;
|
||
isReCleanup = false;
|
||
|
||
/*- 再Cleanupのときにパスを元に戻すために用いる -*/
|
||
TFilePath originalLevelPath = TFilePath();
|
||
|
||
TFilePath actualTargetPath = scene->decodeFilePath(targetPath);
|
||
/*- すでにLevelがある場合 -*/
|
||
if (TSystem::doesExistFileOrLevel(actualTargetPath) &&
|
||
Preferences::instance()->isSaveUnpaintedInCleanupEnable() &&
|
||
overwriteNoPaintOption) {
|
||
overwrite = true;
|
||
originalLevelPath = scene->codeFilePath(targetPath);
|
||
/*- パスを書き換え、再Cleanupのフラグを立てる -*/
|
||
isReCleanup = true;
|
||
/*- nopaintフォルダの作成 -*/
|
||
TFilePath nopaintDir = targetPath.getParentDir() + "nopaint";
|
||
if (!TFileStatus(nopaintDir).doesExist()) {
|
||
try {
|
||
TSystem::mkDir(nopaintDir);
|
||
} catch (...) {
|
||
return 0;
|
||
}
|
||
}
|
||
/*- 保存先のパスをnopaintの方にする -*/
|
||
targetPath =
|
||
targetPath.getParentDir() + "nopaint\\" +
|
||
TFilePath(targetPath.getName() + "_np." + targetPath.getType());
|
||
}
|
||
std::wcout << L"targetPath = " << targetPath.getWideString() << std::endl;
|
||
|
||
if (lineProcessing) {
|
||
if (ltype != TZP_XSHLEVEL) {
|
||
xl->makeTlv(targetPath);
|
||
} else if (targetPath != xl->getPath()) {
|
||
xl->setPath(targetPath, false);
|
||
}
|
||
|
||
xl->setPalette(
|
||
TCleanupper::instance()->createToonzPaletteFromCleanupPalette());
|
||
} else if (!params->getPath(scene).isEmpty()) {
|
||
xl->setScannedPath(xl->getPath());
|
||
xl->setPath(scene->codeFilePath(targetPath), false);
|
||
}
|
||
|
||
std::set<TFrameId> fidsInXsheet = levels[i].second;
|
||
assert(fidsInXsheet.size() > 0);
|
||
|
||
xl->load();
|
||
cleanupLevel(xl, fidsInXsheet, scene, overwrite, m_userLog);
|
||
|
||
/*- Cleanup完了後、Nopaintをnopaintフォルダに保存する -*/
|
||
if (Preferences::instance()->isSaveUnpaintedInCleanupEnable() &&
|
||
!isReCleanup) /*-- 再Cleanupのときはnopaintを作らない --*/
|
||
{
|
||
/*- nopaintフォルダの作成 -*/
|
||
TFilePath nopaintDir = actualTargetPath.getParentDir() + "nopaint";
|
||
if (!TFileStatus(nopaintDir).doesExist()) {
|
||
try {
|
||
TSystem::mkDir(nopaintDir);
|
||
} catch (...) {
|
||
string err = "Can't make directory " + nopaintDir.getName();
|
||
m_userLog.error(err);
|
||
cerr << "Can't make directory" << endl;
|
||
}
|
||
}
|
||
|
||
// Se sono nell'ultimo frame del livello salvo il livello cleanuppato
|
||
// in un file chiamato nome-unpainted (file di backup del cleanup).
|
||
|
||
/*- 保存先 -*/
|
||
TFilePath unpaintedLevelPath =
|
||
actualTargetPath.getParentDir() + "nopaint\\" +
|
||
TFilePath(targetPath.getName() + "_np." + targetPath.getType());
|
||
|
||
if (TFileStatus(actualTargetPath).doesExist() &&
|
||
(!TFileStatus(unpaintedLevelPath).doesExist() ||
|
||
overwriteAllOption) /*- 全て上書きなら既存のNoPaintに上書きする -*/
|
||
&& xl) {
|
||
/*- GUI上でCleanupするときと同様に、Cleanup結果をコピーして作る -*/
|
||
TSystem::copyFile(unpaintedLevelPath, actualTargetPath);
|
||
/*- パレットのコピー -*/
|
||
TFilePath levelPalettePath =
|
||
actualTargetPath.getParentDir() +
|
||
TFilePath(actualTargetPath.getName() + ".tpl");
|
||
TFilePath unpaintedLevelPalettePath =
|
||
levelPalettePath.getParentDir() + "nopaint\\" +
|
||
TFilePath(levelPalettePath.getName() + "_np." +
|
||
levelPalettePath.getType());
|
||
TSystem::copyFile(unpaintedLevelPalettePath, levelPalettePath);
|
||
}
|
||
}
|
||
/*--
|
||
再Cleanupの場合はXsheet上のパスをオリジナルのもの(NoPaintでないもの)に戻す
|
||
--*/
|
||
else if (isReCleanup) {
|
||
xl->setPath(originalLevelPath);
|
||
}
|
||
}
|
||
|
||
/*- CleanupParamをGrobalに戻す -*/
|
||
restoreGlobalSettings(params);
|
||
|
||
/*- CleanupSettingsからCleanupを行った場合はシーンの保存は行わない -*/
|
||
if (sourceFileIsCleanupSetting) {
|
||
std::cout << "Cleanup from Setting file completed" << std::endl;
|
||
return 0;
|
||
}
|
||
|
||
wstring wInfo = L"updating scene " + scene->getSceneName();
|
||
QString qInfo_ = QString::fromStdWString(wInfo);
|
||
string info = qInfo_.toStdString();
|
||
m_userLog.info(info);
|
||
cout << "updating scene " << scene->getSceneName() << endl;
|
||
/*- シーンを上書き保存 -*/
|
||
try {
|
||
scene->save(fp);
|
||
TImageCache::instance()->clear(true);
|
||
} catch (...) {
|
||
wstring wErr = L"Can't save scene " + fp.getWideName();
|
||
QString qErr = QString::fromStdWString(wErr);
|
||
string err = qErr.toStdString();
|
||
m_userLog.error(err);
|
||
cerr << "Can't save scene" << endl;
|
||
TImageCache::instance()->clear(true);
|
||
}
|
||
|
||
DVGui::info("Cleanup Done.");
|
||
return 0;
|
||
}
|
||
//------------------------------------------------------------------------
|