// TnzCore includes #include "tconvert.h" #include "tstream.h" // TnzLib includes #include "toonz/txshsimplelevel.h" #include "toonz/toonzscene.h" #include "toonz/levelset.h" //============================================================================= namespace { const TFilePath defaultRootFolder("Cast"); const TFilePath defaultSoundRootFolder("Audio"); } //============================================================================= // TLevelSet TLevelSet::TLevelSet() : m_defaultFolder(defaultRootFolder) { m_folders.push_back(defaultRootFolder); m_folders.push_back(defaultSoundRootFolder); } //----------------------------------------------------------------------------- TLevelSet::~TLevelSet() { clear(); } //----------------------------------------------------------------------------- void TLevelSet::clear() { for (std::vector::iterator it = m_levels.begin(); it != m_levels.end(); ++it) { TXshLevel *level = *it; if (level->getSimpleLevel()) level->getSimpleLevel()->clearFrames(); (*it)->release(); } m_levelTable.clear(); m_levels.clear(); m_folderTable.clear(); m_folders.clear(); m_folders.push_back(defaultRootFolder); m_folders.push_back(defaultSoundRootFolder); m_defaultFolder = defaultRootFolder; } //----------------------------------------------------------------------------- void TLevelSet::removeLevel(TXshLevel *level, bool deleteIt) { // if(level->getSimpleLevel()) // level->getSimpleLevel()->clearFrames(); m_levels.erase(std::remove(m_levels.begin(), m_levels.end(), level), m_levels.end()); m_levelTable.erase(level->getName()); if (deleteIt) level->release(); m_folderTable.erase(level); } //----------------------------------------------------------------------------- bool TLevelSet::renameLevel(TXshLevel *level, const std::wstring &newName) { if (level->getName() == newName) return true; if (m_levelTable.count(newName) > 0) return false; m_levelTable.erase(level->getName()); level->setName(newName); m_levelTable[newName] = level; return true; } //----------------------------------------------------------------------------- int TLevelSet::getLevelCount() const { return m_levels.size(); } //----------------------------------------------------------------------------- TXshLevel *TLevelSet::getLevel(int index) const { assert(0 <= index && index < getLevelCount()); return m_levels[index]; } //----------------------------------------------------------------------------- TXshLevel *TLevelSet::getLevel(const std::wstring &levelName) const { std::map::const_iterator it; it = m_levelTable.find(levelName); if (it == m_levelTable.end()) return 0; else return it->second; } //----------------------------------------------------------------------------- TXshLevel *TLevelSet::getLevel(const ToonzScene &scene, const TFilePath &levelPath) const { const TFilePath &decodedPath = scene.decodeFilePath(levelPath); int l, lCount = getLevelCount(); for (l = 0; l != lCount; ++l) { TXshLevel *level = getLevel(l); if (decodedPath == scene.decodeFilePath(level->getPath())) return level; } return 0; } //----------------------------------------------------------------------------- bool TLevelSet::hasLevel(const std::wstring &levelName) const { std::vector::const_iterator it = m_levels.begin(); for (auto const level : m_levels) { if (levelName == level->getName()) return true; } return false; } //----------------------------------------------------------------------------- bool TLevelSet::hasLevel(const ToonzScene &scene, const TFilePath &levelPath) const { return getLevel(scene, levelPath); } //----------------------------------------------------------------------------- void TLevelSet::listLevels(std::vector &levels) const { levels = m_levels; } //----------------------------------------------------------------------------- bool TLevelSet::insertLevel(TXshLevel *xl) { std::map::const_iterator it; it = m_levelTable.find(xl->getName()); if (it != m_levelTable.end() && it->second == xl) return it->second == xl; else { xl->addRef(); m_levelTable[xl->getName()] = xl; m_levels.push_back(xl); TFilePath folder = (xl->getSoundLevel()) ? defaultSoundRootFolder : m_defaultFolder; m_folderTable[xl] = folder; assert(std::find(m_folders.begin(), m_folders.end(), folder) != m_folders.end()); return true; } } //----------------------------------------------------------------------------- void TLevelSet::setDefaultFolder(TFilePath folder) { assert(std::find(m_folders.begin(), m_folders.end(), folder) != m_folders.end()); m_defaultFolder = folder; } //----------------------------------------------------------------------------- TFilePath TLevelSet::getFolder(TXshLevel *xl) const { std::map::const_iterator it; it = m_folderTable.find(xl); assert(it != m_folderTable.end()); return it->second; } //----------------------------------------------------------------------------- TFilePath TLevelSet::renameFolder(const TFilePath &folder, const std::wstring &newName) { // Impedisco la creazione di folder con nome "" che creano problemi // (praticamente Ecome se avessero infinite sottocartelle) if (newName == L"") return folder; TFilePath folder2 = folder.withName(newName); for (int i = 0; i < (int)m_folders.size(); i++) { if (folder == m_folders[i]) m_folders[i] = folder2; else if (folder.isAncestorOf(m_folders[i])) m_folders[i] = folder2 + (m_folders[i] - folder); } if (m_defaultFolder == folder) m_defaultFolder = folder2; std::map::iterator it; for (it = m_folderTable.begin(); it != m_folderTable.end(); ++it) { if (folder == it->second) it->second = folder2; else if (folder.isAncestorOf(it->second)) it->second = folder2 + (it->second - folder); } return folder2; } //----------------------------------------------------------------------------- TFilePath TLevelSet::createFolder(const TFilePath &parentFolder, const std::wstring &newName) { TFilePath child = parentFolder + newName; if (std::find(m_folders.begin(), m_folders.end(), child) == m_folders.end()) m_folders.push_back(child); return child; } //----------------------------------------------------------------------------- void TLevelSet::removeFolder(const TFilePath &folder) { if (folder == m_defaultFolder) return; std::vector folders; for (int i = 0; i < (int)m_folders.size(); i++) if (!folder.isAncestorOf(m_folders[i])) folders.push_back(m_folders[i]); folders.swap(m_folders); std::map::iterator it; for (it = m_folderTable.begin(); it != m_folderTable.end(); ++it) { if (folder.isAncestorOf(it->second)) it->second = m_defaultFolder; } } //----------------------------------------------------------------------------- void TLevelSet::listLevels(std::vector &levels, const TFilePath &folder) const { std::map::const_iterator it; for (it = m_folderTable.begin(); it != m_folderTable.end(); ++it) if (folder == it->second) levels.push_back(it->first); } //----------------------------------------------------------------------------- void TLevelSet::listFolders(std::vector &folders, const TFilePath &folder) const { for (int i = 0; i < (int)m_folders.size(); i++) if (m_folders[i].getParentDir() == folder) folders.push_back(m_folders[i]); } //----------------------------------------------------------------------------- void TLevelSet::moveLevelToFolder(const TFilePath &fp, TXshLevel *level) { TFilePath folder(fp); if (folder == TFilePath()) folder = m_defaultFolder; if (std::find(m_folders.begin(), m_folders.end(), folder) == m_folders.end()) { assert(0); return; } std::map::iterator it; it = m_folderTable.find(level); assert(it != m_folderTable.end()); if (it == m_folderTable.end()) return; it->second = folder; } //----------------------------------------------------------------------------- void TLevelSet::saveFolder(TOStream &os, TFilePath folder) { std::map attr; attr["name"] = folder.getName(); if (folder == getDefaultFolder()) attr["type"] = "default"; os.openChild("folder", attr); std::vector folders; listFolders(folders, folder); if (!folders.empty()) { for (int i = 0; i < (int)folders.size(); i++) saveFolder(os, folders[i]); } std::vector levels; listLevels(levels, folder); if (!levels.empty()) { os.openChild("levels"); for (int i = 0; i < (int)levels.size(); i++) if (m_saveSet.empty() || m_saveSet.count(levels[i]) > 0) os << levels[i]; os.closeChild(); } os.closeChild(); } //----------------------------------------------------------------------------- void TLevelSet::loadFolder(TIStream &is, TFilePath folder) { std::string s; is.getTagParam("type", s); if (s == "default") setDefaultFolder(folder); while (!is.eos()) { std::string tagName; is.matchTag(tagName); if (tagName == "levels") { while (!is.eos()) { TPersist *p = 0; is >> p; TXshLevel *xshLevel = dynamic_cast(p); if (xshLevel && !xshLevel->getChildLevel()) moveLevelToFolder(folder, xshLevel); } } else if (tagName == "folder") { is.getTagParam("name", s); TFilePath child = createFolder(folder, ::to_wstring(s)); loadFolder(is, child); } else throw TException("expected or "); is.closeChild(); } } //----------------------------------------------------------------------------- void TLevelSet::loadData(TIStream &is) { int folderCount = 1; while (!is.eos()) { std::string tagName; if (is.matchTag(tagName)) { if (tagName == "levels") { while (!is.eos()) { TPersist *p = 0; is >> p; TXshLevel *xshLevel = dynamic_cast(p); if (xshLevel) { insertLevel(xshLevel); } } } else if (tagName == "folder") { std::string name = ::to_string(defaultRootFolder.getWideString()); is.getTagParam("name", name); TFilePath folder(name); if (folderCount == 1) m_defaultFolder = m_folders[0] = folder; else if (name != defaultSoundRootFolder.getName()) m_folders.push_back(folder); folderCount++; loadFolder(is, folder); } else throw TException("expected or "); is.closeChild(); } else throw TException("expected tag"); } } //----------------------------------------------------------------------------- void TLevelSet::saveData(TOStream &os) { os.openChild("levels"); int i; for (i = 0; i < getLevelCount(); i++) { TXshLevel *level = getLevel(i); if (m_saveSet.empty() || m_saveSet.count(level) > 0) os << level; } os.closeChild(); std::vector folders; listFolders(folders, TFilePath()); assert(!folders.empty()); for (i = 0; i < (int)folders.size(); i++) saveFolder(os, folders[i]); }