mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 04:03:59 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into gpuStreamizing
Conflicts: interface/src/avatar/Hand.cpp interface/src/ui/overlays/ImageOverlay.cpp
This commit is contained in:
commit
4a6cc5c6f2
146 changed files with 3966 additions and 3138 deletions
4
BUILD.md
4
BUILD.md
|
@ -6,12 +6,12 @@
|
|||
* [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g
|
||||
* IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability.
|
||||
* [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3
|
||||
* [Bullet Physics Engine](http://bulletphysics.org) ~> 2.82
|
||||
* [Bullet Physics Engine](https://code.google.com/p/bullet/downloads/list) ~> 2.82
|
||||
|
||||
### OS Specific Build Guides
|
||||
* [BUILD_WIN.md](BUILD_WIN.md) - additional instructions for Windows.
|
||||
* [BUILD_OSX.md](BUILD_OSX.md) - additional instructions for OS X.
|
||||
* [BUILD_LINUX.md](BUILD_LINUX.md) - additional instructions for Linux.
|
||||
* [BUILD_WIN.md](BUILD_WIN.md) - additional instructions for Windows.
|
||||
|
||||
###CMake
|
||||
Hifi uses CMake to generate build files and project files for your platform.
|
||||
|
|
31
BUILD_WIN.md
31
BUILD_WIN.md
|
@ -1,15 +1,10 @@
|
|||
Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Windows specific instructions are found in this file.
|
||||
|
||||
###Windows Dependencies
|
||||
###Windows Specific Dependencies
|
||||
* [GLEW](http://glew.sourceforge.net/) ~> 1.10.0
|
||||
* [freeglut MSVC](http://www.transmissionzero.co.uk/software/freeglut-devel/) ~> 2.8.1
|
||||
* [zLib](http://www.zlib.net/) ~> 1.2.8
|
||||
|
||||
###Visual Studio
|
||||
|
||||
Currently building on Windows has been tested using the following compilers:
|
||||
* Visual Studio 2013
|
||||
* Visual Studio 2013 Express
|
||||
* (remember that you need all other dependencies listed in [BUILD.md](BUILD.md))
|
||||
|
||||
####Visual Studio 2013
|
||||
|
||||
|
@ -30,14 +25,15 @@ You can use the online installer or the offline installer. If you use the offlin
|
|||
|
||||
NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit version of libraries for interface.exe to run. The 32-bit version of the static library is the one linked by our CMake find modules.
|
||||
|
||||
* Download the online installer [here](http://qt-project.org/downloads)
|
||||
* [Download the online installer](http://qt-project.org/downloads)
|
||||
* When it asks you to select components, ONLY select the following:
|
||||
* Qt > Qt 5.3.2 > **msvc2013 32-bit OpenGL**
|
||||
|
||||
* Download the offline installer [here](http://download.qt-project.org/official_releases/qt/5.3/5.3.2/qt-opensource-windows-x86-msvc2013_opengl-5.3.2.exe)
|
||||
* [Download the offline installer](http://download.qt-project.org/official_releases/qt/5.3/5.3.2/qt-opensource-windows-x86-msvc2013_opengl-5.3.2.exe)
|
||||
|
||||
Once Qt is installed, you need to manually configure the following:
|
||||
* Make sure the Qt runtime DLLs are loadable. You must do this before you attempt to build because some tools for the build depend on Qt. E.g., add to the PATH: `Qt\5.3.2\msvc2013_opengl\bin\`.
|
||||
* Go to Control Panel > System > Advanced System Settings > Environment Variables > New ...
|
||||
* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.3.2\msvc2013_opengl` directory.
|
||||
|
||||
###External Libraries
|
||||
|
@ -47,6 +43,9 @@ CMake will need to know where the headers and libraries for required external de
|
|||
The recommended route for CMake to find the external dependencies is to place all of the dependencies in one folder and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure:
|
||||
|
||||
root_lib_dir
|
||||
-> bullet
|
||||
-> include
|
||||
-> lib
|
||||
-> freeglut
|
||||
-> bin
|
||||
-> include
|
||||
|
@ -92,7 +91,7 @@ To prevent these problems, install OpenSSL yourself. Download the following bina
|
|||
* Visual C++ 2008 Redistributables
|
||||
* Win32 OpenSSL v1.0.1h
|
||||
|
||||
Install OpenSSL into the Windows system directory, to make sure that QT uses the version that you've just installed, and not some other version.
|
||||
Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version.
|
||||
|
||||
###Intel Threading Building Blocks (TBB)
|
||||
|
||||
|
@ -111,8 +110,10 @@ Add the following environment variables (remember to substitute your own directo
|
|||
|
||||
Add to the PATH: `%HIFI_LIB_DIR%\zlib`
|
||||
|
||||
Important! This should be added at the beginning of the path, not the end. That's because your
|
||||
system likely has many copies of zlib1.dll, and you want High Fidelity to use the correct version. If High Fidelity picks up the wrong zlib1.dll then it might be unable to use it, and that would cause it to fail to start, showing only the cryptic error "The application was unable to start correctly: 0xc0000022".
|
||||
(The PATH environment variable is where Windows looks for its DLL's and executables. There's a great tool for editing these variables with ease, [Rapid Environment Editor](http://www.rapidee.com/en/download))
|
||||
|
||||
Important! This should be added at the beginning of the path, not the end (your
|
||||
system likely has many copies of zlib1.dll, and you want High Fidelity to use the correct version). If High Fidelity picks up the wrong zlib1.dll then it might be unable to use it, and that would cause it to fail to start, showing only the cryptic error "The application was unable to start correctly: 0xc0000022".
|
||||
|
||||
###freeglut
|
||||
|
||||
|
@ -134,10 +135,10 @@ Be careful with glm. For the folder other libraries would normally call 'include
|
|||
|
||||
###Bullet
|
||||
|
||||
Bullet 2.82 source can be downloaded [here](https://code.google.com/p/bullet/downloads/detail?name=bullet-2.82-r2704.zip). Bullet does not come with prebuilt libraries, you need to make those yourself.
|
||||
Bullet 2.82 source can be [downloaded here](https://code.google.com/p/bullet/downloads/detail?name=bullet-2.82-r2704.zip). Bullet does not come with prebuilt libraries, you need to make those yourself.
|
||||
|
||||
* Download the zip file and extract into a temporary folder
|
||||
* Create a directory named cmakebuild. Bullet comes with a build\ directory by default, however, that directory is intended for use with premake, and considering premake doesn't support VS2013, I prefer to run the cmake build on its own directory.
|
||||
* Create a directory named cmakebuild. Bullet comes with a build\ directory by default, however, that directory is intended for use with premake, and considering premake doesn't support VS2013, we prefer to run the cmake build on its own directory.
|
||||
* Make the following modifications to Bullet's source:
|
||||
1. In file: Extras\HACD\hacdICHull.cpp --- in line: 17 --- insert: #include <algorithm>
|
||||
2. In file: src\MiniCL\cl_MiniCL_Defs.h --- comment lines 364 to 372
|
||||
|
@ -162,7 +163,7 @@ You now have Bullet libraries compiled, now you need to put them in the right pl
|
|||
_Note that the INSTALL target should handle the copying of files into an install directory automatically, however, without modifications to Cmake, the install target didn't work right for me, please update this instructions if you get that working right - Leo <leo@highfidelity.io>_
|
||||
|
||||
###Build High Fidelity using Visual Studio
|
||||
Follow the same build steps from the CMake section, but pass a different generator to CMake.
|
||||
Follow the same build steps from the CMake section of [BUILD.md](BUILD.md), but pass a different generator to CMake.
|
||||
|
||||
cmake .. -DZLIB_LIBRARY=%ZLIB_LIBRARY% -DZLIB_INCLUDE_DIR=%ZLIB_INCLUDE_DIR% -G "Visual Studio 12"
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ Any target can be terminated with Ctrl-C (SIGINT) in the associated Terminal win
|
|||
|
||||
This assignment-client will grab one assignment from the domain-server. You can tell the assignment-client what type you want it to be with the `-t` option. You can also run an assignment-client that forks off *n* assignment-clients with the `-n` option.
|
||||
|
||||
./assignment-client -n 6
|
||||
./assignment-client -n 4
|
||||
|
||||
To test things out you'll want to run the Interface client.
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <QtCore/QEventLoop>
|
||||
#include <QtCore/QStandardPaths>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtNetwork/QNetworkDiskCache>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
|
@ -171,11 +170,6 @@ void Agent::run() {
|
|||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkReply *reply = networkAccessManager.get(QNetworkRequest(scriptURL));
|
||||
|
||||
QNetworkDiskCache* cache = new QNetworkDiskCache();
|
||||
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||
cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "agentCache");
|
||||
networkAccessManager.setCache(cache);
|
||||
|
||||
qDebug() << "Downloading script at" << scriptURL.toString();
|
||||
|
||||
QEventLoop loop;
|
||||
|
|
|
@ -9,10 +9,11 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/qsharedmemory.h>
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QProcess>
|
||||
#include <QSettings>
|
||||
#include <QSharedMemory>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
|
|
|
@ -13,21 +13,22 @@
|
|||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QtCore/QJsonArray>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/qsharedmemory.h>
|
||||
#include <QtCore/QStandardPaths>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QUrlQuery>
|
||||
#include <QDir>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QProcess>
|
||||
#include <QSharedMemory>
|
||||
#include <QStandardPaths>
|
||||
#include <QTimer>
|
||||
#include <QUrlQuery>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <HifiConfigVariantMap.h>
|
||||
#include <HTTPConnection.h>
|
||||
#include <LogUtils.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <Settings.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <ShutdownEventListener.h>
|
||||
#include <UUID.h>
|
||||
|
@ -1920,10 +1921,8 @@ Headers DomainServer::setupCookieHeadersFromProfileReply(QNetworkReply* profileR
|
|||
_cookieSessionHash.insert(cookieUUID, sessionData);
|
||||
|
||||
// persist the cookie to settings file so we can get it back on DS relaunch
|
||||
QSettings localSettings;
|
||||
localSettings.beginGroup(DS_SETTINGS_SESSIONS_GROUP);
|
||||
QVariant sessionVariant = QVariant::fromValue(sessionData);
|
||||
localSettings.setValue(cookieUUID.toString(), QVariant::fromValue(sessionData));
|
||||
QStringList path = QStringList() << DS_SETTINGS_SESSIONS_GROUP << cookieUUID.toString();
|
||||
SettingHandles::SettingHandle<QVariant>(path).set(QVariant::fromValue(sessionData));
|
||||
|
||||
// setup expiry for cookie to 1 month from today
|
||||
QDateTime cookieExpiry = QDateTime::currentDateTimeUtc().addMonths(1);
|
||||
|
@ -1943,11 +1942,12 @@ Headers DomainServer::setupCookieHeadersFromProfileReply(QNetworkReply* profileR
|
|||
|
||||
void DomainServer::loadExistingSessionsFromSettings() {
|
||||
// read data for existing web sessions into memory so existing sessions can be leveraged
|
||||
QSettings domainServerSettings;
|
||||
Settings domainServerSettings;
|
||||
domainServerSettings.beginGroup(DS_SETTINGS_SESSIONS_GROUP);
|
||||
|
||||
foreach(const QString& uuidKey, domainServerSettings.childKeys()) {
|
||||
_cookieSessionHash.insert(QUuid(uuidKey), domainServerSettings.value(uuidKey).value<DomainServerWebSessionData>());
|
||||
_cookieSessionHash.insert(QUuid(uuidKey),
|
||||
domainServerSettings.value(uuidKey).value<DomainServerWebSessionData>());
|
||||
qDebug() << "Pulled web session from settings - cookie UUID is" << uuidKey;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@ var yawFromMouse = 0;
|
|||
var pitchFromMouse = 0;
|
||||
var isMouseDown = false;
|
||||
|
||||
var BULLET_VELOCITY = 5.0;
|
||||
var MIN_THROWER_DELAY = 1000;
|
||||
var MAX_THROWER_DELAY = 1000;
|
||||
var LEFT_BUTTON_3 = 3;
|
||||
|
@ -98,7 +97,7 @@ var reticle = Overlays.addOverlay("image", {
|
|||
y: screenSize.y / 2 - 16,
|
||||
width: 32,
|
||||
height: 32,
|
||||
imageURL: HIFI_PUBLIC_BUCKET + "images/reticle.png",
|
||||
imageURL: HIFI_PUBLIC_BUCKET + "images/billiardsReticle.png",
|
||||
color: { red: 255, green: 255, blue: 255},
|
||||
alpha: 1
|
||||
});
|
||||
|
@ -113,6 +112,25 @@ var offButton = Overlays.addOverlay("image", {
|
|||
alpha: 1
|
||||
});
|
||||
|
||||
var platformButton = Overlays.addOverlay("image", {
|
||||
x: screenSize.x - 48,
|
||||
y: 130,
|
||||
width: 32,
|
||||
height: 32,
|
||||
imageURL: HIFI_PUBLIC_BUCKET + "images/city.png",
|
||||
color: { red: 255, green: 255, blue: 255},
|
||||
alpha: 1
|
||||
});
|
||||
var gridButton = Overlays.addOverlay("image", {
|
||||
x: screenSize.x - 48,
|
||||
y: 164,
|
||||
width: 32,
|
||||
height: 32,
|
||||
imageURL: HIFI_PUBLIC_BUCKET + "images/blocks.png",
|
||||
color: { red: 255, green: 255, blue: 255},
|
||||
alpha: 1
|
||||
});
|
||||
|
||||
if (showScore) {
|
||||
var text = Overlays.addOverlay("text", {
|
||||
x: screenSize.x / 2 - 100,
|
||||
|
@ -127,24 +145,30 @@ if (showScore) {
|
|||
});
|
||||
}
|
||||
|
||||
function printVector(string, vector) {
|
||||
print(string + " " + vector.x + ", " + vector.y + ", " + vector.z);
|
||||
}
|
||||
var BULLET_VELOCITY = 10.0;
|
||||
|
||||
function shootBullet(position, velocity) {
|
||||
var BULLET_SIZE = 0.07;
|
||||
function shootBullet(position, velocity, grenade) {
|
||||
var BULLET_SIZE = 0.10;
|
||||
var BULLET_LIFETIME = 10.0;
|
||||
var BULLET_GRAVITY = 0.0;
|
||||
var BULLET_GRAVITY = -0.25;
|
||||
var GRENADE_VELOCITY = 15.0;
|
||||
var GRENADE_SIZE = 0.35;
|
||||
var GRENADE_GRAVITY = -9.8;
|
||||
|
||||
var bVelocity = grenade ? Vec3.multiply(GRENADE_VELOCITY, Vec3.normalize(velocity)) : velocity;
|
||||
var bSize = grenade ? GRENADE_SIZE : BULLET_SIZE;
|
||||
var bGravity = grenade ? GRENADE_GRAVITY : BULLET_GRAVITY;
|
||||
|
||||
bulletID = Entities.addEntity(
|
||||
{ type: "Sphere",
|
||||
position: position,
|
||||
dimensions: { x: BULLET_SIZE, y: BULLET_SIZE, z: BULLET_SIZE },
|
||||
dimensions: { x: bSize, y: bSize, z: bSize },
|
||||
color: { red: 255, green: 0, blue: 0 },
|
||||
velocity: velocity,
|
||||
velocity: bVelocity,
|
||||
lifetime: BULLET_LIFETIME,
|
||||
gravity: { x: 0, y: BULLET_GRAVITY, z: 0 },
|
||||
gravity: { x: 0, y: bGravity, z: 0 },
|
||||
damping: 0.01,
|
||||
density: 5000,
|
||||
density: 8000,
|
||||
ignoreCollisions: false,
|
||||
collisionsWillMove: true
|
||||
});
|
||||
|
@ -158,13 +182,15 @@ function shootBullet(position, velocity) {
|
|||
}
|
||||
|
||||
// Kickback the arm
|
||||
if (elbowKickAngle > 0.0) {
|
||||
MyAvatar.setJointData("LeftForeArm", rotationBeforeKickback);
|
||||
}
|
||||
rotationBeforeKickback = MyAvatar.getJointRotation("LeftForeArm");
|
||||
var armRotation = MyAvatar.getJointRotation("LeftForeArm");
|
||||
armRotation = Quat.multiply(armRotation, Quat.fromPitchYawRollDegrees(0.0, 0.0, KICKBACK_ANGLE));
|
||||
MyAvatar.setJointData("LeftForeArm", armRotation);
|
||||
elbowKickAngle = KICKBACK_ANGLE;
|
||||
}
|
||||
|
||||
function shootTarget() {
|
||||
var TARGET_SIZE = 0.50;
|
||||
var TARGET_GRAVITY = 0.0;
|
||||
|
@ -174,7 +200,7 @@ function shootTarget() {
|
|||
var DISTANCE_TO_LAUNCH_FROM = 5.0;
|
||||
var ANGLE_RANGE_FOR_LAUNCH = 20.0;
|
||||
var camera = Camera.getPosition();
|
||||
//printVector("camera", camera);
|
||||
|
||||
var targetDirection = Quat.angleAxis(getRandomFloat(-ANGLE_RANGE_FOR_LAUNCH, ANGLE_RANGE_FOR_LAUNCH), { x:0, y:1, z:0 });
|
||||
targetDirection = Quat.multiply(Camera.getOrientation(), targetDirection);
|
||||
var forwardVector = Quat.getFront(targetDirection);
|
||||
|
@ -205,6 +231,78 @@ function shootTarget() {
|
|||
Audio.playSound(targetLaunchSound, audioOptions);
|
||||
}
|
||||
|
||||
function makeGrid(type, scale, size) {
|
||||
var separation = scale * 2;
|
||||
var pos = Vec3.sum(Camera.getPosition(), Vec3.multiply(10.0 * scale * separation, Quat.getFront(Camera.getOrientation())));
|
||||
var x, y, z;
|
||||
var GRID_LIFE = 60.0;
|
||||
var dimensions;
|
||||
|
||||
for (x = 0; x < size; x++) {
|
||||
for (y = 0; y < size; y++) {
|
||||
for (z = 0; z < size; z++) {
|
||||
|
||||
dimensions = { x: separation/2.0 * (0.5 + Math.random()), y: separation/2.0 * (0.5 + Math.random()), z: separation/2.0 * (0.5 + Math.random()) / 4.0 };
|
||||
|
||||
Entities.addEntity(
|
||||
{ type: type,
|
||||
position: { x: pos.x + x * separation, y: pos.y + y * separation, z: pos.z + z * separation },
|
||||
dimensions: dimensions,
|
||||
color: { red: Math.random() * 255, green: Math.random() * 255, blue: Math.random() * 255 },
|
||||
velocity: { x: 0, y: 0, z: 0 },
|
||||
gravity: { x: 0, y: 0, z: 0 },
|
||||
lifetime: GRID_LIFE,
|
||||
rotation: Camera.getOrientation(),
|
||||
damping: 0.1,
|
||||
density: 100.0,
|
||||
collisionsWillMove: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function makePlatform(gravity, scale, size) {
|
||||
var separation = scale * 2;
|
||||
var pos = Vec3.sum(Camera.getPosition(), Vec3.multiply(10.0 * scale * separation, Quat.getFront(Camera.getOrientation())));
|
||||
pos.y -= separation * size;
|
||||
var x, y, z;
|
||||
var TARGET_LIFE = 60.0;
|
||||
var INITIAL_GAP = 0.5;
|
||||
var dimensions;
|
||||
|
||||
for (x = 0; x < size; x++) {
|
||||
for (y = 0; y < size; y++) {
|
||||
for (z = 0; z < size; z++) {
|
||||
|
||||
dimensions = { x: separation/2.0, y: separation, z: separation/2.0 };
|
||||
|
||||
Entities.addEntity(
|
||||
{ type: "Box",
|
||||
position: { x: pos.x - (separation * size / 2.0) + x * separation,
|
||||
y: pos.y + y * (separation + INITIAL_GAP),
|
||||
z: pos.z - (separation * size / 2.0) + z * separation },
|
||||
dimensions: dimensions,
|
||||
color: { red: Math.random() * 255, green: Math.random() * 255, blue: Math.random() * 255 },
|
||||
velocity: { x: 0, y: 0, z: 0 },
|
||||
gravity: { x: 0, y: gravity, z: 0 },
|
||||
lifetime: TARGET_LIFE,
|
||||
damping: 0.1,
|
||||
density: 100.0,
|
||||
collisionsWillMove: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make a floor for this stuff to fall onto
|
||||
Entities.addEntity({
|
||||
type: "Box",
|
||||
position: { x: pos.x, y: pos.y - separation / 2.0, z: pos.z },
|
||||
dimensions: { x: 2.0 * separation * size, y: separation / 2.0, z: 2.0 * separation * size },
|
||||
color: { red: 128, green: 128, blue: 128 },
|
||||
lifetime: TARGET_LIFE
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function entityCollisionWithEntity(entity1, entity2, collision) {
|
||||
|
||||
if (((entity1.id == bulletID.id) || (entity1.id == targetID.id)) &&
|
||||
|
@ -233,7 +331,9 @@ function keyPressEvent(event) {
|
|||
var time = MIN_THROWER_DELAY + Math.random() * MAX_THROWER_DELAY;
|
||||
Script.setTimeout(shootTarget, time);
|
||||
} else if ((event.text == ".") || (event.text == "SPACE")) {
|
||||
shootFromMouse();
|
||||
shootFromMouse(false);
|
||||
} else if (event.text == ",") {
|
||||
shootFromMouse(true);
|
||||
} else if (event.text == "r") {
|
||||
playLoadSound();
|
||||
} else if (event.text == "s") {
|
||||
|
@ -241,7 +341,6 @@ function keyPressEvent(event) {
|
|||
Quat.print("arm = ", MyAvatar.getJointRotation("LeftArm"));
|
||||
Quat.print("forearm = ", MyAvatar.getJointRotation("LeftForeArm"));
|
||||
Quat.print("hand = ", MyAvatar.getJointRotation("LeftHand"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,18 +386,7 @@ function update(deltaTime) {
|
|||
if (targetID && !targetID.isKnownID) {
|
||||
targetID = Entities.identifyEntity(targetID);
|
||||
}
|
||||
// Check for mouseLook movement, update rotation
|
||||
// rotate body yaw for yaw received from mouse
|
||||
var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3Radians( { x: 0, y: yawFromMouse, z: 0 } ));
|
||||
//MyAvatar.orientation = newOrientation;
|
||||
yawFromMouse = 0;
|
||||
|
||||
// apply pitch from mouse
|
||||
var newPitch = MyAvatar.headPitch + pitchFromMouse;
|
||||
//MyAvatar.headPitch = newPitch;
|
||||
pitchFromMouse = 0;
|
||||
|
||||
|
||||
if (activeControllers == 0) {
|
||||
if (Controller.getNumberOfSpatialControls() > 0) {
|
||||
activeControllers = Controller.getNumberOfSpatialControls();
|
||||
|
@ -372,19 +460,19 @@ function update(deltaTime) {
|
|||
|
||||
var velocity = Vec3.multiply(BULLET_VELOCITY, Vec3.normalize(palmToFingerTipVector));
|
||||
|
||||
shootBullet(position, velocity);
|
||||
shootBullet(position, velocity, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function shootFromMouse() {
|
||||
function shootFromMouse(grenade) {
|
||||
var DISTANCE_FROM_CAMERA = 1.0;
|
||||
var camera = Camera.getPosition();
|
||||
var forwardVector = Quat.getFront(Camera.getOrientation());
|
||||
var newPosition = Vec3.sum(camera, Vec3.multiply(forwardVector, DISTANCE_FROM_CAMERA));
|
||||
var velocity = Vec3.multiply(forwardVector, BULLET_VELOCITY);
|
||||
shootBullet(newPosition, velocity);
|
||||
shootBullet(newPosition, velocity, grenade);
|
||||
}
|
||||
|
||||
function mouseReleaseEvent(event) {
|
||||
|
@ -392,21 +480,24 @@ function mouseReleaseEvent(event) {
|
|||
isMouseDown = false;
|
||||
}
|
||||
|
||||
function mouseMoveEvent(event) {
|
||||
if (isMouseDown) {
|
||||
var MOUSE_YAW_SCALE = -0.25;
|
||||
var MOUSE_PITCH_SCALE = -12.5;
|
||||
var FIXED_MOUSE_TIMESTEP = 0.016;
|
||||
yawFromMouse += ((event.x - lastX) * MOUSE_YAW_SCALE * FIXED_MOUSE_TIMESTEP);
|
||||
pitchFromMouse += ((event.y - lastY) * MOUSE_PITCH_SCALE * FIXED_MOUSE_TIMESTEP);
|
||||
lastX = event.x;
|
||||
lastY = event.y;
|
||||
}
|
||||
function mousePressEvent(event) {
|
||||
var clickedText = false;
|
||||
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
|
||||
if (clickedOverlay == offButton) {
|
||||
Script.stop();
|
||||
} else if (clickedOverlay == platformButton) {
|
||||
var platformSize = 3;
|
||||
makePlatform(-9.8, 1.0, platformSize);
|
||||
} else if (clickedOverlay == gridButton) {
|
||||
makeGrid("Box", 1.0, 3);
|
||||
}
|
||||
}
|
||||
|
||||
function scriptEnding() {
|
||||
Overlays.deleteOverlay(reticle);
|
||||
Overlays.deleteOverlay(offButton);
|
||||
Overlays.deleteOverlay(platformButton);
|
||||
Overlays.deleteOverlay(gridButton);
|
||||
Overlays.deleteOverlay(pointer[0]);
|
||||
Overlays.deleteOverlay(pointer[1]);
|
||||
Overlays.deleteOverlay(text);
|
||||
|
@ -418,7 +509,7 @@ Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity);
|
|||
Script.scriptEnding.connect(scriptEnding);
|
||||
Script.update.connect(update);
|
||||
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
Controller.keyPressEvent.connect(keyPressEvent);
|
||||
|
||||
|
||||
|
|
|
@ -14,13 +14,9 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
Script.include("libraries/entityPropertyDialogBox.js");
|
||||
Script.include("../../libraries/entityPropertyDialogBox.js");
|
||||
var entityPropertyDialogBox = EntityPropertyDialogBox;
|
||||
|
||||
var LASER_WIDTH = 4;
|
||||
var LASER_COLOR = { red: 255, green: 0, blue: 0 };
|
||||
var LASER_LENGTH_FACTOR = 500;
|
||||
|
||||
var MIN_ANGULAR_SIZE = 2;
|
||||
var MAX_ANGULAR_SIZE = 45;
|
||||
var allowLargeModels = false;
|
||||
|
@ -32,7 +28,44 @@ var RIGHT = 1;
|
|||
|
||||
var jointList = MyAvatar.getJointNames();
|
||||
|
||||
var mode = 0;
|
||||
var STICKS = 0;
|
||||
var MAPPED = 1;
|
||||
var mode = STICKS;
|
||||
|
||||
var LASER_WIDTH = 4;
|
||||
var LASER_COLOR = [{ red: 200, green: 150, blue: 50 }, // STICKS
|
||||
{ red: 50, green: 150, blue: 200 }]; // MAPPED
|
||||
var LASER_LENGTH_FACTOR = 500;
|
||||
|
||||
var lastAccurateIntersection = null;
|
||||
var accurateIntersections = 0;
|
||||
var totalIntersections = 0;
|
||||
var inaccurateInARow = 0;
|
||||
var maxInaccurateInARow = 0;
|
||||
function getRayIntersection(pickRay) { // pickRay : { origin : {xyz}, direction : {xyz} }
|
||||
if (lastAccurateIntersection === null) {
|
||||
lastAccurateIntersection = Entities.findRayIntersectionBlocking(pickRay);
|
||||
} else {
|
||||
var intersection = Entities.findRayIntersection(pickRay);
|
||||
if (intersection.accurate) {
|
||||
lastAccurateIntersection = intersection;
|
||||
accurateIntersections++;
|
||||
maxInaccurateInARow = (maxInaccurateInARow > inaccurateInARow) ? maxInaccurateInARow : inaccurateInARow;
|
||||
inaccurateInARow = 0;
|
||||
} else {
|
||||
inaccurateInARow++;
|
||||
}
|
||||
totalIntersections++;
|
||||
}
|
||||
return lastAccurateIntersection;
|
||||
}
|
||||
|
||||
function printIntersectionsStats() {
|
||||
var ratio = accurateIntersections / totalIntersections;
|
||||
print("Out of " + totalIntersections + " intersections, " + accurateIntersections + " where accurate. (" + ratio * 100 +"%)");
|
||||
print("Worst case was " + maxInaccurateInARow + " inaccurate intersections in a row.");
|
||||
}
|
||||
|
||||
|
||||
function controller(wichSide) {
|
||||
this.side = wichSide;
|
||||
|
@ -42,10 +75,10 @@ function controller(wichSide) {
|
|||
this.bumper = 6 * wichSide + 5;
|
||||
|
||||
this.oldPalmPosition = Controller.getSpatialControlPosition(this.palm);
|
||||
this.palmPosition = Controller.getSpatialControlPosition(this.palm);
|
||||
this.palmPosition = this.oldPalmPosition;
|
||||
|
||||
this.oldTipPosition = Controller.getSpatialControlPosition(this.tip);
|
||||
this.tipPosition = Controller.getSpatialControlPosition(this.tip);
|
||||
this.tipPosition = this.oldTipPosition;
|
||||
|
||||
this.oldUp = Controller.getSpatialControlNormal(this.palm);
|
||||
this.up = this.oldUp;
|
||||
|
@ -75,13 +108,13 @@ function controller(wichSide) {
|
|||
this.positionAtGrab;
|
||||
this.rotationAtGrab;
|
||||
this.modelPositionAtGrab;
|
||||
this.rotationAtGrab;
|
||||
this.modelRotationAtGrab;
|
||||
this.jointsIntersectingFromStart = [];
|
||||
|
||||
this.laser = Overlays.addOverlay("line3d", {
|
||||
start: { x: 0, y: 0, z: 0 },
|
||||
end: { x: 0, y: 0, z: 0 },
|
||||
color: LASER_COLOR,
|
||||
color: LASER_COLOR[mode],
|
||||
alpha: 1,
|
||||
visible: false,
|
||||
lineWidth: LASER_WIDTH,
|
||||
|
@ -132,7 +165,7 @@ function controller(wichSide) {
|
|||
this.positionAtGrab = this.palmPosition;
|
||||
this.rotationAtGrab = this.rotation;
|
||||
this.modelPositionAtGrab = properties.position;
|
||||
this.rotationAtGrab = properties.rotation;
|
||||
this.modelRotationAtGrab = properties.rotation;
|
||||
this.jointsIntersectingFromStart = [];
|
||||
for (var i = 0; i < jointList.length; i++) {
|
||||
var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition);
|
||||
|
@ -245,9 +278,9 @@ function controller(wichSide) {
|
|||
|
||||
var inverseRotation = Quat.inverse(MyAvatar.orientation);
|
||||
var startPosition = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.palmPosition, MyAvatar.position));
|
||||
startPosition = Vec3.multiply(startPosition, 1 / MyAvatar.scale);
|
||||
var direction = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.tipPosition, this.palmPosition));
|
||||
var distance = Vec3.length(direction);
|
||||
direction = Vec3.multiply(direction, LASER_LENGTH_FACTOR / distance);
|
||||
direction = Vec3.multiply(direction, LASER_LENGTH_FACTOR / (Vec3.length(direction) * MyAvatar.scale));
|
||||
var endPosition = Vec3.sum(startPosition, direction);
|
||||
|
||||
Overlays.editOverlay(this.laser, {
|
||||
|
@ -267,17 +300,16 @@ function controller(wichSide) {
|
|||
start: Vec3.sum(endPosition, Vec3.multiply(this.up, 2 * this.guideScale)),
|
||||
end: Vec3.sum(endPosition, Vec3.multiply(this.up, -2 * this.guideScale))
|
||||
});
|
||||
this.showLaser(!this.grabbing || mode == 0);
|
||||
this.showLaser(!this.grabbing || mode == STICKS);
|
||||
|
||||
if (this.glowedIntersectingModel.isKnownID) {
|
||||
Entities.editEntity(this.glowedIntersectingModel, { glowLevel: 0.0 });
|
||||
this.glowedIntersectingModel.isKnownID = false;
|
||||
}
|
||||
if (!this.grabbing) {
|
||||
var intersection = Entities.findRayIntersection({
|
||||
origin: this.palmPosition,
|
||||
direction: this.front
|
||||
});
|
||||
var intersection = getRayIntersection({ origin: this.palmPosition,
|
||||
direction: this.front
|
||||
});
|
||||
|
||||
var halfDiagonal = Vec3.length(intersection.properties.dimensions) / 2.0;
|
||||
|
||||
|
@ -304,17 +336,16 @@ function controller(wichSide) {
|
|||
if (this.grabbing) {
|
||||
if (!this.entityID.isKnownID) {
|
||||
print("Unknown grabbed ID " + this.entityID.id + ", isKnown: " + this.entityID.isKnownID);
|
||||
this.entityID = Entities.findRayIntersection({
|
||||
origin: this.palmPosition,
|
||||
direction: this.front
|
||||
}).entityID;
|
||||
this.entityID = getRayIntersection({ origin: this.palmPosition,
|
||||
direction: this.front
|
||||
}).entityID;
|
||||
print("Identified ID " + this.entityID.id + ", isKnown: " + this.entityID.isKnownID);
|
||||
}
|
||||
var newPosition;
|
||||
var newRotation;
|
||||
|
||||
switch (mode) {
|
||||
case 0:
|
||||
case STICKS:
|
||||
newPosition = Vec3.sum(this.palmPosition,
|
||||
Vec3.multiply(this.front, this.x));
|
||||
newPosition = Vec3.sum(newPosition,
|
||||
|
@ -328,7 +359,7 @@ function controller(wichSide) {
|
|||
newRotation = Quat.multiply(newRotation,
|
||||
this.oldModelRotation);
|
||||
break;
|
||||
case 1:
|
||||
case MAPPED:
|
||||
var forward = Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1 });
|
||||
var d = Vec3.dot(forward, MyAvatar.position);
|
||||
|
||||
|
@ -350,8 +381,9 @@ function controller(wichSide) {
|
|||
|
||||
newRotation = Quat.multiply(this.rotation,
|
||||
Quat.inverse(this.rotationAtGrab));
|
||||
newRotation = Quat.multiply(newRotation, newRotation);
|
||||
newRotation = Quat.multiply(newRotation,
|
||||
this.rotationAtGrab);
|
||||
this.modelRotationAtGrab);
|
||||
break;
|
||||
}
|
||||
Entities.editEntity(this.entityID, {
|
||||
|
@ -397,15 +429,13 @@ function controller(wichSide) {
|
|||
|
||||
var bumperValue = Controller.isButtonPressed(this.bumper);
|
||||
if (bumperValue && !this.bumperValue) {
|
||||
if (mode == 0) {
|
||||
mode = 1;
|
||||
Overlays.editOverlay(leftController.laser, { color: { red: 0, green: 0, blue: 255 } });
|
||||
Overlays.editOverlay(rightController.laser, { color: { red: 0, green: 0, blue: 255 } });
|
||||
} else {
|
||||
mode = 0;
|
||||
Overlays.editOverlay(leftController.laser, { color: { red: 255, green: 0, blue: 0 } });
|
||||
Overlays.editOverlay(rightController.laser, { color: { red: 255, green: 0, blue: 0 } });
|
||||
if (mode === STICKS) {
|
||||
mode = MAPPED;
|
||||
} else if (mode === MAPPED) {
|
||||
mode = STICKS;
|
||||
}
|
||||
Overlays.editOverlay(leftController.laser, { color: LASER_COLOR[mode] });
|
||||
Overlays.editOverlay(rightController.laser, { color: LASER_COLOR[mode] });
|
||||
}
|
||||
this.bumperValue = bumperValue;
|
||||
|
||||
|
@ -475,10 +505,10 @@ function controller(wichSide) {
|
|||
Vec3.print("Looking at: ", this.palmPosition);
|
||||
var pickRay = { origin: this.palmPosition,
|
||||
direction: Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)) };
|
||||
var foundIntersection = Entities.findRayIntersection(pickRay);
|
||||
var foundIntersection = getRayIntersection(pickRay);
|
||||
|
||||
if(!foundIntersection.accurate) {
|
||||
print("No accurate intersection");
|
||||
if(!foundIntersection.intersects) {
|
||||
print("No intersection");
|
||||
return;
|
||||
}
|
||||
newModel = foundIntersection.entityID;
|
||||
|
@ -526,7 +556,7 @@ function moveEntities() {
|
|||
|
||||
|
||||
switch (mode) {
|
||||
case 0:
|
||||
case STICKS:
|
||||
var oldLeftPoint = Vec3.sum(leftController.oldPalmPosition, Vec3.multiply(leftController.oldFront, leftController.x));
|
||||
var oldRightPoint = Vec3.sum(rightController.oldPalmPosition, Vec3.multiply(rightController.oldFront, rightController.x));
|
||||
|
||||
|
@ -545,7 +575,7 @@ function moveEntities() {
|
|||
newPosition = Vec3.sum(middle,
|
||||
Vec3.multiply(Vec3.subtract(leftController.oldModelPosition, oldMiddle), ratio));
|
||||
break;
|
||||
case 1:
|
||||
case MAPPED:
|
||||
var u = Vec3.normalize(Vec3.subtract(rightController.oldPalmPosition, leftController.oldPalmPosition));
|
||||
var v = Vec3.normalize(Vec3.subtract(rightController.palmPosition, leftController.palmPosition));
|
||||
|
||||
|
@ -566,11 +596,11 @@ function moveEntities() {
|
|||
leftController.positionAtGrab = leftController.palmPosition;
|
||||
leftController.rotationAtGrab = leftController.rotation;
|
||||
leftController.modelPositionAtGrab = leftController.oldModelPosition;
|
||||
leftController.rotationAtGrab = rotation;
|
||||
leftController.modelRotationAtGrab = rotation;
|
||||
rightController.positionAtGrab = rightController.palmPosition;
|
||||
rightController.rotationAtGrab = rightController.rotation;
|
||||
rightController.modelPositionAtGrab = rightController.oldModelPosition;
|
||||
rightController.rotationAtGrab = rotation;
|
||||
rightController.modelRotationAtGrab = rotation;
|
||||
break;
|
||||
}
|
||||
Entities.editEntity(leftController.entityID, {
|
||||
|
@ -628,43 +658,56 @@ var glowedEntityID = { id: -1, isKnownID: false };
|
|||
// In order for editVoxels and editModels to play nice together, they each check to see if a "delete" menu item already
|
||||
// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that
|
||||
// added it.
|
||||
var ROOT_MENU = "Edit";
|
||||
var ITEM_BEFORE = "Physics";
|
||||
var MENU_SEPARATOR = "Models";
|
||||
var EDIT_PROPERTIES = "Edit Properties...";
|
||||
var INTERSECTION_STATS = "Print Intersection Stats";
|
||||
var DELETE = "Delete";
|
||||
var LARGE_MODELS = "Allow Selecting of Large Models";
|
||||
var SMALL_MODELS = "Allow Selecting of Small Models";
|
||||
var LIGHTS = "Allow Selecting of Lights";
|
||||
|
||||
var modelMenuAddedDelete = false;
|
||||
var originalLightsArePickable = Entities.getLightsArePickable();
|
||||
function setupModelMenus() {
|
||||
print("setupModelMenus()");
|
||||
// adj our menuitems
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Models", isSeparator: true, beforeItem: "Physics" });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Edit Properties...",
|
||||
shortcutKeyEvent: { text: "`" }, afterItem: "Models" });
|
||||
if (!Menu.menuItemExists("Edit", "Delete")) {
|
||||
Menu.addMenuItem({ menuName: ROOT_MENU, menuItemName: MENU_SEPARATOR, isSeparator: true, beforeItem: ITEM_BEFORE });
|
||||
Menu.addMenuItem({ menuName: ROOT_MENU, menuItemName: EDIT_PROPERTIES,
|
||||
shortcutKeyEvent: { text: "`" }, afterItem: MENU_SEPARATOR });
|
||||
Menu.addMenuItem({ menuName: ROOT_MENU, menuItemName: INTERSECTION_STATS, afterItem: MENU_SEPARATOR });
|
||||
if (!Menu.menuItemExists(ROOT_MENU, DELETE)) {
|
||||
print("no delete... adding ours");
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete",
|
||||
shortcutKeyEvent: { text: "backspace" }, afterItem: "Models" });
|
||||
Menu.addMenuItem({ menuName: ROOT_MENU, menuItemName: DELETE,
|
||||
shortcutKeyEvent: { text: "backspace" }, afterItem: MENU_SEPARATOR });
|
||||
modelMenuAddedDelete = true;
|
||||
} else {
|
||||
print("delete exists... don't add ours");
|
||||
}
|
||||
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L",
|
||||
afterItem: "Paste Models", isCheckable: true });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S",
|
||||
afterItem: "Allow Selecting of Large Models", isCheckable: true });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L",
|
||||
afterItem: "Allow Selecting of Small Models", isCheckable: true });
|
||||
Menu.addMenuItem({ menuName: ROOT_MENU, menuItemName: LARGE_MODELS, shortcutKey: "CTRL+META+L",
|
||||
afterItem: DELETE, isCheckable: true });
|
||||
Menu.addMenuItem({ menuName: ROOT_MENU, menuItemName: SMALL_MODELS, shortcutKey: "CTRL+META+S",
|
||||
afterItem: LARGE_MODELS, isCheckable: true });
|
||||
Menu.addMenuItem({ menuName: ROOT_MENU, menuItemName: LIGHTS, shortcutKey: "CTRL+SHIFT+META+L",
|
||||
afterItem: SMALL_MODELS, isCheckable: true });
|
||||
|
||||
Entities.setLightsArePickable(false);
|
||||
}
|
||||
|
||||
function cleanupModelMenus() {
|
||||
Menu.removeMenuItem("Edit", "Edit Properties...");
|
||||
Menu.removeSeparator(ROOT_MENU, MENU_SEPARATOR);
|
||||
Menu.removeMenuItem(ROOT_MENU, EDIT_PROPERTIES);
|
||||
Menu.removeMenuItem(ROOT_MENU, INTERSECTION_STATS);
|
||||
if (modelMenuAddedDelete) {
|
||||
// delete our menuitems
|
||||
Menu.removeMenuItem("Edit", "Delete");
|
||||
Menu.removeMenuItem(ROOT_MENU, DELETE);
|
||||
}
|
||||
|
||||
Menu.removeMenuItem("Edit", "Allow Selecting of Large Models");
|
||||
Menu.removeMenuItem("Edit", "Allow Selecting of Small Models");
|
||||
Menu.removeMenuItem("Edit", "Allow Selecting of Lights");
|
||||
Menu.removeMenuItem(ROOT_MENU, LARGE_MODELS);
|
||||
Menu.removeMenuItem(ROOT_MENU, SMALL_MODELS);
|
||||
Menu.removeMenuItem(ROOT_MENU, LIGHTS);
|
||||
|
||||
}
|
||||
|
||||
|
@ -688,13 +731,13 @@ function showPropertiesForm(editModelID) {
|
|||
|
||||
Menu.menuItemEvent.connect(function (menuItem) {
|
||||
print("menuItemEvent() in JS... menuItem=" + menuItem);
|
||||
if (menuItem == "Allow Selecting of Small Models") {
|
||||
allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models");
|
||||
} else if (menuItem == "Allow Selecting of Large Models") {
|
||||
allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models");
|
||||
} else if (menuItem == "Allow Selecting of Lights") {
|
||||
Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights"));
|
||||
} else if (menuItem == "Delete") {
|
||||
if (menuItem == SMALL_MODELS) {
|
||||
allowSmallModels = Menu.isOptionChecked(SMALL_MODELS);
|
||||
} else if (menuItem == LARGE_MODELS) {
|
||||
allowLargeModels = Menu.isOptionChecked(LARGE_MODELS);
|
||||
} else if (menuItem == LIGHTS) {
|
||||
Entities.setLightsArePickable(Menu.isOptionChecked(LIGHTS));
|
||||
} else if (menuItem == DELETE) {
|
||||
if (leftController.grabbing) {
|
||||
print(" Delete Entity.... leftController.entityID="+ leftController.entityID);
|
||||
Entities.deleteEntity(leftController.entityID);
|
||||
|
@ -712,7 +755,7 @@ Menu.menuItemEvent.connect(function (menuItem) {
|
|||
} else {
|
||||
print(" Delete Entity.... not holding...");
|
||||
}
|
||||
} else if (menuItem == "Edit Properties...") {
|
||||
} else if (menuItem == EDIT_PROPERTIES) {
|
||||
editModelID = -1;
|
||||
if (leftController.grabbing) {
|
||||
print(" Edit Properties.... leftController.entityID="+ leftController.entityID);
|
||||
|
@ -727,16 +770,18 @@ Menu.menuItemEvent.connect(function (menuItem) {
|
|||
print(" Edit Properties.... about to edit properties...");
|
||||
showPropertiesForm(editModelID);
|
||||
}
|
||||
} else if (menuItem == INTERSECTION_STATS) {
|
||||
printIntersectionsStats();
|
||||
}
|
||||
});
|
||||
|
||||
Controller.keyReleaseEvent.connect(function (event) {
|
||||
// since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items
|
||||
if (event.text == "`") {
|
||||
handeMenuEvent("Edit Properties...");
|
||||
handeMenuEvent(EDIT_PROPERTIES);
|
||||
}
|
||||
if (event.text == "BACKSPACE") {
|
||||
handeMenuEvent("Delete");
|
||||
handeMenuEvent(DELETE);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
172
examples/controllers/hydra/paddleBall.js
Normal file
172
examples/controllers/hydra/paddleBall.js
Normal file
|
@ -0,0 +1,172 @@
|
|||
// PaddleBall.js
|
||||
//
|
||||
// Created by Philip Rosedale on January 21, 2015
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Move your hand with the hydra controller, and hit the ball with the paddle.
|
||||
// Click 'X' button to turn off this script.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var BALL_SIZE = 0.08;
|
||||
var PADDLE_SIZE = 0.20;
|
||||
var PADDLE_THICKNESS = 0.06;
|
||||
var PADDLE_COLOR = { red: 184, green: 134, blue: 11 };
|
||||
var BALL_COLOR = { red: 255, green: 0, blue: 0 };
|
||||
var LINE_COLOR = { red: 255, green: 255, blue: 0 };
|
||||
var PADDLE_OFFSET = { x: 0.05, y: 0.0, z: 0.0 };
|
||||
var GRAVITY = 0.0;
|
||||
var SPRING_FORCE = 15.0;
|
||||
var lastSoundTime = 0;
|
||||
var gameOn = false;
|
||||
var leftHanded = false;
|
||||
var controllerID;
|
||||
|
||||
if (leftHanded) {
|
||||
controllerID = 1;
|
||||
} else {
|
||||
controllerID = 3;
|
||||
}
|
||||
|
||||
|
||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
hitSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Collisions-ballhitsandcatches/billiards/collision1.wav");
|
||||
|
||||
var screenSize = Controller.getViewportDimensions();
|
||||
var offButton = Overlays.addOverlay("image", {
|
||||
x: screenSize.x - 48,
|
||||
y: 96,
|
||||
width: 32,
|
||||
height: 32,
|
||||
imageURL: HIFI_PUBLIC_BUCKET + "images/close.png",
|
||||
color: { red: 255, green: 255, blue: 255},
|
||||
alpha: 1
|
||||
});
|
||||
|
||||
var ball, paddle, paddleModel, line;
|
||||
|
||||
function createEntities() {
|
||||
ball = Entities.addEntity(
|
||||
{ type: "Sphere",
|
||||
position: Controller.getSpatialControlPosition(controllerID),
|
||||
dimensions: { x: BALL_SIZE, y: BALL_SIZE, z: BALL_SIZE },
|
||||
color: BALL_COLOR,
|
||||
gravity: { x: 0, y: GRAVITY, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
damping: 0.50,
|
||||
collisionsWillMove: true });
|
||||
|
||||
paddle = Entities.addEntity(
|
||||
{ type: "Box",
|
||||
position: Controller.getSpatialControlPosition(controllerID),
|
||||
dimensions: { x: PADDLE_SIZE, y: PADDLE_THICKNESS, z: PADDLE_SIZE * 0.80 },
|
||||
color: PADDLE_COLOR,
|
||||
gravity: { x: 0, y: 0, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
damping: 0.10,
|
||||
visible: false,
|
||||
rotation: Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(controllerID)),
|
||||
collisionsWillMove: false });
|
||||
|
||||
modelURL = "http://public.highfidelity.io/models/attachments/pong_paddle.fbx";
|
||||
paddleModel = Entities.addEntity(
|
||||
{ type: "Model",
|
||||
position: Vec3.sum(Controller.getSpatialControlPosition(controllerID), PADDLE_OFFSET),
|
||||
dimensions: { x: PADDLE_SIZE * 1.5, y: PADDLE_THICKNESS, z: PADDLE_SIZE * 1.25 },
|
||||
color: PADDLE_COLOR,
|
||||
gravity: { x: 0, y: 0, z: 0 },
|
||||
ignoreCollisions: true,
|
||||
modelURL: modelURL,
|
||||
damping: 0.10,
|
||||
rotation: Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(controllerID)),
|
||||
collisionsWillMove: false });
|
||||
|
||||
line = Overlays.addOverlay("line3d", {
|
||||
start: { x: 0, y: 0, z: 0 },
|
||||
end: { x: 0, y: 0, z: 0 },
|
||||
color: LINE_COLOR,
|
||||
alpha: 1,
|
||||
visible: true,
|
||||
lineWidth: 2 });
|
||||
}
|
||||
|
||||
function deleteEntities() {
|
||||
Entities.deleteEntity(ball);
|
||||
Entities.deleteEntity(paddle);
|
||||
Entities.deleteEntity(paddleModel);
|
||||
Overlays.deleteOverlay(line);
|
||||
}
|
||||
|
||||
function update(deltaTime) {
|
||||
var palmPosition = Controller.getSpatialControlPosition(controllerID);
|
||||
var controllerActive = (Vec3.length(palmPosition) > 0);
|
||||
|
||||
if (!gameOn && controllerActive) {
|
||||
createEntities();
|
||||
gameOn = true;
|
||||
} else if (gameOn && !controllerActive) {
|
||||
deleteEntities();
|
||||
gameOn = false;
|
||||
}
|
||||
if (!gameOn || !controllerActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!paddle.isKnownID) {
|
||||
paddle = Entities.identifyEntity(paddle);
|
||||
}
|
||||
if (!ball.isKnownID) {
|
||||
ball = Entities.identifyEntity(ball);
|
||||
} else {
|
||||
var props = Entities.getEntityProperties(ball);
|
||||
var spring = Vec3.subtract(palmPosition, props.position);
|
||||
var paddleWorldOrientation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(controllerID));
|
||||
var springLength = Vec3.length(spring);
|
||||
spring = Vec3.normalize(spring);
|
||||
var ballVelocity = Vec3.sum(props.velocity, Vec3.multiply(springLength * SPRING_FORCE * deltaTime, spring));
|
||||
Entities.editEntity(ball, { velocity: ballVelocity });
|
||||
Overlays.editOverlay(line, { start: props.position, end: palmPosition });
|
||||
Entities.editEntity(paddle, { position: palmPosition,
|
||||
velocity: Controller.getSpatialControlVelocity(controllerID),
|
||||
rotation: paddleWorldOrientation });
|
||||
Entities.editEntity(paddleModel, { position: Vec3.sum(palmPosition, Vec3.multiplyQbyV(paddleWorldOrientation, PADDLE_OFFSET)),
|
||||
velocity: Controller.getSpatialControlVelocity(controllerID),
|
||||
rotation: paddleWorldOrientation });
|
||||
}
|
||||
}
|
||||
|
||||
function entityCollisionWithEntity(entity1, entity2, collision) {
|
||||
if ((entity1.id == ball.id) || (entity2.id ==ball.id)) {
|
||||
var props1 = Entities.getEntityProperties(entity1);
|
||||
var props2 = Entities.getEntityProperties(entity2);
|
||||
var dVel = Vec3.length(Vec3.subtract(props1.velocity, props2.velocity));
|
||||
var currentTime = new Date().getTime();
|
||||
var MIN_MSECS_BETWEEN_BOUNCE_SOUNDS = 100;
|
||||
var MIN_VELOCITY_FOR_SOUND_IMPACT = 0.25;
|
||||
if ((dVel > MIN_VELOCITY_FOR_SOUND_IMPACT) && (currentTime - lastSoundTime) > MIN_MSECS_BETWEEN_BOUNCE_SOUNDS) {
|
||||
Audio.playSound(hitSound, { position: props1.position, volume: Math.min(dVel, 1.0) });
|
||||
lastSoundTime = new Date().getTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mousePressEvent(event) {
|
||||
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
|
||||
if (clickedOverlay == offButton) {
|
||||
Script.stop();
|
||||
}
|
||||
}
|
||||
|
||||
function scriptEnding() {
|
||||
if (gameOn) {
|
||||
deleteEntities();
|
||||
}
|
||||
Overlays.deleteOverlay(offButton);
|
||||
}
|
||||
|
||||
Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity);
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
Script.update.connect(update);
|
|
@ -60,11 +60,9 @@ Script.update.connect(function(deltaTime) {
|
|||
}
|
||||
|
||||
if ((leftFrame != lastLeftFrame) && leftHandAnimation.length){
|
||||
MyAvatar.stopAnimation(leftHandAnimation);
|
||||
MyAvatar.startAnimation(leftHandAnimation, 30.0, 1.0, false, true, leftFrame, leftFrame);
|
||||
}
|
||||
if ((rightFrame != lastRightFrame) && rightHandAnimation.length) {
|
||||
MyAvatar.stopAnimation(rightHandAnimation);
|
||||
MyAvatar.startAnimation(rightHandAnimation, 30.0, 1.0, false, true, rightFrame, rightFrame);
|
||||
}
|
||||
|
||||
|
|
|
@ -669,6 +669,10 @@ function mouseClickEvent(event) {
|
|||
|
||||
print("Model selected: " + foundEntity.id);
|
||||
selectionDisplay.select(selectedEntityID, event);
|
||||
|
||||
cameraManager.focus(selectionManager.worldPosition,
|
||||
selectionManager.worldDimensions,
|
||||
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Pool Table
|
||||
var tableParts = [];
|
||||
var balls = [];
|
||||
var cueBall;
|
||||
|
||||
var LENGTH = 2.84;
|
||||
var WIDTH = 1.42;
|
||||
|
@ -13,6 +14,8 @@ var HOLE_SIZE = BALL_SIZE;
|
|||
var DROP_HEIGHT = BALL_SIZE * 3.0;
|
||||
var GRAVITY = -9.8;
|
||||
var BALL_GAP = 0.001;
|
||||
var tableCenter;
|
||||
var cuePosition;
|
||||
|
||||
var startStroke = 0;
|
||||
|
||||
|
@ -23,7 +26,7 @@ var reticle = Overlays.addOverlay("image", {
|
|||
y: screenSize.y / 2 - 16,
|
||||
width: 32,
|
||||
height: 32,
|
||||
imageURL: HIFI_PUBLIC_BUCKET + "images/reticle.png",
|
||||
imageURL: HIFI_PUBLIC_BUCKET + "images/billiardsReticle.png",
|
||||
color: { red: 255, green: 255, blue: 255},
|
||||
alpha: 1
|
||||
});
|
||||
|
@ -102,7 +105,7 @@ function makeBalls(pos) {
|
|||
{ red: 128, green: 128, blue: 128}]; // Gray
|
||||
|
||||
// Object balls
|
||||
var ballPosition = { x: pos.x + (LENGTH / 4.0) * SCALE, y: pos.y + DROP_HEIGHT, z: pos.z };
|
||||
var ballPosition = { x: pos.x + (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z };
|
||||
for (var row = 1; row <= 5; row++) {
|
||||
ballPosition.z = pos.z - ((row - 1.0) / 2.0 * (BALL_SIZE + BALL_GAP) * SCALE);
|
||||
for (var spot = 0; spot < row; spot++) {
|
||||
|
@ -113,23 +116,26 @@ function makeBalls(pos) {
|
|||
color: colors[balls.length],
|
||||
gravity: { x: 0, y: GRAVITY, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
damping: 0.40,
|
||||
damping: 0.50,
|
||||
collisionsWillMove: true }));
|
||||
ballPosition.z += (BALL_SIZE + BALL_GAP) * SCALE;
|
||||
}
|
||||
ballPosition.x += (BALL_GAP + Math.sqrt(3.0) / 2.0 * BALL_SIZE) * SCALE;
|
||||
}
|
||||
// Cue Ball
|
||||
ballPosition = { x: pos.x - (LENGTH / 4.0) * SCALE, y: pos.y + DROP_HEIGHT, z: pos.z };
|
||||
balls.push(Entities.addEntity(
|
||||
cuePosition = { x: pos.x - (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z };
|
||||
cueBall = Entities.addEntity(
|
||||
{ type: "Sphere",
|
||||
position: ballPosition,
|
||||
position: cuePosition,
|
||||
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
|
||||
color: { red: 255, green: 255, blue: 255 },
|
||||
gravity: { x: 0, y: GRAVITY, z: 0 },
|
||||
angularVelocity: { x: 0, y: 0, z: 0 },
|
||||
velocity: {x: 0, y: 0, z: 0 },
|
||||
ignoreCollisions: false,
|
||||
damping: 0.40,
|
||||
collisionsWillMove: true }));
|
||||
damping: 0.50,
|
||||
collisionsWillMove: true });
|
||||
|
||||
}
|
||||
|
||||
function shootCue(velocity) {
|
||||
|
@ -140,19 +146,23 @@ function shootCue(velocity) {
|
|||
var velocity = Vec3.multiply(forwardVector, velocity);
|
||||
var BULLET_LIFETIME = 3.0;
|
||||
var BULLET_GRAVITY = 0.0;
|
||||
var SHOOTER_COLOR = { red: 255, green: 0, blue: 0 };
|
||||
var SHOOTER_SIZE = BALL_SIZE / 1.5 * SCALE;
|
||||
|
||||
bulletID = Entities.addEntity(
|
||||
{ type: "Sphere",
|
||||
position: cuePosition,
|
||||
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
|
||||
color: { red: 255, green: 255, blue: 255 },
|
||||
dimensions: { x: SHOOTER_SIZE, y: SHOOTER_SIZE, z: SHOOTER_SIZE },
|
||||
color: SHOOTER_COLOR,
|
||||
velocity: velocity,
|
||||
lifetime: BULLET_LIFETIME,
|
||||
gravity: { x: 0, y: BULLET_GRAVITY, z: 0 },
|
||||
damping: 0.10,
|
||||
density: 1000,
|
||||
density: 8000,
|
||||
ignoreCollisions: false,
|
||||
collisionsWillMove: true
|
||||
});
|
||||
print("Shot, velocity = " + velocity);
|
||||
}
|
||||
|
||||
function keyReleaseEvent(event) {
|
||||
|
@ -185,9 +195,25 @@ function cleanup() {
|
|||
Entities.deleteEntity(balls[i]);
|
||||
}
|
||||
Overlays.deleteOverlay(reticle);
|
||||
Entities.deleteEntity(cueBall);
|
||||
}
|
||||
|
||||
var tableCenter = Vec3.sum(MyAvatar.position, Vec3.multiply(4.0, Quat.getFront(Camera.getOrientation())));
|
||||
function update(deltaTime) {
|
||||
if (!cueBall.isKnownID) {
|
||||
cueBall = Entities.identifyEntity(cueBall);
|
||||
} else {
|
||||
// Check if cue ball has fallen off table, re-drop if so
|
||||
var cueProperties = Entities.getEntityProperties(cueBall);
|
||||
if (cueProperties.position.y < tableCenter.y) {
|
||||
// Replace the cueball
|
||||
Entities.editEntity(cueBall, { position: cuePosition } );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tableCenter = Vec3.sum(MyAvatar.position, Vec3.multiply(4.0, Quat.getFront(Camera.getOrientation())));
|
||||
|
||||
makeTable(tableCenter);
|
||||
makeBalls(tableCenter);
|
||||
|
@ -195,3 +221,4 @@ makeBalls(tableCenter);
|
|||
Script.scriptEnding.connect(cleanup);
|
||||
Controller.keyPressEvent.connect(keyPressEvent);
|
||||
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
||||
Script.update.connect(update);
|
|
@ -158,6 +158,11 @@ function handleModes() {
|
|||
avatarOrientation.w != MyAvatar.orientation.w)) {
|
||||
newMode = noMode;
|
||||
}
|
||||
|
||||
if (mode == noMode && newMode != noMode && Camera.mode == "independent") {
|
||||
newMode = noMode;
|
||||
}
|
||||
|
||||
// if leaving noMode
|
||||
if (mode == noMode && newMode != noMode) {
|
||||
saveCameraState();
|
||||
|
|
|
@ -80,7 +80,8 @@ CameraManager = function() {
|
|||
that.lastMousePosition = { x: 0, y: 0 };
|
||||
|
||||
that.enable = function() {
|
||||
if (that.enabled) return;
|
||||
if (Camera.mode == "independent" || that.enabled) return;
|
||||
|
||||
that.enabled = true;
|
||||
that.mode = MODE_INACTIVE;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
//
|
||||
|
||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
Script.include("libraries/toolBars.js");
|
||||
Script.include("../../libraries/toolBars.js");
|
||||
|
||||
var recordingFile = "recording.rec";
|
||||
|
||||
|
|
|
@ -18,6 +18,10 @@ function setupMenus() {
|
|||
}
|
||||
if (!Menu.menuExists("Developer > Entities")) {
|
||||
Menu.addMenu("Developer > Entities");
|
||||
|
||||
// NOTE: these menu items aren't currently working. I've temporarily removed them. Will add them back once we
|
||||
// rewire these to work
|
||||
/*
|
||||
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Bounds", isCheckable: true, isChecked: false });
|
||||
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Triangles", isCheckable: true, isChecked: false });
|
||||
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Display Model Element Bounds", isCheckable: true, isChecked: false });
|
||||
|
@ -26,9 +30,26 @@ function setupMenus() {
|
|||
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Attempt Render Entities as Scene", isCheckable: true, isChecked: false });
|
||||
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't Do Precision Picking", isCheckable: true, isChecked: false });
|
||||
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Disable Light Entities", isCheckable: true, isChecked: false });
|
||||
*/
|
||||
Menu.addMenuItem({ menuName: "Developer > Entities", menuItemName: "Don't send collision updates to server", isCheckable: true, isChecked: false });
|
||||
}
|
||||
}
|
||||
|
||||
Menu.menuItemEvent.connect(function (menuItem) {
|
||||
print("menuItemEvent() in JS... menuItem=" + menuItem);
|
||||
|
||||
if (menuItem == "Don't send collision updates to server") {
|
||||
var dontSendUpdates = Menu.isOptionChecked("Don't send collision updates to server");
|
||||
print(" dontSendUpdates... checked=" + dontSendUpdates);
|
||||
Entities.setSendPhysicsUpdates(!dontSendUpdates);
|
||||
}
|
||||
});
|
||||
|
||||
setupMenus();
|
||||
|
||||
// register our scriptEnding callback
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
|
||||
function scriptEnding() {
|
||||
Menu.removeMenu("Developer > Entities");
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@ set(TARGET_NAME ice-server)
|
|||
setup_hifi_project(Network)
|
||||
|
||||
# link the shared hifi libraries
|
||||
link_hifi_libraries(networking shared)
|
||||
link_hifi_libraries(embedded-webserver networking shared)
|
||||
|
||||
include_dependency_includes()
|
|
@ -20,14 +20,18 @@
|
|||
const int CLEAR_INACTIVE_PEERS_INTERVAL_MSECS = 1 * 1000;
|
||||
const int PEER_SILENCE_THRESHOLD_MSECS = 5 * 1000;
|
||||
|
||||
const quint16 ICE_SERVER_MONITORING_PORT = 40110;
|
||||
|
||||
IceServer::IceServer(int argc, char* argv[]) :
|
||||
QCoreApplication(argc, argv),
|
||||
_id(QUuid::createUuid()),
|
||||
_serverSocket(),
|
||||
_activePeers()
|
||||
_activePeers(),
|
||||
_httpManager(ICE_SERVER_MONITORING_PORT, QString("%1/web/").arg(QCoreApplication::applicationDirPath()), this)
|
||||
{
|
||||
// start the ice-server socket
|
||||
qDebug() << "ice-server socket is listening on" << ICE_SERVER_DEFAULT_PORT;
|
||||
qDebug() << "monitoring http endpoint is listening on " << ICE_SERVER_MONITORING_PORT;
|
||||
_serverSocket.bind(QHostAddress::AnyIPv4, ICE_SERVER_DEFAULT_PORT);
|
||||
|
||||
// call our process datagrams slot when the UDP socket has packets ready
|
||||
|
@ -165,3 +169,17 @@ void IceServer::clearInactivePeers() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IceServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler) {
|
||||
//
|
||||
// We need an HTTP handler in order to monitor the health of the ice server
|
||||
// The correct functioning of the ICE server will be determined by its HTTP availability,
|
||||
//
|
||||
|
||||
if (connection->requestOperation() == QNetworkAccessManager::GetOperation) {
|
||||
if (url.path() == "/status") {
|
||||
connection->respond(HTTPConnection::StatusCode200, QByteArray::number(_activePeers.size()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -12,17 +12,21 @@
|
|||
#ifndef hifi_IceServer_h
|
||||
#define hifi_IceServer_h
|
||||
|
||||
#include <qcoreapplication.h>
|
||||
#include <qsharedpointer.h>
|
||||
#include <qudpsocket.h>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QUdpSocket>
|
||||
|
||||
#include <NetworkPeer.h>
|
||||
#include <HTTPConnection.h>
|
||||
#include <HTTPManager.h>
|
||||
|
||||
typedef QHash<QUuid, SharedNetworkPeer> NetworkPeerHash;
|
||||
|
||||
class IceServer : public QCoreApplication {
|
||||
class IceServer : public QCoreApplication, public HTTPRequestHandler {
|
||||
Q_OBJECT
|
||||
public:
|
||||
IceServer(int argc, char* argv[]);
|
||||
bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler = false);
|
||||
private slots:
|
||||
void processDatagrams();
|
||||
void clearInactivePeers();
|
||||
|
@ -34,6 +38,7 @@ private:
|
|||
QUdpSocket _serverSocket;
|
||||
NetworkPeerHash _activePeers;
|
||||
QHash<QUuid, QSet<QUuid> > _currentConnections;
|
||||
HTTPManager _httpManager;
|
||||
};
|
||||
|
||||
#endif // hifi_IceServer_h
|
|
@ -33,13 +33,12 @@
|
|||
#include <QMenuBar>
|
||||
#include <QMouseEvent>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QOpenGLFramebufferObject>
|
||||
#include <QObject>
|
||||
#include <QWheelEvent>
|
||||
#include <QScreen>
|
||||
#include <QSettings>
|
||||
#include <QShortcut>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
#include <QWindow>
|
||||
|
@ -73,13 +72,16 @@
|
|||
#include <PhysicsEngine.h>
|
||||
#include <ProgramObject.h>
|
||||
#include <ResourceCache.h>
|
||||
#include <Settings.h>
|
||||
#include <SoundCache.h>
|
||||
#include <TextRenderer.h>
|
||||
#include <UserActivityLogger.h>
|
||||
#include <UUID.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Audio.h"
|
||||
#include "InterfaceVersion.h"
|
||||
#include "LODManager.h"
|
||||
#include "Menu.h"
|
||||
#include "ModelUploader.h"
|
||||
#include "Util.h"
|
||||
|
@ -100,7 +102,6 @@
|
|||
#include "gpu/Batch.h"
|
||||
#include "gpu/GLBackend.h"
|
||||
|
||||
|
||||
#include "scripting/AccountScriptingInterface.h"
|
||||
#include "scripting/AudioDeviceScriptingInterface.h"
|
||||
#include "scripting/ClipboardScriptingInterface.h"
|
||||
|
@ -112,9 +113,16 @@
|
|||
#include "scripting/WindowScriptingInterface.h"
|
||||
#include "scripting/WebWindowClass.h"
|
||||
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
#include "SpeechRecognizer.h"
|
||||
#endif
|
||||
|
||||
#include "ui/DataWebDialog.h"
|
||||
#include "ui/DialogsManager.h"
|
||||
#include "ui/InfoView.h"
|
||||
#include "ui/LoginDialog.h"
|
||||
#include "ui/Snapshot.h"
|
||||
#include "ui/StandAloneJSConsole.h"
|
||||
#include "ui/Stats.h"
|
||||
|
||||
|
||||
|
@ -127,9 +135,6 @@ static unsigned STARFIELD_SEED = 1;
|
|||
|
||||
static const int BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH = 6; // farther dragged clicks are ignored
|
||||
|
||||
|
||||
const qint64 MAXIMUM_CACHE_SIZE = 10737418240; // 10GB
|
||||
|
||||
static QTimer* idleTimer = NULL;
|
||||
|
||||
const QString CHECK_VERSION_URL = "https://highfidelity.io/latestVersion.xml";
|
||||
|
@ -137,6 +142,12 @@ const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::D
|
|||
|
||||
const QString DEFAULT_SCRIPTS_JS_URL = "http://s3.amazonaws.com/hifi-public/scripts/defaultScripts.js";
|
||||
|
||||
namespace SettingHandles {
|
||||
const SettingHandle<bool> firstRun("firstRun", true);
|
||||
const SettingHandle<QString> lastScriptLocation("LastScriptLocation");
|
||||
const SettingHandle<QString> scriptsLocation("scriptsLocation");
|
||||
}
|
||||
|
||||
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
|
||||
QString logMessage = LogHandler::getInstance().printMessage((LogMsgType) type, context, message);
|
||||
|
||||
|
@ -153,6 +164,16 @@ bool setupEssentials(int& argc, char** argv) {
|
|||
listenPort = atoi(portStr);
|
||||
}
|
||||
|
||||
// read the ApplicationInfo.ini file for Name/Version/Domain information
|
||||
QSettings::setDefaultFormat(QSettings::IniFormat);
|
||||
QSettings applicationInfo(PathUtils::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat);
|
||||
// set the associated application properties
|
||||
applicationInfo.beginGroup("INFO");
|
||||
QApplication::setApplicationName(applicationInfo.value("name").toString());
|
||||
QApplication::setApplicationVersion(BUILD_VERSION);
|
||||
QApplication::setOrganizationName(applicationInfo.value("organizationName").toString());
|
||||
QApplication::setOrganizationDomain(applicationInfo.value("organizationDomain").toString());
|
||||
|
||||
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
||||
|
||||
// Set dependencies
|
||||
|
@ -173,6 +194,12 @@ bool setupEssentials(int& argc, char** argv) {
|
|||
auto ddeFaceTracker = DependencyManager::set<DdeFaceTracker>();
|
||||
auto modelBlender = DependencyManager::set<ModelBlender>();
|
||||
auto audioToolBox = DependencyManager::set<AudioToolBox>();
|
||||
auto lodManager = DependencyManager::set<LODManager>();
|
||||
auto jsConsole = DependencyManager::set<StandAloneJSConsole>();
|
||||
auto dialogsManager = DependencyManager::set<DialogsManager>();
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
auto speechRecognizer = DependencyManager::set<SpeechRecognizer>();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -192,7 +219,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
_justStarted(true),
|
||||
_physicsEngine(glm::vec3(0.0f)),
|
||||
_entities(true, this, this),
|
||||
_entityCollisionSystem(),
|
||||
_entityClipboardRenderer(false, this, this),
|
||||
_entityClipboard(),
|
||||
_viewFrustum(),
|
||||
|
@ -224,35 +250,21 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
_isVSyncOn(true),
|
||||
_aboutToQuit(false)
|
||||
{
|
||||
auto glCanvas = DependencyManager::get<GLCanvas>();
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
_logger = new FileLogger(this); // After setting organization name in order to get correct directory
|
||||
qInstallMessageHandler(messageHandler);
|
||||
|
||||
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "styles/Inconsolata.otf");
|
||||
_window->setWindowTitle("Interface");
|
||||
|
||||
Model::setAbstractViewStateInterface(this); // The model class will sometimes need to know view state details from us
|
||||
|
||||
|
||||
// read the ApplicationInfo.ini file for Name/Version/Domain information
|
||||
QSettings applicationInfo(PathUtils::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat);
|
||||
|
||||
// set the associated application properties
|
||||
applicationInfo.beginGroup("INFO");
|
||||
|
||||
setApplicationName(applicationInfo.value("name").toString());
|
||||
setApplicationVersion(BUILD_VERSION);
|
||||
setOrganizationName(applicationInfo.value("organizationName").toString());
|
||||
setOrganizationDomain(applicationInfo.value("organizationDomain").toString());
|
||||
|
||||
_logger = new FileLogger(this); // After setting organization name in order to get correct directory
|
||||
|
||||
QSettings::setDefaultFormat(QSettings::IniFormat);
|
||||
auto glCanvas = DependencyManager::get<GLCanvas>();
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
_myAvatar = _avatarManager.getMyAvatar();
|
||||
|
||||
_applicationStartupTime = startup_time;
|
||||
|
||||
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "styles/Inconsolata.otf");
|
||||
_window->setWindowTitle("Interface");
|
||||
|
||||
qInstallMessageHandler(messageHandler);
|
||||
|
||||
qDebug() << "[VERSION] Build sequence: " << qPrintable(applicationVersion());
|
||||
|
||||
_bookmarks = new Bookmarks(); // Before setting up the menu
|
||||
|
@ -281,6 +293,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
auto audioIO = DependencyManager::get<Audio>();
|
||||
audioIO->moveToThread(audioThread);
|
||||
connect(audioThread, &QThread::started, audioIO.data(), &Audio::start);
|
||||
connect(audioIO.data(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled()));
|
||||
|
||||
audioThread->start();
|
||||
|
||||
|
@ -292,7 +305,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle()));
|
||||
connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(clearDomainOctreeDetails()));
|
||||
connect(&domainHandler, &DomainHandler::settingsReceived, this, &Application::domainSettingsReceived);
|
||||
connect(&domainHandler, &DomainHandler::hostnameChanged, Menu::getInstance(), &Menu::clearLoginDialogDisplayedFlag);
|
||||
connect(&domainHandler, &DomainHandler::hostnameChanged,
|
||||
DependencyManager::get<AddressManager>().data(), &AddressManager::storeCurrentAddress);
|
||||
|
||||
// update our location every 5 seconds in the data-server, assuming that we are authenticated with one
|
||||
const qint64 DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS = 5 * 1000;
|
||||
|
@ -318,7 +332,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
|
||||
connect(&accountManager, &AccountManager::balanceChanged, this, &Application::updateWindowTitle);
|
||||
|
||||
connect(&accountManager, &AccountManager::authRequired, Menu::getInstance(), &Menu::loginForCurrentDomain);
|
||||
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
||||
connect(&accountManager, &AccountManager::authRequired, dialogsManager.data(), &DialogsManager::showLoginDialog);
|
||||
connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle);
|
||||
|
||||
// once we have a profile in account manager make sure we generate a new keypair
|
||||
|
@ -339,9 +354,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
|
||||
connect(addressManager.data(), &AddressManager::rootPlaceNameChanged, this, &Application::updateWindowTitle);
|
||||
|
||||
_settings = new QSettings(this);
|
||||
_numChangedSettings = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
WSADATA WsaData;
|
||||
int wsaresult = WSAStartup(MAKEWORD(2,2), &WsaData);
|
||||
|
@ -371,18 +383,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
connect(billboardPacketTimer, &QTimer::timeout, _myAvatar, &MyAvatar::sendBillboardPacket);
|
||||
billboardPacketTimer->start(AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS);
|
||||
|
||||
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkDiskCache* cache = new QNetworkDiskCache();
|
||||
cache->setMaximumCacheSize(MAXIMUM_CACHE_SIZE);
|
||||
cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "interfaceCache");
|
||||
networkAccessManager.setCache(cache);
|
||||
|
||||
ResourceCache::setRequestLimit(3);
|
||||
|
||||
_window->setCentralWidget(glCanvas.data());
|
||||
|
||||
restoreSizeAndPosition();
|
||||
_window->restoreGeometry();
|
||||
|
||||
_window->setVisible(true);
|
||||
glCanvas->setFocusPolicy(Qt::StrongFocus);
|
||||
|
@ -416,23 +423,31 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
connect(this, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
|
||||
|
||||
// check first run...
|
||||
QVariant firstRunValue = _settings->value("firstRun",QVariant(true));
|
||||
if (firstRunValue.isValid() && firstRunValue.toBool()) {
|
||||
bool firstRun = SettingHandles::firstRun.get();
|
||||
if (firstRun) {
|
||||
qDebug() << "This is a first run...";
|
||||
// clear the scripts, and set out script to our default scripts
|
||||
clearScriptsBeforeRunning();
|
||||
loadScript(DEFAULT_SCRIPTS_JS_URL);
|
||||
|
||||
QMutexLocker locker(&_settingsMutex);
|
||||
_settings->setValue("firstRun",QVariant(false));
|
||||
SettingHandles::firstRun.set(false);
|
||||
} else {
|
||||
// do this as late as possible so that all required subsystems are initialized
|
||||
loadScripts();
|
||||
|
||||
QMutexLocker locker(&_settingsMutex);
|
||||
_previousScriptLocation = _settings->value("LastScriptLocation", QVariant("")).toString();
|
||||
_previousScriptLocation = SettingHandles::lastScriptLocation.get();
|
||||
}
|
||||
|
||||
|
||||
loadSettings();
|
||||
int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now
|
||||
connect(&_settingsTimer, &QTimer::timeout, this, &Application::saveSettings);
|
||||
connect(&_settingsThread, SIGNAL(started), &_settingsTimer, SLOT(start));
|
||||
connect(&_settingsThread, &QThread::finished, &_settingsTimer, &QTimer::deleteLater);
|
||||
_settingsTimer.moveToThread(&_settingsThread);
|
||||
_settingsTimer.setSingleShot(false);
|
||||
_settingsTimer.setInterval(SAVE_SETTINGS_INTERVAL);
|
||||
_settingsThread.start();
|
||||
|
||||
_trayIcon->show();
|
||||
|
||||
// set the local loopback interface for local sounds from audio scripts
|
||||
|
@ -453,12 +468,12 @@ void Application::aboutToQuit() {
|
|||
}
|
||||
|
||||
Application::~Application() {
|
||||
saveSettings();
|
||||
|
||||
_entities.getTree()->setSimulation(NULL);
|
||||
qInstallMessageHandler(NULL);
|
||||
|
||||
saveSettings();
|
||||
storeSizeAndPosition();
|
||||
_window->saveGeometry();
|
||||
|
||||
int DELAY_TIME = 1000;
|
||||
UserActivityLogger::getInstance().close(DELAY_TIME);
|
||||
|
@ -495,45 +510,6 @@ Application::~Application() {
|
|||
DependencyManager::destroy<GLCanvas>();
|
||||
}
|
||||
|
||||
void Application::saveSettings() {
|
||||
Menu::getInstance()->saveSettings();
|
||||
_rearMirrorTools->saveSettings(_settings);
|
||||
|
||||
_settings->sync();
|
||||
_numChangedSettings = 0;
|
||||
}
|
||||
|
||||
|
||||
void Application::restoreSizeAndPosition() {
|
||||
QRect available = desktop()->availableGeometry();
|
||||
|
||||
QMutexLocker locker(&_settingsMutex);
|
||||
_settings->beginGroup("Window");
|
||||
|
||||
int x = (int)loadSetting(_settings, "x", 0);
|
||||
int y = (int)loadSetting(_settings, "y", 0);
|
||||
_window->move(x, y);
|
||||
|
||||
int width = (int)loadSetting(_settings, "width", available.width());
|
||||
int height = (int)loadSetting(_settings, "height", available.height());
|
||||
_window->resize(width, height);
|
||||
|
||||
_settings->endGroup();
|
||||
}
|
||||
|
||||
void Application::storeSizeAndPosition() {
|
||||
QMutexLocker locker(&_settingsMutex);
|
||||
_settings->beginGroup("Window");
|
||||
|
||||
_settings->setValue("width", _window->rect().width());
|
||||
_settings->setValue("height", _window->rect().height());
|
||||
|
||||
_settings->setValue("x", _window->pos().x());
|
||||
_settings->setValue("y", _window->pos().y());
|
||||
|
||||
_settings->endGroup();
|
||||
}
|
||||
|
||||
void Application::initializeGL() {
|
||||
qDebug( "Created Display Window.");
|
||||
|
||||
|
@ -655,7 +631,7 @@ void Application::paintGL() {
|
|||
_myCamera.update(1.0f / _fps);
|
||||
}
|
||||
|
||||
if (Menu::getInstance()->getShadowsEnabled()) {
|
||||
if (getShadowsEnabled()) {
|
||||
updateShadowMap();
|
||||
}
|
||||
|
||||
|
@ -711,6 +687,24 @@ void Application::paintGL() {
|
|||
_frameCount++;
|
||||
}
|
||||
|
||||
void Application::runTests() {
|
||||
runTimingTests();
|
||||
}
|
||||
|
||||
void Application::audioMuteToggled() {
|
||||
QAction* muteAction = Menu::getInstance()->getActionForOption(MenuOption::MuteAudio);
|
||||
Q_CHECK_PTR(muteAction);
|
||||
muteAction->setChecked(DependencyManager::get<Audio>()->isMuted());
|
||||
}
|
||||
|
||||
void Application::aboutApp() {
|
||||
InfoView::forcedShow(INFO_HELP_PATH);
|
||||
}
|
||||
|
||||
void Application::showEditEntitiesHelp() {
|
||||
InfoView::forcedShow(INFO_EDIT_ENTITIES_PATH);
|
||||
}
|
||||
|
||||
void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height) {
|
||||
if (OculusManager::isConnected()) {
|
||||
OculusManager::configureCamera(camera, width, height);
|
||||
|
@ -718,7 +712,7 @@ void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height)
|
|||
TV3DManager::configureCamera(camera, width, height);
|
||||
} else {
|
||||
camera.setAspectRatio((float)width / height);
|
||||
camera.setFieldOfView(Menu::getInstance()->getFieldOfView());
|
||||
camera.setFieldOfView(_viewFrustum.getFieldOfView());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1441,10 +1435,6 @@ void Application::idle() {
|
|||
|
||||
// After finishing all of the above work, restart the idle timer, allowing 2ms to process events.
|
||||
idleTimer->start(2);
|
||||
|
||||
if (_numChangedSettings > 0) {
|
||||
saveSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1462,7 +1452,7 @@ void Application::checkBandwidthMeterClick() {
|
|||
|
||||
// The bandwidth meter is visible, the click didn't get dragged too far and
|
||||
// we actually hit the bandwidth meter
|
||||
Menu::getInstance()->bandwidthDetails();
|
||||
DependencyManager::get<DialogsManager>()->bandwidthDetails();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1600,6 +1590,20 @@ bool Application::exportEntities(const QString& filename, float x, float y, floa
|
|||
return true;
|
||||
}
|
||||
|
||||
void Application::loadSettings() {
|
||||
DependencyManager::get<Audio>()->loadSettings();
|
||||
DependencyManager::get<LODManager>()->loadSettings();
|
||||
Menu::getInstance()->loadSettings();
|
||||
_myAvatar->loadData();
|
||||
}
|
||||
|
||||
void Application::saveSettings() {
|
||||
DependencyManager::get<Audio>()->saveSettings();
|
||||
DependencyManager::get<LODManager>()->saveSettings();
|
||||
Menu::getInstance()->saveSettings();
|
||||
_myAvatar->saveData();
|
||||
}
|
||||
|
||||
bool Application::importEntities(const QString& filename) {
|
||||
_entityClipboard.eraseAllOctreeElements();
|
||||
bool success = _entityClipboard.readFromSVOFile(filename.toLocal8Bit().constData());
|
||||
|
@ -1650,8 +1654,6 @@ void Application::init() {
|
|||
|
||||
_timerStart.start();
|
||||
_lastTimeUpdated.start();
|
||||
|
||||
Menu::getInstance()->loadSettings();
|
||||
|
||||
// when --url in command line, teleport to location
|
||||
const QString HIFI_URL_COMMAND_LINE_KEY = "--url";
|
||||
|
@ -1669,11 +1671,11 @@ void Application::init() {
|
|||
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseEnabled)) {
|
||||
// on OS X we only setup sixense if the user wants it on - this allows running without the hid_init crash
|
||||
// if hydra support is temporarily not required
|
||||
Menu::getInstance()->toggleSixense(true);
|
||||
SixenseManager::getInstance().toggleSixense(true);
|
||||
}
|
||||
#else
|
||||
// setup sixense
|
||||
Menu::getInstance()->toggleSixense(true);
|
||||
SixenseManager::getInstance().toggleSixense(true);
|
||||
#endif
|
||||
|
||||
// initialize our face trackers after loading the menu settings
|
||||
|
@ -1689,17 +1691,16 @@ void Application::init() {
|
|||
_entities.init();
|
||||
_entities.setViewFrustum(getViewFrustum());
|
||||
|
||||
EntityTree* entityTree = _entities.getTree();
|
||||
|
||||
_entityCollisionSystem.init(&_entityEditSender, entityTree, &_avatarManager);
|
||||
|
||||
entityTree->setSimulation(&_entityCollisionSystem);
|
||||
EntityTree* tree = _entities.getTree();
|
||||
_physicsEngine.setEntityTree(tree);
|
||||
tree->setSimulation(&_physicsEngine);
|
||||
_physicsEngine.init(&_entityEditSender);
|
||||
|
||||
connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithEntity,
|
||||
connect(&_physicsEngine, &EntitySimulation::entityCollisionWithEntity,
|
||||
ScriptEngine::getEntityScriptingInterface(), &EntityScriptingInterface::entityCollisionWithEntity);
|
||||
|
||||
// connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts
|
||||
connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithEntity,
|
||||
connect(&_physicsEngine, &EntitySimulation::entityCollisionWithEntity,
|
||||
&_entities, &EntityTreeRenderer::entityCollisionWithEntity);
|
||||
|
||||
// connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing
|
||||
|
@ -1713,20 +1714,13 @@ void Application::init() {
|
|||
_metavoxels.init();
|
||||
|
||||
auto glCanvas = DependencyManager::get<GLCanvas>();
|
||||
_rearMirrorTools = new RearMirrorTools(glCanvas.data(), _mirrorViewRect, _settings);
|
||||
_rearMirrorTools = new RearMirrorTools(glCanvas.data(), _mirrorViewRect);
|
||||
|
||||
connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView()));
|
||||
connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView()));
|
||||
connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView()));
|
||||
connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors()));
|
||||
|
||||
// save settings when avatar changes
|
||||
connect(_myAvatar, &MyAvatar::transformChanged, this, &Application::bumpSettings);
|
||||
|
||||
EntityTree* tree = _entities.getTree();
|
||||
_physicsEngine.setEntityTree(tree);
|
||||
tree->setSimulation(&_physicsEngine);
|
||||
_physicsEngine.init(&_entityEditSender);
|
||||
// make sure our texture cache knows about window size changes
|
||||
DependencyManager::get<TextureCache>()->associateWithWidget(glCanvas.data());
|
||||
|
||||
|
@ -1768,9 +1762,9 @@ void Application::updateLOD() {
|
|||
PerformanceTimer perfTimer("LOD");
|
||||
// adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) {
|
||||
Menu::getInstance()->autoAdjustLOD(_fps);
|
||||
DependencyManager::get<LODManager>()->autoAdjustLOD(_fps);
|
||||
} else {
|
||||
Menu::getInstance()->resetLODAdjust();
|
||||
DependencyManager::get<LODManager>()->resetLODAdjust();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1887,7 +1881,7 @@ void Application::updateMyAvatarLookAtPosition() {
|
|||
// deflect using Faceshift gaze data
|
||||
glm::vec3 origin = _myAvatar->getHead()->getEyePosition();
|
||||
float pitchSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? -1.0f : 1.0f;
|
||||
float deflection = Menu::getInstance()->getFaceshiftEyeDeflection();
|
||||
float deflection = DependencyManager::get<Faceshift>()->getEyeDeflection();
|
||||
if (isLookingAtSomeone) {
|
||||
deflection *= GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT;
|
||||
}
|
||||
|
@ -1959,14 +1953,15 @@ void Application::updateDialogs(float deltaTime) {
|
|||
PerformanceTimer perfTimer("updateDialogs");
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateDialogs()");
|
||||
|
||||
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
||||
|
||||
// Update bandwidth dialog, if any
|
||||
BandwidthDialog* bandwidthDialog = Menu::getInstance()->getBandwidthDialog();
|
||||
BandwidthDialog* bandwidthDialog = dialogsManager->getBandwidthDialog();
|
||||
if (bandwidthDialog) {
|
||||
bandwidthDialog->update();
|
||||
}
|
||||
|
||||
OctreeStatsDialog* octreeStatsDialog = Menu::getInstance()->getOctreeStatsDialog();
|
||||
QPointer<OctreeStatsDialog> octreeStatsDialog = dialogsManager->getOctreeStatsDialog();
|
||||
if (octreeStatsDialog) {
|
||||
octreeStatsDialog->update();
|
||||
}
|
||||
|
@ -2047,9 +2042,6 @@ void Application::update(float deltaTime) {
|
|||
// NOTE: the _entities.update() call below will wait for lock
|
||||
// and will simulate entity motion (the EntityTree has been given an EntitySimulation).
|
||||
_entities.update(); // update the models...
|
||||
// The _entityCollisionSystem.updateCollisions() call below merely tries for lock,
|
||||
// and on failure it skips collision detection.
|
||||
_entityCollisionSystem.updateCollisions(); // collide the entities...
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -2240,8 +2232,9 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
_octreeQuery.setCameraNearClip(_viewFrustum.getNearClip());
|
||||
_octreeQuery.setCameraFarClip(_viewFrustum.getFarClip());
|
||||
_octreeQuery.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition());
|
||||
_octreeQuery.setOctreeSizeScale(Menu::getInstance()->getOctreeSizeScale());
|
||||
_octreeQuery.setBoundaryLevelAdjust(Menu::getInstance()->getBoundaryLevelAdjust());
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
_octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale());
|
||||
_octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust());
|
||||
|
||||
unsigned char queryPacket[MAX_PACKET_SIZE];
|
||||
|
||||
|
@ -2293,7 +2286,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
int perServerPPS = 0;
|
||||
const int SMALL_BUDGET = 10;
|
||||
int perUnknownServer = SMALL_BUDGET;
|
||||
int totalPPS = Menu::getInstance()->getMaxOctreePacketsPerSecond();
|
||||
int totalPPS = _octreeQuery.getMaxOctreePacketsPerSecond();
|
||||
|
||||
// determine PPS based on number of servers
|
||||
if (inViewServers >= 1) {
|
||||
|
@ -2414,7 +2407,7 @@ QRect Application::getDesirableApplicationGeometry() {
|
|||
|
||||
// If our parent window is on the HMD, then don't use it's geometry, instead use
|
||||
// the "main screen" geometry.
|
||||
HMDToolsDialog* hmdTools = Menu::getInstance()->getHMDToolsDialog();
|
||||
HMDToolsDialog* hmdTools = DependencyManager::get<DialogsManager>()->getHMDToolsDialog();
|
||||
if (hmdTools && hmdTools->hasHMDScreen()) {
|
||||
QScreen* hmdScreen = hmdTools->getHMDScreen();
|
||||
QWindow* appWindow = getWindow()->windowHandle();
|
||||
|
@ -2639,15 +2632,15 @@ void Application::setupWorldLight() {
|
|||
}
|
||||
|
||||
bool Application::shouldRenderMesh(float largestDimension, float distanceToCamera) {
|
||||
return Menu::getInstance()->shouldRenderMesh(largestDimension, distanceToCamera);
|
||||
return DependencyManager::get<LODManager>()->shouldRenderMesh(largestDimension, distanceToCamera);
|
||||
}
|
||||
|
||||
float Application::getSizeScale() const {
|
||||
return Menu::getInstance()->getOctreeSizeScale();
|
||||
return DependencyManager::get<LODManager>()->getOctreeSizeScale();
|
||||
}
|
||||
|
||||
int Application::getBoundaryLevelAdjust() const {
|
||||
return Menu::getInstance()->getBoundaryLevelAdjust();
|
||||
return DependencyManager::get<LODManager>()->getBoundaryLevelAdjust();
|
||||
}
|
||||
|
||||
PickRay Application::computePickRay(float x, float y) {
|
||||
|
@ -2943,8 +2936,10 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom
|
|||
}
|
||||
}
|
||||
|
||||
bool Application::getShadowsEnabled() {
|
||||
return Menu::getInstance()->getShadowsEnabled();
|
||||
bool Application::getShadowsEnabled() {
|
||||
Menu* menubar = Menu::getInstance();
|
||||
return menubar->isOptionChecked(MenuOption::SimpleShadows) ||
|
||||
menubar->isOptionChecked(MenuOption::CascadedShadows);
|
||||
}
|
||||
|
||||
bool Application::getCascadeShadowsEnabled() {
|
||||
|
@ -2989,7 +2984,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) {
|
|||
_mirrorCamera.setPosition(_myAvatar->getPosition() +
|
||||
_myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * _myAvatar->getScale());
|
||||
|
||||
} else if (_rearMirrorTools->getZoomLevel() == BODY) {
|
||||
} else if (SettingHandles::rearViewZoomLevel.get() == BODY) {
|
||||
_mirrorCamera.setFieldOfView(MIRROR_FIELD_OF_VIEW); // degrees
|
||||
_mirrorCamera.setPosition(_myAvatar->getChestPosition() +
|
||||
_myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale());
|
||||
|
@ -3386,45 +3381,45 @@ void Application::packetSent(quint64 length) {
|
|||
_bandwidthMeter.outputStream(BandwidthMeter::OCTREE).updateValue(length);
|
||||
}
|
||||
|
||||
const QString SETTINGS_KEY = "Settings";
|
||||
|
||||
void Application::loadScripts() {
|
||||
// loads all saved scripts
|
||||
int size = lockSettings()->beginReadArray("Settings");
|
||||
unlockSettings();
|
||||
Settings settings;
|
||||
int size = settings.beginReadArray(SETTINGS_KEY);
|
||||
for (int i = 0; i < size; ++i){
|
||||
lockSettings()->setArrayIndex(i);
|
||||
QString string = _settings->value("script").toString();
|
||||
unlockSettings();
|
||||
settings.setArrayIndex(i);
|
||||
QString string = settings.value("script").toString();
|
||||
if (!string.isEmpty()) {
|
||||
loadScript(string);
|
||||
}
|
||||
}
|
||||
|
||||
QMutexLocker locker(&_settingsMutex);
|
||||
_settings->endArray();
|
||||
settings.endArray();
|
||||
}
|
||||
|
||||
void Application::clearScriptsBeforeRunning() {
|
||||
// clears all scripts from the settings
|
||||
QMutexLocker locker(&_settingsMutex);
|
||||
_settings->remove("Settings");
|
||||
SettingHandles::SettingHandle<QVariant>(SETTINGS_KEY).remove();
|
||||
}
|
||||
|
||||
void Application::saveScripts() {
|
||||
// Saves all currently running user-loaded scripts
|
||||
QMutexLocker locker(&_settingsMutex);
|
||||
_settings->beginWriteArray("Settings");
|
||||
|
||||
QStringList runningScripts = getRunningScripts();
|
||||
if (runningScripts.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Saves all currently running user-loaded scripts
|
||||
Settings settings;
|
||||
settings.beginWriteArray(SETTINGS_KEY);
|
||||
int i = 0;
|
||||
for (QStringList::const_iterator it = runningScripts.begin(); it != runningScripts.end(); it += 1) {
|
||||
for (auto it = runningScripts.begin(); it != runningScripts.end(); ++it) {
|
||||
if (getScriptEngine(*it)->isUserLoaded()) {
|
||||
_settings->setArrayIndex(i);
|
||||
_settings->setValue("script", *it);
|
||||
i += 1;
|
||||
settings.setArrayIndex(i);
|
||||
settings.setValue("script", *it);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
_settings->endArray();
|
||||
settings.endArray();
|
||||
}
|
||||
|
||||
QScriptValue joystickToScriptValue(QScriptEngine *engine, Joystick* const &in) {
|
||||
|
@ -3451,7 +3446,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
scriptEngine->registerGlobalObject("Camera", &_myCamera);
|
||||
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
scriptEngine->registerGlobalObject("SpeechRecognizer", Menu::getInstance()->getSpeechRecognizer());
|
||||
scriptEngine->registerGlobalObject("SpeechRecognizer", DependencyManager::get<SpeechRecognizer>().data());
|
||||
#endif
|
||||
|
||||
ClipboardScriptingInterface* clipboardScriptable = new ClipboardScriptingInterface();
|
||||
|
@ -3551,7 +3546,6 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
|
|||
if (activateMainWindow && !loadScriptFromEditor) {
|
||||
_window->activateWindow();
|
||||
}
|
||||
bumpSettings();
|
||||
|
||||
return scriptEngine;
|
||||
}
|
||||
|
@ -3579,7 +3573,6 @@ void Application::scriptFinished(const QString& scriptName) {
|
|||
_scriptEnginesHash.erase(it);
|
||||
_runningScriptsWidget->scriptStopped(scriptName);
|
||||
_runningScriptsWidget->setRunningScripts(getRunningScripts());
|
||||
bumpSettings();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3675,7 +3668,6 @@ void Application::openUrl(const QUrl& url) {
|
|||
}
|
||||
|
||||
void Application::updateMyAvatarTransform() {
|
||||
bumpSettings();
|
||||
const float SIMULATION_OFFSET_QUANTIZATION = 16.0f; // meters
|
||||
glm::vec3 avatarPosition = _myAvatar->getPosition();
|
||||
glm::vec3 physicsWorldOffset = _physicsEngine.getOriginOffset();
|
||||
|
@ -3692,7 +3684,6 @@ void Application::updateMyAvatarTransform() {
|
|||
}
|
||||
|
||||
void Application::domainSettingsReceived(const QJsonObject& domainSettingsObject) {
|
||||
|
||||
// from the domain-handler, figure out the satoshi cost per voxel and per meter cubed
|
||||
const QString VOXEL_SETTINGS_KEY = "voxels";
|
||||
const QString PER_VOXEL_COST_KEY = "per-voxel-credits";
|
||||
|
@ -3735,9 +3726,7 @@ QString Application::getPreviousScriptLocation() {
|
|||
|
||||
void Application::setPreviousScriptLocation(const QString& previousScriptLocation) {
|
||||
_previousScriptLocation = previousScriptLocation;
|
||||
QMutexLocker locker(&_settingsMutex);
|
||||
_settings->setValue("LastScriptLocation", _previousScriptLocation);
|
||||
bumpSettings();
|
||||
SettingHandles::lastScriptLocation.set(_previousScriptLocation);
|
||||
}
|
||||
|
||||
void Application::loadDialog() {
|
||||
|
@ -3753,7 +3742,6 @@ void Application::loadDialog() {
|
|||
}
|
||||
|
||||
void Application::loadScriptURLDialog() {
|
||||
|
||||
QInputDialog scriptURLDialog(Application::getInstance()->getWindow());
|
||||
scriptURLDialog.setWindowTitle("Open and Run Script URL");
|
||||
scriptURLDialog.setLabelText("Script:");
|
||||
|
@ -3771,11 +3759,16 @@ void Application::loadScriptURLDialog() {
|
|||
}
|
||||
loadScript(newScript);
|
||||
}
|
||||
|
||||
sendFakeEnterEvent();
|
||||
}
|
||||
|
||||
QString Application::getScriptsLocation() const {
|
||||
return SettingHandles::scriptsLocation.get();
|
||||
}
|
||||
|
||||
void Application::setScriptsLocation(const QString& scriptsLocation) {
|
||||
SettingHandles::scriptsLocation.set(scriptsLocation);
|
||||
emit scriptLocationChanged(scriptsLocation);
|
||||
}
|
||||
|
||||
void Application::toggleLogDialog() {
|
||||
if (! _logDialog) {
|
||||
|
@ -3877,7 +3870,8 @@ void Application::takeSnapshot() {
|
|||
_snapshotShareDialog->show();
|
||||
}
|
||||
|
||||
void Application::setVSyncEnabled(bool vsyncOn) {
|
||||
void Application::setVSyncEnabled() {
|
||||
bool vsyncOn = Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerateVSyncOn);
|
||||
#if defined(Q_OS_WIN)
|
||||
if (wglewGetExtension("WGL_EXT_swap_control")) {
|
||||
wglSwapIntervalEXT(vsyncOn);
|
||||
|
@ -3901,6 +3895,7 @@ void Application::setVSyncEnabled(bool vsyncOn) {
|
|||
#else
|
||||
qDebug("V-Sync is FORCED ON on this system\n");
|
||||
#endif
|
||||
vsyncOn = true; // Turns off unused variable warning
|
||||
}
|
||||
|
||||
bool Application::isVSyncOn() const {
|
||||
|
|
|
@ -19,13 +19,11 @@
|
|||
#include <QImage>
|
||||
#include <QPointer>
|
||||
#include <QSet>
|
||||
#include <QSettings>
|
||||
#include <QStringList>
|
||||
#include <QUndoStack>
|
||||
|
||||
#include <AbstractScriptingServicesInterface.h>
|
||||
#include <AbstractViewStateInterface.h>
|
||||
#include <EntityCollisionSystem.h>
|
||||
#include <EntityEditPacketSender.h>
|
||||
#include <EntityTreeRenderer.h>
|
||||
#include <GeometryCache.h>
|
||||
|
@ -35,10 +33,10 @@
|
|||
#include <PacketHeaders.h>
|
||||
#include <PhysicsEngine.h>
|
||||
#include <ScriptEngine.h>
|
||||
#include <StDev.h>
|
||||
#include <TextureCache.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#include "Audio.h"
|
||||
#include "Bookmarks.h"
|
||||
#include "Camera.h"
|
||||
#include "DatagramProcessor.h"
|
||||
|
@ -81,7 +79,6 @@
|
|||
class QGLWidget;
|
||||
class QKeyEvent;
|
||||
class QMouseEvent;
|
||||
class QSettings;
|
||||
class QSystemTrayIcon;
|
||||
class QTouchEvent;
|
||||
class QWheelEvent;
|
||||
|
@ -122,6 +119,12 @@ static const quint64 TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS = 1 * USECS
|
|||
static const QString INFO_HELP_PATH = "html/interface-welcome-allsvg.html";
|
||||
static const QString INFO_EDIT_ENTITIES_PATH = "html/edit-entities-commands.html";
|
||||
|
||||
class Application;
|
||||
#if defined(qApp)
|
||||
#undef qApp
|
||||
#endif
|
||||
#define qApp (static_cast<Application*>(QCoreApplication::instance()))
|
||||
|
||||
class Application : public QApplication, public AbstractViewStateInterface, AbstractScriptingServicesInterface {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -129,18 +132,16 @@ class Application : public QApplication, public AbstractViewStateInterface, Abst
|
|||
friend class DatagramProcessor;
|
||||
|
||||
public:
|
||||
static Application* getInstance() { return static_cast<Application*>(QCoreApplication::instance()); }
|
||||
static Application* getInstance() { return qApp; } // TODO: replace fully by qApp
|
||||
static const glm::vec3& getPositionForPath() { return getInstance()->_myAvatar->getPosition(); }
|
||||
static glm::quat getOrientationForPath() { return getInstance()->_myAvatar->getOrientation(); }
|
||||
|
||||
Application(int& argc, char** argv, QElapsedTimer &startup_time);
|
||||
~Application();
|
||||
|
||||
void restoreSizeAndPosition();
|
||||
void loadScripts();
|
||||
QString getPreviousScriptLocation();
|
||||
void setPreviousScriptLocation(const QString& previousScriptLocation);
|
||||
void storeSizeAndPosition();
|
||||
void clearScriptsBeforeRunning();
|
||||
void initializeGL();
|
||||
void paintGL();
|
||||
|
@ -181,6 +182,7 @@ public:
|
|||
PrioVR* getPrioVR() { return &_prioVR; }
|
||||
QUndoStack* getUndoStack() { return &_undoStack; }
|
||||
MainWindow* getWindow() { return _window; }
|
||||
OctreeQuery& getOctreeQuery() { return _octreeQuery; }
|
||||
|
||||
EntityTree* getEntityClipboard() { return &_entityClipboard; }
|
||||
EntityTreeRenderer* getEntityClipboardRenderer() { return &_entityClipboardRenderer; }
|
||||
|
@ -216,12 +218,6 @@ public:
|
|||
virtual const Transform& getViewTransform() const { return _viewTransform; }
|
||||
void setViewTransform(const Transform& view);
|
||||
|
||||
/// if you need to access the application settings, use lockSettings()/unlockSettings()
|
||||
QSettings* lockSettings() { _settingsMutex.lock(); return _settings; }
|
||||
void unlockSettings() { _settingsMutex.unlock(); }
|
||||
|
||||
void saveSettings();
|
||||
|
||||
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
|
||||
void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); }
|
||||
void unlockOctreeSceneStats() { _octreeSceneStatsLock.unlock(); }
|
||||
|
@ -304,6 +300,9 @@ public:
|
|||
RunningScriptsWidget* getRunningScriptsWidget() { return _runningScriptsWidget; }
|
||||
|
||||
Bookmarks* getBookmarks() const { return _bookmarks; }
|
||||
|
||||
QString getScriptsLocation() const;
|
||||
void setScriptsLocation(const QString& scriptsLocation);
|
||||
|
||||
signals:
|
||||
|
||||
|
@ -318,6 +317,8 @@ signals:
|
|||
|
||||
/// Fired when the import window is closed
|
||||
void importDone();
|
||||
|
||||
void scriptLocationChanged(const QString& newPath);
|
||||
|
||||
public slots:
|
||||
void domainChanged(const QString& domainHostname);
|
||||
|
@ -354,13 +355,17 @@ public slots:
|
|||
void openUrl(const QUrl& url);
|
||||
|
||||
void updateMyAvatarTransform();
|
||||
void bumpSettings() { ++_numChangedSettings; }
|
||||
|
||||
void domainSettingsReceived(const QJsonObject& domainSettingsObject);
|
||||
|
||||
void setVSyncEnabled(bool vsyncOn);
|
||||
void setVSyncEnabled();
|
||||
|
||||
void resetSensors();
|
||||
void aboutApp();
|
||||
void showEditEntitiesHelp();
|
||||
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
|
||||
private slots:
|
||||
void clearDomainOctreeDetails();
|
||||
|
@ -388,6 +393,10 @@ private slots:
|
|||
void parseVersionXml();
|
||||
|
||||
void manageRunningScriptsWidgetVisibility(bool shown);
|
||||
|
||||
void runTests();
|
||||
|
||||
void audioMuteToggled();
|
||||
|
||||
private:
|
||||
void resetCamerasOnResizeGL(Camera& camera, int width, int height);
|
||||
|
@ -444,10 +453,6 @@ private:
|
|||
QThread* _nodeThread;
|
||||
DatagramProcessor _datagramProcessor;
|
||||
|
||||
QMutex _settingsMutex;
|
||||
QSettings* _settings;
|
||||
int _numChangedSettings;
|
||||
|
||||
QUndoStack _undoStack;
|
||||
UndoStackScriptingInterface _undoStackScriptingInterface;
|
||||
|
||||
|
@ -466,7 +471,6 @@ private:
|
|||
PhysicsEngine _physicsEngine;
|
||||
|
||||
EntityTreeRenderer _entities;
|
||||
EntityCollisionSystem _entityCollisionSystem;
|
||||
EntityTreeRenderer _entityClipboardRenderer;
|
||||
EntityTree _entityClipboard;
|
||||
|
||||
|
@ -568,6 +572,7 @@ private:
|
|||
RunningScriptsWidget* _runningScriptsWidget;
|
||||
QHash<QString, ScriptEngine*> _scriptEnginesHash;
|
||||
bool _runningScriptsWidgetWasVisible;
|
||||
QString _scriptsLocation;
|
||||
|
||||
QSystemTrayIcon* _trayIcon;
|
||||
|
||||
|
@ -581,6 +586,9 @@ private:
|
|||
bool _aboutToQuit;
|
||||
|
||||
Bookmarks* _bookmarks;
|
||||
|
||||
QThread _settingsThread;
|
||||
QTimer _settingsTimer;
|
||||
};
|
||||
|
||||
#endif // hifi_Application_h
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
//
|
||||
|
||||
#include <cstring>
|
||||
#include <math.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <CoreAudio/AudioHardware.h>
|
||||
|
@ -28,29 +29,35 @@
|
|||
#include <VersionHelpers.h>
|
||||
#endif
|
||||
|
||||
#include <AudioConstants.h>
|
||||
|
||||
#include <QtCore/QBuffer>
|
||||
#include <QtMultimedia/QAudioInput>
|
||||
#include <QtMultimedia/QAudioOutput>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <AudioConstants.h>
|
||||
#include <AudioInjector.h>
|
||||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
|
||||
#include <PositionalAudioStream.h>
|
||||
|
||||
#include <Settings.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <UUID.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
#include "Audio.h"
|
||||
|
||||
static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 100;
|
||||
|
||||
namespace SettingHandles {
|
||||
const SettingHandle<bool> audioOutputStarveDetectionEnabled("audioOutputStarveDetectionEnabled",
|
||||
DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED);
|
||||
const SettingHandle<int> audioOutputStarveDetectionThreshold("audioOutputStarveDetectionThreshold",
|
||||
DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_THRESHOLD);
|
||||
const SettingHandle<int> audioOutputStarveDetectionPeriod("audioOutputStarveDetectionPeriod",
|
||||
DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD);
|
||||
const SettingHandle<int> audioOutputBufferSize("audioOutputBufferSize",
|
||||
DEFAULT_MAX_FRAMES_OVER_DESIRED);
|
||||
}
|
||||
|
||||
Audio::Audio() :
|
||||
AbstractAudioInterface(),
|
||||
_audioInput(NULL),
|
||||
|
@ -118,7 +125,9 @@ void Audio::audioMixerKilled() {
|
|||
|
||||
QAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) {
|
||||
QAudioDeviceInfo result;
|
||||
#ifdef WIN32
|
||||
// Temporarily enable audio device selection in Windows again to test how it behaves now
|
||||
//#ifdef WIN32
|
||||
#if FALSE
|
||||
// NOTE
|
||||
// this is a workaround for a windows only QtBug https://bugreports.qt-project.org/browse/QTBUG-16117
|
||||
// static QAudioDeviceInfo objects get deallocated when QList<QAudioDevieInfo> objects go out of scope
|
||||
|
@ -1106,3 +1115,28 @@ qint64 Audio::AudioOutputIODevice::readData(char * data, qint64 maxSize) {
|
|||
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
void Audio::loadSettings() {
|
||||
_receivedAudioStream.loadSettings();
|
||||
|
||||
setOutputStarveDetectionEnabled(SettingHandles::audioOutputStarveDetectionEnabled.get());
|
||||
setOutputStarveDetectionThreshold(SettingHandles::audioOutputStarveDetectionThreshold.get());
|
||||
setOutputStarveDetectionPeriod(SettingHandles::audioOutputStarveDetectionPeriod.get());
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setOutputBufferSize",
|
||||
Q_ARG(int, SettingHandles::audioOutputBufferSize.get()));
|
||||
} else {
|
||||
setOutputBufferSize(SettingHandles::audioOutputBufferSize.get());
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::saveSettings() {
|
||||
_receivedAudioStream.saveSettings();
|
||||
|
||||
SettingHandles::audioOutputStarveDetectionEnabled.set(getOutputStarveDetectionEnabled());
|
||||
SettingHandles::audioOutputStarveDetectionThreshold.set(getOutputStarveDetectionThreshold());
|
||||
SettingHandles::audioOutputStarveDetectionPeriod.set(getOutputStarveDetectionPeriod());
|
||||
SettingHandles::audioOutputBufferSize.set(getOutputBufferSize());
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <DependencyManager.h>
|
||||
#include <StDev.h>
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
#include "audio/AudioIOStats.h"
|
||||
#include "audio/AudioNoiseGate.h"
|
||||
#include "AudioStreamStats.h"
|
||||
|
@ -96,14 +95,13 @@ public:
|
|||
};
|
||||
|
||||
const MixedProcessedAudioStream& getReceivedAudioStream() const { return _receivedAudioStream; }
|
||||
MixedProcessedAudioStream& getReceivedAudioStream() { return _receivedAudioStream; }
|
||||
|
||||
float getLastInputLoudness() const { return glm::max(_lastInputLoudness - _inputGate.getMeasuredFloor(), 0.0f); }
|
||||
|
||||
float getTimeSinceLastClip() const { return _timeSinceLastClip; }
|
||||
float getAudioAverageInputLoudness() const { return _lastInputLoudness; }
|
||||
|
||||
void setReceivedAudioStreamSettings(const InboundAudioStream::Settings& settings) { _receivedAudioStream.setSettings(settings); }
|
||||
|
||||
int getDesiredJitterBufferFrames() const { return _receivedAudioStream.getDesiredJitterBufferFrames(); }
|
||||
|
||||
bool isMuted() { return _muted; }
|
||||
|
@ -174,6 +172,9 @@ public slots:
|
|||
|
||||
void outputNotify();
|
||||
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
|
||||
signals:
|
||||
bool muteToggled();
|
||||
void inputReceived(const QByteArray& inputSamples);
|
||||
|
|
|
@ -9,10 +9,21 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
#include <QJsonObject>
|
||||
#include <QFile>
|
||||
#include <QInputDialog>
|
||||
#include <QJsonDocument>
|
||||
#include <QMessageBox>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include <AddressManager.h>
|
||||
#include <Application.h>
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "Menu.h"
|
||||
|
||||
#include "Bookmarks.h"
|
||||
|
||||
Bookmarks::Bookmarks() {
|
||||
|
@ -71,3 +82,125 @@ void Bookmarks::persistToFile() {
|
|||
QByteArray data = json.toJson();
|
||||
saveFile.write(data);
|
||||
}
|
||||
|
||||
void Bookmarks::setupMenus(Menu* menubar, QMenu* menu) {
|
||||
// Add menus/actions
|
||||
menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkLocation, 0,
|
||||
this, SLOT(bookmarkLocation()));
|
||||
_bookmarksMenu = menu->addMenu(MenuOption::Bookmarks);
|
||||
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark, 0,
|
||||
this, SLOT(deleteBookmark()));
|
||||
|
||||
// Enable/Disable menus as needed
|
||||
enableMenuItems(_bookmarks.count() > 0);
|
||||
|
||||
// Load bookmarks
|
||||
for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it ) {
|
||||
QString bookmarkName = it.key();
|
||||
QString bookmarkAddress = it.value().toString();
|
||||
addLocationToMenu(menubar, bookmarkName, bookmarkAddress);
|
||||
}
|
||||
}
|
||||
|
||||
void Bookmarks::bookmarkLocation() {
|
||||
QInputDialog bookmarkLocationDialog(qApp->getWindow());
|
||||
bookmarkLocationDialog.setWindowTitle("Bookmark Location");
|
||||
bookmarkLocationDialog.setLabelText("Name:");
|
||||
bookmarkLocationDialog.setInputMode(QInputDialog::TextInput);
|
||||
bookmarkLocationDialog.resize(400, 200);
|
||||
|
||||
if (bookmarkLocationDialog.exec() == QDialog::Rejected) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString bookmarkName = bookmarkLocationDialog.textValue().trimmed();
|
||||
bookmarkName = bookmarkName.replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
|
||||
if (bookmarkName.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto addressManager = DependencyManager::get<AddressManager>();
|
||||
QString bookmarkAddress = addressManager->currentAddress().toString();
|
||||
|
||||
Menu* menubar = Menu::getInstance();
|
||||
if (contains(bookmarkName)) {
|
||||
QMessageBox duplicateBookmarkMessage;
|
||||
duplicateBookmarkMessage.setIcon(QMessageBox::Warning);
|
||||
duplicateBookmarkMessage.setText("The bookmark name you entered already exists in your list.");
|
||||
duplicateBookmarkMessage.setInformativeText("Would you like to overwrite it?");
|
||||
duplicateBookmarkMessage.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
duplicateBookmarkMessage.setDefaultButton(QMessageBox::Yes);
|
||||
if (duplicateBookmarkMessage.exec() == QMessageBox::No) {
|
||||
return;
|
||||
}
|
||||
removeLocationFromMenu(menubar, bookmarkName);
|
||||
}
|
||||
|
||||
addLocationToMenu(menubar, bookmarkName, bookmarkAddress);
|
||||
insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName.
|
||||
|
||||
enableMenuItems(true);
|
||||
}
|
||||
|
||||
void Bookmarks::teleportToBookmark() {
|
||||
QAction* action = qobject_cast<QAction*>(sender());
|
||||
QString address = action->data().toString();
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(address);
|
||||
}
|
||||
|
||||
void Bookmarks::deleteBookmark() {
|
||||
|
||||
QStringList bookmarkList;
|
||||
QList<QAction*> menuItems = _bookmarksMenu->actions();
|
||||
for (int i = 0; i < menuItems.count(); i += 1) {
|
||||
bookmarkList.append(menuItems[i]->text());
|
||||
}
|
||||
|
||||
QInputDialog deleteBookmarkDialog(qApp->getWindow());
|
||||
deleteBookmarkDialog.setWindowTitle("Delete Bookmark");
|
||||
deleteBookmarkDialog.setLabelText("Select the bookmark to delete");
|
||||
deleteBookmarkDialog.resize(400, 400);
|
||||
deleteBookmarkDialog.setOption(QInputDialog::UseListViewForComboBoxItems);
|
||||
deleteBookmarkDialog.setComboBoxItems(bookmarkList);
|
||||
deleteBookmarkDialog.setOkButtonText("Delete");
|
||||
|
||||
if (deleteBookmarkDialog.exec() == QDialog::Rejected) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString bookmarkName = deleteBookmarkDialog.textValue().trimmed();
|
||||
if (bookmarkName.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
removeLocationFromMenu(Menu::getInstance(), bookmarkName);
|
||||
remove(bookmarkName);
|
||||
|
||||
if (_bookmarksMenu->actions().count() == 0) {
|
||||
enableMenuItems(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Bookmarks::enableMenuItems(bool enabled) {
|
||||
if (_bookmarksMenu) {
|
||||
_bookmarksMenu->setEnabled(enabled);
|
||||
}
|
||||
if (_deleteBookmarksAction) {
|
||||
_deleteBookmarksAction->setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void Bookmarks::addLocationToMenu(Menu* menubar, QString& name, QString& address) {
|
||||
QAction* teleportAction = new QAction(_bookmarksMenu);
|
||||
teleportAction->setData(address);
|
||||
connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark()));
|
||||
|
||||
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction,
|
||||
name, 0, QAction::NoRole);
|
||||
}
|
||||
|
||||
void Bookmarks::removeLocationFromMenu(Menu* menubar, QString& name) {
|
||||
menubar->removeAction(_bookmarksMenu, name);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -12,10 +12,13 @@
|
|||
#ifndef hifi_Bookmarks_h
|
||||
#define hifi_Bookmarks_h
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QDebug>
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
|
||||
class QAction;
|
||||
class QMenu;
|
||||
class Menu;
|
||||
|
||||
class Bookmarks: public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -23,19 +26,32 @@ class Bookmarks: public QObject {
|
|||
public:
|
||||
Bookmarks();
|
||||
|
||||
void setupMenus(Menu* menubar, QMenu* menu);
|
||||
|
||||
private slots:
|
||||
void bookmarkLocation();
|
||||
void teleportToBookmark();
|
||||
void deleteBookmark();
|
||||
|
||||
private:
|
||||
QVariantMap _bookmarks; // { name: address, ... }
|
||||
|
||||
QPointer<QMenu> _bookmarksMenu;
|
||||
QPointer<QAction> _deleteBookmarksAction;
|
||||
|
||||
const QString BOOKMARKS_FILENAME = "bookmarks.json";
|
||||
QString _bookmarksFilename;
|
||||
|
||||
void insert(const QString& name, const QString& address); // Overwrites any existing entry with same name.
|
||||
void remove(const QString& name);
|
||||
bool contains(const QString& name) const;
|
||||
|
||||
QVariantMap* getBookmarks() { return &_bookmarks; };
|
||||
|
||||
private:
|
||||
QVariantMap _bookmarks; // { name: address, ... }
|
||||
|
||||
const QString BOOKMARKS_FILENAME = "bookmarks.json";
|
||||
QString _bookmarksFilename;
|
||||
void readFromFile();
|
||||
void persistToFile();
|
||||
|
||||
void enableMenuItems(bool enabled);
|
||||
void addLocationToMenu(Menu* menubar, QString& name, QString& address);
|
||||
void removeLocationFromMenu(Menu* menubar, QString& name);
|
||||
};
|
||||
|
||||
#endif // hifi_Bookmarks_h
|
|
@ -15,6 +15,7 @@
|
|||
#include <PerfStat.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Audio.h"
|
||||
#include "Menu.h"
|
||||
|
||||
#include "DatagramProcessor.h"
|
||||
|
|
210
interface/src/LODManager.cpp
Normal file
210
interface/src/LODManager.cpp
Normal file
|
@ -0,0 +1,210 @@
|
|||
//
|
||||
// LODManager.cpp
|
||||
//
|
||||
//
|
||||
// Created by Clement on 1/16/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <Util.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "ui/DialogsManager.h"
|
||||
|
||||
#include "LODManager.h"
|
||||
|
||||
namespace SettingHandles {
|
||||
const SettingHandle<bool> automaticAvatarLOD("automaticAvatarLOD", true);
|
||||
const SettingHandle<float> avatarLODDecreaseFPS("avatarLODDecreaseFPS", DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS);
|
||||
const SettingHandle<float> avatarLODIncreaseFPS("avatarLODIncreaseFPS", ADJUST_LOD_UP_FPS);
|
||||
const SettingHandle<float> avatarLODDistanceMultiplier("avatarLODDistanceMultiplier",
|
||||
DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER);
|
||||
const SettingHandle<int> boundaryLevelAdjust("boundaryLevelAdjust", 0);
|
||||
const SettingHandle<float> octreeSizeScale("octreeSizeScale", DEFAULT_OCTREE_SIZE_SCALE);
|
||||
}
|
||||
|
||||
void LODManager::autoAdjustLOD(float currentFPS) {
|
||||
// NOTE: our first ~100 samples at app startup are completely all over the place, and we don't
|
||||
// really want to count them in our average, so we will ignore the real frame rates and stuff
|
||||
// our moving average with simulated good data
|
||||
const int IGNORE_THESE_SAMPLES = 100;
|
||||
const float ASSUMED_FPS = 60.0f;
|
||||
if (_fpsAverage.getSampleCount() < IGNORE_THESE_SAMPLES) {
|
||||
currentFPS = ASSUMED_FPS;
|
||||
}
|
||||
_fpsAverage.updateAverage(currentFPS);
|
||||
_fastFPSAverage.updateAverage(currentFPS);
|
||||
|
||||
quint64 now = usecTimestampNow();
|
||||
|
||||
const quint64 ADJUST_AVATAR_LOD_DOWN_DELAY = 1000 * 1000;
|
||||
if (_automaticAvatarLOD) {
|
||||
if (_fastFPSAverage.getAverage() < _avatarLODDecreaseFPS) {
|
||||
if (now - _lastAvatarDetailDrop > ADJUST_AVATAR_LOD_DOWN_DELAY) {
|
||||
// attempt to lower the detail in proportion to the fps difference
|
||||
float targetFps = (_avatarLODDecreaseFPS + _avatarLODIncreaseFPS) * 0.5f;
|
||||
float averageFps = _fastFPSAverage.getAverage();
|
||||
const float MAXIMUM_MULTIPLIER_SCALE = 2.0f;
|
||||
_avatarLODDistanceMultiplier = qMin(MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER, _avatarLODDistanceMultiplier *
|
||||
(averageFps < EPSILON ? MAXIMUM_MULTIPLIER_SCALE :
|
||||
qMin(MAXIMUM_MULTIPLIER_SCALE, targetFps / averageFps)));
|
||||
_lastAvatarDetailDrop = now;
|
||||
}
|
||||
} else if (_fastFPSAverage.getAverage() > _avatarLODIncreaseFPS) {
|
||||
// let the detail level creep slowly upwards
|
||||
const float DISTANCE_DECREASE_RATE = 0.05f;
|
||||
_avatarLODDistanceMultiplier = qMax(MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER,
|
||||
_avatarLODDistanceMultiplier - DISTANCE_DECREASE_RATE);
|
||||
}
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
quint64 elapsed = now - _lastAdjust;
|
||||
|
||||
if (elapsed > ADJUST_LOD_DOWN_DELAY && _fpsAverage.getAverage() < ADJUST_LOD_DOWN_FPS
|
||||
&& _octreeSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) {
|
||||
|
||||
_octreeSizeScale *= ADJUST_LOD_DOWN_BY;
|
||||
|
||||
if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) {
|
||||
_octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE;
|
||||
}
|
||||
changed = true;
|
||||
_lastAdjust = now;
|
||||
qDebug() << "adjusting LOD down... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage()
|
||||
<< "_octreeSizeScale=" << _octreeSizeScale;
|
||||
}
|
||||
|
||||
if (elapsed > ADJUST_LOD_UP_DELAY && _fpsAverage.getAverage() > ADJUST_LOD_UP_FPS
|
||||
&& _octreeSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) {
|
||||
_octreeSizeScale *= ADJUST_LOD_UP_BY;
|
||||
if (_octreeSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) {
|
||||
_octreeSizeScale = ADJUST_LOD_MAX_SIZE_SCALE;
|
||||
}
|
||||
changed = true;
|
||||
_lastAdjust = now;
|
||||
qDebug() << "adjusting LOD up... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage()
|
||||
<< "_octreeSizeScale=" << _octreeSizeScale;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
_shouldRenderTableNeedsRebuilding = true;
|
||||
auto lodToolsDialog = DependencyManager::get<DialogsManager>()->getLodToolsDialog();
|
||||
if (lodToolsDialog) {
|
||||
lodToolsDialog->reloadSliders();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LODManager::resetLODAdjust() {
|
||||
_fpsAverage.reset();
|
||||
_fastFPSAverage.reset();
|
||||
_lastAvatarDetailDrop = _lastAdjust = usecTimestampNow();
|
||||
}
|
||||
|
||||
QString LODManager::getLODFeedbackText() {
|
||||
// determine granularity feedback
|
||||
int boundaryLevelAdjust = getBoundaryLevelAdjust();
|
||||
QString granularityFeedback;
|
||||
|
||||
switch (boundaryLevelAdjust) {
|
||||
case 0: {
|
||||
granularityFeedback = QString("at standard granularity.");
|
||||
} break;
|
||||
case 1: {
|
||||
granularityFeedback = QString("at half of standard granularity.");
|
||||
} break;
|
||||
case 2: {
|
||||
granularityFeedback = QString("at a third of standard granularity.");
|
||||
} break;
|
||||
default: {
|
||||
granularityFeedback = QString("at 1/%1th of standard granularity.").arg(boundaryLevelAdjust + 1);
|
||||
} break;
|
||||
}
|
||||
|
||||
// distance feedback
|
||||
float octreeSizeScale = getOctreeSizeScale();
|
||||
float relativeToDefault = octreeSizeScale / DEFAULT_OCTREE_SIZE_SCALE;
|
||||
QString result;
|
||||
if (relativeToDefault > 1.01) {
|
||||
result = QString("%1 further %2").arg(relativeToDefault,8,'f',2).arg(granularityFeedback);
|
||||
} else if (relativeToDefault > 0.99) {
|
||||
result = QString("the default distance %1").arg(granularityFeedback);
|
||||
} else {
|
||||
result = QString("%1 of default %2").arg(relativeToDefault,8,'f',3).arg(granularityFeedback);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: This is essentially the same logic used to render octree cells, but since models are more detailed then octree cells
|
||||
// I've added a voxelToModelRatio that adjusts how much closer to a model you have to be to see it.
|
||||
bool LODManager::shouldRenderMesh(float largestDimension, float distanceToCamera) {
|
||||
const float octreeToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it.
|
||||
float octreeSizeScale = getOctreeSizeScale();
|
||||
int boundaryLevelAdjust = getBoundaryLevelAdjust();
|
||||
float maxScale = (float)TREE_SCALE;
|
||||
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / octreeToMeshRatio;
|
||||
|
||||
if (_shouldRenderTableNeedsRebuilding) {
|
||||
_shouldRenderTable.clear();
|
||||
|
||||
float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small
|
||||
float scale = maxScale;
|
||||
float visibleDistanceAtScale = visibleDistanceAtMaxScale;
|
||||
|
||||
while (scale > SMALLEST_SCALE_IN_TABLE) {
|
||||
scale /= 2.0f;
|
||||
visibleDistanceAtScale /= 2.0f;
|
||||
_shouldRenderTable[scale] = visibleDistanceAtScale;
|
||||
}
|
||||
_shouldRenderTableNeedsRebuilding = false;
|
||||
}
|
||||
|
||||
float closestScale = maxScale;
|
||||
float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale;
|
||||
QMap<float, float>::const_iterator lowerBound = _shouldRenderTable.lowerBound(largestDimension);
|
||||
if (lowerBound != _shouldRenderTable.constEnd()) {
|
||||
closestScale = lowerBound.key();
|
||||
visibleDistanceAtClosestScale = lowerBound.value();
|
||||
}
|
||||
|
||||
if (closestScale < largestDimension) {
|
||||
visibleDistanceAtClosestScale *= 2.0f;
|
||||
}
|
||||
|
||||
return (distanceToCamera <= visibleDistanceAtClosestScale);
|
||||
}
|
||||
|
||||
void LODManager::setOctreeSizeScale(float sizeScale) {
|
||||
_octreeSizeScale = sizeScale;
|
||||
_shouldRenderTableNeedsRebuilding = true;
|
||||
}
|
||||
|
||||
void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) {
|
||||
_boundaryLevelAdjust = boundaryLevelAdjust;
|
||||
_shouldRenderTableNeedsRebuilding = true;
|
||||
}
|
||||
|
||||
|
||||
void LODManager::loadSettings() {
|
||||
setAutomaticAvatarLOD(SettingHandles::automaticAvatarLOD.get());
|
||||
setAvatarLODDecreaseFPS(SettingHandles::avatarLODDecreaseFPS.get());
|
||||
setAvatarLODIncreaseFPS(SettingHandles::avatarLODIncreaseFPS.get());
|
||||
setAvatarLODDistanceMultiplier(SettingHandles::avatarLODDistanceMultiplier.get());
|
||||
setBoundaryLevelAdjust(SettingHandles::boundaryLevelAdjust.get());
|
||||
setOctreeSizeScale(SettingHandles::octreeSizeScale.get());
|
||||
}
|
||||
|
||||
void LODManager::saveSettings() {
|
||||
SettingHandles::automaticAvatarLOD.set(getAutomaticAvatarLOD());
|
||||
SettingHandles::avatarLODDecreaseFPS.set(getAvatarLODDecreaseFPS());
|
||||
SettingHandles::avatarLODIncreaseFPS.set(getAvatarLODIncreaseFPS());
|
||||
SettingHandles::avatarLODDistanceMultiplier.set(getAvatarLODDistanceMultiplier());
|
||||
SettingHandles::boundaryLevelAdjust.set(getBoundaryLevelAdjust());
|
||||
SettingHandles::octreeSizeScale.set(getOctreeSizeScale());
|
||||
}
|
||||
|
||||
|
91
interface/src/LODManager.h
Normal file
91
interface/src/LODManager.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
//
|
||||
// LODManager.h
|
||||
//
|
||||
//
|
||||
// Created by Clement on 1/16/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_LODManager_h
|
||||
#define hifi_LODManager_h
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <OctreeConstants.h>
|
||||
#include <Settings.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <SimpleMovingAverage.h>
|
||||
|
||||
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 quint64 ADJUST_LOD_DOWN_DELAY = 1000 * 1000 * 5;
|
||||
const quint64 ADJUST_LOD_UP_DELAY = ADJUST_LOD_DOWN_DELAY * 2;
|
||||
|
||||
const float ADJUST_LOD_DOWN_BY = 0.9f;
|
||||
const float ADJUST_LOD_UP_BY = 1.1f;
|
||||
|
||||
const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.25f;
|
||||
const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE;
|
||||
|
||||
const float MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 0.1f;
|
||||
const float MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 15.0f;
|
||||
const float DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER = 1.0f;
|
||||
|
||||
const int ONE_SECOND_OF_FRAMES = 60;
|
||||
const int FIVE_SECONDS_OF_FRAMES = 5 * ONE_SECOND_OF_FRAMES;
|
||||
|
||||
|
||||
class LODManager : public Dependency {
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
void setAutomaticAvatarLOD(bool automaticAvatarLOD) { _automaticAvatarLOD = automaticAvatarLOD; }
|
||||
bool getAutomaticAvatarLOD() const { return _automaticAvatarLOD; }
|
||||
void setAvatarLODDecreaseFPS(float avatarLODDecreaseFPS) { _avatarLODDecreaseFPS = avatarLODDecreaseFPS; }
|
||||
float getAvatarLODDecreaseFPS() const { return _avatarLODDecreaseFPS; }
|
||||
void setAvatarLODIncreaseFPS(float avatarLODIncreaseFPS) { _avatarLODIncreaseFPS = avatarLODIncreaseFPS; }
|
||||
float getAvatarLODIncreaseFPS() const { return _avatarLODIncreaseFPS; }
|
||||
void setAvatarLODDistanceMultiplier(float multiplier) { _avatarLODDistanceMultiplier = multiplier; }
|
||||
float getAvatarLODDistanceMultiplier() const { return _avatarLODDistanceMultiplier; }
|
||||
|
||||
// User Tweakable LOD Items
|
||||
QString getLODFeedbackText();
|
||||
void setOctreeSizeScale(float sizeScale);
|
||||
float getOctreeSizeScale() const { return _octreeSizeScale; }
|
||||
|
||||
void setBoundaryLevelAdjust(int boundaryLevelAdjust);
|
||||
int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
|
||||
|
||||
void autoAdjustLOD(float currentFPS);
|
||||
void resetLODAdjust();
|
||||
|
||||
bool shouldRenderMesh(float largestDimension, float distanceToCamera);
|
||||
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
|
||||
private:
|
||||
LODManager() {}
|
||||
|
||||
bool _automaticAvatarLOD = true;
|
||||
float _avatarLODDecreaseFPS = DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS;
|
||||
float _avatarLODIncreaseFPS = ADJUST_LOD_UP_FPS;
|
||||
float _avatarLODDistanceMultiplier = DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER;
|
||||
|
||||
float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE;
|
||||
int _boundaryLevelAdjust = 0;
|
||||
|
||||
quint64 _lastAdjust = 0;
|
||||
quint64 _lastAvatarDetailDrop = 0;
|
||||
SimpleMovingAverage _fpsAverage = FIVE_SECONDS_OF_FRAMES;
|
||||
SimpleMovingAverage _fastFPSAverage = ONE_SECOND_OF_FRAMES;
|
||||
|
||||
bool _shouldRenderTableNeedsRebuilding = true;
|
||||
QMap<float, float> _shouldRenderTable;
|
||||
};
|
||||
|
||||
#endif // hifi_LODManager_h
|
|
@ -9,9 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "Menu.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QEvent>
|
||||
#include <QMoveEvent>
|
||||
#include <QResizeEvent>
|
||||
|
@ -19,8 +18,33 @@
|
|||
#include <QHideEvent>
|
||||
#include <QWindowStateChangeEvent>
|
||||
|
||||
MainWindow::MainWindow(QWidget* parent) :
|
||||
QMainWindow(parent) {
|
||||
#include <Settings.h>
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "Menu.h"
|
||||
#include "Util.h"
|
||||
|
||||
namespace SettingHandles {
|
||||
const SettingHandle<QRect> windowGeometry("WindowGeometry");
|
||||
}
|
||||
|
||||
|
||||
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) {
|
||||
}
|
||||
|
||||
void MainWindow::restoreGeometry() {
|
||||
// Did not use setGeometry() on purpose,
|
||||
// see http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application
|
||||
QRect geometry = SettingHandles::windowGeometry.get(qApp->desktop()->availableGeometry());
|
||||
move(geometry.topLeft());
|
||||
resize(geometry.size());
|
||||
}
|
||||
|
||||
void MainWindow::saveGeometry() {
|
||||
// Did not use geometry() on purpose,
|
||||
// see http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application
|
||||
QRect geometry(pos(), size());
|
||||
SettingHandles::windowGeometry.set(geometry);
|
||||
}
|
||||
|
||||
void MainWindow::moveEvent(QMoveEvent* event) {
|
||||
|
|
|
@ -14,12 +14,15 @@
|
|||
|
||||
#include <QMainWindow>
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
class MainWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MainWindow(QWidget* parent = NULL);
|
||||
|
||||
|
||||
public slots:
|
||||
void restoreGeometry();
|
||||
void saveGeometry();
|
||||
|
||||
signals:
|
||||
void windowGeometryChanged(QRect geometry);
|
||||
void windowShown(bool shown);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -19,128 +19,23 @@
|
|||
#include <QPointer>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include <EventTypes.h>
|
||||
#include <MenuItemProperties.h>
|
||||
#include <OctreeConstants.h>
|
||||
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
#include "SpeechRecognizer.h"
|
||||
#endif
|
||||
|
||||
#include "devices/Faceshift.h"
|
||||
#include "devices/SixenseManager.h"
|
||||
#include "ui/ChatWindow.h"
|
||||
#include "ui/JSConsole.h"
|
||||
#include "ui/ScriptEditorWindow.h"
|
||||
|
||||
// Make an LOD handler class and move everything overthere
|
||||
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 quint64 ADJUST_LOD_DOWN_DELAY = 1000 * 1000 * 5;
|
||||
const quint64 ADJUST_LOD_UP_DELAY = ADJUST_LOD_DOWN_DELAY * 2;
|
||||
|
||||
const float ADJUST_LOD_DOWN_BY = 0.9f;
|
||||
const float ADJUST_LOD_UP_BY = 1.1f;
|
||||
|
||||
const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.25f;
|
||||
const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE;
|
||||
|
||||
const float MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 0.1f;
|
||||
const float MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 15.0f;
|
||||
const float DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER = 1.0f;
|
||||
|
||||
const int ONE_SECOND_OF_FRAMES = 60;
|
||||
const int FIVE_SECONDS_OF_FRAMES = 5 * ONE_SECOND_OF_FRAMES;
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f;
|
||||
|
||||
const QString SETTINGS_ADDRESS_KEY = "address";
|
||||
class QSettings;
|
||||
|
||||
class AddressBarDialog;
|
||||
class AnimationsDialog;
|
||||
class AttachmentsDialog;
|
||||
class CachesSizeDialog;
|
||||
class BandwidthDialog;
|
||||
class DataWebDialog;
|
||||
class HMDToolsDialog;
|
||||
class LodToolsDialog;
|
||||
class LoginDialog;
|
||||
class OctreeStatsDialog;
|
||||
class PreferencesDialog;
|
||||
class MetavoxelEditor;
|
||||
class MetavoxelNetworkSimulator;
|
||||
class ChatWindow;
|
||||
class MenuItemProperties;
|
||||
class Settings;
|
||||
|
||||
class Menu : public QMenuBar {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static Menu* getInstance();
|
||||
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
|
||||
QMenu* getMenu(const QString& menuName);
|
||||
|
||||
void triggerOption(const QString& menuOption);
|
||||
QAction* getActionForOption(const QString& menuOption);
|
||||
|
||||
const InboundAudioStream::Settings& getReceivedAudioStreamSettings() const { return _receivedAudioStreamSettings; }
|
||||
void setReceivedAudioStreamSettings(const InboundAudioStream::Settings& receivedAudioStreamSettings) { _receivedAudioStreamSettings = receivedAudioStreamSettings; }
|
||||
float getFieldOfView() const { return _fieldOfView; }
|
||||
void setFieldOfView(float fieldOfView) { _fieldOfView = fieldOfView; bumpSettings(); }
|
||||
float getRealWorldFieldOfView() const { return _realWorldFieldOfView; }
|
||||
void setRealWorldFieldOfView(float realWorldFieldOfView) { _realWorldFieldOfView = realWorldFieldOfView; bumpSettings(); }
|
||||
float getOculusUIAngularSize() const { return _oculusUIAngularSize; }
|
||||
void setOculusUIAngularSize(float oculusUIAngularSize) { _oculusUIAngularSize = oculusUIAngularSize; bumpSettings(); }
|
||||
float getSixenseReticleMoveSpeed() const { return _sixenseReticleMoveSpeed; }
|
||||
void setSixenseReticleMoveSpeed(float sixenseReticleMoveSpeed) { _sixenseReticleMoveSpeed = sixenseReticleMoveSpeed; bumpSettings(); }
|
||||
bool getInvertSixenseButtons() const { return _invertSixenseButtons; }
|
||||
void setInvertSixenseButtons(bool invertSixenseButtons) { _invertSixenseButtons = invertSixenseButtons; bumpSettings(); }
|
||||
|
||||
float getFaceshiftEyeDeflection() const { return _faceshiftEyeDeflection; }
|
||||
void setFaceshiftEyeDeflection(float faceshiftEyeDeflection) { _faceshiftEyeDeflection = faceshiftEyeDeflection; bumpSettings(); }
|
||||
const QString& getFaceshiftHostname() const { return _faceshiftHostname; }
|
||||
void setFaceshiftHostname(const QString& hostname) { _faceshiftHostname = hostname; bumpSettings(); }
|
||||
QString getSnapshotsLocation() const;
|
||||
void setSnapshotsLocation(QString snapshotsLocation) { _snapshotsLocation = snapshotsLocation; bumpSettings(); }
|
||||
|
||||
const QString& getScriptsLocation() const { return _scriptsLocation; }
|
||||
void setScriptsLocation(const QString& scriptsLocation);
|
||||
|
||||
BandwidthDialog* getBandwidthDialog() const { return _bandwidthDialog; }
|
||||
OctreeStatsDialog* getOctreeStatsDialog() const { return _octreeStatsDialog; }
|
||||
LodToolsDialog* getLodToolsDialog() const { return _lodToolsDialog; }
|
||||
HMDToolsDialog* getHMDToolsDialog() const { return _hmdToolsDialog; }
|
||||
|
||||
bool getShadowsEnabled() const;
|
||||
|
||||
// User Tweakable LOD Items
|
||||
QString getLODFeedbackText();
|
||||
void autoAdjustLOD(float currentFPS);
|
||||
void resetLODAdjust();
|
||||
void setOctreeSizeScale(float sizeScale);
|
||||
float getOctreeSizeScale() const { return _octreeSizeScale; }
|
||||
void setAutomaticAvatarLOD(bool automaticAvatarLOD) { _automaticAvatarLOD = automaticAvatarLOD; bumpSettings(); }
|
||||
bool getAutomaticAvatarLOD() const { return _automaticAvatarLOD; }
|
||||
void setAvatarLODDecreaseFPS(float avatarLODDecreaseFPS) { _avatarLODDecreaseFPS = avatarLODDecreaseFPS; bumpSettings(); }
|
||||
float getAvatarLODDecreaseFPS() const { return _avatarLODDecreaseFPS; }
|
||||
void setAvatarLODIncreaseFPS(float avatarLODIncreaseFPS) { _avatarLODIncreaseFPS = avatarLODIncreaseFPS; bumpSettings(); }
|
||||
float getAvatarLODIncreaseFPS() const { return _avatarLODIncreaseFPS; }
|
||||
void setAvatarLODDistanceMultiplier(float multiplier) { _avatarLODDistanceMultiplier = multiplier; bumpSettings(); }
|
||||
float getAvatarLODDistanceMultiplier() const { return _avatarLODDistanceMultiplier; }
|
||||
void setBoundaryLevelAdjust(int boundaryLevelAdjust);
|
||||
int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
|
||||
|
||||
bool shouldRenderMesh(float largestDimension, float distanceToCamera);
|
||||
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
SpeechRecognizer* getSpeechRecognizer() { return &_speechRecognizer; }
|
||||
#endif
|
||||
|
||||
// User Tweakable PPS from Voxel Server
|
||||
int getMaxOctreePacketsPerSecond() const { return _maxOctreePacketsPerSecond; }
|
||||
void setMaxOctreePacketsPerSecond(int value) { _maxOctreePacketsPerSecond = value; bumpSettings(); }
|
||||
|
||||
|
||||
QAction* addActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
const QString& actionName,
|
||||
const QKeySequence& shortcut = 0,
|
||||
|
@ -154,35 +49,10 @@ public:
|
|||
const QKeySequence& shortcut = 0,
|
||||
QAction::MenuRole role = QAction::NoRole,
|
||||
int menuItemLocation = UNSPECIFIED_POSITION);
|
||||
|
||||
|
||||
void removeAction(QMenu* menu, const QString& actionName);
|
||||
|
||||
const QByteArray& getWalletPrivateKey() const { return _walletPrivateKey; }
|
||||
|
||||
signals:
|
||||
void scriptLocationChanged(const QString& newPath);
|
||||
|
||||
public slots:
|
||||
|
||||
void clearLoginDialogDisplayedFlag();
|
||||
void loginForCurrentDomain();
|
||||
void showLoginForCurrentDomain();
|
||||
void bandwidthDetails();
|
||||
void octreeStatsDetails();
|
||||
void cachesSizeDialog();
|
||||
void lodTools();
|
||||
void hmdTools(bool showTools);
|
||||
void loadSettings(QSettings* settings = NULL);
|
||||
void saveSettings(QSettings* settings = NULL);
|
||||
void importSettings();
|
||||
void exportSettings();
|
||||
void toggleAddressBar();
|
||||
void copyAddress();
|
||||
void copyPath();
|
||||
|
||||
void toggleLoginMenuItem();
|
||||
void toggleSixense(bool shouldEnable);
|
||||
|
||||
QMenu* addMenu(const QString& menuName);
|
||||
void removeMenu(const QString& menuName);
|
||||
bool menuExists(const QString& menuName);
|
||||
|
@ -193,47 +63,21 @@ public slots:
|
|||
bool menuItemExists(const QString& menuName, const QString& menuitem);
|
||||
bool isOptionChecked(const QString& menuOption) const;
|
||||
void setIsOptionChecked(const QString& menuOption, bool isChecked);
|
||||
|
||||
private slots:
|
||||
void aboutApp();
|
||||
void showEditEntitiesHelp();
|
||||
void bumpSettings();
|
||||
void editPreferences();
|
||||
void editAttachments();
|
||||
void editAnimations();
|
||||
void changePrivateKey();
|
||||
void bookmarkLocation();
|
||||
void teleportToBookmark();
|
||||
void deleteBookmark();
|
||||
void hmdToolsClosed();
|
||||
void runTests();
|
||||
void showMetavoxelEditor();
|
||||
void showMetavoxelNetworkSimulator();
|
||||
void showScriptEditor();
|
||||
void showChat();
|
||||
void toggleConsole();
|
||||
void toggleToolWindow();
|
||||
void toggleChat();
|
||||
void audioMuteToggled();
|
||||
void displayNameLocationResponse(const QString& errorString);
|
||||
void changeVSync();
|
||||
void loadRSSDKFile();
|
||||
|
||||
|
||||
private:
|
||||
static Menu* _instance;
|
||||
|
||||
Menu();
|
||||
|
||||
typedef void(*settingsAction)(QSettings*, QAction*);
|
||||
static void loadAction(QSettings* set, QAction* action);
|
||||
static void saveAction(QSettings* set, QAction* action);
|
||||
void scanMenuBar(settingsAction modifySetting, QSettings* set);
|
||||
void scanMenu(QMenu* menu, settingsAction modifySetting, QSettings* set);
|
||||
|
||||
|
||||
typedef void(*settingsAction)(Settings&, QAction&);
|
||||
static void loadAction(Settings& settings, QAction& action);
|
||||
static void saveAction(Settings& settings, QAction& action);
|
||||
void scanMenuBar(settingsAction modifySetting);
|
||||
void scanMenu(QMenu& menu, settingsAction modifySetting, Settings& settings);
|
||||
|
||||
/// helper method to have separators with labels that are also compatible with OS X
|
||||
void addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& actionName,
|
||||
int menuItemLocation = UNSPECIFIED_POSITION);
|
||||
|
||||
int menuItemLocation = UNSPECIFIED_POSITION);
|
||||
|
||||
QAction* addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu,
|
||||
const QString& actionName,
|
||||
const QKeySequence& shortcut = 0,
|
||||
|
@ -241,78 +85,17 @@ private:
|
|||
const QObject* receiver = NULL,
|
||||
const char* member = NULL,
|
||||
int menuItemLocation = UNSPECIFIED_POSITION);
|
||||
|
||||
|
||||
QAction* getActionFromName(const QString& menuName, QMenu* menu);
|
||||
QMenu* getSubMenuFromName(const QString& menuName, QMenu* menu);
|
||||
QMenu* getMenuParent(const QString& menuName, QString& finalMenuPart);
|
||||
|
||||
|
||||
QAction* getMenuAction(const QString& menuName);
|
||||
int findPositionOfMenuItem(QMenu* menu, const QString& searchMenuItem);
|
||||
int positionBeforeSeparatorIfNeeded(QMenu* menu, int requestedPosition);
|
||||
QMenu* getMenu(const QString& menuName);
|
||||
|
||||
|
||||
|
||||
|
||||
QHash<QString, QAction*> _actionHash;
|
||||
InboundAudioStream::Settings _receivedAudioStreamSettings;
|
||||
// in Degrees, doesn't apply to HMD like Oculus
|
||||
float _fieldOfView = DEFAULT_FIELD_OF_VIEW_DEGREES;
|
||||
// The actual FOV set by the user's monitor size and view distance
|
||||
float _realWorldFieldOfView = DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES;
|
||||
float _faceshiftEyeDeflection = DEFAULT_FACESHIFT_EYE_DEFLECTION;
|
||||
QString _faceshiftHostname = DEFAULT_FACESHIFT_HOSTNAME;
|
||||
|
||||
QDialog* _jsConsole = nullptr;
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
SpeechRecognizer _speechRecognizer;
|
||||
#endif
|
||||
float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE;
|
||||
float _oculusUIAngularSize = DEFAULT_OCULUS_UI_ANGULAR_SIZE;
|
||||
float _sixenseReticleMoveSpeed = DEFAULT_SIXENSE_RETICLE_MOVE_SPEED;
|
||||
bool _invertSixenseButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS;
|
||||
bool _hasLoginDialogDisplayed = false;
|
||||
|
||||
bool _automaticAvatarLOD = true;
|
||||
float _avatarLODDecreaseFPS = DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS;
|
||||
float _avatarLODIncreaseFPS = ADJUST_LOD_UP_FPS;
|
||||
float _avatarLODDistanceMultiplier = DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER;
|
||||
|
||||
int _boundaryLevelAdjust = 0;
|
||||
int _maxOctreePacketsPerSecond = DEFAULT_MAX_OCTREE_PPS;
|
||||
|
||||
quint64 _lastAdjust;
|
||||
quint64 _lastAvatarDetailDrop;
|
||||
|
||||
SimpleMovingAverage _fpsAverage = FIVE_SECONDS_OF_FRAMES;
|
||||
SimpleMovingAverage _fastFPSAverage = ONE_SECOND_OF_FRAMES;
|
||||
|
||||
QPointer<AddressBarDialog> _addressBarDialog;
|
||||
QPointer<AnimationsDialog> _animationsDialog;
|
||||
QPointer<AttachmentsDialog> _attachmentsDialog;
|
||||
QPointer<BandwidthDialog> _bandwidthDialog;
|
||||
QPointer<CachesSizeDialog> _cachesSizeDialog;
|
||||
QPointer<HMDToolsDialog> _hmdToolsDialog;
|
||||
QPointer<LodToolsDialog> _lodToolsDialog;
|
||||
QPointer<LoginDialog> _loginDialog;
|
||||
QPointer<OctreeStatsDialog> _octreeStatsDialog;
|
||||
QPointer<PreferencesDialog> _preferencesDialog;
|
||||
|
||||
QPointer<MetavoxelEditor> _MetavoxelEditor;
|
||||
QPointer<MetavoxelNetworkSimulator> _metavoxelNetworkSimulator;
|
||||
QPointer<ScriptEditorWindow> _ScriptEditor;
|
||||
QPointer<ChatWindow> _chatWindow;
|
||||
|
||||
QAction* _loginAction = nullptr;
|
||||
QAction* _chatAction = nullptr;
|
||||
QString _snapshotsLocation;
|
||||
QString _scriptsLocation;
|
||||
QByteArray _walletPrivateKey;
|
||||
|
||||
bool _shouldRenderTableNeedsRebuilding = true;
|
||||
QMap<float, float> _shouldRenderTable;
|
||||
|
||||
void loadBookmarks();
|
||||
QMenu* _bookmarksMenu;
|
||||
QAction* _deleteBookmarksMenu;
|
||||
};
|
||||
|
||||
namespace MenuOption {
|
||||
|
@ -402,7 +185,6 @@ namespace MenuOption {
|
|||
const QString LodTools = "LOD Tools";
|
||||
const QString Login = "Login";
|
||||
const QString Log = "Log";
|
||||
const QString Logout = "Logout";
|
||||
const QString LowVelocityFilter = "Low Velocity Filter";
|
||||
const QString MetavoxelEditor = "Metavoxel Editor...";
|
||||
const QString Metavoxels = "Metavoxels";
|
||||
|
@ -484,10 +266,7 @@ namespace MenuOption {
|
|||
const QString UploadSkeleton = "Upload Skeleton Model";
|
||||
const QString UserInterface = "User Interface";
|
||||
const QString Visage = "Visage";
|
||||
const QString WalletPrivateKey = "Wallet Private Key...";
|
||||
const QString Wireframe = "Wireframe";
|
||||
}
|
||||
|
||||
void sendFakeEnterEvent();
|
||||
|
||||
#endif // hifi_Menu_h
|
||||
|
|
|
@ -1427,6 +1427,8 @@ public:
|
|||
void setColorMaterial(const StackArray::Entry& entry) { color = entry.color; material = entry.material; }
|
||||
|
||||
void mix(const EdgeCrossing& first, const EdgeCrossing& second, float t);
|
||||
|
||||
VoxelPoint createPoint(int clampedX, int clampedZ, float step) const;
|
||||
};
|
||||
|
||||
void EdgeCrossing::mix(const EdgeCrossing& first, const EdgeCrossing& second, float t) {
|
||||
|
@ -1437,6 +1439,16 @@ void EdgeCrossing::mix(const EdgeCrossing& first, const EdgeCrossing& second, fl
|
|||
material = (t < 0.5f) ? first.material : second.material;
|
||||
}
|
||||
|
||||
VoxelPoint EdgeCrossing::createPoint(int clampedX, int clampedZ, float step) const {
|
||||
VoxelPoint voxelPoint = { glm::vec3(clampedX + point.x, point.y, clampedZ + point.z) * step,
|
||||
{ (quint8)qRed(color), (quint8)qGreen(color), (quint8)qBlue(color) },
|
||||
{ (char)(normal.x * numeric_limits<qint8>::max()), (char)(normal.y * numeric_limits<qint8>::max()),
|
||||
(char)(normal.z * numeric_limits<qint8>::max()) },
|
||||
{ (quint8)material, 0, 0, 0 },
|
||||
{ numeric_limits<quint8>::max(), 0, 0, 0 } };
|
||||
return voxelPoint;
|
||||
}
|
||||
|
||||
const int MAX_NORMALS_PER_VERTEX = 4;
|
||||
|
||||
class NormalIndex {
|
||||
|
@ -1498,6 +1510,84 @@ const NormalIndex& IndexVector::get(int y) const {
|
|||
return (relative >= 0 && relative < size()) ? at(relative) : invalidIndex;
|
||||
}
|
||||
|
||||
static inline glm::vec3 getNormal(const QVector<VoxelPoint>& vertices, const NormalIndex& i0,
|
||||
const NormalIndex& i1, const NormalIndex& i2, const NormalIndex& i3) {
|
||||
// check both triangles in case one is degenerate
|
||||
const glm::vec3& v0 = vertices.at(i0.indices[0]).vertex;
|
||||
glm::vec3 normal = glm::cross(vertices.at(i1.indices[0]).vertex - v0, vertices.at(i2.indices[0]).vertex - v0);
|
||||
if (glm::length(normal) > EPSILON) {
|
||||
return normal;
|
||||
}
|
||||
return glm::cross(vertices.at(i2.indices[0]).vertex - v0, vertices.at(i3.indices[0]).vertex - v0);
|
||||
}
|
||||
|
||||
static inline void appendTriangle(const EdgeCrossing& e0, const EdgeCrossing& e1, const EdgeCrossing& e2,
|
||||
int clampedX, int clampedZ, float step, QVector<VoxelPoint>& vertices, QVector<int>& indices,
|
||||
QMultiHash<VoxelCoord, int>& quadIndices) {
|
||||
int firstIndex = vertices.size();
|
||||
vertices.append(e0.createPoint(clampedX, clampedZ, step));
|
||||
vertices.append(e1.createPoint(clampedX, clampedZ, step));
|
||||
vertices.append(e2.createPoint(clampedX, clampedZ, step));
|
||||
indices.append(firstIndex);
|
||||
indices.append(firstIndex + 1);
|
||||
indices.append(firstIndex + 2);
|
||||
indices.append(firstIndex + 2);
|
||||
|
||||
int minimumY = qMin((int)e0.point.y, qMin((int)e1.point.y, (int)e2.point.y));
|
||||
int maximumY = qMax((int)e0.point.y, qMax((int)e1.point.y, (int)e2.point.y));
|
||||
for (int y = minimumY; y <= maximumY; y++) {
|
||||
quadIndices.insert(qRgb(clampedX, y, clampedZ), firstIndex);
|
||||
}
|
||||
}
|
||||
|
||||
const int CORNER_COUNT = 4;
|
||||
|
||||
static StackArray::Entry getEntry(const StackArray* lineSrc, int stackWidth, int y, float heightfieldHeight,
|
||||
EdgeCrossing cornerCrossings[CORNER_COUNT], int cornerIndex) {
|
||||
int offsetX = (cornerIndex & X_MAXIMUM_FLAG) ? 1 : 0;
|
||||
int offsetZ = (cornerIndex & Y_MAXIMUM_FLAG) ? 1 : 0;
|
||||
const StackArray& src = lineSrc[offsetZ * stackWidth + offsetX];
|
||||
int count = src.getEntryCount();
|
||||
if (count > 0) {
|
||||
int relative = y - src.getPosition();
|
||||
if (relative < count && (relative >= 0 || heightfieldHeight == 0.0f)) {
|
||||
return src.getEntry(y, heightfieldHeight);
|
||||
}
|
||||
}
|
||||
const EdgeCrossing& cornerCrossing = cornerCrossings[cornerIndex];
|
||||
if (cornerCrossing.point.y == 0.0f) {
|
||||
return src.getEntry(y, heightfieldHeight);
|
||||
}
|
||||
StackArray::Entry entry;
|
||||
bool set = false;
|
||||
if (cornerCrossing.point.y >= y) {
|
||||
entry.color = cornerCrossing.color;
|
||||
entry.material = cornerCrossing.material;
|
||||
set = true;
|
||||
entry.setHermiteY(cornerCrossing.normal, glm::clamp(cornerCrossing.point.y - y, 0.0f, 1.0f));
|
||||
|
||||
} else {
|
||||
entry.material = entry.color = 0;
|
||||
}
|
||||
if (!(cornerIndex & X_MAXIMUM_FLAG)) {
|
||||
const EdgeCrossing& nextCornerCrossingX = cornerCrossings[cornerIndex | X_MAXIMUM_FLAG];
|
||||
if (nextCornerCrossingX.point.y != 0.0f && (nextCornerCrossingX.point.y >= y) != set) {
|
||||
float t = glm::clamp((y - cornerCrossing.point.y) /
|
||||
(nextCornerCrossingX.point.y - cornerCrossing.point.y), 0.0f, 1.0f);
|
||||
entry.setHermiteX(glm::normalize(glm::mix(cornerCrossing.normal, nextCornerCrossingX.normal, t)), t);
|
||||
}
|
||||
}
|
||||
if (!(cornerIndex & Y_MAXIMUM_FLAG)) {
|
||||
const EdgeCrossing& nextCornerCrossingZ = cornerCrossings[cornerIndex | Y_MAXIMUM_FLAG];
|
||||
if (nextCornerCrossingZ.point.y != 0.0f && (nextCornerCrossingZ.point.y >= y) != set) {
|
||||
float t = glm::clamp((y - cornerCrossing.point.y) /
|
||||
(nextCornerCrossingZ.point.y - cornerCrossing.point.y), 0.0f, 1.0f);
|
||||
entry.setHermiteZ(glm::normalize(glm::mix(cornerCrossing.normal, nextCornerCrossingZ.normal, t)), t);
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const glm::vec3& translation,
|
||||
const glm::quat& rotation, const glm::vec3& scale, bool cursor) {
|
||||
if (!node->getHeight()) {
|
||||
|
@ -1706,7 +1796,6 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
const int LOWER_RIGHT_CORNER = 8;
|
||||
const int NO_CORNERS = 0;
|
||||
const int ALL_CORNERS = UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER | LOWER_LEFT_CORNER | LOWER_RIGHT_CORNER;
|
||||
const int CORNER_COUNT = 4;
|
||||
const int NEXT_CORNERS[] = { 1, 3, 0, 2 };
|
||||
int corners = NO_CORNERS;
|
||||
if (heightfieldHeight != 0.0f) {
|
||||
|
@ -1772,6 +1861,15 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
}
|
||||
minimumY = qMin(minimumY, cornerMinimumY);
|
||||
maximumY = qMax(maximumY, cornerMaximumY);
|
||||
|
||||
if (corners == (LOWER_LEFT_CORNER | UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER)) {
|
||||
appendTriangle(cornerCrossings[1], cornerCrossings[0], cornerCrossings[2],
|
||||
clampedX, clampedZ, step, vertices, indices, quadIndices);
|
||||
|
||||
} else if (corners == (UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER)) {
|
||||
appendTriangle(cornerCrossings[2], cornerCrossings[3], cornerCrossings[1],
|
||||
clampedX, clampedZ, step, vertices, indices, quadIndices);
|
||||
}
|
||||
}
|
||||
int position = minimumY;
|
||||
int count = maximumY - minimumY + 1;
|
||||
|
@ -1781,7 +1879,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
indicesZ[x].position = position;
|
||||
indicesZ[x].resize(count);
|
||||
for (int y = position, end = position + count; y < end; y++) {
|
||||
const StackArray::Entry& entry = lineSrc->getEntry(y, heightfieldHeight);
|
||||
StackArray::Entry entry = getEntry(lineSrc, stackWidth, y, heightfieldHeight, cornerCrossings, 0);
|
||||
if (displayHermite && x != 0 && z != 0 && !lineSrc->isEmpty() && y >= lineSrc->getPosition()) {
|
||||
glm::vec3 normal;
|
||||
if (entry.hermiteX != 0) {
|
||||
|
@ -1846,41 +1944,38 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
if (!(corners & (1 << i))) {
|
||||
continue;
|
||||
}
|
||||
int offsetX = (i & X_MAXIMUM_FLAG) ? 1 : 0;
|
||||
int offsetZ = (i & Y_MAXIMUM_FLAG) ? 1 : 0;
|
||||
const quint16* height = heightLineSrc + offsetZ * width + offsetX;
|
||||
float heightValue = *height * voxelScale;
|
||||
if (heightValue >= y && heightValue < y + 1) {
|
||||
const EdgeCrossing& cornerCrossing = cornerCrossings[i];
|
||||
if (cornerCrossing.point.y >= y && cornerCrossing.point.y < y + 1) {
|
||||
crossedCorners |= (1 << i);
|
||||
}
|
||||
}
|
||||
switch (crossedCorners) {
|
||||
case UPPER_LEFT_CORNER:
|
||||
case LOWER_LEFT_CORNER | UPPER_LEFT_CORNER:
|
||||
case LOWER_LEFT_CORNER | UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER:
|
||||
case LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER | UPPER_LEFT_CORNER:
|
||||
case UPPER_LEFT_CORNER | LOWER_RIGHT_CORNER:
|
||||
crossings[crossingCount++] = cornerCrossings[0];
|
||||
crossings[crossingCount - 1].point.y -= y;
|
||||
break;
|
||||
|
||||
|
||||
case UPPER_RIGHT_CORNER:
|
||||
case UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER:
|
||||
case UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER:
|
||||
case UPPER_RIGHT_CORNER | LOWER_LEFT_CORNER:
|
||||
case LOWER_LEFT_CORNER | UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER:
|
||||
crossings[crossingCount++] = cornerCrossings[1];
|
||||
crossings[crossingCount - 1].point.y -= y;
|
||||
break;
|
||||
|
||||
|
||||
case LOWER_LEFT_CORNER:
|
||||
case LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER:
|
||||
case LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER | UPPER_LEFT_CORNER:
|
||||
case UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER:
|
||||
crossings[crossingCount++] = cornerCrossings[2];
|
||||
crossings[crossingCount - 1].point.y -= y;
|
||||
break;
|
||||
|
||||
|
||||
case LOWER_RIGHT_CORNER:
|
||||
case UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER:
|
||||
case UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER:
|
||||
case UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER:
|
||||
crossings[crossingCount++] = cornerCrossings[3];
|
||||
crossings[crossingCount - 1].point.y -= y;
|
||||
break;
|
||||
|
@ -1890,30 +1985,24 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
if (!(corners & (1 << i))) {
|
||||
continue;
|
||||
}
|
||||
int offsetX = (i & X_MAXIMUM_FLAG) ? 1 : 0;
|
||||
int offsetZ = (i & Y_MAXIMUM_FLAG) ? 1 : 0;
|
||||
const quint16* height = heightLineSrc + offsetZ * width + offsetX;
|
||||
float heightValue = *height * voxelScale;
|
||||
int nextIndex = NEXT_CORNERS[i];
|
||||
if (!(corners & (1 << nextIndex))) {
|
||||
continue;
|
||||
}
|
||||
int nextOffsetX = (nextIndex & X_MAXIMUM_FLAG) ? 1 : 0;
|
||||
int nextOffsetZ = (nextIndex & Y_MAXIMUM_FLAG) ? 1 : 0;
|
||||
const quint16* nextHeight = heightLineSrc + nextOffsetZ * width + nextOffsetX;
|
||||
float nextHeightValue = *nextHeight * voxelScale;
|
||||
float divisor = (nextHeightValue - heightValue);
|
||||
const EdgeCrossing& cornerCrossing = cornerCrossings[i];
|
||||
const EdgeCrossing& nextCornerCrossing = cornerCrossings[nextIndex];
|
||||
float divisor = (nextCornerCrossing.point.y - cornerCrossing.point.y);
|
||||
if (divisor == 0.0f) {
|
||||
continue;
|
||||
}
|
||||
float t1 = (y - heightValue) / divisor;
|
||||
float t2 = (y + 1 - heightValue) / divisor;
|
||||
float t1 = (y - cornerCrossing.point.y) / divisor;
|
||||
float t2 = (y + 1 - cornerCrossing.point.y) / divisor;
|
||||
if (t1 >= 0.0f && t1 <= 1.0f) {
|
||||
crossings[crossingCount++].mix(cornerCrossings[i], cornerCrossings[nextIndex], t1);
|
||||
crossings[crossingCount++].mix(cornerCrossing, nextCornerCrossing, t1);
|
||||
crossings[crossingCount - 1].point.y -= y;
|
||||
}
|
||||
if (t2 >= 0.0f && t2 <= 1.0f) {
|
||||
crossings[crossingCount++].mix(cornerCrossings[i], cornerCrossings[nextIndex], t2);
|
||||
crossings[crossingCount++].mix(cornerCrossing, nextCornerCrossing, t2);
|
||||
crossings[crossingCount - 1].point.y -= y;
|
||||
}
|
||||
}
|
||||
|
@ -1924,10 +2013,13 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
// the terrifying conditional code that follows checks each cube edge for a crossing, gathering
|
||||
// its properties (color, material, normal) if one is present; as before, boundary edges are excluded
|
||||
if (crossingCount == 0) {
|
||||
const StackArray::Entry& nextEntryY = lineSrc->getEntry(y + 1, heightfieldHeight);
|
||||
StackArray::Entry nextEntryY = getEntry(lineSrc, stackWidth, y + 1,
|
||||
heightfieldHeight, cornerCrossings, 0);
|
||||
if (middleX) {
|
||||
const StackArray::Entry& nextEntryX = lineSrc[1].getEntry(y, nextHeightfieldHeightX);
|
||||
const StackArray::Entry& nextEntryXY = lineSrc[1].getEntry(y + 1, nextHeightfieldHeightX);
|
||||
StackArray::Entry nextEntryX = getEntry(lineSrc, stackWidth, y, nextHeightfieldHeightX,
|
||||
cornerCrossings, 1);
|
||||
StackArray::Entry nextEntryXY = getEntry(lineSrc, stackWidth, y + 1, nextHeightfieldHeightX,
|
||||
cornerCrossings, 1);
|
||||
if (alpha0 != alpha1) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(entry.getHermiteX(crossing.normal), 0.0f, 0.0f);
|
||||
|
@ -1944,12 +2036,12 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
crossing.setColorMaterial(alpha2 == 0 ? nextEntryXY : nextEntryY);
|
||||
}
|
||||
if (middleZ) {
|
||||
const StackArray::Entry& nextEntryZ = lineSrc[stackWidth].getEntry(y,
|
||||
nextHeightfieldHeightZ);
|
||||
const StackArray::Entry& nextEntryXZ = lineSrc[stackWidth + 1].getEntry(
|
||||
y, nextHeightfieldHeightXZ);
|
||||
const StackArray::Entry& nextEntryXYZ = lineSrc[stackWidth + 1].getEntry(
|
||||
y + 1, nextHeightfieldHeightXZ);
|
||||
StackArray::Entry nextEntryZ = getEntry(lineSrc, stackWidth, y, nextHeightfieldHeightZ,
|
||||
cornerCrossings, 2);
|
||||
StackArray::Entry nextEntryXZ = getEntry(lineSrc, stackWidth, y, nextHeightfieldHeightXZ,
|
||||
cornerCrossings, 3);
|
||||
StackArray::Entry nextEntryXYZ = getEntry(lineSrc, stackWidth, y + 1,
|
||||
nextHeightfieldHeightXZ, cornerCrossings, 3);
|
||||
if (alpha1 != alpha5) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(1.0f, 0.0f, nextEntryX.getHermiteZ(crossing.normal));
|
||||
|
@ -1957,8 +2049,8 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
}
|
||||
if (alpha3 != alpha7) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
const StackArray::Entry& nextEntryXY = lineSrc[1].getEntry(y + 1,
|
||||
nextHeightfieldHeightX);
|
||||
StackArray::Entry nextEntryXY = getEntry(lineSrc, stackWidth, y + 1,
|
||||
nextHeightfieldHeightX, cornerCrossings, 1);
|
||||
crossing.point = glm::vec3(1.0f, 1.0f, nextEntryXY.getHermiteZ(crossing.normal));
|
||||
crossing.setColorMaterial(alpha3 == 0 ? nextEntryXYZ : nextEntryXY);
|
||||
}
|
||||
|
@ -1969,15 +2061,15 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
}
|
||||
if (alpha5 != alpha7) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
const StackArray::Entry& nextEntryXZ = lineSrc[stackWidth + 1].getEntry(
|
||||
y, nextHeightfieldHeightXZ);
|
||||
StackArray::Entry nextEntryXZ = getEntry(lineSrc, stackWidth, y,
|
||||
nextHeightfieldHeightXZ, cornerCrossings, 3);
|
||||
crossing.point = glm::vec3(1.0f, nextEntryXZ.getHermiteY(crossing.normal), 1.0f);
|
||||
crossing.setColorMaterial(alpha5 == 0 ? nextEntryXYZ : nextEntryXZ);
|
||||
}
|
||||
if (alpha6 != alpha7) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
const StackArray::Entry& nextEntryYZ = lineSrc[stackWidth].getEntry(
|
||||
y + 1, nextHeightfieldHeightZ);
|
||||
StackArray::Entry nextEntryYZ = getEntry(lineSrc, stackWidth, y + 1,
|
||||
nextHeightfieldHeightZ, cornerCrossings, 2);
|
||||
crossing.point = glm::vec3(nextEntryYZ.getHermiteX(crossing.normal), 1.0f, 1.0f);
|
||||
crossing.setColorMaterial(alpha6 == 0 ? nextEntryXYZ : nextEntryYZ);
|
||||
}
|
||||
|
@ -1989,9 +2081,10 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
crossing.setColorMaterial(alpha0 == 0 ? nextEntryY : entry);
|
||||
}
|
||||
if (middleZ) {
|
||||
const StackArray::Entry& nextEntryZ = lineSrc[stackWidth].getEntry(y, nextHeightfieldHeightZ);
|
||||
const StackArray::Entry& nextEntryYZ = lineSrc[stackWidth].getEntry(y + 1,
|
||||
nextHeightfieldHeightZ);
|
||||
StackArray::Entry nextEntryZ = getEntry(lineSrc, stackWidth, y,
|
||||
nextHeightfieldHeightZ, cornerCrossings, 2);
|
||||
StackArray::Entry nextEntryYZ = getEntry(lineSrc, stackWidth, y + 1,
|
||||
nextHeightfieldHeightZ, cornerCrossings, 2);
|
||||
if (alpha0 != alpha4) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(0.0f, 0.0f, entry.getHermiteZ(crossing.normal));
|
||||
|
@ -2174,10 +2267,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
quadIndices.insert(qRgb(reclampedX, y - 1, reclampedZ - 1), indices.size());
|
||||
quadIndices.insert(qRgb(reclampedX, y, reclampedZ - 1), indices.size());
|
||||
}
|
||||
const glm::vec3& first = vertices.at(index.indices[0]).vertex;
|
||||
glm::vec3 normal = glm::cross(vertices.at(index1.indices[0]).vertex - first,
|
||||
vertices.at(index3.indices[0]).vertex - first);
|
||||
|
||||
glm::vec3 normal = getNormal(vertices, index, index1, index2, index3);
|
||||
if (alpha0 == 0) { // quad faces negative x
|
||||
indices.append(index3.getClosestIndex(normal = -normal, vertices));
|
||||
indices.append(index2.getClosestIndex(normal, vertices));
|
||||
|
@ -2206,10 +2296,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
if (reclampedZ > 0) {
|
||||
quadIndices.insert(qRgb(reclampedX, y, reclampedZ - 1), indices.size());
|
||||
}
|
||||
const glm::vec3& first = vertices.at(index.indices[0]).vertex;
|
||||
glm::vec3 normal = glm::cross(vertices.at(index3.indices[0]).vertex - first,
|
||||
vertices.at(index1.indices[0]).vertex - first);
|
||||
|
||||
glm::vec3 normal = getNormal(vertices, index, index3, index2, index1);
|
||||
if (alpha0 == 0) { // quad faces negative y
|
||||
indices.append(index3.getClosestIndex(normal, vertices));
|
||||
indices.append(index2.getClosestIndex(normal, vertices));
|
||||
|
@ -2235,10 +2322,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
}
|
||||
quadIndices.insert(qRgb(reclampedX, y - 1, reclampedZ), indices.size());
|
||||
|
||||
const glm::vec3& first = vertices.at(index.indices[0]).vertex;
|
||||
glm::vec3 normal = glm::cross(vertices.at(index1.indices[0]).vertex - first,
|
||||
vertices.at(index3.indices[0]).vertex - first);
|
||||
|
||||
glm::vec3 normal = getNormal(vertices, index, index1, index2, index3);
|
||||
if (alpha0 == 0) { // quad faces negative z
|
||||
indices.append(index1.getClosestIndex(normal, vertices));
|
||||
indices.append(index2.getClosestIndex(normal, vertices));
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
|
@ -21,6 +22,7 @@
|
|||
#include <QHBoxLayout>
|
||||
#include <QHttpMultiPart>
|
||||
#include <QImage>
|
||||
#include <QJsonDocument>
|
||||
#include <QLineEdit>
|
||||
#include <QMessageBox>
|
||||
#include <QProgressBar>
|
||||
|
@ -28,12 +30,17 @@
|
|||
#include <QStandardPaths>
|
||||
#include <QTemporaryFile>
|
||||
#include <QTextStream>
|
||||
#include <QThread>
|
||||
#include <QVBoxLayout>
|
||||
#include <QVariant>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <ResourceCache.h>
|
||||
#include <Settings.h>
|
||||
#include <TextureCache.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "ModelUploader.h"
|
||||
|
||||
|
||||
|
@ -53,8 +60,6 @@ static const QString BLENDSHAPE_FIELD = "bs";
|
|||
static const QString S3_URL = "http://public.highfidelity.io";
|
||||
static const QString MODEL_URL = "/api/v1/models";
|
||||
|
||||
static const QString SETTING_NAME = "LastModelUploadLocation";
|
||||
|
||||
static const unsigned long long MAX_SIZE = 50 * 1024 * BYTES_PER_MEGABYTES; // 50 GB (Virtually remove limit)
|
||||
static const int MAX_TEXTURE_SIZE = 1024;
|
||||
static const int TIMEOUT = 1000;
|
||||
|
@ -63,6 +68,11 @@ static const int MAX_CHECK = 30;
|
|||
static const int QCOMPRESS_HEADER_POSITION = 0;
|
||||
static const int QCOMPRESS_HEADER_SIZE = 4;
|
||||
|
||||
namespace SettingHandles {
|
||||
const SettingHandle<QString> lastModelUploadLocation("LastModelUploadLocation",
|
||||
QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
|
||||
}
|
||||
|
||||
void ModelUploader::uploadModel(ModelType modelType) {
|
||||
ModelUploader* uploader = new ModelUploader(modelType);
|
||||
QThread* thread = new QThread();
|
||||
|
@ -107,8 +117,7 @@ ModelUploader::~ModelUploader() {
|
|||
|
||||
bool ModelUploader::zip() {
|
||||
// File Dialog
|
||||
QSettings* settings = Application::getInstance()->lockSettings();
|
||||
QString lastLocation = settings->value(SETTING_NAME).toString();
|
||||
QString lastLocation = SettingHandles::lastModelUploadLocation.get();
|
||||
|
||||
if (lastLocation.isEmpty()) {
|
||||
lastLocation = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
|
||||
|
@ -123,11 +132,9 @@ bool ModelUploader::zip() {
|
|||
lastLocation, "Model files (*.fst *.fbx)");
|
||||
if (filename == "") {
|
||||
// If the user canceled we return.
|
||||
Application::getInstance()->unlockSettings();
|
||||
return false;
|
||||
}
|
||||
settings->setValue(SETTING_NAME, filename);
|
||||
Application::getInstance()->unlockSettings();
|
||||
SettingHandles::lastModelUploadLocation.set(filename);
|
||||
|
||||
// First we check the FST file (if any)
|
||||
QFile* fst;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <NetworkAccessManager.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Menu.h"
|
||||
|
||||
#include "ScriptsModel.h"
|
||||
|
@ -33,8 +34,8 @@ static const QString KEY_NAME = "Key";
|
|||
|
||||
TreeNodeBase::TreeNodeBase(TreeNodeFolder* parent, const QString& name, TreeNodeType type) :
|
||||
_parent(parent),
|
||||
_name(name),
|
||||
_type(type) {
|
||||
_type(type),
|
||||
_name(name) {
|
||||
};
|
||||
|
||||
TreeNodeScript::TreeNodeScript(const QString& localPath, const QString& fullPath, ScriptOrigin origin) :
|
||||
|
@ -58,10 +59,10 @@ ScriptsModel::ScriptsModel(QObject* parent) :
|
|||
_localDirectory.setFilter(QDir::Files | QDir::Readable);
|
||||
_localDirectory.setNameFilters(QStringList("*.js"));
|
||||
|
||||
updateScriptsLocation(Menu::getInstance()->getScriptsLocation());
|
||||
updateScriptsLocation(qApp->getScriptsLocation());
|
||||
|
||||
connect(&_fsWatcher, &QFileSystemWatcher::directoryChanged, this, &ScriptsModel::reloadLocalFiles);
|
||||
connect(Menu::getInstance(), &Menu::scriptLocationChanged, this, &ScriptsModel::updateScriptsLocation);
|
||||
connect(qApp, &Application::scriptLocationChanged, this, &ScriptsModel::updateScriptsLocation);
|
||||
|
||||
reloadLocalFiles();
|
||||
reloadRemoteFiles();
|
||||
|
|
|
@ -20,12 +20,13 @@
|
|||
#include <QWinEventNotifier>
|
||||
#endif
|
||||
|
||||
class SpeechRecognizer : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
SpeechRecognizer();
|
||||
~SpeechRecognizer();
|
||||
#include <DependencyManager.h>
|
||||
|
||||
class SpeechRecognizer : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
void handleCommandRecognized(const char* command);
|
||||
bool getEnabled() const { return _enabled; }
|
||||
|
||||
|
@ -42,6 +43,9 @@ protected:
|
|||
void reloadCommands();
|
||||
|
||||
private:
|
||||
SpeechRecognizer();
|
||||
virtual ~SpeechRecognizer();
|
||||
|
||||
bool _enabled;
|
||||
QSet<QString> _commands;
|
||||
#if defined(Q_OS_MAC)
|
||||
|
|
|
@ -225,14 +225,6 @@ void runTimingTests() {
|
|||
qDebug("vec3 assign and dot() usecs: %f, last result:%f", elapsedUsecs / (float) numTests, result);
|
||||
}
|
||||
|
||||
float loadSetting(QSettings* settings, const char* name, float defaultValue) {
|
||||
float value = settings->value(name, defaultValue).toFloat();
|
||||
if (glm::isnan(value)) {
|
||||
value = defaultValue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool rayIntersectsSphere(const glm::vec3& rayStarting, const glm::vec3& rayNormalizedDirection,
|
||||
const glm::vec3& sphereCenter, float sphereRadius, float& distance) {
|
||||
glm::vec3 relativeOrigin = rayStarting - sphereCenter;
|
||||
|
|
|
@ -29,8 +29,6 @@ void renderCollisionOverlay(int width, int height, float magnitude, float red =
|
|||
|
||||
void runTimingTests();
|
||||
|
||||
float loadSetting(QSettings* settings, const char* name, float defaultValue);
|
||||
|
||||
bool rayIntersectsSphere(const glm::vec3& rayStarting, const glm::vec3& rayNormalizedDirection,
|
||||
const glm::vec3& sphereCenter, float sphereRadius, float& distance);
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <DeferredLightingEffect.h>
|
||||
#include <GeometryUtil.h>
|
||||
#include <GlowEffect.h>
|
||||
#include <LODManager.h>
|
||||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <PathUtils.h>
|
||||
|
@ -114,8 +115,8 @@ glm::quat Avatar::getWorldAlignedOrientation () const {
|
|||
}
|
||||
|
||||
float Avatar::getLODDistance() const {
|
||||
return Menu::getInstance()->getAvatarLODDistanceMultiplier() *
|
||||
glm::distance(Application::getInstance()->getCamera()->getPosition(), _position) / _scale;
|
||||
return DependencyManager::get<LODManager>()->getAvatarLODDistanceMultiplier() *
|
||||
glm::distance(qApp->getCamera()->getPosition(), _position) / _scale;
|
||||
}
|
||||
|
||||
void Avatar::simulate(float deltaTime) {
|
||||
|
|
|
@ -168,11 +168,8 @@ void Hand::renderHandTargets(bool isMine) {
|
|||
glm::vec3 tip = palm.getTipPosition();
|
||||
glm::vec3 root = palm.getPosition();
|
||||
|
||||
//Scale the positions based on avatar scale
|
||||
myAvatar->scaleVectorRelativeToPosition(tip);
|
||||
myAvatar->scaleVectorRelativeToPosition(root);
|
||||
|
||||
Avatar::renderJointConnectingCone(root, tip, PALM_FINGER_ROD_RADIUS, PALM_FINGER_ROD_RADIUS, glm::vec4(handColor.r, handColor.g, handColor.b, alpha));
|
||||
|
||||
// Render sphere at palm/finger root
|
||||
glm::vec3 offsetFromPalm = root + palm.getNormal() * PALM_DISK_THICKNESS;
|
||||
Avatar::renderJointConnectingCone(root, offsetFromPalm, PALM_DISK_RADIUS, 0.0f, glm::vec4(handColor.r, handColor.g, handColor.b, alpha));
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <PerfStat.h>
|
||||
#include <Settings.h>
|
||||
#include <ShapeCollider.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <TextRenderer.h>
|
||||
|
@ -338,7 +339,8 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
|
|||
head->setDeltaPitch(estimatedRotation.x);
|
||||
head->setDeltaYaw(estimatedRotation.y);
|
||||
} else {
|
||||
float magnifyFieldOfView = Menu::getInstance()->getFieldOfView() / Menu::getInstance()->getRealWorldFieldOfView();
|
||||
float magnifyFieldOfView = qApp->getViewFrustum()->getFieldOfView() /
|
||||
qApp->getViewFrustum()->getRealWorldFieldOfView();
|
||||
head->setDeltaPitch(estimatedRotation.x * magnifyFieldOfView);
|
||||
head->setDeltaYaw(estimatedRotation.y * magnifyFieldOfView);
|
||||
}
|
||||
|
@ -675,60 +677,70 @@ AnimationDetails MyAvatar::getAnimationDetails(const QString& url) {
|
|||
return result;
|
||||
}
|
||||
|
||||
void MyAvatar::saveData(QSettings* settings) {
|
||||
settings->beginGroup("Avatar");
|
||||
void MyAvatar::saveData() {
|
||||
Settings settings;
|
||||
settings.beginGroup("Avatar");
|
||||
|
||||
settings->setValue("headPitch", getHead()->getBasePitch());
|
||||
settings.setValue("headPitch", getHead()->getBasePitch());
|
||||
|
||||
settings->setValue("pupilDilation", getHead()->getPupilDilation());
|
||||
settings.setValue("pupilDilation", getHead()->getPupilDilation());
|
||||
|
||||
settings->setValue("leanScale", _leanScale);
|
||||
settings->setValue("scale", _targetScale);
|
||||
settings.setValue("leanScale", _leanScale);
|
||||
settings.setValue("scale", _targetScale);
|
||||
|
||||
settings->setValue("faceModelURL", _faceModelURL);
|
||||
settings->setValue("skeletonModelURL", _skeletonModelURL);
|
||||
settings.setValue("faceModelURL", _faceModelURL);
|
||||
settings.setValue("skeletonModelURL", _skeletonModelURL);
|
||||
|
||||
settings->beginWriteArray("attachmentData");
|
||||
settings.beginWriteArray("attachmentData");
|
||||
for (int i = 0; i < _attachmentData.size(); i++) {
|
||||
settings->setArrayIndex(i);
|
||||
settings.setArrayIndex(i);
|
||||
const AttachmentData& attachment = _attachmentData.at(i);
|
||||
settings->setValue("modelURL", attachment.modelURL);
|
||||
settings->setValue("jointName", attachment.jointName);
|
||||
settings->setValue("translation_x", attachment.translation.x);
|
||||
settings->setValue("translation_y", attachment.translation.y);
|
||||
settings->setValue("translation_z", attachment.translation.z);
|
||||
settings.setValue("modelURL", attachment.modelURL);
|
||||
settings.setValue("jointName", attachment.jointName);
|
||||
settings.setValue("translation_x", attachment.translation.x);
|
||||
settings.setValue("translation_y", attachment.translation.y);
|
||||
settings.setValue("translation_z", attachment.translation.z);
|
||||
glm::vec3 eulers = safeEulerAngles(attachment.rotation);
|
||||
settings->setValue("rotation_x", eulers.x);
|
||||
settings->setValue("rotation_y", eulers.y);
|
||||
settings->setValue("rotation_z", eulers.z);
|
||||
settings->setValue("scale", attachment.scale);
|
||||
settings.setValue("rotation_x", eulers.x);
|
||||
settings.setValue("rotation_y", eulers.y);
|
||||
settings.setValue("rotation_z", eulers.z);
|
||||
settings.setValue("scale", attachment.scale);
|
||||
}
|
||||
settings->endArray();
|
||||
settings.endArray();
|
||||
|
||||
settings->beginWriteArray("animationHandles");
|
||||
settings.beginWriteArray("animationHandles");
|
||||
for (int i = 0; i < _animationHandles.size(); i++) {
|
||||
settings->setArrayIndex(i);
|
||||
settings.setArrayIndex(i);
|
||||
const AnimationHandlePointer& pointer = _animationHandles.at(i);
|
||||
settings->setValue("role", pointer->getRole());
|
||||
settings->setValue("url", pointer->getURL());
|
||||
settings->setValue("fps", pointer->getFPS());
|
||||
settings->setValue("priority", pointer->getPriority());
|
||||
settings->setValue("loop", pointer->getLoop());
|
||||
settings->setValue("hold", pointer->getHold());
|
||||
settings->setValue("startAutomatically", pointer->getStartAutomatically());
|
||||
settings->setValue("firstFrame", pointer->getFirstFrame());
|
||||
settings->setValue("lastFrame", pointer->getLastFrame());
|
||||
settings->setValue("maskedJoints", pointer->getMaskedJoints());
|
||||
settings.setValue("role", pointer->getRole());
|
||||
settings.setValue("url", pointer->getURL());
|
||||
settings.setValue("fps", pointer->getFPS());
|
||||
settings.setValue("priority", pointer->getPriority());
|
||||
settings.setValue("loop", pointer->getLoop());
|
||||
settings.setValue("hold", pointer->getHold());
|
||||
settings.setValue("startAutomatically", pointer->getStartAutomatically());
|
||||
settings.setValue("firstFrame", pointer->getFirstFrame());
|
||||
settings.setValue("lastFrame", pointer->getLastFrame());
|
||||
settings.setValue("maskedJoints", pointer->getMaskedJoints());
|
||||
}
|
||||
settings->endArray();
|
||||
settings.endArray();
|
||||
|
||||
settings->setValue("displayName", _displayName);
|
||||
settings.setValue("displayName", _displayName);
|
||||
|
||||
settings->endGroup();
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void MyAvatar::loadData(QSettings* settings) {
|
||||
settings->beginGroup("Avatar");
|
||||
float loadSetting(QSettings& settings, const char* name, float defaultValue) {
|
||||
float value = settings.value(name, defaultValue).toFloat();
|
||||
if (glm::isnan(value)) {
|
||||
value = defaultValue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void MyAvatar::loadData() {
|
||||
Settings settings;
|
||||
settings.beginGroup("Avatar");
|
||||
|
||||
getHead()->setBasePitch(loadSetting(settings, "headPitch", 0.0f));
|
||||
|
||||
|
@ -739,16 +751,16 @@ void MyAvatar::loadData(QSettings* settings) {
|
|||
setScale(_scale);
|
||||
Application::getInstance()->getCamera()->setScale(_scale);
|
||||
|
||||
setFaceModelURL(settings->value("faceModelURL", DEFAULT_HEAD_MODEL_URL).toUrl());
|
||||
setSkeletonModelURL(settings->value("skeletonModelURL").toUrl());
|
||||
setFaceModelURL(settings.value("faceModelURL", DEFAULT_HEAD_MODEL_URL).toUrl());
|
||||
setSkeletonModelURL(settings.value("skeletonModelURL").toUrl());
|
||||
|
||||
QVector<AttachmentData> attachmentData;
|
||||
int attachmentCount = settings->beginReadArray("attachmentData");
|
||||
int attachmentCount = settings.beginReadArray("attachmentData");
|
||||
for (int i = 0; i < attachmentCount; i++) {
|
||||
settings->setArrayIndex(i);
|
||||
settings.setArrayIndex(i);
|
||||
AttachmentData attachment;
|
||||
attachment.modelURL = settings->value("modelURL").toUrl();
|
||||
attachment.jointName = settings->value("jointName").toString();
|
||||
attachment.modelURL = settings.value("modelURL").toUrl();
|
||||
attachment.jointName = settings.value("jointName").toString();
|
||||
attachment.translation.x = loadSetting(settings, "translation_x", 0.0f);
|
||||
attachment.translation.y = loadSetting(settings, "translation_y", 0.0f);
|
||||
attachment.translation.z = loadSetting(settings, "translation_z", 0.0f);
|
||||
|
@ -760,10 +772,10 @@ void MyAvatar::loadData(QSettings* settings) {
|
|||
attachment.scale = loadSetting(settings, "scale", 1.0f);
|
||||
attachmentData.append(attachment);
|
||||
}
|
||||
settings->endArray();
|
||||
settings.endArray();
|
||||
setAttachmentData(attachmentData);
|
||||
|
||||
int animationCount = settings->beginReadArray("animationHandles");
|
||||
int animationCount = settings.beginReadArray("animationHandles");
|
||||
while (_animationHandles.size() > animationCount) {
|
||||
_animationHandles.takeLast()->stop();
|
||||
}
|
||||
|
@ -771,65 +783,64 @@ void MyAvatar::loadData(QSettings* settings) {
|
|||
addAnimationHandle();
|
||||
}
|
||||
for (int i = 0; i < animationCount; i++) {
|
||||
settings->setArrayIndex(i);
|
||||
settings.setArrayIndex(i);
|
||||
const AnimationHandlePointer& handle = _animationHandles.at(i);
|
||||
handle->setRole(settings->value("role", "idle").toString());
|
||||
handle->setURL(settings->value("url").toUrl());
|
||||
handle->setRole(settings.value("role", "idle").toString());
|
||||
handle->setURL(settings.value("url").toUrl());
|
||||
handle->setFPS(loadSetting(settings, "fps", 30.0f));
|
||||
handle->setPriority(loadSetting(settings, "priority", 1.0f));
|
||||
handle->setLoop(settings->value("loop", true).toBool());
|
||||
handle->setHold(settings->value("hold", false).toBool());
|
||||
handle->setStartAutomatically(settings->value("startAutomatically", true).toBool());
|
||||
handle->setFirstFrame(settings->value("firstFrame", 0.0f).toFloat());
|
||||
handle->setLastFrame(settings->value("lastFrame", INT_MAX).toFloat());
|
||||
handle->setMaskedJoints(settings->value("maskedJoints").toStringList());
|
||||
handle->setLoop(settings.value("loop", true).toBool());
|
||||
handle->setHold(settings.value("hold", false).toBool());
|
||||
handle->setStartAutomatically(settings.value("startAutomatically", true).toBool());
|
||||
handle->setFirstFrame(settings.value("firstFrame", 0.0f).toFloat());
|
||||
handle->setLastFrame(settings.value("lastFrame", INT_MAX).toFloat());
|
||||
handle->setMaskedJoints(settings.value("maskedJoints").toStringList());
|
||||
}
|
||||
settings->endArray();
|
||||
settings.endArray();
|
||||
|
||||
setDisplayName(settings->value("displayName").toString());
|
||||
setDisplayName(settings.value("displayName").toString());
|
||||
|
||||
settings->endGroup();
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void MyAvatar::saveAttachmentData(const AttachmentData& attachment) const {
|
||||
QSettings* settings = Application::getInstance()->lockSettings();
|
||||
settings->beginGroup("savedAttachmentData");
|
||||
settings->beginGroup(_skeletonModel.getURL().toString());
|
||||
settings->beginGroup(attachment.modelURL.toString());
|
||||
settings->setValue("jointName", attachment.jointName);
|
||||
Settings settings;
|
||||
settings.beginGroup("savedAttachmentData");
|
||||
settings.beginGroup(_skeletonModel.getURL().toString());
|
||||
settings.beginGroup(attachment.modelURL.toString());
|
||||
settings.setValue("jointName", attachment.jointName);
|
||||
|
||||
settings->beginGroup(attachment.jointName);
|
||||
settings->setValue("translation_x", attachment.translation.x);
|
||||
settings->setValue("translation_y", attachment.translation.y);
|
||||
settings->setValue("translation_z", attachment.translation.z);
|
||||
settings.beginGroup(attachment.jointName);
|
||||
settings.setValue("translation_x", attachment.translation.x);
|
||||
settings.setValue("translation_y", attachment.translation.y);
|
||||
settings.setValue("translation_z", attachment.translation.z);
|
||||
glm::vec3 eulers = safeEulerAngles(attachment.rotation);
|
||||
settings->setValue("rotation_x", eulers.x);
|
||||
settings->setValue("rotation_y", eulers.y);
|
||||
settings->setValue("rotation_z", eulers.z);
|
||||
settings->setValue("scale", attachment.scale);
|
||||
settings.setValue("rotation_x", eulers.x);
|
||||
settings.setValue("rotation_y", eulers.y);
|
||||
settings.setValue("rotation_z", eulers.z);
|
||||
settings.setValue("scale", attachment.scale);
|
||||
|
||||
settings->endGroup();
|
||||
settings->endGroup();
|
||||
settings->endGroup();
|
||||
settings->endGroup();
|
||||
Application::getInstance()->unlockSettings();
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
AttachmentData MyAvatar::loadAttachmentData(const QUrl& modelURL, const QString& jointName) const {
|
||||
QSettings* settings = Application::getInstance()->lockSettings();
|
||||
settings->beginGroup("savedAttachmentData");
|
||||
settings->beginGroup(_skeletonModel.getURL().toString());
|
||||
settings->beginGroup(modelURL.toString());
|
||||
Settings settings;
|
||||
settings.beginGroup("savedAttachmentData");
|
||||
settings.beginGroup(_skeletonModel.getURL().toString());
|
||||
settings.beginGroup(modelURL.toString());
|
||||
|
||||
AttachmentData attachment;
|
||||
attachment.modelURL = modelURL;
|
||||
if (jointName.isEmpty()) {
|
||||
attachment.jointName = settings->value("jointName").toString();
|
||||
attachment.jointName = settings.value("jointName").toString();
|
||||
} else {
|
||||
attachment.jointName = jointName;
|
||||
}
|
||||
settings->beginGroup(attachment.jointName);
|
||||
if (settings->contains("translation_x")) {
|
||||
settings.beginGroup(attachment.jointName);
|
||||
if (settings.contains("translation_x")) {
|
||||
attachment.translation.x = loadSetting(settings, "translation_x", 0.0f);
|
||||
attachment.translation.y = loadSetting(settings, "translation_y", 0.0f);
|
||||
attachment.translation.z = loadSetting(settings, "translation_z", 0.0f);
|
||||
|
@ -843,11 +854,10 @@ AttachmentData MyAvatar::loadAttachmentData(const QUrl& modelURL, const QString&
|
|||
attachment = AttachmentData();
|
||||
}
|
||||
|
||||
settings->endGroup();
|
||||
settings->endGroup();
|
||||
settings->endGroup();
|
||||
settings->endGroup();
|
||||
Application::getInstance()->unlockSettings();
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
|
||||
return attachment;
|
||||
}
|
||||
|
|
|
@ -78,8 +78,8 @@ public:
|
|||
Q_INVOKABLE AnimationDetails getAnimationDetails(const QString& url);
|
||||
|
||||
// get/set avatar data
|
||||
void saveData(QSettings* settings);
|
||||
void loadData(QSettings* settings);
|
||||
void saveData();
|
||||
void loadData();
|
||||
|
||||
void saveAttachmentData(const AttachmentData& attachment) const;
|
||||
AttachmentData loadAttachmentData(const QUrl& modelURL, const QString& jointName = QString()) const;
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
|
||||
#include <QTimer>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
#include <PerfStat.h>
|
||||
#include <Settings.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Faceshift.h"
|
||||
|
@ -27,6 +29,11 @@ using namespace std;
|
|||
const quint16 FACESHIFT_PORT = 33433;
|
||||
float STARTING_FACESHIFT_FRAME_TIME = 0.033f;
|
||||
|
||||
namespace SettingHandles {
|
||||
const SettingHandle<float> faceshiftEyeDeflection("faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION);
|
||||
const SettingHandle<QString> faceshiftHostname("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME);
|
||||
}
|
||||
|
||||
Faceshift::Faceshift() :
|
||||
_tcpEnabled(true),
|
||||
_tcpRetryCount(0),
|
||||
|
@ -66,6 +73,9 @@ Faceshift::Faceshift() :
|
|||
|
||||
_udpSocket.bind(FACESHIFT_PORT);
|
||||
#endif
|
||||
|
||||
_eyeDeflection = SettingHandles::faceshiftEyeDeflection.get();
|
||||
_hostname = SettingHandles::faceshiftHostname.get();
|
||||
}
|
||||
|
||||
void Faceshift::init() {
|
||||
|
@ -159,7 +169,7 @@ void Faceshift::connectSocket() {
|
|||
qDebug("Faceshift: Connecting...");
|
||||
}
|
||||
|
||||
_tcpSocket.connectToHost(Menu::getInstance()->getFaceshiftHostname(), FACESHIFT_PORT);
|
||||
_tcpSocket.connectToHost(_hostname, FACESHIFT_PORT);
|
||||
_tracking = false;
|
||||
}
|
||||
}
|
||||
|
@ -309,3 +319,13 @@ void Faceshift::receive(const QByteArray& buffer) {
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Faceshift::setEyeDeflection(float faceshiftEyeDeflection) {
|
||||
_eyeDeflection = faceshiftEyeDeflection;
|
||||
SettingHandles::faceshiftEyeDeflection.set(_eyeDeflection);
|
||||
}
|
||||
|
||||
void Faceshift::setHostname(const QString& hostname) {
|
||||
_hostname = hostname;
|
||||
SettingHandles::faceshiftHostname.set(_hostname);
|
||||
}
|
||||
|
|
|
@ -61,6 +61,12 @@ public:
|
|||
float getMouthSize() const { return getBlendshapeCoefficient(_jawOpenIndex); }
|
||||
float getMouthSmileLeft() const { return getBlendshapeCoefficient(_mouthSmileLeftIndex); }
|
||||
float getMouthSmileRight() const { return getBlendshapeCoefficient(_mouthSmileRightIndex); }
|
||||
|
||||
float getEyeDeflection() const { return _eyeDeflection; }
|
||||
void setEyeDeflection(float faceshiftEyeDeflection);
|
||||
|
||||
const QString& getHostname() const { return _hostname; }
|
||||
void setHostname(const QString& hostname);
|
||||
|
||||
void update();
|
||||
void reset();
|
||||
|
@ -145,6 +151,9 @@ private:
|
|||
float _longTermAverageEyeYaw;
|
||||
bool _longTermAverageInitialized;
|
||||
|
||||
float _eyeDeflection = DEFAULT_FACESHIFT_EYE_DEFLECTION;
|
||||
QString _hostname = DEFAULT_FACESHIFT_HOSTNAME;
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_Faceshift_h
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Application.h"
|
||||
#include "RealSense.h"
|
||||
#include "MainWindow.h"
|
||||
#include "Menu.h"
|
||||
|
|
|
@ -40,6 +40,7 @@ public:
|
|||
|
||||
virtual void update();
|
||||
|
||||
public slots:
|
||||
void loadRSSDKFile();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -301,7 +301,16 @@ const float RANGE_MULT = (MAX_PIXEL_RANGE_MULT - MIN_PIXEL_RANGE_MULT) * 0.01;
|
|||
//Returns a multiplier to be applied to the cursor range for the controllers
|
||||
float SixenseManager::getCursorPixelRangeMult() const {
|
||||
//scales (0,100) to (MINIMUM_PIXEL_RANGE_MULT, MAXIMUM_PIXEL_RANGE_MULT)
|
||||
return Menu::getInstance()->getSixenseReticleMoveSpeed() * RANGE_MULT + MIN_PIXEL_RANGE_MULT;
|
||||
return _reticleMoveSpeed * RANGE_MULT + MIN_PIXEL_RANGE_MULT;
|
||||
}
|
||||
|
||||
void SixenseManager::toggleSixense(bool shouldEnable) {
|
||||
if (shouldEnable && !isInitialized()) {
|
||||
initialize();
|
||||
setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense));
|
||||
setLowVelocityFilter(Menu::getInstance()->isOptionChecked(MenuOption::LowVelocityFilter));
|
||||
}
|
||||
setIsEnabled(shouldEnable);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SIXENSE
|
||||
|
@ -459,7 +468,7 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) {
|
|||
|
||||
unsigned int deviceID = index == 0 ? CONTROLLER_0_EVENT : CONTROLLER_1_EVENT;
|
||||
|
||||
if (Menu::getInstance()->getInvertSixenseButtons()) {
|
||||
if (_invertButtons) {
|
||||
bumperButton = Qt::LeftButton;
|
||||
triggerButton = Qt::RightButton;
|
||||
} else {
|
||||
|
|
|
@ -55,8 +55,13 @@ public:
|
|||
void update(float deltaTime);
|
||||
float getCursorPixelRangeMult() const;
|
||||
|
||||
public slots:
|
||||
float getReticleMoveSpeed() const { return _reticleMoveSpeed; }
|
||||
void setReticleMoveSpeed(float sixenseReticleMoveSpeed) { _reticleMoveSpeed = sixenseReticleMoveSpeed; }
|
||||
bool getInvertButtons() const { return _invertButtons; }
|
||||
void setInvertButtons(bool invertSixenseButtons) { _invertButtons = invertSixenseButtons; }
|
||||
|
||||
public slots:
|
||||
void toggleSixense(bool shouldEnable);
|
||||
void setFilter(bool filter);
|
||||
void setLowVelocityFilter(bool lowVelocityFilter) { _lowVelocityFilter = lowVelocityFilter; };
|
||||
|
||||
|
@ -102,6 +107,9 @@ private:
|
|||
|
||||
bool _lowVelocityFilter;
|
||||
bool _controllersAtBase;
|
||||
|
||||
float _reticleMoveSpeed = DEFAULT_SIXENSE_RETICLE_MOVE_SPEED;
|
||||
bool _invertButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS;
|
||||
};
|
||||
|
||||
#endif // hifi_SixenseManager_h
|
||||
|
|
|
@ -8,13 +8,15 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QSettings>
|
||||
#include <QTranslator>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
QElapsedTimer startupTime;
|
||||
startupTime.start();
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Application.h"
|
||||
#include "Audio.h"
|
||||
#include "AudioDeviceScriptingInterface.h"
|
||||
|
||||
|
||||
|
|
|
@ -12,11 +12,11 @@
|
|||
#ifndef hifi_AudioDeviceScriptingInterface_h
|
||||
#define hifi_AudioDeviceScriptingInterface_h
|
||||
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
#include "Application.h"
|
||||
class AudioEffectOptions;
|
||||
|
||||
class AudioDeviceScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Application.h"
|
||||
#include <Settings.h>
|
||||
|
||||
#include "SettingsScriptingInterface.h"
|
||||
|
||||
|
||||
|
@ -19,9 +20,7 @@ SettingsScriptingInterface* SettingsScriptingInterface::getInstance() {
|
|||
}
|
||||
|
||||
QVariant SettingsScriptingInterface::getValue(const QString& setting) {
|
||||
QSettings* settings = Application::getInstance()->lockSettings();
|
||||
QVariant value = settings->value(setting);
|
||||
Application::getInstance()->unlockSettings();
|
||||
QVariant value = SettingHandles::SettingHandle<QVariant>(setting).get();
|
||||
if (!value.isValid()) {
|
||||
value = "";
|
||||
}
|
||||
|
@ -29,9 +28,7 @@ QVariant SettingsScriptingInterface::getValue(const QString& setting) {
|
|||
}
|
||||
|
||||
QVariant SettingsScriptingInterface::getValue(const QString& setting, const QVariant& defaultValue) {
|
||||
QSettings* settings = Application::getInstance()->lockSettings();
|
||||
QVariant value = settings->value(setting, defaultValue);
|
||||
Application::getInstance()->unlockSettings();
|
||||
QVariant value = SettingHandles::SettingHandle<QVariant>(setting, defaultValue).get();
|
||||
if (!value.isValid()) {
|
||||
value = "";
|
||||
}
|
||||
|
@ -39,7 +36,5 @@ QVariant SettingsScriptingInterface::getValue(const QString& setting, const QVar
|
|||
}
|
||||
|
||||
void SettingsScriptingInterface::setValue(const QString& setting, const QVariant& value) {
|
||||
QSettings* settings = Application::getInstance()->lockSettings();
|
||||
settings->setValue(setting, value);
|
||||
Application::getInstance()->unlockSettings();
|
||||
SettingHandles::SettingHandle<QVariant>(setting).set(value);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QScriptValue>
|
||||
#include <QScrollArea>
|
||||
|
||||
#include "Application.h"
|
||||
#include "MainWindow.h"
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
const QString ADDRESSBAR_GO_BUTTON_ICON = "images/address-bar-submit.svg";
|
||||
const QString ADDRESSBAR_GO_BUTTON_ACTIVE_ICON = "images/address-bar-submit-active.svg";
|
||||
|
||||
AddressBarDialog::AddressBarDialog() :
|
||||
FramelessDialog(Application::getInstance()->getWindow(), 0, FramelessDialog::POSITION_TOP)
|
||||
AddressBarDialog::AddressBarDialog(QWidget* parent) :
|
||||
FramelessDialog(parent, 0, FramelessDialog::POSITION_TOP)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose, false);
|
||||
setupUI();
|
||||
|
|
|
@ -23,7 +23,7 @@ class AddressBarDialog : public FramelessDialog {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AddressBarDialog();
|
||||
AddressBarDialog(QWidget* parent);
|
||||
|
||||
private:
|
||||
void setupUI();
|
||||
|
|
|
@ -20,12 +20,18 @@
|
|||
#include <QScrollArea>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <Settings.h>
|
||||
|
||||
#include "AnimationsDialog.h"
|
||||
#include "Application.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
AnimationsDialog::AnimationsDialog() :
|
||||
QDialog(Application::getInstance()->getWindow()) {
|
||||
namespace SettingHandles {
|
||||
const SettingHandle<QString> animationDirectory("animation_directory", QString());
|
||||
}
|
||||
|
||||
AnimationsDialog::AnimationsDialog(QWidget* parent) :
|
||||
QDialog(parent) {
|
||||
|
||||
setWindowTitle("Edit Animations");
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
@ -157,14 +163,12 @@ AnimationPanel::AnimationPanel(AnimationsDialog* dialog, const AnimationHandlePo
|
|||
}
|
||||
|
||||
void AnimationPanel::chooseURL() {
|
||||
QString directory = Application::getInstance()->lockSettings()->value("animation_directory").toString();
|
||||
Application::getInstance()->unlockSettings();
|
||||
QString directory = SettingHandles::animationDirectory.get();
|
||||
QString filename = QFileDialog::getOpenFileName(this, "Choose Animation", directory, "Animation files (*.fbx)");
|
||||
if (filename.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Application::getInstance()->lockSettings()->setValue("animation_directory", QFileInfo(filename).path());
|
||||
Application::getInstance()->unlockSettings();
|
||||
SettingHandles::animationDirectory.set(QFileInfo(filename).path());
|
||||
_url->setText(QUrl::fromLocalFile(filename).toString());
|
||||
emit _url->returnPressed();
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define hifi_AnimationsDialog_h
|
||||
|
||||
#include <QDialog>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QFrame>
|
||||
|
||||
#include "avatar/MyAvatar.h"
|
||||
|
@ -30,7 +31,7 @@ class AnimationsDialog : public QDialog {
|
|||
|
||||
public:
|
||||
|
||||
AnimationsDialog();
|
||||
AnimationsDialog(QWidget* parent = nullptr);
|
||||
|
||||
virtual void setVisible(bool visible);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <PathUtils.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include "Audio.h"
|
||||
#include "audio/AudioIOStatsRenderer.h"
|
||||
#include "audio/AudioScope.h"
|
||||
#include "audio/AudioToolBox.h"
|
||||
|
@ -164,7 +165,7 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) {
|
|||
Overlays& overlays = application->getOverlays();
|
||||
auto glCanvas = DependencyManager::get<GLCanvas>();
|
||||
|
||||
_textureFov = glm::radians(Menu::getInstance()->getOculusUIAngularSize());
|
||||
_textureFov = glm::radians(_oculusUIAngularSize);
|
||||
_textureAspectRatio = (float)glCanvas->getDeviceWidth() / (float)glCanvas->getDeviceHeight();
|
||||
|
||||
//Handle fading and deactivation/activation of UI
|
||||
|
|
|
@ -20,6 +20,8 @@ const float MAGNIFY_WIDTH = 220.0f;
|
|||
const float MAGNIFY_HEIGHT = 100.0f;
|
||||
const float MAGNIFY_MULT = 2.0f;
|
||||
|
||||
const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f;
|
||||
|
||||
// Handles the drawing of the overlays to the screen
|
||||
class ApplicationOverlay {
|
||||
public:
|
||||
|
@ -35,6 +37,9 @@ public:
|
|||
QPoint getPalmClickLocation(const PalmData *palm) const;
|
||||
bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const;
|
||||
|
||||
float getOculusUIAngularSize() const { return _oculusUIAngularSize; }
|
||||
void setOculusUIAngularSize(float oculusUIAngularSize) { _oculusUIAngularSize = oculusUIAngularSize; }
|
||||
|
||||
// Converter from one frame of reference to another.
|
||||
// Frame of reference:
|
||||
// Screen: Position on the screen (x,y)
|
||||
|
@ -80,6 +85,8 @@ private:
|
|||
VerticesIndices _vbo;
|
||||
};
|
||||
|
||||
float _oculusUIAngularSize = DEFAULT_OCULUS_UI_ANGULAR_SIZE;
|
||||
|
||||
void renderReticle(glm::quat orientation, float alpha);
|
||||
void renderPointers();;
|
||||
void renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder);
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
#include "AttachmentsDialog.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
AttachmentsDialog::AttachmentsDialog() :
|
||||
QDialog(Application::getInstance()->getWindow()) {
|
||||
AttachmentsDialog::AttachmentsDialog(QWidget* parent) :
|
||||
QDialog(parent) {
|
||||
|
||||
setWindowTitle("Edit Attachments");
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
|
|
@ -27,8 +27,7 @@ class AttachmentsDialog : public QDialog {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
AttachmentsDialog();
|
||||
AttachmentsDialog(QWidget* parent = nullptr);
|
||||
|
||||
virtual void setVisible(bool visible);
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <AddressManager.h>
|
||||
#include <AccountManager.h>
|
||||
#include <PathUtils.h>
|
||||
#include <Settings.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "ChatMessageArea.h"
|
||||
|
@ -41,6 +42,10 @@ const QRegularExpression regexHifiLinks("([#@]\\S+)");
|
|||
const QString mentionSoundsPath("/mention-sounds/");
|
||||
const QString mentionRegex("@(\\b%1\\b)");
|
||||
|
||||
namespace SettingHandles {
|
||||
const SettingHandle<QDateTime> usernameMentionTimestamp("MentionTimestamp", QDateTime());
|
||||
}
|
||||
|
||||
ChatWindow::ChatWindow(QWidget* parent) :
|
||||
QWidget(parent, Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint |
|
||||
Qt::WindowCloseButtonHint),
|
||||
|
@ -377,12 +382,10 @@ void ChatWindow::messageReceived(const QXmppMessage& message) {
|
|||
if (message.body().contains(usernameMention)) {
|
||||
|
||||
// Don't show messages already seen in icon tray at start-up.
|
||||
QSettings* settings = Application::getInstance()->lockSettings();
|
||||
bool showMessage = settings->value("usernameMentionTimestamp").toDateTime() < _lastMessageStamp;
|
||||
bool showMessage = SettingHandles::usernameMentionTimestamp.get() < _lastMessageStamp;
|
||||
if (showMessage) {
|
||||
settings->setValue("usernameMentionTimestamp", _lastMessageStamp);
|
||||
SettingHandles::usernameMentionTimestamp.set(_lastMessageStamp);
|
||||
}
|
||||
Application::getInstance()->unlockSettings();
|
||||
|
||||
if (isHidden() && showMessage) {
|
||||
|
||||
|
|
215
interface/src/ui/DialogsManager.cpp
Normal file
215
interface/src/ui/DialogsManager.cpp
Normal file
|
@ -0,0 +1,215 @@
|
|||
//
|
||||
// DialogsManager.cpp
|
||||
//
|
||||
//
|
||||
// Created by Clement on 1/18/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <MainWindow.h>
|
||||
#include <PathUtils.h>
|
||||
#include <XmppClient.h>
|
||||
|
||||
#include "AddressBarDialog.h"
|
||||
#include "AnimationsDialog.h"
|
||||
#include "AttachmentsDialog.h"
|
||||
#include "BandwidthDialog.h"
|
||||
#include "CachesSizeDialog.h"
|
||||
#include "ChatWindow.h"
|
||||
#include "HMDToolsDialog.h"
|
||||
#include "LodToolsDialog.h"
|
||||
#include "LoginDialog.h"
|
||||
#include "MetavoxelEditor.h"
|
||||
#include "MetavoxelNetworkSimulator.h"
|
||||
#include "OctreeStatsDialog.h"
|
||||
#include "PreferencesDialog.h"
|
||||
#include "ScriptEditorWindow.h"
|
||||
|
||||
#include "DialogsManager.h"
|
||||
|
||||
void DialogsManager::toggleAddressBar() {
|
||||
maybeCreateDialog(_addressBarDialog);
|
||||
|
||||
if (!_addressBarDialog->isVisible()) {
|
||||
_addressBarDialog->show();
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsManager::toggleLoginDialog() {
|
||||
maybeCreateDialog(_loginDialog);
|
||||
_loginDialog->toggleQAction();
|
||||
}
|
||||
|
||||
void DialogsManager::showLoginDialog() {
|
||||
maybeCreateDialog(_loginDialog);
|
||||
_loginDialog->showLoginForCurrentDomain();
|
||||
}
|
||||
|
||||
void DialogsManager::octreeStatsDetails() {
|
||||
if (!_octreeStatsDialog) {
|
||||
_octreeStatsDialog = new OctreeStatsDialog(qApp->getWindow(), qApp->getOcteeSceneStats());
|
||||
|
||||
if (_hmdToolsDialog) {
|
||||
_hmdToolsDialog->watchWindow(_octreeStatsDialog->windowHandle());
|
||||
}
|
||||
connect(_octreeStatsDialog, SIGNAL(closed()), _octreeStatsDialog, SLOT(deleteLater()));
|
||||
_octreeStatsDialog->show();
|
||||
}
|
||||
_octreeStatsDialog->raise();
|
||||
}
|
||||
|
||||
void DialogsManager::cachesSizeDialog() {
|
||||
qDebug() << "Caches size:" << _cachesSizeDialog.isNull();
|
||||
if (!_cachesSizeDialog) {
|
||||
maybeCreateDialog(_cachesSizeDialog);
|
||||
|
||||
connect(_cachesSizeDialog, SIGNAL(closed()), _cachesSizeDialog, SLOT(deleteLater()));
|
||||
_cachesSizeDialog->show();
|
||||
}
|
||||
_cachesSizeDialog->raise();
|
||||
}
|
||||
|
||||
void DialogsManager::editPreferences() {
|
||||
if (!_preferencesDialog) {
|
||||
maybeCreateDialog(_preferencesDialog);
|
||||
_preferencesDialog->show();
|
||||
} else {
|
||||
_preferencesDialog->close();
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsManager::editAttachments() {
|
||||
if (!_attachmentsDialog) {
|
||||
maybeCreateDialog(_attachmentsDialog);
|
||||
_attachmentsDialog->show();
|
||||
} else {
|
||||
_attachmentsDialog->close();
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsManager::editAnimations() {
|
||||
if (!_animationsDialog) {
|
||||
maybeCreateDialog(_animationsDialog);
|
||||
_animationsDialog->show();
|
||||
} else {
|
||||
_animationsDialog->close();
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsManager::bandwidthDetails() {
|
||||
if (! _bandwidthDialog) {
|
||||
_bandwidthDialog = new BandwidthDialog(qApp->getWindow(), qApp->getBandwidthMeter());
|
||||
connect(_bandwidthDialog, SIGNAL(closed()), _bandwidthDialog, SLOT(deleteLater()));
|
||||
|
||||
if (_hmdToolsDialog) {
|
||||
_hmdToolsDialog->watchWindow(_bandwidthDialog->windowHandle());
|
||||
}
|
||||
|
||||
_bandwidthDialog->show();
|
||||
}
|
||||
_bandwidthDialog->raise();
|
||||
}
|
||||
|
||||
void DialogsManager::lodTools() {
|
||||
if (!_lodToolsDialog) {
|
||||
maybeCreateDialog(_lodToolsDialog);
|
||||
|
||||
connect(_lodToolsDialog, SIGNAL(closed()), _lodToolsDialog, SLOT(deleteLater()));
|
||||
_lodToolsDialog->show();
|
||||
}
|
||||
_lodToolsDialog->raise();
|
||||
}
|
||||
|
||||
void DialogsManager::toggleToolWindow() {
|
||||
QMainWindow* toolWindow = qApp->getToolWindow();
|
||||
toolWindow->setVisible(!toolWindow->isVisible());
|
||||
}
|
||||
|
||||
void DialogsManager::hmdTools(bool showTools) {
|
||||
if (showTools) {
|
||||
if (!_hmdToolsDialog) {
|
||||
maybeCreateDialog(_hmdToolsDialog);
|
||||
connect(_hmdToolsDialog, SIGNAL(closed()), SLOT(hmdToolsClosed()));
|
||||
}
|
||||
_hmdToolsDialog->show();
|
||||
_hmdToolsDialog->raise();
|
||||
} else {
|
||||
hmdToolsClosed();
|
||||
}
|
||||
qApp->getWindow()->activateWindow();
|
||||
}
|
||||
|
||||
void DialogsManager::hmdToolsClosed() {
|
||||
Menu::getInstance()->getActionForOption(MenuOption::HMDTools)->setChecked(false);
|
||||
_hmdToolsDialog->hide();
|
||||
}
|
||||
|
||||
void DialogsManager::showMetavoxelEditor() {
|
||||
maybeCreateDialog(_metavoxelEditor);
|
||||
_metavoxelEditor->raise();
|
||||
}
|
||||
|
||||
void DialogsManager::showMetavoxelNetworkSimulator() {
|
||||
maybeCreateDialog(_metavoxelNetworkSimulator);
|
||||
_metavoxelNetworkSimulator->raise();
|
||||
}
|
||||
|
||||
void DialogsManager::showScriptEditor() {
|
||||
maybeCreateDialog(_scriptEditor);
|
||||
_scriptEditor->raise();
|
||||
}
|
||||
|
||||
void DialogsManager::setupChat() {
|
||||
#ifdef HAVE_QXMPP
|
||||
const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient();
|
||||
connect(&xmppClient, &QXmppClient::connected, this, &DialogsManager::toggleChat);
|
||||
connect(&xmppClient, &QXmppClient::disconnected, this, &DialogsManager::toggleChat);
|
||||
|
||||
QDir::setCurrent(PathUtils::resourcesPath());
|
||||
// init chat window to listen chat
|
||||
maybeCreateDialog(_chatWindow);
|
||||
#endif
|
||||
}
|
||||
|
||||
void DialogsManager::showChat() {
|
||||
if (AccountManager::getInstance().isLoggedIn()) {
|
||||
maybeCreateDialog(_chatWindow);
|
||||
|
||||
if (_chatWindow->isHidden()) {
|
||||
_chatWindow->show();
|
||||
}
|
||||
_chatWindow->raise();
|
||||
_chatWindow->activateWindow();
|
||||
_chatWindow->setFocus();
|
||||
} else {
|
||||
qApp->getTrayIcon()->showMessage("Interface",
|
||||
"You need to login to be able to chat with others on this domain.");
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsManager::toggleChat() {
|
||||
#ifdef HAVE_QXMPP
|
||||
QAction* chatAction = Menu::getInstance()->getActionForOption(MenuOption::Login);
|
||||
Q_CHECK_PTR(chatAction);
|
||||
|
||||
chatAction->setEnabled(XmppClient::getInstance().getXMPPClient().isConnected());
|
||||
if (!chatAction->isEnabled() && _chatWindow && AccountManager::getInstance().isLoggedIn()) {
|
||||
if (_chatWindow->isHidden()) {
|
||||
_chatWindow->show();
|
||||
_chatWindow->raise();
|
||||
_chatWindow->activateWindow();
|
||||
_chatWindow->setFocus();
|
||||
} else {
|
||||
_chatWindow->hide();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
105
interface/src/ui/DialogsManager.h
Normal file
105
interface/src/ui/DialogsManager.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
//
|
||||
// DialogsManager.h
|
||||
//
|
||||
//
|
||||
// Created by Clement on 1/18/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_DialogsManager_h
|
||||
#define hifi_DialogsManager_h
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
#include <Application.h>
|
||||
#include <DependencyManager.h>
|
||||
|
||||
#include "HMDToolsDialog.h"
|
||||
|
||||
class QAction;
|
||||
|
||||
class AddressBarDialog;
|
||||
class AnimationsDialog;
|
||||
class AttachmentsDialog;
|
||||
class CachesSizeDialog;
|
||||
class ChatWindow;
|
||||
class BandwidthDialog;
|
||||
class LodToolsDialog;
|
||||
class LoginDialog;
|
||||
class MetavoxelEditor;
|
||||
class MetavoxelNetworkSimulator;
|
||||
class OctreeStatsDialog;
|
||||
class PreferencesDialog;
|
||||
class ScriptEditorWindow;
|
||||
|
||||
class DialogsManager : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
QPointer<BandwidthDialog> getBandwidthDialog() const { return _bandwidthDialog; }
|
||||
QPointer<HMDToolsDialog> getHMDToolsDialog() const { return _hmdToolsDialog; }
|
||||
QPointer<LodToolsDialog> getLodToolsDialog() const { return _lodToolsDialog; }
|
||||
QPointer<OctreeStatsDialog> getOctreeStatsDialog() const { return _octreeStatsDialog; }
|
||||
|
||||
void setupChat();
|
||||
|
||||
public slots:
|
||||
void toggleAddressBar();
|
||||
void toggleLoginDialog();
|
||||
void showLoginDialog();
|
||||
void octreeStatsDetails();
|
||||
void cachesSizeDialog();
|
||||
void editPreferences();
|
||||
void editAttachments();
|
||||
void editAnimations();
|
||||
void bandwidthDetails();
|
||||
void lodTools();
|
||||
void hmdTools(bool showTools);
|
||||
void showMetavoxelEditor();
|
||||
void showMetavoxelNetworkSimulator();
|
||||
void showScriptEditor();
|
||||
void showChat();
|
||||
|
||||
private slots:
|
||||
void toggleToolWindow();
|
||||
void hmdToolsClosed();
|
||||
void toggleChat();
|
||||
|
||||
private:
|
||||
DialogsManager() {}
|
||||
|
||||
template<typename T>
|
||||
void maybeCreateDialog(QPointer<T>& member) {
|
||||
if (!member) {
|
||||
MainWindow* parent = qApp->getWindow();
|
||||
Q_CHECK_PTR(parent);
|
||||
member = new T(parent);
|
||||
Q_CHECK_PTR(member);
|
||||
|
||||
if (_hmdToolsDialog) {
|
||||
_hmdToolsDialog->watchWindow(member->windowHandle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPointer<AddressBarDialog> _addressBarDialog;
|
||||
QPointer<AnimationsDialog> _animationsDialog;
|
||||
QPointer<AttachmentsDialog> _attachmentsDialog;
|
||||
QPointer<BandwidthDialog> _bandwidthDialog;
|
||||
QPointer<CachesSizeDialog> _cachesSizeDialog;
|
||||
QPointer<ChatWindow> _chatWindow;
|
||||
QPointer<HMDToolsDialog> _hmdToolsDialog;
|
||||
QPointer<LodToolsDialog> _lodToolsDialog;
|
||||
QPointer<LoginDialog> _loginDialog;
|
||||
QPointer<MetavoxelEditor> _metavoxelEditor;
|
||||
QPointer<MetavoxelNetworkSimulator> _metavoxelNetworkSimulator;
|
||||
QPointer<OctreeStatsDialog> _octreeStatsDialog;
|
||||
QPointer<PreferencesDialog> _preferencesDialog;
|
||||
QPointer<ScriptEditorWindow> _scriptEditor;
|
||||
};
|
||||
|
||||
#endif // hifi_DialogsManager_h
|
|
@ -19,11 +19,13 @@
|
|||
#include <QScreen>
|
||||
#include <QWindow>
|
||||
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "Menu.h"
|
||||
#include "devices/OculusManager.h"
|
||||
#include "ui/DialogsManager.h"
|
||||
#include "ui/HMDToolsDialog.h"
|
||||
|
||||
#include "devices/OculusManager.h"
|
||||
|
||||
HMDToolsDialog::HMDToolsDialog(QWidget* parent) :
|
||||
QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) ,
|
||||
|
@ -67,20 +69,21 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) :
|
|||
// watch for our dialog window moving screens. If it does we want to enforce our rules about
|
||||
// what screens we're allowed on
|
||||
watchWindow(windowHandle());
|
||||
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
||||
if (Application::getInstance()->getRunningScriptsWidget()) {
|
||||
watchWindow(Application::getInstance()->getRunningScriptsWidget()->windowHandle());
|
||||
}
|
||||
if (Application::getInstance()->getToolWindow()) {
|
||||
watchWindow(Application::getInstance()->getToolWindow()->windowHandle());
|
||||
}
|
||||
if (Menu::getInstance()->getBandwidthDialog()) {
|
||||
watchWindow(Menu::getInstance()->getBandwidthDialog()->windowHandle());
|
||||
if (dialogsManager->getBandwidthDialog()) {
|
||||
watchWindow(dialogsManager->getBandwidthDialog()->windowHandle());
|
||||
}
|
||||
if (Menu::getInstance()->getOctreeStatsDialog()) {
|
||||
watchWindow(Menu::getInstance()->getOctreeStatsDialog()->windowHandle());
|
||||
if (dialogsManager->getOctreeStatsDialog()) {
|
||||
watchWindow(dialogsManager->getOctreeStatsDialog()->windowHandle());
|
||||
}
|
||||
if (Menu::getInstance()->getLodToolsDialog()) {
|
||||
watchWindow(Menu::getInstance()->getLodToolsDialog()->windowHandle());
|
||||
if (dialogsManager->getLodToolsDialog()) {
|
||||
watchWindow(dialogsManager->getLodToolsDialog()->windowHandle());
|
||||
}
|
||||
|
||||
// when the application is about to quit, leave HDM mode
|
||||
|
|
|
@ -10,18 +10,21 @@
|
|||
//
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include <QDesktopWidget>
|
||||
#include <QFileInfo>
|
||||
#include <QtWebKitWidgets/QWebFrame>
|
||||
#include <QtWebKit/QWebElement>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
#include <PathUtils.h>
|
||||
#include <Settings.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "InfoView.h"
|
||||
|
||||
#define SETTINGS_VERSION_KEY "info-version"
|
||||
#define MAX_DIALOG_HEIGHT_RATIO 0.9
|
||||
static const float MAX_DIALOG_HEIGHT_RATIO = 0.9f;
|
||||
|
||||
namespace SettingHandles {
|
||||
const SettingHandle<QString> infoVersion("info-version", QString());
|
||||
}
|
||||
|
||||
InfoView::InfoView(bool forced, QString path) :
|
||||
_forced(forced)
|
||||
|
@ -49,20 +52,17 @@ bool InfoView::shouldShow() {
|
|||
return true;
|
||||
}
|
||||
|
||||
QSettings* settings = Application::getInstance()->lockSettings();
|
||||
|
||||
QString lastVersion = settings->value(SETTINGS_VERSION_KEY).toString();
|
||||
QString lastVersion = SettingHandles::infoVersion.get();
|
||||
|
||||
QWebElement versionTag = page()->mainFrame()->findFirstElement("#version");
|
||||
QString version = versionTag.attribute("value");
|
||||
|
||||
if (version != QString::null && (lastVersion == QString::null || lastVersion != version)) {
|
||||
settings->setValue(SETTINGS_VERSION_KEY, version);
|
||||
SettingHandles::infoVersion.set(version);
|
||||
shouldShow = true;
|
||||
} else {
|
||||
shouldShow = false;
|
||||
}
|
||||
Application::getInstance()->unlockSettings();
|
||||
return shouldShow;
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ void InfoView::loaded(bool ok) {
|
|||
return;
|
||||
}
|
||||
|
||||
QDesktopWidget* desktop = Application::getInstance()->desktop();
|
||||
QDesktopWidget* desktop = qApp->desktop();
|
||||
QWebFrame* mainFrame = page()->mainFrame();
|
||||
|
||||
int height = mainFrame->contentsSize().height() > desktop->height() ?
|
||||
|
|
|
@ -9,17 +9,19 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QFormLayout>
|
||||
#include <QDialogButtonBox>
|
||||
|
||||
#include <QPalette>
|
||||
#include <QCheckBox>
|
||||
#include <QColor>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QSlider>
|
||||
#include <QFormLayout>
|
||||
#include <QLabel>
|
||||
#include <QPalette>
|
||||
#include <QPushButton>
|
||||
#include <QSlider>
|
||||
#include <QString>
|
||||
|
||||
#include <LODManager.h>
|
||||
|
||||
#include "Menu.h"
|
||||
#include "ui/LodToolsDialog.h"
|
||||
|
||||
|
@ -28,6 +30,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
|
|||
QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint)
|
||||
{
|
||||
this->setWindowTitle("LOD Tools");
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
|
||||
// Create layouter
|
||||
QFormLayout* form = new QFormLayout(this);
|
||||
|
@ -45,7 +48,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
|
|||
_lodSize->setTickPosition(QSlider::TicksBelow);
|
||||
_lodSize->setFixedWidth(SLIDER_WIDTH);
|
||||
_lodSize->setPageStep(PAGE_STEP_LOD_SIZE);
|
||||
int sliderValue = Menu::getInstance()->getOctreeSizeScale() / TREE_SCALE;
|
||||
int sliderValue = lodManager->getOctreeSizeScale() / TREE_SCALE;
|
||||
_lodSize->setValue(sliderValue);
|
||||
form->addRow("LOD Size Scale:", _lodSize);
|
||||
connect(_lodSize,SIGNAL(valueChanged(int)),this,SLOT(sizeScaleValueChanged(int)));
|
||||
|
@ -60,7 +63,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
|
|||
_boundaryLevelAdjust->setTickInterval(STEP_ADJUST);
|
||||
_boundaryLevelAdjust->setTickPosition(QSlider::TicksBelow);
|
||||
_boundaryLevelAdjust->setFixedWidth(SLIDER_WIDTH);
|
||||
sliderValue = Menu::getInstance()->getBoundaryLevelAdjust();
|
||||
sliderValue = lodManager->getBoundaryLevelAdjust();
|
||||
_boundaryLevelAdjust->setValue(sliderValue);
|
||||
form->addRow("Boundary Level Adjust:", _boundaryLevelAdjust);
|
||||
connect(_boundaryLevelAdjust,SIGNAL(valueChanged(int)),this,SLOT(boundaryLevelValueChanged(int)));
|
||||
|
@ -71,22 +74,22 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
|
|||
const unsigned redish = 0xfff00000;
|
||||
palette.setColor(QPalette::WindowText, QColor::fromRgb(redish));
|
||||
_feedback->setPalette(palette);
|
||||
_feedback->setText(Menu::getInstance()->getLODFeedbackText());
|
||||
_feedback->setText(lodManager->getLODFeedbackText());
|
||||
const int FEEDBACK_WIDTH = 350;
|
||||
_feedback->setFixedWidth(FEEDBACK_WIDTH);
|
||||
form->addRow("You can see... ", _feedback);
|
||||
|
||||
|
||||
form->addRow("Automatic Avatar LOD Adjustment:", _automaticAvatarLOD = new QCheckBox(this));
|
||||
_automaticAvatarLOD->setChecked(Menu::getInstance()->getAutomaticAvatarLOD());
|
||||
_automaticAvatarLOD->setChecked(lodManager->getAutomaticAvatarLOD());
|
||||
connect(_automaticAvatarLOD, SIGNAL(toggled(bool)), SLOT(updateAvatarLODControls()));
|
||||
|
||||
form->addRow("Decrease Avatar LOD Below FPS:", _avatarLODDecreaseFPS = new QDoubleSpinBox(this));
|
||||
_avatarLODDecreaseFPS->setValue(Menu::getInstance()->getAvatarLODDecreaseFPS());
|
||||
_avatarLODDecreaseFPS->setValue(lodManager->getAvatarLODDecreaseFPS());
|
||||
_avatarLODDecreaseFPS->setDecimals(0);
|
||||
connect(_avatarLODDecreaseFPS, SIGNAL(valueChanged(double)), SLOT(updateAvatarLODValues()));
|
||||
|
||||
form->addRow("Increase Avatar LOD Above FPS:", _avatarLODIncreaseFPS = new QDoubleSpinBox(this));
|
||||
_avatarLODIncreaseFPS->setValue(Menu::getInstance()->getAvatarLODIncreaseFPS());
|
||||
_avatarLODIncreaseFPS->setValue(lodManager->getAvatarLODIncreaseFPS());
|
||||
_avatarLODIncreaseFPS->setDecimals(0);
|
||||
connect(_avatarLODIncreaseFPS, SIGNAL(valueChanged(double)), SLOT(updateAvatarLODValues()));
|
||||
|
||||
|
@ -94,7 +97,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
|
|||
_avatarLOD->setDecimals(3);
|
||||
_avatarLOD->setRange(1.0 / MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER, 1.0 / MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER);
|
||||
_avatarLOD->setSingleStep(0.001);
|
||||
_avatarLOD->setValue(1.0 / Menu::getInstance()->getAvatarLODDistanceMultiplier());
|
||||
_avatarLOD->setValue(1.0 / lodManager->getAvatarLODDistanceMultiplier());
|
||||
connect(_avatarLOD, SIGNAL(valueChanged(double)), SLOT(updateAvatarLODValues()));
|
||||
|
||||
// Add a button to reset
|
||||
|
@ -108,15 +111,17 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
|
|||
}
|
||||
|
||||
void LodToolsDialog::reloadSliders() {
|
||||
_lodSize->setValue(Menu::getInstance()->getOctreeSizeScale() / TREE_SCALE);
|
||||
_boundaryLevelAdjust->setValue(Menu::getInstance()->getBoundaryLevelAdjust());
|
||||
_feedback->setText(Menu::getInstance()->getLODFeedbackText());
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
_lodSize->setValue(lodManager->getOctreeSizeScale() / TREE_SCALE);
|
||||
_boundaryLevelAdjust->setValue(lodManager->getBoundaryLevelAdjust());
|
||||
_feedback->setText(lodManager->getLODFeedbackText());
|
||||
}
|
||||
|
||||
void LodToolsDialog::updateAvatarLODControls() {
|
||||
QFormLayout* form = static_cast<QFormLayout*>(layout());
|
||||
|
||||
Menu::getInstance()->setAutomaticAvatarLOD(_automaticAvatarLOD->isChecked());
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
lodManager->setAutomaticAvatarLOD(_automaticAvatarLOD->isChecked());
|
||||
|
||||
_avatarLODDecreaseFPS->setVisible(_automaticAvatarLOD->isChecked());
|
||||
form->labelForField(_avatarLODDecreaseFPS)->setVisible(_automaticAvatarLOD->isChecked());
|
||||
|
@ -128,7 +133,7 @@ void LodToolsDialog::updateAvatarLODControls() {
|
|||
form->labelForField(_avatarLOD)->setVisible(!_automaticAvatarLOD->isChecked());
|
||||
|
||||
if (!_automaticAvatarLOD->isChecked()) {
|
||||
_avatarLOD->setValue(1.0 / Menu::getInstance()->getAvatarLODDistanceMultiplier());
|
||||
_avatarLOD->setValue(1.0 / lodManager->getAvatarLODDistanceMultiplier());
|
||||
}
|
||||
|
||||
if (isVisible()) {
|
||||
|
@ -137,25 +142,28 @@ void LodToolsDialog::updateAvatarLODControls() {
|
|||
}
|
||||
|
||||
void LodToolsDialog::updateAvatarLODValues() {
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
if (_automaticAvatarLOD->isChecked()) {
|
||||
Menu::getInstance()->setAvatarLODDecreaseFPS(_avatarLODDecreaseFPS->value());
|
||||
Menu::getInstance()->setAvatarLODIncreaseFPS(_avatarLODIncreaseFPS->value());
|
||||
lodManager->setAvatarLODDecreaseFPS(_avatarLODDecreaseFPS->value());
|
||||
lodManager->setAvatarLODIncreaseFPS(_avatarLODIncreaseFPS->value());
|
||||
|
||||
} else {
|
||||
Menu::getInstance()->setAvatarLODDistanceMultiplier(1.0 / _avatarLOD->value());
|
||||
lodManager->setAvatarLODDistanceMultiplier(1.0 / _avatarLOD->value());
|
||||
}
|
||||
}
|
||||
|
||||
void LodToolsDialog::sizeScaleValueChanged(int value) {
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
float realValue = value * TREE_SCALE;
|
||||
Menu::getInstance()->setOctreeSizeScale(realValue);
|
||||
lodManager->setOctreeSizeScale(realValue);
|
||||
|
||||
_feedback->setText(Menu::getInstance()->getLODFeedbackText());
|
||||
_feedback->setText(lodManager->getLODFeedbackText());
|
||||
}
|
||||
|
||||
void LodToolsDialog::boundaryLevelValueChanged(int value) {
|
||||
Menu::getInstance()->setBoundaryLevelAdjust(value);
|
||||
_feedback->setText(Menu::getInstance()->getLODFeedbackText());
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
lodManager->setBoundaryLevelAdjust(value);
|
||||
_feedback->setText(lodManager->getLODFeedbackText());
|
||||
}
|
||||
|
||||
void LodToolsDialog::resetClicked(bool checked) {
|
||||
|
|
|
@ -29,12 +29,9 @@ LoginDialog::LoginDialog(QWidget* parent) :
|
|||
_ui(new Ui::LoginDialog) {
|
||||
|
||||
_ui->setupUi(this);
|
||||
_ui->errorLabel->hide();
|
||||
_ui->emailLineEdit->setFocus();
|
||||
_ui->logoLabel->setPixmap(QPixmap(PathUtils::resourcesPath() + "images/hifi-logo.svg"));
|
||||
_ui->loginButton->setIcon(QIcon(PathUtils::resourcesPath() + "images/login.svg"));
|
||||
_ui->infoLabel->setVisible(false);
|
||||
_ui->errorLabel->setVisible(false);
|
||||
reset();
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose, false);
|
||||
|
||||
connect(&AccountManager::getInstance(), &AccountManager::loginComplete,
|
||||
this, &LoginDialog::handleLoginCompleted);
|
||||
|
@ -50,9 +47,21 @@ LoginDialog::~LoginDialog() {
|
|||
delete _ui;
|
||||
};
|
||||
|
||||
void LoginDialog::handleLoginCompleted(const QUrl& authURL) {
|
||||
void LoginDialog::reset() {
|
||||
_ui->errorLabel->hide();
|
||||
_ui->emailLineEdit->setFocus();
|
||||
_ui->logoLabel->setPixmap(QPixmap(PathUtils::resourcesPath() + "images/hifi-logo.svg"));
|
||||
_ui->loginButton->setIcon(QIcon(PathUtils::resourcesPath() + "images/login.svg"));
|
||||
_ui->infoLabel->setVisible(false);
|
||||
_ui->errorLabel->setVisible(false);
|
||||
|
||||
_ui->emailLineEdit->setText("");
|
||||
_ui->passwordLineEdit->setText("");
|
||||
_ui->loginArea->setDisabled(false);
|
||||
}
|
||||
|
||||
void LoginDialog::handleLoginCompleted(const QUrl& authURL) {
|
||||
reset();
|
||||
close();
|
||||
};
|
||||
|
||||
|
@ -87,3 +96,27 @@ void LoginDialog::moveEvent(QMoveEvent* event) {
|
|||
// Modal dialogs seemed to get repositioned automatically. Combat this by moving the window if needed.
|
||||
resizeAndPosition();
|
||||
};
|
||||
|
||||
|
||||
void LoginDialog::toggleQAction() {
|
||||
AccountManager& accountManager = AccountManager::getInstance();
|
||||
QAction* loginAction = Menu::getInstance()->getActionForOption(MenuOption::Login);
|
||||
Q_CHECK_PTR(loginAction);
|
||||
|
||||
disconnect(loginAction, 0, 0, 0);
|
||||
|
||||
if (accountManager.isLoggedIn()) {
|
||||
// change the menu item to logout
|
||||
loginAction->setText("Logout " + accountManager.getAccountInfo().getUsername());
|
||||
connect(loginAction, &QAction::triggered, &accountManager, &AccountManager::logout);
|
||||
} else {
|
||||
// change the menu item to login
|
||||
loginAction->setText("Login");
|
||||
connect(loginAction, &QAction::triggered, this, &LoginDialog::showLoginForCurrentDomain);
|
||||
}
|
||||
}
|
||||
|
||||
void LoginDialog::showLoginForCurrentDomain() {
|
||||
show();
|
||||
resizeAndPosition(false);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,11 @@ public:
|
|||
~LoginDialog();
|
||||
|
||||
public slots:
|
||||
void toggleQAction();
|
||||
void showLoginForCurrentDomain();
|
||||
|
||||
protected slots:
|
||||
void reset();
|
||||
void handleLoginClicked();
|
||||
void handleLoginCompleted(const QUrl& authURL);
|
||||
void handleLoginFailed();
|
||||
|
@ -35,8 +40,7 @@ protected:
|
|||
void moveEvent(QMoveEvent* event);
|
||||
|
||||
private:
|
||||
Ui::LoginDialog* _ui;
|
||||
|
||||
Ui::LoginDialog* _ui = nullptr;
|
||||
};
|
||||
|
||||
#endif // hifi_LoginDialog_h
|
||||
|
|
|
@ -50,8 +50,8 @@ enum GridPlane {
|
|||
|
||||
const glm::vec2 INVALID_VECTOR(FLT_MAX, FLT_MAX);
|
||||
|
||||
MetavoxelEditor::MetavoxelEditor() :
|
||||
QWidget(Application::getInstance()->getWindow(), Qt::Tool) {
|
||||
MetavoxelEditor::MetavoxelEditor(QWidget* parent) :
|
||||
QWidget(parent, Qt::Tool) {
|
||||
|
||||
setWindowTitle("Metavoxel Editor");
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
@ -820,6 +820,12 @@ HeightfieldBrushTool::HeightfieldBrushTool(MetavoxelEditor* editor, const QStrin
|
|||
_radius->setSingleStep(0.01);
|
||||
_radius->setMaximum(FLT_MAX);
|
||||
_radius->setValue(5.0);
|
||||
|
||||
_form->addRow("Granularity:", _granularity = new QDoubleSpinBox());
|
||||
_granularity->setMinimum(-FLT_MAX);
|
||||
_granularity->setMaximum(FLT_MAX);
|
||||
_granularity->setPrefix("2^");
|
||||
_granularity->setValue(8.0);
|
||||
}
|
||||
|
||||
bool HeightfieldBrushTool::appliesTo(const AttributePointer& attribute) const {
|
||||
|
@ -849,7 +855,7 @@ bool HeightfieldBrushTool::eventFilter(QObject* watched, QEvent* event) {
|
|||
if (event->type() == QEvent::Wheel) {
|
||||
float angle = static_cast<QWheelEvent*>(event)->angleDelta().y();
|
||||
const float ANGLE_SCALE = 1.0f / 1000.0f;
|
||||
_radius->setValue(_radius->value() * glm::pow(2.0f, angle * ANGLE_SCALE));
|
||||
_radius->setValue(_radius->value() * pow(2.0f, angle * ANGLE_SCALE));
|
||||
return true;
|
||||
|
||||
} else if (event->type() == QEvent::MouseButtonPress && _positionValid) {
|
||||
|
@ -879,7 +885,7 @@ QVariant HeightfieldHeightBrushTool::createEdit(bool alternate) {
|
|||
const int ERASE_MODE_INDEX = 2;
|
||||
return QVariant::fromValue(PaintHeightfieldHeightEdit(_position, _radius->value(),
|
||||
alternate ? -_height->value() : _height->value(), _mode->currentIndex() == SET_MODE_INDEX,
|
||||
_mode->currentIndex() == ERASE_MODE_INDEX));
|
||||
_mode->currentIndex() == ERASE_MODE_INDEX, pow(2.0f, _granularity->value())));
|
||||
}
|
||||
|
||||
MaterialControl::MaterialControl(QWidget* widget, QFormLayout* form, bool clearable) :
|
||||
|
@ -954,10 +960,11 @@ QVariant HeightfieldMaterialBrushTool::createEdit(bool alternate) {
|
|||
sphere->setScale(_radius->value());
|
||||
if (alternate) {
|
||||
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
||||
SharedObjectPointer(), QColor(0, 0, 0, 0), true));
|
||||
SharedObjectPointer(), QColor(0, 0, 0, 0), true, false, pow(2.0f, _granularity->value())));
|
||||
} else {
|
||||
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
||||
_materialControl->getMaterial(), _materialControl->getColor(), true));
|
||||
_materialControl->getMaterial(), _materialControl->getColor(),
|
||||
true, false, pow(2.0f, _granularity->value())));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -972,10 +979,11 @@ QVariant HeightfieldSculptBrushTool::createEdit(bool alternate) {
|
|||
sphere->setScale(_radius->value());
|
||||
if (alternate) {
|
||||
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
||||
SharedObjectPointer(), QColor(0, 0, 0, 0)));
|
||||
SharedObjectPointer(), QColor(0, 0, 0, 0), false, false, pow(2.0f, _granularity->value())));
|
||||
} else {
|
||||
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
||||
_materialControl->getMaterial(), _materialControl->getColor()));
|
||||
_materialControl->getMaterial(), _materialControl->getColor(),
|
||||
false, false, pow(2.0f, _granularity->value())));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -990,13 +998,14 @@ HeightfieldFillBrushTool::HeightfieldFillBrushTool(MetavoxelEditor* editor) :
|
|||
QVariant HeightfieldFillBrushTool::createEdit(bool alternate) {
|
||||
const int FILL_MODE_INDEX = 0;
|
||||
if (_mode->currentIndex() == FILL_MODE_INDEX) {
|
||||
return QVariant::fromValue(FillHeightfieldHeightEdit(_position, _radius->value()));
|
||||
return QVariant::fromValue(FillHeightfieldHeightEdit(_position, _radius->value(),
|
||||
pow(2.0f, _granularity->value())));
|
||||
}
|
||||
Sphere* sphere = new Sphere();
|
||||
sphere->setTranslation(_position);
|
||||
sphere->setScale(_radius->value());
|
||||
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
||||
SharedObjectPointer(), QColor(), false, true));
|
||||
SharedObjectPointer(), QColor(), false, true, pow(2.0f, _granularity->value())));
|
||||
}
|
||||
|
||||
HeightfieldMaterialBoxTool::HeightfieldMaterialBoxTool(MetavoxelEditor* editor) :
|
||||
|
@ -1015,6 +1024,12 @@ HeightfieldMaterialBoxTool::HeightfieldMaterialBoxTool(MetavoxelEditor* editor)
|
|||
_snapToGrid->setChecked(true);
|
||||
|
||||
_materialControl = new MaterialControl(this, form, true);
|
||||
|
||||
form->addRow("Granularity:", _granularity = new QDoubleSpinBox());
|
||||
_granularity->setMinimum(-FLT_MAX);
|
||||
_granularity->setMaximum(FLT_MAX);
|
||||
_granularity->setPrefix("2^");
|
||||
_granularity->setValue(8.0);
|
||||
}
|
||||
|
||||
bool HeightfieldMaterialBoxTool::appliesTo(const AttributePointer& attribute) const {
|
||||
|
@ -1037,7 +1052,7 @@ void HeightfieldMaterialBoxTool::applyValue(const glm::vec3& minimum, const glm:
|
|||
cuboid->setAspectY(vector.y / vector.x);
|
||||
cuboid->setAspectZ(vector.z / vector.x);
|
||||
MetavoxelEditMessage message = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(cuboid),
|
||||
_materialControl->getMaterial(), _materialControl->getColor())) };
|
||||
_materialControl->getMaterial(), _materialControl->getColor(), false, false, pow(2.0f, _granularity->value()))) };
|
||||
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
||||
}
|
||||
|
||||
|
@ -1054,6 +1069,12 @@ HeightfieldMaterialSpannerTool::HeightfieldMaterialSpannerTool(MetavoxelEditor*
|
|||
|
||||
_materialControl = new MaterialControl(this, form, true);
|
||||
|
||||
form->addRow("Granularity:", _granularity = new QDoubleSpinBox());
|
||||
_granularity->setMinimum(-FLT_MAX);
|
||||
_granularity->setMaximum(FLT_MAX);
|
||||
_granularity->setPrefix("2^");
|
||||
_granularity->setValue(8.0);
|
||||
|
||||
QPushButton* place = new QPushButton("Set");
|
||||
layout()->addWidget(place);
|
||||
connect(place, &QPushButton::clicked, this, &HeightfieldMaterialSpannerTool::place);
|
||||
|
@ -1074,7 +1095,7 @@ QColor HeightfieldMaterialSpannerTool::getColor() {
|
|||
void HeightfieldMaterialSpannerTool::applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) {
|
||||
static_cast<Spanner*>(spanner.data())->setWillBeVoxelized(true);
|
||||
MetavoxelEditMessage message = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(spanner,
|
||||
_materialControl->getMaterial(), _materialControl->getColor())) };
|
||||
_materialControl->getMaterial(), _materialControl->getColor(), false, false, pow(2.0f, _granularity->value()))) };
|
||||
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#ifndef hifi_MetavoxelEditor_h
|
||||
#define hifi_MetavoxelEditor_h
|
||||
|
||||
#include <QFormLayout>
|
||||
#include <QList>
|
||||
#include <QWidget>
|
||||
|
||||
|
@ -38,7 +39,7 @@ class MetavoxelEditor : public QWidget {
|
|||
|
||||
public:
|
||||
|
||||
MetavoxelEditor();
|
||||
MetavoxelEditor(QWidget* parent = nullptr);
|
||||
|
||||
QString getSelectedAttribute() const;
|
||||
|
||||
|
@ -326,6 +327,7 @@ protected:
|
|||
|
||||
QFormLayout* _form;
|
||||
QDoubleSpinBox* _radius;
|
||||
QDoubleSpinBox* _granularity;
|
||||
|
||||
glm::vec3 _position;
|
||||
bool _positionValid;
|
||||
|
@ -448,6 +450,7 @@ private:
|
|||
|
||||
QCheckBox* _snapToGrid;
|
||||
MaterialControl* _materialControl;
|
||||
QDoubleSpinBox* _granularity;
|
||||
};
|
||||
|
||||
/// Allows setting heightfield materials by placing a spanner.
|
||||
|
@ -470,6 +473,7 @@ private:
|
|||
|
||||
SharedObjectEditor* _spannerEditor;
|
||||
MaterialControl* _materialControl;
|
||||
QDoubleSpinBox* _granularity;
|
||||
};
|
||||
|
||||
#endif // hifi_MetavoxelEditor_h
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
const int BYTES_PER_KILOBYTE = 1024;
|
||||
|
||||
MetavoxelNetworkSimulator::MetavoxelNetworkSimulator() :
|
||||
QWidget(DependencyManager::get<GLCanvas>().data(), Qt::Dialog) {
|
||||
MetavoxelNetworkSimulator::MetavoxelNetworkSimulator(QWidget* parent) :
|
||||
QWidget(parent, Qt::Dialog) {
|
||||
|
||||
setWindowTitle("Metavoxel Network Simulator");
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
|
|
@ -23,7 +23,7 @@ class MetavoxelNetworkSimulator : public QWidget {
|
|||
|
||||
public:
|
||||
|
||||
MetavoxelNetworkSimulator();
|
||||
MetavoxelNetworkSimulator(QWidget* parent = nullptr);
|
||||
|
||||
private slots:
|
||||
|
||||
|
|
|
@ -11,18 +11,22 @@
|
|||
|
||||
#include <QFileDialog>
|
||||
|
||||
#include <devices/Faceshift.h>
|
||||
#include <devices/SixenseManager.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Audio.h"
|
||||
#include "MainWindow.h"
|
||||
#include "Menu.h"
|
||||
#include "ModelsBrowser.h"
|
||||
#include "PreferencesDialog.h"
|
||||
#include "Snapshot.h"
|
||||
#include "UserActivityLogger.h"
|
||||
|
||||
const int PREFERENCES_HEIGHT_PADDING = 20;
|
||||
|
||||
PreferencesDialog::PreferencesDialog() :
|
||||
QDialog(Application::getInstance()->getWindow()) {
|
||||
PreferencesDialog::PreferencesDialog(QWidget* parent) :
|
||||
QDialog(parent) {
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
|
@ -117,51 +121,53 @@ void PreferencesDialog::loadPreferences() {
|
|||
|
||||
ui.sendDataCheckBox->setChecked(!menuInstance->isOptionChecked(MenuOption::DisableActivityLogger));
|
||||
|
||||
ui.snapshotLocationEdit->setText(menuInstance->getSnapshotsLocation());
|
||||
ui.snapshotLocationEdit->setText(SettingHandles::snapshotsLocation.get());
|
||||
|
||||
ui.scriptsLocationEdit->setText(menuInstance->getScriptsLocation());
|
||||
ui.scriptsLocationEdit->setText(qApp->getScriptsLocation());
|
||||
|
||||
ui.pupilDilationSlider->setValue(myAvatar->getHead()->getPupilDilation() *
|
||||
ui.pupilDilationSlider->maximum());
|
||||
|
||||
ui.faceshiftEyeDeflectionSider->setValue(menuInstance->getFaceshiftEyeDeflection() *
|
||||
auto faceshift = DependencyManager::get<Faceshift>();
|
||||
ui.faceshiftEyeDeflectionSider->setValue(faceshift->getEyeDeflection() *
|
||||
ui.faceshiftEyeDeflectionSider->maximum());
|
||||
|
||||
ui.faceshiftHostnameEdit->setText(menuInstance->getFaceshiftHostname());
|
||||
ui.faceshiftHostnameEdit->setText(faceshift->getHostname());
|
||||
|
||||
const InboundAudioStream::Settings& streamSettings = menuInstance->getReceivedAudioStreamSettings();
|
||||
|
||||
ui.dynamicJitterBuffersCheckBox->setChecked(streamSettings._dynamicJitterBuffers);
|
||||
ui.staticDesiredJitterBufferFramesSpin->setValue(streamSettings._staticDesiredJitterBufferFrames);
|
||||
ui.maxFramesOverDesiredSpin->setValue(streamSettings._maxFramesOverDesired);
|
||||
ui.useStdevForJitterCalcCheckBox->setChecked(streamSettings._useStDevForJitterCalc);
|
||||
ui.windowStarveThresholdSpin->setValue(streamSettings._windowStarveThreshold);
|
||||
ui.windowSecondsForDesiredCalcOnTooManyStarvesSpin->setValue(streamSettings._windowSecondsForDesiredCalcOnTooManyStarves);
|
||||
ui.windowSecondsForDesiredReductionSpin->setValue(streamSettings._windowSecondsForDesiredReduction);
|
||||
ui.repetitionWithFadeCheckBox->setChecked(streamSettings._repetitionWithFade);
|
||||
|
||||
auto audio = DependencyManager::get<Audio>();
|
||||
MixedProcessedAudioStream& stream = audio->getReceivedAudioStream();
|
||||
|
||||
ui.dynamicJitterBuffersCheckBox->setChecked(stream.getDynamicJitterBuffers());
|
||||
ui.staticDesiredJitterBufferFramesSpin->setValue(stream.getDesiredJitterBufferFrames());
|
||||
ui.maxFramesOverDesiredSpin->setValue(stream.getMaxFramesOverDesired());
|
||||
ui.useStdevForJitterCalcCheckBox->setChecked(stream.getUseStDevForJitterCalc());
|
||||
ui.windowStarveThresholdSpin->setValue(stream.getWindowStarveThreshold());
|
||||
ui.windowSecondsForDesiredCalcOnTooManyStarvesSpin->setValue(
|
||||
stream.getWindowSecondsForDesiredCalcOnTooManyStarves());
|
||||
ui.windowSecondsForDesiredReductionSpin->setValue(stream.getWindowSecondsForDesiredReduction());
|
||||
ui.repetitionWithFadeCheckBox->setChecked(stream.getRepetitionWithFade());
|
||||
|
||||
ui.outputBufferSizeSpinner->setValue(audio->getOutputBufferSize());
|
||||
|
||||
ui.outputStarveDetectionCheckBox->setChecked(audio->getOutputStarveDetectionEnabled());
|
||||
ui.outputStarveDetectionThresholdSpinner->setValue(audio->getOutputStarveDetectionThreshold());
|
||||
ui.outputStarveDetectionPeriodSpinner->setValue(audio->getOutputStarveDetectionPeriod());
|
||||
|
||||
ui.realWorldFieldOfViewSpin->setValue(menuInstance->getRealWorldFieldOfView());
|
||||
ui.realWorldFieldOfViewSpin->setValue(qApp->getViewFrustum()->getRealWorldFieldOfView());
|
||||
|
||||
ui.fieldOfViewSpin->setValue(menuInstance->getFieldOfView());
|
||||
ui.fieldOfViewSpin->setValue(qApp->getViewFrustum()->getFieldOfView());
|
||||
|
||||
ui.leanScaleSpin->setValue(myAvatar->getLeanScale());
|
||||
|
||||
ui.avatarScaleSpin->setValue(myAvatar->getScale());
|
||||
|
||||
ui.maxOctreePPSSpin->setValue(menuInstance->getMaxOctreePacketsPerSecond());
|
||||
ui.maxOctreePPSSpin->setValue(qApp->getOctreeQuery().getMaxOctreePacketsPerSecond());
|
||||
|
||||
ui.oculusUIAngularSizeSpin->setValue(menuInstance->getOculusUIAngularSize());
|
||||
ui.oculusUIAngularSizeSpin->setValue(qApp->getApplicationOverlay().getOculusUIAngularSize());
|
||||
|
||||
ui.sixenseReticleMoveSpeedSpin->setValue(menuInstance->getSixenseReticleMoveSpeed());
|
||||
|
||||
ui.invertSixenseButtonsCheckBox->setChecked(menuInstance->getInvertSixenseButtons());
|
||||
SixenseManager& sixense = SixenseManager::getInstance();
|
||||
ui.sixenseReticleMoveSpeedSpin->setValue(sixense.getReticleMoveSpeed());
|
||||
ui.invertSixenseButtonsCheckBox->setChecked(sixense.getInvertButtons());
|
||||
|
||||
}
|
||||
|
||||
|
@ -213,11 +219,11 @@ void PreferencesDialog::savePreferences() {
|
|||
}
|
||||
|
||||
if (!ui.snapshotLocationEdit->text().isEmpty() && QDir(ui.snapshotLocationEdit->text()).exists()) {
|
||||
Menu::getInstance()->setSnapshotsLocation(ui.snapshotLocationEdit->text());
|
||||
SettingHandles::snapshotsLocation.set(ui.snapshotLocationEdit->text());
|
||||
}
|
||||
|
||||
if (!ui.scriptsLocationEdit->text().isEmpty() && QDir(ui.scriptsLocationEdit->text()).exists()) {
|
||||
Menu::getInstance()->setScriptsLocation(ui.scriptsLocationEdit->text());
|
||||
qApp->setScriptsLocation(ui.scriptsLocationEdit->text());
|
||||
}
|
||||
|
||||
myAvatar->getHead()->setPupilDilation(ui.pupilDilationSlider->value() / (float)ui.pupilDilationSlider->maximum());
|
||||
|
@ -227,36 +233,35 @@ void PreferencesDialog::savePreferences() {
|
|||
auto glCanvas = DependencyManager::get<GLCanvas>();
|
||||
Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height());
|
||||
|
||||
Menu::getInstance()->setRealWorldFieldOfView(ui.realWorldFieldOfViewSpin->value());
|
||||
qApp->getViewFrustum()->setRealWorldFieldOfView(ui.realWorldFieldOfViewSpin->value());
|
||||
|
||||
Menu::getInstance()->setFieldOfView(ui.fieldOfViewSpin->value());
|
||||
|
||||
Menu::getInstance()->setFaceshiftEyeDeflection(ui.faceshiftEyeDeflectionSider->value() /
|
||||
(float)ui.faceshiftEyeDeflectionSider->maximum());
|
||||
qApp->getViewFrustum()->setFieldOfView(ui.fieldOfViewSpin->value());
|
||||
|
||||
Menu::getInstance()->setFaceshiftHostname(ui.faceshiftHostnameEdit->text());
|
||||
auto faceshift = DependencyManager::get<Faceshift>();
|
||||
faceshift->setEyeDeflection(ui.faceshiftEyeDeflectionSider->value() /
|
||||
(float)ui.faceshiftEyeDeflectionSider->maximum());
|
||||
|
||||
Menu::getInstance()->setMaxOctreePacketsPerSecond(ui.maxOctreePPSSpin->value());
|
||||
faceshift->setHostname(ui.faceshiftHostnameEdit->text());
|
||||
|
||||
qApp->getOctreeQuery().setMaxOctreePacketsPerSecond(ui.maxOctreePPSSpin->value());
|
||||
|
||||
Menu::getInstance()->setOculusUIAngularSize(ui.oculusUIAngularSizeSpin->value());
|
||||
|
||||
Menu::getInstance()->setSixenseReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value());
|
||||
|
||||
Menu::getInstance()->setInvertSixenseButtons(ui.invertSixenseButtonsCheckBox->isChecked());
|
||||
|
||||
InboundAudioStream::Settings streamSettings;
|
||||
streamSettings._dynamicJitterBuffers = ui.dynamicJitterBuffersCheckBox->isChecked();
|
||||
streamSettings._staticDesiredJitterBufferFrames = ui.staticDesiredJitterBufferFramesSpin->value();
|
||||
streamSettings._maxFramesOverDesired = ui.maxFramesOverDesiredSpin->value();
|
||||
streamSettings._useStDevForJitterCalc = ui.useStdevForJitterCalcCheckBox->isChecked();
|
||||
streamSettings._windowStarveThreshold = ui.windowStarveThresholdSpin->value();
|
||||
streamSettings._windowSecondsForDesiredCalcOnTooManyStarves = ui.windowSecondsForDesiredCalcOnTooManyStarvesSpin->value();
|
||||
streamSettings._windowSecondsForDesiredReduction = ui.windowSecondsForDesiredReductionSpin->value();
|
||||
streamSettings._repetitionWithFade = ui.repetitionWithFadeCheckBox->isChecked();
|
||||
|
||||
Menu::getInstance()->setReceivedAudioStreamSettings(streamSettings);
|
||||
qApp->getApplicationOverlay().setOculusUIAngularSize(ui.oculusUIAngularSizeSpin->value());
|
||||
|
||||
SixenseManager& sixense = SixenseManager::getInstance();
|
||||
sixense.setReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value());
|
||||
sixense.setInvertButtons(ui.invertSixenseButtonsCheckBox->isChecked());
|
||||
|
||||
auto audio = DependencyManager::get<Audio>();
|
||||
MixedProcessedAudioStream& stream = audio->getReceivedAudioStream();
|
||||
|
||||
stream.setDynamicJitterBuffers(ui.dynamicJitterBuffersCheckBox->isChecked());
|
||||
stream.setStaticDesiredJitterBufferFrames(ui.staticDesiredJitterBufferFramesSpin->value());
|
||||
stream.setMaxFramesOverDesired(ui.maxFramesOverDesiredSpin->value());
|
||||
stream.setUseStDevForJitterCalc(ui.useStdevForJitterCalcCheckBox->isChecked());
|
||||
stream.setWindowStarveThreshold(ui.windowStarveThresholdSpin->value());
|
||||
stream.setWindowSecondsForDesiredCalcOnTooManyStarves(ui.windowSecondsForDesiredCalcOnTooManyStarvesSpin->value());
|
||||
stream.setWindowSecondsForDesiredReduction(ui.windowSecondsForDesiredReductionSpin->value());
|
||||
stream.setRepetitionWithFade(ui.repetitionWithFadeCheckBox->isChecked());
|
||||
|
||||
QMetaObject::invokeMethod(audio.data(), "setOutputBufferSize", Q_ARG(int, ui.outputBufferSizeSpinner->value()));
|
||||
|
||||
|
@ -265,6 +270,4 @@ void PreferencesDialog::savePreferences() {
|
|||
audio->setOutputStarveDetectionPeriod(ui.outputStarveDetectionPeriodSpinner->value());
|
||||
|
||||
Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height());
|
||||
|
||||
Application::getInstance()->bumpSettings();
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class PreferencesDialog : public QDialog {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PreferencesDialog();
|
||||
PreferencesDialog(QWidget* parent = nullptr);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* resizeEvent);
|
||||
|
|
|
@ -20,24 +20,17 @@
|
|||
#include "RearMirrorTools.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
const char SETTINGS_GROUP_NAME[] = "Rear View Tools";
|
||||
const char ZOOM_LEVEL_SETTINGS[] = "ZoomLevel";
|
||||
const int ICON_SIZE = 24;
|
||||
const int ICON_PADDING = 5;
|
||||
|
||||
RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds, QSettings* settings) :
|
||||
RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds) :
|
||||
_parent(parent),
|
||||
_bounds(bounds),
|
||||
_windowed(false),
|
||||
_fullScreen(false)
|
||||
{
|
||||
_zoomLevel = HEAD;
|
||||
_closeTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/close.svg"));
|
||||
|
||||
// Disabled for now https://worklist.net/19548
|
||||
// _resetTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/reset.png"));
|
||||
|
||||
_zoomHeadTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/plus.svg"));
|
||||
_zoomBodyTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/minus.svg"));
|
||||
|
||||
|
@ -46,11 +39,7 @@ RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds, QSettings* se
|
|||
_resetIconRect = QRect(_bounds.width() - ICON_SIZE - ICON_PADDING, _bounds.top() + ICON_PADDING, ICON_SIZE, ICON_SIZE);
|
||||
_bodyZoomIconRect = QRect(_bounds.width() - ICON_SIZE - ICON_PADDING, _bounds.bottom() - ICON_PADDING - ICON_SIZE, ICON_SIZE, ICON_SIZE);
|
||||
_headZoomIconRect = QRect(_bounds.left() + ICON_PADDING, _bounds.bottom() - ICON_PADDING - ICON_SIZE, ICON_SIZE, ICON_SIZE);
|
||||
|
||||
settings->beginGroup(SETTINGS_GROUP_NAME);
|
||||
_zoomLevel = loadSetting(settings, ZOOM_LEVEL_SETTINGS, 0) == HEAD ? HEAD : BODY;
|
||||
settings->endGroup();
|
||||
};
|
||||
}
|
||||
|
||||
void RearMirrorTools::render(bool fullScreen) {
|
||||
if (fullScreen) {
|
||||
|
@ -63,11 +52,9 @@ void RearMirrorTools::render(bool fullScreen) {
|
|||
if (_windowed) {
|
||||
displayIcon(_bounds, _closeIconRect, _closeTextureId);
|
||||
|
||||
// Disabled for now https://worklist.net/19548
|
||||
// displayIcon(_bounds, _resetIconRect, _resetTextureId);
|
||||
|
||||
displayIcon(_bounds, _headZoomIconRect, _zoomHeadTextureId, _zoomLevel == HEAD);
|
||||
displayIcon(_bounds, _bodyZoomIconRect, _zoomBodyTextureId, _zoomLevel == BODY);
|
||||
ZoomLevel zoomLevel = (ZoomLevel)SettingHandles::rearViewZoomLevel.get();
|
||||
displayIcon(_bounds, _headZoomIconRect, _zoomHeadTextureId, zoomLevel == HEAD);
|
||||
displayIcon(_bounds, _bodyZoomIconRect, _zoomBodyTextureId, zoomLevel == BODY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,23 +66,14 @@ bool RearMirrorTools::mousePressEvent(int x, int y) {
|
|||
emit closeView();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Disabled for now https://worklist.net/19548
|
||||
if (_resetIconRect.contains(x, y)) {
|
||||
emit resetView();
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
if (_headZoomIconRect.contains(x, y)) {
|
||||
_zoomLevel = HEAD;
|
||||
Application::getInstance()->bumpSettings();
|
||||
SettingHandles::rearViewZoomLevel.set(HEAD);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_bodyZoomIconRect.contains(x, y)) {
|
||||
_zoomLevel = BODY;
|
||||
Application::getInstance()->bumpSettings();
|
||||
SettingHandles::rearViewZoomLevel.set(BODY);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -116,12 +94,6 @@ bool RearMirrorTools::mousePressEvent(int x, int y) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void RearMirrorTools::saveSettings(QSettings* settings) {
|
||||
settings->beginGroup(SETTINGS_GROUP_NAME);
|
||||
settings->setValue(ZOOM_LEVEL_SETTINGS, _zoomLevel);
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, GLuint textureId, bool selected) {
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
|
|
|
@ -15,21 +15,27 @@
|
|||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QGLWidget>
|
||||
#include <QSettings>
|
||||
|
||||
#include <Settings.h>
|
||||
|
||||
enum ZoomLevel {
|
||||
HEAD,
|
||||
BODY
|
||||
HEAD = 0,
|
||||
BODY = 1
|
||||
};
|
||||
|
||||
namespace SettingHandles {
|
||||
const char SETTINGS_GROUP_NAME[] = "Rear View Tools";
|
||||
const char ZOOM_LEVEL_SETTINGS[] = "ZoomLevel";
|
||||
const SettingHandle<int> rearViewZoomLevel(QStringList() << SETTINGS_GROUP_NAME << ZOOM_LEVEL_SETTINGS,
|
||||
ZoomLevel::HEAD);
|
||||
}
|
||||
|
||||
class RearMirrorTools : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
RearMirrorTools(QGLWidget* parent, QRect& bounds, QSettings* settings);
|
||||
RearMirrorTools(QGLWidget* parent, QRect& bounds);
|
||||
void render(bool fullScreen);
|
||||
bool mousePressEvent(int x, int y);
|
||||
ZoomLevel getZoomLevel() { return _zoomLevel; }
|
||||
void saveSettings(QSettings* settings);
|
||||
|
||||
signals:
|
||||
void closeView();
|
||||
|
@ -44,7 +50,6 @@ private:
|
|||
GLuint _resetTextureId;
|
||||
GLuint _zoomBodyTextureId;
|
||||
GLuint _zoomHeadTextureId;
|
||||
ZoomLevel _zoomLevel;
|
||||
|
||||
QRect _closeIconRect;
|
||||
QRect _resetIconRect;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "ui_scriptEditorWidget.h"
|
||||
#include "ScriptEditorWidget.h"
|
||||
#include "ScriptEditorWindow.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QFileDialog>
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
#include "FlowLayout.h"
|
||||
#include "JSConsole.h"
|
||||
|
||||
ScriptEditorWindow::ScriptEditorWindow() :
|
||||
ScriptEditorWindow::ScriptEditorWindow(QWidget* parent) :
|
||||
QWidget(parent),
|
||||
_ScriptEditorWindowUI(new Ui::ScriptEditorWindow),
|
||||
_loadMenu(new QMenu),
|
||||
_saveMenu(new QMenu)
|
||||
|
|
|
@ -22,7 +22,7 @@ class ScriptEditorWindow : public QWidget {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScriptEditorWindow();
|
||||
ScriptEditorWindow(QWidget* parent = nullptr);
|
||||
~ScriptEditorWindow();
|
||||
|
||||
void terminateCurrentTab();
|
||||
|
|
|
@ -10,13 +10,17 @@
|
|||
//
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QImage>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <Application.h>
|
||||
#include <FileUtils.h>
|
||||
|
||||
#include "Snapshot.h"
|
||||
#include "Menu.h"
|
||||
|
||||
// filename format: hifi-snap-by-%username%-on-%date%_%time%_@-%location%.jpg
|
||||
// %1 <= username, %2 <= date and time, %3 <= current location
|
||||
|
@ -86,7 +90,7 @@ QFile* Snapshot::savedFileForSnapshot(bool isTemporary) {
|
|||
auto glCanvas = DependencyManager::get<GLCanvas>();
|
||||
QImage shot = glCanvas->grabFrameBuffer();
|
||||
|
||||
Avatar* avatar = Application::getInstance()->getAvatar();
|
||||
Avatar* avatar = qApp->getAvatar();
|
||||
|
||||
glm::vec3 location = avatar->getPosition();
|
||||
glm::quat orientation = avatar->getHead()->getOrientation();
|
||||
|
@ -118,7 +122,7 @@ QFile* Snapshot::savedFileForSnapshot(bool isTemporary) {
|
|||
const int IMAGE_QUALITY = 100;
|
||||
|
||||
if (!isTemporary) {
|
||||
QString snapshotFullPath = Menu::getInstance()->getSnapshotsLocation();
|
||||
QString snapshotFullPath = SettingHandles::snapshotsLocation.get();
|
||||
|
||||
if (!snapshotFullPath.endsWith(QDir::separator())) {
|
||||
snapshotFullPath.append(QDir::separator());
|
||||
|
|
|
@ -12,15 +12,19 @@
|
|||
#ifndef hifi_Snapshot_h
|
||||
#define hifi_Snapshot_h
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <qimage.h>
|
||||
#include <qfile.h>
|
||||
#include <qtemporaryfile.h>
|
||||
#include <QGLWidget>
|
||||
#include <qstring.h>
|
||||
#include <QString>
|
||||
|
||||
#include "avatar/Avatar.h"
|
||||
#include <Settings.h>
|
||||
|
||||
class QFile;
|
||||
class QTemporaryFile;
|
||||
|
||||
namespace SettingHandles {
|
||||
const SettingHandle<QString> snapshotsLocation("snapshotsLocation",
|
||||
QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
|
||||
}
|
||||
|
||||
class SnapshotMetaData {
|
||||
public:
|
||||
|
@ -41,7 +45,6 @@ private:
|
|||
};
|
||||
|
||||
class Snapshot {
|
||||
|
||||
public:
|
||||
static QString saveSnapshot();
|
||||
static QTemporaryFile* saveTempSnapshot();
|
||||
|
|
39
interface/src/ui/StandAloneJSConsole.cpp
Normal file
39
interface/src/ui/StandAloneJSConsole.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// StandAloneJSConsole.cpp
|
||||
//
|
||||
//
|
||||
// Created by Clement on 1/17/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QDialog>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <Application.h>
|
||||
#include <MainWindow.h>
|
||||
|
||||
#include "StandAloneJSConsole.h"
|
||||
|
||||
void StandAloneJSConsole::toggleConsole() {
|
||||
QMainWindow* mainWindow = qApp->getWindow();
|
||||
if (!_jsConsole) {
|
||||
QDialog* dialog = new QDialog(mainWindow, Qt::WindowStaysOnTopHint);
|
||||
QVBoxLayout* layout = new QVBoxLayout(dialog);
|
||||
dialog->setLayout(layout);
|
||||
|
||||
dialog->resize(QSize(CONSOLE_WIDTH, CONSOLE_HEIGHT));
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
layout->addWidget(new JSConsole(dialog));
|
||||
dialog->setWindowOpacity(CONSOLE_WINDOW_OPACITY);
|
||||
dialog->setWindowTitle(CONSOLE_TITLE);
|
||||
|
||||
_jsConsole = dialog;
|
||||
}
|
||||
_jsConsole->setVisible(!_jsConsole->isVisible());
|
||||
}
|
||||
|
35
interface/src/ui/StandAloneJSConsole.h
Normal file
35
interface/src/ui/StandAloneJSConsole.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// StandAloneJSConsole.h
|
||||
//
|
||||
//
|
||||
// Created by Clement on 1/17/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_StandAloneJSConsole_h
|
||||
#define hifi_StandAloneJSConsole_h
|
||||
|
||||
#include <QPointer>
|
||||
#include <DependencyManager.h>
|
||||
|
||||
#include "JSConsole.h"
|
||||
|
||||
class QDialog;
|
||||
|
||||
class StandAloneJSConsole : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public slots:
|
||||
void toggleConsole();
|
||||
|
||||
private:
|
||||
StandAloneJSConsole() {}
|
||||
|
||||
QPointer<QDialog> _jsConsole;
|
||||
};
|
||||
|
||||
#endif // hifi_StandAloneJSConsole_h
|
|
@ -18,6 +18,10 @@
|
|||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/vector_angle.hpp>
|
||||
|
||||
#include <Application.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <GLCanvas.h>
|
||||
#include <LODManager.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include "Stats.h"
|
||||
|
@ -621,7 +625,7 @@ void Stats::display(
|
|||
// LOD Details
|
||||
if (_expanded) {
|
||||
octreeStats.str("");
|
||||
QString displayLODDetails = Menu::getInstance()->getLODFeedbackText();
|
||||
QString displayLODDetails = DependencyManager::get<LODManager>()->getLODFeedbackText();
|
||||
octreeStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed());
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);
|
||||
|
|
|
@ -22,88 +22,62 @@
|
|||
#include "ImageOverlay.h"
|
||||
|
||||
ImageOverlay::ImageOverlay() :
|
||||
_textureID(0),
|
||||
_imageURL(),
|
||||
_renderImage(false),
|
||||
_textureBound(false),
|
||||
_wantClipFromImage(false)
|
||||
{
|
||||
_isLoaded = false;
|
||||
}
|
||||
|
||||
ImageOverlay::ImageOverlay(const ImageOverlay* imageOverlay) :
|
||||
Overlay2D(imageOverlay),
|
||||
_texture(imageOverlay->_texture),
|
||||
_imageURL(imageOverlay->_imageURL),
|
||||
_textureImage(imageOverlay->_textureImage),
|
||||
_textureID(0),
|
||||
_fromImage(),
|
||||
_fromImage(imageOverlay->_fromImage),
|
||||
_renderImage(imageOverlay->_renderImage),
|
||||
_textureBound(false),
|
||||
_wantClipFromImage(false)
|
||||
_wantClipFromImage(imageOverlay->_wantClipFromImage)
|
||||
{
|
||||
}
|
||||
|
||||
ImageOverlay::~ImageOverlay() {
|
||||
if (_parent && _textureID) {
|
||||
// do we need to call this?
|
||||
//_parent->deleteTexture(_textureID);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: handle setting image multiple times, how do we manage releasing the bound texture?
|
||||
void ImageOverlay::setImageURL(const QUrl& url) {
|
||||
_imageURL = url;
|
||||
_isLoaded = false;
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url));
|
||||
connect(reply, &QNetworkReply::finished, this, &ImageOverlay::replyFinished);
|
||||
}
|
||||
|
||||
void ImageOverlay::replyFinished() {
|
||||
QNetworkReply* reply = static_cast<QNetworkReply*>(sender());
|
||||
|
||||
// replace our byte array with the downloaded data
|
||||
QByteArray rawData = reply->readAll();
|
||||
_textureImage.loadFromData(rawData);
|
||||
_renderImage = true;
|
||||
_isLoaded = true;
|
||||
reply->deleteLater();
|
||||
if (url.isEmpty()) {
|
||||
_isLoaded = true;
|
||||
_renderImage = false;
|
||||
_texture.clear();
|
||||
} else {
|
||||
_isLoaded = false;
|
||||
_renderImage = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ImageOverlay::render(RenderArgs* args) {
|
||||
if (!_visible || !_isLoaded) {
|
||||
return; // do nothing if we're not visible
|
||||
if (!_isLoaded && _renderImage) {
|
||||
_isLoaded = true;
|
||||
_texture = DependencyManager::get<TextureCache>()->getTexture(_imageURL);
|
||||
}
|
||||
if (_renderImage && !_textureBound) {
|
||||
_textureID = _parent->bindTexture(_textureImage);
|
||||
_textureBound = true;
|
||||
|
||||
// If we are not visible or loaded, return. If we are trying to render an
|
||||
// image but the texture hasn't loaded, return.
|
||||
if (!_visible || !_isLoaded || (_renderImage && !_texture->isLoaded())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_renderImage) {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, _textureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _texture->getID());
|
||||
}
|
||||
|
||||
const float MAX_COLOR = 255.0f;
|
||||
xColor color = getColor();
|
||||
float alpha = getAlpha();
|
||||
glm::vec4 quadColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
|
||||
|
||||
float imageWidth = _textureImage.width();
|
||||
float imageHeight = _textureImage.height();
|
||||
|
||||
QRect fromImage;
|
||||
if (_wantClipFromImage) {
|
||||
fromImage = _fromImage;
|
||||
} else {
|
||||
fromImage.setX(0);
|
||||
fromImage.setY(0);
|
||||
fromImage.setWidth(imageWidth);
|
||||
fromImage.setHeight(imageHeight);
|
||||
}
|
||||
float x = fromImage.x() / imageWidth;
|
||||
float y = fromImage.y() / imageHeight;
|
||||
float w = fromImage.width() / imageWidth; // ?? is this what we want? not sure
|
||||
float h = fromImage.height() / imageHeight;
|
||||
|
||||
int left = _bounds.left();
|
||||
int right = _bounds.right() + 1;
|
||||
int top = _bounds.top();
|
||||
|
@ -111,11 +85,36 @@ void ImageOverlay::render(RenderArgs* args) {
|
|||
|
||||
glm::vec2 topLeft(left, top);
|
||||
glm::vec2 bottomRight(right, bottom);
|
||||
glm::vec2 texCoordTopLeft(x, 1.0f - y);
|
||||
glm::vec2 texCoordBottomRight(x + w, 1.0f - (y + h));
|
||||
|
||||
// if for some reason our image is not over 0 width or height, don't attempt to render the image
|
||||
if (_renderImage && imageWidth > 0 && imageHeight > 0) {
|
||||
float imageWidth = _texture->getWidth();
|
||||
float imageHeight = _texture->getHeight();
|
||||
|
||||
QRect fromImage;
|
||||
if (_wantClipFromImage) {
|
||||
float scaleX = imageWidth / _texture->getOriginalWidth();
|
||||
float scaleY = imageHeight / _texture->getOriginalHeight();
|
||||
|
||||
fromImage.setX(scaleX * _fromImage.x());
|
||||
fromImage.setY(scaleY * _fromImage.y());
|
||||
fromImage.setWidth(scaleX * _fromImage.width());
|
||||
fromImage.setHeight(scaleY * _fromImage.height());
|
||||
} else {
|
||||
fromImage.setX(0);
|
||||
fromImage.setY(0);
|
||||
fromImage.setWidth(imageWidth);
|
||||
fromImage.setHeight(imageHeight);
|
||||
}
|
||||
|
||||
float x = fromImage.x() / imageWidth;
|
||||
float y = fromImage.y() / imageHeight;
|
||||
float w = fromImage.width() / imageWidth; // ?? is this what we want? not sure
|
||||
float h = fromImage.height() / imageHeight;
|
||||
|
||||
glm::vec2 texCoordTopLeft(x, y);
|
||||
glm::vec2 texCoordBottomRight(x + w, y + h);
|
||||
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor);
|
||||
} else {
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, quadColor);
|
||||
|
@ -154,7 +153,7 @@ void ImageOverlay::setProperties(const QScriptValue& properties) {
|
|||
subImageRect.setHeight(oldSubImageRect.height());
|
||||
}
|
||||
setClipFromSource(subImageRect);
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue imageURL = properties.property("imageURL");
|
||||
if (imageURL.isValid()) {
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <NetworkAccessManager.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <TextureCache.h>
|
||||
|
||||
#include "Overlay.h"
|
||||
#include "Overlay2D.h"
|
||||
|
@ -49,18 +50,14 @@ public:
|
|||
|
||||
virtual ImageOverlay* createClone() const;
|
||||
|
||||
private slots:
|
||||
void replyFinished(); // we actually want to hide this...
|
||||
|
||||
private:
|
||||
|
||||
QUrl _imageURL;
|
||||
QImage _textureImage;
|
||||
|
||||
GLuint _textureID;
|
||||
NetworkTexturePointer _texture;
|
||||
QRect _fromImage; // where from in the image to sample
|
||||
bool _renderImage; // is there an image associated with this overlay, or is it just a colored rectangle
|
||||
bool _textureBound; // has the texture been bound
|
||||
bool _wantClipFromImage;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QScriptValueIterator>
|
||||
|
||||
#include <limits>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <Application.h>
|
||||
#include <devices/OculusManager.h>
|
||||
#include <Menu.h>
|
||||
#include <QScriptValueIterator>
|
||||
#include <LODManager.h>
|
||||
|
||||
#include "BillboardOverlay.h"
|
||||
#include "Circle3DOverlay.h"
|
||||
|
@ -83,10 +85,13 @@ void Overlays::update(float deltatime) {
|
|||
|
||||
void Overlays::renderHUD() {
|
||||
QReadLocker lock(&_lock);
|
||||
|
||||
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(),
|
||||
Menu::getInstance()->getOctreeSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(),
|
||||
RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
lodManager->getOctreeSizeScale(),
|
||||
lodManager->getBoundaryLevelAdjust(),
|
||||
RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
foreach(Overlay* thisOverlay, _overlaysHUD) {
|
||||
if (thisOverlay->is3D()) {
|
||||
|
@ -116,9 +121,12 @@ void Overlays::renderWorld(bool drawFront, RenderArgs::RenderMode renderMode, Re
|
|||
glm::vec3 axis(0.0f, 1.0f, 0.0f);
|
||||
float myAvatarScale = 1.0f;
|
||||
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(),
|
||||
Menu::getInstance()->getOctreeSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(),
|
||||
renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
lodManager->getOctreeSizeScale(),
|
||||
lodManager->getBoundaryLevelAdjust(),
|
||||
renderMode, renderSide,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
|
||||
foreach(Overlay* thisOverlay, _overlaysWorld) {
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
<property name="font">
|
||||
<font>
|
||||
<family>Helvetica,Arial,sans-serif</family>
|
||||
<pointsize>-1</pointsize>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
|
@ -78,7 +78,7 @@
|
|||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: #0e7077;
|
||||
font: bold 16px;
|
||||
font: bold 16pt;
|
||||
</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
|
@ -192,7 +192,7 @@ font: bold 16px;
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">font: 14px; color: #5f5f5f; margin: 2px;</string>
|
||||
<string notr="true">font: 14pt; color: #5f5f5f; margin: 2px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>There are no scripts running.</string>
|
||||
|
@ -245,8 +245,8 @@ font: bold 16px;
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>334</width>
|
||||
<height>20</height>
|
||||
<width>328</width>
|
||||
<height>18</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -259,7 +259,7 @@ font: bold 16px;
|
|||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">font-size: 14px;</string>
|
||||
<string notr="true">font-size: 14pt;</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
|
@ -301,7 +301,7 @@ font: bold 16px;
|
|||
<item>
|
||||
<widget class="QLabel" name="tipLabel">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">font: 14px; color: #5f5f5f; margin: 2px;</string>
|
||||
<string notr="true">font: 14pt; color: #5f5f5f; margin: 2px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Tip</string>
|
||||
|
@ -370,7 +370,7 @@ font: bold 16px;
|
|||
<widget class="QLabel" name="label">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: #0e7077;
|
||||
font: bold 16px;</string>
|
||||
font: bold 16pt;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load Scripts</string>
|
||||
|
|
|
@ -11,11 +11,27 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <Settings.h>
|
||||
|
||||
#include "InboundAudioStream.h"
|
||||
#include "PacketHeaders.h"
|
||||
|
||||
const int STARVE_HISTORY_CAPACITY = 50;
|
||||
|
||||
namespace SettingHandles {
|
||||
const SettingHandle<bool> dynamicJitterBuffers("dynamicJitterBuffers", DEFAULT_DYNAMIC_JITTER_BUFFERS);
|
||||
const SettingHandle<int> maxFramesOverDesired("maxFramesOverDesired", DEFAULT_MAX_FRAMES_OVER_DESIRED);
|
||||
const SettingHandle<int> staticDesiredJitterBufferFrames("staticDesiredJitterBufferFrames",
|
||||
DEFAULT_STATIC_DESIRED_JITTER_BUFFER_FRAMES);
|
||||
const SettingHandle<bool> useStDevForJitterCalc("useStDevForJitterCalc", DEFAULT_USE_STDEV_FOR_JITTER_CALC);
|
||||
const SettingHandle<int> windowStarveThreshold("windowStarveThreshold", DEFAULT_WINDOW_STARVE_THRESHOLD);
|
||||
const SettingHandle<int> windowSecondsForDesiredCalcOnTooManyStarves("windowSecondsForDesiredCalcOnTooManyStarves",
|
||||
DEFAULT_WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES);
|
||||
const SettingHandle<int> windowSecondsForDesiredReduction("windowSecondsForDesiredReduction",
|
||||
DEFAULT_WINDOW_SECONDS_FOR_DESIRED_REDUCTION);
|
||||
const SettingHandle<bool> repetitionWithFade("repetitionWithFade", DEFAULT_REPETITION_WITH_FADE);
|
||||
}
|
||||
|
||||
InboundAudioStream::InboundAudioStream(int numFrameSamples, int numFramesCapacity, const Settings& settings) :
|
||||
_ringBuffer(numFrameSamples, false, numFramesCapacity),
|
||||
_lastPopSucceeded(false),
|
||||
|
@ -500,3 +516,28 @@ float calculateRepeatedFrameFadeFactor(int indexOfRepeat) {
|
|||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void InboundAudioStream::loadSettings() {
|
||||
setDynamicJitterBuffers(SettingHandles::dynamicJitterBuffers.get());
|
||||
setMaxFramesOverDesired(SettingHandles::maxFramesOverDesired.get());
|
||||
setStaticDesiredJitterBufferFrames(SettingHandles::staticDesiredJitterBufferFrames.get());
|
||||
setUseStDevForJitterCalc(SettingHandles::useStDevForJitterCalc.get());
|
||||
setWindowStarveThreshold(SettingHandles::windowStarveThreshold.get());
|
||||
setWindowSecondsForDesiredCalcOnTooManyStarves(SettingHandles::windowSecondsForDesiredCalcOnTooManyStarves.get());
|
||||
setWindowSecondsForDesiredReduction(SettingHandles::windowSecondsForDesiredReduction.get());
|
||||
setRepetitionWithFade(SettingHandles::repetitionWithFade.get());
|
||||
}
|
||||
|
||||
void InboundAudioStream::saveSettings() {
|
||||
SettingHandles::dynamicJitterBuffers.set(getDynamicJitterBuffers());
|
||||
SettingHandles::maxFramesOverDesired.set(getMaxFramesOverDesired());
|
||||
SettingHandles::staticDesiredJitterBufferFrames.set(getDesiredJitterBufferFrames());
|
||||
SettingHandles::useStDevForJitterCalc.set(getUseStDevForJitterCalc());
|
||||
SettingHandles::windowStarveThreshold.set(getWindowStarveThreshold());
|
||||
SettingHandles::windowSecondsForDesiredCalcOnTooManyStarves.set(getWindowSecondsForDesiredCalcOnTooManyStarves());
|
||||
SettingHandles::windowSecondsForDesiredReduction.set(getWindowSecondsForDesiredReduction());
|
||||
SettingHandles::repetitionWithFade.set(getRepetitionWithFade());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -126,6 +126,8 @@ public:
|
|||
void setWindowSecondsForDesiredReduction(int windowSecondsForDesiredReduction);
|
||||
void setRepetitionWithFade(bool repetitionWithFade) { _repetitionWithFade = repetitionWithFade; }
|
||||
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
|
||||
virtual AudioStreamStats getAudioStreamStats() const;
|
||||
|
||||
|
@ -138,7 +140,15 @@ public:
|
|||
|
||||
/// returns the desired number of jitter buffer frames using Freddy's method
|
||||
int getCalculatedJitterBufferFramesUsingMaxGap() const { return _calculatedJitterBufferFramesUsingMaxGap; }
|
||||
|
||||
|
||||
int getWindowSecondsForDesiredReduction() const {
|
||||
return _timeGapStatsForDesiredReduction.getWindowIntervals(); }
|
||||
int getWindowSecondsForDesiredCalcOnTooManyStarves() const {
|
||||
return _timeGapStatsForDesiredCalcOnTooManyStarves.getWindowIntervals(); }
|
||||
bool getDynamicJitterBuffers() const { return _dynamicJitterBuffers; }
|
||||
bool getRepetitionWithFade() const { return _repetitionWithFade;}
|
||||
int getWindowStarveThreshold() const { return _starveThreshold;}
|
||||
bool getUseStDevForJitterCalc() const { return _useStDevForJitterCalc; }
|
||||
int getDesiredJitterBufferFrames() const { return _desiredJitterBufferFrames; }
|
||||
int getMaxFramesOverDesired() const { return _maxFramesOverDesired; }
|
||||
int getNumFrameSamples() const { return _ringBuffer.getNumFrameSamples(); }
|
||||
|
@ -204,7 +214,7 @@ protected:
|
|||
|
||||
bool _lastPopSucceeded;
|
||||
AudioRingBuffer::ConstIterator _lastPopOutput;
|
||||
|
||||
|
||||
bool _dynamicJitterBuffers; // if false, _desiredJitterBufferFrames is locked at 1 (old behavior)
|
||||
int _staticDesiredJitterBufferFrames;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ HandData::HandData(AvatarData* owningAvatar) :
|
|||
}
|
||||
|
||||
glm::vec3 HandData::worldToLocalVector(const glm::vec3& worldVector) const {
|
||||
return glm::inverse(getBaseOrientation()) * worldVector;
|
||||
return glm::inverse(getBaseOrientation()) * worldVector / getBaseScale();
|
||||
}
|
||||
|
||||
PalmData& HandData::addNewPalm() {
|
||||
|
@ -108,15 +108,19 @@ glm::quat HandData::getBaseOrientation() const {
|
|||
glm::vec3 HandData::getBasePosition() const {
|
||||
return _owningAvatarData->getPosition();
|
||||
}
|
||||
|
||||
float HandData::getBaseScale() const {
|
||||
return _owningAvatarData->getTargetScale();
|
||||
}
|
||||
|
||||
glm::vec3 PalmData::getFingerDirection() const {
|
||||
const glm::vec3 LOCAL_FINGER_DIRECTION(0.0f, 0.0f, 1.0f);
|
||||
return _owningHandData->localToWorldDirection(_rawRotation * LOCAL_FINGER_DIRECTION);
|
||||
return glm::normalize(_owningHandData->localToWorldDirection(_rawRotation * LOCAL_FINGER_DIRECTION));
|
||||
}
|
||||
|
||||
glm::vec3 PalmData::getNormal() const {
|
||||
const glm::vec3 LOCAL_PALM_DIRECTION(0.0f, -1.0f, 0.0f);
|
||||
return _owningHandData->localToWorldDirection(_rawRotation * LOCAL_PALM_DIRECTION);
|
||||
return glm::normalize(_owningHandData->localToWorldDirection(_rawRotation * LOCAL_PALM_DIRECTION));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -36,11 +36,11 @@ public:
|
|||
|
||||
// position conversion
|
||||
glm::vec3 localToWorldPosition(const glm::vec3& localPosition) {
|
||||
return getBasePosition() + getBaseOrientation() * localPosition;
|
||||
return getBasePosition() + getBaseOrientation() * localPosition * getBaseScale();
|
||||
}
|
||||
|
||||
glm::vec3 localToWorldDirection(const glm::vec3& localVector) {
|
||||
return getBaseOrientation() * localVector;
|
||||
return getBaseOrientation() * localVector * getBaseScale();
|
||||
}
|
||||
|
||||
glm::vec3 worldToLocalVector(const glm::vec3& worldVector) const;
|
||||
|
@ -71,6 +71,7 @@ protected:
|
|||
|
||||
glm::quat getBaseOrientation() const;
|
||||
glm::vec3 getBasePosition() const;
|
||||
float getBaseScale() const;
|
||||
|
||||
private:
|
||||
// privatize copy ctor and assignment operator so copies of this object cannot be made
|
||||
|
|
|
@ -101,3 +101,12 @@ void BoxEntityItem::computeShapeInfo(ShapeInfo& info) const {
|
|||
info.setBox(halfExtents);
|
||||
}
|
||||
|
||||
void BoxEntityItem::debugDump() const {
|
||||
quint64 now = usecTimestampNow();
|
||||
qDebug() << " BOX EntityItem id:" << getEntityItemID() << "---------------------------------------------";
|
||||
qDebug() << " color:" << _color[0] << "," << _color[1] << "," << _color[2];
|
||||
qDebug() << " position:" << debugTreeVector(_position);
|
||||
qDebug() << " dimensions:" << debugTreeVector(_dimensions);
|
||||
qDebug() << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@ public:
|
|||
|
||||
void computeShapeInfo(ShapeInfo& info) const;
|
||||
|
||||
virtual void debugDump() const;
|
||||
|
||||
protected:
|
||||
rgbColor _color;
|
||||
};
|
||||
|
|
|
@ -1,302 +0,0 @@
|
|||
//
|
||||
// EntityCollisionSystem.cpp
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 9/23/14.
|
||||
// Copyright 2013-2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
#include <AbstractAudioInterface.h>
|
||||
#include <AvatarData.h>
|
||||
#include <CollisionInfo.h>
|
||||
#include <HeadData.h>
|
||||
#include <HandData.h>
|
||||
#include <PerfStat.h>
|
||||
#include <SphereShape.h>
|
||||
|
||||
#include "EntityCollisionSystem.h"
|
||||
#include "EntityEditPacketSender.h"
|
||||
#include "EntityItem.h"
|
||||
#include "EntityTreeElement.h"
|
||||
#include "EntityTree.h"
|
||||
|
||||
const int MAX_COLLISIONS_PER_Entity = 16;
|
||||
|
||||
EntityCollisionSystem::EntityCollisionSystem()
|
||||
: SimpleEntitySimulation(),
|
||||
_packetSender(NULL),
|
||||
_avatars(NULL),
|
||||
_collisions(MAX_COLLISIONS_PER_Entity) {
|
||||
}
|
||||
|
||||
void EntityCollisionSystem::init(EntityEditPacketSender* packetSender,
|
||||
EntityTree* entities, AvatarHashMap* avatars) {
|
||||
assert(entities);
|
||||
setEntityTree(entities);
|
||||
_packetSender = packetSender;
|
||||
_avatars = avatars;
|
||||
}
|
||||
|
||||
EntityCollisionSystem::~EntityCollisionSystem() {
|
||||
}
|
||||
|
||||
void EntityCollisionSystem::updateCollisions() {
|
||||
PerformanceTimer perfTimer("collisions");
|
||||
assert(_entityTree);
|
||||
// update all Entities
|
||||
if (_entityTree->tryLockForWrite()) {
|
||||
foreach (EntityItem* entity, _movingEntities) {
|
||||
checkEntity(entity);
|
||||
}
|
||||
_entityTree->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EntityCollisionSystem::checkEntity(EntityItem* entity) {
|
||||
updateCollisionWithEntities(entity);
|
||||
updateCollisionWithAvatars(entity);
|
||||
}
|
||||
|
||||
void EntityCollisionSystem::emitGlobalEntityCollisionWithEntity(EntityItem* entityA,
|
||||
EntityItem* entityB, const Collision& collision) {
|
||||
|
||||
EntityItemID idA = entityA->getEntityItemID();
|
||||
EntityItemID idB = entityB->getEntityItemID();
|
||||
emit entityCollisionWithEntity(idA, idB, collision);
|
||||
}
|
||||
|
||||
void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) {
|
||||
|
||||
if (entityA->getIgnoreForCollisions()) {
|
||||
return; // bail early if this entity is to be ignored...
|
||||
}
|
||||
|
||||
// don't collide entities with unknown IDs,
|
||||
if (!entityA->isKnownID()) {
|
||||
return;
|
||||
}
|
||||
|
||||
glm::vec3 penetration;
|
||||
EntityItem* entityB = NULL;
|
||||
|
||||
const int MAX_COLLISIONS_PER_ENTITY = 32;
|
||||
CollisionList collisions(MAX_COLLISIONS_PER_ENTITY);
|
||||
bool shapeCollisionsAccurate = false;
|
||||
|
||||
bool shapeCollisions = _entityTree->findShapeCollisions(&entityA->getCollisionShapeInMeters(),
|
||||
collisions, Octree::NoLock, &shapeCollisionsAccurate);
|
||||
|
||||
if (shapeCollisions) {
|
||||
for(int i = 0; i < collisions.size(); i++) {
|
||||
|
||||
CollisionInfo* collision = collisions[i];
|
||||
penetration = collision->_penetration;
|
||||
entityB = static_cast<EntityItem*>(collision->_extraData);
|
||||
|
||||
// The collision _extraData should be a valid entity, but if for some reason
|
||||
// it's NULL then continue with a warning.
|
||||
if (!entityB) {
|
||||
qDebug() << "UNEXPECTED - we have a collision with missing _extraData. Something went wrong down below!";
|
||||
continue; // skip this loop pass if the entity is NULL
|
||||
}
|
||||
|
||||
// don't collide entities with unknown IDs,
|
||||
if (!entityB->isKnownID()) {
|
||||
continue; // skip this loop pass if the entity has an unknown ID
|
||||
}
|
||||
|
||||
// NOTE: 'penetration' is the depth that 'entityA' overlaps 'entityB'. It points from A into B.
|
||||
glm::vec3 penetrationInTreeUnits = penetration / (float)(TREE_SCALE);
|
||||
|
||||
// Even if the Entities overlap... when the Entities are already moving appart
|
||||
// we don't want to count this as a collision.
|
||||
glm::vec3 relativeVelocity = entityA->getVelocity() - entityB->getVelocity();
|
||||
|
||||
bool fullyEnclosedCollision = glm::length(penetrationInTreeUnits) > entityA->getLargestDimension();
|
||||
|
||||
bool wantToMoveA = entityA->getCollisionsWillMove();
|
||||
bool wantToMoveB = entityB->getCollisionsWillMove();
|
||||
bool movingTowardEachOther = glm::dot(relativeVelocity, penetrationInTreeUnits) > 0.0f;
|
||||
|
||||
// only do collisions if the entities are moving toward each other and one or the other
|
||||
// of the entities are movable from collisions
|
||||
bool doCollisions = !fullyEnclosedCollision && movingTowardEachOther && (wantToMoveA || wantToMoveB);
|
||||
|
||||
if (doCollisions) {
|
||||
|
||||
quint64 now = usecTimestampNow();
|
||||
|
||||
glm::vec3 axis = glm::normalize(penetration);
|
||||
glm::vec3 axialVelocity = glm::dot(relativeVelocity, axis) * axis;
|
||||
|
||||
float massA = entityA->computeMass();
|
||||
float massB = entityB->computeMass();
|
||||
float totalMass = massA + massB;
|
||||
float massRatioA = (2.0f * massB / totalMass);
|
||||
float massRatioB = (2.0f * massA / totalMass);
|
||||
|
||||
// in the event that one of our entities is non-moving, then fix up these ratios
|
||||
if (wantToMoveA && !wantToMoveB) {
|
||||
massRatioA = 2.0f;
|
||||
massRatioB = 0.0f;
|
||||
}
|
||||
|
||||
if (!wantToMoveA && wantToMoveB) {
|
||||
massRatioA = 0.0f;
|
||||
massRatioB = 2.0f;
|
||||
}
|
||||
|
||||
// unless the entity is configured to not be moved by collision, calculate it's new position
|
||||
// and velocity and apply it
|
||||
if (wantToMoveA) {
|
||||
// handle Entity A
|
||||
glm::vec3 newVelocityA = entityA->getVelocity() - axialVelocity * massRatioA;
|
||||
glm::vec3 newPositionA = entityA->getPosition() - 0.5f * penetrationInTreeUnits;
|
||||
|
||||
EntityItemProperties propertiesA = entityA->getProperties();
|
||||
EntityItemID idA(entityA->getID());
|
||||
propertiesA.setVelocity(newVelocityA * (float)TREE_SCALE);
|
||||
propertiesA.setPosition(newPositionA * (float)TREE_SCALE);
|
||||
propertiesA.setLastEdited(now);
|
||||
|
||||
// NOTE: EntityTree::updateEntity() will cause the entity to get sorted correctly in the EntitySimulation,
|
||||
// thereby waking up static non-moving entities.
|
||||
_entityTree->updateEntity(entityA, propertiesA);
|
||||
_packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idA, propertiesA);
|
||||
}
|
||||
|
||||
// unless the entity is configured to not be moved by collision, calculate it's new position
|
||||
// and velocity and apply it
|
||||
if (wantToMoveB) {
|
||||
glm::vec3 newVelocityB = entityB->getVelocity() + axialVelocity * massRatioB;
|
||||
glm::vec3 newPositionB = entityB->getPosition() + 0.5f * penetrationInTreeUnits;
|
||||
|
||||
EntityItemProperties propertiesB = entityB->getProperties();
|
||||
|
||||
EntityItemID idB(entityB->getID());
|
||||
propertiesB.setVelocity(newVelocityB * (float)TREE_SCALE);
|
||||
propertiesB.setPosition(newPositionB * (float)TREE_SCALE);
|
||||
propertiesB.setLastEdited(now);
|
||||
|
||||
// NOTE: EntityTree::updateEntity() will cause the entity to get sorted correctly in the EntitySimulation,
|
||||
// thereby waking up static non-moving entities.
|
||||
_entityTree->updateEntity(entityB, propertiesB);
|
||||
_packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, idB, propertiesB);
|
||||
}
|
||||
|
||||
// NOTE: Do this after updating the entities so that the callback can delete the entities if they want to
|
||||
Collision collision;
|
||||
collision.penetration = penetration;
|
||||
collision.contactPoint = (0.5f * (float)TREE_SCALE) * (entityA->getPosition() + entityB->getPosition());
|
||||
emitGlobalEntityCollisionWithEntity(entityA, entityB, collision);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityCollisionSystem::updateCollisionWithAvatars(EntityItem* entity) {
|
||||
|
||||
// Entities that are in hand, don't collide with avatars
|
||||
if (!_avatars) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity->getIgnoreForCollisions() || !entity->getCollisionsWillMove()) {
|
||||
return; // bail early if this entity is to be ignored or wont move
|
||||
}
|
||||
|
||||
glm::vec3 center = entity->getPosition() * (float)(TREE_SCALE);
|
||||
float radius = entity->getRadius() * (float)(TREE_SCALE);
|
||||
const float ELASTICITY = 0.9f;
|
||||
const float DAMPING = 0.1f;
|
||||
glm::vec3 penetration;
|
||||
|
||||
_collisions.clear();
|
||||
foreach (const AvatarSharedPointer& avatarPointer, _avatars->getAvatarHash()) {
|
||||
AvatarData* avatar = avatarPointer.data();
|
||||
|
||||
float totalRadius = avatar->getBoundingRadius() + radius;
|
||||
glm::vec3 relativePosition = center - avatar->getPosition();
|
||||
if (glm::dot(relativePosition, relativePosition) > (totalRadius * totalRadius)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (avatar->findSphereCollisions(center, radius, _collisions)) {
|
||||
int numCollisions = _collisions.size();
|
||||
for (int i = 0; i < numCollisions; ++i) {
|
||||
CollisionInfo* collision = _collisions.getCollision(i);
|
||||
collision->_damping = DAMPING;
|
||||
collision->_elasticity = ELASTICITY;
|
||||
|
||||
collision->_addedVelocity /= (float)(TREE_SCALE);
|
||||
glm::vec3 relativeVelocity = collision->_addedVelocity - entity->getVelocity();
|
||||
|
||||
if (glm::dot(relativeVelocity, collision->_penetration) <= 0.0f) {
|
||||
// only collide when Entity and collision point are moving toward each other
|
||||
// (doing this prevents some "collision snagging" when Entity penetrates the object)
|
||||
collision->_penetration /= (float)(TREE_SCALE);
|
||||
applyHardCollision(entity, *collision);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityCollisionSystem::applyHardCollision(EntityItem* entity, const CollisionInfo& collisionInfo) {
|
||||
|
||||
// don't collide entities with unknown IDs,
|
||||
if (!entity->isKnownID()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// HALTING_* params are determined using expected acceleration of gravity over some timescale.
|
||||
// This is a HACK for entities that bounce in a 1.0 gravitational field and should eventually be made more universal.
|
||||
const float HALTING_ENTITY_PERIOD = 0.0167f; // ~1/60th of a second
|
||||
const float HALTING_ENTITY_SPEED = 9.8 * HALTING_ENTITY_PERIOD / (float)(TREE_SCALE);
|
||||
|
||||
//
|
||||
// Update the entity in response to a hard collision. Position will be reset exactly
|
||||
// to outside the colliding surface. Velocity will be modified according to elasticity.
|
||||
//
|
||||
// if elasticity = 0.0, collision is inelastic (vel normal to collision is lost)
|
||||
// if elasticity = 1.0, collision is 100% elastic.
|
||||
//
|
||||
glm::vec3 position = entity->getPosition();
|
||||
glm::vec3 velocity = entity->getVelocity();
|
||||
|
||||
const float EPSILON = 0.0f;
|
||||
glm::vec3 relativeVelocity = collisionInfo._addedVelocity - velocity;
|
||||
float velocityDotPenetration = glm::dot(relativeVelocity, collisionInfo._penetration);
|
||||
if (velocityDotPenetration < EPSILON) {
|
||||
// entity is moving into collision surface
|
||||
//
|
||||
// TODO: do something smarter here by comparing the mass of the entity vs that of the other thing
|
||||
// (other's mass could be stored in the Collision Info). The smaller mass should surrender more
|
||||
// position offset and should slave more to the other's velocity in the static-friction case.
|
||||
position -= collisionInfo._penetration;
|
||||
|
||||
if (glm::length(relativeVelocity) < HALTING_ENTITY_SPEED) {
|
||||
// static friction kicks in and entities moves with colliding object
|
||||
velocity = collisionInfo._addedVelocity;
|
||||
} else {
|
||||
glm::vec3 direction = glm::normalize(collisionInfo._penetration);
|
||||
velocity += glm::dot(relativeVelocity, direction) * (1.0f + collisionInfo._elasticity) * direction; // dynamic reflection
|
||||
velocity += glm::clamp(collisionInfo._damping, 0.0f, 1.0f) * (relativeVelocity - glm::dot(relativeVelocity, direction) * direction); // dynamic friction
|
||||
}
|
||||
}
|
||||
|
||||
EntityItemProperties properties = entity->getProperties();
|
||||
EntityItemID entityItemID(entity->getID());
|
||||
|
||||
properties.setPosition(position * (float)TREE_SCALE);
|
||||
properties.setVelocity(velocity * (float)TREE_SCALE);
|
||||
properties.setLastEdited(usecTimestampNow());
|
||||
|
||||
_entityTree->updateEntity(entity, properties);
|
||||
_packetSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, entityItemID, properties);
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
//
|
||||
// EntityCollisionSystem.h
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 9/23/14.
|
||||
// Copyright 2013-2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_EntityCollisionSystem_h
|
||||
#define hifi_EntityCollisionSystem_h
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <QtScript/QScriptEngine>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <AvatarHashMap.h>
|
||||
#include <CollisionInfo.h>
|
||||
#include <OctreePacketData.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "EntityItem.h"
|
||||
#include "SimpleEntitySimulation.h"
|
||||
|
||||
class AbstractAudioInterface;
|
||||
class AvatarData;
|
||||
class EntityEditPacketSender;
|
||||
class EntityTree;
|
||||
|
||||
class EntityCollisionSystem : public QObject, public SimpleEntitySimulation {
|
||||
Q_OBJECT
|
||||
public:
|
||||
EntityCollisionSystem();
|
||||
|
||||
void init(EntityEditPacketSender* packetSender, EntityTree* entities, AvatarHashMap* _avatars = NULL);
|
||||
|
||||
~EntityCollisionSystem();
|
||||
|
||||
void updateCollisions();
|
||||
|
||||
void checkEntity(EntityItem* Entity);
|
||||
void updateCollisionWithEntities(EntityItem* Entity);
|
||||
void updateCollisionWithAvatars(EntityItem* Entity);
|
||||
void queueEntityPropertiesUpdate(EntityItem* Entity);
|
||||
|
||||
signals:
|
||||
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
||||
|
||||
private:
|
||||
void applyHardCollision(EntityItem* entity, const CollisionInfo& collisionInfo);
|
||||
|
||||
static bool updateOperation(OctreeElement* element, void* extraData);
|
||||
void emitGlobalEntityCollisionWithEntity(EntityItem* entityA, EntityItem* entityB, const Collision& penetration);
|
||||
|
||||
EntityEditPacketSender* _packetSender;
|
||||
AbstractAudioInterface* _audio;
|
||||
AvatarHashMap* _avatars;
|
||||
CollisionList _collisions;
|
||||
};
|
||||
|
||||
#endif // hifi_EntityCollisionSystem_h
|
|
@ -36,6 +36,11 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type, EntityItemI
|
|||
int sizeOut = 0;
|
||||
|
||||
if (EntityItemProperties::encodeEntityEditPacket(type, modelID, properties, &bufferOut[0], _maxPacketSize, sizeOut)) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "calling queueOctreeEditMessage()...";
|
||||
qDebug() << " id:" << modelID;
|
||||
qDebug() << " properties:" << properties;
|
||||
#endif
|
||||
queueOctreeEditMessage(type, bufferOut, sizeOut);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "EntityItem.h"
|
||||
#include "EntityTree.h"
|
||||
|
||||
bool EntityItem::_sendPhysicsUpdates = true;
|
||||
|
||||
void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) {
|
||||
_id = entityItemID.id;
|
||||
_creatorTokenID = entityItemID.creatorTokenID;
|
||||
|
@ -140,9 +142,17 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
ByteCountCoded<quint32> typeCoder = getType();
|
||||
QByteArray encodedType = typeCoder;
|
||||
|
||||
quint64 updateDelta = getLastSimulated() <= getLastEdited() ? 0 : getLastSimulated() - getLastEdited();
|
||||
// last updated (animations, non-physics changes)
|
||||
quint64 updateDelta = getLastUpdated() <= getLastEdited() ? 0 : getLastUpdated() - getLastEdited();
|
||||
ByteCountCoded<quint64> updateDeltaCoder = updateDelta;
|
||||
QByteArray encodedUpdateDelta = updateDeltaCoder;
|
||||
|
||||
// last simulated (velocity, angular velocity, physics changes)
|
||||
quint64 simulatedDelta = getLastSimulated() <= getLastEdited() ? 0 : getLastSimulated() - getLastEdited();
|
||||
ByteCountCoded<quint64> simulatedDeltaCoder = simulatedDelta;
|
||||
QByteArray encodedSimulatedDelta = simulatedDeltaCoder;
|
||||
|
||||
|
||||
EntityPropertyFlags propertyFlags(PROP_LAST_ITEM);
|
||||
EntityPropertyFlags requestedProperties = getEntityProperties(params);
|
||||
EntityPropertyFlags propertiesDidntFit = requestedProperties;
|
||||
|
@ -157,19 +167,19 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
|
||||
quint64 lastEdited = getLastEdited();
|
||||
|
||||
const bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
float editedAgo = getEditedAgo();
|
||||
QString agoAsString = formatSecondsElapsed(editedAgo);
|
||||
qDebug() << "Writing entity " << getEntityItemID() << " to buffer, lastEdited =" << lastEdited
|
||||
<< " ago=" << editedAgo << "seconds - " << agoAsString;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool successIDFits = false;
|
||||
bool successTypeFits = false;
|
||||
bool successCreatedFits = false;
|
||||
bool successLastEditedFits = false;
|
||||
bool successLastUpdatedFits = false;
|
||||
bool successLastSimulatedFits = false;
|
||||
bool successPropertyFlagsFits = false;
|
||||
int propertyFlagsOffset = 0;
|
||||
int oldPropertyFlagsLength = 0;
|
||||
|
@ -189,8 +199,11 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
if (successLastEditedFits) {
|
||||
successLastUpdatedFits = packetData->appendValue(encodedUpdateDelta);
|
||||
}
|
||||
|
||||
if (successLastUpdatedFits) {
|
||||
successLastSimulatedFits = packetData->appendValue(encodedSimulatedDelta);
|
||||
}
|
||||
|
||||
if (successLastSimulatedFits) {
|
||||
propertyFlagsOffset = packetData->getUncompressedByteOffset();
|
||||
encodedPropertyFlags = propertyFlags;
|
||||
oldPropertyFlagsLength = encodedPropertyFlags.length();
|
||||
|
@ -213,11 +226,6 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
|
||||
APPEND_ENTITY_PROPERTY(PROP_POSITION, appendPosition, getPosition());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, appendValue, getDimensions()); // NOTE: PROP_RADIUS obsolete
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " APPEND_ENTITY_PROPERTY() PROP_DIMENSIONS:" << getDimensions();
|
||||
}
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_ROTATION, appendValue, getRotation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DENSITY, appendValue, getDensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VELOCITY, appendValue, getVelocity());
|
||||
|
@ -296,7 +304,6 @@ int EntityItem::expectedBytes() {
|
|||
|
||||
|
||||
int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) {
|
||||
bool wantDebug = false;
|
||||
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_SPLIT_MTU) {
|
||||
|
||||
|
@ -361,17 +368,21 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
_created = createdFromBuffer;
|
||||
}
|
||||
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
quint64 lastEdited = getLastEdited();
|
||||
float editedAgo = getEditedAgo();
|
||||
QString agoAsString = formatSecondsElapsed(editedAgo);
|
||||
QString ageAsString = formatSecondsElapsed(getAge());
|
||||
qDebug() << "------------------------------------------";
|
||||
qDebug() << "Loading entity " << getEntityItemID() << " from buffer...";
|
||||
qDebug() << "------------------------------------------";
|
||||
debugDump();
|
||||
qDebug() << "------------------------------------------";
|
||||
qDebug() << " _created =" << _created;
|
||||
qDebug() << " age=" << getAge() << "seconds - " << ageAsString;
|
||||
qDebug() << " lastEdited =" << lastEdited;
|
||||
qDebug() << " ago=" << editedAgo << "seconds - " << agoAsString;
|
||||
}
|
||||
#endif
|
||||
|
||||
quint64 lastEditedFromBuffer = 0;
|
||||
quint64 lastEditedFromBufferAdjusted = 0;
|
||||
|
@ -388,20 +399,18 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
|
||||
bool fromSameServerEdit = (lastEditedFromBuffer == _lastEditedFromRemoteInRemoteTime);
|
||||
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "data from server **************** ";
|
||||
qDebug() << " entityItemID=" << getEntityItemID();
|
||||
qDebug() << " now=" << now;
|
||||
qDebug() << " getLastEdited()=" << getLastEdited();
|
||||
qDebug() << " lastEditedFromBuffer=" << lastEditedFromBuffer << " (BEFORE clockskew adjust)";
|
||||
qDebug() << " clockSkew=" << clockSkew;
|
||||
qDebug() << " lastEditedFromBufferAdjusted=" << lastEditedFromBufferAdjusted << " (AFTER clockskew adjust)";
|
||||
qDebug() << " _lastEditedFromRemote=" << _lastEditedFromRemote
|
||||
<< " (our local time the last server edit we accepted)";
|
||||
qDebug() << " _lastEditedFromRemoteInRemoteTime=" << _lastEditedFromRemoteInRemoteTime
|
||||
<< " (remote time the last server edit we accepted)";
|
||||
qDebug() << " fromSameServerEdit=" << fromSameServerEdit;
|
||||
}
|
||||
qDebug() << " entityItemID:" << getEntityItemID();
|
||||
qDebug() << " now:" << now;
|
||||
qDebug() << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
qDebug() << " lastEditedFromBuffer:" << debugTime(lastEditedFromBuffer, now);
|
||||
qDebug() << " clockSkew:" << debugTimeOnly(clockSkew);
|
||||
qDebug() << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
||||
qDebug() << " _lastEditedFromRemote:" << debugTime(_lastEditedFromRemote, now);
|
||||
qDebug() << " _lastEditedFromRemoteInRemoteTime:" << debugTime(_lastEditedFromRemoteInRemoteTime, now);
|
||||
qDebug() << " fromSameServerEdit:" << fromSameServerEdit;
|
||||
#endif
|
||||
|
||||
bool ignoreServerPacket = false; // assume we'll use this server packet
|
||||
|
||||
|
@ -424,14 +433,16 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
|
||||
if (ignoreServerPacket) {
|
||||
overwriteLocalData = false;
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "IGNORING old data from server!!! ****************";
|
||||
}
|
||||
debugDump();
|
||||
#endif
|
||||
} else {
|
||||
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "USING NEW data from server!!! ****************";
|
||||
}
|
||||
debugDump();
|
||||
#endif
|
||||
|
||||
// don't allow _lastEdited to be in the future
|
||||
_lastEdited = lastEditedFromBufferAdjusted;
|
||||
|
@ -449,15 +460,44 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
quint64 updateDelta = updateDeltaCoder;
|
||||
if (overwriteLocalData) {
|
||||
_lastUpdated = lastEditedFromBufferAdjusted + updateDelta; // don't adjust for clock skew since we already did that
|
||||
if (wantDebug) {
|
||||
qDebug() << "_lastUpdated =" << _lastUpdated;
|
||||
qDebug() << "_lastEdited=" << _lastEdited;
|
||||
qDebug() << "lastEditedFromBufferAdjusted=" << lastEditedFromBufferAdjusted;
|
||||
}
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << " _lastUpdated:" << debugTime(_lastUpdated, now);
|
||||
qDebug() << " _lastEdited:" << debugTime(_lastEdited, now);
|
||||
qDebug() << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
||||
#endif
|
||||
}
|
||||
encodedUpdateDelta = updateDeltaCoder; // determine true length
|
||||
dataAt += encodedUpdateDelta.size();
|
||||
bytesRead += encodedUpdateDelta.size();
|
||||
|
||||
// Newer bitstreams will have a last simulated and a last updated value
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME) {
|
||||
// last simulated is stored as ByteCountCoded delta from lastEdited
|
||||
QByteArray encodedSimulatedDelta = originalDataBuffer.mid(bytesRead); // maximum possible size
|
||||
ByteCountCoded<quint64> simulatedDeltaCoder = encodedSimulatedDelta;
|
||||
quint64 simulatedDelta = simulatedDeltaCoder;
|
||||
if (overwriteLocalData) {
|
||||
_lastSimulated = lastEditedFromBufferAdjusted + simulatedDelta; // don't adjust for clock skew since we already did that
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << " _lastSimulated:" << debugTime(_lastSimulated, now);
|
||||
qDebug() << " _lastEdited:" << debugTime(_lastEdited, now);
|
||||
qDebug() << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
||||
#endif
|
||||
}
|
||||
encodedSimulatedDelta = simulatedDeltaCoder; // determine true length
|
||||
dataAt += encodedSimulatedDelta.size();
|
||||
bytesRead += encodedSimulatedDelta.size();
|
||||
}
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
if (overwriteLocalData) {
|
||||
qDebug() << "EntityItem::readEntityDataFromBuffer()... changed entity:" << getEntityItemID();
|
||||
qDebug() << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
qDebug() << " getLastSimulated:" << debugTime(getLastSimulated(), now);
|
||||
qDebug() << " getLastUpdated:" << debugTime(getLastUpdated(), now);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Property Flags
|
||||
QByteArray encodedPropertyFlags = originalDataBuffer.mid(bytesRead); // maximum possible size
|
||||
|
@ -477,23 +517,11 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
if (overwriteLocalData) {
|
||||
setRadius(fromBuffer);
|
||||
}
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " readEntityDataFromBuffer() OLD FORMAT... found PROP_RADIUS";
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, setDimensions);
|
||||
if (wantDebug) {
|
||||
qDebug() << " readEntityDataFromBuffer() NEW FORMAT... look for PROP_DIMENSIONS";
|
||||
}
|
||||
}
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " readEntityDataFromBuffer() _dimensions:" << getDimensionsInMeters() << " in meters";
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_QUAT_SETTER(PROP_ROTATION, updateRotation);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_DENSITY, float, updateDensity);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_VELOCITY, glm::vec3, updateVelocity);
|
||||
|
@ -510,17 +538,22 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
READ_ENTITY_PROPERTY(PROP_LOCKED, bool, _locked);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_USER_DATA,setUserData);
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " readEntityDataFromBuffer() _registrationPoint:" << _registrationPoint;
|
||||
qDebug() << " readEntityDataFromBuffer() _visible:" << _visible;
|
||||
qDebug() << " readEntityDataFromBuffer() _ignoreForCollisions:" << _ignoreForCollisions;
|
||||
qDebug() << " readEntityDataFromBuffer() _collisionsWillMove:" << _collisionsWillMove;
|
||||
}
|
||||
|
||||
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData);
|
||||
|
||||
recalculateCollisionShape();
|
||||
if (overwriteLocalData && (getDirtyFlags() & EntityItem::DIRTY_POSITION)) {
|
||||
if (overwriteLocalData && (getDirtyFlags() & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY))) {
|
||||
// NOTE: This code is attempting to "repair" the old data we just got from the server to make it more
|
||||
// closely match where the entities should be if they'd stepped forward in time to "now". The server
|
||||
// is sending us data with a known "last simulated" time. That time is likely in the past, and therefore
|
||||
// this "new" data is actually slightly out of date. We calculate the time we need to skip forward and
|
||||
// use our simulation helper routine to get a best estimate of where the entity should be.
|
||||
float skipTimeForward = (float)(now - _lastSimulated) / (float)(USECS_PER_SECOND);
|
||||
if (skipTimeForward > 0.0f) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "skipTimeForward:" << skipTimeForward;
|
||||
#endif
|
||||
simulateKinematicMotion(skipTimeForward);
|
||||
}
|
||||
_lastSimulated = now;
|
||||
}
|
||||
}
|
||||
|
@ -546,13 +579,12 @@ void EntityItem::adjustEditPacketForClockSkew(unsigned char* editPacketBuffer, s
|
|||
memcpy(&lastEditedInLocalTime, dataAt, sizeof(lastEditedInLocalTime));
|
||||
quint64 lastEditedInServerTime = lastEditedInLocalTime + clockSkew;
|
||||
memcpy(dataAt, &lastEditedInServerTime, sizeof(lastEditedInServerTime));
|
||||
const bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug("EntityItem::adjustEditPacketForClockSkew()...");
|
||||
qDebug() << " lastEditedInLocalTime: " << lastEditedInLocalTime;
|
||||
qDebug() << " clockSkew: " << clockSkew;
|
||||
qDebug() << " lastEditedInServerTime: " << lastEditedInServerTime;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float EntityItem::computeMass() const {
|
||||
|
@ -607,20 +639,13 @@ bool EntityItem::isRestingOnSurface() const {
|
|||
}
|
||||
|
||||
void EntityItem::simulate(const quint64& now) {
|
||||
if (_physicsInfo) {
|
||||
// we rely on bullet for simulation, so bail
|
||||
return;
|
||||
}
|
||||
|
||||
bool wantDebug = false;
|
||||
|
||||
if (_lastSimulated == 0) {
|
||||
_lastSimulated = now;
|
||||
}
|
||||
|
||||
float timeElapsed = (float)(now - _lastSimulated) / (float)(USECS_PER_SECOND);
|
||||
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "********** EntityItem::simulate()";
|
||||
qDebug() << " entity ID=" << getEntityItemID();
|
||||
qDebug() << " now=" << now;
|
||||
|
@ -655,23 +680,23 @@ void EntityItem::simulate(const quint64& now) {
|
|||
qDebug() << " getAge()=" << getAge();
|
||||
qDebug() << " getLifetime()=" << getLifetime();
|
||||
}
|
||||
}
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " ********** EntityItem::simulate() .... SETTING _lastSimulated=" << _lastSimulated;
|
||||
}
|
||||
#endif
|
||||
|
||||
simulateKinematicMotion(timeElapsed);
|
||||
_lastSimulated = now;
|
||||
}
|
||||
|
||||
void EntityItem::simulateKinematicMotion(float timeElapsed) {
|
||||
if (hasAngularVelocity()) {
|
||||
glm::quat rotation = getRotation();
|
||||
|
||||
// angular damping
|
||||
glm::vec3 angularVelocity = getAngularVelocity();
|
||||
if (_angularDamping > 0.0f) {
|
||||
angularVelocity *= powf(1.0f - _angularDamping, timeElapsed);
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << " angularDamping :" << _angularDamping;
|
||||
qDebug() << " newAngularVelocity:" << angularVelocity;
|
||||
}
|
||||
#endif
|
||||
setAngularVelocity(angularVelocity);
|
||||
}
|
||||
|
||||
|
@ -679,6 +704,9 @@ void EntityItem::simulate(const quint64& now) {
|
|||
|
||||
const float EPSILON_ANGULAR_VELOCITY_LENGTH = 0.1f; //
|
||||
if (angularSpeed < EPSILON_ANGULAR_VELOCITY_LENGTH) {
|
||||
if (angularSpeed > 0.0f) {
|
||||
_dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE;
|
||||
}
|
||||
setAngularVelocity(ENTITY_ITEM_ZERO_VEC3);
|
||||
} else {
|
||||
// NOTE: angularSpeed is currently in degrees/sec!!!
|
||||
|
@ -686,7 +714,7 @@ void EntityItem::simulate(const quint64& now) {
|
|||
float angle = timeElapsed * glm::radians(angularSpeed);
|
||||
glm::vec3 axis = _angularVelocity / angularSpeed;
|
||||
glm::quat dQ = glm::angleAxis(angle, axis);
|
||||
rotation = glm::normalize(dQ * rotation);
|
||||
glm::quat rotation = glm::normalize(dQ * getRotation());
|
||||
setRotation(rotation);
|
||||
}
|
||||
}
|
||||
|
@ -696,19 +724,19 @@ void EntityItem::simulate(const quint64& now) {
|
|||
glm::vec3 velocity = getVelocity();
|
||||
if (_damping > 0.0f) {
|
||||
velocity *= powf(1.0f - _damping, timeElapsed);
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << " damping:" << _damping;
|
||||
qDebug() << " velocity AFTER dampingResistance:" << velocity;
|
||||
qDebug() << " glm::length(velocity):" << glm::length(velocity);
|
||||
qDebug() << " velocityEspilon :" << ENTITY_ITEM_EPSILON_VELOCITY_LENGTH;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// integrate position forward
|
||||
glm::vec3 position = getPosition();
|
||||
glm::vec3 newPosition = position + (velocity * timeElapsed);
|
||||
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << " EntityItem::simulate()....";
|
||||
qDebug() << " timeElapsed:" << timeElapsed;
|
||||
qDebug() << " old AACube:" << getMaximumAACube();
|
||||
|
@ -718,91 +746,35 @@ void EntityItem::simulate(const quint64& now) {
|
|||
qDebug() << " getDistanceToBottomOfEntity():" << getDistanceToBottomOfEntity() * (float)TREE_SCALE << " in meters";
|
||||
qDebug() << " newPosition:" << newPosition;
|
||||
qDebug() << " glm::distance(newPosition, position):" << glm::distance(newPosition, position);
|
||||
}
|
||||
#endif
|
||||
|
||||
position = newPosition;
|
||||
|
||||
// handle bounces off the ground... We bounce at the distance to the bottom of our entity
|
||||
if (position.y <= getDistanceToBottomOfEntity()) {
|
||||
velocity = velocity * glm::vec3(1,-1,1);
|
||||
position.y = getDistanceToBottomOfEntity();
|
||||
}
|
||||
|
||||
// apply gravity
|
||||
if (hasGravity()) {
|
||||
// handle resting on surface case, this is definitely a bit of a hack, and it only works on the
|
||||
// "ground" plane of the domain, but for now it's what we've got
|
||||
if (isRestingOnSurface()) {
|
||||
velocity.y = 0.0f;
|
||||
position.y = getDistanceToBottomOfEntity();
|
||||
} else {
|
||||
velocity += getGravity() * timeElapsed;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: we don't zero out very small velocities --> we rely on a remote Bullet simulation
|
||||
// to tell us when the entity has stopped.
|
||||
|
||||
// NOTE: the simulation should NOT set any DirtyFlags on this entity
|
||||
setPosition(position); // this will automatically recalculate our collision shape
|
||||
setVelocity(velocity);
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " new position:" << position;
|
||||
qDebug() << " new velocity:" << velocity;
|
||||
qDebug() << " new AACube:" << getMaximumAACube();
|
||||
qDebug() << " old getAABox:" << getAABox();
|
||||
}
|
||||
}
|
||||
|
||||
_lastSimulated = now;
|
||||
}
|
||||
|
||||
void EntityItem::simulateSimpleKinematicMotion(float timeElapsed) {
|
||||
if (hasAngularVelocity()) {
|
||||
// angular damping
|
||||
glm::vec3 angularVelocity = getAngularVelocity();
|
||||
if (_angularDamping > 0.0f) {
|
||||
angularVelocity *= powf(1.0f - _angularDamping, timeElapsed);
|
||||
setAngularVelocity(angularVelocity);
|
||||
}
|
||||
|
||||
float angularSpeed = glm::length(_angularVelocity);
|
||||
const float EPSILON_ANGULAR_VELOCITY_LENGTH = 0.1f; //
|
||||
if (angularSpeed < EPSILON_ANGULAR_VELOCITY_LENGTH) {
|
||||
setAngularVelocity(ENTITY_ITEM_ZERO_VEC3);
|
||||
} else {
|
||||
// NOTE: angularSpeed is currently in degrees/sec!!!
|
||||
// TODO: Andrew to convert to radians/sec
|
||||
float angle = timeElapsed * glm::radians(angularSpeed);
|
||||
glm::vec3 axis = _angularVelocity / angularSpeed;
|
||||
glm::quat dQ = glm::angleAxis(angle, axis);
|
||||
glm::quat rotation = getRotation();
|
||||
rotation = glm::normalize(dQ * rotation);
|
||||
setRotation(rotation);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasVelocity()) {
|
||||
// linear damping
|
||||
glm::vec3 velocity = getVelocity();
|
||||
if (_damping > 0.0f) {
|
||||
velocity *= powf(1.0f - _damping, timeElapsed);
|
||||
}
|
||||
|
||||
// integrate position forward
|
||||
glm::vec3 position = getPosition() + (velocity * timeElapsed);
|
||||
|
||||
// apply gravity
|
||||
if (hasGravity()) {
|
||||
// handle resting on surface case, this is definitely a bit of a hack, and it only works on the
|
||||
// "ground" plane of the domain, but for now it's what we've got
|
||||
velocity += getGravity() * timeElapsed;
|
||||
}
|
||||
|
||||
// NOTE: the simulation should NOT set any DirtyFlags on this entity
|
||||
setPosition(position); // this will automatically recalculate our collision shape
|
||||
setVelocity(velocity);
|
||||
|
||||
float speed = glm::length(velocity);
|
||||
const float EPSILON_LINEAR_VELOCITY_LENGTH = 0.001f / (float)TREE_SCALE; // 1mm/sec
|
||||
if (speed < EPSILON_LINEAR_VELOCITY_LENGTH) {
|
||||
setVelocity(ENTITY_ITEM_ZERO_VEC3);
|
||||
if (speed > 0.0f) {
|
||||
_dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE;
|
||||
}
|
||||
} else {
|
||||
setPosition(position);
|
||||
setVelocity(velocity);
|
||||
}
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << " new position:" << position;
|
||||
qDebug() << " new velocity:" << velocity;
|
||||
qDebug() << " new AACube:" << getMaximumAACube();
|
||||
qDebug() << " old getAABox:" << getAABox();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -876,17 +848,17 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
|
||||
if (somethingChanged) {
|
||||
somethingChangedNotification(); // notify derived classes that something has changed
|
||||
bool wantDebug = false;
|
||||
uint64_t now = usecTimestampNow();
|
||||
if (wantDebug) {
|
||||
#ifdef WANT_DEBUG
|
||||
int elapsed = now - getLastEdited();
|
||||
qDebug() << "EntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
|
||||
"now=" << now << " getLastEdited()=" << getLastEdited();
|
||||
}
|
||||
#endif
|
||||
if (_created != UNKNOWN_CREATED_TIME) {
|
||||
setLastEdited(now);
|
||||
}
|
||||
if (getDirtyFlags() & EntityItem::DIRTY_POSITION) {
|
||||
if (getDirtyFlags() & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY)) {
|
||||
// TODO: Andrew & Brad to discuss. Is this correct? Maybe it is. Need to think through all cases.
|
||||
_lastSimulated = now;
|
||||
}
|
||||
}
|
||||
|
@ -1023,15 +995,6 @@ void EntityItem::setRadius(float value) {
|
|||
float diameter = value * 2.0f;
|
||||
float maxDimension = sqrt((diameter * diameter) / 3.0f);
|
||||
_dimensions = glm::vec3(maxDimension, maxDimension, maxDimension);
|
||||
|
||||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
qDebug() << "EntityItem::setRadius()...";
|
||||
qDebug() << " radius:" << value;
|
||||
qDebug() << " diameter:" << diameter;
|
||||
qDebug() << " maxDimension:" << maxDimension;
|
||||
qDebug() << " _dimensions:" << _dimensions;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: get rid of all users of this function...
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue