Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/toonzscene.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/txsheet.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshcell.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshchildlevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshleveltypes.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelcolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsoundcolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsoundlevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/sceneproperties.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage.h"
Toshihiro Shimizu 890ddd
#include "toonz/stagevisitor.h"
Toshihiro Shimizu 890ddd
#include "toonz/levelset.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobjecttree.h"
Toshihiro Shimizu 890ddd
#include "toonz/observer.h"
Toshihiro Shimizu 890ddd
#include "toonz/namebuilder.h"
Toshihiro Shimizu 890ddd
#include "toonz/tproject.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzimageutils.h"
Toshihiro Shimizu 890ddd
#include "toonz/childstack.h"
Toshihiro Shimizu 890ddd
#include "toonz/levelproperties.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcamera.h"
Toshihiro Shimizu 890ddd
#include "toonz/sceneresources.h"
Toshihiro Shimizu 890ddd
#include "toonz/preferences.h"
Toshihiro Shimizu 890ddd
#include "toonz/fullcolorpalette.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshpalettecolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshpalettelevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzfolders.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "timagecache.h"
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
#include "tstreamexception.h"
Toshihiro Shimizu 890ddd
#include "tofflinegl.h"
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tfiletype.h"
Toshihiro Shimizu 890ddd
#include "tlevel_io.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "tlogger.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "tcontenthistory.h"
Toshihiro Shimizu 890ddd
#include "toutputproperties.h"
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TOfflineGL *currentOfflineGL = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <qprogressdialog></qprogressdialog>
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Utility functions
Toshihiro Shimizu 890ddd
//=============================================================================
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const VersionNumber l_currentVersion(71, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string getFolderName(int levelType) {
Shinya Kitaoka 120a6e
  switch (levelType) {
Shinya Kitaoka 120a6e
  case TZI_XSHLEVEL:
Shinya Kitaoka 120a6e
    return TProject::Inputs;
Shinya Kitaoka 120a6e
  case PLI_XSHLEVEL:
Shinya Kitaoka 120a6e
    return TProject::Drawings;
Shinya Kitaoka 120a6e
  case TZP_XSHLEVEL:
Shinya Kitaoka 120a6e
    return TProject::Drawings;
Shinya Kitaoka 120a6e
  case OVL_XSHLEVEL:
Shinya Kitaoka 120a6e
    return TProject::Extras;
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    return TProject::Extras;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
TFilePath adjustTypeAndFrame(int levelType, TFilePath fp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  switch(levelType)
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    case TZI_XSHLEVEL:
Toshihiro Shimizu 890ddd
      if(fp.getType()=="") fp=fp.withType("tif");
Toshihiro Shimizu 890ddd
      return fp.withFrame(TFrameId::EMPTY_FRAME);
Toshihiro Shimizu 890ddd
    case PLI_XSHLEVEL:
Toshihiro Shimizu 890ddd
      return fp.withFrame(TFrameId::NO_FRAME)
Toshihiro Shimizu 890ddd
               .withType("pli");
Toshihiro Shimizu 890ddd
    case TZP_XSHLEVEL:
Toshihiro Shimizu 890ddd
      return fp.withFrame(TFrameId::NO_FRAME)
Toshihiro Shimizu 890ddd
               .withType("tlv");
Toshihiro Shimizu 890ddd
    case OVL_XSHLEVEL:
Toshihiro Shimizu 890ddd
    default:
Toshihiro Shimizu 890ddd
      if(fp.getType()=="") fp=fp.withType("png");
Toshihiro Shimizu 890ddd
      return fp;
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFilePath getUntitledScenesDir() {
Shinya Kitaoka 120a6e
  return ToonzFolder::getCacheRootFolder() + "temp";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// se path = head + tail ritorna true e assegna head
Shinya Kitaoka 120a6e
bool checkTail(TFilePath path, TFilePath tail, TFilePath &head) {
Shinya Kitaoka 120a6e
  for (;;) {
Shinya Kitaoka 120a6e
    if (tail == TFilePath()) {
Shinya Kitaoka 120a6e
      head = path;
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (path == TFilePath()) return false;
Shinya Kitaoka 120a6e
    if (path.withoutParentDir() != tail.withoutParentDir()) return false;
Shinya Kitaoka 120a6e
    path = path.getParentDir();
Shinya Kitaoka 120a6e
    tail = tail.getParentDir();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void makeSceneIcon(ToonzScene *scene) {
Shinya Kitaoka 120a6e
  TDimension cameraSize = scene->getCurrentCamera()->getRes();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int maxSize               = 128;
Shinya Kitaoka 120a6e
  TDimension iconCameraSize = cameraSize;
Shinya Kitaoka 120a6e
  if (cameraSize.lx > cameraSize.ly) {
Shinya Kitaoka 120a6e
    iconCameraSize.ly = maxSize * cameraSize.ly / cameraSize.lx;
Shinya Kitaoka 120a6e
    iconCameraSize.lx = maxSize;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    iconCameraSize.lx = maxSize * cameraSize.lx / cameraSize.ly;
Shinya Kitaoka 120a6e
    iconCameraSize.ly = maxSize;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRaster32P ras(iconCameraSize);
Shinya Kitaoka 120a6e
  TPixel32 bgColor = scene->getProperties()->getBgColor();
Shinya Kitaoka 120a6e
  ras->fill(bgColor);
Shinya Kitaoka 120a6e
  scene->renderFrame(ras, 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TFilePath iconPath = scene->getIconPath();
Shinya Kitaoka 120a6e
  if (TSystem::touchParentDir(iconPath)) TImageWriter::save(iconPath, ras);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void deleteUntitledScene(const TFilePath &fp) {
Shinya Kitaoka 120a6e
  if (TFileStatus(fp).isDirectory()) {
Shinya Kitaoka 120a6e
    TFilePath tempDir = getUntitledScenesDir();
Shinya Kitaoka 120a6e
    if (TFileStatus(tempDir).isDirectory() &&
Shinya Kitaoka 120a6e
        tempDir.isAncestorOf(fp))  // per sicurezza
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      try {
Shinya Kitaoka 120a6e
        TSystem::rmDirTree(fp);
Shinya Kitaoka 120a6e
      } catch (...) {
Shinya Kitaoka 120a6e
        assert(0);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      assert(0);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*-- TODO: オプション化して復活させるか、検討のこと --*/
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
void saveBackup(const TFilePath &fp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  if(!TFileStatus(fp).doesExist()) return;
Shinya Kitaoka 120a6e
        wstring sceneName = fp.getWideName();
Toshihiro Shimizu 890ddd
  TFilePath bckDir = fp.getParentDir() + "backups" + sceneName;
Toshihiro Shimizu 890ddd
  if(!TFileStatus(bckDir).doesExist())
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    try {TSystem::mkDir(bckDir);}
Toshihiro Shimizu 890ddd
    catch(...) {return;}
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  std::map<int, tfilepath=""> oldBackups;</int,>
Toshihiro Shimizu 890ddd
  TFilePathSet lst = TSystem::readDirectory(bckDir);
Toshihiro Shimizu 890ddd
  for(TFilePathSet::iterator it = lst.begin(); it != lst.end(); ++it)
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    TFilePath fp2 = *it;
Toshihiro Shimizu 890ddd
    if(fp2.getType() != "tnz" && fp2.getType() != "tab") continue;
Toshihiro Shimizu 890ddd
    wstring name = fp2.getWideName();
Toshihiro Shimizu 890ddd
    if(name.find_first_of(L"0123456789") == wstring::npos) continue;
Shinya Kitaoka 120a6e
                int i = name.find(sceneName);
Shinya Kitaoka 120a6e
                if(i != wstring::npos)
Shinya Kitaoka 120a6e
                        name = name.substr(sceneName.size()+1);
Toshihiro Shimizu 890ddd
    if(name == L"" || name.find_first_not_of(L"0123456789") != wstring::npos)
Toshihiro Shimizu 890ddd
      continue;
Toshihiro Shimizu 890ddd
    int index = toInt(name);
Toshihiro Shimizu 890ddd
    assert(0
Toshihiro Shimizu 890ddd
    assert(oldBackups.count(index)==0);
Toshihiro Shimizu 890ddd
    oldBackups[index] = fp2;
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  int m = 3;
Toshihiro Shimizu 890ddd
  if((int)oldBackups.size()>m)
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    std::map<int, tfilepath="">::iterator it = oldBackups.begin();</int,>
Toshihiro Shimizu 890ddd
    for(int i=0;i+m<(int)oldBackups.size();i++)
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      assert(it != oldBackups.end());
Toshihiro Shimizu 890ddd
      TFilePath toKill = it->second;
Toshihiro Shimizu 890ddd
      try {TSystem::deleteFile(toKill); } catch(...) {}
Toshihiro Shimizu 890ddd
      ++it;
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
  }
Shinya Kitaoka 120a6e
Toshihiro Shimizu 890ddd
  TFilePath bckFp;
Toshihiro Shimizu 890ddd
  if(oldBackups.empty())
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    if(fp.getType() == "tnz")
Toshihiro Shimizu 890ddd
      bckFp = bckDir + TFilePath(sceneName + L"_1.tnz");
Toshihiro Shimizu 890ddd
    else if(fp.getType() == "tab")
Toshihiro Shimizu 890ddd
      bckFp = bckDir + TFilePath(sceneName + L"_1.tab");
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
  else
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    int id = oldBackups.rbegin()->first + 1;
Toshihiro Shimizu 890ddd
    if(fp.getType() == "tnz")
Shinya Kitaoka 9eb50d
      bckFp = bckDir + TFilePath(sceneName + L"_" + ::to_wstring(id) + L".tnz");
Toshihiro Shimizu 890ddd
    else if(fp.getType() == "tab")
Shinya Kitaoka 9eb50d
      bckFp = bckDir + TFilePath(sceneName + L"_" + ::to_wstring(id) + L".tab");
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  TSystem::renameFile(bckFp, fp);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// serve per correggere un problema verificatosi da Bianco (con la beta3)
Toshihiro Shimizu 890ddd
// vengono create coppie di livelli con lo stesso nome e in genere path diverso
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void fixBiancoProblem(ToonzScene *scene, TXsheet *xsh) {
Shinya Kitaoka 120a6e
  TLevelSet *levelSet = scene->getLevelSet();
Shinya Kitaoka 120a6e
  std::set<txsheet *=""> visited, tovisit;</txsheet>
Shinya Kitaoka 120a6e
  tovisit.insert(xsh);
Shinya Kitaoka 120a6e
  while (!tovisit.empty()) {
Shinya Kitaoka 120a6e
    xsh = *tovisit.begin();
Shinya Kitaoka 120a6e
    xsh->setScene(scene);  // sound problem
Shinya Kitaoka 120a6e
    visited.insert(xsh);
Shinya Kitaoka 120a6e
    tovisit.erase(xsh);
Shinya Kitaoka 120a6e
    int c0 = 0, c1 = xsh->getColumnCount() - 1;
Shinya Kitaoka 120a6e
    for (int c = c0; c <= c1; c++) {
Shinya Kitaoka 120a6e
      if (xsh->isColumnEmpty(c)) continue;
Shinya Kitaoka 120a6e
      TXshColumn *column = xsh->getColumn(c);
Shinya Kitaoka 120a6e
      if (!column || !column->getLevelColumn()) continue;
Shinya Kitaoka 120a6e
      TXshLevelColumn *lcolumn = column->getLevelColumn();
Shinya Kitaoka 120a6e
      int r0 = 0, r1 = -1;
Shinya Kitaoka 120a6e
      lcolumn->getRange(r0, r1);
Shinya Kitaoka 120a6e
      for (int r = r0; r <= r1; r++) {
Shinya Kitaoka 120a6e
        TXshCell cell = lcolumn->getCell(r);
Shinya Kitaoka 120a6e
        if (cell.isEmpty()) continue;
Shinya Kitaoka 120a6e
        TXshLevel *xl = cell.m_level.getPointer();
Shinya Kitaoka 120a6e
        scene->getLevelSet()->insertLevel(xl);  // per sicurezza
Shinya Kitaoka 120a6e
        xl->setScene(scene);
Shinya Kitaoka 120a6e
        if (TXshChildLevel *childLevel = xl->getChildLevel()) {
Shinya Kitaoka 120a6e
          TXsheet *childXsh = childLevel->getXsheet();
Shinya Kitaoka 120a6e
          if (visited.count(childXsh) > 0) continue;
Shinya Kitaoka 120a6e
          tovisit.insert(childXsh);
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          TXshLevel *xl2 = levelSet->getLevel(xl->getName());
Shinya Kitaoka 120a6e
          if (xl2) {
Shinya Kitaoka 120a6e
            if (xl2 != xl) {
Shinya Kitaoka 120a6e
              cell.m_level = xl2;
Shinya Kitaoka 120a6e
              lcolumn->setCell(r, cell);
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
          } else {
Shinya Kitaoka 120a6e
            xl->setScene(scene);
Shinya Kitaoka 120a6e
            levelSet->insertLevel(xl);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Campbell Barton b3bd84
static void deleteAllUntitledScenes() {
Shinya Kitaoka 120a6e
  TFilePath tempDir = getUntitledScenesDir();
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    if (TFileStatus(tempDir).isDirectory()) {
Shinya Kitaoka 120a6e
      TFilePathSet fps;
Shinya Kitaoka 120a6e
      TSystem::readDirectory(fps, tempDir);
Shinya Kitaoka 120a6e
      TFilePathSet::iterator fpsIt;
Shinya Kitaoka 120a6e
      for (fpsIt = fps.begin(); fpsIt != fps.end(); ++fpsIt) {
Shinya Kitaoka 120a6e
        TFilePath fp = *fpsIt;
Shinya Kitaoka 120a6e
        if (TFileStatus(fp).isDirectory() &&
Shinya Kitaoka 120a6e
            fp.getName().find("untitled") != -1)
Shinya Kitaoka 120a6e
          TSystem::rmDirTree(fp);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } catch (...) {
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// ToonzScene
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ToonzScene::ToonzScene() : m_contentHistory(0), m_isUntitled(true) {
Shinya Kitaoka 120a6e
  m_childStack = new ChildStack(this);
Shinya Kitaoka 120a6e
  m_properties = new TSceneProperties();
Shinya Kitaoka 120a6e
  m_levelSet   = new TLevelSet();
Shinya Kitaoka 120a6e
  m_project    = new TProject();
Shinya Kitaoka 120a6e
  m_project->addRef();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ToonzScene::~ToonzScene() {
Shinya Kitaoka 120a6e
  delete m_properties;
Shinya Kitaoka 120a6e
  delete m_levelSet;
Shinya Kitaoka 120a6e
  delete m_childStack;
Shinya Kitaoka 120a6e
  delete m_contentHistory;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(m_project);
Shinya Kitaoka 120a6e
  if (m_project) m_project->release();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ToonzScene::setSceneName(std::wstring name) {
Shinya Kitaoka 120a6e
  m_scenePath = m_scenePath.withName(name);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ToonzScene::clear() {
Shinya Kitaoka 120a6e
  if (isUntitled()) deleteUntitledScene(getScenePath().getParentDir());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_childStack->clear();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_scenePath                  = TFilePath();
Shinya Kitaoka 120a6e
  TSceneProperties *properties = m_properties;
Shinya Kitaoka 120a6e
  m_properties                 = new TSceneProperties();
Shinya Kitaoka 120a6e
  delete properties;
Shinya Kitaoka 120a6e
  m_levelSet->clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ToonzScene::setProject(TProject *project) {
Shinya Kitaoka 120a6e
  assert(project);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (project != m_project) {
Shinya Kitaoka 120a6e
    if (project) project->addRef();
Shinya Kitaoka 120a6e
    if (m_project) m_project->release();
Shinya Kitaoka 120a6e
    m_project = project;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TProject *ToonzScene::getProject() const { return m_project; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ToonzScene::setScenePath(const TFilePath &fp) {
Shinya Kitaoka 120a6e
  m_scenePath  = fp;
Shinya Kitaoka 120a6e
  m_isUntitled = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool ToonzScene::isUntitled() const {
Shinya Kitaoka 120a6e
  return m_scenePath == TFilePath() || m_isUntitled;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ToonzScene::load(const TFilePath &path, bool withProgressDialog) {
Shinya Kitaoka 120a6e
  loadNoResources(path);              // This loads a version number ..
Shinya Kitaoka 120a6e
  loadResources(withProgressDialog);  // .. this uses the version number ..
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  setVersionNumber(
Shinya Kitaoka 120a6e
      VersionNumber());  // .. but scene instances in memory do not retain
Shinya Kitaoka 120a6e
}  // a version number beyond resource loading
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Funzioncina veloce per trovare il numero di frame di una scena senza caricare
Shinya Kitaoka 120a6e
// nulla. (implementato per Toonz 6.0 beta 1)
Shinya Kitaoka 120a6e
int ToonzScene::loadFrameCount(const TFilePath &fp) {
Shinya Kitaoka 120a6e
  TIStream is(fp);
Shinya Kitaoka 120a6e
  if (!is) throw TException(fp.getWideString() + L": Can't open file");
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    // Leggo il primo tag (<tnz tab="">) ed estraggo il framecount (se c'e')</tnz>
Shinya Kitaoka 120a6e
    std::string tagName = "";
Shinya Kitaoka 120a6e
    if (!is.matchTag(tagName)) throw TException("Bad file format");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (tagName == "tab" || tagName == "tnz") {
Shinya Kitaoka 120a6e
      int frameCount;
Shinya Kitaoka 120a6e
      if (is.getTagParam("framecount", frameCount))
Shinya Kitaoka 120a6e
        return frameCount;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        return 0;
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      throw TException("Bad file format");
Shinya Kitaoka 120a6e
  } catch (TException &e) {
Shinya Kitaoka 120a6e
    throw TIStreamException(is, e);
Shinya Kitaoka 120a6e
  } catch (...) {
Shinya Kitaoka 120a6e
    throw TIStreamException(is);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ToonzScene::loadNoResources(const TFilePath &fp) {
Shinya Kitaoka 120a6e
  clear();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TProjectManager *pm    = TProjectManager::instance();
Shinya Kitaoka 120a6e
  TProjectP sceneProject = pm->loadSceneProject(fp);
Shinya Kitaoka 120a6e
  if (!sceneProject) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  setProject(sceneProject.getPointer());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  loadTnzFile(fp);
Shinya Kitaoka 120a6e
  getXsheet()->updateFrameCount();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
/*--
Shinya Kitaoka 120a6e
 * プログレスダイアログをGUIからの実行時でのみ表示させる。tcomposerから実行の場合は表示させない
Shinya Kitaoka 120a6e
 * --*/
Shinya Kitaoka 120a6e
void ToonzScene::loadResources(bool withProgressDialog) {
Shinya Kitaoka 120a6e
  /*--- m_levelSet->getLevelCount()が10個以上のとき表示させる ---*/
Shinya Kitaoka 120a6e
  QProgressDialog *progressDialog = 0;
Shinya Kitaoka 120a6e
  if (withProgressDialog && m_levelSet->getLevelCount() >= 10) {
Shinya Kitaoka 120a6e
    progressDialog = new QProgressDialog("Loading Scene Resources", "", 0,
Shinya Kitaoka 120a6e
                                         m_levelSet->getLevelCount());
Shinya Kitaoka 120a6e
    progressDialog->setModal(true);
Shinya Kitaoka 120a6e
    progressDialog->setAutoReset(
Shinya Kitaoka 120a6e
        true); /*--maximumに到達したら自動でresetを呼ぶ--*/
Shinya Kitaoka 120a6e
    progressDialog->setAutoClose(true); /*--resetが呼ばれたら自動で閉じる--*/
Shinya Kitaoka 120a6e
    progressDialog->setAttribute(Qt::WA_DeleteOnClose,
Shinya Kitaoka 120a6e
                                 true); /*--閉じたら自動でDeleteされる--*/
Shinya Kitaoka 120a6e
    progressDialog->setCancelButton(0);
Shinya Kitaoka 120a6e
    progressDialog->setValue(0);
Shinya Kitaoka 120a6e
    progressDialog->show();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < m_levelSet->getLevelCount(); i++) {
Shinya Kitaoka 120a6e
    if (progressDialog) progressDialog->setValue(i + 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TXshLevel *level = m_levelSet->getLevel(i);
Shinya Kitaoka 120a6e
    try {
Shinya Kitaoka 120a6e
      level->load();
Shinya Kitaoka 120a6e
    } catch (...) {
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  getXsheet()->updateFrameCount();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ToonzScene::loadTnzFile(const TFilePath &fp) {
Shinya Kitaoka 120a6e
  bool reading22 = false;
Shinya Kitaoka 120a6e
  TIStream is(fp);
Shinya Kitaoka 120a6e
  if (!is) throw TException(fp.getWideString() + L": Can't open file");
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    std::string tagName = "";
Shinya Kitaoka 120a6e
    if (!is.matchTag(tagName)) throw TException("Bad file format");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (tagName == "tab" || tagName == "tnz") {
Shinya Kitaoka 120a6e
      std::string rootTagName = tagName;
Shinya Kitaoka 120a6e
      std::string v           = is.getTagAttribute("version");
Shinya Kitaoka 120a6e
      VersionNumber versionNumber(0, 0);
Shinya Kitaoka 120a6e
      int k = v.find(".");
Shinya Kitaoka 120a6e
      if (k != (int)std::string::npos && 0 < k && k < (int)v.length()) {
Shinya Kitaoka 120a6e
        versionNumber.first  = std::stoi(v.substr(0, k));
Shinya Kitaoka 120a6e
        versionNumber.second = std::stoi(v.substr(k + 1));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (versionNumber == VersionNumber(0, 0))
Shinya Kitaoka 120a6e
        throw TException("Bad version number :" + v);
Shinya Kitaoka 120a6e
      setVersionNumber(versionNumber);
Shinya Kitaoka 120a6e
      is.setVersion(versionNumber);
Shinya Kitaoka 120a6e
      while (is.matchTag(tagName)) {
Shinya Kitaoka 120a6e
        if (tagName == "generator") {
Shinya Kitaoka 120a6e
          std::string program = is.getString();
Shinya Kitaoka 120a6e
          reading22           = program.find("2.2") != std::string::npos;
Shinya Kitaoka 120a6e
        } else if (tagName == "properties")
Shinya Kitaoka 120a6e
          m_properties->loadData(is, false);
Shinya Kitaoka 120a6e
        else if (tagName == "palette")  // per compatibilita' beta1
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
          TPalette *palette = new TPalette;
Shinya Kitaoka 120a6e
          is >> *palette;
Shinya Kitaoka 120a6e
          delete palette;
Shinya Kitaoka 120a6e
        } else if (tagName == "levelSet")
Shinya Kitaoka 120a6e
          m_levelSet->loadData(is);
Shinya Kitaoka 120a6e
        else if (tagName == "levels") {
Shinya Kitaoka 120a6e
          // obsoleto
Shinya Kitaoka 120a6e
          if (!reading22) assert(0);
Shinya Kitaoka 120a6e
          while (!is.eos()) {
Shinya Kitaoka 120a6e
            TPersist *p = 0;
Shinya Kitaoka 120a6e
            is >> p;
Shinya Kitaoka 120a6e
            TXshLevel *xshLevel = dynamic_cast<txshlevel *="">(p);</txshlevel>
Shinya Kitaoka 120a6e
            if (xshLevel) {
Shinya Kitaoka 120a6e
              xshLevel->setScene(this);
Shinya Kitaoka 120a6e
              TXshSimpleLevel *sl = xshLevel->getSimpleLevel();
Shinya Kitaoka 120a6e
              if (reading22 && sl && sl->getPath() == TFilePath()) {
Shinya Kitaoka 120a6e
                sl->setType(PLI_XSHLEVEL);
Shinya Kitaoka 120a6e
                sl->setPath(TFilePath("+drawings/") +
Shinya Kitaoka 120a6e
                            (sl->getName() + L".pli"));
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
              m_levelSet->insertLevel(xshLevel);
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        } else if (tagName == "xsheet")
Shinya Kitaoka 120a6e
          is >> *getXsheet();
Shinya Kitaoka 120a6e
        else if (tagName == "history") {
Shinya Kitaoka 120a6e
          std::string historyData, s;
Shinya Kitaoka 120a6e
          while (!is.eos()) {
Shinya Kitaoka 120a6e
            is >> s;
Shinya Kitaoka 120a6e
            historyData += s;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          TContentHistory *history = getContentHistory(true);
Shinya Kitaoka 120a6e
          history->deserialize(QString::fromStdString(historyData));
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          throw TException(tagName + " : unexpected tag");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (!is.matchEndTag()) throw TException(tagName + " : missing end tag");
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (!is.matchEndTag())
Shinya Kitaoka 120a6e
        throw TException(rootTagName + " : missing end tag");
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      throw TException("Bad file format");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    setScenePath(fp);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (int i = 0; i < m_levelSet->getLevelCount(); i++)
Shinya Kitaoka 120a6e
      m_levelSet->getLevel(i)->setScene(this);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  } catch (TException &e) {
Shinya Kitaoka 120a6e
    throw TIStreamException(is, e);
Shinya Kitaoka 120a6e
  } catch (...) {
Shinya Kitaoka 120a6e
    throw TIStreamException(is);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_properties->cloneCamerasTo(getXsheet()->getStageObjectTree());
Shinya Kitaoka 120a6e
  fixBiancoProblem(this, getXsheet());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// saveUntitled() viene chiamata subito dopo newScene
Toshihiro Shimizu 890ddd
// serve principalmente come lock per evitare che vengano create due scene
Toshihiro Shimizu 890ddd
// con lo stesso nome.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ToonzScene::setUntitled() {
Shinya Kitaoka 120a6e
  m_isUntitled               = true;
Shinya Kitaoka 120a6e
  const std::string baseName = "untitled";
Shinya Kitaoka 120a6e
  TFilePath tempDir          = getUntitledScenesDir();
Shinya Kitaoka 120a6e
  if (TFileStatus(tempDir).doesExist() == false) {
Shinya Kitaoka 120a6e
    try {
Shinya Kitaoka 120a6e
      TSystem::mkDir(tempDir);
Shinya Kitaoka 120a6e
    } catch (...) {
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::string name = baseName;
Shinya Kitaoka 120a6e
  if (TFileStatus(tempDir + name).doesExist()) {
Shinya Kitaoka 120a6e
    int count = 2;
Shinya Kitaoka 120a6e
    do {
Shinya Kitaoka 120a6e
      name = baseName + std::to_string(count++);
Shinya Kitaoka 120a6e
    } while (TFileStatus(tempDir + name).doesExist());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TFilePath fp = tempDir + name + (name + ".tnz");
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    TSystem::touchParentDir(fp);
Shinya Kitaoka 120a6e
  } catch (...) {
Shinya Kitaoka 120a6e
    assert(0);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  m_scenePath = fp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// When saving as sub-xsheet, the sub becomes top. So, its cameras must be
Shinya Kitaoka 120a6e
// associated to the scene properties.
Shinya Kitaoka 120a6e
class CameraRedirection {
Shinya Kitaoka 120a6e
  ToonzScene *m_scene;
Shinya Kitaoka 120a6e
  TXsheet *m_xsh;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  CameraRedirection(ToonzScene *scene, TXsheet *xsh)
Shinya Kitaoka 120a6e
      : m_scene(scene), m_xsh(xsh) {
Shinya Kitaoka 120a6e
    if (!xsh) xsh = m_scene->getTopXsheet();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_scene->getProperties()->cloneCamerasFrom(xsh->getStageObjectTree());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~CameraRedirection() {
Shinya Kitaoka 120a6e
    if (m_xsh)
Shinya Kitaoka 120a6e
      m_scene->getProperties()->cloneCamerasFrom(
Shinya Kitaoka 120a6e
          m_scene->getTopXsheet()->getStageObjectTree());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ToonzScene::save(const TFilePath &fp, TXsheet *subxsh) {
Shinya Kitaoka 120a6e
  TFilePath oldScenePath = getScenePath();
Shinya Kitaoka 120a6e
  TFilePath newScenePath = fp;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  CameraRedirection redir(this, subxsh);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool wasUntitled = isUntitled();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  setScenePath(fp);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TFileStatus fs(newScenePath);
Shinya Kitaoka 120a6e
  if (fs.doesExist() && !fs.isWritable())
Shinya Kitaoka 120a6e
    throw TSystemException(newScenePath,
Shinya Kitaoka 120a6e
                           "The scene cannot be saved: it is a read only "
Shinya Kitaoka 120a6e
                           "scene.\n All resources have been saved.");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TFilePath scenePath = decodeFilePath(fp);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // if(TFileStatus(scenePath).doesExist()) saveBackup(scenePath);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TSystem::touchFile(scenePath);
Shinya Kitaoka 120a6e
  makeSceneIcon(this);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // TOStream os(scenePath, compressionEnabled);
Shinya Kitaoka 120a6e
  TOStream os(scenePath, false);
Shinya Kitaoka 120a6e
  if (!os.checkStatus()) throw TException("Could not open file");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TXsheet *xsh      = subxsh;
Shinya Kitaoka 120a6e
  if (xsh == 0) xsh = m_childStack->getTopXsheet();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::map<std::string, std::string=""> attr;</std::string,>
Shinya Kitaoka 120a6e
  attr["version"] =
Shinya Kitaoka 120a6e
      (QString::number(l_currentVersion.first) +
Shinya Kitaoka 120a6e
       "."  // From now on, version numbers in saved files will have
Shinya Kitaoka 120a6e
       + QString::number(
Shinya Kitaoka 120a6e
             l_currentVersion.second))  // the signature "MAJOR.MINOR", where:
Shinya Kitaoka 120a6e
          .toStdString();               //
Shinya Kitaoka 120a6e
  attr["framecount"] =
Shinya Kitaoka 120a6e
      QString::number(  //    MAJOR = Toonz version number * 10 (eg 7.0 => 70)
Shinya Kitaoka 120a6e
          xsh->getFrameCount())
Shinya Kitaoka 120a6e
          .toStdString();  //    MINOR = Reset to 0 after each major increment,
Shinya Kitaoka 120a6e
                           //    and
Shinya Kitaoka 120a6e
                           //            advancing on its own when fixing bugs.
Shinya Kitaoka 120a6e
  os.openChild("tnz", attr);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  os.child("generator") << TEnv::getApplicationFullName();
Shinya Kitaoka 120a6e
  os.openChild("properties");
Shinya Kitaoka 120a6e
  m_properties->saveData(os);
Shinya Kitaoka 120a6e
  os.closeChild();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (subxsh) {
Shinya Kitaoka 120a6e
    std::set<txshlevel *=""> saveSet;</txshlevel>
Shinya Kitaoka 120a6e
    subxsh->getUsedLevels(saveSet);
Shinya Kitaoka 120a6e
    m_levelSet->setSaveSet(saveSet);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  os.openChild("levelSet");
Shinya Kitaoka 120a6e
  m_levelSet->saveData(os);
Shinya Kitaoka 120a6e
  os.closeChild();
Shinya Kitaoka 120a6e
  std::set<txshlevel *=""> emptySaveSet;</txshlevel>
Shinya Kitaoka 120a6e
  m_levelSet->setSaveSet(emptySaveSet);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  os.openChild("xsheet");
Shinya Kitaoka 120a6e
  os << *xsh;
Shinya Kitaoka 120a6e
  os.closeChild();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (getContentHistory()) {
Shinya Kitaoka 120a6e
    os.openChild("history");
Shinya Kitaoka 120a6e
    QString data = getContentHistory()->serialize();
Shinya Kitaoka 120a6e
    int i        = 0, j;
Shinya Kitaoka 120a6e
    // non scrivo tutta la std::string di seguito per evitare problemi se
Shinya Kitaoka 120a6e
    // diventa
Shinya Kitaoka 120a6e
    // troppo lunga. Cerco di spezzarla in modo che sia "bella da leggere" nel
Shinya Kitaoka 120a6e
    // tnz
Shinya Kitaoka 120a6e
    while ((j = data.indexOf("||", i)) >= i) {
Shinya Kitaoka 120a6e
      os << data.mid(i, j - i + 1).toStdWString();
Shinya Kitaoka 120a6e
      os.cr();
Shinya Kitaoka 120a6e
      i = j + 1;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    os << data.mid(i).toStdWString();
Shinya Kitaoka 120a6e
    os.closeChild();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  os.closeChild();
Shinya Kitaoka 120a6e
  bool status = os.checkStatus();
Shinya Kitaoka 120a6e
  if (!status) throw TException("Could not complete the save");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (subxsh) {
Shinya Kitaoka 120a6e
    setScenePath(oldScenePath);
Shinya Kitaoka 120a6e
    if (wasUntitled) setUntitled();
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (wasUntitled) deleteUntitledScene(oldScenePath.getParentDir());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int ToonzScene::getFrameCount() const {
Shinya Kitaoka 120a6e
  TXsheet *xsh = getXsheet();
Shinya Kitaoka 120a6e
  return xsh ? xsh->getFrameCount() : 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ToonzScene::renderFrame(const TRaster32P &ras, int row, const TXsheet *xsh,
Shinya Kitaoka 120a6e
                             bool checkFlags) const {
Shinya Kitaoka 120a6e
  if (xsh == 0) xsh = getXsheet();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TCamera *camera        = xsh->getStageObjectTree()->getCurrentCamera();
Shinya Kitaoka 120a6e
  TDimension cameraRes   = camera->getRes();
Shinya Kitaoka 120a6e
  TDimensionD cameraSize = camera->getSize();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // voglio che la camera sia completamente contenuta dentro raster
Shinya Kitaoka 120a6e
  double sx = (double)ras->getLx() / (double)cameraSize.lx;
Shinya Kitaoka 120a6e
  double sy = (double)ras->getLy() / (double)cameraSize.ly;
Shinya Kitaoka 120a6e
  double sc = (sx < sy) ? sx : sy;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TAffine &cameraAff =
Shinya Kitaoka 120a6e
      xsh->getPlacement(xsh->getStageObjectTree()->getCurrentCameraId(), row);
Shinya Kitaoka 120a6e
  const TAffine &viewAff = TScale(sc / Stage::inch) * cameraAff.inv();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRect clipRect(ras->getBounds());
Shinya Kitaoka 120a6e
  TOfflineGL ogl(ras->getSize());
Shinya Kitaoka 120a6e
  currentOfflineGL = &ogl;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ogl.makeCurrent();
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    glTranslated(0.5 * ras->getLx(), 0.5 * ras->getLy(), 0.0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Shinya Kitaoka 120a6e
    glClear(GL_COLOR_BUFFER_BIT);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    ImagePainter::VisualSettings vs;
Shinya Kitaoka 120a6e
    vs.m_plasticVisualSettings.m_drawMeshesWireframe = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    Stage::RasterPainter painter(ras->getSize(), viewAff, clipRect, vs,
Shinya Kitaoka 120a6e
                                 checkFlags);
Shinya Kitaoka 120a6e
    Stage::visit(painter, const_cast<toonzscene *="">(this),</toonzscene>
Shinya Kitaoka 120a6e
                 const_cast<txsheet *="">(xsh), row);</txsheet>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    painter.flushRasterImages();
Shinya Kitaoka 120a6e
    glFlush();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TRop::over(ras, ogl.getRaster());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  ogl.doneCurrent();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  currentOfflineGL = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Performs a camera-stand render of the specified xsheet in the specified
Shinya Kitaoka 120a6e
//! placedRect,
Shinya Kitaoka 120a6e
//! with known world/placed reference change - and returns the result in a
Shinya Kitaoka 120a6e
//! 32-bit raster.
Toshihiro Shimizu 890ddd
void ToonzScene::renderFrame(const TRaster32P &ras, int row, const TXsheet *xsh,
Shinya Kitaoka 120a6e
                             const TRectD &placedRect,
Shinya Kitaoka 120a6e
                             const TAffine &worldToPlacedAff) const {
Shinya Kitaoka 120a6e
  // Build reference change affines
Shinya Kitaoka 120a6e
  const TAffine &placedToOglRefAff =
Shinya Kitaoka 120a6e
      TScale(ras->getLx() / placedRect.getLx(),
Shinya Kitaoka 120a6e
             ras->getLy() / placedRect.getLy()) *
Shinya Kitaoka 120a6e
      TTranslation(-0.5 * (placedRect.x0 + placedRect.x1),
Shinya Kitaoka 120a6e
                   -0.5 * (placedRect.y0 + placedRect.y1));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TAffine &cameraAff =
Shinya Kitaoka 120a6e
      xsh->getPlacement(xsh->getStageObjectTree()->getCurrentCameraId(), row);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TAffine &worldToOglRefAff =
Shinya Kitaoka 120a6e
      placedToOglRefAff * worldToPlacedAff * cameraAff.inv();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRect clipRect(ras->getBounds());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TOfflineGL ogl(ras->getSize());
Shinya Kitaoka 120a6e
  currentOfflineGL = &ogl;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ogl.makeCurrent();
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    glTranslated(0.5 * ras->getLx(), 0.5 * ras->getLy(), 0.0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Shinya Kitaoka 120a6e
    glClear(GL_COLOR_BUFFER_BIT);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    ImagePainter::VisualSettings vs;
Shinya Kitaoka 120a6e
    vs.m_plasticVisualSettings.m_drawMeshesWireframe = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    Stage::RasterPainter painter(ras->getSize(), worldToOglRefAff, clipRect, vs,
Shinya Kitaoka 120a6e
                                 false);
Shinya Kitaoka 120a6e
    Stage::visit(painter, const_cast<toonzscene *="">(this),</toonzscene>
Shinya Kitaoka 120a6e
                 const_cast<txsheet *="">(xsh), row);</txsheet>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    painter.flushRasterImages();
Shinya Kitaoka 120a6e
    glFlush();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TRop::over(ras, ogl.getRaster());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  ogl.doneCurrent();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  currentOfflineGL = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TXshLevel *ToonzScene::createNewLevel(int type, std::wstring levelName,
Shinya Kitaoka 120a6e
                                      const TDimension &dim, double dpi,
Shinya Kitaoka 120a6e
                                      TFilePath fp) {
Shinya Kitaoka 120a6e
  TLevelSet *levelSet = getLevelSet();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (type == TZI_XSHLEVEL)  // TZI type corresponds to the 'Scan Level'
Shinya Kitaoka 120a6e
    type = OVL_XSHLEVEL;     // default option. See Toonz Preferences class.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (type == CHILD_XSHLEVEL && levelName == L"") levelName = L"sub";
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Select a different unique level name in case it already exists (either in
Shinya Kitaoka 120a6e
  // scene or on disk)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 2a7129
    const std::unique_ptr<namebuilder> nameBuilder(</namebuilder>
Shinya Kitaoka 120a6e
        NameBuilder::getBuilder(levelName));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (;;) {
Shinya Kitaoka 120a6e
      levelName = nameBuilder->getNext();
Shinya Kitaoka 120a6e
      /*-- levelが既にロード済みなら、次の名前を取得 --*/
Shinya Kitaoka 120a6e
      if (m_levelSet->getLevel(levelName) != 0) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*-- LevelSetの中に同じファイルパスのLevelがあるかをチェック --*/
Shinya Kitaoka 120a6e
      if (type != CHILD_XSHLEVEL && type != PLT_XSHLEVEL) {
Shinya Kitaoka 120a6e
        if (fp.isEmpty()) fp = getDefaultLevelPath(type, levelName);
Shinya Kitaoka 120a6e
        TFilePath actualFp   = decodeFilePath(fp);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (TSystem::doesExistFileOrLevel(
Shinya Kitaoka 120a6e
                actualFp))  // if(TFileStatus(actualFp).doesExist()) continue;
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
          fp = TFilePath();
Shinya Kitaoka 120a6e
          continue;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        int l, lCount = levelSet->getLevelCount();
Shinya Kitaoka 120a6e
        for (l = 0; l != lCount; ++l) {
Shinya Kitaoka 120a6e
          TXshLevel *xl = levelSet->getLevel(l);
Shinya Kitaoka 120a6e
          if (!xl) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          TXshSimpleLevel *sl = xl->getSimpleLevel();
Shinya Kitaoka 120a6e
          if (!sl) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          TFilePath lfp = decodeFilePath(sl->getPath());
Shinya Kitaoka 120a6e
          if (actualFp == lfp) break;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (l < lCount) {
Shinya Kitaoka 120a6e
          /*-- fpが既存のLevelと重複したため、再設定する --*/
Shinya Kitaoka 120a6e
          fp = TFilePath();
Shinya Kitaoka 120a6e
          continue;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TXshLevel *xl = 0;
Shinya Kitaoka 120a6e
  if (type == CHILD_XSHLEVEL) {
Shinya Kitaoka 120a6e
    TXshChildLevel *cl = new TXshChildLevel(levelName);
Shinya Kitaoka 120a6e
    cl->setScene(this);
Shinya Kitaoka 120a6e
    cl->getXsheet()->setScene(this);
Shinya Kitaoka 120a6e
    xl = cl;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Include the project's default cameras
Shinya Kitaoka 120a6e
    const TSceneProperties &props =
Shinya Kitaoka 120a6e
        TProjectManager::instance()->getCurrentProject()->getSceneProperties();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    props.cloneCamerasTo(cl->getXsheet()->getStageObjectTree());
Shinya Kitaoka 120a6e
  } else if (type == PLT_XSHLEVEL) {
Shinya Kitaoka 120a6e
    TXshPaletteLevel *pl = new TXshPaletteLevel(levelName);
Shinya Kitaoka 120a6e
    pl->setScene(this);
Shinya Kitaoka 120a6e
    xl = pl;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    TXshSimpleLevel *sl = new TXshSimpleLevel(levelName);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    sl->setScene(this);
Shinya Kitaoka 120a6e
    sl->setType(type);
Shinya Kitaoka 120a6e
    sl->setPath(fp);
Shinya Kitaoka 120a6e
    sl->setDirtyFlag(true);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (type == TZP_XSHLEVEL || type == PLI_XSHLEVEL)
Shinya Kitaoka 120a6e
      sl->setPalette(new TPalette());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (type == OVL_XSHLEVEL)
Shinya Kitaoka 120a6e
      sl->setPalette(FullColorPalette::instance()->getPalette(this));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPalette *palette = sl->getPalette();
Shinya Kitaoka 120a6e
    if (palette && type != OVL_XSHLEVEL) {
Shinya Kitaoka 120a6e
      palette->setPaletteName(sl->getName());
Shinya Kitaoka 120a6e
      palette->setDirtyFlag(true);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (type == TZP_XSHLEVEL || type == OVL_XSHLEVEL) {
Jeremy Bullock 44af2c
      double dpiY = dpi;
Shinya Kitaoka 120a6e
      sl->getProperties()->setDpiPolicy(LevelProperties::DP_ImageDpi);
Shinya Kitaoka 120a6e
      if (dim == TDimension()) {
Jeremy Bullock 44af2c
        double w, h;
Shinya Kitaoka 120a6e
        Preferences *pref = Preferences::instance();
Jeremy Bullock 44af2c
        if (pref->isNewLevelSizeToCameraSizeEnabled()) {
Jeremy Bullock 44af2c
          TDimensionD camSize = getCurrentCamera()->getSize();
Jeremy Bullock 44af2c
          w                   = camSize.lx;
Jeremy Bullock 44af2c
          h                   = camSize.ly;
Jeremy Bullock 44af2c
          sl->getProperties()->setDpiPolicy(LevelProperties::DP_CustomDpi);
Jeremy Bullock 44af2c
          dpi  = getCurrentCamera()->getDpi().x;
Jeremy Bullock 44af2c
          dpiY = getCurrentCamera()->getDpi().y;
Jeremy Bullock 44af2c
        } else {
Jeremy Bullock 44af2c
          w    = pref->getDefLevelWidth();
Jeremy Bullock 44af2c
          h    = pref->getDefLevelHeight();
Jeremy Bullock 44af2c
          dpi  = pref->getDefLevelDpi();
Jeremy Bullock 44af2c
          dpiY = dpi;
Jeremy Bullock 44af2c
        }
Jeremy Bullock 44af2c
Shinya Kitaoka 120a6e
        sl->getProperties()->setImageRes(
Jeremy Bullock 44af2c
            TDimension(tround(w * dpi), tround(h * dpiY)));
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        sl->getProperties()->setImageRes(dim);
Shinya Kitaoka 120a6e
Jeremy Bullock 44af2c
      sl->getProperties()->setImageDpi(TPointD(dpi, dpiY));
Shinya Kitaoka 120a6e
      sl->getProperties()->setDpi(dpi);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    xl = sl;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_levelSet->insertLevel(xl);
Shinya Kitaoka 120a6e
  TNotifier::instance()->notify(TCastChange());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return xl;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TXsheet *ToonzScene::getXsheet() const { return m_childStack->getXsheet(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TXsheet *ToonzScene::getTopXsheet() const {
Shinya Kitaoka 120a6e
  return m_childStack->getTopXsheet();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct LevelType {
Shinya Kitaoka 120a6e
  int m_ltype;
Shinya Kitaoka 120a6e
  bool m_oldLevelFlag;
Shinya Kitaoka 120a6e
  bool m_vectorNotPli;
Shinya Kitaoka 120a6e
  std::string m_ext;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Campbell Barton b3bd84
static LevelType getLevelType(const TFilePath &fp) {
Shinya Kitaoka 120a6e
  LevelType ret;
Shinya Kitaoka 120a6e
  ret.m_ltype        = UNKNOWN_XSHLEVEL;
Shinya Kitaoka 120a6e
  ret.m_oldLevelFlag = false;
Shinya Kitaoka 120a6e
  ret.m_vectorNotPli = false;
Shinya Kitaoka 120a6e
  ret.m_ext          = fp.getType();
Shinya Kitaoka 120a6e
  std::string format = ret.m_ext;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TFileType::Type type = TFileType::getInfo(fp);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  switch (type) {
Shinya Kitaoka 120a6e
  case TFileType::RASTER_IMAGE:
Shinya Kitaoka 120a6e
  case TFileType::RASTER_LEVEL:
Shinya Kitaoka 120a6e
  case TFileType::CMAPPED_LEVEL:
Shinya Kitaoka 120a6e
    if (format == "tzp" || format == "tzu") {
Shinya Kitaoka 120a6e
      ret.m_ltype        = TZP_XSHLEVEL;
Shinya Kitaoka 120a6e
      ret.m_oldLevelFlag = true;
Shinya Kitaoka 120a6e
      ret.m_ext          = "tlv";
Shinya Kitaoka 120a6e
    } else if (format == "tzl" || format == "tlv")
Shinya Kitaoka 120a6e
      ret.m_ltype = TZP_XSHLEVEL;
Shinya Kitaoka 120a6e
    else if (format == "tzi")
Shinya Kitaoka 120a6e
      ret.m_ltype = TZI_XSHLEVEL;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      ret.m_ltype = OVL_XSHLEVEL;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case TFileType::VECTOR_LEVEL:
Shinya Kitaoka 120a6e
    if (format == "svg") {
Shinya Kitaoka 120a6e
      ret.m_vectorNotPli = true;
Shinya Kitaoka 120a6e
      ret.m_ext          = "pli";
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    /*  if (format == "svg")
Shinya Kitaoka 120a6e
            ret.m_ext = "pli";*/
Shinya Kitaoka 120a6e
    ret.m_ltype = PLI_XSHLEVEL;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case TFileType::AUDIO_LEVEL:
Shinya Kitaoka 120a6e
    ret.m_ltype = SND_XSHLEVEL;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  case TFileType::MESH_IMAGE:
Shinya Kitaoka 120a6e
  case TFileType::MESH_LEVEL:
Shinya Kitaoka 120a6e
    ret.m_ltype = MESH_XSHLEVEL;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFilePath ToonzScene::getImportedLevelPath(const TFilePath path) const {
Shinya Kitaoka 120a6e
  if (TFileType::getInfo(path) == TFileType::AUDIO_LEVEL)
Shinya Kitaoka 120a6e
    return path.withParentDir(TFilePath("+extras"));
Shinya Kitaoka 120a6e
  else if (TFileType::getInfo(path) == TFileType::PALETTE_LEVEL)
Shinya Kitaoka 120a6e
    return path.withParentDir(TFilePath("+palettes"));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const LevelType <ype = getLevelType(path);
Shinya Kitaoka 120a6e
  if (ltype.m_ltype == UNKNOWN_XSHLEVEL) return path;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const std::wstring &levelName = path.getWideName();
Shinya Kitaoka 120a6e
  const std::string &ext = path.getType(), &dots = path.getDots();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TFilePath importedLevelPath =
Shinya Kitaoka 120a6e
      getDefaultLevelPath(ltype.m_ltype, levelName).getParentDir() +
Shinya Kitaoka 120a6e
      (levelName + ::to_wstring(dots + ext));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (dots == "..")
Shinya Kitaoka 120a6e
    importedLevelPath = importedLevelPath.withFrame(TFrameId::EMPTY_FRAME);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (importedLevelPath.getType() == "tlv")  // Type shouldn't have changed...
Shinya Kitaoka 120a6e
    importedLevelPath =
Shinya Kitaoka 120a6e
        importedLevelPath.withNoFrame();  // Plus, should be unnecessary...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return importedLevelPath;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/* tzp,tzu->tlv */
Shinya Kitaoka 120a6e
bool ToonzScene::convertLevelIfNeeded(TFilePath &levelPath) {
Shinya Kitaoka 120a6e
  LevelType ltype = getLevelType(levelPath);
Shinya Kitaoka 120a6e
  TFilePath fp    = levelPath;
Shinya Kitaoka 120a6e
  if (ltype.m_vectorNotPli) {
Shinya Kitaoka 120a6e
    // livello flash o svg
Shinya Kitaoka 120a6e
    levelPath = levelPath.withType("pli");
Shinya Kitaoka 120a6e
    TLevelWriterP lw(levelPath);
Shinya Kitaoka 120a6e
    TLevelReaderP lr(fp);
Shinya Kitaoka 120a6e
    if (!lr) return false;
Shinya Kitaoka 120a6e
    TLevelP inLevel = lr->loadInfo();
Shinya Kitaoka 120a6e
    if (!inLevel || inLevel->getFrameCount() == 0) return false;
Shinya Kitaoka 120a6e
    TLevelP outLevel;
Shinya Kitaoka 120a6e
    for (TLevel::Iterator it = inLevel->begin(); it != inLevel->end(); ++it) {
Shinya Kitaoka 120a6e
      TVectorImageP img = lr->getFrameReader(it->first)->load();
Shinya Kitaoka 120a6e
      if (!img) continue;
Shinya Kitaoka 120a6e
      lw->getFrameWriter(it->first)->save(img);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else if (ltype.m_oldLevelFlag) {
Shinya Kitaoka 120a6e
    TLevelP outLevel;
Shinya Kitaoka 120a6e
    // livello Toonz 4.6
Shinya Kitaoka 120a6e
    levelPath = TFilePath(levelPath.getParentDir().getWideString() + L"\\" +
Shinya Kitaoka 120a6e
                          levelPath.getWideName() + L".tlv");
Shinya Kitaoka 120a6e
    if (TSystem::doesExistFileOrLevel(levelPath))
Shinya Kitaoka 120a6e
      TSystem::removeFileOrLevel(levelPath);
Shinya Kitaoka 120a6e
    TFilePath pltPath = TFilePath(levelPath.getParentDir().getWideString() +
Shinya Kitaoka 120a6e
                                  L"\\" + levelPath.getWideName() + L".tpl");
Shinya Kitaoka 120a6e
    if (TSystem::doesExistFileOrLevel(pltPath))
Shinya Kitaoka 120a6e
      TSystem::removeFileOrLevel(pltPath);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TLevelWriterP lw(levelPath);
Shinya Kitaoka 120a6e
    lw->setIconSize(Preferences::instance()->getIconSize());
Shinya Kitaoka 120a6e
    TPaletteP palette =
Shinya Kitaoka 120a6e
        ToonzImageUtils::loadTzPalette(fp.withType("plt").withNoFrame());
Shinya Kitaoka 120a6e
    TLevelReaderP lr(fp);
Shinya Kitaoka 120a6e
    if (!lr) return false;
Shinya Kitaoka 120a6e
    TLevelP inLevel = lr->loadInfo();
Shinya Kitaoka 120a6e
    if (!inLevel || inLevel->getFrameCount() == 0) return false;
Shinya Kitaoka 120a6e
    outLevel->setPalette(palette.getPointer());
Shinya Kitaoka 120a6e
    try {
Shinya Kitaoka 120a6e
      for (TLevel::Iterator it = inLevel->begin(); it != inLevel->end(); ++it) {
Shinya Kitaoka 120a6e
        TToonzImageP img = lr->getFrameReader(it->first)->load();
Shinya Kitaoka 120a6e
        if (!img) continue;
Shinya Kitaoka 120a6e
        img->setPalette(palette.getPointer());
Shinya Kitaoka 120a6e
        lw->getFrameWriter(it->first)->save(img);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } catch (TException &e) {
Shinya Kitaoka 120a6e
      // devo buttare il tlv che stavo salvando!
Shinya Kitaoka 120a6e
      QString msg = QString::fromStdWString(e.getMessage());
Shinya Kitaoka 120a6e
      if (msg == QString("Old 4.1 Palette")) {
Shinya Kitaoka 120a6e
        lw = TLevelWriterP();
Shinya Kitaoka 120a6e
        if (TSystem::doesExistFileOrLevel(levelPath))
Shinya Kitaoka 120a6e
          TSystem::removeFileOrLevel(levelPath);
Shinya Kitaoka 120a6e
        throw e;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    lw = TLevelWriterP();  // bisogna liberare prima lw di outLevel,
Shinya Kitaoka 120a6e
    // altrimenti la paletta che lw vuole scrivere e' gia' stata
Shinya Kitaoka 120a6e
    // loutLeveliberata.
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TXshLevel *ToonzScene::loadLevel(const TFilePath &actualPath,
Shinya Kitaoka 120a6e
                                 const LevelOptions *levelOptions,
Shinya Kitaoka 120a6e
                                 std::wstring levelName,
Shinya Kitaoka 120a6e
                                 const std::vector<tframeid> &fIds) {</tframeid>
Shinya Kitaoka 120a6e
  LevelType ltype = getLevelType(actualPath);
Shinya Kitaoka 120a6e
  if (ltype.m_ltype == UNKNOWN_XSHLEVEL) return 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TFilePath levelPath = actualPath;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Ensure the level name is unique
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (QString::fromStdWString(levelName).isEmpty()) {
Shinya Kitaoka 120a6e
    // if the option is set in the preferences,
Shinya Kitaoka 120a6e
    // remove the scene numbers("c####_") from the file name
Shinya Kitaoka 120a6e
    levelName = getLevelNameWithoutSceneNumber(levelPath.getWideName());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  NameModifier nm(levelName);
Shinya Kitaoka 120a6e
  levelName                                         = nm.getNext();
Shinya Kitaoka 120a6e
  while (m_levelSet->hasLevel(levelName)) levelName = nm.getNext();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Discriminate sound levels
Shinya Kitaoka 120a6e
  if (ltype.m_ltype == SND_XSHLEVEL) {
Shinya Kitaoka 120a6e
    TXshSoundLevel *sl = new TXshSoundLevel(levelName);
Shinya Kitaoka 120a6e
    sl->setType(ltype.m_ltype);
Shinya Kitaoka 120a6e
    sl->setScene(this);
Shinya Kitaoka 120a6e
    sl->setPath(codeFilePath(levelPath));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    try {
Shinya Kitaoka 120a6e
      sl->load();
Shinya Kitaoka 120a6e
    } catch (const std::string &msg)  // Intercepting std::string exceptions
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      throw TException(msg);
Shinya Kitaoka 120a6e
    }  // from load, and rethrowing... curious!
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_levelSet->insertLevel(sl);
Shinya Kitaoka 120a6e
    return sl;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    TXshSimpleLevel *xl = new TXshSimpleLevel(levelName);
Shinya Kitaoka 120a6e
    xl->setType(ltype.m_ltype);
Shinya Kitaoka 120a6e
    xl->setScene(this);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!convertLevelIfNeeded(levelPath))
Shinya Kitaoka 120a6e
      return 0;  // Conversion failed, bail out
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    xl->setPath(codeFilePath(levelPath), true);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    try {
Shinya Kitaoka 120a6e
      if (fIds.size() != 0)
Shinya Kitaoka 120a6e
        xl->load(fIds);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        xl->load();
Shinya Kitaoka 120a6e
    } catch (const std::string &msg) {
Shinya Kitaoka 120a6e
      throw TException(msg);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (ltype.m_oldLevelFlag)
Shinya Kitaoka 120a6e
      xl->setDirtyFlag(true);  // Not set on old level formats?
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    LevelProperties *lp = xl->getProperties();
Shinya Kitaoka 120a6e
    assert(lp);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (levelOptions)
Shinya Kitaoka 120a6e
      lp->options() = *levelOptions;
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      const Preferences &prefs = *Preferences::instance();
Shinya Kitaoka 120a6e
      int formatIdx            = prefs.matchLevelFormat(
Shinya Kitaoka 120a6e
          levelPath);  // Should I use actualPath here? It's mostly
Shinya Kitaoka 120a6e
                       // irrelevant anyway, it's for old tzp/tzu...
Shinya Kitaoka 120a6e
      if (formatIdx >= 0)
Shinya Kitaoka 120a6e
        lp->options() = prefs.levelFormat(formatIdx).m_options;
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        // Default subsampling values are assigned from scene properties
Shinya Kitaoka 120a6e
        if (xl->getType() == OVL_XSHLEVEL)
Shinya Kitaoka 120a6e
          lp->setSubsampling(getProperties()->getFullcolorSubsampling());
Shinya Kitaoka 120a6e
        else if (xl->getType() == TZP_XSHLEVEL)
Shinya Kitaoka 120a6e
          lp->setSubsampling(getProperties()->getTlvSubsampling());
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (lp->getDpiPolicy() == LevelProperties::DP_ImageDpi) {
Shinya Kitaoka 120a6e
      // We must check whether the image actually has a dpi.
Shinya Kitaoka 120a6e
      const TPointD &imageDpi = xl->getImageDpi();
Shinya Kitaoka 120a6e
Jeremy Bullock 59dbbf
      if (imageDpi == TPointD() ||
Jeremy Bullock 8c5007
          Preferences::instance()->getUnits() == "pixel" ||
Jeremy Bullock 8c5007
          Preferences::instance()->isIgnoreImageDpiEnabled()) {
Shinya Kitaoka 120a6e
        // Change to "Custom Dpi" policy and use camera dpi
Shinya Kitaoka 120a6e
        TStageObjectId cameraId =
Shinya Kitaoka 120a6e
            getXsheet()->getStageObjectTree()->getCurrentCameraId();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        lp->setDpiPolicy(LevelProperties::DP_CustomDpi);
Shinya Kitaoka 120a6e
        lp->setDpi(getCurrentCamera()->getDpi());
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        // Has dpi alright - assign it to custom dpi, too
Shinya Kitaoka 120a6e
        lp->setDpi(imageDpi);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_levelSet->insertLevel(xl);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return xl;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFilePath ToonzScene::decodeFilePath(const TFilePath &path) const {
Shinya Kitaoka 120a6e
  TProject *project   = getProject();
Shinya Kitaoka 120a6e
  bool projectIsEmpty = false;
Shinya Kitaoka 120a6e
  TFilePath fp        = path;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::wstring head;
Shinya Kitaoka 120a6e
  TFilePath tail;
Shinya Kitaoka 120a6e
  path.split(head, tail);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::string h;
Shinya Kitaoka 120a6e
  std::wstring s;
Shinya Kitaoka 120a6e
  if (head != L"" && head[0] == L'+') {
Shinya Kitaoka 120a6e
    if (TProjectManager::instance()->isTabModeEnabled()) {
Shinya Kitaoka 120a6e
      return m_scenePath.getParentDir() +
Shinya Kitaoka 120a6e
             (m_scenePath.getWideName() + L"_files") + tail;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (TProjectManager::instance()->isTabKidsModeEnabled()) {
Shinya Kitaoka 120a6e
      return m_scenePath.getParentDir() + m_scenePath.getWideName() + tail;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (projectIsEmpty) {
Shinya Kitaoka 120a6e
      TFilePath dir = m_scenePath.getParentDir();
Shinya Kitaoka 120a6e
      if (dir.getName() == "scenes")
Shinya Kitaoka 120a6e
        return dir.withName(head.substr(1)) + tail;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        return dir + tail;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (project) {
Shinya Kitaoka 120a6e
      h                       = ::to_string(head.substr(1));
Shinya Kitaoka 120a6e
      TFilePath f             = project->getFolder(h);
Shinya Kitaoka 120a6e
      if (f != TFilePath()) s = f.getWideString();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (s != L"") {
Shinya Kitaoka 120a6e
    std::map<std::wstring, std::wstring=""> table;</std::wstring,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // se la scena e' untitled e l'espansione del path
Shinya Kitaoka 120a6e
    // dipende dalla scena (o perche' l'espansione contiene
Shinya Kitaoka 120a6e
    // $scenename, $scenepath o perche' si usa il savepath)
Shinya Kitaoka 120a6e
    if (m_isUntitled &&
Shinya Kitaoka 120a6e
        (s.find(L"$scene") != std::wstring::npos ||
Shinya Kitaoka 120a6e
         project->getUseScenePath(h) ||
Shinya Kitaoka 120a6e
         fp.getParentDir().getName() == getScenePath().getName())) {
Shinya Kitaoka 120a6e
      TFilePath parentDir = getScenePath().getParentDir();
Shinya Kitaoka 120a6e
      fp                  = parentDir + head.substr(1) + tail;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      TFilePath scenePath = getScenePath();
Shinya Kitaoka 120a6e
      TFilePath scenePathRoot;
Shinya Kitaoka 120a6e
      if (project)
Shinya Kitaoka 120a6e
        scenePathRoot = project->getFolder(TProject::Scenes);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        scenePathRoot = scenePath.getParentDir();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (scenePathRoot != TFilePath() && !scenePathRoot.isAbsolute() &&
Shinya Kitaoka 120a6e
          project)
Shinya Kitaoka 120a6e
        scenePathRoot = project->getProjectFolder() + scenePathRoot;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (TSystem::isUNC(scenePath) && !TSystem::isUNC(scenePathRoot))
Shinya Kitaoka 120a6e
        scenePathRoot = TSystem::toUNC(scenePathRoot);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (scenePathRoot.isAncestorOf(scenePath))
Shinya Kitaoka 120a6e
        scenePath = scenePath - scenePathRoot;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      table[L"$scenepath"] = scenePath.withType("").getWideString();
Shinya Kitaoka 120a6e
      table[L"$scenename"] = scenePath.withType("").getWideString();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      std::map<std::wstring, std::wstring="">::reverse_iterator it;</std::wstring,>
Shinya Kitaoka 120a6e
      for (it = table.rbegin(); it != table.rend(); ++it) {
Shinya Kitaoka 120a6e
        std::wstring keyword = it->first;
Shinya Kitaoka 120a6e
        int i                = 0;
Shinya Kitaoka 120a6e
        for (;;) {
Shinya Kitaoka 120a6e
          int j = s.find(keyword, i);
Shinya Kitaoka 120a6e
          if (j == (int)std::wstring::npos) break;
Shinya Kitaoka 120a6e
          s.replace(j, keyword.length(), it->second);
Shinya Kitaoka 120a6e
          i = j;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      fp = TFilePath(s) + tail;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (fp != TFilePath() && !fp.isAbsolute() && project)
Shinya Kitaoka 120a6e
    fp = project->getProjectFolder() + fp;
Shinya Kitaoka 120a6e
  return fp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFilePath ToonzScene::codeFilePath(const TFilePath &path) const {
Shinya Kitaoka 120a6e
  TFilePath fp(path);
Shinya Kitaoka 120a6e
  TProject *project = getProject();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (project)
Shinya Kitaoka 120a6e
    for (int i = 0; i < project->getFolderCount(); i++) {
Shinya Kitaoka 120a6e
      TFilePath folderName("+" + project->getFolderName(i));
Shinya Kitaoka 120a6e
      TFilePath folderPath = decodeFilePath(folderName);
Shinya Kitaoka 120a6e
      if (folderPath.isAncestorOf(fp)) {
Shinya Kitaoka 120a6e
        fp = folderName + (fp - folderPath);
Shinya Kitaoka 120a6e
        return fp;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  return fp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFilePath ToonzScene::getDefaultLevelPath(int levelType,
Shinya Kitaoka 120a6e
                                          std::wstring levelName) const {
Shinya Kitaoka 120a6e
  TProject *project = getProject();
Shinya Kitaoka 120a6e
  assert(project);
Shinya Kitaoka 120a6e
  TFilePath levelPath;
Shinya Kitaoka 120a6e
  QString scanLevelType;
Shinya Kitaoka 120a6e
  switch (levelType) {
Shinya Kitaoka 120a6e
  case TZI_XSHLEVEL:
Shinya Kitaoka 120a6e
    scanLevelType = Preferences::instance()->getScanLevelType();
Shinya Kitaoka 120a6e
    levelPath     = TFilePath(levelName + L".." + scanLevelType.toStdWString());
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case PLI_XSHLEVEL:
Shinya Kitaoka 120a6e
    levelPath = TFilePath(levelName).withType("pli");
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TZP_XSHLEVEL:
Shinya Kitaoka 120a6e
    levelPath = TFilePath(levelName).withType("tlv");
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case OVL_XSHLEVEL:
Shinya Kitaoka 120a6e
    levelPath = TFilePath(levelName + L"..tif");
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    levelPath = TFilePath(levelName + L"..png");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  std::string folderName = getFolderName(levelType);
Shinya Kitaoka 120a6e
  if (project->getUseScenePath(folderName))
Shinya Kitaoka 120a6e
    return TFilePath("+" + folderName) + getSavePath() + levelPath;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return TFilePath("+" + folderName) + levelPath;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
const std::wstring savePathString(L"$savepath");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFilePath ToonzScene::codeSavePath(TFilePath path) const {
Shinya Kitaoka 120a6e
  if (path == TFilePath()) return path;
Shinya Kitaoka 120a6e
  TFilePath savePath = getSavePath();
Shinya Kitaoka 120a6e
  if (savePath == TFilePath()) return path;  // non dovrebbe succedere mai
Shinya Kitaoka 120a6e
  TFilePath filename;
Shinya Kitaoka 120a6e
  TFilePath originalPath = path;
Shinya Kitaoka 120a6e
  if (savePath.withoutParentDir() != path.withoutParentDir()) {
Shinya Kitaoka 120a6e
    TFilePath parentDir = path.getParentDir();
Shinya Kitaoka 120a6e
    if (parentDir != TFilePath() && !parentDir.isRoot()) {
Shinya Kitaoka 120a6e
      filename = path.withoutParentDir();
Shinya Kitaoka 120a6e
      path     = parentDir;
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      return originalPath;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TFilePath head;
Shinya Kitaoka 120a6e
  if (!checkTail(path, savePath, head)) return originalPath;
Shinya Kitaoka 120a6e
  if (head.getParentDir() != TFilePath() || head == TFilePath() ||
Shinya Kitaoka 120a6e
      head.getWideString()[0] != L'+')
Shinya Kitaoka 120a6e
    return originalPath;
Shinya Kitaoka 120a6e
  std::string folderName = ::to_string(head.getWideString().substr(1));
Shinya Kitaoka 120a6e
  if (!getProject()->getUseScenePath(folderName)) return originalPath;
Shinya Kitaoka 120a6e
  return head + savePathString + filename;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFilePath ToonzScene::decodeSavePath(TFilePath path) const {
Shinya Kitaoka 120a6e
  std::wstring s = path.getWideString();
Shinya Kitaoka 120a6e
  int i          = s.find(savePathString);
Shinya Kitaoka 120a6e
  if (i != (int)std::wstring::npos) {
Shinya Kitaoka 120a6e
    TFilePath savePath = getSavePath();
Shinya Kitaoka 120a6e
    s.replace(i, savePathString.length(), savePath.getWideString());
Shinya Kitaoka 120a6e
    return TFilePath(s);
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    return path;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool ToonzScene::isExternPath(const TFilePath &fp) const {
Shinya Kitaoka 120a6e
  TProject *project = m_project;
Shinya Kitaoka 120a6e
  assert(project);
Shinya Kitaoka 120a6e
  for (int i = 0; i < project->getFolderCount(); i++) {
Shinya Kitaoka 120a6e
    if (project->getFolderName(i) == "scenes") continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TFilePath folderPath =
Shinya Kitaoka 120a6e
        decodeFilePath(TFilePath("+" + project->getFolderName(i)));
Shinya Kitaoka 120a6e
    if (folderPath.isAncestorOf(fp)) return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TCamera *ToonzScene::getCurrentCamera() {
Shinya Kitaoka 120a6e
  return getXsheet()->getStageObjectTree()->getCurrentCamera();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TCamera *ToonzScene::getCurrentPreviewCamera() {
Shinya Kitaoka 120a6e
  return getXsheet()->getStageObjectTree()->getCurrentPreviewCamera();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TContentHistory *ToonzScene::getContentHistory(bool createIfNeeded) {
Shinya Kitaoka 120a6e
  if (!m_contentHistory && createIfNeeded)
Shinya Kitaoka 120a6e
    m_contentHistory = new TContentHistory(false);
Shinya Kitaoka 120a6e
  return m_contentHistory;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ToonzScene::getSoundColumns(std::vector<txshsoundcolumn *=""> &columns) {</txshsoundcolumn>
Shinya Kitaoka 120a6e
  ToonzScene *scene = this;
Shinya Kitaoka 120a6e
  std::set<txsheet *=""> visited, toVisit;</txsheet>
Shinya Kitaoka 120a6e
  TXsheet *xsh = scene->getChildStack()->getTopXsheet();
Shinya Kitaoka 120a6e
  visited.insert(xsh);
Shinya Kitaoka 120a6e
  toVisit.insert(xsh);
Shinya Kitaoka 120a6e
  while (!toVisit.empty()) {
Shinya Kitaoka 120a6e
    xsh = *toVisit.begin();
Shinya Kitaoka 120a6e
    toVisit.erase(xsh);
Shinya Kitaoka 120a6e
    for (int i = 0; i < xsh->getColumnCount(); i++) {
Shinya Kitaoka 120a6e
      TXshColumn *column = xsh->getColumn(i);
Shinya Kitaoka 120a6e
      if (!column) continue;
Shinya Kitaoka 120a6e
      if (TXshSoundColumn *sc = column->getSoundColumn())
Shinya Kitaoka 120a6e
        columns.push_back(sc);
Shinya Kitaoka 120a6e
      else if (TXshCellColumn *cc = column->getCellColumn()) {
Shinya Kitaoka 120a6e
        int r0 = 0, r1 = -1;
Shinya Kitaoka 120a6e
        cc->getRange(r0, r1);
Shinya Kitaoka 120a6e
        if (!cc->isEmpty() && r0 <= r1) {
Shinya Kitaoka 120a6e
          for (int r = r0; r <= r1; r++) {
Shinya Kitaoka 120a6e
            TXshCell cell = cc->getCell(r);
Shinya Kitaoka 120a6e
            if (cell.m_level && cell.m_level->getChildLevel()) {
Shinya Kitaoka 120a6e
              TXsheet *subxsh = cell.m_level->getChildLevel()->getXsheet();
Shinya Kitaoka 120a6e
              if (visited.find(subxsh) == visited.end()) {
Shinya Kitaoka 120a6e
                visited.insert(subxsh);
Shinya Kitaoka 120a6e
                toVisit.insert(subxsh);
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ToonzScene::updateSoundColumnFrameRate() {
Shinya Kitaoka 120a6e
  std::vector<txshsoundcolumn *=""> soundColumns;</txshsoundcolumn>
Shinya Kitaoka 120a6e
  getSoundColumns(soundColumns);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TSceneProperties *properties = getProperties();
Shinya Kitaoka 120a6e
  if (!properties) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TOutputProperties *outputProperties = properties->getOutputProperties();
Shinya Kitaoka 120a6e
  if (!outputProperties) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double frameRate = outputProperties->getFrameRate();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)soundColumns.size(); i++)
Shinya Kitaoka 120a6e
    soundColumns[i]->updateFrameRate(frameRate);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFilePath ToonzScene::getIconPath(const TFilePath &scenePath) {
Shinya Kitaoka 120a6e
  return scenePath.getParentDir() + "sceneIcons" +
Shinya Kitaoka 120a6e
         (scenePath.getWideName() + L" .png");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// se la scena sta in +scenes/pippo.tnz => pippo
Toshihiro Shimizu 890ddd
// se la scena sta in +scenes/pluto/pippo.tnz => pluto/pippo
Toshihiro Shimizu 890ddd
// se la scena e' untitledxxx.tnz => untitledxxx
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFilePath ToonzScene::getSavePath() const {
Shinya Kitaoka 120a6e
  std::string sceneName = getScenePath().getName();
Shinya Kitaoka 120a6e
  if (isUntitled()) return TFilePath(sceneName);
Shinya Kitaoka 120a6e
  TFilePath sceneRoot = decodeFilePath(TFilePath("+" + TProject::Scenes));
Shinya Kitaoka 120a6e
  TFilePath scenePath = getScenePath().withType("");
Shinya Kitaoka 120a6e
  TFilePath savePath(sceneName);
Shinya Kitaoka 120a6e
  if (sceneRoot.isAncestorOf(scenePath)) savePath = scenePath - sceneRoot;
Shinya Kitaoka 120a6e
  return savePath;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
double ToonzScene::shiftCameraX(double val) {
Shinya Kitaoka 120a6e
  TStageObjectTree *tree = getXsheet()->getStageObjectTree();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TStageObject *stageObject = tree->getStageObject(tree->getCurrentCameraId());
Shinya Kitaoka 120a6e
  TPointD ret               = stageObject->getOffset();
Shinya Kitaoka 120a6e
  stageObject->setOffset(TPointD(ret.x + val, ret.y));
Shinya Kitaoka 120a6e
  return ret.x;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
// if the option is set in the preferences,
Toshihiro Shimizu 890ddd
// remove the scene numbers("c####_") from the file name
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::wstring ToonzScene::getLevelNameWithoutSceneNumber(std::wstring orgName) {
Shinya Kitaoka 120a6e
  if (!Preferences::instance()->isRemoveSceneNumberFromLoadedLevelNameEnabled())
Shinya Kitaoka 120a6e
    return orgName;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QString orgNameQstr = QString::fromStdWString(orgName);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // do nothing if the file name has less than 7 letters
Shinya Kitaoka 120a6e
  if (orgNameQstr.size() <= 6) return orgName;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QString sceneName = QString::fromStdWString(getSceneName()).left(5);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // check if the first 5 letters of the level name is the same as the scene
Shinya Kitaoka 120a6e
  // name.
Shinya Kitaoka 120a6e
  // note that we must consider following both cases; "c0001_hogehoge.tif" and
Shinya Kitaoka 120a6e
  // "c0001A_####.tif"
Shinya Kitaoka 120a6e
  if (!orgNameQstr.startsWith(sceneName)) return orgName;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!orgNameQstr.contains("_")) return orgName;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return orgNameQstr.right(orgNameQstr.size() - orgNameQstr.indexOf("_") - 1)
Shinya Kitaoka 120a6e
      .toStdWString();
Toshihiro Shimizu 890ddd
}