Implement mouse events
This commit is contained in:
1 parent
defb83c9c3
commit
f6fc000287
10 files changed
+491
-24
No files matched your search
@@ -82,6 +82,78 @@ AddEventDialog::AddEventDialog(ProjectTreeModel &projectModel, MainWindow &mainW
|
||||
m_ui->pushButtonCollision->setMenu(menu);
|
||||
}
|
||||
|
||||
{
|
||||
auto menu = new QMenu;
|
||||
menu->addAction(tr("Left button"), this, [this](){ m_eventType = Object::EventType::MouseLeftButton; accept(); });
|
||||
menu->addAction(tr("Right button"), this, [this](){ m_eventType = Object::EventType::MouseRightButton; accept(); });
|
||||
menu->addAction(tr("Middle button"), this, [this](){ m_eventType = Object::EventType::MouseMiddleButton; accept(); });
|
||||
menu->addSeparator();
|
||||
menu->addAction(tr("No button"), this, [this](){ m_eventType = Object::EventType::MouseNoButton; accept(); });
|
||||
menu->addSeparator();
|
||||
menu->addAction(tr("Left pressed"), this, [this](){ m_eventType = Object::EventType::MouseLeftPressed; accept(); });
|
||||
menu->addAction(tr("Right pressed"), this, [this](){ m_eventType = Object::EventType::MouseRightPressed; accept(); });
|
||||
menu->addAction(tr("Middle pressed"), this, [this](){ m_eventType = Object::EventType::MouseMiddlePressed; accept(); });
|
||||
menu->addSeparator();
|
||||
menu->addAction(tr("Left released"), this, [this](){ m_eventType = Object::EventType::MouseLeftReleased; accept(); });
|
||||
menu->addAction(tr("Right released"), this, [this](){ m_eventType = Object::EventType::MouseRightReleased; accept(); });
|
||||
menu->addAction(tr("Middle released"), this, [this](){ m_eventType = Object::EventType::MouseMiddleReleased; accept(); });
|
||||
menu->addSeparator();
|
||||
menu->addAction(tr("Mouse enter"), this, [this](){ m_eventType = Object::EventType::MouseEnter; accept(); });
|
||||
menu->addAction(tr("Mouse leave"), this, [this](){ m_eventType = Object::EventType::MouseLeave; accept(); });
|
||||
menu->addSeparator();
|
||||
menu->addAction(tr("Mouse wheel up"), this, [this](){ m_eventType = Object::EventType::MouseWheelUp; accept(); });
|
||||
menu->addAction(tr("Mouse wheel down"), this, [this](){ m_eventType = Object::EventType::MouseWheelDown; accept(); });
|
||||
menu->addSeparator();
|
||||
{
|
||||
auto subMenu = menu->addMenu(tr("Global mouse"));
|
||||
subMenu->addAction(tr("Global Left button"), this, [this](){ m_eventType = Object::EventType::MouseGlobalLeftButton; accept(); });
|
||||
subMenu->addAction(tr("Global Right button"), this, [this](){ m_eventType = Object::EventType::MouseGlobalRightButton; accept(); });
|
||||
subMenu->addAction(tr("Global Middle button"), this, [this](){ m_eventType = Object::EventType::MouseGlobalMiddleButton; accept(); });
|
||||
subMenu->addSeparator();
|
||||
subMenu->addAction(tr("Global Left pressed"), this, [this](){ m_eventType = Object::EventType::MouseGlobalLeftPressed; accept(); });
|
||||
subMenu->addAction(tr("Global Right pressed"), this, [this](){ m_eventType = Object::EventType::MouseGlobalRightPressed; accept(); });
|
||||
subMenu->addAction(tr("Global Middle pressed"), this, [this](){ m_eventType = Object::EventType::MouseGlobalMiddlePressed; accept(); });
|
||||
subMenu->addSeparator();
|
||||
subMenu->addAction(tr("Global Left released"), this, [this](){ m_eventType = Object::EventType::MouseGlobalLeftReleased; accept(); });
|
||||
subMenu->addAction(tr("Global Right released"), this, [this](){ m_eventType = Object::EventType::MouseGlobalRightReleased; accept(); });
|
||||
subMenu->addAction(tr("Global Middle released"), this, [this](){ m_eventType = Object::EventType::MouseGlobalMiddleReleased; accept(); });
|
||||
}
|
||||
menu->addSeparator();
|
||||
{
|
||||
auto subMenu = menu->addMenu(tr("Joystick 1"));
|
||||
subMenu->addAction(tr("Left"), this, [this](){ m_eventType = Object::EventType::MouseJoystick1Left; accept(); });
|
||||
subMenu->addAction(tr("Right"), this, [this](){ m_eventType = Object::EventType::MouseJoystick1Right; accept(); });
|
||||
subMenu->addAction(tr("Up"), this, [this](){ m_eventType = Object::EventType::MouseJoystick1Up; accept(); });
|
||||
subMenu->addAction(tr("Down"), this, [this](){ m_eventType = Object::EventType::MouseJoystick1Down; accept(); });
|
||||
subMenu->addSeparator();
|
||||
subMenu->addAction(tr("Button 1"), this, [this](){ m_eventType = Object::EventType::MouseJoystick1Button1; accept(); });
|
||||
subMenu->addAction(tr("Button 2"), this, [this](){ m_eventType = Object::EventType::MouseJoystick1Button2; accept(); });
|
||||
subMenu->addAction(tr("Button 3"), this, [this](){ m_eventType = Object::EventType::MouseJoystick1Button3; accept(); });
|
||||
subMenu->addAction(tr("Button 4"), this, [this](){ m_eventType = Object::EventType::MouseJoystick1Button4; accept(); });
|
||||
subMenu->addAction(tr("Button 5"), this, [this](){ m_eventType = Object::EventType::MouseJoystick1Button5; accept(); });
|
||||
subMenu->addAction(tr("Button 6"), this, [this](){ m_eventType = Object::EventType::MouseJoystick1Button6; accept(); });
|
||||
subMenu->addAction(tr("Button 7"), this, [this](){ m_eventType = Object::EventType::MouseJoystick1Button7; accept(); });
|
||||
subMenu->addAction(tr("Button 8"), this, [this](){ m_eventType = Object::EventType::MouseJoystick1Button8; accept(); });
|
||||
}
|
||||
{
|
||||
auto subMenu = menu->addMenu(tr("Joystick 2"));
|
||||
subMenu->addAction(tr("Left"), this, [this](){ m_eventType = Object::EventType::MouseJoystick2Left; accept(); });
|
||||
subMenu->addAction(tr("Right"), this, [this](){ m_eventType = Object::EventType::MouseJoystick2Right; accept(); });
|
||||
subMenu->addAction(tr("Up"), this, [this](){ m_eventType = Object::EventType::MouseJoystick2Up; accept(); });
|
||||
subMenu->addAction(tr("Down"), this, [this](){ m_eventType = Object::EventType::MouseJoystick2Down; accept(); });
|
||||
subMenu->addSeparator();
|
||||
subMenu->addAction(tr("Button 1"), this, [this](){ m_eventType = Object::EventType::MouseJoystick2Button1; accept(); });
|
||||
subMenu->addAction(tr("Button 2"), this, [this](){ m_eventType = Object::EventType::MouseJoystick2Button2; accept(); });
|
||||
subMenu->addAction(tr("Button 3"), this, [this](){ m_eventType = Object::EventType::MouseJoystick2Button3; accept(); });
|
||||
subMenu->addAction(tr("Button 4"), this, [this](){ m_eventType = Object::EventType::MouseJoystick2Button4; accept(); });
|
||||
subMenu->addAction(tr("Button 5"), this, [this](){ m_eventType = Object::EventType::MouseJoystick2Button5; accept(); });
|
||||
subMenu->addAction(tr("Button 6"), this, [this](){ m_eventType = Object::EventType::MouseJoystick2Button6; accept(); });
|
||||
subMenu->addAction(tr("Button 7"), this, [this](){ m_eventType = Object::EventType::MouseJoystick2Button7; accept(); });
|
||||
subMenu->addAction(tr("Button 8"), this, [this](){ m_eventType = Object::EventType::MouseJoystick2Button8; accept(); });
|
||||
}
|
||||
m_ui->pushButtonMouse->setMenu(menu);
|
||||
}
|
||||
|
||||
{
|
||||
auto menu = new QMenu;
|
||||
menu->addAction(tr("Add/Modify Triggers..."), this, [this](){ m_mainWindow.showDefineTriggers(); reject(); });
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
<property name="text">
|
||||
<string>&Mouse</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources_editor.qrc">
|
||||
<normaloff>:/qtgameengine/icons/event-mouse.png</normaloff>:/qtgameengine/icons/event-mouse.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
@@ -133,7 +137,7 @@
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel</set>
|
||||
<set>QDialogButtonBox::StandardButton::Cancel</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>true</bool>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -38,24 +38,71 @@ QVariant ObjectEventsModel::data(const QModelIndex &index, int role) const
|
||||
case Qt::EditRole:
|
||||
switch (pair.first)
|
||||
{
|
||||
case Object::EventType::Create: return tr("Create");
|
||||
case Object::EventType::Destroy: return tr("Destroy");
|
||||
case Object::EventType::Alarm0: return tr("Alarm 0");
|
||||
case Object::EventType::Alarm1: return tr("Alarm 1");
|
||||
case Object::EventType::Alarm2: return tr("Alarm 2");
|
||||
case Object::EventType::Alarm3: return tr("Alarm 3");
|
||||
case Object::EventType::Alarm4: return tr("Alarm 4");
|
||||
case Object::EventType::Alarm5: return tr("Alarm 5");
|
||||
case Object::EventType::Alarm6: return tr("Alarm 6");
|
||||
case Object::EventType::Alarm7: return tr("Alarm 7");
|
||||
case Object::EventType::Alarm8: return tr("Alarm 8");
|
||||
case Object::EventType::Alarm9: return tr("Alarm 9");
|
||||
case Object::EventType::Alarm10: return tr("Alarm 10");
|
||||
case Object::EventType::Alarm11: return tr("Alarm 11");
|
||||
case Object::EventType::Step: return tr("Step");
|
||||
case Object::EventType::BeginStep: return tr("Begin Step");
|
||||
case Object::EventType::EndStep: return tr("End Step");
|
||||
case Object::EventType::Draw: return tr("Draw");
|
||||
case Object::EventType::Create: return tr("Create");
|
||||
case Object::EventType::Destroy: return tr("Destroy");
|
||||
case Object::EventType::Alarm0: return tr("Alarm 0");
|
||||
case Object::EventType::Alarm1: return tr("Alarm 1");
|
||||
case Object::EventType::Alarm2: return tr("Alarm 2");
|
||||
case Object::EventType::Alarm3: return tr("Alarm 3");
|
||||
case Object::EventType::Alarm4: return tr("Alarm 4");
|
||||
case Object::EventType::Alarm5: return tr("Alarm 5");
|
||||
case Object::EventType::Alarm6: return tr("Alarm 6");
|
||||
case Object::EventType::Alarm7: return tr("Alarm 7");
|
||||
case Object::EventType::Alarm8: return tr("Alarm 8");
|
||||
case Object::EventType::Alarm9: return tr("Alarm 9");
|
||||
case Object::EventType::Alarm10: return tr("Alarm 10");
|
||||
case Object::EventType::Alarm11: return tr("Alarm 11");
|
||||
case Object::EventType::Step: return tr("Step");
|
||||
case Object::EventType::BeginStep: return tr("Begin Step");
|
||||
case Object::EventType::EndStep: return tr("End Step");
|
||||
case Object::EventType::Draw: return tr("Draw");
|
||||
case Object::EventType::MouseLeftButton: return tr("Left button");
|
||||
case Object::EventType::MouseRightButton: return tr("Right Button");
|
||||
case Object::EventType::MouseMiddleButton: return tr("Middle Button");
|
||||
case Object::EventType::MouseNoButton: return tr("No Button");
|
||||
case Object::EventType::MouseLeftPressed: return tr("Left Pressed");
|
||||
case Object::EventType::MouseRightPressed: return tr("Right Pressed");
|
||||
case Object::EventType::MouseMiddlePressed: return tr("Middle Pressed");
|
||||
case Object::EventType::MouseLeftReleased: return tr("Left Released");
|
||||
case Object::EventType::MouseRightReleased: return tr("Right Released");
|
||||
case Object::EventType::MouseMiddleReleased: return tr("Middle Released");
|
||||
case Object::EventType::MouseEnter: return tr("Enter");
|
||||
case Object::EventType::MouseLeave: return tr("Leave");
|
||||
case Object::EventType::MouseWheelUp: return tr("Wheel Up");
|
||||
case Object::EventType::MouseWheelDown: return tr("Wheel Down");
|
||||
case Object::EventType::MouseGlobalLeftButton: return tr("Global Left Button");
|
||||
case Object::EventType::MouseGlobalRightButton: return tr("Global Right Button");
|
||||
case Object::EventType::MouseGlobalMiddleButton: return tr("Global Middle Button");
|
||||
case Object::EventType::MouseGlobalLeftPressed: return tr("Global Left Pressed");
|
||||
case Object::EventType::MouseGlobalRightPressed: return tr("Global Right Pressed");
|
||||
case Object::EventType::MouseGlobalMiddlePressed: return tr("Global Middle Pressed");
|
||||
case Object::EventType::MouseGlobalLeftReleased: return tr("Global Left Released");
|
||||
case Object::EventType::MouseGlobalRightReleased: return tr("Global Right Released");
|
||||
case Object::EventType::MouseGlobalMiddleReleased: return tr("Global Middle Released");
|
||||
case Object::EventType::MouseJoystick1Left: return tr("Joystick 1 Left");
|
||||
case Object::EventType::MouseJoystick1Right: return tr("Joystick 1 Right");
|
||||
case Object::EventType::MouseJoystick1Up: return tr("Joystick 1 Up");
|
||||
case Object::EventType::MouseJoystick1Down: return tr("Joystick 1 Down");
|
||||
case Object::EventType::MouseJoystick1Button1: return tr("Joystick 1 Button 1");
|
||||
case Object::EventType::MouseJoystick1Button2: return tr("Joystick 1 Button 2");
|
||||
case Object::EventType::MouseJoystick1Button3: return tr("Joystick 1 Button 3");
|
||||
case Object::EventType::MouseJoystick1Button4: return tr("Joystick 1 Button 4");
|
||||
case Object::EventType::MouseJoystick1Button5: return tr("Joystick 1 Button 5");
|
||||
case Object::EventType::MouseJoystick1Button6: return tr("Joystick 1 Button 6");
|
||||
case Object::EventType::MouseJoystick1Button7: return tr("Joystick 1 Button 7");
|
||||
case Object::EventType::MouseJoystick1Button8: return tr("Joystick 1 Button 8");
|
||||
case Object::EventType::MouseJoystick2Left: return tr("Joystick 2 Left");
|
||||
case Object::EventType::MouseJoystick2Right: return tr("Joystick 2 Right");
|
||||
case Object::EventType::MouseJoystick2Up: return tr("Joystick 2 Up");
|
||||
case Object::EventType::MouseJoystick2Down: return tr("Joystick 2 Down");
|
||||
case Object::EventType::MouseJoystick2Button1: return tr("Joystick 2 Button 1");
|
||||
case Object::EventType::MouseJoystick2Button2: return tr("Joystick 2 Button 2");
|
||||
case Object::EventType::MouseJoystick2Button3: return tr("Joystick 2 Button 3");
|
||||
case Object::EventType::MouseJoystick2Button4: return tr("Joystick 2 Button 4");
|
||||
case Object::EventType::MouseJoystick2Button5: return tr("Joystick 2 Button 5");
|
||||
case Object::EventType::MouseJoystick2Button6: return tr("Joystick 2 Button 6");
|
||||
case Object::EventType::MouseJoystick2Button7: return tr("Joystick 2 Button 7");
|
||||
case Object::EventType::MouseJoystick2Button8: return tr("Joystick 2 Button 8");
|
||||
}
|
||||
|
||||
qWarning() << "unknown event type" << std::to_underlying(pair.first);
|
||||
@@ -63,8 +110,8 @@ QVariant ObjectEventsModel::data(const QModelIndex &index, int role) const
|
||||
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::Create: return QIcon{":/qtgameengine/icons/event-create.png"};
|
||||
case Object::EventType::Destroy: return QIcon{":/qtgameengine/icons/event-destroy.png"};
|
||||
case Object::EventType::Alarm0:
|
||||
case Object::EventType::Alarm1:
|
||||
case Object::EventType::Alarm2:
|
||||
@@ -76,11 +123,58 @@ QVariant ObjectEventsModel::data(const QModelIndex &index, int role) const
|
||||
case Object::EventType::Alarm8:
|
||||
case Object::EventType::Alarm9:
|
||||
case Object::EventType::Alarm10:
|
||||
case Object::EventType::Alarm11: return QIcon{":/qtgameengine/icons/event-alarm.png"};
|
||||
case Object::EventType::Alarm11: return QIcon{":/qtgameengine/icons/event-alarm.png"};
|
||||
case Object::EventType::Step:
|
||||
case Object::EventType::BeginStep:
|
||||
case Object::EventType::EndStep: return QIcon{":/qtgameengine/icons/event-step.png"};
|
||||
case Object::EventType::Draw: return QIcon{":/qtgameengine/icons/event-draw.png"};
|
||||
case Object::EventType::EndStep: return QIcon{":/qtgameengine/icons/event-step.png"};
|
||||
case Object::EventType::Draw: return QIcon{":/qtgameengine/icons/event-draw.png"};
|
||||
case Object::EventType::MouseLeftButton:
|
||||
case Object::EventType::MouseRightButton:
|
||||
case Object::EventType::MouseMiddleButton:
|
||||
case Object::EventType::MouseNoButton:
|
||||
case Object::EventType::MouseLeftPressed:
|
||||
case Object::EventType::MouseRightPressed:
|
||||
case Object::EventType::MouseMiddlePressed:
|
||||
case Object::EventType::MouseLeftReleased:
|
||||
case Object::EventType::MouseRightReleased:
|
||||
case Object::EventType::MouseMiddleReleased:
|
||||
case Object::EventType::MouseEnter:
|
||||
case Object::EventType::MouseLeave:
|
||||
case Object::EventType::MouseWheelUp:
|
||||
case Object::EventType::MouseWheelDown:
|
||||
case Object::EventType::MouseGlobalLeftButton:
|
||||
case Object::EventType::MouseGlobalRightButton:
|
||||
case Object::EventType::MouseGlobalMiddleButton:
|
||||
case Object::EventType::MouseGlobalLeftPressed:
|
||||
case Object::EventType::MouseGlobalRightPressed:
|
||||
case Object::EventType::MouseGlobalMiddlePressed:
|
||||
case Object::EventType::MouseGlobalLeftReleased:
|
||||
case Object::EventType::MouseGlobalRightReleased:
|
||||
case Object::EventType::MouseGlobalMiddleReleased:
|
||||
case Object::EventType::MouseJoystick1Left:
|
||||
case Object::EventType::MouseJoystick1Right:
|
||||
case Object::EventType::MouseJoystick1Up:
|
||||
case Object::EventType::MouseJoystick1Down:
|
||||
case Object::EventType::MouseJoystick1Button1:
|
||||
case Object::EventType::MouseJoystick1Button2:
|
||||
case Object::EventType::MouseJoystick1Button3:
|
||||
case Object::EventType::MouseJoystick1Button4:
|
||||
case Object::EventType::MouseJoystick1Button5:
|
||||
case Object::EventType::MouseJoystick1Button6:
|
||||
case Object::EventType::MouseJoystick1Button7:
|
||||
case Object::EventType::MouseJoystick1Button8:
|
||||
case Object::EventType::MouseJoystick2Left:
|
||||
case Object::EventType::MouseJoystick2Right:
|
||||
case Object::EventType::MouseJoystick2Up:
|
||||
case Object::EventType::MouseJoystick2Down:
|
||||
case Object::EventType::MouseJoystick2Button1:
|
||||
case Object::EventType::MouseJoystick2Button2:
|
||||
case Object::EventType::MouseJoystick2Button3:
|
||||
case Object::EventType::MouseJoystick2Button4:
|
||||
case Object::EventType::MouseJoystick2Button5:
|
||||
case Object::EventType::MouseJoystick2Button6:
|
||||
case Object::EventType::MouseJoystick2Button7:
|
||||
case Object::EventType::MouseJoystick2Button8: return QIcon{":/qtgameengine/icons/event-mouse.png"};
|
||||
}
|
||||
|
||||
qWarning() << "unknown event type" << std::to_underlying(pair.first);
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
<file>icons/event-create.png</file>
|
||||
<file>icons/event-destroy.png</file>
|
||||
<file>icons/event-draw.png</file>
|
||||
<file>icons/event-mouse.png</file>
|
||||
<file>icons/event-step.png</file>
|
||||
<file>icons/exit.png</file>
|
||||
<file>icons/export-resources.png</file>
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QEnterEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QWheelEvent>
|
||||
|
||||
#include "closeeventfilter.h"
|
||||
#include "projectcontainer.h"
|
||||
@@ -22,6 +25,8 @@ GameEngine::GameEngine(const ProjectContainer &project, QObject *parent) :
|
||||
|
||||
m_glGameWindow.setModality(Qt::WindowModal);
|
||||
m_vulkanGameWindow.setModality(Qt::WindowModal);
|
||||
m_glGameWindow.installEventFilter(this);
|
||||
m_vulkanGameWindow.installEventFilter(this);
|
||||
|
||||
m_frameTimer.setTimerType(Qt::PreciseTimer);
|
||||
m_frameTimer.setSingleShot(true);
|
||||
@@ -41,6 +46,81 @@ GameEngine::GameEngine(const ProjectContainer &project, QObject *parent) :
|
||||
});
|
||||
}
|
||||
|
||||
bool GameEngine::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
if (watched != &m_glGameWindow && watched != &m_vulkanGameWindow)
|
||||
return QObject::eventFilter(watched, event);
|
||||
|
||||
auto *window = static_cast<QWindow *>(watched);
|
||||
const auto roomPosition = [this, window](QPointF position) {
|
||||
return QPointF{position.x() * m_scene.roomSize.width() / std::max(1, window->width()),
|
||||
position.y() * m_scene.roomSize.height() / std::max(1, window->height())};
|
||||
};
|
||||
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::FocusIn:
|
||||
if (m_mouseSource != window)
|
||||
{
|
||||
m_scene.resetMouseInput();
|
||||
m_mouseSource = window;
|
||||
}
|
||||
break;
|
||||
case QEvent::FocusOut:
|
||||
case QEvent::Hide:
|
||||
if (m_mouseSource == window)
|
||||
{
|
||||
m_scene.resetMouseInput();
|
||||
m_mouseSource = nullptr;
|
||||
}
|
||||
break;
|
||||
case QEvent::Enter:
|
||||
if (!m_mouseSource)
|
||||
m_mouseSource = window;
|
||||
if (m_mouseSource == window)
|
||||
m_scene.queueMouseMove(roomPosition(static_cast<QEnterEvent *>(event)->position()));
|
||||
break;
|
||||
case QEvent::Leave:
|
||||
if (m_mouseSource == window)
|
||||
m_scene.queueMouseLeave();
|
||||
break;
|
||||
case QEvent::MouseMove:
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease:
|
||||
case QEvent::MouseButtonDblClick:
|
||||
{
|
||||
auto *mouse = static_cast<QMouseEvent *>(event);
|
||||
if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick)
|
||||
{
|
||||
if (m_mouseSource != window)
|
||||
{
|
||||
m_scene.resetMouseInput();
|
||||
m_mouseSource = window;
|
||||
}
|
||||
}
|
||||
if (m_mouseSource != window)
|
||||
break;
|
||||
const QPointF position = roomPosition(mouse->position());
|
||||
if (event->type() == QEvent::MouseMove)
|
||||
m_scene.queueMouseMove(position);
|
||||
else
|
||||
m_scene.queueMouseButton(position, mouse->button(),
|
||||
event->type() != QEvent::MouseButtonRelease);
|
||||
break;
|
||||
}
|
||||
case QEvent::Wheel:
|
||||
if (m_mouseSource == window)
|
||||
{
|
||||
auto *wheel = static_cast<QWheelEvent *>(event);
|
||||
m_scene.queueMouseWheel(roomPosition(wheel->position()), wheel->angleDelta().y());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QObject::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
void GameEngine::run()
|
||||
{
|
||||
if (m_project.rooms.empty())
|
||||
|
||||
@@ -21,6 +21,9 @@ public:
|
||||
explicit GameEngine(const ProjectContainer &project, QObject *parent = nullptr);
|
||||
void run();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
private:
|
||||
const ProjectContainer &m_project;
|
||||
GameScene m_scene;
|
||||
@@ -28,6 +31,7 @@ private:
|
||||
GlGameWindow m_glGameWindow;
|
||||
VulkanGameWindow m_vulkanGameWindow;
|
||||
bool m_vulkanAvailable{};
|
||||
QWindow *m_mouseSource{};
|
||||
QTimer m_frameTimer;
|
||||
QElapsedTimer m_elapsed;
|
||||
qint64 m_nextFrameNanoseconds{};
|
||||
|
||||
@@ -26,6 +26,37 @@ QPointF motion(double degrees, double speed)
|
||||
return {speed * std::cos(radians), -speed * std::sin(radians)};
|
||||
}
|
||||
|
||||
std::optional<Object::EventType> mouseButtonEvent(Qt::MouseButton button, bool pressed, bool global)
|
||||
{
|
||||
using Event = Object::EventType;
|
||||
switch (button)
|
||||
{
|
||||
case Qt::LeftButton:
|
||||
return global ? (pressed ? Event::MouseGlobalLeftPressed : Event::MouseGlobalLeftReleased)
|
||||
: (pressed ? Event::MouseLeftPressed : Event::MouseLeftReleased);
|
||||
case Qt::RightButton:
|
||||
return global ? (pressed ? Event::MouseGlobalRightPressed : Event::MouseGlobalRightReleased)
|
||||
: (pressed ? Event::MouseRightPressed : Event::MouseRightReleased);
|
||||
case Qt::MiddleButton:
|
||||
return global ? (pressed ? Event::MouseGlobalMiddlePressed : Event::MouseGlobalMiddleReleased)
|
||||
: (pressed ? Event::MouseMiddlePressed : Event::MouseMiddleReleased);
|
||||
default:
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<Object::EventType> mouseHeldEvent(Qt::MouseButton button, bool global)
|
||||
{
|
||||
using Event = Object::EventType;
|
||||
switch (button)
|
||||
{
|
||||
case Qt::LeftButton: return global ? Event::MouseGlobalLeftButton : Event::MouseLeftButton;
|
||||
case Qt::RightButton: return global ? Event::MouseGlobalRightButton : Event::MouseRightButton;
|
||||
case Qt::MiddleButton: return global ? Event::MouseGlobalMiddleButton : Event::MouseMiddleButton;
|
||||
default: return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ObjectInstance::executeActions(const ActionsContainer &actions, GameScene &scene,
|
||||
@@ -260,6 +291,115 @@ void GameScene::removeDestroyed()
|
||||
std::erase_if(instances, [](const Instance &instance) { return instance.pendingDestroy; });
|
||||
}
|
||||
|
||||
void GameScene::queueMouseMove(QPointF position)
|
||||
{
|
||||
m_mouseInputs.push_back({MouseInput::Kind::Move, position});
|
||||
}
|
||||
|
||||
void GameScene::queueMouseButton(QPointF position, Qt::MouseButton button, bool pressed)
|
||||
{
|
||||
m_mouseInputs.push_back({pressed ? MouseInput::Kind::Press : MouseInput::Kind::Release,
|
||||
position, button});
|
||||
}
|
||||
|
||||
void GameScene::queueMouseWheel(QPointF position, int angleDeltaY)
|
||||
{
|
||||
m_mouseInputs.push_back({MouseInput::Kind::Wheel, position, Qt::NoButton, angleDeltaY});
|
||||
}
|
||||
|
||||
void GameScene::queueMouseLeave()
|
||||
{
|
||||
m_mouseInputs.push_back({MouseInput::Kind::Leave, {}});
|
||||
}
|
||||
|
||||
void GameScene::resetMouseInput()
|
||||
{
|
||||
m_mouseInputs.push_back({MouseInput::Kind::Reset, {}});
|
||||
}
|
||||
|
||||
void GameScene::dispatchMouseEvent(Object::EventType type, QPointF position, bool global)
|
||||
{
|
||||
for (Instance &instance : instances)
|
||||
if (!instance.pendingDestroy &&
|
||||
(global || collisionRect(instance).contains(position)))
|
||||
instance.executeEvent(type, *this, m_executor);
|
||||
}
|
||||
|
||||
void GameScene::updateMouseHover()
|
||||
{
|
||||
for (Instance &instance : instances)
|
||||
{
|
||||
if (instance.pendingDestroy)
|
||||
continue;
|
||||
const bool over = m_mouseInside && collisionRect(instance).contains(m_mousePosition);
|
||||
if (over == instance.mouseOver)
|
||||
continue;
|
||||
instance.mouseOver = over;
|
||||
instance.executeEvent(over ? Object::EventType::MouseEnter : Object::EventType::MouseLeave,
|
||||
*this, m_executor);
|
||||
}
|
||||
}
|
||||
|
||||
void GameScene::processMouseInput()
|
||||
{
|
||||
const auto inputs = std::exchange(m_mouseInputs, {});
|
||||
const QRectF room{QPointF{}, QSizeF{roomSize}};
|
||||
for (const MouseInput &input : inputs)
|
||||
{
|
||||
if (input.kind == MouseInput::Kind::Leave || input.kind == MouseInput::Kind::Reset)
|
||||
{
|
||||
m_mouseInside = false;
|
||||
if (input.kind == MouseInput::Kind::Reset)
|
||||
m_mouseButtons = Qt::NoButton;
|
||||
updateMouseHover();
|
||||
continue;
|
||||
}
|
||||
|
||||
m_mousePosition = input.position;
|
||||
m_mouseInside = room.contains(input.position);
|
||||
updateMouseHover();
|
||||
if (input.kind == MouseInput::Kind::Press || input.kind == MouseInput::Kind::Release)
|
||||
{
|
||||
const bool pressed = input.kind == MouseInput::Kind::Press;
|
||||
if (pressed)
|
||||
m_mouseButtons |= input.button;
|
||||
else
|
||||
m_mouseButtons &= ~Qt::MouseButtons{input.button};
|
||||
if (const auto local = mouseButtonEvent(input.button, pressed, false); local && m_mouseInside)
|
||||
dispatchMouseEvent(*local, input.position, false);
|
||||
if (const auto global = mouseButtonEvent(input.button, pressed, true); global && m_mouseInside)
|
||||
dispatchMouseEvent(*global, input.position, true);
|
||||
}
|
||||
else if (input.kind == MouseInput::Kind::Wheel && m_mouseInside)
|
||||
{
|
||||
m_wheelRemainder += input.wheelDelta;
|
||||
while (m_wheelRemainder >= 120)
|
||||
{
|
||||
dispatchMouseEvent(Object::EventType::MouseWheelUp, input.position, true);
|
||||
m_wheelRemainder -= 120;
|
||||
}
|
||||
while (m_wheelRemainder <= -120)
|
||||
{
|
||||
dispatchMouseEvent(Object::EventType::MouseWheelDown, input.position, true);
|
||||
m_wheelRemainder += 120;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateMouseHover(); // Instances can also move under a stationary cursor.
|
||||
if (!m_mouseInside)
|
||||
return;
|
||||
if (m_mouseButtons == Qt::NoButton)
|
||||
dispatchMouseEvent(Object::EventType::MouseNoButton, m_mousePosition, false);
|
||||
for (Qt::MouseButton button : {Qt::LeftButton, Qt::RightButton, Qt::MiddleButton})
|
||||
{
|
||||
if (!(m_mouseButtons & button))
|
||||
continue;
|
||||
dispatchMouseEvent(*mouseHeldEvent(button, false), m_mousePosition, false);
|
||||
dispatchMouseEvent(*mouseHeldEvent(button, true), m_mousePosition, true);
|
||||
}
|
||||
}
|
||||
|
||||
void GameScene::advanceTo(qint64 elapsedMilliseconds)
|
||||
{
|
||||
const qint64 targetStep = elapsedMilliseconds * roomSpeed / 1000;
|
||||
@@ -284,6 +424,7 @@ void GameScene::advanceTo(qint64 elapsedMilliseconds)
|
||||
break;
|
||||
}
|
||||
}
|
||||
processMouseInput();
|
||||
for (Instance &instance : instances)
|
||||
if (!instance.pendingDestroy)
|
||||
instance.executeEvent(Object::EventType::Step, *this, m_executor);
|
||||
@@ -295,6 +436,7 @@ void GameScene::advanceTo(qint64 elapsedMilliseconds)
|
||||
for (Instance &instance : instances)
|
||||
if (!instance.pendingDestroy)
|
||||
instance.step();
|
||||
updateMouseHover();
|
||||
|
||||
// Detect every pair at its moved position before collision actions can
|
||||
// change either instance. A sprite-size rectangle is our first mask.
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <QRectF>
|
||||
#include <QSize>
|
||||
#include <QString>
|
||||
#include <Qt>
|
||||
|
||||
#include "projectcontainer.h"
|
||||
|
||||
@@ -39,6 +40,7 @@ struct ObjectInstance
|
||||
int depth{};
|
||||
bool visible{true};
|
||||
bool pendingDestroy{};
|
||||
bool mouseOver{};
|
||||
std::array<int, 12> alarms;
|
||||
|
||||
void step();
|
||||
@@ -71,6 +73,11 @@ struct GameScene
|
||||
std::vector<const Instance *> drawOrder() const;
|
||||
void start(const ActionExecutor &executor);
|
||||
void destroyInstance(Instance &instance);
|
||||
void queueMouseMove(QPointF position);
|
||||
void queueMouseButton(QPointF position, Qt::MouseButton button, bool pressed);
|
||||
void queueMouseWheel(QPointF position, int angleDeltaY);
|
||||
void queueMouseLeave();
|
||||
void resetMouseInput();
|
||||
void advanceTo(qint64 elapsedMilliseconds);
|
||||
void draw();
|
||||
|
||||
@@ -82,7 +89,23 @@ struct GameScene
|
||||
std::vector<Instance> instances;
|
||||
|
||||
private:
|
||||
struct MouseInput
|
||||
{
|
||||
enum class Kind { Move, Press, Release, Wheel, Leave, Reset } kind;
|
||||
QPointF position;
|
||||
Qt::MouseButton button{Qt::NoButton};
|
||||
int wheelDelta{};
|
||||
};
|
||||
|
||||
qint64 m_stepsDone{};
|
||||
ActionExecutor m_executor;
|
||||
std::vector<MouseInput> m_mouseInputs;
|
||||
QPointF m_mousePosition;
|
||||
Qt::MouseButtons m_mouseButtons{Qt::NoButton};
|
||||
bool m_mouseInside{};
|
||||
int m_wheelRemainder{};
|
||||
void removeDestroyed();
|
||||
void updateMouseHover();
|
||||
void dispatchMouseEvent(Object::EventType type, QPointF position, bool global);
|
||||
void processMouseInput();
|
||||
};
|
||||
@@ -262,6 +262,53 @@ struct Object
|
||||
BeginStep,
|
||||
EndStep,
|
||||
Draw,
|
||||
MouseLeftButton,
|
||||
MouseRightButton,
|
||||
MouseMiddleButton,
|
||||
MouseNoButton,
|
||||
MouseLeftPressed,
|
||||
MouseRightPressed,
|
||||
MouseMiddlePressed,
|
||||
MouseLeftReleased,
|
||||
MouseRightReleased,
|
||||
MouseMiddleReleased,
|
||||
MouseEnter,
|
||||
MouseLeave,
|
||||
MouseWheelUp,
|
||||
MouseWheelDown,
|
||||
MouseGlobalLeftButton,
|
||||
MouseGlobalRightButton,
|
||||
MouseGlobalMiddleButton,
|
||||
MouseGlobalLeftPressed,
|
||||
MouseGlobalRightPressed,
|
||||
MouseGlobalMiddlePressed,
|
||||
MouseGlobalLeftReleased,
|
||||
MouseGlobalRightReleased,
|
||||
MouseGlobalMiddleReleased,
|
||||
MouseJoystick1Left,
|
||||
MouseJoystick1Right,
|
||||
MouseJoystick1Up,
|
||||
MouseJoystick1Down,
|
||||
MouseJoystick1Button1,
|
||||
MouseJoystick1Button2,
|
||||
MouseJoystick1Button3,
|
||||
MouseJoystick1Button4,
|
||||
MouseJoystick1Button5,
|
||||
MouseJoystick1Button6,
|
||||
MouseJoystick1Button7,
|
||||
MouseJoystick1Button8,
|
||||
MouseJoystick2Left,
|
||||
MouseJoystick2Right,
|
||||
MouseJoystick2Up,
|
||||
MouseJoystick2Down,
|
||||
MouseJoystick2Button1,
|
||||
MouseJoystick2Button2,
|
||||
MouseJoystick2Button3,
|
||||
MouseJoystick2Button4,
|
||||
MouseJoystick2Button5,
|
||||
MouseJoystick2Button6,
|
||||
MouseJoystick2Button7,
|
||||
MouseJoystick2Button8,
|
||||
};
|
||||
|
||||
using events_container_t = std::map<EventType, ActionsContainer>;
|
||||
|
||||
Reference in new issue
Block a user