From 3f26e1b63ad18ab228b2138e6ab9f4d3f068909f Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 13 Dec 2014 23:04:19 +0100 Subject: [PATCH 001/159] RealSense Initial --- cmake/modules/FindRSSDK.cmake | 33 ++++ interface/CMakeLists.txt | 2 +- interface/src/Application.cpp | 2 + interface/src/Menu.cpp | 10 ++ interface/src/Menu.h | 2 + interface/src/devices/RealSense.cpp | 233 ++++++++++++++++++++++++++++ interface/src/devices/RealSense.h | 63 ++++++++ 7 files changed, 344 insertions(+), 1 deletion(-) create mode 100644 cmake/modules/FindRSSDK.cmake create mode 100644 interface/src/devices/RealSense.cpp create mode 100644 interface/src/devices/RealSense.h diff --git a/cmake/modules/FindRSSDK.cmake b/cmake/modules/FindRSSDK.cmake new file mode 100644 index 0000000000..c31b0efcd9 --- /dev/null +++ b/cmake/modules/FindRSSDK.cmake @@ -0,0 +1,33 @@ +# Try to find the RSSDK library +# +# You must provide a RSSDK_ROOT_DIR which contains lib and include directories +# +# Once done this will define +# +# RSSDK_FOUND - system found RSSDK +# RSSDK_INCLUDE_DIRS - the RSSDK include directory +# RSSDK_LIBRARIES - Link this to use RSSDK +# +# Created on 12/7/2014 by Thijs Wenker +# Copyright (c) 2014 High Fidelity +# + +include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") +hifi_library_search_hints("rssdk") + +find_path(RSSDK_INCLUDE_DIRS pxcbase.h PATH_SUFFIXES include HINTS ${RSSDK_SEARCH_DIRS}) + +if (WIN32) + find_library(RSSDK_LIBRARY_DEBUG libpxc_d PATH_SUFFIXES lib/Win32 HINTS ${RSSDK_SEARCH_DIRS}) + find_library(RSSDK_LIBRARY_RELEASE libpxc PATH_SUFFIXES lib/Win32 HINTS ${RSSDK_SEARCH_DIRS}) +endif () + +include(SelectLibraryConfigurations) +select_library_configurations(RSSDK) + +set(RSSDK_LIBRARIES "${RSSDK_LIBRARY}") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(RSSDK DEFAULT_MSG RSSDK_INCLUDE_DIRS RSSDK_LIBRARIES) + +mark_as_advanced(RSSDK_INCLUDE_DIRS RSSDK_LIBRARIES RSSDK_SEARCH_DIRS) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 38dd02c655..bc25778940 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -2,7 +2,7 @@ set(TARGET_NAME interface) project(${TARGET_NAME}) # set a default root dir for each of our optional externals if it was not passed -set(OPTIONAL_EXTERNALS "Faceshift" "LibOVR" "PrioVR" "Sixense" "Visage" "LeapMotion" "RtMidi" "Qxmpp" "SDL2" "Gverb") +set(OPTIONAL_EXTERNALS "Faceshift" "LibOVR" "PrioVR" "Sixense" "Visage" "LeapMotion" "RtMidi" "Qxmpp" "SDL2" "Gverb" "RSSDK") foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE) if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3824185f52..08e3a78653 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -76,6 +76,7 @@ #include "Util.h" #include "devices/Leapmotion.h" +#include "devices/RealSense.h" #include "devices/MIDIManager.h" #include "devices/OculusManager.h" #include "devices/TV3DManager.h" @@ -1994,6 +1995,7 @@ void Application::init() { _visage.init(); Leapmotion::init(); + RealSense::init(); // fire off an immediate domain-server check in now that settings are loaded NodeList::getInstance()->sendDomainServerCheckIn(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index ae12b5ff26..37e4d96ed6 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -49,6 +49,7 @@ #include "ui/ModelsBrowser.h" #include "ui/LoginDialog.h" #include "ui/NodeBounds.h" +#include "devices/RealSense.h" #include "devices/OculusManager.h" @@ -493,6 +494,11 @@ Menu::Menu() : QMenu* leapOptionsMenu = handOptionsMenu->addMenu("Leap Motion"); addCheckableActionToQMenuAndActionHash(leapOptionsMenu, MenuOption::LeapMotionOnHMD, 0, false); +#ifdef HAVE_RSSDK + QMenu* realSenseOptionsMenu = handOptionsMenu->addMenu("RealSense"); + addActionToQMenuAndActionHash(realSenseOptionsMenu, MenuOption::LoadRSSDKFile, 0, this, SLOT(loadRSSDKFile())); +#endif + QMenu* networkMenu = developerMenu->addMenu("Network"); addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::DisableNackPackets, 0, false); addCheckableActionToQMenuAndActionHash(networkMenu, @@ -1346,6 +1352,10 @@ void Menu::showChat() { } } +void Menu::loadRSSDKFile() { + RealSense::getInstance()->loadRSSDKFile(); +} + void Menu::toggleChat() { #ifdef HAVE_QXMPP _chatAction->setEnabled(XmppClient::getInstance().getXMPPClient().isConnected()); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 138828d3e8..4ed5be8057 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -236,6 +236,7 @@ private slots: void displayAddressNotFoundMessage(); void muteEnvironment(); void changeVSync(); + void loadRSSDKFile(); private: static Menu* _instance; @@ -414,6 +415,7 @@ namespace MenuOption { const QString LeapMotionOnHMD = "Leap Motion on HMD"; const QString LoadScript = "Open and Run Script File..."; const QString LoadScriptURL = "Open and Run Script from URL..."; + const QString LoadRSSDKFile = "Load .rssdk file"; const QString LodTools = "LOD Tools"; const QString Login = "Login"; const QString Log = "Log"; diff --git a/interface/src/devices/RealSense.cpp b/interface/src/devices/RealSense.cpp new file mode 100644 index 0000000000..08492d8377 --- /dev/null +++ b/interface/src/devices/RealSense.cpp @@ -0,0 +1,233 @@ +// +// RealSense.cpp +// interface/src/devices +// +// Created by Thijs Wenker on 12/10/14 +// Copyright 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 "RealSense.h" +#include "Menu.h" +#include "SharedUtil.h" + +const int PALMROOT_NUM_JOINTS = 2; +const int FINGER_NUM_JOINTS = 4; + +const DeviceTracker::Name RealSense::NAME = "RealSense"; + +// find the index of a joint from +// the side: true = right +// the finger & the bone: +// finger in [0..4] : bone in [0..3] a finger phalange +// [-1] up the hand branch : bone in [0..2] <=> [ hand, forearm, arm] +MotionTracker::Index evalRealSenseJointIndex(bool isRightSide, int finger, int bone) { + + MotionTracker::Index offset = 1 // start after root + + (int(isRightSide) * PXCHandData::NUMBER_OF_JOINTS) // then offset for side + + PALMROOT_NUM_JOINTS; // then add the arm/forearm/hand chain + if (finger >= 0) { + // from there go down in the correct finger and bone + return offset + (finger * FINGER_NUM_JOINTS) + bone; + } else { + // or go back up for the correct root bone + return offset - 1 - bone; + } +} + +// static +void RealSense::init() { + DeviceTracker* device = DeviceTracker::getDevice(NAME); + if (!device) { + // create a new RealSense and register it + RealSense* realSense = new RealSense(); + DeviceTracker::registerDevice(NAME, realSense); + } +} + +// static +RealSense* RealSense::getInstance() { + DeviceTracker* device = DeviceTracker::getDevice(NAME); + if (!device) { + // create a new RealSense and register it + RealSense* realSense = new RealSense(); + DeviceTracker::registerDevice(NAME, realSense); + } + return dynamic_cast< RealSense* > (device); +} + +RealSense::RealSense() : + MotionTracker(), + _active(false), + _handData(NULL) +{ + _session = PXCSession_Create(); + initSession(false, NULL); + + // Create the RealSense joint hierarchy + std::vector< Semantic > sides; + sides.push_back("joint_L_"); + sides.push_back("joint_R_"); + + std::vector< Semantic > rootBones; + rootBones.push_back("wrist"); + rootBones.push_back("hand"); + + std::vector< Semantic > fingers; + fingers.push_back("thumb"); + fingers.push_back("index"); + fingers.push_back("middle"); + fingers.push_back("ring"); + fingers.push_back("pinky"); + + std::vector< Semantic > fingerBones; + fingerBones.push_back("1"); + fingerBones.push_back("2"); + fingerBones.push_back("3"); + fingerBones.push_back("4"); + + std::vector< Index > palms; + for (unsigned int s = 0; s < sides.size(); s++) { + Index rootJoint = 0; + for (unsigned int rb = 0; rb < rootBones.size(); rb++) { + rootJoint = addJoint(sides[s] + rootBones[rb], rootJoint); + } + + // capture the hand index for debug + palms.push_back(rootJoint); + + for (unsigned int f = 0; f < fingers.size(); f++) { + for (unsigned int b = 0; b < fingerBones.size(); b++) { + rootJoint = addJoint(sides[s] + fingers[f] + fingerBones[b], rootJoint); + } + } + } +} + +RealSense::~RealSense() { + _manager->Release(); +} + +void RealSense::initSession(bool playback, QString filename) { + _active = false; + _properlyInitialized = false; + if (_handData != NULL) { + _handData->Release(); + _handController->Release(); + _session->Release(); + } + _manager = _session->CreateSenseManager(); + if (playback) { + _manager->QueryCaptureManager()->SetFileName(filename.toStdWString().c_str(), false); + } + _manager->QueryCaptureManager()->SetRealtime(!playback); + _manager->EnableHand(0); + _handController = _manager->QueryHand(); + + if (_manager->Init() == PXC_STATUS_NO_ERROR) { + _handData = _handController->CreateOutput(); + + PXCCapture::Device *device = _manager->QueryCaptureManager()->QueryDevice(); + PXCCapture::DeviceInfo dinfo; + _manager->QueryCaptureManager()->QueryDevice()->QueryDeviceInfo(&dinfo); + if (dinfo.model == PXCCapture::DEVICE_MODEL_IVCAM) + { + device->SetDepthConfidenceThreshold(1); + device->SetMirrorMode(PXCCapture::Device::MIRROR_MODE_DISABLED); + device->SetIVCAMFilterOption(6); + } + _properlyInitialized = true; + } +} + +#ifdef HAVE_RSSDK +glm::quat quatFromPXCPoint4DF32(const PXCPoint4DF32& basis) { + return glm::quat(basis.w, basis.x, basis.y, basis.z); +} + +glm::vec3 vec3FromPXCPoint3DF32(const PXCPoint3DF32& vec) { + return glm::vec3(vec.x, vec.y, vec.z); +} +#endif + +void RealSense::update() { +#ifdef HAVE_RSSDK + bool wasActive = _active; + _active = _manager->IsConnected() && _properlyInitialized; + if (_active || wasActive) { + // Go through all the joints and increment their counter since last update. + // Increment all counters once after controller first becomes inactive so that each joint reports itself as inactive. + // TODO C++11 for (auto jointIt = _jointsArray.begin(); jointIt != _jointsArray.end(); jointIt++) { + for (JointTracker::Vector::iterator jointIt = _jointsArray.begin(); jointIt != _jointsArray.end(); jointIt++) { + (*jointIt).tickNewFrame(); + } + } + + if (!_active) { + return; + } + + pxcStatus sts = _manager->AcquireFrame(true); + _handData->Update(); + PXCHandData::JointData nodes[2][PXCHandData::NUMBER_OF_JOINTS] = {}; + PXCHandData::ExtremityData extremitiesPointsNodes[2][PXCHandData::NUMBER_OF_EXTREMITIES] = {}; + for (pxcI32 i = 0; i < _handData->QueryNumberOfHands(); i++) { + PXCHandData::IHand* handData; + if (_handData->QueryHandData(PXCHandData::ACCESS_ORDER_BY_TIME, i, handData) == PXC_STATUS_NO_ERROR) { + int rightSide = handData->QueryBodySide() == PXCHandData::BODY_SIDE_RIGHT; + PXCHandData::JointData jointData; + JointTracker* parentJointTracker = _jointsArray.data(); + //Iterate Joints + int rootBranchIndex = -1; + JointTracker* palmJoint = NULL; + for (int j = 0; j < PXCHandData::NUMBER_OF_JOINTS; j++) { + handData->QueryTrackedJoint((PXCHandData::JointType)j, jointData); + nodes[i][j] = jointData; + if (j == PXCHandData::JOINT_WRIST) { + JointTracker* wrist = editJointTracker(evalRealSenseJointIndex(rightSide, rootBranchIndex, 1)); // 1 is the index of the wrist joint + wrist->editAbsFrame().setTranslation(vec3FromPXCPoint3DF32(jointData.positionWorld)); + wrist->editAbsFrame().setRotation(quatFromPXCPoint4DF32(jointData.globalOrientation)); + wrist->updateLocFromAbsTransform(parentJointTracker); + wrist->activeFrame(); + parentJointTracker = wrist; + continue; + } else if (j == PXCHandData::JOINT_CENTER) { + palmJoint = editJointTracker(evalRealSenseJointIndex(rightSide, rootBranchIndex, 0)); // 0 is the index of the palm joint + palmJoint->editAbsFrame().setTranslation(vec3FromPXCPoint3DF32(jointData.positionWorld)); + palmJoint->editAbsFrame().setRotation(quatFromPXCPoint4DF32(jointData.globalOrientation)); + palmJoint->updateLocFromAbsTransform(parentJointTracker); + palmJoint->activeFrame(); + parentJointTracker = palmJoint; + continue; + } + int finger_index = j - PALMROOT_NUM_JOINTS; + int finger = finger_index / FINGER_NUM_JOINTS; + int finger_bone = finger_index % FINGER_NUM_JOINTS; + JointTracker* ljointTracker = editJointTracker(evalRealSenseJointIndex(rightSide, finger, finger_bone)); + if (jointData.confidence > 0) { + ljointTracker->editAbsFrame().setTranslation(vec3FromPXCPoint3DF32(jointData.positionWorld)); + ljointTracker->editAbsFrame().setRotation(quatFromPXCPoint4DF32(jointData.globalOrientation)); + ljointTracker->updateLocFromAbsTransform(parentJointTracker); + ljointTracker->activeFrame(); + } + if (finger_bone == (FINGER_NUM_JOINTS - 1)) { + parentJointTracker = palmJoint; + continue; + } + parentJointTracker = ljointTracker; + } + } + } + _manager->ReleaseFrame(); +#endif // HAVE_RSSDK +} + +void RealSense::loadRSSDKFile() { + QString fileNameString = QFileDialog::getOpenFileName(Application::getInstance()->getGLWidget(), tr("Open RSSDK clip"), + NULL, + tr("RSSDK Recordings (*.rssdk)")); + if (!fileNameString.isEmpty()) { + initSession(true, fileNameString); + } +} diff --git a/interface/src/devices/RealSense.h b/interface/src/devices/RealSense.h new file mode 100644 index 0000000000..015f1e7ce6 --- /dev/null +++ b/interface/src/devices/RealSense.h @@ -0,0 +1,63 @@ +// +// RealSense.h +// interface/src/devices +// +// Created by Thijs Wenker on 12/10/14 +// Copyright 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_RealSense_h +#define hifi_RealSense_h + +#include + +#include "MotionTracker.h" + +#ifdef HAVE_RSSDK +#include +#include +#include +#include +#include +#endif + +/// Handles interaction with the RealSense skeleton tracking suit. +class RealSense : public QObject, public MotionTracker { + Q_OBJECT + +public: + static const Name NAME; + + static void init(); + + /// RealSense MotionTracker factory + static RealSense* getInstance(); + + bool isActive() const { return _active; } + + virtual void update(); + + void loadRSSDKFile(); + +protected: + RealSense(); + virtual ~RealSense(); + + void initSession(bool playback, QString filename); + +private: +#ifdef HAVE_RSSDK + PXCSession* _session; + PXCSenseManager* _manager; + PXCHandModule* _handController; + PXCHandData* _handData; + PXCHandConfiguration* _config; +#endif + bool _properlyInitialized; + bool _active; +}; + +#endif // hifi_RealSense_h From c4a9cae943c0efd659c6efb59d319e7c73f7ab16 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Mon, 15 Dec 2014 21:47:00 +0100 Subject: [PATCH 002/159] flipped some values to get a nicer hand-tracking --- interface/src/devices/RealSense.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/interface/src/devices/RealSense.cpp b/interface/src/devices/RealSense.cpp index 08492d8377..2c041a33c9 100644 --- a/interface/src/devices/RealSense.cpp +++ b/interface/src/devices/RealSense.cpp @@ -21,7 +21,7 @@ const DeviceTracker::Name RealSense::NAME = "RealSense"; // the side: true = right // the finger & the bone: // finger in [0..4] : bone in [0..3] a finger phalange -// [-1] up the hand branch : bone in [0..2] <=> [ hand, forearm, arm] +// [-1] up the hand branch : bone in [0..1] <=> [ hand, forearm] MotionTracker::Index evalRealSenseJointIndex(bool isRightSide, int finger, int bone) { MotionTracker::Index offset = 1 // start after root @@ -116,6 +116,7 @@ void RealSense::initSession(bool playback, QString filename) { _handData->Release(); _handController->Release(); _session->Release(); + _config->Release(); } _manager = _session->CreateSenseManager(); if (playback) { @@ -139,15 +140,20 @@ void RealSense::initSession(bool playback, QString filename) { } _properlyInitialized = true; } + + _config = _handController->CreateActiveConfiguration(); + _config->EnableStabilizer(true); + _config->SetTrackingMode(PXCHandData::TRACKING_MODE_FULL_HAND); + _config->ApplyChanges(); } #ifdef HAVE_RSSDK glm::quat quatFromPXCPoint4DF32(const PXCPoint4DF32& basis) { - return glm::quat(basis.w, basis.x, basis.y, basis.z); + return glm::normalize(glm::quat(basis.w, basis.x, basis.y, basis.z) * glm::quat(glm::vec3(0, M_PI, 0))); } glm::vec3 vec3FromPXCPoint3DF32(const PXCPoint3DF32& vec) { - return glm::vec3(vec.x, vec.y, vec.z); + return glm::vec3(-vec.x, vec.y, -vec.z); } #endif From 2633b0dee72d4e285bee3429c1b9eee6b0fec653 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Mon, 15 Dec 2014 22:26:47 +0100 Subject: [PATCH 003/159] reordered includes --- interface/src/Menu.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9ef794db97..a9a039cd38 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -40,6 +40,7 @@ #include "AccountManager.h" #include "devices/Faceshift.h" #include "devices/OculusManager.h" +#include "devices/RealSense.h" #include "devices/Visage.h" #include "Menu.h" #include "scripting/LocationScriptingInterface.h" @@ -53,8 +54,6 @@ #include "ui/ModelsBrowser.h" #include "ui/LoginDialog.h" #include "ui/NodeBounds.h" -#include "devices/RealSense.h" -#include "devices/OculusManager.h" Menu* Menu::_instance = NULL; From 99b0cca8f32f4c93e8c5243dd8f855b598b6ff30 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 18 Dec 2014 00:08:20 +0100 Subject: [PATCH 004/159] realsenseHands.js example --- examples/realsenseHands.js | 525 +++++++++++++++++++++++++++++++++++++ 1 file changed, 525 insertions(+) create mode 100644 examples/realsenseHands.js diff --git a/examples/realsenseHands.js b/examples/realsenseHands.js new file mode 100644 index 0000000000..6b1a5c0a23 --- /dev/null +++ b/examples/realsenseHands.js @@ -0,0 +1,525 @@ +// +// realsenseHands.js +// examples +// +// Created by Thijs Wenker on 18 Dec 2014. +// Copyright 2014 High Fidelity, Inc. +// +// This is an example script that uses the Intel RealSense to make the avatar's hands replicate the user's hand actions. +// Most of this script is copied from leapHands.js +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var leapHands = (function () { + + var isOnHMD, + MotionTracker = "RealSense", + LEAP_ON_HMD_MENU_ITEM = "Leap Motion on HMD", + LEAP_OFFSET = 0.019, // Thickness of Leap Motion plus HMD clip + HMD_OFFSET = 0.070, // Eyeballs to front surface of Oculus DK2 TODO: Confirm and make depend on device and eye relief + hasHandAndWristJoints, + handToWristOffset = [], // For avatars without a wrist joint we control an estimate of a proper hand joint position + HAND_OFFSET = 0.4, // Relative distance of wrist to hand versus wrist to index finger knuckle + hands, + wrists, + NUM_HANDS = 2, // 0 = left; 1 = right + fingers, + NUM_FINGERS = 5, // 0 = thumb; ...; 4 = pinky + THUMB = 0, + MIDDLE_FINGER = 2, + NUM_FINGER_JOINTS = 3, // 0 = metacarpal(hand)-proximal(finger) joint; ...; 2 = intermediate-distal joint + MAX_HAND_INACTIVE_COUNT = 20, + calibrationStatus, + UNCALIBRATED = 0, + CALIBRATING = 1, + CALIBRATED = 2, + CALIBRATION_TIME = 1000, // milliseconds + avatarScale, + avatarFaceModelURL, + avatarSkeletonModelURL, + settingsTimer; + + function printSkeletonJointNames() { + var jointNames, + i; + + print(MyAvatar.skeletonModelURL); + + print("Skeleton joint names ..."); + jointNames = MyAvatar.getJointNames(); + for (i = 0; i < jointNames.length; i += 1) { + print(i + ": " + jointNames[i]); + } + print("... skeleton joint names"); + + /* + http://public.highfidelity.io/models/skeletons/ron_standing.fst + Skeleton joint names ... + 0: Hips + 1: RightUpLeg + 2: RightLeg + 3: RightFoot + 4: RightToeBase + 5: RightToe_End + 6: LeftUpLeg + 7: LeftLeg + 8: LeftFoot + 9: LeftToeBase + 10: LeftToe_End + 11: Spine + 12: Spine1 + 13: Spine2 + 14: RightShoulder + 15: RightArm + 16: RightForeArm + 17: RightHand + 18: RightHandPinky1 + 19: RightHandPinky2 + 20: RightHandPinky3 + 21: RightHandPinky4 + 22: RightHandRing1 + 23: RightHandRing2 + 24: RightHandRing3 + 25: RightHandRing4 + 26: RightHandMiddle1 + 27: RightHandMiddle2 + 28: RightHandMiddle3 + 29: RightHandMiddle4 + 30: RightHandIndex1 + 31: RightHandIndex2 + 32: RightHandIndex3 + 33: RightHandIndex4 + 34: RightHandThumb1 + 35: RightHandThumb2 + 36: RightHandThumb3 + 37: RightHandThumb4 + 38: LeftShoulder + 39: LeftArm + 40: LeftForeArm + 41: LeftHand + 42: LeftHandPinky1 + 43: LeftHandPinky2 + 44: LeftHandPinky3 + 45: LeftHandPinky4 + 46: LeftHandRing1 + 47: LeftHandRing2 + 48: LeftHandRing3 + 49: LeftHandRing4 + 50: LeftHandMiddle1 + 51: LeftHandMiddle2 + 52: LeftHandMiddle3 + 53: LeftHandMiddle4 + 54: LeftHandIndex1 + 55: LeftHandIndex2 + 56: LeftHandIndex3 + 57: LeftHandIndex4 + 58: LeftHandThumb1 + 59: LeftHandThumb2 + 60: LeftHandThumb3 + 61: LeftHandThumb4 + 62: Neck + 63: Head + 64: HeadTop_End + 65: body + ... skeleton joint names + */ + } + + function finishCalibration() { + var avatarPosition, + handPosition, + middleFingerPosition, + leapHandHeight, + h; + + if (!isOnHMD) { + if (hands[0].controller.isActive() && hands[1].controller.isActive()) { + leapHandHeight = (hands[0].controller.getAbsTranslation().y + hands[1].controller.getAbsTranslation().y) / 2.0; + } else { + calibrationStatus = UNCALIBRATED; + return; + } + } + + avatarPosition = MyAvatar.position; + + for (h = 0; h < NUM_HANDS; h += 1) { + handPosition = MyAvatar.getJointPosition(hands[h].jointName); + if (!hasHandAndWristJoints) { + middleFingerPosition = MyAvatar.getJointPosition(fingers[h][MIDDLE_FINGER][0].jointName); + handToWristOffset[h] = Vec3.multiply(Vec3.subtract(handPosition, middleFingerPosition), 1.0 - HAND_OFFSET); + } + + if (isOnHMD) { + // Offset of Leap Motion origin from physical eye position + hands[h].zeroPosition = { x: 0.0, y: 0.0, z: HMD_OFFSET + LEAP_OFFSET }; + } else { + hands[h].zeroPosition = { + x: handPosition.x - avatarPosition.x, + y: handPosition.y - avatarPosition.y, + z: avatarPosition.z - handPosition.z + }; + hands[h].zeroPosition = Vec3.multiplyQbyV(MyAvatar.orientation, hands[h].zeroPosition); + hands[h].zeroPosition.y = hands[h].zeroPosition.y - leapHandHeight; + } + } + + MyAvatar.clearJointData("LeftHand"); + MyAvatar.clearJointData("LeftForeArm"); + MyAvatar.clearJointData("LeftArm"); + MyAvatar.clearJointData("RightHand"); + MyAvatar.clearJointData("RightForeArm"); + MyAvatar.clearJointData("RightArm"); + + calibrationStatus = CALIBRATED; + print("Leap Motion: Calibrated"); + } + + function calibrate() { + var jointNames, + i; + + calibrationStatus = CALIBRATING; + + avatarScale = MyAvatar.scale; + avatarFaceModelURL = MyAvatar.faceModelURL; + avatarSkeletonModelURL = MyAvatar.skeletonModelURL; + + // Does this skeleton have both wrist and hand joints? + hasHandAndWristJoints = false; + jointNames = MyAvatar.getJointNames(); + for (i = 0; i < jointNames.length; i += 1) { + hasHandAndWristJoints = hasHandAndWristJoints || jointNames[i].toLowerCase() === "leftwrist"; + } + + // Set avatar arms vertical, forearms horizontal, as "zero" position for calibration + MyAvatar.setJointData("LeftArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, -90.0)); + MyAvatar.setJointData("LeftForeArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, 180.0)); + MyAvatar.setJointData("LeftHand", Quat.fromPitchYawRollRadians(0.0, 0.0, 0.0)); + MyAvatar.setJointData("RightArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, 90.0)); + MyAvatar.setJointData("RightForeArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, 180.0)); + MyAvatar.setJointData("RightHand", Quat.fromPitchYawRollRadians(0.0, 0.0, 0.0)); + + + // Wait for arms to assume their positions before calculating + Script.setTimeout(finishCalibration, CALIBRATION_TIME); + } + + function checkCalibration() { + + if (calibrationStatus === CALIBRATED) { + return true; + } + + if (calibrationStatus !== CALIBRATING) { + calibrate(); + } + + return false; + } + + function setIsOnHMD() { + isOnHMD = Menu.isOptionChecked(LEAP_ON_HMD_MENU_ITEM); + print("Leap Motion: " + (isOnHMD ? "Is on HMD" : "Is on desk")); + } + + function checkSettings() { + if (calibrationStatus > UNCALIBRATED && (MyAvatar.scale !== avatarScale + || MyAvatar.faceModelURL !== avatarFaceModelURL + || MyAvatar.skeletonModelURL !== avatarSkeletonModelURL + || Menu.isOptionChecked(LEAP_ON_HMD_MENU_ITEM) !== isOnHMD)) { + print("Leap Motion: Recalibrate..."); + calibrationStatus = UNCALIBRATED; + + setIsOnHMD(); + } + } + + function setUp() { + + wrists = [ + { + jointName: "LeftWrist", + controller: Controller.createInputController(MotionTracker, "joint_L_wrist") + }, + { + jointName: "RightWrist", + controller: Controller.createInputController(MotionTracker, "joint_R_wrist") + } + ]; + + hands = [ + { + jointName: "LeftHand", + controller: Controller.createInputController(MotionTracker, "joint_L_hand"), + inactiveCount: 0 + }, + { + jointName: "RightHand", + controller: Controller.createInputController(MotionTracker, "joint_R_hand"), + inactiveCount: 0 + } + ]; + + // The Leap controller's first joint is the hand-metacarpal joint but this joint's data is not used because it's too + // dependent on the model skeleton exactly matching the Leap skeleton; using just the second and subsequent joints + // seems to work better over all. + fingers = [{}, {}]; + fingers[0] = [ + [ + { jointName: "LeftHandThumb1", controller: Controller.createInputController(MotionTracker, "joint_L_thumb2") }, + { jointName: "LeftHandThumb2", controller: Controller.createInputController(MotionTracker, "joint_L_thumb3") }, + { jointName: "LeftHandThumb3", controller: Controller.createInputController(MotionTracker, "joint_L_thumb4") } + ], + [ + { jointName: "LeftHandIndex1", controller: Controller.createInputController(MotionTracker, "joint_L_index2") }, + { jointName: "LeftHandIndex2", controller: Controller.createInputController(MotionTracker, "joint_L_index3") }, + { jointName: "LeftHandIndex3", controller: Controller.createInputController(MotionTracker, "joint_L_index4") } + ], + [ + { jointName: "LeftHandMiddle1", controller: Controller.createInputController(MotionTracker, "joint_L_middle2") }, + { jointName: "LeftHandMiddle2", controller: Controller.createInputController(MotionTracker, "joint_L_middle3") }, + { jointName: "LeftHandMiddle3", controller: Controller.createInputController(MotionTracker, "joint_L_middle4") } + ], + [ + { jointName: "LeftHandRing1", controller: Controller.createInputController(MotionTracker, "joint_L_ring2") }, + { jointName: "LeftHandRing2", controller: Controller.createInputController(MotionTracker, "joint_L_ring3") }, + { jointName: "LeftHandRing3", controller: Controller.createInputController(MotionTracker, "joint_L_ring4") } + ], + [ + { jointName: "LeftHandPinky1", controller: Controller.createInputController(MotionTracker, "joint_L_pinky2") }, + { jointName: "LeftHandPinky2", controller: Controller.createInputController(MotionTracker, "joint_L_pinky3") }, + { jointName: "LeftHandPinky3", controller: Controller.createInputController(MotionTracker, "joint_L_pinky4") } + ] + ]; + fingers[1] = [ + [ + { jointName: "RightHandThumb1", controller: Controller.createInputController(MotionTracker, "joint_R_thumb2") }, + { jointName: "RightHandThumb2", controller: Controller.createInputController(MotionTracker, "joint_R_thumb3") }, + { jointName: "RightHandThumb3", controller: Controller.createInputController(MotionTracker, "joint_R_thumb4") } + ], + [ + { jointName: "RightHandIndex1", controller: Controller.createInputController(MotionTracker, "joint_R_index2") }, + { jointName: "RightHandIndex2", controller: Controller.createInputController(MotionTracker, "joint_R_index3") }, + { jointName: "RightHandIndex3", controller: Controller.createInputController(MotionTracker, "joint_R_index4") } + ], + [ + { jointName: "RightHandMiddle1", controller: Controller.createInputController(MotionTracker, "joint_R_middle2") }, + { jointName: "RightHandMiddle2", controller: Controller.createInputController(MotionTracker, "joint_R_middle3") }, + { jointName: "RightHandMiddle3", controller: Controller.createInputController(MotionTracker, "joint_R_middle4") } + ], + [ + { jointName: "RightHandRing1", controller: Controller.createInputController(MotionTracker, "joint_R_ring2") }, + { jointName: "RightHandRing2", controller: Controller.createInputController(MotionTracker, "joint_R_ring3") }, + { jointName: "RightHandRing3", controller: Controller.createInputController(MotionTracker, "joint_R_ring4") } + ], + [ + { jointName: "RightHandPinky1", controller: Controller.createInputController(MotionTracker, "joint_R_pinky2") }, + { jointName: "RightHandPinky2", controller: Controller.createInputController(MotionTracker, "joint_R_pinky3") }, + { jointName: "RightHandPinky3", controller: Controller.createInputController(MotionTracker, "joint_R_pinky4") } + ] + ]; + + setIsOnHMD(); + + settingsTimer = Script.setInterval(checkSettings, 2000); + + calibrationStatus = UNCALIBRATED; + } + + function moveHands() { + var h, + i, + j, + side, + handOffset, + wristOffset, + handRotation, + locRotation, + cameraOrientation, + inverseAvatarOrientation; + + for (h = 0; h < NUM_HANDS; h += 1) { + side = h === 0 ? -1.0 : 1.0; + + if (hands[h].controller.isActive()) { + + // Calibrate if necessary. + if (!checkCalibration()) { + return; + } + + // Hand position ... + handOffset = hands[h].controller.getAbsTranslation(); + handRotation = hands[h].controller.getAbsRotation(); + + if (isOnHMD) { + + // Adjust to control wrist position if "hand" joint is at wrist ... + if (!hasHandAndWristJoints) { + wristOffset = Vec3.multiplyQbyV(handRotation, handToWristOffset[h]); + handOffset = Vec3.sum(handOffset, wristOffset); + } + + // Hand offset in camera coordinates ... + handOffset = { + x: hands[h].zeroPosition.x - handOffset.x, + y: hands[h].zeroPosition.y - handOffset.z, + z: hands[h].zeroPosition.z + handOffset.y + }; + handOffset.z = -handOffset.z; + + // Hand offset in world coordinates ... + cameraOrientation = Camera.getOrientation(); + handOffset = Vec3.sum(Camera.getPosition(), Vec3.multiplyQbyV(cameraOrientation, handOffset)); + + // Hand offset in avatar coordinates ... + inverseAvatarOrientation = Quat.inverse(MyAvatar.orientation); + handOffset = Vec3.subtract(handOffset, MyAvatar.position); + handOffset = Vec3.multiplyQbyV(inverseAvatarOrientation, handOffset); + handOffset.z = -handOffset.z; + handOffset.x = -handOffset.x; + + // Hand rotation in camera coordinates ... + handRotation = { + x: handRotation.z, + y: handRotation.y, + z: handRotation.x, + w: handRotation.w + }; + + // Hand rotation in avatar coordinates ... + if (h === 0) { + handRotation.x = -handRotation.x; + handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 1, y: 0, z: 0 }), handRotation); + handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 0, y: 0, z: 1 }), handRotation); + } else { + handRotation.z = -handRotation.z; + handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 1, y: 0, z: 0 }), handRotation); + handRotation = Quat.multiply(Quat.angleAxis(-90.0, { x: 0, y: 0, z: 1 }), handRotation); + } + + cameraOrientation.x = -cameraOrientation.x; + cameraOrientation.z = -cameraOrientation.z; + handRotation = Quat.multiply(cameraOrientation, handRotation); + handRotation = Quat.multiply(inverseAvatarOrientation, handRotation); + + } else { + + // Hand offset in camera coordinates ... + handOffset = { + x: -handOffset.x, + y: hands[h].zeroPosition.y + handOffset.y, + z: hands[h].zeroPosition.z - handOffset.z + }; + + // Hand rotation in camera coordinates ... + handRotation = { + x: handRotation.y, + y: handRotation.z, + z: -handRotation.x, + w: handRotation.w + }; + + // Hand rotation in avatar coordinates ... + if (h === 0) { + handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 0, y: 1, z: 0 }), + handRotation); + handRotation = Quat.multiply(Quat.angleAxis(-90.0, { x: 1, y: 0, z: 0 }), + handRotation); + } else { + handRotation = Quat.multiply(Quat.angleAxis(-90.0, { x: 0, y: 1, z: 0 }), + handRotation); + handRotation = Quat.multiply(Quat.angleAxis(-90.0, { x: 1, y: 0, z: 0 }), + handRotation); + } + } + + // Set hand position and orientation ... + MyAvatar.setJointModelPositionAndOrientation(hands[h].jointName, handOffset, handRotation, true); + + // Set finger joints ... + for (i = 0; i < NUM_FINGERS; i += 1) { + for (j = 0; j < NUM_FINGER_JOINTS; j += 1) { + if (fingers[h][i][j].controller !== null) { + locRotation = fingers[h][i][j].controller.getLocRotation(); + if (i === THUMB) { + locRotation = { + x: side * locRotation.y, + y: side * -locRotation.z, + z: side * -locRotation.x, + w: locRotation.w + }; + } else { + locRotation = { + x: -locRotation.x, + y: -locRotation.z, + z: -locRotation.y, + w: locRotation.w + }; + } + MyAvatar.setJointData(fingers[h][i][j].jointName, locRotation); + } + } + } + + hands[h].inactiveCount = 0; + + } else { + + if (hands[h].inactiveCount < MAX_HAND_INACTIVE_COUNT) { + + hands[h].inactiveCount += 1; + + if (hands[h].inactiveCount === MAX_HAND_INACTIVE_COUNT) { + if (h === 0) { + MyAvatar.clearJointData("LeftHand"); + MyAvatar.clearJointData("LeftForeArm"); + MyAvatar.clearJointData("LeftArm"); + } else { + MyAvatar.clearJointData("RightHand"); + MyAvatar.clearJointData("RightForeArm"); + MyAvatar.clearJointData("RightArm"); + } + } + } + } + } + } + + function tearDown() { + var h, + i, + j; + + Script.clearInterval(settingsTimer); + + for (h = 0; h < NUM_HANDS; h += 1) { + Controller.releaseInputController(hands[h].controller); + Controller.releaseInputController(wrists[h].controller); + for (i = 0; i < NUM_FINGERS; i += 1) { + for (j = 0; j < NUM_FINGER_JOINTS; j += 1) { + if (fingers[h][i][j].controller !== null) { + Controller.releaseInputController(fingers[h][i][j].controller); + } + } + } + } + } + + return { + printSkeletonJointNames: printSkeletonJointNames, + setUp : setUp, + moveHands : moveHands, + tearDown : tearDown + }; +}()); + + +//leapHands.printSkeletonJointNames(); + +leapHands.setUp(); +Script.update.connect(leapHands.moveHands); +Script.scriptEnding.connect(leapHands.tearDown); From 151ddab118c4a95b437711f78a83dbe862cdf27c Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 18 Dec 2014 00:16:51 +0100 Subject: [PATCH 005/159] make stuff build without RealSense --- interface/src/devices/RealSense.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/RealSense.cpp b/interface/src/devices/RealSense.cpp index 2c041a33c9..b09c165e44 100644 --- a/interface/src/devices/RealSense.cpp +++ b/interface/src/devices/RealSense.cpp @@ -23,7 +23,7 @@ const DeviceTracker::Name RealSense::NAME = "RealSense"; // finger in [0..4] : bone in [0..3] a finger phalange // [-1] up the hand branch : bone in [0..1] <=> [ hand, forearm] MotionTracker::Index evalRealSenseJointIndex(bool isRightSide, int finger, int bone) { - +#ifdef HAVE_RSSDK MotionTracker::Index offset = 1 // start after root + (int(isRightSide) * PXCHandData::NUMBER_OF_JOINTS) // then offset for side + PALMROOT_NUM_JOINTS; // then add the arm/forearm/hand chain @@ -34,6 +34,9 @@ MotionTracker::Index evalRealSenseJointIndex(bool isRightSide, int finger, int b // or go back up for the correct root bone return offset - 1 - bone; } +#else + return -1; +#endif // HAVE_RSSDK } // static @@ -62,6 +65,7 @@ RealSense::RealSense() : _active(false), _handData(NULL) { +#ifdef HAVE_RSSDK _session = PXCSession_Create(); initSession(false, NULL); @@ -103,13 +107,17 @@ RealSense::RealSense() : } } } +#endif // HAVE_RSSDK } RealSense::~RealSense() { +#ifdef HAVE_RSSDK _manager->Release(); +#endif // HAVE_RSSDK } void RealSense::initSession(bool playback, QString filename) { +#ifdef HAVE_RSSDK _active = false; _properlyInitialized = false; if (_handData != NULL) { @@ -145,6 +153,7 @@ void RealSense::initSession(bool playback, QString filename) { _config->EnableStabilizer(true); _config->SetTrackingMode(PXCHandData::TRACKING_MODE_FULL_HAND); _config->ApplyChanges(); +#endif // HAVE_RSSDK } #ifdef HAVE_RSSDK @@ -155,7 +164,7 @@ glm::quat quatFromPXCPoint4DF32(const PXCPoint4DF32& basis) { glm::vec3 vec3FromPXCPoint3DF32(const PXCPoint3DF32& vec) { return glm::vec3(-vec.x, vec.y, -vec.z); } -#endif +#endif // HAVE_RSSDK void RealSense::update() { #ifdef HAVE_RSSDK From 8a1618c26934af2645fb3d178e2e42d09d769426 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 18 Dec 2014 00:22:59 +0100 Subject: [PATCH 006/159] missed one. --- interface/src/devices/RealSense.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/RealSense.cpp b/interface/src/devices/RealSense.cpp index b09c165e44..5edb3aacee 100644 --- a/interface/src/devices/RealSense.cpp +++ b/interface/src/devices/RealSense.cpp @@ -62,10 +62,10 @@ RealSense* RealSense::getInstance() { RealSense::RealSense() : MotionTracker(), - _active(false), - _handData(NULL) + _active(false) { #ifdef HAVE_RSSDK + _handData = NULL; _session = PXCSession_Create(); initSession(false, NULL); From d9d0166bc958675acbae7830dbdfb5f84e8176ab Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 17 Dec 2014 15:23:39 -0800 Subject: [PATCH 007/159] Use variadic templates to create instance with arguments --- libraries/shared/src/DependencyManager.cpp | 8 ---- libraries/shared/src/DependencyManager.h | 46 ++++++++++++++++++---- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/libraries/shared/src/DependencyManager.cpp b/libraries/shared/src/DependencyManager.cpp index 43bb92258e..440c0ac68d 100644 --- a/libraries/shared/src/DependencyManager.cpp +++ b/libraries/shared/src/DependencyManager.cpp @@ -10,11 +10,3 @@ // #include "DependencyManager.h" - -DependencyManager& DependencyManager::getInstance() { - static DependencyManager instance; - return instance; -} - -DependencyManager::~DependencyManager() { -} \ No newline at end of file diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index fdf8030199..8ed55edf68 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -16,10 +16,12 @@ #include -#define SINGLETON_DEPENDENCY(T)\ +#define SINGLETON_DEPENDENCY(T, NEED_SET)\ public:\ typedef QSharedPointer SharedPointer;\ + typedef QWeakPointer WeakPointer;\ private:\ + static constexpr bool REQUIRE_SET = NEED_SET;\ void customDeleter() {\ QObject* thisObject = dynamic_cast(this);\ if (thisObject) {\ @@ -34,20 +36,50 @@ class QObject; class DependencyManager { public: - // Only accessible method. - // usage: T* instance = DependencyManager::get(); + // usage: + // T* instance = DependencyManager::get(); + // T* instance = DependencyManager::set(Args... args); + // T* instance = DependencyManager::destroy(); template static QSharedPointer get(); + template + static QSharedPointer set(Args&&... args); + + template + static void destroy(); + private: - static DependencyManager& getInstance(); - DependencyManager() {} - ~DependencyManager(); + template + static QSharedPointer& storage(); }; template QSharedPointer DependencyManager::get() { - static QSharedPointer sharedPointer = QSharedPointer(new T(), &T::customDeleter); + static bool requireSet = !T::REQUIRE_SET; + if (requireSet) { + set(); + requireSet = false; + } + + return storage(); +} + +template +QSharedPointer DependencyManager::set(Args&&... args) { + QSharedPointer instance(new T(args...), &T::customDeleter); + storage().swap(instance); + return storage(); +} + +template +void DependencyManager::destroy() { + storage().clear(); +} + +template +QSharedPointer& DependencyManager::storage() { + static QSharedPointer sharedPointer; return sharedPointer; } From ce7f72d2cdd67d76a5271f4a2da3cf236df2babe Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 17 Dec 2014 15:26:47 -0800 Subject: [PATCH 008/159] Update macro --- interface/src/GLCanvas.h | 2 +- interface/src/devices/DdeFaceTracker.h | 2 +- interface/src/devices/Faceshift.h | 2 +- interface/src/devices/Visage.h | 2 +- libraries/animation/src/AnimationCache.h | 2 +- libraries/networking/src/NodeList.h | 2 ++ libraries/render-utils/src/AmbientOcclusionEffect.h | 2 +- libraries/render-utils/src/DeferredLightingEffect.h | 2 +- libraries/render-utils/src/GeometryCache.h | 2 +- libraries/render-utils/src/GlowEffect.h | 2 +- libraries/render-utils/src/Model.h | 2 +- libraries/render-utils/src/TextureCache.h | 2 +- 12 files changed, 13 insertions(+), 11 deletions(-) diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index 420bf77467..d9966714cc 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -20,7 +20,7 @@ /// customized canvas that simply forwards requests/events to the singleton application class GLCanvas : public QGLWidget { Q_OBJECT - SINGLETON_DEPENDENCY(GLCanvas) + SINGLETON_DEPENDENCY(GLCanvas, false) public: bool isThrottleRendering() const; diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 23a5d1fcc8..60a317e887 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -20,7 +20,7 @@ class DdeFaceTracker : public FaceTracker { Q_OBJECT - SINGLETON_DEPENDENCY(DdeFaceTracker) + SINGLETON_DEPENDENCY(DdeFaceTracker, false) public: //initialization diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index b6b942dfee..3587b3dfae 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -26,7 +26,7 @@ /// Handles interaction with the Faceshift software, which provides head position/orientation and facial features. class Faceshift : public FaceTracker { Q_OBJECT - SINGLETON_DEPENDENCY(Faceshift) + SINGLETON_DEPENDENCY(Faceshift, false) public: void init(); diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index c12ce3aabd..6d8c87eef7 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -28,7 +28,7 @@ namespace VisageSDK { /// Handles input from the Visage webcam feature tracking software. class Visage : public FaceTracker { Q_OBJECT - SINGLETON_DEPENDENCY(Visage) + SINGLETON_DEPENDENCY(Visage, false) public: void init(); diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index 4e67014822..5bec0b8902 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -26,7 +26,7 @@ typedef QSharedPointer AnimationPointer; /// Scriptable interface for FBX animation loading. class AnimationCache : public ResourceCache { Q_OBJECT - SINGLETON_DEPENDENCY(AnimationCache) + SINGLETON_DEPENDENCY(AnimationCache, false) public: Q_INVOKABLE AnimationPointer getAnimation(const QString& url) { return getAnimation(QUrl(url)); } diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 921f33b454..78f2f8e457 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -27,6 +27,8 @@ #include #include +#include + #include "DomainHandler.h" #include "LimitedNodeList.h" #include "Node.h" diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 421461860d..12688de1cc 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -21,7 +21,7 @@ class ProgramObject; /// A screen space ambient occlusion effect. See John Chapman's tutorial at /// http://john-chapman-graphics.blogspot.co.uk/2013/01/ssao-tutorial.html for reference. class AmbientOcclusionEffect { - SINGLETON_DEPENDENCY(AmbientOcclusionEffect) + SINGLETON_DEPENDENCY(AmbientOcclusionEffect, false) public: diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 904f9827ea..3450d84713 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -24,7 +24,7 @@ class PostLightingRenderable; /// Handles deferred lighting for the bits that require it (voxels, metavoxels...) class DeferredLightingEffect { - SINGLETON_DEPENDENCY(DeferredLightingEffect) + SINGLETON_DEPENDENCY(DeferredLightingEffect, false) public: diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 97f24f94a3..44b7cda8ec 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -34,7 +34,7 @@ class NetworkTexture; /// Stores cached geometry. class GeometryCache : public ResourceCache { Q_OBJECT - SINGLETON_DEPENDENCY(GeometryCache) + SINGLETON_DEPENDENCY(GeometryCache, false) public: void renderHemisphere(int slices, int stacks); diff --git a/libraries/render-utils/src/GlowEffect.h b/libraries/render-utils/src/GlowEffect.h index 37f29afb62..4828e1764e 100644 --- a/libraries/render-utils/src/GlowEffect.h +++ b/libraries/render-utils/src/GlowEffect.h @@ -27,7 +27,7 @@ class ProgramObject; /// A generic full screen glow effect. class GlowEffect : public QObject { Q_OBJECT - SINGLETON_DEPENDENCY(GlowEffect) + SINGLETON_DEPENDENCY(GlowEffect, false) public: diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 20b828022b..8fedd2e622 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -470,7 +470,7 @@ Q_DECLARE_METATYPE(QVector) /// Handle management of pending models that need blending class ModelBlender : public QObject { Q_OBJECT - SINGLETON_DEPENDENCY(ModelBlender) + SINGLETON_DEPENDENCY(ModelBlender, false) public: diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h index f3ad493cb4..6957fb0830 100644 --- a/libraries/render-utils/src/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -32,7 +32,7 @@ enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_T /// Stores cached textures, including render-to-texture targets. class TextureCache : public ResourceCache { Q_OBJECT - SINGLETON_DEPENDENCY(TextureCache) + SINGLETON_DEPENDENCY(TextureCache, false) public: From 52f2033dce2c67e4cafaf9cfe854f3867869a93b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 17 Dec 2014 15:27:35 -0800 Subject: [PATCH 009/159] Updated Nodelist class --- libraries/networking/src/NodeList.cpp | 35 ++++++--------------------- libraries/networking/src/NodeList.h | 8 +++--- 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index bf992e7b88..f7820c9ee8 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -25,33 +25,6 @@ #include "SharedUtil.h" #include "UUID.h" -NodeList* NodeList::createInstance(char ownerType, unsigned short socketListenPort, unsigned short dtlsPort) { - - NodeType::init(); - - if (_sharedInstance.get()) { - qDebug() << "NodeList called with existing instance." << - "Releasing auto_ptr, deleting existing instance and creating a new one."; - - delete _sharedInstance.release(); - } - - _sharedInstance = std::auto_ptr(new NodeList(ownerType, socketListenPort, dtlsPort)); - - // register the SharedNodePointer meta-type for signals/slots - qRegisterMetaType(); - - return static_cast(_sharedInstance.get()); -} - -NodeList* NodeList::getInstance() { - if (!_sharedInstance.get()) { - qDebug("NodeList getInstance called before call to createInstance. Returning NULL pointer."); - } - - return static_cast(_sharedInstance.get()); -} - NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned short dtlsListenPort) : LimitedNodeList(socketListenPort, dtlsListenPort), _ownerType(newOwnerType), @@ -62,6 +35,14 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned _hasCompletedInitialSTUNFailure(false), _stunRequestsSinceSuccess(0) { + static bool firstCall = true; + if (firstCall) { + NodeType::init(); + // register the SharedNodePointer meta-type for signals/slots + qRegisterMetaType(); + firstCall = false; + } + // clear our NodeList when the domain changes connect(&_domainHandler, &DomainHandler::disconnectedFromDomain, this, &NodeList::reset); diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 78f2f8e457..3a9ecf2405 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -14,6 +14,7 @@ #include #include +#include #ifndef _WIN32 #include // not on windows, not needed for mac or windows @@ -41,9 +42,9 @@ class Assignment; class NodeList : public LimitedNodeList { Q_OBJECT + SINGLETON_DEPENDENCY(NodeList, true) + public: - static NodeList* createInstance(char ownerType, unsigned short socketListenPort = 0, unsigned short dtlsPort = 0); - static NodeList* getInstance(); NodeType_t getOwnerType() const { return _ownerType; } void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; } @@ -72,7 +73,8 @@ public slots: signals: void limitOfSilentDomainCheckInsReached(); private: - NodeList(char ownerType, unsigned short socketListenPort, unsigned short dtlsListenPort); + NodeList() : LimitedNodeList(0, 0) { assert(false); } // Not implemented, needed for DependencyManager templates compile + NodeList(char ownerType, unsigned short socketListenPort = 0, unsigned short dtlsListenPort = 0); NodeList(NodeList const&); // Don't implement, needed to avoid copies of singleton void operator=(NodeList const&); // Don't implement, needed to avoid copies of singleton From 0bd9ed469eedc66196175b2fe669522da917d9a8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 17 Dec 2014 15:28:25 -0800 Subject: [PATCH 010/159] Changed NodeList::getInstance() calls to use the DM --- assignment-client/src/Agent.cpp | 14 +++--- assignment-client/src/AssignmentClient.cpp | 8 ++-- assignment-client/src/audio/AudioMixer.cpp | 12 ++--- .../src/audio/AudioMixerClientData.cpp | 2 +- assignment-client/src/avatars/AvatarMixer.cpp | 10 ++-- .../src/entities/EntityServer.cpp | 7 +-- .../src/metavoxels/MetavoxelServer.cpp | 8 ++-- .../octree/OctreeInboundPacketProcessor.cpp | 4 +- .../src/octree/OctreeSendThread.cpp | 10 ++-- assignment-client/src/octree/OctreeServer.cpp | 16 +++---- .../octree/OctreeServerDatagramProcessor.cpp | 2 +- assignment-client/src/voxels/VoxelServer.cpp | 4 +- domain-server/src/DomainServer.cpp | 21 +++++---- interface/src/Application.cpp | 46 +++++++++---------- interface/src/Audio.cpp | 6 +-- interface/src/DatagramProcessor.cpp | 6 +-- interface/src/Menu.cpp | 8 ++-- interface/src/MetavoxelSystem.cpp | 8 ++-- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/ui/ApplicationOverlay.cpp | 2 +- interface/src/ui/NodeBounds.cpp | 2 +- interface/src/ui/OctreeStatsDialog.cpp | 2 +- interface/src/ui/Snapshot.cpp | 2 +- interface/src/ui/Stats.cpp | 6 +-- .../src/voxels/OctreePacketProcessor.cpp | 2 +- libraries/audio/src/AudioInjector.cpp | 2 +- libraries/avatars/src/AvatarData.cpp | 4 +- libraries/avatars/src/AvatarHashMap.cpp | 2 +- libraries/avatars/src/Player.cpp | 2 +- libraries/avatars/src/Recorder.cpp | 2 +- libraries/avatars/src/Recording.cpp | 2 +- libraries/metavoxels/src/Endpoint.cpp | 2 +- .../metavoxels/src/MetavoxelClientManager.cpp | 10 ++-- libraries/networking/src/AddressManager.cpp | 4 +- libraries/networking/src/DomainHandler.cpp | 4 +- libraries/networking/src/PacketSender.cpp | 2 +- .../networking/src/ThreadedAssignment.cpp | 16 +++---- libraries/octree/src/JurisdictionListener.cpp | 6 +-- libraries/octree/src/JurisdictionSender.cpp | 2 +- .../octree/src/OctreeEditPacketSender.cpp | 10 ++-- libraries/octree/src/OctreeHeadlessViewer.cpp | 4 +- libraries/script-engine/src/ScriptEngine.cpp | 4 +- 42 files changed, 147 insertions(+), 141 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index f3efccf31a..bd55a4a3e0 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -55,7 +55,7 @@ Agent::Agent(const QByteArray& packet) : void Agent::readPendingDatagrams() { QByteArray receivedPacket; HifiSockAddr senderSockAddr; - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); while (readAvailableDatagram(receivedPacket, senderSockAddr)) { if (nodeList->packetVersionAndHashMatch(receivedPacket)) { @@ -113,7 +113,7 @@ void Agent::readPendingDatagrams() { // TODO: this needs to be fixed, the goal is to test the packet version for the piggyback, but // this is testing the version and hash of the original packet // need to use numBytesArithmeticCodingFromBuffer()... - if (!NodeList::getInstance()->packetVersionAndHashMatch(receivedPacket)) { + if (!DependencyManager::get()->packetVersionAndHashMatch(receivedPacket)) { return; // bail since piggyback data doesn't match our versioning } } else { @@ -141,7 +141,7 @@ void Agent::readPendingDatagrams() { // let this continue through to the NodeList so it updates last heard timestamp // for the sending audio mixer - NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); + DependencyManager::get()->processNodeData(senderSockAddr, receivedPacket); } else if (datagramPacketType == PacketTypeBulkAvatarData || datagramPacketType == PacketTypeAvatarIdentity || datagramPacketType == PacketTypeAvatarBillboard @@ -151,9 +151,9 @@ void Agent::readPendingDatagrams() { // let this continue through to the NodeList so it updates last heard timestamp // for the sending avatar-mixer - NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); + DependencyManager::get()->processNodeData(senderSockAddr, receivedPacket); } else { - NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); + DependencyManager::get()->processNodeData(senderSockAddr, receivedPacket); } } } @@ -164,7 +164,7 @@ const QString AGENT_LOGGING_NAME = "agent"; void Agent::run() { ThreadedAssignment::commonInit(AGENT_LOGGING_NAME, NodeType::Agent); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer @@ -176,7 +176,7 @@ void Agent::run() { QUrl scriptURL; if (_payload.isEmpty()) { scriptURL = QUrl(QString("http://%1:%2/assignment/%3") - .arg(NodeList::getInstance()->getDomainHandler().getIP().toString()) + .arg(DependencyManager::get()->getDomainHandler().getIP().toString()) .arg(DOMAIN_SERVER_HTTP_PORT) .arg(uuidStringWithoutCurlyBraces(_uuid))); } else { diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 386d6e8a1d..51bd32f41b 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -93,7 +93,7 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : } // create a NodeList as an unassigned client - NodeList* nodeList = NodeList::createInstance(NodeType::Unassigned); + auto nodeList = DependencyManager::set(NodeType::Unassigned); quint16 assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT; @@ -136,7 +136,7 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : void AssignmentClient::sendAssignmentRequest() { if (!_currentAssignment) { - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); if (_assignmentServerHostname == "localhost") { // we want to check again for the local domain-server port in case the DS has restarted @@ -173,7 +173,7 @@ void AssignmentClient::sendAssignmentRequest() { } void AssignmentClient::readPendingDatagrams() { - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); QByteArray receivedPacket; HifiSockAddr senderSockAddr; @@ -260,7 +260,7 @@ void AssignmentClient::assignmentCompleted() { qDebug("Assignment finished or never started - waiting for new assignment."); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); // have us handle incoming NodeList datagrams again disconnect(&nodeList->getNodeSocket(), 0, _currentAssignment.data(), 0); diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index e8ff072cc7..6218ae7f9d 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -440,7 +440,7 @@ int AudioMixer::prepareMixForListeningNode(Node* node) { // loop through all other nodes that have sufficient audio to mix int streamsMixed = 0; - NodeList::getInstance()->eachNode([&](const SharedNodePointer& otherNode){ + DependencyManager::get()->eachNode([&](const SharedNodePointer& otherNode){ if (otherNode->getLinkedData()) { AudioMixerClientData* otherNodeClientData = (AudioMixerClientData*) otherNode->getLinkedData(); @@ -520,12 +520,12 @@ void AudioMixer::sendAudioEnvironmentPacket(SharedNodePointer node) { memcpy(envDataAt, &wetLevel, sizeof(float)); envDataAt += sizeof(float); } - NodeList::getInstance()->writeDatagram(clientEnvBuffer, envDataAt - clientEnvBuffer, node); + DependencyManager::get()->writeDatagram(clientEnvBuffer, envDataAt - clientEnvBuffer, node); } } void AudioMixer::readPendingDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr) { - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); if (nodeList->packetVersionAndHashMatch(receivedPacket)) { // pull any new audio data from nodes off of the network stack @@ -606,7 +606,7 @@ void AudioMixer::sendStatsPacket() { somethingToSend = true; sizeOfStats += property.size() + value.size(); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); int clientNumber = 0; @@ -639,7 +639,7 @@ void AudioMixer::run() { ThreadedAssignment::commonInit(AUDIO_MIXER_LOGGING_TARGET_NAME, NodeType::AudioMixer); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); // we do not want this event loop to be the handler for UDP datagrams, so disconnect disconnect(&nodeList->getNodeSocket(), 0, this, 0); @@ -892,7 +892,7 @@ void AudioMixer::perSecondActions() { _timeSpentPerHashMatchCallStats.getWindowSum() / WINDOW_LENGTH_USECS * 100.0, _timeSpentPerHashMatchCallStats.getCurrentIntervalSum() / USECS_PER_SECOND * 100.0); - NodeList::getInstance()->eachNode([](const SharedNodePointer& node) { + DependencyManager::get()->eachNode([](const SharedNodePointer& node) { if (node->getLinkedData()) { AudioMixerClientData* nodeData = (AudioMixerClientData*)node->getLinkedData(); diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index 26178eb2af..61f9e544e4 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -147,7 +147,7 @@ void AudioMixerClientData::sendAudioStreamStatsPackets(const SharedNodePointer& removeDeadInjectedStreams(); char packet[MAX_PACKET_SIZE]; - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); // The append flag is a boolean value that will be packed right after the header. The first packet sent // inside this method will have 0 for this flag, while every subsequent packet will have 1 for this flag. diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 671fb17bc8..9616c8cb21 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -41,7 +41,7 @@ AvatarMixer::AvatarMixer(const QByteArray& packet) : _sumIdentityPackets(0) { // make sure we hear about node kills so we can tell the other nodes - connect(NodeList::getInstance(), &NodeList::nodeKilled, this, &AvatarMixer::nodeKilled); + connect(DependencyManager::get().data(), &NodeList::nodeKilled, this, &AvatarMixer::nodeKilled); } AvatarMixer::~AvatarMixer() { @@ -117,7 +117,7 @@ void AvatarMixer::broadcastAvatarData() { int numPacketHeaderBytes = populatePacketHeader(mixedAvatarByteArray, PacketTypeBulkAvatarData); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); AvatarMixerClientData* nodeData = NULL; AvatarMixerClientData* otherNodeData = NULL; @@ -222,7 +222,7 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) { QByteArray killPacket = byteArrayWithPopulatedHeader(PacketTypeKillAvatar); killPacket += killedNode->getUUID().toRfc4122(); - NodeList::getInstance()->broadcastToNodes(killPacket, + DependencyManager::get()->broadcastToNodes(killPacket, NodeSet() << NodeType::Agent); } } @@ -231,7 +231,7 @@ void AvatarMixer::readPendingDatagrams() { QByteArray receivedPacket; HifiSockAddr senderSockAddr; - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); while (readAvailableDatagram(receivedPacket, senderSockAddr)) { if (nodeList->packetVersionAndHashMatch(receivedPacket)) { @@ -309,7 +309,7 @@ void AvatarMixer::sendStatsPacket() { void AvatarMixer::run() { ThreadedAssignment::commonInit(AVATAR_MIXER_LOGGING_NAME, NodeType::AvatarMixer); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->addNodeTypeToInterestSet(NodeType::Agent); nodeList->linkedDataCreateCallback = attachAvatarDataToNode; diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index af450782a2..d882ea19ac 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -76,7 +76,7 @@ void EntityServer::entityCreated(const EntityItem& newEntity, const SharedNodePo copyAt += sizeof(entityID); packetLength += sizeof(entityID); - NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, senderNode); + DependencyManager::get()->writeDatagram((char*) outputBuffer, packetLength, senderNode); } @@ -114,7 +114,8 @@ int EntityServer::sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNo hasMoreToSend = tree->encodeEntitiesDeletedSince(queryNode->getSequenceNumber(), deletedEntitiesSentAt, outputBuffer, MAX_PACKET_SIZE, packetLength); - NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, SharedNodePointer(node)); + DependencyManager::get()->writeDatagram((char*) outputBuffer, packetLength, + SharedNodePointer(node)); queryNode->packetSent(outputBuffer, packetLength); packetsSent++; } @@ -132,7 +133,7 @@ void EntityServer::pruneDeletedEntities() { quint64 earliestLastDeletedEntitiesSent = usecTimestampNow() + 1; // in the future - NodeList::getInstance()->eachNode([&earliestLastDeletedEntitiesSent](const SharedNodePointer& node) { + DependencyManager::get()->eachNode([&earliestLastDeletedEntitiesSent](const SharedNodePointer& node) { if (node->getLinkedData()) { EntityNodeData* nodeData = static_cast(node->getLinkedData()); quint64 nodeLastDeletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt(); diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp index 89b3102391..43c24f218d 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ b/assignment-client/src/metavoxels/MetavoxelServer.cpp @@ -60,11 +60,11 @@ const QString METAVOXEL_SERVER_LOGGING_NAME = "metavoxel-server"; void MetavoxelServer::run() { commonInit(METAVOXEL_SERVER_LOGGING_NAME, NodeType::MetavoxelServer); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->addNodeTypeToInterestSet(NodeType::Agent); - connect(nodeList, &NodeList::nodeAdded, this, &MetavoxelServer::maybeAttachSession); - connect(nodeList, &NodeList::nodeKilled, this, &MetavoxelServer::maybeDeleteSession); + connect(nodeList.data(), &NodeList::nodeAdded, this, &MetavoxelServer::maybeAttachSession); + connect(nodeList.data(), &NodeList::nodeKilled, this, &MetavoxelServer::maybeDeleteSession); // initialize Bitstream before using it in multiple threads Bitstream::preThreadingInit(); @@ -101,7 +101,7 @@ void MetavoxelServer::readPendingDatagrams() { QByteArray receivedPacket; HifiSockAddr senderSockAddr; - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); while (readAvailableDatagram(receivedPacket, senderSockAddr)) { if (nodeList->packetVersionAndHashMatch(receivedPacket)) { diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp index e880615b71..18988a919c 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp @@ -261,7 +261,7 @@ int OctreeInboundPacketProcessor::sendNackPackets() { continue; } - const SharedNodePointer& destinationNode = NodeList::getInstance()->nodeWithUUID(nodeUUID); + const SharedNodePointer& destinationNode = DependencyManager::get()->nodeWithUUID(nodeUUID); // retrieve sequence number stats of node, prune its missing set SequenceNumberStats& sequenceNumberStats = nodeStats.getIncomingEditSequenceNumberStats(); @@ -299,7 +299,7 @@ int OctreeInboundPacketProcessor::sendNackPackets() { numSequenceNumbersAvailable -= numSequenceNumbers; // send it - NodeList::getInstance()->writeUnverifiedDatagram(packet, dataAt - packet, destinationNode); + DependencyManager::get()->writeUnverifiedDatagram(packet, dataAt - packet, destinationNode); packetsSent++; qDebug() << "NACK Sent back to editor/client... destinationNode=" << nodeUUID; diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 46ea49e9a7..2e13b43799 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -179,12 +179,12 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes // actually send it OctreeServer::didCallWriteDatagram(this); - NodeList::getInstance()->writeDatagram((char*) statsMessage, statsMessageLength, _node); + DependencyManager::get()->writeDatagram((char*) statsMessage, statsMessageLength, _node); packetSent = true; } else { // not enough room in the packet, send two packets OctreeServer::didCallWriteDatagram(this); - NodeList::getInstance()->writeDatagram((char*) statsMessage, statsMessageLength, _node); + DependencyManager::get()->writeDatagram((char*) statsMessage, statsMessageLength, _node); // since a stats message is only included on end of scene, don't consider any of these bytes "wasted", since // there was nothing else to send. @@ -213,7 +213,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes packetsSent++; OctreeServer::didCallWriteDatagram(this); - NodeList::getInstance()->writeDatagram((char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); + DependencyManager::get()->writeDatagram((char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); packetSent = true; thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength(); @@ -242,7 +242,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes if (nodeData->isPacketWaiting() && !nodeData->isShuttingDown()) { // just send the voxel packet OctreeServer::didCallWriteDatagram(this); - NodeList::getInstance()->writeDatagram((char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); + DependencyManager::get()->writeDatagram((char*)nodeData->getPacket(), nodeData->getPacketLength(), _node); packetSent = true; int thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength(); @@ -574,7 +574,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus while (nodeData->hasNextNackedPacket() && packetsSentThisInterval < maxPacketsPerInterval) { const QByteArray* packet = nodeData->getNextNackedPacket(); if (packet) { - NodeList::getInstance()->writeDatagram(*packet, _node); + DependencyManager::get()->writeDatagram(*packet, _node); truePacketsSent++; packetsSentThisInterval++; diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 4be2c9873f..c123dd4349 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -829,7 +829,7 @@ void OctreeServer::parsePayload() { } void OctreeServer::readPendingDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr) { - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); if (nodeList->packetVersionAndHashMatch(receivedPacket)) { PacketType packetType = packetTypeForPacket(receivedPacket); @@ -865,13 +865,13 @@ void OctreeServer::readPendingDatagram(const QByteArray& receivedPacket, const H _octreeInboundPacketProcessor->queueReceivedPacket(matchingNode, receivedPacket); } else { // let processNodeData handle it. - NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); + DependencyManager::get()->processNodeData(senderSockAddr, receivedPacket); } } } void OctreeServer::setupDatagramProcessingThread() { - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); // we do not want this event loop to be the handler for UDP datagrams, so disconnect disconnect(&nodeList->getNodeSocket(), 0, this, 0); @@ -960,7 +960,7 @@ void OctreeServer::readConfiguration() { } // wait until we have the domain-server settings, otherwise we bail - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); DomainHandler& domainHandler = nodeList->getDomainHandler(); qDebug() << "Waiting for domain settings from domain-server."; @@ -1106,7 +1106,7 @@ void OctreeServer::run() { _tree->setIsServer(true); // make sure our NodeList knows what type we are - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->setOwnerType(getMyNodeType()); @@ -1223,7 +1223,7 @@ void OctreeServer::aboutToFinish() { qDebug() << qPrintable(_safeServerName) << "inform Octree Inbound Packet Processor that we are shutting down..."; _octreeInboundPacketProcessor->shuttingDown(); - NodeList::getInstance()->eachNode([this](const SharedNodePointer& node) { + DependencyManager::get()->eachNode([this](const SharedNodePointer& node) { qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *node; forceNodeShutdown(node); }); @@ -1388,7 +1388,7 @@ void OctreeServer::sendStatsPacket() { statsObject2[baseName + QString(".2.outbound.timing.5.avgSendTime")] = getAveragePacketSendingTime(); statsObject2[baseName + QString(".2.outbound.timing.5.nodeWaitTime")] = getAverageNodeWaitTime(); - NodeList::getInstance()->sendStatsToDomainServer(statsObject2); + DependencyManager::get()->sendStatsToDomainServer(statsObject2); static QJsonObject statsObject3; @@ -1407,7 +1407,7 @@ void OctreeServer::sendStatsPacket() { statsObject3[baseName + QString(".3.inbound.timing.5.avgLockWaitTimePerElement")] = (double)_octreeInboundPacketProcessor->getAverageLockWaitTimePerElement(); - NodeList::getInstance()->sendStatsToDomainServer(statsObject3); + DependencyManager::get()->sendStatsToDomainServer(statsObject3); } QMap OctreeServer::_threadsDidProcess; diff --git a/assignment-client/src/octree/OctreeServerDatagramProcessor.cpp b/assignment-client/src/octree/OctreeServerDatagramProcessor.cpp index 0d3c622900..9f2ae72147 100644 --- a/assignment-client/src/octree/OctreeServerDatagramProcessor.cpp +++ b/assignment-client/src/octree/OctreeServerDatagramProcessor.cpp @@ -45,7 +45,7 @@ void OctreeServerDatagramProcessor::readPendingDatagrams() { PacketType packetType = packetTypeForPacket(incomingPacket); if (packetType == PacketTypePing) { - NodeList::getInstance()->processNodeData(senderSockAddr, incomingPacket); + DependencyManager::get()->processNodeData(senderSockAddr, incomingPacket); return; // don't emit } diff --git a/assignment-client/src/voxels/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp index a83e3e99e3..eb7eff4930 100644 --- a/assignment-client/src/voxels/VoxelServer.cpp +++ b/assignment-client/src/voxels/VoxelServer.cpp @@ -74,7 +74,7 @@ int VoxelServer::sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNod envPacketLength += getEnvironmentData(i)->getBroadcastData(_tempOutputBuffer + envPacketLength); } - NodeList::getInstance()->writeDatagram((char*) _tempOutputBuffer, envPacketLength, SharedNodePointer(node)); + DependencyManager::get()->writeDatagram((char*) _tempOutputBuffer, envPacketLength, SharedNodePointer(node)); queryNode->packetSent(_tempOutputBuffer, envPacketLength); packetsSent = 1; @@ -98,5 +98,5 @@ void VoxelServer::readAdditionalConfiguration(const QJsonObject& settingsSection } qDebug("Sending environments=%s", debug::valueOf(_sendEnvironments)); - NodeList::getInstance()->addNodeTypeToInterestSet(NodeType::AnimationServer); + DependencyManager::get()->addNodeTypeToInterestSet(NodeType::AnimationServer); } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 73092b694b..e6fcef62c1 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -262,8 +262,8 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { nodeList->setSessionUUID(idValueVariant->toString()); } - connect(nodeList, &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded); - connect(nodeList, &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled); + connect(nodeList.data(), &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded); + connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled); QTimer* silentNodeTimer = new QTimer(this); connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); @@ -368,8 +368,10 @@ void DomainServer::setupAutomaticNetworking() { iceHeartbeatTimer->start(ICE_HEARBEAT_INTERVAL_MSECS); // call our sendHeartbeatToIceServer immediately anytime a local or public socket changes - connect(nodeList, &LimitedNodeList::localSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); - connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer); + connect(nodeList.data(), &LimitedNodeList::localSockAddrChanged, + this, &DomainServer::sendHeartbeatToIceServer); + connect(nodeList.data(), &LimitedNodeList::publicSockAddrChanged, + this, &DomainServer::sendHeartbeatToIceServer); // attempt to update our public socket now, this will send a heartbeat once we get public socket requestCurrentPublicSocketViaSTUN(); @@ -400,7 +402,8 @@ void DomainServer::setupAutomaticNetworking() { dynamicIPTimer->start(STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS); // send public socket changes to the data server so nodes can find us at our new IP - connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::performIPAddressUpdate); + connect(nodeList.data(), &LimitedNodeList::publicSockAddrChanged, + this, &DomainServer::performIPAddressUpdate); // attempt to update our sockets now requestCurrentPublicSocketViaSTUN(); @@ -995,7 +998,7 @@ void DomainServer::readAvailableDatagrams() { void DomainServer::setupPendingAssignmentCredits() { // enumerate the NodeList to find the assigned nodes - NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ + DependencyManager::get()->eachNode([&](const SharedNodePointer& node){ DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); if (!nodeData->getAssignmentUUID().isNull() && !nodeData->getWalletUUID().isNull()) { @@ -1155,7 +1158,7 @@ void DomainServer::sendHeartbeatToDataServer(const QString& networkAddress) { // add the number of currently connected agent users int numConnectedAuthedUsers = 0; - NodeList::getInstance()->eachNode([&numConnectedAuthedUsers](const SharedNodePointer& node){ + DependencyManager::get()->eachNode([&numConnectedAuthedUsers](const SharedNodePointer& node){ if (node->getLinkedData() && !static_cast(node->getLinkedData())->getUsername().isEmpty()) { ++numConnectedAuthedUsers; } @@ -1471,7 +1474,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url QJsonObject assignedNodesJSON; // enumerate the NodeList to find the assigned nodes - NodeList::getInstance()->eachNode([this, &assignedNodesJSON](const SharedNodePointer& node){ + DependencyManager::get()->eachNode([this, &assignedNodesJSON](const SharedNodePointer& node){ DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); if (!nodeData->getAssignmentUUID().isNull()) { @@ -2066,7 +2069,7 @@ void DomainServer::addStaticAssignmentsToQueue() { // add any of the un-matched static assignments to the queue // enumerate the nodes and check if there is one with an attached assignment with matching UUID - if (!NodeList::getInstance()->nodeWithUUID(staticAssignment->data()->getUUID())) { + if (!DependencyManager::get()->nodeWithUUID(staticAssignment->data()->getUUID())) { // this assignment has not been fulfilled - reset the UUID and add it to the assignment queue refreshStaticAssignmentAndAddToQueue(*staticAssignment); } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eed3edcb34..b5fa221bc5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -239,8 +239,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _nodeThread->setPriority(QThread::TimeCriticalPriority); // put the NodeList and datagram processing on the node thread - NodeList* nodeList = NodeList::createInstance(NodeType::Agent, listenPort); - + auto nodeList = DependencyManager::set(NodeType::Agent, listenPort); + nodeList->moveToThread(_nodeThread); _datagramProcessor.moveToThread(_nodeThread); @@ -272,13 +272,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(locationUpdateTimer, &QTimer::timeout, this, &Application::updateLocationInServer); locationUpdateTimer->start(DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS); - connect(nodeList, &NodeList::nodeAdded, this, &Application::nodeAdded); - connect(nodeList, &NodeList::nodeKilled, this, &Application::nodeKilled); - connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); - connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer))); - connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer))); - connect(nodeList, &NodeList::uuidChanged, _myAvatar, &MyAvatar::setSessionUUID); - connect(nodeList, &NodeList::limitOfSilentDomainCheckInsReached, nodeList, &NodeList::reset); + connect(nodeList.data(), &NodeList::nodeAdded, this, &Application::nodeAdded); + connect(nodeList.data(), &NodeList::nodeKilled, this, &Application::nodeKilled); + connect(nodeList.data(), SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); + connect(nodeList.data(), SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer))); + connect(nodeList.data(), SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer))); + connect(nodeList.data(), &NodeList::uuidChanged, _myAvatar, &MyAvatar::setSessionUUID); + connect(nodeList.data(), &NodeList::limitOfSilentDomainCheckInsReached, nodeList.data(), &NodeList::reset); // connect to appropriate slots on AccountManager AccountManager& accountManager = AccountManager::getInstance(); @@ -340,7 +340,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // move the silentNodeTimer to the _nodeThread QTimer* silentNodeTimer = new QTimer(); - connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); + connect(silentNodeTimer, SIGNAL(timeout()), nodeList.data(), SLOT(removeSilentNodes())); silentNodeTimer->start(NODE_SILENCE_THRESHOLD_MSECS); silentNodeTimer->moveToThread(_nodeThread); @@ -812,7 +812,7 @@ void Application::controlledBroadcastToNodes(const QByteArray& packet, const Nod } // Perform the broadcast for one type - int nReceivingNodes = NodeList::getInstance()->broadcastToNodes(packet, NodeSet() << type); + int nReceivingNodes = DependencyManager::get()->broadcastToNodes(packet, NodeSet() << type); // Feed number of bytes to corresponding channel of the bandwidth meter, if any (done otherwise) BandwidthMeter::ChannelIndex channel; @@ -1449,7 +1449,7 @@ void Application::dropEvent(QDropEvent *event) { } void Application::sendPingPackets() { - QByteArray pingPacket = NodeList::getInstance()->constructPingPacket(); + QByteArray pingPacket = DependencyManager::get()->constructPingPacket(); controlledBroadcastToNodes(pingPacket, NodeSet() << NodeType::VoxelServer << NodeType::EntityServer << NodeType::AudioMixer << NodeType::AvatarMixer @@ -1475,7 +1475,7 @@ void Application::timer() { _timerStart.start(); // ask the node list to check in with the domain server - NodeList::getInstance()->sendDomainServerCheckIn(); + DependencyManager::get()->sendDomainServerCheckIn(); } void Application::idle() { @@ -1994,7 +1994,7 @@ void Application::init() { Leapmotion::init(); // fire off an immediate domain-server check in now that settings are loaded - NodeList::getInstance()->sendDomainServerCheckIn(); + DependencyManager::get()->sendDomainServerCheckIn(); // Set up VoxelSystem after loading preferences so we can get the desired max voxel count _voxels.setMaxVoxels(Menu::getInstance()->getMaxVoxels()); @@ -2464,7 +2464,7 @@ int Application::sendNackPackets() { char packet[MAX_PACKET_SIZE]; // iterates thru all nodes in NodeList - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->eachNode([&](const SharedNodePointer& node){ @@ -2563,7 +2563,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node int inViewServers = 0; int unknownJurisdictionServers = 0; - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->eachNode([&](const SharedNodePointer& node) { // only send to the NodeTypes that are serverType @@ -3636,7 +3636,7 @@ void Application::uploadModel(ModelType modelType) { void Application::updateWindowTitle(){ QString buildVersion = " (build " + applicationVersion() + ")"; - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); QString connectionStatus = nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED) "; QString username = AccountManager::getInstance().getAccountInfo().getUsername(); @@ -3663,7 +3663,7 @@ void Application::updateWindowTitle(){ void Application::updateLocationInServer() { AccountManager& accountManager = AccountManager::getInstance(); - DomainHandler& domainHandler = NodeList::getInstance()->getDomainHandler(); + DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler(); if (accountManager.isLoggedIn() && domainHandler.isConnected() && !domainHandler.getUUID().isNull()) { @@ -3689,14 +3689,14 @@ void Application::updateLocationInServer() { } void Application::changeDomainHostname(const QString &newDomainHostname) { - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); if (!nodeList->getDomainHandler().isCurrentHostname(newDomainHostname)) { // tell the MyAvatar object to send a kill packet so that it dissapears from its old avatar mixer immediately _myAvatar->sendKillAvatar(); // call the domain hostname change as a queued connection on the nodelist - QMetaObject::invokeMethod(&NodeList::getInstance()->getDomainHandler(), "setHostname", + QMetaObject::invokeMethod(&DependencyManager::get()->getDomainHandler(), "setHostname", Q_ARG(const QString&, newDomainHostname)); } } @@ -3733,7 +3733,7 @@ void Application::domainChanged(const QString& domainHostname) { void Application::connectedToDomain(const QString& hostname) { AccountManager& accountManager = AccountManager::getInstance(); - const QUuid& domainID = NodeList::getInstance()->getDomainHandler().getUUID(); + const QUuid& domainID = DependencyManager::get()->getDomainHandler().getUUID(); if (accountManager.isLoggedIn() && !domainID.isNull()) { // update our data-server with the domain-server we're logged in with @@ -4063,8 +4063,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri // when the application is about to quit, stop our script engine so it unwinds properly connect(this, SIGNAL(aboutToQuit()), scriptEngine, SLOT(stop())); - NodeList* nodeList = NodeList::getInstance(); - connect(nodeList, &NodeList::nodeKilled, scriptEngine, &ScriptEngine::nodeKilled); + auto nodeList = DependencyManager::get(); + connect(nodeList.data(), &NodeList::nodeKilled, scriptEngine, &ScriptEngine::nodeKilled); scriptEngine->moveToThread(workerThread); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 2511fb4480..d94819c0ea 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -847,7 +847,7 @@ void Audio::handleAudioInput() { _scopeInputOffset = addBufferToScope(_scopeInput, _scopeInputOffset, networkAudioSamples, NETWORK_SAMPLES_PER_FRAME, monoAudioChannel, numMonoAudioChannels); } - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); if (_recorder && _recorder.data()->isRecording()) { @@ -1086,7 +1086,7 @@ void Audio::sendDownstreamAudioStatsPacket() { dataAt += sizeof(AudioStreamStats); // send packet - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); nodeList->writeDatagram(packet, dataAt - packet, audioMixer); } @@ -1516,7 +1516,7 @@ void Audio::renderStats(const float* color, int width, int height) { float audioInputBufferLatency = 0.0f, inputRingBufferLatency = 0.0f, networkRoundtripLatency = 0.0f, mixerRingBufferLatency = 0.0f, outputRingBufferLatency = 0.0f, audioOutputBufferLatency = 0.0f; AudioStreamStats downstreamAudioStreamStats = _receivedAudioStream.getAudioStreamStats(); - SharedNodePointer audioMixerNodePointer = NodeList::getInstance()->soloNodeOfType(NodeType::AudioMixer); + SharedNodePointer audioMixerNodePointer = DependencyManager::get()->soloNodeOfType(NodeType::AudioMixer); if (!audioMixerNodePointer.isNull()) { audioInputBufferLatency = _audioInputMsecsReadStats.getWindowAverage(); inputRingBufferLatency = getInputRingBufferAverageMsecsAvailable(); diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 96680423ed..78530ed43f 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -34,9 +34,9 @@ void DatagramProcessor::processDatagrams() { static QByteArray incomingPacket; Application* application = Application::getInstance(); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); - while (NodeList::getInstance()->getNodeSocket().hasPendingDatagrams()) { + while (DependencyManager::get()->getNodeSocket().hasPendingDatagrams()) { incomingPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); nodeList->getNodeSocket().readDatagram(incomingPacket.data(), incomingPacket.size(), senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); @@ -102,7 +102,7 @@ void DatagramProcessor::processDatagrams() { qDebug("got an Octree data or erase message, sequence:%d flightTime:%d", sequence, flightTime); } - SharedNodePointer matchedNode = NodeList::getInstance()->sendingNodeForPacket(incomingPacket); + SharedNodePointer matchedNode = DependencyManager::get()->sendingNodeForPacket(incomingPacket); if (matchedNode) { // add this packet to our list of voxel packets and process them on the voxel processing diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index f0c2a687a4..f15339db51 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -708,7 +708,7 @@ void Menu::loadSettings(QSettings* settings) { Application::getInstance()->updateWindowTitle(); // notify that a settings has changed - connect(&NodeList::getInstance()->getDomainHandler(), &DomainHandler::hostnameChanged, this, &Menu::bumpSettings); + connect(&DependencyManager::get()->getDomainHandler(), &DomainHandler::hostnameChanged, this, &Menu::bumpSettings); // MyAvatar caches some menu options, so we have to update them whenever we load settings. // TODO: cache more settings in MyAvatar that are checked with very high frequency. @@ -1175,11 +1175,11 @@ void Menu::muteEnvironment() { QByteArray mutePacket(packet, packetSize); // grab our audio mixer from the NodeList, if it exists - SharedNodePointer audioMixer = NodeList::getInstance()->soloNodeOfType(NodeType::AudioMixer); + SharedNodePointer audioMixer = DependencyManager::get()->soloNodeOfType(NodeType::AudioMixer); if (audioMixer) { // send off this mute packet - NodeList::getInstance()->writeDatagram(mutePacket, audioMixer); + DependencyManager::get()->writeDatagram(mutePacket, audioMixer); } free(packet); @@ -1234,7 +1234,7 @@ void Menu::nameLocation() { return; } - DomainHandler& domainHandler = NodeList::getInstance()->getDomainHandler(); + DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler(); if (domainHandler.getUUID().isNull()) { const QString UNREGISTERED_DOMAIN_MESSAGE = "This domain is not registered with High Fidelity." "\n\nYou cannot create a global location in an unregistered domain."; diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 9a26ca6bb5..1368f42603 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -496,7 +496,7 @@ void MetavoxelSystem::render() { } void MetavoxelSystem::refreshVoxelData() { - NodeList::getInstance()->eachNode([](const SharedNodePointer& node){ + DependencyManager::get()->eachNode([](const SharedNodePointer& node){ if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelSystemClient* client = static_cast(node->getLinkedData()); @@ -819,7 +819,7 @@ MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) { } void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor, bool render) { - NodeList::getInstance()->eachNode([&visitor, &render](const SharedNodePointer& node){ + DependencyManager::get()->eachNode([&visitor, &render](const SharedNodePointer& node){ if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelSystemClient* client = static_cast(node->getLinkedData()); @@ -1045,7 +1045,7 @@ SendDelayer::SendDelayer(const SharedNodePointer& node, const QByteArray& data) } void SendDelayer::timerEvent(QTimerEvent* event) { - NodeList::getInstance()->writeDatagram(_data, _node); + DependencyManager::get()->writeDatagram(_data, _node); deleteLater(); } @@ -1068,7 +1068,7 @@ void MetavoxelSystemClient::sendDatagram(const QByteArray& data) { delayer->startTimer(delay); } else { - NodeList::getInstance()->writeDatagram(data, _node); + DependencyManager::get()->writeDatagram(data, _node); } Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::METAVOXELS).updateValue(data.size()); } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6b5d65fbfb..32677dfd30 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -918,7 +918,7 @@ int MyAvatar::parseDataAtOffset(const QByteArray& packet, int offset) { void MyAvatar::sendKillAvatar() { QByteArray killPacket = byteArrayWithPopulatedHeader(PacketTypeKillAvatar); - NodeList::getInstance()->broadcastToNodes(killPacket, NodeSet() << NodeType::AvatarMixer); + DependencyManager::get()->broadcastToNodes(killPacket, NodeSet() << NodeType::AvatarMixer); } void MyAvatar::updateLookAtTargetAvatar() { diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index ab85da125c..a0f1d03dc3 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -934,7 +934,7 @@ void ApplicationOverlay::renderStatsAndLogs() { } void ApplicationOverlay::renderDomainConnectionStatusBorder() { - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); if (nodeList && !nodeList->getDomainHandler().isConnected()) { GLCanvas::SharedPointer glCanvas = DependencyManager::get(); diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index d3fe742ea4..59882d0df8 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -48,7 +48,7 @@ void NodeBounds::draw() { glm::vec3 selectedCenter; float selectedScale = 0; - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->eachNode([&](const SharedNodePointer& node){ NodeType_t nodeType = node->getType(); diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index 403b8827bd..394d210e8a 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -247,7 +247,7 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser QLocale locale(QLocale::English); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->eachNode([&](const SharedNodePointer& node){ // only send to the NodeTypes that are NodeType_t_VOXEL_SERVER diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index e3b512adcc..60fed78fce 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -101,7 +101,7 @@ QFile* Snapshot::savedFileForSnapshot(bool isTemporary) { shot.setText(ORIENTATION_Z, QString::number(orientation.z)); shot.setText(ORIENTATION_W, QString::number(orientation.w)); - shot.setText(DOMAIN_KEY, NodeList::getInstance()->getDomainHandler().getHostname()); + shot.setText(DOMAIN_KEY, DependencyManager::get()->getDomainHandler().getHostname()); QString formattedLocation = QString("%1_%2_%3").arg(location.x).arg(location.y).arg(location.z); // replace decimal . with '-' diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index ab3927a3ab..1402ad53cf 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -218,7 +218,7 @@ void Stats::display( // we need to take one avatar out so we don't include ourselves int totalAvatars = Application::getInstance()->getAvatarManager().size() - 1; - int totalServers = NodeList::getInstance()->size(); + int totalServers = DependencyManager::get()->size(); lines = _expanded ? 5 : 3; int columnOneWidth = _generalStatsWidth; @@ -318,7 +318,7 @@ void Stats::display( if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) { int pingAudio = -1, pingAvatar = -1, pingVoxel = -1, pingVoxelMax = -1; - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer); SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer); @@ -423,7 +423,7 @@ void Stats::display( drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarBodyYaw, color); if (_expanded) { - SharedNodePointer avatarMixer = NodeList::getInstance()->soloNodeOfType(NodeType::AvatarMixer); + SharedNodePointer avatarMixer = DependencyManager::get()->soloNodeOfType(NodeType::AvatarMixer); if (avatarMixer) { sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps", roundf(avatarMixer->getAverageKilobitsPerSecond()), diff --git a/interface/src/voxels/OctreePacketProcessor.cpp b/interface/src/voxels/OctreePacketProcessor.cpp index 9f53492e70..dad8b5a2b1 100644 --- a/interface/src/voxels/OctreePacketProcessor.cpp +++ b/interface/src/voxels/OctreePacketProcessor.cpp @@ -51,7 +51,7 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode, // TODO: this does not look correct, the goal is to test the packet version for the piggyback, but // this is testing the version and hash of the original packet - if (!NodeList::getInstance()->packetVersionAndHashMatch(packet)) { + if (!DependencyManager::get()->packetVersionAndHashMatch(packet)) { return; // bail since piggyback data doesn't match our versioning } } else { diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index d31ab83976..89a9cf9d93 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -229,7 +229,7 @@ void AudioInjector::injectToMixer() { _audioData.data() + _currentSendPosition, bytesToCopy); // grab our audio mixer from the NodeList, if it exists - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); // send off this audio packet diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 95432bc81a..70a60c3a00 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1096,7 +1096,7 @@ void AvatarData::sendIdentityPacket() { QByteArray identityPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity); identityPacket.append(identityByteArray()); - NodeList::getInstance()->broadcastToNodes(identityPacket, NodeSet() << NodeType::AvatarMixer); + DependencyManager::get()->broadcastToNodes(identityPacket, NodeSet() << NodeType::AvatarMixer); } void AvatarData::sendBillboardPacket() { @@ -1104,7 +1104,7 @@ void AvatarData::sendBillboardPacket() { QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard); billboardPacket.append(_billboard); - NodeList::getInstance()->broadcastToNodes(billboardPacket, NodeSet() << NodeType::AvatarMixer); + DependencyManager::get()->broadcastToNodes(billboardPacket, NodeSet() << NodeType::AvatarMixer); } } diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 4f69eb2e3d..3d5af17ab9 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -18,7 +18,7 @@ AvatarHashMap::AvatarHashMap() : _avatarHash(), _lastOwnerSessionUUID() { - connect(NodeList::getInstance(), &NodeList::uuidChanged, this, &AvatarHashMap::sessionUUIDChanged); + connect(DependencyManager::get().data(), &NodeList::uuidChanged, this, &AvatarHashMap::sessionUUIDChanged); } diff --git a/libraries/avatars/src/Player.cpp b/libraries/avatars/src/Player.cpp index 9f01e98730..b215040666 100644 --- a/libraries/avatars/src/Player.cpp +++ b/libraries/avatars/src/Player.cpp @@ -63,7 +63,7 @@ void Player::startPlaying() { if (!isPaused()) { _currentContext.globalTimestamp = usecTimestampNow(); - _currentContext.domain = NodeList::getInstance()->getDomainHandler().getHostname(); + _currentContext.domain = DependencyManager::get()->getDomainHandler().getHostname(); _currentContext.position = _avatar->getPosition(); _currentContext.orientation = _avatar->getOrientation(); _currentContext.scale = _avatar->getTargetScale(); diff --git a/libraries/avatars/src/Recorder.cpp b/libraries/avatars/src/Recorder.cpp index b54c92744a..b90ded2e9a 100644 --- a/libraries/avatars/src/Recorder.cpp +++ b/libraries/avatars/src/Recorder.cpp @@ -42,7 +42,7 @@ void Recorder::startRecording() { RecordingContext& context = _recording->getContext(); context.globalTimestamp = usecTimestampNow(); - context.domain = NodeList::getInstance()->getDomainHandler().getHostname(); + context.domain = DependencyManager::get()->getDomainHandler().getHostname(); context.position = _avatar->getPosition(); context.orientation = _avatar->getOrientation(); context.scale = _avatar->getTargetScale(); diff --git a/libraries/avatars/src/Recording.cpp b/libraries/avatars/src/Recording.cpp index b39421d03a..437680c31a 100644 --- a/libraries/avatars/src/Recording.cpp +++ b/libraries/avatars/src/Recording.cpp @@ -670,7 +670,7 @@ RecordingPointer readRecordingFromRecFile(RecordingPointer recording, const QStr // Fake context RecordingContext& context = recording->getContext(); context.globalTimestamp = usecTimestampNow(); - context.domain = NodeList::getInstance()->getDomainHandler().getHostname(); + context.domain = DependencyManager::get()->getDomainHandler().getHostname(); context.position = glm::vec3(144.5f, 3.3f, 181.3f); context.orientation = glm::angleAxis(glm::radians(-92.5f), glm::vec3(0, 1, 0));; context.scale = baseFrame._scale; diff --git a/libraries/metavoxels/src/Endpoint.cpp b/libraries/metavoxels/src/Endpoint.cpp index 5a4e74ce08..a8a8f922cd 100644 --- a/libraries/metavoxels/src/Endpoint.cpp +++ b/libraries/metavoxels/src/Endpoint.cpp @@ -54,7 +54,7 @@ int Endpoint::parseData(const QByteArray& packet) { } void Endpoint::sendDatagram(const QByteArray& data) { - NodeList::getInstance()->writeDatagram(data, _node); + DependencyManager::get()->writeDatagram(data, _node); } void Endpoint::readMessage(Bitstream& in) { diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index dfc736edc9..0505dcf339 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -34,8 +34,10 @@ MetavoxelClientManager::~MetavoxelClientManager() { } void MetavoxelClientManager::init() { - connect(NodeList::getInstance(), &NodeList::nodeAdded, this, &MetavoxelClientManager::maybeAttachClient); - connect(NodeList::getInstance(), &NodeList::nodeKilled, this, &MetavoxelClientManager::maybeDeleteClient); + connect(DependencyManager::get().data(), &NodeList::nodeAdded, + this, &MetavoxelClientManager::maybeAttachClient); + connect(DependencyManager::get().data(), &NodeList::nodeKilled, + this, &MetavoxelClientManager::maybeDeleteClient); } SharedObjectPointer MetavoxelClientManager::findFirstRaySpannerIntersection(const glm::vec3& origin, @@ -43,7 +45,7 @@ SharedObjectPointer MetavoxelClientManager::findFirstRaySpannerIntersection(cons SharedObjectPointer closestSpanner; float closestDistance = FLT_MAX; - NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ + DependencyManager::get()->eachNode([&](const SharedNodePointer& node){ if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelClient* client = static_cast(node->getLinkedData()); @@ -185,7 +187,7 @@ MetavoxelClient* MetavoxelClientManager::createClient(const SharedNodePointer& n } void MetavoxelClientManager::guide(MetavoxelVisitor& visitor) { - NodeList::getInstance()->eachNode([&visitor](const SharedNodePointer& node){ + DependencyManager::get()->eachNode([&visitor](const SharedNodePointer& node){ if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelClient* client = static_cast(node->getLinkedData()); diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 81b3a1328b..14288de03d 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -35,7 +35,7 @@ AddressManager::AddressManager() : } bool AddressManager::isConnected() { - return NodeList::getInstance()->getDomainHandler().isConnected(); + return DependencyManager::get()->getDomainHandler().isConnected(); } const QUrl AddressManager::currentAddress() const { @@ -73,7 +73,7 @@ const QString AddressManager::currentPath(bool withOrientation) const { } QString AddressManager::getDomainID() const { - const QUuid& domainID = NodeList::getInstance()->getDomainHandler().getUUID(); + const QUuid& domainID = DependencyManager::get()->getDomainHandler().getUUID(); return domainID.isNull() ? "" : uuidStringWithoutCurlyBraces(domainID); } diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index 6091b0cdd2..76f8f2decd 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -198,7 +198,7 @@ void DomainHandler::setIsConnected(bool isConnected) { } void DomainHandler::requestDomainSettings() { - NodeType_t owningNodeType = NodeList::getInstance()->getOwnerType(); + NodeType_t owningNodeType = DependencyManager::get()->getOwnerType(); if (owningNodeType == NodeType::Agent) { // for now the agent nodes don't need any settings - this allows local assignment-clients // to connect to a domain that is using automatic networking (since we don't have TCP hole punch yet) @@ -212,7 +212,7 @@ void DomainHandler::requestDomainSettings() { settingsJSONURL.setHost(_hostname); settingsJSONURL.setPort(DOMAIN_SERVER_HTTP_PORT); settingsJSONURL.setPath("/settings.json"); - Assignment::Type assignmentType = Assignment::typeForNodeType(NodeList::getInstance()->getOwnerType()); + Assignment::Type assignmentType = Assignment::typeForNodeType(DependencyManager::get()->getOwnerType()); settingsJSONURL.setQuery(QString("type=%1").arg(assignmentType)); qDebug() << "Requesting domain-server settings at" << settingsJSONURL.toString(); diff --git a/libraries/networking/src/PacketSender.cpp b/libraries/networking/src/PacketSender.cpp index 3edfc47c04..f560d94b86 100644 --- a/libraries/networking/src/PacketSender.cpp +++ b/libraries/networking/src/PacketSender.cpp @@ -271,7 +271,7 @@ bool PacketSender::nonThreadedProcess() { unlock(); // send the packet through the NodeList... - NodeList::getInstance()->writeDatagram(temporary.getByteArray(), temporary.getNode()); + DependencyManager::get()->writeDatagram(temporary.getByteArray(), temporary.getNode()); packetsSentThisCall++; _packetsOverCheckInterval++; _totalPacketsSent++; diff --git a/libraries/networking/src/ThreadedAssignment.cpp b/libraries/networking/src/ThreadedAssignment.cpp index 52644a9a4e..21f520babb 100644 --- a/libraries/networking/src/ThreadedAssignment.cpp +++ b/libraries/networking/src/ThreadedAssignment.cpp @@ -32,7 +32,7 @@ void ThreadedAssignment::setFinished(bool isFinished) { if (_isFinished) { aboutToFinish(); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); // if we have a datagram processing thread, quit it and wait on it to make sure that // the node socket is back on the same thread as the NodeList @@ -43,7 +43,7 @@ void ThreadedAssignment::setFinished(bool isFinished) { _datagramProcessingThread->wait(); // set node socket parent back to NodeList - nodeList->getNodeSocket().setParent(nodeList); + nodeList->getNodeSocket().setParent(nodeList.data()); } // move the NodeList back to the QCoreApplication instance's thread @@ -57,7 +57,7 @@ void ThreadedAssignment::commonInit(const QString& targetName, NodeType_t nodeTy // change the logging target name while the assignment is running LogHandler::getInstance().setTargetName(targetName); - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->setOwnerType(nodeType); // this is a temp fix for Qt 5.3 - rebinding the node socket gives us readyRead for the socket on this thread @@ -68,7 +68,7 @@ void ThreadedAssignment::commonInit(const QString& targetName, NodeType_t nodeTy domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); QTimer* silentNodeRemovalTimer = new QTimer(this); - connect(silentNodeRemovalTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); + connect(silentNodeRemovalTimer, SIGNAL(timeout()), nodeList.data(), SLOT(removeSilentNodes())); silentNodeRemovalTimer->start(NODE_SILENCE_THRESHOLD_MSECS); if (shouldSendStats) { @@ -80,7 +80,7 @@ void ThreadedAssignment::commonInit(const QString& targetName, NodeType_t nodeTy } void ThreadedAssignment::addPacketStatsAndSendStatsPacket(QJsonObject &statsObject) { - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); float packetsPerSecond, bytesPerSecond; nodeList->getPacketStats(packetsPerSecond, bytesPerSecond); @@ -98,15 +98,15 @@ void ThreadedAssignment::sendStatsPacket() { } void ThreadedAssignment::checkInWithDomainServerOrExit() { - if (NodeList::getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) { + if (DependencyManager::get()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) { setFinished(true); } else { - NodeList::getInstance()->sendDomainServerCheckIn(); + DependencyManager::get()->sendDomainServerCheckIn(); } } bool ThreadedAssignment::readAvailableDatagram(QByteArray& destinationByteArray, HifiSockAddr& senderSockAddr) { - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); if (nodeList->getNodeSocket().hasPendingDatagrams()) { destinationByteArray.resize(nodeList->getNodeSocket().pendingDatagramSize()); diff --git a/libraries/octree/src/JurisdictionListener.cpp b/libraries/octree/src/JurisdictionListener.cpp index bcd5e9ac1c..c050e0bffe 100644 --- a/libraries/octree/src/JurisdictionListener.cpp +++ b/libraries/octree/src/JurisdictionListener.cpp @@ -20,10 +20,10 @@ JurisdictionListener::JurisdictionListener(NodeType_t type) : _nodeType(type), _packetSender(JurisdictionListener::DEFAULT_PACKETS_PER_SECOND) { - connect(NodeList::getInstance(), &NodeList::nodeKilled, this, &JurisdictionListener::nodeKilled); + connect(DependencyManager::get().data(), &NodeList::nodeKilled, this, &JurisdictionListener::nodeKilled); // tell our NodeList we want to hear about nodes with our node type - NodeList::getInstance()->addNodeTypeToInterestSet(type); + DependencyManager::get()->addNodeTypeToInterestSet(type); } void JurisdictionListener::nodeKilled(SharedNodePointer node) { @@ -38,7 +38,7 @@ bool JurisdictionListener::queueJurisdictionRequest() { int sizeOut = populatePacketHeader(reinterpret_cast(bufferOut), PacketTypeJurisdictionRequest); int nodeCount = 0; - NodeList::getInstance()->eachNode([&](const SharedNodePointer& node) { + DependencyManager::get()->eachNode([&](const SharedNodePointer& node) { if (node->getType() == getNodeType() && node->getActiveSocket()) { _packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast(bufferOut), sizeOut)); nodeCount++; diff --git a/libraries/octree/src/JurisdictionSender.cpp b/libraries/octree/src/JurisdictionSender.cpp index d78d883204..f85cf406b9 100644 --- a/libraries/octree/src/JurisdictionSender.cpp +++ b/libraries/octree/src/JurisdictionSender.cpp @@ -61,7 +61,7 @@ bool JurisdictionSender::process() { QUuid nodeUUID = _nodesRequestingJurisdictions.front(); _nodesRequestingJurisdictions.pop(); - SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(nodeUUID); + SharedNodePointer node = DependencyManager::get()->nodeWithUUID(nodeUUID); if (node && node->getActiveSocket()) { _packetSender.queuePacketForSending(node, QByteArray(reinterpret_cast(bufferOut), sizeOut)); diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index cae8919a64..cc47190228 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -52,7 +52,7 @@ bool OctreeEditPacketSender::serversExist() const { bool hasServers = false; bool atLeastOneJurisdictionMissing = false; // assume the best - NodeList::getInstance()->eachNodeBreakable([&](const SharedNodePointer& node){ + DependencyManager::get()->eachNodeBreakable([&](const SharedNodePointer& node){ if (node->getType() == getMyNodeType() && node->getActiveSocket()) { QUuid nodeUUID = node->getUUID(); @@ -85,7 +85,7 @@ void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned c size_t length, qint64 satoshiCost) { bool wantDebug = false; - NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ + DependencyManager::get()->eachNode([&](const SharedNodePointer& node){ // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType() && ((node->getUUID() == nodeUUID) || (nodeUUID.isNull())) @@ -192,7 +192,7 @@ void OctreeEditPacketSender::queuePacketToNodes(unsigned char* buffer, size_t le // for a different server... So we need to actually manage multiple queued packets... one // for each server - NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ + DependencyManager::get()->eachNode([&](const SharedNodePointer& node){ // only send to the NodeTypes that are getMyNodeType() if (node->getActiveSocket() && node->getType() == getMyNodeType()) { QUuid nodeUUID = node->getUUID(); @@ -245,7 +245,7 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, unsigned ch // for each server _packetsQueueLock.lock(); - NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ + DependencyManager::get()->eachNode([&](const SharedNodePointer& node){ // only send to the NodeTypes that are getMyNodeType() if (node->getActiveSocket() && node->getType() == getMyNodeType()) { QUuid nodeUUID = node->getUUID(); @@ -380,7 +380,7 @@ void OctreeEditPacketSender::processNackPacket(const QByteArray& packet) { // retrieve packet from history const QByteArray* packet = sentPacketHistory.getPacket(sequenceNumber); if (packet) { - const SharedNodePointer& node = NodeList::getInstance()->nodeWithUUID(sendingNodeUUID); + const SharedNodePointer& node = DependencyManager::get()->nodeWithUUID(sendingNodeUUID); queuePacketForSending(node, *packet); } } diff --git a/libraries/octree/src/OctreeHeadlessViewer.cpp b/libraries/octree/src/OctreeHeadlessViewer.cpp index e0ca22e4e8..8fe4fbd4d5 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.cpp +++ b/libraries/octree/src/OctreeHeadlessViewer.cpp @@ -77,7 +77,7 @@ void OctreeHeadlessViewer::queryOctree() { int inViewServers = 0; int unknownJurisdictionServers = 0; - NodeList::getInstance()->eachNode([&](const SharedNodePointer& node){ + DependencyManager::get()->eachNode([&](const SharedNodePointer& node){ // only send to the NodeTypes that are serverType if (node->getActiveSocket() && node->getType() == serverType) { totalServers++; @@ -140,7 +140,7 @@ void OctreeHeadlessViewer::queryOctree() { qDebug("perServerPPS: %d perUnknownServer: %d", perServerPPS, perUnknownServer); } - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->eachNode([&](const SharedNodePointer& node){ // only send to the NodeTypes that are serverType if (node->getActiveSocket() && node->getType() == serverType) { diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 7cd6ea07ee..979c56928b 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -359,7 +359,7 @@ void ScriptEngine::run() { int thisFrame = 0; - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); qint64 lastUpdate = usecTimestampNow(); @@ -483,7 +483,7 @@ void ScriptEngine::run() { } // write audio packet to AudioMixer nodes - NodeList* nodeList = NodeList::getInstance(); + auto nodeList = DependencyManager::get(); nodeList->eachNode([this, &nodeList, &audioPacket, &numPreSequenceNumberBytes](const SharedNodePointer& node){ // only send to nodes of type AudioMixer if (node->getType() == NodeType::AudioMixer) { From 95b0f2515b327e38cbd6d0dcb18b0b8a77d8b635 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 18 Dec 2014 00:32:11 +0100 Subject: [PATCH 011/159] this doesn't make `real sense` to me, perhaps this helps --- interface/src/devices/RealSense.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/RealSense.cpp b/interface/src/devices/RealSense.cpp index 5edb3aacee..c2591772d0 100644 --- a/interface/src/devices/RealSense.cpp +++ b/interface/src/devices/RealSense.cpp @@ -239,7 +239,7 @@ void RealSense::update() { } void RealSense::loadRSSDKFile() { - QString fileNameString = QFileDialog::getOpenFileName(Application::getInstance()->getGLWidget(), tr("Open RSSDK clip"), + QString fileNameString = QFileDialog::getOpenFileName(Application::getInstance()->getWindow(), tr("Open RSSDK clip"), NULL, tr("RSSDK Recordings (*.rssdk)")); if (!fileNameString.isEmpty()) { From 835e14a7b2190c807b95782939cf642378e91434 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 18 Dec 2014 00:52:31 +0100 Subject: [PATCH 012/159] This might solve it? --- interface/src/devices/RealSense.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/devices/RealSense.cpp b/interface/src/devices/RealSense.cpp index c2591772d0..aea7a50779 100644 --- a/interface/src/devices/RealSense.cpp +++ b/interface/src/devices/RealSense.cpp @@ -239,8 +239,9 @@ void RealSense::update() { } void RealSense::loadRSSDKFile() { + QString locationDir(QStandardPaths::displayName(QStandardPaths::DesktopLocation)); QString fileNameString = QFileDialog::getOpenFileName(Application::getInstance()->getWindow(), tr("Open RSSDK clip"), - NULL, + locationDir, tr("RSSDK Recordings (*.rssdk)")); if (!fileNameString.isEmpty()) { initSession(true, fileNameString); From 2884de1fe4f6493a888ce7601e7f97994fbe8b0d Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 18 Dec 2014 01:18:05 +0100 Subject: [PATCH 013/159] include fix --- interface/src/devices/RealSense.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/devices/RealSense.cpp b/interface/src/devices/RealSense.cpp index aea7a50779..f082f96949 100644 --- a/interface/src/devices/RealSense.cpp +++ b/interface/src/devices/RealSense.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "RealSense.h" +#include "MainWindow.h" #include "Menu.h" #include "SharedUtil.h" From aa0998dc7d6bd3a88b7905647867f9e028e23d11 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 18 Dec 2014 10:32:18 -0800 Subject: [PATCH 014/159] Moved LimitedNodeList into DM --- domain-server/src/DomainServer.cpp | 42 ++++++++++---------- libraries/networking/src/LimitedNodeList.cpp | 38 +++++------------- libraries/networking/src/LimitedNodeList.h | 10 ++--- libraries/networking/src/PacketHeaders.cpp | 2 +- libraries/shared/src/DependencyManager.h | 10 ++--- tests/metavoxels/src/MetavoxelTests.cpp | 2 +- 6 files changed, 42 insertions(+), 62 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index e6fcef62c1..3cd5d9f50b 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -237,7 +237,8 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { // check for scripts the user wants to persist from their domain-server config populateStaticScriptedAssignmentsFromSettings(); - LimitedNodeList* nodeList = LimitedNodeList::createInstance(domainServerPort, domainServerDTLSPort); + auto nodeList = DependencyManager::set(domainServerPort, + domainServerDTLSPort); // no matter the local port, save it to shared mem so that local assignment clients can ask what it is QSharedMemory* sharedPortMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); @@ -346,8 +347,7 @@ bool DomainServer::optionallySetupAssignmentPayment() { } void DomainServer::setupAutomaticNetworking() { - - LimitedNodeList* nodeList = LimitedNodeList::getInstance(); + auto nodeList = DependencyManager::get(); const int STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS = 10 * 1000; const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 30 * 1000; @@ -617,7 +617,7 @@ void DomainServer::handleConnectRequest(const QByteArray& packet, const HifiSock QByteArray usernameRequestByteArray = byteArrayWithPopulatedHeader(PacketTypeDomainConnectionDenied); // send this oauth request datagram back to the client - LimitedNodeList::getInstance()->writeUnverifiedDatagram(usernameRequestByteArray, senderSockAddr); + DependencyManager::get()->writeUnverifiedDatagram(usernameRequestByteArray, senderSockAddr); return; } @@ -637,7 +637,7 @@ void DomainServer::handleConnectRequest(const QByteArray& packet, const HifiSock } - SharedNodePointer newNode = LimitedNodeList::getInstance()->addOrUpdateNode(nodeUUID, nodeType, + SharedNodePointer newNode = DependencyManager::get()->addOrUpdateNode(nodeUUID, nodeType, publicSockAddr, localSockAddr); // when the newNode is created the linked data is also created // if this was a static assignment set the UUID, set the sendingSockAddr @@ -670,7 +670,7 @@ bool DomainServer::shouldAllowConnectionFromNode(const QString& username, QStringList allowedUsers = allowedUsersVariant ? allowedUsersVariant->toStringList() : QStringList(); // we always let in a user who is sending a packet from our local socket or from the localhost address - if (senderSockAddr.getAddress() == LimitedNodeList::getInstance()->getLocalSockAddr().getAddress() + if (senderSockAddr.getAddress() == DependencyManager::get()->getLocalSockAddr().getAddress() || senderSockAddr.getAddress() == QHostAddress::LocalHost) { return true; } @@ -843,8 +843,8 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif int numBroadcastPacketLeadBytes = broadcastDataStream.device()->pos(); DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); - - LimitedNodeList* nodeList = LimitedNodeList::getInstance(); + + auto nodeList = DependencyManager::get(); // if we've established a connection via ICE with this peer, use that socket // otherwise just try to reply back to them on their sending socket (although that may not work) @@ -910,7 +910,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif } void DomainServer::readAvailableDatagrams() { - LimitedNodeList* nodeList = LimitedNodeList::getInstance(); + auto nodeList = DependencyManager::get(); HifiSockAddr senderSockAddr; QByteArray receivedPacket; @@ -1112,7 +1112,7 @@ void DomainServer::transactionJSONCallback(const QJsonObject& data) { } void DomainServer::requestCurrentPublicSocketViaSTUN() { - LimitedNodeList::getInstance()->sendSTUNRequest(); + DependencyManager::get()->sendSTUNRequest(); } QJsonObject jsonForDomainSocketUpdate(const HifiSockAddr& socket) { @@ -1134,7 +1134,7 @@ void DomainServer::performIPAddressUpdate(const HifiSockAddr& newPublicSockAddr) void DomainServer::sendHeartbeatToDataServer(const QString& networkAddress) { const QString DOMAIN_UPDATE = "/api/v1/domains/%1"; - const QUuid& domainID = LimitedNodeList::getInstance()->getSessionUUID(); + const QUuid& domainID = DependencyManager::get()->getSessionUUID(); // setup the domain object to send to the data server const QString PUBLIC_NETWORK_ADDRESS_KEY = "network_address"; @@ -1187,11 +1187,11 @@ void DomainServer::performICEUpdates() { } void DomainServer::sendHeartbeatToIceServer() { - LimitedNodeList::getInstance()->sendHeartbeatToIceServer(_iceServerSocket); + DependencyManager::get()->sendHeartbeatToIceServer(_iceServerSocket); } void DomainServer::sendICEPingPackets() { - LimitedNodeList* nodeList = LimitedNodeList::getInstance(); + auto nodeList = DependencyManager::get(); QHash::iterator peer = _connectingICEPeers.begin(); @@ -1259,7 +1259,7 @@ void DomainServer::processICEPingReply(const QByteArray& packet, const HifiSockA } void DomainServer::processDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr) { - LimitedNodeList* nodeList = LimitedNodeList::getInstance(); + auto nodeList = DependencyManager::get(); if (nodeList->packetVersionAndHashMatch(receivedPacket)) { PacketType requestType = packetTypeForPacket(receivedPacket); @@ -1410,6 +1410,8 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url const QString UUID_REGEX_STRING = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; + auto nodeList = DependencyManager::get(); + // allow sub-handlers to handle requests that do not require authentication if (_settingsManager.handlePublicHTTPRequest(connection, url)) { return true; @@ -1452,7 +1454,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url const QString URI_ID = "/id"; if (connection->requestOperation() == QNetworkAccessManager::GetOperation && url.path() == URI_ID) { - QUuid domainID = LimitedNodeList::getInstance()->getSessionUUID(); + QUuid domainID = nodeList->getSessionUUID(); connection->respond(HTTPConnection::StatusCode200, uuidStringWithoutCurlyBraces(domainID).toLocal8Bit()); return true; @@ -1536,7 +1538,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url QJsonArray nodesJSONArray; // enumerate the NodeList to find the assigned nodes - LimitedNodeList::getInstance()->eachNode([this, &nodesJSONArray](const SharedNodePointer& node){ + nodeList->eachNode([this, &nodesJSONArray](const SharedNodePointer& node){ // add the node using the UUID as the key nodesJSONArray.append(jsonObjectForNode(node)); }); @@ -1559,7 +1561,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url QUuid matchingUUID = QUuid(nodeShowRegex.cap(1)); // see if we have a node that matches this ID - SharedNodePointer matchingNode = LimitedNodeList::getInstance()->nodeWithUUID(matchingUUID); + SharedNodePointer matchingNode = nodeList->nodeWithUUID(matchingUUID); if (matchingNode) { // create a QJsonDocument with the stats QJsonObject QJsonObject statsObject = @@ -1653,14 +1655,14 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url // pull the captured string, if it exists QUuid deleteUUID = QUuid(nodeDeleteRegex.cap(1)); - SharedNodePointer nodeToKill = LimitedNodeList::getInstance()->nodeWithUUID(deleteUUID); + SharedNodePointer nodeToKill = nodeList->nodeWithUUID(deleteUUID); if (nodeToKill) { // start with a 200 response connection->respond(HTTPConnection::StatusCode200); // we have a valid UUID and node - kill the node that has this assignment - QMetaObject::invokeMethod(LimitedNodeList::getInstance(), "killNodeWithUUID", Q_ARG(const QUuid&, deleteUUID)); + QMetaObject::invokeMethod(nodeList.data(), "killNodeWithUUID", Q_ARG(const QUuid&, deleteUUID)); // successfully processed request return true; @@ -1669,7 +1671,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url return true; } else if (allNodesDeleteRegex.indexIn(url.path()) != -1) { qDebug() << "Received request to kill all nodes."; - LimitedNodeList::getInstance()->eraseAllNodes(); + nodeList->eraseAllNodes(); return true; } diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index c6e79cc18f..827d7960ff 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -38,35 +38,6 @@ const char SOLO_NODE_TYPES[2] = { const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://data.highfidelity.io"); -std::auto_ptr LimitedNodeList::_sharedInstance; - -LimitedNodeList* LimitedNodeList::createInstance(unsigned short socketListenPort, unsigned short dtlsPort) { - NodeType::init(); - - if (_sharedInstance.get()) { - qDebug() << "LimitedNodeList called with existing instance." << - "Releasing auto_ptr, deleting existing instance and creating a new one."; - - delete _sharedInstance.release(); - } - - _sharedInstance = std::auto_ptr(new LimitedNodeList(socketListenPort, dtlsPort)); - - // register the SharedNodePointer meta-type for signals/slots - qRegisterMetaType(); - - return _sharedInstance.get(); -} - -LimitedNodeList* LimitedNodeList::getInstance() { - if (!_sharedInstance.get()) { - qDebug("LimitedNodeList getInstance called before call to createInstance. Returning NULL pointer."); - } - - return _sharedInstance.get(); -} - - LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short dtlsListenPort) : _sessionUUID(), _nodeHash(), @@ -79,6 +50,15 @@ LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short _numCollectedBytes(0), _packetStatTimer() { + static bool firstCall = true; + if (firstCall) { + NodeType::init(); + + // register the SharedNodePointer meta-type for signals/slots + qRegisterMetaType(); + firstCall = false; + } + _nodeSocket.bind(QHostAddress::AnyIPv4, socketListenPort); qDebug() << "NodeList socket is listening on" << _nodeSocket.localPort(); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 9fa9ed9d91..be09123901 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -69,10 +69,9 @@ namespace PingType { class LimitedNodeList : public QObject { Q_OBJECT + SINGLETON_DEPENDENCY(LimitedNodeList, true); + public: - static LimitedNodeList* createInstance(unsigned short socketListenPort = 0, unsigned short dtlsPort = 0); - static LimitedNodeList* getInstance(); - const QUuid& getSessionUUID() const { return _sessionUUID; } void setSessionUUID(const QUuid& sessionUUID); @@ -179,10 +178,9 @@ signals: void localSockAddrChanged(const HifiSockAddr& localSockAddr); void publicSockAddrChanged(const HifiSockAddr& publicSockAddr); + protected: - static std::auto_ptr _sharedInstance; - - LimitedNodeList(unsigned short socketListenPort, unsigned short dtlsListenPort); + LimitedNodeList(unsigned short socketListenPort = 0, unsigned short dtlsListenPort = 0); LimitedNodeList(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton void operator=(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 3f08cdec69..752bdc6b93 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -170,7 +170,7 @@ int populatePacketHeader(char* packet, PacketType type, const QUuid& connectionU char* position = packet + numTypeBytes + sizeof(PacketVersion); - QUuid packUUID = connectionUUID.isNull() ? LimitedNodeList::getInstance()->getSessionUUID() : connectionUUID; + QUuid packUUID = connectionUUID.isNull() ? DependencyManager::get()->getSessionUUID() : connectionUUID; QByteArray rfcUUID = packUUID.toRfc4122(); memcpy(position, rfcUUID.constData(), NUM_BYTES_RFC4122_UUID); diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index 8ed55edf68..93cebb8893 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -21,7 +21,7 @@ public:\ typedef QSharedPointer SharedPointer;\ typedef QWeakPointer WeakPointer;\ private:\ - static constexpr bool REQUIRE_SET = NEED_SET;\ + static const bool REQUIRE_SET = NEED_SET;\ void customDeleter() {\ QObject* thisObject = dynamic_cast(this);\ if (thisObject) {\ @@ -34,12 +34,12 @@ private:\ class QObject; +// usage: +// T* instance = DependencyManager::get(); +// T* instance = DependencyManager::set(Args... args); +// T* instance = DependencyManager::destroy(); class DependencyManager { public: - // usage: - // T* instance = DependencyManager::get(); - // T* instance = DependencyManager::set(Args... args); - // T* instance = DependencyManager::destroy(); template static QSharedPointer get(); diff --git a/tests/metavoxels/src/MetavoxelTests.cpp b/tests/metavoxels/src/MetavoxelTests.cpp index 0609d7bd01..106c56b0fe 100644 --- a/tests/metavoxels/src/MetavoxelTests.cpp +++ b/tests/metavoxels/src/MetavoxelTests.cpp @@ -440,7 +440,7 @@ static bool testSerialization(Bitstream::MetadataType metadataType) { } bool MetavoxelTests::run() { - LimitedNodeList::createInstance(); + DependencyManager::set(); // seed the random number generator so that our tests are reproducible srand(0xBAAAAABE); From f2847cec0699235321af4da102c579e3b5475054 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 18 Dec 2014 15:42:03 -0800 Subject: [PATCH 015/159] Changed Singleton Dependency macro and tweaked DM --- libraries/shared/src/DependencyManager.h | 32 ++++++++---------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index 93cebb8893..16d8ead9a8 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -16,27 +16,23 @@ #include -#define SINGLETON_DEPENDENCY(T, NEED_SET)\ -public:\ - typedef QSharedPointer SharedPointer;\ - typedef QWeakPointer WeakPointer;\ -private:\ - static const bool REQUIRE_SET = NEED_SET;\ - void customDeleter() {\ - QObject* thisObject = dynamic_cast(this);\ - if (thisObject) {\ - thisObject->deleteLater();\ - } else {\ - delete this;\ - }\ - }\ +#define SINGLETON_DEPENDENCY \ +private: \ + virtual void customDeleter() { \ + QObject* thisObject = dynamic_cast(this); \ + if (thisObject) { \ + thisObject->deleteLater(); \ + } else { \ + delete this; \ + } \ + } \ friend class DependencyManager; class QObject; // usage: // T* instance = DependencyManager::get(); -// T* instance = DependencyManager::set(Args... args); +// T* instance = DependencyManager::set(Args... args); // T* instance = DependencyManager::destroy(); class DependencyManager { public: @@ -56,12 +52,6 @@ private: template QSharedPointer DependencyManager::get() { - static bool requireSet = !T::REQUIRE_SET; - if (requireSet) { - set(); - requireSet = false; - } - return storage(); } From 296c0025de1eac4586406b0da044769e7c15d245 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 18 Dec 2014 15:42:38 -0800 Subject: [PATCH 016/159] Switched to auto and changed macro --- assignment-client/src/AssignmentClient.cpp | 2 +- domain-server/src/DomainServer.cpp | 3 +- interface/src/Application.cpp | 31 ++++++++++--------- interface/src/Camera.cpp | 2 +- interface/src/GLCanvas.h | 2 +- interface/src/Menu.cpp | 2 +- interface/src/MetavoxelSystem.cpp | 4 +-- interface/src/ModelUploader.cpp | 2 +- interface/src/Util.cpp | 2 +- interface/src/avatar/Head.cpp | 4 +-- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/avatar/SkeletonModel.cpp | 6 ++-- interface/src/devices/DdeFaceTracker.h | 2 +- interface/src/devices/Faceshift.h | 2 +- interface/src/devices/OculusManager.cpp | 4 +-- interface/src/devices/PrioVR.cpp | 2 +- interface/src/devices/SixenseManager.cpp | 2 +- interface/src/devices/TV3DManager.cpp | 4 +-- interface/src/devices/Visage.h | 2 +- .../ControllerScriptingInterface.cpp | 2 +- interface/src/ui/ApplicationOverlay.cpp | 20 ++++++------ interface/src/ui/PreferencesDialog.cpp | 2 +- interface/src/ui/Snapshot.cpp | 2 +- interface/src/ui/Stats.cpp | 8 ++--- libraries/animation/src/AnimationCache.h | 2 +- libraries/networking/src/LimitedNodeList.h | 4 ++- libraries/networking/src/NodeList.h | 2 +- .../render-utils/src/AmbientOcclusionEffect.h | 2 +- .../src/DeferredLightingEffect.cpp | 6 ++-- .../render-utils/src/DeferredLightingEffect.h | 2 +- libraries/render-utils/src/GeometryCache.cpp | 4 +-- libraries/render-utils/src/GeometryCache.h | 2 +- libraries/render-utils/src/GlowEffect.cpp | 2 +- libraries/render-utils/src/GlowEffect.h | 2 +- libraries/render-utils/src/Model.cpp | 4 +-- libraries/render-utils/src/Model.h | 2 +- libraries/render-utils/src/TextureCache.h | 2 +- 37 files changed, 76 insertions(+), 74 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 51bd32f41b..1eaa870a5b 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -93,7 +93,7 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : } // create a NodeList as an unassigned client - auto nodeList = DependencyManager::set(NodeType::Unassigned); + auto nodeList = DependencyManager::set(NodeType::Unassigned); quint16 assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT; diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 3cd5d9f50b..c3e2aecf7a 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -237,8 +237,7 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { // check for scripts the user wants to persist from their domain-server config populateStaticScriptedAssignmentsFromSettings(); - auto nodeList = DependencyManager::set(domainServerPort, - domainServerDTLSPort); + auto nodeList = DependencyManager::set(domainServerPort, domainServerDTLSPort); // no matter the local port, save it to shared mem so that local assignment clients can ask what it is QSharedMemory* sharedPortMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ff479aa241..63c7b2e05b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -191,9 +191,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _isVSyncOn(true), _aboutToQuit(false) { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::set(); 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); @@ -239,7 +240,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _nodeThread->setPriority(QThread::TimeCriticalPriority); // put the NodeList and datagram processing on the node thread - auto nodeList = DependencyManager::set(NodeType::Agent, listenPort); + auto nodeList = DependencyManager::set(NodeType::Agent, listenPort); nodeList->moveToThread(_nodeThread); _datagramProcessor.moveToThread(_nodeThread); @@ -1045,7 +1046,7 @@ void Application::keyPressEvent(QKeyEvent* event) { if (isShifted) { _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f); if (TV3DManager::isConnected()) { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); TV3DManager::configureCamera(_myCamera, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } } else { @@ -1058,7 +1059,7 @@ void Application::keyPressEvent(QKeyEvent* event) { if (isShifted) { _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f); if (TV3DManager::isConnected()) { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); TV3DManager::configureCamera(_myCamera, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } @@ -1531,7 +1532,7 @@ void Application::idle() { void Application::checkBandwidthMeterClick() { // ... to be called upon button release - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth) && Menu::getInstance()->isOptionChecked(MenuOption::Stats) && Menu::getInstance()->isOptionChecked(MenuOption::UserInterface) && @@ -1567,7 +1568,7 @@ void Application::setFullscreen(bool fullscreen) { } void Application::setEnable3DTVMode(bool enable3DTVMode) { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); resizeGL(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } @@ -1593,7 +1594,7 @@ void Application::setEnableVRMode(bool enableVRMode) { _myCamera.setHmdRotation(glm::quat()); } - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); resizeGL(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } @@ -1656,7 +1657,7 @@ glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVox bool Application::mouseOnScreen() const { if (OculusManager::isConnected()) { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); return getMouseX() >= 0 && getMouseX() <= glCanvas->getDeviceWidth() && getMouseY() >= 0 && getMouseY() <= glCanvas->getDeviceHeight(); } @@ -1698,9 +1699,9 @@ int Application::getMouseDragStartedY() const { } FaceTracker* Application::getActiveFaceTracker() { - Faceshift::SharedPointer faceshift = DependencyManager::get(); - Visage::SharedPointer visage = DependencyManager::get(); - DdeFaceTracker::SharedPointer dde = DependencyManager::get(); + auto faceshift = DependencyManager::get(); + auto visage = DependencyManager::get(); + auto dde = DependencyManager::get(); return (dde->isActive() ? static_cast(dde.data()) : (faceshift->isActive() ? static_cast(faceshift.data()) : @@ -2032,7 +2033,7 @@ void Application::init() { _metavoxels.init(); - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); _audio.init(glCanvas.data()); _rearMirrorTools = new RearMirrorTools(glCanvas.data(), _mirrorViewRect, _settings); @@ -2120,7 +2121,7 @@ void Application::updateMouseRay() { void Application::updateFaceshift() { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateFaceshift()"); - Faceshift::SharedPointer faceshift = DependencyManager::get(); + auto faceshift = DependencyManager::get(); // Update faceshift faceshift->update(); @@ -2925,7 +2926,7 @@ void Application::updateShadowMap() { fbo->release(); - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } @@ -3277,7 +3278,7 @@ bool Application::getCascadeShadowsEnabled() { } glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); float horizontalScale = glCanvas->getDeviceWidth() / 2.0f; float verticalScale = glCanvas->getDeviceHeight() / 2.0f; diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index b2fd30a1a6..14fa79d88b 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -95,7 +95,7 @@ void Camera::setFarClip(float f) { } PickRay Camera::computePickRay(float x, float y) { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); return computeViewPickRay(x / glCanvas->width(), y / glCanvas->height()); } diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index d9966714cc..f4981d16da 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -20,7 +20,7 @@ /// customized canvas that simply forwards requests/events to the singleton application class GLCanvas : public QGLWidget { Q_OBJECT - SINGLETON_DEPENDENCY(GLCanvas, false) + SINGLETON_DEPENDENCY public: bool isThrottleRendering() const; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index f15339db51..6524099c41 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1052,7 +1052,7 @@ void Menu::bumpSettings() { void sendFakeEnterEvent() { QPoint lastCursorPosition = QCursor::pos(); - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); QPoint windowPosition = glCanvas->mapFromGlobal(lastCursorPosition); QEnterEvent enterEvent = QEnterEvent(windowPosition, windowPosition, lastCursorPosition); diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 1368f42603..cceed8a3b2 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -1178,7 +1178,7 @@ void VoxelBuffer::render(bool cursor) { if (!_materials.isEmpty()) { _networkTextures.resize(_materials.size()); - TextureCache::SharedPointer textureCache = DependencyManager::get(); + auto textureCache = DependencyManager::get(); for (int i = 0; i < _materials.size(); i++) { const SharedObjectPointer material = _materials.at(i); if (material) { @@ -2233,7 +2233,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g const QVector& materials = node->getMaterial()->getMaterials(); _networkTextures.resize(materials.size()); - TextureCache::SharedPointer textureCache = DependencyManager::get(); + auto textureCache = DependencyManager::get(); for (int i = 0; i < materials.size(); i++) { const SharedObjectPointer& material = materials.at(i); if (material) { diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index 29d1596809..26afef8d7d 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -472,7 +472,7 @@ void ModelUploader::processCheck() { QString("Your model is now available in the browser."), QMessageBox::Ok); DependencyManager::get()->refresh(_url); - TextureCache::SharedPointer textureCache = DependencyManager::get(); + auto textureCache = DependencyManager::get(); foreach (const QByteArray& filename, _textureFilenames) { textureCache->refresh(_textureBase + filename); } diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 38f18e96d9..07f3e8b15f 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -71,7 +71,7 @@ void renderWorldBox() { glPushMatrix(); glTranslatef(MARKER_DISTANCE, 0, 0); glColor3fv(red); - GeometryCache::SharedPointer geometryCache = DependencyManager::get(); + auto geometryCache = DependencyManager::get(); geometryCache->renderSphere(MARKER_RADIUS, 10, 10); glPopMatrix(); glPushMatrix(); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 9c02b0e380..0f1217db78 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -78,8 +78,8 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { // Only use face trackers when not playing back a recording. if (!myAvatar->isPlaying()) { FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker(); - DdeFaceTracker::SharedPointer dde = DependencyManager::get(); - Faceshift::SharedPointer faceshift = DependencyManager::get(); + auto dde = DependencyManager::get(); + auto faceshift = DependencyManager::get(); if ((_isFaceshiftConnected = (faceshift == faceTracker))) { _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6d0ae6e199..2bacb0160b 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -422,7 +422,7 @@ void MyAvatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bo } void MyAvatar::renderHeadMouse(int screenWidth, int screenHeight) const { - Faceshift::SharedPointer faceshift = DependencyManager::get(); + auto faceshift = DependencyManager::get(); float pixelsPerDegree = screenHeight / Menu::getInstance()->getFieldOfView(); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index b707861677..2573902cb6 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -554,7 +554,7 @@ void SkeletonModel::renderRagdoll() { float radius1 = 0.008f; float radius2 = 0.01f; glm::vec3 simulationTranslation = _ragdoll->getTranslationInSimulationFrame(); - GeometryCache::SharedPointer geometryCache = DependencyManager::get(); + auto geometryCache = DependencyManager::get(); for (int i = 0; i < numPoints; ++i) { glPushMatrix(); // NOTE: ragdollPoints are in simulation-frame but we want them to be model-relative @@ -914,7 +914,7 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) { endPoint = endPoint - _translation; glTranslatef(endPoint.x, endPoint.y, endPoint.z); glColor4f(0.6f, 0.6f, 0.8f, alpha); - GeometryCache::SharedPointer geometryCache = DependencyManager::get(); + auto geometryCache = DependencyManager::get(); geometryCache->renderSphere(_boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS); // draw a yellow sphere at the capsule startpoint @@ -950,7 +950,7 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { continue; } - GeometryCache::SharedPointer geometryCache = DependencyManager::get(); + auto geometryCache = DependencyManager::get(); glPushMatrix(); // shapes are stored in simulation-frame but we want position to be model-relative diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 60a317e887..5ae17729d4 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -20,7 +20,7 @@ class DdeFaceTracker : public FaceTracker { Q_OBJECT - SINGLETON_DEPENDENCY(DdeFaceTracker, false) + SINGLETON_DEPENDENCY public: //initialization diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index 3587b3dfae..73971db49d 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -26,7 +26,7 @@ /// Handles interaction with the Faceshift software, which provides head position/orientation and facial features. class Faceshift : public FaceTracker { Q_OBJECT - SINGLETON_DEPENDENCY(Faceshift, false) + SINGLETON_DEPENDENCY public: void init(); diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 1854c9539d..387052219c 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -562,7 +562,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p } // restore our normal viewport - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); glMatrixMode(GL_PROJECTION); @@ -581,7 +581,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p void OculusManager::renderDistortionMesh(ovrPosef eyeRenderPose[ovrEye_Count]) { glLoadIdentity(); - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); gluOrtho2D(0, glCanvas->getDeviceWidth(), 0, glCanvas->getDeviceHeight()); glDisable(GL_DEPTH_TEST); diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp index 70c668a162..78b802ac9c 100644 --- a/interface/src/devices/PrioVR.cpp +++ b/interface/src/devices/PrioVR.cpp @@ -215,7 +215,7 @@ void PrioVR::renderCalibrationCountdown() { static TextRenderer* textRenderer = TextRenderer::getInstance(MONO_FONT_FAMILY, 18, QFont::Bold, false, TextRenderer::OUTLINE_EFFECT, 2); QByteArray text = "Assume T-Pose in " + QByteArray::number(secondsRemaining) + "..."; - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); textRenderer->draw((glCanvas->width() - textRenderer->computeWidth(text.constData())) / 2, glCanvas->height() / 2, text); diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index e2b4fedd50..fb9f5f74e9 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -461,7 +461,7 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers) void SixenseManager::emulateMouse(PalmData* palm, int index) { Application* application = Application::getInstance(); MyAvatar* avatar = application->getAvatar(); - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); QPoint pos; Qt::MouseButton bumperButton; diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index ff40329b6c..9af13c461e 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -35,7 +35,7 @@ bool TV3DManager::isConnected() { } void TV3DManager::connect() { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); int width = glCanvas->getDeviceWidth(); int height = glCanvas->getDeviceHeight(); Camera& camera = *Application::getInstance()->getCamera(); @@ -93,7 +93,7 @@ void TV3DManager::display(Camera& whichCamera) { // left eye portal int portalX = 0; int portalY = 0; - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); QSize deviceSize = glCanvas->getDeviceSize() * Application::getInstance()->getRenderResolutionScale(); int portalW = deviceSize.width() / 2; diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 6d8c87eef7..38e337aada 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -28,7 +28,7 @@ namespace VisageSDK { /// Handles input from the Visage webcam feature tracking software. class Visage : public FaceTracker { Q_OBJECT - SINGLETON_DEPENDENCY(Visage, false) + SINGLETON_DEPENDENCY public: void init(); diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 545de00d7d..f8b0a61487 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -268,7 +268,7 @@ void ControllerScriptingInterface::releaseJoystick(int joystickIndex) { } glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); return glm::vec2(glCanvas->width(), glCanvas->height()); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index a0f1d03dc3..f26e2b09c1 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -147,7 +147,7 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); Application* application = Application::getInstance(); Overlays& overlays = application->getOverlays(); - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); MyAvatar* myAvatar = application->getAvatar(); _textureFov = glm::radians(Menu::getInstance()->getOculusUIAngularSize()); @@ -215,7 +215,7 @@ void ApplicationOverlay::displayOverlayTexture() { if (_alpha == 0.0f) { return; } - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); @@ -380,7 +380,7 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as glEnd(); - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); if (_crosshairTexture == 0) { _crosshairTexture = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/sixense-reticle.png")); } @@ -434,7 +434,7 @@ void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& origi //Caculate the click location using one of the sixense controllers. Scale is not applied QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { Application* application = Application::getInstance(); - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); MyAvatar* myAvatar = application->getAvatar(); glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm); @@ -513,7 +513,7 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, //Renders optional pointers void ApplicationOverlay::renderPointers() { Application* application = Application::getInstance(); - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); //lazily load crosshair texture if (_crosshairTexture == 0) { @@ -561,7 +561,7 @@ void ApplicationOverlay::renderPointers() { void ApplicationOverlay::renderControllerPointers() { Application* application = Application::getInstance(); - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); MyAvatar* myAvatar = application->getAvatar(); //Static variables used for storing controller state @@ -706,7 +706,7 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { //Renders a small magnification of the currently bound texture at the coordinates void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) const { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); const int widgetWidth = glCanvas->width(); const int widgetHeight = glCanvas->height(); @@ -764,7 +764,7 @@ void ApplicationOverlay::renderAudioMeter() { Application* application = Application::getInstance(); - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); Audio* audio = application->getAudio(); // Display a single screen-size quad to create an alpha blended 'collision' flash @@ -895,7 +895,7 @@ void ApplicationOverlay::renderStatsAndLogs() { Application* application = Application::getInstance(); - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); const OctreePacketProcessor& octreePacketProcessor = application->getOctreePacketProcessor(); BandwidthMeter* bandwidthMeter = application->getBandwidthMeter(); NodeBounds& nodeBoundsDisplay = application->getNodeBoundsDisplay(); @@ -937,7 +937,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { auto nodeList = DependencyManager::get(); if (nodeList && !nodeList->getDomainHandler().isConnected()) { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); int right = glCanvas->width(); int bottom = glCanvas->height(); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 7baacd3d5a..096e2582fc 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -215,7 +215,7 @@ void PreferencesDialog::savePreferences() { myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value()); Application::getInstance()->getVoxels()->setMaxVoxels(ui.maxVoxelsSpin->value()); - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height()); Menu::getInstance()->setRealWorldFieldOfView(ui.realWorldFieldOfViewSpin->value()); diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 60fed78fce..3ea2a2fb2b 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -83,7 +83,7 @@ QTemporaryFile* Snapshot::saveTempSnapshot() { } QFile* Snapshot::savedFileForSnapshot(bool isTemporary) { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); QImage shot = glCanvas->grabFrameBuffer(); Avatar* avatar = Application::getInstance()->getAvatar(); diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 1402ad53cf..717c3c7492 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -56,7 +56,7 @@ Stats::Stats(): _metavoxelReceiveProgress(0), _metavoxelReceiveTotal(0) { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); resetWidth(glCanvas->width(), 0); } @@ -67,7 +67,7 @@ void Stats::toggleExpanded() { // called on mouse click release // check for clicks over stats in order to expand or contract them void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseDragStartedY, int horizontalOffset) { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); if (0 != glm::compMax(glm::abs(glm::ivec2(mouseX - mouseDragStartedX, mouseY - mouseDragStartedY)))) { // not worried about dragging on stats @@ -122,7 +122,7 @@ void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseD } void Stats::resetWidth(int width, int horizontalOffset) { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); int extraSpace = glCanvas->width() - horizontalOffset -2 - STATS_GENERAL_MIN_WIDTH - (Menu::getInstance()->isOptionChecked(MenuOption::TestPing) ? STATS_PING_MIN_WIDTH -1 : 0) @@ -198,7 +198,7 @@ void Stats::display( int bytesPerSecond, int voxelPacketsToProcess) { - GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + auto glCanvas = DependencyManager::get(); unsigned int backgroundColor = 0x33333399; int verticalOffset = 0, lines = 0; diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index 5bec0b8902..f2d4e7c233 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -26,7 +26,7 @@ typedef QSharedPointer AnimationPointer; /// Scriptable interface for FBX animation loading. class AnimationCache : public ResourceCache { Q_OBJECT - SINGLETON_DEPENDENCY(AnimationCache, false) + SINGLETON_DEPENDENCY public: Q_INVOKABLE AnimationPointer getAnimation(const QString& url) { return getAnimation(QUrl(url)); } diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index be09123901..525f65a70f 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -29,6 +29,8 @@ #include +#include + #include "DomainHandler.h" #include "Node.h" #include "UUIDHasher.h" @@ -69,7 +71,7 @@ namespace PingType { class LimitedNodeList : public QObject { Q_OBJECT - SINGLETON_DEPENDENCY(LimitedNodeList, true); + SINGLETON_DEPENDENCY public: const QUuid& getSessionUUID() const { return _sessionUUID; } diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 3a9ecf2405..6128c0f7c9 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -42,7 +42,7 @@ class Assignment; class NodeList : public LimitedNodeList { Q_OBJECT - SINGLETON_DEPENDENCY(NodeList, true) + SINGLETON_DEPENDENCY public: NodeType_t getOwnerType() const { return _ownerType; } diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index c1cfa031d4..29872fc487 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -20,7 +20,7 @@ class ProgramObject; /// A screen space ambient occlusion effect. See John Chapman's tutorial at /// http://john-chapman-graphics.blogspot.co.uk/2013/01/ssao-tutorial.html for reference. class AmbientOcclusionEffect { - SINGLETON_DEPENDENCY(AmbientOcclusionEffect, false) + SINGLETON_DEPENDENCY public: diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 14d383418f..56079b05b7 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -128,7 +128,7 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu void DeferredLightingEffect::prepare() { // clear the normal and specular buffers - TextureCache::SharedPointer textureCache = DependencyManager::get(); + auto textureCache = DependencyManager::get(); textureCache->setPrimaryDrawBuffers(false, true, false); glClear(GL_COLOR_BUFFER_BIT); textureCache->setPrimaryDrawBuffers(false, false, true); @@ -150,7 +150,7 @@ void DeferredLightingEffect::render() { glDisable(GL_COLOR_MATERIAL); glDepthMask(false); - TextureCache::SharedPointer textureCache = DependencyManager::get(); + auto textureCache = DependencyManager::get(); QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); primaryFBO->release(); @@ -247,7 +247,7 @@ void DeferredLightingEffect::render() { const glm::vec3& eyePoint = _viewState->getCurrentViewFrustum()->getPosition(); float nearRadius = glm::distance(eyePoint, _viewState->getCurrentViewFrustum()->getNearTopLeft()); - GeometryCache::SharedPointer geometryCache = DependencyManager::get(); + auto geometryCache = DependencyManager::get(); if (!_pointLights.isEmpty()) { _pointLight.bind(); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index f0f3df91f5..41cac328fb 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -24,7 +24,7 @@ class PostLightingRenderable; /// Handles deferred lighting for the bits that require it (voxels, metavoxels...) class DeferredLightingEffect { - SINGLETON_DEPENDENCY(DeferredLightingEffect, false) + SINGLETON_DEPENDENCY public: diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 56092945a2..b3dd50ea56 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -699,7 +699,7 @@ void NetworkGeometry::clearLoadPriority(const QPointer& owner) { void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& url) { if (_meshes.size() > 0) { - TextureCache::SharedPointer textureCache = DependencyManager::get(); + auto textureCache = DependencyManager::get(); for (int i = 0; i < _meshes.size(); i++) { NetworkMesh& mesh = _meshes[i]; for (int j = 0; j < mesh.parts.size(); j++) { @@ -914,7 +914,7 @@ void NetworkGeometry::reinsert() { void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { _geometry = geometry; - TextureCache::SharedPointer textureCache = DependencyManager::get(); + auto textureCache = DependencyManager::get(); foreach (const FBXMesh& mesh, _geometry.meshes) { NetworkMesh networkMesh; diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 44b7cda8ec..a2c7b197cd 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -34,7 +34,7 @@ class NetworkTexture; /// Stores cached geometry. class GeometryCache : public ResourceCache { Q_OBJECT - SINGLETON_DEPENDENCY(GeometryCache, false) + SINGLETON_DEPENDENCY public: void renderHemisphere(int slices, int stacks); diff --git a/libraries/render-utils/src/GlowEffect.cpp b/libraries/render-utils/src/GlowEffect.cpp index fb7189f61e..22eb9e1764 100644 --- a/libraries/render-utils/src/GlowEffect.cpp +++ b/libraries/render-utils/src/GlowEffect.cpp @@ -138,7 +138,7 @@ static void maybeRelease(QOpenGLFramebufferObject* fbo) { QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { PerformanceTimer perfTimer("glowEffect"); - TextureCache::SharedPointer textureCache = DependencyManager::get(); + auto textureCache = DependencyManager::get(); QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); primaryFBO->release(); glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); diff --git a/libraries/render-utils/src/GlowEffect.h b/libraries/render-utils/src/GlowEffect.h index 4828e1764e..40edf7ca93 100644 --- a/libraries/render-utils/src/GlowEffect.h +++ b/libraries/render-utils/src/GlowEffect.h @@ -27,7 +27,7 @@ class ProgramObject; /// A generic full screen glow effect. class GlowEffect : public QObject { Q_OBJECT - SINGLETON_DEPENDENCY(GlowEffect, false) + SINGLETON_DEPENDENCY public: diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 6d313bc7aa..51acc01ad9 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -2336,8 +2336,8 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod Locations* locations, SkinLocations* skinLocations) { PROFILE_RANGE(__FUNCTION__); - TextureCache::SharedPointer textureCache = DependencyManager::get(); - GlowEffect::SharedPointer glowEffect = DependencyManager::get(); + auto textureCache = DependencyManager::get(); + auto glowEffect = DependencyManager::get(); QString lastMaterialID; int meshPartsRendered = 0; updateVisibleJointStates(); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 1d4f20b617..f6e2de2b99 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -470,7 +470,7 @@ Q_DECLARE_METATYPE(QVector) /// Handle management of pending models that need blending class ModelBlender : public QObject { Q_OBJECT - SINGLETON_DEPENDENCY(ModelBlender, false) + SINGLETON_DEPENDENCY public: diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h index 6957fb0830..b8843c38bc 100644 --- a/libraries/render-utils/src/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -32,7 +32,7 @@ enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_T /// Stores cached textures, including render-to-texture targets. class TextureCache : public ResourceCache { Q_OBJECT - SINGLETON_DEPENDENCY(TextureCache, false) + SINGLETON_DEPENDENCY public: From f67df35f03f5597146da55d06ae917c7bdc9216c Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 19 Dec 2014 16:36:06 +0100 Subject: [PATCH 017/159] rssdk instructions --- interface/external/rssdk/readme.txt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 interface/external/rssdk/readme.txt diff --git a/interface/external/rssdk/readme.txt b/interface/external/rssdk/readme.txt new file mode 100644 index 0000000000..fe2246e32a --- /dev/null +++ b/interface/external/rssdk/readme.txt @@ -0,0 +1,9 @@ + +Instructions for adding the Intel Realsense (RSSDK) to Interface +Thijs Wenker, December 19, 2014 + +This is Windows only for now. + +1. Download the SDK at https://software.intel.com/en-us/intel-realsense-sdk/download + +2. Copy the `lib` and `include` folder inside this directory \ No newline at end of file From 8b0d859686e0f61589eae5db6f2c7cecc76094f2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 6 Jan 2015 15:54:07 -0800 Subject: [PATCH 018/159] Add method to access downloads information in JavaScript --- examples/example/downloadInfoExample.js | 25 +++++++++++ interface/src/Application.cpp | 1 + .../GlobalServicesScriptingInterface.cpp | 41 +++++++++++++++++++ .../GlobalServicesScriptingInterface.h | 14 +++++++ 4 files changed, 81 insertions(+) create mode 100644 examples/example/downloadInfoExample.js diff --git a/examples/example/downloadInfoExample.js b/examples/example/downloadInfoExample.js new file mode 100644 index 0000000000..399c83b5cf --- /dev/null +++ b/examples/example/downloadInfoExample.js @@ -0,0 +1,25 @@ +// +// downloadInfoExample.js +// examples/example +// +// Created by David Rowe on 5 Jan 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Display downloads information the same as in the stats. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// Get and log the current downloads info ... + +var downloadInfo, + downloadInfoString; + +downloadInfo = GlobalServices.getDownloadInfo(); +downloadInfoString = "Downloads: "; +if (downloadInfo.downloading.length > 0) { + downloadInfoString += downloadInfo.downloading.join("% ") + "% "; +} +downloadInfoString += "(" + downloadInfo.pending.toFixed(0) + " pending)"; +print(downloadInfoString); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bbcf90312e..776fef71ff 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3669,6 +3669,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Metavoxels", &_metavoxels); scriptEngine->registerGlobalObject("GlobalServices", GlobalServicesScriptingInterface::getInstance()); + qScriptRegisterMetaType(scriptEngine, DownloadInfoResultToScriptValue, DownloadInfoResultFromScriptValue); scriptEngine->registerGlobalObject("AvatarManager", &_avatarManager); diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.cpp b/interface/src/scripting/GlobalServicesScriptingInterface.cpp index 26fa7c564b..24c2008603 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.cpp +++ b/interface/src/scripting/GlobalServicesScriptingInterface.cpp @@ -11,6 +11,7 @@ #include "AccountManager.h" #include "XmppClient.h" +#include "ResourceCache.h" #include "GlobalServicesScriptingInterface.h" @@ -113,3 +114,43 @@ void GlobalServicesScriptingInterface::messageReceived(const QXmppMessage& messa emit GlobalServicesScriptingInterface::incomingMessage(message.from().right(message.from().count() - 1 - publicChatRoom->jid().count()), message.body()); } #endif // HAVE_QXMPP + +DownloadInfoResult GlobalServicesScriptingInterface::getDownloadInfo() { + DownloadInfoResult result; + foreach(Resource* resource, ResourceCache::getLoadingRequests()) { + result.downloading.append(resource->getProgress() * 100.0f); + } + result.pending = ResourceCache::getPendingRequestCount(); + + return result; +} + + +DownloadInfoResult::DownloadInfoResult() : + downloading(QList()), + pending(0.0f) +{ +} + +QScriptValue DownloadInfoResultToScriptValue(QScriptEngine* engine, const DownloadInfoResult& result) { + QScriptValue object = engine->newObject(); + + QScriptValue array = engine->newArray(result.downloading.count()); + for (int i = 0; i < result.downloading.count(); i += 1) { + array.setProperty(i, result.downloading[i]); + } + + object.setProperty("downloading", array); + object.setProperty("pending", result.pending); + return object; +} + +void DownloadInfoResultFromScriptValue(const QScriptValue& object, DownloadInfoResult& result) { + QList downloading = object.property("downloading").toVariant().toList(); + result.downloading.clear(); + for (int i = 0; i < downloading.count(); i += 1) { + result.downloading.append(downloading[i].toFloat()); + } + + result.pending = object.property("pending").toVariant().toFloat(); +} diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.h b/interface/src/scripting/GlobalServicesScriptingInterface.h index 44b2f7c1bf..2e189a9a69 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.h +++ b/interface/src/scripting/GlobalServicesScriptingInterface.h @@ -26,6 +26,19 @@ #endif // HAVE_QXMPP +class DownloadInfoResult { +public: + DownloadInfoResult(); + QList downloading; // List of percentages + float pending; +}; + +Q_DECLARE_METATYPE(DownloadInfoResult) + +QScriptValue DownloadInfoResultToScriptValue(QScriptEngine* engine, const DownloadInfoResult& result); +void DownloadInfoResultFromScriptValue(const QScriptValue& object, DownloadInfoResult& result); + + class GlobalServicesScriptingInterface : public QObject { Q_OBJECT Q_PROPERTY(bool isConnected READ isConnected) @@ -42,6 +55,7 @@ public: public slots: QScriptValue chat(const QString& message); + DownloadInfoResult getDownloadInfo(); private slots: void loggedOut(); From 40274df2791689eeaf956673fcebb1e8262b62bd Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 7 Jan 2015 11:20:46 -0800 Subject: [PATCH 019/159] Add downloads information changed event for JavaScript --- examples/example/downloadInfoExample.js | 57 ++++++++++++++++--- .../GlobalServicesScriptingInterface.cpp | 40 +++++++++---- .../GlobalServicesScriptingInterface.h | 6 ++ 3 files changed, 84 insertions(+), 19 deletions(-) diff --git a/examples/example/downloadInfoExample.js b/examples/example/downloadInfoExample.js index 399c83b5cf..19995503bc 100644 --- a/examples/example/downloadInfoExample.js +++ b/examples/example/downloadInfoExample.js @@ -11,15 +11,56 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +var downloadInfo, + downloadInfoOverlay; + +function formatInfo(info) { + var string = "Downloads: ", + i; + + for (i = 0; i < info.downloading.length; i += 1) { + string += info.downloading[i].toFixed(0) + "% "; + } + + string += "(" + info.pending.toFixed(0) + " pending)"; + + return string; +} + + // Get and log the current downloads info ... -var downloadInfo, - downloadInfoString; - downloadInfo = GlobalServices.getDownloadInfo(); -downloadInfoString = "Downloads: "; -if (downloadInfo.downloading.length > 0) { - downloadInfoString += downloadInfo.downloading.join("% ") + "% "; +print(formatInfo(downloadInfo)); + + +// Display and update the downloads info in an overlay ... + +function setUp() { + downloadInfoOverlay = Overlays.addOverlay("text", { + x: 300, + y: 200, + width: 300, + height: 50, + color: { red: 255, green: 255, blue: 255 }, + alpha: 1.0, + backgroundColor: { red: 127, green: 127, blue: 127 }, + backgroundAlpha: 0.5, + topMargin: 15, + leftMargin: 20, + text: "" + }); } -downloadInfoString += "(" + downloadInfo.pending.toFixed(0) + " pending)"; -print(downloadInfoString); + +function updateInfo(info) { + Overlays.editOverlay(downloadInfoOverlay, { text: formatInfo(info) }); +} + +function tearDown() { + Overlays.deleteOverlay(downloadInfoOverlay); +} + +setUp(); +GlobalServices.downloadInfoChanged.connect(updateInfo); +GlobalServices.updateDownloadInfo(); +Script.scriptEnding.connect(tearDown); diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.cpp b/interface/src/scripting/GlobalServicesScriptingInterface.cpp index 24c2008603..94777acbc0 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.cpp +++ b/interface/src/scripting/GlobalServicesScriptingInterface.cpp @@ -10,8 +10,9 @@ // #include "AccountManager.h" -#include "XmppClient.h" +#include "Application.h" #include "ResourceCache.h" +#include "XmppClient.h" #include "GlobalServicesScriptingInterface.h" @@ -26,6 +27,9 @@ GlobalServicesScriptingInterface::GlobalServicesScriptingInterface() { const QXmppClient& qxmppClient = XmppClient::getInstance().getXMPPClient(); connect(&qxmppClient, &QXmppClient::messageReceived, this, &GlobalServicesScriptingInterface::messageReceived); #endif // HAVE_QXMPP + + _downloading = false; + connect(Application::getInstance(), &Application::renderingInWorldInterface, this, &GlobalServicesScriptingInterface::checkDownloadInfo); } GlobalServicesScriptingInterface::~GlobalServicesScriptingInterface() { @@ -115,16 +119,6 @@ void GlobalServicesScriptingInterface::messageReceived(const QXmppMessage& messa } #endif // HAVE_QXMPP -DownloadInfoResult GlobalServicesScriptingInterface::getDownloadInfo() { - DownloadInfoResult result; - foreach(Resource* resource, ResourceCache::getLoadingRequests()) { - result.downloading.append(resource->getProgress() * 100.0f); - } - result.pending = ResourceCache::getPendingRequestCount(); - - return result; -} - DownloadInfoResult::DownloadInfoResult() : downloading(QList()), @@ -154,3 +148,27 @@ void DownloadInfoResultFromScriptValue(const QScriptValue& object, DownloadInfoR result.pending = object.property("pending").toVariant().toFloat(); } + +DownloadInfoResult GlobalServicesScriptingInterface::getDownloadInfo() { + DownloadInfoResult result; + foreach(Resource* resource, ResourceCache::getLoadingRequests()) { + result.downloading.append(resource->getProgress() * 100.0f); + } + result.pending = ResourceCache::getPendingRequestCount(); + return result; +} + +void GlobalServicesScriptingInterface::checkDownloadInfo() { + DownloadInfoResult downloadInfo = getDownloadInfo(); + bool downloading = downloadInfo.downloading.count() > 0 || downloadInfo.pending > 0; + + // Emit signal if downloading or have just finished. + if (downloading || _downloading) { + _downloading = downloading; + emit downloadInfoChanged(downloadInfo); + } +} + +void GlobalServicesScriptingInterface::updateDownloadInfo() { + emit downloadInfoChanged(getDownloadInfo()); +} diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.h b/interface/src/scripting/GlobalServicesScriptingInterface.h index 2e189a9a69..657cb945c5 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.h +++ b/interface/src/scripting/GlobalServicesScriptingInterface.h @@ -56,6 +56,7 @@ public: public slots: QScriptValue chat(const QString& message); DownloadInfoResult getDownloadInfo(); + void updateDownloadInfo(); private slots: void loggedOut(); @@ -64,6 +65,7 @@ private slots: #ifdef HAVE_QXMPP void messageReceived(const QXmppMessage& message); #endif // HAVE_QXMPP + void checkDownloadInfo(); signals: void connected(); @@ -71,6 +73,10 @@ signals: void incomingMessage(const QString& username, const QString& message); void onlineUsersChanged(const QStringList& usernames); void myUsernameChanged(const QString& username); + void downloadInfoChanged(DownloadInfoResult info); + +private: + bool _downloading; }; #endif // hifi_GlobalServicesScriptingInterface_h From 6c4932f9d0034c210a379d99cb8f631204650377 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 7 Jan 2015 11:24:10 -0800 Subject: [PATCH 020/159] Coding standard --- .../scripting/GlobalServicesScriptingInterface.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.cpp b/interface/src/scripting/GlobalServicesScriptingInterface.cpp index 94777acbc0..1cceec0e01 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.cpp +++ b/interface/src/scripting/GlobalServicesScriptingInterface.cpp @@ -29,7 +29,8 @@ GlobalServicesScriptingInterface::GlobalServicesScriptingInterface() { #endif // HAVE_QXMPP _downloading = false; - connect(Application::getInstance(), &Application::renderingInWorldInterface, this, &GlobalServicesScriptingInterface::checkDownloadInfo); + connect(Application::getInstance(), &Application::renderingInWorldInterface, + this, &GlobalServicesScriptingInterface::checkDownloadInfo); } GlobalServicesScriptingInterface::~GlobalServicesScriptingInterface() { @@ -43,14 +44,16 @@ GlobalServicesScriptingInterface::~GlobalServicesScriptingInterface() { const QXmppClient& qxmppClient = XmppClient::getInstance().getXMPPClient(); disconnect(&qxmppClient, &QXmppClient::messageReceived, this, &GlobalServicesScriptingInterface::messageReceived); const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); - disconnect(publicChatRoom, &QXmppMucRoom::participantsChanged, this, &GlobalServicesScriptingInterface::participantsChanged); + disconnect(publicChatRoom, &QXmppMucRoom::participantsChanged, + this, &GlobalServicesScriptingInterface::participantsChanged); #endif // HAVE_QXMPP } void GlobalServicesScriptingInterface::onConnected() { #ifdef HAVE_QXMPP const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); - connect(publicChatRoom, &QXmppMucRoom::participantsChanged, this, &GlobalServicesScriptingInterface::participantsChanged, Qt::UniqueConnection); + connect(publicChatRoom, &QXmppMucRoom::participantsChanged, + this, &GlobalServicesScriptingInterface::participantsChanged, Qt::UniqueConnection); #endif // HAVE_QXMPP } @@ -115,7 +118,8 @@ void GlobalServicesScriptingInterface::messageReceived(const QXmppMessage& messa return; } const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); - emit GlobalServicesScriptingInterface::incomingMessage(message.from().right(message.from().count() - 1 - publicChatRoom->jid().count()), message.body()); + QString username = message.from().right(message.from().count() - 1 - publicChatRoom->jid().count()); + emit GlobalServicesScriptingInterface::incomingMessage(username, message.body()); } #endif // HAVE_QXMPP From a46080cbf2889818c5e33d6e9be6a2f24320f574 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 8 Jan 2015 11:23:20 -0800 Subject: [PATCH 021/159] editModels > hydraGrab --- examples/editModels.js | 3043 ---------------------------------------- examples/hydraGrab.js | 742 ++++++++++ 2 files changed, 742 insertions(+), 3043 deletions(-) delete mode 100644 examples/editModels.js create mode 100644 examples/hydraGrab.js diff --git a/examples/editModels.js b/examples/editModels.js deleted file mode 100644 index 8ec099650a..0000000000 --- a/examples/editModels.js +++ /dev/null @@ -1,3043 +0,0 @@ -// -// editEntities.js -// examples -// -// Created by Clément Brisset on 4/24/14. -// Copyright 2014 High Fidelity, Inc. -// -// This script allows you to edit models either with the razor hydras or with your mouse -// -// If using the hydras : -// grab grab models with the triggers, you can then move the models around or scale them with both hands. -// You can switch mode using the bumpers so that you can move models around more easily. -// -// If using the mouse : -// - left click lets you move the model in the plane facing you. -// If pressing shift, it will move on the horizontal plane it's in. -// - right click lets you rotate the model. z and x give access to more axes of rotation while shift provides finer control. -// - left + right click lets you scale the model. -// - you can press r while holding the model to reset its rotation -// -// 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/globals.js"); -Script.include("libraries/toolBars.js"); - -Script.include("libraries/entityPropertyDialogBox.js"); -var entityPropertyDialogBox = EntityPropertyDialogBox; - -var windowDimensions = Controller.getViewportDimensions(); -var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; -var toolHeight = 50; -var toolWidth = 50; - -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; -var allowSmallModels = false; -var wantEntityGlow = false; - -var LEFT = 0; -var RIGHT = 1; - -var SPAWN_DISTANCE = 1; -var DEFAULT_DIMENSION = 0.20; -var DEFAULT_TEXT_DIMENSION_X = 1.0; -var DEFAULT_TEXT_DIMENSION_Y = 1.0; -var DEFAULT_TEXT_DIMENSION_Z = 0.01; - -var modelURLs = [ - HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Alder.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Bush1.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Bush6.fbx", - HIFI_PUBLIC_BUCKET + "meshes/newInvader16x16-large-purple.svo", - HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed2.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed4.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed7.fbx" - ]; - -var jointList = MyAvatar.getJointNames(); - -var mode = 0; -var isActive = false; - - -if (typeof String.prototype.fileName !== "function") { - String.prototype.fileName = function () { - return this.replace(/^(.*[\/\\])*/, ""); - }; -} - -if (typeof String.prototype.fileBase !== "function") { - String.prototype.fileBase = function () { - var filename = this.fileName(); - return filename.slice(0, filename.indexOf(".")); - }; -} - -if (typeof String.prototype.fileType !== "function") { - String.prototype.fileType = function () { - return this.slice(this.lastIndexOf(".") + 1); - }; -} - -if (typeof String.prototype.path !== "function") { - String.prototype.path = function () { - return this.replace(/[\\\/][^\\\/]*$/, ""); - }; -} - -if (typeof String.prototype.regExpEscape !== "function") { - String.prototype.regExpEscape = function () { - return this.replace(/([$\^.+*?|\\\/{}()\[\]])/g, '\\$1'); - }; -} - -if (typeof String.prototype.toArrayBuffer !== "function") { - String.prototype.toArrayBuffer = function () { - var length, - buffer, - view, - charCode, - charCodes, - i; - - charCodes = []; - - length = this.length; - for (i = 0; i < length; i += 1) { - charCode = this.charCodeAt(i); - if (charCode <= 255) { - charCodes.push(charCode); - } else { - charCodes.push(charCode / 256); - charCodes.push(charCode % 256); - } - } - - length = charCodes.length; - buffer = new ArrayBuffer(length); - view = new Uint8Array(buffer); - for (i = 0; i < length; i += 1) { - view[i] = charCodes[i]; - } - - return buffer; - }; -} - -if (typeof DataView.prototype.indexOf !== "function") { - DataView.prototype.indexOf = function (searchString, position) { - var searchLength = searchString.length, - byteArrayLength = this.byteLength, - maxSearchIndex = byteArrayLength - searchLength, - searchCharCodes = [], - found, - i, - j; - - searchCharCodes[searchLength] = 0; - for (j = 0; j < searchLength; j += 1) { - searchCharCodes[j] = searchString.charCodeAt(j); - } - - i = position; - found = false; - while (i < maxSearchIndex && !found) { - j = 0; - while (j < searchLength && this.getUint8(i + j) === searchCharCodes[j]) { - j += 1; - } - found = (j === searchLength); - i += 1; - } - - return found ? i - 1 : -1; - }; -} - -if (typeof DataView.prototype.string !== "function") { - DataView.prototype.string = function (start, length) { - var charCodes = [], - end, - i; - - if (start === undefined) { - start = 0; - } - if (length === undefined) { - length = this.length; - } - - end = start + length; - for (i = start; i < end; i += 1) { - charCodes.push(this.getUint8(i)); - } - - return String.fromCharCode.apply(String, charCodes); - }; -} - -var progressDialog = (function () { - var that = {}, - progressBackground, - progressMessage, - cancelButton, - displayed = false, - backgroundWidth = 300, - backgroundHeight = 100, - messageHeight = 32, - cancelWidth = 70, - cancelHeight = 32, - textColor = { red: 255, green: 255, blue: 255 }, - textBackground = { red: 52, green: 52, blue: 52 }, - backgroundUrl = toolIconUrl + "progress-background.svg", - windowDimensions; - - progressBackground = Overlays.addOverlay("image", { - width: backgroundWidth, - height: backgroundHeight, - imageURL: backgroundUrl, - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - progressMessage = Overlays.addOverlay("text", { - width: backgroundWidth - 40, - height: messageHeight, - text: "", - textColor: textColor, - backgroundColor: textBackground, - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - cancelButton = Overlays.addOverlay("text", { - width: cancelWidth, - height: cancelHeight, - text: "Cancel", - textColor: textColor, - backgroundColor: textBackground, - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - function move() { - var progressX, - progressY; - - if (displayed) { - - if (windowDimensions.x === Window.innerWidth && windowDimensions.y === Window.innerHeight) { - return; - } - windowDimensions.x = Window.innerWidth; - windowDimensions.y = Window.innerHeight; - - progressX = (windowDimensions.x - backgroundWidth) / 2; // Center. - progressY = windowDimensions.y / 2 - backgroundHeight; // A little up from center. - - Overlays.editOverlay(progressBackground, { x: progressX, y: progressY }); - Overlays.editOverlay(progressMessage, { x: progressX + 20, y: progressY + 15 }); - Overlays.editOverlay(cancelButton, { - x: progressX + backgroundWidth - cancelWidth - 20, - y: progressY + backgroundHeight - cancelHeight - 15 - }); - } - } - that.move = move; - - that.onCancel = undefined; - - function open(message) { - if (!displayed) { - windowDimensions = { x: 0, y : 0 }; - displayed = true; - move(); - Overlays.editOverlay(progressBackground, { visible: true }); - Overlays.editOverlay(progressMessage, { visible: true, text: message }); - Overlays.editOverlay(cancelButton, { visible: true }); - } else { - throw new Error("open() called on progressDialog when already open"); - } - } - that.open = open; - - function isOpen() { - return displayed; - } - that.isOpen = isOpen; - - function update(message) { - if (displayed) { - Overlays.editOverlay(progressMessage, { text: message }); - } else { - throw new Error("update() called on progressDialog when not open"); - } - } - that.update = update; - - function close() { - if (displayed) { - Overlays.editOverlay(cancelButton, { visible: false }); - Overlays.editOverlay(progressMessage, { visible: false }); - Overlays.editOverlay(progressBackground, { visible: false }); - displayed = false; - } else { - throw new Error("close() called on progressDialog when not open"); - } - } - that.close = close; - - function mousePressEvent(event) { - if (Overlays.getOverlayAtPoint({ x: event.x, y: event.y }) === cancelButton) { - if (typeof this.onCancel === "function") { - close(); - this.onCancel(); - } - return true; - } - return false; - } - that.mousePressEvent = mousePressEvent; - - function cleanup() { - Overlays.deleteOverlay(cancelButton); - Overlays.deleteOverlay(progressMessage); - Overlays.deleteOverlay(progressBackground); - } - that.cleanup = cleanup; - - return that; -}()); - -var httpMultiPart = (function () { - var that = {}, - parts, - byteLength, - boundaryString, - crlf; - - function clear() { - boundaryString = "--boundary_" + String(Uuid.generate()).slice(1, 36) + "="; - parts = []; - byteLength = 0; - crlf = ""; - } - that.clear = clear; - - function boundary() { - return boundaryString.slice(2); - } - that.boundary = boundary; - - function length() { - return byteLength; - } - that.length = length; - - function add(object) { - // - name, string - // - name, buffer - var buffer, - string, - stringBuffer, - compressedBuffer; - - if (object.name === undefined) { - - throw new Error("Item to add to HttpMultiPart must have a name"); - - } else if (object.string !== undefined) { - //--= - //Content-Disposition: form-data; name="model_name" - // - // - - string = crlf + boundaryString + "\r\n" - + "Content-Disposition: form-data; name=\"" + object.name + "\"\r\n" - + "\r\n" - + object.string; - buffer = string.toArrayBuffer(); - - } else if (object.buffer !== undefined) { - //--= - //Content-Disposition: form-data; name="fbx"; filename="" - //Content-Type: application/octet-stream - // - // - - string = crlf + boundaryString + "\r\n" - + "Content-Disposition: form-data; name=\"" + object.name - + "\"; filename=\"" + object.buffer.filename + "\"\r\n" - + "Content-Type: application/octet-stream\r\n" - + "\r\n"; - stringBuffer = string.toArrayBuffer(); - - compressedBuffer = object.buffer.buffer.compress(); - buffer = new Uint8Array(stringBuffer.byteLength + compressedBuffer.byteLength); - buffer.set(new Uint8Array(stringBuffer)); - buffer.set(new Uint8Array(compressedBuffer), stringBuffer.byteLength); - - } else { - - throw new Error("Item to add to HttpMultiPart not recognized"); - } - - byteLength += buffer.byteLength; - parts.push(buffer); - - crlf = "\r\n"; - - return true; - } - that.add = add; - - function response() { - var buffer, - index, - str, - i; - - str = crlf + boundaryString + "--\r\n"; - buffer = str.toArrayBuffer(); - byteLength += buffer.byteLength; - parts.push(buffer); - - buffer = new Uint8Array(byteLength); - index = 0; - for (i = 0; i < parts.length; i += 1) { - buffer.set(new Uint8Array(parts[i]), index); - index += parts[i].byteLength; - } - - return buffer; - } - that.response = response; - - clear(); - - return that; -}()); - -var modelUploader = (function () { - var that = {}, - modelFile, - modelName, - modelURL, - modelCallback, - isProcessing, - fstBuffer, - fbxBuffer, - //svoBuffer, - mapping, - geometry, - API_URL = "https://data.highfidelity.io/api/v1/models", - MODEL_URL = "http://public.highfidelity.io/models/content", - NAME_FIELD = "name", - SCALE_FIELD = "scale", - FILENAME_FIELD = "filename", - TEXDIR_FIELD = "texdir", - MAX_TEXTURE_SIZE = 1024; - - function info(message) { - if (progressDialog.isOpen()) { - progressDialog.update(message); - } else { - progressDialog.open(message); - } - print(message); - } - - function error(message) { - if (progressDialog.isOpen()) { - progressDialog.close(); - } - print(message); - Window.alert(message); - } - - function randomChar(length) { - var characters = "0123457689abcdefghijklmnopqrstuvwxyz", - string = "", - i; - - for (i = 0; i < length; i += 1) { - string += characters[Math.floor(Math.random() * 36)]; - } - - return string; - } - - function resetDataObjects() { - fstBuffer = null; - fbxBuffer = null; - //svoBuffer = null; - mapping = {}; - geometry = {}; - geometry.textures = []; - geometry.embedded = []; - } - - function readFile(filename) { - var url = "file:///" + filename, - req = new XMLHttpRequest(); - - req.open("GET", url, false); - req.responseType = "arraybuffer"; - req.send(); - if (req.status !== 200) { - error("Could not read file: " + filename + " : " + req.statusText); - return null; - } - - return { - filename: filename.fileName(), - buffer: req.response - }; - } - - function readMapping(buffer) { - var dv = new DataView(buffer.buffer), - lines, - line, - tokens, - i, - name, - value, - remainder, - existing; - - mapping = {}; // { name : value | name : { value : [remainder] } } - lines = dv.string(0, dv.byteLength).split(/\r\n|\r|\n/); - for (i = 0; i < lines.length; i += 1) { - line = lines[i].trim(); - if (line.length > 0 && line[0] !== "#") { - tokens = line.split(/\s*=\s*/); - if (tokens.length > 1) { - name = tokens[0]; - value = tokens[1]; - if (tokens.length > 2) { - remainder = tokens.slice(2, tokens.length).join(" = "); - } else { - remainder = null; - } - if (tokens.length === 2 && mapping[name] === undefined) { - mapping[name] = value; - } else { - if (mapping[name] === undefined) { - mapping[name] = {}; - - } else if (typeof mapping[name] !== "object") { - existing = mapping[name]; - mapping[name] = { existing : null }; - } - - if (mapping[name][value] === undefined) { - mapping[name][value] = []; - } - mapping[name][value].push(remainder); - } - } - } - } - } - - function writeMapping(buffer) { - var name, - value, - remainder, - i, - string = ""; - - for (name in mapping) { - if (mapping.hasOwnProperty(name)) { - if (typeof mapping[name] === "object") { - for (value in mapping[name]) { - if (mapping[name].hasOwnProperty(value)) { - remainder = mapping[name][value]; - if (remainder === null) { - string += (name + " = " + value + "\n"); - } else { - for (i = 0; i < remainder.length; i += 1) { - string += (name + " = " + value + " = " + remainder[i] + "\n"); - } - } - } - } - } else { - string += (name + " = " + mapping[name] + "\n"); - } - } - } - - buffer.buffer = string.toArrayBuffer(); - } - - function readGeometry(fbxBuffer) { - var textures, - view, - index, - EOF, - previousNodeFilename; - - // Reference: - // http://code.blender.org/index.php/2013/08/fbx-binary-file-format-specification/ - - textures = {}; - view = new DataView(fbxBuffer.buffer); - EOF = false; - - function parseBinaryFBX() { - var endOffset, - numProperties, - propertyListLength, - nameLength, - name, - filename; - - endOffset = view.getUint32(index, true); - numProperties = view.getUint32(index + 4, true); - propertyListLength = view.getUint32(index + 8, true); - nameLength = view.getUint8(index + 12); - index += 13; - - if (endOffset === 0) { - return; - } - if (endOffset < index || endOffset > view.byteLength) { - EOF = true; - return; - } - - name = view.string(index, nameLength).toLowerCase(); - index += nameLength; - - if (name === "content" && previousNodeFilename !== "") { - // Blender 2.71 exporter "embeds" external textures as empty binary blobs so ignore these - if (propertyListLength > 5) { - geometry.embedded.push(previousNodeFilename); - } - } - - if (name === "relativefilename") { - filename = view.string(index + 5, view.getUint32(index + 1, true)).fileName(); - if (!textures.hasOwnProperty(filename)) { - textures[filename] = ""; - geometry.textures.push(filename); - } - previousNodeFilename = filename; - } else { - previousNodeFilename = ""; - } - - index += (propertyListLength); - - while (index < endOffset && !EOF) { - parseBinaryFBX(); - } - } - - function readTextFBX() { - var line, - view, - viewLength, - charCode, - charCodes, - numCharCodes, - filename, - relativeFilename = "", - MAX_CHAR_CODES = 250; - - view = new Uint8Array(fbxBuffer.buffer); - viewLength = view.byteLength; - charCodes = []; - numCharCodes = 0; - - for (index = 0; index < viewLength; index += 1) { - charCode = view[index]; - if (charCode !== 9 && charCode !== 32) { - if (charCode === 10) { // EOL. Can ignore EOF. - line = String.fromCharCode.apply(String, charCodes).toLowerCase(); - // For embedded textures, "Content:" line immediately follows "RelativeFilename:" line. - if (line.slice(0, 8) === "content:" && relativeFilename !== "") { - geometry.embedded.push(relativeFilename); - } - if (line.slice(0, 17) === "relativefilename:") { - filename = line.slice(line.indexOf("\""), line.lastIndexOf("\"") - line.length).fileName(); - if (!textures.hasOwnProperty(filename)) { - textures[filename] = ""; - geometry.textures.push(filename); - } - relativeFilename = filename; - } else { - relativeFilename = ""; - } - charCodes = []; - numCharCodes = 0; - } else { - if (numCharCodes < MAX_CHAR_CODES) { // Only interested in start of line - charCodes.push(charCode); - numCharCodes += 1; - } - } - } - } - } - - if (view.string(0, 18) === "Kaydara FBX Binary") { - previousNodeFilename = ""; - - index = 27; - while (index < view.byteLength - 39 && !EOF) { - parseBinaryFBX(); - } - - } else { - - readTextFBX(); - - } - } - - function readModel() { - var fbxFilename, - //svoFilename, - fileType; - - info("Reading model file"); - print("Model file: " + modelFile); - - if (modelFile.toLowerCase().fileType() === "fst") { - fstBuffer = readFile(modelFile); - if (fstBuffer === null) { - return false; - } - readMapping(fstBuffer); - fileType = mapping[FILENAME_FIELD].toLowerCase().fileType(); - if (mapping.hasOwnProperty(FILENAME_FIELD)) { - if (fileType === "fbx") { - fbxFilename = modelFile.path() + "\\" + mapping[FILENAME_FIELD]; - //} else if (fileType === "svo") { - // svoFilename = modelFile.path() + "\\" + mapping[FILENAME_FIELD]; - } else { - error("Unrecognized model type in FST file!"); - return false; - } - } else { - error("Model file name not found in FST file!"); - return false; - } - } else { - fstBuffer = { - filename: "Interface." + randomChar(6), // Simulate avatar model uploading behaviour - buffer: null - }; - - if (modelFile.toLowerCase().fileType() === "fbx") { - fbxFilename = modelFile; - mapping[FILENAME_FIELD] = modelFile.fileName(); - - //} else if (modelFile.toLowerCase().fileType() === "svo") { - // svoFilename = modelFile; - // mapping[FILENAME_FIELD] = modelFile.fileName(); - - } else { - error("Unrecognized file type: " + modelFile); - return false; - } - } - - if (!isProcessing) { return false; } - - if (fbxFilename) { - fbxBuffer = readFile(fbxFilename); - if (fbxBuffer === null) { - return false; - } - - if (!isProcessing) { return false; } - - readGeometry(fbxBuffer); - } - - //if (svoFilename) { - // svoBuffer = readFile(svoFilename); - // if (svoBuffer === null) { - // return false; - // } - //} - - // Add any missing basic mappings - if (!mapping.hasOwnProperty(NAME_FIELD)) { - mapping[NAME_FIELD] = modelFile.fileName().fileBase(); - } - if (!mapping.hasOwnProperty(TEXDIR_FIELD)) { - mapping[TEXDIR_FIELD] = "."; - } - if (!mapping.hasOwnProperty(SCALE_FIELD)) { - mapping[SCALE_FIELD] = 1.0; - } - - return true; - } - - function setProperties() { - var form = [], - directory, - displayAs, - validateAs; - - progressDialog.close(); - print("Setting model properties"); - - form.push({ label: "Name:", value: mapping[NAME_FIELD] }); - - directory = modelFile.path() + "/" + mapping[TEXDIR_FIELD]; - displayAs = new RegExp("^" + modelFile.path().regExpEscape() + "[\\\\\\\/](.*)"); - validateAs = new RegExp("^" + modelFile.path().regExpEscape() + "([\\\\\\\/].*)?"); - - form.push({ - label: "Texture directory:", - directory: modelFile.path() + "/" + mapping[TEXDIR_FIELD], - title: "Choose Texture Directory", - displayAs: displayAs, - validateAs: validateAs, - errorMessage: "Texture directory must be subdirectory of the model directory." - }); - - form.push({ button: "Cancel" }); - - if (!Window.form("Set Model Properties", form)) { - print("User cancelled uploading model"); - return false; - } - - mapping[NAME_FIELD] = form[0].value; - mapping[TEXDIR_FIELD] = form[1].directory.slice(modelFile.path().length + 1); - if (mapping[TEXDIR_FIELD] === "") { - mapping[TEXDIR_FIELD] = "."; - } - - writeMapping(fstBuffer); - - return true; - } - - function createHttpMessage(callback) { - var multiparts = [], - lodCount, - lodFile, - lodBuffer, - textureBuffer, - textureSourceFormat, - textureTargetFormat, - embeddedTextures, - i; - - info("Preparing to send model"); - - // Model name - if (mapping.hasOwnProperty(NAME_FIELD)) { - multiparts.push({ - name : "model_name", - string : mapping[NAME_FIELD] - }); - } else { - error("Model name is missing"); - httpMultiPart.clear(); - return; - } - - // FST file - if (fstBuffer) { - multiparts.push({ - name : "fst", - buffer: fstBuffer - }); - } - - // FBX file - if (fbxBuffer) { - multiparts.push({ - name : "fbx", - buffer: fbxBuffer - }); - } - - // SVO file - //if (svoBuffer) { - // multiparts.push({ - // name : "svo", - // buffer: svoBuffer - // }); - //} - - // LOD files - lodCount = 0; - for (lodFile in mapping.lod) { - if (mapping.lod.hasOwnProperty(lodFile)) { - lodBuffer = readFile(modelFile.path() + "\/" + lodFile); - if (lodBuffer === null) { - return; - } - multiparts.push({ - name: "lod" + lodCount, - buffer: lodBuffer - }); - lodCount += 1; - } - if (!isProcessing) { return; } - } - - // Textures - embeddedTextures = "|" + geometry.embedded.join("|") + "|"; - for (i = 0; i < geometry.textures.length; i += 1) { - if (embeddedTextures.indexOf("|" + geometry.textures[i].fileName() + "|") === -1) { - textureBuffer = readFile(modelFile.path() + "\/" - + (mapping[TEXDIR_FIELD] !== "." ? mapping[TEXDIR_FIELD] + "\/" : "") - + geometry.textures[i]); - if (textureBuffer === null) { - return; - } - - textureSourceFormat = geometry.textures[i].fileType().toLowerCase(); - textureTargetFormat = (textureSourceFormat === "jpg" ? "jpg" : "png"); - textureBuffer.buffer = - textureBuffer.buffer.recodeImage(textureSourceFormat, textureTargetFormat, MAX_TEXTURE_SIZE); - textureBuffer.filename = textureBuffer.filename.slice(0, -textureSourceFormat.length) + textureTargetFormat; - - multiparts.push({ - name: "texture" + i, - buffer: textureBuffer - }); - } - - if (!isProcessing) { return; } - } - - // Model category - multiparts.push({ - name : "model_category", - string : "content" - }); - - // Create HTTP message - httpMultiPart.clear(); - Script.setTimeout(function addMultipart() { - var multipart = multiparts.shift(); - httpMultiPart.add(multipart); - - if (!isProcessing) { return; } - - if (multiparts.length > 0) { - Script.setTimeout(addMultipart, 25); - } else { - callback(); - } - }, 25); - } - - function sendToHighFidelity() { - var req, - uploadedChecks, - HTTP_GET_TIMEOUT = 60, // 1 minute - HTTP_SEND_TIMEOUT = 900, // 15 minutes - UPLOADED_CHECKS = 30, - CHECK_UPLOADED_TIMEOUT = 1, // 1 second - handleCheckUploadedResponses, - handleUploadModelResponses, - handleRequestUploadResponses; - - function uploadTimedOut() { - error("Model upload failed: Internet request timed out!"); - } - - function debugResponse() { - print("req.errorCode = " + req.errorCode); - print("req.readyState = " + req.readyState); - print("req.status = " + req.status); - print("req.statusText = " + req.statusText); - print("req.responseType = " + req.responseType); - print("req.responseText = " + req.responseText); - print("req.response = " + req.response); - print("req.getAllResponseHeaders() = " + req.getAllResponseHeaders()); - } - - function checkUploaded() { - if (!isProcessing) { return; } - - info("Checking uploaded model"); - - req = new XMLHttpRequest(); - req.open("HEAD", modelURL, true); - req.timeout = HTTP_GET_TIMEOUT * 1000; - req.onreadystatechange = handleCheckUploadedResponses; - req.ontimeout = uploadTimedOut; - req.send(); - } - - handleCheckUploadedResponses = function () { - //debugResponse(); - if (req.readyState === req.DONE) { - if (req.status === 200) { - // Note: Unlike avatar models, for content models we don't need to refresh texture cache. - print("Model uploaded: " + modelURL); - progressDialog.close(); - if (Window.confirm("Your model has been uploaded as: " + modelURL + "\nDo you want to rez it?")) { - modelCallback(modelURL); - } - } else if (req.status === 404) { - if (uploadedChecks > 0) { - uploadedChecks -= 1; - Script.setTimeout(checkUploaded, CHECK_UPLOADED_TIMEOUT * 1000); - } else { - print("Error: " + req.status + " " + req.statusText); - error("We could not verify that your model was successfully uploaded but it may have been at: " - + modelURL); - } - } else { - print("Error: " + req.status + " " + req.statusText); - error("There was a problem with your upload, please try again later."); - } - } - }; - - function uploadModel(method) { - var url; - - if (!isProcessing) { return; } - - req = new XMLHttpRequest(); - if (method === "PUT") { - url = API_URL + "\/" + modelName; - req.open("PUT", url, true); //print("PUT " + url); - } else { - url = API_URL; - req.open("POST", url, true); //print("POST " + url); - } - req.setRequestHeader("Content-Type", "multipart/form-data; boundary=\"" + httpMultiPart.boundary() + "\""); - req.timeout = HTTP_SEND_TIMEOUT * 1000; - req.onreadystatechange = handleUploadModelResponses; - req.ontimeout = uploadTimedOut; - req.send(httpMultiPart.response().buffer); - } - - handleUploadModelResponses = function () { - //debugResponse(); - if (req.readyState === req.DONE) { - if (req.status === 200) { - uploadedChecks = UPLOADED_CHECKS; - checkUploaded(); - } else { - print("Error: " + req.status + " " + req.statusText); - error("There was a problem with your upload, please try again later."); - } - } - }; - - function requestUpload() { - var url; - - if (!isProcessing) { return; } - - url = API_URL + "\/" + modelName; // XMLHttpRequest automatically handles authorization of API requests. - req = new XMLHttpRequest(); - req.open("GET", url, true); //print("GET " + url); - req.responseType = "json"; - req.timeout = HTTP_GET_TIMEOUT * 1000; - req.onreadystatechange = handleRequestUploadResponses; - req.ontimeout = uploadTimedOut; - req.send(); - } - - handleRequestUploadResponses = function () { - var response; - - //debugResponse(); - if (req.readyState === req.DONE) { - if (req.status === 200) { - if (req.responseType === "json") { - response = JSON.parse(req.responseText); - if (response.status === "success") { - if (response.exists === false) { - uploadModel("POST"); - } else if (response.can_update === true) { - uploadModel("PUT"); - } else { - error("This model file already exists and is owned by someone else!"); - } - return; - } - } - } else { - print("Error: " + req.status + " " + req.statusText); - } - error("Model upload failed! Something went wrong at the data server."); - } - }; - - info("Sending model to High Fidelity"); - - requestUpload(); - } - - that.upload = function (file, callback) { - - modelFile = file; - modelCallback = callback; - - isProcessing = true; - - progressDialog.onCancel = function () { - print("User cancelled uploading model"); - isProcessing = false; - }; - - resetDataObjects(); - - if (readModel()) { - if (setProperties()) { - modelName = mapping[NAME_FIELD]; - modelURL = MODEL_URL + "\/" + mapping[NAME_FIELD] + ".fst"; // All models are uploaded as an FST - - createHttpMessage(sendToHighFidelity); - } - } - - resetDataObjects(); - }; - - return that; -}()); - -var toolBar = (function () { - var that = {}, - toolBar, - activeButton, - newModelButton, - newCubeButton, - newSphereButton, - newTextButton, - browseModelsButton, - loadURLMenuItem, - loadFileMenuItem, - menuItemWidth, - menuItemOffset, - menuItemHeight, - menuItemMargin = 5, - menuTextColor = { red: 255, green: 255, blue: 255 }, - menuBackgroundColor = { red: 18, green: 66, blue: 66 }; - - function initialize() { - toolBar = new ToolBar(0, 0, ToolBar.VERTICAL); - - activeButton = toolBar.addTool({ - imageURL: toolIconUrl + "models-tool.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }, true, false); - - newModelButton = toolBar.addTool({ - imageURL: toolIconUrl + "add-model-tool.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }, true, false); - - browseModelsButton = toolBar.addTool({ - imageURL: toolIconUrl + "list-icon.svg", - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }); - - menuItemOffset = toolBar.height / 3 + 2; - menuItemHeight = Tool.IMAGE_HEIGHT / 2 - 2; - - loadURLMenuItem = Overlays.addOverlay("text", { - height: menuItemHeight, - backgroundColor: menuBackgroundColor, - topMargin: menuItemMargin, - text: "Model URL", - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - loadFileMenuItem = Overlays.addOverlay("text", { - height: menuItemHeight, - backgroundColor: menuBackgroundColor, - topMargin: menuItemMargin, - text: "Model File", - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - menuItemWidth = Math.max(Overlays.textSize(loadURLMenuItem, "Model URL").width, - Overlays.textSize(loadFileMenuItem, "Model File").width) + 20; - Overlays.editOverlay(loadURLMenuItem, { width: menuItemWidth }); - Overlays.editOverlay(loadFileMenuItem, { width: menuItemWidth }); - - newCubeButton = toolBar.addTool({ - imageURL: toolIconUrl + "add-cube.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }); - - newSphereButton = toolBar.addTool({ - imageURL: toolIconUrl + "add-sphere.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }); - - newTextButton = toolBar.addTool({ - //imageURL: toolIconUrl + "add-text.svg", - imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/tools/add-text.svg", // temporarily - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }); - } - - function toggleNewModelButton(active) { - if (active === undefined) { - active = !toolBar.toolSelected(newModelButton); - } - toolBar.selectTool(newModelButton, active); - - Overlays.editOverlay(loadURLMenuItem, { visible: active }); - Overlays.editOverlay(loadFileMenuItem, { visible: active }); - } - - var RESIZE_INTERVAL = 50; - var RESIZE_TIMEOUT = 20000; - var RESIZE_MAX_CHECKS = RESIZE_TIMEOUT / RESIZE_INTERVAL; - function addModel(url) { - var position; - - position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); - - if (position.x > 0 && position.y > 0 && position.z > 0) { - var entityId = Entities.addEntity({ - type: "Model", - position: position, - dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION }, - modelURL: url - }); - print("Model added: " + url); - - var checkCount = 0; - function resize() { - var entityProperties = Entities.getEntityProperties(entityId); - var naturalDimensions = entityProperties.naturalDimensions; - - checkCount++; - - if (naturalDimensions.x == 0 && naturalDimensions.y == 0 && naturalDimensions.z == 0) { - if (checkCount < RESIZE_MAX_CHECKS) { - Script.setTimeout(resize, RESIZE_INTERVAL); - } else { - print("Resize failed: timed out waiting for model (" + url + ") to load"); - } - } else { - entityProperties.dimensions = naturalDimensions; - Entities.editEntity(entityId, entityProperties); - } - } - - Script.setTimeout(resize, RESIZE_INTERVAL); - - } else { - print("Can't add model: Model would be out of bounds."); - } - } - - that.move = function () { - var newViewPort, - toolsX, - toolsY; - - newViewPort = Controller.getViewportDimensions(); - - if (toolBar === undefined) { - initialize(); - - } else if (windowDimensions.x === newViewPort.x && - windowDimensions.y === newViewPort.y) { - return; - } - - windowDimensions = newViewPort; - toolsX = windowDimensions.x - 8 - toolBar.width; - toolsY = (windowDimensions.y - toolBar.height) / 2; - - toolBar.move(toolsX, toolsY); - - Overlays.editOverlay(loadURLMenuItem, { x: toolsX - menuItemWidth, y: toolsY + menuItemOffset }); - Overlays.editOverlay(loadFileMenuItem, { x: toolsX - menuItemWidth, y: toolsY + menuItemOffset + menuItemHeight }); - }; - - that.mousePressEvent = function (event) { - var clickedOverlay, - url, - file; - - clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (activeButton === toolBar.clicked(clickedOverlay)) { - isActive = !isActive; - return true; - } - - if (newModelButton === toolBar.clicked(clickedOverlay)) { - toggleNewModelButton(); - return true; - } - - if (clickedOverlay === loadURLMenuItem) { - toggleNewModelButton(false); - url = Window.prompt("Model URL", modelURLs[Math.floor(Math.random() * modelURLs.length)]); - if (url !== null && url !== "") { - addModel(url); - } - return true; - } - - if (clickedOverlay === loadFileMenuItem) { - toggleNewModelButton(false); - - file = Window.browse("Select your model file ...", - Settings.getValue("LastModelUploadLocation").path(), - "Model files (*.fst *.fbx)"); - //"Model files (*.fst *.fbx *.svo)"); - if (file !== null) { - Settings.setValue("LastModelUploadLocation", file); - modelUploader.upload(file, addModel); - } - return true; - } - - if (browseModelsButton === toolBar.clicked(clickedOverlay)) { - toggleNewModelButton(false); - url = Window.s3Browse(".*(fbx|FBX)"); - if (url !== null && url !== "") { - addModel(url); - } - return true; - } - - if (newCubeButton === toolBar.clicked(clickedOverlay)) { - var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); - - if (position.x > 0 && position.y > 0 && position.z > 0) { - Entities.addEntity({ - type: "Box", - position: position, - dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION }, - color: { red: 255, green: 0, blue: 0 } - - }); - } else { - print("Can't create box: Box would be out of bounds."); - } - return true; - } - - if (newSphereButton === toolBar.clicked(clickedOverlay)) { - var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); - - if (position.x > 0 && position.y > 0 && position.z > 0) { - Entities.addEntity({ - type: "Sphere", - position: position, - dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION }, - color: { red: 255, green: 0, blue: 0 } - }); - } else { - print("Can't create box: Box would be out of bounds."); - } - return true; - } - - - if (newTextButton === toolBar.clicked(clickedOverlay)) { - var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); - - if (position.x > 0 && position.y > 0 && position.z > 0) { - Entities.addEntity({ - type: "Text", - position: position, - dimensions: { x: DEFAULT_TEXT_DIMENSION_X, y: DEFAULT_TEXT_DIMENSION_Y, z: DEFAULT_TEXT_DIMENSION_Z }, - backgroundColor: { red: 0, green: 0, blue: 0 }, - textColor: { red: 255, green: 255, blue: 255 }, - text: "some text", - lineHight: "0.1" - }); - } else { - print("Can't create box: Text would be out of bounds."); - } - return true; - } - - return false; - }; - - that.cleanup = function () { - toolBar.cleanup(); - Overlays.deleteOverlay(loadURLMenuItem); - Overlays.deleteOverlay(loadFileMenuItem); - }; - - return that; -}()); - - -var exportMenu = null; - -var ExportMenu = function (opts) { - var self = this; - - var windowDimensions = Controller.getViewportDimensions(); - var pos = { x: windowDimensions.x / 2, y: windowDimensions.y - 100 }; - - this._onClose = opts.onClose || function () { }; - this._position = { x: 0.0, y: 0.0, z: 0.0 }; - this._scale = 1.0; - - var minScale = 1; - var maxScale = 32768; - var titleWidth = 120; - var locationWidth = 100; - var scaleWidth = 144; - var exportWidth = 100; - var cancelWidth = 100; - var margin = 4; - var height = 30; - var outerHeight = height + (2 * margin); - var buttonColor = { red: 128, green: 128, blue: 128 }; - - var SCALE_MINUS = scaleWidth * 40.0 / 100.0; - var SCALE_PLUS = scaleWidth * 63.0 / 100.0; - - var fullWidth = locationWidth + scaleWidth + exportWidth + cancelWidth + (2 * margin); - var offset = fullWidth / 2; - pos.x -= offset; - - var background = Overlays.addOverlay("text", { - x: pos.x, - y: pos.y, - opacity: 1, - width: fullWidth, - height: outerHeight, - backgroundColor: { red: 200, green: 200, blue: 200 }, - text: "", - }); - - var titleText = Overlays.addOverlay("text", { - x: pos.x, - y: pos.y - height, - font: { size: 14 }, - width: titleWidth, - height: height, - backgroundColor: { red: 255, green: 255, blue: 255 }, - color: { red: 255, green: 255, blue: 255 }, - text: "Export Models" - }); - - var locationButton = Overlays.addOverlay("text", { - x: pos.x + margin, - y: pos.y + margin, - width: locationWidth, - height: height, - color: { red: 255, green: 255, blue: 255 }, - text: "0, 0, 0", - }); - var scaleOverlay = Overlays.addOverlay("image", { - x: pos.x + margin + locationWidth, - y: pos.y + margin, - width: scaleWidth, - height: height, - subImage: { x: 0, y: 3, width: 144, height: height }, - imageURL: toolIconUrl + "voxel-size-selector.svg", - alpha: 0.9, - }); - var scaleViewWidth = 40; - var scaleView = Overlays.addOverlay("text", { - x: pos.x + margin + locationWidth + SCALE_MINUS, - y: pos.y + margin, - width: scaleViewWidth, - height: height, - alpha: 0.0, - backgroundAlpha: 0.0, - color: { red: 255, green: 255, blue: 255 }, - text: "1" - }); - var exportButton = Overlays.addOverlay("text", { - x: pos.x + margin + locationWidth + scaleWidth, - y: pos.y + margin, - width: exportWidth, - height: height, - color: { red: 0, green: 255, blue: 255 }, - text: "Export" - }); - var cancelButton = Overlays.addOverlay("text", { - x: pos.x + margin + locationWidth + scaleWidth + exportWidth, - y: pos.y + margin, - width: cancelWidth, - height: height, - color: { red: 255, green: 255, blue: 255 }, - text: "Cancel" - }); - - var voxelPreview = Overlays.addOverlay("cube", { - position: { x: 0, y: 0, z: 0 }, - size: this._scale, - color: { red: 255, green: 255, blue: 0 }, - alpha: 1, - solid: false, - visible: true, - lineWidth: 4 - }); - - this.parsePosition = function (str) { - var parts = str.split(','); - if (parts.length == 3) { - var x = parseFloat(parts[0]); - var y = parseFloat(parts[1]); - var z = parseFloat(parts[2]); - if (isFinite(x) && isFinite(y) && isFinite(z)) { - return { x: x, y: y, z: z }; - } - } - return null; - }; - - this.showPositionPrompt = function () { - var positionStr = self._position.x + ", " + self._position.y + ", " + self._position.z; - while (1) { - positionStr = Window.prompt("Position to export form:", positionStr); - if (positionStr == null) { - break; - } - var position = self.parsePosition(positionStr); - if (position != null) { - self.setPosition(position.x, position.y, position.z); - break; - } - Window.alert("The position you entered was invalid."); - } - }; - - this.setScale = function (scale) { - self._scale = Math.min(maxScale, Math.max(minScale, scale)); - Overlays.editOverlay(scaleView, { text: self._scale }); - Overlays.editOverlay(voxelPreview, { size: self._scale }); - } - - this.decreaseScale = function () { - self.setScale(self._scale /= 2); - } - - this.increaseScale = function () { - self.setScale(self._scale *= 2); - } - - this.exportEntities = function() { - var x = self._position.x; - var y = self._position.y; - var z = self._position.z; - var s = self._scale; - var filename = "models__" + Window.location.hostname + "__" + x + "_" + y + "_" + z + "_" + s + "__.svo"; - filename = Window.save("Select where to save", filename, "*.svo") - if (filename) { - var success = Clipboard.exportEntities(filename, x, y, z, s); - if (!success) { - Window.alert("Export failed: no models found in selected area."); - } - } - self.close(); - }; - - this.getPosition = function () { - return self._position; - }; - - this.setPosition = function (x, y, z) { - self._position = { x: x, y: y, z: z }; - var positionStr = x + ", " + y + ", " + z; - Overlays.editOverlay(locationButton, { text: positionStr }); - Overlays.editOverlay(voxelPreview, { position: self._position }); - - }; - - this.mouseReleaseEvent = function (event) { - var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (clickedOverlay == locationButton) { - self.showPositionPrompt(); - } else if (clickedOverlay == exportButton) { - self.exportEntities(); - } else if (clickedOverlay == cancelButton) { - self.close(); - } else if (clickedOverlay == scaleOverlay) { - var x = event.x - pos.x - margin - locationWidth; - print(x); - if (x < SCALE_MINUS) { - self.decreaseScale(); - } else if (x > SCALE_PLUS) { - self.increaseScale(); - } - } - }; - - this.close = function () { - this.cleanup(); - this._onClose(); - }; - - this.cleanup = function () { - Overlays.deleteOverlay(background); - Overlays.deleteOverlay(titleText); - Overlays.deleteOverlay(locationButton); - Overlays.deleteOverlay(exportButton); - Overlays.deleteOverlay(cancelButton); - Overlays.deleteOverlay(voxelPreview); - Overlays.deleteOverlay(scaleOverlay); - Overlays.deleteOverlay(scaleView); - }; - - print("CONNECTING!"); - Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent); -}; - - - -var ModelImporter = function (opts) { - var self = this; - - var height = 30; - var margin = 4; - var outerHeight = height + (2 * margin); - var titleWidth = 120; - var cancelWidth = 100; - var fullWidth = titleWidth + cancelWidth + (2 * margin); - - var localModels = Overlays.addOverlay("localmodels", { - position: { x: 1, y: 1, z: 1 }, - scale: 1, - visible: false - }); - var importScale = 1; - var importBoundaries = Overlays.addOverlay("cube", { - position: { x: 0, y: 0, z: 0 }, - size: 1, - color: { red: 128, blue: 128, green: 128 }, - lineWidth: 4, - solid: false, - visible: false - }); - - var pos = { x: windowDimensions.x / 2 - (fullWidth / 2), y: windowDimensions.y - 100 }; - - var background = Overlays.addOverlay("text", { - x: pos.x, - y: pos.y, - opacity: 1, - width: fullWidth, - height: outerHeight, - backgroundColor: { red: 200, green: 200, blue: 200 }, - visible: false, - text: "", - }); - - var titleText = Overlays.addOverlay("text", { - x: pos.x + margin, - y: pos.y + margin, - font: { size: 14 }, - width: titleWidth, - height: height, - backgroundColor: { red: 255, green: 255, blue: 255 }, - color: { red: 255, green: 255, blue: 255 }, - visible: false, - text: "Import Models" - }); - var cancelButton = Overlays.addOverlay("text", { - x: pos.x + margin + titleWidth, - y: pos.y + margin, - width: cancelWidth, - height: height, - color: { red: 255, green: 255, blue: 255 }, - visible: false, - text: "Close" - }); - this._importing = false; - - this.setImportVisible = function (visible) { - Overlays.editOverlay(importBoundaries, { visible: visible }); - Overlays.editOverlay(localModels, { visible: visible }); - Overlays.editOverlay(cancelButton, { visible: visible }); - Overlays.editOverlay(titleText, { visible: visible }); - Overlays.editOverlay(background, { visible: visible }); - }; - - var importPosition = { x: 0, y: 0, z: 0 }; - this.moveImport = function (position) { - importPosition = position; - Overlays.editOverlay(localModels, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } - }); - Overlays.editOverlay(importBoundaries, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } - }); - } - - this.mouseMoveEvent = function (event) { - if (self._importing) { - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = false; //Voxels.findRayIntersection(pickRay); - - var distance = 2;// * self._scale; - - if (false) {//intersection.intersects) { - var intersectionDistance = Vec3.length(Vec3.subtract(pickRay.origin, intersection.intersection)); - if (intersectionDistance < distance) { - distance = intersectionDistance * 0.99; - } - - } - - var targetPosition = { - x: pickRay.origin.x + (pickRay.direction.x * distance), - y: pickRay.origin.y + (pickRay.direction.y * distance), - z: pickRay.origin.z + (pickRay.direction.z * distance) - }; - - if (targetPosition.x < 0) targetPosition.x = 0; - if (targetPosition.y < 0) targetPosition.y = 0; - if (targetPosition.z < 0) targetPosition.z = 0; - - var nudgeFactor = 1; - var newPosition = { - x: Math.floor(targetPosition.x / nudgeFactor) * nudgeFactor, - y: Math.floor(targetPosition.y / nudgeFactor) * nudgeFactor, - z: Math.floor(targetPosition.z / nudgeFactor) * nudgeFactor - } - - self.moveImport(newPosition); - } - } - - this.mouseReleaseEvent = function (event) { - var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (clickedOverlay == cancelButton) { - self._importing = false; - self.setImportVisible(false); - } - }; - - // Would prefer to use {4} for the coords, but it would only capture the last digit. - var fileRegex = /__(.+)__(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)__/; - this.doImport = function () { - if (!self._importing) { - var filename = Window.browse("Select models to import", "", "*.svo") - if (filename) { - parts = fileRegex.exec(filename); - if (parts == null) { - Window.alert("The file you selected does not contain source domain or location information"); - } else { - var hostname = parts[1]; - var x = parts[2]; - var y = parts[3]; - var z = parts[4]; - var s = parts[5]; - importScale = s; - if (hostname != location.hostname) { - if (!Window.confirm(("These models were not originally exported from this domain. Continue?"))) { - return; - } - } else { - if (Window.confirm(("Would you like to import back to the source location?"))) { - var success = Clipboard.importEntities(filename); - if (success) { - Clipboard.pasteEntities(x, y, z, 1); - } else { - Window.alert("There was an error importing the entity file."); - } - return; - } - } - } - var success = Clipboard.importEntities(filename); - if (success) { - self._importing = true; - self.setImportVisible(true); - Overlays.editOverlay(importBoundaries, { size: s }); - } else { - Window.alert("There was an error importing the entity file."); - } - } - } - } - - this.paste = function () { - if (self._importing) { - // self._importing = false; - // self.setImportVisible(false); - Clipboard.pasteEntities(importPosition.x, importPosition.y, importPosition.z, 1); - } - } - - this.cleanup = function () { - Overlays.deleteOverlay(localModels); - Overlays.deleteOverlay(importBoundaries); - Overlays.deleteOverlay(cancelButton); - Overlays.deleteOverlay(titleText); - Overlays.deleteOverlay(background); - } - - Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent); - Controller.mouseMoveEvent.connect(this.mouseMoveEvent); -}; - -var modelImporter = new ModelImporter(); - - -function isLocked(properties) { - // special case to lock the ground plane model in hq. - if (location.hostname == "hq.highfidelity.io" && - properties.modelURL == HIFI_PUBLIC_BUCKET + "ozan/Terrain_Reduce_forAlpha.fbx") { - return true; - } - return false; -} - - -function controller(wichSide) { - this.side = wichSide; - this.palm = 2 * wichSide; - this.tip = 2 * wichSide + 1; - this.trigger = wichSide; - this.bumper = 6 * wichSide + 5; - - this.oldPalmPosition = Controller.getSpatialControlPosition(this.palm); - this.palmPosition = Controller.getSpatialControlPosition(this.palm); - - this.oldTipPosition = Controller.getSpatialControlPosition(this.tip); - this.tipPosition = Controller.getSpatialControlPosition(this.tip); - - this.oldUp = Controller.getSpatialControlNormal(this.palm); - this.up = this.oldUp; - - this.oldFront = Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)); - this.front = this.oldFront; - - this.oldRight = Vec3.cross(this.front, this.up); - this.right = this.oldRight; - - this.oldRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); - this.rotation = this.oldRotation; - - this.triggerValue = Controller.getTriggerValue(this.trigger); - this.bumperValue = Controller.isButtonPressed(this.bumper); - - this.pressed = false; // is trigger pressed - this.pressing = false; // is trigger being pressed (is pressed now but wasn't previously) - - this.grabbing = false; - this.entityID = { isKnownID: false }; - this.modelURL = ""; - this.oldModelRotation; - this.oldModelPosition; - this.oldModelHalfDiagonal; - - this.positionAtGrab; - this.rotationAtGrab; - this.modelPositionAtGrab; - this.rotationAtGrab; - this.jointsIntersectingFromStart = []; - - this.laser = Overlays.addOverlay("line3d", { - start: { x: 0, y: 0, z: 0 }, - end: { x: 0, y: 0, z: 0 }, - color: LASER_COLOR, - alpha: 1, - visible: false, - lineWidth: LASER_WIDTH, - anchor: "MyAvatar" - }); - - this.guideScale = 0.02; - this.ball = Overlays.addOverlay("sphere", { - position: { x: 0, y: 0, z: 0 }, - size: this.guideScale, - solid: true, - color: { red: 0, green: 255, blue: 0 }, - alpha: 1, - visible: false, - anchor: "MyAvatar" - }); - this.leftRight = Overlays.addOverlay("line3d", { - start: { x: 0, y: 0, z: 0 }, - end: { x: 0, y: 0, z: 0 }, - color: { red: 0, green: 0, blue: 255 }, - alpha: 1, - visible: false, - lineWidth: LASER_WIDTH, - anchor: "MyAvatar" - }); - this.topDown = Overlays.addOverlay("line3d", { - start: { x: 0, y: 0, z: 0 }, - end: { x: 0, y: 0, z: 0 }, - color: { red: 0, green: 0, blue: 255 }, - alpha: 1, - visible: false, - lineWidth: LASER_WIDTH, - anchor: "MyAvatar" - }); - - - - this.grab = function (entityID, properties) { - if (isLocked(properties)) { - print("Model locked " + entityID.id); - } else { - print("Grabbing " + entityID.id); - this.grabbing = true; - this.entityID = entityID; - this.modelURL = properties.modelURL; - - this.oldModelPosition = properties.position; - this.oldModelRotation = properties.rotation; - this.oldModelHalfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - this.positionAtGrab = this.palmPosition; - this.rotationAtGrab = this.rotation; - this.modelPositionAtGrab = properties.position; - this.rotationAtGrab = properties.rotation; - this.jointsIntersectingFromStart = []; - for (var i = 0; i < jointList.length; i++) { - var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition); - if (distance < this.oldModelHalfDiagonal) { - this.jointsIntersectingFromStart.push(i); - } - } - this.showLaser(false); - } - } - - this.release = function () { - if (this.grabbing) { - jointList = MyAvatar.getJointNames(); - - var closestJointIndex = -1; - var closestJointDistance = 10; - for (var i = 0; i < jointList.length; i++) { - var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition); - if (distance < closestJointDistance) { - closestJointDistance = distance; - closestJointIndex = i; - } - } - - if (closestJointIndex != -1) { - print("closestJoint: " + jointList[closestJointIndex]); - print("closestJointDistance (attach max distance): " + closestJointDistance + " (" + this.oldModelHalfDiagonal + ")"); - } - - if (closestJointDistance < this.oldModelHalfDiagonal) { - - if (this.jointsIntersectingFromStart.indexOf(closestJointIndex) != -1 || - (leftController.grabbing && rightController.grabbing && - leftController.entityID.id == rightController.entityID.id)) { - // Do nothing - } else { - print("Attaching to " + jointList[closestJointIndex]); - var jointPosition = MyAvatar.getJointPosition(jointList[closestJointIndex]); - var jointRotation = MyAvatar.getJointCombinedRotation(jointList[closestJointIndex]); - - var attachmentOffset = Vec3.subtract(this.oldModelPosition, jointPosition); - attachmentOffset = Vec3.multiplyQbyV(Quat.inverse(jointRotation), attachmentOffset); - var attachmentRotation = Quat.multiply(Quat.inverse(jointRotation), this.oldModelRotation); - - MyAvatar.attach(this.modelURL, jointList[closestJointIndex], - attachmentOffset, attachmentRotation, 2.0 * this.oldModelHalfDiagonal, - true, false); - Entities.deleteEntity(this.entityID); - } - } - } - - this.grabbing = false; - this.entityID.isKnownID = false; - this.jointsIntersectingFromStart = []; - this.showLaser(true); - } - - this.checkTrigger = function () { - if (this.triggerValue > 0.9) { - if (this.pressed) { - this.pressing = false; - } else { - this.pressing = true; - } - this.pressed = true; - } else { - this.pressing = false; - this.pressed = false; - } - } - - this.checkEntity = function (properties) { - // special case to lock the ground plane model in hq. - if (isLocked(properties)) { - return { valid: false }; - } - - - // P P - Model - // /| A - Palm - // / | d B - unit vector toward tip - // / | X - base of the perpendicular line - // A---X----->B d - distance fom axis - // x x - distance from A - // - // |X-A| = (P-A).B - // X == A + ((P-A).B)B - // d = |P-X| - - var A = this.palmPosition; - var B = this.front; - var P = properties.position; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - var y = Vec3.dot(Vec3.subtract(P, A), this.up); - var z = Vec3.dot(Vec3.subtract(P, A), this.right); - var X = Vec3.sum(A, Vec3.multiply(B, x)); - var d = Vec3.length(Vec3.subtract(P, X)); - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) - && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (0 < x && sizeOK) { - return { valid: true, x: x, y: y, z: z }; - } - return { valid: false }; - } - - this.glowedIntersectingModel = { isKnownID: false }; - this.moveLaser = function () { - // the overlays here are anchored to the avatar, which means they are specified in the avatar's local frame - - var inverseRotation = Quat.inverse(MyAvatar.orientation); - var startPosition = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.palmPosition, MyAvatar.position)); - var direction = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.tipPosition, this.palmPosition)); - var distance = Vec3.length(direction); - direction = Vec3.multiply(direction, LASER_LENGTH_FACTOR / distance); - var endPosition = Vec3.sum(startPosition, direction); - - Overlays.editOverlay(this.laser, { - start: startPosition, - end: endPosition - }); - - - Overlays.editOverlay(this.ball, { - position: endPosition - }); - Overlays.editOverlay(this.leftRight, { - start: Vec3.sum(endPosition, Vec3.multiply(this.right, 2 * this.guideScale)), - end: Vec3.sum(endPosition, Vec3.multiply(this.right, -2 * this.guideScale)) - }); - Overlays.editOverlay(this.topDown, { - 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); - - 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 halfDiagonal = Vec3.length(intersection.properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), intersection.properties.position)) * 180 / 3.14; - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) - && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - if (intersection.accurate && intersection.entityID.isKnownID && sizeOK) { - this.glowedIntersectingModel = intersection.entityID; - - if (wantEntityGlow) { - Entities.editEntity(this.glowedIntersectingModel, { glowLevel: 0.25 }); - } - } - } - } - - this.showLaser = function (show) { - Overlays.editOverlay(this.laser, { visible: show }); - Overlays.editOverlay(this.ball, { visible: show }); - Overlays.editOverlay(this.leftRight, { visible: show }); - Overlays.editOverlay(this.topDown, { visible: show }); - } - this.moveEntity = function () { - 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; - print("Identified ID " + this.entityID.id + ", isKnown: " + this.entityID.isKnownID); - } - var newPosition; - var newRotation; - - switch (mode) { - case 0: - newPosition = Vec3.sum(this.palmPosition, - Vec3.multiply(this.front, this.x)); - newPosition = Vec3.sum(newPosition, - Vec3.multiply(this.up, this.y)); - newPosition = Vec3.sum(newPosition, - Vec3.multiply(this.right, this.z)); - - - newRotation = Quat.multiply(this.rotation, - Quat.inverse(this.oldRotation)); - newRotation = Quat.multiply(newRotation, - this.oldModelRotation); - break; - case 1: - var forward = Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1 }); - var d = Vec3.dot(forward, MyAvatar.position); - - var factor1 = Vec3.dot(forward, this.positionAtGrab) - d; - var factor2 = Vec3.dot(forward, this.modelPositionAtGrab) - d; - var vector = Vec3.subtract(this.palmPosition, this.positionAtGrab); - - if (factor2 < 0) { - factor2 = 0; - } - if (factor1 <= 0) { - factor1 = 1; - factor2 = 1; - } - - newPosition = Vec3.sum(this.modelPositionAtGrab, - Vec3.multiply(vector, - factor2 / factor1)); - - newRotation = Quat.multiply(this.rotation, - Quat.inverse(this.rotationAtGrab)); - newRotation = Quat.multiply(newRotation, - this.rotationAtGrab); - break; - } - Entities.editEntity(this.entityID, { - position: newPosition, - rotation: newRotation - }); - this.oldModelRotation = newRotation; - this.oldModelPosition = newPosition; - - var indicesToRemove = []; - for (var i = 0; i < this.jointsIntersectingFromStart.length; ++i) { - var distance = Vec3.distance(MyAvatar.getJointPosition(this.jointsIntersectingFromStart[i]), this.oldModelPosition); - if (distance >= this.oldModelHalfDiagonal) { - indicesToRemove.push(this.jointsIntersectingFromStart[i]); - } - - } - for (var i = 0; i < indicesToRemove.length; ++i) { - this.jointsIntersectingFromStart.splice(this.jointsIntersectingFromStart.indexOf(indicesToRemove[i], 1)); - } - } - } - - this.update = function () { - this.oldPalmPosition = this.palmPosition; - this.oldTipPosition = this.tipPosition; - this.palmPosition = Controller.getSpatialControlPosition(this.palm); - this.tipPosition = Controller.getSpatialControlPosition(this.tip); - - this.oldUp = this.up; - this.up = Vec3.normalize(Controller.getSpatialControlNormal(this.palm)); - - this.oldFront = this.front; - this.front = Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)); - - this.oldRight = this.right; - this.right = Vec3.normalize(Vec3.cross(this.front, this.up)); - - this.oldRotation = this.rotation; - this.rotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); - - this.triggerValue = Controller.getTriggerValue(this.trigger); - - 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 } }); - } - } - this.bumperValue = bumperValue; - - - this.checkTrigger(); - - this.moveLaser(); - - if (!this.pressed && this.grabbing) { - // release if trigger not pressed anymore. - this.release(); - } - - if (this.pressing) { - // Checking for attachments intersecting - var attachments = MyAvatar.getAttachmentData(); - var attachmentIndex = -1; - var attachmentX = LASER_LENGTH_FACTOR; - - var newModel; - var newProperties; - - for (var i = 0; i < attachments.length; ++i) { - var position = Vec3.sum(MyAvatar.getJointPosition(attachments[i].jointName), - Vec3.multiplyQbyV(MyAvatar.getJointCombinedRotation(attachments[i].jointName), attachments[i].translation)); - var scale = attachments[i].scale; - - var A = this.palmPosition; - var B = this.front; - var P = position; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - var X = Vec3.sum(A, Vec3.multiply(B, x)); - var d = Vec3.length(Vec3.subtract(P, X)); - - if (d < scale / 2.0 && 0 < x && x < attachmentX) { - attachmentIndex = i; - attachmentX = d; - } - } - - if (attachmentIndex != -1) { - print("Detaching: " + attachments[attachmentIndex].modelURL); - MyAvatar.detachOne(attachments[attachmentIndex].modelURL, attachments[attachmentIndex].jointName); - - newProperties = { - type: "Model", - position: Vec3.sum(MyAvatar.getJointPosition(attachments[attachmentIndex].jointName), - Vec3.multiplyQbyV(MyAvatar.getJointCombinedRotation(attachments[attachmentIndex].jointName), attachments[attachmentIndex].translation)), - rotation: Quat.multiply(MyAvatar.getJointCombinedRotation(attachments[attachmentIndex].jointName), - attachments[attachmentIndex].rotation), - - // TODO: how do we know the correct dimensions for detachment??? - dimensions: { x: attachments[attachmentIndex].scale / 2.0, - y: attachments[attachmentIndex].scale / 2.0, - z: attachments[attachmentIndex].scale / 2.0 }, - - modelURL: attachments[attachmentIndex].modelURL - }; - - newModel = Entities.addEntity(newProperties); - - - } else { - // There is none so ... - // Checking model tree - 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); - - if(!foundIntersection.accurate) { - print("No accurate intersection"); - return; - } - newModel = foundIntersection.entityID; - if (!newModel.isKnownID) { - var identify = Entities.identifyEntity(newModel); - if (!identify.isKnownID) { - print("Unknown ID " + identify.id + " (update loop " + newModel.id + ")"); - return; - } - newModel = identify; - } - newProperties = Entities.getEntityProperties(newModel); - } - print("foundEntity.modelURL=" + newProperties.modelURL); - if (isLocked(newProperties)) { - print("Model locked " + newProperties.id); - } else { - var check = this.checkEntity(newProperties); - if (!check.valid) { - return; - } - - this.grab(newModel, newProperties); - - this.x = check.x; - this.y = check.y; - this.z = check.z; - return; - } - } - } - - this.cleanup = function () { - Overlays.deleteOverlay(this.laser); - Overlays.deleteOverlay(this.ball); - Overlays.deleteOverlay(this.leftRight); - Overlays.deleteOverlay(this.topDown); - } -} - -var leftController = new controller(LEFT); -var rightController = new controller(RIGHT); - -function moveEntities() { - if (leftController.grabbing && rightController.grabbing && rightController.entityID.id == leftController.entityID.id) { - var newPosition = leftController.oldModelPosition; - var rotation = leftController.oldModelRotation; - var ratio = 1; - - - switch (mode) { - case 0: - var oldLeftPoint = Vec3.sum(leftController.oldPalmPosition, Vec3.multiply(leftController.oldFront, leftController.x)); - var oldRightPoint = Vec3.sum(rightController.oldPalmPosition, Vec3.multiply(rightController.oldFront, rightController.x)); - - var oldMiddle = Vec3.multiply(Vec3.sum(oldLeftPoint, oldRightPoint), 0.5); - var oldLength = Vec3.length(Vec3.subtract(oldLeftPoint, oldRightPoint)); - - - var leftPoint = Vec3.sum(leftController.palmPosition, Vec3.multiply(leftController.front, leftController.x)); - var rightPoint = Vec3.sum(rightController.palmPosition, Vec3.multiply(rightController.front, rightController.x)); - - var middle = Vec3.multiply(Vec3.sum(leftPoint, rightPoint), 0.5); - var length = Vec3.length(Vec3.subtract(leftPoint, rightPoint)); - - - ratio = length / oldLength; - newPosition = Vec3.sum(middle, - Vec3.multiply(Vec3.subtract(leftController.oldModelPosition, oldMiddle), ratio)); - break; - case 1: - var u = Vec3.normalize(Vec3.subtract(rightController.oldPalmPosition, leftController.oldPalmPosition)); - var v = Vec3.normalize(Vec3.subtract(rightController.palmPosition, leftController.palmPosition)); - - var cos_theta = Vec3.dot(u, v); - if (cos_theta > 1) { - cos_theta = 1; - } - var angle = Math.acos(cos_theta) / Math.PI * 180; - if (angle < 0.1) { - return; - - } - var w = Vec3.normalize(Vec3.cross(u, v)); - - rotation = Quat.multiply(Quat.angleAxis(angle, w), leftController.oldModelRotation); - - - leftController.positionAtGrab = leftController.palmPosition; - leftController.rotationAtGrab = leftController.rotation; - leftController.modelPositionAtGrab = leftController.oldModelPosition; - leftController.rotationAtGrab = rotation; - rightController.positionAtGrab = rightController.palmPosition; - rightController.rotationAtGrab = rightController.rotation; - rightController.modelPositionAtGrab = rightController.oldModelPosition; - rightController.rotationAtGrab = rotation; - break; - } - Entities.editEntity(leftController.entityID, { - position: newPosition, - rotation: rotation, - // TODO: how do we know the correct dimensions for detachment??? - //radius: leftController.oldModelHalfDiagonal * ratio - dimensions: { x: leftController.oldModelHalfDiagonal * ratio, - y: leftController.oldModelHalfDiagonal * ratio, - z: leftController.oldModelHalfDiagonal * ratio } - - - }); - leftController.oldModelPosition = newPosition; - leftController.oldModelRotation = rotation; - leftController.oldModelHalfDiagonal *= ratio; - - rightController.oldModelPosition = newPosition; - rightController.oldModelRotation = rotation; - rightController.oldModelHalfDiagonal *= ratio; - return; - } - leftController.moveEntity(); - rightController.moveEntity(); -} - -var hydraConnected = false; -function checkController(deltaTime) { - var numberOfButtons = Controller.getNumberOfButtons(); - var numberOfTriggers = Controller.getNumberOfTriggers(); - var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); - var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; - - if (!isActive) { - // So that we hide the lasers bellow and keep updating the overlays position - numberOfButtons = 0; - } - - // this is expected for hydras - if (numberOfButtons == 12 && numberOfTriggers == 2 && controllersPerTrigger == 2) { - if (!hydraConnected) { - hydraConnected = true; - } - - leftController.update(); - rightController.update(); - moveEntities(); - } else { - if (hydraConnected) { - hydraConnected = false; - - leftController.showLaser(false); - rightController.showLaser(false); - } - } - toolBar.move(); - progressDialog.move(); -} - -var entitySelected = false; -var selectedEntityID; -var selectedEntityProperties; -var mouseLastPosition; -var orientation; -var intersection; - - -var SCALE_FACTOR = 200.0; - -function rayPlaneIntersection(pickRay, point, normal) { - var d = -Vec3.dot(point, normal); - var t = -(Vec3.dot(pickRay.origin, normal) + d) / Vec3.dot(pickRay.direction, normal); - - return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t)); -} - -function Tooltip() { - this.x = 285; - this.y = 115; - this.width = 500; - this.height = 300; // 145; - this.margin = 5; - this.decimals = 3; - - this.textOverlay = Overlays.addOverlay("text", { - x: this.x, - y: this.y, - width: this.width, - height: this.height, - margin: this.margin, - text: "", - color: { red: 228, green: 228, blue: 228 }, - alpha: 0.8, - backgroundAlpha: 0.8, - visible: false - }); - this.show = function (doShow) { - Overlays.editOverlay(this.textOverlay, { visible: doShow }); - } - this.updateText = function(properties) { - var angles = Quat.safeEulerAngles(properties.rotation); - var text = "Entity Properties:\n" - text += "type: " + properties.type + "\n" - text += "X: " + properties.position.x.toFixed(this.decimals) + "\n" - text += "Y: " + properties.position.y.toFixed(this.decimals) + "\n" - text += "Z: " + properties.position.z.toFixed(this.decimals) + "\n" - text += "Pitch: " + angles.x.toFixed(this.decimals) + "\n" - text += "Yaw: " + angles.y.toFixed(this.decimals) + "\n" - text += "Roll: " + angles.z.toFixed(this.decimals) + "\n" - text += "Dimensions: " + properties.dimensions.x.toFixed(this.decimals) + ", " - + properties.dimensions.y.toFixed(this.decimals) + ", " - + properties.dimensions.z.toFixed(this.decimals) + "\n"; - - text += "Natural Dimensions: " + properties.naturalDimensions.x.toFixed(this.decimals) + ", " - + properties.naturalDimensions.y.toFixed(this.decimals) + ", " - + properties.naturalDimensions.z.toFixed(this.decimals) + "\n"; - - text += "ID: " + properties.id + "\n" - if (properties.type == "Model") { - text += "Model URL: " + properties.modelURL + "\n" - text += "Animation URL: " + properties.animationURL + "\n" - text += "Animation is playing: " + properties.animationIsPlaying + "\n" - if (properties.sittingPoints && properties.sittingPoints.length > 0) { - text += properties.sittingPoints.length + " Sitting points: " - for (var i = 0; i < properties.sittingPoints.length; ++i) { - text += properties.sittingPoints[i].name + " " - } - } else { - text += "No sitting points" + "\n" - } - } - if (properties.lifetime > -1) { - text += "Lifetime: " + properties.lifetime + "\n" - } - text += "Age: " + properties.ageAsText + "\n" - text += "Mass: " + properties.mass + "\n" - text += "Script: " + properties.script + "\n" - - - Overlays.editOverlay(this.textOverlay, { text: text }); - } - - this.cleanup = function () { - Overlays.deleteOverlay(this.textOverlay); - } -} -var tooltip = new Tooltip(); - -function mousePressEvent(event) { - if (event.isAlt) { - return; - } - - mouseLastPosition = { x: event.x, y: event.y }; - entitySelected = false; - var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event)) { - // Event handled; do nothing. - return; - } else { - // If we aren't active and didn't click on an overlay: quit - if (!isActive) { - return; - } - - var pickRay = Camera.computePickRay(event.x, event.y); - Vec3.print("[Mouse] Looking at: ", pickRay.origin); - var foundIntersection = Entities.findRayIntersection(pickRay, true); // we want precision picking here - - if(!foundIntersection.accurate) { - return; - } - var foundEntity = foundIntersection.entityID; - - if (!foundEntity.isKnownID) { - var identify = Entities.identifyEntity(foundEntity); - if (!identify.isKnownID) { - print("Unknown ID " + identify.id + " (update loop " + foundEntity.id + ")"); - return; - } - foundEntity = identify; - } - - var properties = Entities.getEntityProperties(foundEntity); - if (isLocked(properties)) { - print("Model locked " + properties.id); - } else { - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - print("Checking properties: " + properties.id + " " + properties.isKnownID + " - Half Diagonal:" + halfDiagonal); - // P P - Model - // /| A - Palm - // / | d B - unit vector toward tip - // / | X - base of the perpendicular line - // A---X----->B d - distance fom axis - // x x - distance from A - // - // |X-A| = (P-A).B - // X == A + ((P-A).B)B - // d = |P-X| - - var A = pickRay.origin; - var B = Vec3.normalize(pickRay.direction); - var P = properties.position; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - var X = Vec3.sum(A, Vec3.multiply(B, x)); - var d = Vec3.length(Vec3.subtract(P, X)); - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) - && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (0 < x && sizeOK) { - entitySelected = true; - selectedEntityID = foundEntity; - selectedEntityProperties = properties; - orientation = MyAvatar.orientation; - intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation)); - } - } - } - if (entitySelected) { - selectedEntityProperties.oldDimensions = selectedEntityProperties.dimensions; - selectedEntityProperties.oldPosition = { - x: selectedEntityProperties.position.x, - y: selectedEntityProperties.position.y, - z: selectedEntityProperties.position.z, - }; - selectedEntityProperties.oldRotation = { - x: selectedEntityProperties.rotation.x, - y: selectedEntityProperties.rotation.y, - z: selectedEntityProperties.rotation.z, - w: selectedEntityProperties.rotation.w, - }; - selectedEntityProperties.glowLevel = 0.0; - - print("Clicked on " + selectedEntityID.id + " " + entitySelected); - tooltip.updateText(selectedEntityProperties); - tooltip.show(true); - } -} - -var glowedEntityID = { id: -1, isKnownID: false }; -var oldModifier = 0; -var modifier = 0; -var wasShifted = false; -function mouseMoveEvent(event) { - if (event.isAlt || !isActive) { - return; - } - - var pickRay = Camera.computePickRay(event.x, event.y); - if (!entitySelected) { - var entityIntersection = Entities.findRayIntersection(pickRay); - if (entityIntersection.accurate) { - if(glowedEntityID.isKnownID && glowedEntityID.id != entityIntersection.entityID.id) { - Entities.editEntity(glowedEntityID, { glowLevel: 0.0 }); - glowedEntityID.id = -1; - glowedEntityID.isKnownID = false; - } - - var halfDiagonal = Vec3.length(entityIntersection.properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), - entityIntersection.properties.position)) * 180 / 3.14; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) - && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (entityIntersection.entityID.isKnownID && sizeOK) { - if (wantEntityGlow) { - Entities.editEntity(entityIntersection.entityID, { glowLevel: 0.25 }); - } - glowedEntityID = entityIntersection.entityID; - } - - } - return; - } - - if (event.isLeftButton) { - if (event.isRightButton) { - modifier = 1; // Scale - } else { - modifier = 2; // Translate - } - } else if (event.isRightButton) { - modifier = 3; // rotate - } else { - modifier = 0; - } - pickRay = Camera.computePickRay(event.x, event.y); - if (wasShifted != event.isShifted || modifier != oldModifier) { - selectedEntityProperties.oldDimensions = selectedEntityProperties.dimensions; - - selectedEntityProperties.oldPosition = { - x: selectedEntityProperties.position.x, - y: selectedEntityProperties.position.y, - z: selectedEntityProperties.position.z, - }; - selectedEntityProperties.oldRotation = { - x: selectedEntityProperties.rotation.x, - y: selectedEntityProperties.rotation.y, - z: selectedEntityProperties.rotation.z, - w: selectedEntityProperties.rotation.w, - }; - orientation = MyAvatar.orientation; - intersection = rayPlaneIntersection(pickRay, - selectedEntityProperties.oldPosition, - Quat.getFront(orientation)); - - mouseLastPosition = { x: event.x, y: event.y }; - wasShifted = event.isShifted; - oldModifier = modifier; - return; - } - - - switch (modifier) { - case 0: - return; - case 1: - // Let's Scale - selectedEntityProperties.dimensions = Vec3.multiply(selectedEntityProperties.dimensions, - (1.0 + (mouseLastPosition.y - event.y) / SCALE_FACTOR)); - - var halfDiagonal = Vec3.length(selectedEntityProperties.dimensions) / 2.0; - - if (halfDiagonal < 0.01) { - print("Scale too small ... bailling."); - return; - } - break; - - case 2: - // Let's translate - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityProperties.oldPosition, - Quat.getFront(orientation)); - var vector = Vec3.subtract(newIntersection, intersection) - if (event.isShifted) { - var i = Vec3.dot(vector, Quat.getRight(orientation)); - var j = Vec3.dot(vector, Quat.getUp(orientation)); - vector = Vec3.sum(Vec3.multiply(Quat.getRight(orientation), i), - Vec3.multiply(Quat.getFront(orientation), j)); - } - selectedEntityProperties.position = Vec3.sum(selectedEntityProperties.oldPosition, vector); - break; - case 3: - // Let's rotate - if (somethingChanged) { - selectedEntityProperties.oldRotation.x = selectedEntityProperties.rotation.x; - selectedEntityProperties.oldRotation.y = selectedEntityProperties.rotation.y; - selectedEntityProperties.oldRotation.z = selectedEntityProperties.rotation.z; - selectedEntityProperties.oldRotation.w = selectedEntityProperties.rotation.w; - mouseLastPosition.x = event.x; - mouseLastPosition.y = event.y; - somethingChanged = false; - } - - - var pixelPerDegrees = windowDimensions.y / (1 * 360); // the entire height of the window allow you to make 2 full rotations - - //compute delta in pixel - var cameraForward = Quat.getFront(Camera.getOrientation()); - var rotationAxis = (!zIsPressed && xIsPressed) ? { x: 1, y: 0, z: 0 } : - (!zIsPressed && !xIsPressed) ? { x: 0, y: 1, z: 0 } : - { x: 0, y: 0, z: 1 }; - rotationAxis = Vec3.multiplyQbyV(selectedEntityProperties.rotation, rotationAxis); - var orthogonalAxis = Vec3.cross(cameraForward, rotationAxis); - var mouseDelta = { x: event.x - mouseLastPosition - .x, y: mouseLastPosition.y - event.y, z: 0 }; - var transformedMouseDelta = Vec3.multiplyQbyV(Camera.getOrientation(), mouseDelta); - var delta = Math.floor(Vec3.dot(transformedMouseDelta, Vec3.normalize(orthogonalAxis)) / pixelPerDegrees); - - var STEP = 15; - if (!event.isShifted) { - delta = Math.round(delta / STEP) * STEP; - } - - var rotation = Quat.fromVec3Degrees({ - x: (!zIsPressed && xIsPressed) ? delta : 0, // x is pressed - y: (!zIsPressed && !xIsPressed) ? delta : 0, // neither is pressed - z: (zIsPressed && !xIsPressed) ? delta : 0 // z is pressed - }); - rotation = Quat.multiply(selectedEntityProperties.oldRotation, rotation); - - selectedEntityProperties.rotation.x = rotation.x; - selectedEntityProperties.rotation.y = rotation.y; - selectedEntityProperties.rotation.z = rotation.z; - selectedEntityProperties.rotation.w = rotation.w; - break; - } - - Entities.editEntity(selectedEntityID, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); -} - - -function mouseReleaseEvent(event) { - if (event.isAlt || !isActive) { - return; - } - if (entitySelected) { - tooltip.show(false); - } - - entitySelected = false; - - glowedEntityID.id = -1; - glowedEntityID.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 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")) { - print("no delete... adding ours"); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", - shortcutKeyEvent: { text: "backspace" }, afterItem: "Models" }); - modelMenuAddedDelete = true; - } else { - print("delete exists... don't add ours"); - } - - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." }); - 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: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" }); - - Entities.setLightsArePickable(false); - -} - -function cleanupModelMenus() { - Menu.removeSeparator("Edit", "Models"); - Menu.removeMenuItem("Edit", "Edit Properties..."); - if (modelMenuAddedDelete) { - // delete our menuitems - Menu.removeMenuItem("Edit", "Delete"); - } - - Menu.removeMenuItem("Edit", "Model List..."); - Menu.removeMenuItem("Edit", "Paste Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); - - Menu.removeSeparator("File", "Models"); - Menu.removeMenuItem("File", "Export Models"); - Menu.removeMenuItem("File", "Import Models"); -} - -function scriptEnding() { - leftController.cleanup(); - rightController.cleanup(); - progressDialog.cleanup(); - toolBar.cleanup(); - cleanupModelMenus(); - tooltip.cleanup(); - modelImporter.cleanup(); - if (exportMenu) { - exportMenu.close(); - } - Entities.setLightsArePickable(originalLightsArePickable); -} -Script.scriptEnding.connect(scriptEnding); - -// register the call back so it fires before each data send -Script.update.connect(checkController); -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseMoveEvent.connect(mouseMoveEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); - -setupModelMenus(); - -var propertiesForEditedEntity; -var editEntityFormArray; -var editModelID = -1; -var dimensionX; -var dimensionY; -var dimensionZ; -var rescalePercentage; - -function showPropertiesForm(editModelID) { - entityPropertyDialogBox.openDialog(editModelID); -} - -function handeMenuEvent(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 (leftController.grabbing) { - print(" Delete Entity.... leftController.entityID="+ leftController.entityID); - Entities.deleteEntity(leftController.entityID); - leftController.grabbing = false; - if (glowedEntityID.id == leftController.entityID.id) { - glowedEntityID = { id: -1, isKnownID: false }; - } - } else if (rightController.grabbing) { - print(" Delete Entity.... rightController.entityID="+ rightController.entityID); - Entities.deleteEntity(rightController.entityID); - rightController.grabbing = false; - if (glowedEntityID.id == rightController.entityID.id) { - glowedEntityID = { id: -1, isKnownID: false }; - } - } else if (entitySelected) { - print(" Delete Entity.... selectedEntityID="+ selectedEntityID); - Entities.deleteEntity(selectedEntityID); - entitySelected = false; - if (glowedEntityID.id == selectedEntityID.id) { - glowedEntityID = { id: -1, isKnownID: false }; - } - } else { - print(" Delete Entity.... not holding..."); - } - } else if (menuItem == "Model List...") { - var models = new Array(); - models = Entities.findEntities(MyAvatar.position, Number.MAX_VALUE); - for (var i = 0; i < models.length; i++) { - models[i].properties = Entities.getEntityProperties(models[i]); - models[i].toString = function() { - var modelname; - if (this.properties.type == "Model") { - modelname = decodeURIComponent( - this.properties.modelURL.indexOf("/") != -1 ? - this.properties.modelURL.substring(this.properties.modelURL.lastIndexOf("/") + 1) : - this.properties.modelURL); - } else { - modelname = this.properties.id; - } - return "[" + this.properties.type + "] " + modelname; - }; - } - var form = [{label: "Model: ", options: models}]; - form.push({label: "Action: ", options: ["Properties", "Delete", "Teleport"]}); - form.push({ button: "Cancel" }); - if (Window.form("Model List", form)) { - var selectedModel = form[0].value; - if (form[1].value == "Properties") { - editModelID = selectedModel; - showPropertiesForm(editModelID); - } else if (form[1].value == "Delete") { - Entities.deleteEntity(selectedModel); - } else if (form[1].value == "Teleport") { - MyAvatar.position = selectedModel.properties.position; - } - } - } else if (menuItem == "Edit Properties...") { - editModelID = -1; - if (leftController.grabbing) { - print(" Edit Properties.... leftController.entityID="+ leftController.entityID); - editModelID = leftController.entityID; - } else if (rightController.grabbing) { - print(" Edit Properties.... rightController.entityID="+ rightController.entityID); - editModelID = rightController.entityID; - } else if (entitySelected) { - print(" Edit Properties.... selectedEntityID="+ selectedEntityID); - editModelID = selectedEntityID; - } else { - print(" Edit Properties.... not holding..."); - } - if (editModelID != -1) { - print(" Edit Properties.... about to edit properties..."); - showPropertiesForm(editModelID); - } - } else if (menuItem == "Paste Models") { - modelImporter.paste(); - } else if (menuItem == "Export Models") { - if (!exportMenu) { - exportMenu = new ExportMenu({ - onClose: function () { - exportMenu = null; - } - }); - } - } else if (menuItem == "Import Models") { - modelImporter.doImport(); - } - tooltip.show(false); -} -Menu.menuItemEvent.connect(handeMenuEvent); - - - -// handling of inspect.js concurrence -var zIsPressed = false; -var xIsPressed = false; -var somethingChanged = false; -Controller.keyPressEvent.connect(function (event) { - if ((event.text == "z" || event.text == "Z") && !zIsPressed) { - zIsPressed = true; - somethingChanged = true; - } - if ((event.text == "x" || event.text == "X") && !xIsPressed) { - xIsPressed = true; - somethingChanged = true; - } - - // resets model orientation when holding with mouse - if (event.text == "r" && entitySelected) { - selectedEntityProperties.rotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 0 }); - Entities.editEntity(selectedEntityID, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - somethingChanged = true; - } -}); - -Controller.keyReleaseEvent.connect(function (event) { - if (event.text == "z" || event.text == "Z") { - zIsPressed = false; - somethingChanged = true; - } - if (event.text == "x" || event.text == "X") { - xIsPressed = false; - somethingChanged = true; - } - // 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..."); - } - if (event.text == "BACKSPACE") { - handeMenuEvent("Delete"); - } -}); - diff --git a/examples/hydraGrab.js b/examples/hydraGrab.js new file mode 100644 index 0000000000..4d0b873fd2 --- /dev/null +++ b/examples/hydraGrab.js @@ -0,0 +1,742 @@ +// +// hydraGrab.js +// examples +// +// Created by Clément Brisset on 4/24/14. +// Copyright 2014 High Fidelity, Inc. +// +// This script allows you to edit models either with the razor hydras or with your mouse +// +// Using the hydras : +// grab models with the triggers, you can then move the models around or scale them with both hands. +// You can switch mode using the bumpers so that you can move models around more easily. +// +// 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"); +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; +var allowSmallModels = false; +var wantEntityGlow = false; + +var LEFT = 0; +var RIGHT = 1; + +var jointList = MyAvatar.getJointNames(); + +var mode = 0; + +function controller(wichSide) { + this.side = wichSide; + this.palm = 2 * wichSide; + this.tip = 2 * wichSide + 1; + this.trigger = wichSide; + this.bumper = 6 * wichSide + 5; + + this.oldPalmPosition = Controller.getSpatialControlPosition(this.palm); + this.palmPosition = Controller.getSpatialControlPosition(this.palm); + + this.oldTipPosition = Controller.getSpatialControlPosition(this.tip); + this.tipPosition = Controller.getSpatialControlPosition(this.tip); + + this.oldUp = Controller.getSpatialControlNormal(this.palm); + this.up = this.oldUp; + + this.oldFront = Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)); + this.front = this.oldFront; + + this.oldRight = Vec3.cross(this.front, this.up); + this.right = this.oldRight; + + this.oldRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); + this.rotation = this.oldRotation; + + this.triggerValue = Controller.getTriggerValue(this.trigger); + this.bumperValue = Controller.isButtonPressed(this.bumper); + + this.pressed = false; // is trigger pressed + this.pressing = false; // is trigger being pressed (is pressed now but wasn't previously) + + this.grabbing = false; + this.entityID = { isKnownID: false }; + this.modelURL = ""; + this.oldModelRotation; + this.oldModelPosition; + this.oldModelHalfDiagonal; + + this.positionAtGrab; + this.rotationAtGrab; + this.modelPositionAtGrab; + this.rotationAtGrab; + this.jointsIntersectingFromStart = []; + + this.laser = Overlays.addOverlay("line3d", { + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 0, z: 0 }, + color: LASER_COLOR, + alpha: 1, + visible: false, + lineWidth: LASER_WIDTH, + anchor: "MyAvatar" + }); + + this.guideScale = 0.02; + this.ball = Overlays.addOverlay("sphere", { + position: { x: 0, y: 0, z: 0 }, + size: this.guideScale, + solid: true, + color: { red: 0, green: 255, blue: 0 }, + alpha: 1, + visible: false, + anchor: "MyAvatar" + }); + this.leftRight = Overlays.addOverlay("line3d", { + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 0, z: 0 }, + color: { red: 0, green: 0, blue: 255 }, + alpha: 1, + visible: false, + lineWidth: LASER_WIDTH, + anchor: "MyAvatar" + }); + this.topDown = Overlays.addOverlay("line3d", { + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 0, z: 0 }, + color: { red: 0, green: 0, blue: 255 }, + alpha: 1, + visible: false, + lineWidth: LASER_WIDTH, + anchor: "MyAvatar" + }); + + + + this.grab = function (entityID, properties) { + print("Grabbing " + entityID.id); + this.grabbing = true; + this.entityID = entityID; + this.modelURL = properties.modelURL; + + this.oldModelPosition = properties.position; + this.oldModelRotation = properties.rotation; + this.oldModelHalfDiagonal = Vec3.length(properties.dimensions) / 2.0; + + this.positionAtGrab = this.palmPosition; + this.rotationAtGrab = this.rotation; + this.modelPositionAtGrab = properties.position; + this.rotationAtGrab = properties.rotation; + this.jointsIntersectingFromStart = []; + for (var i = 0; i < jointList.length; i++) { + var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition); + if (distance < this.oldModelHalfDiagonal) { + this.jointsIntersectingFromStart.push(i); + } + } + this.showLaser(false); + } + + this.release = function () { + if (this.grabbing) { + jointList = MyAvatar.getJointNames(); + + var closestJointIndex = -1; + var closestJointDistance = 10; + for (var i = 0; i < jointList.length; i++) { + var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition); + if (distance < closestJointDistance) { + closestJointDistance = distance; + closestJointIndex = i; + } + } + + if (closestJointIndex != -1) { + print("closestJoint: " + jointList[closestJointIndex]); + print("closestJointDistance (attach max distance): " + closestJointDistance + " (" + this.oldModelHalfDiagonal + ")"); + } + + if (closestJointDistance < this.oldModelHalfDiagonal) { + + if (this.jointsIntersectingFromStart.indexOf(closestJointIndex) != -1 || + (leftController.grabbing && rightController.grabbing && + leftController.entityID.id == rightController.entityID.id)) { + // Do nothing + } else { + print("Attaching to " + jointList[closestJointIndex]); + var jointPosition = MyAvatar.getJointPosition(jointList[closestJointIndex]); + var jointRotation = MyAvatar.getJointCombinedRotation(jointList[closestJointIndex]); + + var attachmentOffset = Vec3.subtract(this.oldModelPosition, jointPosition); + attachmentOffset = Vec3.multiplyQbyV(Quat.inverse(jointRotation), attachmentOffset); + var attachmentRotation = Quat.multiply(Quat.inverse(jointRotation), this.oldModelRotation); + + MyAvatar.attach(this.modelURL, jointList[closestJointIndex], + attachmentOffset, attachmentRotation, 2.0 * this.oldModelHalfDiagonal, + true, false); + Entities.deleteEntity(this.entityID); + } + } + } + + this.grabbing = false; + this.entityID.isKnownID = false; + this.jointsIntersectingFromStart = []; + this.showLaser(true); + } + + this.checkTrigger = function () { + if (this.triggerValue > 0.9) { + if (this.pressed) { + this.pressing = false; + } else { + this.pressing = true; + } + this.pressed = true; + } else { + this.pressing = false; + this.pressed = false; + } + } + + this.checkEntity = function (properties) { + // P P - Model + // /| A - Palm + // / | d B - unit vector toward tip + // / | X - base of the perpendicular line + // A---X----->B d - distance fom axis + // x x - distance from A + // + // |X-A| = (P-A).B + // X == A + ((P-A).B)B + // d = |P-X| + + var A = this.palmPosition; + var B = this.front; + var P = properties.position; + + var x = Vec3.dot(Vec3.subtract(P, A), B); + var y = Vec3.dot(Vec3.subtract(P, A), this.up); + var z = Vec3.dot(Vec3.subtract(P, A), this.right); + var X = Vec3.sum(A, Vec3.multiply(B, x)); + var d = Vec3.length(Vec3.subtract(P, X)); + var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; + + var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; + + var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) + && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); + + if (0 < x && sizeOK) { + return { valid: true, x: x, y: y, z: z }; + } + return { valid: false }; + } + + this.glowedIntersectingModel = { isKnownID: false }; + this.moveLaser = function () { + // the overlays here are anchored to the avatar, which means they are specified in the avatar's local frame + + var inverseRotation = Quat.inverse(MyAvatar.orientation); + var startPosition = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.palmPosition, MyAvatar.position)); + var direction = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.tipPosition, this.palmPosition)); + var distance = Vec3.length(direction); + direction = Vec3.multiply(direction, LASER_LENGTH_FACTOR / distance); + var endPosition = Vec3.sum(startPosition, direction); + + Overlays.editOverlay(this.laser, { + start: startPosition, + end: endPosition + }); + + + Overlays.editOverlay(this.ball, { + position: endPosition + }); + Overlays.editOverlay(this.leftRight, { + start: Vec3.sum(endPosition, Vec3.multiply(this.right, 2 * this.guideScale)), + end: Vec3.sum(endPosition, Vec3.multiply(this.right, -2 * this.guideScale)) + }); + Overlays.editOverlay(this.topDown, { + 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); + + 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 halfDiagonal = Vec3.length(intersection.properties.dimensions) / 2.0; + + var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), intersection.properties.position)) * 180 / 3.14; + var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) + && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); + if (intersection.accurate && intersection.entityID.isKnownID && sizeOK) { + this.glowedIntersectingModel = intersection.entityID; + + if (wantEntityGlow) { + Entities.editEntity(this.glowedIntersectingModel, { glowLevel: 0.25 }); + } + } + } + } + + this.showLaser = function (show) { + Overlays.editOverlay(this.laser, { visible: show }); + Overlays.editOverlay(this.ball, { visible: show }); + Overlays.editOverlay(this.leftRight, { visible: show }); + Overlays.editOverlay(this.topDown, { visible: show }); + } + this.moveEntity = function () { + 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; + print("Identified ID " + this.entityID.id + ", isKnown: " + this.entityID.isKnownID); + } + var newPosition; + var newRotation; + + switch (mode) { + case 0: + newPosition = Vec3.sum(this.palmPosition, + Vec3.multiply(this.front, this.x)); + newPosition = Vec3.sum(newPosition, + Vec3.multiply(this.up, this.y)); + newPosition = Vec3.sum(newPosition, + Vec3.multiply(this.right, this.z)); + + + newRotation = Quat.multiply(this.rotation, + Quat.inverse(this.oldRotation)); + newRotation = Quat.multiply(newRotation, + this.oldModelRotation); + break; + case 1: + var forward = Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1 }); + var d = Vec3.dot(forward, MyAvatar.position); + + var factor1 = Vec3.dot(forward, this.positionAtGrab) - d; + var factor2 = Vec3.dot(forward, this.modelPositionAtGrab) - d; + var vector = Vec3.subtract(this.palmPosition, this.positionAtGrab); + + if (factor2 < 0) { + factor2 = 0; + } + if (factor1 <= 0) { + factor1 = 1; + factor2 = 1; + } + + newPosition = Vec3.sum(this.modelPositionAtGrab, + Vec3.multiply(vector, + factor2 / factor1)); + + newRotation = Quat.multiply(this.rotation, + Quat.inverse(this.rotationAtGrab)); + newRotation = Quat.multiply(newRotation, + this.rotationAtGrab); + break; + } + Entities.editEntity(this.entityID, { + position: newPosition, + rotation: newRotation + }); + this.oldModelRotation = newRotation; + this.oldModelPosition = newPosition; + + var indicesToRemove = []; + for (var i = 0; i < this.jointsIntersectingFromStart.length; ++i) { + var distance = Vec3.distance(MyAvatar.getJointPosition(this.jointsIntersectingFromStart[i]), this.oldModelPosition); + if (distance >= this.oldModelHalfDiagonal) { + indicesToRemove.push(this.jointsIntersectingFromStart[i]); + } + + } + for (var i = 0; i < indicesToRemove.length; ++i) { + this.jointsIntersectingFromStart.splice(this.jointsIntersectingFromStart.indexOf(indicesToRemove[i], 1)); + } + } + } + + this.update = function () { + this.oldPalmPosition = this.palmPosition; + this.oldTipPosition = this.tipPosition; + this.palmPosition = Controller.getSpatialControlPosition(this.palm); + this.tipPosition = Controller.getSpatialControlPosition(this.tip); + + this.oldUp = this.up; + this.up = Vec3.normalize(Controller.getSpatialControlNormal(this.palm)); + + this.oldFront = this.front; + this.front = Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)); + + this.oldRight = this.right; + this.right = Vec3.normalize(Vec3.cross(this.front, this.up)); + + this.oldRotation = this.rotation; + this.rotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); + + this.triggerValue = Controller.getTriggerValue(this.trigger); + + 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 } }); + } + } + this.bumperValue = bumperValue; + + + this.checkTrigger(); + + this.moveLaser(); + + if (!this.pressed && this.grabbing) { + // release if trigger not pressed anymore. + this.release(); + } + + if (this.pressing) { + // Checking for attachments intersecting + var attachments = MyAvatar.getAttachmentData(); + var attachmentIndex = -1; + var attachmentX = LASER_LENGTH_FACTOR; + + var newModel; + var newProperties; + + for (var i = 0; i < attachments.length; ++i) { + var position = Vec3.sum(MyAvatar.getJointPosition(attachments[i].jointName), + Vec3.multiplyQbyV(MyAvatar.getJointCombinedRotation(attachments[i].jointName), attachments[i].translation)); + var scale = attachments[i].scale; + + var A = this.palmPosition; + var B = this.front; + var P = position; + + var x = Vec3.dot(Vec3.subtract(P, A), B); + var X = Vec3.sum(A, Vec3.multiply(B, x)); + var d = Vec3.length(Vec3.subtract(P, X)); + + if (d < scale / 2.0 && 0 < x && x < attachmentX) { + attachmentIndex = i; + attachmentX = d; + } + } + + if (attachmentIndex != -1) { + print("Detaching: " + attachments[attachmentIndex].modelURL); + MyAvatar.detachOne(attachments[attachmentIndex].modelURL, attachments[attachmentIndex].jointName); + + newProperties = { + type: "Model", + position: Vec3.sum(MyAvatar.getJointPosition(attachments[attachmentIndex].jointName), + Vec3.multiplyQbyV(MyAvatar.getJointCombinedRotation(attachments[attachmentIndex].jointName), attachments[attachmentIndex].translation)), + rotation: Quat.multiply(MyAvatar.getJointCombinedRotation(attachments[attachmentIndex].jointName), + attachments[attachmentIndex].rotation), + + // TODO: how do we know the correct dimensions for detachment??? + dimensions: { x: attachments[attachmentIndex].scale / 2.0, + y: attachments[attachmentIndex].scale / 2.0, + z: attachments[attachmentIndex].scale / 2.0 }, + + modelURL: attachments[attachmentIndex].modelURL + }; + + newModel = Entities.addEntity(newProperties); + + + } else { + // There is none so ... + // Checking model tree + 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); + + if(!foundIntersection.accurate) { + print("No accurate intersection"); + return; + } + newModel = foundIntersection.entityID; + if (!newModel.isKnownID) { + var identify = Entities.identifyEntity(newModel); + if (!identify.isKnownID) { + print("Unknown ID " + identify.id + " (update loop " + newModel.id + ")"); + return; + } + newModel = identify; + } + newProperties = Entities.getEntityProperties(newModel); + } + print("foundEntity.modelURL=" + newProperties.modelURL); + var check = this.checkEntity(newProperties); + if (!check.valid) { + return; + } + + this.grab(newModel, newProperties); + + this.x = check.x; + this.y = check.y; + this.z = check.z; + return; + } + } + + this.cleanup = function () { + Overlays.deleteOverlay(this.laser); + Overlays.deleteOverlay(this.ball); + Overlays.deleteOverlay(this.leftRight); + Overlays.deleteOverlay(this.topDown); + } +} + +var leftController = new controller(LEFT); +var rightController = new controller(RIGHT); + +function moveEntities() { + if (leftController.grabbing && rightController.grabbing && rightController.entityID.id == leftController.entityID.id) { + var newPosition = leftController.oldModelPosition; + var rotation = leftController.oldModelRotation; + var ratio = 1; + + + switch (mode) { + case 0: + var oldLeftPoint = Vec3.sum(leftController.oldPalmPosition, Vec3.multiply(leftController.oldFront, leftController.x)); + var oldRightPoint = Vec3.sum(rightController.oldPalmPosition, Vec3.multiply(rightController.oldFront, rightController.x)); + + var oldMiddle = Vec3.multiply(Vec3.sum(oldLeftPoint, oldRightPoint), 0.5); + var oldLength = Vec3.length(Vec3.subtract(oldLeftPoint, oldRightPoint)); + + + var leftPoint = Vec3.sum(leftController.palmPosition, Vec3.multiply(leftController.front, leftController.x)); + var rightPoint = Vec3.sum(rightController.palmPosition, Vec3.multiply(rightController.front, rightController.x)); + + var middle = Vec3.multiply(Vec3.sum(leftPoint, rightPoint), 0.5); + var length = Vec3.length(Vec3.subtract(leftPoint, rightPoint)); + + + ratio = length / oldLength; + newPosition = Vec3.sum(middle, + Vec3.multiply(Vec3.subtract(leftController.oldModelPosition, oldMiddle), ratio)); + break; + case 1: + var u = Vec3.normalize(Vec3.subtract(rightController.oldPalmPosition, leftController.oldPalmPosition)); + var v = Vec3.normalize(Vec3.subtract(rightController.palmPosition, leftController.palmPosition)); + + var cos_theta = Vec3.dot(u, v); + if (cos_theta > 1) { + cos_theta = 1; + } + var angle = Math.acos(cos_theta) / Math.PI * 180; + if (angle < 0.1) { + return; + + } + var w = Vec3.normalize(Vec3.cross(u, v)); + + rotation = Quat.multiply(Quat.angleAxis(angle, w), leftController.oldModelRotation); + + + leftController.positionAtGrab = leftController.palmPosition; + leftController.rotationAtGrab = leftController.rotation; + leftController.modelPositionAtGrab = leftController.oldModelPosition; + leftController.rotationAtGrab = rotation; + rightController.positionAtGrab = rightController.palmPosition; + rightController.rotationAtGrab = rightController.rotation; + rightController.modelPositionAtGrab = rightController.oldModelPosition; + rightController.rotationAtGrab = rotation; + break; + } + Entities.editEntity(leftController.entityID, { + position: newPosition, + rotation: rotation, + // TODO: how do we know the correct dimensions for detachment??? + //radius: leftController.oldModelHalfDiagonal * ratio + dimensions: { x: leftController.oldModelHalfDiagonal * ratio, + y: leftController.oldModelHalfDiagonal * ratio, + z: leftController.oldModelHalfDiagonal * ratio } + + + }); + leftController.oldModelPosition = newPosition; + leftController.oldModelRotation = rotation; + leftController.oldModelHalfDiagonal *= ratio; + + rightController.oldModelPosition = newPosition; + rightController.oldModelRotation = rotation; + rightController.oldModelHalfDiagonal *= ratio; + return; + } + leftController.moveEntity(); + rightController.moveEntity(); +} + +var hydraConnected = false; +function checkController(deltaTime) { + var numberOfButtons = Controller.getNumberOfButtons(); + var numberOfTriggers = Controller.getNumberOfTriggers(); + var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); + var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; + + // this is expected for hydras + if (numberOfButtons == 12 && numberOfTriggers == 2 && controllersPerTrigger == 2) { + if (!hydraConnected) { + hydraConnected = true; + } + + leftController.update(); + rightController.update(); + moveEntities(); + } else { + if (hydraConnected) { + hydraConnected = false; + + leftController.showLaser(false); + rightController.showLaser(false); + } + } +} + +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 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")) { + print("no delete... adding ours"); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", + shortcutKeyEvent: { text: "backspace" }, afterItem: "Models" }); + 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 }); + + Entities.setLightsArePickable(false); +} + +function cleanupModelMenus() { + Menu.removeMenuItem("Edit", "Edit Properties..."); + if (modelMenuAddedDelete) { + // delete our menuitems + Menu.removeMenuItem("Edit", "Delete"); + } + + Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); + +} + +function scriptEnding() { + leftController.cleanup(); + rightController.cleanup(); + cleanupModelMenus(); + Entities.setLightsArePickable(originalLightsArePickable); +} +Script.scriptEnding.connect(scriptEnding); + +// register the call back so it fires before each data send +Script.update.connect(checkController); + +setupModelMenus(); + +var editModelID = -1; +function showPropertiesForm(editModelID) { + entityPropertyDialogBox.openDialog(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 (leftController.grabbing) { + print(" Delete Entity.... leftController.entityID="+ leftController.entityID); + Entities.deleteEntity(leftController.entityID); + leftController.grabbing = false; + if (glowedEntityID.id == leftController.entityID.id) { + glowedEntityID = { id: -1, isKnownID: false }; + } + } else if (rightController.grabbing) { + print(" Delete Entity.... rightController.entityID="+ rightController.entityID); + Entities.deleteEntity(rightController.entityID); + rightController.grabbing = false; + if (glowedEntityID.id == rightController.entityID.id) { + glowedEntityID = { id: -1, isKnownID: false }; + } + } else { + print(" Delete Entity.... not holding..."); + } + } else if (menuItem == "Edit Properties...") { + editModelID = -1; + if (leftController.grabbing) { + print(" Edit Properties.... leftController.entityID="+ leftController.entityID); + editModelID = leftController.entityID; + } else if (rightController.grabbing) { + print(" Edit Properties.... rightController.entityID="+ rightController.entityID); + editModelID = rightController.entityID; + } else { + print(" Edit Properties.... not holding..."); + } + if (editModelID != -1) { + print(" Edit Properties.... about to edit properties..."); + showPropertiesForm(editModelID); + } + } +}); + +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..."); + } + if (event.text == "BACKSPACE") { + handeMenuEvent("Delete"); + } +}); + From 75758c1a3e6bb15de334b5c84edbff2f8f3bec66 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 8 Jan 2015 15:40:54 -0800 Subject: [PATCH 022/159] Use static GLEW in render-utils for Windows --- libraries/render-utils/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index f84bd97c13..cf3d7a6ad7 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -9,5 +9,10 @@ include_glm() link_hifi_libraries(animation fbx shared gpu) +if (WIN32) + # we're using static GLEW, so define GLEW_STATIC + add_definitions(-DGLEW_STATIC) +endif () + # call macro to include our dependency includes and bubble them up via a property on our target include_dependency_includes() \ No newline at end of file From 9ca0df07967fbc945b16bdf94c59e9ca3955eb9d Mon Sep 17 00:00:00 2001 From: Chris Collins Date: Thu, 8 Jan 2015 16:05:32 -0800 Subject: [PATCH 023/159] Small fixes to scripts -merge duplicate gun scripts -fix url of sit --- examples/controllers/hydra/gun.js | 209 +++++++++++++++++++++--------- examples/gun.js | 3 +- examples/sit.js | 2 +- 3 files changed, 153 insertions(+), 61 deletions(-) diff --git a/examples/controllers/hydra/gun.js b/examples/controllers/hydra/gun.js index de18317335..18fe9c542d 100644 --- a/examples/controllers/hydra/gun.js +++ b/examples/controllers/hydra/gun.js @@ -14,7 +14,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("../../libraries/globals.js"); +Script.include("libraries/globals.js"); function getRandomFloat(min, max) { return Math.random() * (max - min) + min; @@ -26,14 +26,19 @@ var yawFromMouse = 0; var pitchFromMouse = 0; var isMouseDown = false; -var BULLET_VELOCITY = 5.0; +var BULLET_VELOCITY = 20.0; var MIN_THROWER_DELAY = 1000; var MAX_THROWER_DELAY = 1000; var LEFT_BUTTON_3 = 3; var RELOAD_INTERVAL = 5; +var KICKBACK_ANGLE = 15; +var elbowKickAngle = 0.0; +var rotationBeforeKickback; + var showScore = false; + // Load some sound to use for loading and firing var fireSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/GUN-SHOT2.raw"); var loadSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/Gun_Reload_Weapon22.raw"); @@ -48,10 +53,11 @@ var audioOptions = { } var shotsFired = 0; - var shotTime = new Date(); -// initialize our triggers +var activeControllers = 0; + +// initialize our controller triggers var triggerPulled = new Array(); var numberOfTriggers = Controller.getNumberOfTriggers(); for (t = 0; t < numberOfTriggers; t++) { @@ -59,9 +65,11 @@ for (t = 0; t < numberOfTriggers; t++) { } var isLaunchButtonPressed = false; - var score = 0; +var bulletID = false; +var targetID = false; + // Create a reticle image in center of screen var screenSize = Controller.getViewportDimensions(); var reticle = Overlays.addOverlay("image", { @@ -74,6 +82,16 @@ var reticle = Overlays.addOverlay("image", { alpha: 1 }); +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 + }); + if (showScore) { var text = Overlays.addOverlay("text", { x: screenSize.x / 2 - 100, @@ -95,18 +113,20 @@ function printVector(string, vector) { } function shootBullet(position, velocity) { - var BULLET_SIZE = 0.01; - var BULLET_LIFETIME = 20.0; + var BULLET_SIZE = 0.07; + var BULLET_LIFETIME = 10.0; var BULLET_GRAVITY = -0.02; - Entities.addEntity( + bulletID = Entities.addEntity( { type: "Sphere", position: position, dimensions: { x: BULLET_SIZE, y: BULLET_SIZE, z: BULLET_SIZE }, - color: { red: 10, green: 10, blue: 10 }, + color: { red: 255, green: 0, blue: 0 }, velocity: velocity, lifetime: BULLET_LIFETIME, - gravity: { x: 0, y: BULLET_GRAVITY, z: 0 }, - damping: 0 }); + gravity: { x: 0, y: BULLET_GRAVITY, z: 0 }, + ignoreCollisions: false, + collisionsWillMove: true + }); // Play firing sounds audioOptions.position = position; @@ -115,36 +135,45 @@ function shootBullet(position, velocity) { if ((shotsFired % RELOAD_INTERVAL) == 0) { Audio.playSound(loadSound, audioOptions); } + + // Kickback the arm + 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.25; - var TARGET_GRAVITY = -0.6; + var TARGET_SIZE = 0.50; + var TARGET_GRAVITY = -0.25; var TARGET_LIFETIME = 300.0; - var TARGET_UP_VELOCITY = 3.0; - var TARGET_FWD_VELOCITY = 5.0; + var TARGET_UP_VELOCITY = 0.5; + var TARGET_FWD_VELOCITY = 1.0; var DISTANCE_TO_LAUNCH_FROM = 3.0; + var ANGLE_RANGE_FOR_LAUNCH = 20.0; var camera = Camera.getPosition(); //printVector("camera", camera); - var targetDirection = Quat.angleAxis(getRandomFloat(-20.0, 20.0), { x:0, y:1, z:0 }); + 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); - //printVector("forwardVector", forwardVector); + var newPosition = Vec3.sum(camera, Vec3.multiply(forwardVector, DISTANCE_TO_LAUNCH_FROM)); - //printVector("newPosition", newPosition); + var velocity = Vec3.multiply(forwardVector, TARGET_FWD_VELOCITY); velocity.y += TARGET_UP_VELOCITY; - //printVector("velocity", velocity); - - Entities.addEntity( - { type: "Sphere", + + targetID = Entities.addEntity( + { type: "Box", position: newPosition, dimensions: { x: TARGET_SIZE, y: TARGET_SIZE, z: TARGET_SIZE }, color: { red: 0, green: 200, blue: 200 }, + //angularVelocity: { x: 1, y: 0, z: 0 }, velocity: velocity, gravity: { x: 0, y: TARGET_GRAVITY, z: 0 }, lifetime: TARGET_LIFETIME, - damping: 0.0001 }); + damping: 0.0001, + collisionsWillMove: true }); // Record start time shotTime = new Date(); @@ -157,24 +186,25 @@ function shootTarget() { function entityCollisionWithEntity(entity1, entity2, collision) { - score++; - if (showScore) { - Overlays.editOverlay(text, { text: "Score: " + score } ); - } - - // Sort out which entity is which - // Record shot time - var endTime = new Date(); - var msecs = endTime.valueOf() - shotTime.valueOf(); - //print("hit, msecs = " + msecs); - //Vec3.print("penetration = ", collision.penetration); - //Vec3.print("contactPoint = ", collision.contactPoint); - Entities.deleteEntity(entity1); - Entities.deleteEntity(entity2); - // play the sound near the camera so the shooter can hear it - audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); - Audio.playSound(targetHitSound, audioOptions); + if (((entity1.id == bulletID.id) || (entity1.id == targetID.id)) && + ((entity2.id == bulletID.id) || (entity2.id == targetID.id))) { + score++; + if (showScore) { + Overlays.editOverlay(text, { text: "Score: " + score } ); + } + + // We will delete the bullet and target in 1/2 sec, but for now we can see them bounce! + Script.setTimeout(deleteBulletAndTarget, 500); + + // Turn the target and the bullet white + Entities.editEntity(entity1, { color: { red: 255, green: 255, blue: 255 }}); + Entities.editEntity(entity2, { color: { red: 255, green: 255, blue: 255 }}); + + // play the sound near the camera so the shooter can hear it + audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); + Audio.playSound(targetHitSound, audioOptions); + } } function keyPressEvent(event) { @@ -186,12 +216,42 @@ function keyPressEvent(event) { shootFromMouse(); } else if (event.text == "r") { playLoadSound(); + } else if (event.text == "s") { + // Hit this key to dump a posture from hydra to log + Quat.print("arm = ", MyAvatar.getJointRotation("LeftArm")); + Quat.print("forearm = ", MyAvatar.getJointRotation("LeftForeArm")); + Quat.print("hand = ", MyAvatar.getJointRotation("LeftHand")); + } } function playLoadSound() { audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); Audio.playSound(loadSound, audioOptions); + // Raise arm to firing posture + takeFiringPose(); +} + +function clearPose() { + MyAvatar.clearJointData("LeftForeArm"); + MyAvatar.clearJointData("LeftArm"); + MyAvatar.clearJointData("LeftHand"); +} + +function deleteBulletAndTarget() { + Entities.deleteEntity(bulletID); + Entities.deleteEntity(targetID); + bulletID = false; + targetID = false; +} + +function takeFiringPose() { + clearPose(); + if (Controller.getNumberOfSpatialControls() == 0) { + MyAvatar.setJointData("LeftForeArm", {x: -0.251919, y: -0.0415449, z: 0.499487, w: 0.827843}); + MyAvatar.setJointData("LeftArm", { x: 0.470196, y: -0.132559, z: 0.494033, w: 0.719219}); + MyAvatar.setJointData("LeftHand", { x: -0.0104815, y: -0.110551, z: -0.352111, w: 0.929333}); + } } MyAvatar.attach(gunModel, "RightHand", {x:0.02, y: 0.11, z: 0.04}, Quat.fromPitchYawRollDegrees(-0, -160, -79), 0.20); @@ -201,17 +261,49 @@ MyAvatar.attach(gunModel, "RightHand", {x:0.02, y: 0.11, z: 0.04}, Quat.fromPitc Script.setTimeout(playLoadSound, 2000); function update(deltaTime) { + if (bulletID && !bulletID.isKnownID) { + print("Trying to identify bullet"); + bulletID = Entities.identifyEntity(bulletID); + } + 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; + //MyAvatar.orientation = newOrientation; yawFromMouse = 0; // apply pitch from mouse var newPitch = MyAvatar.headPitch + pitchFromMouse; - MyAvatar.headPitch = newPitch; + //MyAvatar.headPitch = newPitch; pitchFromMouse = 0; + + if (activeControllers == 0) { + if (Controller.getNumberOfSpatialControls() > 0) { + activeControllers = Controller.getNumberOfSpatialControls(); + clearPose(); + } + } + + var KICKBACK_DECAY_RATE = 0.125; + if (elbowKickAngle > 0.0) { + if (elbowKickAngle > 0.5) { + var newAngle = elbowKickAngle * KICKBACK_DECAY_RATE; + elbowKickAngle -= newAngle; + var armRotation = MyAvatar.getJointRotation("LeftForeArm"); + armRotation = Quat.multiply(armRotation, Quat.fromPitchYawRollDegrees(0.0, 0.0, -newAngle)); + MyAvatar.setJointData("LeftForeArm", armRotation); + } else { + MyAvatar.setJointData("LeftForeArm", rotationBeforeKickback); + if (Controller.getNumberOfSpatialControls() > 0) { + clearPose(); + } + elbowKickAngle = 0.0; + } + } + // Check hydra controller for launch button press if (!isLaunchButtonPressed && Controller.isButtonPressed(LEFT_BUTTON_3)) { isLaunchButtonPressed = true; @@ -222,15 +314,13 @@ function update(deltaTime) { } - // Check hydra controller for trigger press + // check for trigger press - var numberOfTriggers = Controller.getNumberOfTriggers(); - var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); - var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; + var numberOfTriggers = 2; + var controllersPerTrigger = 2; - // this is expected for hydras if (numberOfTriggers == 2 && controllersPerTrigger == 2) { - for (var t = 0; t < numberOfTriggers; t++) { + for (var t = 0; t < 2; t++) { var shootABullet = false; var triggerValue = Controller.getTriggerValue(t); if (triggerPulled[t]) { @@ -239,14 +329,13 @@ function update(deltaTime) { triggerPulled[t] = false; // unpulled } } else { - // must pull to at least 0.9 - if (triggerValue > 0.9) { + // must pull to at least + if (triggerValue > 0.5) { triggerPulled[t] = true; // pulled shootABullet = true; } } - if (shootABullet) { var palmController = t * controllersPerTrigger; var palmPosition = Controller.getSpatialControlPosition(palmController); @@ -263,12 +352,8 @@ function update(deltaTime) { var position = { x: fingerTipPosition.x + palmToFingerTipVector.x/2, y: fingerTipPosition.y + palmToFingerTipVector.y/2, z: fingerTipPosition.z + palmToFingerTipVector.z/2}; - - var linearVelocity = 25; - - var velocity = { x: palmToFingerTipVector.x * linearVelocity, - y: palmToFingerTipVector.y * linearVelocity, - z: palmToFingerTipVector.z * linearVelocity }; + + var velocity = Vec3.multiply(BULLET_VELOCITY, Vec3.normalize(palmToFingerTipVector)); shootBullet(position, velocity); } @@ -280,8 +365,12 @@ function mousePressEvent(event) { isMouseDown = true; lastX = event.x; lastY = event.y; - //audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); - //Audio.playSound(loadSound, audioOptions); + + if (Overlays.getOverlayAtPoint({ x: event.x, y: event.y }) === offButton) { + Script.stop(); + } else { + shootFromMouse(); + } } function shootFromMouse() { @@ -312,8 +401,10 @@ function mouseMoveEvent(event) { function scriptEnding() { Overlays.deleteOverlay(reticle); + Overlays.deleteOverlay(offButton); Overlays.deleteOverlay(text); MyAvatar.detachOne(gunModel); + clearPose(); } Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); diff --git a/examples/gun.js b/examples/gun.js index c5b7b17052..18fe9c542d 100644 --- a/examples/gun.js +++ b/examples/gun.js @@ -254,7 +254,8 @@ function takeFiringPose() { } } -MyAvatar.attach(gunModel, "LeftHand", {x: -0.02, y: -.14, z: 0.07}, Quat.fromPitchYawRollDegrees(-70, -151, 72), 0.20); +MyAvatar.attach(gunModel, "RightHand", {x:0.02, y: 0.11, z: 0.04}, Quat.fromPitchYawRollDegrees(-0, -160, -79), 0.20); +//MyAvatar.attach(gunModel, "LeftHand", {x: -0.02, y: -.14, z: 0.07}, Quat.fromPitchYawRollDegrees(-70, -151, 72), 0.20); // Give a bit of time to load before playing sound Script.setTimeout(playLoadSound, 2000); diff --git a/examples/sit.js b/examples/sit.js index 71d909d1e7..196a1a1972 100644 --- a/examples/sit.js +++ b/examples/sit.js @@ -10,7 +10,7 @@ // -var buttonImageUrl = "https://public.highfidelity.io/images/tools/sit.svg"; +var buttonImageUrl = "https://s3.amazonaws.com/hifi-public/images/tools/sit.svg"; var windowDimensions = Controller.getViewportDimensions(); From 5ab0df32881fca75a6f6457d22b293a34f609409 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 8 Jan 2015 18:31:10 -0800 Subject: [PATCH 024/159] removed editModels --- examples/editModels.js | 3041 ---------------------------------------- 1 file changed, 3041 deletions(-) delete mode 100644 examples/editModels.js diff --git a/examples/editModels.js b/examples/editModels.js deleted file mode 100644 index 7cb911b490..0000000000 --- a/examples/editModels.js +++ /dev/null @@ -1,3041 +0,0 @@ -// -// editEntities.js -// examples -// -// Created by Clément Brisset on 4/24/14. -// Copyright 2014 High Fidelity, Inc. -// -// This script allows you to edit models either with the razor hydras or with your mouse -// -// If using the hydras : -// grab grab models with the triggers, you can then move the models around or scale them with both hands. -// You can switch mode using the bumpers so that you can move models around more easily. -// -// If using the mouse : -// - left click lets you move the model in the plane facing you. -// If pressing shift, it will move on the horizontal plane it's in. -// - right click lets you rotate the model. z and x give access to more axes of rotation while shift provides finer control. -// - left + right click lets you scale the model. -// - you can press r while holding the model to reset its rotation -// -// 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/globals.js"); -Script.include("libraries/toolBars.js"); - -Script.include("libraries/entityPropertyDialogBox.js"); -var entityPropertyDialogBox = EntityPropertyDialogBox; - -var windowDimensions = Controller.getViewportDimensions(); -var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; -var toolHeight = 50; -var toolWidth = 50; - -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; -var allowSmallModels = false; -var wantEntityGlow = false; - -var LEFT = 0; -var RIGHT = 1; - -var SPAWN_DISTANCE = 1; -var DEFAULT_DIMENSION = 0.20; -var DEFAULT_TEXT_DIMENSION_X = 1.0; -var DEFAULT_TEXT_DIMENSION_Y = 1.0; -var DEFAULT_TEXT_DIMENSION_Z = 0.01; - -var modelURLs = [ - HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Alder.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Bush1.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Bush6.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed2.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed4.fbx", - HIFI_PUBLIC_BUCKET + "models/entities/3-Buildings-1-Rustic-Shed7.fbx" - ]; - -var jointList = MyAvatar.getJointNames(); - -var mode = 0; -var isActive = false; - - -if (typeof String.prototype.fileName !== "function") { - String.prototype.fileName = function () { - return this.replace(/^(.*[\/\\])*/, ""); - }; -} - -if (typeof String.prototype.fileBase !== "function") { - String.prototype.fileBase = function () { - var filename = this.fileName(); - return filename.slice(0, filename.indexOf(".")); - }; -} - -if (typeof String.prototype.fileType !== "function") { - String.prototype.fileType = function () { - return this.slice(this.lastIndexOf(".") + 1); - }; -} - -if (typeof String.prototype.path !== "function") { - String.prototype.path = function () { - return this.replace(/[\\\/][^\\\/]*$/, ""); - }; -} - -if (typeof String.prototype.regExpEscape !== "function") { - String.prototype.regExpEscape = function () { - return this.replace(/([$\^.+*?|\\\/{}()\[\]])/g, '\\$1'); - }; -} - -if (typeof String.prototype.toArrayBuffer !== "function") { - String.prototype.toArrayBuffer = function () { - var length, - buffer, - view, - charCode, - charCodes, - i; - - charCodes = []; - - length = this.length; - for (i = 0; i < length; i += 1) { - charCode = this.charCodeAt(i); - if (charCode <= 255) { - charCodes.push(charCode); - } else { - charCodes.push(charCode / 256); - charCodes.push(charCode % 256); - } - } - - length = charCodes.length; - buffer = new ArrayBuffer(length); - view = new Uint8Array(buffer); - for (i = 0; i < length; i += 1) { - view[i] = charCodes[i]; - } - - return buffer; - }; -} - -if (typeof DataView.prototype.indexOf !== "function") { - DataView.prototype.indexOf = function (searchString, position) { - var searchLength = searchString.length, - byteArrayLength = this.byteLength, - maxSearchIndex = byteArrayLength - searchLength, - searchCharCodes = [], - found, - i, - j; - - searchCharCodes[searchLength] = 0; - for (j = 0; j < searchLength; j += 1) { - searchCharCodes[j] = searchString.charCodeAt(j); - } - - i = position; - found = false; - while (i < maxSearchIndex && !found) { - j = 0; - while (j < searchLength && this.getUint8(i + j) === searchCharCodes[j]) { - j += 1; - } - found = (j === searchLength); - i += 1; - } - - return found ? i - 1 : -1; - }; -} - -if (typeof DataView.prototype.string !== "function") { - DataView.prototype.string = function (start, length) { - var charCodes = [], - end, - i; - - if (start === undefined) { - start = 0; - } - if (length === undefined) { - length = this.length; - } - - end = start + length; - for (i = start; i < end; i += 1) { - charCodes.push(this.getUint8(i)); - } - - return String.fromCharCode.apply(String, charCodes); - }; -} - -var progressDialog = (function () { - var that = {}, - progressBackground, - progressMessage, - cancelButton, - displayed = false, - backgroundWidth = 300, - backgroundHeight = 100, - messageHeight = 32, - cancelWidth = 70, - cancelHeight = 32, - textColor = { red: 255, green: 255, blue: 255 }, - textBackground = { red: 52, green: 52, blue: 52 }, - backgroundUrl = toolIconUrl + "progress-background.svg", - windowDimensions; - - progressBackground = Overlays.addOverlay("image", { - width: backgroundWidth, - height: backgroundHeight, - imageURL: backgroundUrl, - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - progressMessage = Overlays.addOverlay("text", { - width: backgroundWidth - 40, - height: messageHeight, - text: "", - textColor: textColor, - backgroundColor: textBackground, - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - cancelButton = Overlays.addOverlay("text", { - width: cancelWidth, - height: cancelHeight, - text: "Cancel", - textColor: textColor, - backgroundColor: textBackground, - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - function move() { - var progressX, - progressY; - - if (displayed) { - - if (windowDimensions.x === Window.innerWidth && windowDimensions.y === Window.innerHeight) { - return; - } - windowDimensions.x = Window.innerWidth; - windowDimensions.y = Window.innerHeight; - - progressX = (windowDimensions.x - backgroundWidth) / 2; // Center. - progressY = windowDimensions.y / 2 - backgroundHeight; // A little up from center. - - Overlays.editOverlay(progressBackground, { x: progressX, y: progressY }); - Overlays.editOverlay(progressMessage, { x: progressX + 20, y: progressY + 15 }); - Overlays.editOverlay(cancelButton, { - x: progressX + backgroundWidth - cancelWidth - 20, - y: progressY + backgroundHeight - cancelHeight - 15 - }); - } - } - that.move = move; - - that.onCancel = undefined; - - function open(message) { - if (!displayed) { - windowDimensions = { x: 0, y : 0 }; - displayed = true; - move(); - Overlays.editOverlay(progressBackground, { visible: true }); - Overlays.editOverlay(progressMessage, { visible: true, text: message }); - Overlays.editOverlay(cancelButton, { visible: true }); - } else { - throw new Error("open() called on progressDialog when already open"); - } - } - that.open = open; - - function isOpen() { - return displayed; - } - that.isOpen = isOpen; - - function update(message) { - if (displayed) { - Overlays.editOverlay(progressMessage, { text: message }); - } else { - throw new Error("update() called on progressDialog when not open"); - } - } - that.update = update; - - function close() { - if (displayed) { - Overlays.editOverlay(cancelButton, { visible: false }); - Overlays.editOverlay(progressMessage, { visible: false }); - Overlays.editOverlay(progressBackground, { visible: false }); - displayed = false; - } else { - throw new Error("close() called on progressDialog when not open"); - } - } - that.close = close; - - function mousePressEvent(event) { - if (Overlays.getOverlayAtPoint({ x: event.x, y: event.y }) === cancelButton) { - if (typeof this.onCancel === "function") { - close(); - this.onCancel(); - } - return true; - } - return false; - } - that.mousePressEvent = mousePressEvent; - - function cleanup() { - Overlays.deleteOverlay(cancelButton); - Overlays.deleteOverlay(progressMessage); - Overlays.deleteOverlay(progressBackground); - } - that.cleanup = cleanup; - - return that; -}()); - -var httpMultiPart = (function () { - var that = {}, - parts, - byteLength, - boundaryString, - crlf; - - function clear() { - boundaryString = "--boundary_" + String(Uuid.generate()).slice(1, 36) + "="; - parts = []; - byteLength = 0; - crlf = ""; - } - that.clear = clear; - - function boundary() { - return boundaryString.slice(2); - } - that.boundary = boundary; - - function length() { - return byteLength; - } - that.length = length; - - function add(object) { - // - name, string - // - name, buffer - var buffer, - string, - stringBuffer, - compressedBuffer; - - if (object.name === undefined) { - - throw new Error("Item to add to HttpMultiPart must have a name"); - - } else if (object.string !== undefined) { - //--= - //Content-Disposition: form-data; name="model_name" - // - // - - string = crlf + boundaryString + "\r\n" - + "Content-Disposition: form-data; name=\"" + object.name + "\"\r\n" - + "\r\n" - + object.string; - buffer = string.toArrayBuffer(); - - } else if (object.buffer !== undefined) { - //--= - //Content-Disposition: form-data; name="fbx"; filename="" - //Content-Type: application/octet-stream - // - // - - string = crlf + boundaryString + "\r\n" - + "Content-Disposition: form-data; name=\"" + object.name - + "\"; filename=\"" + object.buffer.filename + "\"\r\n" - + "Content-Type: application/octet-stream\r\n" - + "\r\n"; - stringBuffer = string.toArrayBuffer(); - - compressedBuffer = object.buffer.buffer.compress(); - buffer = new Uint8Array(stringBuffer.byteLength + compressedBuffer.byteLength); - buffer.set(new Uint8Array(stringBuffer)); - buffer.set(new Uint8Array(compressedBuffer), stringBuffer.byteLength); - - } else { - - throw new Error("Item to add to HttpMultiPart not recognized"); - } - - byteLength += buffer.byteLength; - parts.push(buffer); - - crlf = "\r\n"; - - return true; - } - that.add = add; - - function response() { - var buffer, - index, - str, - i; - - str = crlf + boundaryString + "--\r\n"; - buffer = str.toArrayBuffer(); - byteLength += buffer.byteLength; - parts.push(buffer); - - buffer = new Uint8Array(byteLength); - index = 0; - for (i = 0; i < parts.length; i += 1) { - buffer.set(new Uint8Array(parts[i]), index); - index += parts[i].byteLength; - } - - return buffer; - } - that.response = response; - - clear(); - - return that; -}()); - -var modelUploader = (function () { - var that = {}, - modelFile, - modelName, - modelURL, - modelCallback, - isProcessing, - fstBuffer, - fbxBuffer, - //svoBuffer, - mapping, - geometry, - API_URL = "https://data.highfidelity.io/api/v1/models", - MODEL_URL = "http://public.highfidelity.io/models/content", - NAME_FIELD = "name", - SCALE_FIELD = "scale", - FILENAME_FIELD = "filename", - TEXDIR_FIELD = "texdir", - MAX_TEXTURE_SIZE = 1024; - - function info(message) { - if (progressDialog.isOpen()) { - progressDialog.update(message); - } else { - progressDialog.open(message); - } - print(message); - } - - function error(message) { - if (progressDialog.isOpen()) { - progressDialog.close(); - } - print(message); - Window.alert(message); - } - - function randomChar(length) { - var characters = "0123457689abcdefghijklmnopqrstuvwxyz", - string = "", - i; - - for (i = 0; i < length; i += 1) { - string += characters[Math.floor(Math.random() * 36)]; - } - - return string; - } - - function resetDataObjects() { - fstBuffer = null; - fbxBuffer = null; - //svoBuffer = null; - mapping = {}; - geometry = {}; - geometry.textures = []; - geometry.embedded = []; - } - - function readFile(filename) { - var url = "file:///" + filename, - req = new XMLHttpRequest(); - - req.open("GET", url, false); - req.responseType = "arraybuffer"; - req.send(); - if (req.status !== 200) { - error("Could not read file: " + filename + " : " + req.statusText); - return null; - } - - return { - filename: filename.fileName(), - buffer: req.response - }; - } - - function readMapping(buffer) { - var dv = new DataView(buffer.buffer), - lines, - line, - tokens, - i, - name, - value, - remainder, - existing; - - mapping = {}; // { name : value | name : { value : [remainder] } } - lines = dv.string(0, dv.byteLength).split(/\r\n|\r|\n/); - for (i = 0; i < lines.length; i += 1) { - line = lines[i].trim(); - if (line.length > 0 && line[0] !== "#") { - tokens = line.split(/\s*=\s*/); - if (tokens.length > 1) { - name = tokens[0]; - value = tokens[1]; - if (tokens.length > 2) { - remainder = tokens.slice(2, tokens.length).join(" = "); - } else { - remainder = null; - } - if (tokens.length === 2 && mapping[name] === undefined) { - mapping[name] = value; - } else { - if (mapping[name] === undefined) { - mapping[name] = {}; - - } else if (typeof mapping[name] !== "object") { - existing = mapping[name]; - mapping[name] = { existing : null }; - } - - if (mapping[name][value] === undefined) { - mapping[name][value] = []; - } - mapping[name][value].push(remainder); - } - } - } - } - } - - function writeMapping(buffer) { - var name, - value, - remainder, - i, - string = ""; - - for (name in mapping) { - if (mapping.hasOwnProperty(name)) { - if (typeof mapping[name] === "object") { - for (value in mapping[name]) { - if (mapping[name].hasOwnProperty(value)) { - remainder = mapping[name][value]; - if (remainder === null) { - string += (name + " = " + value + "\n"); - } else { - for (i = 0; i < remainder.length; i += 1) { - string += (name + " = " + value + " = " + remainder[i] + "\n"); - } - } - } - } - } else { - string += (name + " = " + mapping[name] + "\n"); - } - } - } - - buffer.buffer = string.toArrayBuffer(); - } - - function readGeometry(fbxBuffer) { - var textures, - view, - index, - EOF, - previousNodeFilename; - - // Reference: - // http://code.blender.org/index.php/2013/08/fbx-binary-file-format-specification/ - - textures = {}; - view = new DataView(fbxBuffer.buffer); - EOF = false; - - function parseBinaryFBX() { - var endOffset, - numProperties, - propertyListLength, - nameLength, - name, - filename; - - endOffset = view.getUint32(index, true); - numProperties = view.getUint32(index + 4, true); - propertyListLength = view.getUint32(index + 8, true); - nameLength = view.getUint8(index + 12); - index += 13; - - if (endOffset === 0) { - return; - } - if (endOffset < index || endOffset > view.byteLength) { - EOF = true; - return; - } - - name = view.string(index, nameLength).toLowerCase(); - index += nameLength; - - if (name === "content" && previousNodeFilename !== "") { - // Blender 2.71 exporter "embeds" external textures as empty binary blobs so ignore these - if (propertyListLength > 5) { - geometry.embedded.push(previousNodeFilename); - } - } - - if (name === "relativefilename") { - filename = view.string(index + 5, view.getUint32(index + 1, true)).fileName(); - if (!textures.hasOwnProperty(filename)) { - textures[filename] = ""; - geometry.textures.push(filename); - } - previousNodeFilename = filename; - } else { - previousNodeFilename = ""; - } - - index += (propertyListLength); - - while (index < endOffset && !EOF) { - parseBinaryFBX(); - } - } - - function readTextFBX() { - var line, - view, - viewLength, - charCode, - charCodes, - numCharCodes, - filename, - relativeFilename = "", - MAX_CHAR_CODES = 250; - - view = new Uint8Array(fbxBuffer.buffer); - viewLength = view.byteLength; - charCodes = []; - numCharCodes = 0; - - for (index = 0; index < viewLength; index += 1) { - charCode = view[index]; - if (charCode !== 9 && charCode !== 32) { - if (charCode === 10) { // EOL. Can ignore EOF. - line = String.fromCharCode.apply(String, charCodes).toLowerCase(); - // For embedded textures, "Content:" line immediately follows "RelativeFilename:" line. - if (line.slice(0, 8) === "content:" && relativeFilename !== "") { - geometry.embedded.push(relativeFilename); - } - if (line.slice(0, 17) === "relativefilename:") { - filename = line.slice(line.indexOf("\""), line.lastIndexOf("\"") - line.length).fileName(); - if (!textures.hasOwnProperty(filename)) { - textures[filename] = ""; - geometry.textures.push(filename); - } - relativeFilename = filename; - } else { - relativeFilename = ""; - } - charCodes = []; - numCharCodes = 0; - } else { - if (numCharCodes < MAX_CHAR_CODES) { // Only interested in start of line - charCodes.push(charCode); - numCharCodes += 1; - } - } - } - } - } - - if (view.string(0, 18) === "Kaydara FBX Binary") { - previousNodeFilename = ""; - - index = 27; - while (index < view.byteLength - 39 && !EOF) { - parseBinaryFBX(); - } - - } else { - - readTextFBX(); - - } - } - - function readModel() { - var fbxFilename, - //svoFilename, - fileType; - - info("Reading model file"); - print("Model file: " + modelFile); - - if (modelFile.toLowerCase().fileType() === "fst") { - fstBuffer = readFile(modelFile); - if (fstBuffer === null) { - return false; - } - readMapping(fstBuffer); - fileType = mapping[FILENAME_FIELD].toLowerCase().fileType(); - if (mapping.hasOwnProperty(FILENAME_FIELD)) { - if (fileType === "fbx") { - fbxFilename = modelFile.path() + "\\" + mapping[FILENAME_FIELD]; - //} else if (fileType === "svo") { - // svoFilename = modelFile.path() + "\\" + mapping[FILENAME_FIELD]; - } else { - error("Unrecognized model type in FST file!"); - return false; - } - } else { - error("Model file name not found in FST file!"); - return false; - } - } else { - fstBuffer = { - filename: "Interface." + randomChar(6), // Simulate avatar model uploading behaviour - buffer: null - }; - - if (modelFile.toLowerCase().fileType() === "fbx") { - fbxFilename = modelFile; - mapping[FILENAME_FIELD] = modelFile.fileName(); - - //} else if (modelFile.toLowerCase().fileType() === "svo") { - // svoFilename = modelFile; - // mapping[FILENAME_FIELD] = modelFile.fileName(); - - } else { - error("Unrecognized file type: " + modelFile); - return false; - } - } - - if (!isProcessing) { return false; } - - if (fbxFilename) { - fbxBuffer = readFile(fbxFilename); - if (fbxBuffer === null) { - return false; - } - - if (!isProcessing) { return false; } - - readGeometry(fbxBuffer); - } - - //if (svoFilename) { - // svoBuffer = readFile(svoFilename); - // if (svoBuffer === null) { - // return false; - // } - //} - - // Add any missing basic mappings - if (!mapping.hasOwnProperty(NAME_FIELD)) { - mapping[NAME_FIELD] = modelFile.fileName().fileBase(); - } - if (!mapping.hasOwnProperty(TEXDIR_FIELD)) { - mapping[TEXDIR_FIELD] = "."; - } - if (!mapping.hasOwnProperty(SCALE_FIELD)) { - mapping[SCALE_FIELD] = 1.0; - } - - return true; - } - - function setProperties() { - var form = [], - directory, - displayAs, - validateAs; - - progressDialog.close(); - print("Setting model properties"); - - form.push({ label: "Name:", value: mapping[NAME_FIELD] }); - - directory = modelFile.path() + "/" + mapping[TEXDIR_FIELD]; - displayAs = new RegExp("^" + modelFile.path().regExpEscape() + "[\\\\\\\/](.*)"); - validateAs = new RegExp("^" + modelFile.path().regExpEscape() + "([\\\\\\\/].*)?"); - - form.push({ - label: "Texture directory:", - directory: modelFile.path() + "/" + mapping[TEXDIR_FIELD], - title: "Choose Texture Directory", - displayAs: displayAs, - validateAs: validateAs, - errorMessage: "Texture directory must be subdirectory of the model directory." - }); - - form.push({ button: "Cancel" }); - - if (!Window.form("Set Model Properties", form)) { - print("User cancelled uploading model"); - return false; - } - - mapping[NAME_FIELD] = form[0].value; - mapping[TEXDIR_FIELD] = form[1].directory.slice(modelFile.path().length + 1); - if (mapping[TEXDIR_FIELD] === "") { - mapping[TEXDIR_FIELD] = "."; - } - - writeMapping(fstBuffer); - - return true; - } - - function createHttpMessage(callback) { - var multiparts = [], - lodCount, - lodFile, - lodBuffer, - textureBuffer, - textureSourceFormat, - textureTargetFormat, - embeddedTextures, - i; - - info("Preparing to send model"); - - // Model name - if (mapping.hasOwnProperty(NAME_FIELD)) { - multiparts.push({ - name : "model_name", - string : mapping[NAME_FIELD] - }); - } else { - error("Model name is missing"); - httpMultiPart.clear(); - return; - } - - // FST file - if (fstBuffer) { - multiparts.push({ - name : "fst", - buffer: fstBuffer - }); - } - - // FBX file - if (fbxBuffer) { - multiparts.push({ - name : "fbx", - buffer: fbxBuffer - }); - } - - // SVO file - //if (svoBuffer) { - // multiparts.push({ - // name : "svo", - // buffer: svoBuffer - // }); - //} - - // LOD files - lodCount = 0; - for (lodFile in mapping.lod) { - if (mapping.lod.hasOwnProperty(lodFile)) { - lodBuffer = readFile(modelFile.path() + "\/" + lodFile); - if (lodBuffer === null) { - return; - } - multiparts.push({ - name: "lod" + lodCount, - buffer: lodBuffer - }); - lodCount += 1; - } - if (!isProcessing) { return; } - } - - // Textures - embeddedTextures = "|" + geometry.embedded.join("|") + "|"; - for (i = 0; i < geometry.textures.length; i += 1) { - if (embeddedTextures.indexOf("|" + geometry.textures[i].fileName() + "|") === -1) { - textureBuffer = readFile(modelFile.path() + "\/" - + (mapping[TEXDIR_FIELD] !== "." ? mapping[TEXDIR_FIELD] + "\/" : "") - + geometry.textures[i]); - if (textureBuffer === null) { - return; - } - - textureSourceFormat = geometry.textures[i].fileType().toLowerCase(); - textureTargetFormat = (textureSourceFormat === "jpg" ? "jpg" : "png"); - textureBuffer.buffer = - textureBuffer.buffer.recodeImage(textureSourceFormat, textureTargetFormat, MAX_TEXTURE_SIZE); - textureBuffer.filename = textureBuffer.filename.slice(0, -textureSourceFormat.length) + textureTargetFormat; - - multiparts.push({ - name: "texture" + i, - buffer: textureBuffer - }); - } - - if (!isProcessing) { return; } - } - - // Model category - multiparts.push({ - name : "model_category", - string : "content" - }); - - // Create HTTP message - httpMultiPart.clear(); - Script.setTimeout(function addMultipart() { - var multipart = multiparts.shift(); - httpMultiPart.add(multipart); - - if (!isProcessing) { return; } - - if (multiparts.length > 0) { - Script.setTimeout(addMultipart, 25); - } else { - callback(); - } - }, 25); - } - - function sendToHighFidelity() { - var req, - uploadedChecks, - HTTP_GET_TIMEOUT = 60, // 1 minute - HTTP_SEND_TIMEOUT = 900, // 15 minutes - UPLOADED_CHECKS = 30, - CHECK_UPLOADED_TIMEOUT = 1, // 1 second - handleCheckUploadedResponses, - handleUploadModelResponses, - handleRequestUploadResponses; - - function uploadTimedOut() { - error("Model upload failed: Internet request timed out!"); - } - - function debugResponse() { - print("req.errorCode = " + req.errorCode); - print("req.readyState = " + req.readyState); - print("req.status = " + req.status); - print("req.statusText = " + req.statusText); - print("req.responseType = " + req.responseType); - print("req.responseText = " + req.responseText); - print("req.response = " + req.response); - print("req.getAllResponseHeaders() = " + req.getAllResponseHeaders()); - } - - function checkUploaded() { - if (!isProcessing) { return; } - - info("Checking uploaded model"); - - req = new XMLHttpRequest(); - req.open("HEAD", modelURL, true); - req.timeout = HTTP_GET_TIMEOUT * 1000; - req.onreadystatechange = handleCheckUploadedResponses; - req.ontimeout = uploadTimedOut; - req.send(); - } - - handleCheckUploadedResponses = function () { - //debugResponse(); - if (req.readyState === req.DONE) { - if (req.status === 200) { - // Note: Unlike avatar models, for content models we don't need to refresh texture cache. - print("Model uploaded: " + modelURL); - progressDialog.close(); - if (Window.confirm("Your model has been uploaded as: " + modelURL + "\nDo you want to rez it?")) { - modelCallback(modelURL); - } - } else if (req.status === 404) { - if (uploadedChecks > 0) { - uploadedChecks -= 1; - Script.setTimeout(checkUploaded, CHECK_UPLOADED_TIMEOUT * 1000); - } else { - print("Error: " + req.status + " " + req.statusText); - error("We could not verify that your model was successfully uploaded but it may have been at: " - + modelURL); - } - } else { - print("Error: " + req.status + " " + req.statusText); - error("There was a problem with your upload, please try again later."); - } - } - }; - - function uploadModel(method) { - var url; - - if (!isProcessing) { return; } - - req = new XMLHttpRequest(); - if (method === "PUT") { - url = API_URL + "\/" + modelName; - req.open("PUT", url, true); //print("PUT " + url); - } else { - url = API_URL; - req.open("POST", url, true); //print("POST " + url); - } - req.setRequestHeader("Content-Type", "multipart/form-data; boundary=\"" + httpMultiPart.boundary() + "\""); - req.timeout = HTTP_SEND_TIMEOUT * 1000; - req.onreadystatechange = handleUploadModelResponses; - req.ontimeout = uploadTimedOut; - req.send(httpMultiPart.response().buffer); - } - - handleUploadModelResponses = function () { - //debugResponse(); - if (req.readyState === req.DONE) { - if (req.status === 200) { - uploadedChecks = UPLOADED_CHECKS; - checkUploaded(); - } else { - print("Error: " + req.status + " " + req.statusText); - error("There was a problem with your upload, please try again later."); - } - } - }; - - function requestUpload() { - var url; - - if (!isProcessing) { return; } - - url = API_URL + "\/" + modelName; // XMLHttpRequest automatically handles authorization of API requests. - req = new XMLHttpRequest(); - req.open("GET", url, true); //print("GET " + url); - req.responseType = "json"; - req.timeout = HTTP_GET_TIMEOUT * 1000; - req.onreadystatechange = handleRequestUploadResponses; - req.ontimeout = uploadTimedOut; - req.send(); - } - - handleRequestUploadResponses = function () { - var response; - - //debugResponse(); - if (req.readyState === req.DONE) { - if (req.status === 200) { - if (req.responseType === "json") { - response = JSON.parse(req.responseText); - if (response.status === "success") { - if (response.exists === false) { - uploadModel("POST"); - } else if (response.can_update === true) { - uploadModel("PUT"); - } else { - error("This model file already exists and is owned by someone else!"); - } - return; - } - } - } else { - print("Error: " + req.status + " " + req.statusText); - } - error("Model upload failed! Something went wrong at the data server."); - } - }; - - info("Sending model to High Fidelity"); - - requestUpload(); - } - - that.upload = function (file, callback) { - - modelFile = file; - modelCallback = callback; - - isProcessing = true; - - progressDialog.onCancel = function () { - print("User cancelled uploading model"); - isProcessing = false; - }; - - resetDataObjects(); - - if (readModel()) { - if (setProperties()) { - modelName = mapping[NAME_FIELD]; - modelURL = MODEL_URL + "\/" + mapping[NAME_FIELD] + ".fst"; // All models are uploaded as an FST - - createHttpMessage(sendToHighFidelity); - } - } - - resetDataObjects(); - }; - - return that; -}()); - -var toolBar = (function () { - var that = {}, - toolBar, - activeButton, - newModelButton, - newCubeButton, - newSphereButton, - newTextButton, - browseModelsButton, - loadURLMenuItem, - loadFileMenuItem, - menuItemWidth, - menuItemOffset, - menuItemHeight, - menuItemMargin = 5, - menuTextColor = { red: 255, green: 255, blue: 255 }, - menuBackgroundColor = { red: 18, green: 66, blue: 66 }; - - function initialize() { - toolBar = new ToolBar(0, 0, ToolBar.VERTICAL); - - activeButton = toolBar.addTool({ - imageURL: toolIconUrl + "models-tool.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }, true, false); - - newModelButton = toolBar.addTool({ - imageURL: toolIconUrl + "add-model-tool.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }, true, false); - - browseModelsButton = toolBar.addTool({ - imageURL: toolIconUrl + "list-icon.svg", - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }); - - menuItemOffset = toolBar.height / 3 + 2; - menuItemHeight = Tool.IMAGE_HEIGHT / 2 - 2; - - loadURLMenuItem = Overlays.addOverlay("text", { - height: menuItemHeight, - backgroundColor: menuBackgroundColor, - topMargin: menuItemMargin, - text: "Model URL", - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - loadFileMenuItem = Overlays.addOverlay("text", { - height: menuItemHeight, - backgroundColor: menuBackgroundColor, - topMargin: menuItemMargin, - text: "Model File", - alpha: 0.9, - backgroundAlpha: 0.9, - visible: false - }); - - menuItemWidth = Math.max(Overlays.textSize(loadURLMenuItem, "Model URL").width, - Overlays.textSize(loadFileMenuItem, "Model File").width) + 20; - Overlays.editOverlay(loadURLMenuItem, { width: menuItemWidth }); - Overlays.editOverlay(loadFileMenuItem, { width: menuItemWidth }); - - newCubeButton = toolBar.addTool({ - imageURL: toolIconUrl + "add-cube.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }); - - newSphereButton = toolBar.addTool({ - imageURL: toolIconUrl + "add-sphere.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }); - - newTextButton = toolBar.addTool({ - imageURL: toolIconUrl + "add-text.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true - }); - } - - function toggleNewModelButton(active) { - if (active === undefined) { - active = !toolBar.toolSelected(newModelButton); - } - toolBar.selectTool(newModelButton, active); - - Overlays.editOverlay(loadURLMenuItem, { visible: active }); - Overlays.editOverlay(loadFileMenuItem, { visible: active }); - } - - var RESIZE_INTERVAL = 50; - var RESIZE_TIMEOUT = 20000; - var RESIZE_MAX_CHECKS = RESIZE_TIMEOUT / RESIZE_INTERVAL; - function addModel(url) { - var position; - - position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); - - if (position.x > 0 && position.y > 0 && position.z > 0) { - var entityId = Entities.addEntity({ - type: "Model", - position: position, - dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION }, - modelURL: url - }); - print("Model added: " + url); - - var checkCount = 0; - function resize() { - var entityProperties = Entities.getEntityProperties(entityId); - var naturalDimensions = entityProperties.naturalDimensions; - - checkCount++; - - if (naturalDimensions.x == 0 && naturalDimensions.y == 0 && naturalDimensions.z == 0) { - if (checkCount < RESIZE_MAX_CHECKS) { - Script.setTimeout(resize, RESIZE_INTERVAL); - } else { - print("Resize failed: timed out waiting for model (" + url + ") to load"); - } - } else { - entityProperties.dimensions = naturalDimensions; - Entities.editEntity(entityId, entityProperties); - } - } - - Script.setTimeout(resize, RESIZE_INTERVAL); - - } else { - print("Can't add model: Model would be out of bounds."); - } - } - - that.move = function () { - var newViewPort, - toolsX, - toolsY; - - newViewPort = Controller.getViewportDimensions(); - - if (toolBar === undefined) { - initialize(); - - } else if (windowDimensions.x === newViewPort.x && - windowDimensions.y === newViewPort.y) { - return; - } - - windowDimensions = newViewPort; - toolsX = windowDimensions.x - 8 - toolBar.width; - toolsY = (windowDimensions.y - toolBar.height) / 2; - - toolBar.move(toolsX, toolsY); - - Overlays.editOverlay(loadURLMenuItem, { x: toolsX - menuItemWidth, y: toolsY + menuItemOffset }); - Overlays.editOverlay(loadFileMenuItem, { x: toolsX - menuItemWidth, y: toolsY + menuItemOffset + menuItemHeight }); - }; - - that.mousePressEvent = function (event) { - var clickedOverlay, - url, - file; - - clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (activeButton === toolBar.clicked(clickedOverlay)) { - isActive = !isActive; - return true; - } - - if (newModelButton === toolBar.clicked(clickedOverlay)) { - toggleNewModelButton(); - return true; - } - - if (clickedOverlay === loadURLMenuItem) { - toggleNewModelButton(false); - url = Window.prompt("Model URL", modelURLs[Math.floor(Math.random() * modelURLs.length)]); - if (url !== null && url !== "") { - addModel(url); - } - return true; - } - - if (clickedOverlay === loadFileMenuItem) { - toggleNewModelButton(false); - - file = Window.browse("Select your model file ...", - Settings.getValue("LastModelUploadLocation").path(), - "Model files (*.fst *.fbx)"); - //"Model files (*.fst *.fbx *.svo)"); - if (file !== null) { - Settings.setValue("LastModelUploadLocation", file); - modelUploader.upload(file, addModel); - } - return true; - } - - if (browseModelsButton === toolBar.clicked(clickedOverlay)) { - toggleNewModelButton(false); - url = Window.s3Browse(".*(fbx|FBX)"); - if (url !== null && url !== "") { - addModel(url); - } - return true; - } - - if (newCubeButton === toolBar.clicked(clickedOverlay)) { - var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); - - if (position.x > 0 && position.y > 0 && position.z > 0) { - Entities.addEntity({ - type: "Box", - position: position, - dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION }, - color: { red: 255, green: 0, blue: 0 } - - }); - } else { - print("Can't create box: Box would be out of bounds."); - } - return true; - } - - if (newSphereButton === toolBar.clicked(clickedOverlay)) { - var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); - - if (position.x > 0 && position.y > 0 && position.z > 0) { - Entities.addEntity({ - type: "Sphere", - position: position, - dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION }, - color: { red: 255, green: 0, blue: 0 } - }); - } else { - print("Can't create box: Box would be out of bounds."); - } - return true; - } - - - if (newTextButton === toolBar.clicked(clickedOverlay)) { - var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); - - if (position.x > 0 && position.y > 0 && position.z > 0) { - Entities.addEntity({ - type: "Text", - position: position, - dimensions: { x: DEFAULT_TEXT_DIMENSION_X, y: DEFAULT_TEXT_DIMENSION_Y, z: DEFAULT_TEXT_DIMENSION_Z }, - backgroundColor: { red: 0, green: 0, blue: 0 }, - textColor: { red: 255, green: 255, blue: 255 }, - text: "some text", - lineHight: "0.1" - }); - } else { - print("Can't create box: Text would be out of bounds."); - } - return true; - } - - return false; - }; - - that.cleanup = function () { - toolBar.cleanup(); - Overlays.deleteOverlay(loadURLMenuItem); - Overlays.deleteOverlay(loadFileMenuItem); - }; - - return that; -}()); - - -var exportMenu = null; - -var ExportMenu = function (opts) { - var self = this; - - var windowDimensions = Controller.getViewportDimensions(); - var pos = { x: windowDimensions.x / 2, y: windowDimensions.y - 100 }; - - this._onClose = opts.onClose || function () { }; - this._position = { x: 0.0, y: 0.0, z: 0.0 }; - this._scale = 1.0; - - var minScale = 1; - var maxScale = 32768; - var titleWidth = 120; - var locationWidth = 100; - var scaleWidth = 144; - var exportWidth = 100; - var cancelWidth = 100; - var margin = 4; - var height = 30; - var outerHeight = height + (2 * margin); - var buttonColor = { red: 128, green: 128, blue: 128 }; - - var SCALE_MINUS = scaleWidth * 40.0 / 100.0; - var SCALE_PLUS = scaleWidth * 63.0 / 100.0; - - var fullWidth = locationWidth + scaleWidth + exportWidth + cancelWidth + (2 * margin); - var offset = fullWidth / 2; - pos.x -= offset; - - var background = Overlays.addOverlay("text", { - x: pos.x, - y: pos.y, - opacity: 1, - width: fullWidth, - height: outerHeight, - backgroundColor: { red: 200, green: 200, blue: 200 }, - text: "", - }); - - var titleText = Overlays.addOverlay("text", { - x: pos.x, - y: pos.y - height, - font: { size: 14 }, - width: titleWidth, - height: height, - backgroundColor: { red: 255, green: 255, blue: 255 }, - color: { red: 255, green: 255, blue: 255 }, - text: "Export Models" - }); - - var locationButton = Overlays.addOverlay("text", { - x: pos.x + margin, - y: pos.y + margin, - width: locationWidth, - height: height, - color: { red: 255, green: 255, blue: 255 }, - text: "0, 0, 0", - }); - var scaleOverlay = Overlays.addOverlay("image", { - x: pos.x + margin + locationWidth, - y: pos.y + margin, - width: scaleWidth, - height: height, - subImage: { x: 0, y: 3, width: 144, height: height }, - imageURL: toolIconUrl + "voxel-size-selector.svg", - alpha: 0.9, - }); - var scaleViewWidth = 40; - var scaleView = Overlays.addOverlay("text", { - x: pos.x + margin + locationWidth + SCALE_MINUS, - y: pos.y + margin, - width: scaleViewWidth, - height: height, - alpha: 0.0, - backgroundAlpha: 0.0, - color: { red: 255, green: 255, blue: 255 }, - text: "1" - }); - var exportButton = Overlays.addOverlay("text", { - x: pos.x + margin + locationWidth + scaleWidth, - y: pos.y + margin, - width: exportWidth, - height: height, - color: { red: 0, green: 255, blue: 255 }, - text: "Export" - }); - var cancelButton = Overlays.addOverlay("text", { - x: pos.x + margin + locationWidth + scaleWidth + exportWidth, - y: pos.y + margin, - width: cancelWidth, - height: height, - color: { red: 255, green: 255, blue: 255 }, - text: "Cancel" - }); - - var voxelPreview = Overlays.addOverlay("cube", { - position: { x: 0, y: 0, z: 0 }, - size: this._scale, - color: { red: 255, green: 255, blue: 0 }, - alpha: 1, - solid: false, - visible: true, - lineWidth: 4 - }); - - this.parsePosition = function (str) { - var parts = str.split(','); - if (parts.length == 3) { - var x = parseFloat(parts[0]); - var y = parseFloat(parts[1]); - var z = parseFloat(parts[2]); - if (isFinite(x) && isFinite(y) && isFinite(z)) { - return { x: x, y: y, z: z }; - } - } - return null; - }; - - this.showPositionPrompt = function () { - var positionStr = self._position.x + ", " + self._position.y + ", " + self._position.z; - while (1) { - positionStr = Window.prompt("Position to export form:", positionStr); - if (positionStr == null) { - break; - } - var position = self.parsePosition(positionStr); - if (position != null) { - self.setPosition(position.x, position.y, position.z); - break; - } - Window.alert("The position you entered was invalid."); - } - }; - - this.setScale = function (scale) { - self._scale = Math.min(maxScale, Math.max(minScale, scale)); - Overlays.editOverlay(scaleView, { text: self._scale }); - Overlays.editOverlay(voxelPreview, { size: self._scale }); - } - - this.decreaseScale = function () { - self.setScale(self._scale /= 2); - } - - this.increaseScale = function () { - self.setScale(self._scale *= 2); - } - - this.exportEntities = function() { - var x = self._position.x; - var y = self._position.y; - var z = self._position.z; - var s = self._scale; - var filename = "models__" + Window.location.hostname + "__" + x + "_" + y + "_" + z + "_" + s + "__.svo"; - filename = Window.save("Select where to save", filename, "*.svo") - if (filename) { - var success = Clipboard.exportEntities(filename, x, y, z, s); - if (!success) { - Window.alert("Export failed: no models found in selected area."); - } - } - self.close(); - }; - - this.getPosition = function () { - return self._position; - }; - - this.setPosition = function (x, y, z) { - self._position = { x: x, y: y, z: z }; - var positionStr = x + ", " + y + ", " + z; - Overlays.editOverlay(locationButton, { text: positionStr }); - Overlays.editOverlay(voxelPreview, { position: self._position }); - - }; - - this.mouseReleaseEvent = function (event) { - var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (clickedOverlay == locationButton) { - self.showPositionPrompt(); - } else if (clickedOverlay == exportButton) { - self.exportEntities(); - } else if (clickedOverlay == cancelButton) { - self.close(); - } else if (clickedOverlay == scaleOverlay) { - var x = event.x - pos.x - margin - locationWidth; - print(x); - if (x < SCALE_MINUS) { - self.decreaseScale(); - } else if (x > SCALE_PLUS) { - self.increaseScale(); - } - } - }; - - this.close = function () { - this.cleanup(); - this._onClose(); - }; - - this.cleanup = function () { - Overlays.deleteOverlay(background); - Overlays.deleteOverlay(titleText); - Overlays.deleteOverlay(locationButton); - Overlays.deleteOverlay(exportButton); - Overlays.deleteOverlay(cancelButton); - Overlays.deleteOverlay(voxelPreview); - Overlays.deleteOverlay(scaleOverlay); - Overlays.deleteOverlay(scaleView); - }; - - print("CONNECTING!"); - Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent); -}; - - - -var ModelImporter = function (opts) { - var self = this; - - var height = 30; - var margin = 4; - var outerHeight = height + (2 * margin); - var titleWidth = 120; - var cancelWidth = 100; - var fullWidth = titleWidth + cancelWidth + (2 * margin); - - var localModels = Overlays.addOverlay("localmodels", { - position: { x: 1, y: 1, z: 1 }, - scale: 1, - visible: false - }); - var importScale = 1; - var importBoundaries = Overlays.addOverlay("cube", { - position: { x: 0, y: 0, z: 0 }, - size: 1, - color: { red: 128, blue: 128, green: 128 }, - lineWidth: 4, - solid: false, - visible: false - }); - - var pos = { x: windowDimensions.x / 2 - (fullWidth / 2), y: windowDimensions.y - 100 }; - - var background = Overlays.addOverlay("text", { - x: pos.x, - y: pos.y, - opacity: 1, - width: fullWidth, - height: outerHeight, - backgroundColor: { red: 200, green: 200, blue: 200 }, - visible: false, - text: "", - }); - - var titleText = Overlays.addOverlay("text", { - x: pos.x + margin, - y: pos.y + margin, - font: { size: 14 }, - width: titleWidth, - height: height, - backgroundColor: { red: 255, green: 255, blue: 255 }, - color: { red: 255, green: 255, blue: 255 }, - visible: false, - text: "Import Models" - }); - var cancelButton = Overlays.addOverlay("text", { - x: pos.x + margin + titleWidth, - y: pos.y + margin, - width: cancelWidth, - height: height, - color: { red: 255, green: 255, blue: 255 }, - visible: false, - text: "Close" - }); - this._importing = false; - - this.setImportVisible = function (visible) { - Overlays.editOverlay(importBoundaries, { visible: visible }); - Overlays.editOverlay(localModels, { visible: visible }); - Overlays.editOverlay(cancelButton, { visible: visible }); - Overlays.editOverlay(titleText, { visible: visible }); - Overlays.editOverlay(background, { visible: visible }); - }; - - var importPosition = { x: 0, y: 0, z: 0 }; - this.moveImport = function (position) { - importPosition = position; - Overlays.editOverlay(localModels, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } - }); - Overlays.editOverlay(importBoundaries, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } - }); - } - - this.mouseMoveEvent = function (event) { - if (self._importing) { - var pickRay = Camera.computePickRay(event.x, event.y); - var intersection = false; //Voxels.findRayIntersection(pickRay); - - var distance = 2;// * self._scale; - - if (false) {//intersection.intersects) { - var intersectionDistance = Vec3.length(Vec3.subtract(pickRay.origin, intersection.intersection)); - if (intersectionDistance < distance) { - distance = intersectionDistance * 0.99; - } - - } - - var targetPosition = { - x: pickRay.origin.x + (pickRay.direction.x * distance), - y: pickRay.origin.y + (pickRay.direction.y * distance), - z: pickRay.origin.z + (pickRay.direction.z * distance) - }; - - if (targetPosition.x < 0) targetPosition.x = 0; - if (targetPosition.y < 0) targetPosition.y = 0; - if (targetPosition.z < 0) targetPosition.z = 0; - - var nudgeFactor = 1; - var newPosition = { - x: Math.floor(targetPosition.x / nudgeFactor) * nudgeFactor, - y: Math.floor(targetPosition.y / nudgeFactor) * nudgeFactor, - z: Math.floor(targetPosition.z / nudgeFactor) * nudgeFactor - } - - self.moveImport(newPosition); - } - } - - this.mouseReleaseEvent = function (event) { - var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (clickedOverlay == cancelButton) { - self._importing = false; - self.setImportVisible(false); - } - }; - - // Would prefer to use {4} for the coords, but it would only capture the last digit. - var fileRegex = /__(.+)__(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)_(\d+(?:\.\d+)?)__/; - this.doImport = function () { - if (!self._importing) { - var filename = Window.browse("Select models to import", "", "*.svo") - if (filename) { - parts = fileRegex.exec(filename); - if (parts == null) { - Window.alert("The file you selected does not contain source domain or location information"); - } else { - var hostname = parts[1]; - var x = parts[2]; - var y = parts[3]; - var z = parts[4]; - var s = parts[5]; - importScale = s; - if (hostname != location.hostname) { - if (!Window.confirm(("These models were not originally exported from this domain. Continue?"))) { - return; - } - } else { - if (Window.confirm(("Would you like to import back to the source location?"))) { - var success = Clipboard.importEntities(filename); - if (success) { - Clipboard.pasteEntities(x, y, z, 1); - } else { - Window.alert("There was an error importing the entity file."); - } - return; - } - } - } - var success = Clipboard.importEntities(filename); - if (success) { - self._importing = true; - self.setImportVisible(true); - Overlays.editOverlay(importBoundaries, { size: s }); - } else { - Window.alert("There was an error importing the entity file."); - } - } - } - } - - this.paste = function () { - if (self._importing) { - // self._importing = false; - // self.setImportVisible(false); - Clipboard.pasteEntities(importPosition.x, importPosition.y, importPosition.z, 1); - } - } - - this.cleanup = function () { - Overlays.deleteOverlay(localModels); - Overlays.deleteOverlay(importBoundaries); - Overlays.deleteOverlay(cancelButton); - Overlays.deleteOverlay(titleText); - Overlays.deleteOverlay(background); - } - - Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent); - Controller.mouseMoveEvent.connect(this.mouseMoveEvent); -}; - -var modelImporter = new ModelImporter(); - - -function isLocked(properties) { - // special case to lock the ground plane model in hq. - if (location.hostname == "hq.highfidelity.io" && - properties.modelURL == HIFI_PUBLIC_BUCKET + "ozan/Terrain_Reduce_forAlpha.fbx") { - return true; - } - return false; -} - - -function controller(wichSide) { - this.side = wichSide; - this.palm = 2 * wichSide; - this.tip = 2 * wichSide + 1; - this.trigger = wichSide; - this.bumper = 6 * wichSide + 5; - - this.oldPalmPosition = Controller.getSpatialControlPosition(this.palm); - this.palmPosition = Controller.getSpatialControlPosition(this.palm); - - this.oldTipPosition = Controller.getSpatialControlPosition(this.tip); - this.tipPosition = Controller.getSpatialControlPosition(this.tip); - - this.oldUp = Controller.getSpatialControlNormal(this.palm); - this.up = this.oldUp; - - this.oldFront = Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)); - this.front = this.oldFront; - - this.oldRight = Vec3.cross(this.front, this.up); - this.right = this.oldRight; - - this.oldRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); - this.rotation = this.oldRotation; - - this.triggerValue = Controller.getTriggerValue(this.trigger); - this.bumperValue = Controller.isButtonPressed(this.bumper); - - this.pressed = false; // is trigger pressed - this.pressing = false; // is trigger being pressed (is pressed now but wasn't previously) - - this.grabbing = false; - this.entityID = { isKnownID: false }; - this.modelURL = ""; - this.oldModelRotation; - this.oldModelPosition; - this.oldModelHalfDiagonal; - - this.positionAtGrab; - this.rotationAtGrab; - this.modelPositionAtGrab; - this.rotationAtGrab; - this.jointsIntersectingFromStart = []; - - this.laser = Overlays.addOverlay("line3d", { - start: { x: 0, y: 0, z: 0 }, - end: { x: 0, y: 0, z: 0 }, - color: LASER_COLOR, - alpha: 1, - visible: false, - lineWidth: LASER_WIDTH, - anchor: "MyAvatar" - }); - - this.guideScale = 0.02; - this.ball = Overlays.addOverlay("sphere", { - position: { x: 0, y: 0, z: 0 }, - size: this.guideScale, - solid: true, - color: { red: 0, green: 255, blue: 0 }, - alpha: 1, - visible: false, - anchor: "MyAvatar" - }); - this.leftRight = Overlays.addOverlay("line3d", { - start: { x: 0, y: 0, z: 0 }, - end: { x: 0, y: 0, z: 0 }, - color: { red: 0, green: 0, blue: 255 }, - alpha: 1, - visible: false, - lineWidth: LASER_WIDTH, - anchor: "MyAvatar" - }); - this.topDown = Overlays.addOverlay("line3d", { - start: { x: 0, y: 0, z: 0 }, - end: { x: 0, y: 0, z: 0 }, - color: { red: 0, green: 0, blue: 255 }, - alpha: 1, - visible: false, - lineWidth: LASER_WIDTH, - anchor: "MyAvatar" - }); - - - - this.grab = function (entityID, properties) { - if (isLocked(properties)) { - print("Model locked " + entityID.id); - } else { - print("Grabbing " + entityID.id); - this.grabbing = true; - this.entityID = entityID; - this.modelURL = properties.modelURL; - - this.oldModelPosition = properties.position; - this.oldModelRotation = properties.rotation; - this.oldModelHalfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - this.positionAtGrab = this.palmPosition; - this.rotationAtGrab = this.rotation; - this.modelPositionAtGrab = properties.position; - this.rotationAtGrab = properties.rotation; - this.jointsIntersectingFromStart = []; - for (var i = 0; i < jointList.length; i++) { - var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition); - if (distance < this.oldModelHalfDiagonal) { - this.jointsIntersectingFromStart.push(i); - } - } - this.showLaser(false); - } - } - - this.release = function () { - if (this.grabbing) { - jointList = MyAvatar.getJointNames(); - - var closestJointIndex = -1; - var closestJointDistance = 10; - for (var i = 0; i < jointList.length; i++) { - var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition); - if (distance < closestJointDistance) { - closestJointDistance = distance; - closestJointIndex = i; - } - } - - if (closestJointIndex != -1) { - print("closestJoint: " + jointList[closestJointIndex]); - print("closestJointDistance (attach max distance): " + closestJointDistance + " (" + this.oldModelHalfDiagonal + ")"); - } - - if (closestJointDistance < this.oldModelHalfDiagonal) { - - if (this.jointsIntersectingFromStart.indexOf(closestJointIndex) != -1 || - (leftController.grabbing && rightController.grabbing && - leftController.entityID.id == rightController.entityID.id)) { - // Do nothing - } else { - print("Attaching to " + jointList[closestJointIndex]); - var jointPosition = MyAvatar.getJointPosition(jointList[closestJointIndex]); - var jointRotation = MyAvatar.getJointCombinedRotation(jointList[closestJointIndex]); - - var attachmentOffset = Vec3.subtract(this.oldModelPosition, jointPosition); - attachmentOffset = Vec3.multiplyQbyV(Quat.inverse(jointRotation), attachmentOffset); - var attachmentRotation = Quat.multiply(Quat.inverse(jointRotation), this.oldModelRotation); - - MyAvatar.attach(this.modelURL, jointList[closestJointIndex], - attachmentOffset, attachmentRotation, 2.0 * this.oldModelHalfDiagonal, - true, false); - Entities.deleteEntity(this.entityID); - } - } - } - - this.grabbing = false; - this.entityID.isKnownID = false; - this.jointsIntersectingFromStart = []; - this.showLaser(true); - } - - this.checkTrigger = function () { - if (this.triggerValue > 0.9) { - if (this.pressed) { - this.pressing = false; - } else { - this.pressing = true; - } - this.pressed = true; - } else { - this.pressing = false; - this.pressed = false; - } - } - - this.checkEntity = function (properties) { - // special case to lock the ground plane model in hq. - if (isLocked(properties)) { - return { valid: false }; - } - - - // P P - Model - // /| A - Palm - // / | d B - unit vector toward tip - // / | X - base of the perpendicular line - // A---X----->B d - distance fom axis - // x x - distance from A - // - // |X-A| = (P-A).B - // X == A + ((P-A).B)B - // d = |P-X| - - var A = this.palmPosition; - var B = this.front; - var P = properties.position; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - var y = Vec3.dot(Vec3.subtract(P, A), this.up); - var z = Vec3.dot(Vec3.subtract(P, A), this.right); - var X = Vec3.sum(A, Vec3.multiply(B, x)); - var d = Vec3.length(Vec3.subtract(P, X)); - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) - && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (0 < x && sizeOK) { - return { valid: true, x: x, y: y, z: z }; - } - return { valid: false }; - } - - this.glowedIntersectingModel = { isKnownID: false }; - this.moveLaser = function () { - // the overlays here are anchored to the avatar, which means they are specified in the avatar's local frame - - var inverseRotation = Quat.inverse(MyAvatar.orientation); - var startPosition = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.palmPosition, MyAvatar.position)); - var direction = Vec3.multiplyQbyV(inverseRotation, Vec3.subtract(this.tipPosition, this.palmPosition)); - var distance = Vec3.length(direction); - direction = Vec3.multiply(direction, LASER_LENGTH_FACTOR / distance); - var endPosition = Vec3.sum(startPosition, direction); - - Overlays.editOverlay(this.laser, { - start: startPosition, - end: endPosition - }); - - - Overlays.editOverlay(this.ball, { - position: endPosition - }); - Overlays.editOverlay(this.leftRight, { - start: Vec3.sum(endPosition, Vec3.multiply(this.right, 2 * this.guideScale)), - end: Vec3.sum(endPosition, Vec3.multiply(this.right, -2 * this.guideScale)) - }); - Overlays.editOverlay(this.topDown, { - 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); - - 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 halfDiagonal = Vec3.length(intersection.properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), intersection.properties.position)) * 180 / 3.14; - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) - && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - if (intersection.accurate && intersection.entityID.isKnownID && sizeOK) { - this.glowedIntersectingModel = intersection.entityID; - - if (wantEntityGlow) { - Entities.editEntity(this.glowedIntersectingModel, { glowLevel: 0.25 }); - } - } - } - } - - this.showLaser = function (show) { - Overlays.editOverlay(this.laser, { visible: show }); - Overlays.editOverlay(this.ball, { visible: show }); - Overlays.editOverlay(this.leftRight, { visible: show }); - Overlays.editOverlay(this.topDown, { visible: show }); - } - this.moveEntity = function () { - 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; - print("Identified ID " + this.entityID.id + ", isKnown: " + this.entityID.isKnownID); - } - var newPosition; - var newRotation; - - switch (mode) { - case 0: - newPosition = Vec3.sum(this.palmPosition, - Vec3.multiply(this.front, this.x)); - newPosition = Vec3.sum(newPosition, - Vec3.multiply(this.up, this.y)); - newPosition = Vec3.sum(newPosition, - Vec3.multiply(this.right, this.z)); - - - newRotation = Quat.multiply(this.rotation, - Quat.inverse(this.oldRotation)); - newRotation = Quat.multiply(newRotation, - this.oldModelRotation); - break; - case 1: - var forward = Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1 }); - var d = Vec3.dot(forward, MyAvatar.position); - - var factor1 = Vec3.dot(forward, this.positionAtGrab) - d; - var factor2 = Vec3.dot(forward, this.modelPositionAtGrab) - d; - var vector = Vec3.subtract(this.palmPosition, this.positionAtGrab); - - if (factor2 < 0) { - factor2 = 0; - } - if (factor1 <= 0) { - factor1 = 1; - factor2 = 1; - } - - newPosition = Vec3.sum(this.modelPositionAtGrab, - Vec3.multiply(vector, - factor2 / factor1)); - - newRotation = Quat.multiply(this.rotation, - Quat.inverse(this.rotationAtGrab)); - newRotation = Quat.multiply(newRotation, - this.rotationAtGrab); - break; - } - Entities.editEntity(this.entityID, { - position: newPosition, - rotation: newRotation - }); - this.oldModelRotation = newRotation; - this.oldModelPosition = newPosition; - - var indicesToRemove = []; - for (var i = 0; i < this.jointsIntersectingFromStart.length; ++i) { - var distance = Vec3.distance(MyAvatar.getJointPosition(this.jointsIntersectingFromStart[i]), this.oldModelPosition); - if (distance >= this.oldModelHalfDiagonal) { - indicesToRemove.push(this.jointsIntersectingFromStart[i]); - } - - } - for (var i = 0; i < indicesToRemove.length; ++i) { - this.jointsIntersectingFromStart.splice(this.jointsIntersectingFromStart.indexOf(indicesToRemove[i], 1)); - } - } - } - - this.update = function () { - this.oldPalmPosition = this.palmPosition; - this.oldTipPosition = this.tipPosition; - this.palmPosition = Controller.getSpatialControlPosition(this.palm); - this.tipPosition = Controller.getSpatialControlPosition(this.tip); - - this.oldUp = this.up; - this.up = Vec3.normalize(Controller.getSpatialControlNormal(this.palm)); - - this.oldFront = this.front; - this.front = Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)); - - this.oldRight = this.right; - this.right = Vec3.normalize(Vec3.cross(this.front, this.up)); - - this.oldRotation = this.rotation; - this.rotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); - - this.triggerValue = Controller.getTriggerValue(this.trigger); - - 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 } }); - } - } - this.bumperValue = bumperValue; - - - this.checkTrigger(); - - this.moveLaser(); - - if (!this.pressed && this.grabbing) { - // release if trigger not pressed anymore. - this.release(); - } - - if (this.pressing) { - // Checking for attachments intersecting - var attachments = MyAvatar.getAttachmentData(); - var attachmentIndex = -1; - var attachmentX = LASER_LENGTH_FACTOR; - - var newModel; - var newProperties; - - for (var i = 0; i < attachments.length; ++i) { - var position = Vec3.sum(MyAvatar.getJointPosition(attachments[i].jointName), - Vec3.multiplyQbyV(MyAvatar.getJointCombinedRotation(attachments[i].jointName), attachments[i].translation)); - var scale = attachments[i].scale; - - var A = this.palmPosition; - var B = this.front; - var P = position; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - var X = Vec3.sum(A, Vec3.multiply(B, x)); - var d = Vec3.length(Vec3.subtract(P, X)); - - if (d < scale / 2.0 && 0 < x && x < attachmentX) { - attachmentIndex = i; - attachmentX = d; - } - } - - if (attachmentIndex != -1) { - print("Detaching: " + attachments[attachmentIndex].modelURL); - MyAvatar.detachOne(attachments[attachmentIndex].modelURL, attachments[attachmentIndex].jointName); - - newProperties = { - type: "Model", - position: Vec3.sum(MyAvatar.getJointPosition(attachments[attachmentIndex].jointName), - Vec3.multiplyQbyV(MyAvatar.getJointCombinedRotation(attachments[attachmentIndex].jointName), attachments[attachmentIndex].translation)), - rotation: Quat.multiply(MyAvatar.getJointCombinedRotation(attachments[attachmentIndex].jointName), - attachments[attachmentIndex].rotation), - - // TODO: how do we know the correct dimensions for detachment??? - dimensions: { x: attachments[attachmentIndex].scale / 2.0, - y: attachments[attachmentIndex].scale / 2.0, - z: attachments[attachmentIndex].scale / 2.0 }, - - modelURL: attachments[attachmentIndex].modelURL - }; - - newModel = Entities.addEntity(newProperties); - - - } else { - // There is none so ... - // Checking model tree - 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); - - if(!foundIntersection.accurate) { - print("No accurate intersection"); - return; - } - newModel = foundIntersection.entityID; - if (!newModel.isKnownID) { - var identify = Entities.identifyEntity(newModel); - if (!identify.isKnownID) { - print("Unknown ID " + identify.id + " (update loop " + newModel.id + ")"); - return; - } - newModel = identify; - } - newProperties = Entities.getEntityProperties(newModel); - } - print("foundEntity.modelURL=" + newProperties.modelURL); - if (isLocked(newProperties)) { - print("Model locked " + newProperties.id); - } else { - var check = this.checkEntity(newProperties); - if (!check.valid) { - return; - } - - this.grab(newModel, newProperties); - - this.x = check.x; - this.y = check.y; - this.z = check.z; - return; - } - } - } - - this.cleanup = function () { - Overlays.deleteOverlay(this.laser); - Overlays.deleteOverlay(this.ball); - Overlays.deleteOverlay(this.leftRight); - Overlays.deleteOverlay(this.topDown); - } -} - -var leftController = new controller(LEFT); -var rightController = new controller(RIGHT); - -function moveEntities() { - if (leftController.grabbing && rightController.grabbing && rightController.entityID.id == leftController.entityID.id) { - var newPosition = leftController.oldModelPosition; - var rotation = leftController.oldModelRotation; - var ratio = 1; - - - switch (mode) { - case 0: - var oldLeftPoint = Vec3.sum(leftController.oldPalmPosition, Vec3.multiply(leftController.oldFront, leftController.x)); - var oldRightPoint = Vec3.sum(rightController.oldPalmPosition, Vec3.multiply(rightController.oldFront, rightController.x)); - - var oldMiddle = Vec3.multiply(Vec3.sum(oldLeftPoint, oldRightPoint), 0.5); - var oldLength = Vec3.length(Vec3.subtract(oldLeftPoint, oldRightPoint)); - - - var leftPoint = Vec3.sum(leftController.palmPosition, Vec3.multiply(leftController.front, leftController.x)); - var rightPoint = Vec3.sum(rightController.palmPosition, Vec3.multiply(rightController.front, rightController.x)); - - var middle = Vec3.multiply(Vec3.sum(leftPoint, rightPoint), 0.5); - var length = Vec3.length(Vec3.subtract(leftPoint, rightPoint)); - - - ratio = length / oldLength; - newPosition = Vec3.sum(middle, - Vec3.multiply(Vec3.subtract(leftController.oldModelPosition, oldMiddle), ratio)); - break; - case 1: - var u = Vec3.normalize(Vec3.subtract(rightController.oldPalmPosition, leftController.oldPalmPosition)); - var v = Vec3.normalize(Vec3.subtract(rightController.palmPosition, leftController.palmPosition)); - - var cos_theta = Vec3.dot(u, v); - if (cos_theta > 1) { - cos_theta = 1; - } - var angle = Math.acos(cos_theta) / Math.PI * 180; - if (angle < 0.1) { - return; - - } - var w = Vec3.normalize(Vec3.cross(u, v)); - - rotation = Quat.multiply(Quat.angleAxis(angle, w), leftController.oldModelRotation); - - - leftController.positionAtGrab = leftController.palmPosition; - leftController.rotationAtGrab = leftController.rotation; - leftController.modelPositionAtGrab = leftController.oldModelPosition; - leftController.rotationAtGrab = rotation; - rightController.positionAtGrab = rightController.palmPosition; - rightController.rotationAtGrab = rightController.rotation; - rightController.modelPositionAtGrab = rightController.oldModelPosition; - rightController.rotationAtGrab = rotation; - break; - } - Entities.editEntity(leftController.entityID, { - position: newPosition, - rotation: rotation, - // TODO: how do we know the correct dimensions for detachment??? - //radius: leftController.oldModelHalfDiagonal * ratio - dimensions: { x: leftController.oldModelHalfDiagonal * ratio, - y: leftController.oldModelHalfDiagonal * ratio, - z: leftController.oldModelHalfDiagonal * ratio } - - - }); - leftController.oldModelPosition = newPosition; - leftController.oldModelRotation = rotation; - leftController.oldModelHalfDiagonal *= ratio; - - rightController.oldModelPosition = newPosition; - rightController.oldModelRotation = rotation; - rightController.oldModelHalfDiagonal *= ratio; - return; - } - leftController.moveEntity(); - rightController.moveEntity(); -} - -var hydraConnected = false; -function checkController(deltaTime) { - var numberOfButtons = Controller.getNumberOfButtons(); - var numberOfTriggers = Controller.getNumberOfTriggers(); - var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); - var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; - - if (!isActive) { - // So that we hide the lasers bellow and keep updating the overlays position - numberOfButtons = 0; - } - - // this is expected for hydras - if (numberOfButtons == 12 && numberOfTriggers == 2 && controllersPerTrigger == 2) { - if (!hydraConnected) { - hydraConnected = true; - } - - leftController.update(); - rightController.update(); - moveEntities(); - } else { - if (hydraConnected) { - hydraConnected = false; - - leftController.showLaser(false); - rightController.showLaser(false); - } - } - toolBar.move(); - progressDialog.move(); -} - -var entitySelected = false; -var selectedEntityID; -var selectedEntityProperties; -var mouseLastPosition; -var orientation; -var intersection; - - -var SCALE_FACTOR = 200.0; - -function rayPlaneIntersection(pickRay, point, normal) { - var d = -Vec3.dot(point, normal); - var t = -(Vec3.dot(pickRay.origin, normal) + d) / Vec3.dot(pickRay.direction, normal); - - return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t)); -} - -function Tooltip() { - this.x = 285; - this.y = 115; - this.width = 500; - this.height = 300; // 145; - this.margin = 5; - this.decimals = 3; - - this.textOverlay = Overlays.addOverlay("text", { - x: this.x, - y: this.y, - width: this.width, - height: this.height, - margin: this.margin, - text: "", - color: { red: 228, green: 228, blue: 228 }, - alpha: 0.8, - backgroundAlpha: 0.8, - visible: false - }); - this.show = function (doShow) { - Overlays.editOverlay(this.textOverlay, { visible: doShow }); - } - this.updateText = function(properties) { - var angles = Quat.safeEulerAngles(properties.rotation); - var text = "Entity Properties:\n" - text += "type: " + properties.type + "\n" - text += "X: " + properties.position.x.toFixed(this.decimals) + "\n" - text += "Y: " + properties.position.y.toFixed(this.decimals) + "\n" - text += "Z: " + properties.position.z.toFixed(this.decimals) + "\n" - text += "Pitch: " + angles.x.toFixed(this.decimals) + "\n" - text += "Yaw: " + angles.y.toFixed(this.decimals) + "\n" - text += "Roll: " + angles.z.toFixed(this.decimals) + "\n" - text += "Dimensions: " + properties.dimensions.x.toFixed(this.decimals) + ", " - + properties.dimensions.y.toFixed(this.decimals) + ", " - + properties.dimensions.z.toFixed(this.decimals) + "\n"; - - text += "Natural Dimensions: " + properties.naturalDimensions.x.toFixed(this.decimals) + ", " - + properties.naturalDimensions.y.toFixed(this.decimals) + ", " - + properties.naturalDimensions.z.toFixed(this.decimals) + "\n"; - - text += "ID: " + properties.id + "\n" - if (properties.type == "Model") { - text += "Model URL: " + properties.modelURL + "\n" - text += "Animation URL: " + properties.animationURL + "\n" - text += "Animation is playing: " + properties.animationIsPlaying + "\n" - if (properties.sittingPoints && properties.sittingPoints.length > 0) { - text += properties.sittingPoints.length + " Sitting points: " - for (var i = 0; i < properties.sittingPoints.length; ++i) { - text += properties.sittingPoints[i].name + " " - } - } else { - text += "No sitting points" + "\n" - } - } - if (properties.lifetime > -1) { - text += "Lifetime: " + properties.lifetime + "\n" - } - text += "Age: " + properties.ageAsText + "\n" - text += "Mass: " + properties.mass + "\n" - text += "Script: " + properties.script + "\n" - - - Overlays.editOverlay(this.textOverlay, { text: text }); - } - - this.cleanup = function () { - Overlays.deleteOverlay(this.textOverlay); - } -} -var tooltip = new Tooltip(); - -function mousePressEvent(event) { - if (event.isAlt) { - return; - } - - mouseLastPosition = { x: event.x, y: event.y }; - entitySelected = false; - var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event)) { - // Event handled; do nothing. - return; - } else { - // If we aren't active and didn't click on an overlay: quit - if (!isActive) { - return; - } - - var pickRay = Camera.computePickRay(event.x, event.y); - Vec3.print("[Mouse] Looking at: ", pickRay.origin); - var foundIntersection = Entities.findRayIntersection(pickRay, true); // we want precision picking here - - if(!foundIntersection.accurate) { - return; - } - var foundEntity = foundIntersection.entityID; - - if (!foundEntity.isKnownID) { - var identify = Entities.identifyEntity(foundEntity); - if (!identify.isKnownID) { - print("Unknown ID " + identify.id + " (update loop " + foundEntity.id + ")"); - return; - } - foundEntity = identify; - } - - var properties = Entities.getEntityProperties(foundEntity); - if (isLocked(properties)) { - print("Model locked " + properties.id); - } else { - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - print("Checking properties: " + properties.id + " " + properties.isKnownID + " - Half Diagonal:" + halfDiagonal); - // P P - Model - // /| A - Palm - // / | d B - unit vector toward tip - // / | X - base of the perpendicular line - // A---X----->B d - distance fom axis - // x x - distance from A - // - // |X-A| = (P-A).B - // X == A + ((P-A).B)B - // d = |P-X| - - var A = pickRay.origin; - var B = Vec3.normalize(pickRay.direction); - var P = properties.position; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - var X = Vec3.sum(A, Vec3.multiply(B, x)); - var d = Vec3.length(Vec3.subtract(P, X)); - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) - && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (0 < x && sizeOK) { - entitySelected = true; - selectedEntityID = foundEntity; - selectedEntityProperties = properties; - orientation = MyAvatar.orientation; - intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation)); - } - } - } - if (entitySelected) { - selectedEntityProperties.oldDimensions = selectedEntityProperties.dimensions; - selectedEntityProperties.oldPosition = { - x: selectedEntityProperties.position.x, - y: selectedEntityProperties.position.y, - z: selectedEntityProperties.position.z, - }; - selectedEntityProperties.oldRotation = { - x: selectedEntityProperties.rotation.x, - y: selectedEntityProperties.rotation.y, - z: selectedEntityProperties.rotation.z, - w: selectedEntityProperties.rotation.w, - }; - selectedEntityProperties.glowLevel = 0.0; - - print("Clicked on " + selectedEntityID.id + " " + entitySelected); - tooltip.updateText(selectedEntityProperties); - tooltip.show(true); - } -} - -var glowedEntityID = { id: -1, isKnownID: false }; -var oldModifier = 0; -var modifier = 0; -var wasShifted = false; -function mouseMoveEvent(event) { - if (event.isAlt || !isActive) { - return; - } - - var pickRay = Camera.computePickRay(event.x, event.y); - if (!entitySelected) { - var entityIntersection = Entities.findRayIntersection(pickRay); - if (entityIntersection.accurate) { - if(glowedEntityID.isKnownID && glowedEntityID.id != entityIntersection.entityID.id) { - Entities.editEntity(glowedEntityID, { glowLevel: 0.0 }); - glowedEntityID.id = -1; - glowedEntityID.isKnownID = false; - } - - var halfDiagonal = Vec3.length(entityIntersection.properties.dimensions) / 2.0; - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), - entityIntersection.properties.position)) * 180 / 3.14; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) - && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (entityIntersection.entityID.isKnownID && sizeOK) { - if (wantEntityGlow) { - Entities.editEntity(entityIntersection.entityID, { glowLevel: 0.25 }); - } - glowedEntityID = entityIntersection.entityID; - } - - } - return; - } - - if (event.isLeftButton) { - if (event.isRightButton) { - modifier = 1; // Scale - } else { - modifier = 2; // Translate - } - } else if (event.isRightButton) { - modifier = 3; // rotate - } else { - modifier = 0; - } - pickRay = Camera.computePickRay(event.x, event.y); - if (wasShifted != event.isShifted || modifier != oldModifier) { - selectedEntityProperties.oldDimensions = selectedEntityProperties.dimensions; - - selectedEntityProperties.oldPosition = { - x: selectedEntityProperties.position.x, - y: selectedEntityProperties.position.y, - z: selectedEntityProperties.position.z, - }; - selectedEntityProperties.oldRotation = { - x: selectedEntityProperties.rotation.x, - y: selectedEntityProperties.rotation.y, - z: selectedEntityProperties.rotation.z, - w: selectedEntityProperties.rotation.w, - }; - orientation = MyAvatar.orientation; - intersection = rayPlaneIntersection(pickRay, - selectedEntityProperties.oldPosition, - Quat.getFront(orientation)); - - mouseLastPosition = { x: event.x, y: event.y }; - wasShifted = event.isShifted; - oldModifier = modifier; - return; - } - - - switch (modifier) { - case 0: - return; - case 1: - // Let's Scale - selectedEntityProperties.dimensions = Vec3.multiply(selectedEntityProperties.dimensions, - (1.0 + (mouseLastPosition.y - event.y) / SCALE_FACTOR)); - - var halfDiagonal = Vec3.length(selectedEntityProperties.dimensions) / 2.0; - - if (halfDiagonal < 0.01) { - print("Scale too small ... bailling."); - return; - } - break; - - case 2: - // Let's translate - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityProperties.oldPosition, - Quat.getFront(orientation)); - var vector = Vec3.subtract(newIntersection, intersection) - if (event.isShifted) { - var i = Vec3.dot(vector, Quat.getRight(orientation)); - var j = Vec3.dot(vector, Quat.getUp(orientation)); - vector = Vec3.sum(Vec3.multiply(Quat.getRight(orientation), i), - Vec3.multiply(Quat.getFront(orientation), j)); - } - selectedEntityProperties.position = Vec3.sum(selectedEntityProperties.oldPosition, vector); - break; - case 3: - // Let's rotate - if (somethingChanged) { - selectedEntityProperties.oldRotation.x = selectedEntityProperties.rotation.x; - selectedEntityProperties.oldRotation.y = selectedEntityProperties.rotation.y; - selectedEntityProperties.oldRotation.z = selectedEntityProperties.rotation.z; - selectedEntityProperties.oldRotation.w = selectedEntityProperties.rotation.w; - mouseLastPosition.x = event.x; - mouseLastPosition.y = event.y; - somethingChanged = false; - } - - - var pixelPerDegrees = windowDimensions.y / (1 * 360); // the entire height of the window allow you to make 2 full rotations - - //compute delta in pixel - var cameraForward = Quat.getFront(Camera.getOrientation()); - var rotationAxis = (!zIsPressed && xIsPressed) ? { x: 1, y: 0, z: 0 } : - (!zIsPressed && !xIsPressed) ? { x: 0, y: 1, z: 0 } : - { x: 0, y: 0, z: 1 }; - rotationAxis = Vec3.multiplyQbyV(selectedEntityProperties.rotation, rotationAxis); - var orthogonalAxis = Vec3.cross(cameraForward, rotationAxis); - var mouseDelta = { x: event.x - mouseLastPosition - .x, y: mouseLastPosition.y - event.y, z: 0 }; - var transformedMouseDelta = Vec3.multiplyQbyV(Camera.getOrientation(), mouseDelta); - var delta = Math.floor(Vec3.dot(transformedMouseDelta, Vec3.normalize(orthogonalAxis)) / pixelPerDegrees); - - var STEP = 15; - if (!event.isShifted) { - delta = Math.round(delta / STEP) * STEP; - } - - var rotation = Quat.fromVec3Degrees({ - x: (!zIsPressed && xIsPressed) ? delta : 0, // x is pressed - y: (!zIsPressed && !xIsPressed) ? delta : 0, // neither is pressed - z: (zIsPressed && !xIsPressed) ? delta : 0 // z is pressed - }); - rotation = Quat.multiply(selectedEntityProperties.oldRotation, rotation); - - selectedEntityProperties.rotation.x = rotation.x; - selectedEntityProperties.rotation.y = rotation.y; - selectedEntityProperties.rotation.z = rotation.z; - selectedEntityProperties.rotation.w = rotation.w; - break; - } - - Entities.editEntity(selectedEntityID, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); -} - - -function mouseReleaseEvent(event) { - if (event.isAlt || !isActive) { - return; - } - if (entitySelected) { - tooltip.show(false); - } - - entitySelected = false; - - glowedEntityID.id = -1; - glowedEntityID.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 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")) { - print("no delete... adding ours"); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", - shortcutKeyEvent: { text: "backspace" }, afterItem: "Models" }); - modelMenuAddedDelete = true; - } else { - print("delete exists... don't add ours"); - } - - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." }); - 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: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" }); - Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" }); - - Entities.setLightsArePickable(false); - -} - -function cleanupModelMenus() { - Menu.removeSeparator("Edit", "Models"); - Menu.removeMenuItem("Edit", "Edit Properties..."); - if (modelMenuAddedDelete) { - // delete our menuitems - Menu.removeMenuItem("Edit", "Delete"); - } - - Menu.removeMenuItem("Edit", "Model List..."); - Menu.removeMenuItem("Edit", "Paste Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); - - Menu.removeSeparator("File", "Models"); - Menu.removeMenuItem("File", "Export Models"); - Menu.removeMenuItem("File", "Import Models"); -} - -function scriptEnding() { - leftController.cleanup(); - rightController.cleanup(); - progressDialog.cleanup(); - toolBar.cleanup(); - cleanupModelMenus(); - tooltip.cleanup(); - modelImporter.cleanup(); - if (exportMenu) { - exportMenu.close(); - } - Entities.setLightsArePickable(originalLightsArePickable); -} -Script.scriptEnding.connect(scriptEnding); - -// register the call back so it fires before each data send -Script.update.connect(checkController); -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseMoveEvent.connect(mouseMoveEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); - -setupModelMenus(); - -var propertiesForEditedEntity; -var editEntityFormArray; -var editModelID = -1; -var dimensionX; -var dimensionY; -var dimensionZ; -var rescalePercentage; - -function showPropertiesForm(editModelID) { - entityPropertyDialogBox.openDialog(editModelID); -} - -function handeMenuEvent(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 (leftController.grabbing) { - print(" Delete Entity.... leftController.entityID="+ leftController.entityID); - Entities.deleteEntity(leftController.entityID); - leftController.grabbing = false; - if (glowedEntityID.id == leftController.entityID.id) { - glowedEntityID = { id: -1, isKnownID: false }; - } - } else if (rightController.grabbing) { - print(" Delete Entity.... rightController.entityID="+ rightController.entityID); - Entities.deleteEntity(rightController.entityID); - rightController.grabbing = false; - if (glowedEntityID.id == rightController.entityID.id) { - glowedEntityID = { id: -1, isKnownID: false }; - } - } else if (entitySelected) { - print(" Delete Entity.... selectedEntityID="+ selectedEntityID); - Entities.deleteEntity(selectedEntityID); - entitySelected = false; - if (glowedEntityID.id == selectedEntityID.id) { - glowedEntityID = { id: -1, isKnownID: false }; - } - } else { - print(" Delete Entity.... not holding..."); - } - } else if (menuItem == "Model List...") { - var models = new Array(); - models = Entities.findEntities(MyAvatar.position, Number.MAX_VALUE); - for (var i = 0; i < models.length; i++) { - models[i].properties = Entities.getEntityProperties(models[i]); - models[i].toString = function() { - var modelname; - if (this.properties.type == "Model") { - modelname = decodeURIComponent( - this.properties.modelURL.indexOf("/") != -1 ? - this.properties.modelURL.substring(this.properties.modelURL.lastIndexOf("/") + 1) : - this.properties.modelURL); - } else { - modelname = this.properties.id; - } - return "[" + this.properties.type + "] " + modelname; - }; - } - var form = [{label: "Model: ", options: models}]; - form.push({label: "Action: ", options: ["Properties", "Delete", "Teleport"]}); - form.push({ button: "Cancel" }); - if (Window.form("Model List", form)) { - var selectedModel = form[0].value; - if (form[1].value == "Properties") { - editModelID = selectedModel; - showPropertiesForm(editModelID); - } else if (form[1].value == "Delete") { - Entities.deleteEntity(selectedModel); - } else if (form[1].value == "Teleport") { - MyAvatar.position = selectedModel.properties.position; - } - } - } else if (menuItem == "Edit Properties...") { - editModelID = -1; - if (leftController.grabbing) { - print(" Edit Properties.... leftController.entityID="+ leftController.entityID); - editModelID = leftController.entityID; - } else if (rightController.grabbing) { - print(" Edit Properties.... rightController.entityID="+ rightController.entityID); - editModelID = rightController.entityID; - } else if (entitySelected) { - print(" Edit Properties.... selectedEntityID="+ selectedEntityID); - editModelID = selectedEntityID; - } else { - print(" Edit Properties.... not holding..."); - } - if (editModelID != -1) { - print(" Edit Properties.... about to edit properties..."); - showPropertiesForm(editModelID); - } - } else if (menuItem == "Paste Models") { - modelImporter.paste(); - } else if (menuItem == "Export Models") { - if (!exportMenu) { - exportMenu = new ExportMenu({ - onClose: function () { - exportMenu = null; - } - }); - } - } else if (menuItem == "Import Models") { - modelImporter.doImport(); - } - tooltip.show(false); -} -Menu.menuItemEvent.connect(handeMenuEvent); - - - -// handling of inspect.js concurrence -var zIsPressed = false; -var xIsPressed = false; -var somethingChanged = false; -Controller.keyPressEvent.connect(function (event) { - if ((event.text == "z" || event.text == "Z") && !zIsPressed) { - zIsPressed = true; - somethingChanged = true; - } - if ((event.text == "x" || event.text == "X") && !xIsPressed) { - xIsPressed = true; - somethingChanged = true; - } - - // resets model orientation when holding with mouse - if (event.text == "r" && entitySelected) { - selectedEntityProperties.rotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 0 }); - Entities.editEntity(selectedEntityID, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - somethingChanged = true; - } -}); - -Controller.keyReleaseEvent.connect(function (event) { - if (event.text == "z" || event.text == "Z") { - zIsPressed = false; - somethingChanged = true; - } - if (event.text == "x" || event.text == "X") { - xIsPressed = false; - somethingChanged = true; - } - // 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..."); - } - if (event.text == "BACKSPACE") { - handeMenuEvent("Delete"); - } -}); - From 8d8352946b9d5b271477f4e1e81271dfaddc5211 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 9 Jan 2015 10:01:58 -0800 Subject: [PATCH 025/159] Add rescale button to edit properties window --- examples/editEntities.js | 13 +++++++++++++ examples/html/entityProperties.html | 15 +++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/examples/editEntities.js b/examples/editEntities.js index b65756e9b4..2462c30854 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -1077,6 +1077,19 @@ PropertiesTool = function(opts) { pushCommandForSelections(); selectionManager._update(); } + } else if (data.action == "rescaleDimensions") { + var multiplier = data.percentage / 100; + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + for (var i = 0; i < selectionManager.selections.length; i++) { + var properties = selectionManager.savedProperties[selectionManager.selections[i].id]; + Entities.editEntity(selectionManager.selections[i], { + dimensions: Vec3.multiply(multiplier, properties.dimensions), + }); + } + pushCommandForSelections(); + selectionManager._update(); + } } } }); diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index a3644d8c3d..d7f097966a 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -84,6 +84,8 @@ var elDimensionsY = document.getElementById("property-dim-y"); var elDimensionsZ = document.getElementById("property-dim-z"); var elResetToNaturalDimensions = document.getElementById("reset-to-natural-dimensions"); + var elRescaleDimensionsPct = document.getElementById("dimension-rescale-pct"); + var elRescaleDimensionsButton = document.getElementById("dimension-rescale-button"); var elRegistrationX = document.getElementById("property-reg-x"); var elRegistrationY = document.getElementById("property-reg-y"); @@ -419,6 +421,13 @@ action: "resetToNaturalDimensions", })); }); + elRescaleDimensionsButton.addEventListener("click", function() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "rescaleDimensions", + percentage: parseInt(elRescaleDimensionsPct.value), + })); + }); var resizing = false; @@ -537,6 +546,12 @@
+
+ % +
+ + + From e00b629133fa26c6454746b3c5d2622ba75e5d48 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 9 Jan 2015 16:11:17 -0800 Subject: [PATCH 026/159] Fix gl projection matrix stack overflow when rendering to HUD The projection matrix stack is considerably smaller than the modelview stack and was overflowing on Windows and Linux machines that were tested. --- interface/src/ui/ApplicationOverlay.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 1d710f29d4..106c74cdeb 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -197,19 +197,23 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { const float FAR_CLIP = 10000; glLoadIdentity(); glOrtho(0, glCanvas->width(), glCanvas->height(), 0, NEAR_CLIP, FAR_CLIP); - + + glMatrixMode(GL_MODELVIEW); + renderAudioMeter(); - + renderStatsAndLogs(); - + // give external parties a change to hook in emit application->renderingOverlay(); - + overlays.renderHUD(); - + renderPointers(); - + renderDomainConnectionStatusBorder(); + + glMatrixMode(GL_PROJECTION); } glPopMatrix(); glMatrixMode(GL_MODELVIEW); From 8bb69d0a9085256a82665ce09ab66c5bff992860 Mon Sep 17 00:00:00 2001 From: chris Date: Fri, 9 Jan 2015 16:22:52 -0800 Subject: [PATCH 027/159] Update std::string instances to QString --- interface/CMakeLists.txt | 2 +- libraries/entities/src/EntityTreeElement.cpp | 2 +- libraries/fbx/src/FBXReader.cpp | 90 ++++++++++---------- libraries/fbx/src/FBXReader.h | 2 +- libraries/render-utils/src/GeometryCache.cpp | 4 +- 5 files changed, 50 insertions(+), 50 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 8ddd1153ef..77a20201cb 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -2,7 +2,7 @@ set(TARGET_NAME interface) project(${TARGET_NAME}) # set a default root dir for each of our optional externals if it was not passed -set(OPTIONAL_EXTERNALS "Faceshift" "LibOVR" "PrioVR" "Sixense" "LeapMotion" "RtMidi" "Qxmpp" "SDL2" "Gverb") +set(OPTIONAL_EXTERNALS "Faceshift" "LibOVR" "PrioVR" "Sixense" "LeapMotion" "RtMidi" "Qxmpp" "SDL2" "Gverb" "Visage") foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE) if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 5f072164a0..a7e7b6fdb3 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -665,7 +665,7 @@ const EntityItem* EntityTreeElement::getEntityWithEntityItemID(const EntityItemI } return foundEntity; } - + EntityItem* EntityTreeElement::getEntityWithEntityItemID(const EntityItemID& id) { EntityItem* foundEntity = NULL; uint16_t numberOfEntities = _entityItems->size(); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 9532f44acf..8363084d37 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -38,7 +38,7 @@ struct TextureParam { glm::vec2 UVTranslation; glm::vec2 UVScaling; glm::vec4 cropping; - std::string UVSet; + QString UVSet; glm::vec3 translation; glm::vec3 rotation; @@ -802,14 +802,14 @@ public: QVector > blendshapeIndexMaps; QVector > partMaterialTextures; QHash texcoordSetMap; - std::map texcoordSetMap2; + std::map texcoordSetMap2; }; class AttributeData { public: QVector texCoords; QVector texCoordIndices; - std::string name; + QString name; int index; }; @@ -945,12 +945,12 @@ ExtractedMesh extractMesh(const FBXNode& object) { data.texCoordIndices = getIntVector(subdata); attrib.texCoordIndices = getIntVector(subdata); } else if (subdata.name == "Name") { - attrib.name = subdata.properties.at(0).toString().toStdString(); + attrib.name = subdata.properties.at(0).toString(); } #if defined(DEBUG_FBXREADER) else { int unknown = 0; - std::string subname = subdata.name.data(); + QString subname = subdata.name.data(); if ( (subdata.name == "Version") || (subdata.name == "MappingInformationType") || (subdata.name == "ReferenceInformationType") ) { @@ -960,7 +960,7 @@ ExtractedMesh extractMesh(const FBXNode& object) { } #endif } - data.extracted.texcoordSetMap.insert(QString(attrib.name.c_str()), data.attributes.size()); + data.extracted.texcoordSetMap.insert(attrib.name, data.attributes.size()); data.attributes.push_back(attrib); } else { AttributeData attrib; @@ -971,12 +971,12 @@ ExtractedMesh extractMesh(const FBXNode& object) { } else if (subdata.name == "UVIndex") { attrib.texCoordIndices = getIntVector(subdata); } else if (subdata.name == "Name") { - attrib.name = subdata.properties.at(0).toString().toStdString(); + attrib.name = subdata.properties.at(0).toString(); } #if defined(DEBUG_FBXREADER) else { int unknown = 0; - std::string subname = subdata.name.data(); + QString subname = subdata.name.data(); if ( (subdata.name == "Version") || (subdata.name == "MappingInformationType") || (subdata.name == "ReferenceInformationType") ) { @@ -987,9 +987,9 @@ ExtractedMesh extractMesh(const FBXNode& object) { #endif } - QHash::iterator it = data.extracted.texcoordSetMap.find(QString(attrib.name.c_str())); + QHash::iterator it = data.extracted.texcoordSetMap.find(attrib.name); if (it == data.extracted.texcoordSetMap.end()) { - data.extracted.texcoordSetMap.insert(QString(attrib.name.c_str()), data.attributes.size()); + data.extracted.texcoordSetMap.insert(attrib.name, data.attributes.size()); data.attributes.push_back(attrib); } else { // WTF same names for different UVs? @@ -1198,11 +1198,11 @@ bool checkMaterialsHaveTextures(const QHash& materials, return false; } -int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const QHash& texcoordChannels) { - if (texUVSetName.empty()) { +int matchTextureUVSetToAttributeChannel(const QString& texUVSetName, const QHash& texcoordChannels) { + if (texUVSetName.isEmpty()) { return 0; } else { - QHash::const_iterator tcUnit = texcoordChannels.find(QString(texUVSetName.c_str())); + QHash::const_iterator tcUnit = texcoordChannels.find(texUVSetName); if (tcUnit != texcoordChannels.end()) { int channel = (*tcUnit); if (channel >= 2) { @@ -1220,13 +1220,13 @@ FBXLight extractLight(const FBXNode& object) { FBXLight light; foreach (const FBXNode& subobject, object.children) { - std::string childname = QString(subobject.name).toStdString(); + QString childname = QString(subobject.name); if (subobject.name == "Properties70") { foreach (const FBXNode& property, subobject.children) { int valIndex = 4; - std::string propName = QString(property.name).toStdString(); + QString propName = QString(property.name); if (property.name == "P") { - std::string propname = property.properties.at(0).toString().toStdString(); + QString propname = property.properties.at(0).toString(); if (propname == "Intensity") { light.intensity = 0.01f * property.properties.at(valIndex).value(); } @@ -1238,13 +1238,13 @@ FBXLight extractLight(const FBXNode& object) { } #if defined(DEBUG_FBXREADER) - std::string type = object.properties.at(0).toString().toStdString(); - type = object.properties.at(1).toString().toStdString(); - type = object.properties.at(2).toString().toStdString(); + QString type = object.properties.at(0).toString(); + type = object.properties.at(1).toString(); + type = object.properties.at(2).toString(); foreach (const QVariant& prop, object.properties) { - std::string proptype = prop.typeName(); - std::string propval = prop.toString().toStdString(); + QString proptype = prop.typeName(); + QString propval = prop.toString(); if (proptype == "Properties70") { } } @@ -1281,7 +1281,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, QHash yComponents; QHash zComponents; - std::map lights; + std::map lights; QVariantHash joints = mapping.value("joint").toHash(); QString jointEyeLeftName = processID(getString(joints.value("jointEyeLeft", "jointEyeLeft"))); @@ -1369,7 +1369,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, int index = 4; foreach (const FBXNode& subobject, object.children) { if (subobject.name == propertyName) { - std::string subpropName = subobject.properties.at(0).toString().toStdString(); + QString subpropName = subobject.properties.at(0).toString(); if (subpropName == "UnitScaleFactor") { unitScaleFactor = subobject.properties.at(index).toFloat(); } else if (subpropName == "AmbientColor") { @@ -1393,8 +1393,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, QString id = getID(object.properties); modelIDsToNames.insert(id, name); - std::string modelname = name.toLower().toStdString(); - if (modelname.find("hifi") == 0) { + QString modelname = name.toLower(); + if (modelname.startsWith("hifi")) { hifiGlobalNodeID = id; } @@ -1527,19 +1527,19 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } #if defined(DEBUG_FBXREADER) else if (subobject.name == "TypeFlags") { - std::string attributetype = subobject.properties.at(0).toString().toStdString(); + QString attributetype = subobject.properties.at(0).toString(); if (!attributetype.empty()) { if (attributetype == "Light") { - std::string lightprop; + QString lightprop; foreach (const QVariant& vprop, subobject.properties) { - lightprop = vprop.toString().toStdString(); + lightprop = vprop.toString(); } FBXLight light = extractLight(object); } } } else { - std::string whatisthat = subobject.name; + QString whatisthat = subobject.name; if (whatisthat == "Shape") { } } @@ -1604,7 +1604,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, if (property.name == propertyName) { QString v = property.properties.at(0).toString(); if (property.properties.at(0) == "UVSet") { - tex.assign(tex.UVSet, property.properties.at(index).toString().toStdString()); + tex.assign(tex.UVSet, property.properties.at(index).toString()); } else if (property.properties.at(0) == "CurrentTextureBlendMode") { tex.assign(tex.currentTextureBlendMode, property.properties.at(index).value()); } else if (property.properties.at(0) == "UseMaterial") { @@ -1618,7 +1618,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } #if defined(DEBUG_FBXREADER) else { - std::string propName = v.toStdString(); + QString propName = v; unknown++; } #endif @@ -1632,7 +1632,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } else if (subobject.name == "FileName") { } else if (subobject.name == "Media") { } else { - std::string subname = subobject.name.data(); + QString subname = subobject.name.data(); unknown++; } } @@ -1693,7 +1693,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } #if defined(DEBUG_FBXREADER) else { - const std::string propname = property.properties.at(0).toString().toStdString(); + const QString propname = property.properties.at(0).toString(); if (propname == "EmissiveFactor") { } } @@ -1703,7 +1703,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } #if defined(DEBUG_FBXREADER) else { - std::string propname = subobject.name.data(); + QString propname = subobject.name.data(); int unknown = 0; if ( (propname == "Version") ||(propname == "ShadingModel") @@ -1719,21 +1719,21 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } else if (object.name == "NodeAttribute") { #if defined(DEBUG_FBXREADER) - std::vector properties; + std::vector properties; foreach(const QVariant& v, object.properties) { - properties.push_back(v.toString().toStdString()); + properties.push_back(v.toString()); } #endif - std::string attribID = getID(object.properties).toStdString(); - std::string attributetype; + QString attribID = getID(object.properties); + QString attributetype; foreach (const FBXNode& subobject, object.children) { if (subobject.name == "TypeFlags") { typeFlags.insert(getID(object.properties), subobject.properties.at(0).toString()); - attributetype = subobject.properties.at(0).toString().toStdString(); + attributetype = subobject.properties.at(0).toString(); } } - if (!attributetype.empty()) { + if (!attributetype.isEmpty()) { if (attributetype == "Light") { FBXLight light = extractLight(object); lights[attribID] = light; @@ -1781,7 +1781,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } #if defined(DEBUG_FBXREADER) else { - std::string objectname = object.name.data(); + QString objectname = object.name.data(); if ( objectname == "Pose" || objectname == "AnimationStack" || objectname == "AnimationLayer" @@ -1800,7 +1800,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, QString parentID = getID(connection.properties, 2); ooChildToParent.insert(childID, parentID); if (!hifiGlobalNodeID.isEmpty() && (parentID == hifiGlobalNodeID)) { - std::map< std::string, FBXLight >::iterator lit = lights.find(childID.toStdString()); + std::map< QString, FBXLight >::iterator lit = lights.find(childID); if (lit != lights.end()) { lightmapLevel = (*lit).second.intensity; if (lightmapLevel <= 0.0f) { @@ -1842,7 +1842,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } else if (loadLightmaps && type.contains("ambient")) { ambientTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else { - std::string typenam = type.data(); + QString typenam = type.data(); counter++; } } @@ -1853,7 +1853,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } #if defined(DEBUG_FBXREADER) else { - std::string objectname = child.name.data(); + QString objectname = child.name.data(); if ( objectname == "Pose" || objectname == "CreationTime" || objectname == "FileId" @@ -1875,7 +1875,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, // TODO: check if is code is needed if (!lights.empty()) { if (hifiGlobalNodeID.isEmpty()) { - std::map< std::string, FBXLight >::iterator l = lights.begin(); + std::map< QString, FBXLight >::iterator l = lights.begin(); lightmapLevel = (*l).second.intensity; } } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 44b2bfe4a5..98e4d60826 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -110,7 +110,7 @@ public: Transform transform; int texcoordSet; - std::string texcoordSetName; + QString texcoordSetName; }; /// A single part of a mesh (with the same material). diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 553e460a5c..f7bd56e3ca 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1871,9 +1871,9 @@ void GeometryReader::run() { if (!_reply) { throw QString("Reply is NULL ?!"); } - std::string urlname = _url.path().toLower().toStdString(); + QString urlname = _url.path().toLower(); bool urlValid = true; - urlValid &= !urlname.empty(); + urlValid &= !urlname.isEmpty(); urlValid &= !_url.path().isEmpty(); urlValid &= _url.path().toLower().endsWith(".fbx") || _url.path().toLower().endsWith(".svo"); From d84a65a5f9a0bc2f373e047e6956dc7f7cf48ee1 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 10 Jan 2015 01:29:06 +0100 Subject: [PATCH 028/159] running scripts list -> treeview initial --- interface/src/ScriptsModel.cpp | 113 +++++++++++++++++----- interface/src/ScriptsModel.h | 51 ++++++++-- interface/src/ui/RunningScriptsWidget.cpp | 10 +- interface/ui/runningScriptsWidget.ui | 31 +++++- 4 files changed, 164 insertions(+), 41 deletions(-) diff --git a/interface/src/ScriptsModel.cpp b/interface/src/ScriptsModel.cpp index 41ce16c229..d178397fc2 100644 --- a/interface/src/ScriptsModel.cpp +++ b/interface/src/ScriptsModel.cpp @@ -11,6 +11,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include #include #include @@ -31,18 +32,30 @@ static const QString IS_TRUNCATED_NAME = "IsTruncated"; static const QString CONTAINER_NAME = "Contents"; static const QString KEY_NAME = "Key"; -ScriptItem::ScriptItem(const QString& filename, const QString& fullPath) : +TreeNodeBase::TreeNodeBase(TreeNodeFolder* parent, TreeNodeType type) : + _parent(parent), + _type(type) { +}; + +TreeNodeScript::TreeNodeScript(const QString& filename, const QString& fullPath, ScriptOrigin origin) : + TreeNodeBase(NULL, TREE_NODE_TYPE_SCRIPT), _filename(filename), - _fullPath(fullPath) { + _fullPath(fullPath), + _origin(origin) +{ +}; + +TreeNodeFolder::TreeNodeFolder(const QString& foldername, TreeNodeFolder* parent) : + TreeNodeBase(parent, TREE_NODE_TYPE_FOLDER), + _foldername(foldername) { }; ScriptsModel::ScriptsModel(QObject* parent) : - QAbstractListModel(parent), + QAbstractItemModel(parent), _loadingScripts(false), _localDirectory(), _fsWatcher(), - _localFiles(), - _remoteFiles() + _treeNodes() { _localDirectory.setFilter(QDir::Files | QDir::Readable); @@ -57,23 +70,31 @@ ScriptsModel::ScriptsModel(QObject* parent) : reloadRemoteFiles(); } +QModelIndex ScriptsModel::index(int row, int column, const QModelIndex& parent) const { + return QModelIndex(); +} + +QModelIndex ScriptsModel::parent(const QModelIndex& child) const { + return QModelIndex(); +} + QVariant ScriptsModel::data(const QModelIndex& index, int role) const { - const QList* files = NULL; + /*const QList* files = NULL; int row = 0; bool isLocal = index.row() < _localFiles.size(); - if (isLocal) { - files = &_localFiles; - row = index.row(); - } else { - files = &_remoteFiles; - row = index.row() - _localFiles.size(); - } + if (isLocal) { + files = &_localFiles; + row = index.row(); + } else { + files = &_remoteFiles; + row = index.row() - _localFiles.size(); + } if (role == Qt::DisplayRole) { return QVariant((*files)[row]->getFilename() + (isLocal ? " (local)" : "")); } else if (role == ScriptPath) { return QVariant((*files)[row]->getFullPath()); - } + }*/ return QVariant(); } @@ -81,9 +102,14 @@ int ScriptsModel::rowCount(const QModelIndex& parent) const { if (parent.isValid()) { return 0; } - return _localFiles.length() + _remoteFiles.length(); + return 0;// _localFiles.length() + _remoteFiles.length(); } +int ScriptsModel::columnCount(const QModelIndex& parent) const { + return 1; +} + + void ScriptsModel::updateScriptsLocation(const QString& newPath) { _fsWatcher.removePath(_localDirectory.absolutePath()); @@ -93,7 +119,7 @@ void ScriptsModel::updateScriptsLocation(const QString& newPath) { if (!_localDirectory.absolutePath().isEmpty()) { _fsWatcher.addPath(_localDirectory.absolutePath()); } - } + } reloadLocalFiles(); } @@ -101,8 +127,12 @@ void ScriptsModel::updateScriptsLocation(const QString& newPath) { void ScriptsModel::reloadRemoteFiles() { if (!_loadingScripts) { _loadingScripts = true; - while (!_remoteFiles.isEmpty()) { - delete _remoteFiles.takeFirst(); + for (int i = _treeNodes.size() - 1; i >= 0; i--) { + TreeNodeBase* node = _treeNodes.at(i); + if (typeid(*node) == typeid(TreeNodeScript) && static_cast(node)->getOrigin() == SCRIPT_ORIGIN_REMOTE) { + delete node; + _treeNodes.removeAt(i); + } } requestRemoteFiles(); } @@ -121,7 +151,6 @@ void ScriptsModel::requestRemoteFiles(QString marker) { QNetworkRequest request(url); QNetworkReply* reply = networkAccessManager.get(request); connect(reply, SIGNAL(finished()), SLOT(downloadFinished())); - } void ScriptsModel::downloadFinished() { @@ -170,7 +199,7 @@ bool ScriptsModel::parseXML(QByteArray xmlFile) { xml.readNext(); lastKey = xml.text().toString(); if (jsRegex.exactMatch(xml.text().toString())) { - _remoteFiles.append(new ScriptItem(lastKey.mid(MODELS_LOCATION.length()), S3_URL + "/" + lastKey)); + _treeNodes.append(new TreeNodeScript(lastKey.mid(MODELS_LOCATION.length()), S3_URL + "/" + lastKey, SCRIPT_ORIGIN_REMOTE)); } } xml.readNext(); @@ -178,7 +207,7 @@ bool ScriptsModel::parseXML(QByteArray xmlFile) { } xml.readNext(); } - + rebuildTree(); endResetModel(); // Error handling @@ -198,8 +227,15 @@ bool ScriptsModel::parseXML(QByteArray xmlFile) { void ScriptsModel::reloadLocalFiles() { beginResetModel(); - while (!_localFiles.isEmpty()) { - delete _localFiles.takeFirst(); + for (int i = _treeNodes.size() - 1; i >= 0; i--) { + TreeNodeBase* node = _treeNodes.at(i); + qDebug() << "deleting local " << i << " " << typeid(*node).name(); + if (node->getType() == TREE_NODE_TYPE_SCRIPT && + static_cast(node)->getOrigin() == SCRIPT_ORIGIN_LOCAL) + { + delete node; + _treeNodes.removeAt(i); + } } _localDirectory.refresh(); @@ -207,8 +243,35 @@ void ScriptsModel::reloadLocalFiles() { const QFileInfoList localFiles = _localDirectory.entryInfoList(); for (int i = 0; i < localFiles.size(); i++) { QFileInfo file = localFiles[i]; - _localFiles.append(new ScriptItem(file.fileName(), file.absoluteFilePath())); + _treeNodes.append(new TreeNodeScript(file.fileName(), file.absoluteFilePath(), SCRIPT_ORIGIN_LOCAL)); } - + rebuildTree(); endResetModel(); } + +void ScriptsModel::rebuildTree() { + for (int i = _treeNodes.size() - 1; i >= 0; i--) { + + if (_treeNodes.at(i)->getType() == TREE_NODE_TYPE_FOLDER) { + delete _treeNodes.at(i); + _treeNodes.removeAt(i); + } + } + QHash folders; + for (int i = 0; i < _treeNodes.size(); i++) { + TreeNodeBase* node = _treeNodes.at(i); + qDebug() << "blup" << i << typeid(*node).name(); + if (typeid(*node) == typeid(TreeNodeScript)) { + TreeNodeScript* script = static_cast(node); + TreeNodeFolder* parent = NULL; + QString hash; + QStringList pathList = script->getFilename().split(tr("/")); + QStringList::const_iterator pathIterator; + for (pathIterator = pathList.constBegin(); pathIterator != pathList.constEnd(); ++pathIterator) { + hash.append("/" + *pathIterator); + qDebug() << hash; + } + } + } + folders.clear(); +} diff --git a/interface/src/ScriptsModel.h b/interface/src/ScriptsModel.h index ca72a8d8f4..bb4883e399 100644 --- a/interface/src/ScriptsModel.h +++ b/interface/src/ScriptsModel.h @@ -12,30 +12,67 @@ #ifndef hifi_ScriptsModel_h #define hifi_ScriptsModel_h -#include +#include #include #include #include -class ScriptItem { +class TreeNodeFolder; + +enum ScriptOrigin { + SCRIPT_ORIGIN_LOCAL, + SCRIPT_ORIGIN_REMOTE +}; + +enum TreeNodeType { + TREE_NODE_TYPE_SCRIPT, + TREE_NODE_TYPE_FOLDER +}; + +class TreeNodeBase { public: - ScriptItem(const QString& filename, const QString& fullPath); + const TreeNodeFolder* getParent() { return _parent; } + void setParent(TreeNodeFolder* parent) { _parent = parent; } + TreeNodeType getType() { return _type; } + +private: + TreeNodeFolder* _parent; + TreeNodeType _type; + +protected: + TreeNodeBase(TreeNodeFolder* parent, TreeNodeType type); +}; + +class TreeNodeScript : public TreeNodeBase { +public: + TreeNodeScript(const QString& filename, const QString& fullPath, ScriptOrigin origin); const QString& getFilename() { return _filename; }; const QString& getFullPath() { return _fullPath; }; + const ScriptOrigin getOrigin() { return _origin; }; private: QString _filename; QString _fullPath; + ScriptOrigin _origin; }; -class ScriptsModel : public QAbstractListModel { +class TreeNodeFolder : public TreeNodeBase { +public: + TreeNodeFolder(const QString& foldername, TreeNodeFolder* parent); +private: + QString _foldername; +}; + +class ScriptsModel : public QAbstractItemModel { Q_OBJECT public: ScriptsModel(QObject* parent = NULL); - + QModelIndex index(int row, int column, const QModelIndex& parent) const; + QModelIndex parent(const QModelIndex& child) const; virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; enum Role { ScriptPath = Qt::UserRole, @@ -50,13 +87,13 @@ protected slots: protected: void requestRemoteFiles(QString marker = QString()); bool parseXML(QByteArray xmlFile); + void rebuildTree(); private: bool _loadingScripts; QDir _localDirectory; QFileSystemWatcher _fsWatcher; - QList _localFiles; - QList _remoteFiles; + QList _treeNodes; }; #endif // hifi_ScriptsModel_h diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 57c0532777..f56c6e32af 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -50,10 +50,10 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : _proxyModel.setSourceModel(&_scriptsModel); _proxyModel.sort(0, Qt::AscendingOrder); _proxyModel.setDynamicSortFilter(true); - ui->scriptListView->setModel(&_proxyModel); + ui->scriptTreeView->setModel(&_proxyModel); connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &RunningScriptsWidget::updateFileFilter); - connect(ui->scriptListView, &QListView::doubleClicked, this, &RunningScriptsWidget::loadScriptFromList); + connect(ui->scriptTreeView, &QTreeView::doubleClicked, this, &RunningScriptsWidget::loadScriptFromList); connect(ui->reloadAllButton, &QPushButton::clicked, Application::getInstance(), &Application::reloadAllScripts); @@ -80,7 +80,7 @@ void RunningScriptsWidget::loadScriptFromList(const QModelIndex& index) { } void RunningScriptsWidget::loadSelectedScript() { - QModelIndex selectedIndex = ui->scriptListView->currentIndex(); + QModelIndex selectedIndex = ui->scriptTreeView->currentIndex(); if (selectedIndex.isValid()) { loadScriptFromList(selectedIndex); } @@ -166,7 +166,7 @@ void RunningScriptsWidget::showEvent(QShowEvent* event) { void RunningScriptsWidget::selectFirstInList() { if (_proxyModel.rowCount() > 0) { - ui->scriptListView->setCurrentIndex(_proxyModel.index(0, 0)); + ui->scriptTreeView->setCurrentIndex(_proxyModel.index(0, 0)); } } @@ -177,7 +177,7 @@ bool RunningScriptsWidget::eventFilter(QObject* sender, QEvent* event) { } QKeyEvent* keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) { - QModelIndex selectedIndex = ui->scriptListView->currentIndex(); + QModelIndex selectedIndex = ui->scriptTreeView->currentIndex(); if (selectedIndex.isValid()) { loadScriptFromList(selectedIndex); } diff --git a/interface/ui/runningScriptsWidget.ui b/interface/ui/runningScriptsWidget.ui index b70200e9f2..203db35d2d 100644 --- a/interface/ui/runningScriptsWidget.ui +++ b/interface/ui/runningScriptsWidget.ui @@ -245,8 +245,8 @@ font: bold 16px; 0 0 - 328 - 18 + 334 + 20 @@ -390,10 +390,27 @@ font: bold 16px;
+ + + + color: #0e7077; font: bold 14px; + + + Load script + + + + + + + from URL + + + - Load script + from Disk @@ -429,7 +446,7 @@ font: bold 16px;
- + 0 @@ -442,6 +459,12 @@ font: bold 16px; Qt::ScrollBarAlwaysOff + + true + + + true + From 1d6066c83700e95ef6b518079151188f0d77e2bf Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 10 Jan 2015 01:41:07 +0100 Subject: [PATCH 029/159] replaced GetVersionEx with new Version helpers to resolve deprecation warnings. --- interface/src/Audio.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index bd106d9bc6..7c2586b55c 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #endif #include @@ -179,12 +180,7 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { #ifdef WIN32 QString deviceName; //Check for Windows Vista or higher, IMMDeviceEnumerator doesn't work below that. - OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); - const DWORD VISTA_MAJOR_VERSION = 6; - if (osvi.dwMajorVersion < VISTA_MAJOR_VERSION) {// lower then vista + if (!IsWindowsVistaOrGreater()) { // lower then vista if (mode == QAudio::AudioInput) { WAVEINCAPS wic; // first use WAVE_MAPPER to get the default devices manufacturer ID @@ -223,9 +219,7 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { pPropertyStore->Release(); pPropertyStore = NULL; deviceName = QString::fromWCharArray((wchar_t*)pv.pwszVal); - const DWORD WINDOWS7_MAJOR_VERSION = 6; - const DWORD WINDOWS7_MINOR_VERSION = 1; - if (osvi.dwMajorVersion <= WINDOWS7_MAJOR_VERSION && osvi.dwMinorVersion <= WINDOWS7_MINOR_VERSION) { + if (!IsWindows8OrGreater()) { // Windows 7 provides only the 31 first characters of the device name. const DWORD QT_WIN7_MAX_AUDIO_DEVICENAME_LEN = 31; deviceName = deviceName.left(QT_WIN7_MAX_AUDIO_DEVICENAME_LEN); From e639c5a549ed90b10fec2e7277d0d3c04d5adf0c Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 11 Jan 2015 11:33:21 -0800 Subject: [PATCH 030/159] playing with the ambient lighting --- interface/src/Application.cpp | 3 ++- libraries/fbx/src/FBXReader.cpp | 11 +++++++++++ .../src/directional_light_cascaded_shadow_map.slf | 6 +++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ecce508acf..52704bc5b0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2658,7 +2658,8 @@ void Application::updateShadowMap() { glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } -const GLfloat WORLD_AMBIENT_COLOR[] = { 0.525f, 0.525f, 0.6f }; +//const GLfloat WORLD_AMBIENT_COLOR[] = { 0.525f, 0.525f, 0.6f }; +const GLfloat WORLD_AMBIENT_COLOR[] = { 0.2f, 0.2f, 0.3f }; const GLfloat WORLD_DIFFUSE_COLOR[] = { 0.6f, 0.525f, 0.525f }; const GLfloat WORLD_SPECULAR_COLOR[] = { 0.94f, 0.94f, 0.737f, 1.0f }; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 9532f44acf..d2bda2d747 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -753,6 +753,7 @@ public: float shininess; float opacity; QString id; + model::MaterialPointer _material; }; class Cluster { @@ -1715,6 +1716,14 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, #endif } material.id = getID(object.properties); + + material._material = model::MaterialPointer(new model::Material()); + material._material->setEmissive(material.emissive); + material._material->setDiffuse(material.diffuse); + material._material->setSpecular(material.specular); + material._material->setShininess(material.shininess); + material._material->setOpacity(material.opacity); + materials.insert(material.id, material); } else if (object.name == "NodeAttribute") { @@ -2138,6 +2147,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { if (extracted.partMaterialTextures.at(j).first == materialIndex) { FBXMeshPart& part = extracted.mesh.parts[j]; + + part._material = material._material; part.diffuseColor = material.diffuse; part.specularColor = material.specular; part.emissiveColor = material.emissive; diff --git a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf index e2a58de14b..08fdc3a908 100644 --- a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf +++ b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf @@ -83,7 +83,7 @@ void main(void) { float facingLight = step(0.0, diffuse) * shadowAttenuation; // compute the base color based on OpenGL lighting model - vec3 baseColor = diffuseVal.rgb * (gl_FrontLightModelProduct.sceneColor.rgb + + vec3 baseColor = diffuseVal.rgb * (/*gl_FrontLightModelProduct.sceneColor.rgb + */ gl_FrontLightProduct[0].ambient.rgb + gl_FrontLightProduct[0].diffuse.rgb * (diffuse * facingLight)); // compute the specular multiplier (sans exponent) @@ -93,5 +93,9 @@ void main(void) { // add specular contribution vec4 specularColor = specularVal; gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normalVal.a); + + if (gl_FragCoord.x > 1024) { + gl_FragColor = vec4( (gl_FrontLightProduct[0].ambient.rgb + gl_FrontLightProduct[0].diffuse.rgb * (diffuse * facingLight)), normalVal.a); + } } } From 968a34f9669103e372b407a3f163ade1e33b1ead Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 11 Jan 2015 11:44:16 -0800 Subject: [PATCH 031/159] Add instructions for building with SDL2 --- interface/external/sdl2/readme.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 interface/external/sdl2/readme.txt diff --git a/interface/external/sdl2/readme.txt b/interface/external/sdl2/readme.txt new file mode 100644 index 0000000000..9f3bd40e15 --- /dev/null +++ b/interface/external/sdl2/readme.txt @@ -0,0 +1,13 @@ + +Instructions for adding the SDL library (SDL2) to Interface +David Rowe, 11 Jan 2015 + +You can download the SDL development library from https://www.libsdl.org/. Interface has been tested with version 2.0.3. + +1. Copy the include and lib folders into the interface/externals/sdl2 folder. + This readme.txt should be there as well. + + You may optionally choose to copy the SDK folders to a location outside the repository (so you can re-use with different checkouts and different projects). + If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder 'sdl2' that contains the two folders mentioned above. + +2. Clear your build directory, run cmake and build, and you should be all set. From 8feb51013ba266fec4b80e10b4dcfded6ff84845 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Mon, 12 Jan 2015 00:41:38 +0100 Subject: [PATCH 032/159] running script window treeview fully works --- interface/src/ScriptsModel.cpp | 106 ++++++++++++++-------- interface/src/ScriptsModel.h | 23 ++--- interface/src/ScriptsModelFilter.cpp | 44 +++++++++ interface/src/ScriptsModelFilter.h | 27 ++++++ interface/src/ui/RunningScriptsWidget.cpp | 20 ++-- interface/src/ui/RunningScriptsWidget.h | 3 +- 6 files changed, 161 insertions(+), 62 deletions(-) create mode 100644 interface/src/ScriptsModelFilter.cpp create mode 100644 interface/src/ScriptsModelFilter.h diff --git a/interface/src/ScriptsModel.cpp b/interface/src/ScriptsModel.cpp index d178397fc2..0c711cd940 100644 --- a/interface/src/ScriptsModel.cpp +++ b/interface/src/ScriptsModel.cpp @@ -11,7 +11,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include #include #include #include @@ -32,22 +31,21 @@ static const QString IS_TRUNCATED_NAME = "IsTruncated"; static const QString CONTAINER_NAME = "Contents"; static const QString KEY_NAME = "Key"; -TreeNodeBase::TreeNodeBase(TreeNodeFolder* parent, TreeNodeType type) : +TreeNodeBase::TreeNodeBase(TreeNodeFolder* parent, const QString& name, TreeNodeType type) : _parent(parent), + _name(name), _type(type) { }; -TreeNodeScript::TreeNodeScript(const QString& filename, const QString& fullPath, ScriptOrigin origin) : - TreeNodeBase(NULL, TREE_NODE_TYPE_SCRIPT), - _filename(filename), +TreeNodeScript::TreeNodeScript(const QString& localPath, const QString& fullPath, ScriptOrigin origin) : + TreeNodeBase(NULL, localPath.split("/").last(), TREE_NODE_TYPE_SCRIPT), + _localPath(localPath), _fullPath(fullPath), - _origin(origin) -{ + _origin(origin) { }; TreeNodeFolder::TreeNodeFolder(const QString& foldername, TreeNodeFolder* parent) : - TreeNodeBase(parent, TREE_NODE_TYPE_FOLDER), - _foldername(foldername) { + TreeNodeBase(parent, foldername, TREE_NODE_TYPE_FOLDER) { }; ScriptsModel::ScriptsModel(QObject* parent) : @@ -57,7 +55,6 @@ ScriptsModel::ScriptsModel(QObject* parent) : _fsWatcher(), _treeNodes() { - _localDirectory.setFilter(QDir::Files | QDir::Readable); _localDirectory.setNameFilters(QStringList("*.js")); @@ -70,46 +67,56 @@ ScriptsModel::ScriptsModel(QObject* parent) : reloadRemoteFiles(); } +TreeNodeBase* ScriptsModel::getTreeNodeFromIndex(const QModelIndex& index) const { + if (index.isValid()) { + return static_cast(index.internalPointer()); + } + return NULL; +} + QModelIndex ScriptsModel::index(int row, int column, const QModelIndex& parent) const { - return QModelIndex(); + if (row < 0 || column < 0) { + return QModelIndex(); + } + return createIndex(row, column, getFolderNodes(static_cast(getTreeNodeFromIndex(parent))).at(row)); } QModelIndex ScriptsModel::parent(const QModelIndex& child) const { - return QModelIndex(); + TreeNodeFolder* parent = (static_cast(child.internalPointer()))->getParent(); + if (!parent) { + return QModelIndex(); + } + TreeNodeFolder* grandParent = parent->getParent(); + int row = getFolderNodes(grandParent).indexOf(parent); + return createIndex(row, 0, parent); } QVariant ScriptsModel::data(const QModelIndex& index, int role) const { - /*const QList* files = NULL; - int row = 0; - bool isLocal = index.row() < _localFiles.size(); - if (isLocal) { - files = &_localFiles; - row = index.row(); - } else { - files = &_remoteFiles; - row = index.row() - _localFiles.size(); + TreeNodeBase* node = getTreeNodeFromIndex(index); + if (node->getType() == TREE_NODE_TYPE_SCRIPT) { + TreeNodeScript* script = static_cast(node); + if (role == Qt::DisplayRole) { + return QVariant(script->getName() + (script->getOrigin() == SCRIPT_ORIGIN_LOCAL ? " (local)" : "")); + } else if (role == ScriptPath) { + return QVariant(script->getFullPath()); + } + } else if (node->getType() == TREE_NODE_TYPE_FOLDER) { + TreeNodeFolder* folder = static_cast(node); + if (role == Qt::DisplayRole) { + return QVariant(folder->getName()); + } } - - if (role == Qt::DisplayRole) { - return QVariant((*files)[row]->getFilename() + (isLocal ? " (local)" : "")); - } else if (role == ScriptPath) { - return QVariant((*files)[row]->getFullPath()); - }*/ return QVariant(); } int ScriptsModel::rowCount(const QModelIndex& parent) const { - if (parent.isValid()) { - return 0; - } - return 0;// _localFiles.length() + _remoteFiles.length(); + return getFolderNodes(static_cast(getTreeNodeFromIndex(parent))).count(); } int ScriptsModel::columnCount(const QModelIndex& parent) const { return 1; } - void ScriptsModel::updateScriptsLocation(const QString& newPath) { _fsWatcher.removePath(_localDirectory.absolutePath()); @@ -129,7 +136,9 @@ void ScriptsModel::reloadRemoteFiles() { _loadingScripts = true; for (int i = _treeNodes.size() - 1; i >= 0; i--) { TreeNodeBase* node = _treeNodes.at(i); - if (typeid(*node) == typeid(TreeNodeScript) && static_cast(node)->getOrigin() == SCRIPT_ORIGIN_REMOTE) { + if (node->getType() == TREE_NODE_TYPE_SCRIPT && + static_cast(node)->getOrigin() == SCRIPT_ORIGIN_REMOTE) + { delete node; _treeNodes.removeAt(i); } @@ -229,7 +238,6 @@ void ScriptsModel::reloadLocalFiles() { for (int i = _treeNodes.size() - 1; i >= 0; i--) { TreeNodeBase* node = _treeNodes.at(i); - qDebug() << "deleting local " << i << " " << typeid(*node).name(); if (node->getType() == TREE_NODE_TYPE_SCRIPT && static_cast(node)->getOrigin() == SCRIPT_ORIGIN_LOCAL) { @@ -251,7 +259,6 @@ void ScriptsModel::reloadLocalFiles() { void ScriptsModel::rebuildTree() { for (int i = _treeNodes.size() - 1; i >= 0; i--) { - if (_treeNodes.at(i)->getType() == TREE_NODE_TYPE_FOLDER) { delete _treeNodes.at(i); _treeNodes.removeAt(i); @@ -260,18 +267,37 @@ void ScriptsModel::rebuildTree() { QHash folders; for (int i = 0; i < _treeNodes.size(); i++) { TreeNodeBase* node = _treeNodes.at(i); - qDebug() << "blup" << i << typeid(*node).name(); - if (typeid(*node) == typeid(TreeNodeScript)) { + if (node->getType() == TREE_NODE_TYPE_SCRIPT) { TreeNodeScript* script = static_cast(node); TreeNodeFolder* parent = NULL; QString hash; - QStringList pathList = script->getFilename().split(tr("/")); + QStringList pathList = script->getLocalPath().split(tr("/")); + pathList.removeLast(); QStringList::const_iterator pathIterator; for (pathIterator = pathList.constBegin(); pathIterator != pathList.constEnd(); ++pathIterator) { - hash.append("/" + *pathIterator); - qDebug() << hash; + hash.append(*pathIterator + "/"); + if (!folders.contains(hash)) { + folders[hash] = new TreeNodeFolder(*pathIterator, parent); + } + parent = folders[hash]; } + script->setParent(parent); } } + QHash::const_iterator folderIterator; + for (folderIterator = folders.constBegin(); folderIterator != folders.constEnd(); ++folderIterator) { + _treeNodes.append(*folderIterator); + } folders.clear(); } + +QList ScriptsModel::getFolderNodes(TreeNodeFolder* parent) const { + QList result; + for (int i = 0; i < _treeNodes.size(); i++) { + TreeNodeBase* node = _treeNodes.at(i); + if (node->getParent() == parent) { + result.append(node); + } + } + return result; +} diff --git a/interface/src/ScriptsModel.h b/interface/src/ScriptsModel.h index bb4883e399..549f87c0d7 100644 --- a/interface/src/ScriptsModel.h +++ b/interface/src/ScriptsModel.h @@ -31,28 +31,29 @@ enum TreeNodeType { class TreeNodeBase { public: - const TreeNodeFolder* getParent() { return _parent; } + TreeNodeFolder* getParent() const { return _parent; } void setParent(TreeNodeFolder* parent) { _parent = parent; } TreeNodeType getType() { return _type; } + const QString& getName() { return _name; }; private: TreeNodeFolder* _parent; TreeNodeType _type; protected: - TreeNodeBase(TreeNodeFolder* parent, TreeNodeType type); + QString _name; + TreeNodeBase(TreeNodeFolder* parent, const QString& name, TreeNodeType type); }; class TreeNodeScript : public TreeNodeBase { public: - TreeNodeScript(const QString& filename, const QString& fullPath, ScriptOrigin origin); - - const QString& getFilename() { return _filename; }; + TreeNodeScript(const QString& localPath, const QString& fullPath, ScriptOrigin origin); + const QString& getLocalPath() { return _localPath; } const QString& getFullPath() { return _fullPath; }; const ScriptOrigin getOrigin() { return _origin; }; private: - QString _filename; + QString _localPath; QString _fullPath; ScriptOrigin _origin; }; @@ -60,8 +61,6 @@ private: class TreeNodeFolder : public TreeNodeBase { public: TreeNodeFolder(const QString& foldername, TreeNodeFolder* parent); -private: - QString _foldername; }; class ScriptsModel : public QAbstractItemModel { @@ -70,9 +69,11 @@ public: ScriptsModel(QObject* parent = NULL); QModelIndex index(int row, int column, const QModelIndex& parent) const; QModelIndex parent(const QModelIndex& child) const; - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; - virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; + int rowCount(const QModelIndex& parent = QModelIndex()) const; + int columnCount(const QModelIndex& parent = QModelIndex()) const; + TreeNodeBase* getTreeNodeFromIndex(const QModelIndex& index) const; + QList getFolderNodes(TreeNodeFolder* parent) const; enum Role { ScriptPath = Qt::UserRole, diff --git a/interface/src/ScriptsModelFilter.cpp b/interface/src/ScriptsModelFilter.cpp new file mode 100644 index 0000000000..1879e547c0 --- /dev/null +++ b/interface/src/ScriptsModelFilter.cpp @@ -0,0 +1,44 @@ +// +// ScriptsModelFilter.cpp +// interface/src +// +// Created by Thijs Wenker on 01/11/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 "ScriptsModelFilter.h" + +ScriptsModelFilter::ScriptsModelFilter(QObject *parent) : + QSortFilterProxyModel(parent) { +} + +bool ScriptsModelFilter::lessThan(const QModelIndex& left, const QModelIndex& right) const { + ScriptsModel* scriptsModel = static_cast(sourceModel()); + TreeNodeBase* leftNode = scriptsModel->getTreeNodeFromIndex(left); + TreeNodeBase* rightNode = scriptsModel->getTreeNodeFromIndex(right); + if (leftNode->getType() != rightNode->getType()) { + return leftNode->getType() == TREE_NODE_TYPE_FOLDER; + } + return leftNode->getName() < rightNode->getName(); +} + +bool ScriptsModelFilter::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { + if (!filterRegExp().isEmpty()) { + ScriptsModel* scriptsModel = static_cast(sourceModel()); + TreeNodeBase* node = scriptsModel->getFolderNodes( + static_cast(scriptsModel->getTreeNodeFromIndex(sourceParent))).at(sourceRow); + QModelIndex sourceIndex = sourceModel()->index(sourceRow, this->filterKeyColumn(), sourceParent); + if (node->getType() == TREE_NODE_TYPE_FOLDER) { + int rows = scriptsModel->rowCount(sourceIndex); + for (int i = 0; i < rows; i++) { + if (filterAcceptsRow(i, sourceIndex)) { + return true; + } + } + } + } + return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); +} diff --git a/interface/src/ScriptsModelFilter.h b/interface/src/ScriptsModelFilter.h new file mode 100644 index 0000000000..7b7cdd974e --- /dev/null +++ b/interface/src/ScriptsModelFilter.h @@ -0,0 +1,27 @@ +// +// ScriptsModelFilter.h +// interface/src +// +// Created by Thijs Wenker on 01/11/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_ScriptsModelFilter_h +#define hifi_ScriptsModelFilter_h + +#include "ScriptsModel.h" +#include + +class ScriptsModelFilter : public QSortFilterProxyModel { + Q_OBJECT +public: + ScriptsModelFilter(QObject *parent = NULL); +protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const; + bool lessThan(const QModelIndex& left, const QModelIndex& right) const; +}; + +#endif // hifi_ScriptsModelFilter_h diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index f56c6e32af..d577859ebf 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -33,7 +33,7 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : Qt::WindowCloseButtonHint), ui(new Ui::RunningScriptsWidget), _signalMapper(this), - _proxyModel(this), + _scriptsModelFilter(this), _scriptsModel(this) { ui->setupUi(this); @@ -41,16 +41,16 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : ui->filterLineEdit->installEventFilter(this); - connect(&_proxyModel, &QSortFilterProxyModel::modelReset, + connect(&_scriptsModelFilter, &QSortFilterProxyModel::modelReset, this, &RunningScriptsWidget::selectFirstInList); QString shortcutText = Menu::getInstance()->getActionForOption(MenuOption::ReloadAllScripts)->shortcut().toString(QKeySequence::NativeText); ui->tipLabel->setText("Tip: Use " + shortcutText + " to reload all scripts."); - _proxyModel.setSourceModel(&_scriptsModel); - _proxyModel.sort(0, Qt::AscendingOrder); - _proxyModel.setDynamicSortFilter(true); - ui->scriptTreeView->setModel(&_proxyModel); + _scriptsModelFilter.setSourceModel(&_scriptsModel); + _scriptsModelFilter.sort(0, Qt::AscendingOrder); + _scriptsModelFilter.setDynamicSortFilter(true); + ui->scriptTreeView->setModel(&_scriptsModelFilter); connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &RunningScriptsWidget::updateFileFilter); connect(ui->scriptTreeView, &QTreeView::doubleClicked, this, &RunningScriptsWidget::loadScriptFromList); @@ -70,12 +70,12 @@ RunningScriptsWidget::~RunningScriptsWidget() { void RunningScriptsWidget::updateFileFilter(const QString& filter) { QRegExp regex("^.*" + QRegExp::escape(filter) + ".*$", Qt::CaseInsensitive); - _proxyModel.setFilterRegExp(regex); + _scriptsModelFilter.setFilterRegExp(regex); selectFirstInList(); } void RunningScriptsWidget::loadScriptFromList(const QModelIndex& index) { - QVariant scriptFile = _proxyModel.data(index, ScriptsModel::ScriptPath); + QVariant scriptFile = _scriptsModelFilter.data(index, ScriptsModel::ScriptPath); Application::getInstance()->loadScript(scriptFile.toString()); } @@ -165,8 +165,8 @@ void RunningScriptsWidget::showEvent(QShowEvent* event) { } void RunningScriptsWidget::selectFirstInList() { - if (_proxyModel.rowCount() > 0) { - ui->scriptTreeView->setCurrentIndex(_proxyModel.index(0, 0)); + if (_scriptsModelFilter.rowCount() > 0) { + ui->scriptTreeView->setCurrentIndex(_scriptsModelFilter.index(0, 0)); } } diff --git a/interface/src/ui/RunningScriptsWidget.h b/interface/src/ui/RunningScriptsWidget.h index 69833a890b..3ec5590dee 100644 --- a/interface/src/ui/RunningScriptsWidget.h +++ b/interface/src/ui/RunningScriptsWidget.h @@ -18,6 +18,7 @@ #include #include "ScriptsModel.h" +#include "ScriptsModelFilter.h" #include "ScriptsTableWidget.h" namespace Ui { @@ -54,7 +55,7 @@ private slots: private: Ui::RunningScriptsWidget* ui; QSignalMapper _signalMapper; - QSortFilterProxyModel _proxyModel; + ScriptsModelFilter _scriptsModelFilter; ScriptsModel _scriptsModel; ScriptsTableWidget* _recentlyLoadedScriptsTable; QStringList _recentlyLoadedScripts; From e4fd027d15426ac01bf82b4467231a03daf765bf Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Mon, 12 Jan 2015 00:49:41 +0100 Subject: [PATCH 033/159] "load script from URL" button in Running scripts window --- interface/src/ui/RunningScriptsWidget.cpp | 4 +++- interface/ui/runningScriptsWidget.ui | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index d577859ebf..46c8f90ff6 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -59,8 +59,10 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : Application::getInstance(), &Application::reloadAllScripts); connect(ui->stopAllButton, &QPushButton::clicked, this, &RunningScriptsWidget::allScriptsStopped); - connect(ui->loadScriptButton, &QPushButton::clicked, + connect(ui->loadScriptFromDiskButton, &QPushButton::clicked, Application::getInstance(), &Application::loadDialog); + connect(ui->loadScriptFromURLButton, &QPushButton::clicked, + Application::getInstance(), &Application::loadScriptURLDialog); connect(&_signalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&))); } diff --git a/interface/ui/runningScriptsWidget.ui b/interface/ui/runningScriptsWidget.ui index 203db35d2d..ea53e72e15 100644 --- a/interface/ui/runningScriptsWidget.ui +++ b/interface/ui/runningScriptsWidget.ui @@ -401,14 +401,14 @@ font: bold 16px; - + from URL - + from Disk @@ -463,7 +463,7 @@ font: bold 16px; true - true + false From 5cdc76ad35569d584412a0e2a35e13ae3e61c36b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Sun, 11 Jan 2015 22:48:42 -0800 Subject: [PATCH 034/159] Put cache max size/count as class members --- libraries/networking/src/ResourceCache.cpp | 14 +++++--------- libraries/networking/src/ResourceCache.h | 6 +++--- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 4b769c9a28..962e256e02 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -73,22 +73,18 @@ QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& } void ResourceCache::addUnusedResource(const QSharedPointer& resource) { - static const int BYTES_PER_MEGABYTES = 1024 * 1024; - const int RETAINED_RESOURCE_COUNT = 50; - const int RETAINED_RESOURCE_SIZE = 100 * BYTES_PER_MEGABYTES; - - while (_unusedResourcesTotalBytes + resource->getBytesTotal() > RETAINED_RESOURCE_SIZE && + while (_unusedResourcesSize + resource->getBytesTotal() > _unusedResourcesMaxSize && !_unusedResources.empty()) { // unload the oldest resource QMap >::iterator it = _unusedResources.begin(); - _unusedResourcesTotalBytes -= it.value()->getBytesTotal(); + _unusedResourcesSize -= it.value()->getBytesTotal(); it.value()->setCache(NULL); _unusedResources.erase(it); } - if (_unusedResources.size() > RETAINED_RESOURCE_COUNT) { + if (_unusedResources.size() > _unusedResourcesMaxCount) { // unload the oldest resource QMap >::iterator it = _unusedResources.begin(); it.value()->setCache(NULL); @@ -96,13 +92,13 @@ void ResourceCache::addUnusedResource(const QSharedPointer& resource) } resource->setLRUKey(++_lastLRUKey); _unusedResources.insert(resource->getLRUKey(), resource); - _unusedResourcesTotalBytes += resource->getBytesTotal(); + _unusedResourcesSize += resource->getBytesTotal(); } void ResourceCache::removeUnusedResource(const QSharedPointer& resource) { if (_unusedResources.contains(resource->getLRUKey())) { _unusedResources.remove(resource->getLRUKey()); - _unusedResourcesTotalBytes -= resource->getBytesTotal(); + _unusedResourcesSize -= resource->getBytesTotal(); } } diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 0a4121ca5e..ca1a8a04d9 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -45,8 +45,9 @@ public: void refresh(const QUrl& url); protected: - - qint64 _unusedResourcesTotalBytes = 0; + int _unusedResourcesMaxCount = 50; + qint64 _unusedResourcesMaxSize = 100 * 1024 * 1024; + qint64 _unusedResourcesSize = 0; QMap > _unusedResources; /// Loads a resource from the specified URL. @@ -67,7 +68,6 @@ protected: static void requestCompleted(Resource* resource); private: - friend class Resource; QHash > _resources; From bf71aa6163af4b411d28f0a54991976f4205d025 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 12 Jan 2015 09:15:14 -0800 Subject: [PATCH 035/159] Remove Visage dependency from cmaklists --- interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 77a20201cb..8ddd1153ef 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -2,7 +2,7 @@ set(TARGET_NAME interface) project(${TARGET_NAME}) # set a default root dir for each of our optional externals if it was not passed -set(OPTIONAL_EXTERNALS "Faceshift" "LibOVR" "PrioVR" "Sixense" "LeapMotion" "RtMidi" "Qxmpp" "SDL2" "Gverb" "Visage") +set(OPTIONAL_EXTERNALS "Faceshift" "LibOVR" "PrioVR" "Sixense" "LeapMotion" "RtMidi" "Qxmpp" "SDL2" "Gverb") foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE) if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR) From 17925c7a810159536cbfde189ec9f2a057cb89bc Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 12 Jan 2015 11:06:05 -0800 Subject: [PATCH 036/159] Use more appropriate QNetworkReply error code This error code is available now that Interface is built with Qt 5.3. --- libraries/script-engine/src/XMLHttpRequestClass.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libraries/script-engine/src/XMLHttpRequestClass.cpp b/libraries/script-engine/src/XMLHttpRequestClass.cpp index a756b3fe8f..92c9c1856c 100644 --- a/libraries/script-engine/src/XMLHttpRequestClass.cpp +++ b/libraries/script-engine/src/XMLHttpRequestClass.cpp @@ -66,7 +66,7 @@ QScriptValue XMLHttpRequestClass::getStatus() const { return QScriptValue(200); case QNetworkReply::ContentNotFoundError: return QScriptValue(404); - case QNetworkReply::ContentAccessDenied: + case QNetworkReply::ContentConflictError: return QScriptValue(409); case QNetworkReply::TimeoutError: return QScriptValue(408); @@ -89,7 +89,7 @@ QString XMLHttpRequestClass::getStatusText() const { return "OK"; case QNetworkReply::ContentNotFoundError: return "Not Found"; - case QNetworkReply::ContentAccessDenied: + case QNetworkReply::ContentConflictError: return "Conflict"; case QNetworkReply::TimeoutError: return "Timeout"; @@ -196,8 +196,7 @@ void XMLHttpRequestClass::open(const QString& method, const QString& url, bool a } else if (!_file->open(QIODevice::ReadOnly)) { qDebug() << "Can't open file " << _url.fileName(); abortRequest(); - //_errorCode = QNetworkReply::ContentConflictError; // TODO: Use this status when update to Qt 5.3 - _errorCode = QNetworkReply::ContentAccessDenied; + _errorCode = QNetworkReply::ContentConflictError; setReadyState(DONE); emit requestComplete(); } else { From 98dd401ea363fa333cc696a4e8df6cb5e513fa76 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 11:12:19 -0800 Subject: [PATCH 037/159] Remove duplicate definition --- interface/src/ModelUploader.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index 89b6a4c9c0..7e9d857306 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -55,7 +55,6 @@ static const QString MODEL_URL = "/api/v1/models"; static const QString SETTING_NAME = "LastModelUploadLocation"; -static const long long BYTES_PER_MEGABYTES = 1024 * 1024; 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; From 08317b51daaae2b3470b0357894e2e7709126636 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 11:12:50 -0800 Subject: [PATCH 038/159] Use removeUnusedResources --- libraries/render-utils/src/TextureCache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index df860338ab..0f34282162 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -203,7 +203,7 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, TextureType type texture->setCache(this); _dilatableNetworkTextures.insert(url, texture); } else { - _unusedResources.remove(texture->getLRUKey()); + removeUnusedResource(texture); } return texture; } From cb3f07e6f53758ef4b2c0263ce86ef9fe0d2c7e3 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 11:18:55 -0800 Subject: [PATCH 039/159] Remove unusedResourcesMaxCount --- libraries/networking/src/ResourceCache.cpp | 7 ------- libraries/networking/src/ResourceCache.h | 6 ++++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 962e256e02..1b3d4cc232 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -83,13 +83,6 @@ void ResourceCache::addUnusedResource(const QSharedPointer& resource) _unusedResources.erase(it); } - - if (_unusedResources.size() > _unusedResourcesMaxCount) { - // unload the oldest resource - QMap >::iterator it = _unusedResources.begin(); - it.value()->setCache(NULL); - _unusedResources.erase(it); - } resource->setLRUKey(++_lastLRUKey); _unusedResources.insert(resource->getLRUKey(), resource); _unusedResourcesSize += resource->getBytesTotal(); diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index ca1a8a04d9..90d228fb07 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -27,6 +27,9 @@ class QTimer; class Resource; +static constexpr qint64 BYTES_PER_MEGABYTES = 1024 * 1024; +static constexpr qint64 DEFAULT_MAX_SIZE = 100 * BYTES_PER_MEGABYTES; + /// Base class for resource caches. class ResourceCache : public QObject { Q_OBJECT @@ -45,8 +48,7 @@ public: void refresh(const QUrl& url); protected: - int _unusedResourcesMaxCount = 50; - qint64 _unusedResourcesMaxSize = 100 * 1024 * 1024; + qint64 _unusedResourcesMaxSize = DEFAULT_MAX_SIZE; qint64 _unusedResourcesSize = 0; QMap > _unusedResources; From ea0ffd01256b22468e9e46d1afe2fcfd81ab8dcb Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 11:37:00 -0800 Subject: [PATCH 040/159] Introduce reserveUnusedResource --- libraries/networking/src/ResourceCache.cpp | 25 +++++++++++++++------- libraries/networking/src/ResourceCache.h | 1 + 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 1b3d4cc232..e2fef26b22 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -73,15 +73,12 @@ QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& } void ResourceCache::addUnusedResource(const QSharedPointer& resource) { - while (_unusedResourcesSize + resource->getBytesTotal() > _unusedResourcesMaxSize && - !_unusedResources.empty()) { - // unload the oldest resource - QMap >::iterator it = _unusedResources.begin(); - - _unusedResourcesSize -= it.value()->getBytesTotal(); - it.value()->setCache(NULL); - _unusedResources.erase(it); + if (resource->getBytesTotal() > _unusedResourcesMaxSize) { + // If it doesn't fit anyway, let's leave whatever is already in the cache. + resource->setCache(nullptr); + return; } + reserveUnusedResource(resource->getBytesTotal()); resource->setLRUKey(++_lastLRUKey); _unusedResources.insert(resource->getLRUKey(), resource); @@ -95,6 +92,18 @@ void ResourceCache::removeUnusedResource(const QSharedPointer& resourc } } +void ResourceCache::reserveUnusedResource(qint64 resourceSize) { + while (!_unusedResources.empty() && + _unusedResourcesSize + resourceSize > _unusedResourcesMaxSize) { + // unload the oldest resource + QMap >::iterator it = _unusedResources.begin(); + + _unusedResourcesSize -= it.value()->getBytesTotal(); + it.value()->setCache(NULL); + _unusedResources.erase(it); + } +} + void ResourceCache::attemptRequest(Resource* resource) { if (_requestLimit <= 0) { // wait until a slot becomes available diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 90d228fb07..6ae8b22445 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -65,6 +65,7 @@ protected: void addUnusedResource(const QSharedPointer& resource); void removeUnusedResource(const QSharedPointer& resource); + void reserveUnusedResource(qint64 resourceSize); static void attemptRequest(Resource* resource); static void requestCompleted(Resource* resource); From bad96e0ba40e4be3b158b16b917a07949c315da5 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 11:37:42 -0800 Subject: [PATCH 041/159] cache size getter/setter --- libraries/networking/src/ResourceCache.cpp | 5 +++++ libraries/networking/src/ResourceCache.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index e2fef26b22..63f4a658d1 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -72,6 +72,11 @@ QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& return resource; } +void ResourceCache::setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize) { + _unusedResourcesMaxSize = unusedResourcesMaxSize; + reserveUnusedResource(0); +} + void ResourceCache::addUnusedResource(const QSharedPointer& resource) { if (resource->getBytesTotal() > _unusedResourcesMaxSize) { // If it doesn't fit anyway, let's leave whatever is already in the cache. diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 6ae8b22445..b2bb8b5a39 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -37,6 +37,9 @@ class ResourceCache : public QObject { public: static void setRequestLimit(int limit) { _requestLimit = limit; } static int getRequestLimit() { return _requestLimit; } + + void setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize); + qint64 getUnusedResourceCacheSize() const { return _unusedResourcesMaxSize; } static const QList& getLoadingRequests() { return _loadingRequests; } From 81bf1e4f53a47f8ab490c574c3c20e509fd47d11 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 11:46:38 -0800 Subject: [PATCH 042/159] Some code maintainance --- libraries/networking/src/ResourceCache.cpp | 25 +++++++++------------- libraries/networking/src/ResourceCache.h | 21 +++++++++--------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 63f4a658d1..089cdc5607 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -21,10 +21,7 @@ #include "ResourceCache.h" ResourceCache::ResourceCache(QObject* parent) : - QObject(parent), - _lastLRUKey(0) -{ - + QObject(parent) { } ResourceCache::~ResourceCache() { @@ -32,7 +29,7 @@ ResourceCache::~ResourceCache() { // list on destruction, so keep clearing until there are no references left while (!_unusedResources.isEmpty()) { foreach (const QSharedPointer& resource, _unusedResources) { - resource->setCache(NULL); + resource->setCache(nullptr); } _unusedResources.clear(); } @@ -104,7 +101,7 @@ void ResourceCache::reserveUnusedResource(qint64 resourceSize) { QMap >::iterator it = _unusedResources.begin(); _unusedResourcesSize -= it.value()->getBytesTotal(); - it.value()->setCache(NULL); + it.value()->setCache(nullptr); _unusedResources.erase(it); } } @@ -153,9 +150,7 @@ QList ResourceCache::_loadingRequests; Resource::Resource(const QUrl& url, bool delayLoad) : _url(url), - _request(url), - _lruKey(0), - _reply(NULL) { + _request(url) { init(); @@ -216,13 +211,13 @@ float Resource::getLoadPriority() { } void Resource::refresh() { - if (_reply == NULL && !(_loaded || _failedToLoad)) { + if (_reply == nullptr && !(_loaded || _failedToLoad)) { return; } if (_reply) { ResourceCache::requestCompleted(this); delete _reply; - _reply = NULL; + _reply = nullptr; } init(); _request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork); @@ -298,10 +293,10 @@ void Resource::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { } _reply->disconnect(this); QNetworkReply* reply = _reply; - _reply = NULL; + _reply = nullptr; _replyTimer->disconnect(this); _replyTimer->deleteLater(); - _replyTimer = NULL; + _replyTimer = nullptr; ResourceCache::requestCompleted(this); downloadFinished(reply); @@ -333,10 +328,10 @@ void Resource::makeRequest() { void Resource::handleReplyError(QNetworkReply::NetworkError error, QDebug debug) { _reply->disconnect(this); _reply->deleteLater(); - _reply = NULL; + _reply = nullptr; _replyTimer->disconnect(this); _replyTimer->deleteLater(); - _replyTimer = NULL; + _replyTimer = nullptr; ResourceCache::requestCompleted(this); // retry for certain types of failures diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index b2bb8b5a39..8b5f1abc75 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -77,7 +77,7 @@ private: friend class Resource; QHash > _resources; - int _lastLRUKey; + int _lastLRUKey = 0; static int _requestLimit; static QList > _pendingRequests; @@ -158,9 +158,9 @@ protected: QUrl _url; QNetworkRequest _request; - bool _startedLoading; - bool _failedToLoad; - bool _loaded; + bool _startedLoading = false; + bool _failedToLoad = false; + bool _loaded = false; QHash, float> _loadPriorities; QWeakPointer _self; QPointer _cache; @@ -182,13 +182,12 @@ private: friend class ResourceCache; - int _lruKey; - QNetworkReply* _reply; - QTimer* _replyTimer; - int _index; - qint64 _bytesReceived; - qint64 _bytesTotal; - int _attempts; + int _lruKey = 0; + QNetworkReply* _reply = nullptr; + QTimer* _replyTimer = nullptr; + qint64 _bytesReceived = 0; + qint64 _bytesTotal = 0; + int _attempts = 0; }; uint qHash(const QPointer& value, uint seed = 0); From bece05a994cc7cc27894690e96a26fd16c15c5bf Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 12 Jan 2015 11:49:31 -0800 Subject: [PATCH 043/159] entity prop defaults move to their own header --- libraries/entities/src/EntityItem.cpp | 58 ++++++++++--------- libraries/entities/src/EntityItem.h | 35 ++--------- .../entities/src/EntityItemProperties.cpp | 36 ++++++------ .../src/EntityItemPropertiesDefaults.h | 51 ++++++++++++++++ 4 files changed, 106 insertions(+), 74 deletions(-) create mode 100644 libraries/entities/src/EntityItemPropertiesDefaults.h diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 4bf394314b..70fdb86929 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -35,25 +35,25 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) { _created = UNKNOWN_CREATED_TIME; _changedOnServer = 0; - _position = glm::vec3(0,0,0); - _dimensions = DEFAULT_DIMENSIONS; - _rotation = DEFAULT_ROTATION; - _glowLevel = DEFAULT_GLOW_LEVEL; - _localRenderAlpha = DEFAULT_LOCAL_RENDER_ALPHA; - _mass = DEFAULT_MASS; - _velocity = DEFAULT_VELOCITY; - _gravity = DEFAULT_GRAVITY; - _damping = DEFAULT_DAMPING; - _lifetime = DEFAULT_LIFETIME; - _script = DEFAULT_SCRIPT; - _registrationPoint = DEFAULT_REGISTRATION_POINT; - _angularVelocity = DEFAULT_ANGULAR_VELOCITY; - _angularDamping = DEFAULT_ANGULAR_DAMPING; - _visible = DEFAULT_VISIBLE; - _ignoreForCollisions = DEFAULT_IGNORE_FOR_COLLISIONS; - _collisionsWillMove = DEFAULT_COLLISIONS_WILL_MOVE; - _locked = DEFAULT_LOCKED; - _userData = DEFAULT_USER_DATA; + _position = ENTITY_ITEM_ZERO_VEC3; + _dimensions = ENTITY_ITEM_DEFAULT_DIMENSIONS; + _rotation = ENTITY_ITEM_DEFAULT_ROTATION; + _glowLevel = ENTITY_ITEM_DEFAULT_GLOW_LEVEL; + _localRenderAlpha = ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA; + _mass = ENTITY_ITEM_DEFAULT_MASS; + _velocity = ENTITY_ITEM_DEFAULT_VELOCITY; + _gravity = ENTITY_ITEM_DEFAULT_GRAVITY; + _damping = ENTITY_ITEM_DEFAULT_DAMPING; + _lifetime = ENTITY_ITEM_DEFAULT_LIFETIME; + _script = ENTITY_ITEM_DEFAULT_SCRIPT; + _registrationPoint = ENTITY_ITEM_DEFAULT_REGISTRATION_POINT; + _angularVelocity = ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY; + _angularDamping = ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING; + _visible = ENTITY_ITEM_DEFAULT_VISIBLE; + _ignoreForCollisions = ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS; + _collisionsWillMove = ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE; + _locked = ENTITY_ITEM_DEFAULT_LOCKED; + _userData = ENTITY_ITEM_DEFAULT_USER_DATA; recalculateCollisionShape(); } @@ -555,6 +555,8 @@ void EntityItem::adjustEditPacketForClockSkew(unsigned char* editPacketBuffer, s } } +const float ENTITY_ITEM_EPSILON_VELOCITY_LENGTH = 0.001f / (float)TREE_SCALE; + // TODO: we probably want to change this to make "down" be the direction of the entity's gravity vector // for now, this is always true DOWN even if entity has non-down gravity. // TODO: the old code had "&& _velocity.y >= -EPSILON && _velocity.y <= EPSILON" --- what was I thinking? @@ -562,7 +564,7 @@ bool EntityItem::isRestingOnSurface() const { glm::vec3 downwardVelocity = glm::vec3(0.0f, _velocity.y, 0.0f); return _position.y <= getDistanceToBottomOfEntity() - && (glm::length(downwardVelocity) <= EPSILON_VELOCITY_LENGTH) + && (glm::length(downwardVelocity) <= ENTITY_ITEM_EPSILON_VELOCITY_LENGTH) && _gravity.y < 0.0f; } @@ -639,7 +641,7 @@ void EntityItem::simulate(const quint64& now) { const float EPSILON_ANGULAR_VELOCITY_LENGTH = 0.1f; // if (angularSpeed < EPSILON_ANGULAR_VELOCITY_LENGTH) { - setAngularVelocity(NO_ANGULAR_VELOCITY); + setAngularVelocity(ENTITY_ITEM_ZERO_VEC3); } else { // NOTE: angularSpeed is currently in degrees/sec!!! // TODO: Andrew to convert to radians/sec @@ -668,7 +670,7 @@ void EntityItem::simulate(const quint64& now) { qDebug() << " damping:" << _damping; qDebug() << " velocity AFTER dampingResistance:" << velocity; qDebug() << " glm::length(velocity):" << glm::length(velocity); - qDebug() << " EPSILON_VELOCITY_LENGTH:" << EPSILON_VELOCITY_LENGTH; + qDebug() << " velocityEspilon :" << ENTITY_ITEM_EPSILON_VELOCITY_LENGTH; } } @@ -696,7 +698,7 @@ void EntityItem::simulate(const quint64& now) { #ifndef USE_BULLET_PHYSICS // if we've slowed considerably, then just stop moving, but only if no BULLET - if (glm::length(velocity) <= EPSILON_VELOCITY_LENGTH) { + if (glm::length(velocity) <= ENTITY_ITEM_EPSILON_VELOCITY_LENGTH) { velocity = NO_VELOCITY; } #endif // !USE_BULLET_PHYSICS @@ -720,7 +722,7 @@ void EntityItem::simulate(const quint64& now) { // When Bullet is available we assume that it will tell us when velocities go to zero... #else // !USE_BULLET_PHYSICS // ... otherwise we help things come to rest by clamping small velocities. - if (glm::length(velocity) <= EPSILON_VELOCITY_LENGTH) { + if (glm::length(velocity) <= ENTITY_ITEM_EPSILON_VELOCITY_LENGTH) { velocity = NO_VELOCITY; } #endif // USE_BULLET_PHYSICS @@ -909,8 +911,8 @@ AACube EntityItem::getMinimumAACube() const { // _position represents the position of the registration point. glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; - glm::vec3 unrotatedMinRelativeToEntity = glm::vec3(0.0f, 0.0f, 0.0f) - (_dimensions * _registrationPoint); glm::vec3 unrotatedMaxRelativeToEntity = _dimensions * registrationRemainder; + glm::vec3 unrotatedMinRelativeToEntity = - unrotatedMaxRelativeToEntity; Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation()); @@ -934,8 +936,8 @@ AABox EntityItem::getAABox() const { // _position represents the position of the registration point. glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; - glm::vec3 unrotatedMinRelativeToEntity = glm::vec3(0.0f, 0.0f, 0.0f) - (_dimensions * _registrationPoint); glm::vec3 unrotatedMaxRelativeToEntity = _dimensions * registrationRemainder; + glm::vec3 unrotatedMinRelativeToEntity = - unrotatedMaxRelativeToEntity; Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation()); @@ -1055,7 +1057,7 @@ void EntityItem::updateMass(float value) { void EntityItem::updateVelocity(const glm::vec3& value) { if (glm::distance(_velocity, value) * (float)TREE_SCALE > MIN_VELOCITY_DELTA) { if (glm::length(value) * (float)TREE_SCALE < MIN_VELOCITY_DELTA) { - _velocity = glm::vec3(0.0f); + _velocity = ENTITY_ITEM_ZERO_VEC3; } else { _velocity = value; } @@ -1067,7 +1069,7 @@ void EntityItem::updateVelocityInMeters(const glm::vec3& value) { glm::vec3 velocity = value / (float) TREE_SCALE; if (glm::distance(_velocity, velocity) * (float)TREE_SCALE > MIN_VELOCITY_DELTA) { if (glm::length(value) < MIN_VELOCITY_DELTA) { - _velocity = glm::vec3(0.0f); + _velocity = ENTITY_ITEM_ZERO_VEC3; } else { _velocity = velocity; } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 1b8afa930b..b84739e07e 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -26,6 +26,7 @@ #include "EntityItemID.h" #include "EntityItemProperties.h" +#include "EntityItemPropertiesDefaults.h" #include "EntityTypes.h" class EntityTree; @@ -35,30 +36,6 @@ class EntityTreeElementExtraEncodeData; #define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0; #define ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() { }; -const glm::vec3 DEFAULT_DIMENSIONS = glm::vec3(0.1f) / (float)TREE_SCALE; -const glm::quat DEFAULT_ROTATION; -const float DEFAULT_GLOW_LEVEL = 0.0f; -const float DEFAULT_LOCAL_RENDER_ALPHA = 1.0f; -const float DEFAULT_MASS = 1.0f; -const glm::vec3 NO_VELOCITY= glm::vec3(0.0f); -const glm::vec3 DEFAULT_VELOCITY = NO_VELOCITY; -const float EPSILON_VELOCITY_LENGTH = 0.001f / (float)TREE_SCALE; -const glm::vec3 NO_GRAVITY = glm::vec3(0.0f); -const glm::vec3 DEFAULT_GRAVITY = NO_GRAVITY; -const glm::vec3 REGULAR_GRAVITY = glm::vec3(0, -9.8f / (float)TREE_SCALE, 0); -const float DEFAULT_DAMPING = 0.39347f; // approx timescale = 2.0 sec (see damping timescale formula in header) -const float IMMORTAL = -1.0f; /// special lifetime which means the entity lives for ever. default lifetime -const float DEFAULT_LIFETIME = IMMORTAL; -const QString DEFAULT_SCRIPT = QString(""); -const glm::vec3 DEFAULT_REGISTRATION_POINT = glm::vec3(0.5f, 0.5f, 0.5f); // center -const glm::vec3 NO_ANGULAR_VELOCITY = glm::vec3(0.0f); -const glm::vec3 DEFAULT_ANGULAR_VELOCITY = NO_ANGULAR_VELOCITY; -const float DEFAULT_ANGULAR_DAMPING = 0.39347f; // approx timescale = 2.0 sec (see damping timescale formula in header) -const bool DEFAULT_VISIBLE = true; -const bool DEFAULT_IGNORE_FOR_COLLISIONS = false; -const bool DEFAULT_COLLISIONS_WILL_MOVE = false; -const bool DEFAULT_LOCKED = false; -const QString DEFAULT_USER_DATA = QString(""); /// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available /// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate @@ -201,13 +178,13 @@ public: glm::vec3 getVelocityInMeters() const { return _velocity * (float) TREE_SCALE; } /// get velocity in meters void setVelocity(const glm::vec3& value) { _velocity = value; } /// velocity in domain scale units (0.0-1.0) per second void setVelocityInMeters(const glm::vec3& value) { _velocity = value / (float) TREE_SCALE; } /// velocity in meters - bool hasVelocity() const { return _velocity != NO_VELOCITY; } + bool hasVelocity() const { return _velocity != ENTITY_ITEM_ZERO_VEC3; } const glm::vec3& getGravity() const { return _gravity; } /// gravity in domain scale units (0.0-1.0) per second squared glm::vec3 getGravityInMeters() const { return _gravity * (float) TREE_SCALE; } /// get gravity in meters void setGravity(const glm::vec3& value) { _gravity = value; } /// gravity in domain scale units (0.0-1.0) per second squared void setGravityInMeters(const glm::vec3& value) { _gravity = value / (float) TREE_SCALE; } /// gravity in meters - bool hasGravity() const { return _gravity != NO_GRAVITY; } + bool hasGravity() const { return _gravity != ENTITY_ITEM_ZERO_VEC3; } // TODO: this should eventually be updated to support resting on collisions with other surfaces bool isRestingOnSurface() const; @@ -220,10 +197,10 @@ public: void setLifetime(float value) { _lifetime = value; } /// set the lifetime in seconds for the entity /// is this entity immortal, in that it has no lifetime set, and will exist until manually deleted - bool isImmortal() const { return _lifetime == IMMORTAL; } + bool isImmortal() const { return _lifetime == ENTITY_ITEM_IMMORTAL_LIFETIME; } /// is this entity mortal, in that it has a lifetime set, and will automatically be deleted when that lifetime expires - bool isMortal() const { return _lifetime != IMMORTAL; } + bool isMortal() const { return _lifetime != ENTITY_ITEM_IMMORTAL_LIFETIME; } /// age of this entity in seconds float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; } @@ -247,7 +224,7 @@ public: const glm::vec3& getAngularVelocity() const { return _angularVelocity; } void setAngularVelocity(const glm::vec3& value) { _angularVelocity = value; } - bool hasAngularVelocity() const { return _angularVelocity != NO_ANGULAR_VELOCITY; } + bool hasAngularVelocity() const { return _angularVelocity != ENTITY_ITEM_ZERO_VEC3; } float getAngularDamping() const { return _angularDamping; } void setAngularDamping(float value) { _angularDamping = value; } diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index be6fe01841..d50096f752 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -19,32 +19,34 @@ #include "EntityItem.h" #include "EntityItemProperties.h" +#include "EntityItemPropertiesDefaults.h" #include "ModelEntityItem.h" #include "TextEntityItem.h" + EntityItemProperties::EntityItemProperties() : - CONSTRUCT_PROPERTY(visible, DEFAULT_VISIBLE), + CONSTRUCT_PROPERTY(visible, ENTITY_ITEM_DEFAULT_VISIBLE), CONSTRUCT_PROPERTY(position, 0), - CONSTRUCT_PROPERTY(dimensions, DEFAULT_DIMENSIONS), - CONSTRUCT_PROPERTY(rotation, DEFAULT_ROTATION), - CONSTRUCT_PROPERTY(mass, DEFAULT_MASS), - CONSTRUCT_PROPERTY(velocity, DEFAULT_VELOCITY), - CONSTRUCT_PROPERTY(gravity, DEFAULT_GRAVITY), - CONSTRUCT_PROPERTY(damping, DEFAULT_DAMPING), - CONSTRUCT_PROPERTY(lifetime, DEFAULT_LIFETIME), - CONSTRUCT_PROPERTY(script, DEFAULT_SCRIPT), + CONSTRUCT_PROPERTY(dimensions, ENTITY_ITEM_DEFAULT_DIMENSIONS), + CONSTRUCT_PROPERTY(rotation, ENTITY_ITEM_DEFAULT_ROTATION), + CONSTRUCT_PROPERTY(mass, ENTITY_ITEM_DEFAULT_MASS), + CONSTRUCT_PROPERTY(velocity, ENTITY_ITEM_DEFAULT_VELOCITY), + CONSTRUCT_PROPERTY(gravity, ENTITY_ITEM_DEFAULT_GRAVITY), + CONSTRUCT_PROPERTY(damping, ENTITY_ITEM_DEFAULT_DAMPING), + CONSTRUCT_PROPERTY(lifetime, ENTITY_ITEM_DEFAULT_LIFETIME), + CONSTRUCT_PROPERTY(script, ENTITY_ITEM_DEFAULT_SCRIPT), CONSTRUCT_PROPERTY(color, ), CONSTRUCT_PROPERTY(modelURL, ""), CONSTRUCT_PROPERTY(animationURL, ""), CONSTRUCT_PROPERTY(animationFPS, ModelEntityItem::DEFAULT_ANIMATION_FPS), CONSTRUCT_PROPERTY(animationFrameIndex, ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX), CONSTRUCT_PROPERTY(animationIsPlaying, ModelEntityItem::DEFAULT_ANIMATION_IS_PLAYING), - CONSTRUCT_PROPERTY(registrationPoint, DEFAULT_REGISTRATION_POINT), - CONSTRUCT_PROPERTY(angularVelocity, DEFAULT_ANGULAR_VELOCITY), - CONSTRUCT_PROPERTY(angularDamping, DEFAULT_ANGULAR_DAMPING), - CONSTRUCT_PROPERTY(ignoreForCollisions, DEFAULT_IGNORE_FOR_COLLISIONS), - CONSTRUCT_PROPERTY(collisionsWillMove, DEFAULT_COLLISIONS_WILL_MOVE), + CONSTRUCT_PROPERTY(registrationPoint, ENTITY_ITEM_DEFAULT_REGISTRATION_POINT), + CONSTRUCT_PROPERTY(angularVelocity, ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY), + CONSTRUCT_PROPERTY(angularDamping, ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING), + CONSTRUCT_PROPERTY(ignoreForCollisions, ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS), + CONSTRUCT_PROPERTY(collisionsWillMove, ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE), CONSTRUCT_PROPERTY(isSpotlight, false), CONSTRUCT_PROPERTY(diffuseColor, ), CONSTRUCT_PROPERTY(ambientColor, ), @@ -54,10 +56,10 @@ EntityItemProperties::EntityItemProperties() : CONSTRUCT_PROPERTY(quadraticAttenuation, 0.0f), CONSTRUCT_PROPERTY(exponent, 0.0f), CONSTRUCT_PROPERTY(cutoff, PI), - CONSTRUCT_PROPERTY(locked, false), + CONSTRUCT_PROPERTY(locked, ENTITY_ITEM_DEFAULT_LOCKED), CONSTRUCT_PROPERTY(textures, ""), CONSTRUCT_PROPERTY(animationSettings, ""), - CONSTRUCT_PROPERTY(userData, DEFAULT_USER_DATA), + CONSTRUCT_PROPERTY(userData, ENTITY_ITEM_DEFAULT_USER_DATA), CONSTRUCT_PROPERTY(text, TextEntityItem::DEFAULT_TEXT), CONSTRUCT_PROPERTY(lineHeight, TextEntityItem::DEFAULT_LINE_HEIGHT), CONSTRUCT_PROPERTY(textColor, TextEntityItem::DEFAULT_TEXT_COLOR), @@ -858,8 +860,8 @@ AABox EntityItemProperties::getAABoxInMeters() const { // _position represents the position of the registration point. glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; - glm::vec3 unrotatedMinRelativeToEntity = glm::vec3(0.0f, 0.0f, 0.0f) - (_dimensions * _registrationPoint); glm::vec3 unrotatedMaxRelativeToEntity = _dimensions * registrationRemainder; + glm::vec3 unrotatedMinRelativeToEntity = - unrotatedMaxRelativeToEntity; Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation()); diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h new file mode 100644 index 0000000000..285788c960 --- /dev/null +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -0,0 +1,51 @@ +// +// EntityItemPropertiesDefaults.h +// libraries/entities/src +// +// Created by Andrew Meadows on 2015.01.12 +// 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_EntityItemPropertiesDefaults_h +#define hifi_EntityItemPropertiesDefaults_h + +#include + +#include + +// There is a minor performance gain when comparing/copying an existing glm::vec3 rather than +// creating a new one on the stack so we declare the ZERO_VEC3 constant as an optimization. +const glm::vec3 ENTITY_ITEM_ZERO_VEC3(0.0f); + +const glm::vec3 REGULAR_GRAVITY = glm::vec3(0, -9.8f / (float)TREE_SCALE, 0); + +const bool ENTITY_ITEM_DEFAULT_LOCKED = false; +const QString ENTITY_ITEM_DEFAULT_USER_DATA = QString(""); + +const float ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA = 1.0f; +const float ENTITY_ITEM_DEFAULT_GLOW_LEVEL = 0.0f; +const bool ENTITY_ITEM_DEFAULT_VISIBLE = true; + +const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString(""); +const glm::vec3 ENTITY_ITEM_DEFAULT_REGISTRATION_POINT = glm::vec3(0.5f, 0.5f, 0.5f); // center + +const float ENTITY_ITEM_IMMORTAL_LIFETIME = -1.0f; /// special lifetime which means the entity lives for ever +const float ENTITY_ITEM_DEFAULT_LIFETIME = ENTITY_ITEM_IMMORTAL_LIFETIME; + +const glm::quat ENTITY_ITEM_DEFAULT_ROTATION; +const glm::vec3 ENTITY_ITEM_DEFAULT_DIMENSIONS = glm::vec3(0.1f) / (float)TREE_SCALE; +const float ENTITY_ITEM_DEFAULT_MASS = 1.0f; + +const glm::vec3 ENTITY_ITEM_DEFAULT_VELOCITY = ENTITY_ITEM_ZERO_VEC3; +const glm::vec3 ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY = ENTITY_ITEM_ZERO_VEC3; +const glm::vec3 ENTITY_ITEM_DEFAULT_GRAVITY = ENTITY_ITEM_ZERO_VEC3; +const float ENTITY_ITEM_DEFAULT_DAMPING = 0.39347f; // approx timescale = 2.0 sec (see damping timescale formula in header) +const float ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING = 0.39347f; // approx timescale = 2.0 sec (see damping timescale formula in header) + +const bool ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS = false; +const bool ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE = false; + +#endif // hifi_EntityItemPropertiesDefaults_h From 022760be1d3869b24ed5be250b348064b72a5b35 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 12 Jan 2015 11:52:51 -0800 Subject: [PATCH 044/159] Remove menu item for Show Voxel Nodes which is no longer available And change Show Entity Nodes shortcut from Ctrl-Shift-2 to Ctrl-Shift-1. --- interface/src/Menu.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index c50c722d4a..e4508ba042 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -354,11 +354,8 @@ Menu::Menu() : QMenu* nodeBordersMenu = viewMenu->addMenu("Server Borders"); NodeBounds& nodeBounds = appInstance->getNodeBoundsDisplay(); - addCheckableActionToQMenuAndActionHash(nodeBordersMenu, MenuOption::ShowBordersVoxelNodes, - Qt::CTRL | Qt::SHIFT | Qt::Key_1, false, - &nodeBounds, SLOT(setShowVoxelNodes(bool))); addCheckableActionToQMenuAndActionHash(nodeBordersMenu, MenuOption::ShowBordersEntityNodes, - Qt::CTRL | Qt::SHIFT | Qt::Key_2, false, + Qt::CTRL | Qt::SHIFT | Qt::Key_1, false, &nodeBounds, SLOT(setShowEntityNodes(bool))); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::OffAxisProjection, 0, false); From 1562aab6daad021a7ab7d30b681265d0b532cd07 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 12 Jan 2015 12:35:17 -0800 Subject: [PATCH 045/159] intitial pass at lock file --- libraries/octree/src/OctreePersistThread.cpp | 44 +++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index d9ebea0c2b..49372d1141 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include #include #include @@ -55,6 +57,21 @@ bool OctreePersistThread::process() { _tree->lockForWrite(); { PerformanceWarning warn(true, "Loading Octree File", true); + + // First check to make sure "lock" file doesn't exist. If it does exist, then + // our last save crashed during the save, and we want to load our most recent backup. + QString lockFileName = _filename + ".lock"; + std::ifstream lockFile(qPrintable(lockFileName), std::ios::in|std::ios::binary|std::ios::ate); + if(lockFile.is_open()) { + qDebug() << "WARNING: Octree lock file detected at startup:" << lockFileName + << "-- Attempting to restore from previous backup file."; + + lockFile.close(); + qDebug() << "Loading Octree... lock file closed:" << lockFileName; + remove(qPrintable(lockFileName)); + qDebug() << "Loading Octree... lock file removed:" << lockFileName; + } + persistantFileRead = _tree->readFromSVOFile(_filename.toLocal8Bit().constData()); _tree->pruneTree(); } @@ -142,11 +159,28 @@ void OctreePersistThread::persist() { backup(); // handle backup if requested - qDebug() << "saving Octree to file " << _filename << "..."; - _tree->writeToSVOFile(qPrintable(_filename)); - time(&_lastPersistTime); - _tree->clearDirtyBit(); // tree is clean after saving - qDebug() << "DONE saving Octree to file..."; + + // create our "lock" file to indicate we're saving. + QString lockFileName = _filename + ".lock"; + std::ofstream lockFile(qPrintable(lockFileName), std::ios::out|std::ios::binary); + if(lockFile.is_open()) { + qDebug() << "saving Octree lock file created at:" << lockFileName; + + qDebug() << "saving Octree to file " << _filename << "..."; + + _tree->writeToSVOFile(qPrintable(_filename)); + time(&_lastPersistTime); + _tree->clearDirtyBit(); // tree is clean after saving + qDebug() << "DONE saving Octree to file..."; + + // force crash + //assert(false); + + lockFile.close(); + qDebug() << "saving Octree lock file closed:" << lockFileName; + remove(qPrintable(lockFileName)); + qDebug() << "saving Octree lock file removed:" << lockFileName; + } } } From e70e435dcca6e7ad21656e90af083da9b60609d8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 12:45:13 -0800 Subject: [PATCH 046/159] Added Min/Max values for cache size --- libraries/networking/src/ResourceCache.cpp | 1 + libraries/networking/src/ResourceCache.h | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 089cdc5607..1187b311fc 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -166,6 +166,7 @@ Resource::~Resource() { if (_reply) { ResourceCache::requestCompleted(this); delete _reply; + _reply = nullptr; } } diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 8b5f1abc75..0c2b6d2ce8 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -28,7 +28,10 @@ class QTimer; class Resource; static constexpr qint64 BYTES_PER_MEGABYTES = 1024 * 1024; -static constexpr qint64 DEFAULT_MAX_SIZE = 100 * BYTES_PER_MEGABYTES; +static constexpr qint64 BYTES_PER_GIGABYTES = 1024 * BYTES_PER_MEGABYTES; +static constexpr qint64 DEFAULT_UNUSED_MAX_SIZE = 100 * BYTES_PER_MEGABYTES; +static constexpr qint64 MIN_UNUSED_MAX_SIZE = 0; +static constexpr qint64 MAX_UNUSED_MAX_SIZE = 10 * BYTES_PER_GIGABYTES; /// Base class for resource caches. class ResourceCache : public QObject { @@ -51,7 +54,7 @@ public: void refresh(const QUrl& url); protected: - qint64 _unusedResourcesMaxSize = DEFAULT_MAX_SIZE; + qint64 _unusedResourcesMaxSize = DEFAULT_UNUSED_MAX_SIZE; qint64 _unusedResourcesSize = 0; QMap > _unusedResources; From 5be5dc716f50de4f264405603e34c41721045b3f Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 12:45:50 -0800 Subject: [PATCH 047/159] Make sure every widget has diolog has a parent --- interface/src/ui/LodToolsDialog.cpp | 26 ++++++++++---------------- interface/src/ui/LodToolsDialog.h | 7 +++---- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/interface/src/ui/LodToolsDialog.cpp b/interface/src/ui/LodToolsDialog.cpp index d9f2d788cd..8ff9eadc51 100644 --- a/interface/src/ui/LodToolsDialog.cpp +++ b/interface/src/ui/LodToolsDialog.cpp @@ -30,9 +30,9 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : this->setWindowTitle("LOD Tools"); // Create layouter - QFormLayout* form = new QFormLayout(); + QFormLayout* form = new QFormLayout(this); - _lodSize = new QSlider(Qt::Horizontal); + _lodSize = new QSlider(Qt::Horizontal, this); const int MAX_LOD_SIZE = MAX_LOD_SIZE_MULTIPLIER; const int MIN_LOD_SIZE = 0; const int STEP_LOD_SIZE = 1; @@ -50,7 +50,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : form->addRow("LOD Size Scale:", _lodSize); connect(_lodSize,SIGNAL(valueChanged(int)),this,SLOT(sizeScaleValueChanged(int))); - _boundaryLevelAdjust = new QSlider(Qt::Horizontal); + _boundaryLevelAdjust = new QSlider(Qt::Horizontal, this); const int MAX_ADJUST = 10; const int MIN_ADJUST = 0; const int STEP_ADJUST = 1; @@ -66,7 +66,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : connect(_boundaryLevelAdjust,SIGNAL(valueChanged(int)),this,SLOT(boundaryLevelValueChanged(int))); // Create a label with feedback... - _feedback = new QLabel(); + _feedback = new QLabel(this); QPalette palette = _feedback->palette(); const unsigned redish = 0xfff00000; palette.setColor(QPalette::WindowText, QColor::fromRgb(redish)); @@ -76,21 +76,21 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : _feedback->setFixedWidth(FEEDBACK_WIDTH); form->addRow("You can see... ", _feedback); - form->addRow("Automatic Avatar LOD Adjustment:", _automaticAvatarLOD = new QCheckBox()); + form->addRow("Automatic Avatar LOD Adjustment:", _automaticAvatarLOD = new QCheckBox(this)); _automaticAvatarLOD->setChecked(Menu::getInstance()->getAutomaticAvatarLOD()); connect(_automaticAvatarLOD, SIGNAL(toggled(bool)), SLOT(updateAvatarLODControls())); - form->addRow("Decrease Avatar LOD Below FPS:", _avatarLODDecreaseFPS = new QDoubleSpinBox()); + form->addRow("Decrease Avatar LOD Below FPS:", _avatarLODDecreaseFPS = new QDoubleSpinBox(this)); _avatarLODDecreaseFPS->setValue(Menu::getInstance()->getAvatarLODDecreaseFPS()); _avatarLODDecreaseFPS->setDecimals(0); connect(_avatarLODDecreaseFPS, SIGNAL(valueChanged(double)), SLOT(updateAvatarLODValues())); - form->addRow("Increase Avatar LOD Above FPS:", _avatarLODIncreaseFPS = new QDoubleSpinBox()); + form->addRow("Increase Avatar LOD Above FPS:", _avatarLODIncreaseFPS = new QDoubleSpinBox(this)); _avatarLODIncreaseFPS->setValue(Menu::getInstance()->getAvatarLODIncreaseFPS()); _avatarLODIncreaseFPS->setDecimals(0); connect(_avatarLODIncreaseFPS, SIGNAL(valueChanged(double)), SLOT(updateAvatarLODValues())); - form->addRow("Avatar LOD:", _avatarLOD = new QDoubleSpinBox()); + form->addRow("Avatar LOD:", _avatarLOD = new QDoubleSpinBox(this)); _avatarLOD->setDecimals(3); _avatarLOD->setRange(1.0 / MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER, 1.0 / MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER); _avatarLOD->setSingleStep(0.001); @@ -98,21 +98,15 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : connect(_avatarLOD, SIGNAL(valueChanged(double)), SLOT(updateAvatarLODValues())); // Add a button to reset - QPushButton* resetButton = new QPushButton("Reset"); + QPushButton* resetButton = new QPushButton("Reset", this); form->addRow("", resetButton); - connect(resetButton,SIGNAL(clicked(bool)),this,SLOT(resetClicked(bool))); + connect(resetButton, SIGNAL(clicked(bool)), this, SLOT(resetClicked(bool))); this->QDialog::setLayout(form); updateAvatarLODControls(); } -LodToolsDialog::~LodToolsDialog() { - delete _feedback; - delete _lodSize; - delete _boundaryLevelAdjust; -} - void LodToolsDialog::reloadSliders() { _lodSize->setValue(Menu::getInstance()->getOctreeSizeScale() / TREE_SCALE); _boundaryLevelAdjust->setValue(Menu::getInstance()->getBoundaryLevelAdjust()); diff --git a/interface/src/ui/LodToolsDialog.h b/interface/src/ui/LodToolsDialog.h index 5b34a5efd0..772027790c 100644 --- a/interface/src/ui/LodToolsDialog.h +++ b/interface/src/ui/LodToolsDialog.h @@ -13,18 +13,17 @@ #define hifi_LodToolsDialog_h #include -#include -#include class QCheckBox; class QDoubleSpinBox; +class QLabel; +class QSlider; class LodToolsDialog : public QDialog { Q_OBJECT public: // Sets up the UI LodToolsDialog(QWidget* parent); - ~LodToolsDialog(); signals: void closed(); @@ -41,7 +40,7 @@ public slots: protected: // Emits a 'closed' signal when this dialog is closed. - void closeEvent(QCloseEvent*); + void closeEvent(QCloseEvent* event); private: QSlider* _lodSize; From 38dc1643ef9ed139c9a0418286eec905dd6dbd64 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 12:46:11 -0800 Subject: [PATCH 048/159] New Caches size dialog --- interface/src/ui/CachesSizeDialog.cpp | 83 +++++++++++++++++++++++++++ interface/src/ui/CachesSizeDialog.h | 45 +++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 interface/src/ui/CachesSizeDialog.cpp create mode 100644 interface/src/ui/CachesSizeDialog.h diff --git a/interface/src/ui/CachesSizeDialog.cpp b/interface/src/ui/CachesSizeDialog.cpp new file mode 100644 index 0000000000..9e5d1fd9e0 --- /dev/null +++ b/interface/src/ui/CachesSizeDialog.cpp @@ -0,0 +1,83 @@ +// +// CachesSizeDialog.cpp +// +// +// Created by Clement on 1/12/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 +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "CachesSizeDialog.h" + + +QDoubleSpinBox* createDoubleSpinBox(QWidget* parent) { + QDoubleSpinBox* box = new QDoubleSpinBox(parent); + box->setDecimals(0); + box->setRange(MIN_UNUSED_MAX_SIZE / BYTES_PER_MEGABYTES, MAX_UNUSED_MAX_SIZE / BYTES_PER_MEGABYTES); + + return box; +} + +CachesSizeDialog::CachesSizeDialog(QWidget* parent) : + QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint) +{ + setWindowTitle("Caches Size"); + + // Create layouter + QFormLayout* form = new QFormLayout(this); + setLayout(form); + + form->addRow("Animations cache size (MB):", _animations = createDoubleSpinBox(this)); + form->addRow("Geometries cache size (MB):", _geometries = createDoubleSpinBox(this)); + form->addRow("Scripts cache size (MB):", _scripts = createDoubleSpinBox(this)); + form->addRow("Sounds cache size (MB):", _sounds = createDoubleSpinBox(this)); + form->addRow("Textures cache size (MB):", _textures = createDoubleSpinBox(this)); + + resetClicked(true); + + // Add a button to reset + QPushButton* confirmButton = new QPushButton("Confirm", this); + QPushButton* resetButton = new QPushButton("Reset", this); + form->addRow(confirmButton, resetButton); + connect(confirmButton, SIGNAL(clicked(bool)), this, SLOT(confirmClicked(bool))); + connect(resetButton, SIGNAL(clicked(bool)), this, SLOT(resetClicked(bool))); +} + +void CachesSizeDialog::confirmClicked(bool checked) { + DependencyManager::get()->setUnusedResourceCacheSize(_animations->value() * BYTES_PER_MEGABYTES); + DependencyManager::get()->setUnusedResourceCacheSize(_geometries->value() * BYTES_PER_MEGABYTES); + DependencyManager::get()->setUnusedResourceCacheSize(_scripts->value() * BYTES_PER_MEGABYTES); + DependencyManager::get()->setUnusedResourceCacheSize(_sounds->value() * BYTES_PER_MEGABYTES); + DependencyManager::get()->setUnusedResourceCacheSize(_textures->value() * BYTES_PER_MEGABYTES); +} + +void CachesSizeDialog::resetClicked(bool checked) { + _animations->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); + _geometries->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); + _scripts->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); + _sounds->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); + _textures->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); +} + +void CachesSizeDialog::reject() { + // Just regularly close upon ESC + this->QDialog::close(); +} + +void CachesSizeDialog::closeEvent(QCloseEvent* event) { + this->QDialog::closeEvent(event); + emit closed(); +} \ No newline at end of file diff --git a/interface/src/ui/CachesSizeDialog.h b/interface/src/ui/CachesSizeDialog.h new file mode 100644 index 0000000000..fa01ce4534 --- /dev/null +++ b/interface/src/ui/CachesSizeDialog.h @@ -0,0 +1,45 @@ +// +// CachesSizeDialog.h +// +// +// Created by Clement on 1/12/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_CachesSizeDialog_h +#define hifi_CachesSizeDialog_h + +#include + +class QDoubleSpinBox; + +class CachesSizeDialog : public QDialog { + Q_OBJECT +public: + // Sets up the UI + CachesSizeDialog(QWidget* parent); + +signals: + void closed(); + +public slots: + void reject(); + void confirmClicked(bool checked); + void resetClicked(bool checked); + +protected: + // Emits a 'closed' signal when this dialog is closed. + void closeEvent(QCloseEvent* event); + +private: + QDoubleSpinBox* _animations = nullptr; + QDoubleSpinBox* _geometries = nullptr; + QDoubleSpinBox* _scripts = nullptr; + QDoubleSpinBox* _sounds = nullptr; + QDoubleSpinBox* _textures = nullptr; +}; + +#endif // hifi_CachesSizeDialog_h \ No newline at end of file From 19f321c171ce1d8cd679b8df2c850d2cab265321 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 13:56:41 -0800 Subject: [PATCH 049/159] Fixed caches not in DM --- interface/src/ui/CachesSizeDialog.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/CachesSizeDialog.cpp b/interface/src/ui/CachesSizeDialog.cpp index 9e5d1fd9e0..12e88f5100 100644 --- a/interface/src/ui/CachesSizeDialog.cpp +++ b/interface/src/ui/CachesSizeDialog.cpp @@ -59,16 +59,16 @@ CachesSizeDialog::CachesSizeDialog(QWidget* parent) : void CachesSizeDialog::confirmClicked(bool checked) { DependencyManager::get()->setUnusedResourceCacheSize(_animations->value() * BYTES_PER_MEGABYTES); DependencyManager::get()->setUnusedResourceCacheSize(_geometries->value() * BYTES_PER_MEGABYTES); - DependencyManager::get()->setUnusedResourceCacheSize(_scripts->value() * BYTES_PER_MEGABYTES); - DependencyManager::get()->setUnusedResourceCacheSize(_sounds->value() * BYTES_PER_MEGABYTES); + ScriptCache::getInstance()->setUnusedResourceCacheSize(_scripts->value() * BYTES_PER_MEGABYTES); + SoundCache::getInstance().setUnusedResourceCacheSize(_sounds->value() * BYTES_PER_MEGABYTES); DependencyManager::get()->setUnusedResourceCacheSize(_textures->value() * BYTES_PER_MEGABYTES); } void CachesSizeDialog::resetClicked(bool checked) { _animations->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); _geometries->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); - _scripts->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); - _sounds->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); + _scripts->setValue(ScriptCache::getInstance()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); + _sounds->setValue(SoundCache::getInstance().getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); _textures->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); } From 894c4c9d59c0692e6b93a64a5a5c9781057e04aa Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 14:00:23 -0800 Subject: [PATCH 050/159] All dialogs in Menu are QPointers --- interface/src/Menu.cpp | 10 ++-------- interface/src/Menu.h | 12 ++++++------ 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index c50c722d4a..d4b4671ac1 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -93,17 +93,11 @@ const int CONSOLE_HEIGHT = 200; Menu::Menu() : _actionHash(), _receivedAudioStreamSettings(), - _bandwidthDialog(NULL), _fieldOfView(DEFAULT_FIELD_OF_VIEW_DEGREES), _realWorldFieldOfView(DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES), _faceshiftEyeDeflection(DEFAULT_FACESHIFT_EYE_DEFLECTION), _faceshiftHostname(DEFAULT_FACESHIFT_HOSTNAME), _jsConsole(NULL), - _octreeStatsDialog(NULL), - _lodToolsDialog(NULL), - _hmdToolsDialog(NULL), - _newLocationDialog(NULL), - _userLocationsDialog(NULL), #if defined(Q_OS_MAC) || defined(Q_OS_WIN) _speechRecognizer(), #endif @@ -122,8 +116,8 @@ Menu::Menu() : _fpsAverage(FIVE_SECONDS_OF_FRAMES), _fastFPSAverage(ONE_SECOND_OF_FRAMES), _loginAction(NULL), - _preferencesDialog(NULL), - _loginDialog(NULL), + _newLocationDialog(NULL), + _userLocationsDialog(NULL), _hasLoginDialogDisplayed(false), _snapshotsLocation(), _scriptsLocation(), diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 20408f1406..20a7e7ebb8 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -242,7 +242,6 @@ private: QHash _actionHash; InboundAudioStream::Settings _receivedAudioStreamSettings; - BandwidthDialog* _bandwidthDialog; float _fieldOfView; /// in Degrees, doesn't apply to HMD like Oculus float _realWorldFieldOfView; // The actual FOV set by the user's monitor size and view distance float _faceshiftEyeDeflection; @@ -252,11 +251,6 @@ private: QPointer _ScriptEditor; QPointer _chatWindow; QDialog* _jsConsole; - OctreeStatsDialog* _octreeStatsDialog; - LodToolsDialog* _lodToolsDialog; - HMDToolsDialog* _hmdToolsDialog; - QPointer _newLocationDialog; - QPointer _userLocationsDialog; #if defined(Q_OS_MAC) || defined(Q_OS_WIN) SpeechRecognizer _speechRecognizer; #endif @@ -276,6 +270,12 @@ private: SimpleMovingAverage _fpsAverage; SimpleMovingAverage _fastFPSAverage; QAction* _loginAction; + QPointer _bandwidthDialog; + QPointer _octreeStatsDialog; + QPointer _lodToolsDialog; + QPointer _hmdToolsDialog; + QPointer _newLocationDialog; + QPointer _userLocationsDialog; QPointer _preferencesDialog; QPointer _attachmentsDialog; QPointer _animationsDialog; From fd2b0edf7a65c1d977b94350ac9e07f89bc3cfdb Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 14:01:56 -0800 Subject: [PATCH 051/159] Alphabetical order --- interface/src/Menu.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 20a7e7ebb8..502ab01633 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -270,17 +270,17 @@ private: SimpleMovingAverage _fpsAverage; SimpleMovingAverage _fastFPSAverage; QAction* _loginAction; + QPointer _addressBarDialog; + QPointer _animationsDialog; + QPointer _attachmentsDialog; QPointer _bandwidthDialog; - QPointer _octreeStatsDialog; - QPointer _lodToolsDialog; - QPointer _hmdToolsDialog; QPointer _newLocationDialog; QPointer _userLocationsDialog; - QPointer _preferencesDialog; - QPointer _attachmentsDialog; - QPointer _animationsDialog; - QPointer _addressBarDialog; + QPointer _hmdToolsDialog; + QPointer _lodToolsDialog; QPointer _loginDialog; + QPointer _octreeStatsDialog; + QPointer _preferencesDialog; bool _hasLoginDialogDisplayed; QAction* _chatAction; QString _snapshotsLocation; From e62fbe25579b385619abe8dd934859f79f4c497c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 14:09:26 -0800 Subject: [PATCH 052/159] Cleanup some headers --- interface/src/Menu.cpp | 32 ++++++++------------------------ interface/src/Menu.h | 11 +++++------ 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index d4b4671ac1..c25ab67db5 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -51,13 +51,20 @@ #include "scripting/LocationScriptingInterface.h" #include "scripting/MenuScriptingInterface.h" #include "Util.h" +#include "ui/AddressBarDialog.h" #include "ui/AnimationsDialog.h" #include "ui/AttachmentsDialog.h" +#include "ui/BandwidthDialog" +#include "ui/DataWebDialog" +#include "ui/HMDToolsDialog" +#include "ui/LodToolsDialog" +#include "ui/LoginDialog.h" +#include "ui/OctreeStatsDialog" +#include "ui/PreferencesDialog" #include "ui/InfoView.h" #include "ui/MetavoxelEditor.h" #include "ui/MetavoxelNetworkSimulator.h" #include "ui/ModelsBrowser.h" -#include "ui/LoginDialog.h" #include "ui/NodeBounds.h" Menu* Menu::_instance = NULL; @@ -613,15 +620,6 @@ Menu::Menu() : #endif } -Menu::~Menu() { - bandwidthDetailsClosed(); - octreeStatsDetailsClosed(); - if (_hmdToolsDialog) { - delete _hmdToolsDialog; - _hmdToolsDialog = NULL; - } -} - void Menu::loadSettings(QSettings* settings) { bool lockedSettings = false; if (!settings) { @@ -1247,13 +1245,6 @@ void Menu::audioMuteToggled() { } } -void Menu::bandwidthDetailsClosed() { - if (_bandwidthDialog) { - delete _bandwidthDialog; - _bandwidthDialog = NULL; - } -} - void Menu::octreeStatsDetails() { if (!_octreeStatsDialog) { _octreeStatsDialog = new OctreeStatsDialog(DependencyManager::get().data(), @@ -1267,13 +1258,6 @@ void Menu::octreeStatsDetails() { _octreeStatsDialog->raise(); } -void Menu::octreeStatsDetailsClosed() { - if (_octreeStatsDialog) { - delete _octreeStatsDialog; - _octreeStatsDialog = NULL; - } -} - QString Menu::getLODFeedbackText() { // determine granularity feedback int boundaryLevelAdjust = getBoundaryLevelAdjust(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 502ab01633..2cd9c8ecf2 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -27,12 +27,8 @@ #include "SpeechRecognizer.h" #endif -#include "ui/AddressBarDialog.h" #include "ui/ChatWindow.h" -#include "ui/DataWebDialog.h" #include "ui/JSConsole.h" -#include "ui/LoginDialog.h" -#include "ui/PreferencesDialog.h" #include "ui/ScriptEditorWindow.h" const float ADJUST_LOD_DOWN_FPS = 40.0; @@ -54,22 +50,25 @@ const float MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 15.0f; const QString SETTINGS_ADDRESS_KEY = "address"; class QSettings; +class AddressBarDialog; class AnimationsDialog; class AttachmentsDialog; class BandwidthDialog; +class DataWebDialog; class HMDToolsDialog; class LodToolsDialog; +class LoginDialog; +class OctreeStatsDialog; +class PreferencesDialog; class MetavoxelEditor; class MetavoxelNetworkSimulator; class ChatWindow; -class OctreeStatsDialog; class MenuItemProperties; class Menu : public QMenuBar { Q_OBJECT public: static Menu* getInstance(); - ~Menu(); void triggerOption(const QString& menuOption); QAction* getActionForOption(const QString& menuOption); From 7b65c754147b99696ee9dbf70ae079b28c05fdf5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 12 Jan 2015 14:32:13 -0800 Subject: [PATCH 053/159] first cut at restoreFromMostRecentBackup --- libraries/octree/src/OctreePersistThread.cpp | 67 ++++++++++++++++++++ libraries/octree/src/OctreePersistThread.h | 2 + 2 files changed, 69 insertions(+) diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index 49372d1141..8c1901e8e4 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -13,7 +13,10 @@ #include #include +#include #include +#include +#include #include #include @@ -65,6 +68,10 @@ bool OctreePersistThread::process() { if(lockFile.is_open()) { qDebug() << "WARNING: Octree lock file detected at startup:" << lockFileName << "-- Attempting to restore from previous backup file."; + + // This is where we should attempt to find the most recent backup and restore from + // that file as our persist file. + restoreFromMostRecentBackup(); lockFile.close(); qDebug() << "Loading Octree... lock file closed:" << lockFileName; @@ -184,6 +191,66 @@ void OctreePersistThread::persist() { } } +void OctreePersistThread::restoreFromMostRecentBackup() { + qDebug() << "Restoring from most recent backup..."; + + // Based on our backup file name, determine the path and file name pattern for backup files + QFileInfo persistFileInfo(_filename); + QString path = persistFileInfo.path(); + QString fileNamePart = persistFileInfo.fileName(); + + // Create a file filter that will find all backup files of this extension format + QString backupExtension = _backupExtensionFormat; + + if (_backupExtensionFormat.contains("%N")) { + backupExtension.replace(QString("%N"), "*"); + } else { + qDebug() << "This backup extension format does not yet support restoring from most recent backup..."; + return; // exit early, unable to restore from backup + } + + QString backupFileNamePart = fileNamePart + backupExtension; + QStringList filters; + filters << backupFileNamePart; + + bool bestBackupFound = false; + QString bestBackupFile; + QDateTime bestBackupFileTime; + + // Iterate over all of the backup files in the persist location + QDirIterator dirIterator(path, filters, QDir::Files|QDir::NoSymLinks, QDirIterator::NoIteratorFlags); + while(dirIterator.hasNext()) { + + dirIterator.next(); + QDateTime lastModified = dirIterator.fileInfo().lastModified(); + + // Based on last modified date, track the most recently modified file as the best backup + if (lastModified > bestBackupFileTime) { + bestBackupFound = true; + bestBackupFile = dirIterator.filePath(); + bestBackupFileTime = lastModified; + } + } + + // If we found a backup file, restore from that file. + if (bestBackupFound) { + qDebug() << "BEST backup file:" << bestBackupFile << " last modified:" << bestBackupFileTime.toString(); + + qDebug() << "Removing old file:" << _filename; + remove(qPrintable(_filename)); + + qDebug() << "Restoring backup file " << bestBackupFile << "..."; + bool result = QFile::copy(bestBackupFile, _filename); + if (result) { + qDebug() << "DONE restoring backup file " << bestBackupFile << "to" << _filename << "..."; + } else { + qDebug() << "ERROR while restoring backup file " << bestBackupFile << "to" << _filename << "..."; + } + } else { + qDebug() << "NO BEST backup file found."; + } +} + void OctreePersistThread::rollOldBackupVersions() { if (!_backupExtensionFormat.contains("%N")) { return; // this backup extension format doesn't support rolling diff --git a/libraries/octree/src/OctreePersistThread.h b/libraries/octree/src/OctreePersistThread.h index b2093b89c0..70d2d9b747 100644 --- a/libraries/octree/src/OctreePersistThread.h +++ b/libraries/octree/src/OctreePersistThread.h @@ -48,6 +48,8 @@ protected: void persist(); void backup(); void rollOldBackupVersions(); + void restoreFromMostRecentBackup(); + private: Octree* _tree; QString _filename; From 7a2ecd27fd8a1696ef6d7a4719dbac26915ac931 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 12 Jan 2015 14:32:32 -0800 Subject: [PATCH 054/159] fix typo --- libraries/entities/src/EntityItem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 70fdb86929..76045d9c15 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -699,7 +699,7 @@ void EntityItem::simulate(const quint64& now) { #ifndef USE_BULLET_PHYSICS // if we've slowed considerably, then just stop moving, but only if no BULLET if (glm::length(velocity) <= ENTITY_ITEM_EPSILON_VELOCITY_LENGTH) { - velocity = NO_VELOCITY; + velocity = ENTITY_ITEM_ZERO_VEC3; } #endif // !USE_BULLET_PHYSICS @@ -723,7 +723,7 @@ void EntityItem::simulate(const quint64& now) { #else // !USE_BULLET_PHYSICS // ... otherwise we help things come to rest by clamping small velocities. if (glm::length(velocity) <= ENTITY_ITEM_EPSILON_VELOCITY_LENGTH) { - velocity = NO_VELOCITY; + velocity = ENTITY_ITEM_ZERO_VEC3; } #endif // USE_BULLET_PHYSICS From 8f3aba35852d698441966b78ccdccbf0e83f3b15 Mon Sep 17 00:00:00 2001 From: Chris Collins Date: Mon, 12 Jan 2015 14:39:13 -0800 Subject: [PATCH 055/159] Removing double entry of gun.js Removing double entry of gun.js --- examples/gun.js | 419 ------------------------------------------------ 1 file changed, 419 deletions(-) delete mode 100644 examples/gun.js diff --git a/examples/gun.js b/examples/gun.js deleted file mode 100644 index 18fe9c542d..0000000000 --- a/examples/gun.js +++ /dev/null @@ -1,419 +0,0 @@ -// -// gun.js -// examples -// -// Created by Brad Hefta-Gaub on 12/31/13. -// Modified by Philip on 3/3/14 -// Copyright 2013 High Fidelity, Inc. -// -// This is an example script that turns the hydra controllers and mouse into a entity gun. -// It reads the controller, watches for trigger pulls, and launches entities. -// When entities collide with voxels they blow little holes out of the voxels. -// -// 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/globals.js"); - -function getRandomFloat(min, max) { - return Math.random() * (max - min) + min; -} - -var lastX = 0; -var lastY = 0; -var yawFromMouse = 0; -var pitchFromMouse = 0; -var isMouseDown = false; - -var BULLET_VELOCITY = 20.0; -var MIN_THROWER_DELAY = 1000; -var MAX_THROWER_DELAY = 1000; -var LEFT_BUTTON_3 = 3; -var RELOAD_INTERVAL = 5; - -var KICKBACK_ANGLE = 15; -var elbowKickAngle = 0.0; -var rotationBeforeKickback; - -var showScore = false; - - -// Load some sound to use for loading and firing -var fireSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/GUN-SHOT2.raw"); -var loadSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/Gun_Reload_Weapon22.raw"); -var impactSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Guns/BulletImpact2.raw"); -var targetHitSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/hit.raw"); -var targetLaunchSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Space%20Invaders/shoot.raw"); - -var gunModel = "http://public.highfidelity.io/models/attachments/HaloGun.fst"; - -var audioOptions = { - volume: 0.9 -} - -var shotsFired = 0; -var shotTime = new Date(); - -var activeControllers = 0; - -// initialize our controller triggers -var triggerPulled = new Array(); -var numberOfTriggers = Controller.getNumberOfTriggers(); -for (t = 0; t < numberOfTriggers; t++) { - triggerPulled[t] = false; -} - -var isLaunchButtonPressed = false; -var score = 0; - -var bulletID = false; -var targetID = false; - -// Create a reticle image in center of screen -var screenSize = Controller.getViewportDimensions(); -var reticle = Overlays.addOverlay("image", { - x: screenSize.x / 2 - 16, - y: screenSize.y / 2 - 16, - width: 32, - height: 32, - imageURL: HIFI_PUBLIC_BUCKET + "images/reticle.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1 - }); - -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 - }); - -if (showScore) { - var text = Overlays.addOverlay("text", { - x: screenSize.x / 2 - 100, - y: screenSize.y / 2 - 50, - width: 150, - height: 50, - color: { red: 0, green: 0, blue: 0}, - textColor: { red: 255, green: 0, blue: 0}, - topMargin: 4, - leftMargin: 4, - text: "Score: " + score - }); -} - - - -function printVector(string, vector) { - print(string + " " + vector.x + ", " + vector.y + ", " + vector.z); -} - -function shootBullet(position, velocity) { - var BULLET_SIZE = 0.07; - var BULLET_LIFETIME = 10.0; - var BULLET_GRAVITY = -0.02; - bulletID = Entities.addEntity( - { type: "Sphere", - position: position, - dimensions: { x: BULLET_SIZE, y: BULLET_SIZE, z: BULLET_SIZE }, - color: { red: 255, green: 0, blue: 0 }, - velocity: velocity, - lifetime: BULLET_LIFETIME, - gravity: { x: 0, y: BULLET_GRAVITY, z: 0 }, - ignoreCollisions: false, - collisionsWillMove: true - }); - - // Play firing sounds - audioOptions.position = position; - Audio.playSound(fireSound, audioOptions); - shotsFired++; - if ((shotsFired % RELOAD_INTERVAL) == 0) { - Audio.playSound(loadSound, audioOptions); - } - - // Kickback the arm - 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.25; - var TARGET_LIFETIME = 300.0; - var TARGET_UP_VELOCITY = 0.5; - var TARGET_FWD_VELOCITY = 1.0; - var DISTANCE_TO_LAUNCH_FROM = 3.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); - - var newPosition = Vec3.sum(camera, Vec3.multiply(forwardVector, DISTANCE_TO_LAUNCH_FROM)); - - var velocity = Vec3.multiply(forwardVector, TARGET_FWD_VELOCITY); - velocity.y += TARGET_UP_VELOCITY; - - targetID = Entities.addEntity( - { type: "Box", - position: newPosition, - dimensions: { x: TARGET_SIZE, y: TARGET_SIZE, z: TARGET_SIZE }, - color: { red: 0, green: 200, blue: 200 }, - //angularVelocity: { x: 1, y: 0, z: 0 }, - velocity: velocity, - gravity: { x: 0, y: TARGET_GRAVITY, z: 0 }, - lifetime: TARGET_LIFETIME, - damping: 0.0001, - collisionsWillMove: true }); - - // Record start time - shotTime = new Date(); - - // Play target shoot sound - audioOptions.position = newPosition; - Audio.playSound(targetLaunchSound, audioOptions); -} - - - -function entityCollisionWithEntity(entity1, entity2, collision) { - - if (((entity1.id == bulletID.id) || (entity1.id == targetID.id)) && - ((entity2.id == bulletID.id) || (entity2.id == targetID.id))) { - score++; - if (showScore) { - Overlays.editOverlay(text, { text: "Score: " + score } ); - } - - // We will delete the bullet and target in 1/2 sec, but for now we can see them bounce! - Script.setTimeout(deleteBulletAndTarget, 500); - - // Turn the target and the bullet white - Entities.editEntity(entity1, { color: { red: 255, green: 255, blue: 255 }}); - Entities.editEntity(entity2, { color: { red: 255, green: 255, blue: 255 }}); - - // play the sound near the camera so the shooter can hear it - audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); - Audio.playSound(targetHitSound, audioOptions); - } -} - -function keyPressEvent(event) { - // if our tools are off, then don't do anything - if (event.text == "t") { - var time = MIN_THROWER_DELAY + Math.random() * MAX_THROWER_DELAY; - Script.setTimeout(shootTarget, time); - } else if (event.text == ".") { - shootFromMouse(); - } else if (event.text == "r") { - playLoadSound(); - } else if (event.text == "s") { - // Hit this key to dump a posture from hydra to log - Quat.print("arm = ", MyAvatar.getJointRotation("LeftArm")); - Quat.print("forearm = ", MyAvatar.getJointRotation("LeftForeArm")); - Quat.print("hand = ", MyAvatar.getJointRotation("LeftHand")); - - } -} - -function playLoadSound() { - audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); - Audio.playSound(loadSound, audioOptions); - // Raise arm to firing posture - takeFiringPose(); -} - -function clearPose() { - MyAvatar.clearJointData("LeftForeArm"); - MyAvatar.clearJointData("LeftArm"); - MyAvatar.clearJointData("LeftHand"); -} - -function deleteBulletAndTarget() { - Entities.deleteEntity(bulletID); - Entities.deleteEntity(targetID); - bulletID = false; - targetID = false; -} - -function takeFiringPose() { - clearPose(); - if (Controller.getNumberOfSpatialControls() == 0) { - MyAvatar.setJointData("LeftForeArm", {x: -0.251919, y: -0.0415449, z: 0.499487, w: 0.827843}); - MyAvatar.setJointData("LeftArm", { x: 0.470196, y: -0.132559, z: 0.494033, w: 0.719219}); - MyAvatar.setJointData("LeftHand", { x: -0.0104815, y: -0.110551, z: -0.352111, w: 0.929333}); - } -} - -MyAvatar.attach(gunModel, "RightHand", {x:0.02, y: 0.11, z: 0.04}, Quat.fromPitchYawRollDegrees(-0, -160, -79), 0.20); -//MyAvatar.attach(gunModel, "LeftHand", {x: -0.02, y: -.14, z: 0.07}, Quat.fromPitchYawRollDegrees(-70, -151, 72), 0.20); - -// Give a bit of time to load before playing sound -Script.setTimeout(playLoadSound, 2000); - -function update(deltaTime) { - if (bulletID && !bulletID.isKnownID) { - print("Trying to identify bullet"); - bulletID = Entities.identifyEntity(bulletID); - } - 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(); - clearPose(); - } - } - - var KICKBACK_DECAY_RATE = 0.125; - if (elbowKickAngle > 0.0) { - if (elbowKickAngle > 0.5) { - var newAngle = elbowKickAngle * KICKBACK_DECAY_RATE; - elbowKickAngle -= newAngle; - var armRotation = MyAvatar.getJointRotation("LeftForeArm"); - armRotation = Quat.multiply(armRotation, Quat.fromPitchYawRollDegrees(0.0, 0.0, -newAngle)); - MyAvatar.setJointData("LeftForeArm", armRotation); - } else { - MyAvatar.setJointData("LeftForeArm", rotationBeforeKickback); - if (Controller.getNumberOfSpatialControls() > 0) { - clearPose(); - } - elbowKickAngle = 0.0; - } - } - - // Check hydra controller for launch button press - if (!isLaunchButtonPressed && Controller.isButtonPressed(LEFT_BUTTON_3)) { - isLaunchButtonPressed = true; - var time = MIN_THROWER_DELAY + Math.random() * MAX_THROWER_DELAY; - Script.setTimeout(shootTarget, time); - } else if (isLaunchButtonPressed && !Controller.isButtonPressed(LEFT_BUTTON_3)) { - isLaunchButtonPressed = false; - - } - - // check for trigger press - - var numberOfTriggers = 2; - var controllersPerTrigger = 2; - - if (numberOfTriggers == 2 && controllersPerTrigger == 2) { - for (var t = 0; t < 2; t++) { - var shootABullet = false; - var triggerValue = Controller.getTriggerValue(t); - if (triggerPulled[t]) { - // must release to at least 0.1 - if (triggerValue < 0.1) { - triggerPulled[t] = false; // unpulled - } - } else { - // must pull to at least - if (triggerValue > 0.5) { - triggerPulled[t] = true; // pulled - shootABullet = true; - } - } - - if (shootABullet) { - var palmController = t * controllersPerTrigger; - var palmPosition = Controller.getSpatialControlPosition(palmController); - - var fingerTipController = palmController + 1; - var fingerTipPosition = Controller.getSpatialControlPosition(fingerTipController); - - var palmToFingerTipVector = - { x: (fingerTipPosition.x - palmPosition.x), - y: (fingerTipPosition.y - palmPosition.y), - z: (fingerTipPosition.z - palmPosition.z) }; - - // just off the front of the finger tip - var position = { x: fingerTipPosition.x + palmToFingerTipVector.x/2, - y: fingerTipPosition.y + palmToFingerTipVector.y/2, - z: fingerTipPosition.z + palmToFingerTipVector.z/2}; - - var velocity = Vec3.multiply(BULLET_VELOCITY, Vec3.normalize(palmToFingerTipVector)); - - shootBullet(position, velocity); - } - } - } -} - -function mousePressEvent(event) { - isMouseDown = true; - lastX = event.x; - lastY = event.y; - - if (Overlays.getOverlayAtPoint({ x: event.x, y: event.y }) === offButton) { - Script.stop(); - } else { - shootFromMouse(); - } -} - -function shootFromMouse() { - var DISTANCE_FROM_CAMERA = 2.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); -} - -function mouseReleaseEvent(event) { - // position - 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 scriptEnding() { - Overlays.deleteOverlay(reticle); - Overlays.deleteOverlay(offButton); - Overlays.deleteOverlay(text); - MyAvatar.detachOne(gunModel); - clearPose(); -} - -Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity); -Script.scriptEnding.connect(scriptEnding); -Script.update.connect(update); -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); -Controller.mouseMoveEvent.connect(mouseMoveEvent); -Controller.keyPressEvent.connect(keyPressEvent); - - - From 7bf57b3cca68b09d75fc83d87ecb618b2241a175 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 14:53:31 -0800 Subject: [PATCH 056/159] Removed unecessary method/cleanup header --- interface/src/Menu.cpp | 32 ++++++++++---------------------- interface/src/Menu.h | 10 ++++------ 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index c25ab67db5..3e4f2c212a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -54,13 +54,14 @@ #include "ui/AddressBarDialog.h" #include "ui/AnimationsDialog.h" #include "ui/AttachmentsDialog.h" -#include "ui/BandwidthDialog" -#include "ui/DataWebDialog" -#include "ui/HMDToolsDialog" -#include "ui/LodToolsDialog" +#include "ui/BandwidthDialog.h" +#include "ui/CachesSizeDialog.h" +#include "ui/DataWebDialog.h" +#include "ui/HMDToolsDialog.h" +#include "ui/LodToolsDialog.h" #include "ui/LoginDialog.h" -#include "ui/OctreeStatsDialog" -#include "ui/PreferencesDialog" +#include "ui/OctreeStatsDialog.h" +#include "ui/PreferencesDialog.h" #include "ui/InfoView.h" #include "ui/MetavoxelEditor.h" #include "ui/MetavoxelNetworkSimulator.h" @@ -122,13 +123,7 @@ Menu::Menu() : _lastAvatarDetailDrop(usecTimestampNow()), _fpsAverage(FIVE_SECONDS_OF_FRAMES), _fastFPSAverage(ONE_SECOND_OF_FRAMES), - _loginAction(NULL), - _newLocationDialog(NULL), - _userLocationsDialog(NULL), _hasLoginDialogDisplayed(false), - _snapshotsLocation(), - _scriptsLocation(), - _walletPrivateKey(), _shouldRenderTableNeedsRebuilding(true) { Application *appInstance = Application::getInstance(); @@ -1145,7 +1140,7 @@ void Menu::bandwidthDetails() { if (! _bandwidthDialog) { _bandwidthDialog = new BandwidthDialog(DependencyManager::get().data(), Application::getInstance()->getBandwidthMeter()); - connect(_bandwidthDialog, SIGNAL(closed()), SLOT(bandwidthDetailsClosed())); + connect(_bandwidthDialog, SIGNAL(closed()), _bandwidthDialog, SLOT(deleteLater())); _bandwidthDialog->show(); @@ -1249,7 +1244,7 @@ void Menu::octreeStatsDetails() { if (!_octreeStatsDialog) { _octreeStatsDialog = new OctreeStatsDialog(DependencyManager::get().data(), Application::getInstance()->getOcteeSceneStats()); - connect(_octreeStatsDialog, SIGNAL(closed()), SLOT(octreeStatsDetailsClosed())); + connect(_octreeStatsDialog, SIGNAL(closed()), _octreeStatsDialog, SLOT(deleteLater())); _octreeStatsDialog->show(); if (_hmdToolsDialog) { _hmdToolsDialog->watchWindow(_octreeStatsDialog->windowHandle()); @@ -1425,7 +1420,7 @@ bool Menu::shouldRenderMesh(float largestDimension, float distanceToCamera) { void Menu::lodTools() { if (!_lodToolsDialog) { _lodToolsDialog = new LodToolsDialog(DependencyManager::get().data()); - connect(_lodToolsDialog, SIGNAL(closed()), SLOT(lodToolsClosed())); + connect(_lodToolsDialog, SIGNAL(closed()), _lodToolsDialog, SLOT(deleteLater())); _lodToolsDialog->show(); if (_hmdToolsDialog) { _hmdToolsDialog->watchWindow(_lodToolsDialog->windowHandle()); @@ -1434,13 +1429,6 @@ void Menu::lodTools() { _lodToolsDialog->raise(); } -void Menu::lodToolsClosed() { - if (_lodToolsDialog) { - delete _lodToolsDialog; - _lodToolsDialog = NULL; - } -} - void Menu::hmdTools(bool showTools) { if (showTools) { if (!_hmdToolsDialog) { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 2cd9c8ecf2..3bc15fd99a 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -53,6 +53,7 @@ class QSettings; class AddressBarDialog; class AnimationsDialog; class AttachmentsDialog; +class CachesSizeDialog; class BandwidthDialog; class DataWebDialog; class HMDToolsDialog; @@ -190,9 +191,6 @@ private slots: void changePrivateKey(); void nameLocation(); void toggleLocationList(); - void bandwidthDetailsClosed(); - void octreeStatsDetailsClosed(); - void lodToolsClosed(); void hmdToolsClosed(); void runTests(); void showMetavoxelEditor(); @@ -263,16 +261,15 @@ private: float _avatarLODDistanceMultiplier; int _boundaryLevelAdjust; int _maxOctreePacketsPerSecond; - QString replaceLastOccurrence(QChar search, QChar replace, QString string); quint64 _lastAdjust; quint64 _lastAvatarDetailDrop; SimpleMovingAverage _fpsAverage; SimpleMovingAverage _fastFPSAverage; - QAction* _loginAction; QPointer _addressBarDialog; QPointer _animationsDialog; QPointer _attachmentsDialog; QPointer _bandwidthDialog; + QPointer _cachesSizeDialog; QPointer _newLocationDialog; QPointer _userLocationsDialog; QPointer _hmdToolsDialog; @@ -281,7 +278,8 @@ private: QPointer _octreeStatsDialog; QPointer _preferencesDialog; bool _hasLoginDialogDisplayed; - QAction* _chatAction; + QAction* _loginAction = nullptr; + QAction* _chatAction = nullptr; QString _snapshotsLocation; QString _scriptsLocation; QByteArray _walletPrivateKey; From c45f618852dfeeae44cf68f934f8d57609b661a5 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 12 Jan 2015 15:00:35 -0800 Subject: [PATCH 057/159] Factorising the shader code to unpack data from the deferred buffer --- libraries/render-utils/src/DeferredBuffer.slh | 65 +++++++++++++++++++ .../render-utils/src/directional_light.slf | 47 +++----------- .../directional_light_cascaded_shadow_map.slf | 54 ++++----------- .../src/directional_light_shadow_map.slf | 48 +++----------- 4 files changed, 96 insertions(+), 118 deletions(-) create mode 100755 libraries/render-utils/src/DeferredBuffer.slh diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh new file mode 100755 index 0000000000..c5630c3564 --- /dev/null +++ b/libraries/render-utils/src/DeferredBuffer.slh @@ -0,0 +1,65 @@ + +<@if not DEFERRED_BUFFER_SLH@> +<@def DEFERRED_BUFFER_SLH@> + + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the normal texture +uniform sampler2D normalMap; + +// the specular texture +uniform sampler2D specularMap; + +// the depth texture +uniform sampler2D depthMap; + +// the distance to the near clip plane +uniform float near; + +// scale factor for depth: (far - near) / far +uniform float depthScale; + +// offset for depth texture coordinates +uniform vec2 depthTexCoordOffset; + +// scale for depth texture coordinates +uniform vec2 depthTexCoordScale; + +struct DeferredFragment { + float depthVal; + vec4 normalVal; + vec4 diffuseVal; + vec4 specularVal; + vec4 position; + vec3 normal; +}; + +DeferredFragment unpackDeferredFragment(vec2 texcoord) { + DeferredFragment frag; + frag.depthVal = texture2D(depthMap, texcoord).r; + frag.normalVal = texture2D(normalMap, texcoord); + frag.diffuseVal = texture2D(diffuseMap, texcoord); + frag.specularVal = texture2D(specularMap, texcoord); + + // compute the view space position using the depth + float z = near / (frag.depthVal * depthScale - 1.0); + frag.position = vec4((depthTexCoordOffset + texcoord * depthTexCoordScale) * z, z, 1.0); + + // Unpack the normal from the map + frag.normal = normalize(frag.normalVal.xyz * 2.0 - vec3(1.0)); + + return frag; +} + +<@endif@> diff --git a/libraries/render-utils/src/directional_light.slf b/libraries/render-utils/src/directional_light.slf index 7a02e3c3a8..db963be913 100644 --- a/libraries/render-utils/src/directional_light.slf +++ b/libraries/render-utils/src/directional_light.slf @@ -12,56 +12,29 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// the diffuse texture -uniform sampler2D diffuseMap; - -// the normal texture -uniform sampler2D normalMap; - -// the specular texture -uniform sampler2D specularMap; - -// the depth texture -uniform sampler2D depthMap; - -// the distance to the near clip plane -uniform float near; - -// scale factor for depth: (far - near) / far -uniform float depthScale; - -// offset for depth texture coordinates -uniform vec2 depthTexCoordOffset; - -// scale for depth texture coordinates -uniform vec2 depthTexCoordScale; +// Everything about deferred buffer +<@include DeferredBuffer.slh@> void main(void) { - float depthVal = texture2D(depthMap, gl_TexCoord[0].st).r; - vec4 normalVal = texture2D(normalMap, gl_TexCoord[0].st); - vec4 diffuseVal = texture2D(diffuseMap, gl_TexCoord[0].st); - vec4 specularVal = texture2D(specularMap, gl_TexCoord[0].st); + DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + + vec4 normalVal = frag.normalVal; + vec4 diffuseVal = frag.diffuseVal; + vec4 specularVal = frag.specularVal; - // compute the view space position using the depth - float z = near / (depthVal * depthScale - 1.0); - vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 0.0); - // Light mapped or not ? if ((normalVal.a >= 0.45) && (normalVal.a <= 0.55)) { gl_FragColor = vec4(diffuseVal.rgb * specularVal.rgb, 1.0); } else { - // get the normal from the map - vec3 normalizedNormal = normalize(normalVal.xyz * 2.0 - vec3(1.0)); - // compute the base color based on OpenGL lighting model - float diffuse = dot(normalizedNormal, gl_LightSource[0].position.xyz); + float diffuse = dot(frag.normal, gl_LightSource[0].position.xyz); float facingLight = step(0.0, diffuse); vec3 baseColor = diffuseVal.rgb * (gl_FrontLightModelProduct.sceneColor.rgb + gl_FrontLightProduct[0].ambient.rgb + gl_FrontLightProduct[0].diffuse.rgb * (diffuse * facingLight)); // compute the specular multiplier (sans exponent) - float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position.xyz - normalize(position.xyz)), - normalizedNormal)); + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position.xyz - normalize(frag.position.xyz)), + frag.normal)); // add specular contribution vec4 specularColor = specularVal; diff --git a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf index 08fdc3a908..f7e21252fb 100644 --- a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf +++ b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf @@ -12,52 +12,24 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// the diffuse texture -uniform sampler2D diffuseMap; - -// the normal texture -uniform sampler2D normalMap; - -// the specular texture -uniform sampler2D specularMap; - -// the depth texture -uniform sampler2D depthMap; +// Everything about deferred buffer +<@include DeferredBuffer.slh@> // Everything about shadow <@include Shadow.slh@> -// the distance to the near clip plane -uniform float near; - -// scale factor for depth: (far - near) / far -uniform float depthScale; - -// offset for depth texture coordinates -uniform vec2 depthTexCoordOffset; - -// scale for depth texture coordinates -uniform vec2 depthTexCoordScale; - void main(void) { - float depthVal = texture2D(depthMap, gl_TexCoord[0].st).r; - vec4 normalVal = texture2D(normalMap, gl_TexCoord[0].st); - vec4 diffuseVal = texture2D(diffuseMap, gl_TexCoord[0].st); - vec4 specularVal = texture2D(specularMap, gl_TexCoord[0].st); - - // compute the view space position using the depth - float z = near / (depthVal * depthScale - 1.0); - vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0); + DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + vec4 normalVal = frag.normalVal; + vec4 diffuseVal = frag.diffuseVal; + vec4 specularVal = frag.specularVal; // Eval shadow Texcoord and then Attenuation - vec4 shadowTexcoord = evalCascadedShadowTexcoord(position); + vec4 shadowTexcoord = evalCascadedShadowTexcoord(frag.position); float shadowAttenuation = evalShadowAttenuation(shadowTexcoord); - // get the normal from the map - vec3 normalizedNormal = normalize(normalVal.xyz * 2.0 - vec3(1.0)); - // how much this fragment faces the light direction - float diffuse = dot(normalizedNormal, gl_LightSource[0].position.xyz); + float diffuse = dot(frag.normal, gl_LightSource[0].position.xyz); // Light mapped or not ? if ((normalVal.a >= 0.45) && (normalVal.a <= 0.55)) { @@ -83,19 +55,15 @@ void main(void) { float facingLight = step(0.0, diffuse) * shadowAttenuation; // compute the base color based on OpenGL lighting model - vec3 baseColor = diffuseVal.rgb * (/*gl_FrontLightModelProduct.sceneColor.rgb + */ + vec3 baseColor = diffuseVal.rgb * (gl_FrontLightModelProduct.sceneColor.rgb + gl_FrontLightProduct[0].ambient.rgb + gl_FrontLightProduct[0].diffuse.rgb * (diffuse * facingLight)); // compute the specular multiplier (sans exponent) - float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position.xyz - normalize(position.xyz)), - normalizedNormal)); + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position.xyz - normalize(frag.position.xyz)), + frag.normal)); // add specular contribution vec4 specularColor = specularVal; gl_FragColor = vec4(baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb, normalVal.a); - - if (gl_FragCoord.x > 1024) { - gl_FragColor = vec4( (gl_FrontLightProduct[0].ambient.rgb + gl_FrontLightProduct[0].diffuse.rgb * (diffuse * facingLight)), normalVal.a); - } } } diff --git a/libraries/render-utils/src/directional_light_shadow_map.slf b/libraries/render-utils/src/directional_light_shadow_map.slf index 7a34f56f93..1a781af131 100644 --- a/libraries/render-utils/src/directional_light_shadow_map.slf +++ b/libraries/render-utils/src/directional_light_shadow_map.slf @@ -12,52 +12,24 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// the diffuse texture -uniform sampler2D diffuseMap; - -// the normal texture -uniform sampler2D normalMap; - -// the specular texture -uniform sampler2D specularMap; - -// the depth texture -uniform sampler2D depthMap; +// Everything about deferred buffer +<@include DeferredBuffer.slh@> // Everything about shadow <@include Shadow.slh@> -// the distance to the near clip plane -uniform float near; - -// scale factor for depth: (far - near) / far -uniform float depthScale; - -// offset for depth texture coordinates -uniform vec2 depthTexCoordOffset; - -// scale for depth texture coordinates -uniform vec2 depthTexCoordScale; - void main(void) { - float depthVal = texture2D(depthMap, gl_TexCoord[0].st).r; - vec4 normalVal = texture2D(normalMap, gl_TexCoord[0].st); - vec4 diffuseVal = texture2D(diffuseMap, gl_TexCoord[0].st); - vec4 specularVal = texture2D(specularMap, gl_TexCoord[0].st); - - // compute the view space position using the depth - float z = near / (depthVal * depthScale - 1.0); - vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0); + DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st); + vec4 normalVal = frag.normalVal; + vec4 diffuseVal = frag.diffuseVal; + vec4 specularVal = frag.specularVal; // Eval shadow Texcoord and then Attenuation - vec4 shadowTexcoord = evalShadowTexcoord(position); + vec4 shadowTexcoord = evalShadowTexcoord(frag.position); float shadowAttenuation = evalShadowAttenuation(shadowTexcoord); - // get the normal from the map - vec3 normalizedNormal = normalize(normalVal.xyz * 2.0 - vec3(1.0)); - // how much this fragment faces the light direction - float diffuse = dot(normalizedNormal, gl_LightSource[0].position.xyz); + float diffuse = dot(frag.normal, gl_LightSource[0].position.xyz); // Light mapped or not ? if ((normalVal.a >= 0.45) && (normalVal.a <= 0.55)) { @@ -86,8 +58,8 @@ void main(void) { gl_FrontLightProduct[0].ambient.rgb + gl_FrontLightProduct[0].diffuse.rgb * (diffuse * facingLight)); // compute the specular multiplier (sans exponent) - float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position.xyz - normalize(position.xyz)), - normalizedNormal)); + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position.xyz - normalize(frag.position.xyz)), + frag.normal)); // add specular contribution vec4 specularColor = specularVal; From 208af5cbca5cd62e3ea4fce00aeeea68b1a59ed4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 12 Jan 2015 15:14:49 -0800 Subject: [PATCH 058/159] Revert "don't play muzak from lobby to avoid error" This reverts commit 69f5c769b8c4f930e3b02c19e644223adee9203b. --- examples/lobby.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/lobby.js b/examples/lobby.js index e34d119502..b03be7c29b 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -139,10 +139,10 @@ function drawLobby() { MyAvatar.attach(HELMET_ATTACHMENT_URL, "Neck", {x: 0, y: 0, z: 0}, Quat.fromPitchYawRollDegrees(0, 0, 0), 1.15); // start the drone sound - // currentDrone = Audio.playSound(droneSound, { stereo: true, loop: true, localOnly: true, volume: DRONE_VOLUME }); + currentDrone = Audio.playSound(droneSound, { stereo: true, loop: true, localOnly: true, volume: DRONE_VOLUME }); // start one of our muzak sounds - // playRandomMuzak(); + playRandomMuzak(); } } @@ -353,9 +353,9 @@ function update(deltaTime) { Overlays.editOverlay(descriptionText, { position: textOverlayPosition() }); // if the reticle is up then we may need to play the next muzak - // if (!Audio.isInjectorPlaying(currentMuzakInjector)) { -// playNextMuzak(); -// } + if (!Audio.isInjectorPlaying(currentMuzakInjector)) { + playNextMuzak(); + } } } From 59c9e0bb50aa08925921a5e56d1d783942255b8f Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 15:19:36 -0800 Subject: [PATCH 059/159] Wire CachesSizeDialog in Menu --- interface/src/Menu.cpp | 13 +++++++++++++ interface/src/Menu.h | 2 ++ interface/src/ui/CachesSizeDialog.cpp | 6 ++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 3e4f2c212a..2cc16102b0 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -488,6 +488,7 @@ Menu::Menu() : false, &UserActivityLogger::getInstance(), SLOT(disable(bool))); + addActionToQMenuAndActionHash(networkMenu, MenuOption::CachesSize, 0, this, SLOT(cachesSizeDialog())); addActionToQMenuAndActionHash(developerMenu, MenuOption::WalletPrivateKey, 0, this, SLOT(changePrivateKey())); @@ -1416,6 +1417,18 @@ bool Menu::shouldRenderMesh(float largestDimension, float distanceToCamera) { return (distanceToCamera <= visibleDistanceAtClosestScale); } +void Menu::cachesSizeDialog() { + qDebug() << "Caches size:" << _cachesSizeDialog.isNull(); + if (!_cachesSizeDialog) { + _cachesSizeDialog = new CachesSizeDialog(DependencyManager::get().data()); + connect(_cachesSizeDialog, SIGNAL(closed()), _cachesSizeDialog, SLOT(deleteLater())); + _cachesSizeDialog->show(); + if (_hmdToolsDialog) { + _hmdToolsDialog->watchWindow(_cachesSizeDialog->windowHandle()); + } + } + _cachesSizeDialog->raise(); +} void Menu::lodTools() { if (!_lodToolsDialog) { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 3bc15fd99a..c23559229d 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -159,6 +159,7 @@ public slots: void showLoginForCurrentDomain(); void bandwidthDetails(); void octreeStatsDetails(); + void cachesSizeDialog(); void lodTools(); void hmdTools(bool showTools); void loadSettings(QSettings* settings = NULL); @@ -315,6 +316,7 @@ namespace MenuOption { const QString BandwidthDetails = "Bandwidth Details"; const QString BlueSpeechSphere = "Blue Sphere While Speaking"; const QString CascadedShadows = "Cascaded"; + const QString CachesSize = "Caches Size"; const QString Chat = "Chat..."; const QString ChatCircling = "Chat Circling"; const QString CollideAsRagdoll = "Collide With Self (Ragdoll)"; diff --git a/interface/src/ui/CachesSizeDialog.cpp b/interface/src/ui/CachesSizeDialog.cpp index 12e88f5100..4d4457c922 100644 --- a/interface/src/ui/CachesSizeDialog.cpp +++ b/interface/src/ui/CachesSizeDialog.cpp @@ -62,6 +62,8 @@ void CachesSizeDialog::confirmClicked(bool checked) { ScriptCache::getInstance()->setUnusedResourceCacheSize(_scripts->value() * BYTES_PER_MEGABYTES); SoundCache::getInstance().setUnusedResourceCacheSize(_sounds->value() * BYTES_PER_MEGABYTES); DependencyManager::get()->setUnusedResourceCacheSize(_textures->value() * BYTES_PER_MEGABYTES); + + QDialog::close(); } void CachesSizeDialog::resetClicked(bool checked) { @@ -74,10 +76,10 @@ void CachesSizeDialog::resetClicked(bool checked) { void CachesSizeDialog::reject() { // Just regularly close upon ESC - this->QDialog::close(); + QDialog::close(); } void CachesSizeDialog::closeEvent(QCloseEvent* event) { - this->QDialog::closeEvent(event); + QDialog::closeEvent(event); emit closed(); } \ No newline at end of file From 67da1148ac69476372456fc6860a713d24f4a018 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 12 Jan 2015 15:22:47 -0800 Subject: [PATCH 060/159] global ambient light back --- interface/src/Application.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 89a27b25d7..22a2b6bc22 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2589,8 +2589,7 @@ void Application::updateShadowMap() { glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); } -//const GLfloat WORLD_AMBIENT_COLOR[] = { 0.525f, 0.525f, 0.6f }; -const GLfloat WORLD_AMBIENT_COLOR[] = { 0.2f, 0.2f, 0.3f }; +const GLfloat WORLD_AMBIENT_COLOR[] = { 0.525f, 0.525f, 0.6f }; const GLfloat WORLD_DIFFUSE_COLOR[] = { 0.6f, 0.525f, 0.525f }; const GLfloat WORLD_SPECULAR_COLOR[] = { 0.94f, 0.94f, 0.737f, 1.0f }; From 8415098fc2ef0a22735d7662af3c6d1ae4c287e2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 15:36:36 -0800 Subject: [PATCH 061/159] Set different caches size depending on cache type --- libraries/animation/src/AnimationCache.cpp | 5 ++++- libraries/audio/src/SoundCache.cpp | 3 ++- libraries/metavoxels/src/ScriptCache.cpp | 7 +++++-- libraries/networking/src/ResourceCache.cpp | 4 +++- libraries/networking/src/ResourceCache.h | 7 +++++++ libraries/render-utils/src/GeometryCache.cpp | 2 ++ libraries/render-utils/src/TextureCache.cpp | 2 ++ 7 files changed, 25 insertions(+), 5 deletions(-) diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index 1a68aeb908..6c02ccbd2b 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -17,7 +17,10 @@ static int animationPointerMetaTypeId = qRegisterMetaType(); AnimationCache::AnimationCache(QObject* parent) : - ResourceCache(parent) { + ResourceCache(parent) +{ + const qint64 ANIMATION_DEFAULT_UNUSED_MAX_SIZE = 50 * BYTES_PER_MEGABYTES; + setUnusedResourceCacheSize(ANIMATION_DEFAULT_UNUSED_MAX_SIZE); } AnimationPointer AnimationCache::getAnimation(const QUrl& url) { diff --git a/libraries/audio/src/SoundCache.cpp b/libraries/audio/src/SoundCache.cpp index 4fbd98fea0..fe05372ce5 100644 --- a/libraries/audio/src/SoundCache.cpp +++ b/libraries/audio/src/SoundCache.cpp @@ -23,7 +23,8 @@ SoundCache& SoundCache::getInstance() { SoundCache::SoundCache(QObject* parent) : ResourceCache(parent) { - + const qint64 SOUND_DEFAULT_UNUSED_MAX_SIZE = 50 * BYTES_PER_MEGABYTES; + setUnusedResourceCacheSize(SOUND_DEFAULT_UNUSED_MAX_SIZE); } SharedSoundPointer SoundCache::getSound(const QUrl& url) { diff --git a/libraries/metavoxels/src/ScriptCache.cpp b/libraries/metavoxels/src/ScriptCache.cpp index ffd5200a2e..7e8dbc4bae 100644 --- a/libraries/metavoxels/src/ScriptCache.cpp +++ b/libraries/metavoxels/src/ScriptCache.cpp @@ -109,9 +109,12 @@ ScriptCache* ScriptCache::getInstance() { } ScriptCache::ScriptCache() : - _engine(NULL) { - + _engine(NULL) +{ setEngine(new QScriptEngine(this)); + + const qint64 SCRIPT_DEFAULT_UNUSED_MAX_SIZE = 50 * BYTES_PER_MEGABYTES; + setUnusedResourceCacheSize(SCRIPT_DEFAULT_UNUSED_MAX_SIZE); } void ScriptCache::setEngine(QScriptEngine* engine) { diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 1187b311fc..f4d9a2909d 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -16,6 +16,8 @@ #include #include +#include + #include "NetworkAccessManager.h" #include "ResourceCache.h" @@ -70,7 +72,7 @@ QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& } void ResourceCache::setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize) { - _unusedResourcesMaxSize = unusedResourcesMaxSize; + _unusedResourcesMaxSize = glm::clamp(unusedResourcesMaxSize, MIN_UNUSED_MAX_SIZE, MAX_UNUSED_MAX_SIZE); reserveUnusedResource(0); } diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 0c2b6d2ce8..7b8ffc392b 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -29,7 +29,14 @@ class Resource; static constexpr qint64 BYTES_PER_MEGABYTES = 1024 * 1024; static constexpr qint64 BYTES_PER_GIGABYTES = 1024 * BYTES_PER_MEGABYTES; + +// Windows can have troubles allocating that much memory in ram sometimes +// so default cache size at 100 MB on windows (1GB otherwise) +#ifdef Q_OS_WIN32 static constexpr qint64 DEFAULT_UNUSED_MAX_SIZE = 100 * BYTES_PER_MEGABYTES; +#else +static constexpr qint64 DEFAULT_UNUSED_MAX_SIZE = 1024 * BYTES_PER_MEGABYTES; +#endif static constexpr qint64 MIN_UNUSED_MAX_SIZE = 0; static constexpr qint64 MAX_UNUSED_MAX_SIZE = 10 * BYTES_PER_GIGABYTES; diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 553e460a5c..25f988472f 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -30,6 +30,8 @@ const int GeometryCache::UNKNOWN_ID = -1; GeometryCache::GeometryCache() : _nextID(0) { + const qint64 GEOMETRY_DEFAULT_UNUSED_MAX_SIZE = DEFAULT_UNUSED_MAX_SIZE; + setUnusedResourceCacheSize(GEOMETRY_DEFAULT_UNUSED_MAX_SIZE); } GeometryCache::~GeometryCache() { diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 0f34282162..3bd05a14ee 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -39,6 +39,8 @@ TextureCache::TextureCache() : _frameBufferSize(100, 100), _associatedWidget(NULL) { + const qint64 TEXTURE_DEFAULT_UNUSED_MAX_SIZE = DEFAULT_UNUSED_MAX_SIZE; + setUnusedResourceCacheSize(TEXTURE_DEFAULT_UNUSED_MAX_SIZE); } TextureCache::~TextureCache() { From 1566157250c919cd541512aa0f5f0002782d2a5f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 12 Jan 2015 15:52:31 -0800 Subject: [PATCH 062/159] Use the DeferredBuffer.slh in point and spot lights --- libraries/render-utils/src/point_light.slf | 25 ++-------------------- libraries/render-utils/src/spot_light.slf | 25 ++-------------------- 2 files changed, 4 insertions(+), 46 deletions(-) diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index 320dc93f5e..e5142b25ce 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -12,29 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// the diffuse texture -uniform sampler2D diffuseMap; - -// the normal texture -uniform sampler2D normalMap; - -// the specular texture -uniform sampler2D specularMap; - -// the depth texture -uniform sampler2D depthMap; - -// the distance to the near clip plane -uniform float near; - -// scale factor for depth: (far - near) / far -uniform float depthScale; - -// offset for depth texture coordinates -uniform vec2 depthTexCoordOffset; - -// scale for depth texture coordinates -uniform vec2 depthTexCoordScale; +// Everything about deferred buffer +<@include DeferredBuffer.slh@> // the radius (hard cutoff) of the light effect uniform float radius; diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 489802d061..f987760eb8 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -12,29 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// the diffuse texture -uniform sampler2D diffuseMap; - -// the normal texture -uniform sampler2D normalMap; - -// the specular texture -uniform sampler2D specularMap; - -// the depth texture -uniform sampler2D depthMap; - -// the distance to the near clip plane -uniform float near; - -// scale factor for depth: (far - near) / far -uniform float depthScale; - -// offset for depth texture coordinates -uniform vec2 depthTexCoordOffset; - -// scale for depth texture coordinates -uniform vec2 depthTexCoordScale; +// Everything about deferred buffer +<@include DeferredBuffer.slh@> // the radius (hard cutoff) of the light effect uniform float radius; From e30b119464303707dc29ce64fe88c54ceeeee673 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 15:55:25 -0800 Subject: [PATCH 063/159] Some simple code cleanup --- interface/src/Menu.cpp | 37 +------------- interface/src/Menu.h | 65 +++++++++++++++---------- interface/src/ui/JSConsole.h | 5 ++ interface/src/ui/ScriptEditorWindow.cpp | 2 - 4 files changed, 46 insertions(+), 63 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 2cc16102b0..48403b7511 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -87,44 +87,9 @@ Menu* Menu::getInstance() { return _instance; } -const float DEFAULT_FACESHIFT_EYE_DEFLECTION = 0.25f; -const QString DEFAULT_FACESHIFT_HOSTNAME = "localhost"; -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 QString CONSOLE_TITLE = "Scripting Console"; -const float CONSOLE_WINDOW_OPACITY = 0.95f; -const int CONSOLE_WIDTH = 800; -const int CONSOLE_HEIGHT = 200; - Menu::Menu() : - _actionHash(), - _receivedAudioStreamSettings(), - _fieldOfView(DEFAULT_FIELD_OF_VIEW_DEGREES), - _realWorldFieldOfView(DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES), - _faceshiftEyeDeflection(DEFAULT_FACESHIFT_EYE_DEFLECTION), - _faceshiftHostname(DEFAULT_FACESHIFT_HOSTNAME), - _jsConsole(NULL), -#if defined(Q_OS_MAC) || defined(Q_OS_WIN) - _speechRecognizer(), -#endif - _octreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE), - _oculusUIAngularSize(DEFAULT_OCULUS_UI_ANGULAR_SIZE), - _sixenseReticleMoveSpeed(DEFAULT_SIXENSE_RETICLE_MOVE_SPEED), - _invertSixenseButtons(DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS), - _automaticAvatarLOD(true), - _avatarLODDecreaseFPS(DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS), - _avatarLODIncreaseFPS(ADJUST_LOD_UP_FPS), - _avatarLODDistanceMultiplier(DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER), - _boundaryLevelAdjust(0), - _maxOctreePacketsPerSecond(DEFAULT_MAX_OCTREE_PPS), _lastAdjust(usecTimestampNow()), - _lastAvatarDetailDrop(usecTimestampNow()), - _fpsAverage(FIVE_SECONDS_OF_FRAMES), - _fastFPSAverage(ONE_SECOND_OF_FRAMES), - _hasLoginDialogDisplayed(false), - _shouldRenderTableNeedsRebuilding(true) + _lastAvatarDetailDrop(usecTimestampNow()) { Application *appInstance = Application::getInstance(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index c23559229d..563ed42d30 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -48,6 +48,13 @@ const float MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 0.1f; const float MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 15.0f; const QString SETTINGS_ADDRESS_KEY = "address"; + +const float DEFAULT_FACESHIFT_EYE_DEFLECTION = 0.25f; +const QString DEFAULT_FACESHIFT_HOSTNAME = "localhost"; +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 QSettings; class AddressBarDialog; @@ -240,32 +247,37 @@ private: QHash _actionHash; InboundAudioStream::Settings _receivedAudioStreamSettings; - float _fieldOfView; /// in Degrees, doesn't apply to HMD like Oculus - float _realWorldFieldOfView; // The actual FOV set by the user's monitor size and view distance - float _faceshiftEyeDeflection; - QString _faceshiftHostname; - QPointer _MetavoxelEditor; - QPointer _metavoxelNetworkSimulator; - QPointer _ScriptEditor; - QPointer _chatWindow; - QDialog* _jsConsole; + // 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; - float _oculusUIAngularSize; - float _sixenseReticleMoveSpeed; - bool _invertSixenseButtons; - bool _automaticAvatarLOD; - float _avatarLODDecreaseFPS; - float _avatarLODIncreaseFPS; - float _avatarLODDistanceMultiplier; - int _boundaryLevelAdjust; - int _maxOctreePacketsPerSecond; + 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; - SimpleMovingAverage _fastFPSAverage; + + SimpleMovingAverage _fpsAverage = FIVE_SECONDS_OF_FRAMES; + SimpleMovingAverage _fastFPSAverage = ONE_SECOND_OF_FRAMES; + QPointer _addressBarDialog; QPointer _animationsDialog; QPointer _attachmentsDialog; @@ -278,16 +290,20 @@ private: QPointer _loginDialog; QPointer _octreeStatsDialog; QPointer _preferencesDialog; - bool _hasLoginDialogDisplayed; + + QPointer _MetavoxelEditor; + QPointer _metavoxelNetworkSimulator; + QPointer _ScriptEditor; + QPointer _chatWindow; + QAction* _loginAction = nullptr; QAction* _chatAction = nullptr; QString _snapshotsLocation; QString _scriptsLocation; QByteArray _walletPrivateKey; - bool _shouldRenderTableNeedsRebuilding; + bool _shouldRenderTableNeedsRebuilding = true; QMap _shouldRenderTable; - }; namespace MenuOption { @@ -405,7 +421,6 @@ namespace MenuOption { const QString RenderTargetFramerate40 = "40"; const QString RenderTargetFramerate30 = "30"; const QString RenderTargetFramerateVSyncOn = "V-Sync On"; - const QString RenderResolution = "Scale Resolution"; const QString RenderResolutionOne = "1"; const QString RenderResolutionTwoThird = "2/3"; diff --git a/interface/src/ui/JSConsole.h b/interface/src/ui/JSConsole.h index f28132a1f5..daeba8ea15 100644 --- a/interface/src/ui/JSConsole.h +++ b/interface/src/ui/JSConsole.h @@ -20,6 +20,11 @@ #include "ui_console.h" #include "ScriptEngine.h" +const QString CONSOLE_TITLE = "Scripting Console"; +const float CONSOLE_WINDOW_OPACITY = 0.95f; +const int CONSOLE_WIDTH = 800; +const int CONSOLE_HEIGHT = 200; + class JSConsole : public QWidget { Q_OBJECT public: diff --git a/interface/src/ui/ScriptEditorWindow.cpp b/interface/src/ui/ScriptEditorWindow.cpp index 0496040724..f5cd6de49a 100644 --- a/interface/src/ui/ScriptEditorWindow.cpp +++ b/interface/src/ui/ScriptEditorWindow.cpp @@ -31,8 +31,6 @@ #include "FlowLayout.h" #include "JSConsole.h" -const int CONSOLE_HEIGHT = 150; - ScriptEditorWindow::ScriptEditorWindow() : _ScriptEditorWindowUI(new Ui::ScriptEditorWindow), _loadMenu(new QMenu), From 934d8d58ef43f25ee36c4a3a7a28c3620ccf4bee Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 15:59:27 -0800 Subject: [PATCH 064/159] Move some constants out of Menu class files --- interface/src/Menu.cpp | 3 --- interface/src/Menu.h | 18 ++++++++++-------- interface/src/devices/Faceshift.h | 3 +++ 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 48403b7511..12671ef6e3 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -11,7 +11,6 @@ #include - #include #include #include @@ -44,8 +43,6 @@ #include "Audio.h" #include "audio/AudioIOStatsRenderer.h" #include "audio/AudioScope.h" -#include "devices/Faceshift.h" -#include "devices/OculusManager.h" #include "devices/Visage.h" #include "Menu.h" #include "scripting/LocationScriptingInterface.h" diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 563ed42d30..95436a5b8b 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -27,10 +27,14 @@ #include "SpeechRecognizer.h" #endif +#include "devices/Faceshift.h" +#include "devices/OculusManager.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; @@ -46,15 +50,13 @@ 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 QString SETTINGS_ADDRESS_KEY = "address"; - -const float DEFAULT_FACESHIFT_EYE_DEFLECTION = 0.25f; -const QString DEFAULT_FACESHIFT_HOSTNAME = "localhost"; 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 QString SETTINGS_ADDRESS_KEY = "address"; class QSettings; class AddressBarDialog; @@ -259,9 +261,9 @@ private: 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; + 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; diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index b6b942dfee..9ed23ddb9f 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -23,6 +23,9 @@ #include "FaceTracker.h" +const float DEFAULT_FACESHIFT_EYE_DEFLECTION = 0.25f; +const QString DEFAULT_FACESHIFT_HOSTNAME = "localhost"; + /// Handles interaction with the Faceshift software, which provides head position/orientation and facial features. class Faceshift : public FaceTracker { Q_OBJECT From 661221a189cb946598d214430253766d6a8c0f1c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 12 Jan 2015 16:04:00 -0800 Subject: [PATCH 065/159] repairs to AudioScriptingInterface playSound --- examples/lobby.js | 8 +++++--- interface/src/Audio.cpp | 2 +- libraries/audio/src/AudioScriptingInterface.cpp | 3 ++- libraries/audio/src/Sound.cpp | 15 ++++++++++++--- libraries/audio/src/Sound.h | 8 ++++++-- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/examples/lobby.js b/examples/lobby.js index b03be7c29b..15a8aca328 100644 --- a/examples/lobby.js +++ b/examples/lobby.js @@ -138,8 +138,10 @@ function drawLobby() { // add an attachment on this avatar so other people see them in the lobby MyAvatar.attach(HELMET_ATTACHMENT_URL, "Neck", {x: 0, y: 0, z: 0}, Quat.fromPitchYawRollDegrees(0, 0, 0), 1.15); - // start the drone sound - currentDrone = Audio.playSound(droneSound, { stereo: true, loop: true, localOnly: true, volume: DRONE_VOLUME }); + if (droneSound.downloaded) { + // start the drone sound + currentDrone = Audio.playSound(droneSound, { stereo: true, loop: true, localOnly: true, volume: DRONE_VOLUME }); + } // start one of our muzak sounds playRandomMuzak(); @@ -353,7 +355,7 @@ function update(deltaTime) { Overlays.editOverlay(descriptionText, { position: textOverlayPosition() }); // if the reticle is up then we may need to play the next muzak - if (!Audio.isInjectorPlaying(currentMuzakInjector)) { + if (currentMuzakInjector && !Audio.isInjectorPlaying(currentMuzakInjector)) { playNextMuzak(); } } diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index bd106d9bc6..844386c9e5 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -880,7 +880,7 @@ bool Audio::outputLocalInjector(bool isStereo, qreal volume, AudioInjector* inje localFormat.setChannelCount(isStereo ? 2 : 1); QAudioOutput* localOutput = new QAudioOutput(getNamedAudioDeviceForMode(QAudio::AudioOutput, _outputAudioDeviceName), - localFormat, this); + localFormat); localOutput->setVolume(volume); // move the localOutput to the same thread as the local injector buffer diff --git a/libraries/audio/src/AudioScriptingInterface.cpp b/libraries/audio/src/AudioScriptingInterface.cpp index 8cd133ad40..120c7a6b5a 100644 --- a/libraries/audio/src/AudioScriptingInterface.cpp +++ b/libraries/audio/src/AudioScriptingInterface.cpp @@ -13,7 +13,8 @@ void registerAudioMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, injectorOptionsToScriptValue, injectorOptionsFromScriptValue); - qScriptRegisterMetaType(engine, soundToScriptValue, soundFromScriptValue); + qScriptRegisterMetaType(engine, soundSharedPointerToScriptValue, soundSharedPointerFromScriptValue); + qScriptRegisterMetaType(engine, soundPointerToScriptValue, soundPointerFromScriptValue); } AudioScriptingInterface& AudioScriptingInterface::getInstance() { diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp index 54ff61d66a..cc41a849e7 100644 --- a/libraries/audio/src/Sound.cpp +++ b/libraries/audio/src/Sound.cpp @@ -29,13 +29,22 @@ #include "AudioEditBuffer.h" #include "Sound.h" -QScriptValue soundToScriptValue(QScriptEngine* engine, SharedSoundPointer const& in) { +static int soundMetaTypeId = qRegisterMetaType(); + +QScriptValue soundSharedPointerToScriptValue(QScriptEngine* engine, SharedSoundPointer const& in) { return engine->newQObject(in.data()); } -void soundFromScriptValue(const QScriptValue &object, SharedSoundPointer &out) { +void soundSharedPointerFromScriptValue(const QScriptValue& object, SharedSoundPointer &out) { out = SharedSoundPointer(qobject_cast(object.toQObject())); - qDebug() << "Sound from script value" << out.data(); +} + +QScriptValue soundPointerToScriptValue(QScriptEngine* engine, Sound* const& in) { + return engine->newQObject(in); +} + +void soundPointerFromScriptValue(const QScriptValue &object, Sound* &out) { + out = qobject_cast(object.toQObject()); } Sound::Sound(const QUrl& url, bool isStereo) : diff --git a/libraries/audio/src/Sound.h b/libraries/audio/src/Sound.h index 02b75417e8..9aa92feea1 100644 --- a/libraries/audio/src/Sound.h +++ b/libraries/audio/src/Sound.h @@ -45,8 +45,12 @@ private: typedef QSharedPointer SharedSoundPointer; Q_DECLARE_METATYPE(SharedSoundPointer) +QScriptValue soundSharedPointerToScriptValue(QScriptEngine* engine, SharedSoundPointer const& in); +void soundSharedPointerFromScriptValue(const QScriptValue& object, SharedSoundPointer &out); + +Q_DECLARE_METATYPE(Sound*) +QScriptValue soundPointerToScriptValue(QScriptEngine* engine, Sound* const& in); +void soundPointerFromScriptValue(const QScriptValue& object, Sound* &out); -QScriptValue soundToScriptValue(QScriptEngine* engine, SharedSoundPointer const& in); -void soundFromScriptValue(const QScriptValue& object, SharedSoundPointer& out); #endif // hifi_Sound_h From 8c7099a0bb44abbac5cf9e5aad20a1260353ee66 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 13 Jan 2015 01:09:28 +0100 Subject: [PATCH 066/159] changed "Load Scripts" label to be better understandable --- interface/ui/runningScriptsWidget.ui | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/interface/ui/runningScriptsWidget.ui b/interface/ui/runningScriptsWidget.ui index ea53e72e15..3d7db5064a 100644 --- a/interface/ui/runningScriptsWidget.ui +++ b/interface/ui/runningScriptsWidget.ui @@ -373,7 +373,7 @@ font: bold 16px; font: bold 16px; - Scripts + Load Scripts @@ -390,16 +390,6 @@ font: bold 16px; - - - - color: #0e7077; font: bold 14px; - - - Load script - - - From 80af2adf128a1a92bbd96067b3f7229dc4847c57 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 16:42:27 -0800 Subject: [PATCH 067/159] Remove constexpr because windows can't handle them --- libraries/networking/src/ResourceCache.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 7b8ffc392b..519b205d46 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -27,18 +27,18 @@ class QTimer; class Resource; -static constexpr qint64 BYTES_PER_MEGABYTES = 1024 * 1024; -static constexpr qint64 BYTES_PER_GIGABYTES = 1024 * BYTES_PER_MEGABYTES; +static const qint64 BYTES_PER_MEGABYTES = 1024 * 1024; +static const qint64 BYTES_PER_GIGABYTES = 1024 * BYTES_PER_MEGABYTES; // Windows can have troubles allocating that much memory in ram sometimes // so default cache size at 100 MB on windows (1GB otherwise) #ifdef Q_OS_WIN32 -static constexpr qint64 DEFAULT_UNUSED_MAX_SIZE = 100 * BYTES_PER_MEGABYTES; +static const qint64 DEFAULT_UNUSED_MAX_SIZE = 100 * BYTES_PER_MEGABYTES; #else -static constexpr qint64 DEFAULT_UNUSED_MAX_SIZE = 1024 * BYTES_PER_MEGABYTES; +static const qint64 DEFAULT_UNUSED_MAX_SIZE = 1024 * BYTES_PER_MEGABYTES; #endif -static constexpr qint64 MIN_UNUSED_MAX_SIZE = 0; -static constexpr qint64 MAX_UNUSED_MAX_SIZE = 10 * BYTES_PER_GIGABYTES; +static const qint64 MIN_UNUSED_MAX_SIZE = 0; +static const qint64 MAX_UNUSED_MAX_SIZE = 10 * BYTES_PER_GIGABYTES; /// Base class for resource caches. class ResourceCache : public QObject { From b6ba82653f4e355759b0af20d9390ccfa2c7da29 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 17:00:39 -0800 Subject: [PATCH 068/159] Remove glm dependency --- libraries/networking/src/ResourceCache.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index f4d9a2909d..5a95bd6028 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -16,12 +16,14 @@ #include #include -#include - #include "NetworkAccessManager.h" #include "ResourceCache.h" +#define clamp(x, min, max) (((x) < (min)) ? (min) :\ + (((x) > (max)) ? (max) :\ + (x))) + ResourceCache::ResourceCache(QObject* parent) : QObject(parent) { } @@ -72,7 +74,7 @@ QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& } void ResourceCache::setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize) { - _unusedResourcesMaxSize = glm::clamp(unusedResourcesMaxSize, MIN_UNUSED_MAX_SIZE, MAX_UNUSED_MAX_SIZE); + _unusedResourcesMaxSize = clamp(unusedResourcesMaxSize, MIN_UNUSED_MAX_SIZE, MAX_UNUSED_MAX_SIZE); reserveUnusedResource(0); } From ea3a5b7fcdf5c3161b0116b218bd8741093f6ded Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 12 Jan 2015 17:29:10 -0800 Subject: [PATCH 069/159] use last backup files timestamp as last backup time. --- libraries/octree/src/OctreePersistThread.cpp | 80 +++++++++++++++----- libraries/octree/src/OctreePersistThread.h | 2 + 2 files changed, 64 insertions(+), 18 deletions(-) diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index 8c1901e8e4..79469ade1f 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -49,6 +49,23 @@ OctreePersistThread::OctreePersistThread(Octree* tree, const QString& filename, { } +quint64 OctreePersistThread::getMostRecentBackupTimeInUsecs() { + + quint64 mostRecentBackupInUsecs = 0; + + QString mostRecentBackupFileName; + QDateTime mostRecentBackupTime; + + bool recentBackup = getMostRecentBackup(mostRecentBackupFileName, mostRecentBackupTime); + + if (recentBackup) { + mostRecentBackupInUsecs = mostRecentBackupTime.toMSecsSinceEpoch() * USECS_PER_MSEC; + } + + return mostRecentBackupInUsecs; +} + + bool OctreePersistThread::process() { if (!_initialLoadComplete) { @@ -109,7 +126,19 @@ bool OctreePersistThread::process() { } _initialLoadComplete = true; - _lastBackup = _lastCheck = usecTimestampNow(); // we just loaded, no need to save again + + // Since we just loaded the persistent file, we can consider ourselves as having "just checked" for persistance. + _lastCheck = usecTimestampNow(); // we just loaded, no need to save again + + // The last backup time, should be the timestamp for most recent backup file. + _lastBackup = getMostRecentBackupTimeInUsecs(); + + qDebug() << "Last Check:" << qPrintable(formatUsecTime(usecTimestampNow() - _lastCheck)) << "ago..."; + qDebug() << "Last Backup:" << qPrintable(formatUsecTime(usecTimestampNow() - _lastBackup)) << "ago..."; + + // This last persist time is not really used until the file is actually persisted. It is only + // used in formatting the backup filename in cases of non-rolling backup names. However, we don't + // want an uninitialized value for this, so we set it to the current time (startup of the server) time(&_lastPersistTime); emit loadCompleted(); @@ -193,6 +222,32 @@ void OctreePersistThread::persist() { void OctreePersistThread::restoreFromMostRecentBackup() { qDebug() << "Restoring from most recent backup..."; + + QString mostRecentBackupFileName; + QDateTime mostRecentBackupTime; + + bool recentBackup = getMostRecentBackup(mostRecentBackupFileName, mostRecentBackupTime); + + // If we found a backup file, restore from that file. + if (recentBackup) { + qDebug() << "BEST backup file:" << mostRecentBackupFileName << " last modified:" << mostRecentBackupTime.toString(); + + qDebug() << "Removing old file:" << _filename; + remove(qPrintable(_filename)); + + qDebug() << "Restoring backup file " << mostRecentBackupFileName << "..."; + bool result = QFile::copy(mostRecentBackupFileName, _filename); + if (result) { + qDebug() << "DONE restoring backup file " << mostRecentBackupFileName << "to" << _filename << "..."; + } else { + qDebug() << "ERROR while restoring backup file " << mostRecentBackupFileName << "to" << _filename << "..."; + } + } else { + qDebug() << "NO BEST backup file found."; + } +} + +bool OctreePersistThread::getMostRecentBackup(QString& mostRecentBackupFileName, QDateTime& mostRecentBackupTime) { // Based on our backup file name, determine the path and file name pattern for backup files QFileInfo persistFileInfo(_filename); @@ -206,7 +261,7 @@ void OctreePersistThread::restoreFromMostRecentBackup() { backupExtension.replace(QString("%N"), "*"); } else { qDebug() << "This backup extension format does not yet support restoring from most recent backup..."; - return; // exit early, unable to restore from backup + return false; // exit early, unable to restore from backup } QString backupFileNamePart = fileNamePart + backupExtension; @@ -231,24 +286,13 @@ void OctreePersistThread::restoreFromMostRecentBackup() { bestBackupFileTime = lastModified; } } - - // If we found a backup file, restore from that file. + + // If we found a backup then return the results if (bestBackupFound) { - qDebug() << "BEST backup file:" << bestBackupFile << " last modified:" << bestBackupFileTime.toString(); - - qDebug() << "Removing old file:" << _filename; - remove(qPrintable(_filename)); - - qDebug() << "Restoring backup file " << bestBackupFile << "..."; - bool result = QFile::copy(bestBackupFile, _filename); - if (result) { - qDebug() << "DONE restoring backup file " << bestBackupFile << "to" << _filename << "..."; - } else { - qDebug() << "ERROR while restoring backup file " << bestBackupFile << "to" << _filename << "..."; - } - } else { - qDebug() << "NO BEST backup file found."; + mostRecentBackupFileName = bestBackupFile; + mostRecentBackupTime = bestBackupFileTime; } + return bestBackupFound; } void OctreePersistThread::rollOldBackupVersions() { diff --git a/libraries/octree/src/OctreePersistThread.h b/libraries/octree/src/OctreePersistThread.h index 70d2d9b747..6f08b63197 100644 --- a/libraries/octree/src/OctreePersistThread.h +++ b/libraries/octree/src/OctreePersistThread.h @@ -49,6 +49,8 @@ protected: void backup(); void rollOldBackupVersions(); void restoreFromMostRecentBackup(); + bool getMostRecentBackup(QString& mostRecentBackupFileName, QDateTime& mostRecentBackupTime); + quint64 getMostRecentBackupTimeInUsecs(); private: Octree* _tree; From 7d39b45f16d9487cb6701f424118e749b3c5c332 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 17:34:07 -0800 Subject: [PATCH 070/159] Hopefully fixes the windows compile error --- interface/src/devices/OculusManager.cpp | 1 + interface/src/devices/OculusManager.h | 2 -- libraries/script-engine/src/EventTypes.h | 2 +- libraries/script-engine/src/KeyEvent.h | 2 +- libraries/shared/src/SharedUtil.h | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index f59ce639a0..2b444c4a25 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -13,6 +13,7 @@ #include "InterfaceConfig.h" #include "OculusManager.h" +#include "ui/overlays/Text3DOverlay.h" #include #include diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index d9700d9530..b9b5d81c68 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -19,8 +19,6 @@ #include -#include "ui/overlays/Text3DOverlay.h" - const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f; class Camera; diff --git a/libraries/script-engine/src/EventTypes.h b/libraries/script-engine/src/EventTypes.h index fc808ea560..906006e4f4 100644 --- a/libraries/script-engine/src/EventTypes.h +++ b/libraries/script-engine/src/EventTypes.h @@ -12,7 +12,7 @@ #ifndef hifi_EventTypes_h #define hifi_EventTypes_h -#include +#include void registerEventTypes(QScriptEngine* engine); diff --git a/libraries/script-engine/src/KeyEvent.h b/libraries/script-engine/src/KeyEvent.h index bdadcec374..350b733eaf 100644 --- a/libraries/script-engine/src/KeyEvent.h +++ b/libraries/script-engine/src/KeyEvent.h @@ -13,7 +13,7 @@ #define hifi_KeyEvent_h #include -#include +#include class KeyEvent { public: diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 61b7365877..01dcd7ff02 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -19,7 +19,7 @@ #include // not on windows, not needed for mac or windows #endif -#include +#include const int BYTES_PER_COLOR = 3; const int BYTES_PER_FLAGS = 1; From 9ce405a7444475027e358bcf7af19d2f2987b895 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 17:46:38 -0800 Subject: [PATCH 071/159] Text3DOverlay forward definition --- interface/src/devices/OculusManager.h | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index b9b5d81c68..591ba53239 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -23,6 +23,7 @@ const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f; class Camera; class PalmData; +class Text3DOverlay; /// Handles interaction with the Oculus Rift. class OculusManager { From 2b48d31cbb23bd3938eba9f68cc92af2d674cd1a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 17:48:54 -0800 Subject: [PATCH 072/159] Move scripts to correct directory --- examples/{ => controllers/hydra}/hydraGrab.js | 0 examples/{ => controllers/hydra}/hydraMove.js | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename examples/{ => controllers/hydra}/hydraGrab.js (100%) rename examples/{ => controllers/hydra}/hydraMove.js (100%) diff --git a/examples/hydraGrab.js b/examples/controllers/hydra/hydraGrab.js similarity index 100% rename from examples/hydraGrab.js rename to examples/controllers/hydra/hydraGrab.js diff --git a/examples/hydraMove.js b/examples/controllers/hydra/hydraMove.js similarity index 100% rename from examples/hydraMove.js rename to examples/controllers/hydra/hydraMove.js From cf7089e145cb5209cf0b54c4a0282866d67a2732 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 12 Jan 2015 18:49:05 -0800 Subject: [PATCH 073/159] Move constant back to Menu --- interface/src/Menu.h | 3 ++- interface/src/devices/OculusManager.h | 2 -- interface/src/devices/SixenseManager.h | 2 ++ interface/src/ui/ApplicationOverlay.h | 1 + 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 95436a5b8b..6f30ca983b 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -28,7 +28,6 @@ #endif #include "devices/Faceshift.h" -#include "devices/OculusManager.h" #include "devices/SixenseManager.h" #include "ui/ChatWindow.h" #include "ui/JSConsole.h" @@ -56,6 +55,8 @@ 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; diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index 591ba53239..71fc08c8f9 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -19,8 +19,6 @@ #include -const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f; - class Camera; class PalmData; class Text3DOverlay; diff --git a/interface/src/devices/SixenseManager.h b/interface/src/devices/SixenseManager.h index 0a7ab78c0e..4082edd153 100644 --- a/interface/src/devices/SixenseManager.h +++ b/interface/src/devices/SixenseManager.h @@ -25,6 +25,8 @@ #endif +class PalmData; + const unsigned int BUTTON_0 = 1U << 0; // the skinny button between 1 and 2 const unsigned int BUTTON_1 = 1U << 5; const unsigned int BUTTON_2 = 1U << 6; diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index e2094f2a8e..33dcea67a3 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -12,6 +12,7 @@ #ifndef hifi_ApplicationOverlay_h #define hifi_ApplicationOverlay_h +class Camera; class Overlays; class QOpenGLFramebufferObject; From fc698a8525a35f9059023d8fcad66f2d4f0a6c12 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 12 Jan 2015 18:51:26 -0800 Subject: [PATCH 074/159] first step factorizing the packDeferredFragment --- libraries/render-utils/src/DeferredBuffer.slh | 1 - .../render-utils/src/DeferredBufferWrite.slh | 28 +++++++++++++++++++ libraries/render-utils/src/model.slf | 11 ++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100755 libraries/render-utils/src/DeferredBufferWrite.slh diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh index c5630c3564..da02ef750e 100755 --- a/libraries/render-utils/src/DeferredBuffer.slh +++ b/libraries/render-utils/src/DeferredBuffer.slh @@ -11,7 +11,6 @@ <@if not DEFERRED_BUFFER_SLH@> <@def DEFERRED_BUFFER_SLH@> - // the diffuse texture uniform sampler2D diffuseMap; diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh new file mode 100755 index 0000000000..32822af2cb --- /dev/null +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -0,0 +1,28 @@ + +<@if not DEFERRED_BUFFER_WRITE_SLH@> +<@def DEFERRED_BUFFER_WRITE_SLH@> +/* +// the glow intensity +uniform float glowIntensity; + +// the alpha threshold +uniform float alphaThreshold; +*/ + +void packFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) { + // gl_FragData[0] = vec4(diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(diffuse.rgb, alpha); + gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(specular, shininess / 128.0); +} + +<@endif@> diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index 42421c71a2..9c263869f0 100755 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -11,6 +11,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include DeferredBufferWrite.slh@> + // the diffuse texture uniform sampler2D diffuseMap; @@ -23,7 +25,16 @@ varying vec4 normal; void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + + packDeferredFragment( + normalize(normal.xyz), + mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold)), + gl_Color.rgb * diffuse.rgb, + gl_FrontMaterial.specular.rgb, + gl_FrontMaterial.shininess); +/* gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); +*/ } From 80351a768e9ca319ff52eed6e243b7a802ddbe86 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 13 Jan 2015 08:26:11 -0800 Subject: [PATCH 075/159] Enable camera tool --- examples/libraries/entityCameraTool.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/libraries/entityCameraTool.js b/examples/libraries/entityCameraTool.js index b6a86e7a4d..cd8aa3656b 100644 --- a/examples/libraries/entityCameraTool.js +++ b/examples/libraries/entityCameraTool.js @@ -243,9 +243,9 @@ CameraManager = function() { } that.mousePressEvent = function(event) { - // if (cameraTool.mousePressEvent(event)) { - // return true; - // } + if (cameraTool.mousePressEvent(event)) { + return true; + } if (!that.enabled) return; @@ -291,7 +291,7 @@ CameraManager = function() { that.updateCamera = function() { if (!that.enabled || Camera.mode != "independent") { - // cameraTool.update(); + cameraTool.update(); return; } @@ -313,7 +313,7 @@ CameraManager = function() { Camera.setOrientation(q); - // cameraTool.update(); + cameraTool.update(); } function normalizeDegrees(degrees) { @@ -383,7 +383,7 @@ CameraManager = function() { Controller.wheelEvent.connect(that.wheelEvent); - // var cameraTool = new CameraTool(that); + var cameraTool = new CameraTool(that); return that; } From aad49e4404ff8526c4578dd7ef71b3b31d100e6f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 13 Jan 2015 08:26:32 -0800 Subject: [PATCH 076/159] Update camera tool to only show when edit entities is enabled --- examples/libraries/entityCameraTool.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/libraries/entityCameraTool.js b/examples/libraries/entityCameraTool.js index cd8aa3656b..ecc8935f26 100644 --- a/examples/libraries/entityCameraTool.js +++ b/examples/libraries/entityCameraTool.js @@ -105,6 +105,8 @@ CameraManager = function() { Camera.mode = "independent"; that.updateCamera(); + + cameraTool.setVisible(true); } that.disable = function(ignoreCamera) { @@ -115,6 +117,7 @@ CameraManager = function() { if (!ignoreCamera) { Camera.mode = that.previousCameraMode; } + cameraTool.setVisible(false); } that.focus = function(position, dimensions, easeOrientation) { From e873df9680fd11d7d632417330552a4936fb0bb6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 13 Jan 2015 08:39:59 -0800 Subject: [PATCH 077/159] Remove mode buttons from camera tool and increase size --- examples/libraries/entityCameraTool.js | 122 +++++++++---------------- examples/libraries/overlayUtils.js | 2 +- 2 files changed, 46 insertions(+), 78 deletions(-) diff --git a/examples/libraries/entityCameraTool.js b/examples/libraries/entityCameraTool.js index ecc8935f26..078ce0bbca 100644 --- a/examples/libraries/entityCameraTool.js +++ b/examples/libraries/entityCameraTool.js @@ -398,43 +398,21 @@ CameraTool = function(cameraManager) { var GREEN = { red: 26, green: 193, blue: 105 }; var BLUE = { red: 0, green: 131, blue: 204 }; - var ORIENTATION_OVERLAY_SIZE = 20; + var BORDER_WIDTH = 1; + + var ORIENTATION_OVERLAY_SIZE = 26; var ORIENTATION_OVERLAY_HALF_SIZE = ORIENTATION_OVERLAY_SIZE / 2; - var ORIENTATION_OVERLAY_CUBE_SIZE = 8, + var ORIENTATION_OVERLAY_CUBE_SIZE = 11, var ORIENTATION_OVERLAY_OFFSET = { - x: 96, + x: 30, y: 30, } - var UI_URL = HIFI_PUBLIC_BUCKET + "images/tools/camera-controls.svg"; - - var UI_WIDTH = 128; - var UI_HEIGHT = 61; + var UI_WIDTH = 70; + var UI_HEIGHT = 70; var UI_PADDING = 10; - var UI_BUTTON_WIDTH = 64; - var UI_BUTTON_HEIGHT = 30; - - var UI_SUBIMAGE_FIRST_PERSON = { - x: 0, - y: 0, - width: UI_WIDTH, - height: UI_HEIGHT - }, - var UI_SUBIMAGE_THIRD_PERSON = { - x: 0, - y: UI_HEIGHT, - width: UI_WIDTH, - height: UI_HEIGHT - }, - var UI_SUBIMAGE_OTHER = { - x: 0, - y: UI_HEIGHT * 2, - width: UI_WIDTH, - height: UI_HEIGHT - }, - var lastKnownWidth = Window.innerWidth; var uiPosition = { @@ -442,20 +420,28 @@ CameraTool = function(cameraManager) { y: UI_PADDING, }; - var ui = Overlays.addOverlay("image", { - imageURL: UI_URL, + var backgroundBorder = Overlays.addOverlay("text", { + x: uiPosition.x - BORDER_WIDTH, + y: uiPosition.y - BORDER_WIDTH, + width: UI_WIDTH + BORDER_WIDTH * 2, + height: UI_HEIGHT + BORDER_WIDTH * 2, + alpha: 0, + text: "", + backgroundColor: { red: 101, green: 101, blue: 101 }, + backgroundAlpha: 1.0, + visible: false, + }); + + var background = Overlays.addOverlay("text", { x: uiPosition.x, y: uiPosition.y, - subImage: { - x: 0, - y: 0, - width: UI_WIDTH, - height: UI_HEIGHT - }, width: UI_WIDTH, height: UI_HEIGHT, - alpha: 1.0, - visible: true + alpha: 0, + text: "", + backgroundColor: { red: 51, green: 51, blue: 51 }, + backgroundAlpha: 1.0, + visible: false, }); var defaultCubeProps = { @@ -473,15 +459,16 @@ CameraTool = function(cameraManager) { start: { x: 0, y: 0, z: 0 }, end: { x: 0, y: 0, z: 0 }, color: { red: 255, green: 0, blue: 0 }, - visible: true, + visible: false, drawOnHUD: true, }; var orientationOverlay = OverlayGroup({ position: { - x: uiPosition.x + ORIENTATION_OVERLAY_OFFSET.x, - y: uiPosition.y + ORIENTATION_OVERLAY_OFFSET.y, - } + x: uiPosition.x + UI_WIDTH / 2, + y: uiPosition.y + UI_HEIGHT / 2, + }, + visible: false, }); var OOHS = ORIENTATION_OVERLAY_HALF_SIZE; @@ -515,7 +502,8 @@ CameraTool = function(cameraManager) { Script.scriptEnding.connect(function() { orientationOverlay.destroy(); - Overlays.deleteOverlay(ui); + Overlays.deleteOverlay(background); + Overlays.deleteOverlay(backgroundBorder); }); var flip = Quat.fromPitchYawRollDegrees(0, 180, 0); @@ -530,16 +518,20 @@ CameraTool = function(cameraManager) { x: lastKnownWidth - UI_WIDTH - UI_PADDING, y: UI_PADDING, }; - Overlays.editOverlay(ui, { - x: uiPosition.x, - y: uiPosition.y - }); orientationOverlay.setProperties({ position: { x: uiPosition.x + ORIENTATION_OVERLAY_OFFSET.x, y: uiPosition.y + ORIENTATION_OVERLAY_OFFSET.y, } }); + Overlays.editOverlay(backgroundBorder, { + x: uiPosition.x - BORDER_WIDTH, + y: uiPosition.y - BORDER_WIDTH, + }); + Overlays.editOverlay(background, { + x: uiPosition.x, + y: uiPosition.y, + }); } } @@ -561,40 +553,16 @@ CameraTool = function(cameraManager) { targetYaw = event.isLeftButton ? 0 : 180; cameraManager.setTargetPitchYaw(targetPitch, targetYaw); return true; - } else if (clickedOverlay == ui) { - var x = event.x - uiPosition.x; - var y = event.y - uiPosition.y; - - // Did we hit a button? - if (x < UI_BUTTON_WIDTH) { - if (y < UI_BUTTON_HEIGHT) { - Camera.mode = "first person"; - } else { - Camera.mode = "third person"; - } - } - return true; } }; - function updateMode() { - var mode = Camera.mode; - - var subImage = UI_SUBIMAGE_OTHER; - if (mode == "first person") { - subImage = UI_SUBIMAGE_FIRST_PERSON; - } else if (mode == "third person") { - subImage = UI_SUBIMAGE_THIRD_PERSON; - } - - Overlays.editOverlay(ui, { subImage: subImage }); - } - - Camera.modeUpdated.connect(updateMode); - updateMode(); - that.setVisible = function(visible) { + orientationOverlay.setProperties({ visible: visible }); + Overlays.editOverlay(background, { visible: visible }); + Overlays.editOverlay(backgroundBorder, { visible: visible }); }; + that.setVisible(false); + return that; }; diff --git a/examples/libraries/overlayUtils.js b/examples/libraries/overlayUtils.js index 7623bfbb30..636ea40825 100644 --- a/examples/libraries/overlayUtils.js +++ b/examples/libraries/overlayUtils.js @@ -9,7 +9,7 @@ OverlayGroup = function(opts) { var rootPosition = opts.position || { x: 0, y: 0, z: 0 }; var rootRotation = opts.rotation || Quat.fromPitchYawRollRadians(0, 0, 0); - var visible = true; + var visible = opts.visible == true; function updateOverlays() { for (overlayID in overlays) { From 0c58572d3283527c4b045f29d2a3837851ee2c1d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 13 Jan 2015 08:45:11 -0800 Subject: [PATCH 078/159] Reduce size of camera tool cubes --- examples/libraries/entityCameraTool.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/libraries/entityCameraTool.js b/examples/libraries/entityCameraTool.js index 078ce0bbca..b9170dc25d 100644 --- a/examples/libraries/entityCameraTool.js +++ b/examples/libraries/entityCameraTool.js @@ -402,7 +402,7 @@ CameraTool = function(cameraManager) { var ORIENTATION_OVERLAY_SIZE = 26; var ORIENTATION_OVERLAY_HALF_SIZE = ORIENTATION_OVERLAY_SIZE / 2; - var ORIENTATION_OVERLAY_CUBE_SIZE = 11, + var ORIENTATION_OVERLAY_CUBE_SIZE = 10.5, var ORIENTATION_OVERLAY_OFFSET = { x: 30, From 30f898109d34a1278fda97d27eb081acf428acc0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 13 Jan 2015 09:40:55 -0800 Subject: [PATCH 079/159] don't warn about c++11 for MSVC12 --- CMakeLists.txt | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a0d463b766..367fb88a26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,17 +38,19 @@ elseif (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fno-strict-aliasing") endif(WIN32) -include(CheckCXXCompilerFlag) -CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) -CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) +if (NOT MSVC12) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) + CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) -if (COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -elseif(COMPILER_SUPPORTS_CXX0X) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") -else() - message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") -endif() + if (COMPILER_SUPPORTS_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + elseif(COMPILER_SUPPORTS_CXX0X) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + else() + message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") + endif() +endif () if (APPLE) set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++0x") From 96f75df8318d52925d0a6ad16c432470f5a25340 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 13 Jan 2015 10:09:05 -0800 Subject: [PATCH 080/159] Add missing model properties to entity property window --- examples/html/entityProperties.html | 35 +++++++++++++++++++++++++++-- examples/html/style.css | 7 +++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index d7f097966a..c23a3cd5ab 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -31,8 +31,13 @@ } function createEmitTextPropertyUpdateFunction(propertyName) { return function() { + var properties = {}; + properties[propertyName] = this.value; EventBridge.emitWebEvent( - '{ "type":"update", "properties":{"' + propertyName + '":"' + this.value + '"}}' + JSON.stringify({ + type: "update", + properties: properties, + }) ); }; } @@ -146,6 +151,9 @@ var elModelAnimationPlaying = document.getElementById("property-model-animation-playing"); var elModelAnimationFPS = document.getElementById("property-model-animation-fps"); var elModelAnimationFrame = document.getElementById("property-model-animation-frame"); + var elModelAnimationSettings = document.getElementById("property-model-animation-settings"); + var elModelTextures = document.getElementById("property-model-textures"); + var elModelOriginalTextures = document.getElementById("property-model-original-textures"); var elTextSections = document.querySelectorAll(".text-section"); var elTextText = document.getElementById("property-text-text"); @@ -244,6 +252,10 @@ elModelAnimationURL.value = properties.animationURL; elModelAnimationPlaying.checked = properties.animationIsPlaying; elModelAnimationFPS.value = properties.animationFPS; + elModelAnimationFrame.value = properties.animationFrameIndex; + elModelAnimationSettings.value = properties.animationSettings; + elModelTextures.value = properties.textures; + elModelOriginalTextures.value = properties.originalTextures; } if (properties.type != "Text") { @@ -387,6 +399,8 @@ elModelAnimationPlaying.addEventListener('change', createEmitCheckedPropertyUpdateFunction('animationIsPlaying')); elModelAnimationFPS.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFPS')); elModelAnimationFrame.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFrameIndex')); + elModelAnimationSettings.addEventListener('change', createEmitTextPropertyUpdateFunction('animationSettings')); + elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures')); elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text')); elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight')); @@ -429,7 +443,6 @@ })); }); - var resizing = false; var startX = 0; var originalWidth = 0; @@ -679,6 +692,24 @@ + + Animation Settings + + + + + + Textures + + + + + + Original Textures + + + + diff --git a/examples/html/style.css b/examples/html/style.css index 2f43b1c356..7ffbacb15e 100644 --- a/examples/html/style.css +++ b/examples/html/style.css @@ -90,12 +90,17 @@ input[type=button] { font-size: .9em; } -input { +textarea, input { padding: 2px; border: 1px solid #999; background-color: #eee; } +textarea { + width: 100%; + resize: vertical; +} + input.url { width: 100%; } From 00f7bf7efeb58646bbc376b234c0bee3dae98330 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 13 Jan 2015 10:12:15 -0800 Subject: [PATCH 081/159] Remove 'Edit Properties...' in favor of properties window --- examples/editEntities.js | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index 2462c30854..172089ed62 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -662,8 +662,6 @@ 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")) { print("no delete... adding ours"); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete", @@ -674,7 +672,7 @@ function setupModelMenus() { } Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." }); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Model List..." }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L", afterItem: "Paste Models", isCheckable: true, isChecked: true }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S", @@ -696,7 +694,6 @@ setupModelMenus(); // do this when first running our script. function cleanupModelMenus() { Menu.removeSeparator("Edit", "Models"); - Menu.removeMenuItem("Edit", "Edit Properties..."); if (modelMenuAddedDelete) { // delete our menuitems Menu.removeMenuItem("Edit", "Delete"); @@ -798,22 +795,6 @@ function handeMenuEvent(menuItem) { MyAvatar.position = selectedModel.properties.position; } } - } else if (menuItem == "Edit Properties...") { - // good place to put the properties dialog - - editModelID = -1; - if (selectionManager.selections.length == 1) { - print(" Edit Properties.... selectedEntityID="+ selectedEntityID); - editModelID = selectionManager.selections[0]; - } else { - print(" Edit Properties.... not holding..."); - } - if (editModelID != -1) { - print(" Edit Properties.... about to edit properties..."); - entityPropertyDialogBox.openDialog(editModelID); - selectionManager._update(); - } - } else if (menuItem == "Paste Models") { modelImporter.paste(); } else if (menuItem == "Export Models") { @@ -841,9 +822,6 @@ Controller.keyPressEvent.connect(function(event) { 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..."); - } if (event.text == "BACKSPACE" || event.text == "DELETE") { handeMenuEvent("Delete"); } else if (event.text == "TAB") { From 522e7698a558845b3290076d10367fc06baea705 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 13 Jan 2015 10:23:00 -0800 Subject: [PATCH 082/159] first step factorizing the packDeferredFragment --- libraries/render-utils/src/DeferredBufferWrite.slh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index 32822af2cb..8a547315cd 100755 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -18,7 +18,7 @@ uniform float glowIntensity; uniform float alphaThreshold; */ -void packFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) { +void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) { // gl_FragData[0] = vec4(diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[0] = vec4(diffuse.rgb, alpha); gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); From d8170516ff8d17db596d122bbaa04f95bef28fb8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 13 Jan 2015 11:05:51 -0800 Subject: [PATCH 083/159] Remove VoxelServer.cpp kept during merge --- assignment-client/src/voxels/VoxelServer.cpp | 102 ------------------- 1 file changed, 102 deletions(-) delete mode 100644 assignment-client/src/voxels/VoxelServer.cpp diff --git a/assignment-client/src/voxels/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp deleted file mode 100644 index eb7eff4930..0000000000 --- a/assignment-client/src/voxels/VoxelServer.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// -// VoxelServer.cpp -// assignment-client/src/voxels -// -// Created by Brad Hefta-Gaub on 9/16/13. -// Copyright 2013 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 - -#include "VoxelServer.h" -#include "VoxelServerConsts.h" -#include "VoxelNodeData.h" - -const char* VOXEL_SERVER_NAME = "Voxel"; -const char* VOXEL_SERVER_LOGGING_TARGET_NAME = "voxel-server"; -const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.svo"; - -VoxelServer::VoxelServer(const QByteArray& packet) : OctreeServer(packet) { - // nothing special to do here... -} - -VoxelServer::~VoxelServer() { - // nothing special to do here... -} - -OctreeQueryNode* VoxelServer::createOctreeQueryNode() { - return new VoxelNodeData(); -} - -Octree* VoxelServer::createTree() { - return new VoxelTree(true); -} - -bool VoxelServer::hasSpecialPacketToSend(const SharedNodePointer& node) { - bool shouldSendEnvironments = _sendEnvironments && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, OCTREE_SEND_INTERVAL_USECS); - return shouldSendEnvironments; -} - -int VoxelServer::sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent) { - - unsigned char* copyAt = _tempOutputBuffer; - - int numBytesPacketHeader = populatePacketHeader(reinterpret_cast(_tempOutputBuffer), PacketTypeEnvironmentData); - copyAt += numBytesPacketHeader; - int envPacketLength = numBytesPacketHeader; - - // pack in flags - OCTREE_PACKET_FLAGS flags = 0; - OCTREE_PACKET_FLAGS* flagsAt = (OCTREE_PACKET_FLAGS*)copyAt; - *flagsAt = flags; - copyAt += sizeof(OCTREE_PACKET_FLAGS); - envPacketLength += sizeof(OCTREE_PACKET_FLAGS); - - // pack in sequence number - OCTREE_PACKET_SEQUENCE* sequenceAt = (OCTREE_PACKET_SEQUENCE*)copyAt; - *sequenceAt = queryNode->getSequenceNumber(); - copyAt += sizeof(OCTREE_PACKET_SEQUENCE); - envPacketLength += sizeof(OCTREE_PACKET_SEQUENCE); - - // pack in timestamp - OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); - OCTREE_PACKET_SENT_TIME* timeAt = (OCTREE_PACKET_SENT_TIME*)copyAt; - *timeAt = now; - copyAt += sizeof(OCTREE_PACKET_SENT_TIME); - envPacketLength += sizeof(OCTREE_PACKET_SENT_TIME); - - int environmentsToSend = getSendMinimalEnvironment() ? 1 : getEnvironmentDataCount(); - - for (int i = 0; i < environmentsToSend; i++) { - envPacketLength += getEnvironmentData(i)->getBroadcastData(_tempOutputBuffer + envPacketLength); - } - - DependencyManager::get()->writeDatagram((char*) _tempOutputBuffer, envPacketLength, SharedNodePointer(node)); - queryNode->packetSent(_tempOutputBuffer, envPacketLength); - packetsSent = 1; - - return envPacketLength; -} - - -void VoxelServer::readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { - // should we send environments? Default is yes, but this command line suppresses sending - readOptionBool(QString("sendEnvironments"), settingsSectionObject, _sendEnvironments); - bool dontSendEnvironments = !_sendEnvironments; - if (dontSendEnvironments) { - qDebug("Sending environments suppressed..."); - } else { - // should we send environments? Default is yes, but this command line suppresses sending - //const char* MINIMAL_ENVIRONMENT = "--minimalEnvironment"; - //_sendMinimalEnvironment = cmdOptionExists(_argc, _argv, MINIMAL_ENVIRONMENT); - - readOptionBool(QString("minimalEnvironment"), settingsSectionObject, _sendMinimalEnvironment); - qDebug("Using Minimal Environment=%s", debug::valueOf(_sendMinimalEnvironment)); - } - qDebug("Sending environments=%s", debug::valueOf(_sendEnvironments)); - - DependencyManager::get()->addNodeTypeToInterestSet(NodeType::AnimationServer); -} From 4429e144f4342b0427976c27511f505899c6bd0f Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 13 Jan 2015 11:10:13 -0800 Subject: [PATCH 084/159] Fix merge accidental code delete --- interface/src/ui/ApplicationOverlay.cpp | 14 ++++++++++++++ interface/src/ui/ApplicationOverlay.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 9381ad48f8..2c5cc5b267 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -950,6 +950,20 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { if (nodeList && !nodeList->getDomainHandler().isConnected()) { auto glCanvas = DependencyManager::get(); auto geometryCache = DependencyManager::get(); + int width = glCanvas->width(); + int height = glCanvas->height(); + + if (width != _previousBorderWidth || height != _previousBorderHeight) { + QVector border; + border << glm::vec2(0, 0); + border << glm::vec2(0, height); + border << glm::vec2(width, height); + border << glm::vec2(width, 0); + border << glm::vec2(0, 0); + geometryCache->updateVertices(_domainStatusBorder, border); + _previousBorderWidth = width; + _previousBorderHeight = height; + } glColor3f(CONNECTION_STATUS_BORDER_COLOR[0], CONNECTION_STATUS_BORDER_COLOR[1], diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index b20172f3f9..e2094f2a8e 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -116,6 +116,9 @@ private: int _domainStatusBorder; int _magnifierBorder; + int _previousBorderWidth; + int _previousBorderHeight; + glm::vec3 _previousMagnifierBottomLeft; glm::vec3 _previousMagnifierBottomRight; glm::vec3 _previousMagnifierTopLeft; From 60aec8ac000887b648a97305b3fd123944c85ca3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 13 Jan 2015 13:41:32 -0800 Subject: [PATCH 085/159] add support for multiple backup rules --- assignment-client/src/octree/OctreeServer.cpp | 21 +- assignment-client/src/octree/OctreeServer.h | 1 + .../resources/describe-settings.json | 88 ++++---- libraries/octree/src/OctreePersistThread.cpp | 204 +++++++++++------- libraries/octree/src/OctreePersistThread.h | 33 +-- 5 files changed, 200 insertions(+), 147 deletions(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index cb206f626e..3ac094ff7a 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include #include #include @@ -978,6 +979,7 @@ void OctreeServer::readConfiguration() { const QJsonObject& settingsObject = domainHandler.getSettingsObject(); QString settingsKey = getMyDomainSettingsKey(); QJsonObject settingsSectionObject = settingsObject[settingsKey].toObject(); + _settings = settingsSectionObject; // keep this for later if (!readOptionString(QString("statusHost"), settingsSectionObject, _statusHost) || _statusHost.isEmpty()) { _statusHost = getLocalAddress().toString(); @@ -1042,20 +1044,8 @@ void OctreeServer::readConfiguration() { _wantBackup = !noBackup; qDebug() << "wantBackup=" << _wantBackup; - if (_wantBackup) { - _backupExtensionFormat = OctreePersistThread::DEFAULT_BACKUP_EXTENSION_FORMAT; - readOptionString(QString("backupExtensionFormat"), settingsSectionObject, _backupExtensionFormat); - qDebug() << "backupExtensionFormat=" << _backupExtensionFormat; - - _backupInterval = OctreePersistThread::DEFAULT_BACKUP_INTERVAL; - readOptionInt(QString("backupInterval"), settingsSectionObject, _backupInterval); - qDebug() << "backupInterval=" << _backupInterval; - - _maxBackupVersions = OctreePersistThread::DEFAULT_MAX_BACKUP_VERSIONS; - readOptionInt(QString("maxBackupVersions"), settingsSectionObject, _maxBackupVersions); - qDebug() << "maxBackupVersions=" << _maxBackupVersions; - } - + //qDebug() << "settingsSectionObject:" << settingsSectionObject; + } else { qDebug("persistFilename= DISABLED"); } @@ -1140,8 +1130,7 @@ void OctreeServer::run() { // now set up PersistThread _persistThread = new OctreePersistThread(_tree, _persistFilename, _persistInterval, - _wantBackup, _backupInterval, _backupExtensionFormat, - _maxBackupVersions, _debugTimestampNow); + _wantBackup, _settings, _debugTimestampNow); if (_persistThread) { _persistThread->initialize(true); } diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index a467a8a650..0f90c2941e 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -150,6 +150,7 @@ protected: int _argc; const char** _argv; char** _parsedArgV; + QJsonObject _settings; HTTPManager* _httpManager; int _statusPort; diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 3435f49b71..3ee62634c8 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -308,70 +308,86 @@ "label": "Persistant Filename", "help": "the filename for your entities", "placeholder": "resources/models.svo", - "default": "resources/models.svo", - "advanced": true + "default": "resources/models.svo" }, { "name": "persistInterval", "label": "Persist Interval", "help": "Interval between persist checks in msecs.", "placeholder": "30000", - "default": "30000", - "advanced": true + "default": "30000" + }, + { + "name": "backups", + "type": "table", + "label": "Backup Rules", + "help": "In this table you can define a set of rules for how frequently to backup copies of your content file.", + "numbered": false, + "default": [ + {"Name":"Half Hourly Rolling","backupInterval":1800,"format":".backup.halfhourly.%N","maxBackupVersions":5}, + {"Name":"Daily Rolling","backupInterval":86400,"format":".backup.daily.%N","maxBackupVersions":7}, + {"Name":"Weekly Rolling","backupInterval":604800,"format":".backup.weekly.%N","maxBackupVersions":4}, + {"Name":"Thirty Day Rolling","backupInterval":2592000,"format":".backup.thirtyday.%N","maxBackupVersions":12} + ], + "columns": [ + { + "name": "Name", + "label": "Name", + "can_set": true, + "placeholder": "Example", + "default": "Example" + }, + { + "name": "format", + "label": "Rule Format", + "can_set": true, + "help": "Format used to create the extension for the backup of your persisted entities. Use a format with %N to get rolling. Or use date formatting like %Y-%m-%d.%H:%M:%S.%z", + "placeholder": ".backup.example.%N", + "default": ".backup.example.%N" + }, + { + "name": "backupInterval", + "label": "Backup Interval", + "help": "Interval between backup checks in seconds.", + "placeholder": 1800, + "default": 1800, + "can_set": true + }, + { + "name": "maxBackupVersions", + "label": "Max Rolled Backup Versions", + "help": "If your backup extension format uses 'rolling', how many versions do you want us to keep?", + "placeholder": 5, + "default": 5, + "can_set": true + } + ] }, { "name": "NoPersist", "type": "checkbox", "help": "Don't persist your entities to a file.", - "default": false, - "advanced": true - }, - { - "name": "backupExtensionFormat", - "label": "Backup File Extension Format:", - "help": "Format used to create the extension for the backup of your persisted entities. Use a format with %N to get rolling. Or use date formatting like %Y-%m-%d.%H:%M:%S.%z", - "placeholder": ".backup.%N", - "default": ".backup.%N", - "advanced": true - }, - { - "name": "backupInterval", - "label": "Backup Interval", - "help": "Interval between backup checks in msecs.", - "placeholder": "1800000", - "default": "1800000", - "advanced": true - }, - { - "name": "maxBackupVersions", - "label": "Max Rolled Backup Versions", - "help": "If your backup extension format uses 'rolling', how many versions do you want us to keep?", - "placeholder": "5", - "default": "5", - "advanced": true + "default": false }, { "name": "NoBackup", "type": "checkbox", "help": "Don't regularly backup your persisted entities to a backup file.", - "default": false, - "advanced": true + "default": false }, { "name": "statusHost", "label": "Status Hostname", "help": "host name or IP address of the server for accessing the status page", "placeholder": "", - "default": "", - "advanced": true + "default": "" }, { "name": "statusPort", "label": "Status Port", "help": "port of the server for accessing the status page", "placeholder": "", - "default": "", - "advanced": true + "default": "" }, { "name": "verboseDebug", diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index 79469ade1f..9b54a3ab25 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include @@ -25,38 +27,68 @@ #include "OctreePersistThread.h" const int OctreePersistThread::DEFAULT_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds -const int OctreePersistThread::DEFAULT_BACKUP_INTERVAL = 1000 * 60 * 30; // every 30 minutes -const QString OctreePersistThread::DEFAULT_BACKUP_EXTENSION_FORMAT(".backup.%N"); -const int OctreePersistThread::DEFAULT_MAX_BACKUP_VERSIONS = 5; - OctreePersistThread::OctreePersistThread(Octree* tree, const QString& filename, int persistInterval, - bool wantBackup, int backupInterval, const QString& backupExtensionFormat, - int maxBackupVersions, bool debugTimestampNow) : + bool wantBackup, const QJsonObject& settings, bool debugTimestampNow) : _tree(tree), _filename(filename), - _backupExtensionFormat(backupExtensionFormat), - _maxBackupVersions(maxBackupVersions), _persistInterval(persistInterval), - _backupInterval(backupInterval), _initialLoadComplete(false), _loadTimeUSecs(0), _lastCheck(0), - _lastBackup(0), _wantBackup(wantBackup), _debugTimestampNow(debugTimestampNow), _lastTimeDebug(0) { + parseSettings(settings); } -quint64 OctreePersistThread::getMostRecentBackupTimeInUsecs() { +void OctreePersistThread::parseSettings(const QJsonObject& settings) { + qDebug() << "settings[backups]:" << settings["backups"]; + + if (settings["backups"].isArray()) { + const QJsonArray& backupRules = settings["backups"].toArray(); + qDebug() << "BACKUP RULES:" << backupRules; + + foreach (const QJsonValue& value, backupRules) { + QJsonObject obj = value.toObject(); + qDebug() << " Name:" << obj["Name"].toString(); + qDebug() << " format:" << obj["format"].toString(); + qDebug() << " interval:" << obj["backupInterval"].toInt(); + qDebug() << " count:" << obj["maxBackupVersions"].toInt(); + + BackupRule newRule = { obj["Name"].toString(), obj["backupInterval"].toInt(), + obj["format"].toString(), obj["maxBackupVersions"].toInt(), 0}; + + newRule.lastBackup = getMostRecentBackupTimeInUsecs(obj["format"].toString()); + + if (newRule.lastBackup > 0) { + quint64 now = usecTimestampNow(); + quint64 sinceLastBackup = now - newRule.lastBackup; + qDebug() << " now:" << now; + qDebug() << "newRule.lastBackup:" << newRule.lastBackup; + qDebug() << " sinceLastBackup:" << sinceLastBackup; + + qDebug() << " lastBackup:" << qPrintable(formatUsecTime(sinceLastBackup)) << "ago"; + } else { + qDebug() << " lastBackup: NEVER"; + } + + _backupRules << newRule; + } + } else { + qDebug() << "BACKUP RULES: NONE"; + } +} + +quint64 OctreePersistThread::getMostRecentBackupTimeInUsecs(const QString& format) { quint64 mostRecentBackupInUsecs = 0; QString mostRecentBackupFileName; QDateTime mostRecentBackupTime; - bool recentBackup = getMostRecentBackup(mostRecentBackupFileName, mostRecentBackupTime); + bool recentBackup = getMostRecentBackup(format, mostRecentBackupFileName, mostRecentBackupTime); if (recentBackup) { mostRecentBackupInUsecs = mostRecentBackupTime.toMSecsSinceEpoch() * USECS_PER_MSEC; @@ -130,12 +162,6 @@ bool OctreePersistThread::process() { // Since we just loaded the persistent file, we can consider ourselves as having "just checked" for persistance. _lastCheck = usecTimestampNow(); // we just loaded, no need to save again - // The last backup time, should be the timestamp for most recent backup file. - _lastBackup = getMostRecentBackupTimeInUsecs(); - - qDebug() << "Last Check:" << qPrintable(formatUsecTime(usecTimestampNow() - _lastCheck)) << "ago..."; - qDebug() << "Last Backup:" << qPrintable(formatUsecTime(usecTimestampNow() - _lastBackup)) << "ago..."; - // This last persist time is not really used until the file is actually persisted. It is only // used in formatting the backup filename in cases of non-rolling backup names. However, we don't // want an uninitialized value for this, so we set it to the current time (startup of the server) @@ -226,7 +252,7 @@ void OctreePersistThread::restoreFromMostRecentBackup() { QString mostRecentBackupFileName; QDateTime mostRecentBackupTime; - bool recentBackup = getMostRecentBackup(mostRecentBackupFileName, mostRecentBackupTime); + bool recentBackup = getMostRecentBackup(QString(""), mostRecentBackupFileName, mostRecentBackupTime); // If we found a backup file, restore from that file. if (recentBackup) { @@ -247,27 +273,31 @@ void OctreePersistThread::restoreFromMostRecentBackup() { } } -bool OctreePersistThread::getMostRecentBackup(QString& mostRecentBackupFileName, QDateTime& mostRecentBackupTime) { +bool OctreePersistThread::getMostRecentBackup(const QString& format, + QString& mostRecentBackupFileName, QDateTime& mostRecentBackupTime) { // Based on our backup file name, determine the path and file name pattern for backup files QFileInfo persistFileInfo(_filename); QString path = persistFileInfo.path(); QString fileNamePart = persistFileInfo.fileName(); - // Create a file filter that will find all backup files of this extension format - QString backupExtension = _backupExtensionFormat; - - if (_backupExtensionFormat.contains("%N")) { - backupExtension.replace(QString("%N"), "*"); + QStringList filters; + + if (format.isEmpty()) { + // Create a file filter that will find all backup files of this extension format + foreach(const BackupRule& rule, _backupRules) { + QString backupExtension = rule.extensionFormat; + backupExtension.replace(QRegExp("%."), "*"); + QString backupFileNamePart = fileNamePart + backupExtension; + filters << backupFileNamePart; + } } else { - qDebug() << "This backup extension format does not yet support restoring from most recent backup..."; - return false; // exit early, unable to restore from backup + QString backupExtension = format; + backupExtension.replace(QRegExp("%."), "*"); + QString backupFileNamePart = fileNamePart + backupExtension; + filters << backupFileNamePart; } - QString backupFileNamePart = fileNamePart + backupExtension; - QStringList filters; - filters << backupFileNamePart; - bool bestBackupFound = false; QString bestBackupFile; QDateTime bestBackupFileTime; @@ -295,74 +325,88 @@ bool OctreePersistThread::getMostRecentBackup(QString& mostRecentBackupFileName, return bestBackupFound; } -void OctreePersistThread::rollOldBackupVersions() { - if (!_backupExtensionFormat.contains("%N")) { - return; // this backup extension format doesn't support rolling - } +void OctreePersistThread::rollOldBackupVersions(const BackupRule& rule) { - qDebug() << "Rolling old backup versions..."; - for(int n = _maxBackupVersions - 1; n > 0; n--) { - QString backupExtensionN = _backupExtensionFormat; - QString backupExtensionNplusOne = _backupExtensionFormat; - backupExtensionN.replace(QString("%N"), QString::number(n)); - backupExtensionNplusOne.replace(QString("%N"), QString::number(n+1)); - - QString backupFilenameN = _filename + backupExtensionN; - QString backupFilenameNplusOne = _filename + backupExtensionNplusOne; + if (rule.extensionFormat.contains("%N")) { + qDebug() << "Rolling old backup versions for rule" << rule.name << "..."; + for(int n = rule.maxBackupVersions - 1; n > 0; n--) { + QString backupExtensionN = rule.extensionFormat; + QString backupExtensionNplusOne = rule.extensionFormat; + backupExtensionN.replace(QString("%N"), QString::number(n)); + backupExtensionNplusOne.replace(QString("%N"), QString::number(n+1)); + + QString backupFilenameN = _filename + backupExtensionN; + QString backupFilenameNplusOne = _filename + backupExtensionNplusOne; - QFile backupFileN(backupFilenameN); + QFile backupFileN(backupFilenameN); - if (backupFileN.exists()) { - qDebug() << "rolling backup file " << backupFilenameN << "to" << backupFilenameNplusOne << "..."; - int result = rename(qPrintable(backupFilenameN), qPrintable(backupFilenameNplusOne)); - if (result == 0) { - qDebug() << "DONE rolling backup file " << backupFilenameN << "to" << backupFilenameNplusOne << "..."; - } else { - qDebug() << "ERROR in rolling backup file " << backupFilenameN << "to" << backupFilenameNplusOne << "..."; + if (backupFileN.exists()) { + qDebug() << "rolling backup file " << backupFilenameN << "to" << backupFilenameNplusOne << "..."; + int result = rename(qPrintable(backupFilenameN), qPrintable(backupFilenameNplusOne)); + if (result == 0) { + qDebug() << "DONE rolling backup file " << backupFilenameN << "to" << backupFilenameNplusOne << "..."; + } else { + qDebug() << "ERROR in rolling backup file " << backupFilenameN << "to" << backupFilenameNplusOne << "..."; + } } } + qDebug() << "Done rolling old backup versions..."; } - qDebug() << "Done rolling old backup versions..."; } void OctreePersistThread::backup() { if (_wantBackup) { quint64 now = usecTimestampNow(); - quint64 sinceLastBackup = now - _lastBackup; - quint64 MSECS_TO_USECS = 1000; - quint64 intervalToBackup = _backupInterval * MSECS_TO_USECS; + qDebug() << "OctreePersistThread::backup() - now:" << now; - if (sinceLastBackup > intervalToBackup) { - qDebug() << "Time since last backup [" << sinceLastBackup << "] exceeds backup interval [" - << intervalToBackup << "] doing backup now..."; + // TODO: add a loop over all backup rules, we need to keep track of the last backup for each rule + // because we need to know when each backup rule has "elapsed" + for(int i = 0; i < _backupRules.count(); i++) { + BackupRule& rule = _backupRules[i]; - struct tm* localTime = localtime(&_lastPersistTime); + quint64 sinceLastBackup = now - rule.lastBackup; - QString backupFileName; + qDebug() << " now:" << now; + qDebug() << "newRule.lastBackup:" << rule.lastBackup; + qDebug() << " sinceLastBackup:" << sinceLastBackup; + + qDebug() << " lastBackup:" << qPrintable(formatUsecTime(sinceLastBackup)) << "ago"; + + quint64 SECS_TO_USECS = 1000 * 1000; + quint64 intervalToBackup = rule.interval * SECS_TO_USECS; + + if (sinceLastBackup > intervalToBackup) { + qDebug() << "Time since last backup [" << sinceLastBackup << "] for rule [" << rule.name + << "] exceeds backup interval [" << intervalToBackup << "] doing backup now..."; + + struct tm* localTime = localtime(&_lastPersistTime); + + QString backupFileName; - // check to see if they asked for version rolling format - if (_backupExtensionFormat.contains("%N")) { - rollOldBackupVersions(); // rename all the old backup files accordingly - QString backupExtension = _backupExtensionFormat; - backupExtension.replace(QString("%N"), QString("1")); - backupFileName = _filename + backupExtension; - } else { - char backupExtension[256]; - strftime(backupExtension, sizeof(backupExtension), qPrintable(_backupExtensionFormat), localTime); - backupFileName = _filename + backupExtension; - } + // check to see if they asked for version rolling format + if (rule.extensionFormat.contains("%N")) { + rollOldBackupVersions(rule); // rename all the old backup files accordingly + QString backupExtension = rule.extensionFormat; + backupExtension.replace(QString("%N"), QString("1")); + backupFileName = _filename + backupExtension; + } else { + char backupExtension[256]; + strftime(backupExtension, sizeof(backupExtension), qPrintable(rule.extensionFormat), localTime); + backupFileName = _filename + backupExtension; + } - qDebug() << "backing up persist file " << _filename << "to" << backupFileName << "..."; - int result = rename(qPrintable(_filename), qPrintable(backupFileName)); - if (result == 0) { - qDebug() << "DONE backing up persist file..."; - } else { - qDebug() << "ERROR in backing up persist file..."; - } + qDebug() << "backing up persist file " << _filename << "to" << backupFileName << "..."; + bool result = QFile::copy(_filename, backupFileName); + if (result) { + qDebug() << "DONE backing up persist file..."; + } else { + qDebug() << "ERROR in backing up persist file..."; + } - _lastBackup = now; + rule.lastBackup = now; + } } } } diff --git a/libraries/octree/src/OctreePersistThread.h b/libraries/octree/src/OctreePersistThread.h index 6f08b63197..374de79f0a 100644 --- a/libraries/octree/src/OctreePersistThread.h +++ b/libraries/octree/src/OctreePersistThread.h @@ -22,15 +22,19 @@ class OctreePersistThread : public GenericThread { Q_OBJECT public: + class BackupRule { + public: + QString name; + int interval; + QString extensionFormat; + int maxBackupVersions; + quint64 lastBackup; + }; + static const int DEFAULT_PERSIST_INTERVAL; - static const int DEFAULT_BACKUP_INTERVAL; - static const QString DEFAULT_BACKUP_EXTENSION_FORMAT; - static const int DEFAULT_MAX_BACKUP_VERSIONS; OctreePersistThread(Octree* tree, const QString& filename, int persistInterval = DEFAULT_PERSIST_INTERVAL, - bool wantBackup = false, int backupInterval = DEFAULT_BACKUP_INTERVAL, - const QString& backupExtensionFormat = DEFAULT_BACKUP_EXTENSION_FORMAT, - int maxBackupVersions = DEFAULT_MAX_BACKUP_VERSIONS, + bool wantBackup = false, const QJsonObject& settings = QJsonObject(), bool debugTimestampNow = false); bool isInitialLoadComplete() const { return _initialLoadComplete; } @@ -47,25 +51,24 @@ protected: void persist(); void backup(); - void rollOldBackupVersions(); + void rollOldBackupVersions(const BackupRule& rule); void restoreFromMostRecentBackup(); - bool getMostRecentBackup(QString& mostRecentBackupFileName, QDateTime& mostRecentBackupTime); - quint64 getMostRecentBackupTimeInUsecs(); + bool getMostRecentBackup(const QString& format, QString& mostRecentBackupFileName, QDateTime& mostRecentBackupTime); + quint64 getMostRecentBackupTimeInUsecs(const QString& format); + void parseSettings(const QJsonObject& settings); private: Octree* _tree; QString _filename; - QString _backupExtensionFormat; - int _maxBackupVersions; int _persistInterval; - int _backupInterval; bool _initialLoadComplete; quint64 _loadTimeUSecs; - quint64 _lastCheck; - quint64 _lastBackup; - bool _wantBackup; + time_t _lastPersistTime; + quint64 _lastCheck; + bool _wantBackup; + QVector _backupRules; bool _debugTimestampNow; quint64 _lastTimeDebug; From 0e19e1f8a5a982abd37701b096134eb94a12508e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 13 Jan 2015 13:48:28 -0800 Subject: [PATCH 086/159] cleanup some dead code --- libraries/octree/src/OctreePersistThread.cpp | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index 9b54a3ab25..f0612cc9b1 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -44,11 +44,9 @@ OctreePersistThread::OctreePersistThread(Octree* tree, const QString& filename, } void OctreePersistThread::parseSettings(const QJsonObject& settings) { - qDebug() << "settings[backups]:" << settings["backups"]; - if (settings["backups"].isArray()) { const QJsonArray& backupRules = settings["backups"].toArray(); - qDebug() << "BACKUP RULES:" << backupRules; + qDebug() << "BACKUP RULES:"; foreach (const QJsonValue& value, backupRules) { QJsonObject obj = value.toObject(); @@ -65,10 +63,6 @@ void OctreePersistThread::parseSettings(const QJsonObject& settings) { if (newRule.lastBackup > 0) { quint64 now = usecTimestampNow(); quint64 sinceLastBackup = now - newRule.lastBackup; - qDebug() << " now:" << now; - qDebug() << "newRule.lastBackup:" << newRule.lastBackup; - qDebug() << " sinceLastBackup:" << sinceLastBackup; - qDebug() << " lastBackup:" << qPrintable(formatUsecTime(sinceLastBackup)) << "ago"; } else { qDebug() << " lastBackup: NEVER"; @@ -235,9 +229,6 @@ void OctreePersistThread::persist() { _tree->clearDirtyBit(); // tree is clean after saving qDebug() << "DONE saving Octree to file..."; - // force crash - //assert(false); - lockFile.close(); qDebug() << "saving Octree lock file closed:" << lockFileName; remove(qPrintable(lockFileName)); @@ -358,21 +349,12 @@ void OctreePersistThread::rollOldBackupVersions(const BackupRule& rule) { void OctreePersistThread::backup() { if (_wantBackup) { quint64 now = usecTimestampNow(); - qDebug() << "OctreePersistThread::backup() - now:" << now; - // TODO: add a loop over all backup rules, we need to keep track of the last backup for each rule - // because we need to know when each backup rule has "elapsed" for(int i = 0; i < _backupRules.count(); i++) { BackupRule& rule = _backupRules[i]; quint64 sinceLastBackup = now - rule.lastBackup; - qDebug() << " now:" << now; - qDebug() << "newRule.lastBackup:" << rule.lastBackup; - qDebug() << " sinceLastBackup:" << sinceLastBackup; - - qDebug() << " lastBackup:" << qPrintable(formatUsecTime(sinceLastBackup)) << "ago"; - quint64 SECS_TO_USECS = 1000 * 1000; quint64 intervalToBackup = rule.interval * SECS_TO_USECS; From dcca5d532aae3b2dbbe5d5a094fe24c1c6874b52 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 13 Jan 2015 14:00:37 -0800 Subject: [PATCH 087/159] fix for glitchy physics updates The main problem was: ObjectMotionState::_sentPosition and friends were not being updated when the EntityServer update arrives. --- libraries/entities/src/EntityItem.cpp | 2 +- libraries/physics/src/EntityMotionState.cpp | 62 +++++++++++++++++---- libraries/physics/src/EntityMotionState.h | 4 +- libraries/physics/src/ObjectMotionState.cpp | 6 +- libraries/physics/src/ObjectMotionState.h | 7 ++- libraries/physics/src/PhysicsEngine.cpp | 46 ++++----------- libraries/physics/src/PhysicsEngine.h | 6 -- 7 files changed, 71 insertions(+), 62 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 76045d9c15..a18f8fc71d 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1000,7 +1000,7 @@ void EntityItem::recalculateCollisionShape() { const float MIN_POSITION_DELTA = 0.0001f; const float MIN_ALIGNMENT_DOT = 0.9999f; const float MIN_MASS_DELTA = 0.001f; -const float MIN_VELOCITY_DELTA = 0.025f; +const float MIN_VELOCITY_DELTA = 0.01f; const float MIN_DAMPING_DELTA = 0.001f; const float MIN_GRAVITY_DELTA = 0.001f; const float MIN_SPIN_DELTA = 0.0003f; diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 7aa43f944c..019f00fb48 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -79,21 +79,59 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { } #endif // USE_BULLET_PHYSICS -void EntityMotionState::applyVelocities() const { +void EntityMotionState::updateObjectEasy(uint32_t flags, uint32_t frame) { #ifdef USE_BULLET_PHYSICS - if (_body) { - setVelocity(_entity->getVelocityInMeters()); - // DANGER! EntityItem stores angularVelocity in degrees/sec!!! - setAngularVelocity(glm::radians(_entity->getAngularVelocity())); - _body->setActivationState(ACTIVE_TAG); - } -#endif // USE_BULLET_PHYSICS -} + if (flags & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY)) { + if (flags & EntityItem::DIRTY_POSITION) { + _sentPosition = _entity->getPositionInMeters() - ObjectMotionState::getWorldOffset(); + btTransform worldTrans; + worldTrans.setOrigin(glmToBullet(_sentPosition)); -void EntityMotionState::applyGravity() const { + _sentRotation = _entity->getRotation(); + worldTrans.setRotation(glmToBullet(_sentRotation)); + + _body->setWorldTransform(worldTrans); + } + if (flags & EntityItem::DIRTY_VELOCITY) { + updateObjectVelocities(); + } + _sentFrame = frame; + } + + // TODO: entity support for friction and restitution + //_restitution = _entity->getRestitution(); + _body->setRestitution(_restitution); + //_friction = _entity->getFriction(); + _body->setFriction(_friction); + + _linearDamping = _entity->getDamping(); + _angularDamping = _entity->getAngularDamping(); + _body->setDamping(_linearDamping, _angularDamping); + + if (flags & EntityItem::DIRTY_MASS) { + float mass = getMass(); + btVector3 inertia(0.0f, 0.0f, 0.0f); + _body->getCollisionShape()->calculateLocalInertia(mass, inertia); + _body->setMassProps(mass, inertia); + _body->updateInertiaTensor(); + } + _body->activate(); +#endif // USE_BULLET_PHYSICS +}; + +void EntityMotionState::updateObjectVelocities() { #ifdef USE_BULLET_PHYSICS if (_body) { - setGravity(_entity->getGravityInMeters()); + _sentVelocity = _entity->getVelocityInMeters(); + setVelocity(_sentVelocity); + + // DANGER! EntityItem stores angularVelocity in degrees/sec!!! + _sentAngularVelocity = glm::radians(_entity->getAngularVelocity()); + setAngularVelocity(_sentAngularVelocity); + + _sentAcceleration = _entity->getGravityInMeters(); + setGravity(_sentAcceleration); + _body->setActivationState(ACTIVE_TAG); } #endif // USE_BULLET_PHYSICS @@ -123,7 +161,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ _sentAngularVelocity = bulletToGLM(_body->getAngularVelocity()); // if the speeds are very small we zero them out - const float MINIMUM_EXTRAPOLATION_SPEED_SQUARED = 4.0e-6f; // 2mm/sec + const float MINIMUM_EXTRAPOLATION_SPEED_SQUARED = 1.0e-4f; // 1cm/sec bool zeroSpeed = (glm::length2(_sentVelocity) < MINIMUM_EXTRAPOLATION_SPEED_SQUARED); if (zeroSpeed) { _sentVelocity = glm::vec3(0.0f); diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 379470087f..863edebe7d 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -54,8 +54,8 @@ public: #endif // USE_BULLET_PHYSICS // these relay incoming values to the RigidBody - void applyVelocities() const; - void applyGravity() const; + void updateObjectEasy(uint32_t flags, uint32_t frame); + void updateObjectVelocities(); void computeShapeInfo(ShapeInfo& info); diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index 46c67c0ec2..6e0b2a784c 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -123,9 +123,9 @@ bool ObjectMotionState::doesNotNeedToSendUpdate() const { const float FIXED_SUBSTEP = 1.0f / 60.0f; -bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame, float subStepRemainder) { +bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame) { assert(_body); - float dt = (float)(simulationFrame - _sentFrame) * FIXED_SUBSTEP + subStepRemainder; + float dt = (float)(simulationFrame - _sentFrame) * FIXED_SUBSTEP; _sentFrame = simulationFrame; bool isActive = _body->isActive(); @@ -183,7 +183,7 @@ bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame, float subStep } const float MIN_ROTATION_DOT = 0.98f; glm::quat actualRotation = bulletToGLM(worldTrans.getRotation()); - return (glm::dot(actualRotation, _sentRotation) < MIN_ROTATION_DOT); + return (fabsf(glm::dot(actualRotation, _sentRotation)) < MIN_ROTATION_DOT); } #endif // USE_BULLET_PHYSICS diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index cb19babc1d..b9d077f4bb 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -56,8 +56,9 @@ public: ObjectMotionState(); ~ObjectMotionState(); - virtual void applyVelocities() const = 0; - virtual void applyGravity() const = 0; + // An EASY update does not require the object to be removed and then reinserted into the PhysicsEngine + virtual void updateObjectEasy(uint32_t flags, uint32_t frame) = 0; + virtual void updateObjectVelocities() = 0; virtual void computeShapeInfo(ShapeInfo& info) = 0; @@ -84,7 +85,7 @@ public: void clearOutgoingPacketFlags(uint32_t flags) { _outgoingPacketFlags &= ~flags; } bool doesNotNeedToSendUpdate() const; - virtual bool shouldSendUpdate(uint32_t simulationFrame, float subStepRemainder); + virtual bool shouldSendUpdate(uint32_t simulationFrame); virtual void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame) = 0; virtual MotionType computeMotionType() const = 0; diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 4129f1c7b0..666fcd2e89 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -41,14 +41,12 @@ void PhysicsEngine::updateEntitiesInternal(const quint64& now) { // this is step (4) QSet::iterator stateItr = _outgoingPackets.begin(); - uint32_t frame = getFrameCount(); - float subStepRemainder = getSubStepRemainder(); while (stateItr != _outgoingPackets.end()) { ObjectMotionState* state = *stateItr; if (state->doesNotNeedToSendUpdate()) { stateItr = _outgoingPackets.erase(stateItr); - } else if (state->shouldSendUpdate(frame, subStepRemainder)) { - state->sendUpdate(_entityPacketSender, frame); + } else if (state->shouldSendUpdate(_frameCount)) { + state->sendUpdate(_entityPacketSender, _frameCount); ++stateItr; } else { ++stateItr; @@ -140,7 +138,8 @@ void PhysicsEngine::relayIncomingChangesToSimulation() { updateObjectHard(body, motionState, flags); } else if (flags) { // an EASY update does NOT require that the body be pulled out of physics engine - updateObjectEasy(body, motionState, flags); + // hence the MotionState has all the knowledge and authority to perform the update. + motionState->updateObjectEasy(flags, _frameCount); } } @@ -269,8 +268,12 @@ bool PhysicsEngine::addObject(ObjectMotionState* motionState) { body = new btRigidBody(mass, motionState, shape, inertia); body->updateInertiaTensor(); motionState->_body = body; - motionState->applyVelocities(); - motionState->applyGravity(); + motionState->updateObjectVelocities(); + // NOTE: Bullet will deactivate any object whose velocity is below these thresholds for longer than 2 seconds. + // (the 2 seconds is determined by: static btRigidBody::gDeactivationTime + const float LINEAR_VELOCITY_THRESHOLD = 0.05f; // 5 cm/sec + const float ANGULAR_VELOCITY_THRESHOLD = 0.087266f; // ~5 deg/sec + body->setSleepingThresholds(LINEAR_VELOCITY_THRESHOLD, ANGULAR_VELOCITY_THRESHOLD); break; } case MOTION_TYPE_STATIC: @@ -334,7 +337,7 @@ void PhysicsEngine::updateObjectHard(btRigidBody* body, ObjectMotionState* motio } bool easyUpdate = flags & EASY_DIRTY_PHYSICS_FLAGS; if (easyUpdate) { - updateObjectEasy(body, motionState, flags); + motionState->updateObjectEasy(flags, _frameCount); } // update the motion parameters @@ -385,31 +388,4 @@ void PhysicsEngine::updateObjectHard(btRigidBody* body, ObjectMotionState* motio body->activate(); } -// private -void PhysicsEngine::updateObjectEasy(btRigidBody* body, ObjectMotionState* motionState, uint32_t flags) { - if (flags & EntityItem::DIRTY_POSITION) { - btTransform transform; - motionState->getWorldTransform(transform); - body->setWorldTransform(transform); - } - if (flags & EntityItem::DIRTY_VELOCITY) { - motionState->applyVelocities(); - motionState->applyGravity(); - } - body->setRestitution(motionState->_restitution); - body->setFriction(motionState->_friction); - body->setDamping(motionState->_linearDamping, motionState->_angularDamping); - - if (flags & EntityItem::DIRTY_MASS) { - float mass = motionState->getMass(); - btVector3 inertia(0.0f, 0.0f, 0.0f); - body->getCollisionShape()->calculateLocalInertia(mass, inertia); - body->setMassProps(mass, inertia); - body->updateInertiaTensor(); - } - body->activate(); - - // TODO: support collision groups -}; - #endif // USE_BULLET_PHYSICS diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index e93495e1d2..c6d6bd4626 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -71,12 +71,6 @@ public: /// \return number of simulation frames the physics engine has taken uint32_t getFrameCount() const { return _frameCount; } - /// \return substep remainder used for Bullet MotionState extrapolation - // Bullet will extrapolate the positions provided to MotionState::setWorldTransform() in an effort to provide - // smoother visible motion when the render frame rate does not match that of the simulation loop. We provide - // access to this fraction for improved filtering of update packets to interested parties. - float getSubStepRemainder() { return _dynamicsWorld->getLocalTimeAccumulation(); } - protected: void updateObjectHard(btRigidBody* body, ObjectMotionState* motionState, uint32_t flags); void updateObjectEasy(btRigidBody* body, ObjectMotionState* motionState, uint32_t flags); From d9efafac7ee593404224a5ccb454b0d05cc16816 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 13 Jan 2015 14:11:38 -0800 Subject: [PATCH 088/159] updating the model fragment shaders to use DeferredBUfferWrite --- .../render-utils/src/DeferredBufferWrite.slh | 15 ++++++++++++--- libraries/render-utils/src/Model.cpp | 6 +++++- libraries/render-utils/src/Model.h | 1 + libraries/render-utils/src/model.slf | 10 +--------- libraries/render-utils/src/model_lightmap.slf | 16 ++++++++++------ .../src/model_lightmap_normal_map.slf | 17 +++++++++++------ .../src/model_lightmap_normal_specular_map.slf | 16 +++++++++++++--- .../src/model_lightmap_specular_map.slf | 16 +++++++++++++--- libraries/render-utils/src/model_normal_map.slf | 15 +++++++++++---- .../src/model_normal_specular_map.slf | 15 +++++++++++---- .../render-utils/src/model_specular_map.slf | 14 +++++++++++--- libraries/render-utils/src/simple.slf | 14 ++++++++++++-- 12 files changed, 111 insertions(+), 44 deletions(-) diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index 8a547315cd..7b4ca7ba3b 100755 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -10,19 +10,28 @@ !> <@if not DEFERRED_BUFFER_WRITE_SLH@> <@def DEFERRED_BUFFER_WRITE_SLH@> -/* + // the glow intensity uniform float glowIntensity; // the alpha threshold uniform float alphaThreshold; -*/ + +float evalOpaqueFinalAlpha(float alpha, float mapAlpha) { + return mix(alpha * glowIntensity, 1.0 - alpha * glowIntensity, step(mapAlpha, alphaThreshold)); +} void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) { - // gl_FragData[0] = vec4(diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[0] = vec4(diffuse.rgb, alpha); gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(specular, shininess / 128.0); } +void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess, vec3 emissive) { + gl_FragData[0] = vec4(diffuse.rgb, alpha); + //gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5); + gl_FragData[2] = vec4(emissive, shininess / 128.0); +} + <@endif@> diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 46fc6a6e4d..6cfad9931d 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -178,7 +178,7 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, boo locations.alphaThreshold = program.uniformLocation("alphaThreshold"); locations.texcoordMatrices = program.uniformLocation("texcoordMatrices"); locations.emissiveParams = program.uniformLocation("emissiveParams"); - + locations.glowIntensity = program.uniformLocation("glowIntensity"); program.setUniformValue("diffuseMap", 0); program.setUniformValue("normalMap", 1); @@ -2367,6 +2367,10 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } glm::vec4 diffuse = glm::vec4(part.diffuseColor, part.opacity); + + if (locations->glowIntensity >= 0) { + GLBATCH(glUniform1f)(locations->glowIntensity, glowEffect->getIntensity()); + } if (!(translucent && alphaThreshold == 0.0f)) { GLBATCH(glAlphaFunc)(GL_EQUAL, diffuse.a = glowEffect->getIntensity()); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 83ceab109f..ef97e7dfd8 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -338,6 +338,7 @@ private: int specularTextureUnit; int emissiveTextureUnit; int emissiveParams; + int glowIntensity; }; static Locations _locations; diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index 9c263869f0..bbff368c2d 100755 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -16,9 +16,6 @@ // the diffuse texture uniform sampler2D diffuseMap; -// the alpha threshold -uniform float alphaThreshold; - // the interpolated normal varying vec4 normal; @@ -28,13 +25,8 @@ void main(void) { packDeferredFragment( normalize(normal.xyz), - mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold)), + evalOpaqueFinalAlpha(gl_Color.a, diffuse.a), gl_Color.rgb * diffuse.rgb, gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess); -/* - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); - gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); - gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); -*/ } diff --git a/libraries/render-utils/src/model_lightmap.slf b/libraries/render-utils/src/model_lightmap.slf index 9feacbe057..6b25921318 100755 --- a/libraries/render-utils/src/model_lightmap.slf +++ b/libraries/render-utils/src/model_lightmap.slf @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include DeferredBufferWrite.slh@> + // the diffuse texture uniform sampler2D diffuseMap; @@ -19,9 +21,6 @@ uniform sampler2D diffuseMap; uniform sampler2D emissiveMap; uniform vec2 emissiveParams; -// the alpha threshold -uniform float alphaThreshold; - // the interpolated normal varying vec4 normal; @@ -32,7 +31,12 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); - gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5); - gl_FragData[2] = vec4((vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), gl_FrontMaterial.shininess / 128.0); + + packDeferredFragmentLightmap( + normalize(normal.xyz), + evalOpaqueFinalAlpha(gl_Color.a, diffuse.a), + gl_Color.rgb * diffuse.rgb, + gl_FrontMaterial.specular.rgb, + gl_FrontMaterial.shininess, + (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb)); } diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slf b/libraries/render-utils/src/model_lightmap_normal_map.slf index 5bebbee3f6..9ef75802a8 100755 --- a/libraries/render-utils/src/model_lightmap_normal_map.slf +++ b/libraries/render-utils/src/model_lightmap_normal_map.slf @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include DeferredBufferWrite.slh@> + // the diffuse texture uniform sampler2D diffuseMap; @@ -22,9 +24,6 @@ uniform sampler2D normalMap; uniform sampler2D emissiveMap; uniform vec2 emissiveParams; -// the alpha threshold -uniform float alphaThreshold; - // the interpolated normal varying vec4 interpolatedNormal; @@ -45,7 +44,13 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); - gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); - gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); + + packDeferredFragmentLightmap( + normalize(viewNormal.xyz), + evalOpaqueFinalAlpha(gl_Color.a, diffuse.a), + //gl_Color.rgb * diffuse.rgb, + vec3(1.0, 0.0, 0.0), + gl_FrontMaterial.specular.rgb, + gl_FrontMaterial.shininess, + (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb)); } diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf index d2f76e4ef3..3bc72384f7 100755 --- a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf +++ b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include DeferredBufferWrite.slh@> + // the diffuse texture uniform sampler2D diffuseMap; @@ -25,9 +27,6 @@ uniform sampler2D normalMap; // the specular map texture uniform sampler2D specularMap; -// the alpha threshold -uniform float alphaThreshold; - // the interpolated normal varying vec4 interpolatedNormal; @@ -47,9 +46,20 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec3 specular = texture2D(specularMap, gl_TexCoord[0].st).rgb; vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + + packDeferredFragmentLightmap( + normalize(viewNormal.xyz), + evalOpaqueFinalAlpha(gl_Color.a, diffuse.a), + gl_Color.rgb * diffuse.rgb, + specular, + gl_FrontMaterial.shininess, + (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb)); +/* gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); +*/ } diff --git a/libraries/render-utils/src/model_lightmap_specular_map.slf b/libraries/render-utils/src/model_lightmap_specular_map.slf index 40879a8fc3..7322da6b3a 100755 --- a/libraries/render-utils/src/model_lightmap_specular_map.slf +++ b/libraries/render-utils/src/model_lightmap_specular_map.slf @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include DeferredBufferWrite.slh@> + // the diffuse texture uniform sampler2D diffuseMap; @@ -22,9 +24,6 @@ uniform vec2 emissiveParams; // the specular texture uniform sampler2D specularMap; -// the alpha threshold -uniform float alphaThreshold; - // the interpolated normal varying vec4 normal; @@ -33,9 +32,20 @@ varying vec2 interpolatedTexcoord1; void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec3 specular = texture2D(specularMap, gl_TexCoord[0].st).rgb; vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + + packDeferredFragmentLightmap( + normalize(normal.xyz), + evalOpaqueFinalAlpha(gl_Color.a, diffuse.a), + gl_Color.rgb * diffuse.rgb, + specular, + gl_FrontMaterial.shininess, + (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb)); +/* gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); +*/ } diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf index b625b346ed..74da394850 100755 --- a/libraries/render-utils/src/model_normal_map.slf +++ b/libraries/render-utils/src/model_normal_map.slf @@ -12,15 +12,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include DeferredBufferWrite.slh@> + // the diffuse texture uniform sampler2D diffuseMap; // the normal map texture uniform sampler2D normalMap; -// the alpha threshold -uniform float alphaThreshold; - // the interpolated normal varying vec4 interpolatedNormal; @@ -38,7 +37,15 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); +/* gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); + */ + + packDeferredFragment( + normalize(viewNormal.xyz), + evalOpaqueFinalAlpha(gl_Color.a, diffuse.a), + gl_Color.rgb * diffuse.rgb, + gl_FrontMaterial.specular.rgb, + gl_FrontMaterial.shininess); } diff --git a/libraries/render-utils/src/model_normal_specular_map.slf b/libraries/render-utils/src/model_normal_specular_map.slf index fd288f0867..4248edfc90 100755 --- a/libraries/render-utils/src/model_normal_specular_map.slf +++ b/libraries/render-utils/src/model_normal_specular_map.slf @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include DeferredBufferWrite.slh@> + // the diffuse texture uniform sampler2D diffuseMap; @@ -21,9 +23,6 @@ uniform sampler2D normalMap; // the specular map texture uniform sampler2D specularMap; -// the alpha threshold -uniform float alphaThreshold; - // the interpolated normal varying vec4 interpolatedNormal; @@ -41,8 +40,16 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + vec3 specular = texture2D(specularMap, gl_TexCoord[0].st).rgb; +/* gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); + */ + packDeferredFragment( + normalize(viewNormal.xyz), + evalOpaqueFinalAlpha(gl_Color.a, diffuse.a), + gl_Color.rgb * diffuse.rgb, + specular, + gl_FrontMaterial.shininess); } diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf index 4428173562..db1c2df9c5 100755 --- a/libraries/render-utils/src/model_specular_map.slf +++ b/libraries/render-utils/src/model_specular_map.slf @@ -12,23 +12,31 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include DeferredBufferWrite.slh@> + // the diffuse texture uniform sampler2D diffuseMap; // the specular texture uniform sampler2D specularMap; -// the alpha threshold -uniform float alphaThreshold; - // the interpolated normal varying vec4 normal; void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec3 specular = texture2D(specularMap, gl_TexCoord[0].st).rgb; +/* gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); + */ + packDeferredFragment( + normalize(normal.xyz), + evalOpaqueFinalAlpha(gl_Color.a, diffuse.a), + gl_Color.rgb * diffuse.rgb, + specular, + gl_FrontMaterial.shininess); } diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 50e584669d..faa4af4573 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -12,15 +12,25 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include DeferredBufferWrite.slh@> + // the interpolated normal varying vec4 normal; // the glow intensity -uniform float glowIntensity; +//uniform float glowIntensity; void main(void) { - // set the diffuse, normal, specular data + /* // set the diffuse, normal, specular data gl_FragData[0] = vec4(gl_Color.rgb, glowIntensity); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); + */ + + packDeferredFragment( + normalize(normal.xyz), + glowIntensity, + gl_Color.rgb, + gl_FrontMaterial.specular.rgb, + gl_FrontMaterial.shininess); } From 1af87e57dadca6eb3283ff52354a382283e658ce Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 13 Jan 2015 14:21:07 -0800 Subject: [PATCH 089/159] handle new places API format in AddressManager --- libraries/networking/src/AddressManager.cpp | 39 ++++++++++++--------- libraries/networking/src/AddressManager.h | 3 +- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 23aa8dad72..e6ad3220c2 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -22,7 +22,8 @@ #include "AddressManager.h" AddressManager::AddressManager() : - _currentDomain(), + _rootPlaceName(), + _rootPlaceID(), _positionGetter(NULL), _orientationGetter(NULL) { @@ -37,7 +38,7 @@ const QUrl AddressManager::currentAddress() const { QUrl hifiURL; hifiURL.setScheme(HIFI_URL_SCHEME); - hifiURL.setHost(_currentDomain); + hifiURL.setHost(_rootPlaceName); hifiURL.setPath(currentPath()); return hifiURL; @@ -174,15 +175,21 @@ void AddressManager::handleAPIResponse(QNetworkReply& requestReply) { } void AddressManager::goToAddressFromObject(const QVariantMap& addressMap) { + const QString ADDRESS_API_ROOT_KEY = "root"; const QString ADDRESS_API_DOMAIN_KEY = "domain"; const QString ADDRESS_API_ONLINE_KEY = "online"; if (!addressMap.contains(ADDRESS_API_ONLINE_KEY) || addressMap[ADDRESS_API_ONLINE_KEY].toBool()) { - if (addressMap.contains(ADDRESS_API_DOMAIN_KEY)) { - QVariantMap domainObject = addressMap[ADDRESS_API_DOMAIN_KEY].toMap(); - + QVariantMap rootMap = addressMap[ADDRESS_API_ROOT_KEY].toMap(); + if (rootMap.isEmpty()) { + rootMap = addressMap; + } + + QVariantMap domainObject = rootMap[ADDRESS_API_DOMAIN_KEY].toMap(); + + if (!domainObject.isEmpty()) { const QString DOMAIN_NETWORK_ADDRESS_KEY = "network_address"; const QString DOMAIN_ICE_SERVER_ADDRESS_KEY = "ice_server_address"; @@ -200,22 +207,22 @@ void AddressManager::goToAddressFromObject(const QVariantMap& addressMap) { emit possibleDomainChangeRequiredViaICEForID(iceServerAddress, domainID); } - // set our current domain to the name that came back - const QString DOMAIN_NAME_KEY = "name"; + // set our current root place id to the ID that came back + const QString PLACE_ID_KEY = "id"; + _rootPlaceID = rootMap[PLACE_ID_KEY].toUuid(); - _currentDomain = domainObject[DOMAIN_NAME_KEY].toString(); + // set our current root place name to the name that came back + const QString PLACE_NAME_KEY = "name"; + _rootPlaceName = rootMap[PLACE_NAME_KEY].toString(); // take the path that came back - const QString LOCATION_KEY = "location"; - const QString LOCATION_PATH_KEY = "path"; + const QString PLACE_PATH_KEY = "path"; QString returnedPath; - if (domainObject.contains(LOCATION_PATH_KEY)) { - returnedPath = domainObject[LOCATION_PATH_KEY].toString(); - } else if (domainObject.contains(LOCATION_KEY)) { - returnedPath = domainObject[LOCATION_KEY].toMap()[LOCATION_PATH_KEY].toString(); - } else if (addressMap.contains(LOCATION_PATH_KEY)) { - returnedPath = addressMap[LOCATION_PATH_KEY].toString(); + if (addressMap.contains(PLACE_PATH_KEY) && !addressMap[PLACE_PATH_KEY].toString().isEmpty()) { + returnedPath = addressMap[PLACE_PATH_KEY].toString(); + } else if (rootMap.contains(PLACE_PATH_KEY) && !rootMap[PLACE_PATH_KEY].toString().isEmpty()) { + returnedPath = rootMap[PLACE_PATH_KEY].toString(); } bool shouldFaceViewpoint = addressMap.contains(ADDRESS_API_ONLINE_KEY); diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index dee070740f..ac4200d675 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -85,7 +85,8 @@ private: bool handleRelativeViewpoint(const QString& pathSubsection, bool shouldFace = false); bool handleUsername(const QString& lookupString); - QString _currentDomain; + QString _rootPlaceName; + QUuid _rootPlaceID; PositionGetter _positionGetter; OrientationGetter _orientationGetter; }; From 04b4a95ccb4605ed88cad78e0c5316b59d593faf Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 13 Jan 2015 14:21:41 -0800 Subject: [PATCH 090/159] fix for bad cleanup (3 places) --- libraries/entities/src/EntityItem.cpp | 4 ++-- libraries/entities/src/EntityItemProperties.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index a18f8fc71d..885d589ed1 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -911,8 +911,8 @@ AACube EntityItem::getMinimumAACube() const { // _position represents the position of the registration point. glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; + glm::vec3 unrotatedMinRelativeToEntity = - (_dimensions * _registrationPoint); glm::vec3 unrotatedMaxRelativeToEntity = _dimensions * registrationRemainder; - glm::vec3 unrotatedMinRelativeToEntity = - unrotatedMaxRelativeToEntity; Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation()); @@ -936,8 +936,8 @@ AABox EntityItem::getAABox() const { // _position represents the position of the registration point. glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; + glm::vec3 unrotatedMinRelativeToEntity = - (_dimensions * _registrationPoint); glm::vec3 unrotatedMaxRelativeToEntity = _dimensions * registrationRemainder; - glm::vec3 unrotatedMinRelativeToEntity = - unrotatedMaxRelativeToEntity; Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation()); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index d50096f752..77d70e8abd 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -860,8 +860,8 @@ AABox EntityItemProperties::getAABoxInMeters() const { // _position represents the position of the registration point. glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; + glm::vec3 unrotatedMinRelativeToEntity = - (_dimensions * _registrationPoint); glm::vec3 unrotatedMaxRelativeToEntity = _dimensions * registrationRemainder; - glm::vec3 unrotatedMinRelativeToEntity = - unrotatedMaxRelativeToEntity; Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation()); From 16261a5fc1ba0be82f4d81c563a4338310b88259 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 13 Jan 2015 14:49:24 -0800 Subject: [PATCH 091/159] more updates for new place/location APIs --- interface/src/Application.cpp | 2 +- libraries/networking/src/AddressManager.cpp | 140 +++++++++++--------- libraries/networking/src/AddressManager.h | 8 +- 3 files changed, 81 insertions(+), 69 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 22a2b6bc22..6960f2d025 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3112,7 +3112,7 @@ void Application::updateWindowTitle(){ QString connectionStatus = nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED) "; QString username = AccountManager::getInstance().getAccountInfo().getUsername(); QString title = QString() + (!username.isEmpty() ? username + " @ " : QString()) - + DependencyManager::get()->getCurrentDomain() + connectionStatus + buildVersion; + + DependencyManager::get()->getRootPlaceName() + connectionStatus + buildVersion; #ifndef WIN32 // crashes with vs2013/win32 diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index e6ad3220c2..8ca0226a34 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -89,11 +89,6 @@ const QString AddressManager::currentPath(bool withOrientation) const { } } -QString AddressManager::getDomainID() const { - const QUuid& domainID = NodeList::getInstance()->getDomainHandler().getUUID(); - return domainID.isNull() ? "" : uuidStringWithoutCurlyBraces(domainID); -} - const JSONCallbackParameters& AddressManager::apiCallbackParameters() { static bool hasSetupParameters = false; static JSONCallbackParameters callbackParams; @@ -174,73 +169,90 @@ void AddressManager::handleAPIResponse(QNetworkReply& requestReply) { emit lookupResultsFinished(); } -void AddressManager::goToAddressFromObject(const QVariantMap& addressMap) { - const QString ADDRESS_API_ROOT_KEY = "root"; - const QString ADDRESS_API_DOMAIN_KEY = "domain"; - const QString ADDRESS_API_ONLINE_KEY = "online"; +void AddressManager::goToAddressFromObject(const QVariantMap& dataObject) { - if (!addressMap.contains(ADDRESS_API_ONLINE_KEY) - || addressMap[ADDRESS_API_ONLINE_KEY].toBool()) { - - QVariantMap rootMap = addressMap[ADDRESS_API_ROOT_KEY].toMap(); - if (rootMap.isEmpty()) { - rootMap = addressMap; - } - - QVariantMap domainObject = rootMap[ADDRESS_API_DOMAIN_KEY].toMap(); + const QString DATA_OBJECT_PLACE_KEY = "place"; + const QString DATA_OBJECT_USER_LOCATION_KEY = "location"; - if (!domainObject.isEmpty()) { - const QString DOMAIN_NETWORK_ADDRESS_KEY = "network_address"; - const QString DOMAIN_ICE_SERVER_ADDRESS_KEY = "ice_server_address"; + QVariantMap locationMap; + if (dataObject.contains(DATA_OBJECT_PLACE_KEY)) { + locationMap = dataObject[DATA_OBJECT_PLACE_KEY].toMap(); + } else { + locationMap = dataObject[DATA_OBJECT_USER_LOCATION_KEY].toMap(); + } + + qDebug() << locationMap; + + if (!locationMap.isEmpty()) { + const QString LOCATION_API_ROOT_KEY = "root"; + const QString LOCATION_API_DOMAIN_KEY = "domain"; + const QString LOCATION_API_ONLINE_KEY = "online"; + + if (!locationMap.contains(LOCATION_API_ONLINE_KEY) + || locationMap[LOCATION_API_ONLINE_KEY].toBool()) { - if (domainObject.contains(DOMAIN_NETWORK_ADDRESS_KEY)) { - QString domainHostname = domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString(); - - emit possibleDomainChangeRequired(domainHostname, DEFAULT_DOMAIN_SERVER_PORT); - } else { - QString iceServerAddress = domainObject[DOMAIN_ICE_SERVER_ADDRESS_KEY].toString(); - - const QString DOMAIN_ID_KEY = "id"; - QString domainIDString = domainObject[DOMAIN_ID_KEY].toString(); - QUuid domainID(domainIDString); - - emit possibleDomainChangeRequiredViaICEForID(iceServerAddress, domainID); + QVariantMap rootMap = locationMap[LOCATION_API_ROOT_KEY].toMap(); + if (rootMap.isEmpty()) { + rootMap = locationMap; } - // set our current root place id to the ID that came back - const QString PLACE_ID_KEY = "id"; - _rootPlaceID = rootMap[PLACE_ID_KEY].toUuid(); + QVariantMap domainObject = rootMap[LOCATION_API_DOMAIN_KEY].toMap(); - // set our current root place name to the name that came back - const QString PLACE_NAME_KEY = "name"; - _rootPlaceName = rootMap[PLACE_NAME_KEY].toString(); - - // take the path that came back - const QString PLACE_PATH_KEY = "path"; - QString returnedPath; - - if (addressMap.contains(PLACE_PATH_KEY) && !addressMap[PLACE_PATH_KEY].toString().isEmpty()) { - returnedPath = addressMap[PLACE_PATH_KEY].toString(); - } else if (rootMap.contains(PLACE_PATH_KEY) && !rootMap[PLACE_PATH_KEY].toString().isEmpty()) { - returnedPath = rootMap[PLACE_PATH_KEY].toString(); - } - - bool shouldFaceViewpoint = addressMap.contains(ADDRESS_API_ONLINE_KEY); - - if (!returnedPath.isEmpty()) { - // try to parse this returned path as a viewpoint, that's the only thing it could be for now - if (!handleRelativeViewpoint(returnedPath, shouldFaceViewpoint)) { - qDebug() << "Received a location path that was could not be handled as a viewpoint -" << returnedPath; + if (!domainObject.isEmpty()) { + const QString DOMAIN_NETWORK_ADDRESS_KEY = "network_address"; + const QString DOMAIN_ICE_SERVER_ADDRESS_KEY = "ice_server_address"; + + if (domainObject.contains(DOMAIN_NETWORK_ADDRESS_KEY)) { + QString domainHostname = domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString(); + + emit possibleDomainChangeRequired(domainHostname, DEFAULT_DOMAIN_SERVER_PORT); + } else { + QString iceServerAddress = domainObject[DOMAIN_ICE_SERVER_ADDRESS_KEY].toString(); + + const QString DOMAIN_ID_KEY = "id"; + QString domainIDString = domainObject[DOMAIN_ID_KEY].toString(); + QUuid domainID(domainIDString); + + emit possibleDomainChangeRequiredViaICEForID(iceServerAddress, domainID); } + + // set our current root place id to the ID that came back + const QString PLACE_ID_KEY = "id"; + _rootPlaceID = rootMap[PLACE_ID_KEY].toUuid(); + + // set our current root place name to the name that came back + const QString PLACE_NAME_KEY = "name"; + _rootPlaceName = rootMap[PLACE_NAME_KEY].toString(); + + // take the path that came back + const QString PLACE_PATH_KEY = "path"; + QString returnedPath; + + if (locationMap.contains(PLACE_PATH_KEY) && !locationMap[PLACE_PATH_KEY].toString().isEmpty()) { + returnedPath = locationMap[PLACE_PATH_KEY].toString(); + } else if (rootMap.contains(PLACE_PATH_KEY) && !rootMap[PLACE_PATH_KEY].toString().isEmpty()) { + returnedPath = rootMap[PLACE_PATH_KEY].toString(); + } + + bool shouldFaceViewpoint = locationMap.contains(LOCATION_API_ONLINE_KEY); + + if (!returnedPath.isEmpty()) { + // try to parse this returned path as a viewpoint, that's the only thing it could be for now + if (!handleRelativeViewpoint(returnedPath, shouldFaceViewpoint)) { + qDebug() << "Received a location path that was could not be handled as a viewpoint -" << returnedPath; + } + } + } else { + qDebug() << "Received an address manager API response with no domain key. Cannot parse."; + qDebug() << locationMap; } - } else { - qDebug() << "Received an address manager API response with no domain key. Cannot parse."; - qDebug() << addressMap; + // we've been told that this result exists but is offline, emit our signal so the application can handle + emit lookupResultIsOffline(); } } else { - // we've been told that this result exists but is offline, emit our signal so the application can handle - emit lookupResultIsOffline(); + qDebug() << "Received an address manager API response with no location key or place key. Cannot parse."; + qDebug() << locationMap; } } @@ -373,8 +385,10 @@ bool AddressManager::handleUsername(const QString& lookupString) { } -void AddressManager::setDomainInfo(const QString& hostname, quint16 port, const QString& domainName) { - _currentDomain = domainName.isEmpty() ? hostname : domainName; +void AddressManager::setDomainInfo(const QString& hostname, quint16 port) { + _rootPlaceName = hostname; + _rootPlaceID = QUuid(); + emit possibleDomainChangeRequired(hostname, port); } diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index ac4200d675..e98526689b 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -33,9 +33,8 @@ class AddressManager : public QObject { Q_PROPERTY(bool isConnected READ isConnected) Q_PROPERTY(QUrl href READ currentAddress) Q_PROPERTY(QString protocol READ getProtocol) - Q_PROPERTY(QString hostname READ getCurrentDomain) + Q_PROPERTY(QString hostname READ getRootPlaceName) Q_PROPERTY(QString pathname READ currentPath) - Q_PROPERTY(QString domainID READ getDomainID) public: bool isConnected(); const QString& getProtocol() { return HIFI_URL_SCHEME; }; @@ -43,8 +42,7 @@ public: const QUrl currentAddress() const; const QString currentPath(bool withOrientation = true) const; - const QString& getCurrentDomain() const { return _currentDomain; } - QString getDomainID() const; + const QString& getRootPlaceName() const { return _rootPlaceName; } void attemptPlaceNameLookup(const QString& lookupString); @@ -75,7 +73,7 @@ private slots: void handleAPIResponse(QNetworkReply& requestReply); void handleAPIError(QNetworkReply& errorReply); private: - void setDomainInfo(const QString& hostname, quint16 port, const QString& domainName = QString()); + void setDomainInfo(const QString& hostname, quint16 port); const JSONCallbackParameters& apiCallbackParameters(); From 92b8cd2d1e888e23d66d10c54ff939c5ef56b817 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 13 Jan 2015 15:02:04 -0800 Subject: [PATCH 092/159] handle storage of user location in new format --- interface/src/Application.cpp | 19 ++++++++++++++----- libraries/networking/src/AddressManager.h | 1 + 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6960f2d025..c156de03ca 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3124,23 +3124,32 @@ void Application::updateWindowTitle(){ void Application::updateLocationInServer() { AccountManager& accountManager = AccountManager::getInstance(); + AddressManager::SharedPointer addressManager = DependencyManager::get(); DomainHandler& domainHandler = NodeList::getInstance()->getDomainHandler(); - if (accountManager.isLoggedIn() && domainHandler.isConnected() && !domainHandler.getUUID().isNull()) { + if (accountManager.isLoggedIn() && domainHandler.isConnected() + && (!addressManager->getRootPlaceID().isNull() || !domainHandler.getUUID().isNull())) { // construct a QJsonObject given the user's current address information QJsonObject rootObject; QJsonObject locationObject; - QString pathString = DependencyManager::get()->currentPath(); + QString pathString = addressManager->currentPath(); const QString LOCATION_KEY_IN_ROOT = "location"; - const QString PATH_KEY_IN_LOCATION = "path"; - const QString DOMAIN_ID_KEY_IN_LOCATION = "domain_id"; + const QString PATH_KEY_IN_LOCATION = "path"; locationObject.insert(PATH_KEY_IN_LOCATION, pathString); - locationObject.insert(DOMAIN_ID_KEY_IN_LOCATION, domainHandler.getUUID().toString()); + + if (!addressManager->getRootPlaceID().isNull()) { + const QString PLACE_ID_KEY_IN_LOCATION = "place_id"; + locationObject.insert(PLACE_ID_KEY_IN_LOCATION, addressManager->getRootPlaceID().toString()); + + } else { + const QString DOMAIN_ID_KEY_IN_LOCATION = "domain_id"; + locationObject.insert(DOMAIN_ID_KEY_IN_LOCATION, domainHandler.getUUID().toString()); + } rootObject.insert(LOCATION_KEY_IN_ROOT, locationObject); diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index e98526689b..a8adf57741 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -42,6 +42,7 @@ public: const QUrl currentAddress() const; const QString currentPath(bool withOrientation = true) const; + const QUuid& getRootPlaceID() const { return _rootPlaceID; } const QString& getRootPlaceName() const { return _rootPlaceName; } void attemptPlaceNameLookup(const QString& lookupString); From 6e1ba17c6eda08361d660596436eb2e3c7f79325 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 13 Jan 2015 15:07:45 -0800 Subject: [PATCH 093/159] handle application title change for place name change --- interface/src/Application.cpp | 2 ++ libraries/networking/src/AddressManager.cpp | 12 +++++++++--- libraries/networking/src/AddressManager.h | 3 +++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c156de03ca..ecc36d7f05 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -306,6 +306,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // use our MyAvatar position and quat for address manager path addressManager->setPositionGetter(getPositionForPath); addressManager->setOrientationGetter(getOrientationForPath); + + connect(addressManager.data(), &AddressManager::rootPlaceNameChanged, this, &Application::updateWindowTitle); _settings = new QSettings(this); _numChangedSettings = 0; diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 8ca0226a34..4802f3ca15 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -181,8 +181,6 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject) { locationMap = dataObject[DATA_OBJECT_USER_LOCATION_KEY].toMap(); } - qDebug() << locationMap; - if (!locationMap.isEmpty()) { const QString LOCATION_API_ROOT_KEY = "root"; const QString LOCATION_API_DOMAIN_KEY = "domain"; @@ -222,7 +220,8 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject) { // set our current root place name to the name that came back const QString PLACE_NAME_KEY = "name"; - _rootPlaceName = rootMap[PLACE_NAME_KEY].toString(); + QString newRootPlaceName = rootMap[PLACE_NAME_KEY].toString(); + setRootPlaceName(newRootPlaceName); // take the path that came back const QString PLACE_PATH_KEY = "path"; @@ -384,6 +383,13 @@ bool AddressManager::handleUsername(const QString& lookupString) { return false; } +void AddressManager::setRootPlaceName(const QString& rootPlaceName) { + if (rootPlaceName != _rootPlaceName) { + _rootPlaceName = rootPlaceName; + emit rootPlaceNameChanged(_rootPlaceName); + } +} + void AddressManager::setDomainInfo(const QString& hostname, quint16 port) { _rootPlaceName = hostname; diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index a8adf57741..6cb5cdbf60 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -43,7 +43,9 @@ public: const QString currentPath(bool withOrientation = true) const; const QUuid& getRootPlaceID() const { return _rootPlaceID; } + const QString& getRootPlaceName() const { return _rootPlaceName; } + void setRootPlaceName(const QString& rootPlaceName); void attemptPlaceNameLookup(const QString& lookupString); @@ -68,6 +70,7 @@ signals: void locationChangeRequired(const glm::vec3& newPosition, bool hasOrientationChange, const glm::quat& newOrientation, bool shouldFaceLocation); + void rootPlaceNameChanged(const QString& newRootPlaceName); protected: AddressManager(); private slots: From 6d2c87c7a3faf7f4deca34c2cb17a266c10a8e14 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 13 Jan 2015 15:15:39 -0800 Subject: [PATCH 094/159] put current domain hostname if no place name present --- interface/src/Application.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ecc36d7f05..8c82281007 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3113,8 +3113,14 @@ void Application::updateWindowTitle(){ QString connectionStatus = nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED) "; QString username = AccountManager::getInstance().getAccountInfo().getUsername(); + QString currentPlaceName = DependencyManager::get()->getRootPlaceName(); + + if (currentPlaceName.isEmpty()) { + currentPlaceName = nodeList->getDomainHandler().getHostname(); + } + QString title = QString() + (!username.isEmpty() ? username + " @ " : QString()) - + DependencyManager::get()->getRootPlaceName() + connectionStatus + buildVersion; + + currentPlaceName + connectionStatus + buildVersion; #ifndef WIN32 // crashes with vs2013/win32 From 9c083ce86e6e9ed7e5235f40e90c1592c3168a95 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 13 Jan 2015 15:51:18 -0800 Subject: [PATCH 095/159] Using the model::Material for rendering and in shaders --- libraries/render-utils/src/Material.slh | 59 +++++++++++++++++++++++++ libraries/render-utils/src/Model.cpp | 42 +++++++++++++++--- libraries/render-utils/src/Model.h | 1 + libraries/render-utils/src/model.slf | 14 +++--- 4 files changed, 105 insertions(+), 11 deletions(-) create mode 100755 libraries/render-utils/src/Material.slh diff --git a/libraries/render-utils/src/Material.slh b/libraries/render-utils/src/Material.slh new file mode 100755 index 0000000000..4720b19d00 --- /dev/null +++ b/libraries/render-utils/src/Material.slh @@ -0,0 +1,59 @@ + +<@if not MATERIAL_SLH@> +<@def MATERIAL_SLH@> + +struct Material { + vec4 _diffuse; + vec4 _specular; + + float getOpacity() { return _diffuse.a; } + vec3 getDiffuse() { return _diffuse.rgb; } + vec3 getSpecular() { return _specular.rgb; } + float getShininess() { return _specular.a; } +}; + +<@if GLPROFILE == PC_GL@> +uniform materialBuffer { + Material mat; +}; +Material getMaterial() { + return mat; +} +<@elif GLPROFILE == MAC_GL@> +uniform vec4 materialBuffer[2]; +Material getMaterial() { + Material mat; + mat._diffuse = materialBuffer[0]; + mat._specular = materialBuffer[1]; + return mat; +} +<@else@> +uniform vec4 materialBuffer[2]; +Material getMaterial() { + Material mat; + mat._diffuse = materialBuffer[0]; + mat._specular = materialBuffer[1]; + return mat; +} +<@endif@> + + + +<@endif@> \ No newline at end of file diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 6cfad9931d..2b9418b82f 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -198,6 +198,28 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, boo locations.emissiveTextureUnit = -1; } + // bindable uniform version +#if defined(Q_OS_MAC) + loc = program.uniformLocation("materialBuffer"); + if (loc >= 0) { + locations.materialBufferUnit = loc; + } else { + locations.materialBufferUnit = -1; + } +#else + loc = glGetUniformBlockIndex(program.programId(), "materialBuffer"); + if (loc >= 0) { + glUniformBlockBinding(program.programId(), loc, 1); + locations.materialBufferUnit = 1; + } else { + locations.materialBufferUnit = -1; + } +#endif + + if (!program.isLinked()) { + program.release(); + } + program.release(); } @@ -2348,6 +2370,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod for (int j = 0; j < networkMesh.parts.size(); j++) { const NetworkMeshPart& networkPart = networkMesh.parts.at(j); const FBXMeshPart& part = mesh.parts.at(j); + model::MaterialPointer material = part._material; if ((networkPart.isTranslucent() || part.opacity != 1.0f) != translucent) { offset += (part.quadIndices.size() + part.triangleIndices.size()) * sizeof(int); continue; @@ -2366,7 +2389,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod qDebug() << "NEW part.materialID:" << part.materialID; } - glm::vec4 diffuse = glm::vec4(part.diffuseColor, part.opacity); + glm::vec4 diffuse = glm::vec4(material->getDiffuse(), material->getOpacity()); if (locations->glowIntensity >= 0) { GLBATCH(glUniform1f)(locations->glowIntensity, glowEffect->getIntensity()); @@ -2374,11 +2397,18 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod if (!(translucent && alphaThreshold == 0.0f)) { GLBATCH(glAlphaFunc)(GL_EQUAL, diffuse.a = glowEffect->getIntensity()); } - glm::vec4 specular = glm::vec4(part.specularColor, 1.0f); - GLBATCH(glMaterialfv)(GL_FRONT, GL_AMBIENT, (const float*)&diffuse); - GLBATCH(glMaterialfv)(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse); - GLBATCH(glMaterialfv)(GL_FRONT, GL_SPECULAR, (const float*)&specular); - GLBATCH(glMaterialf)(GL_FRONT, GL_SHININESS, (part.shininess > 128.0f ? 128.0f: part.shininess)); + glm::vec4 specular = glm::vec4(material->getSpecular(), 1.0f); + float shininess = material->getShininess(); + shininess = (shininess > 128.0f ? 128.0f: shininess); + + if (locations->materialBufferUnit >= 0) { + batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer()); + } else { + GLBATCH(glMaterialfv)(GL_FRONT, GL_AMBIENT, (const float*)&diffuse); + GLBATCH(glMaterialfv)(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse); + GLBATCH(glMaterialfv)(GL_FRONT, GL_SPECULAR, (const float*)&specular); + GLBATCH(glMaterialf)(GL_FRONT, GL_SHININESS, shininess); + } Texture* diffuseMap = networkPart.diffuseTexture.data(); if (mesh.isEye && diffuseMap) { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index ef97e7dfd8..e10f218563 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -339,6 +339,7 @@ private: int emissiveTextureUnit; int emissiveParams; int glowIntensity; + int materialBufferUnit; }; static Locations _locations; diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index bbff368c2d..396935b4b8 100755 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -13,6 +13,8 @@ <@include DeferredBufferWrite.slh@> +<@include Material.slh@> + // the diffuse texture uniform sampler2D diffuseMap; @@ -20,13 +22,15 @@ uniform sampler2D diffuseMap; varying vec4 normal; void main(void) { - // set the diffuse, normal, specular data + // Fetch diffuse map vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + Material mat = getMaterial(); + packDeferredFragment( normalize(normal.xyz), - evalOpaqueFinalAlpha(gl_Color.a, diffuse.a), - gl_Color.rgb * diffuse.rgb, - gl_FrontMaterial.specular.rgb, - gl_FrontMaterial.shininess); + evalOpaqueFinalAlpha(mat.getOpacity(), diffuse.a), + mat.getDiffuse()/* * diffuse.rgb*/, + mat.getSpecular(), + mat.getShininess()); } From 6eb35bf98cfbefc3b5c4a23caa3eba66c266c646 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 13 Jan 2015 16:13:18 -0800 Subject: [PATCH 096/159] tweaks to descriptions --- .../resources/describe-settings.json | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 3ee62634c8..e2f751a7f0 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -305,23 +305,25 @@ "settings": [ { "name": "persistFilename", - "label": "Persistant Filename", - "help": "the filename for your entities", + "label": "Entities Filename", + "help": "the path to the file entities are stored in. Make sure the path exists.", "placeholder": "resources/models.svo", - "default": "resources/models.svo" + "default": "resources/models.svo", + "advanced": true }, { "name": "persistInterval", - "label": "Persist Interval", - "help": "Interval between persist checks in msecs.", + "label": "Save Check Interval", + "help": "Milliseconds between checks for saving the current state of entities.", "placeholder": "30000", - "default": "30000" + "default": "30000", + "advanced": true }, { "name": "backups", "type": "table", "label": "Backup Rules", - "help": "In this table you can define a set of rules for how frequently to backup copies of your content file.", + "help": "In this table you can define a set of rules for how frequently to backup copies of your entites content file.", "numbered": false, "default": [ {"Name":"Half Hourly Rolling","backupInterval":1800,"format":".backup.halfhourly.%N","maxBackupVersions":5}, @@ -347,7 +349,7 @@ }, { "name": "backupInterval", - "label": "Backup Interval", + "label": "Backup Interval in Seconds", "help": "Interval between backup checks in seconds.", "placeholder": 1800, "default": 1800, @@ -367,27 +369,31 @@ "name": "NoPersist", "type": "checkbox", "help": "Don't persist your entities to a file.", - "default": false + "default": false, + "advanced": true }, { "name": "NoBackup", "type": "checkbox", "help": "Don't regularly backup your persisted entities to a backup file.", - "default": false + "default": false, + "advanced": true }, { "name": "statusHost", "label": "Status Hostname", "help": "host name or IP address of the server for accessing the status page", "placeholder": "", - "default": "" + "default": "", + "advanced": true }, { "name": "statusPort", "label": "Status Port", "help": "port of the server for accessing the status page", "placeholder": "", - "default": "" + "default": "", + "advanced": true }, { "name": "verboseDebug", From d3edd14638d0be8233ca7970d67beb7bd8ac0064 Mon Sep 17 00:00:00 2001 From: dev Date: Tue, 13 Jan 2015 16:53:22 -0800 Subject: [PATCH 097/159] fixes for glsl mac --- libraries/render-utils/src/Material.slh | 10 ++++++---- libraries/render-utils/src/model.slf | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/libraries/render-utils/src/Material.slh b/libraries/render-utils/src/Material.slh index 4720b19d00..2ea7b2a12c 100755 --- a/libraries/render-utils/src/Material.slh +++ b/libraries/render-utils/src/Material.slh @@ -15,12 +15,14 @@ struct Material { vec4 _diffuse; vec4 _specular; - float getOpacity() { return _diffuse.a; } - vec3 getDiffuse() { return _diffuse.rgb; } - vec3 getSpecular() { return _specular.rgb; } - float getShininess() { return _specular.a; } }; +float getMaterialOpacity(Material m) { return m._diffuse.a; } +vec3 getMaterialDiffuse(Material m) { return m._diffuse.rgb; } +vec3 getMaterialSpecular(Material m) { return m._specular.rgb; } +float getMaterialShininess(Material m) { return m._specular.a; } + + <@if GLPROFILE == PC_GL@> uniform materialBuffer { Material mat; diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index 396935b4b8..bc6f127a77 100755 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -29,8 +29,8 @@ void main(void) { packDeferredFragment( normalize(normal.xyz), - evalOpaqueFinalAlpha(mat.getOpacity(), diffuse.a), - mat.getDiffuse()/* * diffuse.rgb*/, - mat.getSpecular(), - mat.getShininess()); + evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), + getMaterialDiffuse(mat) * diffuse.rgb, + getMaterialSpecular(mat), + getMaterialShininess(mat)); } From d7ad5a35d69072d773feccc875d9528e112b6283 Mon Sep 17 00:00:00 2001 From: dev Date: Tue, 13 Jan 2015 18:24:32 -0800 Subject: [PATCH 098/159] fixes for glsl mac --- libraries/gpu/src/gpu/GLBackend.cpp | 8 ++++---- libraries/render-utils/src/Material.slh | 19 ++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index f5f998d0d9..ed1b97a58f 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -494,13 +494,13 @@ void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { #if defined(Q_OS_MAC) GLfloat* data = (GLfloat*) (uniformBuffer->getData() + rangeStart); glUniform4fv(slot, rangeSize / sizeof(GLfloat[4]), data); + + // NOT working so we ll stick to the uniform float array until we move to core profile + // GLuint bo = getBufferID(*uniformBuffer); + //glUniformBufferEXT(_shader._program, slot, bo); #else GLuint bo = getBufferID(*uniformBuffer); glBindBufferRange(GL_UNIFORM_BUFFER, slot, bo, rangeStart, rangeSize); - - // glUniformBufferEXT(_shader._program, slot, bo); - - //glBindBufferBase(GL_UNIFORM_BUFFER, slot, bo); #endif CHECK_GL_ERROR(); } diff --git a/libraries/render-utils/src/Material.slh b/libraries/render-utils/src/Material.slh index 2ea7b2a12c..e77b664ee1 100755 --- a/libraries/render-utils/src/Material.slh +++ b/libraries/render-utils/src/Material.slh @@ -36,8 +36,17 @@ Material getMaterial() { Material mat; mat._diffuse = materialBuffer[0]; mat._specular = materialBuffer[1]; - return mat; + return mat; } + <@else@> uniform vec4 materialBuffer[2]; Material getMaterial() { @@ -48,14 +57,6 @@ Material getMaterial() { } <@endif@> - <@endif@> \ No newline at end of file From 7130c579f5c8214d1ba8f13f0795867ae888de54 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 13 Jan 2015 17:56:34 -0800 Subject: [PATCH 099/159] First pass at Bookmarks class In-memory for starters. --- interface/src/Bookmarks.cpp | 54 +++++++++++++++++++++++++++++++++++++ interface/src/Bookmarks.h | 39 +++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 interface/src/Bookmarks.cpp create mode 100644 interface/src/Bookmarks.h diff --git a/interface/src/Bookmarks.cpp b/interface/src/Bookmarks.cpp new file mode 100644 index 0000000000..c8879e1a8f --- /dev/null +++ b/interface/src/Bookmarks.cpp @@ -0,0 +1,54 @@ +// +// Bookmarks.cpp +// interface/src +// +// Created by David Rowe on 13 Jan 2015. +// 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 "Bookmarks.h" + +Bookmarks::Bookmarks() { +} + +void Bookmarks::insert(QString name, QString address) { + QString key = name.toLower(); + + if (isValidName(name)) { + QJsonObject bookmark; + bookmark.insert("name", name); + bookmark.insert("address", address); + _bookmarks.insert(key, bookmark); + + if (contains(key)) { + qDebug() << "Added bookmark: " << name << ", " << address; + } else { + qDebug() << "Couldn't add bookmark: " << name << ", " << address; + } + } else { + qDebug() << "Invalid bookmark: " << name << ", " << address; + } +} + +void Bookmarks::remove(QString name) { + QString key = name.toLower(); + + _bookmarks.remove(key); + + if (!contains(key)) { + qDebug() << "Removed bookmark: " << name; + } else { + qDebug() << "Couldn't remove bookmark: " << name; + } +} + +bool Bookmarks::contains(QString name) { + return _bookmarks.contains(name.toLower()); +} + +bool Bookmarks::isValidName(QString name) { + return _nameRegExp.exactMatch(name); +} diff --git a/interface/src/Bookmarks.h b/interface/src/Bookmarks.h new file mode 100644 index 0000000000..a2def873b0 --- /dev/null +++ b/interface/src/Bookmarks.h @@ -0,0 +1,39 @@ +// +// Bookmarks.h +// interface/src +// +// Created by David Rowe on 13 Jan 2015. +// 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_Bookmarks_h +#define hifi_Bookmarks_h + +#include +#include +#include +#include +#include + +class Bookmarks: public QObject { + Q_OBJECT + +public: + Bookmarks(); + + void insert(QString name, QString address); // Overwrites any existing entry with same name. + void remove(QString name); + + bool contains(QString name); + bool isValidName(QString name); + +private: + QMap _bookmarks; // key: { name: string, address: string } + // key is a lowercase copy of name, used to make the bookmarks case insensitive. + const QRegExp _nameRegExp = QRegExp("^[\\w\\-]+$"); +}; + +#endif // hifi_Bookmarks_h \ No newline at end of file From 27cc3d297eb00952558d5e4794282cf86b639c16 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 13 Jan 2015 20:27:38 -0800 Subject: [PATCH 100/159] DependencyManager update - Now need a call to DependencyManager::set(...) that support variable arguments number and type - Now support destroy operation via DependencyManager::destroy() - Now support inheritance. All inheritance relationship need to be specified via DependencyManager::registerInheritance() before any call to the DepedencyManager involving Base. - Dependencies should now inherit from the class Dependency as well as using SINGLETON_DEPENDENCY --- libraries/shared/src/DependencyManager.cpp | 6 ++ libraries/shared/src/DependencyManager.h | 86 ++++++++++++++++------ 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/libraries/shared/src/DependencyManager.cpp b/libraries/shared/src/DependencyManager.cpp index 440c0ac68d..5f78f6bcd5 100644 --- a/libraries/shared/src/DependencyManager.cpp +++ b/libraries/shared/src/DependencyManager.cpp @@ -10,3 +10,9 @@ // #include "DependencyManager.h" + +DependencyManager DependencyManager::_manager; + +QSharedPointer& DependencyManager::safeGet(size_t hashCode) { + return _instanceHash[hashCode]; +} \ No newline at end of file diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index 9aecb45657..e996e10590 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -12,29 +12,31 @@ #ifndef hifi_DependencyManager_h #define hifi_DependencyManager_h -#include #include +#include +#include +#include #include #define SINGLETON_DEPENDENCY \ -private:\ - void customDeleter() {\ - QObject* thisObject = dynamic_cast(this);\ - if (thisObject && thisObject->parent()) {\ - thisObject->deleteLater();\ - } else {\ - delete this;\ - }\ - }\ friend class DependencyManager; -class QObject; +class Dependency { +protected: + virtual ~Dependency() {} + virtual void customDeleter() { + delete this; + } + + friend class DependencyManager; +}; // usage: -// T* instance = DependencyManager::get(); -// T* instance = DependencyManager::set(Args... args); -// T* instance = DependencyManager::destroy(); +// auto instance = DependencyManager::get(); +// auto instance = DependencyManager::set(Args... args); +// DependencyManager::destroy(); +// DependencyManager::registerInheritance(); class DependencyManager { public: template @@ -46,32 +48,72 @@ public: template static void destroy(); + template + static void registerInheritance(); + private: + static DependencyManager _manager; + template - static QSharedPointer& storage(); + size_t getHashCode(); + + QSharedPointer& safeGet(size_t hashCode); + + QHash> _instanceHash; + QHash _inheritanceHash; }; template QSharedPointer DependencyManager::get() { - return storage(); + static size_t hashCode = _manager.getHashCode(); + static QWeakPointer instance; + + if (instance.isNull()) { + instance = qSharedPointerCast(_manager.safeGet(hashCode)); + + if (instance.isNull()) { + qWarning() << "DependencyManager::get(): No instance available for" << typeid(T).name(); + } + } + + return instance.toStrongRef(); } template QSharedPointer DependencyManager::set(Args&&... args) { + static size_t hashCode = _manager.getHashCode(); + QSharedPointer instance(new T(args...), &T::customDeleter); - storage().swap(instance); - return storage(); + QSharedPointer storedInstance = qSharedPointerCast(instance); + _manager.safeGet(hashCode).swap(storedInstance); + + return instance; } template void DependencyManager::destroy() { - storage().clear(); + static size_t hashCode = _manager.getHashCode(); + _manager.safeGet(hashCode).clear(); +} + +template +void DependencyManager::registerInheritance() { + size_t baseHashCode = typeid(Base).hash_code(); + size_t derivedHashCode = typeid(Derived).hash_code(); + _manager._inheritanceHash.insert(baseHashCode, derivedHashCode); } template -QSharedPointer& DependencyManager::storage() { - static QSharedPointer sharedPointer; - return sharedPointer; +size_t DependencyManager::getHashCode() { + size_t hashCode = typeid(T).hash_code(); + auto derivedHashCode = _inheritanceHash.find(hashCode); + + while (derivedHashCode != _inheritanceHash.end()) { + hashCode = derivedHashCode.value(); + derivedHashCode = _inheritanceHash.find(hashCode); + } + + return hashCode; } #endif // hifi_DependencyManager_h From 36db547c0f25f457dbdf5770c679fd1ea8866550 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 13 Jan 2015 20:35:45 -0800 Subject: [PATCH 101/159] Setup DependencyManager before any member of Application --- interface/src/Application.cpp | 53 +++++++++++++++++++++++++++-------- interface/src/Application.h | 1 + 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 11b28fc503..1ac3b29e76 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -85,6 +85,8 @@ #include "Util.h" #include "audio/AudioToolBox.h" +#include "audio/AudioIOStatsRenderer.h" +#include "audio/AudioScope.h" #include "devices/DdeFaceTracker.h" #include "devices/Faceshift.h" @@ -142,8 +144,43 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt } } +bool setupEssentials(int& argc, char** argv) { + unsigned int listenPort = 0; // bind to an ephemeral port by default + const char** constArgv = const_cast(argv); + const char* portStr = getCmdOption(argc, constArgv, "--listenPort"); + if (portStr) { + listenPort = atoi(portStr); + } + + DependencyManager::registerInheritance(); + + // Set dependencies + DependencyManager::get(); + auto glCanvas = DependencyManager::set(); + auto addressManager = DependencyManager::set(); + auto nodeList = DependencyManager::set(NodeType::Agent, listenPort); + auto geometryCache = DependencyManager::set(); + auto glowEffect = DependencyManager::set(); + auto faceshift = DependencyManager::set(); + auto audio = DependencyManager::set