Implement parent objects
This commit is contained in:
@ -22,7 +22,9 @@ ObjectPropertiesDialog::ObjectPropertiesDialog(Object &object, ProjectTreeModel
|
|||||||
m_collisionEvents{m_object.collisionEvents},
|
m_collisionEvents{m_object.collisionEvents},
|
||||||
m_eventsModel{std::make_unique<ObjectEventsModel>(m_events, m_collisionEvents)},
|
m_eventsModel{std::make_unique<ObjectEventsModel>(m_events, m_collisionEvents)},
|
||||||
m_menuSprites{new QMenu{this}},
|
m_menuSprites{new QMenu{this}},
|
||||||
m_spriteName{object.spriteName}
|
m_menuParents{new QMenu{this}},
|
||||||
|
m_spriteName{object.spriteName},
|
||||||
|
m_parentName{object.parentName}
|
||||||
{
|
{
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
@ -35,14 +37,17 @@ ObjectPropertiesDialog::ObjectPropertiesDialog(Object &object, ProjectTreeModel
|
|||||||
|
|
||||||
m_ui->lineEditName->setText(m_object.name);
|
m_ui->lineEditName->setText(m_object.name);
|
||||||
m_ui->lineEditSprite->setText(m_spriteName.isEmpty() ? tr("<no sprite>") : m_spriteName);
|
m_ui->lineEditSprite->setText(m_spriteName.isEmpty() ? tr("<no sprite>") : m_spriteName);
|
||||||
|
m_ui->lineEditParent->setText(m_parentName.isEmpty() ? tr("<no parent>") : m_parentName);
|
||||||
updateSpritePreview();
|
updateSpritePreview();
|
||||||
m_ui->toolButtonSprite->setMenu(m_menuSprites);
|
m_ui->toolButtonSprite->setMenu(m_menuSprites);
|
||||||
|
m_ui->toolButtonParent->setMenu(m_menuParents);
|
||||||
m_ui->checkBoxVisible->setChecked(m_object.visible);
|
m_ui->checkBoxVisible->setChecked(m_object.visible);
|
||||||
m_ui->checkBoxSolid->setChecked(m_object.solid);
|
m_ui->checkBoxSolid->setChecked(m_object.solid);
|
||||||
m_ui->spinBoxDepth->setValue(m_object.depth);
|
m_ui->spinBoxDepth->setValue(m_object.depth);
|
||||||
m_ui->checkBoxPersistent->setChecked(m_object.persistent);
|
m_ui->checkBoxPersistent->setChecked(m_object.persistent);
|
||||||
|
|
||||||
m_ui->lineEditSprite->setMenu(m_menuSprites);
|
m_ui->lineEditSprite->setMenu(m_menuSprites);
|
||||||
|
m_ui->lineEditParent->setMenu(m_menuParents);
|
||||||
|
|
||||||
m_ui->listViewEvents->setModel(m_eventsModel.get());
|
m_ui->listViewEvents->setModel(m_eventsModel.get());
|
||||||
|
|
||||||
@ -50,6 +55,8 @@ ObjectPropertiesDialog::ObjectPropertiesDialog(Object &object, ProjectTreeModel
|
|||||||
this, &ObjectPropertiesDialog::objectNameChanged);
|
this, &ObjectPropertiesDialog::objectNameChanged);
|
||||||
connect(&m_projectModel, &ProjectTreeModel::spriteNameChanged,
|
connect(&m_projectModel, &ProjectTreeModel::spriteNameChanged,
|
||||||
this, &ObjectPropertiesDialog::spriteNameChanged);
|
this, &ObjectPropertiesDialog::spriteNameChanged);
|
||||||
|
connect(&m_projectModel, &ProjectTreeModel::objectAboutToBeRemoved,
|
||||||
|
this, &ObjectPropertiesDialog::objectAboutToBeRemoved);
|
||||||
connect(&m_projectModel, &ProjectTreeModel::spriteAboutToBeRemoved,
|
connect(&m_projectModel, &ProjectTreeModel::spriteAboutToBeRemoved,
|
||||||
this, &ObjectPropertiesDialog::spriteAboutToBeRemoved);
|
this, &ObjectPropertiesDialog::spriteAboutToBeRemoved);
|
||||||
connect(&m_projectModel, &ProjectTreeModel::spritePixmapsChanged,
|
connect(&m_projectModel, &ProjectTreeModel::spritePixmapsChanged,
|
||||||
@ -92,6 +99,8 @@ ObjectPropertiesDialog::ObjectPropertiesDialog(Object &object, ProjectTreeModel
|
|||||||
|
|
||||||
connect(m_menuSprites, &QMenu::aboutToShow,
|
connect(m_menuSprites, &QMenu::aboutToShow,
|
||||||
this, &ObjectPropertiesDialog::spritesMenuAboutToShow);
|
this, &ObjectPropertiesDialog::spritesMenuAboutToShow);
|
||||||
|
connect(m_menuParents, &QMenu::aboutToShow,
|
||||||
|
this, &ObjectPropertiesDialog::parentsMenuAboutToShow);
|
||||||
|
|
||||||
connect(m_ui->listViewEvents->selectionModel(), &QItemSelectionModel::currentChanged,
|
connect(m_ui->listViewEvents->selectionModel(), &QItemSelectionModel::currentChanged,
|
||||||
this, &ObjectPropertiesDialog::currentEventChanged);
|
this, &ObjectPropertiesDialog::currentEventChanged);
|
||||||
@ -132,6 +141,7 @@ void ObjectPropertiesDialog::accept()
|
|||||||
m_object.solid = m_ui->checkBoxSolid->isChecked();
|
m_object.solid = m_ui->checkBoxSolid->isChecked();
|
||||||
m_object.depth = m_ui->spinBoxDepth->value();
|
m_object.depth = m_ui->spinBoxDepth->value();
|
||||||
m_object.persistent = m_ui->checkBoxPersistent->isChecked();
|
m_object.persistent = m_ui->checkBoxPersistent->isChecked();
|
||||||
|
m_object.parentName = m_parentName;
|
||||||
m_object.events = std::move(m_events);
|
m_object.events = std::move(m_events);
|
||||||
m_object.collisionEvents = std::move(m_collisionEvents);
|
m_object.collisionEvents = std::move(m_collisionEvents);
|
||||||
|
|
||||||
@ -259,17 +269,23 @@ void ObjectPropertiesDialog::changed()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectPropertiesDialog::objectNameChanged(const Object &object)
|
void ObjectPropertiesDialog::objectNameChanged(const Object &object, const QString &oldName)
|
||||||
{
|
{
|
||||||
if (&object != &m_object)
|
if (&object == &m_object)
|
||||||
return;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
QSignalBlocker blocker{m_ui->lineEditName};
|
{
|
||||||
m_ui->lineEditName->setText(object.name);
|
QSignalBlocker blocker{m_ui->lineEditName};
|
||||||
|
m_ui->lineEditName->setText(object.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTitle();
|
if (!m_parentName.isEmpty() && m_parentName == oldName)
|
||||||
|
{
|
||||||
|
m_parentName = object.name;
|
||||||
|
m_ui->lineEditParent->setText(object.name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectPropertiesDialog::spriteNameChanged(const Sprite &sprite, const QString &oldName)
|
void ObjectPropertiesDialog::spriteNameChanged(const Sprite &sprite, const QString &oldName)
|
||||||
@ -288,20 +304,26 @@ void ObjectPropertiesDialog::spriteNameChanged(const Sprite &sprite, const QStri
|
|||||||
updateSpritePreview();
|
updateSpritePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ObjectPropertiesDialog::objectAboutToBeRemoved(const Object &object)
|
||||||
|
{
|
||||||
|
if (!m_parentName.isEmpty() && m_parentName == object.name)
|
||||||
|
{
|
||||||
|
m_parentName.clear();
|
||||||
|
m_ui->lineEditParent->setText(tr("<no parent>"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ObjectPropertiesDialog::spriteAboutToBeRemoved(const Sprite &sprite)
|
void ObjectPropertiesDialog::spriteAboutToBeRemoved(const Sprite &sprite)
|
||||||
{
|
{
|
||||||
if (m_spriteName.isEmpty())
|
if (!m_spriteName.isEmpty() && m_spriteName == sprite.name)
|
||||||
return;
|
|
||||||
|
|
||||||
if (m_spriteName != sprite.name)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_spriteName.clear();
|
|
||||||
{
|
{
|
||||||
QSignalBlocker blocker{m_ui->lineEditSprite};
|
m_spriteName.clear();
|
||||||
m_ui->lineEditSprite->setText(tr("<no sprite>"));
|
{
|
||||||
|
QSignalBlocker blocker{m_ui->lineEditSprite};
|
||||||
|
m_ui->lineEditSprite->setText(tr("<no sprite>"));
|
||||||
|
}
|
||||||
|
m_ui->labelSpritePreview->setPixmap(QPixmap{});
|
||||||
}
|
}
|
||||||
m_ui->labelSpritePreview->setPixmap(QPixmap{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectPropertiesDialog::spritePixmapsChanged(const Sprite &sprite)
|
void ObjectPropertiesDialog::spritePixmapsChanged(const Sprite &sprite)
|
||||||
@ -326,6 +348,29 @@ void ObjectPropertiesDialog::spritesMenuAboutToShow()
|
|||||||
[&sprite,this](){ setSprite(sprite); });
|
[&sprite,this](){ setSprite(sprite); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ObjectPropertiesDialog::parentsMenuAboutToShow()
|
||||||
|
{
|
||||||
|
m_menuParents->clear();
|
||||||
|
m_menuParents->addAction(tr("<no parent>"), this, &ObjectPropertiesDialog::clearParent);
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_menuParents->addAction(icon, object.name, this,
|
||||||
|
[&object,this](){ setParent(object); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ObjectPropertiesDialog::currentEventChanged(const QModelIndex &index)
|
void ObjectPropertiesDialog::currentEventChanged(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
if (index.isValid())
|
if (index.isValid())
|
||||||
@ -339,7 +384,7 @@ void ObjectPropertiesDialog::currentEventChanged(const QModelIndex &index)
|
|||||||
{
|
{
|
||||||
none:
|
none:
|
||||||
m_ui->actionsWidget->setActionsContainer(nullptr);
|
m_ui->actionsWidget->setActionsContainer(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectPropertiesDialog::eventsContextMenuRequested(const QPoint &pos)
|
void ObjectPropertiesDialog::eventsContextMenuRequested(const QPoint &pos)
|
||||||
@ -376,6 +421,26 @@ void ObjectPropertiesDialog::setSprite(const Sprite &sprite)
|
|||||||
changed();
|
changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ObjectPropertiesDialog::clearParent()
|
||||||
|
{
|
||||||
|
m_parentName.clear();
|
||||||
|
m_ui->lineEditParent->setText(tr("<no parent>"));
|
||||||
|
changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectPropertiesDialog::setParent(const Object &object)
|
||||||
|
{
|
||||||
|
if (&m_object == &object)
|
||||||
|
{
|
||||||
|
QMessageBox::warning(m_mainWindow, tr("This will create a loop in parents."), tr("This will create a loop in parents."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_parentName = object.name;
|
||||||
|
m_ui->lineEditParent->setText(object.name);
|
||||||
|
changed();
|
||||||
|
}
|
||||||
|
|
||||||
void ObjectPropertiesDialog::updateTitle()
|
void ObjectPropertiesDialog::updateTitle()
|
||||||
{
|
{
|
||||||
setWindowTitle(tr("Object Properties: %0%1")
|
setWindowTitle(tr("Object Properties: %0%1")
|
||||||
|
@ -35,12 +35,14 @@ private slots:
|
|||||||
|
|
||||||
void changed();
|
void changed();
|
||||||
|
|
||||||
void objectNameChanged(const Object &object);
|
void objectNameChanged(const Object &object, const QString &oldName);
|
||||||
void spriteNameChanged(const Sprite &sprite, const QString &oldName);
|
void spriteNameChanged(const Sprite &sprite, const QString &oldName);
|
||||||
|
void objectAboutToBeRemoved(const Object &object);
|
||||||
void spriteAboutToBeRemoved(const Sprite &sprite);
|
void spriteAboutToBeRemoved(const Sprite &sprite);
|
||||||
void spritePixmapsChanged(const Sprite &sprite);
|
void spritePixmapsChanged(const Sprite &sprite);
|
||||||
|
|
||||||
void spritesMenuAboutToShow();
|
void spritesMenuAboutToShow();
|
||||||
|
void parentsMenuAboutToShow();
|
||||||
void currentEventChanged(const QModelIndex &index);
|
void currentEventChanged(const QModelIndex &index);
|
||||||
void eventsContextMenuRequested(const QPoint &pos);
|
void eventsContextMenuRequested(const QPoint &pos);
|
||||||
void rowsInserted(const QModelIndex &parent, int first);
|
void rowsInserted(const QModelIndex &parent, int first);
|
||||||
@ -48,6 +50,9 @@ private slots:
|
|||||||
void clearSprite();
|
void clearSprite();
|
||||||
void setSprite(const Sprite &sprite);
|
void setSprite(const Sprite &sprite);
|
||||||
|
|
||||||
|
void clearParent();
|
||||||
|
void setParent(const Object &object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateTitle();
|
void updateTitle();
|
||||||
void updateSpritePreview();
|
void updateSpritePreview();
|
||||||
@ -65,8 +70,10 @@ private:
|
|||||||
const std::unique_ptr<ObjectEventsModel> m_eventsModel;
|
const std::unique_ptr<ObjectEventsModel> m_eventsModel;
|
||||||
|
|
||||||
QMenu * const m_menuSprites;
|
QMenu * const m_menuSprites;
|
||||||
|
QMenu * const m_menuParents;
|
||||||
|
|
||||||
QString m_spriteName;
|
QString m_spriteName;
|
||||||
|
QString m_parentName;
|
||||||
|
|
||||||
bool m_unsavedChanges{};
|
bool m_unsavedChanges{};
|
||||||
};
|
};
|
||||||
|
@ -211,7 +211,7 @@
|
|||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="lineEditParent">
|
<widget class="QLineEditWithMenu" name="lineEditParent">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
|
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -224,6 +224,9 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string><no parent></string>
|
<string><no parent></string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -231,6 +234,9 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string>...</string>
|
<string>...</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="popupMode">
|
||||||
|
<enum>QToolButton::InstantPopup</enum>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@ -251,6 +257,9 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string><same as sprite></string>
|
<string><same as sprite></string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -258,6 +267,9 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string>...</string>
|
<string>...</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="popupMode">
|
||||||
|
<enum>QToolButton::InstantPopup</enum>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -961,10 +961,15 @@ template<> void ProjectTreeModel::onBeforeRemove<Sprite>(const Sprite &sprite)
|
|||||||
|
|
||||||
template<> void ProjectTreeModel::onBeforeRemove<Object>(const Object &object)
|
template<> void ProjectTreeModel::onBeforeRemove<Object>(const Object &object)
|
||||||
{
|
{
|
||||||
for (auto &object : m_project->objects)
|
for (Object &obj : m_project->objects)
|
||||||
object.collisionEvents.erase(object.name);
|
{
|
||||||
|
if (!obj.parentName.isEmpty() && obj.parentName == object.name)
|
||||||
|
obj.parentName.clear();
|
||||||
|
|
||||||
for (auto &room : m_project->rooms)
|
obj.collisionEvents.erase(object.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Room &room : m_project->rooms)
|
||||||
for (auto iter = std::begin(room.objects); iter != std::end(room.objects); )
|
for (auto iter = std::begin(room.objects); iter != std::end(room.objects); )
|
||||||
if (iter->objectName == object.name)
|
if (iter->objectName == object.name)
|
||||||
iter = room.objects.erase(iter);
|
iter = room.objects.erase(iter);
|
||||||
@ -1004,13 +1009,16 @@ template<> void ProjectTreeModel::onAfterRename<Sprite>(const Sprite &sprite, co
|
|||||||
|
|
||||||
template<> void ProjectTreeModel::onBeforeRename<Object>(const Object &object, const QString &newName)
|
template<> void ProjectTreeModel::onBeforeRename<Object>(const Object &object, const QString &newName)
|
||||||
{
|
{
|
||||||
for (auto &object : m_project->objects)
|
for (Object &obj : m_project->objects)
|
||||||
{
|
{
|
||||||
if (const auto iter = object.collisionEvents.find(object.name); iter != std::end(object.collisionEvents))
|
if (!obj.parentName.isEmpty() && obj.parentName == object.name)
|
||||||
|
obj.parentName = newName;
|
||||||
|
|
||||||
|
if (const auto iter = obj.collisionEvents.find(object.name); iter != std::end(obj.collisionEvents))
|
||||||
{
|
{
|
||||||
auto node = object.collisionEvents.extract(iter);
|
auto node = obj.collisionEvents.extract(iter);
|
||||||
node.key() = newName;
|
node.key() = newName;
|
||||||
object.collisionEvents.insert(std::move(node));
|
obj.collisionEvents.insert(std::move(node));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,6 +306,7 @@ QDataStream &operator<<(QDataStream &ds, const Object &object)
|
|||||||
<< object.solid
|
<< object.solid
|
||||||
<< object.depth
|
<< object.depth
|
||||||
<< object.persistent
|
<< object.persistent
|
||||||
|
<< object.parentName
|
||||||
<< object.events
|
<< object.events
|
||||||
<< object.collisionEvents;
|
<< object.collisionEvents;
|
||||||
return ds;
|
return ds;
|
||||||
@ -319,6 +320,7 @@ QDataStream &operator>>(QDataStream &ds, Object &object)
|
|||||||
>> object.solid
|
>> object.solid
|
||||||
>> object.depth
|
>> object.depth
|
||||||
>> object.persistent
|
>> object.persistent
|
||||||
|
>> object.parentName
|
||||||
>> object.events
|
>> object.events
|
||||||
>> object.collisionEvents;
|
>> object.collisionEvents;
|
||||||
return ds;
|
return ds;
|
||||||
|
@ -126,6 +126,7 @@ struct Object
|
|||||||
bool solid{};
|
bool solid{};
|
||||||
int depth{};
|
int depth{};
|
||||||
bool persistent{};
|
bool persistent{};
|
||||||
|
QString parentName;
|
||||||
events_container_t events;
|
events_container_t events;
|
||||||
collision_events_container_t collisionEvents;
|
collision_events_container_t collisionEvents;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user