1 
2 
3 #include "toonz/sceneresources.h"
4 #include "toonz/toonzscene.h"
5 #include "toonz/tproject.h"
6 #include "toonz/levelset.h"
7 #include "toonz/txshsimplelevel.h"
8 #include "toonz/txshpalettelevel.h"
9 #include "toonz/levelproperties.h"
10 #include "toonz/txshsoundlevel.h"
11 #include "toonz/namebuilder.h"
12 #include "toonz/childstack.h"
13 #include "toonz/txsheet.h"
14 #include "toonz/preferences.h"
15 #include "tpalette.h"
16 
17 #include "tmsgcore.h"
18 
19 #include "tconvert.h"
20 #include "tlogger.h"
21 #include "tsystem.h"
22 
23 namespace {
24 //=============================================================================
25 
26 // se path e' della forma +folder/<oldSavePath>/name.type
27 // allora sostituisce oldSavePath con newSavePath e ritorna true
28 
changeSavePath(TFilePath & path,TFilePath oldSavePath,TFilePath newSavePath)29 bool changeSavePath(TFilePath &path, TFilePath oldSavePath,
30                     TFilePath newSavePath) {
31   if (oldSavePath == newSavePath) return false;
32   TFilePath fp = path.getParentDir();
33   std::wstring head;
34   TFilePath tail;
35   fp.split(head, tail);
36   if (head != L"" && tail == oldSavePath) {
37     path = path.withParentDir(TFilePath(head) + newSavePath);
38     return true;
39   } else
40     return false;
41 }
42 
43 //-----------------------------------------------------------------------------
44 
45 // From ../../../filename#type.psd to ../../../filename.psd
restorePsdPath(const TFilePath & fp)46 TFilePath restorePsdPath(const TFilePath &fp) {
47   QString path = QString::fromStdWString(fp.getWideString());
48   if (fp.getType() != "psd" || !path.contains("#")) return fp;
49   int from = path.indexOf("#");
50   int to   = path.lastIndexOf(".");
51   path.remove(from, to - from);
52   return TFilePath(path.toStdWString());
53 }
54 
55 //-----------------------------------------------------------------------------
56 
makePathUnique(ToonzScene * scene,TFilePath & path)57 bool makePathUnique(ToonzScene *scene, TFilePath &path) {
58   std::wstring name = path.getWideName();
59   int id            = 2;
60   int i             = name.length() - 1;
61   int num = 0, p = 1;
62   while (i >= 0 && L'0' <= name[i] && name[i] <= L'9') {
63     num += p * (name[i] - L'0');
64     p *= 10;
65     i--;
66   }
67   if (i >= 0 && name[i] == L'_') {
68     id   = num + 1;
69     name = name.substr(0, i);
70   }
71 
72   bool ret = false;
73   while (TSystem::doesExistFileOrLevel(scene->decodeFilePath(path))) {
74     ret  = true;
75     path = path.withName(name + L"_" + std::to_wstring(id));
76     id++;
77   }
78   return ret;
79 }
80 
81 //-----------------------------------------------------------------------------
82 
getCollectedPath(ToonzScene * scene,TFilePath & path)83 bool getCollectedPath(ToonzScene *scene, TFilePath &path) {
84   if (!path.isAbsolute() || path.getWideString()[0] == L'+') return false;
85 
86   TFilePath collectedPath = scene->getImportedLevelPath(path);
87   if (path == collectedPath) return false;
88 
89   TFilePath actualCollectedPath = scene->decodeFilePath(collectedPath);
90 
91   if (makePathUnique(scene, actualCollectedPath))
92     collectedPath = collectedPath.withName(actualCollectedPath.getName());
93 
94   path = collectedPath;
95   return true;
96 }
97 
98 }  // namespace
99 
100 //=============================================================================
101 //
102 // ResourceImportStrategy
103 //
104 //-----------------------------------------------------------------------------
105 
ResourceImportStrategy(int strategy)106 ResourceImportStrategy::ResourceImportStrategy(int strategy)
107     : m_childFolderEnabled(false), m_strategy(strategy) {
108   setChildFolderEnabled(Preferences::instance()->isSubsceneFolderEnabled());
109 }
110 
111 //-----------------------------------------------------------------------------
112 
process(ToonzScene * scene,ToonzScene * srcScene,TFilePath srcPath)113 TFilePath ResourceImportStrategy::process(ToonzScene *scene,
114                                           ToonzScene *srcScene,
115                                           TFilePath srcPath) {
116   TFilePath srcActualPath = srcScene->decodeFilePath(srcPath);
117   if (!scene->isExternPath(srcActualPath) || m_strategy == DONT_IMPORT)
118     return srcPath;
119 
120   TFilePath dstPath;
121   if (srcPath.getWideString().find(L'+') == 0)
122     dstPath = srcPath;
123   else
124     dstPath = scene->getImportedLevelPath(srcPath);
125   TFilePath actualDstPath = scene->decodeFilePath(dstPath);
126   assert(actualDstPath != TFilePath());
127 
128   if (m_strategy == IMPORT_AND_OVERWRITE) {
129     // bool overwritten = false;
130     if (TSystem::doesExistFileOrLevel(actualDstPath)) {
131       TSystem::removeFileOrLevel(actualDstPath);
132       //  overwritten = true;
133     }
134     if (TSystem::doesExistFileOrLevel(srcPath))
135       TXshSimpleLevel::copyFiles(actualDstPath, srcPath);
136 
137     return dstPath;
138   } else if (m_strategy == IMPORT_AND_RENAME) {
139     std::wstring levelName    = srcPath.getWideName();
140     TLevelSet *parentLevelSet = scene->getLevelSet();
141     NameModifier nm(levelName);
142     std::wstring newName;
143     for (;;) {
144       newName = nm.getNext();
145       if (!parentLevelSet->hasLevel(newName)) break;
146     }
147 
148     dstPath       = dstPath.withName(newName);
149     actualDstPath = scene->decodeFilePath(dstPath);
150 
151     if (TSystem::doesExistFileOrLevel(actualDstPath))
152       TSystem::removeFileOrLevel(actualDstPath);
153 
154     if (TSystem::doesExistFileOrLevel(srcActualPath)) {
155       TXshSimpleLevel::copyFiles(actualDstPath, srcActualPath);
156     }
157     return dstPath;
158   }
159   return srcPath;
160 }
161 
162 //=============================================================================
163 //
164 // SceneResource
165 //
166 //-----------------------------------------------------------------------------
167 
SceneResource(ToonzScene * scene)168 SceneResource::SceneResource(ToonzScene *scene)
169     : m_scene(scene)
170     , m_untitledScene(scene->isUntitled())
171     , m_oldSavePath(scene->getSavePath()) {}
172 
173 //-----------------------------------------------------------------------------
174 
~SceneResource()175 SceneResource::~SceneResource() {}
176 
177 //-----------------------------------------------------------------------------
178 
updatePath(TFilePath & fp)179 void SceneResource::updatePath(TFilePath &fp) {
180   if (m_untitledScene)
181     changeSavePath(fp, m_oldSavePath, m_scene->getSavePath());
182 }
183 
184 //=============================================================================
185 //
186 // SceneLevel
187 //
188 //-----------------------------------------------------------------------------
189 
SceneLevel(ToonzScene * scene,TXshSimpleLevel * sl)190 SceneLevel::SceneLevel(ToonzScene *scene, TXshSimpleLevel *sl)
191     : SceneResource(scene)
192     , m_sl(sl)
193     , m_oldPath(sl->getPath())
194     , m_oldActualPath(scene->decodeFilePath(sl->getPath()))
195     , m_oldScannedPath(sl->getScannedPath())
196     , m_oldRefImgPath()
197     , m_oldActualRefImgPath() {
198   if (m_oldScannedPath != TFilePath())
199     m_oldActualScannedPath = m_scene->decodeFilePath(m_oldScannedPath);
200   if ((sl->getPath().getType() == "tlv" || sl->getPath().getType() == "pli") &&
201       sl->getPalette()) {
202     m_oldRefImgPath       = sl->getPalette()->getRefImgPath();
203     m_oldActualRefImgPath = m_scene->decodeFilePath(m_oldRefImgPath);
204   }
205 }
206 
207 //-----------------------------------------------------------------------------
208 
save()209 void SceneLevel::save() {
210   TFilePath fp = m_oldPath;
211   SceneResource::updatePath(fp);
212   TFilePath actualFp      = m_scene->decodeFilePath(fp);
213   actualFp                = restorePsdPath(actualFp);
214   TFilePath oldActualPath = restorePsdPath(m_oldActualPath);
215   assert(actualFp.getWideString() == L"" ||
216          actualFp.getWideString()[0] != L'+');
217   if (actualFp != oldActualPath ||
218       !TSystem::doesExistFileOrLevel(oldActualPath) ||
219       m_sl->getProperties()->getDirtyFlag() ||
220       (m_sl->getPalette() && m_sl->getPalette()->getDirtyFlag())) {
221     try {
222       TSystem::touchParentDir(actualFp);
223       if (actualFp != oldActualPath &&
224           TSystem::doesExistFileOrLevel(oldActualPath) &&
225           m_sl->getProperties()->getDirtyFlag() == false &&
226           (!m_sl->getPalette() ||
227            (m_sl->getPalette() &&
228             m_sl->getPalette()->getDirtyFlag() == false))) {
229         try {
230           TXshSimpleLevel::copyFiles(actualFp, oldActualPath);
231         } catch (...) {
232         }
233         // Must NOT KEEP FRAMES, it generate a level frames bind necessary to
234         // imageBuilder path refresh.
235         m_sl->setPath(fp, false);
236       } else {
237         try {
238           m_sl->save(actualFp, oldActualPath);
239         } catch (...) {
240           throw;
241         }
242         if ((actualFp.getType() == "tlv" || actualFp.getType() == "pli") &&
243             actualFp != oldActualPath && m_oldRefImgPath != TFilePath()) {
244           // Devo preoccuparmi dell'eventuale livello colormodel
245           TFilePath actualRefImagPath =
246               m_scene->decodeFilePath(m_oldRefImgPath);
247           TFilePath actualRefImagPathTpl = actualRefImagPath.withType("tpl");
248           TFilePath oldRefImagPathTpl = m_oldActualRefImgPath.withType("tpl");
249           TSystem::copyFile(actualRefImagPath, m_oldActualRefImgPath);
250           if (actualRefImagPath.getType() == "tlv")
251             TSystem::copyFile(actualRefImagPathTpl, oldRefImagPathTpl);
252         }
253 
254         if (actualFp.getType() == "tif" || actualFp.getType() == "tiff" ||
255             actualFp.getType() == "tga" || actualFp.getType() == "tzi") {
256           TFilePath clnin = oldActualPath.withNoFrame().withType("cln");
257           if (TSystem::doesExistFileOrLevel(clnin))
258             TSystem::copyFile(actualFp.withNoFrame().withType("cln"), clnin);
259         }
260       }
261       // Se il livello e' tlv verifico se esiste il corrispondente unpainted ed
262       // in caso affermativo lo copio.
263       // Questo controllo viene fatto qui e non nella copia o nel salvataggio
264       // del livello perche' in generale
265       // non si vuole che il livello unpainted venga copiato con il livello.
266       if (actualFp.getType() == "tlv") {
267         TFilePath oldUnpaintedLevelPath =
268             oldActualPath.getParentDir() + "nopaint\\" +
269             TFilePath(oldActualPath.getName() + "_np." +
270                       oldActualPath.getType());
271         TFilePath unpaintedLevelPath =
272             actualFp.getParentDir() + "nopaint\\" +
273             TFilePath(actualFp.getName() + "_np." + actualFp.getType());
274         if (TSystem::doesExistFileOrLevel(oldUnpaintedLevelPath) &&
275             !TSystem::doesExistFileOrLevel(unpaintedLevelPath) &&
276             TSystem::touchParentDir(unpaintedLevelPath))
277           TSystem::copyFile(unpaintedLevelPath, oldUnpaintedLevelPath);
278         TFilePath oldUnpaintedPalettePath =
279             oldUnpaintedLevelPath.withType("tpl");
280         TFilePath unpaintedPalettePath = unpaintedLevelPath.withType("tpl");
281         if (TSystem::doesExistFileOrLevel(oldUnpaintedPalettePath) &&
282             !TSystem::doesExistFileOrLevel(unpaintedPalettePath) &&
283             TSystem::touchParentDir(unpaintedPalettePath))
284           TSystem::copyFile(unpaintedPalettePath, oldUnpaintedPalettePath);
285       }
286     } catch (...) {
287     }
288   }
289   fp = m_oldScannedPath;
290   if (fp != TFilePath()) {
291     SceneResource::updatePath(fp);
292     actualFp = m_scene->decodeFilePath(fp);
293     if (actualFp != m_oldActualScannedPath &&
294         TSystem::doesExistFileOrLevel(m_oldActualScannedPath)) {
295       try {
296         TSystem::touchParentDir(actualFp);
297         TSystem::copyFileOrLevel_throw(actualFp, m_oldActualScannedPath);
298         m_sl->clearFrames();
299         m_sl->load();
300       } catch (...) {
301       }
302     }
303   }
304 }
305 
306 //-----------------------------------------------------------------------------
307 
updatePath()308 void SceneLevel::updatePath() {
309   if (!m_untitledScene) return;
310   TFilePath fp = m_oldPath;
311   SceneResource::updatePath(fp);
312   m_sl->setPath(fp, true);
313   fp = m_oldScannedPath;
314   SceneResource::updatePath(fp);
315   m_sl->setScannedPath(fp);
316 }
317 
318 //-----------------------------------------------------------------------------
319 
rollbackPath()320 void SceneLevel::rollbackPath() {
321   if (!m_untitledScene) return;
322   m_sl->setPath(m_oldPath, true);
323   m_sl->setScannedPath(m_oldScannedPath);
324 }
325 
326 //-----------------------------------------------------------------------------
327 
isDirty()328 bool SceneLevel::isDirty() {
329   if (m_sl->getProperties()->getDirtyFlag() ||
330       (m_sl->getPalette() && m_sl->getPalette()->getDirtyFlag()))
331     return true;
332   else
333     return false;
334 }
335 //-----------------------------------------------------------------------------
336 
getResourceName()337 QStringList SceneLevel::getResourceName() {
338   QStringList ret;
339   QString string;
340   bool levelIsDirty = false;
341   if (m_sl->getProperties()->getDirtyFlag()) {
342     string += QString::fromStdString(m_sl->getPath().getLevelName());
343     levelIsDirty = true;
344   }
345   if (m_sl->getPalette() && m_sl->getPalette()->getDirtyFlag()) {
346     QString paletteName =
347         QString::fromStdWString(m_sl->getPalette()->getPaletteName());
348     if (m_sl->getType() & FULLCOLOR_TYPE) {
349       if (levelIsDirty) ret << string;
350       ret << paletteName + ".tpl";
351     } else {
352       if (levelIsDirty) string += " and ";
353       if (m_sl->getPath().getType() == "pli")
354         string += paletteName + ".pli (palette)";
355       else
356         string += paletteName + ".tpl";
357       ret << string;
358     }
359   } else if (levelIsDirty)
360     ret << string;
361 
362   return ret;
363 }
364 
365 //=============================================================================
366 //
367 // ScenePalette
368 //
369 //-----------------------------------------------------------------------------
370 
ScenePalette(ToonzScene * scene,TXshPaletteLevel * pl)371 ScenePalette::ScenePalette(ToonzScene *scene, TXshPaletteLevel *pl)
372     : SceneResource(scene)
373     , m_pl(pl)
374     , m_oldPath(pl->getPath())
375     , m_oldActualPath(scene->decodeFilePath(pl->getPath())) {}
376 
377 //-----------------------------------------------------------------------------
378 
save()379 void ScenePalette::save() {
380   assert(m_oldPath != TFilePath());
381   TFilePath fp = m_oldPath;
382   SceneResource::updatePath(fp);
383   TFilePath actualFp = m_scene->decodeFilePath(fp);
384   try {
385     TSystem::touchParentDir(actualFp);
386     if (actualFp != m_oldActualPath &&
387         TSystem::doesExistFileOrLevel(m_oldActualPath)) {
388       TSystem::copyFile(actualFp, m_oldActualPath);
389     }
390     m_pl->save();  // actualFp non so perche' era cosi'
391   } catch (...) {
392     TLogger::error() << "Can't save " << actualFp;
393   }
394 }
395 
396 //-----------------------------------------------------------------------------
397 
updatePath()398 void ScenePalette::updatePath() {
399   TFilePath fp = m_oldPath;
400   SceneResource::updatePath(fp);
401   if (fp != m_oldPath) m_pl->setPath(fp);
402 }
403 
404 //-----------------------------------------------------------------------------
405 
rollbackPath()406 void ScenePalette::rollbackPath() { m_pl->setPath(m_oldPath); }
407 
408 //-----------------------------------------------------------------------------
409 
isDirty()410 bool ScenePalette::isDirty() { return m_pl->getPalette()->getDirtyFlag(); }
411 
412 //-----------------------------------------------------------------------------
413 
getResourceName()414 QStringList ScenePalette::getResourceName() {
415   return QStringList(QString::fromStdString(m_pl->getPath().getLevelName()));
416 }
417 
418 //=============================================================================
419 //
420 // SceneSound
421 //
422 //-----------------------------------------------------------------------------
423 
SceneSound(ToonzScene * scene,TXshSoundLevel * sl)424 SceneSound::SceneSound(ToonzScene *scene, TXshSoundLevel *sl)
425     : SceneResource(scene)
426     , m_sl(sl)
427     , m_oldPath(sl->getPath())
428     , m_oldActualPath(scene->decodeFilePath(sl->getPath())) {}
429 
430 //-----------------------------------------------------------------------------
431 
save()432 void SceneSound::save() {
433   assert(m_oldPath != TFilePath());
434   TFilePath fp = m_oldPath;
435   SceneResource::updatePath(fp);
436   TFilePath actualFp = m_scene->decodeFilePath(fp);
437   try {
438     TSystem::touchParentDir(actualFp);
439     if (!TSystem::doesExistFileOrLevel(m_oldActualPath)) {
440       m_sl->save(actualFp);
441     } else if (actualFp != m_oldActualPath) {
442       TSystem::copyFile(actualFp, m_oldActualPath);
443     }
444   } catch (...) {
445     DVGui::warning(QObject::tr("Can't save") +
446                    QString::fromStdWString(L": " + actualFp.getLevelNameW()));
447   }
448 }
449 
450 //-----------------------------------------------------------------------------
451 
updatePath()452 void SceneSound::updatePath() {
453   TFilePath fp = m_oldPath;
454   SceneResource::updatePath(fp);
455   if (fp != m_oldPath) m_sl->setPath(fp);
456 }
457 
458 //-----------------------------------------------------------------------------
459 
rollbackPath()460 void SceneSound::rollbackPath() { m_sl->setPath(m_oldPath); }
461 
462 //=============================================================================
463 //
464 // SceneResources
465 //
466 //-----------------------------------------------------------------------------
467 
SceneResources(ToonzScene * scene,TXsheet * subXsheet)468 SceneResources::SceneResources(ToonzScene *scene, TXsheet *subXsheet)
469     : m_scene(scene)
470     , m_commitDone(false)
471     , m_wasUntitled(scene->isUntitled())
472     , m_subXsheet(subXsheet) {
473   getResources();
474 }
475 
476 //-----------------------------------------------------------------------------
477 
~SceneResources()478 SceneResources::~SceneResources() {
479   if (!m_commitDone) rollbackPaths();
480   clearPointerContainer(m_resources);
481 }
482 
483 //-----------------------------------------------------------------------------
484 
getResources()485 void SceneResources::getResources() {
486   ToonzScene *scene = m_scene;
487   std::vector<TXshLevel *> levels;
488   scene->getLevelSet()->listLevels(levels);
489   std::vector<TXshLevel *>::iterator it;
490 
491   for (it = levels.begin(); it != levels.end(); ++it) {
492     TXshSimpleLevel *sl = (*it)->getSimpleLevel();
493     if (sl) m_resources.push_back(new SceneLevel(scene, sl));
494     TXshPaletteLevel *pl = (*it)->getPaletteLevel();
495     if (pl) m_resources.push_back(new ScenePalette(scene, pl));
496     TXshSoundLevel *sdl = (*it)->getSoundLevel();
497     if (sdl) m_resources.push_back(new SceneSound(scene, sdl));
498   }
499 }
500 
501 //-----------------------------------------------------------------------------
502 
save(const TFilePath newScenePath)503 void SceneResources::save(const TFilePath newScenePath) {
504   TFilePath oldScenePath = m_scene->getScenePath();
505   m_scene->setScenePath(newScenePath);
506   bool failedSave = false;
507   for (int i = 0; i < (int)m_resources.size(); i++) {
508     m_resources[i]->save();
509   }
510 
511   QStringList failedList;
512   getDirtyResources(failedList);
513 
514   if (!failedList.isEmpty()) {  // didn't save for some reason
515     // show up to 5 items
516     int extraCount = failedList.count() - 5;
517     if (extraCount > 0) {
518       failedList = failedList.mid(0, 5);
519       failedList.append(QObject::tr("and %1 more item(s).").arg(extraCount));
520     }
521 
522     DVGui::warning(QObject::tr("Failed to save the following resources:\n") +
523                    "  " + failedList.join("\n  "));
524   }
525   m_scene->setScenePath(oldScenePath);
526 }
527 
528 //-----------------------------------------------------------------------------
529 
updatePaths()530 void SceneResources::updatePaths() {
531   for (int i = 0; i < (int)m_resources.size(); i++)
532     m_resources[i]->updatePath();
533 }
534 
535 //-----------------------------------------------------------------------------
536 
rollbackPaths()537 void SceneResources::rollbackPaths() {
538   for (int i = 0; i < (int)m_resources.size(); i++)
539     m_resources[i]->rollbackPath();
540 }
541 
542 //-----------------------------------------------------------------------------
543 
accept(ResourceProcessor * processor,bool autoCommit)544 void SceneResources::accept(ResourceProcessor *processor, bool autoCommit) {
545   for (int i = 0; i < (int)m_resources.size() && !processor->aborted(); i++)
546     m_resources[i]->accept(processor);
547   if (autoCommit) commit();
548 }
549 
550 //-----------------------------------------------------------------------------
551 // return the name list of dirty resources
getDirtyResources(QStringList & dirtyResources)552 void SceneResources::getDirtyResources(QStringList &dirtyResources) {
553   for (SceneResource *resource : m_resources)
554     if (resource->isDirty()) {
555       dirtyResources << resource->getResourceName();
556     }
557   dirtyResources.removeDuplicates();
558 }
559 
560 //=============================================================================
561 //
562 // ResourceImporter
563 //
564 //-----------------------------------------------------------------------------
565 
ResourceImporter(ToonzScene * scene,TProject * dstProject,ResourceImportStrategy & importStrategy)566 ResourceImporter::ResourceImporter(ToonzScene *scene, TProject *dstProject,
567                                    ResourceImportStrategy &importStrategy)
568     : m_scene(scene)
569     , m_dstProject(dstProject)
570     , m_dstScene(new ToonzScene())
571     , m_importStrategy(importStrategy) {
572   m_dstScene->setProject(dstProject);
573   // scene file may not be in the "+scenes" path for the sandbox project.
574   // in such case, try to save as "+scenes/filename.tnz" on import.
575   TFilePath relativeScenePath =
576       scene->getScenePath() - scene->getProject()->getScenesPath();
577   if (relativeScenePath.isAbsolute())
578     relativeScenePath = scene->getScenePath().withoutParentDir();
579   TFilePath newFp = dstProject->getScenesPath() + relativeScenePath;
580   makeUnique(newFp);
581   m_dstScene->setScenePath(newFp);
582 }
583 
584 //-----------------------------------------------------------------------------
585 
~ResourceImporter()586 ResourceImporter::~ResourceImporter() { delete m_dstScene; }
587 
588 //-----------------------------------------------------------------------------
589 
makeUnique(TFilePath & path)590 bool ResourceImporter::makeUnique(TFilePath &path) {
591   return makePathUnique(m_dstScene, path);
592 }
593 
594 //-----------------------------------------------------------------------------
595 
getImportedScenePath() const596 TFilePath ResourceImporter::getImportedScenePath() const {
597   return m_dstScene->getScenePath();
598 }
599 
600 //-----------------------------------------------------------------------------
601 
codePath(const TFilePath & oldPath,const TFilePath & newActualPath)602 TFilePath ResourceImporter::codePath(const TFilePath &oldPath,
603                                      const TFilePath &newActualPath) {
604   return oldPath.withName(newActualPath.getName());
605 }
606 
607 //-----------------------------------------------------------------------------
608 
extractPsdSuffix(TFilePath & path)609 std::string ResourceImporter::extractPsdSuffix(TFilePath &path) {
610   if (path.getType() != "psd") return "";
611   std::string name = path.getName();
612   int i            = name.find("#");
613   if (i == std::string::npos) return "";
614   std::string suffix = name.substr(i);
615   path               = path.withName(name.substr(0, i));
616   return suffix;
617 }
618 
619 //-----------------------------------------------------------------------------
620 
buildPsd(const TFilePath & basePath,const std::string & suffix)621 TFilePath ResourceImporter::buildPsd(const TFilePath &basePath,
622                                      const std::string &suffix) {
623   return basePath.withName(basePath.getName() + suffix);
624 }
625 
626 //-----------------------------------------------------------------------------
627 
process(TXshSimpleLevel * sl)628 void ResourceImporter::process(TXshSimpleLevel *sl) {
629   if (sl->getPath().isAbsolute()) return;
630   TFilePath newPath;
631 
632   TFilePath slPath   = sl->getPath();
633   std::string suffix = extractPsdSuffix(slPath);
634 
635   TFilePath imgRefPath;
636   if (sl->getPalette()) imgRefPath = sl->getPalette()->getRefImgPath();
637   newPath = m_importStrategy.process(m_dstScene, m_scene, slPath);
638   if (imgRefPath != TFilePath() &&
639       !m_dstScene->isExternPath(m_dstScene->decodeFilePath(imgRefPath)))
640     m_importStrategy.process(m_dstScene, m_scene, imgRefPath);
641 
642   if (suffix != "") newPath = buildPsd(newPath, suffix);
643 
644   sl->setPath(newPath);
645   if (sl->getScannedPath() != TFilePath()) {
646     newPath =
647         m_importStrategy.process(m_dstScene, m_scene, sl->getScannedPath());
648     sl->setScannedPath(newPath);
649   }
650   sl->setDirtyFlag(false);
651 }
652 
653 //-----------------------------------------------------------------------------
654 
process(TXshPaletteLevel * pl)655 void ResourceImporter::process(TXshPaletteLevel *pl) {
656   if (pl->getPath().isAbsolute()) return;
657   TFilePath newPath;
658   newPath = m_importStrategy.process(m_dstScene, m_scene, pl->getPath());
659   pl->setPath(newPath);
660 }
661 
662 //-----------------------------------------------------------------------------
663 
process(TXshSoundLevel * sl)664 void ResourceImporter::process(TXshSoundLevel *sl) {
665   if (sl->getPath().isAbsolute()) return;
666   TFilePath newPath;
667   newPath = m_importStrategy.process(m_dstScene, m_scene, sl->getPath());
668   sl->setPath(newPath);
669 }
670 
671 //=============================================================================
672 //
673 // ResourceCollector
674 //
675 //-----------------------------------------------------------------------------
676 
ResourceCollector(ToonzScene * scene)677 ResourceCollector::ResourceCollector(ToonzScene *scene)
678     : m_scene(scene), m_count(0) {}
679 
680 //-----------------------------------------------------------------------------
681 
~ResourceCollector()682 ResourceCollector::~ResourceCollector() {}
683 
684 //-----------------------------------------------------------------------------
685 
makeUnique(TFilePath & path)686 bool ResourceCollector::makeUnique(TFilePath &path) {
687   return makePathUnique(m_scene, path);
688 }
689 
690 //-----------------------------------------------------------------------------
691 
process(TXshSimpleLevel * sl)692 void ResourceCollector::process(TXshSimpleLevel *sl) {
693   TFilePath path     = sl->getPath();
694   std::string suffix = ResourceImporter::extractPsdSuffix(path);
695   std::map<TFilePath, TFilePath>::iterator it = m_collectedFiles.find(path);
696   if (it != m_collectedFiles.end()) {
697     TFilePath destPath = it->second;
698     if (suffix != "") destPath = ResourceImporter::buildPsd(destPath, suffix);
699     sl->setPath(destPath);
700   } else {
701     TFilePath collectedPath = path;
702     if (getCollectedPath(m_scene, collectedPath)) {
703       TFilePath actualCollectedPath = m_scene->decodeFilePath(collectedPath);
704       if (actualCollectedPath != path && TSystem::doesExistFileOrLevel(path) &&
705           !TSystem::doesExistFileOrLevel(actualCollectedPath)) {
706         try {
707           TSystem::touchParentDir(actualCollectedPath);
708           TXshSimpleLevel::copyFiles(actualCollectedPath, path);
709         } catch (...) {
710         }
711       }
712       ++m_count;
713       TFilePath destPath = collectedPath;
714       if (suffix != "") destPath = ResourceImporter::buildPsd(destPath, suffix);
715       sl->setPath(destPath);
716       m_collectedFiles[path] = collectedPath;
717     }
718   }
719 
720   if (sl->getScannedPath() != TFilePath()) {
721     path                    = sl->getScannedPath();
722     TFilePath collectedPath = path;
723     if (getCollectedPath(m_scene, collectedPath)) {
724       TFilePath actualCollectedPath = m_scene->decodeFilePath(collectedPath);
725       if (actualCollectedPath != path && TSystem::doesExistFileOrLevel(path)) {
726         try {
727           TSystem::touchParentDir(actualCollectedPath);
728           TXshSimpleLevel::copyFiles(actualCollectedPath, path);
729         } catch (...) {
730         }
731       }
732       sl->setScannedPath(collectedPath);
733       m_count++;
734     }
735   }
736   sl->setDirtyFlag(false);
737 }
738 
739 //-----------------------------------------------------------------------------
740 
process(TXshSoundLevel * sl)741 void ResourceCollector::process(TXshSoundLevel *sl) {
742   TFilePath path          = sl->getPath();
743   TFilePath collectedPath = path;
744   if (!getCollectedPath(m_scene, collectedPath)) return;
745 
746   TFilePath actualCollectedPath = m_scene->decodeFilePath(collectedPath);
747   if (actualCollectedPath != path && TSystem::doesExistFileOrLevel(path)) {
748     try {
749       TSystem::touchParentDir(actualCollectedPath);
750       TXshSimpleLevel::copyFiles(actualCollectedPath, path);
751 
752     } catch (...) {
753     }
754   }
755   sl->setPath(collectedPath);
756   m_count++;
757 }
758 
759 //-----------------------------------------------------------------------------
760 
process(TXshPaletteLevel * pl)761 void ResourceCollector::process(TXshPaletteLevel *pl) {
762   TFilePath path          = pl->getPath();
763   TFilePath collectedPath = path;
764   if (!getCollectedPath(m_scene, collectedPath)) return;
765 
766   TFilePath actualCollectedPath = m_scene->decodeFilePath(collectedPath);
767   if (actualCollectedPath != path && TSystem::doesExistFileOrLevel(path)) {
768     try {
769       TSystem::touchParentDir(actualCollectedPath);
770       TXshSimpleLevel::copyFiles(actualCollectedPath, path);
771 
772     } catch (...) {
773     }
774   }
775   pl->setPath(collectedPath);
776   m_count++;
777 }
778