diff --git a/src/editor/dialogs/addeventdialog.cpp b/src/editor/dialogs/addeventdialog.cpp index e99610b..e994f9f 100644 --- a/src/editor/dialogs/addeventdialog.cpp +++ b/src/editor/dialogs/addeventdialog.cpp @@ -2,9 +2,13 @@ #include "ui_addeventdialog.h" #include +#include -AddEventDialog::AddEventDialog(QWidget *parent) : +#include "models/projecttreemodel.h" + +AddEventDialog::AddEventDialog(ProjectTreeModel &projectModel, QWidget *parent) : QDialog{parent}, + m_projectModel{projectModel}, m_ui{std::make_unique()} { m_ui->setupUi(this); @@ -27,6 +31,29 @@ AddEventDialog::AddEventDialog(QWidget *parent) : this, [this](){ m_eventType = Object::EventType::Draw; accept(); }); connect(m_ui->pushButtonStep, &QAbstractButton::clicked, this, [this](){ m_eventType = Object::EventType::Step; accept(); }); + + auto menu = new QMenu; + connect(menu, &QMenu::aboutToShow, menu, [this,menu](){ + for (const Object &object : m_projectModel.project()->objects) + { + QIcon icon; + if (!object.spriteName.isEmpty()) + { + const auto &sprites = m_projectModel.project()->sprites; + const auto iter = std::find_if(std::cbegin(sprites), std::cend(sprites), + [&](const Sprite &sprite){ return sprite.name == object.spriteName; }); + if (iter != std::cend(sprites)) + { + if (!iter->pixmaps.empty()) + icon = iter->pixmaps.front(); + } + } + menu->addAction(icon, object.name, this, [this,&object](){ + m_eventType = object.name; accept(); + }); + } + }, Qt::SingleShotConnection); + m_ui->pushButtonCollision->setMenu(menu); } AddEventDialog::~AddEventDialog() = default; diff --git a/src/editor/dialogs/addeventdialog.h b/src/editor/dialogs/addeventdialog.h index 3b88fd6..ce4c23b 100644 --- a/src/editor/dialogs/addeventdialog.h +++ b/src/editor/dialogs/addeventdialog.h @@ -3,26 +3,31 @@ #include #include +#include #include "projectcontainer.h" namespace Ui { class AddEventDialog; } +class ProjectTreeModel; + class AddEventDialog : public QDialog { Q_OBJECT public: - explicit AddEventDialog(QWidget *parent = nullptr); + explicit AddEventDialog(ProjectTreeModel &projectModel, QWidget *parent = nullptr); ~AddEventDialog(); - Object::EventType eventType() const { return *m_eventType; } + const std::optional> &eventType() const { return m_eventType; } void accept() override; void reject() override; private: + ProjectTreeModel &m_projectModel; + const std::unique_ptr m_ui; - std::optional m_eventType; + std::optional> m_eventType; }; diff --git a/src/editor/dialogs/addeventdialog.ui b/src/editor/dialogs/addeventdialog.ui index bfd4e6b..3d4e022 100644 --- a/src/editor/dialogs/addeventdialog.ui +++ b/src/editor/dialogs/addeventdialog.ui @@ -7,7 +7,7 @@ 0 0 265 - 221 + 238 @@ -82,6 +82,10 @@ C&ollision + + + :/qtgameengine/icons/event-collision.png:/qtgameengine/icons/event-collision.png + diff --git a/src/editor/dialogs/objectpropertiesdialog.cpp b/src/editor/dialogs/objectpropertiesdialog.cpp index ed1fae6..def3293 100644 --- a/src/editor/dialogs/objectpropertiesdialog.cpp +++ b/src/editor/dialogs/objectpropertiesdialog.cpp @@ -19,7 +19,8 @@ ObjectPropertiesDialog::ObjectPropertiesDialog(Object &object, ProjectTreeModel m_projectModel{projectModel}, m_mainWindow{mainWindow}, m_events{m_object.events}, - m_eventsModel{std::make_unique(m_events)}, + m_collisionEvents{m_object.collisionEvents}, + m_eventsModel{std::make_unique(m_events, m_collisionEvents)}, m_menuSprites{new QMenu{this}}, m_spriteName{object.spriteName} { @@ -132,6 +133,7 @@ void ObjectPropertiesDialog::accept() m_object.depth = m_ui->spinBoxDepth->value(); m_object.persistent = m_ui->checkBoxPersistent->isChecked(); m_object.events = std::move(m_events); + m_object.collisionEvents = std::move(m_collisionEvents); QDialog::accept(); } @@ -204,12 +206,11 @@ void ObjectPropertiesDialog::showInformation() void ObjectPropertiesDialog::addEvent() { - AddEventDialog dialog{this}; + AddEventDialog dialog{m_projectModel, this}; if (dialog.exec() == QDialog::Accepted) - { - if (!m_eventsModel->addEvent(dialog.eventType())) - QMessageBox::warning(this, tr("Could not add Event!"), tr("Could not add Event!")); - } + if (const auto &eventType = dialog.eventType()) + if (!m_eventsModel->addEvent(*eventType)) + QMessageBox::warning(this, tr("Could not add Event!"), tr("Could not add Event!")); } void ObjectPropertiesDialog::deleteEvent() @@ -235,12 +236,13 @@ void ObjectPropertiesDialog::replaceEvent() if (!event) return; - AddEventDialog dialog{this}; + std::variant x = event->first; + + AddEventDialog dialog{m_projectModel, this}; if (dialog.exec() == QDialog::Accepted) - { - if (!m_eventsModel->changeEvent(event->first, dialog.eventType())) + if (const auto &eventType = dialog.eventType()) + if (!m_eventsModel->changeEvent(event->first, *eventType)) QMessageBox::warning(this, tr("Could not change Event!"), tr("Could not change Event!")); - } } void ObjectPropertiesDialog::duplicateEvent() @@ -329,7 +331,7 @@ void ObjectPropertiesDialog::currentEventChanged(const QModelIndex &index) if (index.isValid()) { if (auto event = m_eventsModel->getEvent(index)) - m_ui->actionsWidget->setActionsContainer(&event->second); + m_ui->actionsWidget->setActionsContainer(&event->second.get()); else goto none; } @@ -343,13 +345,13 @@ none: void ObjectPropertiesDialog::eventsContextMenuRequested(const QPoint &pos) { const auto index = m_ui->listViewEvents->indexAt(pos); - auto event = index.isValid() ? m_eventsModel->getEvent(index) : nullptr; + auto event = index.isValid() ? m_eventsModel->getEvent(index) : std::nullopt; QMenu menu{this}; menu.addAction(tr("&Add Event"), this, &ObjectPropertiesDialog::addEvent); - menu.addAction(tr("&Change Event"), this, &ObjectPropertiesDialog::replaceEvent)->setEnabled(event); - menu.addAction(tr("&Duplicate Event"), this, &ObjectPropertiesDialog::duplicateEvent)->setEnabled(event); - menu.addAction(tr("D&elete Event"), this, &ObjectPropertiesDialog::deleteEvent)->setEnabled(event); + menu.addAction(tr("&Change Event"), this, &ObjectPropertiesDialog::replaceEvent)->setEnabled(event.has_value()); + menu.addAction(tr("&Duplicate Event"), this, &ObjectPropertiesDialog::duplicateEvent)->setEnabled(event.has_value()); + menu.addAction(tr("D&elete Event"), this, &ObjectPropertiesDialog::deleteEvent)->setEnabled(event.has_value()); menu.exec(m_ui->listViewEvents->viewport()->mapToGlobal(pos)); } diff --git a/src/editor/dialogs/objectpropertiesdialog.h b/src/editor/dialogs/objectpropertiesdialog.h index 8f6fc61..c470629 100644 --- a/src/editor/dialogs/objectpropertiesdialog.h +++ b/src/editor/dialogs/objectpropertiesdialog.h @@ -60,6 +60,7 @@ private: MainWindow * const m_mainWindow; Object::events_container_t m_events; + Object::collision_events_container_t m_collisionEvents; const std::unique_ptr m_eventsModel; diff --git a/src/editor/dialogs/roompropertiesdialog.cpp b/src/editor/dialogs/roompropertiesdialog.cpp index 1bc89bd..41e78d1 100644 --- a/src/editor/dialogs/roompropertiesdialog.cpp +++ b/src/editor/dialogs/roompropertiesdialog.cpp @@ -343,29 +343,35 @@ void RoomPropertiesDialog::spritePixmapsChanged(const Sprite &sprite) m_ui->labelObjectPreview->setPixmap(std::move(pixmap)); } -void RoomPropertiesDialog::objectNameChanged(const Object &object) +void RoomPropertiesDialog::objectNameChanged(const Object &object, const QString &oldName) { - if (!m_selectedObject) - return; + if (m_selectedObject && &object == m_selectedObject) + m_ui->lineEditObject->setText(object.name); - if (&object != m_selectedObject) - return; + for (auto &obj : m_objects) + { + if (obj.objectName != oldName) + continue; - m_ui->lineEditObject->setText(object.name); + obj.objectName = object.name; + } } void RoomPropertiesDialog::objectAboutToBeRemoved(const Object &object) { - if (!m_selectedObject) - return; + if (m_selectedObject && &object == m_selectedObject) + { + m_selectedObject = nullptr; + m_ui->lineEditObject->clear(); + m_ui->labelObjectPreview->setPixmap({}); + m_ui->roomEditWidget->setSelectedObject(nullptr); + } - if (&object != m_selectedObject) - return; - - m_selectedObject = nullptr; - m_ui->lineEditObject->clear(); - m_ui->labelObjectPreview->setPixmap({}); - m_ui->roomEditWidget->setSelectedObject(nullptr); + for (auto iter = std::begin(m_objects); iter != std::end(m_objects);) + if (iter->objectName == object.name) + iter = m_objects.erase(iter); + else + iter++; } void RoomPropertiesDialog::objectSpriteNameChanged(const Object &object) diff --git a/src/editor/dialogs/roompropertiesdialog.h b/src/editor/dialogs/roompropertiesdialog.h index ddb02b1..1d551e8 100644 --- a/src/editor/dialogs/roompropertiesdialog.h +++ b/src/editor/dialogs/roompropertiesdialog.h @@ -41,7 +41,7 @@ private slots: void roomNameChanged(const Room &room); void spritePixmapsChanged(const Sprite &sprite); - void objectNameChanged(const Object &object); + void objectNameChanged(const Object &object, const QString &oldName); void objectAboutToBeRemoved(const Object &object); void objectSpriteNameChanged(const Object &object); diff --git a/src/editor/icons/event-collision.png b/src/editor/icons/event-collision.png new file mode 100644 index 0000000..c8a0c48 Binary files /dev/null and b/src/editor/icons/event-collision.png differ diff --git a/src/editor/models/objecteventsmodel.cpp b/src/editor/models/objecteventsmodel.cpp index 3e26084..afc1acf 100644 --- a/src/editor/models/objecteventsmodel.cpp +++ b/src/editor/models/objecteventsmodel.cpp @@ -5,56 +5,78 @@ #include "futurecpp.h" -ObjectEventsModel::ObjectEventsModel(Object::events_container_t &events, QObject *parent) : +ObjectEventsModel::ObjectEventsModel(Object::events_container_t &events, Object::collision_events_container_t &collisionEvents, + QObject *parent) : QAbstractListModel{parent}, - m_events{events} + m_events{events}, + m_collisionEvents{collisionEvents} { } int ObjectEventsModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent) - return m_events.size(); + return m_events.size() + m_collisionEvents.size(); } QVariant ObjectEventsModel::data(const QModelIndex &index, int role) const { Q_UNUSED(index) - if (index.row() < 0 || std::size_t(index.row()) >= m_events.size()) + if (index.row() < 0) { qWarning() << "row out of bounds" << index.row(); return {}; } - - const auto &pair = *std::next(std::cbegin(m_events), index.row()); - - switch (role) + else if (std::size_t(index.row()) < m_events.size()) { - case Qt::DisplayRole: - case Qt::EditRole: - switch (pair.first) + const auto &pair = *std::next(std::cbegin(m_events), index.row()); + + switch (role) { - case Object::EventType::Create: return tr("Create"); - case Object::EventType::Destroy: return tr("Destroy"); - case Object::EventType::Step: return tr("Step"); - case Object::EventType::Draw: return tr("Draw"); - default: - qWarning() << "unknown event type" << std::to_underlying(pair.first); - return QString::number(std::to_underlying(pair.first)); + case Qt::DisplayRole: + case Qt::EditRole: + switch (pair.first) + { + case Object::EventType::Create: return tr("Create"); + case Object::EventType::Destroy: return tr("Destroy"); + case Object::EventType::Step: return tr("Step"); + case Object::EventType::Draw: return tr("Draw"); + default: + qWarning() << "unknown event type" << std::to_underlying(pair.first); + return QString::number(std::to_underlying(pair.first)); + } + case Qt::DecorationRole: + switch (pair.first) + { + case Object::EventType::Create: return QIcon{":/qtgameengine/icons/event-create.png"}; + case Object::EventType::Destroy: return QIcon{":/qtgameengine/icons/event-destroy.png"}; + case Object::EventType::Step: return QIcon{":/qtgameengine/icons/event-step.png"}; + case Object::EventType::Draw: return QIcon{":/qtgameengine/icons/event-draw.png"}; + default: + qWarning() << "unknown event type" << std::to_underlying(pair.first); + return {}; + } } - case Qt::DecorationRole: - switch (pair.first) + } + else if (std::size_t(index.row()) < m_collisionEvents.size() + m_events.size()) + { + const auto &pair = *std::next(std::cbegin(m_collisionEvents), index.row() - m_events.size()); + + switch (role) { - case Object::EventType::Create: return QIcon{":/qtgameengine/icons/event-create.png"}; - case Object::EventType::Destroy: return QIcon{":/qtgameengine/icons/event-destroy.png"}; - case Object::EventType::Step: return QIcon{":/qtgameengine/icons/event-step.png"}; - case Object::EventType::Draw: return QIcon{":/qtgameengine/icons/event-draw.png"}; - default: - qWarning() << "unknown event type" << std::to_underlying(pair.first); - return {}; + case Qt::DisplayRole: + case Qt::EditRole: + return pair.first; + case Qt::DecorationRole: + return QIcon{":/qtgameengine/icons/event-collision.png"}; } } + else + { + qWarning() << "row out of bounds" << index.row(); + return {}; + } return {}; } @@ -63,27 +85,62 @@ bool ObjectEventsModel::removeRows(int row, int count, const QModelIndex &parent { Q_UNUSED(parent) - if (row < 0 || std::size_t(row) >= m_events.size()) + if (row < 0 || std::size_t(row) >= m_events.size() + m_collisionEvents.size()) { qWarning() << "unexpected row" << row; return false; } - if (count < 0 || std::size_t(count) > m_events.size() - row) + if (count < 0 || std::size_t(count) > m_events.size() + m_collisionEvents.size() - row) { qWarning() << "unexpected row+count" << count << row; return false; } beginRemoveRows({}, row, row + count - 1); - auto begin = std::next(std::begin(m_events), row); - auto end = std::next(begin, count); - m_events.erase(begin, end); + + if (std::size_t(row) < m_events.size()) + { + const auto remaining = m_events.size() - row; + const auto begin = std::next(std::begin(m_events), row); + const auto end = std::next(begin, std::min(count, remaining)); + m_events.erase(begin, end); + + if (std::size_t(count) > remaining) + { + count -= remaining; + + const auto begin = std::begin(m_collisionEvents); + const auto end = std::next(begin, count); + m_collisionEvents.erase(begin, end); + } + } + else if (std::size_t(row) < m_events.size() + m_collisionEvents.size()) + { + qDebug() << row - m_events.size(); + qDebug() << count; + qDebug() << m_collisionEvents.size(); + + const auto begin = std::next(std::begin(m_collisionEvents), row - m_events.size()); + const auto end = std::next(begin, count); + m_collisionEvents.erase(begin, end); + } + endRemoveRows(); return true; } +bool ObjectEventsModel::addEvent(std::variant eventType) +{ + if (const auto &type = std::get_if(&eventType)) + return addEvent(*type); + if (const auto &object = std::get_if(&eventType)) + return addEvent(*object); + qCritical() << "not implemented"; + return false; +} + bool ObjectEventsModel::addEvent(Object::EventType eventType) { if (m_events.contains(eventType)) @@ -122,6 +179,72 @@ bool ObjectEventsModel::addEvent(Object::EventType eventType) return true; } +bool ObjectEventsModel::addEvent(const QString &object) +{ + if (m_collisionEvents.contains(object)) + { + qWarning() << object << "duplicate"; + return false; + } + + // temporary copy to find row before inserting, as its needed for beginInsertRows() + auto tempevents = m_collisionEvents; + + const auto &tempInsertResult = tempevents.insert(std::make_pair(object, ActionsContainer{})); + if (!tempInsertResult.second) + { + qWarning() << "temp inserting failed!"; + return false; + } + + const auto tempNewRow = std::distance(std::begin(tempevents), tempInsertResult.first); + + + beginInsertRows({}, tempNewRow + m_events.size(), tempNewRow + m_events.size()); + + const auto &insertResult = m_collisionEvents.insert(std::make_pair(object, ActionsContainer{})); + if (!insertResult.second) + { + qWarning() << "inserting failed!"; + return false; + } + + const auto newRow = std::distance(std::begin(m_collisionEvents), insertResult.first); + Q_ASSERT(tempNewRow == newRow); + + endInsertRows(); + + return true; +} + +bool ObjectEventsModel::changeEvent(std::variant eventType, std::variant newEventType) +{ + if (const auto &type = std::get_if(&eventType)) + { + if (const auto &newType = std::get_if(&newEventType)) + return changeEvent(*type, *newType); + if (const auto &newObject = std::get_if(&newEventType)) + { + //return changeEvent(*type, *newObject); + } + qCritical() << "not implemented"; + return false; + } + if (const auto &object = std::get_if(&eventType)) + { + if (const auto &newType = std::get_if(&newEventType)) + { + //return changeEvent(*object, *newType); + } + if (const auto &newObject = std::get_if(&newEventType)) + return changeEvent(*object, *newObject); + qCritical() << "not implemented"; + return false; + } + qCritical() << "not implemented"; + return false; +} + bool ObjectEventsModel::changeEvent(Object::EventType eventType, Object::EventType newEventType) { const auto iter = m_events.find(eventType); @@ -137,6 +260,12 @@ bool ObjectEventsModel::changeEvent(Object::EventType eventType, Object::EventTy return true; } + if (m_events.contains(newEventType)) + { + qWarning() << std::to_underlying(eventType) << "duplicate"; + return false; + } + auto container = std::move(iter->second); const auto oldRow = std::distance(std::begin(m_events), iter); @@ -175,6 +304,75 @@ bool ObjectEventsModel::changeEvent(Object::EventType eventType, Object::EventTy return true; } +bool ObjectEventsModel::changeEvent(const QString &object, const QString &newObject) +{ + const auto iter = m_collisionEvents.find(object); + if (iter == std::cend(m_collisionEvents)) + { + qWarning() << object << "not found"; + return false; + } + + if (object == newObject) + { + qWarning() << "same event again"; + return true; + } + + if (m_collisionEvents.contains(newObject)) + { + qWarning() << newObject << "duplicate"; + return false; + } + + auto container = std::move(iter->second); + + const auto oldRow = std::distance(std::begin(m_collisionEvents), iter); + + beginRemoveRows({}, oldRow + m_events.size(), oldRow + m_events.size()); + m_collisionEvents.erase(iter); + endRemoveRows(); + + // temporary copy to find row before inserting, as its needed for beginInsertRows() + auto tempevents = m_collisionEvents; + + const auto &tempInsertResult = tempevents.insert(std::make_pair(newObject, ActionsContainer{})); + if (!tempInsertResult.second) + { + qWarning() << "temp inserting failed!"; + return false; + } + + const auto tempNewRow = std::distance(std::begin(tempevents), tempInsertResult.first); + + + beginInsertRows({}, tempNewRow + m_events.size(), tempNewRow + m_events.size()); + + const auto &insertResult = m_collisionEvents.insert(std::make_pair(newObject, std::move(container))); + if (!insertResult.second) + { + qWarning() << "inserting failed!"; + return false; + } + + const auto newRow = std::distance(std::begin(m_collisionEvents), insertResult.first); + Q_ASSERT(tempNewRow == newRow); + + endInsertRows(); + + return true; +} + +bool ObjectEventsModel::removeEvent(std::variant eventType) +{ + if (const auto &type = std::get_if(&eventType)) + return removeEvent(*type); + if (const auto &object = std::get_if(&eventType)) + return removeEvent(*object); + qCritical() << "not implemented"; + return false; +} + bool ObjectEventsModel::removeEvent(Object::EventType eventType) { const auto iter = m_events.find(eventType); @@ -193,46 +391,79 @@ bool ObjectEventsModel::removeEvent(Object::EventType eventType) return true; } -std::pair *ObjectEventsModel::getEvent(const QModelIndex &index) +bool ObjectEventsModel::removeEvent(const QString &object) +{ + Q_UNUSED(object); + qCritical() << "not implemented"; + return false; +} + +auto ObjectEventsModel::getEvent(const QModelIndex &index) -> get_event_result_t { if (!index.isValid()) { qWarning() << "unexpected invalid index"; - return nullptr; + return std::nullopt; } return getEvent(index.row()); } -const std::pair *ObjectEventsModel::getEvent(const QModelIndex &index) const +auto ObjectEventsModel::getEvent(const QModelIndex &index) const -> const_get_event_result_t { if (!index.isValid()) { qWarning() << "unexpected invalid index"; - return nullptr; + return std::nullopt; } return getEvent(index.row()); } -std::pair *ObjectEventsModel::getEvent(int row) +auto ObjectEventsModel::getEvent(int row) -> get_event_result_t { - if (row < 0 || std::size_t(row) >= m_events.size()) + if (row < 0) { qWarning() << "unexpected row" << row; - return nullptr; + return std::nullopt; } - - return &*std::next(std::begin(m_events), row); -} - -const std::pair *ObjectEventsModel::getEvent(int row) const -{ - if (row < 0 || std::size_t(row) >= m_events.size()) + else if (std::size_t(row) < m_events.size()) + { + auto iter = std::next(std::begin(m_events), row); + return std::make_pair(iter->first, std::ref(iter->second)); + } + else if (std::size_t(row) < m_events.size() + m_collisionEvents.size()) + { + auto iter = std::next(std::begin(m_collisionEvents), row - m_events.size()); + return std::make_pair(iter->first, std::ref(iter->second)); + } + else { qWarning() << "unexpected row" << row; - return nullptr; + return std::nullopt; + } +} + +auto ObjectEventsModel::getEvent(int row) const -> const_get_event_result_t +{ + if (row < 0) + { + qWarning() << "unexpected row" << row; + return std::nullopt; + } + else if (std::size_t(row) >= m_events.size()) + { + auto iter = std::next(std::cbegin(m_events), row); + return std::make_pair(iter->first, std::cref(iter->second)); + } + else if (std::size_t(row) >= m_events.size() + m_collisionEvents.size()) + { + auto iter = std::next(std::cbegin(m_collisionEvents), row - m_events.size()); + return std::make_pair(iter->first, std::cref(iter->second)); + } + else + { + qWarning() << "unexpected row" << row; + return std::nullopt; } - - return &*std::next(std::cbegin(m_events), row); } diff --git a/src/editor/models/objecteventsmodel.h b/src/editor/models/objecteventsmodel.h index 0e542a9..5dba891 100644 --- a/src/editor/models/objecteventsmodel.h +++ b/src/editor/models/objecteventsmodel.h @@ -11,21 +11,32 @@ class ObjectEventsModel : public QAbstractListModel Q_OBJECT public: - explicit ObjectEventsModel(Object::events_container_t &events, QObject *parent = nullptr); + explicit ObjectEventsModel(Object::events_container_t &events, Object::collision_events_container_t &collisionEvents, + QObject *parent = nullptr); int rowCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex{}) override; + bool addEvent(std::variant eventType); bool addEvent(Object::EventType eventType); + bool addEvent(const QString &object); + bool changeEvent(std::variant eventType, std::variant newEventType); bool changeEvent(Object::EventType eventType, Object::EventType newEventType); + bool changeEvent(const QString &object, const QString &newObject); + bool removeEvent(std::variant eventType); bool removeEvent(Object::EventType eventType); + bool removeEvent(const QString &object); - std::pair *getEvent(const QModelIndex &index); - const std::pair *getEvent(const QModelIndex &index) const; - std::pair *getEvent(int row); - const std::pair *getEvent(int row) const; + using get_event_result_t = std::optional, std::reference_wrapper>>; + using const_get_event_result_t = std::optional, std::reference_wrapper>>; + + get_event_result_t getEvent(const QModelIndex &index); + const_get_event_result_t getEvent(const QModelIndex &index) const; + get_event_result_t getEvent(int row); + const_get_event_result_t getEvent(int row) const; private: Object::events_container_t &m_events; + Object::collision_events_container_t &m_collisionEvents; }; diff --git a/src/editor/models/projecttreemodel.cpp b/src/editor/models/projecttreemodel.cpp index d4cf477..839ad9e 100644 --- a/src/editor/models/projecttreemodel.cpp +++ b/src/editor/models/projecttreemodel.cpp @@ -959,6 +959,16 @@ template<> void ProjectTreeModel::onBeforeRemove(const Sprite &sprite) } } +template<> void ProjectTreeModel::onBeforeRemove(const Object &object) +{ + for (auto &room : m_project->rooms) + for (auto iter = std::begin(room.objects); iter != std::end(room.objects); ) + if (iter->objectName == object.name) + iter = room.objects.erase(iter); + else + iter++; +} + template void ProjectTreeModel::onBeforeRename(const T &entry, const QString &newName) { Q_UNUSED(entry) @@ -973,22 +983,38 @@ template void ProjectTreeModel::onAfterRename(const T &entry, const template<> void ProjectTreeModel::onAfterRename(const Sprite &sprite, const QString &oldName) { - for (auto iter = std::begin(m_project->objects); iter != std::end(m_project->objects); iter++) + for (auto &object : m_project->objects) { - if (iter->spriteName != oldName) + if (object.spriteName != oldName) continue; - auto oldSpriteName = std::move(iter->spriteName); + auto oldSpriteName = std::move(object.spriteName); - iter->spriteName = sprite.name; + object.spriteName = sprite.name; // const auto index = this->index(std::distance(std::begin(m_project->objects), iter), 0, rootFor()); // emit dataChanged(index, index, {Qt::DecorationRole}); - emit objectSpriteNameChanged(*iter, std::move(oldSpriteName)); + emit objectSpriteNameChanged(object, std::move(oldSpriteName)); } } +template<> void ProjectTreeModel::onAfterRename(const Object &object, const QString &oldName) +{ + for (auto &room : m_project->rooms) + { + for (auto &obj : room.objects) + { + if (obj.objectName != oldName) + continue; + + obj.objectName = object.name; + } + } + + // TODO object collision events +} + template QString ProjectTreeModel::getFreeNameFor(const std::list &container) { diff --git a/src/editor/resources_editor.qrc b/src/editor/resources_editor.qrc index 8a7be93..c2f0725 100644 --- a/src/editor/resources_editor.qrc +++ b/src/editor/resources_editor.qrc @@ -76,6 +76,7 @@ icons/info.png icons/merge.png icons/sort.png + icons/event-collision.png icons/event-create.png icons/event-destroy.png icons/event-step.png diff --git a/src/projectcontainer.cpp b/src/projectcontainer.cpp index d2f14a5..56346d2 100644 --- a/src/projectcontainer.cpp +++ b/src/projectcontainer.cpp @@ -306,7 +306,8 @@ QDataStream &operator<<(QDataStream &ds, const Object &object) << object.solid << object.depth << object.persistent - << object.events; + << object.events + << object.collisionEvents; return ds; } @@ -318,7 +319,8 @@ QDataStream &operator>>(QDataStream &ds, Object &object) >> object.solid >> object.depth >> object.persistent - >> object.events; + >> object.events + >> object.collisionEvents; return ds; } diff --git a/src/projectcontainer.h b/src/projectcontainer.h index 15052c7..8d16478 100644 --- a/src/projectcontainer.h +++ b/src/projectcontainer.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -117,6 +118,7 @@ struct Object }; using events_container_t = std::map; + using collision_events_container_t = std::map; QString name; QString spriteName; @@ -125,6 +127,7 @@ struct Object int depth{}; bool persistent{}; events_container_t events; + collision_events_container_t collisionEvents; }; struct Room