Merge branch 'master' into out-of-body-experience

This commit is contained in:
Anthony J. Thibault 2016-10-13 17:27:15 -07:00
commit 81db8f7e08
53 changed files with 501 additions and 199 deletions

View file

@ -15,6 +15,7 @@
#include <QtNetwork/QNetworkDiskCache> #include <QtNetwork/QNetworkDiskCache>
#include <QtNetwork/QNetworkRequest> #include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply> #include <QtNetwork/QNetworkReply>
#include <QThread>
#include <AssetClient.h> #include <AssetClient.h>
#include <AvatarHashMap.h> #include <AvatarHashMap.h>
@ -33,6 +34,9 @@
#include <recording/Recorder.h> #include <recording/Recorder.h>
#include <recording/Frame.h> #include <recording/Frame.h>
#include <plugins/CodecPlugin.h>
#include <plugins/PluginManager.h>
#include <WebSocketServerClass.h> #include <WebSocketServerClass.h>
#include <EntityScriptingInterface.h> // TODO: consider moving to scriptengine.h #include <EntityScriptingInterface.h> // TODO: consider moving to scriptengine.h
@ -42,6 +46,7 @@
#include "AbstractAudioInterface.h" #include "AbstractAudioInterface.h"
#include "Agent.h" #include "Agent.h"
#include "AvatarAudioTimer.h"
static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10; static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10;
@ -72,6 +77,17 @@ Agent::Agent(ReceivedMessage& message) :
{ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase }, { PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase },
this, "handleOctreePacket"); this, "handleOctreePacket");
packetReceiver.registerListener(PacketType::Jurisdiction, this, "handleJurisdictionPacket"); packetReceiver.registerListener(PacketType::Jurisdiction, this, "handleJurisdictionPacket");
packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat");
}
void Agent::playAvatarSound(SharedSoundPointer sound) {
// this must happen on Agent's main thread
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "playAvatarSound", Q_ARG(SharedSoundPointer, sound));
return;
} else {
setAvatarSound(sound);
}
} }
void Agent::handleOctreePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) { void Agent::handleOctreePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
@ -118,7 +134,6 @@ void Agent::handleAudioPacket(QSharedPointer<ReceivedMessage> message) {
_receivedAudioStream.parseData(*message); _receivedAudioStream.parseData(*message);
_lastReceivedAudioLoudness = _receivedAudioStream.getNextOutputFrameLoudness(); _lastReceivedAudioLoudness = _receivedAudioStream.getNextOutputFrameLoudness();
_receivedAudioStream.clearBuffer(); _receivedAudioStream.clearBuffer();
} }
@ -214,6 +229,59 @@ void Agent::nodeActivated(SharedNodePointer activatedNode) {
_pendingScriptRequest = nullptr; _pendingScriptRequest = nullptr;
} }
if (activatedNode->getType() == NodeType::AudioMixer) {
negotiateAudioFormat();
}
}
void Agent::negotiateAudioFormat() {
auto nodeList = DependencyManager::get<NodeList>();
auto negotiateFormatPacket = NLPacket::create(PacketType::NegotiateAudioFormat);
auto codecPlugins = PluginManager::getInstance()->getCodecPlugins();
quint8 numberOfCodecs = (quint8)codecPlugins.size();
negotiateFormatPacket->writePrimitive(numberOfCodecs);
for (auto& plugin : codecPlugins) {
auto codecName = plugin->getName();
negotiateFormatPacket->writeString(codecName);
}
// grab our audio mixer from the NodeList, if it exists
SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer);
if (audioMixer) {
// send off this mute packet
nodeList->sendPacket(std::move(negotiateFormatPacket), *audioMixer);
}
}
void Agent::handleSelectedAudioFormat(QSharedPointer<ReceivedMessage> message) {
QString selectedCodecName = message->readString();
selectAudioFormat(selectedCodecName);
}
void Agent::selectAudioFormat(const QString& selectedCodecName) {
_selectedCodecName = selectedCodecName;
qDebug() << "Selected Codec:" << _selectedCodecName;
// release any old codec encoder/decoder first...
if (_codec && _encoder) {
_codec->releaseEncoder(_encoder);
_encoder = nullptr;
_codec = nullptr;
}
_receivedAudioStream.cleanupCodec();
auto codecPlugins = PluginManager::getInstance()->getCodecPlugins();
for (auto& plugin : codecPlugins) {
if (_selectedCodecName == plugin->getName()) {
_codec = plugin;
_receivedAudioStream.setupCodec(plugin, _selectedCodecName, AudioConstants::STEREO);
_encoder = plugin->createEncoder(AudioConstants::SAMPLE_RATE, AudioConstants::MONO);
qDebug() << "Selected Codec Plugin:" << _codec.get();
break;
}
}
} }
void Agent::scriptRequestFinished() { void Agent::scriptRequestFinished() {
@ -315,9 +383,17 @@ void Agent::executeScript() {
DependencyManager::set<AssignmentParentFinder>(_entityViewer.getTree()); DependencyManager::set<AssignmentParentFinder>(_entityViewer.getTree());
// wire up our additional agent related processing to the update signal // 100Hz timer for audio
QObject::connect(_scriptEngine.get(), &ScriptEngine::update, this, &Agent::processAgentAvatarAndAudio); AvatarAudioTimer* audioTimerWorker = new AvatarAudioTimer();
audioTimerWorker->moveToThread(&_avatarAudioTimerThread);
connect(audioTimerWorker, &AvatarAudioTimer::avatarTick, this, &Agent::processAgentAvatarAudio);
connect(this, &Agent::startAvatarAudioTimer, audioTimerWorker, &AvatarAudioTimer::start);
connect(this, &Agent::stopAvatarAudioTimer, audioTimerWorker, &AvatarAudioTimer::stop);
connect(&_avatarAudioTimerThread, &QThread::finished, audioTimerWorker, &QObject::deleteLater);
_avatarAudioTimerThread.start();
// 60Hz timer for avatar
QObject::connect(_scriptEngine.get(), &ScriptEngine::update, this, &Agent::processAgentAvatar);
_scriptEngine->run(); _scriptEngine->run();
Frame::clearFrameHandler(AUDIO_FRAME_TYPE); Frame::clearFrameHandler(AUDIO_FRAME_TYPE);
@ -343,6 +419,10 @@ void Agent::setIsAvatar(bool isAvatar) {
// start the timers // start the timers
_avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); _avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS);
// tell the avatarAudioTimer to start ticking
emit startAvatarAudioTimer();
} }
if (!_isAvatar) { if (!_isAvatar) {
@ -367,6 +447,7 @@ void Agent::setIsAvatar(bool isAvatar) {
nodeList->sendPacketList(std::move(packetList), *node); nodeList->sendPacketList(std::move(packetList), *node);
}); });
} }
emit stopAvatarAudioTimer();
} }
} }
@ -377,11 +458,9 @@ void Agent::sendAvatarIdentityPacket() {
} }
} }
void Agent::processAgentAvatarAndAudio(float deltaTime) { void Agent::processAgentAvatar() {
if (!_scriptEngine->isFinished() && _isAvatar) { if (!_scriptEngine->isFinished() && _isAvatar) {
auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>(); auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>();
const int SCRIPT_AUDIO_BUFFER_SAMPLES = AudioConstants::SAMPLE_RATE / SCRIPT_FPS + 0.5;
const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t);
QByteArray avatarByteArray = scriptedAvatar->toByteArray(true, randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO); QByteArray avatarByteArray = scriptedAvatar->toByteArray(true, randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO);
scriptedAvatar->doneEncoding(true); scriptedAvatar->doneEncoding(true);
@ -395,12 +474,16 @@ void Agent::processAgentAvatarAndAudio(float deltaTime) {
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
nodeList->broadcastToNodes(std::move(avatarPacket), NodeSet() << NodeType::AvatarMixer); nodeList->broadcastToNodes(std::move(avatarPacket), NodeSet() << NodeType::AvatarMixer);
}
}
if (_isListeningToAudioStream || _avatarSound) { void Agent::processAgentAvatarAudio() {
if (_isAvatar && (_isListeningToAudioStream || _avatarSound)) {
// if we have an avatar audio stream then send it out to our audio-mixer // if we have an avatar audio stream then send it out to our audio-mixer
auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>();
bool silentFrame = true; bool silentFrame = true;
int16_t numAvailableSamples = SCRIPT_AUDIO_BUFFER_SAMPLES; int16_t numAvailableSamples = AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL;
const int16_t* nextSoundOutput = NULL; const int16_t* nextSoundOutput = NULL;
if (_avatarSound) { if (_avatarSound) {
@ -408,8 +491,8 @@ void Agent::processAgentAvatarAndAudio(float deltaTime) {
nextSoundOutput = reinterpret_cast<const int16_t*>(soundByteArray.data() nextSoundOutput = reinterpret_cast<const int16_t*>(soundByteArray.data()
+ _numAvatarSoundSentBytes); + _numAvatarSoundSentBytes);
int numAvailableBytes = (soundByteArray.size() - _numAvatarSoundSentBytes) > SCRIPT_AUDIO_BUFFER_BYTES int numAvailableBytes = (soundByteArray.size() - _numAvatarSoundSentBytes) > AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL
? SCRIPT_AUDIO_BUFFER_BYTES ? AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL
: soundByteArray.size() - _numAvatarSoundSentBytes; : soundByteArray.size() - _numAvatarSoundSentBytes;
numAvailableSamples = (int16_t)numAvailableBytes / sizeof(int16_t); numAvailableSamples = (int16_t)numAvailableBytes / sizeof(int16_t);
@ -445,7 +528,7 @@ void Agent::processAgentAvatarAndAudio(float deltaTime) {
} }
// write the number of silent samples so the audio-mixer can uphold timing // write the number of silent samples so the audio-mixer can uphold timing
audioPacket->writePrimitive(SCRIPT_AUDIO_BUFFER_SAMPLES); audioPacket->writePrimitive(AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
// use the orientation and position of this avatar for the source of this audio // use the orientation and position of this avatar for the source of this audio
audioPacket->writePrimitive(scriptedAvatar->getPosition()); audioPacket->writePrimitive(scriptedAvatar->getPosition());
@ -453,9 +536,9 @@ void Agent::processAgentAvatarAndAudio(float deltaTime) {
audioPacket->writePrimitive(headOrientation); audioPacket->writePrimitive(headOrientation);
} else if (nextSoundOutput) { } else if (nextSoundOutput) {
// write the codec // write the codec
QString codecName; audioPacket->writeString(_selectedCodecName);
audioPacket->writeString(codecName);
// assume scripted avatar audio is mono and set channel flag to zero // assume scripted avatar audio is mono and set channel flag to zero
audioPacket->writePrimitive((quint8)0); audioPacket->writePrimitive((quint8)0);
@ -465,13 +548,21 @@ void Agent::processAgentAvatarAndAudio(float deltaTime) {
glm::quat headOrientation = scriptedAvatar->getHeadOrientation(); glm::quat headOrientation = scriptedAvatar->getHeadOrientation();
audioPacket->writePrimitive(headOrientation); audioPacket->writePrimitive(headOrientation);
// write the raw audio data // encode it
audioPacket->write(reinterpret_cast<const char*>(nextSoundOutput), numAvailableSamples * sizeof(int16_t)); if(_encoder) {
QByteArray decodedBuffer(reinterpret_cast<const char*>(nextSoundOutput), numAvailableSamples*sizeof(int16_t));
QByteArray encodedBuffer;
_encoder->encode(decodedBuffer, encodedBuffer);
audioPacket->write(encodedBuffer.data(), encodedBuffer.size());
} else {
audioPacket->write(reinterpret_cast<const char*>(nextSoundOutput), numAvailableSamples*sizeof(int16_t));
}
} }
// write audio packet to AudioMixer nodes // write audio packet to AudioMixer nodes
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
nodeList->eachNode([this, &nodeList, &audioPacket](const SharedNodePointer& node){ nodeList->eachNode([this, &nodeList, &audioPacket](const SharedNodePointer& node) {
// only send to nodes of type AudioMixer // only send to nodes of type AudioMixer
if (node->getType() == NodeType::AudioMixer) { if (node->getType() == NodeType::AudioMixer) {
// pack sequence number // pack sequence number
@ -484,7 +575,6 @@ void Agent::processAgentAvatarAndAudio(float deltaTime) {
} }
}); });
} }
}
} }
void Agent::aboutToFinish() { void Agent::aboutToFinish() {
@ -501,4 +591,13 @@ void Agent::aboutToFinish() {
// cleanup the AudioInjectorManager (and any still running injectors) // cleanup the AudioInjectorManager (and any still running injectors)
DependencyManager::destroy<AudioInjectorManager>(); DependencyManager::destroy<AudioInjectorManager>();
emit stopAvatarAudioTimer();
_avatarAudioTimerThread.quit();
// cleanup codec & encoder
if (_codec && _encoder) {
_codec->releaseEncoder(_encoder);
_encoder = nullptr;
}
} }

View file

@ -18,6 +18,7 @@
#include <QtScript/QScriptEngine> #include <QtScript/QScriptEngine>
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QUrl> #include <QtCore/QUrl>
#include <QtCore/QTimer>
#include <QUuid> #include <QUuid>
#include <EntityEditPacketSender.h> #include <EntityEditPacketSender.h>
@ -26,8 +27,9 @@
#include <ScriptEngine.h> #include <ScriptEngine.h>
#include <ThreadedAssignment.h> #include <ThreadedAssignment.h>
#include "MixedAudioStream.h" #include <plugins/CodecPlugin.h>
#include "MixedAudioStream.h"
class Agent : public ThreadedAssignment { class Agent : public ThreadedAssignment {
Q_OBJECT Q_OBJECT
@ -56,7 +58,7 @@ public:
public slots: public slots:
void run() override; void run() override;
void playAvatarSound(SharedSoundPointer avatarSound) { setAvatarSound(avatarSound); } void playAvatarSound(SharedSoundPointer avatarSound);
private slots: private slots:
void requestScript(); void requestScript();
@ -66,12 +68,20 @@ private slots:
void handleAudioPacket(QSharedPointer<ReceivedMessage> message); void handleAudioPacket(QSharedPointer<ReceivedMessage> message);
void handleOctreePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode); void handleOctreePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
void handleJurisdictionPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode); void handleJurisdictionPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
void handleSelectedAudioFormat(QSharedPointer<ReceivedMessage> message);
void processAgentAvatarAndAudio(float deltaTime);
void nodeActivated(SharedNodePointer activatedNode); void nodeActivated(SharedNodePointer activatedNode);
void processAgentAvatar();
void processAgentAvatarAudio();
signals:
void startAvatarAudioTimer();
void stopAvatarAudioTimer();
private: private:
void negotiateAudioFormat();
void selectAudioFormat(const QString& selectedCodecName);
std::unique_ptr<ScriptEngine> _scriptEngine; std::unique_ptr<ScriptEngine> _scriptEngine;
EntityEditPacketSender _entityEditSender; EntityEditPacketSender _entityEditSender;
EntityTreeHeadlessViewer _entityViewer; EntityTreeHeadlessViewer _entityViewer;
@ -93,6 +103,10 @@ private:
QTimer* _avatarIdentityTimer = nullptr; QTimer* _avatarIdentityTimer = nullptr;
QHash<QUuid, quint16> _outgoingScriptAudioSequenceNumbers; QHash<QUuid, quint16> _outgoingScriptAudioSequenceNumbers;
CodecPluginPointer _codec;
QString _selectedCodecName;
Encoder* _encoder { nullptr };
QThread _avatarAudioTimerThread;
}; };
#endif // hifi_Agent_h #endif // hifi_Agent_h

View file

@ -0,0 +1,33 @@
//
// AvatarAudioTimer.cpp
// assignment-client/src
//
// Created by David Kelly on 10/12/13.
// Copyright 2016 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 <QDebug>
#include <SharedUtil.h>
#include "AvatarAudioTimer.h"
// this should send a signal every 10ms, with pretty good precision. Hardcoding
// to 10ms since that's what you'd want for audio.
void AvatarAudioTimer::start() {
qDebug() << "AvatarAudioTimer::start called";
auto startTime = usecTimestampNow();
quint64 frameCounter = 0;
const int TARGET_INTERVAL_USEC = 10000; // 10ms
while (!_quit) {
frameCounter++;
// simplest possible timer
quint64 targetTime = startTime + frameCounter * TARGET_INTERVAL_USEC;
quint64 interval = std::max((quint64)0, targetTime - usecTimestampNow());
usleep(interval);
emit avatarTick();
}
qDebug() << "AvatarAudioTimer is finished";
}

View file

@ -0,0 +1,31 @@
//
// AvatarAudioTimer.h
// assignment-client/src
//
// Created by David Kelly on 10/12/13.
// Copyright 2016 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_AvatarAudioTimer_h
#define hifi_AvatarAudioTimer_h
#include <QtCore/QObject>
class AvatarAudioTimer : public QObject {
Q_OBJECT
signals:
void avatarTick();
public slots:
void start();
void stop() { _quit = true; }
private:
bool _quit { false };
};
#endif //hifi_AvatarAudioTimer_h

View file

@ -46,14 +46,21 @@ AnimationDetails ScriptableAvatar::getAnimationDetails() {
return _animationDetails; return _animationDetails;
} }
void ScriptableAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
_bind.reset();
_animSkeleton.reset();
AvatarData::setSkeletonModelURL(skeletonModelURL);
}
void ScriptableAvatar::update(float deltatime) { void ScriptableAvatar::update(float deltatime) {
if (_bind.isNull() && !_skeletonFBXURL.isEmpty()) { // AvatarData will parse the .fst, but not get the .fbx skeleton. if (_bind.isNull() && !_skeletonFBXURL.isEmpty()) { // AvatarData will parse the .fst, but not get the .fbx skeleton.
_bind = DependencyManager::get<AnimationCache>()->getAnimation(_skeletonFBXURL); _bind = DependencyManager::get<AnimationCache>()->getAnimation(_skeletonFBXURL);
} }
// Run animation // Run animation
if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0 && _bind->isLoaded()) { if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0 && !_bind.isNull() && _bind->isLoaded()) {
if (!_animSkeleton) {
_animSkeleton = std::make_shared<AnimSkeleton>(_bind->getGeometry());
}
float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps; float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps;
if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) { if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) {
while (currentFrame >= _animationDetails.lastFrame) { while (currentFrame >= _animationDetails.lastFrame) {
@ -64,14 +71,16 @@ void ScriptableAvatar::update(float deltatime) {
const QVector<FBXJoint>& modelJoints = _bind->getGeometry().joints; const QVector<FBXJoint>& modelJoints = _bind->getGeometry().joints;
QStringList animationJointNames = _animation->getJointNames(); QStringList animationJointNames = _animation->getJointNames();
if (_jointData.size() != modelJoints.size()) { const int nJoints = modelJoints.size();
_jointData.resize(modelJoints.size()); if (_jointData.size() != nJoints) {
_jointData.resize(nJoints);
} }
const int frameCount = _animation->getFrames().size(); const int frameCount = _animation->getFrames().size();
const FBXAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount); const FBXAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
const FBXAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount); const FBXAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
const float frameFraction = glm::fract(currentFrame); const float frameFraction = glm::fract(currentFrame);
std::vector<AnimPose> poses = _animSkeleton->getRelativeDefaultPoses();
for (int i = 0; i < animationJointNames.size(); i++) { for (int i = 0; i < animationJointNames.size(); i++) {
const QString& name = animationJointNames[i]; const QString& name = animationJointNames[i];
@ -79,18 +88,21 @@ void ScriptableAvatar::update(float deltatime) {
// trusting the .fst (which is sometimes not updated to match changes to .fbx). // trusting the .fst (which is sometimes not updated to match changes to .fbx).
int mapping = _bind->getGeometry().getJointIndex(name); int mapping = _bind->getGeometry().getJointIndex(name);
if (mapping != -1 && !_maskedJoints.contains(name)) { if (mapping != -1 && !_maskedJoints.contains(name)) {
JointData& data = _jointData[mapping]; // Eventually, this should probably deal with post rotations and translations, too.
poses[mapping].rot = modelJoints[mapping].preRotation *
auto newRotation = modelJoints[mapping].preRotation * safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);;
safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction); }
// We could probably do translations as in interpolation in model space (rather than the parent space that each frame is in), }
// but we don't do so for MyAvatar yet, so let's not be different here. _animSkeleton->convertRelativePosesToAbsolute(poses);
if (data.rotation != newRotation) { for (int i = 0; i < nJoints; i++) {
data.rotation = newRotation; JointData& data = _jointData[i];
AnimPose& pose = poses[i];
if (data.rotation != pose.rot) {
data.rotation = pose.rot;
data.rotationSet = true; data.rotationSet = true;
} }
} }
}
} else { } else {
_animation.clear(); _animation.clear();
} }

View file

@ -13,6 +13,7 @@
#define hifi_ScriptableAvatar_h #define hifi_ScriptableAvatar_h
#include <AnimationCache.h> #include <AnimationCache.h>
#include <AnimSkeleton.h>
#include <AvatarData.h> #include <AvatarData.h>
#include <ScriptEngine.h> #include <ScriptEngine.h>
@ -25,6 +26,7 @@ public:
bool hold = false, float firstFrame = 0.0f, float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList()); bool hold = false, float firstFrame = 0.0f, float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList());
Q_INVOKABLE void stopAnimation(); Q_INVOKABLE void stopAnimation();
Q_INVOKABLE AnimationDetails getAnimationDetails(); Q_INVOKABLE AnimationDetails getAnimationDetails();
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
private slots: private slots:
void update(float deltatime); void update(float deltatime);
@ -34,6 +36,7 @@ private:
AnimationDetails _animationDetails; AnimationDetails _animationDetails;
QStringList _maskedJoints; QStringList _maskedJoints;
AnimationPointer _bind; // a sleazy way to get the skeleton, given the various library/cmake dependencies AnimationPointer _bind; // a sleazy way to get the skeleton, given the various library/cmake dependencies
std::shared_ptr<AnimSkeleton> _animSkeleton;
}; };
#endif // hifi_ScriptableAvatar_h #endif // hifi_ScriptableAvatar_h

