mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 18:44:00 +02:00
Merge remote-tracking branch 'upstream/master' into slaps
This commit is contained in:
commit
be27f36a7e
31 changed files with 699 additions and 170 deletions
|
@ -24,6 +24,8 @@
|
|||
Agent::Agent(const unsigned char* dataBuffer, int numBytes) :
|
||||
ThreadedAssignment(dataBuffer, numBytes)
|
||||
{
|
||||
_particleScriptingInterface.init();
|
||||
_voxelScriptingInterface.init();
|
||||
}
|
||||
|
||||
void Agent::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) {
|
||||
|
|
|
@ -17,6 +17,14 @@ set(OPENCV_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/OpenCV)
|
|||
set(SIXENSE_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/Sixense)
|
||||
set(UVCCAMERACONTROL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/UVCCameraControl)
|
||||
|
||||
if (DEFINED ENV{JOB_ID})
|
||||
set(BUILD_SEQ $ENV{JOB_ID})
|
||||
else ()
|
||||
set(BUILD_SEQ "0")
|
||||
endif ()
|
||||
|
||||
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} $ENV{QT_CMAKE_PREFIX_PATH})
|
||||
|
||||
if (APPLE)
|
||||
set(GL_HEADERS "#include <GLUT/glut.h>\n#include <OpenGL/glext.h>")
|
||||
else (APPLE)
|
||||
|
@ -35,6 +43,7 @@ include_glm(${TARGET_NAME} ${ROOT_DIR})
|
|||
|
||||
# create the InterfaceConfig.h file based on GL_HEADERS above
|
||||
configure_file(InterfaceConfig.h.in ${PROJECT_BINARY_DIR}/includes/InterfaceConfig.h)
|
||||
configure_file(InterfaceVersion.h.in ${PROJECT_BINARY_DIR}/includes/InterfaceVersion.h)
|
||||
|
||||
# grab the implementation and header files from src dirs
|
||||
file(GLOB INTERFACE_SRCS src/*.cpp src/*.h)
|
||||
|
@ -87,6 +96,7 @@ link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
|
|||
link_hifi_library(particles ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(scriptengine ${TARGET_NAME} ${ROOT_DIR})
|
||||
|
||||
# find required libraries
|
||||
find_package(Faceshift)
|
||||
|
|
|
@ -12,5 +12,4 @@
|
|||
#define GL_GLEXT_PROTOTYPES 1
|
||||
@GL_HEADERS@
|
||||
|
||||
|
||||
#endif
|
||||
|
|
9
interface/InterfaceVersion.h.in
Normal file
9
interface/InterfaceVersion.h.in
Normal file
|
@ -0,0 +1,9 @@
|
|||
//
|
||||
// InterfaceVersion.h
|
||||
// Declaration of version and build data
|
||||
//
|
||||
// Created by Leonardo Murillo on 12/16/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc.. All rights reserved.
|
||||
//
|
||||
|
||||
const int BUILD_VERSION = @BUILD_SEQ@;
|
|
@ -49,6 +49,7 @@
|
|||
|
||||
#include "Application.h"
|
||||
#include "DataServerClient.h"
|
||||
#include "InterfaceVersion.h"
|
||||
#include "LogDisplay.h"
|
||||
#include "Menu.h"
|
||||
#include "Swatch.h"
|
||||
|
@ -144,6 +145,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
_applicationStartupTime = startup_time;
|
||||
_window->setWindowTitle("Interface");
|
||||
|
||||
qDebug( "[VERSION] Build sequence: %i", BUILD_VERSION);
|
||||
|
||||
qInstallMessageHandler(messageHandler);
|
||||
|
||||
unsigned int listenPort = 0; // bind to an ephemeral port by default
|
||||
|
@ -215,9 +218,11 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes()));
|
||||
silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000);
|
||||
|
||||
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||
|
||||
_networkAccessManager = new QNetworkAccessManager(this);
|
||||
QNetworkDiskCache* cache = new QNetworkDiskCache(_networkAccessManager);
|
||||
cache->setCacheDirectory("interfaceCache");
|
||||
cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "interfaceCache");
|
||||
_networkAccessManager->setCache(cache);
|
||||
|
||||
_window->setCentralWidget(_glWidget);
|
||||
|
@ -261,7 +266,7 @@ Application::~Application() {
|
|||
_sharedVoxelSystem.changeTree(new VoxelTree);
|
||||
|
||||
VoxelTreeElement::removeDeleteHook(&_voxels); // we don't need to do this processing on shutdown
|
||||
delete Menu::getInstance();
|
||||
Menu::getInstance()->deleteLater();
|
||||
|
||||
delete _settings;
|
||||
delete _followMode;
|
||||
|
@ -1396,6 +1401,7 @@ void Application::terminate() {
|
|||
pthread_join(_networkReceiveThread, NULL);
|
||||
}
|
||||
|
||||
printf("");
|
||||
_voxelProcessor.terminate();
|
||||
_voxelHideShowThread.terminate();
|
||||
_voxelEditSender.terminate();
|
||||
|
@ -4103,12 +4109,14 @@ void Application::attachNewHeadToNode(Node* newNode) {
|
|||
|
||||
void Application::updateWindowTitle(){
|
||||
QString title = "";
|
||||
QString buildVersion = " (build " + QString::number(BUILD_VERSION) + ")";
|
||||
QString username = _profile.getUsername();
|
||||
if(!username.isEmpty()){
|
||||
title += _profile.getUsername();
|
||||
title += " @ ";
|
||||
}
|
||||
title += _profile.getLastDomain();
|
||||
title += buildVersion;
|
||||
|
||||
qDebug("Application title set to: %s.\n", title.toStdString().c_str());
|
||||
_window->setWindowTitle(title);
|
||||
|
@ -4388,3 +4396,67 @@ void Application::packetSentNotification(ssize_t length) {
|
|||
_bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(length);
|
||||
}
|
||||
|
||||
void Application::loadScript() {
|
||||
// shut down and stop any existing script
|
||||
QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||
QString suggestedName = desktopLocation.append("/script.js");
|
||||
|
||||
QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Open Script"), suggestedName,
|
||||
tr("JavaScript Files (*.js)"));
|
||||
QByteArray fileNameAscii = fileNameString.toLocal8Bit();
|
||||
const char* fileName = fileNameAscii.data();
|
||||
|
||||
printf("fileName:%s\n",fileName);
|
||||
|
||||
std::ifstream file(fileName, std::ios::in|std::ios::binary|std::ios::ate);
|
||||
if(!file.is_open()) {
|
||||
printf("error loading file\n");
|
||||
return;
|
||||
}
|
||||
qDebug("loading file %s...\n", fileName);
|
||||
|
||||
// get file length....
|
||||
unsigned long fileLength = file.tellg();
|
||||
file.seekg( 0, std::ios::beg );
|
||||
|
||||
// read the entire file into a buffer, WHAT!? Why not.
|
||||
char* entireFile = new char[fileLength+1];
|
||||
file.read((char*)entireFile, fileLength);
|
||||
file.close();
|
||||
|
||||
entireFile[fileLength] = 0;// null terminate
|
||||
QString script(entireFile);
|
||||
delete[] entireFile;
|
||||
|
||||
// start the script on a new thread...
|
||||
bool wantMenuItems = true; // tells the ScriptEngine object to add menu items for itself
|
||||
|
||||
|
||||
ScriptEngine* scriptEngine = new ScriptEngine(script, wantMenuItems, fileName, Menu::getInstance());
|
||||
scriptEngine->setupMenuItems();
|
||||
|
||||
// setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so
|
||||
// we can use the same ones from the application.
|
||||
scriptEngine->getVoxelScriptingInterface()->setPacketSender(&_voxelEditSender);
|
||||
scriptEngine->getParticleScriptingInterface()->setPacketSender(&_particleEditSender);
|
||||
|
||||
QThread* workerThread = new QThread(this);
|
||||
|
||||
// when the worker thread is started, call our engine's run..
|
||||
connect(workerThread, SIGNAL(started()), scriptEngine, SLOT(run()));
|
||||
|
||||
// when the thread is terminated, add both scriptEngine and thread to the deleteLater queue
|
||||
connect(scriptEngine, SIGNAL(finished()), scriptEngine, SLOT(deleteLater()));
|
||||
connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
|
||||
|
||||
// when the application is about to quit, stop our script engine so it unwinds properly
|
||||
connect(this, SIGNAL(aboutToQuit()), scriptEngine, SLOT(stop()));
|
||||
|
||||
scriptEngine->moveToThread(workerThread);
|
||||
|
||||
// Starts an event loop, and emits workerThread->started()
|
||||
workerThread->start();
|
||||
|
||||
// restore the main window's active state
|
||||
_window->activateWindow();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <PacketHeaders.h>
|
||||
#include <ParticleCollisionSystem.h>
|
||||
#include <ParticleEditPacketSender.h>
|
||||
#include <ScriptEngine.h>
|
||||
#include <VoxelQuery.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
|
@ -218,6 +219,7 @@ public slots:
|
|||
void doKillLocalVoxels();
|
||||
void decreaseVoxelSize();
|
||||
void increaseVoxelSize();
|
||||
void loadScript();
|
||||
|
||||
|
||||
private slots:
|
||||
|
|
|
@ -90,6 +90,10 @@ Menu::Menu() :
|
|||
this,
|
||||
SLOT(login())));
|
||||
|
||||
addDisabledActionAndSeparator(fileMenu, "Scripts");
|
||||
addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O, appInstance, SLOT(loadScript()));
|
||||
_activeScriptsMenu = fileMenu->addMenu("Running Scripts");
|
||||
|
||||
addDisabledActionAndSeparator(fileMenu, "Voxels");
|
||||
addActionToQMenuAndActionHash(fileMenu, MenuOption::ExportVoxels, Qt::CTRL | Qt::Key_E, appInstance, SLOT(exportVoxels()));
|
||||
addActionToQMenuAndActionHash(fileMenu, MenuOption::ImportVoxels, Qt::CTRL | Qt::Key_I, appInstance, SLOT(importVoxels()));
|
||||
|
@ -368,6 +372,8 @@ Menu::Menu() :
|
|||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::SimulateLeapHand);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayLeapHands, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::LeapDrive, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::BallFromHand, 0, false);
|
||||
|
||||
|
||||
QMenu* trackingOptionsMenu = developerMenu->addMenu("Tracking Options");
|
||||
|
@ -712,6 +718,11 @@ QAction* Menu::addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu,
|
|||
return action;
|
||||
}
|
||||
|
||||
void Menu::removeAction(QMenu* menu, const QString& actionName) {
|
||||
menu->removeAction(_actionHash.value(actionName));
|
||||
}
|
||||
|
||||
|
||||
bool Menu::isOptionChecked(const QString& menuOption) {
|
||||
return _actionHash.value(menuOption)->isChecked();
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include <QHash>
|
||||
#include <QKeySequence>
|
||||
|
||||
#include <AbstractMenuInterface.h>
|
||||
|
||||
enum FrustumDrawMode {
|
||||
FRUSTUM_DRAW_MODE_ALL,
|
||||
FRUSTUM_DRAW_MODE_VECTORS,
|
||||
|
@ -37,7 +39,7 @@ class BandwidthDialog;
|
|||
class VoxelStatsDialog;
|
||||
class LodToolsDialog;
|
||||
|
||||
class Menu : public QMenuBar {
|
||||
class Menu : public QMenuBar, public AbstractMenuInterface {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static Menu* getInstance();
|
||||
|
@ -71,6 +73,15 @@ public:
|
|||
// User Tweakable PPS from Voxel Server
|
||||
int getMaxVoxelPacketsPerSecond() const { return _maxVoxelPacketsPerSecond; }
|
||||
|
||||
virtual QMenu* getActiveScriptsMenu() { return _activeScriptsMenu;}
|
||||
virtual QAction* addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
const QString actionName,
|
||||
const QKeySequence& shortcut = 0,
|
||||
const QObject* receiver = NULL,
|
||||
const char* member = NULL,
|
||||
QAction::MenuRole role = QAction::NoRole);
|
||||
virtual void removeAction(QMenu* menu, const QString& actionName);
|
||||
|
||||
public slots:
|
||||
void bandwidthDetails();
|
||||
void voxelStatsDetails();
|
||||
|
@ -110,12 +121,6 @@ private:
|
|||
|
||||
/// helper method to have separators with labels that are also compatible with OS X
|
||||
void addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& actionName);
|
||||
QAction* addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
const QString actionName,
|
||||
const QKeySequence& shortcut = 0,
|
||||
const QObject* receiver = NULL,
|
||||
const char* member = NULL,
|
||||
QAction::MenuRole role = QAction::NoRole);
|
||||
|
||||
QAction* addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
const QString actionName,
|
||||
|
@ -141,6 +146,8 @@ private:
|
|||
int _boundaryLevelAdjust;
|
||||
QAction* _useVoxelShader;
|
||||
int _maxVoxelPacketsPerSecond;
|
||||
|
||||
QMenu* _activeScriptsMenu;
|
||||
};
|
||||
|
||||
namespace MenuOption {
|
||||
|
@ -149,6 +156,7 @@ namespace MenuOption {
|
|||
const QString Avatars = "Avatars";
|
||||
const QString Atmosphere = "Atmosphere";
|
||||
const QString AutomaticallyAuditTree = "Automatically Audit Tree Stats";
|
||||
const QString BallFromHand = "Ball from Hand";
|
||||
const QString Bandwidth = "Bandwidth Display";
|
||||
const QString BandwidthDetails = "Bandwidth Details";
|
||||
const QString ChatCircling = "Chat Circling";
|
||||
|
@ -167,6 +175,7 @@ namespace MenuOption {
|
|||
const QString DisableLowRes = "Disable Lower Resolution While Moving";
|
||||
const QString DisplayFrustum = "Display Frustum";
|
||||
const QString DisplayLeapHands = "Display Leap Hands";
|
||||
const QString DisplayHandTargets = "Display Hand Targets";
|
||||
const QString FilterSixense = "Smooth Sixense Movement";
|
||||
const QString DontRenderVoxels = "Don't call _voxels.render()";
|
||||
const QString DontCallOpenGLForVoxels = "Don't call glDrawRangeElementsEXT() for Voxels";
|
||||
|
@ -218,6 +227,7 @@ namespace MenuOption {
|
|||
const QString OldVoxelCullingMode = "Old Voxel Culling Mode";
|
||||
const QString TurnWithHead = "Turn using Head";
|
||||
const QString ClickToFly = "Fly to voxel on click";
|
||||
const QString LoadScript = "Open and Run Script...";
|
||||
const QString Oscilloscope = "Audio Oscilloscope";
|
||||
const QString Pair = "Pair";
|
||||
const QString PasteVoxels = "Paste";
|
||||
|
|
|
@ -74,21 +74,57 @@ void Hand::reset() {
|
|||
}
|
||||
|
||||
void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime) {
|
||||
glm::vec3 targetPosition = fingerTipPosition / (float)TREE_SCALE;
|
||||
float targetRadius = (TOY_BALL_RADIUS * 2.0f) / (float)TREE_SCALE;
|
||||
bool ballFromHand = Menu::getInstance()->isOptionChecked(MenuOption::BallFromHand);
|
||||
int handID = palm.getSixenseID();
|
||||
glm::vec3 targetPosition = palm.getPosition() / (float)TREE_SCALE;
|
||||
float targetRadius = (TOY_BALL_RADIUS * 4.0f) / (float)TREE_SCALE;
|
||||
const Particle* closestParticle = Application::getInstance()->getParticles()
|
||||
->getTree()->findClosestParticle(targetPosition, targetRadius);
|
||||
|
||||
if (closestParticle) {
|
||||
//printf("potentially caught... particle ID:%d\n", closestParticle->getID());
|
||||
|
||||
// you can create a ParticleEditHandle by doing this...
|
||||
ParticleEditHandle* caughtParticle = Application::getInstance()->newParticleEditHandle(closestParticle->getID());
|
||||
if (!_toyBallInHand[handID]) {
|
||||
printf("particle ID:%d NOT IN HAND\n", closestParticle->getID());
|
||||
|
||||
// you can create a ParticleEditHandle by doing this...
|
||||
ParticleEditHandle* caughtParticle = Application::getInstance()->newParticleEditHandle(closestParticle->getID());
|
||||
|
||||
// but make sure you clean it up, when you're done
|
||||
delete caughtParticle;
|
||||
// reflect off the hand...
|
||||
printf("particle ID:%d old velocity=%f,%f,%f\n", closestParticle->getID(),
|
||||
closestParticle->getVelocity().x, closestParticle->getVelocity().y, closestParticle->getVelocity().z);
|
||||
glm::vec3 newVelocity = glm::reflect(closestParticle->getVelocity(), palm.getNormal());
|
||||
|
||||
printf("particle ID:%d REFLECT velocity=%f,%f,%f\n", closestParticle->getID(),
|
||||
newVelocity.x, newVelocity.y, newVelocity.z);
|
||||
|
||||
newVelocity += palm.getTipVelocity() / (float)TREE_SCALE;
|
||||
|
||||
printf("particle ID:%d with TIP velocity=%f,%f,%f\n", closestParticle->getID(),
|
||||
newVelocity.x, newVelocity.y, newVelocity.z);
|
||||
|
||||
|
||||
printf("particle ID:%d OLD position=%f,%f,%f\n", closestParticle->getID(),
|
||||
closestParticle->getPosition().x, closestParticle->getPosition().y, closestParticle->getPosition().z);
|
||||
glm::vec3 newPosition = closestParticle->getPosition();
|
||||
|
||||
newPosition += newVelocity; // move it as if it's already been moving in new direction
|
||||
|
||||
printf("particle ID:%d NEW position=%f,%f,%f\n", closestParticle->getID(),
|
||||
newPosition.x, newPosition.y, newPosition.z);
|
||||
|
||||
caughtParticle->updateParticle(newPosition,
|
||||
closestParticle->getRadius(),
|
||||
closestParticle->getXColor(),
|
||||
newVelocity,
|
||||
closestParticle->getGravity(),
|
||||
closestParticle->getDamping(),
|
||||
closestParticle->getUpdateScript());
|
||||
|
||||
// but make sure you clean it up, when you're done
|
||||
delete caughtParticle;
|
||||
}
|
||||
}
|
||||
int handID = palm.getSixenseID();
|
||||
|
||||
// If there's a ball in hand, and the user presses the skinny button, then change the color of the ball
|
||||
int currentControllerButtons = palm.getControllerButtons();
|
||||
|
@ -117,8 +153,9 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f
|
|||
// create the ball, call MakeParticle, and use the resulting ParticleEditHandle to
|
||||
// manage the newly created particle.
|
||||
// Create a particle on the particle server
|
||||
glm::vec3 ballPosition = ballFromHand ? palm.getPosition() : fingerTipPosition;
|
||||
_ballParticleEditHandles[handID] = Application::getInstance()->makeParticle(
|
||||
fingerTipPosition / (float)TREE_SCALE,
|
||||
ballPosition / (float)TREE_SCALE,
|
||||
TOY_BALL_RADIUS / (float) TREE_SCALE,
|
||||
TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]],
|
||||
NO_VELOCITY / (float)TREE_SCALE,
|
||||
|
@ -128,7 +165,8 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f
|
|||
}
|
||||
} else {
|
||||
// Ball is in hand
|
||||
_ballParticleEditHandles[handID]->updateParticle(fingerTipPosition / (float)TREE_SCALE,
|
||||
glm::vec3 ballPosition = ballFromHand ? palm.getPosition() : fingerTipPosition;
|
||||
_ballParticleEditHandles[handID]->updateParticle(ballPosition / (float)TREE_SCALE,
|
||||
TOY_BALL_RADIUS / (float) TREE_SCALE,
|
||||
TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]],
|
||||
NO_VELOCITY / (float)TREE_SCALE,
|
||||
|
@ -141,13 +179,14 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f
|
|||
if (_toyBallInHand[handID]) {
|
||||
|
||||
_toyBallInHand[handID] = false;
|
||||
glm::vec3 ballPosition = ballFromHand ? palm.getPosition() : fingerTipPosition;
|
||||
glm::vec3 handVelocity = palm.getRawVelocity();
|
||||
glm::vec3 fingerTipVelocity = palm.getTipVelocity();
|
||||
glm::quat avatarRotation = _owningAvatar->getOrientation();
|
||||
glm::vec3 toyBallVelocity = avatarRotation * fingerTipVelocity;
|
||||
|
||||
// ball is no longer in hand...
|
||||
_ballParticleEditHandles[handID]->updateParticle(fingerTipPosition / (float)TREE_SCALE,
|
||||
_ballParticleEditHandles[handID]->updateParticle(ballPosition / (float)TREE_SCALE,
|
||||
TOY_BALL_RADIUS / (float) TREE_SCALE,
|
||||
TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]],
|
||||
toyBallVelocity / (float)TREE_SCALE,
|
||||
|
@ -455,8 +494,37 @@ void Hand::renderLeapHands() {
|
|||
//const glm::vec3 handColor = _ballColor;
|
||||
const glm::vec3 handColor(1.0, 0.84, 0.66); // use the skin color
|
||||
|
||||
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayHandTargets)) {
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
if (!palm.isActive()) {
|
||||
continue;
|
||||
}
|
||||
glm::vec3 targetPosition = palm.getPosition();
|
||||
float targetRadius = (TOY_BALL_RADIUS * 4.0f);
|
||||
glPushMatrix();
|
||||
|
||||
const Particle* closestParticle = Application::getInstance()->getParticles()
|
||||
->getTree()->findClosestParticle(targetPosition / (float)TREE_SCALE,
|
||||
targetRadius / (float)TREE_SCALE);
|
||||
|
||||
// If we are hitting a particle then draw the target green, otherwise yellow
|
||||
if (closestParticle) {
|
||||
glColor4f(0,1,0, alpha);
|
||||
} else {
|
||||
glColor4f(1,1,0, alpha);
|
||||
}
|
||||
glTranslatef(targetPosition.x, targetPosition.y, targetPosition.z);
|
||||
glutWireSphere(targetRadius, 20.0f, 20.0f);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
// Draw the leap balls
|
||||
for (size_t i = 0; i < _leapFingerTipBalls.size(); i++) {
|
||||
|
@ -501,7 +569,9 @@ void Hand::renderLeapHands() {
|
|||
}
|
||||
glm::vec3 tip = palm.getPosition();
|
||||
glm::vec3 root = palm.getPosition() + palm.getNormal() * palmThickness;
|
||||
Avatar::renderJointConnectingCone(root, tip, 0.05, 0.03);
|
||||
const float radiusA = 0.05f;
|
||||
const float radiusB = 0.03f;
|
||||
Avatar::renderJointConnectingCone(root, tip, radiusA, radiusB);
|
||||
}
|
||||
}
|
||||
glDepthMask(GL_TRUE);
|
||||
|
|
|
@ -122,8 +122,8 @@ private:
|
|||
class PalmData {
|
||||
public:
|
||||
PalmData(HandData* owningHandData);
|
||||
glm::vec3 getPosition() const { return _owningHandData->leapPositionToWorldPosition(_rawPosition); }
|
||||
glm::vec3 getNormal() const { return _owningHandData->leapDirectionToWorldDirection(_rawNormal); }
|
||||
glm::vec3 getPosition() const { return _owningHandData->leapPositionToWorldPosition(_rawPosition); }
|
||||
glm::vec3 getNormal() const { return _owningHandData->leapDirectionToWorldDirection(_rawNormal); }
|
||||
|
||||
const glm::vec3& getRawPosition() const { return _rawPosition; }
|
||||
const glm::vec3& getRawNormal() const { return _rawNormal; }
|
||||
|
@ -140,7 +140,7 @@ public:
|
|||
void setSixenseID(int id) { _sixenseID = id; }
|
||||
|
||||
void setRawRotation(const glm::quat rawRotation) { _rawRotation = rawRotation; };
|
||||
const glm::quat getRawRotation() const { return _rawRotation; }
|
||||
glm::quat getRawRotation() const { return _rawRotation; }
|
||||
void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; }
|
||||
void setRawNormal(const glm::vec3& normal) { _rawNormal = normal; }
|
||||
void setRawVelocity(const glm::vec3& velocity) { _rawVelocity = velocity; }
|
||||
|
|
|
@ -35,6 +35,7 @@ OctreeEditPacketSender::OctreeEditPacketSender(PacketSenderNotify* notify) :
|
|||
_serverJurisdictions(NULL),
|
||||
_sequenceNumber(0),
|
||||
_maxPacketSize(MAX_PACKET_SIZE) {
|
||||
//printf("OctreeEditPacketSender::OctreeEditPacketSender() [%p] created... \n", this);
|
||||
}
|
||||
|
||||
OctreeEditPacketSender::~OctreeEditPacketSender() {
|
||||
|
@ -48,6 +49,7 @@ OctreeEditPacketSender::~OctreeEditPacketSender() {
|
|||
delete packet;
|
||||
_preServerPackets.erase(_preServerPackets.begin());
|
||||
}
|
||||
//printf("OctreeEditPacketSender::~OctreeEditPacketSender() [%p] destroyed... \n", this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ public:
|
|||
};
|
||||
|
||||
/// Utility for processing, packing, queueing and sending of outbound edit messages.
|
||||
class OctreeEditPacketSender : public virtual PacketSender {
|
||||
class OctreeEditPacketSender : public PacketSender {
|
||||
public:
|
||||
OctreeEditPacketSender(PacketSenderNotify* notify = NULL);
|
||||
~OctreeEditPacketSender();
|
||||
|
|
61
libraries/octree/src/OctreeScriptingInterface.cpp
Normal file
61
libraries/octree/src/OctreeScriptingInterface.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// OctreeScriptingInterface.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/6/13
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "OctreeScriptingInterface.h"
|
||||
|
||||
OctreeScriptingInterface::OctreeScriptingInterface(OctreeEditPacketSender* packetSender,
|
||||
JurisdictionListener* jurisdictionListener)
|
||||
{
|
||||
setPacketSender(packetSender);
|
||||
setJurisdictionListener(jurisdictionListener);
|
||||
}
|
||||
|
||||
OctreeScriptingInterface::~OctreeScriptingInterface() {
|
||||
//printf("OctreeScriptingInterface::~OctreeScriptingInterface()\n");
|
||||
if (_managedJuridiciontListerner) {
|
||||
//printf("OctreeScriptingInterface::~OctreeScriptingInterface() _managedJuridiciontListerner... _jurisdictionListener->terminate()\n");
|
||||
_jurisdictionListener->terminate();
|
||||
//printf("OctreeScriptingInterface::~OctreeScriptingInterface() _managedJuridiciontListerner... deleting _jurisdictionListener\n");
|
||||
delete _jurisdictionListener;
|
||||
}
|
||||
if (_managedPacketSender) {
|
||||
//printf("OctreeScriptingInterface::~OctreeScriptingInterface() _managedJuridiciontListerner... _packetSender->terminate()\n");
|
||||
_packetSender->terminate();
|
||||
//printf("OctreeScriptingInterface::~OctreeScriptingInterface() _managedPacketSender... deleting _packetSender\n");
|
||||
delete _packetSender;
|
||||
}
|
||||
}
|
||||
|
||||
void OctreeScriptingInterface::setPacketSender(OctreeEditPacketSender* packetSender) {
|
||||
_packetSender = packetSender;
|
||||
}
|
||||
|
||||
void OctreeScriptingInterface::setJurisdictionListener(JurisdictionListener* jurisdictionListener) {
|
||||
_jurisdictionListener = jurisdictionListener;
|
||||
}
|
||||
|
||||
void OctreeScriptingInterface::init() {
|
||||
//printf("OctreeScriptingInterface::init()\n");
|
||||
if (_jurisdictionListener) {
|
||||
_managedJuridiciontListerner = false;
|
||||
} else {
|
||||
_managedJuridiciontListerner = true;
|
||||
_jurisdictionListener = new JurisdictionListener(getServerNodeType());
|
||||
//printf("OctreeScriptingInterface::init() _managedJuridiciontListerner=true, creating _jurisdictionListener=%p\n", _jurisdictionListener);
|
||||
_jurisdictionListener->initialize(true);
|
||||
}
|
||||
|
||||
if (_packetSender) {
|
||||
_managedPacketSender = false;
|
||||
} else {
|
||||
_managedPacketSender = true;
|
||||
_packetSender = createPacketSender();
|
||||
//printf("OctreeScriptingInterface::init() _managedPacketSender=true, creating _packetSender=%p\n", _packetSender);
|
||||
_packetSender->setServerJurisdictions(_jurisdictionListener->getJurisdictions());
|
||||
}
|
||||
}
|
95
libraries/octree/src/OctreeScriptingInterface.h
Normal file
95
libraries/octree/src/OctreeScriptingInterface.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
//
|
||||
// OctreeScriptingInterface.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/6/13
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __hifi__OctreeScriptingInterface__
|
||||
#define __hifi__OctreeScriptingInterface__
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "JurisdictionListener.h"
|
||||
#include "OctreeEditPacketSender.h"
|
||||
|
||||
/// handles scripting of Particle commands from JS passed to assigned clients
|
||||
class OctreeScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
OctreeScriptingInterface(OctreeEditPacketSender* packetSender = NULL,
|
||||
JurisdictionListener* jurisdictionListener = NULL);
|
||||
|
||||
~OctreeScriptingInterface();
|
||||
|
||||
OctreeEditPacketSender* getPacketSender() const { return _packetSender; }
|
||||
JurisdictionListener* getJurisdictionListener() const { return _jurisdictionListener; }
|
||||
void setPacketSender(OctreeEditPacketSender* packetSender);
|
||||
void setJurisdictionListener(JurisdictionListener* jurisdictionListener);
|
||||
void init();
|
||||
|
||||
virtual NODE_TYPE getServerNodeType() const = 0;
|
||||
virtual OctreeEditPacketSender* createPacketSender() = 0;
|
||||
|
||||
public slots:
|
||||
/// Set the desired max packet size in bytes that should be created
|
||||
void setMaxPacketSize(int maxPacketSize) { return _packetSender->setMaxPacketSize(maxPacketSize); }
|
||||
|
||||
/// returns the current desired max packet size in bytes that will be created
|
||||
int getMaxPacketSize() const { return _packetSender->getMaxPacketSize(); }
|
||||
|
||||
/// set the max packets per second send rate
|
||||
void setPacketsPerSecond(int packetsPerSecond) { return _packetSender->setPacketsPerSecond(packetsPerSecond); }
|
||||
|
||||
/// get the max packets per second send rate
|
||||
int getPacketsPerSecond() const { return _packetSender->getPacketsPerSecond(); }
|
||||
|
||||
/// does a particle server exist to send to
|
||||
bool serversExist() const { return _packetSender->serversExist(); }
|
||||
|
||||
/// are there packets waiting in the send queue to be sent
|
||||
bool hasPacketsToSend() const { return _packetSender->hasPacketsToSend(); }
|
||||
|
||||
/// how many packets are there in the send queue waiting to be sent
|
||||
int packetsToSendCount() const { return _packetSender->packetsToSendCount(); }
|
||||
|
||||
/// returns the packets per second send rate of this object over its lifetime
|
||||
float getLifetimePPS() const { return _packetSender->getLifetimePPS(); }
|
||||
|
||||
/// returns the bytes per second send rate of this object over its lifetime
|
||||
float getLifetimeBPS() const { return _packetSender->getLifetimeBPS(); }
|
||||
|
||||
/// returns the packets per second queued rate of this object over its lifetime
|
||||
float getLifetimePPSQueued() const { return _packetSender->getLifetimePPSQueued(); }
|
||||
|
||||
/// returns the bytes per second queued rate of this object over its lifetime
|
||||
float getLifetimeBPSQueued() const { return _packetSender->getLifetimeBPSQueued(); }
|
||||
|
||||
/// returns lifetime of this object from first packet sent to now in usecs
|
||||
long long unsigned int getLifetimeInUsecs() const { return _packetSender->getLifetimeInUsecs(); }
|
||||
|
||||
/// returns lifetime of this object from first packet sent to now in usecs
|
||||
float getLifetimeInSeconds() const { return _packetSender->getLifetimeInSeconds(); }
|
||||
|
||||
/// returns the total packets sent by this object over its lifetime
|
||||
long long unsigned int getLifetimePacketsSent() const { return _packetSender->getLifetimePacketsSent(); }
|
||||
|
||||
/// returns the total bytes sent by this object over its lifetime
|
||||
long long unsigned int getLifetimeBytesSent() const { return _packetSender->getLifetimeBytesSent(); }
|
||||
|
||||
/// returns the total packets queued by this object over its lifetime
|
||||
long long unsigned int getLifetimePacketsQueued() const { return _packetSender->getLifetimePacketsQueued(); }
|
||||
|
||||
/// returns the total bytes queued by this object over its lifetime
|
||||
long long unsigned int getLifetimeBytesQueued() const { return _packetSender->getLifetimeBytesQueued(); }
|
||||
|
||||
protected:
|
||||
/// attached OctreeEditPacketSender that handles queuing and sending of packets to VS
|
||||
OctreeEditPacketSender* _packetSender;
|
||||
JurisdictionListener* _jurisdictionListener;
|
||||
bool _managedPacketSender;
|
||||
bool _managedJuridiciontListerner;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__OctreeScriptingInterface__) */
|
|
@ -415,6 +415,9 @@ void Particle::update() {
|
|||
|
||||
void Particle::runScript() {
|
||||
if (!_updateScript.isEmpty()) {
|
||||
|
||||
//qDebug() << "Script: " << _updateScript << "\n";
|
||||
|
||||
QScriptEngine engine;
|
||||
|
||||
// register meta-type for glm::vec3 and rgbColor conversions
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
|
||||
const glm::vec3& getPosition() const { return _position; }
|
||||
const rgbColor& getColor() const { return _color; }
|
||||
xColor getColor() { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
|
||||
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
|
||||
float getRadius() const { return _radius; }
|
||||
const glm::vec3& getVelocity() const { return _velocity; }
|
||||
const glm::vec3& getGravity() const { return _gravity; }
|
||||
|
@ -129,7 +129,7 @@ public:
|
|||
public slots:
|
||||
glm::vec3 getPosition() const { return _particle->getPosition(); }
|
||||
glm::vec3 getVelocity() const { return _particle->getVelocity(); }
|
||||
xColor getColor() const { return _particle->getColor(); }
|
||||
xColor getColor() const { return _particle->getXColor(); }
|
||||
glm::vec3 getGravity() const { return _particle->getGravity(); }
|
||||
float getDamping() const { return _particle->getDamping(); }
|
||||
float getRadius() const { return _particle->getRadius(); }
|
||||
|
|
|
@ -119,7 +119,7 @@ void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm::
|
|||
}
|
||||
}
|
||||
ParticleEditHandle particleEditHandle(_packetSender, _particles, particle->getID());
|
||||
particleEditHandle.updateParticle(position, particle->getRadius(), particle->getColor(), velocity,
|
||||
particleEditHandle.updateParticle(position, particle->getRadius(), particle->getXColor(), velocity,
|
||||
particle->getGravity(), particle->getDamping(), particle->getUpdateScript());
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include "Particle.h"
|
||||
|
||||
/// Utility for processing, packing, queueing and sending of outbound edit voxel messages.
|
||||
class ParticleEditPacketSender : public virtual OctreeEditPacketSender {
|
||||
class ParticleEditPacketSender : public OctreeEditPacketSender {
|
||||
public:
|
||||
ParticleEditPacketSender(PacketSenderNotify* notify = NULL) : OctreeEditPacketSender(notify) { }
|
||||
~ParticleEditPacketSender() { }
|
||||
|
|
|
@ -8,19 +8,13 @@
|
|||
|
||||
#include "ParticleScriptingInterface.h"
|
||||
|
||||
ParticleScriptingInterface::ParticleScriptingInterface() :
|
||||
_jurisdictionListener(NODE_TYPE_PARTICLE_SERVER),
|
||||
_nextCreatorTokenID(0)
|
||||
{
|
||||
_jurisdictionListener.initialize(true);
|
||||
_particlePacketSender.setServerJurisdictions(_jurisdictionListener.getJurisdictions());
|
||||
}
|
||||
|
||||
|
||||
void ParticleScriptingInterface::queueParticleAdd(PACKET_TYPE addPacketType, ParticleDetail& addParticleDetails) {
|
||||
_particlePacketSender.queueParticleEditMessages(addPacketType, 1, &addParticleDetails);
|
||||
getParticlePacketSender()->queueParticleEditMessages(addPacketType, 1, &addParticleDetails);
|
||||
}
|
||||
|
||||
uint32_t ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, float radius,
|
||||
unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, float radius,
|
||||
xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, QString updateScript) {
|
||||
|
||||
// The application will keep track of creatorTokenID
|
||||
|
|
|
@ -12,78 +12,24 @@
|
|||
#include <QtCore/QObject>
|
||||
|
||||
#include <JurisdictionListener.h>
|
||||
#include <OctreeScriptingInterface.h>
|
||||
#include "ParticleEditPacketSender.h"
|
||||
|
||||
/// handles scripting of Particle commands from JS passed to assigned clients
|
||||
class ParticleScriptingInterface : public QObject {
|
||||
class ParticleScriptingInterface : public OctreeScriptingInterface {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ParticleScriptingInterface();
|
||||
|
||||
ParticleEditPacketSender* getParticlePacketSender() { return &_particlePacketSender; }
|
||||
JurisdictionListener* getJurisdictionListener() { return &_jurisdictionListener; }
|
||||
ParticleEditPacketSender* getParticlePacketSender() const { return (ParticleEditPacketSender*)getPacketSender(); }
|
||||
virtual NODE_TYPE getServerNodeType() const { return NODE_TYPE_PARTICLE_SERVER; }
|
||||
virtual OctreeEditPacketSender* createPacketSender() { return new ParticleEditPacketSender(); }
|
||||
|
||||
public slots:
|
||||
/// queues the creation of a Particle which will be sent by calling process on the PacketSender
|
||||
/// returns the creatorTokenID for the newly created particle
|
||||
uint32_t queueParticleAdd(glm::vec3 position, float radius,
|
||||
unsigned int queueParticleAdd(glm::vec3 position, float radius,
|
||||
xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, QString updateScript);
|
||||
|
||||
/// Set the desired max packet size in bytes that should be created
|
||||
void setMaxPacketSize(int maxPacketSize) { return _particlePacketSender.setMaxPacketSize(maxPacketSize); }
|
||||
|
||||
/// returns the current desired max packet size in bytes that will be created
|
||||
int getMaxPacketSize() const { return _particlePacketSender.getMaxPacketSize(); }
|
||||
|
||||
/// set the max packets per second send rate
|
||||
void setPacketsPerSecond(int packetsPerSecond) { return _particlePacketSender.setPacketsPerSecond(packetsPerSecond); }
|
||||
|
||||
/// get the max packets per second send rate
|
||||
int getPacketsPerSecond() const { return _particlePacketSender.getPacketsPerSecond(); }
|
||||
|
||||
/// does a particle server exist to send to
|
||||
bool serversExist() const { return _particlePacketSender.serversExist(); }
|
||||
|
||||
/// are there packets waiting in the send queue to be sent
|
||||
bool hasPacketsToSend() const { return _particlePacketSender.hasPacketsToSend(); }
|
||||
|
||||
/// how many packets are there in the send queue waiting to be sent
|
||||
int packetsToSendCount() const { return _particlePacketSender.packetsToSendCount(); }
|
||||
|
||||
/// returns the packets per second send rate of this object over its lifetime
|
||||
float getLifetimePPS() const { return _particlePacketSender.getLifetimePPS(); }
|
||||
|
||||
/// returns the bytes per second send rate of this object over its lifetime
|
||||
float getLifetimeBPS() const { return _particlePacketSender.getLifetimeBPS(); }
|
||||
|
||||
/// returns the packets per second queued rate of this object over its lifetime
|
||||
float getLifetimePPSQueued() const { return _particlePacketSender.getLifetimePPSQueued(); }
|
||||
|
||||
/// returns the bytes per second queued rate of this object over its lifetime
|
||||
float getLifetimeBPSQueued() const { return _particlePacketSender.getLifetimeBPSQueued(); }
|
||||
|
||||
/// returns lifetime of this object from first packet sent to now in usecs
|
||||
long long unsigned int getLifetimeInUsecs() const { return _particlePacketSender.getLifetimeInUsecs(); }
|
||||
|
||||
/// returns lifetime of this object from first packet sent to now in usecs
|
||||
float getLifetimeInSeconds() const { return _particlePacketSender.getLifetimeInSeconds(); }
|
||||
|
||||
/// returns the total packets sent by this object over its lifetime
|
||||
long long unsigned int getLifetimePacketsSent() const { return _particlePacketSender.getLifetimePacketsSent(); }
|
||||
|
||||
/// returns the total bytes sent by this object over its lifetime
|
||||
long long unsigned int getLifetimeBytesSent() const { return _particlePacketSender.getLifetimeBytesSent(); }
|
||||
|
||||
/// returns the total packets queued by this object over its lifetime
|
||||
long long unsigned int getLifetimePacketsQueued() const { return _particlePacketSender.getLifetimePacketsQueued(); }
|
||||
|
||||
/// returns the total bytes queued by this object over its lifetime
|
||||
long long unsigned int getLifetimeBytesQueued() const { return _particlePacketSender.getLifetimeBytesQueued(); }
|
||||
|
||||
private:
|
||||
/// attached ParticleEditPacketSender that handles queuing and sending of packets to VS
|
||||
ParticleEditPacketSender _particlePacketSender;
|
||||
JurisdictionListener _jurisdictionListener;
|
||||
|
||||
void queueParticleAdd(PACKET_TYPE addPacketType, ParticleDetail& addParticleDetails);
|
||||
|
||||
uint32_t _nextCreatorTokenID;
|
||||
|
|
|
@ -78,9 +78,12 @@ bool ParticleTree::findNearPointOperation(OctreeElement* element, void* extraDat
|
|||
FindNearPointArgs* args = static_cast<FindNearPointArgs*>(extraData);
|
||||
ParticleTreeElement* particleTreeElement = static_cast<ParticleTreeElement*>(element);
|
||||
|
||||
glm::vec3 penetration;
|
||||
bool sphereIntersection = particleTreeElement->getAABox().findSpherePenetration(args->position,
|
||||
args->targetRadius, penetration);
|
||||
|
||||
// If this particleTreeElement contains the point, then search it...
|
||||
if (particleTreeElement->getAABox().contains(args->position)) {
|
||||
if (sphereIntersection) {
|
||||
const Particle* thisClosestParticle = particleTreeElement->getClosestParticle(args->position);
|
||||
|
||||
// we may have gotten NULL back, meaning no particle was available
|
||||
|
|
30
libraries/scriptengine/CMakeLists.txt
Normal file
30
libraries/scriptengine/CMakeLists.txt
Normal file
|
@ -0,0 +1,30 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(ROOT_DIR ../..)
|
||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||
|
||||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
|
||||
|
||||
set(TARGET_NAME scriptengine)
|
||||
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
|
||||
setup_hifi_library(${TARGET_NAME})
|
||||
|
||||
qt5_use_modules(${TARGET_NAME} Widgets)
|
||||
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(particles ${TARGET_NAME} ${ROOT_DIR})
|
||||
|
||||
# link ZLIB
|
||||
find_package(ZLIB)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES})
|
169
libraries/scriptengine/src/ScriptEngine.cpp
Normal file
169
libraries/scriptengine/src/ScriptEngine.cpp
Normal file
|
@ -0,0 +1,169 @@
|
|||
//
|
||||
// Agent.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/14/13.
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QEventLoop>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QThread>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
#include <AvatarData.h>
|
||||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <UUID.h>
|
||||
#include <VoxelConstants.h>
|
||||
|
||||
#include "ScriptEngine.h"
|
||||
|
||||
int ScriptEngine::_scriptNumber = 1;
|
||||
|
||||
ScriptEngine::ScriptEngine(QString scriptContents, bool wantMenuItems,
|
||||
const char* scriptMenuName, AbstractMenuInterface* menu) {
|
||||
_scriptContents = scriptContents;
|
||||
_isFinished = false;
|
||||
_wantMenuItems = wantMenuItems;
|
||||
if (scriptMenuName) {
|
||||
_scriptMenuName = "Stop ";
|
||||
_scriptMenuName.append(scriptMenuName);
|
||||
} else {
|
||||
_scriptMenuName = "Stop Script ";
|
||||
_scriptNumber++;
|
||||
_scriptMenuName.append(_scriptNumber);
|
||||
}
|
||||
_menu = menu;
|
||||
}
|
||||
|
||||
ScriptEngine::~ScriptEngine() {
|
||||
//printf("ScriptEngine::~ScriptEngine()...\n");
|
||||
}
|
||||
|
||||
|
||||
void ScriptEngine::setupMenuItems() {
|
||||
if (_menu && _wantMenuItems) {
|
||||
_menu->addActionToQMenuAndActionHash(_menu->getActiveScriptsMenu(), _scriptMenuName, 0, this, SLOT(stop()));
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::cleanMenuItems() {
|
||||
if (_menu && _wantMenuItems) {
|
||||
_menu->removeAction(_menu->getActiveScriptsMenu(), _scriptMenuName);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::run() {
|
||||
|
||||
//setupMenuItems();
|
||||
|
||||
QScriptEngine engine;
|
||||
|
||||
_voxelScriptingInterface.init();
|
||||
_particleScriptingInterface.init();
|
||||
|
||||
// register meta-type for glm::vec3 conversions
|
||||
registerMetaTypes(&engine);
|
||||
|
||||
QScriptValue agentValue = engine.newQObject(this);
|
||||
engine.globalObject().setProperty("Agent", agentValue);
|
||||
|
||||
QScriptValue voxelScripterValue = engine.newQObject(&_voxelScriptingInterface);
|
||||
engine.globalObject().setProperty("Voxels", voxelScripterValue);
|
||||
|
||||
QScriptValue particleScripterValue = engine.newQObject(&_particleScriptingInterface);
|
||||
engine.globalObject().setProperty("Particles", particleScripterValue);
|
||||
|
||||
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE));
|
||||
engine.globalObject().setProperty("TREE_SCALE", treeScaleValue);
|
||||
|
||||
const unsigned int VISUAL_DATA_CALLBACK_USECS = (1.0 / 60.0) * 1000 * 1000;
|
||||
|
||||
// let the VoxelPacketSender know how frequently we plan to call it
|
||||
_voxelScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
|
||||
_particleScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
|
||||
|
||||
//qDebug() << "Script:\n" << _scriptContents << "\n";
|
||||
|
||||
QScriptValue result = engine.evaluate(_scriptContents);
|
||||
qDebug() << "Evaluated script.\n";
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
|
||||
}
|
||||
|
||||
timeval startTime;
|
||||
gettimeofday(&startTime, NULL);
|
||||
|
||||
int thisFrame = 0;
|
||||
|
||||
while (!_isFinished) {
|
||||
int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * VISUAL_DATA_CALLBACK_USECS) - usecTimestampNow();
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
}
|
||||
|
||||
if (_isFinished) {
|
||||
//qDebug() << "line: " << __LINE__ << " _isFinished... breaking loop\n";
|
||||
break;
|
||||
}
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
if (_isFinished) {
|
||||
//qDebug() << "line: " << __LINE__ << " _isFinished... breaking loop\n";
|
||||
break;
|
||||
}
|
||||
|
||||
bool willSendVisualDataCallBack = false;
|
||||
if (_voxelScriptingInterface.getVoxelPacketSender()->serversExist()) {
|
||||
// allow the scripter's call back to setup visual data
|
||||
willSendVisualDataCallBack = true;
|
||||
|
||||
// release the queue of edit voxel messages.
|
||||
_voxelScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages();
|
||||
|
||||
// since we're in non-threaded mode, call process so that the packets are sent
|
||||
//_voxelScriptingInterface.getVoxelPacketSender()->process();
|
||||
}
|
||||
|
||||
if (_particleScriptingInterface.getParticlePacketSender()->serversExist()) {
|
||||
// allow the scripter's call back to setup visual data
|
||||
willSendVisualDataCallBack = true;
|
||||
|
||||
// release the queue of edit voxel messages.
|
||||
_particleScriptingInterface.getParticlePacketSender()->releaseQueuedMessages();
|
||||
|
||||
// since we're in non-threaded mode, call process so that the packets are sent
|
||||
//_particleScriptingInterface.getParticlePacketSender()->process();
|
||||
}
|
||||
|
||||
if (willSendVisualDataCallBack) {
|
||||
emit willSendVisualDataCallback();
|
||||
}
|
||||
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << engine.uncaughtException().toString() << "\n";
|
||||
}
|
||||
}
|
||||
cleanMenuItems();
|
||||
|
||||
// If we were on a thread, then wait till it's done
|
||||
if (thread()) {
|
||||
thread()->quit();
|
||||
}
|
||||
|
||||
emit finished();
|
||||
}
|
||||
|
||||
void ScriptEngine::stop() {
|
||||
_isFinished = true;
|
||||
}
|
||||
|
61
libraries/scriptengine/src/ScriptEngine.h
Normal file
61
libraries/scriptengine/src/ScriptEngine.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// ScriptEngine.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/14/13.
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __hifi__ScriptEngine__
|
||||
#define __hifi__ScriptEngine__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <QtScript/QScriptEngine>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QUrl>
|
||||
|
||||
#include <AbstractMenuInterface.h>
|
||||
#include <ParticleScriptingInterface.h>
|
||||
#include <VoxelScriptingInterface.h>
|
||||
|
||||
class ScriptEngine : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScriptEngine(QString scriptContents, bool wantMenuItems = false,
|
||||
const char* scriptMenuName = NULL, AbstractMenuInterface* menu = NULL);
|
||||
|
||||
~ScriptEngine();
|
||||
|
||||
/// Access the VoxelScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener
|
||||
VoxelScriptingInterface* getVoxelScriptingInterface() { return &_voxelScriptingInterface; }
|
||||
|
||||
/// Access the ParticleScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener
|
||||
ParticleScriptingInterface* getParticleScriptingInterface() { return &_particleScriptingInterface; }
|
||||
|
||||
void setupMenuItems();
|
||||
void cleanMenuItems();
|
||||
|
||||
public slots:
|
||||
void run();
|
||||
void stop();
|
||||
|
||||
signals:
|
||||
void willSendAudioDataCallback();
|
||||
void willSendVisualDataCallback();
|
||||
void finished();
|
||||
protected:
|
||||
QString _scriptContents;
|
||||
bool _isFinished;
|
||||
|
||||
|
||||
private:
|
||||
VoxelScriptingInterface _voxelScriptingInterface;
|
||||
ParticleScriptingInterface _particleScriptingInterface;
|
||||
bool _wantMenuItems;
|
||||
QString _scriptMenuName;
|
||||
AbstractMenuInterface* _menu;
|
||||
static int _scriptNumber;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__ScriptEngine__) */
|
29
libraries/shared/src/AbstractMenuInterface.h
Normal file
29
libraries/shared/src/AbstractMenuInterface.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// AbstractMenuInterface.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/16/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __hifi__AbstractMenuInterface__
|
||||
#define __hifi__AbstractMenuInterface__
|
||||
|
||||
#include <QMenuBar>
|
||||
//#include <QHash>
|
||||
//#include <QKeySequence>
|
||||
|
||||
class AbstractMenuInterface {
|
||||
public:
|
||||
virtual QMenu* getActiveScriptsMenu() = 0;
|
||||
virtual QAction* addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
const QString actionName,
|
||||
const QKeySequence& shortcut = 0,
|
||||
const QObject* receiver = NULL,
|
||||
const char* member = NULL,
|
||||
QAction::MenuRole role = QAction::NoRole) = 0;
|
||||
virtual void removeAction(QMenu* menu, const QString& actionName) = 0;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__AbstractMenuInterface__) */
|
|
@ -42,8 +42,11 @@ HifiSockAddr::HifiSockAddr(const QString& hostname, quint16 hostOrderPort) {
|
|||
}
|
||||
|
||||
HifiSockAddr& HifiSockAddr::operator=(const HifiSockAddr& rhsSockAddr) {
|
||||
HifiSockAddr temp(rhsSockAddr);
|
||||
swap(temp);
|
||||
//HifiSockAddr temp(rhsSockAddr);
|
||||
//swap(temp);
|
||||
_address = rhsSockAddr._address;
|
||||
_port = rhsSockAddr._port;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,11 @@ PacketSender::PacketSender(PacketSenderNotify* notify, int packetsPerSecond) :
|
|||
_totalPacketsQueued(0),
|
||||
_totalBytesQueued(0)
|
||||
{
|
||||
//printf("PacketSender[%p] created... \n", this);
|
||||
}
|
||||
|
||||
PacketSender::~PacketSender() {
|
||||
//printf("PacketSender::~PacketSender[%p] destroyed... \n", this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ public:
|
|||
static const int MINIMAL_SLEEP_INTERVAL;
|
||||
|
||||
PacketSender(PacketSenderNotify* notify = NULL, int packetsPerSecond = DEFAULT_PACKETS_PER_SECOND);
|
||||
~PacketSender();
|
||||
|
||||
/// Add packet to outbound queue.
|
||||
/// \param HifiSockAddr& address the destination address
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <OctreeEditPacketSender.h>
|
||||
|
||||
/// Utility for processing, packing, queueing and sending of outbound edit voxel messages.
|
||||
class VoxelEditPacketSender : public virtual OctreeEditPacketSender {
|
||||
class VoxelEditPacketSender : public OctreeEditPacketSender {
|
||||
public:
|
||||
VoxelEditPacketSender(PacketSenderNotify* notify = NULL) : OctreeEditPacketSender(notify) { }
|
||||
~VoxelEditPacketSender() { }
|
||||
|
|
|
@ -8,13 +8,8 @@
|
|||
|
||||
#include "VoxelScriptingInterface.h"
|
||||
|
||||
VoxelScriptingInterface::VoxelScriptingInterface() {
|
||||
_jurisdictionListener.initialize(true);
|
||||
_voxelPacketSender.setVoxelServerJurisdictions(_jurisdictionListener.getJurisdictions());
|
||||
}
|
||||
|
||||
void VoxelScriptingInterface::queueVoxelAdd(PACKET_TYPE addPacketType, VoxelDetail& addVoxelDetails) {
|
||||
_voxelPacketSender.queueVoxelEditMessages(addPacketType, 1, &addVoxelDetails);
|
||||
getVoxelPacketSender()->queueVoxelEditMessages(addPacketType, 1, &addVoxelDetails);
|
||||
}
|
||||
|
||||
void VoxelScriptingInterface::queueVoxelAdd(float x, float y, float z, float scale, uchar red, uchar green, uchar blue) {
|
||||
|
@ -39,6 +34,6 @@ void VoxelScriptingInterface::queueVoxelDelete(float x, float y, float z, float
|
|||
// setup a VoxelDetail struct with data
|
||||
VoxelDetail deleteVoxelDetail = {x, y, z, scale, 0, 0, 0};
|
||||
|
||||
_voxelPacketSender.queueVoxelEditMessages(PACKET_TYPE_VOXEL_ERASE, 1, &deleteVoxelDetail);
|
||||
getVoxelPacketSender()->queueVoxelEditMessages(PACKET_TYPE_VOXEL_ERASE, 1, &deleteVoxelDetail);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,16 +12,18 @@
|
|||
#include <QtCore/QObject>
|
||||
|
||||
#include <JurisdictionListener.h>
|
||||
#include <OctreeScriptingInterface.h>
|
||||
#include "VoxelEditPacketSender.h"
|
||||
|
||||
/// handles scripting of voxel commands from JS passed to assigned clients
|
||||
class VoxelScriptingInterface : public QObject {
|
||||
class VoxelScriptingInterface : public OctreeScriptingInterface {
|
||||
Q_OBJECT
|
||||
public:
|
||||
VoxelScriptingInterface();
|
||||
|
||||
VoxelEditPacketSender* getVoxelPacketSender() { return &_voxelPacketSender; }
|
||||
JurisdictionListener* getJurisdictionListener() { return &_jurisdictionListener; }
|
||||
VoxelEditPacketSender* getVoxelPacketSender() { return (VoxelEditPacketSender*)getPacketSender(); }
|
||||
|
||||
virtual NODE_TYPE getServerNodeType() const { return NODE_TYPE_VOXEL_SERVER; }
|
||||
virtual OctreeEditPacketSender* createPacketSender() { return new VoxelEditPacketSender(); }
|
||||
|
||||
public slots:
|
||||
/// queues the creation of a voxel which will be sent by calling process on the PacketSender
|
||||
/// \param x the x-coordinate of the voxel (in VS space)
|
||||
|
@ -50,62 +52,7 @@ public slots:
|
|||
/// \param scale the scale of the voxel (in VS space)
|
||||
void queueVoxelDelete(float x, float y, float z, float scale);
|
||||
|
||||
/// Set the desired max packet size in bytes that should be created
|
||||
void setMaxPacketSize(int maxPacketSize) { return _voxelPacketSender.setMaxPacketSize(maxPacketSize); }
|
||||
|
||||
/// returns the current desired max packet size in bytes that will be created
|
||||
int getMaxPacketSize() const { return _voxelPacketSender.getMaxPacketSize(); }
|
||||
|
||||
/// set the max packets per second send rate
|
||||
void setPacketsPerSecond(int packetsPerSecond) { return _voxelPacketSender.setPacketsPerSecond(packetsPerSecond); }
|
||||
|
||||
/// get the max packets per second send rate
|
||||
int getPacketsPerSecond() const { return _voxelPacketSender.getPacketsPerSecond(); }
|
||||
|
||||
/// does a voxel server exist to send to
|
||||
bool voxelServersExist() const { return _voxelPacketSender.voxelServersExist(); }
|
||||
|
||||
/// are there packets waiting in the send queue to be sent
|
||||
bool hasPacketsToSend() const { return _voxelPacketSender.hasPacketsToSend(); }
|
||||
|
||||
/// how many packets are there in the send queue waiting to be sent
|
||||
int packetsToSendCount() const { return _voxelPacketSender.packetsToSendCount(); }
|
||||
|
||||
/// returns the packets per second send rate of this object over its lifetime
|
||||
float getLifetimePPS() const { return _voxelPacketSender.getLifetimePPS(); }
|
||||
|
||||
/// returns the bytes per second send rate of this object over its lifetime
|
||||
float getLifetimeBPS() const { return _voxelPacketSender.getLifetimeBPS(); }
|
||||
|
||||
/// returns the packets per second queued rate of this object over its lifetime
|
||||
float getLifetimePPSQueued() const { return _voxelPacketSender.getLifetimePPSQueued(); }
|
||||
|
||||
/// returns the bytes per second queued rate of this object over its lifetime
|
||||
float getLifetimeBPSQueued() const { return _voxelPacketSender.getLifetimeBPSQueued(); }
|
||||
|
||||
/// returns lifetime of this object from first packet sent to now in usecs
|
||||
long long unsigned int getLifetimeInUsecs() const { return _voxelPacketSender.getLifetimeInUsecs(); }
|
||||
|
||||
/// returns lifetime of this object from first packet sent to now in usecs
|
||||
float getLifetimeInSeconds() const { return _voxelPacketSender.getLifetimeInSeconds(); }
|
||||
|
||||
/// returns the total packets sent by this object over its lifetime
|
||||
long long unsigned int getLifetimePacketsSent() const { return _voxelPacketSender.getLifetimePacketsSent(); }
|
||||
|
||||
/// returns the total bytes sent by this object over its lifetime
|
||||
long long unsigned int getLifetimeBytesSent() const { return _voxelPacketSender.getLifetimeBytesSent(); }
|
||||
|
||||
/// returns the total packets queued by this object over its lifetime
|
||||
long long unsigned int getLifetimePacketsQueued() const { return _voxelPacketSender.getLifetimePacketsQueued(); }
|
||||
|
||||
/// returns the total bytes queued by this object over its lifetime
|
||||
long long unsigned int getLifetimeBytesQueued() const { return _voxelPacketSender.getLifetimeBytesQueued(); }
|
||||
|
||||
private:
|
||||
/// attached VoxelEditPacketSender that handles queuing and sending of packets to VS
|
||||
VoxelEditPacketSender _voxelPacketSender;
|
||||
JurisdictionListener _jurisdictionListener;
|
||||
|
||||
void queueVoxelAdd(PACKET_TYPE addPacketType, VoxelDetail& addVoxelDetails);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue