0f8299

0f8299
#include <iostream>
</iostream>
0f8299

0f8299
#include <tsystem.h>
</tsystem.h>
0f8299
#include <tconvert.h>
</tconvert.h>
0f8299
#include <tiio.h>
</tiio.h>
0f8299

0f8299
#include <tmetaimage.h>
</tmetaimage.h>
0f8299
#include <toonz txshsimplelevel.h="">
</toonz>
0f8299

0f8299
#include "tiio_tzm.h"
0f8299

0f8299

0f8299

0f8299
//===========================================================================
0f8299

0f8299
namespace {
0f8299
  class TLevelWriterTzm;
0f8299

0f8299
  class TImageWriterTzm final : public TImageWriter {
0f8299
  private:
0f8299
    TLevelWriterTzm &m_writer;
0f8299
    TFrameId m_frameId;
0f8299
  public:
0f8299
    TImageWriterTzm(const TFilePath &path, TLevelWriterTzm &writer, const TFrameId &frameId):
0f8299
      TImageWriter(path), m_writer(writer), m_frameId(frameId) { }
0f8299
    void save(const TImageP &image) override;
0f8299
  };
0f8299

0f8299
  class TLevelWriterTzm final : public TLevelWriter {
0f8299
  private:
0f8299
    TVariant m_data;
0f8299
    Tofstream *m_stream;
0f8299

0f8299
  public:
0f8299
    TLevelWriterTzm(const TFilePath &path, TPropertyGroup *winfo):
0f8299
      TLevelWriter(path, winfo)
0f8299
    {
0f8299
      // lock file for whole time of saving process to avoid collisions
0f8299
      try {
0f8299
        m_stream = new Tofstream(path);
0f8299
      } catch (const std::exception &e) {
0f8299
        throw TImageException(path, e.what());
0f8299
      } catch (const TException &e) {
0f8299
        throw TImageException(path, to_string(e.getMessage()));
0f8299
      }
0f8299

0f8299
      m_data["type"].setString("tzm");
0f8299
      m_data["version"].setDouble( 0.0 );
0f8299
    }
0f8299

0f8299
    TImageWriterP getFrameWriter(TFrameId frameId) override
0f8299
      { return TImageWriterP(new TImageWriterTzm(m_path, *this, frameId)); }
0f8299

0f8299
    void saveFrame(const TFrameId &frameId, const TImageP &image) {
0f8299
      if (const TMetaImage *metaImage = dynamic_cast<const tmetaimage*="">(image.getPointer())) {
</const>
0f8299
        TMetaImage::Reader reader(*metaImage);
0f8299
        TVariant &frameData = m_data["frames"][frameId.expand()];
0f8299
        TVariant &objectsData = frameData["objects"];
0f8299
        objectsData.setType(TVariant::List);
57d357
        for(TMetaObjectListCW::iterator i = reader->begin(); i != reader->end(); ++i) {
0f8299
          if (*i) {
0f8299
            TVariant &objectData = objectsData[ objectsData.size() ];
0f8299
            objectData["type"].setString( (*i)->getTypeName() );
0f8299
            objectData["data"] = (*i)->data();
0f8299
          }
0f8299
        }
0f8299
      }
0f8299
    }
0f8299

0f8299
    ~TLevelWriterTzm() {
0f8299
      try {
0f8299
        m_data["creator"].setString( m_creator.toStdString() );
0f8299
        m_data.toStream(*m_stream, true);
0f8299
        delete m_stream;
0f8299
      } catch (const std::exception &e) {
0f8299
        throw TImageException(m_path, e.what());
0f8299
      } catch (const TException &e) {
0f8299
        throw TImageException(m_path, to_string(e.getMessage()));
0f8299
      }
0f8299
    }
0f8299
  };
0f8299

0f8299
  void TImageWriterTzm::save(const TImageP &image)
0f8299
    { m_writer.saveFrame(m_frameId, image); }
0f8299
} // end of anonymous namespace for TLevelWriterTzm
0f8299

0f8299
//===========================================================================
0f8299

0f8299
namespace {
0f8299
  class TLevelReaderTzm;
0f8299

0f8299
  class TImageReaderTzm final : public TImageReader {
0f8299
  private:
0f8299
    TLevelReaderTzm &m_reader;
0f8299
    TFrameId m_frameId;
0f8299
  public:
0f8299
    TImageReaderTzm(const TFilePath &path, TLevelReaderTzm &reader, const TFrameId &frameId):
0f8299
      TImageReader(path), m_reader(reader), m_frameId(frameId) { }
0f8299
    TImageP load() override;
0f8299
  };
0f8299

0f8299

0f8299
  class TLevelReaderTzm final : public TLevelReader {
0f8299
  private:
0f8299
    TVariant m_data;
0f8299
    TLevelP m_level;
0f8299

0f8299
    void warning(const std::string &msg)
0f8299
      { std::cerr << to_string(m_path.getWideString()) << ": " << msg << std::endl; }
0f8299

0f8299
  public:
0f8299
    TLevelReaderTzm(const TFilePath &path):
0f8299
      TLevelReader(path) { }
0f8299

0f8299
    TImageReaderP getFrameReader(TFrameId frameId) override
0f8299
      { return TImageReaderP(new TImageReaderTzm(m_path, *this, frameId)); }
0f8299

0f8299
    TLevelP loadInfo() override {
0f8299
      try {
0f8299
        Tifstream stream(m_path);
0f8299
        m_data.fromStream(stream);
0f8299
      } catch (const std::exception &e) {
0f8299
        throw TImageException(m_path, e.what());
0f8299
      } catch (const TException &e) {
0f8299
        throw TImageException(m_path, to_string(e.getMessage()));
0f8299
      }
0f8299

0f8299
      if (m_data["type"].getString() != "tzm")
0f8299
        warning("seems it's not TZM");
0f8299
      if (m_data["version"].getDouble() > 0.0 + TConsts::epsilon)
0f8299
        warning( "version ("
0f8299
               + std::to_string(m_data["version"].getDouble())
0f8299
               + ") is higher than supported (0.0)");
0f8299

0f8299
      const TVariantMap &map = m_data["frames"].getMap();
0f8299
      for(TVariantMap::const_iterator i = map.begin(); i != map.end(); ++i) {
0f8299
        TFrameId frameId(i->first.str());
0f8299
        if (frameId.getNumber() < 0)
0f8299
          warning("wrong frame number: " + i->first.str());
0f8299
        else
0f8299
        if (m_level->getTable()->count(frameId))
0f8299
          warning(frameId.expand());
0f8299
        else
0f8299
          m_level->setFrame(frameId, TImageP());
0f8299
      }
0f8299

0f8299
      return m_level;
0f8299
    }
0f8299

0f8299
    QString getCreator() override
0f8299
      { return QString::fromStdString( m_data["creator"].getString() ); }
0f8299

0f8299
    TImageP loadFrame(const TFrameId &frameId) {
0f8299
      const TVariantMap &map = m_data["frames"].getMap();
0f8299
      for(TVariantMap::const_iterator i = map.begin(); i != map.end(); ++i) {
0f8299
        if (TFrameId(i->first.str()) == frameId) {
0f8299
          TMetaImage *image = new TMetaImage();
0f8299
          TMetaImage::Writer writer(*image);
0f8299
          const TVariant &objectsData = i->second["objects"];
0f8299
          if (objectsData.getType() == TVariant::List) {
0f8299
            for(int j = 0; j < objectsData.size(); ++j) {
0f8299
              const TVariant &objectData = objectsData[j];
0f8299
              if (!objectData["type"].getString().empty()) {
57d357
                TMetaObjectP obj( new TMetaObject(objectData["type"].getString()) );
0f8299
                obj->data() = objectData["data"];
0f8299
                writer->push_back(obj);
0f8299
              }
0f8299
            }
0f8299
          }
0f8299
          return image;
0f8299
        }
0f8299
      }
0f8299
      return TImageP();
0f8299
    }
0f8299
  };
0f8299

0f8299
  TImageP TImageReaderTzm::load()
0f8299
    { return m_reader.loadFrame(m_frameId); }
0f8299
} // end of anonymous namespace for TLevelReaderTzm
0f8299

0f8299
//===========================================================================
0f8299

0f8299
namespace tzm {
0f8299
  TLevelWriter* createWriter(const TFilePath &path, TPropertyGroup *winfo)
0f8299
    { return new TLevelWriterTzm(path, winfo); }
0f8299
  TLevelReader* createReader(const TFilePath &path)
0f8299
    { return new TLevelReaderTzm(path); }
0f8299
}
0f8299

0f8299
//=============================================================================