Implement mask sprite in objects

This commit is contained in:
2024-01-09 20:55:13 +01:00
parent ef2a9e9fb8
commit 2e7d6ad6c5
7 changed files with 99 additions and 46 deletions

View File

@@ -23,8 +23,10 @@ ObjectPropertiesDialog::ObjectPropertiesDialog(Object &object, ProjectTreeModel
m_eventsModel{std::make_unique<ObjectEventsModel>(m_events, m_collisionEvents)},
m_menuSprites{new QMenu{this}},
m_menuParents{new QMenu{this}},
m_menuMaskSprites{new QMenu{this}},
m_spriteName{object.spriteName},
m_parentName{object.parentName}
m_parentName{object.parentName},
m_maskSpriteName{object.maskSpriteName}
{
m_ui->setupUi(this);
@@ -38,9 +40,11 @@ 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);
m_ui->lineEditMask->setText(m_maskSpriteName.isEmpty() ? tr("<same as sprite>") : m_maskSpriteName);
updateSpritePreview();
m_ui->toolButtonSprite->setMenu(m_menuSprites);
m_ui->toolButtonParent->setMenu(m_menuParents);
m_ui->toolButtonMask->setMenu(m_menuMaskSprites);
m_ui->checkBoxVisible->setChecked(m_object.visible);
m_ui->checkBoxSolid->setChecked(m_object.solid);
m_ui->spinBoxDepth->setValue(m_object.depth);
@@ -48,6 +52,7 @@ ObjectPropertiesDialog::ObjectPropertiesDialog(Object &object, ProjectTreeModel
m_ui->lineEditSprite->setMenu(m_menuSprites);
m_ui->lineEditParent->setMenu(m_menuParents);
m_ui->lineEditMask->setMenu(m_menuMaskSprites);
m_ui->listViewEvents->setModel(m_eventsModel.get());
@@ -101,6 +106,8 @@ ObjectPropertiesDialog::ObjectPropertiesDialog(Object &object, ProjectTreeModel
this, &ObjectPropertiesDialog::spritesMenuAboutToShow);
connect(m_menuParents, &QMenu::aboutToShow,
this, &ObjectPropertiesDialog::parentsMenuAboutToShow);
connect(m_menuMaskSprites, &QMenu::aboutToShow,
this, &ObjectPropertiesDialog::maskSpritesMenuAboutToShow);
connect(m_ui->listViewEvents->selectionModel(), &QItemSelectionModel::currentChanged,
this, &ObjectPropertiesDialog::currentEventChanged);
@@ -142,6 +149,7 @@ void ObjectPropertiesDialog::accept()
m_object.depth = m_ui->spinBoxDepth->value();
m_object.persistent = m_ui->checkBoxPersistent->isChecked();
m_object.parentName = m_parentName;
m_object.maskSpriteName = m_maskSpriteName;
m_object.events = std::move(m_events);
m_object.collisionEvents = std::move(m_collisionEvents);
@@ -284,18 +292,24 @@ void ObjectPropertiesDialog::objectNameChanged(const Object &object, const QStri
void ObjectPropertiesDialog::spriteNameChanged(const Sprite &sprite, const QString &oldName)
{
if (m_spriteName.isEmpty())
return;
if (m_spriteName != oldName)
return;
m_spriteName = sprite.name;
if (!m_spriteName.isEmpty() && m_spriteName == oldName)
{
QSignalBlocker blocker{m_ui->lineEditSprite};
m_ui->lineEditSprite->setText(sprite.name);
m_spriteName = sprite.name;
{
QSignalBlocker blocker{m_ui->lineEditSprite};
m_ui->lineEditSprite->setText(sprite.name);
}
updateSpritePreview();
}
if (!m_maskSpriteName.isEmpty() && m_maskSpriteName == oldName)
{
m_maskSpriteName = sprite.name;
{
QSignalBlocker blocker{m_ui->lineEditMask};
m_ui->lineEditMask->setText(sprite.name);
}
}
updateSpritePreview();
}
void ObjectPropertiesDialog::objectAboutToBeRemoved(const Object &object)
@@ -318,6 +332,15 @@ void ObjectPropertiesDialog::spriteAboutToBeRemoved(const Sprite &sprite)
}
m_ui->labelSpritePreview->setPixmap(QPixmap{});
}
if (!m_maskSpriteName.isEmpty() && m_maskSpriteName == sprite.name)
{
m_maskSpriteName.clear();
{
QSignalBlocker blocker{m_ui->lineEditMask};
m_ui->lineEditMask->setText(tr("<same as sprite>"));
}
}
}
void ObjectPropertiesDialog::spritePixmapsChanged(const Sprite &sprite)
@@ -365,6 +388,17 @@ void ObjectPropertiesDialog::parentsMenuAboutToShow()
}
}
void ObjectPropertiesDialog::maskSpritesMenuAboutToShow()
{
m_menuMaskSprites->clear();
m_menuMaskSprites->addAction(tr("<same as sprite>"), this, &ObjectPropertiesDialog::clearMaskSprite);
for (const auto &sprite : m_projectModel.project()->sprites)
m_menuMaskSprites->addAction(sprite.pixmaps.empty() ? QPixmap{} : sprite.pixmaps.front(),
sprite.name,
this,
[&sprite,this](){ setMaskSprite(sprite); });
}
void ObjectPropertiesDialog::currentEventChanged(const QModelIndex &index)
{
if (index.isValid())
@@ -435,6 +469,20 @@ void ObjectPropertiesDialog::setParent(const Object &object)
changed();
}
void ObjectPropertiesDialog::clearMaskSprite()
{
m_maskSpriteName.clear();
m_ui->lineEditMask->setText(tr("<same as sprite>"));
changed();
}
void ObjectPropertiesDialog::setMaskSprite(const Sprite &sprite)
{
m_maskSpriteName = sprite.name;
m_ui->lineEditMask->setText(sprite.name);
changed();
}
void ObjectPropertiesDialog::updateTitle()
{
setWindowTitle(tr("Object Properties: %0%1")

View File

@@ -43,6 +43,7 @@ private slots:
void spritesMenuAboutToShow();
void parentsMenuAboutToShow();
void maskSpritesMenuAboutToShow();
void currentEventChanged(const QModelIndex &index);
void eventsContextMenuRequested(const QPoint &pos);
void rowsInserted(const QModelIndex &parent, int first);
@@ -53,6 +54,9 @@ private slots:
void clearParent();
void setParent(const Object &object);
void clearMaskSprite();
void setMaskSprite(const Sprite &sprite);
private:
void updateTitle();
void updateSpritePreview();
@@ -71,9 +75,11 @@ private:
QMenu * const m_menuSprites;
QMenu * const m_menuParents;
QMenu * const m_menuMaskSprites;
QString m_spriteName;
QString m_parentName;
QString m_maskSpriteName;
bool m_unsavedChanges{};
};

View File

@@ -244,7 +244,7 @@
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLineEdit" name="lineEditMask">
<widget class="QLineEditWithMenu" name="lineEditMask">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>0</horstretch>

View File

@@ -283,16 +283,21 @@ template<> void ProjectTreeModel::onBeforeRemove<Sprite>(const Sprite &sprite)
{
for (auto iter = std::begin(m_project->objects); iter != std::end(m_project->objects); iter++)
{
if (iter->spriteName != sprite.name)
continue;
if (iter->spriteName == sprite.name)
{
auto oldSpriteName = std::move(iter->spriteName);
iter->spriteName.clear();
auto oldSpriteName = std::move(iter->spriteName);
iter->spriteName.clear();
const auto index = this->index(std::distance(std::begin(m_project->objects), iter), 0, rootFor<Object>());
emit dataChanged(index, index, {Qt::DecorationRole});
const auto index = this->index(std::distance(std::begin(m_project->objects), iter), 0, rootFor<Object>());
emit dataChanged(index, index, {Qt::DecorationRole});
emit objectSpriteNameChanged(*iter, std::move(oldSpriteName));
}
emit objectSpriteNameChanged(*iter, std::move(oldSpriteName));
if (iter->maskSpriteName == sprite.name)
{
iter->maskSpriteName.clear();
}
}
}
@@ -330,17 +335,22 @@ template<> void ProjectTreeModel::onAfterRename<Sprite>(const Sprite &sprite, co
{
for (auto &object : m_project->objects)
{
if (object.spriteName != oldName)
continue;
if (object.spriteName == oldName)
{
auto oldSpriteName = std::move(object.spriteName);
auto oldSpriteName = std::move(object.spriteName);
object.spriteName = sprite.name;
object.spriteName = sprite.name;
// const auto index = this->index(std::distance(std::begin(m_project->objects), iter), 0, rootFor<Object>());
// emit dataChanged(index, index, {Qt::DecorationRole});
// const auto index = this->index(std::distance(std::begin(m_project->objects), iter), 0, rootFor<Object>());
// emit dataChanged(index, index, {Qt::DecorationRole});
emit objectSpriteNameChanged(object, std::move(oldSpriteName));
}
emit objectSpriteNameChanged(object, std::move(oldSpriteName));
if (object.maskSpriteName == oldName)
{
object.maskSpriteName = sprite.name;
}
}
}

View File

@@ -40,6 +40,11 @@ ActionsContainerWidget::ActionsContainerWidget(QWidget *parent) :
emit changed();
}
});
m_ui->toolButtonMoveFixed->setAction(MoveFixedAction{});
m_ui->toolButtonMoveFree->setAction(MoveFreeAction{});
m_ui->toolButtonMoveTowards->setAction(MoveTowardsAction{});
m_ui->toolButtonExecuteCode->setAction(ExecuteCodeAction{});
}
ActionsContainerWidget::~ActionsContainerWidget() = default;

View File

@@ -232,26 +232,8 @@ struct Object
int depth{};
bool persistent{};
QString parentName;
events_container_t events {
{
EventType::Create,
ActionsContainer {
Action { MoveFixedAction{} },
Action { MoveFreeAction{} },
Action { MoveTowardsAction{} },
Action { ExecuteCodeAction{} }
}
},
{
EventType::Destroy,
ActionsContainer {
Action { ExecuteCodeAction{} },
Action { MoveTowardsAction{} },
Action { MoveFreeAction{} },
Action { MoveFixedAction{} }
}
}
};
QString maskSpriteName;
events_container_t events;
collision_events_container_t collisionEvents;
};

View File

@@ -341,6 +341,7 @@ QDataStream &operator<<(QDataStream &ds, const Object &object)
<< object.depth
<< object.persistent
<< object.parentName
<< object.maskSpriteName
<< object.events
<< object.collisionEvents;
return ds;
@@ -355,6 +356,7 @@ QDataStream &operator>>(QDataStream &ds, Object &object)
>> object.depth
>> object.persistent
>> object.parentName
>> object.maskSpriteName
>> object.events
>> object.collisionEvents;
return ds;