From c2894749096321502d23b8dc7a986365e6873b86 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 6 Nov 2015 14:25:01 -0800 Subject: [PATCH 01/20] avatr mover --- examples/avatarMover/avatarMover.js | 188 +++++++++++++++++++++ examples/avatarMover/avatarMoverSpawner.js | 6 + 2 files changed, 194 insertions(+) create mode 100644 examples/avatarMover/avatarMover.js create mode 100644 examples/avatarMover/avatarMoverSpawner.js diff --git a/examples/avatarMover/avatarMover.js b/examples/avatarMover/avatarMover.js new file mode 100644 index 0000000000..a47bd01ed5 --- /dev/null +++ b/examples/avatarMover/avatarMover.js @@ -0,0 +1,188 @@ +(function() { + this.defaultRange = 5; + this.acceleration = { + x: 0, + y: 0, + z: 0 + }; + this.onColor = { + red: 77, + green: 11, + blue: 111 + }; + this.offColor = { + red: 200, + green: 0, + blue: 0 + }; + var self = this; + //Default forward direction of mover object + this.forward = { + x: 0, + y: 0, + z: -1 + }; + this.isMoving = false; + this.velocity = { + x: 0, + y: 0, + z: 0 + }; + this.defaultThrust = 500; + this.maxRotMixVal = 0.01; + this.minRotMixVal = this.maxRotMixVal * 0.5; + this.minThrustPercentage = 0.2; + this.userData = {}; + + + this.getUserData = function() { + if (this.properties.userData) { + this.userData = JSON.parse(this.properties.userData); + } + } + + this.updateUserData = function() { + Entities.editEntity(this.entityId, { + userData: JSON.stringify(this.userData) + }); + } + + + this.toggleMover = function() { + if (!this.userData.active) { + this.activate(); + } else if (this.userData.active) { + this.deactivate(); + } + + } + + this.clickReleaseOnEntity = function(entityId, mouseEvent) { + this.entityId = entityId + if (mouseEvent.isLeftButton) { + this.toggleMover(); + } + } + + this.activate = function() { + //activate a light at the movers position + this.properties = Entities.getEntityProperties(this.entityId); + this.getUserData(); + this.userData.active = true; + this.initUserData(); + var lightPos = this.properties.position; + lightPos.y += .1; + this.light = Entities.addEntity({ + type: "Light", + position: lightPos, + isSpotlight: false, + dimensions: { + x: 2, + y: 2, + z: 2 + }, + color: this.onColor, + intensity: 10 + // rotation: {x : 0, y: Math.PI/2, z: 0} + }); + + this.field = Overlays.addOverlay("sphere", { + position: this.properties.position, + size: this.userData.range, + solid: false, + color: { + red: 250, + green: 10, + blue: 10 + }, + }) + + //change color + Entities.editEntity(this.entityId, { + color: this.onColor, + }); + } + + this.initUserData = function() { + this.userData.range = this.userData.range || this.defaultRange; + this.userData.thrust = this.userData.thrust || this.defaultThrust; + this.updateUserData(); + } + + this.updateOverlays = function() { + if (this.field) { + Overlays.editOverlay(this.field, { + size: this.userData.range + }); + } + } + + + this.deactivate = function() { + this.userData.active = false; + this.updateUserData(); + Entities.editEntity(this.entityId, { + color: this.offColor + }); + this.cleanUp(); + } + + this.scriptEnding = function() { + this.cleanUp(); + } + + this.update = function(deltaTime) { + self.properties = Entities.getEntityProperties(self.entityId); + self.getUserData(); + self.updateOverlays(); + if (!self.userData.active) { + return; + } + self.distance = Vec3.distance(MyAvatar.position, self.properties.position); + if (self.distance < self.userData.range) { + self.rotationMixVal = map(self.distance, 0, self.userData.range, self.maxRotMixVal, self.minRotMixVal); + + //We want to extract yaw from rotated object so avatars do not pith or roll, as they will be stuck that way. + self.sanitizedRotation = Quat.fromPitchYawRollDegrees(0, Quat.safeEulerAngles(self.properties.rotation).y, 0); + self.newOrientation = Quat.mix(MyAvatar.orientation, self.sanitizedRotation, self.rotationMixVal); + MyAvatar.orientation = self.newOrientation; + + self.rotatedDir = { + x: self.forward.x, + y: self.forward.y, + z: self.forward.z + }; + self.rotatedDir = Vec3.multiplyQbyV(self.properties.rotation, self.rotatedDir); + + self.thrust = map(self.distance, 0, self.userData.range, self.userData.thrust, self.userData.thrust * self.minThrustPercentage); + self.direction = Vec3.normalize(self.rotatedDir); + self.velocity = Vec3.multiply(self.direction, self.thrust); + MyAvatar.addThrust(Vec3.multiply(self.velocity, deltaTime)); + } + + } + + + this.preload = function(entityId) { + this.entityId = entityId; + } + + this.unload = function() { + Script.update.disconnect(this.update); + this.cleanUp(); + } + + + this.cleanUp = function() { + Entities.deleteEntity(this.light); + Overlays.deleteOverlay(this.field); + } + + function map(value, min1, max1, min2, max2) { + return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); + } + + Script.scriptEnding.connect(this.scriptEnding); + Script.update.connect(this.update); + +}); \ No newline at end of file diff --git a/examples/avatarMover/avatarMoverSpawner.js b/examples/avatarMover/avatarMoverSpawner.js new file mode 100644 index 0000000000..0bff3b02c0 --- /dev/null +++ b/examples/avatarMover/avatarMoverSpawner.js @@ -0,0 +1,6 @@ +var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/arrow.fbx"; + +var avatarMover = Entities.addEntity({ + type: "Model", + modelURL: modelURL +}) \ No newline at end of file From 4513b638dbec8e15149801d1b408fdcdccb2ee98 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 6 Nov 2015 14:40:10 -0800 Subject: [PATCH 02/20] Adding clip serialization implementation, tests --- libraries/recording/src/recording/Clip.cpp | 27 +-- libraries/recording/src/recording/Clip.h | 19 +- libraries/recording/src/recording/Frame.h | 4 + libraries/recording/src/recording/Logging.cpp | 11 + libraries/recording/src/recording/Logging.h | 16 ++ .../recording/src/recording/Recorder.cpp | 2 +- .../src/recording/impl/BufferClip.cpp | 18 +- .../recording/src/recording/impl/BufferClip.h | 10 +- .../recording/src/recording/impl/FileClip.cpp | 196 ++++++++++++++++-- .../recording/src/recording/impl/FileClip.h | 29 ++- tests/recording/CMakeLists.txt | 22 +- tests/recording/src/Constants.h | 2 + tests/recording/src/FrameTests.cpp | 4 + tests/recording/src/FrameTests.h | 3 + tests/recording/src/RecorderTests.cpp | 4 + tests/recording/src/RecorderTests.h | 4 + tests/recording/src/main.cpp | 114 ++++++++++ 17 files changed, 427 insertions(+), 58 deletions(-) create mode 100644 libraries/recording/src/recording/Logging.cpp create mode 100644 libraries/recording/src/recording/Logging.h create mode 100644 tests/recording/src/main.cpp diff --git a/libraries/recording/src/recording/Clip.cpp b/libraries/recording/src/recording/Clip.cpp index ef59532f09..09acf0579f 100644 --- a/libraries/recording/src/recording/Clip.cpp +++ b/libraries/recording/src/recording/Clip.cpp @@ -16,33 +16,34 @@ using namespace recording; Clip::Pointer Clip::fromFile(const QString& filePath) { - return std::make_shared(filePath); + auto result = std::make_shared(filePath); + if (result->frameCount() == 0) { + return Clip::Pointer(); + } + return result; } -void Clip::toFile(Clip::Pointer clip, const QString& filePath) { - // FIXME +void Clip::toFile(const QString& filePath, Clip::Pointer clip) { + FileClip::write(filePath, clip->duplicate()); +} + +Clip::Pointer Clip::newClip() { + return std::make_shared(); } Clip::Pointer Clip::duplicate() { Clip::Pointer result = std::make_shared(); + Locker lock(_mutex); float currentPosition = position(); seek(0); Frame::Pointer frame = nextFrame(); while (frame) { - result->appendFrame(frame); + result->addFrame(frame); + frame = nextFrame(); } seek(currentPosition); return result; } - -#if 0 -Clip::Pointer Clip::fromIODevice(QIODevice * device) { - return std::make_shared(device); -} - -void Clip::fromIODevice(Clip::Pointer clip, QIODevice * device) { -} -#endif \ No newline at end of file diff --git a/libraries/recording/src/recording/Clip.h b/libraries/recording/src/recording/Clip.h index ca77ba8969..e7034ef077 100644 --- a/libraries/recording/src/recording/Clip.h +++ b/libraries/recording/src/recording/Clip.h @@ -12,35 +12,44 @@ #include "Forward.h" +#include + #include class QIODevice; namespace recording { -class Clip : public QObject { +class Clip { public: using Pointer = std::shared_ptr; - Clip(QObject* parent = nullptr) : QObject(parent) {} virtual ~Clip() {} Pointer duplicate(); + virtual float duration() const = 0; + virtual size_t frameCount() const = 0; + virtual void seek(float offset) = 0; virtual float position() const = 0; virtual FramePointer peekFrame() const = 0; virtual FramePointer nextFrame() = 0; virtual void skipFrame() = 0; - virtual void appendFrame(FramePointer) = 0; - + virtual void addFrame(FramePointer) = 0; static Pointer fromFile(const QString& filePath); - static void toFile(Pointer clip, const QString& filePath); + static void toFile(const QString& filePath, Pointer clip); + static Pointer newClip(); protected: + using Mutex = std::recursive_mutex; + using Locker = std::unique_lock; + virtual void reset() = 0; + + mutable Mutex _mutex; }; } diff --git a/libraries/recording/src/recording/Frame.h b/libraries/recording/src/recording/Frame.h index 2834637a6b..0fb95c4b2e 100644 --- a/libraries/recording/src/recording/Frame.h +++ b/libraries/recording/src/recording/Frame.h @@ -29,6 +29,10 @@ public: float timeOffset { 0 }; QByteArray data; + Frame() {} + Frame(FrameType type, float timeOffset, const QByteArray& data) + : type(type), timeOffset(timeOffset), data(data) {} + static FrameType registerFrameType(const QString& frameTypeName); static QMap getFrameTypes(); static QMap getFrameTypeNames(); diff --git a/libraries/recording/src/recording/Logging.cpp b/libraries/recording/src/recording/Logging.cpp new file mode 100644 index 0000000000..5673e6e175 --- /dev/null +++ b/libraries/recording/src/recording/Logging.cpp @@ -0,0 +1,11 @@ +// +// Created by Bradley Austin Davis 2015/10/11 +// 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 "Logging.h" + +Q_LOGGING_CATEGORY(recordingLog, "hifi.recording") diff --git a/libraries/recording/src/recording/Logging.h b/libraries/recording/src/recording/Logging.h new file mode 100644 index 0000000000..a1b28329d7 --- /dev/null +++ b/libraries/recording/src/recording/Logging.h @@ -0,0 +1,16 @@ +// +// Created by Bradley Austin Davis 2015/10/11 +// 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_Controllers_Logging_h +#define hifi_Controllers_Logging_h + +#include + +Q_DECLARE_LOGGING_CATEGORY(recordingLog) + +#endif diff --git a/libraries/recording/src/recording/Recorder.cpp b/libraries/recording/src/recording/Recorder.cpp index a38e4252b9..b2e7399cd4 100644 --- a/libraries/recording/src/recording/Recorder.cpp +++ b/libraries/recording/src/recording/Recorder.cpp @@ -51,7 +51,7 @@ void Recorder::recordFrame(FrameType type, QByteArray frameData) { frame->type = type; frame->data = frameData; frame->timeOffset = (float)(_elapsed + _timer.elapsed()) / MSECS_PER_SECOND; - _clip->appendFrame(frame); + _clip->addFrame(frame); } ClipPointer Recorder::getClip() { diff --git a/libraries/recording/src/recording/impl/BufferClip.cpp b/libraries/recording/src/recording/impl/BufferClip.cpp index 378fee2558..4d5a910d42 100644 --- a/libraries/recording/src/recording/impl/BufferClip.cpp +++ b/libraries/recording/src/recording/impl/BufferClip.cpp @@ -51,11 +51,15 @@ FramePointer BufferClip::nextFrame() { return result; } -void BufferClip::appendFrame(FramePointer newFrame) { +void BufferClip::addFrame(FramePointer newFrame) { + if (newFrame->timeOffset < 0.0f) { + throw std::runtime_error("Frames may not have negative time offsets"); + } auto currentPosition = position(); seek(newFrame->timeOffset); { Locker lock(_mutex); + _frames.insert(_frames.begin() + _frameIndex, newFrame); } seek(currentPosition); @@ -72,3 +76,15 @@ void BufferClip::reset() { Locker lock(_mutex); _frameIndex = 0; } + +float BufferClip::duration() const { + if (_frames.empty()) { + return 0; + } + return (*_frames.rbegin())->timeOffset; +} + +size_t BufferClip::frameCount() const { + return _frames.size(); +} + diff --git a/libraries/recording/src/recording/impl/BufferClip.h b/libraries/recording/src/recording/impl/BufferClip.h index 8fd78a9091..b40687a4ec 100644 --- a/libraries/recording/src/recording/impl/BufferClip.h +++ b/libraries/recording/src/recording/impl/BufferClip.h @@ -20,25 +20,23 @@ class BufferClip : public Clip { public: using Pointer = std::shared_ptr; - BufferClip(QObject* parent = nullptr) : Clip(parent) {} virtual ~BufferClip() {} + virtual float duration() const override; + virtual size_t frameCount() const override; + virtual void seek(float offset) override; virtual float position() const override; virtual FramePointer peekFrame() const override; virtual FramePointer nextFrame() override; virtual void skipFrame() override; - virtual void appendFrame(FramePointer) override; + virtual void addFrame(FramePointer) override; private: - using Mutex = std::mutex; - using Locker = std::unique_lock; - virtual void reset() override; std::vector _frames; - mutable Mutex _mutex; mutable size_t _frameIndex { 0 }; }; diff --git a/libraries/recording/src/recording/impl/FileClip.cpp b/libraries/recording/src/recording/impl/FileClip.cpp index 354a97c5db..be7230e3f8 100644 --- a/libraries/recording/src/recording/impl/FileClip.cpp +++ b/libraries/recording/src/recording/impl/FileClip.cpp @@ -8,42 +8,197 @@ #include "FileClip.h" -#include "../Frame.h" - #include +#include +#include +#include + +#include + +#include "../Frame.h" +#include "../Logging.h" + + using namespace recording; -static const qint64 MINIMUM_FRAME_SIZE = sizeof(FrameType) + sizeof(float) + sizeof(uint16_t) + 1; +static const qint64 MINIMUM_FRAME_SIZE = sizeof(FrameType) + sizeof(float) + sizeof(uint16_t); -FileClip::FileClip(const QString& fileName, QObject* parent) : Clip(parent), _file(fileName) { - auto size = _file.size(); - _map = _file.map(0, size, QFile::MapPrivateOption); +static const QString FRAME_TYPE_MAP = QStringLiteral("frameTypes"); - auto current = _map; +using FrameHeaderList = std::list; +using FrameTranslationMap = QMap; + +FrameTranslationMap parseTranslationMap(const QJsonDocument& doc) { + FrameTranslationMap results; + auto headerObj = doc.object(); + if (headerObj.contains(FRAME_TYPE_MAP)) { + auto frameTypeObj = headerObj[FRAME_TYPE_MAP].toObject(); + auto currentFrameTypes = Frame::getFrameTypes(); + for (auto frameTypeName : frameTypeObj.keys()) { + qDebug() << frameTypeName; + if (!currentFrameTypes.contains(frameTypeName)) { + continue; + } + FrameType currentTypeEnum = currentFrameTypes[frameTypeName]; + FrameType storedTypeEnum = static_cast(frameTypeObj[frameTypeName].toInt()); + results[storedTypeEnum] = currentTypeEnum; + } + } + return results; +} + + +FrameHeaderList parseFrameHeaders(uchar* const start, const qint64& size) { + using FrameHeader = FileClip::FrameHeader; + FrameHeaderList results; + auto current = start; auto end = current + size; // Read all the frame headers - while (end - current < MINIMUM_FRAME_SIZE) { + // FIXME move to Frame::readHeader? + while (end - current >= MINIMUM_FRAME_SIZE) { FrameHeader header; memcpy(&(header.type), current, sizeof(FrameType)); current += sizeof(FrameType); - memcpy(&(header.timeOffset), current, sizeof(FrameType)); + memcpy(&(header.timeOffset), current, sizeof(float)); current += sizeof(float); memcpy(&(header.size), current, sizeof(uint16_t)); current += sizeof(uint16_t); - header.fileOffset = current - _map; + header.fileOffset = current - start; if (end - current < header.size) { + current = end; break; } - - _frameHeaders.push_back(header); + current += header.size; + results.push_back(header); } + return results; +} + + +FileClip::FileClip(const QString& fileName) : _file(fileName) { + auto size = _file.size(); + bool opened = _file.open(QIODevice::ReadOnly); + if (!opened) { + qCWarning(recordingLog) << "Unable to open file " << fileName; + return; + } + _map = _file.map(0, size, QFile::MapPrivateOption); + if (!_map) { + qCWarning(recordingLog) << "Unable to map file " << fileName; + return; + } + + FrameHeaderList parsedFrameHeaders = parseFrameHeaders(_map, size); + + // Verify that at least one frame exists and that the first frame is a header + if (0 == parsedFrameHeaders.size()) { + qWarning() << "No frames found, invalid file"; + return; + } + + // Grab the file header + { + auto fileHeaderFrameHeader = *parsedFrameHeaders.begin(); + parsedFrameHeaders.pop_front(); + if (fileHeaderFrameHeader.type != Frame::TYPE_HEADER) { + qWarning() << "Missing header frame, invalid file"; + return; + } + + QByteArray fileHeaderData((char*)_map + fileHeaderFrameHeader.fileOffset, fileHeaderFrameHeader.size); + _fileHeader = QJsonDocument::fromBinaryData(fileHeaderData); + } + + // Find the type enum translation map and fix up the frame headers + { + FrameTranslationMap translationMap = parseTranslationMap(_fileHeader); + if (translationMap.empty()) { + qWarning() << "Header missing frame type map, invalid file"; + return; + } + + // Update the loaded headers with the frame data + _frameHeaders.reserve(parsedFrameHeaders.size()); + for (auto& frameHeader : parsedFrameHeaders) { + if (!translationMap.contains(frameHeader.type)) { + continue; + } + frameHeader.type = translationMap[frameHeader.type]; + _frameHeaders.push_back(frameHeader); + } + } +} + +// FIXME move to frame? +bool writeFrame(QIODevice& output, const Frame& frame) { + auto written = output.write((char*)&(frame.type), sizeof(FrameType)); + if (written != sizeof(FrameType)) { + return false; + } + written = output.write((char*)&(frame.timeOffset), sizeof(float)); + if (written != sizeof(float)) { + return false; + } + uint16_t dataSize = frame.data.size(); + written = output.write((char*)&dataSize, sizeof(uint16_t)); + if (written != sizeof(uint16_t)) { + return false; + } + if (dataSize != 0) { + written = output.write(frame.data); + if (written != dataSize) { + return false; + } + } + return true; +} + +bool FileClip::write(const QString& fileName, Clip::Pointer clip) { + qCDebug(recordingLog) << "Writing clip to file " << fileName; + + if (0 == clip->frameCount()) { + return false; + } + + QFile outputFile(fileName); + if (!outputFile.open(QFile::Truncate | QFile::WriteOnly)) { + return false; + } + + Finally closer([&] { outputFile.close(); }); + { + auto frameTypes = Frame::getFrameTypes(); + QJsonObject frameTypeObj; + for (const auto& frameTypeName : frameTypes.keys()) { + frameTypeObj[frameTypeName] = frameTypes[frameTypeName]; + } + + QJsonObject rootObject; + rootObject.insert(FRAME_TYPE_MAP, frameTypeObj); + QByteArray headerFrameData = QJsonDocument(rootObject).toBinaryData(); + if (!writeFrame(outputFile, Frame({ Frame::TYPE_HEADER, 0, headerFrameData }))) { + return false; + } + } + + clip->seek(0); + for (auto frame = clip->nextFrame(); frame; frame = clip->nextFrame()) { + if (!writeFrame(outputFile, *frame)) { + return false; + } + } + outputFile.close(); + return true; } FileClip::~FileClip() { Locker lock(_mutex); _file.unmap(_map); _map = nullptr; + if (_file.isOpen()) { + _file.close(); + } } void FileClip::seek(float offset) { @@ -72,7 +227,9 @@ FramePointer FileClip::readFrame(uint32_t frameIndex) const { const FrameHeader& header = _frameHeaders[frameIndex]; result->type = header.type; result->timeOffset = header.timeOffset; - result->data.insert(0, reinterpret_cast(_map)+header.fileOffset, header.size); + if (header.size) { + result->data.insert(0, reinterpret_cast(_map)+header.fileOffset, header.size); + } } return result; } @@ -99,7 +256,18 @@ void FileClip::reset() { _frameIndex = 0; } -void FileClip::appendFrame(FramePointer) { +void FileClip::addFrame(FramePointer) { throw std::runtime_error("File clips are read only"); } +float FileClip::duration() const { + if (_frameHeaders.empty()) { + return 0; + } + return _frameHeaders.rbegin()->timeOffset; +} + +size_t FileClip::frameCount() const { + return _frameHeaders.size(); +} + diff --git a/libraries/recording/src/recording/impl/FileClip.h b/libraries/recording/src/recording/impl/FileClip.h index 9b13adc9ef..08eacd8337 100644 --- a/libraries/recording/src/recording/impl/FileClip.h +++ b/libraries/recording/src/recording/impl/FileClip.h @@ -13,6 +13,7 @@ #include "../Clip.h" #include +#include #include @@ -22,22 +23,25 @@ class FileClip : public Clip { public: using Pointer = std::shared_ptr; - FileClip(const QString& file, QObject* parent = nullptr); + FileClip(const QString& file); virtual ~FileClip(); + virtual float duration() const override; + virtual size_t frameCount() const override; + virtual void seek(float offset) override; virtual float position() const override; virtual FramePointer peekFrame() const override; virtual FramePointer nextFrame() override; - virtual void appendFrame(FramePointer) override; virtual void skipFrame() override; + virtual void addFrame(FramePointer) override; -private: - using Mutex = std::mutex; - using Locker = std::unique_lock; + const QJsonDocument& getHeader() { + return _fileHeader; + } - virtual void reset() override; + static bool write(const QString& filePath, Clip::Pointer clip); struct FrameHeader { FrameType type; @@ -46,15 +50,20 @@ private: quint64 fileOffset; }; - using FrameHeaders = std::vector; +private: + + virtual void reset() override; + + + using FrameHeaderVector = std::vector; FramePointer readFrame(uint32_t frameIndex) const; - mutable Mutex _mutex; + QJsonDocument _fileHeader; QFile _file; uint32_t _frameIndex { 0 }; - uchar* _map; - FrameHeaders _frameHeaders; + uchar* _map { nullptr }; + FrameHeaderVector _frameHeaders; }; } diff --git a/tests/recording/CMakeLists.txt b/tests/recording/CMakeLists.txt index f1e130956d..a523947f52 100644 --- a/tests/recording/CMakeLists.txt +++ b/tests/recording/CMakeLists.txt @@ -1,10 +1,16 @@ +set(TARGET_NAME recording-test) +# This is not a testcase -- just set it up as a regular hifi project +setup_hifi_project(Test) +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") +link_hifi_libraries(shared recording) +copy_dlls_beside_windows_executable() +# FIXME convert to unit tests # Declare dependencies -macro (setup_testcase_dependencies) - # link in the shared libraries - link_hifi_libraries(shared recording) - - copy_dlls_beside_windows_executable() -endmacro () - -setup_hifi_testcase() +#macro (setup_testcase_dependencies) +# # link in the shared libraries +# link_hifi_libraries(shared recording) +# +# copy_dlls_beside_windows_executable() +#endmacro () +#setup_hifi_testcase() diff --git a/tests/recording/src/Constants.h b/tests/recording/src/Constants.h index 37758bfd68..2aa19fe786 100644 --- a/tests/recording/src/Constants.h +++ b/tests/recording/src/Constants.h @@ -11,6 +11,8 @@ #ifndef hifi_Constants_h #define hifi_Constants_h +#include + static const QString HEADER_NAME = "com.highfidelity.recording.Header"; static const QString TEST_NAME = "com.highfidelity.recording.Test"; diff --git a/tests/recording/src/FrameTests.cpp b/tests/recording/src/FrameTests.cpp index f61d45c197..ebd7f90e31 100644 --- a/tests/recording/src/FrameTests.cpp +++ b/tests/recording/src/FrameTests.cpp @@ -8,6 +8,9 @@ #include "FrameTests.h" #include "Constants.h" + +#if 0 + #include "../QTestExtensions.h" #include @@ -27,3 +30,4 @@ void FrameTests::registerFrameTypeTest() { QCOMPARE(backMap[recording::Frame::TYPE_HEADER], HEADER_NAME); } +#endif diff --git a/tests/recording/src/FrameTests.h b/tests/recording/src/FrameTests.h index 04f73532a5..bdf4542846 100644 --- a/tests/recording/src/FrameTests.h +++ b/tests/recording/src/FrameTests.h @@ -10,6 +10,7 @@ #ifndef hifi_FrameTests_h #define hifi_FrameTests_h +#if 0 #include class FrameTests : public QObject { @@ -18,4 +19,6 @@ private slots: void registerFrameTypeTest(); }; +#endif + #endif // hifi_FrameTests_h diff --git a/tests/recording/src/RecorderTests.cpp b/tests/recording/src/RecorderTests.cpp index 76b4b46577..b102a3c931 100644 --- a/tests/recording/src/RecorderTests.cpp +++ b/tests/recording/src/RecorderTests.cpp @@ -8,6 +8,9 @@ #include "RecorderTests.h" #include "Constants.h" + +#if 0 + #include "../QTestExtensions.h" #include @@ -23,3 +26,4 @@ void RecorderTests::recorderTest() { //QCOMPARE(recoreder.isRecording(), false); } +#endif diff --git a/tests/recording/src/RecorderTests.h b/tests/recording/src/RecorderTests.h index 8e97a828a2..9bfd8e2d10 100644 --- a/tests/recording/src/RecorderTests.h +++ b/tests/recording/src/RecorderTests.h @@ -10,6 +10,8 @@ #ifndef hifi_RecorderTests_h #define hifi_RecorderTests_h +#if 0 + #include class RecorderTests : public QObject { @@ -19,3 +21,5 @@ private slots: }; #endif + +#endif diff --git a/tests/recording/src/main.cpp b/tests/recording/src/main.cpp new file mode 100644 index 0000000000..836d8b5ac1 --- /dev/null +++ b/tests/recording/src/main.cpp @@ -0,0 +1,114 @@ +#include +#include +#include +#include + +#ifdef Q_OS_WIN32 +#include +#endif + +#include +#include + +#include "Constants.h" + +#define QVERIFY Q_ASSERT + +using namespace recording; +FrameType TEST_FRAME_TYPE { Frame::TYPE_INVALID }; + +void testFrameTypeRegistration() { + TEST_FRAME_TYPE = Frame::registerFrameType(TEST_NAME); + QVERIFY(TEST_FRAME_TYPE != Frame::TYPE_INVALID); + QVERIFY(TEST_FRAME_TYPE != Frame::TYPE_HEADER); + + auto forwardMap = recording::Frame::getFrameTypes(); + QVERIFY(forwardMap.count(TEST_NAME) == 1); + QVERIFY(forwardMap[TEST_NAME] == TEST_FRAME_TYPE); + QVERIFY(forwardMap[HEADER_NAME] == recording::Frame::TYPE_HEADER); + + auto backMap = recording::Frame::getFrameTypeNames(); + QVERIFY(backMap.count(TEST_FRAME_TYPE) == 1); + QVERIFY(backMap[TEST_FRAME_TYPE] == TEST_NAME); + QVERIFY(backMap[recording::Frame::TYPE_HEADER] == HEADER_NAME); +} + +void testFilePersist() { + QTemporaryFile file; + QString fileName; + if (file.open()) { + fileName = file.fileName(); + file.close(); + } + auto readClip = Clip::fromFile(fileName); + QVERIFY(Clip::Pointer() == readClip); + auto writeClip = Clip::newClip(); + writeClip->addFrame(std::make_shared(TEST_FRAME_TYPE, 5.0f, QByteArray())); + QVERIFY(writeClip->frameCount() == 1); + QVERIFY(writeClip->duration() == 5.0f); + + Clip::toFile(fileName, writeClip); + readClip = Clip::fromFile(fileName); + QVERIFY(readClip != Clip::Pointer()); + QVERIFY(readClip->frameCount() == 1); + QVERIFY(readClip->duration() == 5.0f); + readClip->seek(0); + writeClip->seek(0); + + size_t count = 0; + for (auto readFrame = readClip->nextFrame(), writeFrame = writeClip->nextFrame(); readFrame && writeFrame; + readFrame = readClip->nextFrame(), writeFrame = writeClip->nextFrame(), ++count) { + QVERIFY(readFrame->type == writeFrame->type); + QVERIFY(readFrame->timeOffset == writeFrame->timeOffset); + QVERIFY(readFrame->data == writeFrame->data); + } + QVERIFY(readClip->frameCount() == count); + + + writeClip = Clip::newClip(); + writeClip->addFrame(std::make_shared(TEST_FRAME_TYPE, 5.0f, QByteArray())); + // Simulate an unknown frametype + writeClip->addFrame(std::make_shared(Frame::TYPE_INVALID - 1, 10.0f, QByteArray())); + QVERIFY(writeClip->frameCount() == 2); + QVERIFY(writeClip->duration() == 10.0f); + Clip::toFile(fileName, writeClip); + + // Verify that the read version of the clip ignores the unknown frame type + readClip = Clip::fromFile(fileName); + QVERIFY(readClip != Clip::Pointer()); + QVERIFY(readClip->frameCount() == 1); + QVERIFY(readClip->duration() == 5.0f); +} + +void testClipOrdering() { + auto writeClip = Clip::newClip(); + // simulate our of order addition of frames + writeClip->addFrame(std::make_shared(TEST_FRAME_TYPE, 10.0f, QByteArray())); + writeClip->addFrame(std::make_shared(TEST_FRAME_TYPE, 5.0f, QByteArray())); + QVERIFY(writeClip->frameCount() == 2); + QVERIFY(writeClip->duration() == 10.0f); + + QVERIFY(std::numeric_limits::max() == writeClip->position()); + writeClip->seek(0); + QVERIFY(5.0f == writeClip->position()); + float lastFrameTimeOffset { 0 }; + for (auto writeFrame = writeClip->nextFrame(); writeFrame; writeFrame = writeClip->nextFrame()) { + QVERIFY(writeClip->position() >= lastFrameTimeOffset); + } +} + +#ifdef Q_OS_WIN32 +void myMessageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg) { + OutputDebugStringA(msg.toLocal8Bit().toStdString().c_str()); + OutputDebugStringA("\n"); +} +#endif + +int main(int, const char**) { +#ifdef Q_OS_WIN32 + qInstallMessageHandler(myMessageHandler); +#endif + testFrameTypeRegistration(); + testFilePersist(); + testClipOrdering(); +} \ No newline at end of file From c1690bcf322d24bdc200e86201db6f4ef44db20c Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Fri, 6 Nov 2015 15:19:14 -0800 Subject: [PATCH 03/20] restoring avatarMover app post S3-loss event --- examples/avatarMover/avatarMoverSpawner.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/examples/avatarMover/avatarMoverSpawner.js b/examples/avatarMover/avatarMoverSpawner.js index 0bff3b02c0..526446ecdb 100644 --- a/examples/avatarMover/avatarMoverSpawner.js +++ b/examples/avatarMover/avatarMoverSpawner.js @@ -1,6 +1,18 @@ var modelURL = "https://s3.amazonaws.com/hifi-public/eric/models/arrow.fbx"; +var scriptURL = Script.resolvePath('avatarMover.js'); +var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(Camera.getOrientation()))); var avatarMover = Entities.addEntity({ type: "Model", - modelURL: modelURL -}) \ No newline at end of file + modelURL: modelURL, + position: center, + userData: JSON.stringify({range: 5}), + script: scriptURL +}); + + +function cleanup() { + Entities.deleteEntity(avatarMover); +} + +Script.scriptEnding.connect(cleanup); \ No newline at end of file From 298ac650d8ea36f12d877d28ce35ac585e6d4c8f Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 20 Oct 2015 21:25:49 -0700 Subject: [PATCH 04/20] Isolate sixense dynamic linking for OSX --- .../src/input-plugins/SixenseManager.cpp | 101 +++--------------- .../src/input-plugins/SixenseManager.h | 18 ---- .../src/input-plugins/SixenseSupportOSX.cpp | 97 +++++++++++++++++ 3 files changed, 109 insertions(+), 107 deletions(-) create mode 100644 libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index 33b4332430..24b1b60356 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -9,12 +9,21 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +#include "SixenseManager.h" + +#ifdef HAVE_SIXENSE +#include "sixense.h" +#endif #include #include #include +// TODO: This should not be here +#include +Q_DECLARE_LOGGING_CATEGORY(inputplugins) +Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins") + #include #include #include @@ -25,40 +34,12 @@ #include #include -#include "SixenseManager.h" - - -#ifdef HAVE_SIXENSE - #include "sixense.h" - -#ifdef __APPLE__ -static QLibrary* _sixenseLibrary { nullptr }; -#endif - -#endif - -// TODO: This should not be here -#include -Q_DECLARE_LOGGING_CATEGORY(inputplugins) -Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins") - -#ifdef HAVE_SIXENSE - +#include "UserActivityLogger.h" const glm::vec3 SixenseManager::DEFAULT_AVATAR_POSITION { -0.25f, -0.35f, -0.3f }; // in hydra frame const float SixenseManager::CONTROLLER_THRESHOLD { 0.35f }; const float SixenseManager::DEFAULT_REACH_LENGTH { 1.5f }; -#endif - -#ifdef __APPLE__ -typedef int (*SixenseBaseFunction)(); -typedef int (*SixenseTakeIntFunction)(int); -#ifdef HAVE_SIXENSE -typedef int (*SixenseTakeIntAndSixenseControllerData)(int, sixenseControllerData*); -#endif -#endif - const QString SixenseManager::NAME = "Sixense"; const QString SixenseManager::HYDRA_ID_STRING = "Razer Hydra"; @@ -94,31 +75,6 @@ void SixenseManager::activate() { auto userInputMapper = DependencyManager::get(); userInputMapper->registerDevice(_inputDevice); -#ifdef __APPLE__ - - if (!_sixenseLibrary) { - -#ifdef SIXENSE_LIB_FILENAME - _sixenseLibrary = new QLibrary(SIXENSE_LIB_FILENAME); -#else - const QString SIXENSE_LIBRARY_NAME = "libsixense_x64"; - QString frameworkSixenseLibrary = QCoreApplication::applicationDirPath() + "/../Frameworks/" - + SIXENSE_LIBRARY_NAME; - - _sixenseLibrary = new QLibrary(frameworkSixenseLibrary); -#endif - } - - if (_sixenseLibrary->load()){ - qCDebug(inputplugins) << "Loaded sixense library for hydra support -" << _sixenseLibrary->fileName(); - } else { - qCDebug(inputplugins) << "Sixense library at" << _sixenseLibrary->fileName() << "failed to load." - << "Continuing without hydra support."; - return; - } - - SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit"); -#endif loadSettings(); sixenseInit(); #endif @@ -139,26 +95,13 @@ void SixenseManager::deactivate() { userInputMapper->removeDevice(_inputDevice->_deviceID); } -#ifdef __APPLE__ - SixenseBaseFunction sixenseExit = (SixenseBaseFunction)_sixenseLibrary->resolve("sixenseExit"); -#endif - sixenseExit(); - -#ifdef __APPLE__ - delete _sixenseLibrary; -#endif - #endif } void SixenseManager::setSixenseFilter(bool filter) { #ifdef HAVE_SIXENSE -#ifdef __APPLE__ - SixenseTakeIntFunction sixenseSetFilterEnabled = (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseSetFilterEnabled"); -#endif - int newFilter = filter ? 1 : 0; - sixenseSetFilterEnabled(newFilter); + sixenseSetFilterEnabled(filter ? 1 : 0); #endif } @@ -180,11 +123,6 @@ void SixenseManager::InputDevice::update(float deltaTime, bool jointsCaptured) { #ifdef HAVE_SIXENSE _buttonPressedMap.clear(); -#ifdef __APPLE__ - SixenseBaseFunction sixenseGetNumActiveControllers = - (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseGetNumActiveControllers"); -#endif - auto userInputMapper = DependencyManager::get(); static const float MAX_DISCONNECTED_TIME = 2.0f; @@ -213,24 +151,11 @@ void SixenseManager::InputDevice::update(float deltaTime, bool jointsCaptured) { // FIXME send this message once when we've positively identified hydra hardware //UserActivityLogger::getInstance().connectedDevice("spatial_controller", "hydra"); -#ifdef __APPLE__ - SixenseBaseFunction sixenseGetMaxControllers = - (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseGetMaxControllers"); -#endif - int maxControllers = sixenseGetMaxControllers(); // we only support two controllers sixenseControllerData controllers[2]; -#ifdef __APPLE__ - SixenseTakeIntFunction sixenseIsControllerEnabled = - (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseIsControllerEnabled"); - - SixenseTakeIntAndSixenseControllerData sixenseGetNewestData = - (SixenseTakeIntAndSixenseControllerData) _sixenseLibrary->resolve("sixenseGetNewestData"); -#endif - int numActiveControllers = 0; for (int i = 0; i < maxControllers && numActiveControllers < 2; i++) { if (!sixenseIsControllerEnabled(i)) { @@ -479,8 +404,6 @@ void SixenseManager::InputDevice::handlePoseEvent(float deltaTime, glm::vec3 pos glm::vec3 velocity(0.0f); glm::quat angularVelocity; - - if (prevPose.isValid() && deltaTime > std::numeric_limits::epsilon()) { velocity = (position - prevPose.getTranslation()) / deltaTime; diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/libraries/input-plugins/src/input-plugins/SixenseManager.h index 062a27390c..bf657d347b 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.h @@ -12,18 +12,6 @@ #ifndef hifi_SixenseManager_h #define hifi_SixenseManager_h -#ifdef HAVE_SIXENSE - #include - #include - #include "sixense.h" - -#ifdef __APPLE__ - #include - #include -#endif - -#endif - #include #include @@ -31,8 +19,6 @@ #include "InputPlugin.h" -class QLibrary; - 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; @@ -75,7 +61,6 @@ private: static const float CONTROLLER_THRESHOLD; static const float DEFAULT_REACH_LENGTH; - using Samples = std::pair< MovingAverage< glm::vec3, MAX_NUM_AVERAGING_SAMPLES>, MovingAverage< glm::vec4, MAX_NUM_AVERAGING_SAMPLES> >; using MovingAverageMap = std::map< int, Samples >; @@ -113,9 +98,6 @@ private: glm::vec3 _reachRight; }; - - - bool _useSixenseFilter = true; std::shared_ptr _inputDevice { std::make_shared() }; static const QString NAME; diff --git a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp new file mode 100644 index 0000000000..c5c3f7f14a --- /dev/null +++ b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp @@ -0,0 +1,97 @@ +// +// SixenseSupportOSX.cpp +// +// +// Created by Clement on 10/20/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 +// + +#ifdef __APPLE__ +#include "sixense.h" + +#include +#include +#include + +using std::string; +using std::unique_ptr; +using SixenseBaseFunction = int (*)(); +using SixenseTakeIntFunction = int (*)(int); +using SixenseTakeIntAndSixenseControllerData = int (*)(int, sixenseControllerData*); + +static unique_ptr SIXENSE; + +bool loadSixense() { + if (!SIXENSE) { + static const QString LIBRARY_PATH = +#ifdef SIXENSE_LIB_FILENAME + SIXENSE_LIB_FILENAME; +#else + QCoreApplication::applicationDirPath() + "/../Frameworks/libsixense_x64"; +#endif + SIXENSE.reset(new QLibrary(LIBRARY_PATH)); + } + + if (SIXENSE->load()){ + qDebug() << "Loaded sixense library for hydra support -" << SIXENSE->fileName(); + } else { + qDebug() << "Sixense library at" << SIXENSE->fileName() << "failed to load:" << SIXENSE->errorString(); + qDebug() << "Continuing without hydra support."; + } + return SIXENSE->isLoaded(); +} + +void unloadSixense() { + SIXENSE->unload(); +} + +template +Func resolve(const char* name) { + Q_ASSERT_X(SIXENSE && SIXENSE->isLoaded(), __FUNCTION__, "Sixense library not loaded"); + auto func = reinterpret_cast(SIXENSE->resolve(name)); + Q_ASSERT_X(func, __FUNCTION__, string("Could not resolve ").append(name).c_str()); + return func; +} + +// sixense.h wrapper for OSX dynamic linking +int sixenseInit() { + loadSixense(); + auto sixenseInit = resolve("sixenseInit"); + return sixenseInit(); +} + +int sixenseExit() { + auto sixenseExit = resolve("sixenseExit"); + auto returnCode = sixenseExit(); + unloadSixense(); + return returnCode; +} + +int sixenseSetFilterEnabled(int input) { + auto sixenseSetFilterEnabled = resolve("sixenseSetFilterEnabled"); + return sixenseSetFilterEnabled(input); +} + +int sixenseGetNumActiveControllers() { + auto sixenseGetNumActiveControllers = resolve("sixenseGetNumActiveControllers"); + return sixenseGetNumActiveControllers(); +} + +int sixenseGetMaxControllers() { + auto sixenseGetMaxControllers = resolve("sixenseGetMaxControllers"); + return sixenseGetMaxControllers(); +} + +int sixenseIsControllerEnabled(int input) { + auto sixenseIsControllerEnabled = resolve("sixenseIsControllerEnabled"); + return sixenseIsControllerEnabled(input); +} + +int sixenseGetNewestData(int input1, sixenseControllerData* intput2) { + auto sixenseGetNewestData = resolve("sixenseGetNewestData"); + return sixenseGetNewestData(input1, intput2); +} +#endif From 96aa5be457d1455348ffdf5e90f38898c79eaf3a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 20 Oct 2015 23:06:44 -0700 Subject: [PATCH 05/20] Implement all Sixense methods for OS X --- .../src/input-plugins/SixenseSupportOSX.cpp | 102 +++++++++++++----- 1 file changed, 76 insertions(+), 26 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp index c5c3f7f14a..a890d7c138 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp @@ -24,7 +24,7 @@ using SixenseTakeIntAndSixenseControllerData = int (*)(int, sixenseControllerDat static unique_ptr SIXENSE; -bool loadSixense() { +void loadSixense() { if (!SIXENSE) { static const QString LIBRARY_PATH = #ifdef SIXENSE_LIB_FILENAME @@ -41,57 +41,107 @@ bool loadSixense() { qDebug() << "Sixense library at" << SIXENSE->fileName() << "failed to load:" << SIXENSE->errorString(); qDebug() << "Continuing without hydra support."; } - return SIXENSE->isLoaded(); } void unloadSixense() { SIXENSE->unload(); } -template -Func resolve(const char* name) { +template +int call(const char* name, Args... args) { Q_ASSERT_X(SIXENSE && SIXENSE->isLoaded(), __FUNCTION__, "Sixense library not loaded"); - auto func = reinterpret_cast(SIXENSE->resolve(name)); + auto func = reinterpret_cast(SIXENSE->resolve(name)); Q_ASSERT_X(func, __FUNCTION__, string("Could not resolve ").append(name).c_str()); - return func; + return func(args...); } // sixense.h wrapper for OSX dynamic linking int sixenseInit() { loadSixense(); - auto sixenseInit = resolve("sixenseInit"); - return sixenseInit(); + return call(__FUNCTION__); } - int sixenseExit() { - auto sixenseExit = resolve("sixenseExit"); - auto returnCode = sixenseExit(); + auto returnCode = call(__FUNCTION__); unloadSixense(); return returnCode; } -int sixenseSetFilterEnabled(int input) { - auto sixenseSetFilterEnabled = resolve("sixenseSetFilterEnabled"); - return sixenseSetFilterEnabled(input); +int sixenseGetMaxBases() { + return call(__FUNCTION__); } - -int sixenseGetNumActiveControllers() { - auto sixenseGetNumActiveControllers = resolve("sixenseGetNumActiveControllers"); - return sixenseGetNumActiveControllers(); +int sixenseSetActiveBase(int i) { + return call(__FUNCTION__, i); +} +int sixenseIsBaseConnected(int i) { + return call(__FUNCTION__, i); } int sixenseGetMaxControllers() { - auto sixenseGetMaxControllers = resolve("sixenseGetMaxControllers"); - return sixenseGetMaxControllers(); + return call(__FUNCTION__); +} +int sixenseIsControllerEnabled(int which) { + return call(__FUNCTION__, which); +} +int sixenseGetNumActiveControllers() { + return call(__FUNCTION__); } -int sixenseIsControllerEnabled(int input) { - auto sixenseIsControllerEnabled = resolve("sixenseIsControllerEnabled"); - return sixenseIsControllerEnabled(input); +int sixenseGetHistorySize() { + return call(__FUNCTION__); } -int sixenseGetNewestData(int input1, sixenseControllerData* intput2) { - auto sixenseGetNewestData = resolve("sixenseGetNewestData"); - return sixenseGetNewestData(input1, intput2); +int sixenseGetData(int which, int index_back, sixenseControllerData* data) { + return call(__FUNCTION__, which, index_back, data); +} +int sixenseGetAllData(int index_back, sixenseAllControllerData* data) { + return call(__FUNCTION__, index_back, data); +} +int sixenseGetNewestData(int which, sixenseControllerData* data) { + return call(__FUNCTION__, which, data); +} +int sixenseGetAllNewestData(sixenseAllControllerData* data) { + return call(__FUNCTION__, data); +} + +int sixenseSetHemisphereTrackingMode(int which_controller, int state) { + return call(__FUNCTION__, which_controller, state); +} +int sixenseGetHemisphereTrackingMode(int which_controller, int* state) { + return call(__FUNCTION__, which_controller, state); +} +int sixenseAutoEnableHemisphereTracking(int which_controller) { + return call(__FUNCTION__, which_controller); +} + +int sixenseSetHighPriorityBindingEnabled(int on_or_off) { + return call(__FUNCTION__, on_or_off); +} +int sixenseGetHighPriorityBindingEnabled(int* on_or_off) { + return call(__FUNCTION__, on_or_off); +} + +int sixenseTriggerVibration(int controller_id, int duration_100ms, int pattern_id) { + return call(__FUNCTION__, controller_id, duration_100ms, pattern_id); +} + +int sixenseSetFilterEnabled(int on_or_off) { + return call(__FUNCTION__, on_or_off); +} +int sixenseGetFilterEnabled(int* on_or_off) { + return call(__FUNCTION__, on_or_off); +} + +int sixenseSetFilterParams(float near_range, float near_val, float far_range, float far_val) { + return call(__FUNCTION__, near_range, near_val, far_range, far_val); +} +int sixenseGetFilterParams(float* near_range, float* near_val, float* far_range, float* far_val) { + return call(__FUNCTION__, near_range, near_val, far_range, far_val); +} + +int sixenseSetBaseColor(unsigned char red, unsigned char green, unsigned char blue) { + return call(__FUNCTION__, red, green, blue); +} +int sixenseGetBaseColor(unsigned char* red, unsigned char* green, unsigned char* blue) { + return call(__FUNCTION__, red, green, blue); } #endif From 503e03d4a811b67c7beade04bc030c45a494cab3 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 20 Oct 2015 23:17:58 -0700 Subject: [PATCH 06/20] Remove unused `using` --- .../src/input-plugins/SixenseSupportOSX.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp index a890d7c138..99af9c0ffc 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp @@ -16,13 +16,7 @@ #include #include -using std::string; -using std::unique_ptr; -using SixenseBaseFunction = int (*)(); -using SixenseTakeIntFunction = int (*)(int); -using SixenseTakeIntAndSixenseControllerData = int (*)(int, sixenseControllerData*); - -static unique_ptr SIXENSE; +static std::unique_ptr SIXENSE; void loadSixense() { if (!SIXENSE) { @@ -51,7 +45,7 @@ template int call(const char* name, Args... args) { Q_ASSERT_X(SIXENSE && SIXENSE->isLoaded(), __FUNCTION__, "Sixense library not loaded"); auto func = reinterpret_cast(SIXENSE->resolve(name)); - Q_ASSERT_X(func, __FUNCTION__, string("Could not resolve ").append(name).c_str()); + Q_ASSERT_X(func, __FUNCTION__, std::string("Could not resolve ").append(name).c_str()); return func(args...); } From e3b54f0272a25a8f38ddd4721109f4f1eae4a939 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 20 Oct 2015 23:41:20 -0700 Subject: [PATCH 07/20] Cleanup --- .../src/input-plugins/SixenseSupportOSX.cpp | 81 ++++++++++--------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp index 99af9c0ffc..4c8a285d76 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp @@ -1,6 +1,6 @@ // // SixenseSupportOSX.cpp -// +// libraries/input-plugins/src/input-plugins // // Created by Clement on 10/20/15. // Copyright 2015 High Fidelity, Inc. @@ -9,14 +9,31 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifdef __APPLE__ +#if defined(__APPLE__) && defined(HAVE_SIXENSE) #include "sixense.h" #include #include #include -static std::unique_ptr SIXENSE; +using Library = std::unique_ptr; +static Library SIXENSE; + +struct Callable { + template int operator() (Args... args){ + return reinterpret_cast(function)(args...); + } + QFunctionPointer function; +}; + +Callable resolve(const Library& library, const char* name) { + Q_ASSERT_X(library && library->isLoaded(), __FUNCTION__, "Sixense library not loaded"); + auto function = library->resolve(name); + Q_ASSERT_X(function, __FUNCTION__, std::string("Could not resolve ").append(name).c_str()); + return Callable { function }; +} +#define FOREWARD resolve(SIXENSE, __FUNCTION__) + void loadSixense() { if (!SIXENSE) { @@ -36,106 +53,98 @@ void loadSixense() { qDebug() << "Continuing without hydra support."; } } - void unloadSixense() { SIXENSE->unload(); } -template -int call(const char* name, Args... args) { - Q_ASSERT_X(SIXENSE && SIXENSE->isLoaded(), __FUNCTION__, "Sixense library not loaded"); - auto func = reinterpret_cast(SIXENSE->resolve(name)); - Q_ASSERT_X(func, __FUNCTION__, std::string("Could not resolve ").append(name).c_str()); - return func(args...); -} // sixense.h wrapper for OSX dynamic linking int sixenseInit() { loadSixense(); - return call(__FUNCTION__); + return FOREWARD(); } int sixenseExit() { - auto returnCode = call(__FUNCTION__); + auto returnCode = FOREWARD(); unloadSixense(); return returnCode; } int sixenseGetMaxBases() { - return call(__FUNCTION__); + return FOREWARD(); } int sixenseSetActiveBase(int i) { - return call(__FUNCTION__, i); + return FOREWARD(i); } int sixenseIsBaseConnected(int i) { - return call(__FUNCTION__, i); + return FOREWARD(i); } int sixenseGetMaxControllers() { - return call(__FUNCTION__); + return FOREWARD(); } int sixenseIsControllerEnabled(int which) { - return call(__FUNCTION__, which); + return FOREWARD(which); } int sixenseGetNumActiveControllers() { - return call(__FUNCTION__); + return FOREWARD(); } int sixenseGetHistorySize() { - return call(__FUNCTION__); + return FOREWARD(); } int sixenseGetData(int which, int index_back, sixenseControllerData* data) { - return call(__FUNCTION__, which, index_back, data); + return FOREWARD(which, index_back, data); } int sixenseGetAllData(int index_back, sixenseAllControllerData* data) { - return call(__FUNCTION__, index_back, data); + return FOREWARD(index_back, data); } int sixenseGetNewestData(int which, sixenseControllerData* data) { - return call(__FUNCTION__, which, data); + return FOREWARD(which, data); } int sixenseGetAllNewestData(sixenseAllControllerData* data) { - return call(__FUNCTION__, data); + return FOREWARD(data); } int sixenseSetHemisphereTrackingMode(int which_controller, int state) { - return call(__FUNCTION__, which_controller, state); + return FOREWARD(which_controller, state); } int sixenseGetHemisphereTrackingMode(int which_controller, int* state) { - return call(__FUNCTION__, which_controller, state); + return FOREWARD(which_controller, state); } int sixenseAutoEnableHemisphereTracking(int which_controller) { - return call(__FUNCTION__, which_controller); + return FOREWARD(which_controller); } int sixenseSetHighPriorityBindingEnabled(int on_or_off) { - return call(__FUNCTION__, on_or_off); + return FOREWARD(on_or_off); } int sixenseGetHighPriorityBindingEnabled(int* on_or_off) { - return call(__FUNCTION__, on_or_off); + return FOREWARD(on_or_off); } int sixenseTriggerVibration(int controller_id, int duration_100ms, int pattern_id) { - return call(__FUNCTION__, controller_id, duration_100ms, pattern_id); + return FOREWARD(controller_id, duration_100ms, pattern_id); } int sixenseSetFilterEnabled(int on_or_off) { - return call(__FUNCTION__, on_or_off); + return FOREWARD(on_or_off); } int sixenseGetFilterEnabled(int* on_or_off) { - return call(__FUNCTION__, on_or_off); + return FOREWARD(on_or_off); } int sixenseSetFilterParams(float near_range, float near_val, float far_range, float far_val) { - return call(__FUNCTION__, near_range, near_val, far_range, far_val); + return FOREWARD(near_range, near_val, far_range, far_val); } int sixenseGetFilterParams(float* near_range, float* near_val, float* far_range, float* far_val) { - return call(__FUNCTION__, near_range, near_val, far_range, far_val); + return FOREWARD(near_range, near_val, far_range, far_val); } int sixenseSetBaseColor(unsigned char red, unsigned char green, unsigned char blue) { - return call(__FUNCTION__, red, green, blue); + return FOREWARD(red, green, blue); } int sixenseGetBaseColor(unsigned char* red, unsigned char* green, unsigned char* blue) { - return call(__FUNCTION__, red, green, blue); + return FOREWARD(red, green, blue); } #endif From 6ad20e417b41ddce22c7c13bc8d6811742b21600 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 21 Oct 2015 18:27:32 -0700 Subject: [PATCH 08/20] Typo --- .../src/input-plugins/SixenseSupportOSX.cpp | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp index 4c8a285d76..3ac2d197c2 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp @@ -32,7 +32,7 @@ Callable resolve(const Library& library, const char* name) { Q_ASSERT_X(function, __FUNCTION__, std::string("Could not resolve ").append(name).c_str()); return Callable { function }; } -#define FOREWARD resolve(SIXENSE, __FUNCTION__) +#define FORWARD resolve(SIXENSE, __FUNCTION__) void loadSixense() { @@ -61,90 +61,90 @@ void unloadSixense() { // sixense.h wrapper for OSX dynamic linking int sixenseInit() { loadSixense(); - return FOREWARD(); + return FORWARD(); } int sixenseExit() { - auto returnCode = FOREWARD(); + auto returnCode = FORWARD(); unloadSixense(); return returnCode; } int sixenseGetMaxBases() { - return FOREWARD(); + return FORWARD(); } int sixenseSetActiveBase(int i) { - return FOREWARD(i); + return FORWARD(i); } int sixenseIsBaseConnected(int i) { - return FOREWARD(i); + return FORWARD(i); } int sixenseGetMaxControllers() { - return FOREWARD(); + return FORWARD(); } int sixenseIsControllerEnabled(int which) { - return FOREWARD(which); + return FORWARD(which); } int sixenseGetNumActiveControllers() { - return FOREWARD(); + return FORWARD(); } int sixenseGetHistorySize() { - return FOREWARD(); + return FORWARD(); } int sixenseGetData(int which, int index_back, sixenseControllerData* data) { - return FOREWARD(which, index_back, data); + return FORWARD(which, index_back, data); } int sixenseGetAllData(int index_back, sixenseAllControllerData* data) { - return FOREWARD(index_back, data); + return FORWARD(index_back, data); } int sixenseGetNewestData(int which, sixenseControllerData* data) { - return FOREWARD(which, data); + return FORWARD(which, data); } int sixenseGetAllNewestData(sixenseAllControllerData* data) { - return FOREWARD(data); + return FORWARD(data); } int sixenseSetHemisphereTrackingMode(int which_controller, int state) { - return FOREWARD(which_controller, state); + return FORWARD(which_controller, state); } int sixenseGetHemisphereTrackingMode(int which_controller, int* state) { - return FOREWARD(which_controller, state); + return FORWARD(which_controller, state); } int sixenseAutoEnableHemisphereTracking(int which_controller) { - return FOREWARD(which_controller); + return FORWARD(which_controller); } int sixenseSetHighPriorityBindingEnabled(int on_or_off) { - return FOREWARD(on_or_off); + return FORWARD(on_or_off); } int sixenseGetHighPriorityBindingEnabled(int* on_or_off) { - return FOREWARD(on_or_off); + return FORWARD(on_or_off); } int sixenseTriggerVibration(int controller_id, int duration_100ms, int pattern_id) { - return FOREWARD(controller_id, duration_100ms, pattern_id); + return FORWARD(controller_id, duration_100ms, pattern_id); } int sixenseSetFilterEnabled(int on_or_off) { - return FOREWARD(on_or_off); + return FORWARD(on_or_off); } int sixenseGetFilterEnabled(int* on_or_off) { - return FOREWARD(on_or_off); + return FORWARD(on_or_off); } int sixenseSetFilterParams(float near_range, float near_val, float far_range, float far_val) { - return FOREWARD(near_range, near_val, far_range, far_val); + return FORWARD(near_range, near_val, far_range, far_val); } int sixenseGetFilterParams(float* near_range, float* near_val, float* far_range, float* far_val) { - return FOREWARD(near_range, near_val, far_range, far_val); + return FORWARD(near_range, near_val, far_range, far_val); } int sixenseSetBaseColor(unsigned char red, unsigned char green, unsigned char blue) { - return FOREWARD(red, green, blue); + return FORWARD(red, green, blue); } int sixenseGetBaseColor(unsigned char* red, unsigned char* green, unsigned char* blue) { - return FOREWARD(red, green, blue); + return FORWARD(red, green, blue); } #endif From 0a65bb145b0b4a1cb9445999619b576af93578ee Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 5 Nov 2015 11:08:20 -0800 Subject: [PATCH 09/20] Some more code cleanup --- interface/src/ui/ApplicationCompositor.cpp | 13 +------ .../src/input-plugins/SixenseManager.cpp | 38 +++++++++---------- .../src/input-plugins/SixenseManager.h | 23 +++-------- 3 files changed, 24 insertions(+), 50 deletions(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 2a2a45b67b..5b7bbc2aba 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -473,18 +473,7 @@ void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) { continue; } - int controllerButtons = 0; - - //Check for if we should toggle or drag the magnification window - if (controllerButtons & BUTTON_3) { - if (isPressed[index] == false) { - //We are now dragging the window - isPressed[index] = true; - //set the pressed time in us - pressedTime[index] = usecTimestampNow(); - stateWhenPressed[index] = _magActive[index]; - } - } else if (isPressed[index]) { + if (isPressed[index]) { isPressed[index] = false; //If the button was only pressed for < 250 ms //then disable it. diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index 24b1b60356..56f79ce3c1 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -24,21 +24,25 @@ Q_DECLARE_LOGGING_CATEGORY(inputplugins) Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins") +#include #include #include -#include -#include -#include #include -#include +#include +#include +#include #include -#include -#include "UserActivityLogger.h" +static const unsigned int BUTTON_0 = 1U << 0; // the skinny button between 1 and 2 +static const unsigned int BUTTON_1 = 1U << 5; +static const unsigned int BUTTON_2 = 1U << 6; +static const unsigned int BUTTON_3 = 1U << 3; +static const unsigned int BUTTON_4 = 1U << 4; +static const unsigned int BUTTON_FWD = 1U << 7; +static const unsigned int BUTTON_TRIGGER = 1U << 8; const glm::vec3 SixenseManager::DEFAULT_AVATAR_POSITION { -0.25f, -0.35f, -0.3f }; // in hydra frame const float SixenseManager::CONTROLLER_THRESHOLD { 0.35f }; -const float SixenseManager::DEFAULT_REACH_LENGTH { 1.5f }; const QString SixenseManager::NAME = "Sixense"; const QString SixenseManager::HYDRA_ID_STRING = "Razer Hydra"; @@ -47,7 +51,6 @@ const QString MENU_PARENT = "Avatar"; const QString MENU_NAME = "Sixense"; const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME; const QString TOGGLE_SMOOTH = "Smooth Sixense Movement"; -const float DEFAULT_REACH_LENGTH = 1.5f; bool SixenseManager::isSupported() const { #ifdef HAVE_SIXENSE @@ -65,11 +68,11 @@ bool SixenseManager::isSupported() const { void SixenseManager::activate() { InputPlugin::activate(); + #ifdef HAVE_SIXENSE - _container->addMenu(MENU_PATH); _container->addMenuItem(MENU_PATH, TOGGLE_SMOOTH, - [this] (bool clicked) { this->setSixenseFilter(clicked); }, + [this] (bool clicked) { setSixenseFilter(clicked); }, true, true); auto userInputMapper = DependencyManager::get(); @@ -96,6 +99,7 @@ void SixenseManager::deactivate() { } sixenseExit(); + saveSettings(); #endif } @@ -123,8 +127,6 @@ void SixenseManager::InputDevice::update(float deltaTime, bool jointsCaptured) { #ifdef HAVE_SIXENSE _buttonPressedMap.clear(); - auto userInputMapper = DependencyManager::get(); - static const float MAX_DISCONNECTED_TIME = 2.0f; static bool disconnected { false }; static float disconnectedInterval { 0.0f }; @@ -218,9 +220,9 @@ void SixenseManager::InputDevice::update(float deltaTime, bool jointsCaptured) { // (4) assume that the orb is on a flat surface (yAxis is UP) // (5) compute the forward direction (zAxis = xAxis cross yAxis) -const float MINIMUM_ARM_REACH = 0.3f; // meters -const float MAXIMUM_NOISE_LEVEL = 0.05f; // meters -const quint64 LOCK_DURATION = USECS_PER_SECOND / 4; // time for lock to be acquired +static const float MINIMUM_ARM_REACH = 0.3f; // meters +static const float MAXIMUM_NOISE_LEVEL = 0.05f; // meters +static const quint64 LOCK_DURATION = USECS_PER_SECOND / 4; // time for lock to be acquired void SixenseManager::InputDevice::updateCalibration(void* controllersX) { auto controllers = reinterpret_cast(controllersX); @@ -240,14 +242,12 @@ void SixenseManager::InputDevice::updateCalibration(void* controllersX) { glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft); glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, Vectors::UNIT_Y)); xAxis = glm::normalize(glm::cross(Vectors::UNIT_Y, zAxis)); - _reachLength = glm::dot(xAxis, _reachRight - _reachLeft); _avatarRotation = glm::inverse(glm::quat_cast(glm::mat3(xAxis, Vectors::UNIT_Y, zAxis))); const float Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR = -0.3f; _avatarPosition.y += Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR; qCDebug(inputplugins, "succeess: sixense calibration"); } break; - default: _calibrationState = CALIBRATION_STATE_IDLE; qCDebug(inputplugins, "failed: sixense calibration"); @@ -441,8 +441,6 @@ static const auto R2 = controller::A; static const auto R3 = controller::B; static const auto R4 = controller::Y; -using namespace controller; - controller::Input::NamedVector SixenseManager::InputDevice::getAvailableInputs() const { using namespace controller; static const Input::NamedVector availableInputs { @@ -486,7 +484,6 @@ void SixenseManager::saveSettings() const { { settings.setVec3Value(QString("avatarPosition"), _inputDevice->_avatarPosition); settings.setQuatValue(QString("avatarRotation"), _inputDevice->_avatarRotation); - settings.setValue(QString("reachLength"), QVariant(_inputDevice->_reachLength)); } settings.endGroup(); } @@ -498,7 +495,6 @@ void SixenseManager::loadSettings() { { settings.getVec3ValueIfValid(QString("avatarPosition"), _inputDevice->_avatarPosition); settings.getQuatValueIfValid(QString("avatarRotation"), _inputDevice->_avatarRotation); - settings.getFloatValueIfValid(QString("reachLength"), _inputDevice->_reachLength); } settings.endGroup(); } diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/libraries/input-plugins/src/input-plugins/SixenseManager.h index bf657d347b..bdfbd539cb 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.h @@ -19,21 +19,10 @@ #include "InputPlugin.h" -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; -const unsigned int BUTTON_3 = 1U << 3; -const unsigned int BUTTON_4 = 1U << 4; -const unsigned int BUTTON_FWD = 1U << 7; -const unsigned int BUTTON_TRIGGER = 1U << 8; - -const bool DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS = false; - // Handles interaction with the Sixense SDK (e.g., Razer Hydra). class SixenseManager : public InputPlugin { Q_OBJECT public: - // Plugin functions virtual bool isSupported() const override; virtual bool isJointController() const override { return true; } @@ -52,17 +41,18 @@ public: public slots: void setSixenseFilter(bool filter); -private: +private: static const int MAX_NUM_AVERAGING_SAMPLES = 50; // At ~100 updates per seconds this means averaging over ~.5s static const int CALIBRATION_STATE_IDLE = 0; static const int CALIBRATION_STATE_IN_PROGRESS = 1; static const int CALIBRATION_STATE_COMPLETE = 2; static const glm::vec3 DEFAULT_AVATAR_POSITION; static const float CONTROLLER_THRESHOLD; - static const float DEFAULT_REACH_LENGTH; - - using Samples = std::pair< MovingAverage< glm::vec3, MAX_NUM_AVERAGING_SAMPLES>, MovingAverage< glm::vec4, MAX_NUM_AVERAGING_SAMPLES> >; - using MovingAverageMap = std::map< int, Samples >; + + template + using SampleAverage = MovingAverage; + using Samples = std::pair, SampleAverage>; + using MovingAverageMap = std::map; class InputDevice : public controller::InputDevice { public: @@ -88,7 +78,6 @@ private: glm::vec3 _avatarPosition { DEFAULT_AVATAR_POSITION }; // in hydra-frame glm::quat _avatarRotation; // in hydra-frame - float _reachLength { DEFAULT_REACH_LENGTH }; float _lastDistance; // these are measured values used to compute the calibration results quint64 _lockExpiry; From d95709ee731aaa9fa031963e021b10d32062ddfc Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 6 Nov 2015 16:45:23 -0800 Subject: [PATCH 10/20] Added input plugins logging category --- .../src/input-plugins/InputPluginsLogging.cpp | 14 ++++++++++++++ .../src/input-plugins/InputPluginsLogging.h | 18 ++++++++++++++++++ .../src/input-plugins/SixenseManager.cpp | 5 ----- .../src/input-plugins/SixenseSupportOSX.cpp | 2 ++ 4 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 libraries/input-plugins/src/input-plugins/InputPluginsLogging.cpp create mode 100644 libraries/input-plugins/src/input-plugins/InputPluginsLogging.h diff --git a/libraries/input-plugins/src/input-plugins/InputPluginsLogging.cpp b/libraries/input-plugins/src/input-plugins/InputPluginsLogging.cpp new file mode 100644 index 0000000000..c96941a8ca --- /dev/null +++ b/libraries/input-plugins/src/input-plugins/InputPluginsLogging.cpp @@ -0,0 +1,14 @@ +// +// InputPluginsLogging.cpp +// +// +// Created by Clement on 11/6/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 "InputPluginsLogging.h" + +Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins") diff --git a/libraries/input-plugins/src/input-plugins/InputPluginsLogging.h b/libraries/input-plugins/src/input-plugins/InputPluginsLogging.h new file mode 100644 index 0000000000..6460469190 --- /dev/null +++ b/libraries/input-plugins/src/input-plugins/InputPluginsLogging.h @@ -0,0 +1,18 @@ +// +// InputPluginsLogging.h +// +// +// Created by Clement on 11/6/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_InputPluginsLogging_h +#define hifi_InputPluginsLogging_h + +#include +Q_DECLARE_LOGGING_CATEGORY(inputplugins) + +#endif // hifi_InputPluginsLogging_h diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index 56f79ce3c1..9340cbf950 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -19,11 +19,6 @@ #include #include -// TODO: This should not be here -#include -Q_DECLARE_LOGGING_CATEGORY(inputplugins) -Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins") - #include #include #include diff --git a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp index 3ac2d197c2..4a4eab2ee1 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp @@ -16,6 +16,8 @@ #include #include +#include "InputPluginsLogging.h" + using Library = std::unique_ptr; static Library SIXENSE; From 6323728d7a5092073ec445663ff2d8ea276ad8b1 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 6 Nov 2015 16:56:48 -0800 Subject: [PATCH 11/20] Added perfect forwarding of arguments --- .../src/input-plugins/SixenseManager.cpp | 4 +++- .../src/input-plugins/SixenseSupportOSX.cpp | 11 +++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index 9340cbf950..3085b377f0 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -12,7 +12,7 @@ #include "SixenseManager.h" #ifdef HAVE_SIXENSE -#include "sixense.h" +#include #endif #include @@ -28,6 +28,8 @@ #include #include +#include "InputPluginsLogging.h" + static const unsigned int BUTTON_0 = 1U << 0; // the skinny button between 1 and 2 static const unsigned int BUTTON_1 = 1U << 5; static const unsigned int BUTTON_2 = 1U << 6; diff --git a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp index 4a4eab2ee1..378c99de76 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp @@ -9,11 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +// Mock implementation of sixense.h to hide dynamic linking on OS X #if defined(__APPLE__) && defined(HAVE_SIXENSE) -#include "sixense.h" +#include + +#include #include -#include #include #include "InputPluginsLogging.h" @@ -22,8 +24,9 @@ using Library = std::unique_ptr; static Library SIXENSE; struct Callable { - template int operator() (Args... args){ - return reinterpret_cast(function)(args...); + template + int operator() (Args&&... args){ + return reinterpret_cast(function)(std::forward(args)...); } QFunctionPointer function; }; From 0c60538952e82a3b0ce5afe338ca490ec88048ee Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 2 Nov 2015 17:47:02 -0800 Subject: [PATCH 12/20] Ensure that dependencies of runtime plugins are included in the DLL copy --- cmake/macros/CopyDllsBesideWindowsExecutable.cmake | 7 +++++++ cmake/templates/FixupBundlePostBuild.cmake.in | 14 +++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index b57c781eff..69fd20a57b 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -18,12 +18,19 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) @ONLY ) + if (APPLE) + set(PLUGIN_PATH "interface.app/Contents/MacOS/plugins") + else() + set(PLUGIN_PATH "plugins") + endif() + # add a post-build command to copy DLLs beside the executable add_custom_command( TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -DBUNDLE_EXECUTABLE=$ + -DBUNDLE_PLUGIN_DIR=$/${PLUGIN_PATH} -P ${CMAKE_CURRENT_BINARY_DIR}/FixupBundlePostBuild.cmake ) diff --git a/cmake/templates/FixupBundlePostBuild.cmake.in b/cmake/templates/FixupBundlePostBuild.cmake.in index 4afe4de403..ee686a6967 100644 --- a/cmake/templates/FixupBundlePostBuild.cmake.in +++ b/cmake/templates/FixupBundlePostBuild.cmake.in @@ -41,4 +41,16 @@ function(copy_resolved_item_into_bundle resolved_item resolved_embedded_item) endfunction() message(STATUS "FIXUP_LIBS for fixup_bundle called for bundle ${BUNDLE_EXECUTABLE} are @FIXUP_LIBS@") -fixup_bundle("${BUNDLE_EXECUTABLE}" "" "@FIXUP_LIBS@") \ No newline at end of file + +message(STATUS "Scanning for plugins from ${BUNDLE_PLUGIN_DIR}") + +if (APPLE) + set(PLUGIN_EXTENSION "dylib") +elseif (WIN32) + set(PLUGIN_EXTENSION "dll") +else() + set(PLUGIN_EXTENSION "so") +endif() + +file(GLOB RUNTIME_PLUGINS "${BUNDLE_PLUGIN_DIR}/*.${PLUGIN_EXTENSION}") +fixup_bundle("${BUNDLE_EXECUTABLE}" "${RUNTIME_PLUGINS}" "@FIXUP_LIBS@") \ No newline at end of file From 11733c039f5311c09de192e76d286cd9298f7269 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 2 Nov 2015 17:16:28 -0800 Subject: [PATCH 13/20] Allow shared libraries to access core global objects --- interface/src/Menu.cpp | 17 +++---------- interface/src/Menu.h | 4 +--- libraries/shared/src/DependencyManager.cpp | 9 ++++++- libraries/shared/src/DependencyManager.h | 22 ++++++++--------- libraries/shared/src/SharedUtil.h | 28 +++++++++++++++++++++- 5 files changed, 50 insertions(+), 30 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 92ff39a489..2d60b9d79f 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -44,22 +44,11 @@ #include "Menu.h" -Menu* Menu::_instance = NULL; +static const char* const MENU_PROPERTY_NAME = "com.highfidelity.Menu"; Menu* Menu::getInstance() { - static QMutex menuInstanceMutex; - - // lock the menu instance mutex to make sure we don't race and create two menus and crash - menuInstanceMutex.lock(); - - if (!_instance) { - qCDebug(interfaceapp, "First call to Menu::getInstance() - initing menu."); - _instance = new Menu(); - } - - menuInstanceMutex.unlock(); - - return _instance; + static Menu& instance = globalInstace(MENU_PROPERTY_NAME); + return &instance; } Menu::Menu() { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 162fad1b9f..dfa2cfa41b 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -57,6 +57,7 @@ private: class Menu : public QMenuBar { Q_OBJECT public: + Menu(); static Menu* getInstance(); void loadSettings(); @@ -103,9 +104,6 @@ public slots: void setIsOptionChecked(const QString& menuOption, bool isChecked); private: - static Menu* _instance; - Menu(); - typedef void(*settingsAction)(Settings&, QAction&); static void loadAction(Settings& settings, QAction& action); static void saveAction(Settings& settings, QAction& action); diff --git a/libraries/shared/src/DependencyManager.cpp b/libraries/shared/src/DependencyManager.cpp index 5f78f6bcd5..54d4e08259 100644 --- a/libraries/shared/src/DependencyManager.cpp +++ b/libraries/shared/src/DependencyManager.cpp @@ -11,7 +11,14 @@ #include "DependencyManager.h" -DependencyManager DependencyManager::_manager; +#include "SharedUtil.h" + +static const char* const DEPENDENCY_PROPERTY_NAME = "com.highfidelity.DependencyMananger"; + +DependencyManager& DependencyManager::manager() { + static DependencyManager& instance = globalInstace(DEPENDENCY_PROPERTY_NAME); + return instance; +} QSharedPointer& DependencyManager::safeGet(size_t hashCode) { return _instanceHash[hashCode]; diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index db41e72e1e..c0568bc752 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -62,8 +62,8 @@ public: static void registerInheritance(); private: - static DependencyManager _manager; - + static DependencyManager& manager(); + template size_t getHashCode(); @@ -75,11 +75,11 @@ private: template QSharedPointer DependencyManager::get() { - static size_t hashCode = _manager.getHashCode(); + static size_t hashCode = manager().getHashCode(); static QWeakPointer instance; if (instance.isNull()) { - instance = qSharedPointerCast(_manager.safeGet(hashCode)); + instance = qSharedPointerCast(manager().safeGet(hashCode)); if (instance.isNull()) { qWarning() << "DependencyManager::get(): No instance available for" << typeid(T).name(); @@ -91,9 +91,9 @@ QSharedPointer DependencyManager::get() { template QSharedPointer DependencyManager::set(Args&&... args) { - static size_t hashCode = _manager.getHashCode(); + static size_t hashCode = manager().getHashCode(); - QSharedPointer& instance = _manager.safeGet(hashCode); + QSharedPointer& instance = manager().safeGet(hashCode); instance.clear(); // Clear instance before creation of new one to avoid edge cases QSharedPointer newInstance(new T(args...), &T::customDeleter); QSharedPointer storedInstance = qSharedPointerCast(newInstance); @@ -104,9 +104,9 @@ QSharedPointer DependencyManager::set(Args&&... args) { template QSharedPointer DependencyManager::set(Args&&... args) { - static size_t hashCode = _manager.getHashCode(); + static size_t hashCode = manager().getHashCode(); - QSharedPointer& instance = _manager.safeGet(hashCode); + QSharedPointer& instance = manager().safeGet(hashCode); instance.clear(); // Clear instance before creation of new one to avoid edge cases QSharedPointer newInstance(new I(args...), &I::customDeleter); QSharedPointer storedInstance = qSharedPointerCast(newInstance); @@ -117,15 +117,15 @@ QSharedPointer DependencyManager::set(Args&&... args) { template void DependencyManager::destroy() { - static size_t hashCode = _manager.getHashCode(); - _manager.safeGet(hashCode).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); + manager()._inheritanceHash.insert(baseHashCode, derivedHashCode); } template diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index cd4f734d40..4c547417c8 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -13,6 +13,7 @@ #define hifi_SharedUtil_h #include +#include #include #include @@ -20,7 +21,32 @@ #include // not on windows, not needed for mac or windows #endif -#include +#include +#include + +// Provides efficient access to a named global type. By storing the value +// in the QApplication by name we can implement the singleton pattern and +// have the single instance function across DLL boundaries. +template +T& globalInstace(const char* propertyName, Args&&... args) { + static T *instance { nullptr }; + static std::mutex mutex; + if (!instance) { + std::unique_lock lock(mutex); + if (!instance) { + auto variant = qApp->property(propertyName); + if (variant.isNull()) { + auto* typedInstance = new T(args...); + void* voidInstance = typedInstance; + variant = QVariant::fromValue(voidInstance); + qApp->setProperty(propertyName, variant); + } + void* returnedVoidInstance = variant.value(); + instance = static_cast(returnedVoidInstance); + } + } + return *instance; +} const int BYTES_PER_COLOR = 3; const int BYTES_PER_FLAGS = 1; From 37a9538f104b6efec4b7cfc34f9474c6ba746be4 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 4 Nov 2015 19:10:31 -0800 Subject: [PATCH 14/20] PR feedback, ensure destruction of shared objects --- interface/src/Menu.cpp | 4 ++-- libraries/shared/src/DependencyManager.cpp | 5 +++-- libraries/shared/src/SharedUtil.h | 19 +++++++++++-------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 2d60b9d79f..3ed31e609a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -47,8 +47,8 @@ static const char* const MENU_PROPERTY_NAME = "com.highfidelity.Menu"; Menu* Menu::getInstance() { - static Menu& instance = globalInstace(MENU_PROPERTY_NAME); - return &instance; + static Menu* instance = globalInstace(MENU_PROPERTY_NAME); + return instance; } Menu::Menu() { diff --git a/libraries/shared/src/DependencyManager.cpp b/libraries/shared/src/DependencyManager.cpp index 54d4e08259..5100d99691 100644 --- a/libraries/shared/src/DependencyManager.cpp +++ b/libraries/shared/src/DependencyManager.cpp @@ -12,12 +12,13 @@ #include "DependencyManager.h" #include "SharedUtil.h" +#include "Finally.h" static const char* const DEPENDENCY_PROPERTY_NAME = "com.highfidelity.DependencyMananger"; DependencyManager& DependencyManager::manager() { - static DependencyManager& instance = globalInstace(DEPENDENCY_PROPERTY_NAME); - return instance; + static DependencyManager* instance = globalInstace(DEPENDENCY_PROPERTY_NAME); + return *instance; } QSharedPointer& DependencyManager::safeGet(size_t hashCode) { diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 4c547417c8..097444a62c 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -28,24 +28,27 @@ // in the QApplication by name we can implement the singleton pattern and // have the single instance function across DLL boundaries. template -T& globalInstace(const char* propertyName, Args&&... args) { - static T *instance { nullptr }; +T* globalInstace(const char* propertyName, Args&&... args) { + static std::shared_ptr instancePtr; + static T *resultInstance { nullptr }; static std::mutex mutex; - if (!instance) { + if (!resultInstance) { std::unique_lock lock(mutex); - if (!instance) { + if (!resultInstance) { auto variant = qApp->property(propertyName); if (variant.isNull()) { - auto* typedInstance = new T(args...); - void* voidInstance = typedInstance; + // Since we're building the object, store it in a shared_ptr so it's + // destroyed by the destructor of the static instancePtr + instancePtr = std::make_shared(args...); + void* voidInstance = &(*instancePtr); variant = QVariant::fromValue(voidInstance); qApp->setProperty(propertyName, variant); } void* returnedVoidInstance = variant.value(); - instance = static_cast(returnedVoidInstance); + resultInstance = static_cast(returnedVoidInstance); } } - return *instance; + return resultInstance; } const int BYTES_PER_COLOR = 3; From 314c11e8d42760d6afde193410bfcd5ce2501096 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 6 Nov 2015 16:59:46 -0800 Subject: [PATCH 15/20] Make life easier for Sam. --- libraries/animation/src/Rig.cpp | 4 ++++ libraries/avatars/src/AvatarData.h | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 4d66097265..7926b268b5 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -300,6 +300,8 @@ void Rig::setJointAnimatinoPriority(int index, float newPriority) { } } +// Deprecated. +// WARNING: this is not symmetric with getJointRotation. It's historical. Use the appropriate specific variation. void Rig::setJointRotation(int index, bool valid, const glm::quat& rotation, float priority) { if (index != -1 && index < _jointStates.size()) { JointState& state = _jointStates[index]; @@ -350,6 +352,8 @@ bool Rig::getJointRotationInWorldFrame(int jointIndex, glm::quat& result, const return true; } +// Deprecated. +// WARNING: this is not symmetric with setJointRotation. It's historical. Use the appropriate specific variation. bool Rig::getJointRotation(int jointIndex, glm::quat& rotation) const { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return false; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 3abd63bf63..9079f15f53 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -240,7 +240,8 @@ public: Q_INVOKABLE void setHandState(char s) { _handState = s; } Q_INVOKABLE char getHandState() const { return _handState; } - const QVector& getJointData() const { return _jointData; } + const QVector& getRawJointData() const { return _jointData; } + void setRawJointData(QVector data) { _jointData = data; } Q_INVOKABLE virtual void setJointData(int index, const glm::quat& rotation, const glm::vec3& translation); Q_INVOKABLE virtual void setJointRotation(int index, const glm::quat& rotation); From d8f169bd4e11c535a70fa6df6b01760f1ccf105e Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 6 Nov 2015 17:04:55 -0800 Subject: [PATCH 16/20] add collision sounds to bballs --- unpublishedScripts/basketballsResetter.js | 2 +- unpublishedScripts/hiddenEntityReset.js | 3 ++- unpublishedScripts/masterReset.js | 9 +++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/unpublishedScripts/basketballsResetter.js b/unpublishedScripts/basketballsResetter.js index 4d02296e8e..791ac1c0cf 100644 --- a/unpublishedScripts/basketballsResetter.js +++ b/unpublishedScripts/basketballsResetter.js @@ -82,7 +82,7 @@ var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; z: 0 }, collisionsWillMove: true, - collisionsSoundURL: basketballCollisionSoundURL, + collisionSoundURL: basketballCollisionSoundURL, ignoreForCollisions: false, modelURL: basketballURL, userData: JSON.stringify({ diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index ef0557a54f..0773cc5640 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -308,6 +308,7 @@ z: 0 }, collisionsWillMove: true, + collisionSoundURL: 'http://hifi-public.s3.amazonaws.com/sounds/basketball/basketball.wav', ignoreForCollisions: false, modelURL: basketballURL, userData: JSON.stringify({ @@ -1258,4 +1259,4 @@ }; // entity scripts always need to return a newly constructed object of our type return new ResetSwitch(); -}); +}); \ No newline at end of file diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index a8e156617a..aa7a1912de 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -248,7 +248,7 @@ MasterReset = function() { }, grabbableKey: { grabbable: false, - wantsTrigger:true + wantsTrigger: true } }) }); @@ -289,6 +289,7 @@ MasterReset = function() { z: 0 }, collisionsWillMove: true, + collisionSoundURL: 'http://hifi-public.s3.amazonaws.com/sounds/basketball/basketball.wav', ignoreForCollisions: false, modelURL: basketballURL, userData: JSON.stringify({ @@ -334,7 +335,7 @@ MasterReset = function() { name: "Basketball Resetter", script: basketballResetterScriptURL, dimensions: dimensions, - visible:false, + visible: false, userData: JSON.stringify({ resetMe: { resetMe: true @@ -367,7 +368,7 @@ MasterReset = function() { name: "Target Resetter", script: targetsResetterScriptURL, dimensions: dimensions, - visible:false, + visible: false, userData: JSON.stringify({ resetMe: { resetMe: true @@ -1238,4 +1239,4 @@ MasterReset = function() { Script.scriptEnding.connect(cleanup); } -}; +}; \ No newline at end of file From 137a2c1c48bfe67d5f4713342297cf1ce1176a07 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 6 Nov 2015 17:15:34 -0800 Subject: [PATCH 17/20] Fix file headers --- .../input-plugins/src/input-plugins/InputPluginsLogging.cpp | 2 +- libraries/input-plugins/src/input-plugins/InputPluginsLogging.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/InputPluginsLogging.cpp b/libraries/input-plugins/src/input-plugins/InputPluginsLogging.cpp index c96941a8ca..43a708e5c7 100644 --- a/libraries/input-plugins/src/input-plugins/InputPluginsLogging.cpp +++ b/libraries/input-plugins/src/input-plugins/InputPluginsLogging.cpp @@ -1,6 +1,6 @@ // // InputPluginsLogging.cpp -// +// libraries/input-plugins/src/input-plugins // // Created by Clement on 11/6/15. // Copyright 2015 High Fidelity, Inc. diff --git a/libraries/input-plugins/src/input-plugins/InputPluginsLogging.h b/libraries/input-plugins/src/input-plugins/InputPluginsLogging.h index 6460469190..f82ffdbe2e 100644 --- a/libraries/input-plugins/src/input-plugins/InputPluginsLogging.h +++ b/libraries/input-plugins/src/input-plugins/InputPluginsLogging.h @@ -1,6 +1,6 @@ // // InputPluginsLogging.h -// +// libraries/input-plugins/src/input-plugins // // Created by Clement on 11/6/15. // Copyright 2015 High Fidelity, Inc. From 6122fa145db9beadb66581223c80a48cc11901fc Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 6 Nov 2015 17:02:56 -0800 Subject: [PATCH 18/20] More PR feedback --- interface/src/Menu.cpp | 2 +- libraries/shared/src/DependencyManager.cpp | 4 ++-- libraries/shared/src/SharedUtil.h | 11 ++++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 3ed31e609a..24033325f6 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -47,7 +47,7 @@ static const char* const MENU_PROPERTY_NAME = "com.highfidelity.Menu"; Menu* Menu::getInstance() { - static Menu* instance = globalInstace(MENU_PROPERTY_NAME); + static Menu* instance = globalInstance(MENU_PROPERTY_NAME); return instance; } diff --git a/libraries/shared/src/DependencyManager.cpp b/libraries/shared/src/DependencyManager.cpp index 5100d99691..a870feab98 100644 --- a/libraries/shared/src/DependencyManager.cpp +++ b/libraries/shared/src/DependencyManager.cpp @@ -17,10 +17,10 @@ static const char* const DEPENDENCY_PROPERTY_NAME = "com.highfidelity.DependencyMananger"; DependencyManager& DependencyManager::manager() { - static DependencyManager* instance = globalInstace(DEPENDENCY_PROPERTY_NAME); + static DependencyManager* instance = globalInstance(DEPENDENCY_PROPERTY_NAME); return *instance; } QSharedPointer& DependencyManager::safeGet(size_t hashCode) { return _instanceHash[hashCode]; -} \ No newline at end of file +} diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 097444a62c..89ccba1479 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -27,10 +27,10 @@ // Provides efficient access to a named global type. By storing the value // in the QApplication by name we can implement the singleton pattern and // have the single instance function across DLL boundaries. -template -T* globalInstace(const char* propertyName, Args&&... args) { - static std::shared_ptr instancePtr; - static T *resultInstance { nullptr }; +template +T* globalInstance(const char* propertyName, Args&&... args) { + static std::unique_ptr instancePtr; + static T* resultInstance { nullptr }; static std::mutex mutex; if (!resultInstance) { std::unique_lock lock(mutex); @@ -39,7 +39,8 @@ T* globalInstace(const char* propertyName, Args&&... args) { if (variant.isNull()) { // Since we're building the object, store it in a shared_ptr so it's // destroyed by the destructor of the static instancePtr - instancePtr = std::make_shared(args...); + instancePtr = std::unique_ptr(new T(std::forward(args)...)); + void* voidInstance = &(*instancePtr); variant = QVariant::fromValue(voidInstance); qApp->setProperty(propertyName, variant); From 68a72b0f4161ea565bbd5f2a4d19efb74aecfbcd Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 6 Nov 2015 17:22:12 -0800 Subject: [PATCH 19/20] Bit of cleanup --- .../src/input-plugins/SixenseSupportOSX.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp index 378c99de76..f6cec5d67f 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp @@ -20,6 +20,10 @@ #include "InputPluginsLogging.h" +#ifndef SIXENSE_LIB_FILENAME +#define SIXENSE_LIB_FILENAME QCoreApplication::applicationDirPath() + "/../Frameworks/libsixense_x64" +#endif + using Library = std::unique_ptr; static Library SIXENSE; @@ -41,15 +45,9 @@ Callable resolve(const Library& library, const char* name) { void loadSixense() { - if (!SIXENSE) { - static const QString LIBRARY_PATH = -#ifdef SIXENSE_LIB_FILENAME - SIXENSE_LIB_FILENAME; -#else - QCoreApplication::applicationDirPath() + "/../Frameworks/libsixense_x64"; -#endif - SIXENSE.reset(new QLibrary(LIBRARY_PATH)); - } + Q_ASSERT_X(!(SIXENSE && SIXENSE->isLoaded()), __FUNCTION__, "Sixense library already loaded"); + SIXENSE.reset(new QLibrary(SIXENSE_LIB_FILENAME)); + Q_CHECK_PTR(SIXENSE); if (SIXENSE->load()){ qDebug() << "Loaded sixense library for hydra support -" << SIXENSE->fileName(); From bf4320e5ccd507d15e7b5367399f2570f3a54b77 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 6 Nov 2015 22:55:33 -0800 Subject: [PATCH 20/20] re-add this example --- examples/controllers/rightClickExample.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 examples/controllers/rightClickExample.js diff --git a/examples/controllers/rightClickExample.js b/examples/controllers/rightClickExample.js new file mode 100644 index 0000000000..c3e6ea8f3d --- /dev/null +++ b/examples/controllers/rightClickExample.js @@ -0,0 +1,10 @@ +var MAPPING_NAME = "com.highfidelity.rightClickExample"; +var mapping = Controller.newMapping(MAPPING_NAME); +mapping.from(Controller.Hardware.Keyboard.RightMouseClicked).to(function (value) { + print("Keyboard.RightMouseClicked"); +}); +Controller.enableMapping(MAPPING_NAME); + +Script.scriptEnding.connect(function () { + Controller.disableMapping(MAPPING_NAME); +}); \ No newline at end of file