View file

@ -20,7 +20,7 @@ macro(SET_PACKAGING_PARAMETERS)
set(RELEASE_NUMBER $ENV{RELEASE_NUMBER}) set(RELEASE_NUMBER $ENV{RELEASE_NUMBER})
string(TOLOWER "$ENV{BRANCH}" BUILD_BRANCH) string(TOLOWER "$ENV{BRANCH}" BUILD_BRANCH)
set(BUILD_GLOBAL_SERVICES "DEVELOPMENT") set(BUILD_GLOBAL_SERVICES "DEVELOPMENT")
set(USE_STABLE_GLOBAL_SERVICES FALSE) set(USE_STABLE_GLOBAL_SERVICES 0)
message(STATUS "The BUILD_BRANCH variable is: ${BUILD_BRANCH}") message(STATUS "The BUILD_BRANCH variable is: ${BUILD_BRANCH}")
message(STATUS "The BRANCH environment variable is: $ENV{BRANCH}") message(STATUS "The BRANCH environment variable is: $ENV{BRANCH}")
@ -43,7 +43,7 @@ macro(SET_PACKAGING_PARAMETERS)
if (BUILD_BRANCH STREQUAL "stable") if (BUILD_BRANCH STREQUAL "stable")
message(STATUS "The RELEASE_TYPE is PRODUCTION and the BUILD_BRANCH is stable...") message(STATUS "The RELEASE_TYPE is PRODUCTION and the BUILD_BRANCH is stable...")
set(BUILD_GLOBAL_SERVICES "STABLE") set(BUILD_GLOBAL_SERVICES "STABLE")
set(USE_STABLE_GLOBAL_SERVICES TRUE) set(USE_STABLE_GLOBAL_SERVICES 1)
endif() endif()
elseif (RELEASE_TYPE STREQUAL "PR") elseif (RELEASE_TYPE STREQUAL "PR")

