2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
|
|
|
|
#include "toonz/studiopalette.h"
|
|
|
|
#include "tfiletype.h"
|
|
|
|
#include "tstream.h"
|
|
|
|
#include "tconvert.h"
|
|
|
|
#include "tlevel_io.h"
|
|
|
|
#include "trasterimage.h"
|
|
|
|
#include "traster.h"
|
|
|
|
#include "tsystem.h"
|
|
|
|
#include "tcolorstyles.h"
|
|
|
|
#include "toonz/toonzfolders.h"
|
|
|
|
#include "toonz/tproject.h"
|
|
|
|
#include "toonz/toonzscene.h"
|
|
|
|
#include "tpalette.h"
|
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2020-10-22 19:47:52 +13:00
|
|
|
#include <QSettings>
|
|
|
|
|
2016-03-19 06:57:51 +13:00
|
|
|
//===================================================================
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
2016-06-15 18:43:10 +12:00
|
|
|
namespace {
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
|
|
TFilePath makeUniqueName(TFilePath fp) {
|
|
|
|
if (TFileStatus(fp).doesExist() == false) return fp;
|
|
|
|
std::wstring name = fp.getWideName();
|
|
|
|
int index = 2;
|
|
|
|
int j = name.find_last_not_of(L"0123456789");
|
|
|
|
if (j != (int)std::wstring::npos && j + 1 < (int)name.length()) {
|
|
|
|
index = std::stoi(name.substr(j + 1)) + 1;
|
|
|
|
name = name.substr(0, j + 1);
|
|
|
|
}
|
|
|
|
for (;;) {
|
|
|
|
fp = fp.withName(name + std::to_wstring(index));
|
|
|
|
if (TFileStatus(fp).doesExist() == false) return fp;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
|
|
TPalette *loadPliPalette(const TFilePath &fp) {
|
|
|
|
TLevelReaderP lr(fp);
|
|
|
|
TLevelP level = lr->loadInfo();
|
|
|
|
int frameCount = level->getFrameCount();
|
|
|
|
if (frameCount < 1) return 0;
|
|
|
|
TPalette *palette = level->getPalette();
|
|
|
|
if (!palette) return 0;
|
|
|
|
return palette->clone();
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
|
|
TPalette *loadTplPalette(const TFilePath &fp) {
|
|
|
|
TPersist *p = 0;
|
|
|
|
TIStream is(fp);
|
|
|
|
is >> p;
|
|
|
|
TPalette *palette = dynamic_cast<TPalette *>(p);
|
|
|
|
return palette;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
|
|
TPalette *loadToonz46Palette(const TFilePath &fp) {
|
|
|
|
TImageP pltImg;
|
|
|
|
TImageReader::load(fp, pltImg);
|
|
|
|
if (!pltImg) return 0;
|
|
|
|
TRasterImageP pltRasImg(pltImg);
|
|
|
|
if (!pltRasImg) return 0;
|
|
|
|
TRaster32P rasPlt = pltRasImg->getRaster();
|
|
|
|
if (!rasPlt) return 0;
|
|
|
|
TPalette *palette = new TPalette();
|
|
|
|
const int offset = 0; // FirstUserStyle-1;
|
|
|
|
assert(rasPlt->getLy() == 2);
|
|
|
|
rasPlt->lock();
|
|
|
|
TPixel32 *pixelRow = rasPlt->pixels(0);
|
|
|
|
int x;
|
|
|
|
for (x = 1; x < rasPlt->getLx(); ++x) {
|
|
|
|
TPixel32 color = pixelRow[x];
|
|
|
|
int styleId = offset + x;
|
|
|
|
if (styleId < palette->getStyleCount())
|
|
|
|
palette->setStyle(styleId, color);
|
|
|
|
else {
|
|
|
|
int j = palette->addStyle(color);
|
|
|
|
assert(j == styleId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// aggiungo solo i colori usati (salvo il BG)
|
|
|
|
|
|
|
|
pixelRow = rasPlt->pixels(1);
|
|
|
|
TPalette::Page *page = palette->getPage(0);
|
|
|
|
for (x = 1; x < rasPlt->getLx(); ++x) {
|
|
|
|
if (pixelRow[x].r == 255)
|
|
|
|
page->addStyle(offset +
|
|
|
|
x); // palette->addStyleToPage(offset+x, L"colors");
|
|
|
|
}
|
|
|
|
rasPlt->unlock();
|
|
|
|
return palette;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
|
|
std::wstring readPaletteGlobalName(TFilePath path) {
|
|
|
|
try {
|
|
|
|
TIStream is(path);
|
|
|
|
if (!is) return L"";
|
|
|
|
std::string tagName;
|
|
|
|
if (!is.matchTag(tagName) || tagName != "palette") return L"";
|
|
|
|
std::string name;
|
|
|
|
if (is.getTagParam("name", name)) return ::to_wstring(name);
|
|
|
|
} catch (...) {
|
|
|
|
}
|
|
|
|
return L"";
|
|
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
|
|
TFilePath searchPalette(TFilePath path, std::wstring paletteId) {
|
|
|
|
TFilePathSet q;
|
|
|
|
try {
|
|
|
|
TSystem::readDirectory(q, path);
|
|
|
|
} catch (...) {
|
|
|
|
}
|
|
|
|
|
|
|
|
for (TFilePathSet::iterator i = q.begin(); i != q.end(); ++i) {
|
|
|
|
TFilePath fp = *i;
|
|
|
|
if (fp.getType() == "tpl") {
|
|
|
|
std::wstring gname = readPaletteGlobalName(fp);
|
|
|
|
if (gname == paletteId) return fp;
|
|
|
|
} else if (TFileStatus(fp).isDirectory()) {
|
|
|
|
TFilePath palettePath = searchPalette(fp, paletteId);
|
|
|
|
if (palettePath != TFilePath()) return palettePath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TFilePath();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
bool studioPaletteHasBeenReferred = false;
|
|
|
|
|
2016-04-19 19:32:17 +12:00
|
|
|
static std::map<std::wstring, TFilePath> table;
|
2020-10-22 19:47:52 +13:00
|
|
|
// table loaded from the cache. verify once before storing in the table
|
|
|
|
static std::map<std::wstring, TFilePath> table_cached;
|
|
|
|
|
|
|
|
const std::string pathTableFileName = "palette_paths.ini";
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
2016-06-15 18:43:10 +12:00
|
|
|
} // namespace
|
2016-03-19 06:57:51 +13:00
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
|
|
//===================================================================
|
|
|
|
//
|
|
|
|
// StudioPalette
|
|
|
|
//
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
StudioPalette::StudioPalette() {
|
|
|
|
try {
|
|
|
|
m_root = ToonzFolder::getStudioPaletteFolder();
|
|
|
|
} catch (...) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!TFileStatus(m_root).doesExist()) {
|
|
|
|
try {
|
|
|
|
TSystem::mkDir(m_root);
|
|
|
|
FolderListenerManager::instance()->notifyFolderChanged(
|
|
|
|
m_root.getParentDir());
|
|
|
|
} catch (...) {
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
TSystem::mkDir(getLevelPalettesRoot());
|
|
|
|
FolderListenerManager::instance()->notifyFolderChanged(
|
|
|
|
getLevelPalettesRoot().getParentDir());
|
|
|
|
} catch (...) {
|
|
|
|
}
|
|
|
|
}
|
2020-10-22 19:47:52 +13:00
|
|
|
|
|
|
|
// load [global id] - [path] table file
|
|
|
|
TFilePath rootFps[2] = {m_root, getProjectPalettesRoot()};
|
|
|
|
for (auto rootFp : rootFps) {
|
|
|
|
if (rootFp.isEmpty()) continue;
|
|
|
|
TFilePath tablePath = rootFp + pathTableFileName;
|
|
|
|
if (!TFileStatus(tablePath).doesExist()) continue;
|
|
|
|
QSettings tableSettings(QString::fromStdWString(tablePath.getWideString()),
|
|
|
|
QSettings::IniFormat);
|
|
|
|
for (auto key : tableSettings.allKeys())
|
|
|
|
table_cached[key.toStdWString()] =
|
|
|
|
rootFp + TFilePath(tableSettings.value(key, "").toString());
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
StudioPalette::~StudioPalette() {}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
|
|
bool StudioPalette::m_enabled = true;
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void StudioPalette::enable(bool enabled) {
|
|
|
|
assert(studioPaletteHasBeenReferred == false);
|
|
|
|
m_enabled = enabled;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
StudioPalette *StudioPalette::instance() {
|
|
|
|
static StudioPalette _instance;
|
|
|
|
studioPaletteHasBeenReferred = true;
|
|
|
|
assert(m_enabled);
|
|
|
|
return &_instance;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TFilePath StudioPalette::getLevelPalettesRoot() {
|
2016-06-16 17:15:05 +12:00
|
|
|
return m_root + "Global Palettes";
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TFilePath StudioPalette::getProjectPalettesRoot() {
|
|
|
|
TProjectP p = TProjectManager::instance()->getCurrentProject();
|
|
|
|
TFilePath folderName = p->getFolder(TProject::Palettes);
|
|
|
|
if (folderName.isEmpty()) return TFilePath();
|
|
|
|
if (folderName.isAbsolute()) return folderName;
|
|
|
|
return p->getProjectFolder() + folderName;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2020-07-26 16:51:26 +12:00
|
|
|
TFilePath StudioPalette::getPersonalPalettesRoot() {
|
|
|
|
TFilePath folderName = ToonzFolder::getMyPalettesDir();
|
|
|
|
if (folderName.isEmpty()) return TFilePath();
|
|
|
|
return folderName;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-07-14 00:05:06 +12:00
|
|
|
static bool loadRefImg(TPalette *palette, TFilePath dir) {
|
2016-06-15 18:43:10 +12:00
|
|
|
assert(palette);
|
|
|
|
TFilePath fp = palette->getRefImgPath();
|
|
|
|
if (fp == TFilePath() || !TSystem::doesExistFileOrLevel(fp)) return false;
|
|
|
|
if (!fp.isAbsolute()) fp = dir + fp;
|
|
|
|
TLevelReaderP lr(fp);
|
|
|
|
if (!lr) return false;
|
|
|
|
TLevelP level = lr->loadInfo();
|
|
|
|
if (!level || level->getFrameCount() == 0) return false;
|
|
|
|
TLevel::Iterator it = level->begin();
|
|
|
|
TImageP img = lr->getFrameReader(it->first)->load();
|
|
|
|
if (!img) return false;
|
|
|
|
img->setPalette(0);
|
|
|
|
palette->setRefImg(img);
|
|
|
|
return true;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TPalette *StudioPalette::getPalette(const TFilePath &path,
|
|
|
|
bool loadRefImgFlag) {
|
|
|
|
try {
|
|
|
|
if (path.getType() != "tpl") return 0;
|
|
|
|
TPalette *palette = load(path);
|
|
|
|
if (!palette) return 0;
|
|
|
|
if (loadRefImgFlag) loadRefImg(palette, path.getParentDir());
|
|
|
|
// palette->addRef(); // ci va??
|
|
|
|
return palette;
|
|
|
|
} catch (...) {
|
|
|
|
return 0;
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void StudioPalette::movePalette(const TFilePath &dstPath,
|
|
|
|
const TFilePath &srcPath) {
|
|
|
|
try {
|
2018-04-23 17:13:40 +12:00
|
|
|
// do not allow overwrite palette
|
|
|
|
TSystem::renameFile(dstPath, srcPath, false);
|
2016-06-15 18:43:10 +12:00
|
|
|
} catch (...) {
|
2018-04-23 17:13:40 +12:00
|
|
|
throw;
|
2016-06-15 18:43:10 +12:00
|
|
|
}
|
|
|
|
std::wstring id = readPaletteGlobalName(dstPath);
|
|
|
|
table.erase(id);
|
2020-10-22 19:47:52 +13:00
|
|
|
removeEntry(id);
|
2016-06-15 18:43:10 +12:00
|
|
|
FolderListenerManager::instance()->notifyFolderChanged(
|
|
|
|
dstPath.getParentDir());
|
|
|
|
notifyMove(dstPath, srcPath);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
int StudioPalette::getChildren(std::vector<TFilePath> &fps,
|
|
|
|
const TFilePath &folderPath) {
|
|
|
|
TFilePathSet q;
|
|
|
|
if (TFileStatus(folderPath).isDirectory()) {
|
|
|
|
try {
|
|
|
|
TSystem::readDirectory(q, folderPath, false, false);
|
|
|
|
} catch (...) {
|
|
|
|
}
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2018-04-23 17:13:40 +12:00
|
|
|
// put the folders above the palette items
|
|
|
|
std::vector<TFilePath> palettes;
|
|
|
|
for (TFilePathSet::iterator i = q.begin(); i != q.end(); ++i) {
|
|
|
|
if (isFolder(*i))
|
|
|
|
fps.push_back(*i);
|
|
|
|
else if (isPalette(*i))
|
|
|
|
palettes.push_back(*i);
|
|
|
|
}
|
|
|
|
if (!palettes.empty()) {
|
|
|
|
fps.reserve(fps.size() + palettes.size());
|
|
|
|
std::copy(palettes.begin(), palettes.end(), std::back_inserter(fps));
|
|
|
|
}
|
2016-06-15 18:43:10 +12:00
|
|
|
// fps.push_back(m_root+"butta.tpl");
|
|
|
|
return fps.size();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
int StudioPalette::getChildCount(const TFilePath &folderPath) {
|
|
|
|
TFilePathSet q;
|
|
|
|
try {
|
|
|
|
TSystem::readDirectory(q, folderPath);
|
|
|
|
} catch (...) {
|
|
|
|
}
|
|
|
|
return q.size();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bool StudioPalette::isFolder(const TFilePath &path) {
|
|
|
|
return TFileStatus(path).isDirectory();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bool StudioPalette::isReadOnly(const TFilePath &path) {
|
|
|
|
return !TFileStatus(path).isWritable();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bool StudioPalette::isPalette(const TFilePath &path) {
|
|
|
|
return path.getType() == "tpl";
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
2016-06-15 18:43:10 +12:00
|
|
|
/*! check if the palette is studio palette or level palette in order to separate
|
|
|
|
* icons in the StudioPaletteTree.
|
2020-07-06 17:32:52 +12:00
|
|
|
*/
|
2016-06-15 18:43:10 +12:00
|
|
|
bool StudioPalette::hasGlobalName(const TFilePath &path) {
|
|
|
|
return (readPaletteGlobalName(path) != L"");
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bool StudioPalette::isLevelPalette(const TFilePath &path) {
|
|
|
|
TPalette *palette = getPalette(path);
|
|
|
|
if (!palette) return false;
|
2020-05-27 18:38:36 +12:00
|
|
|
bool ret = !palette->isCleanupPalette();
|
2016-06-15 18:43:10 +12:00
|
|
|
delete palette;
|
|
|
|
return ret;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TFilePath StudioPalette::createFolder(const TFilePath &parentFolderPath) {
|
|
|
|
TFilePath path = makeUniqueName(parentFolderPath + "new folder");
|
|
|
|
try {
|
|
|
|
TSystem::mkDir(path);
|
|
|
|
} catch (...) {
|
|
|
|
return TFilePath();
|
|
|
|
}
|
|
|
|
FolderListenerManager::instance()->notifyFolderChanged(parentFolderPath);
|
|
|
|
notifyTreeChange();
|
|
|
|
return path;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void StudioPalette::createFolder(const TFilePath &parentFolderPath,
|
|
|
|
std::wstring name) {
|
|
|
|
TFilePath fp = parentFolderPath + name;
|
|
|
|
if (TFileStatus(fp).doesExist()) return;
|
|
|
|
try {
|
|
|
|
TSystem::mkDir(fp);
|
|
|
|
} catch (...) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
FolderListenerManager::instance()->notifyFolderChanged(parentFolderPath);
|
|
|
|
notifyTreeChange();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TFilePath StudioPalette::createPalette(const TFilePath &folderPath,
|
|
|
|
std::string name) {
|
2020-07-06 17:32:52 +12:00
|
|
|
TPalette *palette = 0;
|
2016-06-15 18:43:10 +12:00
|
|
|
if (name == "") name = "new palette";
|
2020-07-06 17:32:52 +12:00
|
|
|
palette = new TPalette();
|
|
|
|
TFilePath fp = makeUniqueName(folderPath + (name + ".tpl"));
|
2016-06-15 18:43:10 +12:00
|
|
|
time_t ltime;
|
|
|
|
time(<ime);
|
|
|
|
std::wstring gname = std::to_wstring(ltime) + L"_" + std::to_wstring(rand());
|
|
|
|
palette->setGlobalName(gname);
|
|
|
|
setStylesGlobalNames(palette);
|
2020-07-06 17:32:52 +12:00
|
|
|
try {
|
|
|
|
save(fp, palette);
|
|
|
|
} catch (...) {
|
|
|
|
delete palette;
|
|
|
|
throw;
|
|
|
|
}
|
2016-06-15 18:43:10 +12:00
|
|
|
delete palette;
|
|
|
|
notifyTreeChange();
|
|
|
|
return fp;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void StudioPalette::setPalette(const TFilePath &palettePath,
|
|
|
|
const TPalette *plt, bool notifyPaletteChanged) {
|
|
|
|
assert(palettePath.getType() == "tpl");
|
|
|
|
TPalette *palette = plt->clone();
|
|
|
|
palette->setIsLocked(plt->isLocked());
|
|
|
|
palette->addRef();
|
|
|
|
std::wstring pgn = palette->getGlobalName();
|
|
|
|
if (TFileStatus(palettePath).doesExist())
|
|
|
|
pgn = readPaletteGlobalName(palettePath);
|
|
|
|
palette->setGlobalName(pgn);
|
|
|
|
setStylesGlobalNames(palette);
|
2020-07-06 17:32:52 +12:00
|
|
|
try {
|
|
|
|
save(palettePath, palette);
|
|
|
|
} catch (...) {
|
|
|
|
palette->release();
|
|
|
|
throw;
|
|
|
|
}
|
2016-06-15 18:43:10 +12:00
|
|
|
palette->release();
|
|
|
|
if (notifyPaletteChanged) notifyPaletteChange(palettePath);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void StudioPalette::deletePalette(const TFilePath &palettePath) {
|
|
|
|
assert(palettePath.getType() == "tpl");
|
|
|
|
try {
|
|
|
|
TSystem::deleteFile(palettePath);
|
|
|
|
} catch (...) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
notifyTreeChange();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void StudioPalette::deleteFolder(const TFilePath &path) {
|
|
|
|
try {
|
|
|
|
TSystem::rmDirTree(path);
|
|
|
|
} catch (...) {
|
|
|
|
}
|
|
|
|
notifyTreeChange();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TFilePath StudioPalette::importPalette(const TFilePath &dstFolder,
|
|
|
|
const TFilePath &srcPath) {
|
|
|
|
TPaletteP palette;
|
|
|
|
std::string ext = srcPath.getType();
|
|
|
|
try {
|
|
|
|
if (ext == "plt")
|
|
|
|
palette = loadToonz46Palette(srcPath);
|
|
|
|
else if (ext == "pli")
|
|
|
|
palette = loadPliPalette(srcPath);
|
|
|
|
else if (ext == "tpl")
|
|
|
|
palette = loadTplPalette(srcPath);
|
|
|
|
} catch (...) {
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
if (!palette) return TFilePath();
|
|
|
|
std::wstring name = srcPath.getWideName();
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2020-05-27 18:38:36 +12:00
|
|
|
assert(!palette->isCleanupPalette());
|
|
|
|
// convertToLevelPalette(palette.getPointer());
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TFilePath fp = makeUniqueName(dstFolder + (name + L".tpl"));
|
|
|
|
time_t ltime;
|
|
|
|
time(<ime);
|
|
|
|
std::wstring gname = std::to_wstring(ltime) + L"_" + std::to_wstring(rand());
|
|
|
|
palette->setGlobalName(gname);
|
|
|
|
setStylesGlobalNames(palette.getPointer());
|
|
|
|
TSystem::touchParentDir(fp);
|
|
|
|
save(fp, palette.getPointer());
|
|
|
|
notifyTreeChange();
|
|
|
|
return fp;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
2016-06-15 18:43:10 +12:00
|
|
|
|
|
|
|
// TFilePath StudioPalette::getRefImage(const TFilePath palette)
|
2016-03-19 06:57:51 +13:00
|
|
|
//{
|
|
|
|
// return palette.withType("pli");
|
|
|
|
//}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-07-14 00:05:06 +12:00
|
|
|
static void foobar(std::wstring paletteId) { table.erase(paletteId); }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TFilePath StudioPalette::getPalettePath(std::wstring paletteId) {
|
|
|
|
std::map<std::wstring, TFilePath>::iterator it = table.find(paletteId);
|
|
|
|
if (it != table.end()) return it->second;
|
2020-10-22 19:47:52 +13:00
|
|
|
TFilePath fp;
|
|
|
|
// not found in the verified table, then check for the cached table
|
|
|
|
it = table_cached.find(paletteId);
|
|
|
|
// found in the cached table
|
|
|
|
if (it != table_cached.end()) {
|
|
|
|
fp = it->second;
|
|
|
|
// verify if cached path is correct
|
|
|
|
if (fp.getType() != "tpl" ||
|
|
|
|
readPaletteGlobalName(it->second) != paletteId) {
|
|
|
|
fp = TFilePath();
|
|
|
|
// erase the entry
|
|
|
|
it = table_cached.erase(it);
|
|
|
|
removeEntry(paletteId);
|
|
|
|
}
|
2016-06-15 18:43:10 +12:00
|
|
|
}
|
2020-10-22 19:47:52 +13:00
|
|
|
if (fp.isEmpty()) {
|
|
|
|
fp = searchPalette(m_root, paletteId);
|
|
|
|
if (fp.isEmpty()) fp = searchPalette(getProjectPalettesRoot(), paletteId);
|
|
|
|
if (fp.isEmpty()) fp = searchPalette(getPersonalPalettesRoot(), paletteId);
|
|
|
|
|
|
|
|
addEntry(paletteId, fp);
|
2020-07-26 16:51:26 +12:00
|
|
|
}
|
2016-06-15 18:43:10 +12:00
|
|
|
table[paletteId] = fp;
|
|
|
|
return fp;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TPalette *StudioPalette::getPalette(std::wstring paletteId) {
|
|
|
|
TFilePath palettePath = getPalettePath(paletteId);
|
|
|
|
if (palettePath != TFilePath())
|
|
|
|
return getPalette(palettePath);
|
|
|
|
else
|
|
|
|
return 0;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TColorStyle *StudioPalette::getStyle(std::wstring styleId) { return 0; }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
std::pair<TFilePath, int> StudioPalette::getSourceStyle(TColorStyle *cs) {
|
|
|
|
std::pair<TFilePath, int> ret(TFilePath(), -1);
|
|
|
|
if (!cs) return ret;
|
|
|
|
std::wstring gname = cs->getGlobalName();
|
|
|
|
if (gname == L"") return ret;
|
|
|
|
int k = gname.find_first_of(L'-', 1);
|
|
|
|
if (k == (int)std::wstring::npos) return ret;
|
|
|
|
std::wstring paletteId = gname.substr(1, k - 1);
|
|
|
|
ret.first = getPalettePath(paletteId) - m_root;
|
|
|
|
ret.second = std::stoi(gname.substr(k + 1));
|
|
|
|
return ret;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
/*! return if any style in the palette is changed
|
2020-07-06 17:32:52 +12:00
|
|
|
*/
|
2016-06-15 18:43:10 +12:00
|
|
|
bool StudioPalette::updateLinkedColors(TPalette *palette) {
|
|
|
|
bool paletteIsChanged = false;
|
|
|
|
std::map<std::wstring, TPaletteP> table;
|
|
|
|
|
|
|
|
for (int i = 0; i < palette->getStyleCount(); i++) {
|
|
|
|
TColorStyle *cs = palette->getStyle(i);
|
|
|
|
std::wstring gname = cs->getGlobalName();
|
|
|
|
if (gname == L"" || gname[0] != L'+') continue;
|
|
|
|
int k = gname.find_first_of(L'-', 1);
|
|
|
|
if (k == (int)std::wstring::npos) continue;
|
|
|
|
std::wstring paletteId = gname.substr(1, k - 1);
|
|
|
|
std::map<std::wstring, TPaletteP>::iterator it;
|
|
|
|
it = table.find(paletteId);
|
|
|
|
TPalette *spPalette = 0;
|
|
|
|
if (it == table.end()) {
|
2020-10-22 19:47:52 +13:00
|
|
|
spPalette = getPalette(paletteId);
|
2016-06-15 18:43:10 +12:00
|
|
|
if (!spPalette) continue;
|
|
|
|
table[paletteId] = spPalette;
|
|
|
|
// spPalette->release();
|
|
|
|
assert(spPalette->getRefCount() == 1);
|
|
|
|
} else
|
|
|
|
spPalette = it->second.getPointer();
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
int j = std::stoi(gname.substr(k + 1));
|
|
|
|
if (spPalette && 0 <= j && j < spPalette->getStyleCount()) {
|
|
|
|
TColorStyle *spStyle = spPalette->getStyle(j);
|
|
|
|
assert(spStyle);
|
|
|
|
spStyle = spStyle->clone();
|
|
|
|
spStyle->setGlobalName(gname);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
// put the style name in the studio palette into the original name
|
|
|
|
spStyle->setOriginalName(spStyle->getName());
|
|
|
|
//.. and keep the style name unchanged
|
|
|
|
spStyle->setName(cs->getName());
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
palette->setStyle(i, spStyle);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
paletteIsChanged = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return paletteIsChanged;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void StudioPalette::setStylesGlobalNames(TPalette *palette) {
|
|
|
|
for (int i = 0; i < palette->getStyleCount(); i++) {
|
|
|
|
TColorStyle *cs = palette->getStyle(i);
|
|
|
|
// set global name only to the styles of which the global name is empty
|
|
|
|
if (cs->getGlobalName() == L"") {
|
|
|
|
std::wstring gname =
|
|
|
|
L"-" + palette->getGlobalName() + L"-" + std::to_wstring(i);
|
|
|
|
cs->setGlobalName(gname);
|
|
|
|
}
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void StudioPalette::save(const TFilePath &path, TPalette *palette) {
|
2019-05-16 07:04:48 +12:00
|
|
|
TFileStatus fs(path);
|
2019-06-07 13:08:15 +12:00
|
|
|
if (fs.doesExist() && !fs.isWritable()) {
|
2019-05-16 07:04:48 +12:00
|
|
|
throw TSystemException(path,
|
|
|
|
"The studio palette cannot be saved: it is a read "
|
|
|
|
"only studio palette.");
|
|
|
|
}
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TOStream os(path);
|
2020-07-06 17:32:52 +12:00
|
|
|
if (!os) {
|
|
|
|
throw TSystemException(path,
|
|
|
|
"The studio palette cannot be saved: the output "
|
|
|
|
"stream status is invalid.");
|
|
|
|
}
|
2016-06-15 18:43:10 +12:00
|
|
|
std::map<std::string, std::string> attr;
|
|
|
|
attr["name"] = ::to_string(palette->getGlobalName());
|
|
|
|
os.openChild("palette", attr);
|
|
|
|
palette->saveData(os);
|
|
|
|
os.closeChild();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TPalette *StudioPalette::load(const TFilePath &path) {
|
|
|
|
try {
|
|
|
|
TIStream is(path);
|
|
|
|
if (!is) return 0;
|
|
|
|
std::string tagName;
|
|
|
|
if (!is.matchTag(tagName) || tagName != "palette") return 0;
|
|
|
|
std::string gname;
|
|
|
|
is.getTagParam("name", gname);
|
|
|
|
TPalette *palette = new TPalette();
|
|
|
|
palette->loadData(is);
|
|
|
|
palette->setGlobalName(::to_wstring(gname));
|
|
|
|
is.matchEndTag();
|
|
|
|
palette->setPaletteName(path.getWideName());
|
|
|
|
return palette;
|
|
|
|
} catch (...) {
|
|
|
|
return 0;
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void StudioPalette::addListener(Listener *listener) {
|
|
|
|
if (std::find(m_listeners.begin(), m_listeners.end(), listener) ==
|
|
|
|
m_listeners.end())
|
|
|
|
m_listeners.push_back(listener);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void StudioPalette::removeListener(Listener *listener) {
|
|
|
|
m_listeners.erase(
|
|
|
|
std::remove(m_listeners.begin(), m_listeners.end(), listener),
|
|
|
|
m_listeners.end());
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void StudioPalette::notifyTreeChange() {
|
|
|
|
for (std::vector<Listener *>::iterator it = m_listeners.begin();
|
|
|
|
it != m_listeners.end(); ++it)
|
|
|
|
(*it)->onStudioPaletteTreeChange();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void StudioPalette::notifyMove(const TFilePath &dstPath,
|
|
|
|
const TFilePath &srcPath) {
|
|
|
|
for (std::vector<Listener *>::iterator it = m_listeners.begin();
|
|
|
|
it != m_listeners.end(); ++it)
|
|
|
|
(*it)->onStudioPaletteMove(dstPath, srcPath);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void StudioPalette::notifyPaletteChange(const TFilePath &palette) {
|
|
|
|
for (std::vector<Listener *>::iterator it = m_listeners.begin();
|
|
|
|
it != m_listeners.end(); ++it)
|
|
|
|
(*it)->onStudioPaletteChange(palette);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
2020-10-22 19:47:52 +13:00
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
|
|
void StudioPalette::removeEntry(const std::wstring paletteId) {
|
|
|
|
TFilePath rootFps[2] = {m_root, getProjectPalettesRoot()};
|
|
|
|
for (auto rootFp : rootFps) {
|
|
|
|
if (rootFp.isEmpty()) continue;
|
|
|
|
TFilePath tablePath = rootFp + pathTableFileName;
|
|
|
|
if (!TFileStatus(tablePath).doesExist()) continue;
|
|
|
|
QSettings tableSettings(QString::fromStdWString(tablePath.getWideString()),
|
|
|
|
QSettings::IniFormat);
|
|
|
|
if (tableSettings.contains(QString::fromStdWString(paletteId))) {
|
|
|
|
tableSettings.remove(QString::fromStdWString(paletteId));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
|
|
void StudioPalette::addEntry(const std::wstring paletteId,
|
|
|
|
const TFilePath &path) {
|
|
|
|
TFilePath rootFps[2] = {m_root, getProjectPalettesRoot()};
|
|
|
|
for (auto rootFp : rootFps) {
|
|
|
|
if (rootFp.isEmpty()) continue;
|
|
|
|
if (!rootFp.isAncestorOf(path)) continue;
|
|
|
|
|
|
|
|
TFilePath tablePath = rootFp + pathTableFileName;
|
|
|
|
QSettings tableSettings(QString::fromStdWString(tablePath.getWideString()),
|
|
|
|
QSettings::IniFormat);
|
|
|
|
QString pathValue = (path - rootFp).getQString();
|
|
|
|
tableSettings.setValue(QString::fromStdWString(paletteId), pathValue);
|
|
|
|
}
|
|
|
|
}
|