mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-09 07:33:19 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into stack-manager
This commit is contained in:
commit
5d2700309d
22 changed files with 208 additions and 116 deletions
|
@ -22,6 +22,7 @@
|
|||
#include <NodeList.h>
|
||||
#include <udt/PacketHeaders.h>
|
||||
#include <ResourceCache.h>
|
||||
#include <ScriptCache.h>
|
||||
#include <SoundCache.h>
|
||||
#include <UUID.h>
|
||||
|
||||
|
@ -116,6 +117,11 @@ void Agent::handleAudioPacket(QSharedPointer<NLPacket> packet) {
|
|||
const QString AGENT_LOGGING_NAME = "agent";
|
||||
|
||||
void Agent::run() {
|
||||
|
||||
// make sure we request our script once the agent connects to the domain
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
connect(&nodeList->getDomainHandler(), &DomainHandler::connectedToDomain, this, &Agent::requestScript);
|
||||
|
||||
ThreadedAssignment::commonInit(AGENT_LOGGING_NAME, NodeType::Agent);
|
||||
|
||||
// Setup MessagesClient
|
||||
|
@ -125,72 +131,99 @@ void Agent::run() {
|
|||
messagesClient->moveToThread(messagesThread);
|
||||
connect(messagesThread, &QThread::started, messagesClient.data(), &MessagesClient::init);
|
||||
messagesThread->start();
|
||||
|
||||
nodeList->addSetOfNodeTypesToNodeInterestSet({
|
||||
NodeType::AudioMixer, NodeType::AvatarMixer, NodeType::EntityServer, NodeType::MessagesMixer
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Agent::requestScript() {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet()
|
||||
<< NodeType::AudioMixer
|
||||
<< NodeType::AvatarMixer
|
||||
<< NodeType::EntityServer
|
||||
<< NodeType::MessagesMixer
|
||||
);
|
||||
|
||||
disconnect(&nodeList->getDomainHandler(), &DomainHandler::connectedToDomain, this, &Agent::requestScript);
|
||||
|
||||
// figure out the URL for the script for this agent assignment
|
||||
QUrl scriptURL;
|
||||
if (_payload.isEmpty()) {
|
||||
scriptURL = QUrl(QString("http://%1:%2/assignment/%3")
|
||||
.arg(DependencyManager::get<NodeList>()->getDomainHandler().getIP().toString())
|
||||
.arg(DOMAIN_SERVER_HTTP_PORT)
|
||||
.arg(uuidStringWithoutCurlyBraces(_uuid)));
|
||||
scriptURL = QUrl(QString("http://%1:%2/assignment/%3/")
|
||||
.arg(nodeList->getDomainHandler().getIP().toString())
|
||||
.arg(DOMAIN_SERVER_HTTP_PORT)
|
||||
.arg(uuidStringWithoutCurlyBraces(nodeList->getSessionUUID())));
|
||||
} else {
|
||||
scriptURL = QUrl(_payload);
|
||||
}
|
||||
|
||||
|
||||
// setup a network access manager and
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkRequest networkRequest = QNetworkRequest(scriptURL);
|
||||
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||
QNetworkReply* reply = networkAccessManager.get(networkRequest);
|
||||
|
||||
|
||||
QNetworkDiskCache* cache = new QNetworkDiskCache();
|
||||
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||
cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "agentCache");
|
||||
networkAccessManager.setCache(cache);
|
||||
|
||||
|
||||
QNetworkRequest networkRequest = QNetworkRequest(scriptURL);
|
||||
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||
|
||||
// setup a timeout for script request
|
||||
static const int SCRIPT_TIMEOUT_MS = 10000;
|
||||
_scriptRequestTimeout = new QTimer(this);
|
||||
connect(_scriptRequestTimeout, &QTimer::timeout, this, &Agent::scriptRequestFinished);
|
||||
_scriptRequestTimeout->start(SCRIPT_TIMEOUT_MS);
|
||||
|
||||
qDebug() << "Downloading script at" << scriptURL.toString();
|
||||
QNetworkReply* reply = networkAccessManager.get(networkRequest);
|
||||
connect(reply, &QNetworkReply::finished, this, &Agent::scriptRequestFinished);
|
||||
}
|
||||
|
||||
QEventLoop loop;
|
||||
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
void Agent::scriptRequestFinished() {
|
||||
auto reply = qobject_cast<QNetworkReply*>(sender());
|
||||
|
||||
loop.exec();
|
||||
_scriptRequestTimeout->stop();
|
||||
|
||||
if (reply && reply->error() == QNetworkReply::NoError) {
|
||||
_scriptContents = reply->readAll();
|
||||
qDebug() << "Downloaded script:" << _scriptContents;
|
||||
|
||||
// we could just call executeScript directly - we use a QueuedConnection to allow scriptRequestFinished
|
||||
// to return before calling executeScript
|
||||
QMetaObject::invokeMethod(this, "executeScript", Qt::QueuedConnection);
|
||||
} else {
|
||||
if (reply) {
|
||||
qDebug() << "Failed to download script at" << reply->url().toString() << " - bailing on assignment.";
|
||||
qDebug() << "QNetworkReply error was" << reply->errorString();
|
||||
} else {
|
||||
qDebug() << "Failed to download script - request timed out. Bailing on assignment.";
|
||||
}
|
||||
|
||||
setFinished(true);
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
QString scriptContents(reply->readAll());
|
||||
delete reply;
|
||||
|
||||
qDebug() << "Downloaded script:" << scriptContents;
|
||||
|
||||
_scriptEngine = std::unique_ptr<ScriptEngine>(new ScriptEngine(scriptContents, _payload));
|
||||
void Agent::executeScript() {
|
||||
_scriptEngine = std::unique_ptr<ScriptEngine>(new ScriptEngine(_scriptContents, _payload));
|
||||
_scriptEngine->setParent(this); // be the parent of the script engine so it gets moved when we do
|
||||
|
||||
|
||||
// setup an Avatar for the script to use
|
||||
auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>();
|
||||
connect(_scriptEngine.get(), SIGNAL(update(float)), scriptedAvatar.data(), SLOT(update(float)), Qt::ConnectionType::QueuedConnection);
|
||||
scriptedAvatar->setForceFaceTrackerConnected(true);
|
||||
|
||||
|
||||
// call model URL setters with empty URLs so our avatar, if user, will have the default models
|
||||
scriptedAvatar->setFaceModelURL(QUrl());
|
||||
scriptedAvatar->setSkeletonModelURL(QUrl());
|
||||
// give this AvatarData object to the script engine
|
||||
_scriptEngine->registerGlobalObject("Avatar", scriptedAvatar.data());
|
||||
|
||||
|
||||
|
||||
|
||||
using namespace recording;
|
||||
static const FrameType AVATAR_FRAME_TYPE = Frame::registerFrameType(AvatarData::FRAME_NAME);
|
||||
// FIXME how to deal with driving multiple avatars locally?
|
||||
// FIXME how to deal with driving multiple avatars locally?
|
||||
Frame::registerFrameHandler(AVATAR_FRAME_TYPE, [this, scriptedAvatar](Frame::ConstPointer frame) {
|
||||
AvatarData::fromFrame(frame->data, *scriptedAvatar);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
using namespace recording;
|
||||
static const FrameType AUDIO_FRAME_TYPE = Frame::registerFrameType(AudioConstants::AUDIO_FRAME_NAME);
|
||||
Frame::registerFrameHandler(AUDIO_FRAME_TYPE, [this, &scriptedAvatar](Frame::ConstPointer frame) {
|
||||
|
@ -201,32 +234,30 @@ void Agent::run() {
|
|||
audioTransform.setRotation(scriptedAvatar->getOrientation());
|
||||
AbstractAudioInterface::emitAudioPacket(audio.data(), audio.size(), audioSequenceNumber, audioTransform, PacketType::MicrophoneAudioNoEcho);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
auto avatarHashMap = DependencyManager::set<AvatarHashMap>();
|
||||
_scriptEngine->registerGlobalObject("AvatarList", avatarHashMap.data());
|
||||
|
||||
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::BulkAvatarData, avatarHashMap.data(), "processAvatarDataPacket");
|
||||
packetReceiver.registerListener(PacketType::KillAvatar, avatarHashMap.data(), "processKillAvatar");
|
||||
packetReceiver.registerListener(PacketType::AvatarIdentity, avatarHashMap.data(), "processAvatarIdentityPacket");
|
||||
packetReceiver.registerListener(PacketType::AvatarBillboard, avatarHashMap.data(), "processAvatarBillboardPacket");
|
||||
|
||||
|
||||
// register ourselves to the script engine
|
||||
_scriptEngine->registerGlobalObject("Agent", this);
|
||||
|
||||
// FIXME -we shouldn't be calling this directly, it's normally called by run(), not sure why
|
||||
|
||||
// FIXME -we shouldn't be calling this directly, it's normally called by run(), not sure why
|
||||
// viewers would need this called.
|
||||
//_scriptEngine->init(); // must be done before we set up the viewers
|
||||
|
||||
|
||||
_scriptEngine->registerGlobalObject("SoundCache", DependencyManager::get<SoundCache>().data());
|
||||
|
||||
|
||||
QScriptValue webSocketServerConstructorValue = _scriptEngine->newFunction(WebSocketServerClass::constructor);
|
||||
_scriptEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue);
|
||||
|
||||
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
|
||||
|
||||
_scriptEngine->registerGlobalObject("EntityViewer", &_entityViewer);
|
||||
|
||||
// we need to make sure that init has been called for our EntityScriptingInterface
|
||||
|
@ -237,15 +268,15 @@ void Agent::run() {
|
|||
_entityViewer.init();
|
||||
|
||||
entityScriptingInterface->setEntityTree(_entityViewer.getTree());
|
||||
|
||||
|
||||
// wire up our additional agent related processing to the update signal
|
||||
QObject::connect(_scriptEngine.get(), &ScriptEngine::update, this, &Agent::processAgentAvatarAndAudio);
|
||||
|
||||
|
||||
_scriptEngine->run();
|
||||
|
||||
|
||||
Frame::clearFrameHandler(AUDIO_FRAME_TYPE);
|
||||
Frame::clearFrameHandler(AVATAR_FRAME_TYPE);
|
||||
|
||||
|
||||
setFinished(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,10 @@ public slots:
|
|||
void playAvatarSound(Sound* avatarSound) { setAvatarSound(avatarSound); }
|
||||
|
||||
private slots:
|
||||
void requestScript();
|
||||
void scriptRequestFinished();
|
||||
void executeScript();
|
||||
|
||||
void handleAudioPacket(QSharedPointer<NLPacket> packet);
|
||||
void handleOctreePacket(QSharedPointer<NLPacket> packet, SharedNodePointer senderNode);
|
||||
void handleJurisdictionPacket(QSharedPointer<NLPacket> packet, SharedNodePointer senderNode);
|
||||
|
@ -73,6 +77,8 @@ private:
|
|||
void sendAvatarIdentityPacket();
|
||||
void sendAvatarBillboardPacket();
|
||||
|
||||
QString _scriptContents;
|
||||
QTimer* _scriptRequestTimeout { nullptr };
|
||||
bool _isListeningToAudioStream = false;
|
||||
Sound* _avatarSound = nullptr;
|
||||
int _numAvatarSoundSentBytes = 0;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <memory>
|
||||
#include <signal.h>
|
||||
|
||||
#include <AddressManager.h>
|
||||
|
@ -227,8 +228,9 @@ void AssignmentClientMonitor::handleChildStatusPacket(QSharedPointer<NLPacket> p
|
|||
matchingNode = DependencyManager::get<LimitedNodeList>()->addOrUpdateNode
|
||||
(senderID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false, false);
|
||||
|
||||
childData = new AssignmentClientChildData(Assignment::Type::AllTypes);
|
||||
matchingNode->setLinkedData(childData);
|
||||
auto childData = std::unique_ptr<AssignmentClientChildData>
|
||||
{ new AssignmentClientChildData(Assignment::Type::AllTypes) };
|
||||
matchingNode->setLinkedData(std::move(childData));
|
||||
} else {
|
||||
// tell unknown assignment-client child to exit.
|
||||
qDebug() << "Asking unknown child at" << senderSockAddr << "to exit.";
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <memory>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -661,7 +662,7 @@ void AudioMixer::domainSettingsRequestComplete() {
|
|||
nodeList->addNodeTypeToInterestSet(NodeType::Agent);
|
||||
|
||||
nodeList->linkedDataCreateCallback = [](Node* node) {
|
||||
node->setLinkedData(new AudioMixerClientData());
|
||||
node->setLinkedData(std::unique_ptr<AudioMixerClientData> { new AudioMixerClientData });
|
||||
};
|
||||
|
||||
DomainHandler& domainHandler = nodeList->getDomainHandler();
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <cfloat>
|
||||
#include <random>
|
||||
#include <memory>
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QDateTime>
|
||||
|
@ -536,7 +537,7 @@ void AvatarMixer::domainSettingsRequestComplete() {
|
|||
nodeList->addNodeTypeToInterestSet(NodeType::Agent);
|
||||
|
||||
nodeList->linkedDataCreateCallback = [] (Node* node) {
|
||||
node->setLinkedData(new AvatarMixerClientData());
|
||||
node->setLinkedData(std::unique_ptr<AvatarMixerClientData> { new AvatarMixerClientData });
|
||||
};
|
||||
|
||||
// parse the settings to pull out the values we need
|
||||
|
|
|
@ -46,8 +46,8 @@ void EntityServer::handleEntityPacket(QSharedPointer<NLPacket> packet, SharedNod
|
|||
}
|
||||
}
|
||||
|
||||
OctreeQueryNode* EntityServer::createOctreeQueryNode() {
|
||||
return new EntityNodeData();
|
||||
std::unique_ptr<OctreeQueryNode> EntityServer::createOctreeQueryNode() {
|
||||
return std::unique_ptr<OctreeQueryNode> { new EntityNodeData() };
|
||||
}
|
||||
|
||||
OctreePointer EntityServer::createTree() {
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include "../octree/OctreeServer.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "EntityItem.h"
|
||||
#include "EntityServerConsts.h"
|
||||
#include "EntityTree.h"
|
||||
|
@ -26,7 +28,7 @@ public:
|
|||
~EntityServer();
|
||||
|
||||
// Subclasses must implement these methods
|
||||
virtual OctreeQueryNode* createOctreeQueryNode() override ;
|
||||
virtual std::unique_ptr<OctreeQueryNode> createOctreeQueryNode() override ;
|
||||
virtual char getMyNodeType() const override { return NodeType::EntityServer; }
|
||||
virtual PacketType getMyQueryMessageType() const override { return PacketType::EntityQuery; }
|
||||
virtual const char* getMyServerName() const override { return MODEL_SERVER_NAME; }
|
||||
|
|
|
@ -1113,9 +1113,9 @@ void OctreeServer::domainSettingsRequestComplete() {
|
|||
#endif
|
||||
|
||||
nodeList->linkedDataCreateCallback = [] (Node* node) {
|
||||
OctreeQueryNode* newQueryNodeData = _instance->createOctreeQueryNode();
|
||||
newQueryNodeData->init();
|
||||
node->setLinkedData(newQueryNodeData);
|
||||
auto queryNodeData = _instance->createOctreeQueryNode();
|
||||
queryNodeData->init();
|
||||
node->setLinkedData(std::move(queryNodeData));
|
||||
};
|
||||
|
||||
srand((unsigned)time(0));
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#ifndef hifi_OctreeServer_h
|
||||
#define hifi_OctreeServer_h
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QStringList>
|
||||
#include <QDateTime>
|
||||
#include <QtCore/QCoreApplication>
|
||||
|
@ -64,7 +66,7 @@ public:
|
|||
QByteArray getPersistFileContents() const { return (_persistThread) ? _persistThread->getPersistFileContents() : QByteArray(); }
|
||||
|
||||
// Subclasses must implement these methods
|
||||
virtual OctreeQueryNode* createOctreeQueryNode() = 0;
|
||||
virtual std::unique_ptr<OctreeQueryNode> createOctreeQueryNode() = 0;
|
||||
virtual char getMyNodeType() const = 0;
|
||||
virtual PacketType getMyQueryMessageType() const = 0;
|
||||
virtual const char* getMyServerName() const = 0;
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "DomainServer.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QDir>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
@ -1097,29 +1099,37 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
|||
|
||||
if (connection->requestOperation() == QNetworkAccessManager::GetOperation
|
||||
&& assignmentRegex.indexIn(url.path()) != -1) {
|
||||
QUuid matchingUUID = QUuid(assignmentRegex.cap(1));
|
||||
|
||||
SharedAssignmentPointer matchingAssignment = _allAssignments.value(matchingUUID);
|
||||
if (!matchingAssignment) {
|
||||
// check if we have a pending assignment that matches this temp UUID, and it is a scripted assignment
|
||||
QUuid assignmentUUID = _gatekeeper.assignmentUUIDForPendingAssignment(matchingUUID);
|
||||
if (!assignmentUUID.isNull()) {
|
||||
matchingAssignment = _allAssignments.value(assignmentUUID);
|
||||
|
||||
if (matchingAssignment && matchingAssignment->getType() == Assignment::AgentType) {
|
||||
// we have a matching assignment and it is for the right type, have the HTTP manager handle it
|
||||
// via correct URL for the script so the client can download
|
||||
|
||||
QUrl scriptURL = url;
|
||||
scriptURL.setPath(URI_ASSIGNMENT + "/scripts/"
|
||||
+ uuidStringWithoutCurlyBraces(assignmentUUID));
|
||||
|
||||
// have the HTTPManager serve the appropriate script file
|
||||
return _httpManager.handleHTTPRequest(connection, scriptURL, true);
|
||||
}
|
||||
}
|
||||
QUuid nodeUUID = QUuid(assignmentRegex.cap(1));
|
||||
|
||||
auto matchingNode = nodeList->nodeWithUUID(nodeUUID);
|
||||
|
||||
// don't handle if we don't have a matching node
|
||||
if (!matchingNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
auto nodeData = dynamic_cast<DomainServerNodeData*>(matchingNode->getLinkedData());
|
||||
|
||||
// don't handle if we don't have node data for this node
|
||||
if (!nodeData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SharedAssignmentPointer matchingAssignment = _allAssignments.value(nodeData->getAssignmentUUID());
|
||||
|
||||
// check if we have an assignment that matches this temp UUID, and it is a scripted assignment
|
||||
if (matchingAssignment && matchingAssignment->getType() == Assignment::AgentType) {
|
||||
// we have a matching assignment and it is for the right type, have the HTTP manager handle it
|
||||
// via correct URL for the script so the client can download
|
||||
|
||||
QUrl scriptURL = url;
|
||||
scriptURL.setPath(URI_ASSIGNMENT + "/scripts/"
|
||||
+ uuidStringWithoutCurlyBraces(matchingAssignment->getUUID()));
|
||||
|
||||
// have the HTTPManager serve the appropriate script file
|
||||
return _httpManager.handleHTTPRequest(connection, scriptURL, true);
|
||||
}
|
||||
|
||||
// request not handled
|
||||
return false;
|
||||
}
|
||||
|
@ -1640,7 +1650,7 @@ void DomainServer::refreshStaticAssignmentAndAddToQueue(SharedAssignmentPointer&
|
|||
|
||||
void DomainServer::nodeAdded(SharedNodePointer node) {
|
||||
// we don't use updateNodeWithData, so add the DomainServerNodeData to the node here
|
||||
node->setLinkedData(new DomainServerNodeData());
|
||||
node->setLinkedData(std::unique_ptr<DomainServerNodeData> { new DomainServerNodeData() });
|
||||
}
|
||||
|
||||
void DomainServer::nodeKilled(SharedNodePointer node) {
|
||||
|
|
|
@ -19,10 +19,11 @@ var MAX_LINE_LENGTH = 40; // This must be 2 or greater;
|
|||
var DEFAULT_STROKE_WIDTH = 0.1;
|
||||
var DEFAULT_LIFETIME = 20;
|
||||
var DEFAULT_COLOR = { red: 255, green: 255, blue: 255 };
|
||||
var PolyLine = function(position, color, lifetime) {
|
||||
var PolyLine = function(position, color, lifetime, texture) {
|
||||
this.position = position;
|
||||
this.color = color;
|
||||
this.lifetime = lifetime === undefined ? DEFAULT_LIFETIME : lifetime;
|
||||
this.texture = texture ? texture : "";
|
||||
this.points = [
|
||||
];
|
||||
this.strokeWidths = [
|
||||
|
@ -37,7 +38,8 @@ var PolyLine = function(position, color, lifetime) {
|
|||
strokeWidths: this.strokeWidths,
|
||||
dimensions: LINE_DIMENSIONS,
|
||||
color: color,
|
||||
lifetime: lifetime
|
||||
lifetime: lifetime,
|
||||
textures: this.texture
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -98,26 +100,29 @@ PolyLine.prototype.destroy = function() {
|
|||
|
||||
|
||||
// InfiniteLine
|
||||
InfiniteLine = function(position, color, lifetime) {
|
||||
InfiniteLine = function(position, color, lifetime, textureBegin, textureMiddle) {
|
||||
this.position = position;
|
||||
this.color = color;
|
||||
this.lifetime = lifetime === undefined ? DEFAULT_LIFETIME : lifetime;
|
||||
this.lines = [];
|
||||
this.size = 0;
|
||||
|
||||
this.textureBegin = textureBegin ? textureBegin : "";
|
||||
this.textureMiddle = textureMiddle ? textureMiddle : "";
|
||||
};
|
||||
|
||||
InfiniteLine.prototype.enqueuePoint = function(position, strokeWidth) {
|
||||
var currentLine;
|
||||
|
||||
if (this.lines.length == 0) {
|
||||
currentLine = new PolyLine(position, this.color, this.lifetime);
|
||||
currentLine = new PolyLine(position, this.color, this.lifetime, this.textureBegin);
|
||||
this.lines.push(currentLine);
|
||||
} else {
|
||||
currentLine = this.lines[this.lines.length - 1];
|
||||
}
|
||||
|
||||
if (currentLine.isFull()) {
|
||||
var newLine = new PolyLine(currentLine.getLastPoint(), this.color, this.lifetime);
|
||||
var newLine = new PolyLine(currentLine.getLastPoint(), this.color, this.lifetime, this.textureMiddle);
|
||||
newLine.enqueuePoint(currentLine.getLastPoint(), strokeWidth);
|
||||
this.lines.push(newLine);
|
||||
currentLine = newLine;
|
||||
|
|
|
@ -801,6 +801,14 @@ void AvatarData::changeReferential(Referential* ref) {
|
|||
_referential = ref;
|
||||
}
|
||||
|
||||
void AvatarData::setRawJointData(QVector<JointData> data) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setRawJointData", Q_ARG(QVector<JointData>, data));
|
||||
return;
|
||||
}
|
||||
_jointData = data;
|
||||
}
|
||||
|
||||
void AvatarData::setJointData(int index, const glm::quat& rotation, const glm::vec3& translation) {
|
||||
if (index == -1) {
|
||||
return;
|
||||
|
@ -1538,16 +1546,15 @@ void AvatarData::fromFrame(const QByteArray& frameData, AvatarData& result) {
|
|||
QVector<JointData> jointArray;
|
||||
QJsonArray jointArrayJson = root[JSON_AVATAR_JOINT_ARRAY].toArray();
|
||||
jointArray.reserve(jointArrayJson.size());
|
||||
int i = 0;
|
||||
for (const auto& jointJson : jointArrayJson) {
|
||||
jointArray.push_back(jointDataFromJsonValue(jointJson));
|
||||
auto joint = jointDataFromJsonValue(jointJson);
|
||||
jointArray.push_back(joint);
|
||||
result.setJointData(i, joint.rotation, joint.translation);
|
||||
result._jointData[i].rotationSet = true; // Have to do that to broadcast the avatar new pose
|
||||
i++;
|
||||
}
|
||||
|
||||
QVector<glm::quat> jointRotations;
|
||||
jointRotations.reserve(jointArray.size());
|
||||
for (const auto& joint : jointArray) {
|
||||
jointRotations.push_back(joint.rotation);
|
||||
}
|
||||
result.setJointRotations(jointRotations);
|
||||
result.setRawJointData(jointArray);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -247,7 +247,7 @@ public:
|
|||
Q_INVOKABLE char getHandState() const { return _handState; }
|
||||
|
||||
const QVector<JointData>& getRawJointData() const { return _jointData; }
|
||||
void setRawJointData(QVector<JointData> data) { _jointData = data; }
|
||||
Q_INVOKABLE void setRawJointData(QVector<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);
|
||||
|
|
|
@ -36,7 +36,6 @@ PolyLineEntityItem(entityItemID, properties) {
|
|||
|
||||
gpu::PipelinePointer RenderablePolyLineEntityItem::_pipeline;
|
||||
gpu::Stream::FormatPointer RenderablePolyLineEntityItem::_format;
|
||||
gpu::TexturePointer RenderablePolyLineEntityItem::_texture;
|
||||
int32_t RenderablePolyLineEntityItem::PAINTSTROKE_GPU_SLOT;
|
||||
|
||||
void RenderablePolyLineEntityItem::createPipeline() {
|
||||
|
@ -44,9 +43,6 @@ void RenderablePolyLineEntityItem::createPipeline() {
|
|||
static const int COLOR_OFFSET = 24;
|
||||
static const int TEXTURE_OFFSET = 28;
|
||||
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
QString path = PathUtils::resourcesPath() + "images/paintStroke.png";
|
||||
_texture = textureCache->getImageTexture(path);
|
||||
_format.reset(new gpu::Stream::Format());
|
||||
_format->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
||||
_format->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), NORMAL_OFFSET);
|
||||
|
@ -132,6 +128,13 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) {
|
|||
createPipeline();
|
||||
}
|
||||
|
||||
if (!_texture || _texturesChangedFlag) {
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
QString path = _textures.isEmpty() ? PathUtils::resourcesPath() + "images/paintStroke.png" : _textures;
|
||||
_texture = textureCache->getTexture(QUrl(path));
|
||||
_texturesChangedFlag = false;
|
||||
}
|
||||
|
||||
PerformanceTimer perfTimer("RenderablePolyLineEntityItem::render");
|
||||
Q_ASSERT(getType() == EntityTypes::PolyLine);
|
||||
|
||||
|
@ -147,7 +150,11 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) {
|
|||
batch.setModelTransform(transform);
|
||||
|
||||
batch.setPipeline(_pipeline);
|
||||
batch.setResourceTexture(PAINTSTROKE_GPU_SLOT, _texture);
|
||||
if (_texture->isLoaded()) {
|
||||
batch.setResourceTexture(PAINTSTROKE_GPU_SLOT, _texture->getGPUTexture());
|
||||
} else {
|
||||
batch.setResourceTexture(PAINTSTROKE_GPU_SLOT, args->_whiteTexture);
|
||||
}
|
||||
|
||||
batch.setInputFormat(_format);
|
||||
batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride);
|
||||
|
|
|
@ -12,10 +12,13 @@
|
|||
#ifndef hifi_RenderablePolyLineEntityItem_h
|
||||
#define hifi_RenderablePolyLineEntityItem_h
|
||||
|
||||
|
||||
#include <gpu/Batch.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <PolyLineEntityItem.h>
|
||||
#include "RenderableEntityItem.h"
|
||||
#include <GeometryCache.h>
|
||||
#include <TextureCache.h>
|
||||
|
||||
#include <QReadWriteLock>
|
||||
|
||||
|
||||
|
@ -29,9 +32,10 @@ public:
|
|||
|
||||
SIMPLE_RENDERABLE();
|
||||
|
||||
NetworkTexturePointer _texture;
|
||||
|
||||
static gpu::PipelinePointer _pipeline;
|
||||
static gpu::Stream::FormatPointer _format;
|
||||
static gpu::TexturePointer _texture;
|
||||
static int32_t PAINTSTROKE_GPU_SLOT;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -432,6 +432,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_POINTS, linePoints);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_NORMALS, normals);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_STROKE_WIDTHS, strokeWidths);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXTURES, textures);
|
||||
}
|
||||
|
||||
// Sitting properties support
|
||||
|
@ -1011,6 +1012,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, properties.getLinePoints());
|
||||
APPEND_ENTITY_PROPERTY(PROP_NORMALS, properties.getNormals());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, properties.getStrokeWidths());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, properties.getTextures());
|
||||
}
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, properties.getMarketplaceID());
|
||||
|
@ -1287,6 +1289,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_POINTS, QVector<glm::vec3>, setLinePoints);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NORMALS, QVector<glm::vec3>, setNormals);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STROKE_WIDTHS, QVector<float>, setStrokeWidths);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
|
||||
|
|
|
@ -37,7 +37,8 @@ _pointsChanged(true),
|
|||
_points(QVector<glm::vec3>(0.0f)),
|
||||
_vertices(QVector<glm::vec3>(0.0f)),
|
||||
_normals(QVector<glm::vec3>(0.0f)),
|
||||
_strokeWidths(QVector<float>(0.0f))
|
||||
_strokeWidths(QVector<float>(0.0f)),
|
||||
_textures("")
|
||||
{
|
||||
_type = EntityTypes::PolyLine;
|
||||
_created = properties.getCreated();
|
||||
|
@ -56,6 +57,7 @@ EntityItemProperties PolyLineEntityItem::getProperties(EntityPropertyFlags desir
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(linePoints, getLinePoints);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(normals, getNormals);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(strokeWidths, getStrokeWidths);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
|
||||
|
||||
properties._glowLevel = getGlowLevel();
|
||||
properties._glowLevelChanged = false;
|
||||
|
@ -72,6 +74,7 @@ bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(linePoints, setLinePoints);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(normals, setNormals);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(strokeWidths, setStrokeWidths);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
|
@ -196,6 +199,7 @@ int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da
|
|||
READ_ENTITY_PROPERTY(PROP_LINE_POINTS, QVector<glm::vec3>, setLinePoints);
|
||||
READ_ENTITY_PROPERTY(PROP_NORMALS, QVector<glm::vec3>, setNormals);
|
||||
READ_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, QVector<float>, setStrokeWidths);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -209,6 +213,7 @@ EntityPropertyFlags PolyLineEntityItem::getEntityProperties(EncodeBitstreamParam
|
|||
requestedProperties += PROP_LINE_POINTS;
|
||||
requestedProperties += PROP_NORMALS;
|
||||
requestedProperties += PROP_STROKE_WIDTHS;
|
||||
requestedProperties += PROP_TEXTURES;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
|
@ -228,6 +233,7 @@ void PolyLineEntityItem::appendSubclassData(OctreePacketData* packetData, Encode
|
|||
APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, getLinePoints());
|
||||
APPEND_ENTITY_PROPERTY(PROP_NORMALS, getNormals());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, getStrokeWidths());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures());
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::debugDump() const {
|
||||
|
|
|
@ -67,7 +67,14 @@ class PolyLineEntityItem : public EntityItem {
|
|||
|
||||
bool setStrokeWidths(const QVector<float>& strokeWidths);
|
||||
const QVector<float>& getStrokeWidths() const{ return _strokeWidths; }
|
||||
|
||||
|
||||
const QString& getTextures() const { return _textures; }
|
||||
void setTextures(const QString& textures) {
|
||||
if (_textures != textures) {
|
||||
_textures = textures;
|
||||
_texturesChangedFlag = true;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_LINE; }
|
||||
|
||||
|
@ -90,6 +97,8 @@ class PolyLineEntityItem : public EntityItem {
|
|||
QVector<glm::vec3> _vertices;
|
||||
QVector<glm::vec3> _normals;
|
||||
QVector<float> _strokeWidths;
|
||||
QString _textures;
|
||||
bool _texturesChangedFlag { false };
|
||||
mutable QReadWriteLock _quadReadWriteLock;
|
||||
};
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket,
|
|||
NetworkPeer(uuid, publicSocket, localSocket, parent),
|
||||
_type(type),
|
||||
_connectionSecret(connectionSecret),
|
||||
_linkedData(NULL),
|
||||
_isAlive(true),
|
||||
_pingMs(-1), // "Uninitialized"
|
||||
_clockSkewUsec(0),
|
||||
|
@ -61,10 +60,6 @@ Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket,
|
|||
setType(_type);
|
||||
}
|
||||
|
||||
Node::~Node() {
|
||||
delete _linkedData;
|
||||
}
|
||||
|
||||
void Node::setType(char type) {
|
||||
_type = type;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#ifndef hifi_Node_h
|
||||
#define hifi_Node_h
|
||||
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -34,7 +35,6 @@ public:
|
|||
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
|
||||
bool canAdjustLocks, bool canRez, const QUuid& connectionSecret = QUuid(),
|
||||
QObject* parent = 0);
|
||||
~Node();
|
||||
|
||||
bool operator==(const Node& otherNode) const { return _uuid == otherNode._uuid; }
|
||||
bool operator!=(const Node& otherNode) const { return !(*this == otherNode); }
|
||||
|
@ -45,8 +45,8 @@ public:
|
|||
const QUuid& getConnectionSecret() const { return _connectionSecret; }
|
||||
void setConnectionSecret(const QUuid& connectionSecret) { _connectionSecret = connectionSecret; }
|
||||
|
||||
NodeData* getLinkedData() const { return _linkedData; }
|
||||
void setLinkedData(NodeData* linkedData) { _linkedData = linkedData; }
|
||||
NodeData* getLinkedData() const { return _linkedData.get(); }
|
||||
void setLinkedData(std::unique_ptr<NodeData> linkedData) { _linkedData = std::move(linkedData); }
|
||||
|
||||
bool isAlive() const { return _isAlive; }
|
||||
void setAlive(bool isAlive) { _isAlive = isAlive; }
|
||||
|
@ -75,7 +75,7 @@ private:
|
|||
NodeType_t _type;
|
||||
|
||||
QUuid _connectionSecret;
|
||||
NodeData* _linkedData;
|
||||
std::unique_ptr<NodeData> _linkedData;
|
||||
bool _isAlive;
|
||||
int _pingMs;
|
||||
int _clockSkewUsec;
|
||||
|
|
|
@ -41,7 +41,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::EntityAdd:
|
||||
case PacketType::EntityEdit:
|
||||
case PacketType::EntityData:
|
||||
return VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING;
|
||||
return VERSION_ENTITIES_POLYLINE_TEXTURE;
|
||||
case PacketType::AvatarData:
|
||||
case PacketType::BulkAvatarData:
|
||||
default:
|
||||
|
|
|
@ -159,5 +159,6 @@ const PacketVersion VERSION_ENTITIES_ANIMATION_PROPERTIES_GROUP = 46;
|
|||
const PacketVersion VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP = 47;
|
||||
const PacketVersion VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP_BIS = 48;
|
||||
const PacketVersion VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING = 49;
|
||||
const PacketVersion VERSION_ENTITIES_POLYLINE_TEXTURE = 50;
|
||||
|
||||
#endif // hifi_PacketHeaders_h
|
||||
|
|
Loading…
Reference in a new issue