View file

@ -2267,7 +2267,7 @@ void DomainServer::processPathQueryPacket(QSharedPointer<ReceivedMessage> messag
QByteArray viewpointUTF8 = responseViewpoint.toUtf8(); QByteArray viewpointUTF8 = responseViewpoint.toUtf8();
// prepare a packet for the response // prepare a packet for the response
auto pathResponsePacket = NLPacket::create(PacketType::DomainServerPathResponse); auto pathResponsePacket = NLPacket::create(PacketType::DomainServerPathResponse, -1, true);
// check the number of bytes the viewpoint is // check the number of bytes the viewpoint is
quint16 numViewpointBytes = viewpointUTF8.size(); quint16 numViewpointBytes = viewpointUTF8.size();

View file

@ -11,42 +11,34 @@
{ "from": "OculusTouch.LY", "to": "Standard.LY", { "from": "OculusTouch.LY", "to": "Standard.LY",
"filters": [ "filters": [
{ "type": "deadZone", "min": 0.05 }, { "type": "deadZone", "min": 0.3 },
"invert" "invert"
] ]
}, },
{ "from": "OculusTouch.LX", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Standard.LX" }, { "from": "OculusTouch.LX", "filters": { "type": "deadZone", "min": 0.3 }, "to": "Standard.LX" },
{ "from": "OculusTouch.LT", "to": "Standard.LTClick", { "from": "OculusTouch.LT", "to": "Standard.LTClick",
"peek": true, "peek": true,
"filters": [ { "type": "hysteresis", "min": 0.85, "max": 0.9 } ] "filters": [ { "type": "hysteresis", "min": 0.85, "max": 0.9 } ]
}, },
{ "from": "OculusTouch.LT", "to": "Standard.LT" }, { "from": "OculusTouch.LT", "to": "Standard.LT" },
{ "from": "OculusTouch.LS", "to": "Standard.LS" }, { "from": "OculusTouch.LS", "to": "Standard.LS" },
{ "from": "OculusTouch.LeftGrip", "to": "Standard.LTClick", { "from": "OculusTouch.LeftGrip", "filters": { "type": "deadZone", "min": 0.5 }, "to": "Standard.LeftGrip" },
"peek": true,
"filters": [ { "type": "hysteresis", "min": 0.85, "max": 0.9 } ]
},
{ "from": "OculusTouch.LeftGrip", "to": "Standard.LT" },
{ "from": "OculusTouch.LeftHand", "to": "Standard.LeftHand" }, { "from": "OculusTouch.LeftHand", "to": "Standard.LeftHand" },
{ "from": "OculusTouch.RY", "to": "Standard.RY", { "from": "OculusTouch.RY", "to": "Standard.RY",
"filters": [ "filters": [
{ "type": "deadZone", "min": 0.05 }, { "type": "deadZone", "min": 0.3 },
"invert" "invert"
] ]
}, },
{ "from": "OculusTouch.RX", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Standard.RX" }, { "from": "OculusTouch.RX", "filters": { "type": "deadZone", "min": 0.3 }, "to": "Standard.RX" },
{ "from": "OculusTouch.RT", "to": "Standard.RTClick", { "from": "OculusTouch.RT", "to": "Standard.RTClick",
"peek": true, "peek": true,
"filters": [ { "type": "hysteresis", "min": 0.85, "max": 0.9 } ] "filters": [ { "type": "hysteresis", "min": 0.85, "max": 0.9 } ]
}, },
{ "from": "OculusTouch.RT", "to": "Standard.RT" }, { "from": "OculusTouch.RT", "to": "Standard.RT" },
{ "from": "OculusTouch.RS", "to": "Standard.RS" }, { "from": "OculusTouch.RS", "to": "Standard.RS" },
{ "from": "OculusTouch.RightGrip", "to": "Standard.LTClick", { "from": "OculusTouch.RightGrip", "filters": { "type": "deadZone", "min": 0.5 }, "to": "Standard.RightGrip" },
"peek": true,
"filters": [ { "type": "hysteresis", "min": 0.85, "max": 0.9 } ]
},
{ "from": "OculusTouch.RightGrip", "to": "Standard.RT" },
{ "from": "OculusTouch.RightHand", "to": "Standard.RightHand" }, { "from": "OculusTouch.RightHand", "to": "Standard.RightHand" },
{ "from": "OculusTouch.LeftApplicationMenu", "to": "Standard.Back" }, { "from": "OculusTouch.LeftApplicationMenu", "to": "Standard.Back" },

View file

@ -668,6 +668,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(clearDomainOctreeDetails())); connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(clearDomainOctreeDetails()));
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &Application::domainConnectionRefused); connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &Application::domainConnectionRefused);
// We could clear ATP assets only when changing domains, but it's possible that the domain you are connected
// to has gone down and switched to a new content set, so when you reconnect the cached ATP assets will no longer be valid.
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, DependencyManager::get<ScriptCache>().data(), &ScriptCache::clearATPScriptsFromCache);
// update our location every 5 seconds in the metaverse server, assuming that we are authenticated with one // update our location every 5 seconds in the metaverse server, assuming that we are authenticated with one
const qint64 DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS = 5 * MSECS_PER_SECOND; const qint64 DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS = 5 * MSECS_PER_SECOND;
@ -1498,6 +1502,9 @@ void Application::cleanupBeforeQuit() {
DependencyManager::get<ScriptEngines>()->shutdownScripting(); // stop all currently running global scripts DependencyManager::get<ScriptEngines>()->shutdownScripting(); // stop all currently running global scripts
DependencyManager::destroy<ScriptEngines>(); DependencyManager::destroy<ScriptEngines>();
_displayPlugin.reset();
PluginManager::getInstance()->shutdown();
// Cleanup all overlays after the scripts, as scripts might add more // Cleanup all overlays after the scripts, as scripts might add more
_overlays.cleanupAllOverlays(); _overlays.cleanupAllOverlays();

View file

@ -37,10 +37,14 @@ AvatarActionHold::AvatarActionHold(const QUuid& id, EntityItemPointer ownerEntit
} }
AvatarActionHold::~AvatarActionHold() { AvatarActionHold::~AvatarActionHold() {
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar(); // Sometimes actions are destroyed after the AvatarManager is destroyed by the Application.
auto avatarManager = DependencyManager::get<AvatarManager>();
if (avatarManager) {
auto myAvatar = avatarManager->getMyAvatar();
if (myAvatar) { if (myAvatar) {
myAvatar->removeHoldAction(this); myAvatar->removeHoldAction(this);
} }
}
#if WANT_DEBUG #if WANT_DEBUG
qDebug() << "AvatarActionHold::~AvatarActionHold" << (void*)this; qDebug() << "AvatarActionHold::~AvatarActionHold" << (void*)this;

View file

@ -2427,12 +2427,13 @@ void MyAvatar::updateHoldActions(const AnimPose& prePhysicsPose, const AnimPose&
EntityTreeRenderer* entityTreeRenderer = qApp->getEntities(); EntityTreeRenderer* entityTreeRenderer = qApp->getEntities();
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr; EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
if (entityTree) { if (entityTree) {
// lateAvatarUpdate will modify entity position & orientation, so we need an entity write lock
entityTree->withWriteLock([&] {
// to prevent actions from adding or removing themselves from the _holdActions vector // to prevent actions from adding or removing themselves from the _holdActions vector
// while we are iterating, we need to enter a critical section. // while we are iterating, we need to enter a critical section.
std::lock_guard<std::mutex> guard(_holdActionsMutex); std::lock_guard<std::mutex> guard(_holdActionsMutex);
// lateAvatarUpdate will modify entity position & orientation, so we need an entity write lock
entityTree->withWriteLock([&] {
for (auto& holdAction : _holdActions) { for (auto& holdAction : _holdActions) {
holdAction->lateAvatarUpdate(prePhysicsPose, postUpdatePose); holdAction->lateAvatarUpdate(prePhysicsPose, postUpdatePose);
} }

View file

@ -258,7 +258,7 @@ void ApplicationOverlay::buildFramebufferObject() {
auto uiSize = qApp->getUiSize(); auto uiSize = qApp->getUiSize();
if (!_overlayFramebuffer || uiSize != _overlayFramebuffer->getSize()) { if (!_overlayFramebuffer || uiSize != _overlayFramebuffer->getSize()) {
_overlayFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _overlayFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("ApplicationOverlay"));
} }
auto width = uiSize.x; auto width = uiSize.x;

View file

@ -356,6 +356,7 @@ void OpenGLDisplayPlugin::customizeContext() {
gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA),
image.width(), image.height(), image.width(), image.height(),
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
cursorData.texture->setSource("cursor texture");
auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha(); auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha();
cursorData.texture->setUsage(usage.build()); cursorData.texture->setUsage(usage.build());
cursorData.texture->assignStoredMip(0, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), image.byteCount(), image.constBits()); cursorData.texture->assignStoredMip(0, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), image.byteCount(), image.constBits());
@ -413,8 +414,6 @@ void OpenGLDisplayPlugin::customizeContext() {
_cursorPipeline = gpu::Pipeline::create(program, state); _cursorPipeline = gpu::Pipeline::create(program, state);
} }
} }
auto renderSize = getRecommendedRenderSize();
_compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, renderSize.x, renderSize.y));
} }
void OpenGLDisplayPlugin::uncustomizeContext() { void OpenGLDisplayPlugin::uncustomizeContext() {
@ -424,6 +423,7 @@ void OpenGLDisplayPlugin::uncustomizeContext() {
_compositeFramebuffer.reset(); _compositeFramebuffer.reset();
withPresentThreadLock([&] { withPresentThreadLock([&] {
_currentFrame.reset(); _currentFrame.reset();
_lastFrame = nullptr;
while (!_newFrameQueue.empty()) { while (!_newFrameQueue.empty()) {
_gpuContext->consumeFrameUpdates(_newFrameQueue.front()); _gpuContext->consumeFrameUpdates(_newFrameQueue.front());
_newFrameQueue.pop(); _newFrameQueue.pop();
@ -559,7 +559,7 @@ void OpenGLDisplayPlugin::compositeScene() {
void OpenGLDisplayPlugin::compositeLayers() { void OpenGLDisplayPlugin::compositeLayers() {
auto renderSize = getRecommendedRenderSize(); auto renderSize = getRecommendedRenderSize();
if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) { if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) {
_compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, renderSize.x, renderSize.y)); _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("displayPlugin::composite", gpu::Element::COLOR_RGBA_32, renderSize.x, renderSize.y));
} }
{ {
@ -611,10 +611,10 @@ void OpenGLDisplayPlugin::present() {
{ {
withPresentThreadLock([&] { withPresentThreadLock([&] {
_renderRate.increment(); _renderRate.increment();
if (_currentFrame != _lastFrame) { if (_currentFrame.get() != _lastFrame) {
_newFrameRate.increment(); _newFrameRate.increment();
} }
_lastFrame = _currentFrame; _lastFrame = _currentFrame.get();
}); });
// Execute the frame rendering commands // Execute the frame rendering commands
PROFILE_RANGE_EX("execute", 0xff00ff00, (uint64_t)presentCount()) PROFILE_RANGE_EX("execute", 0xff00ff00, (uint64_t)presentCount())
@ -755,3 +755,8 @@ void OpenGLDisplayPlugin::render(std::function<void(gpu::Batch& batch)> f) {
f(batch); f(batch);
_gpuContext->executeBatch(batch); _gpuContext->executeBatch(batch);
} }
OpenGLDisplayPlugin::~OpenGLDisplayPlugin() {
qDebug() << "Destroying OpenGLDisplayPlugin";
}

View file

@ -36,6 +36,7 @@ protected:
using Lock = std::unique_lock<Mutex>; using Lock = std::unique_lock<Mutex>;
using Condition = std::condition_variable; using Condition = std::condition_variable;
public: public:
~OpenGLDisplayPlugin();
// These must be final to ensure proper ordering of operations // These must be final to ensure proper ordering of operations
// between the main thread and the presentation thread // between the main thread and the presentation thread
bool activate() override final; bool activate() override final;
@ -115,7 +116,7 @@ protected:
RateCounter<> _renderRate; RateCounter<> _renderRate;
gpu::FramePointer _currentFrame; gpu::FramePointer _currentFrame;
gpu::FramePointer _lastFrame; gpu::Frame* _lastFrame { nullptr };
gpu::FramebufferPointer _compositeFramebuffer; gpu::FramebufferPointer _compositeFramebuffer;
gpu::PipelinePointer _overlayPipeline; gpu::PipelinePointer _overlayPipeline;
gpu::PipelinePointer _simplePipeline; gpu::PipelinePointer _simplePipeline;

View file

@ -125,6 +125,7 @@ void HmdDisplayPlugin::uncustomizeContext() {
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0)); batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0));
}); });
_overlayRenderer = OverlayRenderer(); _overlayRenderer = OverlayRenderer();
_previewTexture.reset();
Parent::uncustomizeContext(); Parent::uncustomizeContext();
} }
@ -265,6 +266,7 @@ void HmdDisplayPlugin::internalPresent() {
gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA),
image.width(), image.height(), image.width(), image.height(),
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
_previewTexture->setSource("HMD Preview Texture");
_previewTexture->setUsage(gpu::Texture::Usage::Builder().withColor().build()); _previewTexture->setUsage(gpu::Texture::Usage::Builder().withColor().build());
_previewTexture->assignStoredMip(0, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), image.byteCount(), image.constBits()); _previewTexture->assignStoredMip(0, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), image.byteCount(), image.constBits());
_previewTexture->autoGenerateMips(-1); _previewTexture->autoGenerateMips(-1);
@ -634,3 +636,6 @@ void HmdDisplayPlugin::compositeExtra() {
}); });
} }
HmdDisplayPlugin::~HmdDisplayPlugin() {
qDebug() << "Destroying HmdDisplayPlugin";
}

View file

@ -23,6 +23,7 @@
class HmdDisplayPlugin : public OpenGLDisplayPlugin { class HmdDisplayPlugin : public OpenGLDisplayPlugin {
using Parent = OpenGLDisplayPlugin; using Parent = OpenGLDisplayPlugin;
public: public:
~HmdDisplayPlugin();
bool isHmd() const override final { return true; } bool isHmd() const override final { return true; }
float getIPD() const override final { return _ipd; } float getIPD() const override final { return _ipd; }
glm::mat4 getEyeToHeadTransform(Eye eye) const override final { return _eyeOffsets[eye]; } glm::mat4 getEyeToHeadTransform(Eye eye) const override final { return _eyeOffsets[eye]; }

View file

@ -20,16 +20,17 @@ using namespace gpu;
Framebuffer::~Framebuffer() { Framebuffer::~Framebuffer() {
} }
Framebuffer* Framebuffer::create() { Framebuffer* Framebuffer::create(const std::string& name) {
auto framebuffer = new Framebuffer(); auto framebuffer = new Framebuffer();
framebuffer->setName(name);
framebuffer->_renderBuffers.resize(MAX_NUM_RENDER_BUFFERS); framebuffer->_renderBuffers.resize(MAX_NUM_RENDER_BUFFERS);
framebuffer->_colorStamps.resize(MAX_NUM_RENDER_BUFFERS, 0); framebuffer->_colorStamps.resize(MAX_NUM_RENDER_BUFFERS, 0);
return framebuffer; return framebuffer;
} }
Framebuffer* Framebuffer::create( const Format& colorBufferFormat, uint16 width, uint16 height) { Framebuffer* Framebuffer::create(const std::string& name, const Format& colorBufferFormat, uint16 width, uint16 height) {
auto framebuffer = Framebuffer::create(); auto framebuffer = Framebuffer::create(name);
auto colorTexture = TexturePointer(Texture::create2D(colorBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT))); auto colorTexture = TexturePointer(Texture::create2D(colorBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT)));
colorTexture->setSource("Framebuffer::colorTexture"); colorTexture->setSource("Framebuffer::colorTexture");
@ -39,13 +40,11 @@ Framebuffer* Framebuffer::create( const Format& colorBufferFormat, uint16 width,
return framebuffer; return framebuffer;
} }
Framebuffer* Framebuffer::create( const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height) { Framebuffer* Framebuffer::create(const std::string& name, const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height) {
auto framebuffer = Framebuffer::create(); auto framebuffer = Framebuffer::create(name);
auto colorTexture = TexturePointer(Texture::create2D(colorBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT))); auto colorTexture = TexturePointer(Texture::create2D(colorBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT)));
colorTexture->setSource("Framebuffer::colorTexture");
auto depthTexture = TexturePointer(Texture::create2D(depthStencilBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT))); auto depthTexture = TexturePointer(Texture::create2D(depthStencilBufferFormat, width, height, Sampler(Sampler::FILTER_MIN_MAG_POINT)));
depthTexture->setSource("Framebuffer::depthTexture");
framebuffer->setRenderBuffer(0, colorTexture); framebuffer->setRenderBuffer(0, colorTexture);
framebuffer->setDepthStencilBuffer(depthTexture, depthStencilBufferFormat); framebuffer->setDepthStencilBuffer(depthTexture, depthStencilBufferFormat);
@ -53,11 +52,10 @@ Framebuffer* Framebuffer::create( const Format& colorBufferFormat, const Format&
} }
Framebuffer* Framebuffer::createShadowmap(uint16 width) { Framebuffer* Framebuffer::createShadowmap(uint16 width) {
auto framebuffer = Framebuffer::create(); auto framebuffer = Framebuffer::create("Shadowmap");
auto depthFormat = Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); // Depth32 texel format auto depthFormat = Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); // Depth32 texel format
auto depthTexture = TexturePointer(Texture::create2D(depthFormat, width, width)); auto depthTexture = TexturePointer(Texture::create2D(depthFormat, width, width));
depthTexture->setSource("Framebuffer::shadowMap");
Sampler::Desc samplerDesc; Sampler::Desc samplerDesc;
samplerDesc._borderColor = glm::vec4(1.0f); samplerDesc._borderColor = glm::vec4(1.0f);
samplerDesc._wrapModeU = Sampler::WRAP_BORDER; samplerDesc._wrapModeU = Sampler::WRAP_BORDER;
@ -155,6 +153,10 @@ int Framebuffer::setRenderBuffer(uint32 slot, const TexturePointer& texture, uin
if (!validateTargetCompatibility(*texture, subresource)) { if (!validateTargetCompatibility(*texture, subresource)) {
return -1; return -1;
} }
if (texture->source().empty()) {
texture->setSource(_name + "::color::" + std::to_string(slot));
}
} }
++_colorStamps[slot]; ++_colorStamps[slot];
@ -216,7 +218,6 @@ uint32 Framebuffer::getRenderBufferSubresource(uint32 slot) const {
} }
bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource) { bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, const Format& format, uint32 subresource) {
++_depthStamp;
if (isSwapchain()) { if (isSwapchain()) {
return false; return false;
} }
@ -226,8 +227,13 @@ bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, const For
if (!validateTargetCompatibility(*texture)) { if (!validateTargetCompatibility(*texture)) {
return false; return false;
} }
if (texture->source().empty()) {
texture->setSource(_name + "::depthStencil");
}
} }
++_depthStamp;
updateSize(texture); updateSize(texture);
// assign the new one // assign the new one

