diff --git a/QtGameMaker.pro b/QtGameMaker.pro index b424f6b..d0c0f19 100644 --- a/QtGameMaker.pro +++ b/QtGameMaker.pro @@ -81,7 +81,9 @@ HEADERS += \ src/editor/widgets/actionscontainerwidget.h \ src/editor/widgets/codeeditorwidget.h \ src/editor/widgets/drawingcanvaswidget.h \ - src/editor/widgets/pathpointswidget.h + src/editor/widgets/pathpointswidget.h \ + src/projectserialization.h \ + src/stdserialization.h SOURCES += \ src/closeeventfilter.cpp \ @@ -140,7 +142,8 @@ SOURCES += \ src/editor/widgets/actionscontainerwidget.cpp \ src/editor/widgets/codeeditorwidget.cpp \ src/editor/widgets/drawingcanvaswidget.cpp \ - src/editor/widgets/pathpointswidget.cpp + src/editor/widgets/pathpointswidget.cpp \ + src/projectserialization.cpp FORMS += \ src/editor/mainwindow.ui \ diff --git a/src/editor/mainwindow.cpp b/src/editor/mainwindow.cpp index d2b0fd3..f7eb247 100644 --- a/src/editor/mainwindow.cpp +++ b/src/editor/mainwindow.cpp @@ -11,6 +11,7 @@ #include #include +#include "projectserialization.h" #include "models/projecttreemodel.h" #include "dialogs/preferencesdialog.h" #include "dialogs/spritepropertiesdialog.h" diff --git a/src/editor/models/actionscontainermodel.cpp b/src/editor/models/actionscontainermodel.cpp index fd48f85..19ad23e 100644 --- a/src/editor/models/actionscontainermodel.cpp +++ b/src/editor/models/actionscontainermodel.cpp @@ -2,6 +2,10 @@ #include #include +#include + +#include "projectserialization.h" +#include "stdserialization.h" ActionsContainerModel::ActionsContainerModel(QObject *parent) : QAbstractListModel{parent} @@ -86,7 +90,7 @@ Qt::DropActions ActionsContainerModel::supportedDropActions() const { auto actions = QAbstractListModel::supportedDropActions(); actions |= Qt::MoveAction; - actions |= Qt::TargetMoveAction; + // actions |= Qt::TargetMoveAction; return actions; } @@ -94,10 +98,184 @@ Qt::DropActions ActionsContainerModel::supportedDragActions() const { auto actions = QAbstractListModel::supportedDragActions(); actions |= Qt::MoveAction; - actions |= Qt::TargetMoveAction; + // actions |= Qt::TargetMoveAction; return actions; } +QStringList ActionsContainerModel::mimeTypes() const +{ + return {"custom"}; +} + +QMimeData *ActionsContainerModel::mimeData(const QModelIndexList &indexes) const +{ + if (!m_actionsContainer) + return nullptr; + if (indexes.size() <= 0) + return nullptr; + + QStringList types = mimeTypes(); + if (types.isEmpty()) + return nullptr; + QMimeData *data = new QMimeData; + QString format = types.at(0); + QByteArray encoded; + QDataStream stream(&encoded, QDataStream::WriteOnly); + for (const auto &index : indexes) + { + const Action &action = *std::next(std::cbegin(*m_actionsContainer), index.row()); + stream << action; + } + data->setData(format, encoded); + return data; +} + +bool ActionsContainerModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const +{ + if (!m_actionsContainer) + { + qWarning() << "no container"; + return false; + } + // if the drop is on an item, reject drop + if (parent.isValid() && row == -1 && column == -1) + { + // qWarning() << "drop on item"; + return false; + } + + return QAbstractListModel::canDropMimeData(data, action, row, column, parent); +} + +bool ActionsContainerModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) +{ + if (!m_actionsContainer) + { + qWarning() << "no container"; + return false; + } + // check if the action is supported + if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction)) + { + qWarning() << "wrong action"; + return false; + } + + // if the drop is on an item, replace the data in the items + if (parent.isValid() && row == -1 && column == -1) + { + // qWarning() << "drop on item"; + return false; + } + + // check if the format is supported + QStringList types = mimeTypes(); + if (types.isEmpty()) + return false; + QString format = types.at(0); + if (!data->hasFormat(format)) + { + qWarning() << "wrong format"; + return false; + } + if (row > rowCount(parent)) + row = rowCount(parent); + if (row == -1) + row = rowCount(parent); + if (column == -1) + column = 0; + // decode and insert + QByteArray encoded = data->data(format); + QDataStream stream(&encoded, QDataStream::ReadOnly); + + QList actions; + while (!stream.atEnd()) + { + Action action; + stream >> action; + actions << std::move(action); + } + if (actions.isEmpty()) + { + qWarning() << "empty actions"; + return false; + } + + beginInsertRows({}, row, row + actions.size() - 1); + auto iter = std::next(std::begin(*m_actionsContainer), row); + for (auto &action : actions) + iter = m_actionsContainer->insert(iter, std::move(action)); + endInsertRows(); + + return true; +} + +QMap ActionsContainerModel::itemData(const QModelIndex &index) const +{ + auto itemData = QAbstractListModel::itemData(index); + qDebug() << index << itemData; + return itemData; +} + +bool ActionsContainerModel::setItemData(const QModelIndex &index, const QMap &roles) +{ + auto setItemData = QAbstractListModel::setItemData(index, roles); + qDebug() << index << roles << setItemData; + return setItemData; +} + +bool ActionsContainerModel::removeRows(int row, int count, const QModelIndex &parent) +{ + qDebug() << row << count << parent.isValid(); + + if (!m_actionsContainer) + return false; + if (parent.isValid()) + return false; + + if (row < 0 || std::size_t(row) >= m_actionsContainer->size()) + { + qWarning() << "unexpected row" << row; + return false; + } + + if (count < 0 || std::size_t(count) > m_actionsContainer->size() - row) + { + qWarning() << "unexpected row+count" << count << row; + return false; + } + + beginRemoveRows({}, row, row + count - 1); + auto begin = std::next(std::begin(*m_actionsContainer), row); + auto end = std::next(begin, count); + m_actionsContainer->erase(begin, end); + endRemoveRows(); + + return true; +} + +bool ActionsContainerModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) +{ + qDebug() << sourceRow << count << destinationChild; + + if (!m_actionsContainer) + return false; + if (sourceParent.isValid()) + return false; + if (destinationParent.isValid()) + return false; + + if (count != 1) + return false; + + beginMoveRows({}, sourceRow, sourceRow, {}, destinationChild); + m_actionsContainer->splice(std::next(std::begin(*m_actionsContainer), destinationChild), *m_actionsContainer, std::next(std::begin(*m_actionsContainer), sourceRow)); + endMoveRows(); + + + return true; +} + void ActionsContainerModel::setActionsContainer(ActionsContainer *actionsContainer) { beginResetModel(); diff --git a/src/editor/models/actionscontainermodel.h b/src/editor/models/actionscontainermodel.h index 878062c..df23735 100644 --- a/src/editor/models/actionscontainermodel.h +++ b/src/editor/models/actionscontainermodel.h @@ -15,10 +15,22 @@ public: int rowCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; + Qt::ItemFlags flags(const QModelIndex &index) const override; Qt::DropActions supportedDropActions() const override; Qt::DropActions supportedDragActions() const override; + QStringList mimeTypes() const override; + QMimeData *mimeData(const QModelIndexList &indexes) const override; + bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override; + bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; + + QMap itemData(const QModelIndex &index) const override; + bool setItemData(const QModelIndex &index, const QMap &roles) override; + + bool removeRows(int row, int count, const QModelIndex &parent) override; + bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override; + ActionsContainer *actionsContainer() const { return m_actionsContainer; } void setActionsContainer(ActionsContainer *actionsContainer); diff --git a/src/editor/widgets/actiondragwidget.cpp b/src/editor/widgets/actiondragwidget.cpp index 26b0f2d..2f0f329 100644 --- a/src/editor/widgets/actiondragwidget.cpp +++ b/src/editor/widgets/actiondragwidget.cpp @@ -5,6 +5,10 @@ #include #include +#include "projectcontainer.h" +#include "projectserialization.h" +#include "stdserialization.h" + ActionDragWidget::ActionDragWidget(QWidget *parent) : QToolButton{parent} { @@ -33,8 +37,12 @@ void ActionDragWidget::mouseMoveEvent(QMouseEvent *event) drag->setPixmap(this->icon().pixmap(QSize{32, 32})); QMimeData *mimeData = new QMimeData; - mimeData->setData("custom", QByteArray{"aaaaaa"}); + QByteArray encoded; + QDataStream stream(&encoded, QDataStream::WriteOnly); + stream << Action{ExecuteCodeAction{ .script = "hatschi" }}; + mimeData->setData("custom", encoded); drag->setMimeData(mimeData); - Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction); + Qt::DropAction dropAction = drag->exec(Qt::CopyAction); + qDebug() << dropAction; } diff --git a/src/editor/widgets/actionscontainerwidget.cpp b/src/editor/widgets/actionscontainerwidget.cpp index 78286c1..8e31138 100644 --- a/src/editor/widgets/actionscontainerwidget.cpp +++ b/src/editor/widgets/actionscontainerwidget.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "models/actionscontainermodel.h" #include "dialogs/codeactiondialog.h" @@ -84,16 +85,55 @@ void ActionsContainerWidget::actionsContextMenuRequested(const QPoint &pos) auto action = index.isValid() ? m_actionsModel->getAction(index) : nullptr; QMenu menu{this}; - menu.addAction(tr("&Edit Values"), this, [this,index](){ actionDoubleClicked(index); })->setEnabled(action); + if (auto action = menu.addAction(tr("&Edit Values"), this, [this,index](){ + actionDoubleClicked(index); + })) + action->setEnabled(action); menu.addSeparator(); - menu.addAction(tr("C&ut"))->setEnabled(false); - menu.addAction(tr("&Copy"))->setEnabled(false); - menu.addAction(tr("&Paste"))->setEnabled(false); + if (auto action = menu.addAction(tr("C&ut"), this, [this](){ + QMessageBox::information(this, tr("Not implemented!"), tr("Not implemented!")); + })) + { + action->setEnabled(action); + action->setShortcut(QKeySequence::Cut); + } + if (auto action = menu.addAction(tr("&Copy"), this, [this](){ + QMessageBox::information(this, tr("Not implemented!"), tr("Not implemented!")); + })) + { + action->setEnabled(action); + action->setShortcut(QKeySequence::Copy); + } + if (auto action = menu.addAction(tr("&Paste"), this, [this](){ + QMessageBox::information(this, tr("Not implemented!"), tr("Not implemented!")); + })) + { + action->setEnabled(action); + action->setShortcut(QKeySequence::Paste); + } menu.addSeparator(); - menu.addAction(tr("&Delete"))->setEnabled(false); + if (auto action = menu.addAction(tr("&Delete"), this, [this,index](){ + if (!m_actionsModel->removeRow(index.row())) + QMessageBox::warning(this, tr("Could not remove action!"), tr("Could not remove action!")); + })) + { + action->setEnabled(action); + action->setShortcut(QKeySequence::Delete); + } menu.addSeparator(); - menu.addAction(tr("Select &All"))->setEnabled(false); + if (auto action = menu.addAction(tr("Select &All"), this, [this](){ + QMessageBox::information(this, tr("Not implemented!"), tr("Not implemented!")); + })) + { + action->setEnabled(m_actionsModel->actionsContainer() && !m_actionsModel->actionsContainer()->empty()); + action->setShortcut(QKeySequence::SelectAll); + } menu.addSeparator(); - menu.addAction(tr("C&lear"))->setEnabled(false); + if (auto action = menu.addAction(tr("C&lear"), this, [this](){ + QMessageBox::information(this, tr("Not implemented!"), tr("Not implemented!")); + })) + { + action->setEnabled(m_actionsModel->actionsContainer() && !m_actionsModel->actionsContainer()->empty()); + } menu.exec(m_ui->listViewActions->viewport()->mapToGlobal(pos)); } diff --git a/src/editor/widgets/actionscontainerwidget.ui b/src/editor/widgets/actionscontainerwidget.ui index 9b5242c..2944c8a 100644 --- a/src/editor/widgets/actionscontainerwidget.ui +++ b/src/editor/widgets/actionscontainerwidget.ui @@ -10,6 +10,9 @@ 667 + + Qt::CustomContextMenu + Form @@ -56,7 +59,7 @@ true - QAbstractItemView::InternalMove + QAbstractItemView::DragDrop Qt::MoveAction diff --git a/src/projectcontainer.cpp b/src/projectcontainer.cpp index d1fe88e..056b931 100644 --- a/src/projectcontainer.cpp +++ b/src/projectcontainer.cpp @@ -18,474 +18,3 @@ template<> std::list &ProjectContainer::containerFor() { return objects; template<> const std::list &ProjectContainer::containerFor() const { return objects; } template<> std::list &ProjectContainer::containerFor() { return rooms; } template<> const std::list &ProjectContainer::containerFor() const { return rooms; } - -template -QDataStream &operator<<(QDataStream &ds, const std::array &array) -{ - for (const auto &entry : array) - ds << entry; - return ds; -} - -template -QDataStream &operator>>(QDataStream &ds, std::array &array) -{ - for (size_t i = 0; i < Tsize; i++) - ds >> array[i]; - return ds; -} - -template -QDataStream &operator<<(QDataStream &ds, const std::list &list) -{ - { - int entries = list.size(); - ds << entries; - } - for (const auto &entry : list) - ds << entry; - return ds; -} - -template -QDataStream &operator>>(QDataStream &ds, std::list &list) -{ - int entries; - ds >> entries; - - for (int i = 0; i < entries; i++) - { - T entry; - ds >> entry; - list.emplace_back(std::move(entry)); - } - return ds; -} - -template -QDataStream &operator<<(QDataStream &ds, const std::vector &list) -{ - { - int entries = list.size(); - ds << entries; - } - for (const auto &entry : list) - ds << entry; - return ds; -} - -template -QDataStream &operator>>(QDataStream &ds, std::vector &list) -{ - int entries; - ds >> entries; - - for (int i = 0; i < entries; i++) - { - T entry; - ds >> entry; - list.emplace_back(std::move(entry)); - } - return ds; -} - -template -QDataStream &operator<<(QDataStream &ds, const std::map &map) -{ - { - int entries = map.size(); - ds << entries; - } - for (auto iter = std::cbegin(map); iter != std::cend(map); iter++) - ds << iter->first << iter->second; - return ds; -} - -template -QDataStream &operator>>(QDataStream &ds, std::map &map) -{ - int entries; - ds >> entries; - - for (int i = 0; i < entries; i++) - { - Tkey key; - Tvalue value; - ds >> key - >> value; - map[std::move(key)] = std::move(value); - } - return ds; -} - -template -QDataStream &operator<<(QDataStream &ds, const std::variant &variant) -{ - int index = variant.index(); - ds << index; - - using func_t = void(QDataStream&, const std::variant &); - static constexpr func_t *funcs[] = { - [](QDataStream& ds, const std::variant &variant) { - ds << std::get(variant); - }... - }; - - funcs[index](ds, variant); - - return ds; -} - -// for idiotic GCC we cannot use the usual lambda syntax but instead -// have to provide a template method, GCC sucks -template -std::variant variantUnpacker(QDataStream& ds) -{ - T value; - ds >> value; - return value; -} - -template -QDataStream &operator>>(QDataStream &ds, std::variant &variant) -{ - int index; - ds >> index; - - using func_t = std::variant (QDataStream&); - static constexpr func_t *funcs[] = { - variantUnpacker... - }; - variant = funcs[index](ds); - - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const GlobalGameSettings &globalGameSettings) -{ - Q_UNUSED(globalGameSettings); - //ds << globalGameSettings.; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, GlobalGameSettings &globalGameSettings) -{ - Q_UNUSED(globalGameSettings); - //ds >> globalGameSettings.; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const Sprite &sprite) -{ - ds << sprite.name - << sprite.pixmaps - << sprite.origin.x - << sprite.origin.y - << sprite.preciseCollisionChecking - << sprite.separateCollisionMasks; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, Sprite &sprite) -{ - ds >> sprite.name - >> sprite.pixmaps - >> sprite.origin.x - >> sprite.origin.y - >> sprite.preciseCollisionChecking - >> sprite.separateCollisionMasks; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const Sound &sound) -{ - ds << sound.name - << sound.type - << sound.path - << sound.effects.chorus - << sound.effects.flanger - << sound.effects.gargle - << sound.effects.echo - << sound.effects.reverb - << sound.volume - << sound.pan - << sound.preload; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, Sound &sound) -{ - ds >> sound.name - >> sound.type - >> sound.path - >> sound.effects.chorus - >> sound.effects.flanger - >> sound.effects.gargle - >> sound.effects.echo - >> sound.effects.reverb - >> sound.volume - >> sound.pan - >> sound.preload; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const Background &background) -{ - ds << background.name - << background.pixmap - << background.tileset; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, Background &background) -{ - ds >> background.name - >> background.pixmap - >> background.tileset; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const Path::Point &point) -{ - ds << point.point - << point.sp; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, Path::Point &point) -{ - ds >> point.point - >> point.sp; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const Path &path) -{ - ds << path.name - << path.points - << path.type - << path.closed - << path.precision - << path.snapX - << path.snapY - << path.gridEnabled; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, Path &path) -{ - ds >> path.name - >> path.points - >> path.type - >> path.closed - >> path.precision - >> path.snapX - >> path.snapY - >> path.gridEnabled; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const Script &script) -{ - ds << script.name - << script.script; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, Script &script) -{ - ds >> script.name - >> script.script; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const Font &font) -{ - ds << font.name - << font.font; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, Font &font) -{ - ds >> font.name - >> font.font; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const MoveFixedAction &action) -{ - Q_UNUSED(action); -// ds << action.; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, MoveFixedAction &action) -{ - Q_UNUSED(action); -// ds >> action.; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const MoveFreeAction &action) -{ - Q_UNUSED(action); -// ds << action.; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, MoveFreeAction &action) -{ - Q_UNUSED(action); -// ds >> action.; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const MoveTowardsAction &action) -{ - Q_UNUSED(action); -// ds << action.; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, MoveTowardsAction &action) -{ - Q_UNUSED(action); -// ds >> action.; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const ExecuteCodeAction &action) -{ - ds << action.script; - ds << action.appliesTo; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, ExecuteCodeAction &action) -{ - ds >> action.script; - ds >> action.appliesTo; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const TimeLine &timeLine) -{ - ds << timeLine.name - << timeLine.moments; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, TimeLine &timeLine) -{ - ds >> timeLine.name - >> timeLine.moments; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const Object &object) -{ - ds << object.name - << object.spriteName - << object.visible - << object.solid - << object.depth - << object.persistent - << object.parentName - << object.events - << object.collisionEvents; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, Object &object) -{ - ds >> object.name - >> object.spriteName - >> object.visible - >> object.solid - >> object.depth - >> object.persistent - >> object.parentName - >> object.events - >> object.collisionEvents; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const Room::Object &object) -{ - ds << object.objectName - << object.pos; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, Room::Object &object) -{ - ds >> object.objectName - >> object.pos; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const Room &room) -{ - ds << room.name - << room.caption - << room.width - << room.height - << room.speed - << room.persistent - << room.creationCode - << room.snapX - << room.snapY - << room.gridEnabled - << room.isometricGrid - << room.objects; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, Room &room) -{ - ds >> room.name - >> room.caption - >> room.width - >> room.height - >> room.speed - >> room.persistent - >> room.creationCode - >> room.snapX - >> room.snapY - >> room.gridEnabled - >> room.isometricGrid - >> room.objects; - return ds; -} - -QDataStream &operator<<(QDataStream &ds, const ProjectContainer &project) -{ - ds << project.globalGameSettings - << project.sprites - << project.sounds - << project.backgrounds - << project.paths - << project.scripts - << project.fonts - << project.timeLines - << project.objects - << project.rooms; - return ds; -} - -QDataStream &operator>>(QDataStream &ds, ProjectContainer &project) -{ - ds >> project.globalGameSettings - >> project.sprites - >> project.sounds - >> project.backgrounds - >> project.paths - >> project.scripts - >> project.fonts - >> project.timeLines - >> project.objects - >> project.rooms; - return ds; -} - diff --git a/src/projectcontainer.h b/src/projectcontainer.h index ae50290..84e6e50 100644 --- a/src/projectcontainer.h +++ b/src/projectcontainer.h @@ -8,7 +8,6 @@ #include #include #include -#include #include struct GlobalGameSettings @@ -222,6 +221,3 @@ struct ProjectContainer template std::list &containerFor(); template const std::list &containerFor() const; }; - -QDataStream &operator<<(QDataStream &ds, const ProjectContainer &project); -QDataStream &operator>>(QDataStream &ds, ProjectContainer &project); diff --git a/src/projectserialization.cpp b/src/projectserialization.cpp new file mode 100644 index 0000000..ea99f62 --- /dev/null +++ b/src/projectserialization.cpp @@ -0,0 +1,331 @@ +#include "projectserialization.h" + +#include "stdserialization.h" + +QDataStream &operator<<(QDataStream &ds, const GlobalGameSettings &globalGameSettings) +{ + Q_UNUSED(globalGameSettings); + //ds << globalGameSettings.; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, GlobalGameSettings &globalGameSettings) +{ + Q_UNUSED(globalGameSettings); + //ds >> globalGameSettings.; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const Sprite &sprite) +{ + ds << sprite.name + << sprite.pixmaps + << sprite.origin.x + << sprite.origin.y + << sprite.preciseCollisionChecking + << sprite.separateCollisionMasks; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, Sprite &sprite) +{ + ds >> sprite.name + >> sprite.pixmaps + >> sprite.origin.x + >> sprite.origin.y + >> sprite.preciseCollisionChecking + >> sprite.separateCollisionMasks; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const Sound &sound) +{ + ds << sound.name + << sound.type + << sound.path + << sound.effects.chorus + << sound.effects.flanger + << sound.effects.gargle + << sound.effects.echo + << sound.effects.reverb + << sound.volume + << sound.pan + << sound.preload; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, Sound &sound) +{ + ds >> sound.name + >> sound.type + >> sound.path + >> sound.effects.chorus + >> sound.effects.flanger + >> sound.effects.gargle + >> sound.effects.echo + >> sound.effects.reverb + >> sound.volume + >> sound.pan + >> sound.preload; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const Background &background) +{ + ds << background.name + << background.pixmap + << background.tileset; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, Background &background) +{ + ds >> background.name + >> background.pixmap + >> background.tileset; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const Path::Point &point) +{ + ds << point.point + << point.sp; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, Path::Point &point) +{ + ds >> point.point + >> point.sp; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const Path &path) +{ + ds << path.name + << path.points + << path.type + << path.closed + << path.precision + << path.snapX + << path.snapY + << path.gridEnabled; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, Path &path) +{ + ds >> path.name + >> path.points + >> path.type + >> path.closed + >> path.precision + >> path.snapX + >> path.snapY + >> path.gridEnabled; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const Script &script) +{ + ds << script.name + << script.script; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, Script &script) +{ + ds >> script.name + >> script.script; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const Font &font) +{ + ds << font.name + << font.font; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, Font &font) +{ + ds >> font.name + >> font.font; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const MoveFixedAction &action) +{ + Q_UNUSED(action); +// ds << action.; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, MoveFixedAction &action) +{ + Q_UNUSED(action); +// ds >> action.; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const MoveFreeAction &action) +{ + Q_UNUSED(action); +// ds << action.; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, MoveFreeAction &action) +{ + Q_UNUSED(action); +// ds >> action.; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const MoveTowardsAction &action) +{ + Q_UNUSED(action); +// ds << action.; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, MoveTowardsAction &action) +{ + Q_UNUSED(action); +// ds >> action.; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const ExecuteCodeAction &action) +{ + ds << action.script; + ds << action.appliesTo; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, ExecuteCodeAction &action) +{ + ds >> action.script; + ds >> action.appliesTo; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const TimeLine &timeLine) +{ + ds << timeLine.name + << timeLine.moments; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, TimeLine &timeLine) +{ + ds >> timeLine.name + >> timeLine.moments; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const Object &object) +{ + ds << object.name + << object.spriteName + << object.visible + << object.solid + << object.depth + << object.persistent + << object.parentName + << object.events + << object.collisionEvents; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, Object &object) +{ + ds >> object.name + >> object.spriteName + >> object.visible + >> object.solid + >> object.depth + >> object.persistent + >> object.parentName + >> object.events + >> object.collisionEvents; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const Room::Object &object) +{ + ds << object.objectName + << object.pos; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, Room::Object &object) +{ + ds >> object.objectName + >> object.pos; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const Room &room) +{ + ds << room.name + << room.caption + << room.width + << room.height + << room.speed + << room.persistent + << room.creationCode + << room.snapX + << room.snapY + << room.gridEnabled + << room.isometricGrid + << room.objects; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, Room &room) +{ + ds >> room.name + >> room.caption + >> room.width + >> room.height + >> room.speed + >> room.persistent + >> room.creationCode + >> room.snapX + >> room.snapY + >> room.gridEnabled + >> room.isometricGrid + >> room.objects; + return ds; +} + +QDataStream &operator<<(QDataStream &ds, const ProjectContainer &project) +{ + ds << project.globalGameSettings + << project.sprites + << project.sounds + << project.backgrounds + << project.paths + << project.scripts + << project.fonts + << project.timeLines + << project.objects + << project.rooms; + return ds; +} + +QDataStream &operator>>(QDataStream &ds, ProjectContainer &project) +{ + ds >> project.globalGameSettings + >> project.sprites + >> project.sounds + >> project.backgrounds + >> project.paths + >> project.scripts + >> project.fonts + >> project.timeLines + >> project.objects + >> project.rooms; + return ds; +} diff --git a/src/projectserialization.h b/src/projectserialization.h new file mode 100644 index 0000000..3cd9c65 --- /dev/null +++ b/src/projectserialization.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include "projectcontainer.h" + +QDataStream &operator<<(QDataStream &ds, const GlobalGameSettings &globalGameSettings); +QDataStream &operator>>(QDataStream &ds, GlobalGameSettings &globalGameSettings); +QDataStream &operator<<(QDataStream &ds, const Sprite &sprite); +QDataStream &operator>>(QDataStream &ds, Sprite &sprite); +QDataStream &operator<<(QDataStream &ds, const Sound &sound); +QDataStream &operator>>(QDataStream &ds, Sound &sound); +QDataStream &operator<<(QDataStream &ds, const Background &background); +QDataStream &operator>>(QDataStream &ds, Background &background); +QDataStream &operator<<(QDataStream &ds, const Path::Point &point); +QDataStream &operator>>(QDataStream &ds, Path::Point &point); +QDataStream &operator<<(QDataStream &ds, const Path &path); +QDataStream &operator>>(QDataStream &ds, Path &path); +QDataStream &operator<<(QDataStream &ds, const Script &script); +QDataStream &operator>>(QDataStream &ds, Script &script); +QDataStream &operator<<(QDataStream &ds, const Font &font); +QDataStream &operator>>(QDataStream &ds, Font &font); +QDataStream &operator<<(QDataStream &ds, const MoveFixedAction &action); +QDataStream &operator>>(QDataStream &ds, MoveFixedAction &action); +QDataStream &operator<<(QDataStream &ds, const MoveFreeAction &action); +QDataStream &operator>>(QDataStream &ds, MoveFreeAction &action); +QDataStream &operator<<(QDataStream &ds, const MoveTowardsAction &action); +QDataStream &operator>>(QDataStream &ds, MoveTowardsAction &action); +QDataStream &operator<<(QDataStream &ds, const ExecuteCodeAction &action); +QDataStream &operator>>(QDataStream &ds, ExecuteCodeAction &action); +QDataStream &operator<<(QDataStream &ds, const TimeLine &timeLine); +QDataStream &operator>>(QDataStream &ds, TimeLine &timeLine); +QDataStream &operator<<(QDataStream &ds, const Object &object); +QDataStream &operator>>(QDataStream &ds, Object &object); +QDataStream &operator<<(QDataStream &ds, const Room::Object &object); +QDataStream &operator>>(QDataStream &ds, Room::Object &object); +QDataStream &operator<<(QDataStream &ds, const Room &room); +QDataStream &operator>>(QDataStream &ds, Room &room); +QDataStream &operator<<(QDataStream &ds, const ProjectContainer &project);; +QDataStream &operator>>(QDataStream &ds, ProjectContainer &project);; diff --git a/src/stdserialization.h b/src/stdserialization.h new file mode 100644 index 0000000..fcdd623 --- /dev/null +++ b/src/stdserialization.h @@ -0,0 +1,152 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +template +QDataStream &operator<<(QDataStream &ds, const std::array &array) +{ + for (const auto &entry : array) + ds << entry; + return ds; +} + +template +QDataStream &operator>>(QDataStream &ds, std::array &array) +{ + for (size_t i = 0; i < Tsize; i++) + ds >> array[i]; + return ds; +} + +template +QDataStream &operator<<(QDataStream &ds, const std::list &list) +{ + { + int entries = list.size(); + ds << entries; + } + for (const auto &entry : list) + ds << entry; + return ds; +} + +template +QDataStream &operator>>(QDataStream &ds, std::list &list) +{ + int entries; + ds >> entries; + + for (int i = 0; i < entries; i++) + { + T entry; + ds >> entry; + list.emplace_back(std::move(entry)); + } + return ds; +} + +template +QDataStream &operator<<(QDataStream &ds, const std::vector &list) +{ + { + int entries = list.size(); + ds << entries; + } + for (const auto &entry : list) + ds << entry; + return ds; +} + +template +QDataStream &operator>>(QDataStream &ds, std::vector &list) +{ + int entries; + ds >> entries; + + for (int i = 0; i < entries; i++) + { + T entry; + ds >> entry; + list.emplace_back(std::move(entry)); + } + return ds; +} + +template +QDataStream &operator<<(QDataStream &ds, const std::map &map) +{ + { + int entries = map.size(); + ds << entries; + } + for (auto iter = std::cbegin(map); iter != std::cend(map); iter++) + ds << iter->first << iter->second; + return ds; +} + +template +QDataStream &operator>>(QDataStream &ds, std::map &map) +{ + int entries; + ds >> entries; + + for (int i = 0; i < entries; i++) + { + Tkey key; + Tvalue value; + ds >> key + >> value; + map[std::move(key)] = std::move(value); + } + return ds; +} + +template +QDataStream &operator<<(QDataStream &ds, const std::variant &variant) +{ + int index = variant.index(); + ds << index; + + using func_t = void(QDataStream&, const std::variant &); + static constexpr func_t *funcs[] = { + [](QDataStream& ds, const std::variant &variant) { + ds << std::get(variant); + }... + }; + + funcs[index](ds, variant); + + return ds; +} + +namespace detail { +// for idiotic GCC we cannot use the usual lambda syntax but instead +// have to provide a template method, GCC sucks +template +std::variant variantUnpacker(QDataStream& ds) +{ + T value; + ds >> value; + return value; +} +} + +template +QDataStream &operator>>(QDataStream &ds, std::variant &variant) +{ + int index; + ds >> index; + + using func_t = std::variant (QDataStream&); + static constexpr func_t *funcs[] = { + detail::variantUnpacker... + }; + variant = funcs[index](ds); + + return ds; +}