| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| TOfflineGL *currentOfflineGL = 0; |
| |
| |
| |
| |
| |
| namespace |
| { |
| |
| const VersionNumber l_currentVersion(71, 0); |
| |
| |
| |
| string getFolderName(int levelType) |
| { |
| switch (levelType) { |
| case TZI_XSHLEVEL: |
| return TProject::Inputs; |
| case PLI_XSHLEVEL: |
| return TProject::Drawings; |
| case TZP_XSHLEVEL: |
| return TProject::Drawings; |
| case OVL_XSHLEVEL: |
| return TProject::Extras; |
| default: |
| return TProject::Extras; |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| TFilePath getUntitledScenesDir() |
| { |
| return ToonzFolder::getCacheRootFolder() + "temp"; |
| } |
| |
| |
| |
| |
| bool checkTail(TFilePath path, TFilePath tail, TFilePath &head) |
| { |
| for (;;) { |
| if (tail == TFilePath()) { |
| head = path; |
| return true; |
| } |
| if (path == TFilePath()) |
| return false; |
| if (path.withoutParentDir() != tail.withoutParentDir()) |
| return false; |
| path = path.getParentDir(); |
| tail = tail.getParentDir(); |
| } |
| } |
| |
| |
| |
| void makeSceneIcon(ToonzScene *scene) |
| { |
| TDimension cameraSize = scene->getCurrentCamera()->getRes(); |
| |
| int maxSize = 128; |
| TDimension iconCameraSize = cameraSize; |
| if (cameraSize.lx > cameraSize.ly) { |
| iconCameraSize.ly = maxSize * cameraSize.ly / cameraSize.lx; |
| iconCameraSize.lx = maxSize; |
| } else { |
| iconCameraSize.lx = maxSize * cameraSize.lx / cameraSize.ly; |
| iconCameraSize.ly = maxSize; |
| } |
| |
| TRaster32P ras(iconCameraSize); |
| TPixel32 bgColor = scene->getProperties()->getBgColor(); |
| ras->fill(bgColor); |
| scene->renderFrame(ras, 0); |
| |
| TFilePath iconPath = scene->getIconPath(); |
| if (TSystem::touchParentDir(iconPath)) |
| TImageWriter::save(iconPath, ras); |
| } |
| |
| |
| |
| void deleteUntitledScene(const TFilePath &fp) |
| { |
| if (TFileStatus(fp).isDirectory()) { |
| TFilePath tempDir = getUntitledScenesDir(); |
| if (TFileStatus(tempDir).isDirectory() && |
| tempDir.isAncestorOf(fp)) |
| { |
| try { |
| TSystem::rmDirTree(fp); |
| } catch (...) { |
| assert(0); |
| } |
| } else |
| assert(0); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| void fixBiancoProblem(ToonzScene *scene, TXsheet *xsh) |
| { |
| TLevelSet *levelSet = scene->getLevelSet(); |
| std::set<TXsheet *> visited, tovisit; |
| tovisit.insert(xsh); |
| while (!tovisit.empty()) { |
| xsh = *tovisit.begin(); |
| xsh->setScene(scene); |
| visited.insert(xsh); |
| tovisit.erase(xsh); |
| int c0 = 0, c1 = xsh->getColumnCount() - 1; |
| for (int c = c0; c <= c1; c++) { |
| if (xsh->isColumnEmpty(c)) |
| continue; |
| TXshColumn *column = xsh->getColumn(c); |
| if (!column || !column->getLevelColumn()) |
| continue; |
| TXshLevelColumn *lcolumn = column->getLevelColumn(); |
| int r0 = 0, r1 = -1; |
| lcolumn->getRange(r0, r1); |
| for (int r = r0; r <= r1; r++) { |
| TXshCell cell = lcolumn->getCell(r); |
| if (cell.isEmpty()) |
| continue; |
| TXshLevel *xl = cell.m_level.getPointer(); |
| scene->getLevelSet()->insertLevel(xl); |
| xl->setScene(scene); |
| if (TXshChildLevel *childLevel = xl->getChildLevel()) { |
| TXsheet *childXsh = childLevel->getXsheet(); |
| if (visited.count(childXsh) > 0) |
| continue; |
| tovisit.insert(childXsh); |
| } else { |
| TXshLevel *xl2 = levelSet->getLevel(xl->getName()); |
| if (xl2) { |
| if (xl2 != xl) { |
| cell.m_level = xl2; |
| lcolumn->setCell(r, cell); |
| } |
| } else { |
| xl->setScene(scene); |
| levelSet->insertLevel(xl); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| } |
| |
| |
| |
| |
| void deleteAllUntitledScenes() |
| { |
| TFilePath tempDir = getUntitledScenesDir(); |
| try { |
| if (TFileStatus(tempDir).isDirectory()) { |
| TFilePathSet fps; |
| TSystem::readDirectory(fps, tempDir); |
| TFilePathSet::iterator fpsIt; |
| for (fpsIt = fps.begin(); fpsIt != fps.end(); ++fpsIt) { |
| TFilePath fp = *fpsIt; |
| if (TFileStatus(fp).isDirectory() && fp.getName().find("untitled") != -1) |
| TSystem::rmDirTree(fp); |
| } |
| } |
| } catch (...) { |
| } |
| } |
| |
| |
| |
| |
| ToonzScene::ToonzScene() |
| : m_contentHistory(0), m_isUntitled(true) |
| { |
| m_childStack = new ChildStack(this); |
| m_properties = new TSceneProperties(); |
| m_levelSet = new TLevelSet(); |
| m_project = new TProject(); |
| m_project->addRef(); |
| } |
| |
| |
| |
| ToonzScene::~ToonzScene() |
| { |
| delete m_properties; |
| delete m_levelSet; |
| delete m_childStack; |
| delete m_contentHistory; |
| |
| assert(m_project); |
| if (m_project) |
| m_project->release(); |
| } |
| |
| |
| |
| void ToonzScene::setSceneName(wstring name) |
| { |
| m_scenePath = m_scenePath.withName(name); |
| } |
| |
| |
| |
| void ToonzScene::clear() |
| { |
| if (isUntitled()) |
| deleteUntitledScene(getScenePath().getParentDir()); |
| |
| m_childStack->clear(); |
| |
| m_scenePath = TFilePath(); |
| TSceneProperties *properties = m_properties; |
| m_properties = new TSceneProperties(); |
| delete properties; |
| m_levelSet->clear(); |
| } |
| |
| |
| |
| void ToonzScene::setProject(TProject *project) |
| { |
| assert(project); |
| |
| if (project != m_project) { |
| if (project) |
| project->addRef(); |
| if (m_project) |
| m_project->release(); |
| m_project = project; |
| } |
| } |
| |
| |
| |
| TProject *ToonzScene::getProject() const |
| { |
| return m_project; |
| } |
| |
| |
| |
| void ToonzScene::setScenePath(const TFilePath &fp) |
| { |
| m_scenePath = fp; |
| m_isUntitled = false; |
| } |
| |
| |
| |
| bool ToonzScene::isUntitled() const |
| { |
| return m_scenePath == TFilePath() || m_isUntitled; |
| } |
| |
| |
| |
| void ToonzScene::load(const TFilePath &path, bool withProgressDialog) |
| { |
| loadNoResources(path); |
| loadResources(withProgressDialog); |
| |
| setVersionNumber(VersionNumber()); |
| } |
| |
| |
| |
| |
| |
| int ToonzScene::loadFrameCount(const TFilePath &fp) |
| { |
| TIStream is(fp); |
| if (!is) |
| throw TException(fp.getWideString() + L": Can't open file"); |
| try { |
| |
| string tagName = ""; |
| if (!is.matchTag(tagName)) |
| throw TException("Bad file format"); |
| |
| if (tagName == "tab" || tagName == "tnz") { |
| int frameCount; |
| if (is.getTagParam("framecount", frameCount)) |
| return frameCount; |
| else |
| return 0; |
| } else |
| throw TException("Bad file format"); |
| } catch (TException &e) { |
| throw TIStreamException(is, e); |
| } catch (...) { |
| throw TIStreamException(is); |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| void ToonzScene::loadNoResources(const TFilePath &fp) |
| { |
| clear(); |
| |
| TProjectManager *pm = TProjectManager::instance(); |
| TProjectP sceneProject = pm->loadSceneProject(fp); |
| if (!sceneProject) |
| return; |
| |
| setProject(sceneProject.getPointer()); |
| |
| loadTnzFile(fp); |
| getXsheet()->updateFrameCount(); |
| } |
| |
| |
| |
| void ToonzScene::loadResources(bool withProgressDialog) |
| { |
| |
| QProgressDialog *progressDialog = 0; |
| if (withProgressDialog && m_levelSet->getLevelCount() >= 10) { |
| progressDialog = new QProgressDialog("Loading Scene Resources", "", 0, m_levelSet->getLevelCount()); |
| progressDialog->setModal(true); |
| progressDialog->setAutoReset(true); |
| progressDialog->setAutoClose(true); |
| progressDialog->setAttribute(Qt::WA_DeleteOnClose, true); |
| progressDialog->setCancelButton(0); |
| progressDialog->setValue(0); |
| progressDialog->show(); |
| } |
| |
| int i; |
| for (i = 0; i < m_levelSet->getLevelCount(); i++) { |
| if (progressDialog) |
| progressDialog->setValue(i + 1); |
| |
| TXshLevel *level = m_levelSet->getLevel(i); |
| try { |
| level->load(); |
| } catch (...) { |
| } |
| } |
| getXsheet()->updateFrameCount(); |
| } |
| |
| |
| |
| void ToonzScene::loadTnzFile(const TFilePath &fp) |
| { |
| bool reading22 = false; |
| TIStream is(fp); |
| if (!is) |
| throw TException(fp.getWideString() + L": Can't open file"); |
| try { |
| string tagName = ""; |
| if (!is.matchTag(tagName)) |
| throw TException("Bad file format"); |
| |
| if (tagName == "tab" || tagName == "tnz") { |
| string rootTagName = tagName; |
| string v = is.getTagAttribute("version"); |
| VersionNumber versionNumber(0, 0); |
| int k = v.find("."); |
| if (k != (int)string::npos && 0 < k && k < (int)v.length()) { |
| versionNumber.first = toInt(v.substr(0, k)); |
| versionNumber.second = toInt(v.substr(k + 1)); |
| } |
| if (versionNumber == VersionNumber(0, 0)) |
| throw TException("Bad version number :" + v); |
| setVersionNumber(versionNumber); |
| is.setVersion(versionNumber); |
| while (is.matchTag(tagName)) { |
| if (tagName == "generator") { |
| string program = is.getString(); |
| reading22 = program.find("2.2") != string::npos; |
| } else if (tagName == "properties") |
| m_properties->loadData(is, false); |
| else if (tagName == "palette") |
| { |
| TPalette *palette = new TPalette; |
| is >> *palette; |
| delete palette; |
| } else if (tagName == "levelSet") |
| m_levelSet->loadData(is); |
| else if (tagName == "levels") { |
| |
| if (!reading22) |
| assert(0); |
| while (!is.eos()) { |
| TPersist *p = 0; |
| is >> p; |
| TXshLevel *xshLevel = dynamic_cast<TXshLevel *>(p); |
| if (xshLevel) { |
| xshLevel->setScene(this); |
| TXshSimpleLevel *sl = xshLevel->getSimpleLevel(); |
| if (reading22 && sl && sl->getPath() == TFilePath()) { |
| sl->setType(PLI_XSHLEVEL); |
| sl->setPath(TFilePath("+drawings/") + (sl->getName() + L".pli")); |
| } |
| m_levelSet->insertLevel(xshLevel); |
| } |
| } |
| } else if (tagName == "xsheet") |
| is >> *getXsheet(); |
| else if (tagName == "history") { |
| std::string historyData, s; |
| while (!is.eos()) { |
| is >> s; |
| historyData += s; |
| } |
| TContentHistory *history = getContentHistory(true); |
| history->deserialize(QString::fromStdString(historyData)); |
| } else |
| throw TException(tagName + " : unexpected tag"); |
| |
| if (!is.matchEndTag()) |
| throw TException(tagName + " : missing end tag"); |
| } |
| if (!is.matchEndTag()) |
| throw TException(rootTagName + " : missing end tag"); |
| } else |
| throw TException("Bad file format"); |
| |
| setScenePath(fp); |
| |
| for (int i = 0; i < m_levelSet->getLevelCount(); i++) |
| m_levelSet->getLevel(i)->setScene(this); |
| |
| } catch (TException &e) { |
| throw TIStreamException(is, e); |
| } catch (...) { |
| throw TIStreamException(is); |
| } |
| |
| m_properties->cloneCamerasTo(getXsheet()->getStageObjectTree()); |
| fixBiancoProblem(this, getXsheet()); |
| } |
| |
| |
| |
| |
| |
| |
| |
| void ToonzScene::setUntitled() |
| { |
| m_isUntitled = true; |
| const string baseName = "untitled"; |
| TFilePath tempDir = getUntitledScenesDir(); |
| if (TFileStatus(tempDir).doesExist() == false) { |
| try { |
| TSystem::mkDir(tempDir); |
| } catch (...) { |
| } |
| } |
| |
| string name = baseName; |
| if (TFileStatus(tempDir + name).doesExist()) { |
| int count = 2; |
| do { |
| name = baseName + toString(count++); |
| } while (TFileStatus(tempDir + name).doesExist()); |
| } |
| TFilePath fp = tempDir + name + (name + ".tnz"); |
| try { |
| TSystem::touchParentDir(fp); |
| } catch (...) { |
| assert(0); |
| } |
| m_scenePath = fp; |
| } |
| |
| |
| |
| |
| |
| class CameraRedirection |
| { |
| ToonzScene *m_scene; |
| TXsheet *m_xsh; |
| |
| public: |
| CameraRedirection(ToonzScene *scene, TXsheet *xsh) |
| : m_scene(scene), m_xsh(xsh) |
| { |
| if (!xsh) |
| xsh = m_scene->getTopXsheet(); |
| |
| m_scene->getProperties()->cloneCamerasFrom(xsh->getStageObjectTree()); |
| } |
| |
| ~CameraRedirection() |
| { |
| if (m_xsh) |
| m_scene->getProperties()->cloneCamerasFrom(m_scene->getTopXsheet()->getStageObjectTree()); |
| } |
| }; |
| |
| |
| |
| void ToonzScene::save(const TFilePath &fp, TXsheet *subxsh) |
| { |
| TFilePath oldScenePath = getScenePath(); |
| TFilePath newScenePath = fp; |
| |
| CameraRedirection redir(this, subxsh); |
| |
| bool wasUntitled = isUntitled(); |
| |
| setScenePath(fp); |
| |
| TFileStatus fs(newScenePath); |
| if (fs.doesExist() && !fs.isWritable()) |
| throw TSystemException(newScenePath, "The scene cannot be saved: it is a read only scene.\n All resources have been saved."); |
| |
| TFilePath scenePath = decodeFilePath(fp); |
| |
| |
| |
| TSystem::touchFile(scenePath); |
| makeSceneIcon(this); |
| |
| |
| TOStream os(scenePath, false); |
| if (!os.checkStatus()) |
| throw TException("Could not open file"); |
| |
| TXsheet *xsh = subxsh; |
| if (xsh == 0) |
| xsh = m_childStack->getTopXsheet(); |
| |
| std::map<string, string> attr; |
| attr["version"] = (QString::number(l_currentVersion.first) + "." |
| + QString::number(l_currentVersion.second)) |
| .toStdString(); |
| attr["framecount"] = QString::number( |
| xsh->getFrameCount()) |
| .toStdString(); |
| |
| os.openChild("tnz", attr); |
| |
| os.child("generator") << TEnv::getApplicationFullName(); |
| os.openChild("properties"); |
| m_properties->saveData(os); |
| os.closeChild(); |
| |
| if (subxsh) { |
| std::set<TXshLevel *> saveSet; |
| subxsh->getUsedLevels(saveSet); |
| m_levelSet->setSaveSet(saveSet); |
| } |
| os.openChild("levelSet"); |
| m_levelSet->saveData(os); |
| os.closeChild(); |
| std::set<TXshLevel *> emptySaveSet; |
| m_levelSet->setSaveSet(emptySaveSet); |
| |
| os.openChild("xsheet"); |
| os << *xsh; |
| os.closeChild(); |
| |
| if (getContentHistory()) { |
| os.openChild("history"); |
| QString data = getContentHistory()->serialize(); |
| int i = 0, j; |
| |
| |
| while ((j = data.indexOf("||", i)) >= i) { |
| os << data.mid(i, j - i + 1).toStdWString(); |
| os.cr(); |
| i = j + 1; |
| } |
| os << data.mid(i).toStdWString(); |
| os.closeChild(); |
| } |
| |
| os.closeChild(); |
| bool status = os.checkStatus(); |
| if (!status) |
| throw TException("Could not complete the save"); |
| |
| if (subxsh) { |
| setScenePath(oldScenePath); |
| if (wasUntitled) |
| setUntitled(); |
| } else { |
| if (wasUntitled) |
| deleteUntitledScene(oldScenePath.getParentDir()); |
| } |
| } |
| |
| |
| |
| int ToonzScene::getFrameCount() const |
| { |
| TXsheet *xsh = getXsheet(); |
| return xsh ? xsh->getFrameCount() : 0; |
| } |
| |
| |
| |
| void ToonzScene::renderFrame(const TRaster32P &ras, int row, const TXsheet *xsh, bool checkFlags) const |
| { |
| if (xsh == 0) |
| xsh = getXsheet(); |
| |
| TCamera *camera = xsh->getStageObjectTree()->getCurrentCamera(); |
| TDimension cameraRes = camera->getRes(); |
| TDimensionD cameraSize = camera->getSize(); |
| |
| |
| double sx = (double)ras->getLx() / (double)cameraSize.lx; |
| double sy = (double)ras->getLy() / (double)cameraSize.ly; |
| double sc = (sx < sy) ? sx : sy; |
| |
| const TAffine &cameraAff = xsh->getPlacement(xsh->getStageObjectTree()->getCurrentCameraId(), row); |
| const TAffine &viewAff = TScale(sc / Stage::inch) * cameraAff.inv(); |
| |
| TRect clipRect(ras->getBounds()); |
| TOfflineGL ogl(ras->getSize()); |
| currentOfflineGL = &ogl; |
| |
| ogl.makeCurrent(); |
| { |
| glTranslated(0.5 * ras->getLx(), 0.5 * ras->getLy(), 0.0); |
| |
| glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
| glClear(GL_COLOR_BUFFER_BIT); |
| |
| ImagePainter::VisualSettings vs; |
| vs.m_plasticVisualSettings.m_drawMeshesWireframe = false; |
| |
| Stage::RasterPainter painter(ras->getSize(), viewAff, clipRect, vs, checkFlags); |
| Stage::visit(painter, const_cast<ToonzScene *>(this), const_cast<TXsheet *>(xsh), row); |
| |
| painter.flushRasterImages(); |
| glFlush(); |
| |
| TRop::over(ras, ogl.getRaster()); |
| } |
| ogl.doneCurrent(); |
| |
| currentOfflineGL = 0; |
| } |
| |
| |
| |
| |
| |
| void ToonzScene::renderFrame(const TRaster32P &ras, int row, const TXsheet *xsh, |
| const TRectD &placedRect, const TAffine &worldToPlacedAff) const |
| { |
| |
| const TAffine &placedToOglRefAff = |
| TScale(ras->getLx() / placedRect.getLx(), ras->getLy() / placedRect.getLy()) * |
| TTranslation(-0.5 * (placedRect.x0 + placedRect.x1), -0.5 * (placedRect.y0 + placedRect.y1)); |
| |
| const TAffine &cameraAff = xsh->getPlacement(xsh->getStageObjectTree()->getCurrentCameraId(), row); |
| |
| const TAffine &worldToOglRefAff = placedToOglRefAff * worldToPlacedAff * cameraAff.inv(); |
| |
| TRect clipRect(ras->getBounds()); |
| |
| TOfflineGL ogl(ras->getSize()); |
| currentOfflineGL = &ogl; |
| |
| ogl.makeCurrent(); |
| { |
| glTranslated(0.5 * ras->getLx(), 0.5 * ras->getLy(), 0.0); |
| |
| glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
| glClear(GL_COLOR_BUFFER_BIT); |
| |
| ImagePainter::VisualSettings vs; |
| vs.m_plasticVisualSettings.m_drawMeshesWireframe = false; |
| |
| Stage::RasterPainter painter(ras->getSize(), worldToOglRefAff, clipRect, vs, false); |
| Stage::visit(painter, const_cast<ToonzScene *>(this), const_cast<TXsheet *>(xsh), row); |
| |
| painter.flushRasterImages(); |
| glFlush(); |
| |
| TRop::over(ras, ogl.getRaster()); |
| } |
| ogl.doneCurrent(); |
| |
| currentOfflineGL = 0; |
| } |
| |
| |
| |
| TXshLevel *ToonzScene::createNewLevel(int type, wstring levelName, const TDimension &dim, double dpi, TFilePath fp) |
| { |
| TLevelSet *levelSet = getLevelSet(); |
| |
| if (type == TZI_XSHLEVEL) |
| type = OVL_XSHLEVEL; |
| |
| if (type == CHILD_XSHLEVEL && levelName == L"") |
| levelName = L"sub"; |
| |
| |
| { |
| const std::auto_ptr<NameBuilder> nameBuilder(NameBuilder::getBuilder(levelName)); |
| |
| for (;;) { |
| levelName = nameBuilder->getNext(); |
| |
| if (m_levelSet->getLevel(levelName) != 0) |
| continue; |
| |
| |
| if (type != CHILD_XSHLEVEL && type != PLT_XSHLEVEL) { |
| if (fp.isEmpty()) |
| fp = getDefaultLevelPath(type, levelName); |
| TFilePath actualFp = decodeFilePath(fp); |
| |
| if (TSystem::doesExistFileOrLevel(actualFp)) |
| { |
| fp = TFilePath(); |
| continue; |
| } |
| |
| int l, lCount = levelSet->getLevelCount(); |
| for (l = 0; l != lCount; ++l) { |
| TXshLevel *xl = levelSet->getLevel(l); |
| if (!xl) |
| continue; |
| |
| TXshSimpleLevel *sl = xl->getSimpleLevel(); |
| if (!sl) |
| continue; |
| |
| TFilePath lfp = decodeFilePath(sl->getPath()); |
| if (actualFp == lfp) |
| break; |
| } |
| |
| if (l < lCount) { |
| |
| fp = TFilePath(); |
| continue; |
| } |
| } |
| break; |
| } |
| } |
| |
| TXshLevel *xl = 0; |
| if (type == CHILD_XSHLEVEL) { |
| TXshChildLevel *cl = new TXshChildLevel(levelName); |
| cl->setScene(this); |
| cl->getXsheet()->setScene(this); |
| xl = cl; |
| |
| |
| const TSceneProperties &props = |
| TProjectManager::instance()->getCurrentProject()->getSceneProperties(); |
| |
| props.cloneCamerasTo(cl->getXsheet()->getStageObjectTree()); |
| } else if (type == PLT_XSHLEVEL) { |
| TXshPaletteLevel *pl = new TXshPaletteLevel(levelName); |
| pl->setScene(this); |
| xl = pl; |
| } else { |
| TXshSimpleLevel *sl = new TXshSimpleLevel(levelName); |
| |
| sl->setScene(this); |
| sl->setType(type); |
| sl->setPath(fp); |
| sl->setDirtyFlag(true); |
| |
| if (type == TZP_XSHLEVEL || type == PLI_XSHLEVEL) |
| sl->setPalette(new TPalette()); |
| |
| if (type == OVL_XSHLEVEL) |
| sl->setPalette(FullColorPalette::instance()->getPalette(this)); |
| |
| TPalette *palette = sl->getPalette(); |
| if (palette && type != OVL_XSHLEVEL) { |
| palette->setPaletteName(sl->getName()); |
| palette->setDirtyFlag(true); |
| } |
| |
| if (type == TZP_XSHLEVEL || type == OVL_XSHLEVEL) { |
| sl->getProperties()->setDpiPolicy(LevelProperties::DP_ImageDpi); |
| if (dim == TDimension()) { |
| Preferences *pref = Preferences::instance(); |
| double w = pref->getDefLevelWidth(); |
| double h = pref->getDefLevelHeight(); |
| dpi = pref->getDefLevelDpi(); |
| sl->getProperties()->setImageRes(TDimension(tround(w * dpi), tround(h * dpi))); |
| } else |
| sl->getProperties()->setImageRes(dim); |
| |
| sl->getProperties()->setImageDpi(TPointD(dpi, dpi)); |
| sl->getProperties()->setDpi(dpi); |
| } |
| |
| xl = sl; |
| } |
| |
| m_levelSet->insertLevel(xl); |
| TNotifier::instance()->notify(TCastChange()); |
| |
| return xl; |
| } |
| |
| |
| |
| TXsheet *ToonzScene::getXsheet() const |
| { |
| return m_childStack->getXsheet(); |
| } |
| |
| |
| |
| TXsheet *ToonzScene::getTopXsheet() const |
| { |
| return m_childStack->getTopXsheet(); |
| } |
| |
| |
| |
| struct LevelType { |
| int m_ltype; |
| bool m_oldLevelFlag; |
| bool m_vectorNotPli; |
| std::string m_ext; |
| }; |
| |
| |
| |
| LevelType getLevelType(const TFilePath &fp) |
| { |
| LevelType ret; |
| ret.m_ltype = UNKNOWN_XSHLEVEL; |
| ret.m_oldLevelFlag = false; |
| ret.m_vectorNotPli = false; |
| ret.m_ext = fp.getType(); |
| std::string format = ret.m_ext; |
| |
| TFileType::Type type = TFileType::getInfo(fp); |
| |
| switch (type) { |
| case TFileType::RASTER_IMAGE: |
| case TFileType::RASTER_LEVEL: |
| case TFileType::CMAPPED_LEVEL: { |
| if (format == "tzp" || format == "tzu") { |
| ret.m_ltype = TZP_XSHLEVEL; |
| ret.m_oldLevelFlag = true; |
| ret.m_ext = "tlv"; |
| } else if (format == "tzl" || format == "tlv") |
| ret.m_ltype = TZP_XSHLEVEL; |
| else if (format == "tzi") |
| ret.m_ltype = TZI_XSHLEVEL; |
| else |
| ret.m_ltype = OVL_XSHLEVEL; |
| } |
| |
| CASE TFileType::VECTOR_LEVEL: |
| { |
| if (format == "svg") { |
| ret.m_vectorNotPli = true; |
| ret.m_ext = "pli"; |
| } |
| |
| |
| ret.m_ltype = PLI_XSHLEVEL; |
| } |
| |
| CASE TFileType::AUDIO_LEVEL : |
| |
| ret.m_ltype = SND_XSHLEVEL; |
| |
| CASE TFileType::MESH_IMAGE : case TFileType::MESH_LEVEL : |
| |
| ret.m_ltype = MESH_XSHLEVEL; |
| } |
| |
| return ret; |
| } |
| |
| |
| |
| TFilePath ToonzScene::getImportedLevelPath(const TFilePath path) const |
| { |
| if (TFileType::getInfo(path) == TFileType::AUDIO_LEVEL) |
| return path.withParentDir(TFilePath("+extras")); |
| else if (TFileType::getInfo(path) == TFileType::PALETTE_LEVEL) |
| return path.withParentDir(TFilePath("+palettes")); |
| |
| const LevelType <ype = getLevelType(path); |
| if (ltype.m_ltype == UNKNOWN_XSHLEVEL) |
| return path; |
| |
| const std::wstring &levelName = path.getWideName(); |
| const std::string &ext = path.getType(), |
| &dots = path.getDots(); |
| |
| TFilePath importedLevelPath = |
| getDefaultLevelPath(ltype.m_ltype, levelName).getParentDir() + (levelName + toWideString(dots + ext)); |
| |
| if (dots == "..") |
| importedLevelPath = importedLevelPath.withFrame(TFrameId::EMPTY_FRAME); |
| |
| if (importedLevelPath.getType() == "tlv") |
| importedLevelPath = importedLevelPath.withNoFrame(); |
| |
| return importedLevelPath; |
| } |
| |
| |
| |
| |
| bool ToonzScene::convertLevelIfNeeded(TFilePath &levelPath) |
| { |
| LevelType ltype = getLevelType(levelPath); |
| TFilePath fp = levelPath; |
| if (ltype.m_vectorNotPli) { |
| |
| levelPath = levelPath.withType("pli"); |
| TLevelWriterP lw(levelPath); |
| TLevelReaderP lr(fp); |
| if (!lr) |
| return false; |
| TLevelP inLevel = lr->loadInfo(); |
| if (!inLevel || inLevel->getFrameCount() == 0) |
| return false; |
| TLevelP outLevel; |
| for (TLevel::Iterator it = inLevel->begin(); |
| it != inLevel->end(); ++it) { |
| TVectorImageP img = lr->getFrameReader(it->first)->load(); |
| if (!img) |
| continue; |
| lw->getFrameWriter(it->first)->save(img); |
| } |
| } else if (ltype.m_oldLevelFlag) { |
| TLevelP outLevel; |
| |
| levelPath = TFilePath(levelPath.getParentDir().getWideString() + L"\\" + levelPath.getWideName() + L".tlv"); |
| if (TSystem::doesExistFileOrLevel(levelPath)) |
| TSystem::removeFileOrLevel(levelPath); |
| TFilePath pltPath = TFilePath(levelPath.getParentDir().getWideString() + L"\\" + levelPath.getWideName() + L".tpl"); |
| if (TSystem::doesExistFileOrLevel(pltPath)) |
| TSystem::removeFileOrLevel(pltPath); |
| |
| TLevelWriterP lw(levelPath); |
| lw->setIconSize(Preferences::instance()->getIconSize()); |
| TPaletteP palette = ToonzImageUtils::loadTzPalette(fp.withType("plt").withNoFrame()); |
| TLevelReaderP lr(fp); |
| if (!lr) |
| return false; |
| TLevelP inLevel = lr->loadInfo(); |
| if (!inLevel || inLevel->getFrameCount() == 0) |
| return false; |
| outLevel->setPalette(palette.getPointer()); |
| try { |
| for (TLevel::Iterator it = inLevel->begin(); it != inLevel->end(); ++it) { |
| TToonzImageP img = lr->getFrameReader(it->first)->load(); |
| if (!img) |
| continue; |
| img->setPalette(palette.getPointer()); |
| lw->getFrameWriter(it->first)->save(img); |
| } |
| } catch (TException &e) { |
| |
| QString msg = QString::fromStdWString(e.getMessage()); |
| if (msg == QString("Old 4.1 Palette")) { |
| lw = TLevelWriterP(); |
| if (TSystem::doesExistFileOrLevel(levelPath)) |
| TSystem::removeFileOrLevel(levelPath); |
| throw e; |
| } |
| } |
| lw = TLevelWriterP(); |
| |
| } |
| return true; |
| } |
| |
| |
| |
| TXshLevel *ToonzScene::loadLevel(const TFilePath &actualPath, |
| const LevelOptions *levelOptions, |
| std::wstring levelName, |
| const std::vector<TFrameId> &fIds) |
| { |
| LevelType ltype = getLevelType(actualPath); |
| if (ltype.m_ltype == UNKNOWN_XSHLEVEL) |
| return 0; |
| |
| TFilePath levelPath = actualPath; |
| |
| |
| |
| if (QString::fromStdWString(levelName).isEmpty()) { |
| |
| |
| levelName = getLevelNameWithoutSceneNumber(levelPath.getWideName()); |
| } |
| |
| NameModifier nm(levelName); |
| levelName = nm.getNext(); |
| while (m_levelSet->hasLevel(levelName)) |
| levelName = nm.getNext(); |
| |
| |
| if (ltype.m_ltype == SND_XSHLEVEL) { |
| TXshSoundLevel *sl = new TXshSoundLevel(levelName); |
| sl->setType(ltype.m_ltype); |
| sl->setScene(this); |
| sl->setPath(codeFilePath(levelPath)); |
| |
| try { |
| sl->load(); |
| } catch (const std::string &msg) |
| { |
| throw TException(msg); |
| } |
| |
| m_levelSet->insertLevel(sl); |
| return sl; |
| } else { |
| TXshSimpleLevel *xl = new TXshSimpleLevel(levelName); |
| xl->setType(ltype.m_ltype); |
| xl->setScene(this); |
| |
| if (!convertLevelIfNeeded(levelPath)) |
| return 0; |
| |
| xl->setPath(codeFilePath(levelPath), true); |
| |
| try { |
| if (fIds.size() != 0) |
| xl->load(fIds); |
| else |
| xl->load(); |
| } catch (const std::string &msg) { |
| throw TException(msg); |
| } |
| |
| if (ltype.m_oldLevelFlag) |
| xl->setDirtyFlag(true); |
| |
| LevelProperties *lp = xl->getProperties(); |
| assert(lp); |
| |
| if (levelOptions) |
| lp->options() = *levelOptions; |
| else { |
| const Preferences &prefs = *Preferences::instance(); |
| int formatIdx = prefs.matchLevelFormat(levelPath); |
| |
| if (formatIdx >= 0) |
| lp->options() = prefs.levelFormat(formatIdx).m_options; |
| else { |
| |
| if (xl->getType() == OVL_XSHLEVEL) |
| lp->setSubsampling(getProperties()->getFullcolorSubsampling()); |
| else if (xl->getType() == TZP_XSHLEVEL) |
| lp->setSubsampling(getProperties()->getTlvSubsampling()); |
| } |
| } |
| |
| if (lp->getDpiPolicy() == LevelProperties::DP_ImageDpi) { |
| |
| const TPointD &imageDpi = xl->getImageDpi(); |
| |
| if (imageDpi == TPointD()) { |
| |
| TStageObjectId cameraId = getXsheet()->getStageObjectTree()->getCurrentCameraId(); |
| |
| lp->setDpiPolicy(LevelProperties::DP_CustomDpi); |
| lp->setDpi(getCurrentCamera()->getDpi()); |
| } else { |
| |
| lp->setDpi(imageDpi); |
| } |
| } |
| |
| m_levelSet->insertLevel(xl); |
| |
| return xl; |
| } |
| |
| return 0; |
| } |
| |
| |
| |
| TFilePath ToonzScene::decodeFilePath(const TFilePath &path) const |
| { |
| TProject *project = getProject(); |
| bool projectIsEmpty = false; |
| TFilePath fp = path; |
| |
| wstring head; |
| TFilePath tail; |
| path.split(head, tail); |
| |
| string h; |
| wstring s; |
| if (head != L"" && head[0] == L'+') { |
| if (TProjectManager::instance()->isTabModeEnabled()) { |
| return m_scenePath.getParentDir() + |
| (m_scenePath.getWideName() + L"_files") + |
| tail; |
| } |
| |
| if (TProjectManager::instance()->isTabKidsModeEnabled()) { |
| return m_scenePath.getParentDir() + |
| m_scenePath.getWideName() + |
| tail; |
| } |
| |
| if (projectIsEmpty) { |
| TFilePath dir = m_scenePath.getParentDir(); |
| if (dir.getName() == "scenes") |
| return dir.withName(head.substr(1)) + tail; |
| else |
| return dir + tail; |
| } |
| if (project) { |
| h = toString(head.substr(1)); |
| TFilePath f = project->getFolder(h); |
| if (f != TFilePath()) |
| s = f.getWideString(); |
| } |
| } |
| if (s != L"") { |
| map<wstring, wstring> table; |
| |
| |
| |
| |
| if (m_isUntitled && |
| (s.find(L"$scene") != wstring::npos || |
| project->getUseScenePath(h) || |
| fp.getParentDir().getName() == getScenePath().getName())) { |
| TFilePath parentDir = getScenePath().getParentDir(); |
| fp = parentDir + head.substr(1) + tail; |
| } else { |
| TFilePath scenePath = getScenePath(); |
| TFilePath scenePathRoot; |
| if (project) |
| scenePathRoot = project->getFolder(TProject::Scenes); |
| else |
| scenePathRoot = scenePath.getParentDir(); |
| |
| if (scenePathRoot != TFilePath() && !scenePathRoot.isAbsolute() && project) |
| scenePathRoot = project->getProjectFolder() + scenePathRoot; |
| |
| if (TSystem::isUNC(scenePath) && !TSystem::isUNC(scenePathRoot)) |
| scenePathRoot = TSystem::toUNC(scenePathRoot); |
| |
| if (scenePathRoot.isAncestorOf(scenePath)) |
| scenePath = scenePath - scenePathRoot; |
| |
| table[L"$scenepath"] = scenePath.withType("").getWideString(); |
| table[L"$scenename"] = scenePath.withType("").getWideString(); |
| |
| std::map<wstring, wstring>::reverse_iterator it; |
| for (it = table.rbegin(); it != table.rend(); ++it) { |
| wstring keyword = it->first; |
| int i = 0; |
| for (;;) { |
| int j = s.find(keyword, i); |
| if (j == (int)wstring::npos) |
| break; |
| s.replace(j, keyword.length(), it->second); |
| i = j; |
| } |
| } |
| fp = TFilePath(s) + tail; |
| } |
| } |
| |
| if (fp != TFilePath() && !fp.isAbsolute() && project) |
| fp = project->getProjectFolder() + fp; |
| return fp; |
| } |
| |
| |
| |
| TFilePath ToonzScene::codeFilePath(const TFilePath &path) const |
| { |
| TFilePath fp(path); |
| TProject *project = getProject(); |
| |
| if (project) |
| for (int i = 0; i < project->getFolderCount(); i++) { |
| TFilePath folderName("+" + project->getFolderName(i)); |
| TFilePath folderPath = decodeFilePath(folderName); |
| if (folderPath.isAncestorOf(fp)) { |
| fp = folderName + (fp - folderPath); |
| return fp; |
| } |
| } |
| return fp; |
| } |
| |
| |
| |
| TFilePath ToonzScene::getDefaultLevelPath(int levelType, wstring levelName) const |
| { |
| TProject *project = getProject(); |
| assert(project); |
| TFilePath levelPath; |
| QString scanLevelType; |
| switch (levelType) { |
| case TZI_XSHLEVEL: |
| scanLevelType = Preferences::instance()->getScanLevelType(); |
| levelPath = TFilePath(levelName + L".." + scanLevelType.toStdWString()); |
| break; |
| case PLI_XSHLEVEL: |
| levelPath = TFilePath(levelName).withType("pli"); |
| break; |
| case TZP_XSHLEVEL: |
| levelPath = TFilePath(levelName).withType("tlv"); |
| break; |
| case OVL_XSHLEVEL: |
| levelPath = TFilePath(levelName + L"..tif"); |
| break; |
| default: |
| levelPath = TFilePath(levelName + L"..png"); |
| } |
| string folderName = getFolderName(levelType); |
| if (project->getUseScenePath(folderName)) |
| return TFilePath("+" + folderName) + getSavePath() + levelPath; |
| else |
| return TFilePath("+" + folderName) + levelPath; |
| } |
| |
| |
| |
| const wstring savePathString(L"$savepath"); |
| |
| |
| |
| TFilePath ToonzScene::codeSavePath(TFilePath path) const |
| { |
| if (path == TFilePath()) |
| return path; |
| TFilePath savePath = getSavePath(); |
| if (savePath == TFilePath()) |
| return path; |
| TFilePath filename; |
| TFilePath originalPath = path; |
| if (savePath.withoutParentDir() != path.withoutParentDir()) { |
| TFilePath parentDir = path.getParentDir(); |
| if (parentDir != TFilePath() && !parentDir.isRoot()) { |
| filename = path.withoutParentDir(); |
| path = parentDir; |
| } else |
| return originalPath; |
| } |
| |
| TFilePath head; |
| if (!checkTail(path, savePath, head)) |
| return originalPath; |
| if (head.getParentDir() != TFilePath() || |
| head == TFilePath() || |
| head.getWideString()[0] != L'+') |
| return originalPath; |
| string folderName = toString(head.getWideString().substr(1)); |
| if (!getProject()->getUseScenePath(folderName)) |
| return originalPath; |
| return head + savePathString + filename; |
| } |
| |
| |
| |
| TFilePath ToonzScene::decodeSavePath(TFilePath path) const |
| { |
| wstring s = path.getWideString(); |
| int i = s.find(savePathString); |
| if (i != (int)wstring::npos) { |
| TFilePath savePath = getSavePath(); |
| s.replace(i, savePathString.length(), savePath.getWideString()); |
| return TFilePath(s); |
| } else |
| return path; |
| } |
| |
| |
| |
| bool ToonzScene::isExternPath(const TFilePath &fp) const |
| { |
| TProject *project = m_project; |
| assert(project); |
| for (int i = 0; i < project->getFolderCount(); i++) { |
| if (project->getFolderName(i) == "scenes") |
| continue; |
| |
| TFilePath folderPath = decodeFilePath(TFilePath("+" + project->getFolderName(i))); |
| if (folderPath.isAncestorOf(fp)) |
| return false; |
| } |
| return true; |
| } |
| |
| |
| |
| TCamera *ToonzScene::getCurrentCamera() |
| { |
| return getXsheet()->getStageObjectTree()->getCurrentCamera(); |
| } |
| |
| |
| |
| TCamera *ToonzScene::getCurrentPreviewCamera() |
| { |
| return getXsheet()->getStageObjectTree()->getCurrentPreviewCamera(); |
| } |
| |
| |
| |
| TContentHistory *ToonzScene::getContentHistory(bool createIfNeeded) |
| { |
| if (!m_contentHistory && createIfNeeded) |
| m_contentHistory = new TContentHistory(false); |
| return m_contentHistory; |
| } |
| |
| |
| |
| void ToonzScene::getSoundColumns(std::vector<TXshSoundColumn *> &columns) |
| { |
| ToonzScene *scene = this; |
| std::set<TXsheet *> visited, toVisit; |
| TXsheet *xsh = scene->getChildStack()->getTopXsheet(); |
| visited.insert(xsh); |
| toVisit.insert(xsh); |
| while (!toVisit.empty()) { |
| xsh = *toVisit.begin(); |
| toVisit.erase(xsh); |
| for (int i = 0; i < xsh->getColumnCount(); i++) { |
| TXshColumn *column = xsh->getColumn(i); |
| if (!column) |
| continue; |
| if (TXshSoundColumn *sc = column->getSoundColumn()) |
| columns.push_back(sc); |
| else if (TXshCellColumn *cc = column->getCellColumn()) { |
| int r0 = 0, r1 = -1; |
| cc->getRange(r0, r1); |
| if (!cc->isEmpty() && r0 <= r1) { |
| for (int r = r0; r <= r1; r++) { |
| TXshCell cell = cc->getCell(r); |
| if (cell.m_level && cell.m_level->getChildLevel()) { |
| TXsheet *subxsh = cell.m_level->getChildLevel()->getXsheet(); |
| if (visited.find(subxsh) == visited.end()) { |
| visited.insert(subxsh); |
| toVisit.insert(subxsh); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| |
| void ToonzScene::updateSoundColumnFrameRate() |
| { |
| std::vector<TXshSoundColumn *> soundColumns; |
| getSoundColumns(soundColumns); |
| |
| TSceneProperties *properties = getProperties(); |
| if (!properties) |
| return; |
| |
| TOutputProperties *outputProperties = properties->getOutputProperties(); |
| if (!outputProperties) |
| return; |
| |
| double frameRate = outputProperties->getFrameRate(); |
| |
| int i; |
| for (i = 0; i < (int)soundColumns.size(); i++) |
| soundColumns[i]->updateFrameRate(frameRate); |
| } |
| |
| |
| |
| TFilePath ToonzScene::getIconPath(const TFilePath &scenePath) |
| { |
| return scenePath.getParentDir() + "sceneIcons" + (scenePath.getWideName() + L" .png"); |
| } |
| |
| |
| |
| |
| |
| |
| |
| TFilePath ToonzScene::getSavePath() const |
| { |
| string sceneName = getScenePath().getName(); |
| if (isUntitled()) |
| return TFilePath(sceneName); |
| TFilePath sceneRoot = decodeFilePath(TFilePath("+" + TProject::Scenes)); |
| TFilePath scenePath = getScenePath().withType(""); |
| TFilePath savePath(sceneName); |
| if (sceneRoot.isAncestorOf(scenePath)) |
| savePath = scenePath - sceneRoot; |
| return savePath; |
| } |
| |
| |
| |
| double ToonzScene::shiftCameraX(double val) |
| { |
| TStageObjectTree *tree = getXsheet()->getStageObjectTree(); |
| |
| TStageObject *stageObject = tree->getStageObject(tree->getCurrentCameraId()); |
| TPointD ret = stageObject->getOffset(); |
| stageObject->setOffset(TPointD(ret.x + val, ret.y)); |
| return ret.x; |
| } |
| |
| |
| |
| |
| |
| std::wstring ToonzScene::getLevelNameWithoutSceneNumber(std::wstring orgName) |
| { |
| if (!Preferences::instance()->isRemoveSceneNumberFromLoadedLevelNameEnabled()) |
| return orgName; |
| |
| QString orgNameQstr = QString::fromStdWString(orgName); |
| |
| |
| if (orgNameQstr.size() <= 6) |
| return orgName; |
| |
| QString sceneName = QString::fromStdWString(getSceneName()).left(5); |
| |
| |
| |
| if (!orgNameQstr.startsWith(sceneName)) |
| return orgName; |
| |
| if (!orgNameQstr.contains("_")) |
| return orgName; |
| |
| return orgNameQstr.right(orgNameQstr.size() - orgNameQstr.indexOf("_") - 1).toStdWString(); |
| } |
| |