View file

@ -88,9 +88,9 @@ public:
~Framebuffer(); ~Framebuffer();
static Framebuffer* create(const SwapchainPointer& swapchain); static Framebuffer* create(const SwapchainPointer& swapchain);
static Framebuffer* create(); static Framebuffer* create(const std::string& name);
static Framebuffer* create(const Format& colorBufferFormat, uint16 width, uint16 height); static Framebuffer* create(const std::string& name, const Format& colorBufferFormat, uint16 width, uint16 height);
static Framebuffer* create(const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height); static Framebuffer* create(const std::string& name, const Format& colorBufferFormat, const Format& depthStencilBufferFormat, uint16 width, uint16 height);
static Framebuffer* createShadowmap(uint16 width); static Framebuffer* createShadowmap(uint16 width);
bool isSwapchain() const; bool isSwapchain() const;
@ -127,6 +127,8 @@ public:
uint16 getWidth() const; uint16 getWidth() const;
uint16 getHeight() const; uint16 getHeight() const;
uint16 getNumSamples() const; uint16 getNumSamples() const;
const std::string& getName() const { return _name; }
void setName(const std::string& name) { _name = name; }
float getAspectRatio() const { return getWidth() / (float) getHeight() ; } float getAspectRatio() const { return getWidth() / (float) getHeight() ; }
@ -145,6 +147,7 @@ public:
static Transform evalSubregionTexcoordTransform(const glm::ivec2& sourceSurface, const glm::ivec4& destViewport); static Transform evalSubregionTexcoordTransform(const glm::ivec2& sourceSurface, const glm::ivec4& destViewport);
protected: protected:
std::string _name;
SwapchainPointer _swapchain; SwapchainPointer _swapchain;
Stamp _depthStamp { 0 }; Stamp _depthStamp { 0 };

View file

@ -23,7 +23,7 @@
#include "AccountManager.h" #include "AccountManager.h"
const QString HIFI_URL_SCHEME = "hifi"; const QString HIFI_URL_SCHEME = "hifi";
const QString DEFAULT_HIFI_ADDRESS = "hifi://dev-welcome"; const QString DEFAULT_HIFI_ADDRESS = "hifi://welcome";
const QString SANDBOX_HIFI_ADDRESS = "hifi://localhost"; const QString SANDBOX_HIFI_ADDRESS = "hifi://localhost";
const QString SANDBOX_STATUS_URL = "http://localhost:60332/status"; const QString SANDBOX_STATUS_URL = "http://localhost:60332/status";
const QString INDEX_PATH = "/"; const QString INDEX_PATH = "/";

View file

@ -389,7 +389,7 @@ void NodeList::sendDSPathQuery(const QString& newPath) {
// only send a path query if we know who our DS is or is going to be // only send a path query if we know who our DS is or is going to be
if (_domainHandler.isSocketKnown()) { if (_domainHandler.isSocketKnown()) {
// construct the path query packet // construct the path query packet
auto pathQueryPacket = NLPacket::create(PacketType::DomainServerPathQuery); auto pathQueryPacket = NLPacket::create(PacketType::DomainServerPathQuery, -1, true);
// get the UTF8 representation of path query // get the UTF8 representation of path query
QByteArray pathQueryUTF8 = newPath.toUtf8(); QByteArray pathQueryUTF8 = newPath.toUtf8();

View file

@ -276,4 +276,30 @@ void PluginManager::saveSettings() {
saveInputPluginSettings(getInputPlugins()); saveInputPluginSettings(getInputPlugins());
} }
void PluginManager::shutdown() {
for (auto inputPlugin : getInputPlugins()) {
if (inputPlugin->isActive()) {
inputPlugin->deactivate();
}
}
for (auto displayPlugins : getDisplayPlugins()) {
if (displayPlugins->isActive()) {
displayPlugins->deactivate();
}
}
auto loadedPlugins = getLoadedPlugins();
// Now grab the dynamic plugins
for (auto loader : getLoadedPlugins()) {
InputProvider* inputProvider = qobject_cast<InputProvider*>(loader->instance());
if (inputProvider) {
inputProvider->destroyInputPlugins();
}
DisplayProvider* displayProvider = qobject_cast<DisplayProvider*>(loader->instance());
if (displayProvider) {
displayProvider->destroyDisplayPlugins();
}
}
}
#endif #endif

View file

@ -28,6 +28,8 @@ public:
void disableInputs(const QStringList& inputs); void disableInputs(const QStringList& inputs);
void saveSettings(); void saveSettings();
void setContainer(PluginContainer* container) { _container = container; } void setContainer(PluginContainer* container) { _container = container; }
void shutdown();
private: private:
PluginContainer* _container { nullptr }; PluginContainer* _container { nullptr };
}; };

