Merge branch 'master' of https://github.com/worklist/hifi into 19597

This commit is contained in:
Stojce Slavkovski 2014-05-01 01:41:11 +02:00
commit d6b7dac649
33 changed files with 891 additions and 491 deletions

View file

@ -19,6 +19,12 @@ function mouseMoveEvent(event) {
print("computePickRay direction=" + pickRay.direction.x + ", " + pickRay.direction.y + ", " + pickRay.direction.z);
var pickRay = Camera.computePickRay(event.x, event.y);
var intersection = Voxels.findRayIntersection(pickRay);
if (!intersection.accurate) {
print(">>> NOTE: intersection not accurate. will try calling Voxels.findRayIntersectionBlocking()");
intersection = Voxels.findRayIntersectionBlocking(pickRay);
print(">>> AFTER BLOCKING CALL intersection.accurate=" + intersection.accurate);
}
if (intersection.intersects) {
print("intersection voxel.red/green/blue=" + intersection.voxel.red + ", "
+ intersection.voxel.green + ", " + intersection.voxel.blue);

View file

@ -4,22 +4,22 @@
<context>
<name>Application</name>
<message>
<location filename="src/Application.cpp" line="1380"/>
<location filename="src/Application.cpp" line="1481"/>
<source>Export Voxels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="1381"/>
<location filename="src/Application.cpp" line="1482"/>
<source>Sparse Voxel Octree Files (*.svo)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="3608"/>
<location filename="src/Application.cpp" line="3465"/>
<source>Open Script</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="3609"/>
<location filename="src/Application.cpp" line="3466"/>
<source>JavaScript Files (*.js)</source>
<translation type="unfinished"></translation>
</message>
@ -113,18 +113,18 @@
<context>
<name>Menu</name>
<message>
<location filename="src/Menu.cpp" line="460"/>
<location filename="src/Menu.cpp" line="554"/>
<source>Open .ini config file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Menu.cpp" line="462"/>
<location filename="src/Menu.cpp" line="474"/>
<location filename="src/Menu.cpp" line="556"/>
<location filename="src/Menu.cpp" line="568"/>
<source>Text files (*.ini)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Menu.cpp" line="472"/>
<location filename="src/Menu.cpp" line="566"/>
<source>Save .ini config file</source>
<translation type="unfinished"></translation>
</message>
@ -271,4 +271,57 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>RunningScriptsWidget</name>
<message>
<location filename="ui/runningScriptsWidget.ui" line="14"/>
<location filename="../build/interface/ui_runningScriptsWidget.h" line="140"/>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/runningScriptsWidget.ui" line="39"/>
<location filename="../build/interface/ui_runningScriptsWidget.h" line="141"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:18pt;&quot;&gt;Running Scripts&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/runningScriptsWidget.ui" line="63"/>
<location filename="../build/interface/ui_runningScriptsWidget.h" line="142"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Currently running&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/runningScriptsWidget.ui" line="89"/>
<location filename="../build/interface/ui_runningScriptsWidget.h" line="143"/>
<source>Reload all</source>
<oldsource>Reload All</oldsource>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/runningScriptsWidget.ui" line="116"/>
<location filename="../build/interface/ui_runningScriptsWidget.h" line="144"/>
<source>Stop all</source>
<oldsource>Stop All</oldsource>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/runningScriptsWidget.ui" line="137"/>
<location filename="../build/interface/ui_runningScriptsWidget.h" line="145"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Recently loaded&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/runningScriptsWidget.ui" line="154"/>
<location filename="../build/interface/ui_runningScriptsWidget.h" line="146"/>
<source>(click a script or use the 1-9 keys to load and run it)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/runningScriptsWidget.ui" line="202"/>
<location filename="../build/interface/ui_runningScriptsWidget.h" line="148"/>
<source>There are no scripts currently running.</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Your_Icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="23 23 54 54" enable-background="new 23 23 54 54" xml:space="preserve">
<polygon fill="#FFFFFF" points="77,41 59,41 59,23 41,23 41,41 23,41 23,59 41,59 41,77 59,77 59,59 77,59 "/>
</svg>

After

Width:  |  Height:  |  Size: 565 B

View file

@ -30,7 +30,6 @@
#include <QImage>
#include <QInputDialog>
#include <QKeyEvent>
#include <QMainWindow>
#include <QMenuBar>
#include <QMouseEvent>
#include <QNetworkAccessManager>
@ -132,7 +131,7 @@ QString& Application::resourcesPath() {
Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
QApplication(argc, argv),
_window(new QMainWindow(desktop())),
_window(new MainWindow(desktop())),
_glWidget(new GLCanvas()),
_nodeThread(new QThread(this)),
_datagramProcessor(),
@ -164,11 +163,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
_packetsPerSecond(0),
_bytesPerSecond(0),
_previousScriptLocation(),
_logger(new FileLogger(this))
_logger(new FileLogger(this)),
_runningScriptsWidget(new RunningScriptsWidget(_window)),
_runningScriptsWidgetWasVisible(false)
{
// init GnuTLS for DTLS with domain-servers
DTLSClientSession::globalInit();
// read the ApplicationInfo.ini file for Name/Version/Domain information
QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat);
@ -334,7 +335,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
LocalVoxelsList::getInstance()->addPersistantTree(DOMAIN_TREE_NAME, _voxels.getTree());
LocalVoxelsList::getInstance()->addPersistantTree(CLIPBOARD_TREE_NAME, &_clipboard);
_window->addDockWidget(Qt::NoDockWidgetArea, _runningScriptsWidget = new RunningScriptsWidget());
_runningScriptsWidget->setRunningScripts(getRunningScripts());
connect(_runningScriptsWidget, &RunningScriptsWidget::stopScriptName, this, &Application::stopScript);
@ -345,16 +345,22 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
// clear the scripts, and set out script to our default scripts
clearScriptsBeforeRunning();
loadScript("http://public.highfidelity.io/scripts/defaultScripts.js");
QMutexLocker locker(&_settingsMutex);
_settings->setValue("firstRun",QVariant(false));
} else {
// do this as late as possible so that all required subsystems are inialized
loadScripts();
QMutexLocker locker(&_settingsMutex);
_previousScriptLocation = _settings->value("LastScriptLocation", QVariant("")).toString();
}
connect(_window, &MainWindow::windowGeometryChanged,
_runningScriptsWidget, &RunningScriptsWidget::setBoundary);
//When -url in command line, teleport to location
urlGoTo(argc, constArgv);
}
Application::~Application() {
@ -363,11 +369,11 @@ Application::~Application() {
// make sure we don't call the idle timer any more
delete idleTimer;
_sharedVoxelSystem.changeTree(new VoxelTree);
saveSettings();
delete _voxelImporter;
// let the avatar mixer know we're out
@ -400,14 +406,14 @@ Application::~Application() {
delete _glWidget;
AccountManager::getInstance().destroy();
DTLSClientSession::globalDeinit();
}
void Application::saveSettings() {
Menu::getInstance()->saveSettings();
_rearMirrorTools->saveSettings(_settings);
if (_voxelImporter) {
_voxelImporter->saveSettings(_settings);
}
@ -574,7 +580,7 @@ void Application::paintGL() {
pushback = qMin(pushback, MAX_PUSHBACK * _myAvatar->getScale());
const float BASE_PUSHBACK_FOCAL_LENGTH = 0.5f;
pushbackFocalLength = BASE_PUSHBACK_FOCAL_LENGTH * _myAvatar->getScale();
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
_myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing
_myCamera.setTargetPosition(_myAvatar->getUprightHeadPosition());
@ -587,7 +593,7 @@ void Application::paintGL() {
_myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _myAvatar->getScale());
_myCamera.setTargetPosition(_myAvatar->getPosition() + glm::vec3(0, headHeight, 0));
_myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f)));
// if the head would intersect the near clip plane, we must push the camera out
glm::vec3 relativePosition = glm::inverse(_myCamera.getTargetRotation()) *
(eyePosition - _myCamera.getTargetPosition());
@ -596,7 +602,7 @@ void Application::paintGL() {
pushback = relativePosition.z + pushbackRadius - _myCamera.getDistance();
pushbackFocalLength = _myCamera.getDistance();
}
// handle pushback, if any
if (pushbackFocalLength > 0.0f) {
const float PUSHBACK_DECAY = 0.5f;
@ -1275,7 +1281,7 @@ void Application::timer() {
if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) {
sendPingPackets();
}
float diffTime = (float)_timerStart.nsecsElapsed() / 1000000000.0f;
_fps = (float)_frameCount / diffTime;
@ -1676,7 +1682,7 @@ void Application::init() {
connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView()));
connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView()));
connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors()));
// set up our audio reflector
_audioReflector.setMyAvatar(getAvatar());
_audioReflector.setVoxels(_voxels.getTree());
@ -1685,7 +1691,7 @@ void Application::init() {
connect(getAudio(), &Audio::processInboundAudio, &_audioReflector, &AudioReflector::processInboundAudio,Qt::DirectConnection);
connect(getAudio(), &Audio::processLocalAudio, &_audioReflector, &AudioReflector::processLocalAudio,Qt::DirectConnection);
connect(getAudio(), &Audio::preProcessOriginalInboundAudio, &_audioReflector,
connect(getAudio(), &Audio::preProcessOriginalInboundAudio, &_audioReflector,
&AudioReflector::preProcessOriginalInboundAudio,Qt::DirectConnection);
// save settings when avatar changes
@ -1819,7 +1825,7 @@ void Application::updateMyAvatarLookAtPosition() {
if (tracker) {
float eyePitch = tracker->getEstimatedEyePitch();
float eyeYaw = tracker->getEstimatedEyeYaw();
// deflect using Faceshift gaze data
glm::vec3 origin = _myAvatar->getHead()->calculateAverageEyePosition();
float pitchSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? -1.0f : 1.0f;
@ -1906,7 +1912,7 @@ void Application::updateCamera(float deltaTime) {
PerformanceWarning warn(showWarnings, "Application::updateCamera()");
if (!OculusManager::isConnected() && !TV3DManager::isConnected() &&
Menu::getInstance()->isOptionChecked(MenuOption::OffAxisProjection)) {
Menu::getInstance()->isOptionChecked(MenuOption::OffAxisProjection)) {
FaceTracker* tracker = getActiveFaceTracker();
if (tracker) {
const float EYE_OFFSET_SCALE = 0.025f;
@ -2461,7 +2467,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
// disable specular lighting for ground and voxels
glMaterialfv(GL_FRONT, GL_SPECULAR, NO_SPECULAR_COLOR);
// draw the audio reflector overlay
_audioReflector.render();
@ -2619,7 +2625,7 @@ void Application::displayOverlay() {
const float LOG2_LOUDNESS_FLOOR = 11.f;
float audioLevel = 0.f;
float loudness = _audio.getLastInputLoudness() + 1.f;
_trailingAudioLoudness = AUDIO_METER_AVERAGING * _trailingAudioLoudness + (1.f - AUDIO_METER_AVERAGING) * loudness;
float log2loudness = log(_trailingAudioLoudness) / LOG2;
@ -2631,9 +2637,8 @@ void Application::displayOverlay() {
if (audioLevel > AUDIO_METER_SCALE_WIDTH) {
audioLevel = AUDIO_METER_SCALE_WIDTH;
}
bool isClipping = ((_audio.getTimeSinceLastClip() > 0.f) && (_audio.getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME));
if ((_audio.getTimeSinceLastClip() > 0.f) && (_audio.getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)) {
const float MAX_MAGNITUDE = 0.7f;
float magnitude = MAX_MAGNITUDE * (1 - _audio.getTimeSinceLastClip() / CLIPPING_INDICATOR_TIME);
@ -3271,7 +3276,7 @@ void Application::loadScripts() {
loadScript(string);
}
}
QMutexLocker locker(&_settingsMutex);
_settings->endArray();
}
@ -3326,31 +3331,23 @@ void Application::reloadAllScripts() {
}
}
void Application::toggleRunningScriptsWidget()
{
if (!_runningScriptsWidget->toggleViewAction()->isChecked()) {
_runningScriptsWidget->move(_window->geometry().topLeft().x(), _window->geometry().topLeft().y());
_runningScriptsWidget->resize(0, _window->height());
_runningScriptsWidget->toggleViewAction()->trigger();
_runningScriptsWidget->grabKeyboard();
void Application::manageRunningScriptsWidgetVisibility(bool shown) {
if (_runningScriptsWidgetWasVisible && shown) {
_runningScriptsWidget->show();
} else if (_runningScriptsWidgetWasVisible && !shown) {
_runningScriptsWidget->hide();
}
}
QPropertyAnimation* slideAnimation = new QPropertyAnimation(_runningScriptsWidget, "geometry", _runningScriptsWidget);
slideAnimation->setStartValue(_runningScriptsWidget->geometry());
slideAnimation->setEndValue(QRect(_window->geometry().topLeft().x(), _window->geometry().topLeft().y(),
310, _runningScriptsWidget->height()));
slideAnimation->setDuration(250);
slideAnimation->start(QAbstractAnimation::DeleteWhenStopped);
void Application::toggleRunningScriptsWidget() {
if (_runningScriptsWidgetWasVisible) {
_runningScriptsWidget->hide();
_runningScriptsWidgetWasVisible = false;
} else {
_runningScriptsWidget->releaseKeyboard();
QPropertyAnimation* slideAnimation = new QPropertyAnimation(_runningScriptsWidget, "geometry", _runningScriptsWidget);
slideAnimation->setStartValue(_runningScriptsWidget->geometry());
slideAnimation->setEndValue(QRect(_window->geometry().topLeft().x(), _window->geometry().topLeft().y(),
0, _runningScriptsWidget->height()));
slideAnimation->setDuration(250);
slideAnimation->start(QAbstractAnimation::DeleteWhenStopped);
QTimer::singleShot(260, _runningScriptsWidget->toggleViewAction(), SLOT(trigger()));
_runningScriptsWidget->setBoundary(QRect(_window->geometry().topLeft(),
_window->size()));
_runningScriptsWidget->show();
_runningScriptsWidgetWasVisible = true;
}
}
@ -3360,7 +3357,7 @@ void Application::uploadFST(bool isHead) {
thread->connect(uploader, SIGNAL(destroyed()), SLOT(quit()));
thread->connect(thread, SIGNAL(finished()), SLOT(deleteLater()));
uploader->connect(thread, SIGNAL(started()), SLOT(send()));
thread->start();
}
@ -3458,7 +3455,7 @@ void Application::loadDialog() {
_previousScriptLocation = fileNameString;
QMutexLocker locker(&_settingsMutex);
_settings->setValue("LastScriptLocation", _previousScriptLocation);
loadScript(fileNameString);
}
}
@ -3595,7 +3592,7 @@ void Application::urlGoTo(int argc, const char * constArgv[]) {
QString orientation = urlParts.count() > 2 ? urlParts[2] : QString();
Menu::goToDomain(domain);
// goto either @user, #place, or x-xx,y-yy,z-zz
// style co-ordinate.
Menu::goTo(destination);

View file

@ -25,6 +25,7 @@
#include <QSet>
#include <QSettings>
#include <QStringList>
#include <QHash>
#include <QTouchEvent>
#include <QUndoStack>
@ -38,6 +39,7 @@
#include <ViewFrustum.h>
#include <VoxelEditPacketSender.h>
#include "MainWindow.h"
#include "Audio.h"
#include "AudioReflector.h"
#include "BuckyBalls.h"
@ -85,7 +87,6 @@ class QAction;
class QActionGroup;
class QGLWidget;
class QKeyEvent;
class QMainWindow;
class QMouseEvent;
class QNetworkAccessManager;
class QSettings;
@ -136,6 +137,7 @@ public:
void keyReleaseEvent(QKeyEvent* event);
void focusOutEvent(QFocusEvent* event);
void focusInEvent(QFocusEvent* event);
void mouseMoveEvent(QMouseEvent* event);
void mousePressEvent(QMouseEvent* event);
@ -192,10 +194,10 @@ public:
/// if you need to access the application settings, use lockSettings()/unlockSettings()
QSettings* lockSettings() { _settingsMutex.lock(); return _settings; }
void unlockSettings() { _settingsMutex.unlock(); }
void saveSettings();
QMainWindow* getWindow() { return _window; }
MainWindow* getWindow() { return _window; }
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); }
void unlockOctreeSceneStats() { _octreeSceneStatsLock.unlock(); }
@ -312,6 +314,8 @@ private slots:
void parseVersionXml();
void manageRunningScriptsWidgetVisibility(bool shown);
private:
void resetCamerasOnResizeGL(Camera& camera, int width, int height);
void updateProjectionMatrix();
@ -372,7 +376,7 @@ private:
void displayRearMirrorTools();
QMainWindow* _window;
MainWindow* _window;
GLCanvas* _glWidget; // our GLCanvas has a couple extra features
BandwidthMeter _bandwidthMeter;
@ -386,7 +390,7 @@ private:
int _numChangedSettings;
QUndoStack _undoStack;
glm::vec3 _gravity;
// Frame Rate Measurement
@ -431,7 +435,7 @@ private:
Faceplus _faceplus;
Faceshift _faceshift;
Visage _visage;
SixenseManager _sixenseManager;
Camera _myCamera; // My view onto the world
@ -519,9 +523,11 @@ private:
TouchEvent _lastTouchEvent;
Overlays _overlays;
AudioReflector _audioReflector;
RunningScriptsWidget* _runningScriptsWidget;
QHash<QString, ScriptEngine*> _scriptEnginesHash;
bool _runningScriptsWidgetWasVisible;
};
#endif // hifi_Application_h

View file

@ -24,8 +24,8 @@ GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer)),
{
}
bool GLCanvas::isThrottleRendering() const {
return _throttleRendering || Application::getInstance()->getWindow()->isMinimized();
bool GLCanvas::isThrottleRendering() const {
return _throttleRendering || Application::getInstance()->getWindow()->isMinimized();
}
void GLCanvas::initializeGL() {
@ -34,7 +34,7 @@ void GLCanvas::initializeGL() {
setAcceptDrops(true);
connect(Application::getInstance(), SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(activeChanged(Qt::ApplicationState)));
connect(&_frameTimer, SIGNAL(timeout()), this, SLOT(throttleRender()));
// Note, we *DO NOT* want Qt to automatically swap buffers for us. This results in the "ringing" bug mentioned in WL#19514 when we're throttling the framerate.
setAutoBufferSwap(false);
}
@ -81,14 +81,14 @@ void GLCanvas::activeChanged(Qt::ApplicationState state) {
_frameTimer.stop();
_throttleRendering = false;
break;
case Qt::ApplicationSuspended:
case Qt::ApplicationHidden:
// If we're hidden or are about to suspend, don't render anything.
_throttleRendering = false;
_frameTimer.stop();
break;
default:
// Otherwise, throttle.
if (!_throttleRendering) {

View file

@ -22,31 +22,31 @@ public:
GLCanvas();
bool isThrottleRendering() const;
protected:
QTimer _frameTimer;
bool _throttleRendering;
int _idleRenderInterval;
virtual void initializeGL();
virtual void paintGL();
virtual void resizeGL(int width, int height);
virtual void keyPressEvent(QKeyEvent* event);
virtual void keyReleaseEvent(QKeyEvent* event);
virtual void focusOutEvent(QFocusEvent* event);
virtual void mouseMoveEvent(QMouseEvent* event);
virtual void mousePressEvent(QMouseEvent* event);
virtual void mouseReleaseEvent(QMouseEvent* event);
virtual bool event(QEvent* event);
virtual void wheelEvent(QWheelEvent* event);
virtual void dragEnterEvent(QDragEnterEvent *event);
virtual void dropEvent(QDropEvent* event);
private slots:
void activeChanged(Qt::ApplicationState state);
void throttleRender();

View file

@ -0,0 +1,67 @@
//
// MainWindow.cpp
// interface
//
// Created by Mohammed Nafees on 04/06/2014.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "MainWindow.h"
#include <QEvent>
#include <QMoveEvent>
#include <QResizeEvent>
#include <QShowEvent>
#include <QHideEvent>
#include <QWindowStateChangeEvent>
MainWindow::MainWindow(QWidget* parent) :
QMainWindow(parent) {
}
void MainWindow::moveEvent(QMoveEvent* event) {
emit windowGeometryChanged(QRect(event->pos(), size()));
QMainWindow::moveEvent(event);
}
void MainWindow::resizeEvent(QResizeEvent* event) {
emit windowGeometryChanged(QRect(QPoint(x(), y()), event->size()));
QMainWindow::resizeEvent(event);
}
void MainWindow::showEvent(QShowEvent* event) {
if (event->spontaneous()) {
emit windowShown(true);
}
QMainWindow::showEvent(event);
}
void MainWindow::hideEvent(QHideEvent* event) {
if (event->spontaneous()) {
emit windowShown(false);
}
QMainWindow::hideEvent(event);
}
void MainWindow::changeEvent(QEvent* event) {
if (event->type() == QEvent::WindowStateChange) {
QWindowStateChangeEvent* stateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
if ((stateChangeEvent->oldState() == Qt::WindowNoState ||
stateChangeEvent->oldState() == Qt::WindowMaximized) &&
windowState() == Qt::WindowMinimized) {
emit windowShown(false);
} else {
emit windowShown(true);
}
} else if (event->type() == QEvent::ActivationChange) {
if (isActiveWindow()) {
emit windowShown(true);
} else {
emit windowShown(false);
}
}
QMainWindow::changeEvent(event);
}

View file

@ -0,0 +1,35 @@
//
// MainWindow.h
// interface
//
// Created by Mohammed Nafees on 04/06/2014.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef __hifi__MainWindow__
#define __hifi__MainWindow__
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget* parent = NULL);
signals:
void windowGeometryChanged(QRect geometry);
void windowShown(bool shown);
protected:
virtual void moveEvent(QMoveEvent* event);
virtual void resizeEvent(QResizeEvent* event);
virtual void showEvent(QShowEvent* event);
virtual void hideEvent(QHideEvent* event);
virtual void changeEvent(QEvent* event);
};
#endif /* defined(__hifi__MainWindow__) */

View file

@ -170,12 +170,12 @@ Menu::Menu() :
QMenu* editMenu = addMenu("Edit");
QUndoStack* undoStack = Application::getInstance()->getUndoStack();
QAction* undoAction = undoStack->createUndoAction(editMenu);
undoAction->setShortcut(Qt::CTRL | Qt::Key_Z);
addActionToQMenuAndActionHash(editMenu, undoAction);
QAction* redoAction = undoStack->createRedoAction(editMenu);
redoAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_Z);
addActionToQMenuAndActionHash(editMenu, redoAction);
@ -325,7 +325,7 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Visage, 0, true,
appInstance->getVisage(), SLOT(updateEnabled()));
#endif
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::GlowWhenSpeaking, 0, true);
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::ChatCircling, 0, false);
@ -728,31 +728,31 @@ QAction* Menu::addActionToQMenuAndActionHash(QMenu* destinationMenu,
QAction::MenuRole role,
int menuItemLocation) {
QAction* actionBefore = NULL;
if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) {
actionBefore = destinationMenu->actions()[menuItemLocation];
}
if (!actionName.isEmpty()) {
action->setText(actionName);
}
if (shortcut != 0) {
action->setShortcut(shortcut);
}
if (role != QAction::NoRole) {
action->setMenuRole(role);
}
if (!actionBefore) {
destinationMenu->addAction(action);
} else {
destinationMenu->insertAction(actionBefore, action);
}
_actionHash.insert(action->text(), action);
return action;
}
@ -818,7 +818,6 @@ void sendFakeEnterEvent() {
QCoreApplication::sendEvent(glWidget, &enterEvent);
}
const int QLINE_MINIMUM_WIDTH = 400;
const float DIALOG_RATIO_OF_WINDOW = 0.30f;
void Menu::loginForCurrentDomain() {
@ -924,7 +923,7 @@ void Menu::goTo() {
QString orientation = urlParts.count() > 2 ? urlParts[2] : QString();
goToDomain(domain);
// goto either @user, #place, or x-xx,y-yy,z-zz
// style co-ordinate.
goTo(destination);
@ -1250,7 +1249,7 @@ void Menu::autoAdjustLOD(float currentFPS) {
_avatarLODDistanceMultiplier - DISTANCE_DECREASE_RATE);
}
}
bool changed = false;
quint64 elapsed = now - _lastAdjust;

View file

@ -30,7 +30,7 @@
const float ADJUST_LOD_DOWN_FPS = 40.0;
const float ADJUST_LOD_UP_FPS = 55.0;
const float DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS = 30.0f;
const float DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS = 30.0f;
const quint64 ADJUST_LOD_DOWN_DELAY = 1000 * 1000 * 5;
const quint64 ADJUST_LOD_UP_DELAY = ADJUST_LOD_DOWN_DELAY * 2;
@ -79,7 +79,7 @@ public:
void triggerOption(const QString& menuOption);
QAction* getActionForOption(const QString& menuOption);
float getAudioJitterBufferSamples() const { return _audioJitterBufferSamples; }
void setAudioJitterBufferSamples(float audioJitterBufferSamples) { _audioJitterBufferSamples = audioJitterBufferSamples; }
float getFieldOfView() const { return _fieldOfView; }
@ -133,7 +133,7 @@ public:
const QKeySequence& shortcut = 0,
QAction::MenuRole role = QAction::NoRole,
int menuItemLocation = UNSPECIFIED_POSITION);
void removeAction(QMenu* menu, const QString& actionName);
bool static goToDestination(QString destination);
@ -276,8 +276,8 @@ namespace MenuOption {
const QString AudioSpatialProcessingWithDiffusions = "With Diffusions";
const QString AudioSpatialProcessingDontDistanceAttenuate = "Don't calculate distance attenuation";
const QString AudioSpatialProcessingAlternateDistanceAttenuate = "Alternate distance attenuation";
const QString Avatars = "Avatars";
const QString Bandwidth = "Bandwidth Display";

View file

@ -206,13 +206,13 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
GLOW_FROM_AVERAGE_LOUDNESS = 0.0f;
}
Glower glower(_moving && distanceToTarget > GLOW_DISTANCE && renderMode == NORMAL_RENDER_MODE
float glowLevel = _moving && distanceToTarget > GLOW_DISTANCE && renderMode == NORMAL_RENDER_MODE
? 1.0f
: GLOW_FROM_AVERAGE_LOUDNESS);
: GLOW_FROM_AVERAGE_LOUDNESS;
// render body
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
renderBody(renderMode);
renderBody(renderMode, glowLevel);
}
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionShapes)) {
_skeletonModel.updateShapePositions();
@ -326,17 +326,21 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
return glm::angleAxis(angle * proportion, axis);
}
void Avatar::renderBody(RenderMode renderMode) {
if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
// render the billboard until both models are loaded
renderBillboard();
return;
}
void Avatar::renderBody(RenderMode renderMode, float glowLevel) {
Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ?
Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
_skeletonModel.render(1.0f, modelRenderMode);
Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
{
Glower glower(glowLevel);
if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
// render the billboard until both models are loaded
renderBillboard();
return;
}
_skeletonModel.render(1.0f, modelRenderMode);
getHand()->render(false);
}
getHead()->render(1.0f, modelRenderMode);
getHand()->render(false);
}
bool Avatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const {
@ -451,7 +455,7 @@ void Avatar::renderDisplayName() {
// The up vector must be relative to the rotation current rotation matrix:
// we set the identity
glm::dvec3 testPoint0 = glm::dvec3(textPosition);
glm::dvec3 testPoint1 = glm::dvec3(textPosition) + glm::dvec3(IDENTITY_UP);
glm::dvec3 testPoint1 = glm::dvec3(textPosition) + glm::dvec3(Application::getInstance()->getCamera()->getRotation() * IDENTITY_UP);
bool success;
success = gluProject(testPoint0.x, testPoint0.y, testPoint0.z,
@ -466,7 +470,7 @@ void Avatar::renderDisplayName() {
double textWindowHeight = abs(result1[1] - result0[1]);
float scaleFactor = (textWindowHeight > EPSILON) ? 1.0f / textWindowHeight : 1.0f;
glScalef(scaleFactor, scaleFactor, 1.0);
glScalef(1.0f, -1.0f, 1.0f); // TextRenderer::draw paints the text upside down in y axis
int text_x = -_displayNameBoundingRect.width() / 2;

View file

@ -185,7 +185,7 @@ protected:
float getPelvisToHeadLength() const;
void renderDisplayName();
virtual void renderBody(RenderMode renderMode);
virtual void renderBody(RenderMode renderMode, float glowLevel);
virtual bool shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const;
virtual void updateJointMappings();

View file

@ -16,6 +16,7 @@ const int RESIZE_HANDLE_WIDTH = 7;
FramelessDialog::FramelessDialog(QWidget *parent, Qt::WindowFlags flags, Position position) :
QDialog(parent, flags | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint),
_allowResize(true),
_isResizing(false),
_resizeInitialWidth(0),
_selfHidden(false),
@ -114,7 +115,7 @@ void FramelessDialog::resizeAndPosition(bool resizeParent) {
}
void FramelessDialog::mousePressEvent(QMouseEvent* mouseEvent) {
if (mouseEvent->button() == Qt::LeftButton) {
if (_allowResize && mouseEvent->button() == Qt::LeftButton) {
if (_position == POSITION_LEFT || _position == POSITION_RIGHT) {
bool hitLeft = (_position == POSITION_LEFT) && (abs(mouseEvent->pos().x() - size().width()) < RESIZE_HANDLE_WIDTH);
bool hitRight = (_position == POSITION_RIGHT) && (mouseEvent->pos().x() < RESIZE_HANDLE_WIDTH);

View file

@ -23,8 +23,10 @@ public:
FramelessDialog(QWidget* parent, Qt::WindowFlags flags = 0, Position position = POSITION_LEFT);
void setStyleSheetFile(const QString& fileName);
void setHideOnBlur(bool hideOnBlur) { _hideOnBlur = hideOnBlur; };
bool getHideOnBlur() { return _hideOnBlur; };
void setAllowResize(bool allowResize) { _allowResize = allowResize; }
bool getAllowResize() { return _allowResize; }
void setHideOnBlur(bool hideOnBlur) { _hideOnBlur = hideOnBlur; }
bool getHideOnBlur() { return _hideOnBlur; }
void resizeAndPosition(bool resizeParent = true);
protected:
@ -36,6 +38,7 @@ protected:
bool eventFilter(QObject* sender, QEvent* event);
private:
bool _allowResize;
bool _isResizing;
int _resizeInitialWidth;
bool _selfHidden; ///< true when the dialog itself because of a window event (deactivation or minimization)

View file

@ -12,39 +12,35 @@
#include "ui_runningScriptsWidget.h"
#include "RunningScriptsWidget.h"
#include <QFileInfo>
#include <QKeyEvent>
#include <QPainter>
#include <QTableWidgetItem>
#include "Application.h"
RunningScriptsWidget::RunningScriptsWidget(QDockWidget *parent) :
QDockWidget(parent),
ui(new Ui::RunningScriptsWidget)
{
RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
FramelessDialog(parent, 0, POSITION_LEFT),
ui(new Ui::RunningScriptsWidget) {
ui->setupUi(this);
// remove the title bar (see the Qt docs on setTitleBarWidget)
setTitleBarWidget(new QWidget());
setAllowResize(false);
ui->runningScriptsTableWidget->setColumnCount(2);
ui->runningScriptsTableWidget->verticalHeader()->setVisible(false);
ui->runningScriptsTableWidget->horizontalHeader()->setVisible(false);
ui->runningScriptsTableWidget->setSelectionMode(QAbstractItemView::NoSelection);
ui->runningScriptsTableWidget->setShowGrid(false);
ui->runningScriptsTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->runningScriptsTableWidget->setColumnWidth(0, 235);
ui->runningScriptsTableWidget->setColumnWidth(1, 25);
connect(ui->runningScriptsTableWidget, &QTableWidget::cellClicked, this, &RunningScriptsWidget::stopScript);
ui->hideWidgetButton->setIcon(QIcon(Application::resourcesPath() + "images/close.svg"));
ui->reloadAllButton->setIcon(QIcon(Application::resourcesPath() + "images/reload.svg"));
ui->stopAllButton->setIcon(QIcon(Application::resourcesPath() + "images/stop.svg"));
ui->loadScriptButton->setIcon(QIcon(Application::resourcesPath() + "images/plus-white.svg"));
ui->recentlyLoadedScriptsTableWidget->setColumnCount(2);
ui->recentlyLoadedScriptsTableWidget->verticalHeader()->setVisible(false);
ui->recentlyLoadedScriptsTableWidget->horizontalHeader()->setVisible(false);
ui->recentlyLoadedScriptsTableWidget->setSelectionMode(QAbstractItemView::NoSelection);
ui->recentlyLoadedScriptsTableWidget->setShowGrid(false);
ui->recentlyLoadedScriptsTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->recentlyLoadedScriptsTableWidget->setColumnWidth(0, 25);
ui->recentlyLoadedScriptsTableWidget->setColumnWidth(1, 235);
connect(ui->recentlyLoadedScriptsTableWidget, &QTableWidget::cellClicked,
_runningScriptsTable = new ScriptsTableWidget(ui->runningScriptsTableWidget);
_runningScriptsTable->setColumnCount(2);
_runningScriptsTable->setColumnWidth(0, 245);
_runningScriptsTable->setColumnWidth(1, 22);
connect(_runningScriptsTable, &QTableWidget::cellClicked, this, &RunningScriptsWidget::stopScript);
_recentlyLoadedScriptsTable = new ScriptsTableWidget(ui->recentlyLoadedScriptsTableWidget);
_recentlyLoadedScriptsTable->setColumnCount(1);
_recentlyLoadedScriptsTable->setColumnWidth(0, 265);
connect(_recentlyLoadedScriptsTable, &QTableWidget::cellClicked,
this, &RunningScriptsWidget::loadScript);
connect(ui->hideWidgetButton, &QPushButton::clicked,
@ -53,118 +49,126 @@ RunningScriptsWidget::RunningScriptsWidget(QDockWidget *parent) :
Application::getInstance(), &Application::reloadAllScripts);
connect(ui->stopAllButton, &QPushButton::clicked,
this, &RunningScriptsWidget::allScriptsStopped);
connect(ui->loadScriptButton, &QPushButton::clicked,
Application::getInstance(), &Application::loadDialog);
}
RunningScriptsWidget::~RunningScriptsWidget()
{
RunningScriptsWidget::~RunningScriptsWidget() {
delete ui;
}
void RunningScriptsWidget::setRunningScripts(const QStringList& list)
{
ui->runningScriptsTableWidget->setRowCount(list.size());
void RunningScriptsWidget::setBoundary(const QRect& rect) {
_boundary = rect;
}
void RunningScriptsWidget::setRunningScripts(const QStringList& list) {
_runningScriptsTable->setRowCount(list.size());
ui->noRunningScriptsLabel->setVisible(list.isEmpty());
ui->currentlyRunningLabel->setVisible(!list.isEmpty());
ui->line1->setVisible(!list.isEmpty());
ui->runningScriptsTableWidget->setVisible(!list.isEmpty());
ui->reloadAllButton->setVisible(!list.isEmpty());
ui->stopAllButton->setVisible(!list.isEmpty());
const int CLOSE_ICON_HEIGHT = 12;
for (int i = 0; i < list.size(); ++i) {
QTableWidgetItem *scriptName = new QTableWidgetItem;
scriptName->setText(list.at(i));
scriptName->setText(QFileInfo(list.at(i)).fileName());
scriptName->setToolTip(list.at(i));
scriptName->setTextAlignment(Qt::AlignCenter);
scriptName->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
QTableWidgetItem *closeIcon = new QTableWidgetItem;
closeIcon->setIcon(QIcon(Application::resourcesPath() + "/images/kill-script.svg"));
closeIcon->setIcon(QIcon(QPixmap(Application::resourcesPath() + "images/kill-script.svg").scaledToHeight(CLOSE_ICON_HEIGHT)));
ui->runningScriptsTableWidget->setItem(i, 0, scriptName);
ui->runningScriptsTableWidget->setItem(i, 1, closeIcon);
_runningScriptsTable->setItem(i, 0, scriptName);
_runningScriptsTable->setItem(i, 1, closeIcon);
}
const int RUNNING_SCRIPTS_TABLE_LEFT_MARGIN = 12;
const int RECENTLY_LOADED_TOP_MARGIN = 61;
const int RECENTLY_LOADED_LABEL_TOP_MARGIN = 19;
int y = ui->runningScriptsTableWidget->y() + RUNNING_SCRIPTS_TABLE_LEFT_MARGIN;
for (int i = 0; i < _runningScriptsTable->rowCount(); ++i) {
y += _runningScriptsTable->rowHeight(i);
}
ui->runningScriptsTableWidget->resize(ui->runningScriptsTableWidget->width(), y - RUNNING_SCRIPTS_TABLE_LEFT_MARGIN);
_runningScriptsTable->resize(_runningScriptsTable->width(), y - RUNNING_SCRIPTS_TABLE_LEFT_MARGIN);
ui->reloadAllButton->move(ui->reloadAllButton->x(), y);
ui->stopAllButton->move(ui->stopAllButton->x(), y);
ui->recentlyLoadedLabel->move(ui->recentlyLoadedLabel->x(),
ui->stopAllButton->y() + ui->stopAllButton->height() + RECENTLY_LOADED_TOP_MARGIN);
ui->recentlyLoadedScriptsTableWidget->move(ui->recentlyLoadedScriptsTableWidget->x(),
ui->recentlyLoadedLabel->y() + RECENTLY_LOADED_LABEL_TOP_MARGIN);
createRecentlyLoadedScriptsTable();
}
void RunningScriptsWidget::keyPressEvent(QKeyEvent *e)
void RunningScriptsWidget::keyPressEvent(QKeyEvent* event)
{
switch(e->key()) {
int loadScriptNumber = -1;
switch(event->key()) {
case Qt::Key_Escape:
Application::getInstance()->toggleRunningScriptsWidget();
break;
case Qt::Key_1:
if (_recentlyLoadedScripts.size() > 0) {
Application::getInstance()->loadScript(_recentlyLoadedScripts.at(0));
}
break;
case Qt::Key_2:
if (_recentlyLoadedScripts.size() > 0 && _recentlyLoadedScripts.size() >= 2) {
Application::getInstance()->loadScript(_recentlyLoadedScripts.at(1));
}
break;
case Qt::Key_3:
if (_recentlyLoadedScripts.size() > 0 && _recentlyLoadedScripts.size() >= 3) {
Application::getInstance()->loadScript(_recentlyLoadedScripts.at(2));
}
break;
case Qt::Key_4:
if (_recentlyLoadedScripts.size() > 0 && _recentlyLoadedScripts.size() >= 4) {
Application::getInstance()->loadScript(_recentlyLoadedScripts.at(3));
}
break;
case Qt::Key_5:
if (_recentlyLoadedScripts.size() > 0 && _recentlyLoadedScripts.size() >= 5) {
Application::getInstance()->loadScript(_recentlyLoadedScripts.at(4));
}
break;
case Qt::Key_6:
if (_recentlyLoadedScripts.size() > 0 && _recentlyLoadedScripts.size() >= 6) {
Application::getInstance()->loadScript(_recentlyLoadedScripts.at(5));
}
break;
case Qt::Key_7:
if (_recentlyLoadedScripts.size() > 0 && _recentlyLoadedScripts.size() >= 7) {
Application::getInstance()->loadScript(_recentlyLoadedScripts.at(6));
}
break;
case Qt::Key_8:
if (_recentlyLoadedScripts.size() > 0 && _recentlyLoadedScripts.size() >= 8) {
Application::getInstance()->loadScript(_recentlyLoadedScripts.at(7));
}
break;
case Qt::Key_9:
if (_recentlyLoadedScripts.size() > 0 && _recentlyLoadedScripts.size() >= 9) {
Application::getInstance()->loadScript(_recentlyLoadedScripts.at(8));
}
loadScriptNumber = event->key() - Qt::Key_1;
break;
default:
break;
}
if (loadScriptNumber >= 0) {
if (_recentlyLoadedScripts.size() > loadScriptNumber) {
Application::getInstance()->loadScript(_recentlyLoadedScripts.at(loadScriptNumber));
}
}
FramelessDialog::keyPressEvent(event);
}
void RunningScriptsWidget::stopScript(int row, int column)
{
void RunningScriptsWidget::paintEvent(QPaintEvent* event) {
QPainter painter(this);
painter.setPen(QColor::fromRgb(225, 225, 225)); // #e1e1e1
if (ui->currentlyRunningLabel->isVisible()) {
// line below the 'Currently Running' label
painter.drawLine(36, ui->currentlyRunningLabel->y() + ui->currentlyRunningLabel->height(),
300, ui->currentlyRunningLabel->y() + ui->currentlyRunningLabel->height());
}
if (ui->recentlyLoadedLabel->isVisible()) {
// line below the 'Recently loaded' label
painter.drawLine(36, ui->recentlyLoadedLabel->y() + ui->recentlyLoadedLabel->height(),
300, ui->recentlyLoadedLabel->y() + ui->recentlyLoadedLabel->height());
}
painter.end();
}
void RunningScriptsWidget::stopScript(int row, int column) {
if (column == 1) { // make sure the user has clicked on the close icon
_lastStoppedScript = ui->runningScriptsTableWidget->item(row, 0)->text();
emit stopScriptName(ui->runningScriptsTableWidget->item(row, 0)->text());
_lastStoppedScript = _runningScriptsTable->item(row, 0)->toolTip();
emit stopScriptName(_runningScriptsTable->item(row, 0)->toolTip());
}
}
void RunningScriptsWidget::loadScript(int row, int column)
{
Application::getInstance()->loadScript(ui->recentlyLoadedScriptsTableWidget->item(row, column)->text());
void RunningScriptsWidget::loadScript(int row, int column) {
Application::getInstance()->loadScript(_recentlyLoadedScriptsTable->item(row, column)->toolTip());
}
void RunningScriptsWidget::allScriptsStopped()
{
void RunningScriptsWidget::allScriptsStopped() {
QStringList list = Application::getInstance()->getRunningScripts();
for (int i = 0; i < list.size(); ++i) {
_recentlyLoadedScripts.prepend(list.at(i));
@ -173,8 +177,7 @@ void RunningScriptsWidget::allScriptsStopped()
Application::getInstance()->stopAllScripts();
}
void RunningScriptsWidget::createRecentlyLoadedScriptsTable()
{
void RunningScriptsWidget::createRecentlyLoadedScriptsTable() {
if (!_recentlyLoadedScripts.contains(_lastStoppedScript) && !_lastStoppedScript.isEmpty()) {
_recentlyLoadedScripts.prepend(_lastStoppedScript);
_lastStoppedScript = "";
@ -187,21 +190,28 @@ void RunningScriptsWidget::createRecentlyLoadedScriptsTable()
}
ui->recentlyLoadedLabel->setVisible(!_recentlyLoadedScripts.isEmpty());
ui->line2->setVisible(!_recentlyLoadedScripts.isEmpty());
ui->recentlyLoadedScriptsTableWidget->setVisible(!_recentlyLoadedScripts.isEmpty());
ui->recentlyLoadedInstruction->setVisible(!_recentlyLoadedScripts.isEmpty());
int limit = _recentlyLoadedScripts.size() > 9 ? 9 : _recentlyLoadedScripts.size();
ui->recentlyLoadedScriptsTableWidget->setRowCount(limit);
for (int i = 0; i < limit; ++i) {
_recentlyLoadedScriptsTable->setRowCount(limit);
for (int i = 0; i < limit; i++) {
QTableWidgetItem *scriptName = new QTableWidgetItem;
scriptName->setText(_recentlyLoadedScripts.at(i));
scriptName->setText(QString::number(i + 1) + ". " + QFileInfo(_recentlyLoadedScripts.at(i)).fileName());
scriptName->setToolTip(_recentlyLoadedScripts.at(i));
scriptName->setTextAlignment(Qt::AlignCenter);
QTableWidgetItem *number = new QTableWidgetItem;
number->setText(QString::number(i+1) + ".");
scriptName->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
ui->recentlyLoadedScriptsTableWidget->setItem(i, 0, number);
ui->recentlyLoadedScriptsTableWidget->setItem(i, 1, scriptName);
_recentlyLoadedScriptsTable->setItem(i, 0, scriptName);
}
int y = ui->recentlyLoadedScriptsTableWidget->y() + 15;
for (int i = 0; i < _recentlyLoadedScriptsTable->rowCount(); ++i) {
y += _recentlyLoadedScriptsTable->rowHeight(i);
}
ui->recentlyLoadedInstruction->setGeometry(36, y,
ui->recentlyLoadedInstruction->width(),
ui->recentlyLoadedInstruction->height());
repaint();
}

View file

@ -12,18 +12,18 @@
#ifndef hifi_RunningScriptsWidget_h
#define hifi_RunningScriptsWidget_h
// Qt
#include <QDockWidget>
#include "FramelessDialog.h"
#include "ScriptsTableWidget.h"
namespace Ui {
class RunningScriptsWidget;
}
class RunningScriptsWidget : public QDockWidget
class RunningScriptsWidget : public FramelessDialog
{
Q_OBJECT
public:
explicit RunningScriptsWidget(QDockWidget *parent = 0);
explicit RunningScriptsWidget(QWidget* parent = NULL);
~RunningScriptsWidget();
void setRunningScripts(const QStringList& list);
@ -32,7 +32,11 @@ signals:
void stopScriptName(const QString& name);
protected:
void keyPressEvent(QKeyEvent *e);
virtual void keyPressEvent(QKeyEvent* event);
virtual void paintEvent(QPaintEvent* event);
public slots:
void setBoundary(const QRect& rect);
private slots:
void stopScript(int row, int column);
@ -40,9 +44,12 @@ private slots:
void allScriptsStopped();
private:
Ui::RunningScriptsWidget *ui;
Ui::RunningScriptsWidget* ui;
ScriptsTableWidget* _runningScriptsTable;
ScriptsTableWidget* _recentlyLoadedScriptsTable;
QStringList _recentlyLoadedScripts;
QString _lastStoppedScript;
QRect _boundary;
void createRecentlyLoadedScriptsTable();
};

View file

@ -0,0 +1,49 @@
//
// ScriptsTableWidget.cpp
// interface
//
// Created by Mohammed Nafees on 04/03/2014.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QDebug>
#include <QHeaderView>
#include <QKeyEvent>
#include <QPainter>
#include "ScriptsTableWidget.h"
ScriptsTableWidget::ScriptsTableWidget(QWidget* parent) :
QTableWidget(parent) {
verticalHeader()->setVisible(false);
horizontalHeader()->setVisible(false);
setShowGrid(false);
setSelectionMode(QAbstractItemView::NoSelection);
setEditTriggers(QAbstractItemView::NoEditTriggers);
setStyleSheet("QTableWidget { background: transparent; color: #333333; } QToolTip { color: #000000; background: #f9f6e4; padding: 2px; }");
setToolTipDuration(200);
setWordWrap(true);
setGeometry(0, 0, parent->width(), parent->height());
}
void ScriptsTableWidget::paintEvent(QPaintEvent* event) {
QPainter painter(viewport());
painter.setPen(QColor::fromRgb(225, 225, 225)); // #e1e1e1
int y = 0;
for (int i = 0; i < rowCount(); i++) {
painter.drawLine(5, rowHeight(i) + y, width(), rowHeight(i) + y);
y += rowHeight(i);
}
painter.end();
QTableWidget::paintEvent(event);
}
void ScriptsTableWidget::keyPressEvent(QKeyEvent* event) {
// Ignore keys so they will propagate correctly
event->ignore();
}

View file

@ -0,0 +1,28 @@
//
// ScriptsTableWidget.h
// interface
//
// Created by Mohammed Nafees on 04/03/2014.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi__ScriptsTableWidget_h
#define hifi__ScriptsTableWidget_h
#include <QDebug>
#include <QTableWidget>
class ScriptsTableWidget : public QTableWidget {
Q_OBJECT
public:
explicit ScriptsTableWidget(QWidget* parent);
protected:
virtual void paintEvent(QPaintEvent* event);
virtual void keyPressEvent(QKeyEvent* event);
};
#endif // hifi__ScriptsTableWidget_h

View file

@ -6,44 +6,58 @@
<rect>
<x>0</x>
<y>0</y>
<width>310</width>
<height>651</height>
<width>323</width>
<height>894</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="styleSheet">
<string notr="true">background: #f7f7f7;
font-family: Helvetica, Arial, &quot;DejaVu Sans&quot;; </string>
<string notr="true">* {
font-family: Helvetica, Arial, sans-serif;
}
QWidget {
background: #f7f7f7;
}</string>
</property>
<widget class="QLabel" name="widgetTitle">
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>221</width>
<height>31</height>
<x>37</x>
<y>29</y>
<width>251</width>
<height>20</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">color: #0e7077;</string>
<string notr="true">color: #0e7077;
font-size: 20pt;
background: transparent;</string>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:18pt;&quot;&gt;Running Scripts&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="margin">
<number>0</number>
</property>
<property name="indent">
<number>-1</number>
</property>
</widget>
<widget class="QLabel" name="currentlyRunningLabel">
<property name="geometry">
<rect>
<x>20</x>
<y>40</y>
<width>301</width>
<x>36</x>
<y>110</y>
<width>270</width>
<height>20</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">color: #0e7077;</string>
<string notr="true">color: #0e7077;
font: bold 14pt;
background: transparent;</string>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Currently running&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@ -52,22 +66,27 @@ font-family: Helvetica, Arial, &quot;DejaVu Sans&quot;; </string>
<widget class="QPushButton" name="reloadAllButton">
<property name="geometry">
<rect>
<x>40</x>
<y>230</y>
<x>36</x>
<y>270</y>
<width>111</width>
<height>31</height>
<height>35</height>
</rect>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true">background: #0e7077;
color: #fff;
border-radius: 6px;</string>
border-radius: 4px;
font: bold 14pt;
padding-top: 3px;</string>
</property>
<property name="text">
<string>Reload All</string>
<string>Reload all</string>
</property>
<property name="icon">
<iconset>
@ -78,9 +97,9 @@ border-radius: 6px;</string>
<property name="geometry">
<rect>
<x>160</x>
<y>230</y>
<width>101</width>
<height>31</height>
<y>270</y>
<width>93</width>
<height>35</height>
</rect>
</property>
<property name="cursor">
@ -89,10 +108,12 @@ border-radius: 6px;</string>
<property name="styleSheet">
<string notr="true">background: #0e7077;
color: #fff;
border-radius: 6px;</string>
border-radius: 4px;
font: bold 14pt;
padding-top: 3px;</string>
</property>
<property name="text">
<string>Stop All</string>
<string>Stop all</string>
</property>
<property name="icon">
<iconset>
@ -102,46 +123,32 @@ border-radius: 6px;</string>
<widget class="QLabel" name="recentlyLoadedLabel">
<property name="geometry">
<rect>
<x>20</x>
<y>280</y>
<width>301</width>
<x>36</x>
<y>320</y>
<width>265</width>
<height>20</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">color: #0e7077;</string>
<string notr="true">color: #0e7077;
font: bold 14pt;</string>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Recently loaded&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
<widget class="Line" name="line2">
<property name="geometry">
<rect>
<x>20</x>
<y>300</y>
<width>271</width>
<height>8</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
<widget class="QLabel" name="recentlyLoadedInstruction">
<property name="geometry">
<rect>
<x>20</x>
<y>590</y>
<width>271</width>
<x>36</x>
<y>630</y>
<width>211</width>
<height>41</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">color: #95a5a6;</string>
<string notr="true">color: #95a5a6;
font-size: 14pt;</string>
</property>
<property name="text">
<string>(click a script or use the 1-9 keys to load and run it)</string>
@ -153,10 +160,10 @@ border-radius: 6px;</string>
<widget class="QPushButton" name="hideWidgetButton">
<property name="geometry">
<rect>
<x>270</x>
<y>10</y>
<width>31</width>
<height>31</height>
<x>285</x>
<y>29</y>
<width>16</width>
<height>16</height>
</rect>
</property>
<property name="cursor">
@ -165,81 +172,101 @@ border-radius: 6px;</string>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>../resources/images/close.svg</normaloff>../resources/images/close.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
<widget class="QTableWidget" name="runningScriptsTableWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>70</y>
<width>271</width>
<height>141</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">background: transparent;</string>
</property>
</widget>
<widget class="Line" name="line1">
<property name="geometry">
<rect>
<x>20</x>
<y>60</y>
<width>271</width>
<height>8</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
<widget class="QTableWidget" name="recentlyLoadedScriptsTableWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>310</y>
<width>271</width>
<height>281</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">background: transparent;</string>
</property>
</widget>
<widget class="QLabel" name="noRunningScriptsLabel">
<property name="geometry">
<rect>
<x>20</x>
<y>40</y>
<x>36</x>
<y>110</y>
<width>271</width>
<height>51</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">font: 14px;</string>
<string notr="true">font: 14pt;</string>
</property>
<property name="text">
<string>There are no scripts currently running.</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="QWidget" name="recentlyLoadedScriptsTableWidget" native="true">
<property name="geometry">
<rect>
<x>30</x>
<y>340</y>
<width>272</width>
<height>280</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">background: transparent;
font-size: 14pt;</string>
</property>
</widget>
<widget class="QWidget" name="runningScriptsTableWidget" native="true">
<property name="geometry">
<rect>
<x>30</x>
<y>128</y>
<width>272</width>
<height>161</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">background: transparent;
font-size: 14pt;</string>
</property>
</widget>
<widget class="QPushButton" name="loadScriptButton">
<property name="geometry">
<rect>
<x>36</x>
<y>70</y>
<width>111</width>
<height>35</height>
</rect>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="styleSheet">
<string notr="true">background: #0e7077;
color: #fff;
border-radius: 4px;
font: bold 14pt;
padding-top: 3px;</string>
</property>
<property name="text">
<string>Load script</string>
</property>
<property name="icon">
<iconset>
<normaloff>../resources/images/plus.svg</normaloff>../resources/images/plus.svg</iconset>
</property>
</widget>
<zorder>widgetTitle</zorder>
<zorder>currentlyRunningLabel</zorder>
<zorder>recentlyLoadedLabel</zorder>
<zorder>recentlyLoadedInstruction</zorder>
<zorder>hideWidgetButton</zorder>
<zorder>recentlyLoadedScriptsTableWidget</zorder>
<zorder>runningScriptsTableWidget</zorder>
<zorder>noRunningScriptsLabel</zorder>
<zorder>reloadAllButton</zorder>
<zorder>stopAllButton</zorder>
<zorder>loadScriptButton</zorder>
</widget>
<resources/>
<connections/>

View file

@ -62,6 +62,8 @@ PacketVersion versionForPacketType(PacketType type) {
case PacketTypeVoxelSet:
case PacketTypeVoxelSetDestructive:
return 1;
case PacketTypeOctreeStats:
return 1;
default:
return 0;
}

View file

@ -594,8 +594,9 @@ bool findRayIntersectionOp(OctreeElement* node, void* extraData) {
}
bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
OctreeElement*& node, float& distance, BoxFace& face, Octree::lockType lockType) {
RayArgs args = { origin / (float)(TREE_SCALE), direction, node, distance, face };
OctreeElement*& node, float& distance, BoxFace& face,
Octree::lockType lockType, bool* accurateResult) {
RayArgs args = { origin / (float)(TREE_SCALE), direction, node, distance, face, false};
bool gotLock = false;
if (lockType == Octree::Lock) {
@ -604,6 +605,9 @@ bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc
} else if (lockType == Octree::TryLock) {
gotLock = tryLockForRead();
if (!gotLock) {
if (accurateResult) {
*accurateResult = false; // if user asked to accuracy or result, let them know this is inaccurate
}
return args.found; // if we wanted to tryLock, and we couldn't then just bail...
}
}
@ -614,6 +618,9 @@ bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc
unlock();
}
if (accurateResult) {
*accurateResult = true; // if user asked to accuracy or result, let them know this is accurate
}
return args.found;
}
@ -640,7 +647,8 @@ bool findSpherePenetrationOp(OctreeElement* element, void* extraData) {
if (element->hasContent()) {
glm::vec3 elementPenetration;
if (element->findSpherePenetration(args->center, args->radius, elementPenetration, &args->penetratedObject)) {
// NOTE: it is possible for this penetration accumulation algorithm to produce a final penetration vector with zero length.
// NOTE: it is possible for this penetration accumulation algorithm to produce a
// final penetration vector with zero length.
args->penetration = addPenetrations(args->penetration, elementPenetration * (float)(TREE_SCALE));
args->found = true;
}
@ -649,7 +657,7 @@ bool findSpherePenetrationOp(OctreeElement* element, void* extraData) {
}
bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration,
void** penetratedObject, Octree::lockType lockType) {
void** penetratedObject, Octree::lockType lockType, bool* accurateResult) {
SphereArgs args = {
center / (float)(TREE_SCALE),
@ -666,6 +674,9 @@ bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::v
} else if (lockType == Octree::TryLock) {
gotLock = tryLockForRead();
if (!gotLock) {
if (accurateResult) {
*accurateResult = false; // if user asked to accuracy or result, let them know this is inaccurate
}
return args.found; // if we wanted to tryLock, and we couldn't then just bail...
}
}
@ -679,6 +690,9 @@ bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::v
unlock();
}
if (accurateResult) {
*accurateResult = true; // if user asked to accuracy or result, let them know this is accurate
}
return args.found;
}
@ -741,7 +755,7 @@ bool findShapeCollisionsOp(OctreeElement* node, void* extraData) {
}
bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius,
glm::vec3& penetration, Octree::lockType lockType) {
glm::vec3& penetration, Octree::lockType lockType, bool* accurateResult) {
CapsuleArgs args = {
start / (float)(TREE_SCALE),
@ -758,6 +772,9 @@ bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end
} else if (lockType == Octree::TryLock) {
gotLock = tryLockForRead();
if (!gotLock) {
if (accurateResult) {
*accurateResult = false; // if user asked to accuracy or result, let them know this is inaccurate
}
return args.found; // if we wanted to tryLock, and we couldn't then just bail...
}
}
@ -767,10 +784,15 @@ bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end
if (gotLock) {
unlock();
}
if (accurateResult) {
*accurateResult = true; // if user asked to accuracy or result, let them know this is accurate
}
return args.found;
}
bool Octree::findShapeCollisions(const Shape* shape, CollisionList& collisions, Octree::lockType lockType) {
bool Octree::findShapeCollisions(const Shape* shape, CollisionList& collisions,
Octree::lockType lockType, bool* accurateResult) {
ShapeArgs args = { shape, collisions, false };
@ -781,6 +803,9 @@ bool Octree::findShapeCollisions(const Shape* shape, CollisionList& collisions,
} else if (lockType == Octree::TryLock) {
gotLock = tryLockForRead();
if (!gotLock) {
if (accurateResult) {
*accurateResult = false; // if user asked to accuracy or result, let them know this is inaccurate
}
return args.found; // if we wanted to tryLock, and we couldn't then just bail...
}
}
@ -790,6 +815,10 @@ bool Octree::findShapeCollisions(const Shape* shape, CollisionList& collisions,
if (gotLock) {
unlock();
}
if (accurateResult) {
*accurateResult = true; // if user asked to accuracy or result, let them know this is accurate
}
return args.found;
}
@ -816,7 +845,7 @@ bool getElementEnclosingOperation(OctreeElement* element, void* extraData) {
return true; // keep looking
}
OctreeElement* Octree::getElementEnclosingPoint(const glm::vec3& point, Octree::lockType lockType) {
OctreeElement* Octree::getElementEnclosingPoint(const glm::vec3& point, Octree::lockType lockType, bool* accurateResult) {
GetElementEnclosingArgs args;
args.point = point;
args.element = NULL;
@ -828,6 +857,9 @@ OctreeElement* Octree::getElementEnclosingPoint(const glm::vec3& point, Octree::
} else if (lockType == Octree::TryLock) {
gotLock = tryLockForRead();
if (!gotLock) {
if (accurateResult) {
*accurateResult = false; // if user asked to accuracy or result, let them know this is inaccurate
}
return args.element; // if we wanted to tryLock, and we couldn't then just bail...
}
}
@ -838,6 +870,9 @@ OctreeElement* Octree::getElementEnclosingPoint(const glm::vec3& point, Octree::
unlock();
}
if (accurateResult) {
*accurateResult = false; // if user asked to accuracy or result, let them know this is inaccurate
}
return args.element;
}

View file

@ -249,17 +249,20 @@ public:
} lockType;
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
OctreeElement*& node, float& distance, BoxFace& face, Octree::lockType lockType = Octree::TryLock);
OctreeElement*& node, float& distance, BoxFace& face,
Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration,
void** penetratedObject = NULL, Octree::lockType lockType = Octree::TryLock);
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject = NULL,
Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius,
glm::vec3& penetration, Octree::lockType lockType = Octree::TryLock);
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration,
Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
bool findShapeCollisions(const Shape* shape, CollisionList& collisions, Octree::lockType = Octree::TryLock);
bool findShapeCollisions(const Shape* shape, CollisionList& collisions,
Octree::lockType = Octree::TryLock, bool* accurateResult = NULL);
OctreeElement* getElementEnclosingPoint(const glm::vec3& point, Octree::lockType lockType = Octree::TryLock);
OctreeElement* getElementEnclosingPoint(const glm::vec3& point,
Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL);
// Note: this assumes the fileFormat is the HIO individual voxels code files
void loadOctreeFile(const char* fileName, bool wantColorRandomizer);

View file

@ -646,70 +646,70 @@ int OctreeSceneStats::unpackFromMessage(const unsigned char* sourceBuffer, int a
void OctreeSceneStats::printDebugDetails() {
qDebug("\n------------------------------");
qDebug("OctreeSceneStats:");
qDebug(" start : %llu", (long long unsigned int)_start);
qDebug(" end : %llu", (long long unsigned int)_end);
qDebug(" elapsed : %llu", (long long unsigned int)_elapsed);
qDebug(" encoding : %llu", (long long unsigned int)_totalEncodeTime);
qDebug() << "\n------------------------------";
qDebug() << "OctreeSceneStats:";
qDebug() << "start: " << _start;
qDebug() << "end: " << _end;
qDebug() << "elapsed: " << _elapsed;
qDebug() << "encoding: " << _totalEncodeTime;
qDebug();
qDebug(" full scene: %s", debug::valueOf(_isFullScene));
qDebug(" moving: %s", debug::valueOf(_isMoving));
qDebug() << "full scene: " << debug::valueOf(_isFullScene);
qDebug() << "moving: " << debug::valueOf(_isMoving);
qDebug();
qDebug(" packets: %d", _packets);
qDebug(" bytes : %ld", _bytes);
qDebug() << "packets: " << _packets;
qDebug() << "bytes: " << _bytes;
qDebug();
qDebug(" total elements : %lu", _totalElements );
qDebug(" internal : %lu", _totalInternal );
qDebug(" leaves : %lu", _totalLeaves );
qDebug(" traversed : %lu", _traversed );
qDebug(" internal : %lu", _internal );
qDebug(" leaves : %lu", _leaves );
qDebug(" skipped distance : %lu", _skippedDistance );
qDebug(" internal : %lu", _internalSkippedDistance );
qDebug(" leaves : %lu", _leavesSkippedDistance );
qDebug(" skipped out of view : %lu", _skippedOutOfView );
qDebug(" internal : %lu", _internalSkippedOutOfView );
qDebug(" leaves : %lu", _leavesSkippedOutOfView );
qDebug(" skipped was in view : %lu", _skippedWasInView );
qDebug(" internal : %lu", _internalSkippedWasInView );
qDebug(" leaves : %lu", _leavesSkippedWasInView );
qDebug(" skipped no change : %lu", _skippedNoChange );
qDebug(" internal : %lu", _internalSkippedNoChange );
qDebug(" leaves : %lu", _leavesSkippedNoChange );
qDebug(" skipped occluded : %lu", _skippedOccluded );
qDebug(" internal : %lu", _internalSkippedOccluded );
qDebug(" leaves : %lu", _leavesSkippedOccluded );
qDebug() << "total elements: " << _totalElements;
qDebug() << "internal: " << _totalInternal;
qDebug() << "leaves: " << _totalLeaves;
qDebug() << "traversed: " << _traversed;
qDebug() << "internal: " << _internal;
qDebug() << "leaves: " << _leaves;
qDebug() << "skipped distance: " << _skippedDistance;
qDebug() << "internal: " << _internalSkippedDistance;
qDebug() << "leaves: " << _leavesSkippedDistance;
qDebug() << "skipped out of view: " << _skippedOutOfView;
qDebug() << "internal: " << _internalSkippedOutOfView;
qDebug() << "leaves: " << _leavesSkippedOutOfView;
qDebug() << "skipped was in view: " << _skippedWasInView;
qDebug() << "internal: " << _internalSkippedWasInView;
qDebug() << "leaves: " << _leavesSkippedWasInView;
qDebug() << "skipped no change: " << _skippedNoChange;
qDebug() << "internal: " << _internalSkippedNoChange;
qDebug() << "leaves: " << _leavesSkippedNoChange;
qDebug() << "skipped occluded: " << _skippedOccluded;
qDebug() << "internal: " << _internalSkippedOccluded;
qDebug() << "leaves: " << _leavesSkippedOccluded;
qDebug();
qDebug(" color sent : %lu", _colorSent );
qDebug(" internal : %lu", _internalColorSent );
qDebug(" leaves : %lu", _leavesColorSent );
qDebug(" Didn't Fit : %lu", _didntFit );
qDebug(" internal : %lu", _internalDidntFit );
qDebug(" leaves : %lu", _leavesDidntFit );
qDebug(" color bits : %lu", _colorBitsWritten );
qDebug(" exists bits : %lu", _existsBitsWritten );
qDebug(" in packet bit : %lu", _existsInPacketBitsWritten);
qDebug(" trees removed : %lu", _treesRemoved );
qDebug() << "color sent: " << _colorSent;
qDebug() << "internal: " << _internalColorSent;
qDebug() << "leaves: " << _leavesColorSent;
qDebug() << "Didn't Fit: " << _didntFit;
qDebug() << "internal: " << _internalDidntFit;
qDebug() << "leaves: " << _leavesDidntFit;
qDebug() << "color bits: " << _colorBitsWritten;
qDebug() << "exists bits: " << _existsBitsWritten;
qDebug() << "in packet bit: " << _existsInPacketBitsWritten;
qDebug() << "trees removed: " << _treesRemoved;
}
OctreeSceneStats::ItemInfo OctreeSceneStats::_ITEMS[] = {
{ "Elapsed" , GREENISH , 2 , "Elapsed,fps" },
{ "Encode" , YELLOWISH , 2 , "Time,fps" },
{ "Network" , GREYISH , 3 , "Packets,Bytes,KBPS" },
{ "Octrees on Server" , GREENISH , 3 , "Total,Internal,Leaves" },
{ "Octrees Sent" , YELLOWISH , 5 , "Total,Bits/Octree,Avg Bits/Octree,Internal,Leaves" },
{ "Colors Sent" , GREYISH , 3 , "Total,Internal,Leaves" },
{ "Bitmasks Sent" , GREENISH , 3 , "Colors,Exists,In Packets" },
{ "Traversed" , YELLOWISH , 3 , "Total,Internal,Leaves" },
{ "Skipped - Total" , GREYISH , 3 , "Total,Internal,Leaves" },
{ "Skipped - Distance" , GREENISH , 3 , "Total,Internal,Leaves" },
{ "Skipped - Out of View", YELLOWISH , 3 , "Total,Internal,Leaves" },
{ "Skipped - Was in View", GREYISH , 3 , "Total,Internal,Leaves" },
{ "Skipped - No Change" , GREENISH , 3 , "Total,Internal,Leaves" },
{ "Skipped - Occluded" , YELLOWISH , 3 , "Total,Internal,Leaves" },
{ "Didn't fit in packet" , GREYISH , 4 , "Total,Internal,Leaves,Removed" },
{ "Mode" , GREENISH , 4 , "Moving,Stationary,Partial,Full" },
{ "Elapsed", GREENISH, 2, "Elapsed,fps" },
{ "Encode", YELLOWISH, 2, "Time,fps" },
{ "Network", GREYISH, 3, "Packets,Bytes,KBPS" },
{ "Octrees on Server", GREENISH, 3, "Total,Internal,Leaves" },
{ "Octrees Sent", YELLOWISH, 5, "Total,Bits/Octree,Avg Bits/Octree,Internal,Leaves" },
{ "Colors Sent", GREYISH, 3, "Total,Internal,Leaves" },
{ "Bitmasks Sent", GREENISH, 3, "Colors,Exists,In Packets" },
{ "Traversed", YELLOWISH, 3, "Total,Internal,Leaves" },
{ "Skipped - Total", GREYISH, 3, "Total,Internal,Leaves" },
{ "Skipped - Distance", GREENISH, 3, "Total,Internal,Leaves" },
{ "Skipped - Out of View", YELLOWISH, 3, "Total,Internal,Leaves" },
{ "Skipped - Was in View", GREYISH, 3, "Total,Internal,Leaves" },
{ "Skipped - No Change", GREENISH, 3, "Total,Internal,Leaves" },
{ "Skipped - Occluded", YELLOWISH, 3, "Total,Internal,Leaves" },
{ "Didn't fit in packet", GREYISH, 4, "Total,Internal,Leaves,Removed" },
{ "Mode", GREENISH, 4, "Moving,Stationary,Partial,Full" },
};
const char* OctreeSceneStats::getItemValue(Item item) {
@ -732,12 +732,14 @@ const char* OctreeSceneStats::getItemValue(Item item) {
case ITEM_PACKETS: {
float elapsedSecs = ((float)_elapsed / (float)USECS_PER_SECOND);
calculatedKBPS = elapsedSecs == 0 ? 0 : ((_bytes * 8) / elapsedSecs) / 1000;
sprintf(_itemValueBuffer, "%d packets %lu bytes (%d kbps)", _packets, _bytes, calculatedKBPS);
sprintf(_itemValueBuffer, "%d packets %lu bytes (%d kbps)", _packets, (long unsigned int)_bytes, calculatedKBPS);
break;
}
case ITEM_VOXELS_SERVER: {
sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves",
_totalElements, _totalInternal, _totalLeaves);
sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves",
(long unsigned int)_totalElements,
(long unsigned int)_totalInternal,
(long unsigned int)_totalLeaves);
break;
}
case ITEM_VOXELS: {
@ -745,12 +747,14 @@ const char* OctreeSceneStats::getItemValue(Item item) {
float calculatedBPV = total == 0 ? 0 : (_bytes * 8) / total;
float averageBPV = _bitsPerOctreeAverage.getAverage();
sprintf(_itemValueBuffer, "%lu (%.2f bits/octree Average: %.2f bits/octree) %lu internal %lu leaves",
total, calculatedBPV, averageBPV, _existsInPacketBitsWritten, _colorSent);
total, calculatedBPV, averageBPV,
(long unsigned int)_existsInPacketBitsWritten,
(long unsigned int)_colorSent);
break;
}
case ITEM_TRAVERSED: {
sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves",
_traversed, _internal, _leaves);
(long unsigned int)_traversed, (long unsigned int)_internal, (long unsigned int)_leaves);
break;
}
case ITEM_SKIPPED: {
@ -769,42 +773,59 @@ const char* OctreeSceneStats::getItemValue(Item item) {
}
case ITEM_SKIPPED_DISTANCE: {
sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves",
_skippedDistance, _internalSkippedDistance, _leavesSkippedDistance);
(long unsigned int)_skippedDistance,
(long unsigned int)_internalSkippedDistance,
(long unsigned int)_leavesSkippedDistance);
break;
}
case ITEM_SKIPPED_OUT_OF_VIEW: {
sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves",
_skippedOutOfView, _internalSkippedOutOfView, _leavesSkippedOutOfView);
(long unsigned int)_skippedOutOfView,
(long unsigned int)_internalSkippedOutOfView,
(long unsigned int)_leavesSkippedOutOfView);
break;
}
case ITEM_SKIPPED_WAS_IN_VIEW: {
sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves",
_skippedWasInView, _internalSkippedWasInView, _leavesSkippedWasInView);
(long unsigned int)_skippedWasInView,
(long unsigned int)_internalSkippedWasInView,
(long unsigned int)_leavesSkippedWasInView);
break;
}
case ITEM_SKIPPED_NO_CHANGE: {
sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves",
_skippedNoChange, _internalSkippedNoChange, _leavesSkippedNoChange);
(long unsigned int)_skippedNoChange,
(long unsigned int)_internalSkippedNoChange,
(long unsigned int)_leavesSkippedNoChange);
break;
}
case ITEM_SKIPPED_OCCLUDED: {
sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves",
_skippedOccluded, _internalSkippedOccluded, _leavesSkippedOccluded);
(long unsigned int)_skippedOccluded,
(long unsigned int)_internalSkippedOccluded,
(long unsigned int)_leavesSkippedOccluded);
break;
}
case ITEM_COLORS: {
sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves",
_colorSent, _internalColorSent, _leavesColorSent);
(long unsigned int)_colorSent,
(long unsigned int)_internalColorSent,
(long unsigned int)_leavesColorSent);
break;
}
case ITEM_DIDNT_FIT: {
sprintf(_itemValueBuffer, "%lu total %lu internal %lu leaves (removed: %lu)",
_didntFit, _internalDidntFit, _leavesDidntFit, _treesRemoved);
(long unsigned int)_didntFit,
(long unsigned int)_internalDidntFit,
(long unsigned int)_leavesDidntFit,
(long unsigned int)_treesRemoved);
break;
}
case ITEM_BITS: {
sprintf(_itemValueBuffer, "colors: %lu, exists: %lu, in packets: %lu",
_colorBitsWritten, _existsBitsWritten, _existsInPacketBitsWritten);
(long unsigned int)_colorBitsWritten,
(long unsigned int)_existsBitsWritten,
(long unsigned int)_existsInPacketBitsWritten);
break;
}
case ITEM_MODE: {

View file

@ -146,30 +146,30 @@ public:
const std::vector<unsigned char*>& getJurisdictionEndNodes() const { return _jurisdictionEndNodes; }
bool isMoving() const { return _isMoving; };
unsigned long getTotalElements() const { return _totalElements; }
unsigned long getTotalInternal() const { return _totalInternal; }
unsigned long getTotalLeaves() const { return _totalLeaves; }
unsigned long getTotalEncodeTime() const { return _totalEncodeTime; }
unsigned long getElapsedTime() const { return _elapsed; }
quint64 getTotalElements() const { return _totalElements; }
quint64 getTotalInternal() const { return _totalInternal; }
quint64 getTotalLeaves() const { return _totalLeaves; }
quint64 getTotalEncodeTime() const { return _totalEncodeTime; }
quint64 getElapsedTime() const { return _elapsed; }
unsigned long getLastFullElapsedTime() const { return _lastFullElapsed; }
unsigned long getLastFullTotalEncodeTime() const { return _lastFullTotalEncodeTime; }
unsigned int getLastFullTotalPackets() const { return _lastFullTotalPackets; }
unsigned long getLastFullTotalBytes() const { return _lastFullTotalBytes; }
quint64 getLastFullElapsedTime() const { return _lastFullElapsed; }
quint64 getLastFullTotalEncodeTime() const { return _lastFullTotalEncodeTime; }
quint32 getLastFullTotalPackets() const { return _lastFullTotalPackets; }
quint64 getLastFullTotalBytes() const { return _lastFullTotalBytes; }
// Used in client implementations to track individual octree packets
void trackIncomingOctreePacket(const QByteArray& packet, bool wasStatsPacket, int nodeClockSkewUsec);
unsigned int getIncomingPackets() const { return _incomingPacket; }
unsigned long getIncomingBytes() const { return _incomingBytes; }
unsigned long getIncomingWastedBytes() const { return _incomingWastedBytes; }
unsigned int getIncomingOutOfOrder() const { return _incomingLate + _incomingEarly; }
unsigned int getIncomingLikelyLost() const { return _incomingLikelyLost; }
unsigned int getIncomingRecovered() const { return _incomingRecovered; }
unsigned int getIncomingEarly() const { return _incomingEarly; }
unsigned int getIncomingLate() const { return _incomingLate; }
unsigned int getIncomingReallyLate() const { return _incomingReallyLate; }
unsigned int getIncomingPossibleDuplicate() const { return _incomingPossibleDuplicate; }
quint32 getIncomingPackets() const { return _incomingPacket; }
quint64 getIncomingBytes() const { return _incomingBytes; }
quint64 getIncomingWastedBytes() const { return _incomingWastedBytes; }
quint32 getIncomingOutOfOrder() const { return _incomingLate + _incomingEarly; }
quint32 getIncomingLikelyLost() const { return _incomingLikelyLost; }
quint32 getIncomingRecovered() const { return _incomingRecovered; }
quint32 getIncomingEarly() const { return _incomingEarly; }
quint32 getIncomingLate() const { return _incomingLate; }
quint32 getIncomingReallyLate() const { return _incomingReallyLate; }
quint32 getIncomingPossibleDuplicate() const { return _incomingPossibleDuplicate; }
float getIncomingFlightTimeAverage() { return _incomingFlightTimeAverage.getAverage(); }
private:
@ -178,7 +178,8 @@ private:
bool _isReadyToSend;
unsigned char _statsMessage[MAX_PACKET_SIZE];
int _statsMessageLength;
qint32 _statsMessageLength;
// scene timing data in usecs
bool _isStarted;
@ -188,8 +189,8 @@ private:
quint64 _lastFullElapsed;
quint64 _lastFullTotalEncodeTime;
unsigned int _lastFullTotalPackets;
unsigned long _lastFullTotalBytes;
quint32 _lastFullTotalPackets;
quint64 _lastFullTotalBytes;
SimpleMovingAverage _elapsedAverage;
SimpleMovingAverage _bitsPerOctreeAverage;
@ -198,46 +199,46 @@ private:
quint64 _encodeStart;
// scene octree related data
unsigned long _totalElements;
unsigned long _totalInternal;
unsigned long _totalLeaves;
quint64 _totalElements;
quint64 _totalInternal;
quint64 _totalLeaves;
unsigned long _traversed;
unsigned long _internal;
unsigned long _leaves;
quint64 _traversed;
quint64 _internal;
quint64 _leaves;
unsigned long _skippedDistance;
unsigned long _internalSkippedDistance;
unsigned long _leavesSkippedDistance;
quint64 _skippedDistance;
quint64 _internalSkippedDistance;
quint64 _leavesSkippedDistance;
unsigned long _skippedOutOfView;
unsigned long _internalSkippedOutOfView;
unsigned long _leavesSkippedOutOfView;
quint64 _skippedOutOfView;
quint64 _internalSkippedOutOfView;
quint64 _leavesSkippedOutOfView;
unsigned long _skippedWasInView;
unsigned long _internalSkippedWasInView;
unsigned long _leavesSkippedWasInView;
quint64 _skippedWasInView;
quint64 _internalSkippedWasInView;
quint64 _leavesSkippedWasInView;
unsigned long _skippedNoChange;
unsigned long _internalSkippedNoChange;
unsigned long _leavesSkippedNoChange;
quint64 _skippedNoChange;
quint64 _internalSkippedNoChange;
quint64 _leavesSkippedNoChange;
unsigned long _skippedOccluded;
unsigned long _internalSkippedOccluded;
unsigned long _leavesSkippedOccluded;
quint64 _skippedOccluded;
quint64 _internalSkippedOccluded;
quint64 _leavesSkippedOccluded;
unsigned long _colorSent;
unsigned long _internalColorSent;
unsigned long _leavesColorSent;
quint64 _colorSent;
quint64 _internalColorSent;
quint64 _leavesColorSent;
unsigned long _didntFit;
unsigned long _internalDidntFit;
unsigned long _leavesDidntFit;
quint64 _didntFit;
quint64 _internalDidntFit;
quint64 _leavesDidntFit;
unsigned long _colorBitsWritten;
unsigned long _existsBitsWritten;
unsigned long _existsInPacketBitsWritten;
unsigned long _treesRemoved;
quint64 _colorBitsWritten;
quint64 _existsBitsWritten;
quint64 _existsInPacketBitsWritten;
quint64 _treesRemoved;
// Accounting Notes:
//
@ -255,22 +256,22 @@ private:
//
// scene network related data
unsigned int _packets;
unsigned long _bytes;
unsigned int _passes;
quint32 _packets;
quint64 _bytes;
quint32 _passes;
// incoming packets stats
unsigned int _incomingPacket;
unsigned long _incomingBytes;
unsigned long _incomingWastedBytes;
quint32 _incomingPacket;
quint64 _incomingBytes;
quint64 _incomingWastedBytes;
uint16_t _incomingLastSequence; /// last incoming sequence number
unsigned int _incomingLikelyLost; /// count of packets likely lost, may be off by _incomingReallyLate count
unsigned int _incomingRecovered; /// packets that were late, and we had in our missing list, we consider recovered
unsigned int _incomingEarly; /// out of order earlier than expected
unsigned int _incomingLate; /// out of order later than expected
unsigned int _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late
unsigned int _incomingPossibleDuplicate; /// out of order possibly a duplicate
quint16 _incomingLastSequence; /// last incoming sequence number
quint32 _incomingLikelyLost; /// count of packets likely lost, may be off by _incomingReallyLate count
quint32 _incomingRecovered; /// packets that were late, and we had in our missing list, we consider recovered
quint32 _incomingEarly; /// out of order earlier than expected
quint32 _incomingLate; /// out of order later than expected
quint32 _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late
quint32 _incomingPossibleDuplicate; /// out of order possibly a duplicate
QSet<uint16_t> _missingSequenceNumbers;
SimpleMovingAverage _incomingFlightTimeAverage;
@ -280,7 +281,7 @@ private:
static ItemInfo _ITEMS[];
static int const MAX_ITEM_VALUE_LENGTH = 128;
static const int MAX_ITEM_VALUE_LENGTH = 128;
char _itemValueBuffer[MAX_ITEM_VALUE_LENGTH];
unsigned char* _jurisdictionRoot;

View file

@ -119,10 +119,19 @@ void LocalVoxels::pasteFrom(float x, float y, float z, float scale, const QStrin
}
RayToVoxelIntersectionResult LocalVoxels::findRayIntersection(const PickRay& ray) {
return findRayIntersectionWorker(ray, Octree::TryLock);
}
RayToVoxelIntersectionResult LocalVoxels::findRayIntersectionBlocking(const PickRay& ray) {
return findRayIntersectionWorker(ray, Octree::Lock);
}
RayToVoxelIntersectionResult LocalVoxels::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType) {
RayToVoxelIntersectionResult result;
if (_tree) {
OctreeElement* element;
result.intersects = _tree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face);
result.intersects = _tree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face,
lockType, &result.accurate);
if (result.intersects) {
VoxelTreeElement* voxel = (VoxelTreeElement*)element;
result.voxel.x = voxel->getCorner().x;

View file

@ -76,13 +76,22 @@ public:
/// \param source LocalVoxels' source tree
Q_INVOKABLE void pasteFrom(float x, float y, float z, float scale, const QString source);
/// If the scripting context has visible voxels, this will determine a ray intersection
/// If the scripting context has visible voxels, this will determine a ray intersection, the results
/// may be inaccurate if the engine is unable to access the visible voxels, in which case result.accurate
/// will be false.
Q_INVOKABLE RayToVoxelIntersectionResult findRayIntersection(const PickRay& ray);
/// If the scripting context has visible voxels, this will determine a ray intersection, and will block in
/// order to return an accurate result
Q_INVOKABLE RayToVoxelIntersectionResult findRayIntersectionBlocking(const PickRay& ray);
/// returns a voxel space axis aligned vector for the face, useful in doing voxel math
Q_INVOKABLE glm::vec3 getFaceVector(const QString& face);
private:
/// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode
RayToVoxelIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType);
QString _name;
StrongVoxelTreePointer _tree;
};

