// // PointerEvent.cpp // script-engine/src // // Created by Anthony Thibault on 2016-8-11. // Copyright 2016 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "PointerEvent.h" #include #include #include "RegisteredMetaTypes.h" static bool areFlagsSet(uint32_t flags, uint32_t mask) { return (flags & mask) != 0; } PointerEvent::PointerEvent(EventType type, uint32_t id) : _type(type), _id(id) { } PointerEvent::PointerEvent(EventType type, uint32_t id, const glm::vec2& pos2D, Button button, uint32_t buttons, Qt::KeyboardModifiers keyboardModifiers) : _type(type), _id(id), _pos2D(pos2D), _button(button), _buttons(buttons), _keyboardModifiers(keyboardModifiers) { } PointerEvent::PointerEvent(const glm::vec2& pos2D, const glm::vec3& pos3D, const glm::vec3& normal, const glm::vec3& direction) : _pos2D(pos2D), _pos3D(pos3D), _normal(normal), _direction(direction) { } PointerEvent::PointerEvent(EventType type, uint32_t id, const glm::vec2& pos2D, const glm::vec3& pos3D, const glm::vec3& normal, const glm::vec3& direction, Button button, uint32_t buttons, Qt::KeyboardModifiers keyboardModifiers) : _type(type), _id(id), _pos2D(pos2D), _pos3D(pos3D), _normal(normal), _direction(direction), _button(button), _buttons(buttons), _keyboardModifiers(keyboardModifiers) { } void PointerEvent::setButton(Button button) { _button = button; _buttons |= button; } /**jsdoc * A PointerEvent defines a 2D or 3D mouse or similar pointer event. * @typedef {object} PointerEvent * @property {string} type - The type of event: "Press", "DoublePress", "Release", or * "Move". * @property {number} id - Integer number used to identify the pointer: 0 = hardware mouse, 1 = left * controller, 2 = right controller. * @property {Vec2} pos2D - The 2D position of the event on the intersected overlay or entity XY plane. * @property {Vec3} pos3D - The 3D position of the event on the intersected overlay or entity. * @property {Vec3} normal - The surface normal at the intersection point. * @property {Vec3} direction - The direction of the intersection ray. * @property {string} button - The name of the button pressed: None, Primary, Secondary, * or Tertiary. * @property {boolean} isPrimaryButton - true if the button pressed was the primary button, otherwise * undefined; * @property {boolean} isLeftButton - true if the button pressed was the primary button, otherwise * undefined; * @property {boolean} isSecondaryButton - true if the button pressed was the secondary button, otherwise * undefined; * @property {boolean} isRightButton - true if the button pressed was the secondary button, otherwise * undefined; * @property {boolean} isTertiaryButton - true if the button pressed was the tertiary button, otherwise * undefined; * @property {boolean} isMiddleButton - true if the button pressed was the tertiary button, otherwise * undefined; * @property {boolean} isPrimaryHeld - true if the primary button is currently being pressed, otherwise * false * @property {boolean} isSecondaryHeld - true if the secondary button is currently being pressed, otherwise * false * @property {boolean} isTertiaryHeld - true if the tertiary button is currently being pressed, otherwise * false * @property {KeyboardModifiers} keyboardModifiers - Integer value being and with bits set according to which keyboard modifier * keys are were pressed when the event was generated. */ /**jsdoc *

A KeyboardModifiers value is used to specify which modifier keys on the keyboard are pressed. The value is the sum * (bitwise OR) of the relevant combination of values from the following table:

