| |
| |
|
|
| #include "tsystem.h" |
| #include "tiio.h" |
| #include "tcontenthistory.h" |
| #include "tconvert.h" |
| #include "tmsgcore.h" |
| |
| |
| #include <map> |
| |
| |
| #include <QDir> |
| |
| #include "tlevel_io.h" |
| |
| using namespace std; |
| |
| DEFINE_CLASS_CODE(TLevelReader, 8) |
| DEFINE_CLASS_CODE(TLevelWriter, 9) |
| |
| |
| |
| |
| typedef std::pair<QString, int> LevelReaderKey; |
| std::map<LevelReaderKey, TLevelReaderCreateProc *> LevelReaderTable; |
| std::map<QString, std::pair<TLevelWriterCreateProc *, bool>> LevelWriterTable; |
| |
| |
| |
| |
| TLevelReader::TLevelReader(const TFilePath &path) |
| : TSmartObject(m_classCode) |
| , m_info(0) |
| , m_path(path) |
| , m_contentHistory(0) |
| , m_frameFormat(TFrameId::FOUR_ZEROS) {} |
| |
| |
| |
| TLevelReader::~TLevelReader() { |
| delete m_contentHistory; |
| delete m_info; |
| } |
| |
| |
| |
| TLevelReaderP::TLevelReaderP(const TFilePath &path, int reader) { |
| QString extension = QString::fromStdString(toLower(path.getType())); |
| LevelReaderKey key(extension, reader); |
| std::map<LevelReaderKey, TLevelReaderCreateProc *>::iterator it; |
| it = LevelReaderTable.find(key); |
| if (it != LevelReaderTable.end()) { |
| m_pointer = it->second(path); |
| assert(m_pointer); |
| } else { |
| m_pointer = new TLevelReader(path); |
| } |
| m_pointer->addRef(); |
| } |
| |
| |
| |
| namespace { |
| bool myLess(const TFilePath &l, const TFilePath &r) { |
| return l.getFrame() < r.getFrame(); |
| } |
| } |
| |
| |
| |
| const TImageInfo *TLevelReader::getImageInfo(TFrameId fid) { |
| if (m_info) |
| return m_info; |
| else { |
| TImageReaderP frameReader = getFrameReader(fid); |
| if (!frameReader) return 0; |
| |
| const TImageInfo *fInfo = frameReader->getImageInfo(); |
| if (!fInfo) return 0; |
| |
| m_info = new TImageInfo(*fInfo); |
| if (m_info->m_properties) |
| m_info->m_properties = m_info->m_properties->clone(); |
| |
| return m_info; |
| } |
| } |
| |
| |
| |
| const TImageInfo *TLevelReader::getImageInfo() { |
| if (m_info) return m_info; |
| TLevelP level = loadInfo(); |
| if (level->getFrameCount() == 0) return 0; |
| return getImageInfo(level->begin()->first); |
| } |
| |
| |
| |
| TLevelP TLevelReader::loadInfo() { |
| TFilePath parentDir = m_path.getParentDir(); |
| TFilePath levelName(m_path.getLevelName()); |
| |
| |
| TFilePathSet files; |
| try { |
| files = TSystem::readDirectory(parentDir, false, true, true); |
| } catch (...) { |
| throw TImageException(m_path, "unable to read directory content"); |
| } |
| TLevelP level; |
| vector<TFilePath> data; |
| for (TFilePathSet::iterator it = files.begin(); it != files.end(); it++) { |
| TFilePath ln(it->getLevelName()); |
| |
| if (levelName == TFilePath(it->getLevelName())) { |
| try { |
| level->setFrame(it->getFrame(), TImageP()); |
| data.push_back(*it); |
| } catch (TMalformedFrameException tmfe) { |
| |
| |
| DVGui::warning(QString::fromStdWString( |
| tmfe.getMessage() + L": " + |
| QObject::tr("Skipping frame.").toStdWString())); |
| continue; |
| } |
| } |
| } |
| if (!data.empty()) { |
| std::vector<TFilePath>::iterator it = |
| std::min_element(data.begin(), data.end(), myLess); |
| |
| m_frameFormat = (*it).getFrame().getCurrentFormat(); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } else |
| m_frameFormat = TFrameId::FOUR_ZEROS; |
| |
| return level; |
| } |
| |
| |
| |
| TImageReaderP TLevelReader::getFrameReader(TFrameId fid) { |
| return TImageReaderP(m_path.withFrame(fid, m_frameFormat)); |
| } |
| |
| |
| |
| void TLevelReader::getSupportedFormats(QStringList &names) { |
| for (std::map<LevelReaderKey, TLevelReaderCreateProc *>::iterator it = |
| LevelReaderTable.begin(); |
| it != LevelReaderTable.end(); ++it) { |
| names.push_back(it->first.first); |
| } |
| } |
| |
| |
| |
| TSoundTrack *TLevelReader::loadSoundTrack() { return 0; } |
| |
| |
| |
| TLevelWriter::TLevelWriter(const TFilePath &path, TPropertyGroup *prop) |
| : TSmartObject(m_classCode) |
| , m_path(path) |
| , m_properties(prop) |
| , m_contentHistory(0) |
| , m_frameFormatTemplateFId(TFrameId::NO_FRAME) { |
| string ext = path.getType(); |
| if (!prop) m_properties = Tiio::makeWriterProperties(ext); |
| } |
| |
| |
| |
| TLevelWriter::~TLevelWriter() { |
| delete m_properties; |
| delete m_contentHistory; |
| } |
| |
| |
| |
| TLevelWriterP::TLevelWriterP(const TFilePath &path, TPropertyGroup *winfo) { |
| QString type = QString::fromStdString(toLower(path.getType())); |
| std::map<QString, std::pair<TLevelWriterCreateProc *, bool>>::iterator it; |
| it = LevelWriterTable.find(type); |
| if (it != LevelWriterTable.end()) |
| m_pointer = it->second.first( |
| path, |
| winfo ? winfo->clone() : Tiio::makeWriterProperties(path.getType())); |
| else |
| m_pointer = new TLevelWriter( |
| path, |
| winfo ? winfo->clone() : Tiio::makeWriterProperties(path.getType())); |
| |
| assert(m_pointer); |
| m_pointer->addRef(); |
| } |
| |
| |
| |
| void TLevelWriter::save(const TLevelP &level) { |
| for (TLevel::Iterator it = level->begin(); it != level->end(); it++) { |
| if (it->second) getFrameWriter(it->first)->save(it->second); |
| } |
| } |
| |
| |
| |
| void TLevelWriter::saveSoundTrack(TSoundTrack *) { |
| return; |
| throw TException("The level format doesn't support soundtracks"); |
| } |
| |
| |
| |
| void TLevelWriter::setFrameRate(double fps) { m_frameRate = fps; } |
| |
| |
| |
| void TLevelWriter::getSupportedFormats(QStringList &names, |
| bool onlyRenderFormats) { |
| for (std::map<QString, std::pair<TLevelWriterCreateProc *, bool>>::iterator |
| it = LevelWriterTable.begin(); |
| it != LevelWriterTable.end(); ++it) { |
| if (!onlyRenderFormats || it->second.second) names.push_back(it->first); |
| } |
| } |
| |
| |
| |
| TImageWriterP TLevelWriter::getFrameWriter(TFrameId fid) { |
| |
| if (!m_frameFormatTemplateFId.isNoFrame()) { |
| fid.setZeroPadding(m_frameFormatTemplateFId.getZeroPadding()); |
| fid.setStartSeqInd(m_frameFormatTemplateFId.getStartSeqInd()); |
| } |
| |
| TImageWriterP iw(m_path.withFrame(fid)); |
| iw->setProperties(m_properties); |
| return iw; |
| } |
| |
| |
| |
| void TLevelWriter::setContentHistory(TContentHistory *contentHistory) { |
| if (contentHistory != m_contentHistory) { |
| delete m_contentHistory; |
| m_contentHistory = contentHistory; |
| } |
| } |
| |
| |
| |
| void TLevelWriter::renumberFids(const std::map<TFrameId, TFrameId> &table) { |
| typedef std::map<TFrameId, TFrameId> Table; |
| |
| struct locals { |
| static inline QString qstring(const TFilePath &fp) { |
| return QString::fromStdWString(fp.getWideString()); |
| } |
| static inline QString temp(const QString &str) { |
| return str + QString("_"); |
| } |
| }; |
| |
| if (m_path.getDots() == "..") { |
| try { |
| |
| QDir parentDir( |
| QString::fromStdWString(m_path.getParentDir().getWideString())); |
| parentDir.setFilter(QDir::Files); |
| |
| QStringList nameFilters; |
| |
| nameFilters << QString::fromStdWString(m_path.getWideName()) + ".*." + |
| QString::fromStdString(m_path.getType()) |
| << QString::fromStdWString(m_path.getWideName()) + "_*." + |
| QString::fromStdString(m_path.getType()); |
| parentDir.setNameFilters(nameFilters); |
| |
| TFilePathSet fpset; |
| TSystem::readDirectory(fpset, parentDir, false); |
| |
| |
| std::vector<QString> storedDstPaths; |
| |
| TFilePathSet::iterator st, sEnd(fpset.end()); |
| for (st = fpset.begin(); st != sEnd; ++st) { |
| const QString &src = locals::qstring(*st); |
| const TFrameId &fid = st->getFrame(); |
| |
| |
| Table::const_iterator dt(table.find(fid)); |
| if (dt == table.end()) { |
| |
| QFile::remove(src); |
| } else { |
| if (fid == dt->second) continue; |
| |
| |
| const QString &dst = locals::qstring(st->withFrame(dt->second)); |
| |
| if (!QFile::rename(src, dst)) { |
| |
| |
| |
| if (QFile::rename(locals::qstring(*st), locals::temp(dst))) |
| storedDstPaths.push_back(dst); |
| |
| |
| |
| |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| std::vector<QString>::iterator dt, dEnd(storedDstPaths.end()); |
| for (dt = storedDstPaths.begin(); dt != dEnd; ++dt) |
| QFile::rename(locals::temp(*dt), *dt); |
| } catch (...) { |
| |
| } |
| } |
| } |
| |
| |
| |
| void TLevelReader::define(QString extension, int reader, |
| TLevelReaderCreateProc *proc) { |
| LevelReaderKey key(extension, reader); |
| LevelReaderTable[key] = proc; |
| |
| } |
| |
| |
| |
| void TLevelWriter::define(QString extension, TLevelWriterCreateProc *proc, |
| bool isRenderFormat) { |
| LevelWriterTable[extension] = |
| std::pair<TLevelWriterCreateProc *, bool>(proc, isRenderFormat); |
| |
| } |
| |