mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 18:44:00 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into metavoxels
Conflicts: assignment-client/CMakeLists.txt
This commit is contained in:
commit
d19f32fefa
19 changed files with 543 additions and 48 deletions
|
@ -9,11 +9,13 @@ set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
|||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
||||
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5Script REQUIRED)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||
|
||||
qt5_use_modules(${TARGET_NAME} Gui Network Script)
|
||||
qt5_use_modules(${TARGET_NAME} Network Script Widgets)
|
||||
|
||||
# include glm
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
|
|
|
@ -4450,7 +4450,8 @@ void Application::loadScript() {
|
|||
bool wantMenuItems = true; // tells the ScriptEngine object to add menu items for itself
|
||||
|
||||
|
||||
ScriptEngine* scriptEngine = new ScriptEngine(script, wantMenuItems, fileName, Menu::getInstance());
|
||||
ScriptEngine* scriptEngine = new ScriptEngine(script, wantMenuItems, fileName, Menu::getInstance(),
|
||||
&_controllerScriptingInterface);
|
||||
scriptEngine->setupMenuItems();
|
||||
|
||||
// setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so
|
||||
|
|
|
@ -71,6 +71,8 @@
|
|||
#include "ui/LogDialog.h"
|
||||
#include "ParticleTreeRenderer.h"
|
||||
#include "ParticleEditHandle.h"
|
||||
#include "ControllerScriptingInterface.h"
|
||||
|
||||
|
||||
class QAction;
|
||||
class QActionGroup;
|
||||
|
@ -505,7 +507,7 @@ private:
|
|||
|
||||
std::vector<VoxelFade> _voxelFades;
|
||||
std::vector<Avatar*> _avatarFades;
|
||||
|
||||
ControllerScriptingInterface _controllerScriptingInterface;
|
||||
QPointer<LogDialog> _logDialog;
|
||||
};
|
||||
|
||||
|
|
183
interface/src/ControllerScriptingInterface.cpp
Normal file
183
interface/src/ControllerScriptingInterface.cpp
Normal file
|
@ -0,0 +1,183 @@
|
|||
//
|
||||
// ControllerScriptingInterface.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/17/13
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <HandData.h>
|
||||
#include "Application.h"
|
||||
#include "ControllerScriptingInterface.h"
|
||||
|
||||
const PalmData* ControllerScriptingInterface::getPrimaryPalm() const {
|
||||
int leftPalmIndex, rightPalmIndex;
|
||||
|
||||
const HandData* handData = Application::getInstance()->getAvatar()->getHandData();
|
||||
handData->getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex);
|
||||
|
||||
if (rightPalmIndex != -1) {
|
||||
return &handData->getPalms()[rightPalmIndex];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ControllerScriptingInterface::getNumberOfActivePalms() const {
|
||||
const HandData* handData = Application::getInstance()->getAvatar()->getHandData();
|
||||
int numberOfPalms = handData->getNumPalms();
|
||||
int numberOfActivePalms = 0;
|
||||
for (int i = 0; i < numberOfPalms; i++) {
|
||||
if (getPalm(i)->isActive()) {
|
||||
numberOfActivePalms++;
|
||||
}
|
||||
}
|
||||
return numberOfActivePalms;
|
||||
}
|
||||
|
||||
const PalmData* ControllerScriptingInterface::getPalm(int palmIndex) const {
|
||||
const HandData* handData = Application::getInstance()->getAvatar()->getHandData();
|
||||
return &handData->getPalms()[palmIndex];
|
||||
}
|
||||
|
||||
const PalmData* ControllerScriptingInterface::getActivePalm(int palmIndex) const {
|
||||
const HandData* handData = Application::getInstance()->getAvatar()->getHandData();
|
||||
int numberOfPalms = handData->getNumPalms();
|
||||
int numberOfActivePalms = 0;
|
||||
for (int i = 0; i < numberOfPalms; i++) {
|
||||
if (getPalm(i)->isActive()) {
|
||||
if (numberOfActivePalms == palmIndex) {
|
||||
return &handData->getPalms()[i];
|
||||
}
|
||||
numberOfActivePalms++;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ControllerScriptingInterface::isPrimaryButtonPressed() const {
|
||||
const PalmData* primaryPalm = getPrimaryPalm();
|
||||
if (primaryPalm) {
|
||||
if (primaryPalm->getControllerButtons() & BUTTON_FWD) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
glm::vec2 ControllerScriptingInterface::getPrimaryJoystickPosition() const {
|
||||
const PalmData* primaryPalm = getPrimaryPalm();
|
||||
if (primaryPalm) {
|
||||
return glm::vec2(primaryPalm->getJoystickX(), primaryPalm->getJoystickY());
|
||||
}
|
||||
|
||||
return glm::vec2(0);
|
||||
}
|
||||
|
||||
int ControllerScriptingInterface::getNumberOfButtons() const {
|
||||
return getNumberOfActivePalms() * NUMBER_OF_BUTTONS_PER_PALM;
|
||||
}
|
||||
|
||||
bool ControllerScriptingInterface::isButtonPressed(int buttonIndex) const {
|
||||
int palmIndex = buttonIndex / NUMBER_OF_BUTTONS_PER_PALM;
|
||||
int buttonOnPalm = buttonIndex % NUMBER_OF_BUTTONS_PER_PALM;
|
||||
const PalmData* palmData = getActivePalm(palmIndex);
|
||||
if (palmData) {
|
||||
switch (buttonOnPalm) {
|
||||
case 0:
|
||||
return palmData->getControllerButtons() & BUTTON_0;
|
||||
case 1:
|
||||
return palmData->getControllerButtons() & BUTTON_1;
|
||||
case 2:
|
||||
return palmData->getControllerButtons() & BUTTON_2;
|
||||
case 3:
|
||||
return palmData->getControllerButtons() & BUTTON_3;
|
||||
case 4:
|
||||
return palmData->getControllerButtons() & BUTTON_4;
|
||||
case 5:
|
||||
return palmData->getControllerButtons() & BUTTON_FWD;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int ControllerScriptingInterface::getNumberOfTriggers() const {
|
||||
return getNumberOfActivePalms() * NUMBER_OF_TRIGGERS_PER_PALM;
|
||||
}
|
||||
|
||||
float ControllerScriptingInterface::getTriggerValue(int triggerIndex) const {
|
||||
// we know there's one trigger per palm, so the triggerIndex is the palm Index
|
||||
int palmIndex = triggerIndex;
|
||||
const PalmData* palmData = getActivePalm(palmIndex);
|
||||
if (palmData) {
|
||||
return palmData->getTrigger();
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
int ControllerScriptingInterface::getNumberOfJoysticks() const {
|
||||
return getNumberOfActivePalms() * NUMBER_OF_JOYSTICKS_PER_PALM;
|
||||
}
|
||||
|
||||
glm::vec2 ControllerScriptingInterface::getJoystickPosition(int joystickIndex) const {
|
||||
// we know there's one joystick per palm, so the joystickIndex is the palm Index
|
||||
int palmIndex = joystickIndex;
|
||||
const PalmData* palmData = getActivePalm(palmIndex);
|
||||
if (palmData) {
|
||||
return glm::vec2(palmData->getJoystickX(), palmData->getJoystickY());
|
||||
}
|
||||
return glm::vec2(0);
|
||||
}
|
||||
|
||||
int ControllerScriptingInterface::getNumberOfSpatialControls() const {
|
||||
return getNumberOfActivePalms() * NUMBER_OF_SPATIALCONTROLS_PER_PALM;
|
||||
}
|
||||
|
||||
glm::vec3 ControllerScriptingInterface::getSpatialControlPosition(int controlIndex) const {
|
||||
int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM;
|
||||
int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM;
|
||||
const PalmData* palmData = getActivePalm(palmIndex);
|
||||
if (palmData) {
|
||||
switch (controlOfPalm) {
|
||||
case PALM_SPATIALCONTROL:
|
||||
return palmData->getPosition();
|
||||
case TIP_SPATIALCONTROL:
|
||||
return palmData->getTipPosition();
|
||||
}
|
||||
}
|
||||
return glm::vec3(0); // bad index
|
||||
}
|
||||
|
||||
glm::vec3 ControllerScriptingInterface::getSpatialControlVelocity(int controlIndex) const {
|
||||
int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM;
|
||||
int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM;
|
||||
const PalmData* palmData = getActivePalm(palmIndex);
|
||||
if (palmData) {
|
||||
switch (controlOfPalm) {
|
||||
case PALM_SPATIALCONTROL:
|
||||
return palmData->getVelocity();
|
||||
case TIP_SPATIALCONTROL:
|
||||
return palmData->getTipVelocity();
|
||||
}
|
||||
}
|
||||
return glm::vec3(0); // bad index
|
||||
}
|
||||
|
||||
glm::vec3 ControllerScriptingInterface::getSpatialControlNormal(int controlIndex) const {
|
||||
int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM;
|
||||
int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM;
|
||||
const PalmData* palmData = getActivePalm(palmIndex);
|
||||
if (palmData) {
|
||||
switch (controlOfPalm) {
|
||||
case PALM_SPATIALCONTROL:
|
||||
return palmData->getNormal();
|
||||
case TIP_SPATIALCONTROL:
|
||||
return palmData->getNormal(); // currently the tip doesn't have a unique normal, use the palm normal
|
||||
}
|
||||
}
|
||||
return glm::vec3(0); // bad index
|
||||
}
|
||||
|
||||
|
||||
|
52
interface/src/ControllerScriptingInterface.h
Normal file
52
interface/src/ControllerScriptingInterface.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// ControllerScriptingInterface.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/17/13
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __hifi__ControllerScriptingInterface__
|
||||
#define __hifi__ControllerScriptingInterface__
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <AbstractControllerScriptingInterface.h>
|
||||
|
||||
/// handles scripting of input controller commands from JS
|
||||
class ControllerScriptingInterface : public AbstractControllerScriptingInterface {
|
||||
Q_OBJECT
|
||||
|
||||
public slots:
|
||||
virtual bool isPrimaryButtonPressed() const;
|
||||
virtual glm::vec2 getPrimaryJoystickPosition() const;
|
||||
|
||||
virtual int getNumberOfButtons() const;
|
||||
virtual bool isButtonPressed(int buttonIndex) const;
|
||||
|
||||
virtual int getNumberOfTriggers() const;
|
||||
virtual float getTriggerValue(int triggerIndex) const;
|
||||
|
||||
virtual int getNumberOfJoysticks() const;
|
||||
virtual glm::vec2 getJoystickPosition(int joystickIndex) const;
|
||||
|
||||
virtual int getNumberOfSpatialControls() const;
|
||||
virtual glm::vec3 getSpatialControlPosition(int controlIndex) const;
|
||||
virtual glm::vec3 getSpatialControlVelocity(int controlIndex) const;
|
||||
virtual glm::vec3 getSpatialControlNormal(int controlIndex) const;
|
||||
|
||||
private:
|
||||
const PalmData* getPrimaryPalm() const;
|
||||
const PalmData* getPalm(int palmIndex) const;
|
||||
int getNumberOfActivePalms() const;
|
||||
const PalmData* getActivePalm(int palmIndex) const;
|
||||
};
|
||||
|
||||
const int NUMBER_OF_SPATIALCONTROLS_PER_PALM = 2; // the hand and the tip
|
||||
const int NUMBER_OF_JOYSTICKS_PER_PALM = 1;
|
||||
const int NUMBER_OF_TRIGGERS_PER_PALM = 1;
|
||||
const int NUMBER_OF_BUTTONS_PER_PALM = 6;
|
||||
const int PALM_SPATIALCONTROL = 0;
|
||||
const int TIP_SPATIALCONTROL = 1;
|
||||
|
||||
#endif /* defined(__hifi__ControllerScriptingInterface__) */
|
|
@ -690,10 +690,10 @@ void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString&
|
|||
|
||||
QAction* Menu::addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
const QString actionName,
|
||||
const QKEYSEQUENCE& shortcut,
|
||||
const QKeySequence& shortcut,
|
||||
const QObject* receiver,
|
||||
const char* member,
|
||||
QACTION_MENUROLE role) {
|
||||
QAction::MenuRole role) {
|
||||
QAction* action;
|
||||
|
||||
if (receiver && member) {
|
||||
|
@ -702,7 +702,7 @@ QAction* Menu::addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
|||
action = destinationMenu->addAction(actionName);
|
||||
action->setShortcut(shortcut);
|
||||
}
|
||||
action->setMenuRole((QAction::MenuRole)role);
|
||||
action->setMenuRole(role);
|
||||
|
||||
_actionHash.insert(actionName, action);
|
||||
|
||||
|
@ -715,7 +715,7 @@ QAction* Menu::addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu,
|
|||
const bool checked,
|
||||
const QObject* receiver,
|
||||
const char* member) {
|
||||
QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, (QKEYSEQUENCE&)shortcut, receiver, member);
|
||||
QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, shortcut, receiver, member);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(checked);
|
||||
|
||||
|
|
|
@ -76,10 +76,10 @@ public:
|
|||
virtual QMenu* getActiveScriptsMenu() { return _activeScriptsMenu;}
|
||||
virtual QAction* addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
const QString actionName,
|
||||
const QKEYSEQUENCE& shortcut = 0,
|
||||
const QKeySequence& shortcut = 0,
|
||||
const QObject* receiver = NULL,
|
||||
const char* member = NULL,
|
||||
QACTION_MENUROLE role = NO_ROLE);
|
||||
QAction::MenuRole role = QAction::NoRole);
|
||||
virtual void removeAction(QMenu* menu, const QString& actionName);
|
||||
|
||||
public slots:
|
||||
|
|
|
@ -169,6 +169,9 @@ int HandData::decodeRemoteData(unsigned char* sourceBuffer) {
|
|||
palm.setRawNormal(handNormal);
|
||||
palm.setActive(true);
|
||||
|
||||
// For received data, set the sixense controller ID to match the order initialized and sent - 0 Left, 1 Right
|
||||
palm.setSixenseID(handIndex);
|
||||
|
||||
for (unsigned int fingerIndex = 0; fingerIndex < numFingers; ++fingerIndex) {
|
||||
if (fingerIndex < palm.getNumFingers()) {
|
||||
FingerData& finger = palm.getFingers()[fingerIndex];
|
||||
|
|
|
@ -53,9 +53,10 @@ public:
|
|||
glm::vec3 worldPositionToLeapPosition(const glm::vec3& worldPosition) const;
|
||||
glm::vec3 worldVectorToLeapVector(const glm::vec3& worldVector) const;
|
||||
|
||||
std::vector<PalmData>& getPalms() { return _palms; }
|
||||
size_t getNumPalms() { return _palms.size(); }
|
||||
PalmData& addNewPalm();
|
||||
std::vector<PalmData>& getPalms() { return _palms; }
|
||||
const std::vector<PalmData>& getPalms() const { return _palms; }
|
||||
size_t getNumPalms() const { return _palms.size(); }
|
||||
PalmData& addNewPalm();
|
||||
|
||||
/// Finds the indices of the left and right palms according to their locations, or -1 if either or
|
||||
/// both is not found.
|
||||
|
@ -137,17 +138,18 @@ public:
|
|||
|
||||
const glm::vec3& getRawPosition() const { return _rawPosition; }
|
||||
const glm::vec3& getRawNormal() const { return _rawNormal; }
|
||||
bool isActive() const { return _isActive; }
|
||||
int getLeapID() const { return _leapID; }
|
||||
int getSixenseID() const { return _sixenseID; }
|
||||
bool isActive() const { return _isActive; }
|
||||
int getLeapID() const { return _leapID; }
|
||||
int getSixenseID() const { return _sixenseID; }
|
||||
|
||||
|
||||
std::vector<FingerData>& getFingers() { return _fingers; }
|
||||
size_t getNumFingers() { return _fingers.size(); }
|
||||
std::vector<FingerData>& getFingers() { return _fingers; }
|
||||
const std::vector<FingerData>& getFingers() const { return _fingers; }
|
||||
size_t getNumFingers() const { return _fingers.size(); }
|
||||
|
||||
void setActive(bool active) { _isActive = active; }
|
||||
void setLeapID(int id) { _leapID = id; }
|
||||
void setSixenseID(int id) { _sixenseID = id; }
|
||||
void setActive(bool active) { _isActive = active; }
|
||||
void setLeapID(int id) { _leapID = id; }
|
||||
void setSixenseID(int id) { _sixenseID = id; }
|
||||
|
||||
void setRawRotation(const glm::quat rawRotation) { _rawRotation = rawRotation; };
|
||||
glm::quat getRawRotation() const { return _rawRotation; }
|
||||
|
@ -164,27 +166,27 @@ public:
|
|||
const glm::vec3& getTipVelocity() const { return _tipVelocity; }
|
||||
void setTipVelocity(const glm::vec3& velocity) { _tipVelocity = velocity; }
|
||||
|
||||
void incrementFramesWithoutData() { _numFramesWithoutData++; }
|
||||
void resetFramesWithoutData() { _numFramesWithoutData = 0; }
|
||||
int getFramesWithoutData() const { return _numFramesWithoutData; }
|
||||
void incrementFramesWithoutData() { _numFramesWithoutData++; }
|
||||
void resetFramesWithoutData() { _numFramesWithoutData = 0; }
|
||||
int getFramesWithoutData() const { return _numFramesWithoutData; }
|
||||
|
||||
// Controller buttons
|
||||
void setControllerButtons(int controllerButtons) { _controllerButtons = controllerButtons; }
|
||||
void setLastControllerButtons(int controllerButtons) { _lastControllerButtons = controllerButtons; }
|
||||
|
||||
int getControllerButtons() { return _controllerButtons; }
|
||||
int getLastControllerButtons() { return _lastControllerButtons; }
|
||||
int getControllerButtons() const { return _controllerButtons; }
|
||||
int getLastControllerButtons() const { return _lastControllerButtons; }
|
||||
|
||||
void setTrigger(float trigger) { _trigger = trigger; }
|
||||
float getTrigger() { return _trigger; }
|
||||
float getTrigger() const { return _trigger; }
|
||||
void setJoystick(float joystickX, float joystickY) { _joystickX = joystickX; _joystickY = joystickY; }
|
||||
float getJoystickX() { return _joystickX; }
|
||||
float getJoystickY() { return _joystickY; }
|
||||
float getJoystickX() const { return _joystickX; }
|
||||
float getJoystickY() const { return _joystickY; }
|
||||
|
||||
bool getIsCollidingWithVoxel() { return _isCollidingWithVoxel; }
|
||||
bool getIsCollidingWithVoxel() const { return _isCollidingWithVoxel; }
|
||||
void setIsCollidingWithVoxel(bool isCollidingWithVoxel) { _isCollidingWithVoxel = isCollidingWithVoxel; }
|
||||
|
||||
bool getIsCollidingWithPalm() { return _isCollidingWithPalm; }
|
||||
bool getIsCollidingWithPalm() const { return _isCollidingWithPalm; }
|
||||
void setIsCollidingWithPalm(bool isCollidingWithPalm) { _isCollidingWithPalm = isCollidingWithPalm; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -6,18 +6,27 @@
|
|||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QMetaProperty>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "Bitstream.h"
|
||||
|
||||
QHash<QByteArray, const QMetaObject*> Bitstream::_metaObjects;
|
||||
QHash<int, TypeStreamer*> Bitstream::_typeStreamers;
|
||||
|
||||
void Bitstream::registerMetaObject(const QByteArray& name, const QMetaObject* metaObject) {
|
||||
_metaObjects.insert(name, metaObject);
|
||||
}
|
||||
|
||||
Bitstream::Bitstream(QDataStream& underlying)
|
||||
: _underlying(underlying), _byte(0), _position(0) {
|
||||
void Bitstream::registerTypeStreamer(int type, TypeStreamer* streamer) {
|
||||
_typeStreamers.insert(type, streamer);
|
||||
}
|
||||
|
||||
Bitstream::Bitstream(QDataStream& underlying) :
|
||||
_underlying(underlying), _byte(0), _position(0), _classNameStreamer(*this) {
|
||||
}
|
||||
|
||||
const int BITS_IN_BYTE = 8;
|
||||
|
@ -86,9 +95,88 @@ Bitstream& Bitstream::operator>>(bool& value) {
|
|||
}
|
||||
|
||||
Bitstream& Bitstream::operator<<(qint32 value) {
|
||||
return write(&value, 32, 0);
|
||||
return write(&value, 32);
|
||||
}
|
||||
|
||||
Bitstream& Bitstream::operator>>(qint32& value) {
|
||||
return read(&value, 32, 0);
|
||||
return read(&value, 32);
|
||||
}
|
||||
|
||||
Bitstream& Bitstream::operator<<(const QByteArray& string) {
|
||||
*this << (qint32)string.size();
|
||||
return write(string.constData(), string.size() * BITS_IN_BYTE);
|
||||
}
|
||||
|
||||
Bitstream& Bitstream::operator>>(QByteArray& string) {
|
||||
qint32 size;
|
||||
*this >> size;
|
||||
return read(string.data(), size * BITS_IN_BYTE);
|
||||
}
|
||||
|
||||
Bitstream& Bitstream::operator<<(const QString& string) {
|
||||
*this << (qint32)string.size();
|
||||
return write(string.constData(), string.size() * sizeof(QChar) * BITS_IN_BYTE);
|
||||
}
|
||||
|
||||
Bitstream& Bitstream::operator>>(QString& string) {
|
||||
qint32 size;
|
||||
*this >> size;
|
||||
return read(string.data(), size * sizeof(QChar) * BITS_IN_BYTE);
|
||||
}
|
||||
|
||||
Bitstream& Bitstream::operator<<(QObject* object) {
|
||||
const QMetaObject* metaObject = object->metaObject();
|
||||
_classNameStreamer << QByteArray::fromRawData(metaObject->className(), strlen(metaObject->className()));
|
||||
for (int i = 0; i < metaObject->propertyCount(); i++) {
|
||||
QMetaProperty property = metaObject->property(i);
|
||||
if (!property.isStored(object)) {
|
||||
continue;
|
||||
}
|
||||
TypeStreamer* streamer = _typeStreamers.value(property.userType());
|
||||
if (streamer) {
|
||||
streamer->write(*this, property.read(object));
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Bitstream& Bitstream::operator>>(QObject*& object) {
|
||||
QByteArray className;
|
||||
_classNameStreamer >> className;
|
||||
const QMetaObject* metaObject = _metaObjects.value(className);
|
||||
if (metaObject) {
|
||||
object = metaObject->newInstance();
|
||||
for (int i = 0; i < metaObject->propertyCount(); i++) {
|
||||
QMetaProperty property = metaObject->property(i);
|
||||
if (!property.isStored(object)) {
|
||||
continue;
|
||||
}
|
||||
TypeStreamer* streamer = _typeStreamers.value(property.userType());
|
||||
if (streamer) {
|
||||
property.write(object, streamer->read(*this));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Unknown class name: " << className << "\n";
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
IDStreamer::IDStreamer(Bitstream& stream) :
|
||||
_stream(stream),
|
||||
_bits(1) {
|
||||
}
|
||||
|
||||
IDStreamer& IDStreamer::operator<<(int value) {
|
||||
_stream.write(&value, _bits);
|
||||
if (value == (1 << _bits) - 1) {
|
||||
_bits++;
|
||||
}
|
||||
}
|
||||
|
||||
IDStreamer& IDStreamer::operator>>(int& value) {
|
||||
_stream.read(&value, _bits);
|
||||
if (value == (1 << _bits) - 1) {
|
||||
_bits++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,77 @@
|
|||
#define __interface__Bitstream__
|
||||
|
||||
#include <QHash>
|
||||
#include <QtGlobal>
|
||||
#include <QVariant>
|
||||
|
||||
class QByteArray;
|
||||
class QDataStream;
|
||||
class QMetaObject;
|
||||
class QObject;
|
||||
|
||||
class Bitstream;
|
||||
class TypeStreamer;
|
||||
|
||||
/// Streams integer identifiers that conform to the following pattern: each ID encountered in the stream is either one that
|
||||
/// has been sent (received) before, or is one more than the highest previously encountered ID (starting at zero). This allows
|
||||
/// us to use the minimum number of bits to encode the IDs.
|
||||
class IDStreamer {
|
||||
public:
|
||||
|
||||
IDStreamer(Bitstream& stream);
|
||||
|
||||
IDStreamer& operator<<(int value);
|
||||
IDStreamer& operator>>(int& value);
|
||||
|
||||
private:
|
||||
|
||||
Bitstream& _stream;
|
||||
int _bits;
|
||||
};
|
||||
|
||||
/// Provides a means to stream repeated values efficiently. The value is first streamed along with a unique ID. When
|
||||
/// subsequently streamed, only the ID is sent.
|
||||
template<class T> class RepeatedValueStreamer {
|
||||
public:
|
||||
|
||||
RepeatedValueStreamer(Bitstream& stream) : _stream(stream), _idStreamer(stream), _lastNewID(0) { }
|
||||
|
||||
RepeatedValueStreamer& operator<<(T value);
|
||||
RepeatedValueStreamer& operator>>(T& value);
|
||||
|
||||
private:
|
||||
|
||||
Bitstream& _stream;
|
||||
IDStreamer _idStreamer;
|
||||
int _lastNewID;
|
||||
QHash<T, int> _ids;
|
||||
QHash<int, T> _values;
|
||||
};
|
||||
|
||||
template<class T> inline RepeatedValueStreamer<T>& RepeatedValueStreamer<T>::operator<<(T value) {
|
||||
int& id = _ids[value];
|
||||
if (id == 0) {
|
||||
_idStreamer << (id = ++_lastNewID);
|
||||
_stream << value;
|
||||
|
||||
} else {
|
||||
_idStreamer << id;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T> inline RepeatedValueStreamer<T>& RepeatedValueStreamer<T>::operator>>(T& value) {
|
||||
int id;
|
||||
_idStreamer >> id;
|
||||
typename QHash<int, T>::iterator it = _values.find(id);
|
||||
if (it == _values.end()) {
|
||||
_stream >> value;
|
||||
_values.insert(id, value);
|
||||
|
||||
} else {
|
||||
value = *it;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// A stream for bit-aligned data.
|
||||
class Bitstream {
|
||||
|
@ -23,6 +89,10 @@ public:
|
|||
/// Registers a metaobject under its name so that instances of it can be streamed.
|
||||
static void registerMetaObject(const QByteArray& name, const QMetaObject* metaObject);
|
||||
|
||||
/// Registers a streamer for the specified Qt-registered type.
|
||||
static void registerTypeStreamer(int type, TypeStreamer* streamer);
|
||||
|
||||
/// Creates a new bitstream. Note: the stream may be used for reading or writing, but not both.
|
||||
Bitstream(QDataStream& underlying);
|
||||
|
||||
/// Writes a set of bits to the underlying stream.
|
||||
|
@ -44,15 +114,41 @@ public:
|
|||
Bitstream& operator<<(qint32 value);
|
||||
Bitstream& operator>>(qint32& value);
|
||||
|
||||
Bitstream& operator<<(const QByteArray& string);
|
||||
Bitstream& operator>>(QByteArray& string);
|
||||
|
||||
Bitstream& operator<<(const QString& string);
|
||||
Bitstream& operator>>(QString& string);
|
||||
|
||||
Bitstream& operator<<(QObject* object);
|
||||
Bitstream& operator>>(QObject*& object);
|
||||
|
||||
private:
|
||||
|
||||
QDataStream& _underlying;
|
||||
quint8 _byte;
|
||||
int _position;
|
||||
|
||||
|
||||
RepeatedValueStreamer<QByteArray> _classNameStreamer;
|
||||
|
||||
static QHash<QByteArray, const QMetaObject*> _metaObjects;
|
||||
static QHash<int, TypeStreamer*> _typeStreamers;
|
||||
};
|
||||
|
||||
/// Interface for objects that can write values to and read values from bitstreams.
|
||||
class TypeStreamer {
|
||||
public:
|
||||
|
||||
virtual void write(Bitstream& out, const QVariant& value) const = 0;
|
||||
virtual QVariant read(Bitstream& in) const = 0;
|
||||
};
|
||||
|
||||
/// A streamer that works with Bitstream's operators.
|
||||
template<class T> class SimpleTypeStreamer {
|
||||
public:
|
||||
|
||||
virtual void write(Bitstream& out, const QVariant& value) const { out << value.value<T>(); }
|
||||
virtual QVariant read(Bitstream& in) const { T value; in >> value; return QVariant::fromValue(value); }
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__Bitstream__) */
|
||||
|
|
|
@ -75,6 +75,7 @@ void MetavoxelData::read(Bitstream& in) {
|
|||
void MetavoxelData::write(Bitstream& out) const {
|
||||
out << (qint32)_roots.size();
|
||||
for (QHash<AttributePointer, MetavoxelNode*>::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) {
|
||||
|
||||
it.value()->write(it.key(), out);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// AbstractControllerScriptingInterface.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/17/13
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __hifi__AbstractControllerScriptingInterface__
|
||||
#define __hifi__AbstractControllerScriptingInterface__
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
/// handles scripting of input controller commands from JS
|
||||
class AbstractControllerScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public slots:
|
||||
virtual bool isPrimaryButtonPressed() const = 0;
|
||||
virtual glm::vec2 getPrimaryJoystickPosition() const = 0;
|
||||
|
||||
virtual int getNumberOfButtons() const = 0;
|
||||
virtual bool isButtonPressed(int buttonIndex) const = 0;
|
||||
|
||||
virtual int getNumberOfTriggers() const = 0;
|
||||
virtual float getTriggerValue(int triggerIndex) const = 0;
|
||||
|
||||
virtual int getNumberOfJoysticks() const = 0;
|
||||
virtual glm::vec2 getJoystickPosition(int joystickIndex) const = 0;
|
||||
|
||||
virtual int getNumberOfSpatialControls() const = 0;
|
||||
virtual glm::vec3 getSpatialControlPosition(int controlIndex) const = 0;
|
||||
virtual glm::vec3 getSpatialControlVelocity(int controlIndex) const = 0;
|
||||
virtual glm::vec3 getSpatialControlNormal(int controlIndex) const = 0;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__AbstractControllerScriptingInterface__) */
|
|
@ -25,7 +25,8 @@
|
|||
int ScriptEngine::_scriptNumber = 1;
|
||||
|
||||
ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems,
|
||||
const char* scriptMenuName, AbstractMenuInterface* menu) {
|
||||
const char* scriptMenuName, AbstractMenuInterface* menu,
|
||||
AbstractControllerScriptingInterface* controllerScriptingInterface) {
|
||||
_scriptContents = scriptContents;
|
||||
_isFinished = false;
|
||||
_isRunning = false;
|
||||
|
@ -41,6 +42,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems,
|
|||
_scriptMenuName.append(_scriptNumber);
|
||||
}
|
||||
_menu = menu;
|
||||
_controllerScriptingInterface = controllerScriptingInterface;
|
||||
}
|
||||
|
||||
ScriptEngine::~ScriptEngine() {
|
||||
|
@ -87,6 +89,11 @@ void ScriptEngine::run() {
|
|||
QScriptValue particleScripterValue = engine.newQObject(&_particleScriptingInterface);
|
||||
engine.globalObject().setProperty("Particles", particleScripterValue);
|
||||
|
||||
if (_controllerScriptingInterface) {
|
||||
QScriptValue controllerScripterValue = engine.newQObject(_controllerScriptingInterface);
|
||||
engine.globalObject().setProperty("Controller", controllerScripterValue);
|
||||
}
|
||||
|
||||
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE));
|
||||
engine.globalObject().setProperty("TREE_SCALE", treeScaleValue);
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <AbstractMenuInterface.h>
|
||||
#include <ParticleScriptingInterface.h>
|
||||
#include <VoxelScriptingInterface.h>
|
||||
#include "AbstractControllerScriptingInterface.h"
|
||||
|
||||
const QString NO_SCRIPT("");
|
||||
|
||||
|
@ -25,7 +26,8 @@ class ScriptEngine : public QObject {
|
|||
Q_OBJECT
|
||||
public:
|
||||
ScriptEngine(const QString& scriptContents = NO_SCRIPT, bool wantMenuItems = false,
|
||||
const char* scriptMenuName = NULL, AbstractMenuInterface* menu = NULL);
|
||||
const char* scriptMenuName = NULL, AbstractMenuInterface* menu = NULL,
|
||||
AbstractControllerScriptingInterface* controllerScriptingInterface = NULL);
|
||||
|
||||
~ScriptEngine();
|
||||
|
||||
|
@ -58,6 +60,7 @@ protected:
|
|||
private:
|
||||
VoxelScriptingInterface _voxelScriptingInterface;
|
||||
ParticleScriptingInterface _particleScriptingInterface;
|
||||
AbstractControllerScriptingInterface* _controllerScriptingInterface;
|
||||
bool _wantMenuItems;
|
||||
QString _scriptMenuName;
|
||||
AbstractMenuInterface* _menu;
|
||||
|
|
|
@ -7,11 +7,12 @@ set(TARGET_NAME shared)
|
|||
project(${TARGET_NAME})
|
||||
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
|
||||
setup_hifi_library(${TARGET_NAME})
|
||||
|
||||
qt5_use_modules(${TARGET_NAME} Network)
|
||||
qt5_use_modules(${TARGET_NAME} Network Widgets)
|
||||
|
||||
# include GLM
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
|
|
|
@ -10,27 +10,23 @@
|
|||
#ifndef __hifi__AbstractMenuInterface__
|
||||
#define __hifi__AbstractMenuInterface__
|
||||
|
||||
#include <QAction>
|
||||
|
||||
class QMenu;
|
||||
class QString;
|
||||
class QObject;
|
||||
class QKeySequence;
|
||||
class QAction;
|
||||
|
||||
// these are actually class scoped enums, but we don't want to depend on the class for this abstract interface
|
||||
const int NO_ROLE = 0;
|
||||
typedef int QACTION_MENUROLE;
|
||||
typedef int QKEYSEQUENCE;
|
||||
|
||||
class AbstractMenuInterface {
|
||||
public:
|
||||
virtual QMenu* getActiveScriptsMenu() = 0;
|
||||
virtual QAction* addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
const QString actionName,
|
||||
const QKEYSEQUENCE& shortcut = 0,
|
||||
const QKeySequence& shortcut = 0,
|
||||
const QObject* receiver = NULL,
|
||||
const char* member = NULL,
|
||||
QACTION_MENUROLE role = NO_ROLE) = 0;
|
||||
QAction::MenuRole role = QAction::NoRole) = 0;
|
||||
virtual void removeAction(QMenu* menu, const QString& actionName) = 0;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__AbstractMenuInterface__) */
|
||||
#endif /* defined(__hifi__AbstractMenuInterface__) */
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
void registerMetaTypes(QScriptEngine* engine) {
|
||||
qScriptRegisterMetaType(engine, vec3toScriptValue, vec3FromScriptValue);
|
||||
qScriptRegisterMetaType(engine, vec2toScriptValue, vec2FromScriptValue);
|
||||
qScriptRegisterMetaType(engine, xColorToScriptValue, xColorFromScriptValue);
|
||||
}
|
||||
|
||||
|
@ -29,6 +30,19 @@ void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3) {
|
|||
vec3.z = object.property("z").toVariant().toFloat();
|
||||
}
|
||||
|
||||
QScriptValue vec2toScriptValue(QScriptEngine* engine, const glm::vec2 &vec2) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
obj.setProperty("x", vec2.x);
|
||||
obj.setProperty("y", vec2.y);
|
||||
return obj;
|
||||
}
|
||||
|
||||
void vec2FromScriptValue(const QScriptValue &object, glm::vec2 &vec2) {
|
||||
vec2.x = object.property("x").toVariant().toFloat();
|
||||
vec2.y = object.property("y").toVariant().toFloat();
|
||||
}
|
||||
|
||||
|
||||
QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
obj.setProperty("red", color.red);
|
||||
|
|
|
@ -17,11 +17,17 @@
|
|||
#include "SharedUtil.h"
|
||||
|
||||
Q_DECLARE_METATYPE(glm::vec3)
|
||||
Q_DECLARE_METATYPE(glm::vec2)
|
||||
Q_DECLARE_METATYPE(xColor)
|
||||
|
||||
void registerMetaTypes(QScriptEngine* engine);
|
||||
|
||||
QScriptValue vec3toScriptValue(QScriptEngine* engine, const glm::vec3 &vec3);
|
||||
void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3);
|
||||
|
||||
QScriptValue vec2toScriptValue(QScriptEngine* engine, const glm::vec2 &vec2);
|
||||
void vec2FromScriptValue(const QScriptValue &object, glm::vec2 &vec2);
|
||||
|
||||
QScriptValue xColorToScriptValue(QScriptEngine* engine, const xColor& color);
|
||||
void xColorFromScriptValue(const QScriptValue &object, xColor& color);
|
||||
|
||||
|
|
Loading…
Reference in a new issue