* * * * * * * * * * * * * * * * * * *
KeyHexadecimal valueDecimal valueDescription
Shift0x0200000033554432A Shift key on the keyboard is pressed.
Control0x0400000067108864A Control key on the keyboard is pressed.
Alt0x08000000134217728An Alt key on the keyboard is pressed.
Meta0x10000000268435456A Meta or Windows key on the keyboard is pressed.
Keypad0x20000000536870912A keypad button is pressed.
Group0x400000001073741824X11 operating system only: An AltGr / Mode_switch key on the keyboard is pressed.
* @typedef {number} KeyboardModifiers */ QScriptValue PointerEvent::toScriptValue(QScriptEngine* engine, const PointerEvent& event) { QScriptValue obj = engine->newObject(); switch (event._type) { case Press: obj.setProperty("type", "Press"); break; case DoublePress: obj.setProperty("type", "DoublePress"); break; case Release: obj.setProperty("type", "Release"); break; default: case Move: obj.setProperty("type", "Move"); break; }; obj.setProperty("id", event._id); QScriptValue pos2D = engine->newObject(); pos2D.setProperty("x", event._pos2D.x); pos2D.setProperty("y", event._pos2D.y); obj.setProperty("pos2D", pos2D); QScriptValue pos3D = engine->newObject(); pos3D.setProperty("x", event._pos3D.x); pos3D.setProperty("y", event._pos3D.y); pos3D.setProperty("z", event._pos3D.z); obj.setProperty("pos3D", pos3D); QScriptValue normal = engine->newObject(); normal.setProperty("x", event._normal.x); normal.setProperty("y", event._normal.y); normal.setProperty("z", event._normal.z); obj.setProperty("normal", normal); QScriptValue direction = engine->newObject(); direction.setProperty("x", event._direction.x); direction.setProperty("y", event._direction.y); direction.setProperty("z", event._direction.z); obj.setProperty("direction", direction); bool isPrimaryButton = false; bool isSecondaryButton = false; bool isTertiaryButton = false; switch (event._button) { case NoButtons: obj.setProperty("button", "None"); break; case PrimaryButton: obj.setProperty("button", "Primary"); isPrimaryButton = true; break; case SecondaryButton: obj.setProperty("button", "Secondary"); isSecondaryButton = true; break; case TertiaryButton: obj.setProperty("button", "Tertiary"); isTertiaryButton = true; break; } if (isPrimaryButton) { obj.setProperty("isPrimaryButton", isPrimaryButton); obj.setProperty("isLeftButton", isPrimaryButton); } if (isSecondaryButton) { obj.setProperty("isSecondaryButton", isSecondaryButton); obj.setProperty("isRightButton", isSecondaryButton); } if (isTertiaryButton) { obj.setProperty("isTertiaryButton", isTertiaryButton); obj.setProperty("isMiddleButton", isTertiaryButton); } obj.setProperty("isPrimaryHeld", areFlagsSet(event._buttons, PrimaryButton)); obj.setProperty("isSecondaryHeld", areFlagsSet(event._buttons, SecondaryButton)); obj.setProperty("isTertiaryHeld", areFlagsSet(event._buttons, TertiaryButton)); obj.setProperty("keyboardModifiers", QScriptValue(event.getKeyboardModifiers())); return obj; } void PointerEvent::fromScriptValue(const QScriptValue& object, PointerEvent& event) { if (object.isObject()) { QScriptValue type = object.property("type"); QString typeStr = type.isString() ? type.toString() : "Move"; if (typeStr == "Press") { event._type = Press; } else if (typeStr == "DoublePress") { event._type = DoublePress; } else if (typeStr == "Release") { event._type = Release; } else { event._type = Move; } QScriptValue id = object.property("id"); event._id = id.isNumber() ? (uint32_t)id.toNumber() : 0; glm::vec2 pos2D; vec2FromScriptValue(object.property("pos2D"), event._pos2D); glm::vec3 pos3D; vec3FromScriptValue(object.property("pos3D"), event._pos3D); glm::vec3 normal; vec3FromScriptValue(object.property("normal"), event._normal); glm::vec3 direction; vec3FromScriptValue(object.property("direction"), event._direction); QScriptValue button = object.property("button"); QString buttonStr = type.isString() ? button.toString() : "NoButtons"; if (buttonStr == "Primary") { event._button = PrimaryButton; } else if (buttonStr == "Secondary") { event._button = SecondaryButton; } else if (buttonStr == "Tertiary") { event._button = TertiaryButton; } else { event._button = NoButtons; } bool primary = object.property("isPrimaryHeld").toBool(); bool secondary = object.property("isSecondaryHeld").toBool(); bool tertiary = object.property("isTertiaryHeld").toBool(); event._buttons = 0; if (primary) { event._buttons |= PrimaryButton; } if (secondary) { event._buttons |= SecondaryButton; } if (tertiary) { event._buttons |= TertiaryButton; } event._keyboardModifiers = (Qt::KeyboardModifiers)(object.property("keyboardModifiers").toUInt32()); } } static const char* typeToStringMap[PointerEvent::NumEventTypes] = { "Press", "DoublePress", "Release", "Move" }; static const char* buttonsToStringMap[8] = { "NoButtons", "PrimaryButton", "SecondaryButton", "PrimaryButton | SecondaryButton", "TertiaryButton", "PrimaryButton | TertiaryButton", "SecondaryButton | TertiaryButton", "PrimaryButton | SecondaryButton | TertiaryButton", }; QDebug& operator<<(QDebug& dbg, const PointerEvent& p) { dbg.nospace() << "PointerEvent, type = " << typeToStringMap[p.getType()] << ", id = " << p.getID(); dbg.nospace() << ", pos2D = (" << p.getPos2D().x << ", " << p.getPos2D().y; dbg.nospace() << "), pos3D = (" << p.getPos3D().x << ", " << p.getPos3D().y << ", " << p.getPos3D().z; dbg.nospace() << "), normal = (" << p.getNormal().x << ", " << p.getNormal().y << ", " << p.getNormal().z; dbg.nospace() << "), dir = (" << p.getDirection().x << ", " << p.getDirection().y << ", " << p.getDirection().z; dbg.nospace() << "), button = " << buttonsToStringMap[p.getButton()] << " " << (int)p.getButton(); dbg.nospace() << ", buttons = " << buttonsToStringMap[p.getButtons()]; return dbg; }