mirror of
https://github.com/JulianGro/overte.git
synced 2025-08-16 19:56:45 +02:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
abd0951696
31 changed files with 648 additions and 175 deletions
|
@ -9,11 +9,12 @@ 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(Qt5Widgets REQUIRED)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||
|
||||
qt5_use_modules(${TARGET_NAME} Network)
|
||||
qt5_use_modules(${TARGET_NAME} Network Widgets)
|
||||
|
||||
# include glm
|
||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||
|
|
BIN
interface/resources/styles/Inconsolata.otf
Normal file
BIN
interface/resources/styles/Inconsolata.otf
Normal file
Binary file not shown.
7
interface/resources/styles/log_dialog.qss
Normal file
7
interface/resources/styles/log_dialog.qss
Normal file
|
@ -0,0 +1,7 @@
|
|||
QPlainTextEdit {
|
||||
font-family: Inconsolata, Lucida Console, Andale Mono, Monaco;
|
||||
font-size: 16px;
|
||||
padding-left: 28px;
|
||||
color: #333333;
|
||||
background-color: #FFFFFF;
|
||||
}
|
|
@ -143,11 +143,17 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
_pasteMode(false)
|
||||
{
|
||||
_applicationStartupTime = startup_time;
|
||||
|
||||
switchToResourcesParentIfRequired();
|
||||
QFontDatabase::addApplicationFont("resources/styles/Inconsolata.otf");
|
||||
_window->setWindowTitle("Interface");
|
||||
|
||||
qDebug( "[VERSION] Build sequence: %i", BUILD_VERSION);
|
||||
|
||||
|
||||
qInstallMessageHandler(messageHandler);
|
||||
|
||||
// call Menu getInstance static method to set up the menu
|
||||
_window->setMenuBar(Menu::getInstance());
|
||||
|
||||
qDebug("[VERSION] Build sequence: %i", BUILD_VERSION);
|
||||
|
||||
unsigned int listenPort = 0; // bind to an ephemeral port by default
|
||||
const char** constArgv = const_cast<const char**>(argv);
|
||||
|
@ -173,16 +179,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
|
||||
// network receive thread and voxel parsing thread are both controlled by the --nonblocking command line
|
||||
_enableProcessVoxelsThread = _enableNetworkThread = !cmdOptionExists(argc, constArgv, "--nonblocking");
|
||||
|
||||
// setup QSettings
|
||||
#ifdef Q_OS_MAC
|
||||
QString resourcesPath = QCoreApplication::applicationDirPath() + "/../Resources";
|
||||
#else
|
||||
QString resourcesPath = QCoreApplication::applicationDirPath() + "/resources";
|
||||
#endif
|
||||
|
||||
|
||||
// read the ApplicationInfo.ini file for Name/Version/Domain information
|
||||
QSettings applicationInfo(resourcesPath + "/info/ApplicationInfo.ini", QSettings::IniFormat);
|
||||
QSettings applicationInfo("resources/info/ApplicationInfo.ini", QSettings::IniFormat);
|
||||
|
||||
// set the associated application properties
|
||||
applicationInfo.beginGroup("INFO");
|
||||
|
@ -191,11 +190,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
setApplicationVersion(applicationInfo.value("version").toString());
|
||||
setOrganizationName(applicationInfo.value("organizationName").toString());
|
||||
setOrganizationDomain(applicationInfo.value("organizationDomain").toString());
|
||||
|
||||
|
||||
_settings = new QSettings(this);
|
||||
|
||||
// call Menu getInstance static method to set up the menu
|
||||
_window->setMenuBar(Menu::getInstance());
|
||||
|
||||
// Check to see if the user passed in a command line option for loading a local
|
||||
// Voxel File.
|
||||
|
@ -251,6 +247,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
}
|
||||
|
||||
Application::~Application() {
|
||||
|
||||
qInstallMessageHandler(NULL);
|
||||
|
||||
// make sure we don't call the idle timer any more
|
||||
delete idleTimer;
|
||||
|
||||
|
@ -4462,7 +4461,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
|
||||
|
@ -4490,3 +4490,12 @@ void Application::loadScript() {
|
|||
// restore the main window's active state
|
||||
_window->activateWindow();
|
||||
}
|
||||
|
||||
void Application::toggleLogDialog() {
|
||||
if (! _logDialog) {
|
||||
_logDialog = new LogDialog(_glWidget);
|
||||
_logDialog->show();
|
||||
} else {
|
||||
_logDialog->close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <QSettings>
|
||||
#include <QTouchEvent>
|
||||
#include <QList>
|
||||
#include <QPointer>
|
||||
|
||||
#include <NetworkPacket.h>
|
||||
#include <NodeList.h>
|
||||
|
@ -67,8 +68,11 @@
|
|||
#include "ui/VoxelStatsDialog.h"
|
||||
#include "ui/RearMirrorTools.h"
|
||||
#include "ui/LodToolsDialog.h"
|
||||
#include "ui/LogDialog.h"
|
||||
#include "ParticleTreeRenderer.h"
|
||||
#include "ParticleEditHandle.h"
|
||||
#include "ControllerScriptingInterface.h"
|
||||
|
||||
|
||||
class QAction;
|
||||
class QActionGroup;
|
||||
|
@ -222,7 +226,7 @@ public slots:
|
|||
void decreaseVoxelSize();
|
||||
void increaseVoxelSize();
|
||||
void loadScript();
|
||||
|
||||
void toggleLogDialog();
|
||||
|
||||
private slots:
|
||||
|
||||
|
@ -503,6 +507,8 @@ private:
|
|||
|
||||
std::vector<VoxelFade> _voxelFades;
|
||||
std::vector<Avatar*> _avatarFades;
|
||||
ControllerScriptingInterface _controllerScriptingInterface;
|
||||
QPointer<LogDialog> _logDialog;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__Application__) */
|
||||
|
|
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__) */
|
|
@ -6,12 +6,13 @@
|
|||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "LogDisplay.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
#include "LogDisplay.h"
|
||||
#include "Util.h"
|
||||
|
||||
using namespace std;
|
||||
|
@ -91,6 +92,7 @@ void LogDisplay::setCharacterSize(unsigned width, unsigned height) {
|
|||
void LogDisplay::addMessage(const char* ptr) {
|
||||
|
||||
pthread_mutex_lock(& _mutex);
|
||||
emit logReceived(ptr);
|
||||
|
||||
// T-pipe, if requested
|
||||
if (_stream != 0l) {
|
||||
|
@ -118,7 +120,7 @@ void LogDisplay::addMessage(const char* ptr) {
|
|||
_writePos = _chars;
|
||||
}
|
||||
|
||||
if (++_writtenInLine >= _lineLength || c == '\0') {
|
||||
if (c == '\0') {
|
||||
|
||||
// new line? store its start to the line buffer and mark next line as empty
|
||||
++_lastLinePos;
|
||||
|
@ -148,13 +150,24 @@ void LogDisplay::addMessage(const char* ptr) {
|
|||
|
||||
// remember start position in character buffer for next line and reset character count
|
||||
_writeLineStartPos = _writePos;
|
||||
_writtenInLine = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(& _mutex);
|
||||
}
|
||||
|
||||
QStringList LogDisplay::getLogData() {
|
||||
// wait for adding new log data whilr iterating over _lines
|
||||
pthread_mutex_lock(& _mutex);
|
||||
QStringList list;
|
||||
int i = 0;
|
||||
while (_lines[i] != *_lastLinePos) {
|
||||
list.append(_lines[i++]);
|
||||
}
|
||||
pthread_mutex_unlock(& _mutex);
|
||||
return list;
|
||||
}
|
||||
|
||||
//
|
||||
// Rendering
|
||||
//
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
|
||||
#include "ui/TextRenderer.h"
|
||||
|
||||
class LogDisplay {
|
||||
class LogDisplay : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
static LogDisplay instance;
|
||||
|
@ -43,6 +44,11 @@ public:
|
|||
static unsigned const LINE_BUFFER_SIZE = 256; // number of lines that are buffered
|
||||
static unsigned const MAX_MESSAGE_LENGTH = 512; // maximum number of characters for a message
|
||||
|
||||
QStringList getLogData();
|
||||
|
||||
signals:
|
||||
void logReceived(QString message);
|
||||
|
||||
private:
|
||||
// use static 'instance' to access the single instance
|
||||
LogDisplay();
|
||||
|
|
|
@ -265,7 +265,7 @@ Menu::Menu() :
|
|||
|
||||
addDisabledActionAndSeparator(viewMenu, "Stats");
|
||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, Qt::Key_Slash);
|
||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Log, Qt::CTRL | Qt::Key_L);
|
||||
addActionToQMenuAndActionHash(viewMenu, MenuOption::Log, Qt::CTRL | Qt::Key_L, appInstance, SLOT(toggleLogDialog()));
|
||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Oscilloscope, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Bandwidth, 0, true);
|
||||
addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, this, SLOT(bandwidthDetails()));
|
||||
|
@ -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:
|
||||
|
@ -146,7 +146,6 @@ private:
|
|||
int _boundaryLevelAdjust;
|
||||
QAction* _useVoxelShader;
|
||||
int _maxVoxelPacketsPerSecond;
|
||||
|
||||
QMenu* _activeScriptsMenu;
|
||||
};
|
||||
|
||||
|
|
|
@ -19,11 +19,23 @@
|
|||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
timeval startup_time;
|
||||
gettimeofday(&startup_time, NULL);
|
||||
|
||||
// Debug option to demonstrate that the client's local time does not
|
||||
// need to be in sync with any other network node. This forces clock
|
||||
// skew for the individual client
|
||||
const char* CLOCK_SKEW = "--clockSkew";
|
||||
const char* clockSkewOption = getCmdOption(argc, argv, CLOCK_SKEW);
|
||||
if (clockSkewOption) {
|
||||
int clockSkew = atoi(clockSkewOption);
|
||||
usecTimestampNowForceClockSkew(clockSkew);
|
||||
qDebug("clockSkewOption=%s clockSkew=%d\n", clockSkewOption, clockSkew);
|
||||
}
|
||||
|
||||
int exitCode;
|
||||
{
|
||||
Application app(argc, const_cast<char**>(argv), startup_time);
|
||||
|
|
75
interface/src/ui/LogDialog.cpp
Normal file
75
interface/src/ui/LogDialog.cpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// LogDialog.cpp
|
||||
// interface
|
||||
//
|
||||
// Created by Stojce Slavkovski on 12/12/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <QDesktopWidget>
|
||||
#include <QTextBlock>
|
||||
#include <QtGui>
|
||||
|
||||
#include "SharedUtil.h"
|
||||
#include "ui/LogDialog.h"
|
||||
#include "LogDisplay.h"
|
||||
|
||||
const int INITIAL_WIDTH = 720;
|
||||
const float INITIAL_HEIGHT_RATIO = 0.6f;
|
||||
|
||||
int cursorMeta = qRegisterMetaType<QTextCursor>("QTextCursor");
|
||||
int blockMeta = qRegisterMetaType<QTextBlock>("QTextBlock");
|
||||
|
||||
LogDialog::LogDialog(QWidget* parent) : QDialog(parent, Qt::Dialog) {
|
||||
|
||||
setWindowTitle("Log");
|
||||
|
||||
_logTextBox = new QPlainTextEdit(this);
|
||||
_logTextBox->setReadOnly(true);
|
||||
_logTextBox->show();
|
||||
|
||||
switchToResourcesParentIfRequired();
|
||||
QFile styleSheet("resources/styles/log_dialog.qss");
|
||||
|
||||
if (styleSheet.open(QIODevice::ReadOnly)) {
|
||||
setStyleSheet(styleSheet.readAll());
|
||||
}
|
||||
|
||||
QDesktopWidget desktop;
|
||||
QRect screen = desktop.screenGeometry();
|
||||
resize(INITIAL_WIDTH, static_cast<int>(screen.height() * INITIAL_HEIGHT_RATIO));
|
||||
move(screen.center() - rect().center());
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
}
|
||||
|
||||
LogDialog::~LogDialog() {
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void LogDialog::showEvent(QShowEvent *e) {
|
||||
_logTextBox->clear();
|
||||
|
||||
pthread_mutex_lock(& _mutex);
|
||||
QStringList _logData = LogDisplay::instance.getLogData();
|
||||
|
||||
connect(&LogDisplay::instance, &LogDisplay::logReceived, this, &LogDialog::appendLogLine);
|
||||
for(int i = 0; i < _logData.size(); ++i) {
|
||||
appendLogLine(_logData[i]);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(& _mutex);
|
||||
}
|
||||
|
||||
void LogDialog::resizeEvent(QResizeEvent *e) {
|
||||
_logTextBox->resize(width(), height());
|
||||
}
|
||||
|
||||
void LogDialog::appendLogLine(QString logLine) {
|
||||
if (isVisible()) {
|
||||
pthread_mutex_lock(& _mutex);
|
||||
_logTextBox->appendPlainText(logLine.simplified());
|
||||
pthread_mutex_unlock(& _mutex);
|
||||
_logTextBox->ensureCursorVisible();
|
||||
}
|
||||
}
|
36
interface/src/ui/LogDialog.h
Normal file
36
interface/src/ui/LogDialog.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// LogDialog.h
|
||||
// interface
|
||||
//
|
||||
// Created by Stojce Slavkovski on 12/12/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__LogDialog__
|
||||
#define __interface__LogDialog__
|
||||
|
||||
#include <QDialog>
|
||||
#include <QPlainTextEdit>
|
||||
|
||||
class LogDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LogDialog(QWidget* parent);
|
||||
~LogDialog();
|
||||
|
||||
public slots:
|
||||
void appendLogLine(QString logLine);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* e);
|
||||
void showEvent(QShowEvent* e);
|
||||
|
||||
private:
|
||||
QPlainTextEdit* _logTextBox;
|
||||
pthread_mutex_t _mutex;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -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:
|
||||
|
|
|
@ -656,6 +656,17 @@ void OctreeServer::run() {
|
|||
_persistThread->initialize(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Debug option to demonstrate that the server's local time does not
|
||||
// need to be in sync with any other network node. This forces clock
|
||||
// skew for the individual server node
|
||||
const char* CLOCK_SKEW = "--clockSkew";
|
||||
const char* clockSkewOption = getCmdOption(_argc, _argv, CLOCK_SKEW);
|
||||
if (clockSkewOption) {
|
||||
int clockSkew = atoi(clockSkewOption);
|
||||
usecTimestampNowForceClockSkew(clockSkew);
|
||||
qDebug("clockSkewOption=%s clockSkew=%d\n", clockSkewOption, clockSkew);
|
||||
}
|
||||
|
||||
// Check to see if the user passed in a command line option for setting packet send rate
|
||||
const char* PACKETS_PER_SECOND = "--packetsPerSecond";
|
||||
|
|
|
@ -36,15 +36,16 @@ Particle::~Particle() {
|
|||
void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity,
|
||||
float damping, bool inHand, QString updateScript, uint32_t id) {
|
||||
if (id == NEW_PARTICLE) {
|
||||
_created = usecTimestampNow();
|
||||
_id = _nextID;
|
||||
_nextID++;
|
||||
} else {
|
||||
_id = id;
|
||||
}
|
||||
_lastUpdated = usecTimestampNow();
|
||||
_lastEdited = _lastUpdated;
|
||||
|
||||
uint64_t now = usecTimestampNow();
|
||||
_edited = now;
|
||||
_lastSimulated = now;
|
||||
_created = now; // will get updated as appropriate in setLifetime()
|
||||
|
||||
_position = position;
|
||||
_radius = radius;
|
||||
memcpy(_color, color, sizeof(_color));
|
||||
|
@ -63,13 +64,10 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const {
|
|||
//printf("Particle::appendParticleData()... getID()=%d\n", getID());
|
||||
|
||||
if (success) {
|
||||
success = packetData->appendValue(getCreated());
|
||||
success = packetData->appendValue(getLifetime());
|
||||
}
|
||||
if (success) {
|
||||
success = packetData->appendValue(getLastUpdated());
|
||||
}
|
||||
if (success) {
|
||||
success = packetData->appendValue(getLastEdited());
|
||||
success = packetData->appendValue(getEditedAgo());
|
||||
}
|
||||
if (success) {
|
||||
success = packetData->appendValue(getRadius());
|
||||
|
@ -103,9 +101,17 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const {
|
|||
}
|
||||
|
||||
int Particle::expectedBytes() {
|
||||
int expectedBytes = sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(float) +
|
||||
sizeof(glm::vec3) + sizeof(rgbColor) + sizeof(glm::vec3) +
|
||||
sizeof(glm::vec3) + sizeof(float) + sizeof(bool);
|
||||
int expectedBytes = sizeof(uint32_t) // id
|
||||
+ sizeof(float) // lifetime
|
||||
+ sizeof(float) // edited ago
|
||||
+ sizeof(float) // radius
|
||||
+ sizeof(glm::vec3) // position
|
||||
+ sizeof(rgbColor) // color
|
||||
+ sizeof(glm::vec3) // velocity
|
||||
+ sizeof(glm::vec3) // gravity
|
||||
+ sizeof(float) // damping
|
||||
+ sizeof(bool); // inhand
|
||||
// potentially more...
|
||||
return expectedBytes;
|
||||
}
|
||||
|
||||
|
@ -119,20 +125,19 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
dataAt += sizeof(_id);
|
||||
bytesRead += sizeof(_id);
|
||||
|
||||
// created
|
||||
memcpy(&_created, dataAt, sizeof(_created));
|
||||
dataAt += sizeof(_created);
|
||||
bytesRead += sizeof(_created);
|
||||
// lifetime
|
||||
float lifetime;
|
||||
memcpy(&lifetime, dataAt, sizeof(lifetime));
|
||||
dataAt += sizeof(lifetime);
|
||||
bytesRead += sizeof(lifetime);
|
||||
setLifetime(lifetime);
|
||||
|
||||
// lastupdated
|
||||
memcpy(&_lastUpdated, dataAt, sizeof(_lastUpdated));
|
||||
dataAt += sizeof(_lastUpdated);
|
||||
bytesRead += sizeof(_lastUpdated);
|
||||
|
||||
// _lastEdited
|
||||
memcpy(&_lastEdited, dataAt, sizeof(_lastEdited));
|
||||
dataAt += sizeof(_lastEdited);
|
||||
bytesRead += sizeof(_lastEdited);
|
||||
// edited ago
|
||||
float editedAgo;
|
||||
memcpy(&editedAgo, dataAt, sizeof(editedAgo));
|
||||
dataAt += sizeof(editedAgo);
|
||||
bytesRead += sizeof(editedAgo);
|
||||
setEditedAgo(editedAgo);
|
||||
|
||||
// radius
|
||||
memcpy(&_radius, dataAt, sizeof(_radius));
|
||||
|
@ -186,7 +191,7 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
|
||||
|
||||
Particle Particle::fromEditPacket(unsigned char* data, int length, int& processedBytes) {
|
||||
Particle newParticle; // id and lastUpdated will get set here...
|
||||
Particle newParticle; // id and _lastSimulated will get set here...
|
||||
unsigned char* dataAt = data;
|
||||
processedBytes = 0;
|
||||
|
||||
|
@ -214,26 +219,17 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
|
|||
processedBytes += sizeof(creatorTokenID);
|
||||
newParticle.setCreatorTokenID(creatorTokenID);
|
||||
newParticle._newlyCreated = true;
|
||||
|
||||
newParticle.setLifetime(0); // this guy is new!
|
||||
|
||||
} else {
|
||||
newParticle._id = editID;
|
||||
newParticle._newlyCreated = false;
|
||||
}
|
||||
|
||||
// created
|
||||
memcpy(&newParticle._created, dataAt, sizeof(newParticle._created));
|
||||
dataAt += sizeof(newParticle._created);
|
||||
processedBytes += sizeof(newParticle._created);
|
||||
|
||||
// lastUpdated
|
||||
memcpy(&newParticle._lastUpdated, dataAt, sizeof(newParticle._lastUpdated));
|
||||
dataAt += sizeof(newParticle._lastUpdated);
|
||||
processedBytes += sizeof(newParticle._lastUpdated);
|
||||
|
||||
// lastEdited
|
||||
memcpy(&newParticle._lastEdited, dataAt, sizeof(newParticle._lastEdited));
|
||||
dataAt += sizeof(newParticle._lastEdited);
|
||||
processedBytes += sizeof(newParticle._lastEdited);
|
||||
|
||||
// clearly we just edited it
|
||||
newParticle.setEditedAgo(0);
|
||||
|
||||
// radius
|
||||
memcpy(&newParticle._radius, dataAt, sizeof(newParticle._radius));
|
||||
dataAt += sizeof(newParticle._radius);
|
||||
|
@ -291,9 +287,8 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
|
|||
|
||||
void Particle::debugDump() const {
|
||||
printf("Particle id :%u\n", _id);
|
||||
printf(" created:%llu\n", _created);
|
||||
printf(" last updated:%llu\n", _lastUpdated);
|
||||
printf(" last edited:%llu\n", _lastEdited);
|
||||
printf(" lifetime:%f\n", getLifetime());
|
||||
printf(" edited ago:%f\n", getEditedAgo());
|
||||
printf(" position:%f,%f,%f\n", _position.x, _position.y, _position.z);
|
||||
printf(" velocity:%f,%f,%f\n", _velocity.x, _velocity.y, _velocity.z);
|
||||
printf(" gravity:%f,%f,%f\n", _gravity.x, _gravity.y, _gravity.z);
|
||||
|
@ -325,7 +320,6 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
|||
sizeOut += lengthOfOctcode;
|
||||
|
||||
// Now add our edit content details...
|
||||
uint64_t created = usecTimestampNow();
|
||||
|
||||
// id
|
||||
memcpy(copyAt, &details[i].id, sizeof(details[i].id));
|
||||
|
@ -338,25 +332,8 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
|||
memcpy(copyAt, &details[i].creatorTokenID, sizeof(details[i].creatorTokenID));
|
||||
copyAt += sizeof(details[i].creatorTokenID);
|
||||
sizeOut += sizeof(details[i].creatorTokenID);
|
||||
} else {
|
||||
created = 0;
|
||||
}
|
||||
|
||||
// created
|
||||
memcpy(copyAt, &created, sizeof(created));
|
||||
copyAt += sizeof(created);
|
||||
sizeOut += sizeof(created);
|
||||
|
||||
// lastUpdated
|
||||
memcpy(copyAt, &details[i].lastUpdated, sizeof(details[i].lastUpdated));
|
||||
copyAt += sizeof(details[i].lastUpdated);
|
||||
sizeOut += sizeof(details[i].lastUpdated);
|
||||
|
||||
// lastEdited
|
||||
memcpy(copyAt, &details[i].lastEdited, sizeof(details[i].lastEdited));
|
||||
copyAt += sizeof(details[i].lastEdited);
|
||||
sizeOut += sizeof(details[i].lastEdited);
|
||||
|
||||
// radius
|
||||
memcpy(copyAt, &details[i].radius, sizeof(details[i].radius));
|
||||
copyAt += sizeof(details[i].radius);
|
||||
|
@ -405,7 +382,6 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
|||
if (wantDebugging) {
|
||||
printf("encodeParticleEditMessageDetails()....\n");
|
||||
printf("Particle id :%u\n", details[i].id);
|
||||
printf(" last updated:%llu\n", details[i].lastUpdated);
|
||||
printf(" nextID:%u\n", _nextID);
|
||||
}
|
||||
}
|
||||
|
@ -418,21 +394,30 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
|||
|
||||
|
||||
void Particle::update() {
|
||||
|
||||
uint64_t now = usecTimestampNow();
|
||||
uint64_t elapsed = now - _lastUpdated;
|
||||
uint64_t USECS_PER_SECOND = 1000 * 1000;
|
||||
uint64_t elapsed = now - _lastSimulated;
|
||||
float timeElapsed = (float)((float)elapsed/(float)USECS_PER_SECOND);
|
||||
|
||||
|
||||
// calculate our default shouldDie state... then allow script to change it if it wants...
|
||||
float velocityScalar = glm::length(getVelocity());
|
||||
const float STILL_MOVING = 0.05 / TREE_SCALE;
|
||||
bool isStillMoving = (velocityScalar > STILL_MOVING);
|
||||
const uint64_t REALLY_OLD = 30 * 1000 * 1000;
|
||||
const float REALLY_OLD = 30.0f; // 30 seconds
|
||||
bool isReallyOld = (getLifetime() > REALLY_OLD);
|
||||
bool isInHand = getInHand();
|
||||
bool shouldDie = !isInHand && !isStillMoving && isReallyOld;
|
||||
setShouldDie(shouldDie);
|
||||
|
||||
|
||||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
printf("Particle::update()... timeElapsed: %f lifeTime:%f editedAgo:%f "
|
||||
"isInHand:%s isStillMoveing:%s isReallyOld:%s shouldDie:%s\n",
|
||||
timeElapsed, getLifetime(), getEditedAgo(), debug::valueOf(isInHand), debug::valueOf(isStillMoving),
|
||||
debug::valueOf(isReallyOld), debug::valueOf(shouldDie));
|
||||
}
|
||||
|
||||
runScript(); // allow the javascript to alter our state
|
||||
|
||||
// If the ball is in hand, it doesn't move or have gravity effect it
|
||||
|
@ -454,7 +439,7 @@ void Particle::update() {
|
|||
//printf("applying damping to Particle timeElapsed=%f\n",timeElapsed);
|
||||
}
|
||||
|
||||
_lastUpdated = now;
|
||||
_lastSimulated = now;
|
||||
}
|
||||
|
||||
void Particle::runScript() {
|
||||
|
@ -484,3 +469,19 @@ void Particle::runScript() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Particle::setLifetime(float lifetime) {
|
||||
uint64_t lifetimeInUsecs = lifetime * USECS_PER_SECOND;
|
||||
_created = usecTimestampNow() - lifetimeInUsecs;
|
||||
}
|
||||
|
||||
void Particle::setEditedAgo(float editedAgo) {
|
||||
uint64_t editedAgoInUsecs = editedAgo * USECS_PER_SECOND;
|
||||
_edited = usecTimestampNow() - editedAgoInUsecs;
|
||||
}
|
||||
|
||||
void Particle::copyChangedProperties(const Particle& other) {
|
||||
float lifetime = getLifetime();
|
||||
*this = other;
|
||||
setLifetime(lifetime);
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@ const uint32_t UNKNOWN_TOKEN = 0xFFFFFFFF;
|
|||
class ParticleDetail {
|
||||
public:
|
||||
uint32_t id;
|
||||
uint64_t lastUpdated;
|
||||
uint64_t lastEdited;
|
||||
glm::vec3 position;
|
||||
float radius;
|
||||
rgbColor color;
|
||||
|
@ -68,10 +66,11 @@ public:
|
|||
const glm::vec3& getGravity() const { return _gravity; }
|
||||
bool getInHand() const { return _inHand; }
|
||||
float getDamping() const { return _damping; }
|
||||
uint64_t getCreated() const { return _created; }
|
||||
uint64_t getLifetime() const { return usecTimestampNow() - _created; }
|
||||
uint64_t getLastUpdated() const { return _lastUpdated; }
|
||||
uint64_t getLastEdited() const { return _lastEdited; }
|
||||
|
||||
/// lifetime of the particle in seconds
|
||||
float getLifetime() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; }
|
||||
/// seconds since last edited
|
||||
float getEditedAgo() const { return (float)(usecTimestampNow() - _edited) / (float)USECS_PER_SECOND; }
|
||||
uint32_t getID() const { return _id; }
|
||||
bool getShouldDie() const { return _shouldDie; }
|
||||
QString getUpdateScript() const { return _updateScript; }
|
||||
|
@ -93,7 +92,6 @@ public:
|
|||
void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; }
|
||||
void setUpdateScript(QString updateScript) { _updateScript = updateScript; }
|
||||
void setCreatorTokenID(uint32_t creatorTokenID) { _creatorTokenID = creatorTokenID; }
|
||||
void setCreated(uint64_t created) { _created = created; }
|
||||
|
||||
bool appendParticleData(OctreePacketData* packetData) const;
|
||||
int readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args);
|
||||
|
@ -105,20 +103,24 @@ public:
|
|||
void update();
|
||||
|
||||
void debugDump() const;
|
||||
|
||||
// similar to assignment/copy, but it handles keeping lifetime accurate
|
||||
void copyChangedProperties(const Particle& other);
|
||||
|
||||
protected:
|
||||
void runScript();
|
||||
static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3);
|
||||
static void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3);
|
||||
static QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color);
|
||||
static void xColorFromScriptValue(const QScriptValue &object, xColor& color);
|
||||
|
||||
void setLifetime(float lifetime);
|
||||
void setEditedAgo(float editedAgo);
|
||||
|
||||
glm::vec3 _position;
|
||||
rgbColor _color;
|
||||
float _radius;
|
||||
glm::vec3 _velocity;
|
||||
uint64_t _lastUpdated;
|
||||
uint64_t _created;
|
||||
uint64_t _lastEdited;
|
||||
uint32_t _id;
|
||||
static uint32_t _nextID;
|
||||
bool _shouldDie;
|
||||
|
@ -129,6 +131,12 @@ protected:
|
|||
|
||||
uint32_t _creatorTokenID;
|
||||
bool _newlyCreated;
|
||||
|
||||
// these are never included in wire time
|
||||
uint64_t _lastSimulated;
|
||||
uint64_t _created;
|
||||
uint64_t _edited;
|
||||
|
||||
};
|
||||
|
||||
class ParticleScriptObject : public QObject {
|
||||
|
@ -144,9 +152,7 @@ public slots:
|
|||
float getDamping() const { return _particle->getDamping(); }
|
||||
float getRadius() const { return _particle->getRadius(); }
|
||||
bool getShouldDie() { return _particle->getShouldDie(); }
|
||||
float getCreated() const { return ((float)_particle->getCreated() / (float)USECS_PER_SECOND); }
|
||||
float getLifetime() const { return ((float)_particle->getLifetime() / (float)USECS_PER_SECOND); }
|
||||
|
||||
float getLifetime() const { return _particle->getLifetime(); }
|
||||
|
||||
void setPosition(glm::vec3 value) { _particle->setPosition(value); }
|
||||
void setVelocity(glm::vec3 value) { _particle->setVelocity(value); }
|
||||
|
|
|
@ -44,8 +44,7 @@ void ParticleEditHandle::createParticle(glm::vec3 position, float radius, xColor
|
|||
glm::vec3 gravity, float damping, bool inHand, QString updateScript) {
|
||||
|
||||
// setup a ParticleDetail struct with the data
|
||||
uint64_t now = usecTimestampNow();
|
||||
ParticleDetail addParticleDetail = { NEW_PARTICLE, now, now,
|
||||
ParticleDetail addParticleDetail = { NEW_PARTICLE,
|
||||
position, radius, {color.red, color.green, color.blue },
|
||||
velocity, gravity, damping, inHand, updateScript, _creatorTokenID };
|
||||
|
||||
|
@ -70,8 +69,7 @@ bool ParticleEditHandle::updateParticle(glm::vec3 position, float radius, xColor
|
|||
}
|
||||
|
||||
// setup a ParticleDetail struct with the data
|
||||
uint64_t now = usecTimestampNow();
|
||||
ParticleDetail newParticleDetail = { _id, now, now,
|
||||
ParticleDetail newParticleDetail = { _id,
|
||||
position, radius, {color.red, color.green, color.blue },
|
||||
velocity, gravity, damping, inHand, updateScript, _creatorTokenID };
|
||||
|
||||
|
|
|
@ -22,8 +22,7 @@ unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, fl
|
|||
_nextCreatorTokenID++;
|
||||
|
||||
// setup a ParticleDetail struct with the data
|
||||
uint64_t now = usecTimestampNow();
|
||||
ParticleDetail addParticleDetail = { NEW_PARTICLE, now, now,
|
||||
ParticleDetail addParticleDetail = { NEW_PARTICLE,
|
||||
position, radius, {color.red, color.green, color.blue }, velocity,
|
||||
gravity, damping, inHand, updateScript, creatorTokenID };
|
||||
|
||||
|
|
|
@ -119,33 +119,19 @@ bool ParticleTreeElement::updateParticle(const Particle& particle) {
|
|||
uint16_t numberOfParticles = _particles.size();
|
||||
for (uint16_t i = 0; i < numberOfParticles; i++) {
|
||||
if (_particles[i].getID() == particle.getID()) {
|
||||
int difference = _particles[i].getLastUpdated() - particle.getLastUpdated();
|
||||
|
||||
bool changedOnServer = _particles[i].getLastEdited() < particle.getLastEdited();
|
||||
bool localOlder = _particles[i].getLastUpdated() < particle.getLastUpdated();
|
||||
|
||||
if (changedOnServer || localOlder) {
|
||||
|
||||
bool changedOnServer = _particles[i].getEditedAgo() > particle.getEditedAgo();
|
||||
if (changedOnServer) {
|
||||
if (wantDebug) {
|
||||
printf("local particle [id:%d] %s and %s than server particle by %d, particle.isNewlyCreated()=%s\n",
|
||||
printf("local particle [id:%d] %s, particle.isNewlyCreated()=%s\n",
|
||||
particle.getID(), (changedOnServer ? "CHANGED" : "same"),
|
||||
(localOlder ? "OLDER" : "NEWER"),
|
||||
difference, debug::valueOf(particle.isNewlyCreated()) );
|
||||
debug::valueOf(particle.isNewlyCreated()) );
|
||||
}
|
||||
|
||||
uint64_t actuallyCreated = particle.getCreated();
|
||||
if (!particle.isNewlyCreated()) {
|
||||
actuallyCreated = _particles[i].getCreated();
|
||||
}
|
||||
_particles[i] = particle;
|
||||
_particles[i].setCreated(actuallyCreated);
|
||||
_particles[i].copyChangedProperties(particle);
|
||||
} else {
|
||||
if (wantDebug) {
|
||||
printf(">>> NO CHANGE <<< -- local particle [id:%d] %s and %s than server particle by %d, "
|
||||
"particle.isNewlyCreated()=%s\n",
|
||||
printf(">>> NO CHANGE <<< -- local particle [id:%d] %s particle.isNewlyCreated()=%s\n",
|
||||
particle.getID(), (changedOnServer ? "CHANGED" : "same"),
|
||||
(localOlder ? "OLDER" : "NEWER"),
|
||||
difference, debug::valueOf(particle.isNewlyCreated()) );
|
||||
debug::valueOf(particle.isNewlyCreated()) );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -54,7 +54,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) {
|
|||
return 2;
|
||||
|
||||
case PACKET_TYPE_PARTICLE_DATA:
|
||||
return 3;
|
||||
return 4;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -30,10 +30,15 @@ uint64_t usecTimestamp(const timeval *time) {
|
|||
return (time->tv_sec * 1000000 + time->tv_usec);
|
||||
}
|
||||
|
||||
int usecTimestampNowAdjust = 0;
|
||||
void usecTimestampNowForceClockSkew(int clockSkew) {
|
||||
::usecTimestampNowAdjust = clockSkew;
|
||||
}
|
||||
|
||||
uint64_t usecTimestampNow() {
|
||||
timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
return (now.tv_sec * 1000000 + now.tv_usec);
|
||||
return (now.tv_sec * 1000000 + now.tv_usec) + ::usecTimestampNowAdjust;
|
||||
}
|
||||
|
||||
float randFloat () {
|
||||
|
|
|
@ -56,6 +56,7 @@ static const uint64_t USECS_PER_SECOND = 1000 * 1000;
|
|||
|
||||
uint64_t usecTimestamp(const timeval *time);
|
||||
uint64_t usecTimestampNow();
|
||||
void usecTimestampNowForceClockSkew(int clockSkew);
|
||||
|
||||
float randFloat();
|
||||
int randIntInRange (int min, int max);
|
||||
|
|
Loading…
Reference in a new issue