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