Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mouse wheel event injection from script engine #1067

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions interface/src/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7516,6 +7516,10 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer
return statsMessageLength;
}

void Application::postEventToOverlayUI(QEvent *event) {
QCoreApplication::postEvent(getPrimaryWidget(), event);
}

void Application::registerScriptEngineWithApplicationServices(ScriptManagerPointer& scriptManager) {

auto scriptEngine = scriptManager->engine();
Expand Down
3 changes: 3 additions & 0 deletions interface/src/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <AvatarHashMap.h>
#include <ThreadHelpers.h>
#include <AbstractScriptingServicesInterface.h>
#include <controllers/AbstractInputEventInterface.h>
#include <AbstractViewStateInterface.h>
#include <EntityEditPacketSender.h>
#include <EntityTreeRenderer.h>
Expand Down Expand Up @@ -112,6 +113,7 @@ class Application;
#define qApp (static_cast<Application*>(QCoreApplication::instance()))

class Application : public QApplication,
public AbstractInputEventInterface,
public AbstractViewStateInterface,
public AbstractScriptingServicesInterface,
public AbstractUriHandler,
Expand Down Expand Up @@ -277,6 +279,7 @@ class Application : public QApplication,
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }

virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; }
void postEventToOverlayUI(QEvent *event) override;
virtual void registerScriptEngineWithApplicationServices(ScriptManagerPointer& scriptManager) override;

virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const override { copyDisplayViewFrustum(viewOut); }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// AbstractInputEventInterface.h
// libraries/controllers/src/controllers
//
// Created by dr Karol Suprynowicz on 2024.07.04.
// Copyright 2023 Overte e.V.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Copyright 2023 Overte e.V.
// Copyright 2024 Overte e.V.

//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//

#ifndef overte_AbstractInputEventInterface_h
#define overte_AbstractInputEventInterface_h

#include <QEvent>

/// Used by the libraries to post events into overlay UI.
class AbstractInputEventInterface {
public:
virtual void postEventToOverlayUI(QEvent *event) = 0;
};

#endif // overte_AbstractInputEventInterface_h
24 changes: 24 additions & 0 deletions libraries/controllers/src/controllers/ScriptingInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <QEventLoop>
#include <QThread>
#include <QWheelEvent>

#include <GLMHelpers.h>
#include <DependencyManager.h>
Expand All @@ -32,6 +33,8 @@
#include <ScriptManager.h>
#include <ScriptValue.h>

#include "AbstractInputEventInterface.h"


ScriptValue inputControllerToScriptValue(ScriptEngine* engine, controller::InputController* const& in) {
return engine->newQObject(in, ScriptEngine::QtOwnership);
Expand Down Expand Up @@ -214,6 +217,27 @@ namespace controller {
return DependencyManager::get<UserInputMapper>()->triggerHapticPulseOnDevice(device, strength, SHORT_HAPTIC_DURATION_MS, index);
}

void ScriptingInterface::emitMouseWheelEvent(glm::vec2 position, glm::vec2 globalPosition, glm::vec2 angleDelta, bool sendToHUDUI) {
auto wheelEvent = new QWheelEvent(QPointF(position.x, position.y),
QPointF(globalPosition.x, globalPosition.y),
QPoint(0,0),
QPoint((int)(angleDelta.x), (int)(angleDelta.y)),
Qt::NoButton,
Qt::NoModifier, Qt::NoScrollPhase,
false);
if (sendToHUDUI) {
auto abstractViewStateInterface = dynamic_cast<AbstractInputEventInterface*>(QCoreApplication::instance());
if (abstractViewStateInterface) {
abstractViewStateInterface->postEventToOverlayUI(wheelEvent);
} else {
// This should never happen.
Q_ASSERT(false);
}
} else {
QCoreApplication::postEvent(QCoreApplication::instance(), wheelEvent);
}
}

void ScriptingInterface::updateMaps() {
QVariantMap newHardware;
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
Expand Down
16 changes: 16 additions & 0 deletions libraries/controllers/src/controllers/ScriptingInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,22 @@ namespace controller {
*/
Q_INVOKABLE bool triggerShortHapticPulseOnDevice(unsigned int device, float strength, uint16_t index = 2) const;

/*@jsdoc
* Emits a mouse wheel scroll event.
* @function Controller.emitMouseWheelEvent
* @param {Vec2} position - Event position relative to the UI element.
* @param {Vec2} globalPosition - Global position of the event.
* @param {Vec2} delta - Amount to scroll horizontally and vertically.
* @param {boolean} sendToHUDUI - If <code>true</code>, the event will be sent to HUD UI first, and only if it
* is not used there it will go to other UI elements. If <code>false</code> the mouse wheel event will skip HUD UI.
* @example <caption>Emit a sideways scroll event every 1 second.</caption>
* Script.setInterval(function () {
* Controller.emitMouseWheelEvent({x:50,y:50}, {x:50,y:50}, {x:50,y:50}, true);
* print("Wheel event emitted.");
* }, 1000);
*/
Q_INVOKABLE void emitMouseWheelEvent(glm::vec2 position, glm::vec2 globalPosition, glm::vec2 delta, bool sendToHUDUI);

/*@jsdoc
* Creates a new controller mapping. Routes can then be added to the mapping using {@link MappingObject} methods and
* routed to <code>Standard</code> controls, <code>Actions</code>, or script functions using {@link RouteObject}
Expand Down
Loading