View file

@ -19,6 +19,7 @@ public:
virtual ~DisplayProvider() {} virtual ~DisplayProvider() {}
virtual DisplayPluginList getDisplayPlugins() = 0; virtual DisplayPluginList getDisplayPlugins() = 0;
virtual void destroyDisplayPlugins() = 0;
}; };
#define DisplayProvider_iid "com.highfidelity.plugins.display" #define DisplayProvider_iid "com.highfidelity.plugins.display"
@ -29,6 +30,7 @@ class InputProvider {
public: public:
virtual ~InputProvider() {} virtual ~InputProvider() {}
virtual InputPluginList getInputPlugins() = 0; virtual InputPluginList getInputPlugins() = 0;
virtual void destroyInputPlugins() = 0;
}; };
#define InputProvider_iid "com.highfidelity.plugins.input" #define InputProvider_iid "com.highfidelity.plugins.input"

View file

@ -75,11 +75,11 @@ void AmbientOcclusionFramebuffer::allocate() {
auto height = _frameSize.y; auto height = _frameSize.y;
_occlusionTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); _occlusionTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
_occlusionFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _occlusionFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusion"));
_occlusionFramebuffer->setRenderBuffer(0, _occlusionTexture); _occlusionFramebuffer->setRenderBuffer(0, _occlusionTexture);
_occlusionBlurredTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); _occlusionBlurredTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
_occlusionBlurredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _occlusionBlurredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusionBlurred"));
_occlusionBlurredFramebuffer->setRenderBuffer(0, _occlusionBlurredTexture); _occlusionBlurredFramebuffer->setRenderBuffer(0, _occlusionBlurredTexture);
} }

View file

@ -41,11 +41,10 @@ const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() {
if (!_antialiasingBuffer) { if (!_antialiasingBuffer) {
// Link the antialiasing FBO to texture // Link the antialiasing FBO to texture
_antialiasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _antialiasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("antialiasing"));
auto format = gpu::Element::COLOR_SRGBA_32; // DependencyManager::get<FramebufferCache>()->getLightingTexture()->getTexelFormat(); auto format = gpu::Element::COLOR_SRGBA_32; // DependencyManager::get<FramebufferCache>()->getLightingTexture()->getTexelFormat();
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT);
_antialiasingTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); _antialiasingTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler));
_antialiasingTexture->setSource("Antialiasing::_antialiasingTexture");
_antialiasingBuffer->setRenderBuffer(0, _antialiasingTexture); _antialiasingBuffer->setRenderBuffer(0, _antialiasingTexture);
} }

View file

@ -43,8 +43,8 @@ void DeferredFramebuffer::updatePrimaryDepth(const gpu::TexturePointer& depthBuf
void DeferredFramebuffer::allocate() { void DeferredFramebuffer::allocate() {
_deferredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _deferredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("deferred"));
_deferredFramebufferDepthColor = gpu::FramebufferPointer(gpu::Framebuffer::create()); _deferredFramebufferDepthColor = gpu::FramebufferPointer(gpu::Framebuffer::create("deferredDepthColor"));
auto colorFormat = gpu::Element::COLOR_SRGBA_32; auto colorFormat = gpu::Element::COLOR_SRGBA_32;
auto linearFormat = gpu::Element::COLOR_RGBA_32; auto linearFormat = gpu::Element::COLOR_RGBA_32;
@ -54,11 +54,8 @@ void DeferredFramebuffer::allocate() {
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT);
_deferredColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); _deferredColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler));
_deferredColorTexture->setSource("DeferredFramebuffer::_deferredColorTexture");
_deferredNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(linearFormat, width, height, defaultSampler)); _deferredNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(linearFormat, width, height, defaultSampler));
_deferredNormalTexture->setSource("DeferredFramebuffer::_deferredNormalTexture");
_deferredSpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); _deferredSpecularTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler));
_deferredSpecularTexture->setSource("DeferredFramebuffer::_deferredSpecularTexture");
_deferredFramebuffer->setRenderBuffer(0, _deferredColorTexture); _deferredFramebuffer->setRenderBuffer(0, _deferredColorTexture);
_deferredFramebuffer->setRenderBuffer(1, _deferredNormalTexture); _deferredFramebuffer->setRenderBuffer(1, _deferredNormalTexture);
@ -69,7 +66,6 @@ void DeferredFramebuffer::allocate() {
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format
if (!_primaryDepthTexture) { if (!_primaryDepthTexture) {
_primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler)); _primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler));
_primaryDepthTexture->setSource("DeferredFramebuffer::_primaryDepthTexture");
} }
_deferredFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); _deferredFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
@ -80,8 +76,7 @@ void DeferredFramebuffer::allocate() {
auto smoothSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR); auto smoothSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR);
_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::R11G11B10), width, height, defaultSampler)); _lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::R11G11B10), width, height, defaultSampler));
_lightingTexture->setSource("DeferredFramebuffer::_lightingTexture"); _lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("lighting"));
_lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
_lightingFramebuffer->setRenderBuffer(0, _lightingTexture); _lightingFramebuffer->setRenderBuffer(0, _lightingTexture);
_lightingFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); _lightingFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);

View file

@ -346,12 +346,11 @@ void PreparePrimaryFramebuffer::run(const SceneContextPointer& sceneContext, con
} }
if (!_primaryFramebuffer) { if (!_primaryFramebuffer) {
_primaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _primaryFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("deferredPrimary"));
auto colorFormat = gpu::Element::COLOR_SRGBA_32; auto colorFormat = gpu::Element::COLOR_SRGBA_32;
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT);
auto primaryColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, frameSize.x, frameSize.y, defaultSampler)); auto primaryColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, frameSize.x, frameSize.y, defaultSampler));
primaryColorTexture->setSource("PreparePrimaryFramebuffer::primaryColorTexture");
_primaryFramebuffer->setRenderBuffer(0, primaryColorTexture); _primaryFramebuffer->setRenderBuffer(0, primaryColorTexture);
@ -359,7 +358,6 @@ void PreparePrimaryFramebuffer::run(const SceneContextPointer& sceneContext, con
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format
auto primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, frameSize.x, frameSize.y, defaultSampler)); auto primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, frameSize.x, frameSize.y, defaultSampler));
primaryDepthTexture->setSource("PreparePrimaryFramebuffer::primaryDepthTexture");
_primaryFramebuffer->setDepthStencilBuffer(primaryDepthTexture, depthFormat); _primaryFramebuffer->setDepthStencilBuffer(primaryDepthTexture, depthFormat);
} }

View file