View file

@ -166,7 +166,7 @@ void ScriptEngine::setAvatarData(AvatarData* avatarData, const QString& objectNa
void ScriptEngine::setAvatarHashMap(AvatarHashMap* avatarHashMap, const QString& objectName) {
// remove the old Avatar property, if it exists
_engine.globalObject().setProperty(objectName, QScriptValue());
// give the script engine the new avatar hash map
registerGlobalObject(objectName, avatarHashMap);
}
@ -228,7 +228,7 @@ void ScriptEngine::init() {
registerGlobalObject("Vec3", &_vec3Library);
registerGlobalObject("Uuid", &_uuidLibrary);
registerGlobalObject("AnimationCache", &_animationCache);
registerGlobalObject("Voxels", &_voxelsScriptingInterface);
// constants

View file

@ -615,7 +615,7 @@ int unpackClipValueFromTwoByte(const unsigned char* buffer, float& clipValue) {
}
int packFloatToByte(unsigned char* buffer, float value, float scaleBy) {
unsigned char holder;
quint8 holder;
const float CONVERSION_RATIO = (255 / scaleBy);
holder = floorf(value * CONVERSION_RATIO);
memcpy(buffer, &holder, sizeof(holder));
@ -623,7 +623,7 @@ int packFloatToByte(unsigned char* buffer, float value, float scaleBy) {
}
int unpackFloatFromByte(const unsigned char* buffer, float& value, float scaleBy) {
unsigned char holder;
quint8 holder;
memcpy(&holder, buffer, sizeof(holder));
value = ((float)holder / (float) 255) * scaleBy;
return sizeof(holder);

View file

@ -41,6 +41,7 @@ void voxelDetailFromScriptValue(const QScriptValue &object, VoxelDetail& voxelDe
RayToVoxelIntersectionResult::RayToVoxelIntersectionResult() :
intersects(false),
accurate(true), // assume it's accurate
voxel(),
distance(0),
face()
@ -50,6 +51,7 @@ RayToVoxelIntersectionResult::RayToVoxelIntersectionResult() :
QScriptValue rayToVoxelIntersectionResultToScriptValue(QScriptEngine* engine, const RayToVoxelIntersectionResult& value) {
QScriptValue obj = engine->newObject();
obj.setProperty("intersects", value.intersects);
obj.setProperty("accurate", value.accurate);
QScriptValue voxelValue = voxelDetailToScriptValue(engine, value.voxel);
obj.setProperty("voxel", voxelValue);
obj.setProperty("distance", value.distance);
@ -88,6 +90,7 @@ QScriptValue rayToVoxelIntersectionResultToScriptValue(QScriptEngine* engine, co
void rayToVoxelIntersectionResultFromScriptValue(const QScriptValue& object, RayToVoxelIntersectionResult& value) {
value.intersects = object.property("intersects").toVariant().toBool();
value.accurate = object.property("accurate").toVariant().toBool();
QScriptValue voxelValue = object.property("voxel");
if (voxelValue.isValid()) {
voxelDetailFromScriptValue(voxelValue, value.voxel);

View file

@ -39,6 +39,7 @@ class RayToVoxelIntersectionResult {
public:
RayToVoxelIntersectionResult();
bool intersects;
bool accurate;
VoxelDetail voxel;
float distance;
BoxFace face;

View file

@ -122,12 +122,21 @@ void VoxelsScriptingInterface::eraseVoxel(float x, float y, float z, float scale
}
}
RayToVoxelIntersectionResult VoxelsScriptingInterface::findRayIntersection(const PickRay& ray) {
return findRayIntersectionWorker(ray, Octree::TryLock);
}
RayToVoxelIntersectionResult VoxelsScriptingInterface::findRayIntersectionBlocking(const PickRay& ray) {
return findRayIntersectionWorker(ray, Octree::Lock);
}
RayToVoxelIntersectionResult VoxelsScriptingInterface::findRayIntersectionWorker(const PickRay& ray,
Octree::lockType lockType) {
RayToVoxelIntersectionResult result;
if (_tree) {
OctreeElement* element;
result.intersects = _tree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face);
result.intersects = _tree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face,
lockType, &result.accurate);
if (result.intersects) {
VoxelTreeElement* voxel = (VoxelTreeElement*)element;
result.voxel.x = voxel->getCorner().x;

View file

@ -35,17 +35,16 @@ public:
void setVoxelTree(VoxelTree* tree) { _tree = tree; }
void setUndoStack(QUndoStack* undoStack) { _undoStack = undoStack; }
public slots:
public:
/// provide the world scale
const int getTreeScale() const { return TREE_SCALE; }
Q_INVOKABLE const int getTreeScale() const { return TREE_SCALE; }
/// checks the local voxel tree for a voxel at the specified location and scale
/// \param x the x-coordinate of the voxel (in meter units)
/// \param y the y-coordinate of the voxel (in meter units)
/// \param z the z-coordinate of the voxel (in meter units)
/// \param scale the scale of the voxel (in meter units)
VoxelDetail getVoxelAt(float x, float y, float z, float scale);
Q_INVOKABLE VoxelDetail getVoxelAt(float x, float y, float z, float scale);
/// 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 meter units)
@ -55,7 +54,7 @@ public slots:
/// \param red the R value for RGB color of voxel
/// \param green the G value for RGB color of voxel
/// \param blue the B value for RGB color of voxel
void setVoxelNonDestructive(float x, float y, float z, float scale, uchar red, uchar green, uchar blue);
Q_INVOKABLE void setVoxelNonDestructive(float x, float y, float z, float scale, uchar red, uchar green, uchar blue);
/// queues the destructive creation of a voxel which will be sent by calling process on the PacketSender
/// \param x the x-coordinate of the voxel (in meter units)
@ -65,27 +64,36 @@ public slots:
/// \param red the R value for RGB color of voxel
/// \param green the G value for RGB color of voxel
/// \param blue the B value for RGB color of voxel
void setVoxel(float x, float y, float z, float scale, uchar red, uchar green, uchar blue);
Q_INVOKABLE void setVoxel(float x, float y, float z, float scale, uchar red, uchar green, uchar blue);
/// queues the deletion of a voxel, sent by calling process on the PacketSender
/// \param x the x-coordinate of the voxel (in meter units)
/// \param y the y-coordinate of the voxel (in meter units)
/// \param z the z-coordinate of the voxel (in meter units)
/// \param scale the scale of the voxel (in meter units)
void eraseVoxel(float x, float y, float z, float scale);
Q_INVOKABLE void eraseVoxel(float x, float y, float z, float scale);
/// If the scripting context has visible voxels, this will determine a ray intersection
RayToVoxelIntersectionResult findRayIntersection(const PickRay& ray);
/// If the scripting context has visible voxels, this will determine a ray intersection, the results
/// may be inaccurate if the engine is unable to access the visible voxels, in which case result.accurate
/// will be false.
Q_INVOKABLE RayToVoxelIntersectionResult findRayIntersection(const PickRay& ray);
/// If the scripting context has visible voxels, this will determine a ray intersection, and will block in
/// order to return an accurate result
Q_INVOKABLE RayToVoxelIntersectionResult findRayIntersectionBlocking(const PickRay& ray);
/// returns a voxel space axis aligned vector for the face, useful in doing voxel math
glm::vec3 getFaceVector(const QString& face);
Q_INVOKABLE glm::vec3 getFaceVector(const QString& face);
/// checks the local voxel tree for the smallest voxel enclosing the point
/// \param point the x,y,z coordinates of the point (in meter units)
/// \return VoxelDetail - if no voxel encloses the point then VoxelDetail items will be 0
VoxelDetail getVoxelEnclosingPoint(const glm::vec3& point);
Q_INVOKABLE VoxelDetail getVoxelEnclosingPoint(const glm::vec3& point);
private:
/// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode
RayToVoxelIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType);
void queueVoxelAdd(PacketType addPacketType, VoxelDetail& addVoxelDetails);
VoxelTree* _tree;
QUndoStack* _undoStack;