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