@ -36,7 +36,7 @@ void FramebufferCache::createPrimaryFramebuffer() {
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT);
_selfieFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _selfieFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("selfie"));
auto tex = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width * 0.5, height * 0.5, defaultSampler)); auto tex = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width * 0.5, height * 0.5, defaultSampler));
_selfieFramebuffer->setRenderBuffer(0, tex); _selfieFramebuffer->setRenderBuffer(0, tex);
@ -47,7 +47,7 @@ void FramebufferCache::createPrimaryFramebuffer() {
gpu::FramebufferPointer FramebufferCache::getFramebuffer() { gpu::FramebufferPointer FramebufferCache::getFramebuffer() {
std::unique_lock<std::mutex> lock(_mutex); std::unique_lock<std::mutex> lock(_mutex);
if (_cachedFramebuffers.empty()) { if (_cachedFramebuffers.empty()) {
_cachedFramebuffers.push_back(gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_SRGBA_32, _frameBufferSize.width(), _frameBufferSize.height()))); _cachedFramebuffers.push_back(gpu::FramebufferPointer(gpu::Framebuffer::create("cached", gpu::Element::COLOR_SRGBA_32, _frameBufferSize.width(), _frameBufferSize.height())));
} }
gpu::FramebufferPointer result = _cachedFramebuffers.front(); gpu::FramebufferPointer result = _cachedFramebuffers.front();
_cachedFramebuffers.pop_front(); _cachedFramebuffers.pop_front();

View file

@ -319,7 +319,7 @@ void diffuseProfileGPU(gpu::TexturePointer& profileMap, RenderArgs* args) {
makePipeline = gpu::Pipeline::create(program, state); makePipeline = gpu::Pipeline::create(program, state);
} }
auto makeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); auto makeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("diffuseProfile"));
makeFramebuffer->setRenderBuffer(0, profileMap); makeFramebuffer->setRenderBuffer(0, profileMap);
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
@ -356,7 +356,7 @@ void diffuseScatterGPU(const gpu::TexturePointer& profileMap, gpu::TexturePointe
makePipeline = gpu::Pipeline::create(program, state); makePipeline = gpu::Pipeline::create(program, state);
} }
auto makeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); auto makeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("diffuseScatter"));
makeFramebuffer->setRenderBuffer(0, lut); makeFramebuffer->setRenderBuffer(0, lut);
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
@ -393,7 +393,7 @@ void computeSpecularBeckmannGPU(gpu::TexturePointer& beckmannMap, RenderArgs* ar
makePipeline = gpu::Pipeline::create(program, state); makePipeline = gpu::Pipeline::create(program, state);
} }
auto makeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); auto makeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("computeSpecularBeckmann"));
makeFramebuffer->setRenderBuffer(0, beckmannMap); makeFramebuffer->setRenderBuffer(0, beckmannMap);
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {

View file

@ -74,22 +74,19 @@ void LinearDepthFramebuffer::allocate() {
// For Linear Depth: // For Linear Depth:
_linearDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RGB), width, height, _linearDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RGB), width, height,
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
_linearDepthTexture->setSource("LinearDepthFramebuffer::_linearDepthTexture"); _linearDepthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("linearDepth"));
_linearDepthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
_linearDepthFramebuffer->setRenderBuffer(0, _linearDepthTexture); _linearDepthFramebuffer->setRenderBuffer(0, _linearDepthTexture);
_linearDepthFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, _primaryDepthTexture->getTexelFormat()); _linearDepthFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, _primaryDepthTexture->getTexelFormat());
// For Downsampling: // For Downsampling:
_halfLinearDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RGB), _halfFrameSize.x, _halfFrameSize.y, _halfLinearDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RGB), _halfFrameSize.x, _halfFrameSize.y,
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
_halfLinearDepthTexture->setSource("LinearDepthFramebuffer::_halfLinearDepthTexture");
_halfLinearDepthTexture->autoGenerateMips(5); _halfLinearDepthTexture->autoGenerateMips(5);
_halfNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB), _halfFrameSize.x, _halfFrameSize.y, _halfNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB), _halfFrameSize.x, _halfFrameSize.y,
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
_halfNormalTexture->setSource("LinearDepthFramebuffer::_halfNormalTexture");
_downsampleFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _downsampleFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("halfLinearDepth"));
_downsampleFramebuffer->setRenderBuffer(0, _halfLinearDepthTexture); _downsampleFramebuffer->setRenderBuffer(0, _halfLinearDepthTexture);
_downsampleFramebuffer->setRenderBuffer(1, _halfNormalTexture); _downsampleFramebuffer->setRenderBuffer(1, _halfNormalTexture);
} }
@ -304,18 +301,15 @@ void SurfaceGeometryFramebuffer::allocate() {
auto height = _frameSize.y; auto height = _frameSize.y;
_curvatureTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); _curvatureTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
_curvatureTexture->setSource("SurfaceGeometryFramebuffer::_curvatureTexture"); _curvatureFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("surfaceGeometry::curvature"));
_curvatureFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
_curvatureFramebuffer->setRenderBuffer(0, _curvatureTexture); _curvatureFramebuffer->setRenderBuffer(0, _curvatureTexture);
_lowCurvatureTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); _lowCurvatureTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
_lowCurvatureTexture->setSource("SurfaceGeometryFramebuffer::_lowCurvatureTexture"); _lowCurvatureFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("surfaceGeometry::lowCurvature"));
_lowCurvatureFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
_lowCurvatureFramebuffer->setRenderBuffer(0, _lowCurvatureTexture); _lowCurvatureFramebuffer->setRenderBuffer(0, _lowCurvatureTexture);
_blurringTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); _blurringTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
_blurringTexture->setSource("SurfaceGeometryFramebuffer::_blurringTexture"); _blurringFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("surfaceGeometry::blurring"));
_blurringFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
_blurringFramebuffer->setRenderBuffer(0, _blurringTexture); _blurringFramebuffer->setRenderBuffer(0, _blurringTexture);
} }

View file

@ -101,7 +101,7 @@ bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFra
} }
if (!_blurredFramebuffer) { if (!_blurredFramebuffer) {
_blurredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _blurredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("blur"));
// attach depthStencil if present in source // attach depthStencil if present in source
//if (sourceFramebuffer->hasDepthStencil()) { //if (sourceFramebuffer->hasDepthStencil()) {
@ -124,7 +124,7 @@ bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFra
// The job output the blur result in a new Framebuffer spawning here. // The job output the blur result in a new Framebuffer spawning here.
// Let s make sure it s ready for this // Let s make sure it s ready for this
if (!_outputFramebuffer) { if (!_outputFramebuffer) {
_outputFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _outputFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("blurOutput"));
// attach depthStencil if present in source // attach depthStencil if present in source
/* if (sourceFramebuffer->hasDepthStencil()) { /* if (sourceFramebuffer->hasDepthStencil()) {

View file

@ -36,6 +36,19 @@ void ScriptCache::clearCache() {
_scriptCache.clear(); _scriptCache.clear();
} }
void ScriptCache::clearATPScriptsFromCache() {
Lock lock(_containerLock);
qCDebug(scriptengine) << "Clearing ATP scripts from ScriptCache";
for (auto it = _scriptCache.begin(); it != _scriptCache.end();) {
if (it.key().scheme() == "atp") {
qCDebug(scriptengine) << "Removing: " << it.key();
it = _scriptCache.erase(it);
} else {
++it;
}
}
}
QString ScriptCache::getScript(const QUrl& unnormalizedURL, ScriptUser* scriptUser, bool& isPending, bool reload) { QString ScriptCache::getScript(const QUrl& unnormalizedURL, ScriptUser* scriptUser, bool& isPending, bool reload) {
QUrl url = ResourceManager::normalizeURL(unnormalizedURL); QUrl url = ResourceManager::normalizeURL(unnormalizedURL);
QString scriptContents; QString scriptContents;

View file

@ -39,6 +39,7 @@ class ScriptCache : public QObject, public Dependency {
public: public:
void clearCache(); void clearCache();
Q_INVOKABLE void clearATPScriptsFromCache();
void getScriptContents(const QString& scriptOrURL, contentAvailableCallback contentAvailable, bool forceDownload = false); void getScriptContents(const QString& scriptOrURL, contentAvailableCallback contentAvailable, bool forceDownload = false);

View file

@ -38,6 +38,10 @@ public:
return _inputPlugins; return _inputPlugins;
} }
virtual void destroyInputPlugins() override {
_inputPlugins.clear();
}
private: private:
InputPluginList _inputPlugins; InputPluginList _inputPlugins;
}; };

View file

@ -37,6 +37,10 @@ public:
return _inputPlugins; return _inputPlugins;
} }
virtual void destroyInputPlugins() override {
_inputPlugins.clear();
}
private: private:
InputPluginList _inputPlugins; InputPluginList _inputPlugins;
}; };

View file

@ -38,6 +38,9 @@ public:
return _inputPlugins; return _inputPlugins;
} }
virtual void destroyInputPlugins() override {
_inputPlugins.clear();
}
private: private:
InputPluginList _inputPlugins; InputPluginList _inputPlugins;
}; };

View file

@ -126,3 +126,7 @@ void OculusBaseDisplayPlugin::updatePresentPose() {
//_currentPresentFrameInfo.presentPose = toGlm(trackingState.HeadPose.ThePose); //_currentPresentFrameInfo.presentPose = toGlm(trackingState.HeadPose.ThePose);
_currentPresentFrameInfo.presentPose = _currentPresentFrameInfo.renderPose; _currentPresentFrameInfo.presentPose = _currentPresentFrameInfo.renderPose;
} }
OculusBaseDisplayPlugin::~OculusBaseDisplayPlugin() {
qDebug() << "Destroying OculusBaseDisplayPlugin";
}

View file

@ -16,6 +16,7 @@
class OculusBaseDisplayPlugin : public HmdDisplayPlugin { class OculusBaseDisplayPlugin : public HmdDisplayPlugin {
using Parent = HmdDisplayPlugin; using Parent = HmdDisplayPlugin;
public: public:
~OculusBaseDisplayPlugin();
bool isSupported() const override; bool isSupported() const override;
// Stereo specific methods // Stereo specific methods

View file

@ -46,7 +46,7 @@ void OculusDisplayPlugin::cycleDebugOutput() {
void OculusDisplayPlugin::customizeContext() { void OculusDisplayPlugin::customizeContext() {
Parent::customizeContext(); Parent::customizeContext();
_outputFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_SRGBA_32, _renderTargetSize.x, _renderTargetSize.y)); _outputFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OculusOutput", gpu::Element::COLOR_SRGBA_32, _renderTargetSize.x, _renderTargetSize.y));
ovrTextureSwapChainDesc desc = { }; ovrTextureSwapChainDesc desc = { };
desc.Type = ovrTexture_2D; desc.Type = ovrTexture_2D;
desc.ArraySize = 1; desc.ArraySize = 1;
@ -97,6 +97,7 @@ void OculusDisplayPlugin::uncustomizeContext() {
ovr_DestroyTextureSwapChain(_session, _textureSwapChain); ovr_DestroyTextureSwapChain(_session, _textureSwapChain);
_textureSwapChain = nullptr; _textureSwapChain = nullptr;
_outputFramebuffer.reset();
Parent::uncustomizeContext(); Parent::uncustomizeContext();
} }
@ -163,3 +164,7 @@ QString OculusDisplayPlugin::getPreferredAudioOutDevice() const {
} }
return AudioClient::friendlyNameForAudioDevice(buffer); return AudioClient::friendlyNameForAudioDevice(buffer);
} }
OculusDisplayPlugin::~OculusDisplayPlugin() {
qDebug() << "Destroying OculusDisplayPlugin";
}

View file

@ -12,6 +12,7 @@
class OculusDisplayPlugin : public OculusBaseDisplayPlugin { class OculusDisplayPlugin : public OculusBaseDisplayPlugin {
using Parent = OculusBaseDisplayPlugin; using Parent = OculusBaseDisplayPlugin;
public: public:
~OculusDisplayPlugin();
const QString& getName() const override { return NAME; } const QString& getName() const override { return NAME; }
void init() override; void init() override;

View file

@ -62,6 +62,14 @@ public:
return _inputPlugins; return _inputPlugins;
} }
virtual void destroyInputPlugins() override {
_inputPlugins.clear();
}
virtual void destroyDisplayPlugins() override {
_displayPlugins.clear();
}
private: private:
DisplayPluginList _displayPlugins; DisplayPluginList _displayPlugins;
InputPluginList _inputPlugins; InputPluginList _inputPlugins;

View file

@ -38,6 +38,10 @@ public:
return _displayPlugins; return _displayPlugins;
} }
virtual void destroyDisplayPlugins() override {
_displayPlugins.clear();
}
private: private:
DisplayPluginList _displayPlugins; DisplayPluginList _displayPlugins;
}; };

View file

@ -445,8 +445,9 @@ void OpenVrDisplayPlugin::internalDeactivate() {
_openVrDisplayActive = false; _openVrDisplayActive = false;
_container->setIsOptionChecked(StandingHMDSensorMode, false); _container->setIsOptionChecked(StandingHMDSensorMode, false);
if (_system) { if (_system) {
// Invalidate poses. It's fine if someone else sets these shared values, but we're about to stop updating them, and // TODO: Invalidate poses. It's fine if someone else sets these shared values, but we're about to stop updating them, and
// we don't want ViveControllerManager to consider old values to be valid. // we don't want ViveControllerManager to consider old values to be valid.
_container->makeRenderingContextCurrent();
releaseOpenVrSystem(); releaseOpenVrSystem();
_system = nullptr; _system = nullptr;
} }

View file

@ -51,6 +51,13 @@ public:
return _inputPlugins; return _inputPlugins;
} }
virtual void destroyInputPlugins() override {
_inputPlugins.clear();
}
virtual void destroyDisplayPlugins() override {
_displayPlugins.clear();
}
private: private:
DisplayPluginList _displayPlugins; DisplayPluginList _displayPlugins;

View file

@ -132,6 +132,7 @@ void ViveControllerManager::deactivate() {
_container->removeMenu(MENU_PATH); _container->removeMenu(MENU_PATH);
if (_system) { if (_system) {
_container->makeRenderingContextCurrent();
releaseOpenVrSystem(); releaseOpenVrSystem();
_system = nullptr; _system = nullptr;
} }

View file

@ -22,6 +22,7 @@ print('crowd-agent version 2');
- File urls for AC scripts silently fail. Use a local server (e.g., python SimpleHTTPServer) for development. - File urls for AC scripts silently fail. Use a local server (e.g., python SimpleHTTPServer) for development.
- URLs are cached regardless of server headers. Must use cache-defeating query parameters. - URLs are cached regardless of server headers. Must use cache-defeating query parameters.
- JSON.stringify(Avatar) silently fails (even when Agent.isAvatar) - JSON.stringify(Avatar) silently fails (even when Agent.isAvatar)
- If you run from a dev build directory, you must link assignment-client/<target>/resources to ../../interface/<target>/resources
*/ */
function messageSend(message) { function messageSend(message) {

View file

@ -23,6 +23,14 @@ var DENSITY = 0.3; // square meters per person. Some say 10 sq ft is arm's lengt
var SOUND_DATA = {url: "http://howard-stearns.github.io/models/sounds/piano1.wav"}; var SOUND_DATA = {url: "http://howard-stearns.github.io/models/sounds/piano1.wav"};
var AVATARS_CHATTERING_AT_ONCE = 4; // How many of the agents should we request to play SOUND at once. var AVATARS_CHATTERING_AT_ONCE = 4; // How many of the agents should we request to play SOUND at once.
var NEXT_SOUND_SPREAD = 500; // millisecond range of how long to wait after one sound finishes, before playing the next var NEXT_SOUND_SPREAD = 500; // millisecond range of how long to wait after one sound finishes, before playing the next
var ANIMATION_DATA = {
"url": "http://howard-stearns.github.io/models/resources/avatar/animations/idle.fbx",
// "url": "http://howard-stearns.github.io/models/resources/avatar/animations/walk_fwd.fbx", // alternative example
"startFrame": 0.0,
"endFrame": 300.0,
"timeScale": 1.0,
"loopFlag": true
};
var spread = Math.sqrt(MINIMUM_AVATARS * DENSITY); // meters var spread = Math.sqrt(MINIMUM_AVATARS * DENSITY); // meters
var turnSpread = 90; // How many degrees should turn from front range over. var turnSpread = 90; // How many degrees should turn from front range over.
@ -71,18 +79,8 @@ function messageHandler(channel, messageString, senderID) {
rcpt: senderID, rcpt: senderID,
position: Vec3.sum(MyAvatar.position, {x: coord(), y: 0, z: coord()}), position: Vec3.sum(MyAvatar.position, {x: coord(), y: 0, z: coord()}),
orientation: Quat.fromPitchYawRollDegrees(0, Quat.safeEulerAngles(MyAvatar.orientation).y + (turnSpread * (Math.random() - 0.5)), 0), orientation: Quat.fromPitchYawRollDegrees(0, Quat.safeEulerAngles(MyAvatar.orientation).y + (turnSpread * (Math.random() - 0.5)), 0),
soundData: chatter && SOUND_DATA/* soundData: chatter && SOUND_DATA,
// No need to specify skeletonModelURL animationData: ANIMATION_DATA
//skeletonModelURL: "file:///c:/Program Files/High Fidelity Release/resources/meshes/being_of_light/being_of_light.fbx",
//skeletonModelURL: "file:///c:/Program Files/High Fidelity Release/resources/meshes/defaultAvatar_full.fst"/,
animationData: { // T-pose until we get animations working again.
"url": "file:///C:/Program Files/High Fidelity Release/resources/avatar/animations/idle.fbx",
//"url": "file:///c:/Program Files/High Fidelity Release/resources/avatar/animations/walk_fwd.fbx",
"startFrame": 0.0,
"endFrame": 300.0,
"timeScale": 1.0,
"loopFlag": true
}*/
}); });
} }
break; break;

View file

@ -471,7 +471,12 @@ function update() {
if (!Menu.isOptionChecked("First Person")) { if (!Menu.isOptionChecked("First Person")) {
return off(); // What to do? menus can be behind hand! return off(); // What to do? menus can be behind hand!
} }
if (!Window.hasFocus() || !Reticle.allowMouseCapture) { if ((!Window.hasFocus() && !HMD.active) || !Reticle.allowMouseCapture) {
// In desktop it's pretty clear when another app is on top. In that case we bail, because
// hand controllers might be sputtering "valid" data and that will keep someone from deliberately
// using the mouse on another app. (Fogbugz case 546.)
// However, in HMD, you might not realize you're not on top, and you wouldn't be able to operate
// other apps anyway. So in that case, we DO keep going even though we're not on top. (Fogbugz 1831.)
return off(); // Don't mess with other apps or paused mouse activity return off(); // Don't mess with other apps or paused mouse activity
} }
leftTrigger.update(); leftTrigger.update();

View file

@ -1155,7 +1155,7 @@ function getPositionToImportEntity() {
return position; return position;
} }
function importSVO(importURL) { function importSVO(importURL) {
if (!Entities.canAdjustLocks()) { if (!Entities.canRez() && !Entities.canRezTmp()) {
Window.notifyEditError(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); Window.notifyEditError(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG);
return; return;
} }

View file

@ -6,7 +6,7 @@
<link rel="stylesheet" type="text/css" href="content-update.css"></link> <link rel="stylesheet" type="text/css" href="content-update.css"></link>
</head> </head>
<body onload="ready()"> <body onload="ready()">
<div class="colmask"> <div class="colmask" id="content">
<h3>We backed up your old Sandbox content, just in case.</h3> <h3>We backed up your old Sandbox content, just in case.</h3>
<p><b>To restore it, follow these steps:</b> <p><b>To restore it, follow these steps:</b>
@ -45,9 +45,9 @@
</div> </div>
<div class="footer"> <div class="footer">
<p>For more information about managing your high Fidelity Sandbox Server, check out our docs: <a href="https://wiki.highfidelity.com/wiki/Sandbox" target="_blank">wiki.highfidelity.com/wiki/Sandbox</a> <p>For more information about managing your high Fidelity Sandbox Server, check out our docs: <a href="https://wiki.highfidelity.com/wiki/Sandbox" target="_blank">wiki.highfidelity.com/wiki/Sandbox</a>
</p>
</div>
</div> </div>
</div>
</body> </body>
</html> </html>

View file

@ -6,6 +6,11 @@ function ready() {
electron.ipcRenderer.on('update', function(event, message) { electron.ipcRenderer.on('update', function(event, message) {
$('#directory').html(message); $('#directory').html(message);
electron.ipcRenderer.send('setSize', {
width: $(window).width(),
height: $('#content').height() + 50
});
}); });
electron.ipcRenderer.send('ready'); electron.ipcRenderer.send('ready');

View file

@ -530,6 +530,9 @@ function openBackupInstructions(folder) {
} }
window.show(); window.show();
electron.ipcMain.on('setSize', function(event, obj) {
window.setSize(obj.width, obj.height);
});
electron.ipcMain.on('ready', function() { electron.ipcMain.on('ready', function() {
console.log("got ready"); console.log("got ready");
window.webContents.send('update', folder); window.webContents.send('update', folder);