mirror of
https://github.com/lubosz/overte.git
synced 2025-04-26 22:15:53 +02:00
Merge remote-tracking branch 'upstream/master' into 19554-2
This commit is contained in:
commit
c65d5f08ca
93 changed files with 4986 additions and 1103 deletions
animation-server/src
assignment-client/src
domain-server/src
examples
audioReflectorTools.jsclap.jsdancing_bot.jsdrumStick.jseditVoxels.jsplaySound.jsspaceInvadersExample.jstestingVoxelViewerRestart.jstoyball.jsvoxelDrumming.js
interface
resources/icons
src
Application.cppApplication.hAudio.cppAudio.hAudioReflector.cppAudioReflector.hCamera.cppDatagramProcessor.cppMenu.cppMenu.hModelUploader.cppModelUploader.hScriptHighlighting.cppScriptHighlighting.hUtil.cpp
avatar
devices
renderer
scripting
ui
ScriptEditorWidget.cppScriptEditorWidget.hScriptEditorWindow.cppScriptEditorWindow.hStats.cpp
overlays
voxels
ui
libraries
audio/src
avatars/src
fbx/src
networking/src
octree/src
Octree.cppOctree.hOctreeEditPacketSender.cppOctreeElement.cppOctreeElementBag.cppOctreeElementBag.hOctreeHeadlessViewer.cppOctreePacketData.cppOctreeProjectedPolygon.cppPlane.cppViewFrustum.cpp
particles/src
script-engine/src
voxels/src
voxel-edit/src
|
@ -171,7 +171,7 @@ static void renderMovingBug() {
|
|||
}
|
||||
} else {
|
||||
|
||||
//printf("bugPathCenter=(%f,%f,%f)\n", bugPathCenter.x, bugPathCenter.y, bugPathCenter.z);
|
||||
//qDebug("bugPathCenter=(%f,%f,%f)", bugPathCenter.x, bugPathCenter.y, bugPathCenter.z);
|
||||
|
||||
bugPathTheta += bugAngleDelta; // move slightly
|
||||
bugRotation -= bugAngleDelta; // rotate slightly
|
||||
|
@ -187,12 +187,12 @@ static void renderMovingBug() {
|
|||
float y = bugPathCenter.y;
|
||||
|
||||
bugPosition = glm::vec3(x, y, z);
|
||||
//printf("bugPathTheta=%f\n", bugPathTheta);
|
||||
//printf("bugRotation=%f\n", bugRotation);
|
||||
//qDebug("bugPathTheta=%f", bugPathTheta);
|
||||
//qDebug("bugRotation=%f", bugRotation);
|
||||
}
|
||||
|
||||
//printf("bugPosition=(%f,%f,%f)\n", bugPosition.x, bugPosition.y, bugPosition.z);
|
||||
//printf("bugDirection=(%f,%f,%f)\n", bugDirection.x, bugDirection.y, bugDirection.z);
|
||||
//qDebug("bugPosition=(%f,%f,%f)", bugPosition.x, bugPosition.y, bugPosition.z);
|
||||
//qDebug("bugDirection=(%f,%f,%f)", bugDirection.x, bugDirection.y, bugDirection.z);
|
||||
// would be nice to add some randomness here...
|
||||
|
||||
// Generate voxels for where bug is going to
|
||||
|
@ -690,32 +690,32 @@ AnimationServer::AnimationServer(int &argc, char **argv) :
|
|||
// Handle Local Domain testing with the --local command line
|
||||
const char* NON_THREADED_PACKETSENDER = "--NonThreadedPacketSender";
|
||||
::nonThreadedPacketSender = cmdOptionExists(argc, (const char**) argv, NON_THREADED_PACKETSENDER);
|
||||
printf("nonThreadedPacketSender=%s\n", debug::valueOf(::nonThreadedPacketSender));
|
||||
qDebug("nonThreadedPacketSender=%s", debug::valueOf(::nonThreadedPacketSender));
|
||||
|
||||
// Handle Local Domain testing with the --local command line
|
||||
const char* NO_BILLBOARD = "--NoBillboard";
|
||||
::includeBillboard = !cmdOptionExists(argc, (const char**) argv, NO_BILLBOARD);
|
||||
printf("includeBillboard=%s\n", debug::valueOf(::includeBillboard));
|
||||
qDebug("includeBillboard=%s", debug::valueOf(::includeBillboard));
|
||||
|
||||
const char* NO_BORDER_TRACER = "--NoBorderTracer";
|
||||
::includeBorderTracer = !cmdOptionExists(argc, (const char**) argv, NO_BORDER_TRACER);
|
||||
printf("includeBorderTracer=%s\n", debug::valueOf(::includeBorderTracer));
|
||||
qDebug("includeBorderTracer=%s", debug::valueOf(::includeBorderTracer));
|
||||
|
||||
const char* NO_MOVING_BUG = "--NoMovingBug";
|
||||
::includeMovingBug = !cmdOptionExists(argc, (const char**) argv, NO_MOVING_BUG);
|
||||
printf("includeMovingBug=%s\n", debug::valueOf(::includeMovingBug));
|
||||
qDebug("includeMovingBug=%s", debug::valueOf(::includeMovingBug));
|
||||
|
||||
const char* INCLUDE_BLINKING_VOXEL = "--includeBlinkingVoxel";
|
||||
::includeBlinkingVoxel = cmdOptionExists(argc, (const char**) argv, INCLUDE_BLINKING_VOXEL);
|
||||
printf("includeBlinkingVoxel=%s\n", debug::valueOf(::includeBlinkingVoxel));
|
||||
qDebug("includeBlinkingVoxel=%s", debug::valueOf(::includeBlinkingVoxel));
|
||||
|
||||
const char* NO_DANCE_FLOOR = "--NoDanceFloor";
|
||||
::includeDanceFloor = !cmdOptionExists(argc, (const char**) argv, NO_DANCE_FLOOR);
|
||||
printf("includeDanceFloor=%s\n", debug::valueOf(::includeDanceFloor));
|
||||
qDebug("includeDanceFloor=%s", debug::valueOf(::includeDanceFloor));
|
||||
|
||||
const char* BUILD_STREET = "--BuildStreet";
|
||||
::buildStreet = cmdOptionExists(argc, (const char**) argv, BUILD_STREET);
|
||||
printf("buildStreet=%s\n", debug::valueOf(::buildStreet));
|
||||
qDebug("buildStreet=%s", debug::valueOf(::buildStreet));
|
||||
|
||||
// Handle Local Domain testing with the --local command line
|
||||
const char* showPPS = "--showPPS";
|
||||
|
@ -725,7 +725,7 @@ AnimationServer::AnimationServer(int &argc, char **argv) :
|
|||
const char* local = "--local";
|
||||
::wantLocalDomain = cmdOptionExists(argc, (const char**) argv,local);
|
||||
if (::wantLocalDomain) {
|
||||
printf("Local Domain MODE!\n");
|
||||
qDebug("Local Domain MODE!");
|
||||
nodeList->getDomainHandler().setIPToLocalhost();
|
||||
}
|
||||
|
||||
|
@ -738,7 +738,7 @@ AnimationServer::AnimationServer(int &argc, char **argv) :
|
|||
if (packetsPerSecondCommand) {
|
||||
::packetsPerSecond = atoi(packetsPerSecondCommand);
|
||||
}
|
||||
printf("packetsPerSecond=%d\n",packetsPerSecond);
|
||||
qDebug("packetsPerSecond=%d",packetsPerSecond);
|
||||
|
||||
const char* animateFPSCommand = getCmdOption(argc, (const char**) argv, "--AnimateFPS");
|
||||
const char* animateIntervalCommand = getCmdOption(argc, (const char**) argv, "--AnimateInterval");
|
||||
|
@ -753,8 +753,8 @@ AnimationServer::AnimationServer(int &argc, char **argv) :
|
|||
::ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000.0); // converts from milliseconds to usecs
|
||||
}
|
||||
}
|
||||
printf("ANIMATE_FPS=%d\n",ANIMATE_FPS);
|
||||
printf("ANIMATE_VOXELS_INTERVAL_USECS=%llu\n",ANIMATE_VOXELS_INTERVAL_USECS);
|
||||
qDebug("ANIMATE_FPS=%d",ANIMATE_FPS);
|
||||
qDebug("ANIMATE_VOXELS_INTERVAL_USECS=%llu",ANIMATE_VOXELS_INTERVAL_USECS);
|
||||
|
||||
const char* processingFPSCommand = getCmdOption(argc, (const char**) argv, "--ProcessingFPS");
|
||||
const char* processingIntervalCommand = getCmdOption(argc, (const char**) argv, "--ProcessingInterval");
|
||||
|
@ -769,8 +769,8 @@ AnimationServer::AnimationServer(int &argc, char **argv) :
|
|||
::PROCESSING_INTERVAL_USECS = (PROCESSING_FPS_IN_MILLISECONDS * 1000.0) - FUDGE_USECS; // converts from milliseconds to usecs
|
||||
}
|
||||
}
|
||||
printf("PROCESSING_FPS=%d\n",PROCESSING_FPS);
|
||||
printf("PROCESSING_INTERVAL_USECS=%llu\n",PROCESSING_INTERVAL_USECS);
|
||||
qDebug("PROCESSING_FPS=%d",PROCESSING_FPS);
|
||||
qDebug("PROCESSING_INTERVAL_USECS=%llu",PROCESSING_INTERVAL_USECS);
|
||||
|
||||
nodeList->linkedDataCreateCallback = NULL; // do we need a callback?
|
||||
|
||||
|
|
|
@ -33,7 +33,8 @@ Agent::Agent(const QByteArray& packet) :
|
|||
ThreadedAssignment(packet),
|
||||
_voxelEditSender(),
|
||||
_particleEditSender(),
|
||||
_receivedAudioBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO)
|
||||
_receivedAudioBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO),
|
||||
_avatarHashMap()
|
||||
{
|
||||
// be the parent of the script engine so it gets moved when we do
|
||||
_scriptEngine.setParent(this);
|
||||
|
@ -131,6 +132,16 @@ void Agent::readPendingDatagrams() {
|
|||
// let this continue through to the NodeList so it updates last heard timestamp
|
||||
// for the sending audio mixer
|
||||
NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket);
|
||||
} else if (datagramPacketType == PacketTypeBulkAvatarData
|
||||
|| datagramPacketType == PacketTypeAvatarIdentity
|
||||
|| datagramPacketType == PacketTypeAvatarBillboard
|
||||
|| datagramPacketType == PacketTypeKillAvatar) {
|
||||
// let the avatar hash map process it
|
||||
_avatarHashMap.processAvatarMixerDatagram(receivedPacket, nodeList->sendingNodeForPacket(receivedPacket));
|
||||
|
||||
// let this continue through to the NodeList so it updates last heard timestamp
|
||||
// for the sending avatar-mixer
|
||||
NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket);
|
||||
} else {
|
||||
NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket);
|
||||
}
|
||||
|
@ -191,6 +202,7 @@ void Agent::run() {
|
|||
|
||||
// give this AvatarData object to the script engine
|
||||
_scriptEngine.setAvatarData(&scriptedAvatar, "Avatar");
|
||||
_scriptEngine.setAvatarHashMap(&_avatarHashMap, "AvatarList");
|
||||
|
||||
// register ourselves to the script engine
|
||||
_scriptEngine.registerGlobalObject("Agent", this);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <QtCore/QObject>
|
||||
#include <QtCore/QUrl>
|
||||
|
||||
#include <AvatarHashMap.h>
|
||||
#include <MixedAudioRingBuffer.h>
|
||||
#include <ParticleEditPacketSender.h>
|
||||
#include <ParticleTree.h>
|
||||
|
@ -65,6 +66,7 @@ private:
|
|||
VoxelTreeHeadlessViewer _voxelViewer;
|
||||
|
||||
MixedAudioRingBuffer _receivedAudioBuffer;
|
||||
AvatarHashMap _avatarHashMap;
|
||||
};
|
||||
|
||||
#endif // hifi_Agent_h
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <PacketHeaders.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
|
||||
#include "AssignmentFactory.h"
|
||||
#include "AssignmentThread.h"
|
||||
|
||||
|
@ -30,11 +31,12 @@
|
|||
const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client";
|
||||
const long long ASSIGNMENT_REQUEST_INTERVAL_MSECS = 1 * 1000;
|
||||
|
||||
SharedAssignmentPointer AssignmentClient::_currentAssignment;
|
||||
|
||||
int hifiSockAddrMeta = qRegisterMetaType<HifiSockAddr>("HifiSockAddr");
|
||||
|
||||
AssignmentClient::AssignmentClient(int &argc, char **argv) :
|
||||
QCoreApplication(argc, argv),
|
||||
_currentAssignment(),
|
||||
_assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME)
|
||||
{
|
||||
DTLSClientSession::globalInit();
|
||||
|
|
|
@ -20,15 +20,17 @@ class AssignmentClient : public QCoreApplication {
|
|||
Q_OBJECT
|
||||
public:
|
||||
AssignmentClient(int &argc, char **argv);
|
||||
static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; }
|
||||
~AssignmentClient();
|
||||
private slots:
|
||||
void sendAssignmentRequest();
|
||||
void readPendingDatagrams();
|
||||
void assignmentCompleted();
|
||||
void handleAuthenticationRequest();
|
||||
|
||||
private:
|
||||
Assignment _requestAssignment;
|
||||
SharedAssignmentPointer _currentAssignment;
|
||||
static SharedAssignmentPointer _currentAssignment;
|
||||
QString _assignmentServerHostname;
|
||||
};
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin
|
|||
bool debugProcessPacket = _myServer->wantsVerboseDebug();
|
||||
|
||||
if (debugProcessPacket) {
|
||||
printf("OctreeInboundPacketProcessor::processPacket() packetData=%p packetLength=%d\n", &packet, packet.size());
|
||||
qDebug("OctreeInboundPacketProcessor::processPacket() packetData=%p packetLength=%d", &packet, packet.size());
|
||||
}
|
||||
|
||||
int numBytesPacketHeader = numBytesForPacketHeader(packet);
|
||||
|
@ -78,8 +78,8 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin
|
|||
int maxSize = packet.size() - atByte;
|
||||
|
||||
if (debugProcessPacket) {
|
||||
printf("OctreeInboundPacketProcessor::processPacket() %c "
|
||||
"packetData=%p packetLength=%d voxelData=%p atByte=%d maxSize=%d\n",
|
||||
qDebug("OctreeInboundPacketProcessor::processPacket() %c "
|
||||
"packetData=%p packetLength=%d voxelData=%p atByte=%d maxSize=%d",
|
||||
packetType, packetData, packet.size(), editData, atByte, maxSize);
|
||||
}
|
||||
|
||||
|
@ -105,8 +105,8 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin
|
|||
}
|
||||
|
||||
if (debugProcessPacket) {
|
||||
printf("OctreeInboundPacketProcessor::processPacket() DONE LOOPING FOR %c "
|
||||
"packetData=%p packetLength=%d voxelData=%p atByte=%d\n",
|
||||
qDebug("OctreeInboundPacketProcessor::processPacket() DONE LOOPING FOR %c "
|
||||
"packetData=%p packetLength=%d voxelData=%p atByte=%d",
|
||||
packetType, packetData, packet.size(), editData, atByte);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,41 +47,54 @@ OctreeQueryNode::OctreeQueryNode() :
|
|||
|
||||
OctreeQueryNode::~OctreeQueryNode() {
|
||||
_isShuttingDown = true;
|
||||
const bool extraDebugging = false;
|
||||
if (extraDebugging) {
|
||||
qDebug() << "OctreeQueryNode::~OctreeQueryNode()";
|
||||
}
|
||||
if (_octreeSendThread) {
|
||||
if (extraDebugging) {
|
||||
qDebug() << "OctreeQueryNode::~OctreeQueryNode()... calling _octreeSendThread->terminate()";
|
||||
}
|
||||
_octreeSendThread->terminate();
|
||||
if (extraDebugging) {
|
||||
qDebug() << "OctreeQueryNode::~OctreeQueryNode()... calling delete _octreeSendThread";
|
||||
}
|
||||
delete _octreeSendThread;
|
||||
forceNodeShutdown();
|
||||
}
|
||||
|
||||
|
||||
delete[] _octreePacket;
|
||||
delete[] _lastOctreePacket;
|
||||
if (extraDebugging) {
|
||||
qDebug() << "OctreeQueryNode::~OctreeQueryNode()... DONE...";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OctreeQueryNode::deleteLater() {
|
||||
void OctreeQueryNode::nodeKilled() {
|
||||
_isShuttingDown = true;
|
||||
nodeBag.unhookNotifications(); // if our node is shutting down, then we no longer need octree element notifications
|
||||
if (_octreeSendThread) {
|
||||
// just tell our thread we want to shutdown, this is asynchronous, and fast, we don't need or want it to block
|
||||
// while the thread actually shuts down
|
||||
_octreeSendThread->setIsShuttingDown();
|
||||
}
|
||||
OctreeQuery::deleteLater();
|
||||
}
|
||||
|
||||
void OctreeQueryNode::forceNodeShutdown() {
|
||||
_isShuttingDown = true;
|
||||
nodeBag.unhookNotifications(); // if our node is shutting down, then we no longer need octree element notifications
|
||||
if (_octreeSendThread) {
|
||||
// we really need to force our thread to shutdown, this is synchronous, we will block while the thread actually
|
||||
// shuts down because we really need it to shutdown, and it's ok if we wait for it to complete
|
||||
OctreeSendThread* sendThread = _octreeSendThread;
|
||||
_octreeSendThread = NULL;
|
||||
sendThread->setIsShuttingDown();
|
||||
sendThread->terminate();
|
||||
delete sendThread;
|
||||
}
|
||||
}
|
||||
|
||||
void OctreeQueryNode::initializeOctreeSendThread(OctreeServer* octreeServer, SharedNodePointer node) {
|
||||
// Create octree sending thread...
|
||||
_octreeSendThread = new OctreeSendThread(octreeServer, node);
|
||||
void OctreeQueryNode::sendThreadFinished() {
|
||||
// We've been notified by our thread that it is shutting down. So we can clean up our reference to it, and
|
||||
// delete the actual thread object. Cleaning up our thread will correctly unroll all refereces to shared
|
||||
// pointers to our node as well as the octree server assignment
|
||||
if (_octreeSendThread) {
|
||||
OctreeSendThread* sendThread = _octreeSendThread;
|
||||
_octreeSendThread = NULL;
|
||||
delete sendThread;
|
||||
}
|
||||
}
|
||||
|
||||
void OctreeQueryNode::initializeOctreeSendThread(const SharedAssignmentPointer& myAssignment, const SharedNodePointer& node) {
|
||||
_octreeSendThread = new OctreeSendThread(myAssignment, node);
|
||||
|
||||
// we want to be notified when the thread finishes
|
||||
connect(_octreeSendThread, &GenericThread::finished, this, &OctreeQueryNode::sendThreadFinished);
|
||||
_octreeSendThread->initialize(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,25 +13,25 @@
|
|||
#define hifi_OctreeQueryNode_h
|
||||
|
||||
#include <iostream>
|
||||
#include <NodeData.h>
|
||||
#include <OctreePacketData.h>
|
||||
#include <OctreeQuery.h>
|
||||
|
||||
|
||||
#include <CoverageMap.h>
|
||||
#include <NodeData.h>
|
||||
#include <OctreeConstants.h>
|
||||
#include <OctreeElementBag.h>
|
||||
#include <OctreePacketData.h>
|
||||
#include <OctreeQuery.h>
|
||||
#include <OctreeSceneStats.h>
|
||||
#include <ThreadedAssignment.h> // for SharedAssignmentPointer
|
||||
|
||||
class OctreeSendThread;
|
||||
class OctreeServer;
|
||||
|
||||
class OctreeQueryNode : public OctreeQuery {
|
||||
Q_OBJECT
|
||||
public:
|
||||
OctreeQueryNode();
|
||||
virtual ~OctreeQueryNode();
|
||||
virtual void deleteLater();
|
||||
|
||||
|
||||
void init(); // called after creation to set up some virtual items
|
||||
virtual PacketType getMyPacketType() const = 0;
|
||||
|
||||
|
@ -86,7 +86,7 @@ public:
|
|||
|
||||
OctreeSceneStats stats;
|
||||
|
||||
void initializeOctreeSendThread(OctreeServer* octreeServer, SharedNodePointer node);
|
||||
void initializeOctreeSendThread(const SharedAssignmentPointer& myAssignment, const SharedNodePointer& node);
|
||||
bool isOctreeSendThreadInitalized() { return _octreeSendThread; }
|
||||
|
||||
void dumpOutOfView();
|
||||
|
@ -96,8 +96,13 @@ public:
|
|||
unsigned int getlastOctreePacketLength() const { return _lastOctreePacketLength; }
|
||||
int getDuplicatePacketCount() const { return _duplicatePacketCount; }
|
||||
|
||||
void nodeKilled();
|
||||
void forceNodeShutdown();
|
||||
bool isShuttingDown() const { return _isShuttingDown; }
|
||||
|
||||
private slots:
|
||||
void sendThreadFinished();
|
||||
|
||||
private:
|
||||
OctreeQueryNode(const OctreeQueryNode &);
|
||||
OctreeQueryNode& operator= (const OctreeQueryNode&);
|
||||
|
|
|
@ -23,12 +23,13 @@
|
|||
quint64 startSceneSleepTime = 0;
|
||||
quint64 endSceneSleepTime = 0;
|
||||
|
||||
OctreeSendThread::OctreeSendThread(OctreeServer* myServer, SharedNodePointer node) :
|
||||
_myServer(myServer),
|
||||
OctreeSendThread::OctreeSendThread(const SharedAssignmentPointer& myAssignment, const SharedNodePointer& node) :
|
||||
_myAssignment(myAssignment),
|
||||
_myServer(static_cast<OctreeServer*>(myAssignment.data())),
|
||||
_node(node),
|
||||
_nodeUUID(node->getUUID()),
|
||||
_packetData(),
|
||||
_nodeMissingCount(0),
|
||||
_processLock(),
|
||||
_isShuttingDown(false)
|
||||
{
|
||||
QString safeServerName("Octree");
|
||||
|
@ -41,22 +42,24 @@ OctreeSendThread::OctreeSendThread(OctreeServer* myServer, SharedNodePointer nod
|
|||
OctreeServer::clientConnected();
|
||||
}
|
||||
|
||||
OctreeSendThread::~OctreeSendThread() {
|
||||
OctreeSendThread::~OctreeSendThread() {
|
||||
QString safeServerName("Octree");
|
||||
if (_myServer) {
|
||||
safeServerName = _myServer->getMyServerName();
|
||||
}
|
||||
|
||||
qDebug() << qPrintable(safeServerName) << "server [" << _myServer << "]: client disconnected "
|
||||
"- ending sending thread [" << this << "]";
|
||||
|
||||
OctreeServer::clientDisconnected();
|
||||
OctreeServer::stopTrackingThread(this);
|
||||
|
||||
_node.clear();
|
||||
_myAssignment.clear();
|
||||
}
|
||||
|
||||
void OctreeSendThread::setIsShuttingDown() {
|
||||
_isShuttingDown = true;
|
||||
OctreeServer::stopTrackingThread(this);
|
||||
|
||||
// this will cause us to wait till the process loop is complete, we do this after we change _isShuttingDown
|
||||
QMutexLocker locker(&_processLock);
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,47 +68,29 @@ bool OctreeSendThread::process() {
|
|||
return false; // exit early if we're shutting down
|
||||
}
|
||||
|
||||
// check that our server and assignment is still valid
|
||||
if (!_myServer || !_myAssignment) {
|
||||
return false; // exit early if it's not, it means the server is shutting down
|
||||
}
|
||||
|
||||
OctreeServer::didProcess(this);
|
||||
|
||||
float lockWaitElapsedUsec = OctreeServer::SKIP_TIME;
|
||||
quint64 lockWaitStart = usecTimestampNow();
|
||||
_processLock.lock();
|
||||
quint64 lockWaitEnd = usecTimestampNow();
|
||||
lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart);
|
||||
OctreeServer::trackProcessWaitTime(lockWaitElapsedUsec);
|
||||
|
||||
quint64 start = usecTimestampNow();
|
||||
|
||||
// don't do any send processing until the initial load of the octree is complete...
|
||||
if (_myServer->isInitialLoadComplete()) {
|
||||
SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(_nodeUUID, false);
|
||||
if (node) {
|
||||
if (_node) {
|
||||
_nodeMissingCount = 0;
|
||||
OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(node->getLinkedData());
|
||||
OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(_node->getLinkedData());
|
||||
|
||||
// Sometimes the node data has not yet been linked, in which case we can't really do anything
|
||||
if (nodeData && !nodeData->isShuttingDown()) {
|
||||
bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
|
||||
packetDistributor(node, nodeData, viewFrustumChanged);
|
||||
}
|
||||
} else {
|
||||
_nodeMissingCount++;
|
||||
const int MANY_FAILED_LOCKS = 1;
|
||||
if (_nodeMissingCount >= MANY_FAILED_LOCKS) {
|
||||
|
||||
QString safeServerName("Octree");
|
||||
if (_myServer) {
|
||||
safeServerName = _myServer->getMyServerName();
|
||||
}
|
||||
|
||||
qDebug() << qPrintable(safeServerName) << "server: sending thread [" << this << "]"
|
||||
<< "failed to get nodeWithUUID() " << _nodeUUID <<". Failed:" << _nodeMissingCount << "times";
|
||||
packetDistributor(nodeData, viewFrustumChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_processLock.unlock();
|
||||
|
||||
if (_isShuttingDown) {
|
||||
return false; // exit early if we're shutting down
|
||||
}
|
||||
|
@ -135,8 +120,7 @@ quint64 OctreeSendThread::_totalBytes = 0;
|
|||
quint64 OctreeSendThread::_totalWastedBytes = 0;
|
||||
quint64 OctreeSendThread::_totalPackets = 0;
|
||||
|
||||
int OctreeSendThread::handlePacketSend(const SharedNodePointer& node,
|
||||
OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent) {
|
||||
int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent) {
|
||||
|
||||
OctreeServer::didHandlePacketSend(this);
|
||||
|
||||
|
@ -196,12 +180,12 @@ int OctreeSendThread::handlePacketSend(const SharedNodePointer& node,
|
|||
|
||||
// actually send it
|
||||
OctreeServer::didCallWriteDatagram(this);
|
||||
NodeList::getInstance()->writeDatagram((char*) statsMessage, statsMessageLength, SharedNodePointer(node));
|
||||
NodeList::getInstance()->writeDatagram((char*) statsMessage, statsMessageLength, _node);
|
||||
packetSent = true;
|
||||
} else {
|
||||
// not enough room in the packet, send two packets
|
||||
OctreeServer::didCallWriteDatagram(this);
|
||||
NodeList::getInstance()->writeDatagram((char*) statsMessage, statsMessageLength, SharedNodePointer(node));
|
||||
NodeList::getInstance()->writeDatagram((char*) statsMessage, statsMessageLength, _node);
|
||||
|
||||
// since a stats message is only included on end of scene, don't consider any of these bytes "wasted", since
|
||||
// there was nothing else to send.
|
||||
|
@ -220,8 +204,7 @@ int OctreeSendThread::handlePacketSend(const SharedNodePointer& node,
|
|||
packetsSent++;
|
||||
|
||||
OctreeServer::didCallWriteDatagram(this);
|
||||
NodeList::getInstance()->writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(),
|
||||
SharedNodePointer(node));
|
||||
NodeList::getInstance()->writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), _node);
|
||||
|
||||
packetSent = true;
|
||||
|
||||
|
@ -241,8 +224,7 @@ int OctreeSendThread::handlePacketSend(const SharedNodePointer& node,
|
|||
if (nodeData->isPacketWaiting() && !nodeData->isShuttingDown()) {
|
||||
// just send the voxel packet
|
||||
OctreeServer::didCallWriteDatagram(this);
|
||||
NodeList::getInstance()->writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(),
|
||||
SharedNodePointer(node));
|
||||
NodeList::getInstance()->writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), _node);
|
||||
packetSent = true;
|
||||
|
||||
int thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength();
|
||||
|
@ -269,7 +251,8 @@ int OctreeSendThread::handlePacketSend(const SharedNodePointer& node,
|
|||
}
|
||||
|
||||
/// Version of voxel distributor that sends the deepest LOD level at once
|
||||
int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQueryNode* nodeData, bool viewFrustumChanged) {
|
||||
int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrustumChanged) {
|
||||
|
||||
OctreeServer::didPacketDistributor(this);
|
||||
|
||||
// if shutting down, exit early
|
||||
|
@ -299,7 +282,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue
|
|||
// then let's just send that waiting packet.
|
||||
if (!nodeData->getCurrentPacketFormatMatches()) {
|
||||
if (nodeData->isPacketWaiting()) {
|
||||
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
packetsSentThisInterval += handlePacketSend(nodeData, trueBytesSent, truePacketsSent);
|
||||
} else {
|
||||
nodeData->resetOctreePacket();
|
||||
}
|
||||
|
@ -340,7 +323,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue
|
|||
//unsigned long encodeTime = nodeData->stats.getTotalEncodeTime();
|
||||
//unsigned long elapsedTime = nodeData->stats.getElapsedTime();
|
||||
|
||||
int packetsJustSent = handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
int packetsJustSent = handlePacketSend(nodeData, trueBytesSent, truePacketsSent);
|
||||
packetsSentThisInterval += packetsJustSent;
|
||||
|
||||
// If we're starting a full scene, then definitely we want to empty the nodeBag
|
||||
|
@ -491,7 +474,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue
|
|||
|
||||
|
||||
if (writtenSize > nodeData->getAvailable()) {
|
||||
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
packetsSentThisInterval += handlePacketSend(nodeData, trueBytesSent, truePacketsSent);
|
||||
}
|
||||
|
||||
nodeData->writeToPacket(_packetData.getFinalizedData(), _packetData.getFinalizedSize());
|
||||
|
@ -513,7 +496,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue
|
|||
int targetSize = MAX_OCTREE_PACKET_DATA_SIZE;
|
||||
if (sendNow) {
|
||||
quint64 packetSendingStart = usecTimestampNow();
|
||||
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
packetsSentThisInterval += handlePacketSend(nodeData, trueBytesSent, truePacketsSent);
|
||||
quint64 packetSendingEnd = usecTimestampNow();
|
||||
packetSendingElapsedUsec = (float)(packetSendingEnd - packetSendingStart);
|
||||
|
||||
|
@ -546,8 +529,8 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue
|
|||
// Here's where we can/should allow the server to send other data...
|
||||
// send the environment packet
|
||||
// TODO: should we turn this into a while loop to better handle sending multiple special packets
|
||||
if (_myServer->hasSpecialPacketToSend(node) && !nodeData->isShuttingDown()) {
|
||||
trueBytesSent += _myServer->sendSpecialPacket(node);
|
||||
if (_myServer->hasSpecialPacketToSend(_node) && !nodeData->isShuttingDown()) {
|
||||
trueBytesSent += _myServer->sendSpecialPacket(_node);
|
||||
truePacketsSent++;
|
||||
packetsSentThisInterval++;
|
||||
}
|
||||
|
|
|
@ -17,15 +17,16 @@
|
|||
#include <GenericThread.h>
|
||||
#include <NetworkPacket.h>
|
||||
#include <OctreeElementBag.h>
|
||||
#include "OctreeQueryNode.h"
|
||||
#include "OctreeServer.h"
|
||||
|
||||
#include "OctreeQueryNode.h"
|
||||
|
||||
class OctreeServer;
|
||||
|
||||
/// Threaded processor for sending voxel packets to a single client
|
||||
class OctreeSendThread : public GenericThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
OctreeSendThread(OctreeServer* myServer, SharedNodePointer node);
|
||||
OctreeSendThread(const SharedAssignmentPointer& myAssignment, const SharedNodePointer& node);
|
||||
virtual ~OctreeSendThread();
|
||||
|
||||
void setIsShuttingDown();
|
||||
|
@ -42,16 +43,17 @@ protected:
|
|||
virtual bool process();
|
||||
|
||||
private:
|
||||
SharedAssignmentPointer _myAssignment;
|
||||
OctreeServer* _myServer;
|
||||
SharedNodePointer _node;
|
||||
QUuid _nodeUUID;
|
||||
|
||||
int handlePacketSend(const SharedNodePointer& node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent);
|
||||
int packetDistributor(const SharedNodePointer& node, OctreeQueryNode* nodeData, bool viewFrustumChanged);
|
||||
int handlePacketSend(OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent);
|
||||
int packetDistributor(OctreeQueryNode* nodeData, bool viewFrustumChanged);
|
||||
|
||||
OctreePacketData _packetData;
|
||||
|
||||
int _nodeMissingCount;
|
||||
QMutex _processLock; // don't allow us to have our nodeData, or our thread to be deleted while we're processing
|
||||
bool _isShuttingDown;
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <Logging.h>
|
||||
#include <UUID.h>
|
||||
|
||||
#include "../AssignmentClient.h"
|
||||
|
||||
#include "OctreeServer.h"
|
||||
#include "OctreeServerConsts.h"
|
||||
|
||||
|
@ -206,7 +208,7 @@ void OctreeServer::trackProcessWaitTime(float time) {
|
|||
}
|
||||
|
||||
void OctreeServer::attachQueryNodeToNode(Node* newNode) {
|
||||
if (!newNode->getLinkedData()) {
|
||||
if (!newNode->getLinkedData() && _instance) {
|
||||
OctreeQueryNode* newQueryNodeData = _instance->createOctreeQueryNode();
|
||||
newQueryNodeData->init();
|
||||
newNode->setLinkedData(newQueryNodeData);
|
||||
|
@ -234,7 +236,13 @@ OctreeServer::OctreeServer(const QByteArray& packet) :
|
|||
_started(time(0)),
|
||||
_startedUSecs(usecTimestampNow())
|
||||
{
|
||||
if (_instance) {
|
||||
qDebug() << "Octree Server starting... while old instance still running _instance=["<<_instance<<"] this=[" << this << "]";
|
||||
}
|
||||
|
||||
qDebug() << "Octree Server starting... setting _instance to=[" << this << "]";
|
||||
_instance = this;
|
||||
|
||||
_averageLoopTime.updateAverage(0);
|
||||
qDebug() << "Octree server starting... [" << this << "]";
|
||||
}
|
||||
|
@ -265,6 +273,16 @@ OctreeServer::~OctreeServer() {
|
|||
|
||||
delete _jurisdiction;
|
||||
_jurisdiction = NULL;
|
||||
|
||||
// cleanup our tree here...
|
||||
qDebug() << qPrintable(_safeServerName) << "server START cleaning up octree... [" << this << "]";
|
||||
delete _tree;
|
||||
_tree = NULL;
|
||||
qDebug() << qPrintable(_safeServerName) << "server DONE cleaning up octree... [" << this << "]";
|
||||
|
||||
if (_instance == this) {
|
||||
_instance = NULL; // we are gone
|
||||
}
|
||||
qDebug() << qPrintable(_safeServerName) << "server DONE shutting down... [" << this << "]";
|
||||
}
|
||||
|
||||
|
@ -812,33 +830,22 @@ void OctreeServer::readPendingDatagrams() {
|
|||
while (readAvailableDatagram(receivedPacket, senderSockAddr)) {
|
||||
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
|
||||
PacketType packetType = packetTypeForPacket(receivedPacket);
|
||||
|
||||
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket);
|
||||
|
||||
if (packetType == getMyQueryMessageType()) {
|
||||
bool debug = false;
|
||||
if (debug) {
|
||||
if (matchingNode) {
|
||||
qDebug() << "Got PacketTypeVoxelQuery at" << usecTimestampNow() << "node:" << *matchingNode;
|
||||
} else {
|
||||
qDebug() << "Got PacketTypeVoxelQuery at" << usecTimestampNow() << "node: ??????";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If we got a PacketType_VOXEL_QUERY, then we're talking to an NodeType_t_AVATAR, and we
|
||||
// need to make sure we have it in our nodeList.
|
||||
if (matchingNode) {
|
||||
if (debug) {
|
||||
qDebug() << "calling updateNodeWithDataFromPacket()... node:" << *matchingNode;
|
||||
}
|
||||
nodeList->updateNodeWithDataFromPacket(matchingNode, receivedPacket);
|
||||
|
||||
OctreeQueryNode* nodeData = (OctreeQueryNode*) matchingNode->getLinkedData();
|
||||
if (nodeData && !nodeData->isOctreeSendThreadInitalized()) {
|
||||
if (debug) {
|
||||
qDebug() << "calling initializeOctreeSendThread()... node:" << *matchingNode;
|
||||
}
|
||||
nodeData->initializeOctreeSendThread(this, matchingNode);
|
||||
|
||||
// NOTE: this is an important aspect of the proper ref counting. The send threads/node data need to
|
||||
// know that the OctreeServer/Assignment will not get deleted on it while it's still active. The
|
||||
// solution is to get the shared pointer for the current assignment. We need to make sure this is the
|
||||
// same SharedAssignmentPointer that was ref counted by the assignment client.
|
||||
SharedAssignmentPointer sharedAssignment = AssignmentClient::getCurrentAssignment();
|
||||
nodeData->initializeOctreeSendThread(sharedAssignment, matchingNode);
|
||||
}
|
||||
}
|
||||
} else if (packetType == PacketTypeJurisdictionRequest) {
|
||||
|
@ -1042,23 +1049,46 @@ void OctreeServer::nodeAdded(SharedNodePointer node) {
|
|||
}
|
||||
|
||||
void OctreeServer::nodeKilled(SharedNodePointer node) {
|
||||
quint64 start = usecTimestampNow();
|
||||
|
||||
qDebug() << qPrintable(_safeServerName) << "server killed node:" << *node;
|
||||
OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(node->getLinkedData());
|
||||
if (nodeData) {
|
||||
qDebug() << qPrintable(_safeServerName) << "server resetting Linked Data for node:" << *node;
|
||||
node->setLinkedData(NULL); // set this first in case another thread comes through and tryes to acces this
|
||||
qDebug() << qPrintable(_safeServerName) << "server deleting Linked Data for node:" << *node;
|
||||
nodeData->deleteLater();
|
||||
nodeData->nodeKilled(); // tell our node data and sending threads that we'd like to shut down
|
||||
} else {
|
||||
qDebug() << qPrintable(_safeServerName) << "server node missing linked data node:" << *node;
|
||||
}
|
||||
|
||||
quint64 end = usecTimestampNow();
|
||||
quint64 usecsElapsed = (end - start);
|
||||
if (usecsElapsed > 1000) {
|
||||
qDebug() << qPrintable(_safeServerName) << "server nodeKilled() took: " << usecsElapsed << " usecs for node:" << *node;
|
||||
}
|
||||
}
|
||||
|
||||
void OctreeServer::forceNodeShutdown(SharedNodePointer node) {
|
||||
quint64 start = usecTimestampNow();
|
||||
|
||||
qDebug() << qPrintable(_safeServerName) << "server killed node:" << *node;
|
||||
OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(node->getLinkedData());
|
||||
if (nodeData) {
|
||||
nodeData->forceNodeShutdown(); // tell our node data and sending threads that we'd like to shut down
|
||||
} else {
|
||||
qDebug() << qPrintable(_safeServerName) << "server node missing linked data node:" << *node;
|
||||
}
|
||||
|
||||
quint64 end = usecTimestampNow();
|
||||
quint64 usecsElapsed = (end - start);
|
||||
qDebug() << qPrintable(_safeServerName) << "server forceNodeShutdown() took: "
|
||||
<< usecsElapsed << " usecs for node:" << *node;
|
||||
}
|
||||
|
||||
|
||||
void OctreeServer::aboutToFinish() {
|
||||
qDebug() << qPrintable(_safeServerName) << "server STARTING about to finish...";
|
||||
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||
qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *node;
|
||||
nodeKilled(node);
|
||||
forceNodeShutdown(node);
|
||||
}
|
||||
qDebug() << qPrintable(_safeServerName) << "server ENDING about to finish...";
|
||||
}
|
||||
|
|
|
@ -117,6 +117,7 @@ public:
|
|||
bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url);
|
||||
|
||||
virtual void aboutToFinish();
|
||||
void forceNodeShutdown(SharedNodePointer node);
|
||||
|
||||
public slots:
|
||||
/// runs the voxel server assignment
|
||||
|
|
|
@ -278,6 +278,7 @@ void DomainServer::createScriptedAssignmentsFromArray(const QJsonArray &configAr
|
|||
qDebug() << "Adding scripted assignment to queue -" << *scriptAssignment;
|
||||
qDebug() << "URL for script is" << assignmentURL;
|
||||
|
||||
// scripts passed on CL or via JSON are static - so they are added back to the queue if the node dies
|
||||
_assignmentQueue.enqueue(SharedAssignmentPointer(scriptAssignment));
|
||||
}
|
||||
}
|
||||
|
@ -343,7 +344,6 @@ const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer
|
|||
<< NodeType::AvatarMixer << NodeType::VoxelServer << NodeType::ParticleServer
|
||||
<< NodeType::MetavoxelServer;
|
||||
|
||||
|
||||
void DomainServer::addNodeToNodeListAndConfirmConnection(const QByteArray& packet, const HifiSockAddr& senderSockAddr) {
|
||||
|
||||
NodeType_t nodeType;
|
||||
|
@ -352,34 +352,40 @@ void DomainServer::addNodeToNodeListAndConfirmConnection(const QByteArray& packe
|
|||
int numPreInterestBytes = parseNodeDataFromByteArray(nodeType, publicSockAddr, localSockAddr, packet, senderSockAddr);
|
||||
|
||||
QUuid assignmentUUID = uuidFromPacketHeader(packet);
|
||||
SharedAssignmentPointer matchingAssignment;
|
||||
bool isStaticAssignment = _staticAssignmentHash.contains(assignmentUUID);
|
||||
SharedAssignmentPointer matchingAssignment = SharedAssignmentPointer();
|
||||
|
||||
if (!assignmentUUID.isNull() && (matchingAssignment = matchingStaticAssignmentForCheckIn(assignmentUUID, nodeType))
|
||||
&& matchingAssignment) {
|
||||
// this is an assigned node, make sure the UUID sent is for an assignment we're actually trying to give out
|
||||
if (isStaticAssignment) {
|
||||
// this is a static assignment, make sure the UUID sent is for an assignment we're actually trying to give out
|
||||
matchingAssignment = matchingQueuedAssignmentForCheckIn(assignmentUUID, nodeType);
|
||||
|
||||
// remove the matching assignment from the assignment queue so we don't take the next check in
|
||||
// (if it exists)
|
||||
removeMatchingAssignmentFromQueue(matchingAssignment);
|
||||
if (matchingAssignment) {
|
||||
// remove the matching assignment from the assignment queue so we don't take the next check in
|
||||
// (if it exists)
|
||||
removeMatchingAssignmentFromQueue(matchingAssignment);
|
||||
}
|
||||
} else {
|
||||
assignmentUUID = QUuid();
|
||||
}
|
||||
|
||||
// create a new session UUID for this node
|
||||
QUuid nodeUUID = QUuid::createUuid();
|
||||
|
||||
SharedNodePointer newNode = LimitedNodeList::getInstance()->addOrUpdateNode(nodeUUID, nodeType,
|
||||
publicSockAddr, localSockAddr);
|
||||
|
||||
// when the newNode is created the linked data is also created
|
||||
// if this was a static assignment set the UUID, set the sendingSockAddr
|
||||
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(newNode->getLinkedData());
|
||||
|
||||
nodeData->setStaticAssignmentUUID(assignmentUUID);
|
||||
nodeData->setSendingSockAddr(senderSockAddr);
|
||||
|
||||
// reply back to the user with a PacketTypeDomainList
|
||||
sendDomainListToNode(newNode, senderSockAddr, nodeInterestListFromPacket(packet, numPreInterestBytes));
|
||||
// make sure this was either not a static assignment or it was and we had a matching one in teh queue
|
||||
if ((!isStaticAssignment && !STATICALLY_ASSIGNED_NODES.contains(nodeType)) || (isStaticAssignment && matchingAssignment)) {
|
||||
// create a new session UUID for this node
|
||||
QUuid nodeUUID = QUuid::createUuid();
|
||||
|
||||
SharedNodePointer newNode = LimitedNodeList::getInstance()->addOrUpdateNode(nodeUUID, nodeType,
|
||||
publicSockAddr, localSockAddr);
|
||||
|
||||
// when the newNode is created the linked data is also created
|
||||
// if this was a static assignment set the UUID, set the sendingSockAddr
|
||||
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(newNode->getLinkedData());
|
||||
|
||||
nodeData->setStaticAssignmentUUID(assignmentUUID);
|
||||
nodeData->setSendingSockAddr(senderSockAddr);
|
||||
|
||||
// reply back to the user with a PacketTypeDomainList
|
||||
sendDomainListToNode(newNode, senderSockAddr, nodeInterestListFromPacket(packet, numPreInterestBytes));
|
||||
}
|
||||
}
|
||||
|
||||
int DomainServer::parseNodeDataFromByteArray(NodeType_t& nodeType, HifiSockAddr& publicSockAddr,
|
||||
|
@ -740,6 +746,16 @@ QJsonObject DomainServer::jsonObjectForNode(const SharedNodePointer& node) {
|
|||
return nodeJson;
|
||||
}
|
||||
|
||||
const char ASSIGNMENT_SCRIPT_HOST_LOCATION[] = "resources/web/assignment";
|
||||
|
||||
QString pathForAssignmentScript(const QUuid& assignmentUUID) {
|
||||
QString newPath(ASSIGNMENT_SCRIPT_HOST_LOCATION);
|
||||
newPath += "/";
|
||||
// append the UUID for this script as the new filename, remove the curly braces
|
||||
newPath += uuidStringWithoutCurlyBraces(assignmentUUID);
|
||||
return newPath;
|
||||
}
|
||||
|
||||
bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url) {
|
||||
const QString JSON_MIME_TYPE = "application/json";
|
||||
|
||||
|
@ -847,8 +863,9 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
|||
// this is a script upload - ask the HTTPConnection to parse the form data
|
||||
QList<FormData> formData = connection->parseFormData();
|
||||
|
||||
// check how many instances of this assignment the user wants by checking the ASSIGNMENT-INSTANCES header
|
||||
// check optional headers for # of instances and pool
|
||||
const QString ASSIGNMENT_INSTANCES_HEADER = "ASSIGNMENT-INSTANCES";
|
||||
const QString ASSIGNMENT_POOL_HEADER = "ASSIGNMENT-POOL";
|
||||
|
||||
QByteArray assignmentInstancesValue = connection->requestHeaders().value(ASSIGNMENT_INSTANCES_HEADER.toLocal8Bit());
|
||||
|
||||
|
@ -860,25 +877,30 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
|||
|
||||
numInstances = assignmentInstancesValue.toInt();
|
||||
}
|
||||
|
||||
const char ASSIGNMENT_SCRIPT_HOST_LOCATION[] = "resources/web/assignment";
|
||||
|
||||
QString assignmentPool = emptyPool;
|
||||
QByteArray assignmentPoolValue = connection->requestHeaders().value(ASSIGNMENT_POOL_HEADER.toLocal8Bit());
|
||||
|
||||
if (!assignmentPoolValue.isEmpty()) {
|
||||
// specific pool requested, set that on the created assignment
|
||||
assignmentPool = QString(assignmentPoolValue);
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < numInstances; i++) {
|
||||
|
||||
// create an assignment for this saved script
|
||||
Assignment* scriptAssignment = new Assignment(Assignment::CreateCommand, Assignment::AgentType);
|
||||
Assignment* scriptAssignment = new Assignment(Assignment::CreateCommand, Assignment::AgentType, assignmentPool);
|
||||
|
||||
QString newPath(ASSIGNMENT_SCRIPT_HOST_LOCATION);
|
||||
newPath += "/";
|
||||
// append the UUID for this script as the new filename, remove the curly braces
|
||||
newPath += uuidStringWithoutCurlyBraces(scriptAssignment->getUUID());
|
||||
QString newPath = pathForAssignmentScript(scriptAssignment->getUUID());
|
||||
|
||||
// create a file with the GUID of the assignment in the script host locaiton
|
||||
// create a file with the GUID of the assignment in the script host location
|
||||
QFile scriptFile(newPath);
|
||||
scriptFile.open(QIODevice::WriteOnly);
|
||||
scriptFile.write(formData[0].second);
|
||||
|
||||
qDebug("Saved a script for assignment at %s", qPrintable(newPath));
|
||||
qDebug() << qPrintable(QString("Saved a script for assignment at %1%2")
|
||||
.arg(newPath).arg(assignmentPool == emptyPool ? "" : " - pool is " + assignmentPool));
|
||||
|
||||
// add the script assigment to the assignment queue
|
||||
_assignmentQueue.enqueue(SharedAssignmentPointer(scriptAssignment));
|
||||
|
@ -935,6 +957,11 @@ void DomainServer::refreshStaticAssignmentAndAddToQueue(SharedAssignmentPointer&
|
|||
qDebug() << "Reset UUID for assignment -" << *assignment.data() << "- and added to queue. Old UUID was"
|
||||
<< uuidStringWithoutCurlyBraces(oldUUID);
|
||||
|
||||
if (assignment->getType() == Assignment::AgentType && assignment->getPayload().isEmpty()) {
|
||||
// if this was an Agent without a script URL, we need to rename the old file so it can be retrieved at the new UUID
|
||||
QFile::rename(pathForAssignmentScript(oldUUID), pathForAssignmentScript(assignment->getUUID()));
|
||||
}
|
||||
|
||||
// add the static assignment back under the right UUID, and to the queue
|
||||
_staticAssignmentHash.insert(assignment->getUUID(), assignment);
|
||||
|
||||
|
@ -982,7 +1009,7 @@ void DomainServer::nodeKilled(SharedNodePointer node) {
|
|||
}
|
||||
}
|
||||
|
||||
SharedAssignmentPointer DomainServer::matchingStaticAssignmentForCheckIn(const QUuid& checkInUUID, NodeType_t nodeType) {
|
||||
SharedAssignmentPointer DomainServer::matchingQueuedAssignmentForCheckIn(const QUuid& checkInUUID, NodeType_t nodeType) {
|
||||
QQueue<SharedAssignmentPointer>::iterator i = _assignmentQueue.begin();
|
||||
|
||||
while (i != _assignmentQueue.end()) {
|
||||
|
@ -1009,22 +1036,21 @@ SharedAssignmentPointer DomainServer::deployableAssignmentForRequest(const Assig
|
|||
bool assignmentPoolsMatch = assignment->getPool() == requestAssignment.getPool();
|
||||
|
||||
if ((requestIsAllTypes || assignmentTypesMatch) && (nietherHasPool || assignmentPoolsMatch)) {
|
||||
|
||||
if (assignment->getType() == Assignment::AgentType) {
|
||||
// if there is more than one instance to send out, simply decrease the number of instances
|
||||
return _assignmentQueue.takeAt(sharedAssignment - _assignmentQueue.begin());
|
||||
} else {
|
||||
// remove the assignment from the queue
|
||||
SharedAssignmentPointer deployableAssignment = _assignmentQueue.takeAt(sharedAssignment
|
||||
- _assignmentQueue.begin());
|
||||
|
||||
|
||||
// remove the assignment from the queue
|
||||
SharedAssignmentPointer deployableAssignment = _assignmentQueue.takeAt(sharedAssignment
|
||||
- _assignmentQueue.begin());
|
||||
|
||||
if (deployableAssignment->getType() != Assignment::AgentType
|
||||
|| _staticAssignmentHash.contains(deployableAssignment->getUUID())) {
|
||||
// this is a static assignment
|
||||
// until we get a check-in from that GUID
|
||||
// put assignment back in queue but stick it at the back so the others have a chance to go out
|
||||
_assignmentQueue.enqueue(deployableAssignment);
|
||||
|
||||
// stop looping, we've handed out an assignment
|
||||
return deployableAssignment;
|
||||
}
|
||||
|
||||
// stop looping, we've handed out an assignment
|
||||
return deployableAssignment;
|
||||
} else {
|
||||
// push forward the iterator to check the next assignment
|
||||
++sharedAssignment;
|
||||
|
|
|
@ -70,7 +70,7 @@ private:
|
|||
void createStaticAssignmentsForType(Assignment::Type type, const QJsonArray& configArray);
|
||||
void populateDefaultStaticAssignmentsExcludingTypes(const QSet<Assignment::Type>& excludedTypes);
|
||||
|
||||
SharedAssignmentPointer matchingStaticAssignmentForCheckIn(const QUuid& checkInUUID, NodeType_t nodeType);
|
||||
SharedAssignmentPointer matchingQueuedAssignmentForCheckIn(const QUuid& checkInUUID, NodeType_t nodeType);
|
||||
SharedAssignmentPointer deployableAssignmentForRequest(const Assignment& requestAssignment);
|
||||
void removeMatchingAssignmentFromQueue(const SharedAssignmentPointer& removableAssignment);
|
||||
void refreshStaticAssignmentAndAddToQueue(SharedAssignmentPointer& assignment);
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
//
|
||||
// Tools for manipulating the attributes of the AudioReflector behavior
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
|
@ -19,6 +21,8 @@ var reflectiveScale = 100.0;
|
|||
var diffusionScale = 100.0;
|
||||
var absorptionScale = 100.0;
|
||||
var combFilterScale = 50.0;
|
||||
var originalScale = 2.0;
|
||||
var echoesScale = 2.0;
|
||||
|
||||
// these three properties are bound together, if you change one, the others will also change
|
||||
var reflectiveRatio = AudioReflector.getReflectiveRatio();
|
||||
|
@ -421,6 +425,84 @@ var absorptionThumb = Overlays.addOverlay("image", {
|
|||
alpha: 1
|
||||
});
|
||||
|
||||
var originalY = topY;
|
||||
topY += sliderHeight;
|
||||
|
||||
var originalLabel = Overlays.addOverlay("text", {
|
||||
x: 40,
|
||||
y: originalY,
|
||||
width: 60,
|
||||
height: sliderHeight,
|
||||
color: { red: 0, green: 0, blue: 0},
|
||||
textColor: { red: 255, green: 255, blue: 255},
|
||||
topMargin: 6,
|
||||
leftMargin: 5,
|
||||
text: "Original\nMix:"
|
||||
});
|
||||
|
||||
|
||||
var originalSlider = Overlays.addOverlay("image", {
|
||||
// alternate form of expressing bounds
|
||||
bounds: { x: 100, y: originalY, width: 150, height: sliderHeight},
|
||||
subImage: { x: 46, y: 0, width: 200, height: 71 },
|
||||
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/slider.png",
|
||||
color: { red: 255, green: 255, blue: 255},
|
||||
alpha: 1
|
||||
});
|
||||
|
||||
|
||||
var originalMinThumbX = 110;
|
||||
var originalMaxThumbX = originalMinThumbX + 110;
|
||||
var originalThumbX = originalMinThumbX + ((originalMaxThumbX - originalMinThumbX) * (AudioReflector.getOriginalSourceAttenuation() / originalScale));
|
||||
var originalThumb = Overlays.addOverlay("image", {
|
||||
x: originalThumbX,
|
||||
y: originalY+9,
|
||||
width: 18,
|
||||
height: 17,
|
||||
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png",
|
||||
color: { red: 128, green: 128, blue: 0},
|
||||
alpha: 1
|
||||
});
|
||||
|
||||
var echoesY = topY;
|
||||
topY += sliderHeight;
|
||||
|
||||
var echoesLabel = Overlays.addOverlay("text", {
|
||||
x: 40,
|
||||
y: echoesY,
|
||||
width: 60,
|
||||
height: sliderHeight,
|
||||
color: { red: 0, green: 0, blue: 0},
|
||||
textColor: { red: 255, green: 255, blue: 255},
|
||||
topMargin: 6,
|
||||
leftMargin: 5,
|
||||
text: "Echoes\nMix:"
|
||||
});
|
||||
|
||||
|
||||
var echoesSlider = Overlays.addOverlay("image", {
|
||||
// alternate form of expressing bounds
|
||||
bounds: { x: 100, y: echoesY, width: 150, height: sliderHeight},
|
||||
subImage: { x: 46, y: 0, width: 200, height: 71 },
|
||||
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/slider.png",
|
||||
color: { red: 255, green: 255, blue: 255},
|
||||
alpha: 1
|
||||
});
|
||||
|
||||
|
||||
var echoesMinThumbX = 110;
|
||||
var echoesMaxThumbX = echoesMinThumbX + 110;
|
||||
var echoesThumbX = echoesMinThumbX + ((echoesMaxThumbX - echoesMinThumbX) * (AudioReflector.getEchoesAttenuation() / echoesScale));
|
||||
var echoesThumb = Overlays.addOverlay("image", {
|
||||
x: echoesThumbX,
|
||||
y: echoesY+9,
|
||||
width: 18,
|
||||
height: 17,
|
||||
imageURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/images/thumb.png",
|
||||
color: { red: 128, green: 128, blue: 0},
|
||||
alpha: 1
|
||||
});
|
||||
|
||||
|
||||
// When our script shuts down, we should clean up all of our overlays
|
||||
function scriptEnding() {
|
||||
|
@ -460,6 +542,14 @@ function scriptEnding() {
|
|||
Overlays.deleteOverlay(absorptionThumb);
|
||||
Overlays.deleteOverlay(absorptionSlider);
|
||||
|
||||
Overlays.deleteOverlay(echoesLabel);
|
||||
Overlays.deleteOverlay(echoesThumb);
|
||||
Overlays.deleteOverlay(echoesSlider);
|
||||
|
||||
Overlays.deleteOverlay(originalLabel);
|
||||
Overlays.deleteOverlay(originalThumb);
|
||||
Overlays.deleteOverlay(originalSlider);
|
||||
|
||||
}
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
|
||||
|
@ -483,6 +573,8 @@ var movingSliderLocalFactor = false;
|
|||
var movingSliderReflective = false;
|
||||
var movingSliderDiffusion = false;
|
||||
var movingSliderAbsorption = false;
|
||||
var movingSliderOriginal = false;
|
||||
var movingSliderEchoes = false;
|
||||
|
||||
var thumbClickOffsetX = 0;
|
||||
function mouseMoveEvent(event) {
|
||||
|
@ -546,7 +638,6 @@ function mouseMoveEvent(event) {
|
|||
var combFilter = ((newThumbX - combFilterMinThumbX) / (combFilterMaxThumbX - combFilterMinThumbX)) * combFilterScale;
|
||||
AudioReflector.setCombFilterWindow(combFilter);
|
||||
}
|
||||
|
||||
if (movingSliderLocalFactor) {
|
||||
newThumbX = event.x - thumbClickOffsetX;
|
||||
if (newThumbX < localFactorMinThumbX) {
|
||||
|
@ -598,6 +689,30 @@ function mouseMoveEvent(event) {
|
|||
var diffusion = ((newThumbX - diffusionMinThumbX) / (diffusionMaxThumbX - diffusionMinThumbX)) * diffusionScale;
|
||||
setDiffusionRatio(diffusion);
|
||||
}
|
||||
if (movingSliderEchoes) {
|
||||
newThumbX = event.x - thumbClickOffsetX;
|
||||
if (newThumbX < echoesMinThumbX) {
|
||||
newThumbX = echoesMminThumbX;
|
||||
}
|
||||
if (newThumbX > echoesMaxThumbX) {
|
||||
newThumbX = echoesMaxThumbX;
|
||||
}
|
||||
Overlays.editOverlay(echoesThumb, { x: newThumbX } );
|
||||
var echoes = ((newThumbX - echoesMinThumbX) / (echoesMaxThumbX - echoesMinThumbX)) * echoesScale;
|
||||
AudioReflector.setEchoesAttenuation(echoes);
|
||||
}
|
||||
if (movingSliderOriginal) {
|
||||
newThumbX = event.x - thumbClickOffsetX;
|
||||
if (newThumbX < originalMinThumbX) {
|
||||
newThumbX = originalMminThumbX;
|
||||
}
|
||||
if (newThumbX > originalMaxThumbX) {
|
||||
newThumbX = originalMaxThumbX;
|
||||
}
|
||||
Overlays.editOverlay(originalThumb, { x: newThumbX } );
|
||||
var original = ((newThumbX - originalMinThumbX) / (originalMaxThumbX - originalMinThumbX)) * originalScale;
|
||||
AudioReflector.setOriginalSourceAttenuation(original);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -640,7 +755,16 @@ function mousePressEvent(event) {
|
|||
movingSliderReflective = true;
|
||||
thumbClickOffsetX = event.x - reflectiveThumbX;
|
||||
}
|
||||
if (clickedOverlay == originalThumb) {
|
||||
movingSliderOriginal = true;
|
||||
thumbClickOffsetX = event.x - originalThumbX;
|
||||
}
|
||||
if (clickedOverlay == echoesThumb) {
|
||||
movingSliderEchoes = true;
|
||||
thumbClickOffsetX = event.x - echoesThumbX;
|
||||
}
|
||||
}
|
||||
|
||||
function mouseReleaseEvent(event) {
|
||||
if (movingSliderDelay) {
|
||||
movingSliderDelay = false;
|
||||
|
@ -672,14 +796,12 @@ function mouseReleaseEvent(event) {
|
|||
AudioReflector.setCombFilterWindow(combFilter);
|
||||
combFilterThumbX = newThumbX;
|
||||
}
|
||||
|
||||
if (movingSliderLocalFactor) {
|
||||
movingSliderLocalFactor = false;
|
||||
var localFactor = ((newThumbX - localFactorMinThumbX) / (localFactorMaxThumbX - localFactorMinThumbX)) * localFactorScale;
|
||||
AudioReflector.setLocalAudioAttenuationFactor(localFactor);
|
||||
localFactorThumbX = newThumbX;
|
||||
}
|
||||
|
||||
if (movingSliderReflective) {
|
||||
movingSliderReflective = false;
|
||||
var reflective = ((newThumbX - reflectiveMinThumbX) / (reflectiveMaxThumbX - reflectiveMinThumbX)) * reflectiveScale;
|
||||
|
@ -687,7 +809,6 @@ function mouseReleaseEvent(event) {
|
|||
reflectiveThumbX = newThumbX;
|
||||
updateRatioSliders();
|
||||
}
|
||||
|
||||
if (movingSliderDiffusion) {
|
||||
movingSliderDiffusion = false;
|
||||
var diffusion = ((newThumbX - diffusionMinThumbX) / (diffusionMaxThumbX - diffusionMinThumbX)) * diffusionScale;
|
||||
|
@ -695,7 +816,6 @@ function mouseReleaseEvent(event) {
|
|||
diffusionThumbX = newThumbX;
|
||||
updateRatioSliders();
|
||||
}
|
||||
|
||||
if (movingSliderAbsorption) {
|
||||
movingSliderAbsorption = false;
|
||||
var absorption = ((newThumbX - absorptionMinThumbX) / (absorptionMaxThumbX - absorptionMinThumbX)) * absorptionScale;
|
||||
|
@ -703,6 +823,18 @@ function mouseReleaseEvent(event) {
|
|||
absorptionThumbX = newThumbX;
|
||||
updateRatioSliders();
|
||||
}
|
||||
if (movingSliderEchoes) {
|
||||
movingSliderEchoes = false;
|
||||
var echoes = ((newThumbX - echoesMinThumbX) / (echoesMaxThumbX - echoesMinThumbX)) * echoesScale;
|
||||
AudioReflector.setEchoesAttenuation(echoes);
|
||||
echoesThumbX = newThumbX;
|
||||
}
|
||||
if (movingSliderOriginal) {
|
||||
movingSliderOriginal = false;
|
||||
var original = ((newThumbX - originalMinThumbX) / (originalMaxThumbX - originalMinThumbX)) * originalScale;
|
||||
AudioReflector.setOriginalSourceAttenuation(original);
|
||||
originalThumbX = newThumbX;
|
||||
}
|
||||
}
|
||||
|
||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||
|
|
|
@ -50,7 +50,7 @@ function maybePlaySound(deltaTime) {
|
|||
const CLAP_DISTANCE = 0.2;
|
||||
|
||||
if (!clapping[palm] && (distanceBetween < CLAP_DISTANCE) && (speed > CLAP_SPEED)) {
|
||||
var options = new AudioInjectionOptions();
|
||||
var options = new AudioInjectionOptions();
|
||||
options.position = palm1Position;
|
||||
options.volume = speed / 2.0;
|
||||
if (options.volume > 1.0) options.volume = 1.0;
|
||||
|
|
|
@ -27,7 +27,7 @@ Script.update.connect(function(deltaTime) {
|
|||
if (!jointMapping) {
|
||||
var avatarJointNames = Avatar.jointNames;
|
||||
var animationJointNames = animation.jointNames;
|
||||
if (avatarJointNames === 0 || animationJointNames.length === 0) {
|
||||
if (avatarJointNames.length === 0 || animationJointNames.length === 0) {
|
||||
return;
|
||||
}
|
||||
jointMapping = new Array(avatarJointNames.length);
|
||||
|
|
|
@ -61,7 +61,7 @@ function checkSticks(deltaTime) {
|
|||
// Waiting for change in velocity direction or slowing to trigger drum sound
|
||||
if ((palmVelocity.y > 0.0) || (speed < STOP_SPEED)) {
|
||||
state[palm] = 0;
|
||||
var options = new AudioInjectionOptions();
|
||||
var options = new AudioInjectionOptions();
|
||||
options.position = Controller.getSpatialControlPosition(palm * 2 + 1);
|
||||
if (strokeSpeed[palm] > 1.0) { strokeSpeed[palm] = 1.0; }
|
||||
options.volume = strokeSpeed[palm];
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,12 +9,12 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
// First, load the clap sound from a URL
|
||||
var clap = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/bushtit_1.raw");
|
||||
var clap = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/bushtit_1.raw");
|
||||
|
||||
function maybePlaySound(deltaTime) {
|
||||
if (Math.random() < 0.01) {
|
||||
// Set the location and other info for the sound to play
|
||||
var options = new AudioInjectionOptions();
|
||||
var options = new AudioInjectionOptions();
|
||||
var palmPosition = Controller.getSpatialControlPosition(0);
|
||||
options.position = palmPosition;
|
||||
options.volume = 0.5;
|
||||
|
|
|
@ -217,7 +217,7 @@ function update(deltaTime) {
|
|||
|
||||
if (invaderStepOfCycle % stepsPerSound == 0) {
|
||||
// play the move sound
|
||||
var options = new AudioInjectionOptions();
|
||||
var options = new AudioInjectionOptions();
|
||||
if (soundInMyHead) {
|
||||
options.position = { x: MyAvatar.position.x + 0.0,
|
||||
y: MyAvatar.position.y + 0.1,
|
||||
|
@ -329,7 +329,7 @@ function fireMissile() {
|
|||
lifetime: 5
|
||||
});
|
||||
|
||||
var options = new AudioInjectionOptions();
|
||||
var options = new AudioInjectionOptions();
|
||||
if (soundInMyHead) {
|
||||
options.position = { x: MyAvatar.position.x + 0.0,
|
||||
y: MyAvatar.position.y + 0.1,
|
||||
|
@ -379,7 +379,7 @@ function deleteIfInvader(possibleInvaderParticle) {
|
|||
Particles.deleteParticle(myMissile);
|
||||
|
||||
// play the hit sound
|
||||
var options = new AudioInjectionOptions();
|
||||
var options = new AudioInjectionOptions();
|
||||
if (soundInMyHead) {
|
||||
options.position = { x: MyAvatar.position.x + 0.0,
|
||||
y: MyAvatar.position.y + 0.1,
|
||||
|
@ -417,4 +417,3 @@ initializeInvaders();
|
|||
|
||||
// shut down the game after 1 minute
|
||||
var gameTimer = Script.setTimeout(endGame, itemLifetimes * 1000);
|
||||
|
||||
|
|
94
examples/testingVoxelViewerRestart.js
Normal file
94
examples/testingVoxelViewerRestart.js
Normal file
|
@ -0,0 +1,94 @@
|
|||
//
|
||||
// testingVoxelSeeingRestart.js
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 2/26/14
|
||||
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var count = 0;
|
||||
var yawDirection = -1;
|
||||
var yaw = 45;
|
||||
var yawMax = 70;
|
||||
var yawMin = 20;
|
||||
var vantagePoint = {x: 5000, y: 500, z: 5000};
|
||||
|
||||
var isLocal = false;
|
||||
|
||||
// set up our VoxelViewer with a position and orientation
|
||||
var orientation = Quat.fromPitchYawRollDegrees(0, yaw, 0);
|
||||
|
||||
function getRandomInt(min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
function init() {
|
||||
if (isLocal) {
|
||||
MyAvatar.position = vantagePoint;
|
||||
MyAvatar.orientation = orientation;
|
||||
} else {
|
||||
VoxelViewer.setPosition(vantagePoint);
|
||||
VoxelViewer.setOrientation(orientation);
|
||||
VoxelViewer.queryOctree();
|
||||
Agent.isAvatar = true;
|
||||
}
|
||||
}
|
||||
|
||||
function keepLooking(deltaTime) {
|
||||
//print("count =" + count);
|
||||
|
||||
if (count == 0) {
|
||||
init();
|
||||
}
|
||||
count++;
|
||||
if (count % getRandomInt(5, 15) == 0) {
|
||||
yaw += yawDirection;
|
||||
orientation = Quat.fromPitchYawRollDegrees(0, yaw, 0);
|
||||
if (yaw > yawMax || yaw < yawMin) {
|
||||
yawDirection = yawDirection * -1;
|
||||
}
|
||||
|
||||
//if (count % 10000 == 0) {
|
||||
// print("calling VoxelViewer.queryOctree()... count=" + count + " yaw=" + yaw);
|
||||
//}
|
||||
|
||||
if (isLocal) {
|
||||
MyAvatar.orientation = orientation;
|
||||
} else {
|
||||
VoxelViewer.setOrientation(orientation);
|
||||
VoxelViewer.queryOctree();
|
||||
|
||||
//if (count % 10000 == 0) {
|
||||
// print("VoxelViewer.getOctreeElementsCount()=" + VoxelViewer.getOctreeElementsCount());
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
// approximately every second, consider stopping
|
||||
if (count % 60 == 0) {
|
||||
print("considering stop.... elementCount:" + VoxelViewer.getOctreeElementsCount());
|
||||
var stopProbability = 0.05; // 5% chance of stopping
|
||||
if (Math.random() < stopProbability) {
|
||||
print("stopping.... elementCount:" + VoxelViewer.getOctreeElementsCount());
|
||||
Script.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function scriptEnding() {
|
||||
print("SCRIPT ENDNG!!!\n");
|
||||
}
|
||||
|
||||
// register the call back so it fires before each data send
|
||||
Script.update.connect(keepLooking);
|
||||
|
||||
// register our scriptEnding callback
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
|
||||
|
||||
// test for local...
|
||||
Menu.isOptionChecked("Voxels");
|
||||
isLocal = true; // will only get here on local client
|
|
@ -111,7 +111,7 @@ function checkControllerSide(whichSide) {
|
|||
velocity : { x: 0, y: 0, z: 0}, inHand: true };
|
||||
Particles.editParticle(closestParticle, properties);
|
||||
|
||||
var options = new AudioInjectionOptions();
|
||||
var options = new AudioInjectionOptions();
|
||||
options.position = ballPosition;
|
||||
options.volume = 1.0;
|
||||
Audio.playSound(catchSound, options);
|
||||
|
@ -152,7 +152,7 @@ function checkControllerSide(whichSide) {
|
|||
}
|
||||
|
||||
// Play a new ball sound
|
||||
var options = new AudioInjectionOptions();
|
||||
var options = new AudioInjectionOptions();
|
||||
options.position = ballPosition;
|
||||
options.volume = 1.0;
|
||||
Audio.playSound(catchSound, options);
|
||||
|
@ -201,7 +201,7 @@ function checkControllerSide(whichSide) {
|
|||
rightHandParticle = false;
|
||||
}
|
||||
|
||||
var options = new AudioInjectionOptions();
|
||||
var options = new AudioInjectionOptions();
|
||||
options.position = ballPosition;
|
||||
options.volume = 1.0;
|
||||
Audio.playSound(throwSound, options);
|
||||
|
|
|
@ -64,7 +64,7 @@ collisionBubble[1] = Overlays.addOverlay("sphere",
|
|||
visible: false
|
||||
});
|
||||
|
||||
var audioOptions = new AudioInjectionOptions();
|
||||
var audioOptions = new AudioInjectionOptions();
|
||||
audioOptions.position = { x: MyAvatar.position.x, y: MyAvatar.position.y + 1, z: MyAvatar.position.z };
|
||||
audioOptions.volume = 1;
|
||||
|
||||
|
|
125
interface/resources/icons/load-script.svg
Normal file
125
interface/resources/icons/load-script.svg
Normal file
|
@ -0,0 +1,125 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="45"
|
||||
height="45"
|
||||
id="svg3827"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.1 r9760"
|
||||
sodipodi:docname="load-script.svg">
|
||||
<defs
|
||||
id="defs3829" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.959798"
|
||||
inkscape:cx="171.17264"
|
||||
inkscape:cy="-8.0710166"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1028"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata3832">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>T.Hofmeister</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1007.3622)">
|
||||
<g
|
||||
id="layer1-7"
|
||||
transform="matrix(-0.25019951,0,0,0.28877175,123.44112,917.40972)"
|
||||
style="fill:#696969">
|
||||
<g
|
||||
id="g3257"
|
||||
transform="matrix(1.9175,0,0,1.9175,-607.19,-179.09)"
|
||||
style="fill:#696969">
|
||||
<path
|
||||
id="path3224"
|
||||
d="m 563.06,260.72 -1.25,0.16 -40.15,4.87 -1.66,0.22 0.38,1.62 c 3.78,16.93 -0.59,34.07 -2.88,51.57 l -0.22,1.84 1.81,-0.16 42,-3 1.25,-0.06 0.16,-1.25 c 2.13,-17.86 6.92,-36.12 0.94,-54.62 l -0.38,-1.19 z m -2.18,3.28 c 4.96,16.72 -1.56,33.17 -3.72,50.47 l -35.63,2.78 c 2.25,-16.14 7.03,-29.55 3.78,-46.19 L 560.88,264 z"
|
||||
style="fill:#696969;fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3237"
|
||||
d="m 531.39,275.61 23.34,-4.6"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3243"
|
||||
d="m 532.1,280.91 22.27,-2.83"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3247"
|
||||
d="m 531.92,285.86 22.89,-1.95"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3249"
|
||||
d="m 530.15,292.84 24.22,-2.12"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3251"
|
||||
d="m 529.45,297.53 22.98,-0.8"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3253"
|
||||
d="m 528.65,304.24 22.45,-2.56"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3255"
|
||||
d="m 527.5,309.37 22.81,-1.77"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
display="block"
|
||||
d="m 22.50945,1041.7031 c 10.249979,14.5758 18.326744,5.8628 15.179173,-14.1826 l 3.401516,-0.2354 -8.04206,-17.0393 -2.800459,17.789 3.507825,-0.2428 c 2.535261,14.6877 0.402108,18.0407 -11.324416,13.7916 z"
|
||||
style="color:#000000;fill:#a9a9a9;stroke:#000000;stroke-width:0.61923206;display:block"
|
||||
id="path1432"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<rect
|
||||
style="color:#000000;fill:#00ffff;fill-opacity:0;fill-rule:nonzero;stroke:none;stroke-width:0.42527184;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect3032"
|
||||
width="44.57473"
|
||||
height="44.57473"
|
||||
x="0.18852967"
|
||||
y="1007.5989" />
|
||||
</g>
|
||||
</svg>
|
After (image error) Size: 4.5 KiB |
129
interface/resources/icons/new-script.svg
Normal file
129
interface/resources/icons/new-script.svg
Normal file
|
@ -0,0 +1,129 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="45"
|
||||
height="45"
|
||||
id="svg3827"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.1 r9760"
|
||||
sodipodi:docname="new-script - Kopie (2).svg">
|
||||
<defs
|
||||
id="defs3829" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6"
|
||||
inkscape:cx="39.376692"
|
||||
inkscape:cy="9.0006701"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1028"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata3832">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>T.Hofmeister</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1007.3622)">
|
||||
<rect
|
||||
style="color:#000000;fill:#00ffff;fill-opacity:0;fill-rule:nonzero;stroke:none;stroke-width:0.42527184;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect3032"
|
||||
width="44.57473"
|
||||
height="44.57473"
|
||||
x="0.18852967"
|
||||
y="1007.5989" />
|
||||
<g
|
||||
id="layer1-7-7"
|
||||
transform="matrix(-0.23943965,0,0,0.3096188,117.90945,912.00498)"
|
||||
style="fill:#696969">
|
||||
<g
|
||||
id="g3257-4"
|
||||
transform="matrix(1.9175,0,0,1.9175,-607.19,-179.09)"
|
||||
style="fill:#696969">
|
||||
<path
|
||||
id="path3224-0"
|
||||
d="m 563.06,260.72 -1.25,0.16 -40.15,4.87 -1.66,0.22 0.38,1.62 c 3.78,16.93 -0.59,34.07 -2.88,51.57 l -0.22,1.84 1.81,-0.16 42,-3 1.25,-0.06 0.16,-1.25 c 2.13,-17.86 6.92,-36.12 0.94,-54.62 l -0.38,-1.19 z m -2.18,3.28 c 4.96,16.72 -1.56,33.17 -3.72,50.47 l -35.63,2.78 c 2.25,-16.14 7.03,-29.55 3.78,-46.19 L 560.88,264 z"
|
||||
style="fill:#696969;fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3237-9"
|
||||
d="m 531.39,275.61 23.34,-4.6"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3243-4"
|
||||
d="m 532.1,280.91 22.27,-2.83"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3247-8"
|
||||
d="m 531.92,285.86 22.89,-1.95"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3249-8"
|
||||
d="m 530.15,292.84 24.22,-2.12"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3251-2"
|
||||
d="m 529.45,297.53 22.98,-0.8"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3253-4"
|
||||
d="m 528.65,304.24 22.45,-2.56"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3255-5"
|
||||
d="m 527.5,309.37 22.81,-1.77"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="layer1-1"
|
||||
transform="matrix(0.85515704,0.72492349,-0.91920854,2.1402565,983.21735,-1213.0824)"
|
||||
style="fill:#a9a9a9;stroke:#000000">
|
||||
<path
|
||||
style="fill:#a9a9a9;fill-opacity:1;stroke:#000000;stroke-width:0.25;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path2996"
|
||||
transform="translate(0,1036.3622)"
|
||||
d="m 3.4723994,8.5185577 3.0304576,-7.0710678 6.944799,0 -5.0191957,5.08233 4.1353117,0 -8.1127873,9.0913731 2.0834396,-7.1342026 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After (image error) Size: 4.7 KiB |
674
interface/resources/icons/save-script.svg
Normal file
674
interface/resources/icons/save-script.svg
Normal file
|
@ -0,0 +1,674 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="45"
|
||||
height="45"
|
||||
id="svg3827"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.1 r9760"
|
||||
sodipodi:docname="load-script - Kopie.svg">
|
||||
<defs
|
||||
id="defs3829">
|
||||
<linearGradient
|
||||
x1="28.061"
|
||||
x2="28.061"
|
||||
y1="31.431"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="36.437"
|
||||
id="linearGradient6971">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#ddd"
|
||||
id="stop6967" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#fdfdfd"
|
||||
id="stop6969" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="12.25"
|
||||
x2="7"
|
||||
y1="18.25"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="21.118"
|
||||
id="linearGradient6931">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#204a87"
|
||||
id="stop6927" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
stop-color="#204a87"
|
||||
id="stop6929" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="14.752"
|
||||
x2="8.8953"
|
||||
y1="15.868"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="16.743"
|
||||
id="linearGradient6907">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#3465a4"
|
||||
id="stop6903" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
stop-color="#3465a4"
|
||||
id="stop6905" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="33.431"
|
||||
x2="21.748"
|
||||
y1="31.965"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="11.781"
|
||||
id="linearGradient2553">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#fff"
|
||||
id="stop2557" />
|
||||
<stop
|
||||
offset=".5"
|
||||
stop-color="#e6e6e6"
|
||||
id="stop2561" />
|
||||
<stop
|
||||
offset=".75"
|
||||
stop-color="#fff"
|
||||
id="stop2563" />
|
||||
<stop
|
||||
offset=".84167"
|
||||
stop-color="#e1e1e1"
|
||||
id="stop2565" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#fff"
|
||||
id="stop2559" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="26.357"
|
||||
y1="11.319"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
x2="23.688"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="23.688"
|
||||
id="linearGradient4272">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-opacity=".2549"
|
||||
stop-color="#fff"
|
||||
id="stop4276" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#fff"
|
||||
id="stop4278" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="47.621"
|
||||
y1="4.4331"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
x2="44.096"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="12.378"
|
||||
id="linearGradient4260">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#fff"
|
||||
id="stop4256" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
stop-color="#fff"
|
||||
id="stop4258" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="20.936"
|
||||
gradientTransform="matrix(1.2862,0.7817,-0.71078,1.1696,-2.3543,0.24814)"
|
||||
cx="15.571"
|
||||
cy="2.9585"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient4250">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#e4e4e4"
|
||||
id="stop4246" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#d3d3d3"
|
||||
id="stop4248" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
y2="33.759"
|
||||
y1="37.206"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
x2="12.222"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="12.277"
|
||||
id="linearGradient4242">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#eee"
|
||||
id="stop4238" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
stop-color="#eee"
|
||||
id="stop4240" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="40.944"
|
||||
y1="28.481"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
x2="36.183"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="7.6046"
|
||||
id="linearGradient4234">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#bbb"
|
||||
id="stop4230" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#9f9f9f"
|
||||
id="stop4232" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="35.281"
|
||||
y1="35.281"
|
||||
gradientTransform="translate(0.79549,3.7992)"
|
||||
x2="24.688"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="7.0625"
|
||||
id="linearGradient4209">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#838383"
|
||||
id="stop4186" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
stop-color="#bbb"
|
||||
id="stop4188" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="15.645"
|
||||
gradientTransform="matrix(1,0,0,0.53672,0,16.873)"
|
||||
cx="24.837"
|
||||
cy="36.421"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient8668">
|
||||
<stop
|
||||
offset="0"
|
||||
id="stop8664" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
id="stop8666" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
y2="12.584"
|
||||
x2="12.624"
|
||||
gradientTransform="matrix(0.91411,0,0,0.91411,-3.8687,-2.7069)"
|
||||
y1="27.394"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="33.06"
|
||||
id="linearGradient1764">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#fff"
|
||||
id="stop2189" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
stop-color="#fff"
|
||||
id="stop2191" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="19.062"
|
||||
gradientTransform="matrix(-1.3145,-0.010063,-0.01023,1.3362,46.221,-4.9099)"
|
||||
cx="23.447"
|
||||
cy="6.4577"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient4997">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#fff"
|
||||
id="stop4993" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
stop-color="#fff"
|
||||
id="stop4995" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
y2="609.51"
|
||||
x2="302.86"
|
||||
gradientTransform="matrix(2.7744,0,0,1.9697,-1892.2,-872.89)"
|
||||
y1="366.65"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="302.86"
|
||||
id="linearGradient5027">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-opacity="0"
|
||||
id="stop5050" />
|
||||
<stop
|
||||
offset=".5"
|
||||
id="stop5056" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
id="stop5052" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="117.14"
|
||||
gradientTransform="matrix(2.7744,0,0,1.9697,-1891.6,-872.89)"
|
||||
cx="605.71"
|
||||
cy="486.65"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient5029" />
|
||||
<linearGradient
|
||||
id="linearGradient5060">
|
||||
<stop
|
||||
offset="0"
|
||||
id="stop5062" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
id="stop5064" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
r="117.14"
|
||||
gradientTransform="matrix(-2.7744,0,0,1.9697,112.76,-872.89)"
|
||||
cx="605.71"
|
||||
cy="486.65"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient5031" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6971"
|
||||
id="linearGradient3239"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="28.061"
|
||||
y1="31.431"
|
||||
x2="28.061"
|
||||
y2="36.437"
|
||||
gradientTransform="translate(51.972416,1005.3761)" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#radialGradient8668"
|
||||
id="radialGradient3253"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.1302,0,0,-0.40769251,48.062716,1046.2254)"
|
||||
cx="24.837"
|
||||
cy="36.421"
|
||||
r="15.645" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5027"
|
||||
id="linearGradient3361"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.7744,0,0,1.9697,-1892.2,-872.89)"
|
||||
x1="302.86"
|
||||
y1="366.65"
|
||||
x2="302.86"
|
||||
y2="609.51" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient3363"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.7744,0,0,1.9697,-1891.6,-872.89)"
|
||||
cx="605.71"
|
||||
cy="486.65"
|
||||
r="117.14" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient3365"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-2.7744,0,0,1.9697,112.76,-872.89)"
|
||||
cx="605.71"
|
||||
cy="486.65"
|
||||
r="117.14" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4234"
|
||||
id="linearGradient3367"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
x1="7.6046"
|
||||
y1="28.481"
|
||||
x2="36.183"
|
||||
y2="40.944" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#radialGradient4250"
|
||||
id="radialGradient3369"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.2862,0.7817,-0.71078,1.1696,-2.3543,0.24814)"
|
||||
cx="15.571"
|
||||
cy="2.9585"
|
||||
r="20.936" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4209"
|
||||
id="linearGradient3371"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0.79549,3.7992)"
|
||||
x1="7.0625"
|
||||
y1="35.281"
|
||||
x2="24.688"
|
||||
y2="35.281" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4242"
|
||||
id="linearGradient3373"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
x1="12.277"
|
||||
y1="37.206"
|
||||
x2="12.222"
|
||||
y2="33.759" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4272"
|
||||
id="linearGradient3375"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
x1="23.688"
|
||||
y1="11.319"
|
||||
x2="23.688"
|
||||
y2="26.357" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4260"
|
||||
id="linearGradient3377"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
x1="12.378"
|
||||
y1="4.4331"
|
||||
x2="44.096"
|
||||
y2="47.621" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2553"
|
||||
id="linearGradient3379"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="33.431"
|
||||
y1="31.965"
|
||||
x2="21.748"
|
||||
y2="11.781" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#radialGradient8668"
|
||||
id="radialGradient3381"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.1302,0,0,-0.40769251,48.062716,1046.2254)"
|
||||
cx="24.837"
|
||||
cy="36.421"
|
||||
r="15.645" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6971"
|
||||
id="linearGradient3383"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(51.972416,1005.3761)"
|
||||
x1="28.061"
|
||||
y1="31.431"
|
||||
x2="28.061"
|
||||
y2="36.437" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6"
|
||||
inkscape:cx="113.76169"
|
||||
inkscape:cy="-12.107928"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1028"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata3832">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>T.Hofmeister</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1007.3622)">
|
||||
<g
|
||||
id="g3385">
|
||||
<g
|
||||
transform="matrix(0.87964671,0,0,1,-44.027424,-2)"
|
||||
id="g3255">
|
||||
<g
|
||||
id="layer2"
|
||||
transform="translate(51.972416,1005.3761)">
|
||||
<g
|
||||
id="g5022"
|
||||
transform="matrix(0.024114,0,0,0.019292,45.49,41.752)">
|
||||
<rect
|
||||
id="rect4173"
|
||||
style="opacity:0.40206;color:#000000;fill:url(#linearGradient3361)"
|
||||
height="478.35999"
|
||||
width="1339.6"
|
||||
y="-150.7"
|
||||
x="-1559.3" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5058"
|
||||
style="opacity:0.40206;color:#000000;fill:url(#radialGradient3363)"
|
||||
d="m -219.62,-150.68 v 478.33 c 142.88,0.9 345.4,-107.17 345.4,-239.2 0,-132.02 -159.44,-239.13 -345.4,-239.13 z" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5018"
|
||||
style="opacity:0.40206;color:#000000;fill:url(#radialGradient3365)"
|
||||
d="m -1559.3,-150.68 v 478.33 c -142.8,0.9 -345.4,-107.17 -345.4,-239.2 0,-132.02 159.5,-239.13 345.4,-239.13 z" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#535353;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4196"
|
||||
d="m 11.286,13.088 c -0.625,0 -1.032,0.29 -1.282,0.843 L 3.5357,31.035 c 0,0 -0.25,0.671 -0.25,1.781 v 9.65 c 0,1.083 0.6578,1.625 1.6562,1.625 h 38.562 c 0.985,0 1.594,-0.718 1.594,-1.844 v -9.65 c 0,0 0.106,-0.77 -0.094,-1.312 l -6.718,-17.197 c -0.185,-0.512 -0.637,-0.988 -1.125,-1 h -25.875 z" />
|
||||
<path
|
||||
style="fill:url(#linearGradient3367);fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4170"
|
||||
d="m 3.2736,32.122 0.7646,-0.692 37.61,0.062 3.462,0.317 v 10.439 c 0,1.125 -0.607,1.843 -1.592,1.843 H 4.9352 c -0.998,0 -1.6614,-0.542 -1.6614,-1.624 V 32.122 z" />
|
||||
<path
|
||||
style="fill:url(#radialGradient3369);fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3093"
|
||||
d="m 3.5491,31.039 c -0.7143,1.465 -6e-4,2.393 1.0357,2.393 h 39 c 1.119,-0.024 1.845,-1.012 1.428,-2.143 l -6.714,-17.21 c -0.184,-0.512 -0.655,-0.988 -1.143,-1 h -25.857 c -0.625,0 -1.036,0.303 -1.286,0.857 L 3.5489,31.039 z" />
|
||||
<rect
|
||||
id="rect4174"
|
||||
style="color:#000000;fill:url(#linearGradient3371);fill-rule:evenodd"
|
||||
height="5.5625"
|
||||
width="17.625"
|
||||
y="36.299"
|
||||
x="7.8579998" />
|
||||
<path
|
||||
style="opacity:0.81142997;fill:url(#linearGradient3373);fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4194"
|
||||
d="M 7.858,41.862 V 37.85 c 1.8355,3.179 8.296,4.012 12.937,4.012 H 7.858 z" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4201"
|
||||
d="m 44.796,30.754 c 0.064,1.25 -0.414,2.316 -1.322,2.343 H 5.355 c -1.2889,0 -1.8674,-0.325 -2.0837,-0.868 0.0917,0.945 0.8258,1.65 2.084,1.65 h 38.119 c 1.076,-0.033 1.753,-1.424 1.352,-2.995 l -0.03,-0.13 z" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4211"
|
||||
style="opacity:0.69142995;color:#000000;fill:url(#linearGradient3375);fill-rule:evenodd"
|
||||
d="m 10.969,15.281 c -0.046,0.201 -0.188,0.387 -0.188,0.594 0,0.949 0.591,1.789 1.344,2.594 0.24,-0.154 0.365,-0.355 0.625,-0.5 -0.94,-0.816 -1.553,-1.717 -1.781,-2.688 z m 26.656,0 c -0.229,0.97 -0.842,1.873 -1.781,2.688 0.274,0.153 0.404,0.368 0.656,0.531 0.757,-0.807 1.312,-1.673 1.312,-2.625 0,-0.207 -0.141,-0.393 -0.187,-0.594 z m 2.187,8.438 c -0.613,4.04 -7.298,7.25 -15.531,7.25 -8.212,0 -14.86,-3.193 -15.5,-7.219 -0.0321,0.197 -0.1248,0.392 -0.1248,0.594 10e-5,4.318 6.9888,7.844 15.625,7.844 8.636,0 15.656,-3.526 15.657,-7.844 0,-0.213 -0.09,-0.418 -0.126,-0.625 z" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4224"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:0.45762999;fill-rule:evenodd"
|
||||
d="m 8.5737,25.594 a 1.37005,1.0165371 0 1 1 -2.7401,0 1.37005,1.0165371 0 1 1 2.7401,0 z"
|
||||
transform="translate(0.088388,5.3018)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4226"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:0.45762999;fill-rule:evenodd"
|
||||
d="m 8.5737,25.594 a 1.37005,1.0165371 0 1 1 -2.7401,0 1.37005,1.0165371 0 1 1 2.7401,0 z"
|
||||
transform="translate(33.967,5.2134)" />
|
||||
<path
|
||||
style="fill:none;stroke:url(#linearGradient3377);stroke-linecap:round;stroke-linejoin:round"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4252"
|
||||
d="m 11.643,13.541 c -0.602,0 -0.993,0.279 -1.234,0.812 L 3.994,30.944 c 0,0 -0.2406,0.646 -0.2406,1.715 v 9.29 c 0,1.354 0.444,1.627 1.5944,1.627 h 37.687 c 1.323,0 1.534,-0.317 1.534,-1.838 v -9.29 c 0,0 0.102,-0.742 -0.09,-1.264 l -6.593,-16.806 c -0.178,-0.492 -0.551,-0.826 -1.021,-0.837 h -25.222 z" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:square;stroke-opacity:0.42372999"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4282"
|
||||
d="m 40.5,36.554 v 5.021" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:square;stroke-opacity:0.42372999"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4284"
|
||||
d="m 38.5,36.614 v 5.021" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:square;stroke-opacity:0.42372999"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4286"
|
||||
d="m 36.5,36.614 v 5.021" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:square;stroke-opacity:0.42372999"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4288"
|
||||
d="m 34.5,36.614 v 5.021" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:square;stroke-opacity:0.42372999"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4290"
|
||||
d="m 32.5,36.614 v 5.021" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:square;stroke-opacity:0.42372999"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4292"
|
||||
d="m 30.5,36.614 v 5.021" />
|
||||
<path
|
||||
style="opacity:0.09714302;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:square"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4294"
|
||||
d="m 39.5,36.604 v 5.021" />
|
||||
<path
|
||||
style="opacity:0.09714302;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:square"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4296"
|
||||
d="m 37.5,36.664 v 5.021" />
|
||||
<path
|
||||
style="opacity:0.09714302;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:square"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4298"
|
||||
d="m 35.5,36.664 v 5.021" />
|
||||
<path
|
||||
style="opacity:0.09714302;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:square"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4300"
|
||||
d="m 33.5,36.664 v 5.021" />
|
||||
<path
|
||||
style="opacity:0.09714302;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:square"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4302"
|
||||
d="m 31.5,36.664 v 5.021" />
|
||||
<path
|
||||
style="opacity:0.43999999;fill:#ffffff;fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4572"
|
||||
d="m 7.875,36.312 v 5.532 H 20.438 L 8.219,41.5 7.875,36.312 z" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2545"
|
||||
style="opacity:0.20571002;color:#000000;fill:url(#linearGradient3379);fill-rule:evenodd"
|
||||
d="m 39.875,19.562 a 14.875,6.6875 0 1 1 -29.75,0 14.875,6.6875 0 1 1 29.75,0 z"
|
||||
transform="matrix(1.0378,0,0,1.0607,-1.6329,3.0304)" />
|
||||
</g>
|
||||
<path
|
||||
d="m 93.815472,1031.3767 a 17.681979,6.3782852 0 1 0 -35.363958,0 17.681979,6.3782852 0 1 0 35.363958,0 z"
|
||||
style="opacity:0.14118;color:#000000;fill:url(#radialGradient3381);fill-rule:evenodd"
|
||||
id="path8660"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
x="56.535915"
|
||||
y="1035.6741"
|
||||
width="39.248001"
|
||||
height="12.278"
|
||||
ry="1.625"
|
||||
rx="1.625"
|
||||
display="block"
|
||||
style="color:#000000;fill:url(#linearGradient3383);stroke:#7d7d7d;stroke-linecap:round;display:block"
|
||||
id="rect6951" />
|
||||
<rect
|
||||
x="58.972416"
|
||||
y="1038.3761"
|
||||
width="16"
|
||||
height="7"
|
||||
ry="0"
|
||||
display="block"
|
||||
style="opacity:0.59658999;color:#000000;fill:#7d7d7d;display:block"
|
||||
id="rect6953" />
|
||||
<rect
|
||||
display="block"
|
||||
height="9"
|
||||
x="75.97242"
|
||||
y="1037.3761"
|
||||
width="1"
|
||||
style="color:#000000;display:block"
|
||||
id="rect6957" />
|
||||
</g>
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path1432"
|
||||
style="color:#000000;fill:#a9a9a9;stroke:#000000;stroke-width:0.48586071;display:block"
|
||||
d="m 6.087091,1019.0168 c -2.4783484,-13.3382 7.140839,-12.9964 16.821938,-0.5354 l 2.083662,-1.7011 5.154697,13.4755 -11.796108,-8.0529 2.148807,-1.7542 c -6.962373,-9.2534 -10.105498,-9.9089 -14.389461,-1.3256 z"
|
||||
display="block" />
|
||||
<rect
|
||||
y="1007.8514"
|
||||
x="0.20883489"
|
||||
height="44.57473"
|
||||
width="44.57473"
|
||||
id="rect3032"
|
||||
style="color:#000000;fill:#00ffff;fill-opacity:0;fill-rule:nonzero;stroke:none;stroke-width:0.42527184;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After (image error) Size: 23 KiB |
557
interface/resources/icons/start-script.svg
Normal file
557
interface/resources/icons/start-script.svg
Normal file
|
@ -0,0 +1,557 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="45"
|
||||
height="45"
|
||||
id="svg3827"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.1 r9760"
|
||||
sodipodi:docname="start-script.svg">
|
||||
<defs
|
||||
id="defs3829">
|
||||
<radialGradient
|
||||
r="15.645"
|
||||
cy="36.421"
|
||||
cx="24.837"
|
||||
gradientTransform="matrix(1.1302,0,0,-0.40769251,48.062716,1046.2254)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient3253"
|
||||
xlink:href="#radialGradient8668"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientTransform="translate(51.972416,1005.3761)"
|
||||
y2="36.437"
|
||||
x2="28.061"
|
||||
y1="31.431"
|
||||
x1="28.061"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3239"
|
||||
xlink:href="#linearGradient6971"
|
||||
inkscape:collect="always" />
|
||||
<radialGradient
|
||||
id="radialGradient5031"
|
||||
xlink:href="#linearGradient5060"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cy="486.65"
|
||||
cx="605.71"
|
||||
gradientTransform="matrix(-2.7744,0,0,1.9697,112.76,-872.89)"
|
||||
r="117.14" />
|
||||
<linearGradient
|
||||
id="linearGradient5060">
|
||||
<stop
|
||||
id="stop5062"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop5064"
|
||||
stop-opacity="0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
id="radialGradient5029"
|
||||
xlink:href="#linearGradient5060"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cy="486.65"
|
||||
cx="605.71"
|
||||
gradientTransform="matrix(2.7744,0,0,1.9697,-1891.6,-872.89)"
|
||||
r="117.14" />
|
||||
<linearGradient
|
||||
id="linearGradient5027"
|
||||
x1="302.86"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y1="366.65"
|
||||
gradientTransform="matrix(2.7744,0,0,1.9697,-1892.2,-872.89)"
|
||||
x2="302.86"
|
||||
y2="609.51">
|
||||
<stop
|
||||
id="stop5050"
|
||||
stop-opacity="0"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop5056"
|
||||
offset=".5" />
|
||||
<stop
|
||||
id="stop5052"
|
||||
stop-opacity="0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
id="radialGradient4997"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cy="6.4577"
|
||||
cx="23.447"
|
||||
gradientTransform="matrix(-1.3145,-0.010063,-0.01023,1.3362,46.221,-4.9099)"
|
||||
r="19.062">
|
||||
<stop
|
||||
id="stop4993"
|
||||
stop-color="#fff"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop4995"
|
||||
stop-color="#fff"
|
||||
stop-opacity="0"
|
||||
offset="1" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient1764"
|
||||
x1="33.06"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y1="27.394"
|
||||
gradientTransform="matrix(0.91411,0,0,0.91411,-3.8687,-2.7069)"
|
||||
x2="12.624"
|
||||
y2="12.584">
|
||||
<stop
|
||||
id="stop2189"
|
||||
stop-color="#fff"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop2191"
|
||||
stop-color="#fff"
|
||||
stop-opacity="0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
id="radialGradient8668"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cy="36.421"
|
||||
cx="24.837"
|
||||
gradientTransform="matrix(1,0,0,0.53672,0,16.873)"
|
||||
r="15.645">
|
||||
<stop
|
||||
id="stop8664"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop8666"
|
||||
stop-opacity="0"
|
||||
offset="1" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4209"
|
||||
x1="7.0625"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="24.688"
|
||||
gradientTransform="translate(0.79549,3.7992)"
|
||||
y1="35.281"
|
||||
y2="35.281">
|
||||
<stop
|
||||
id="stop4186"
|
||||
stop-color="#838383"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop4188"
|
||||
stop-color="#bbb"
|
||||
stop-opacity="0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4234"
|
||||
x1="7.6046"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="36.183"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
y1="28.481"
|
||||
y2="40.944">
|
||||
<stop
|
||||
id="stop4230"
|
||||
stop-color="#bbb"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop4232"
|
||||
stop-color="#9f9f9f"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4242"
|
||||
x1="12.277"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="12.222"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
y1="37.206"
|
||||
y2="33.759">
|
||||
<stop
|
||||
id="stop4238"
|
||||
stop-color="#eee"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop4240"
|
||||
stop-color="#eee"
|
||||
stop-opacity="0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
id="radialGradient4250"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cy="2.9585"
|
||||
cx="15.571"
|
||||
gradientTransform="matrix(1.2862,0.7817,-0.71078,1.1696,-2.3543,0.24814)"
|
||||
r="20.936">
|
||||
<stop
|
||||
id="stop4246"
|
||||
stop-color="#e4e4e4"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop4248"
|
||||
stop-color="#d3d3d3"
|
||||
offset="1" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4260"
|
||||
x1="12.378"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="44.096"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
y1="4.4331"
|
||||
y2="47.621">
|
||||
<stop
|
||||
id="stop4256"
|
||||
stop-color="#fff"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop4258"
|
||||
stop-color="#fff"
|
||||
stop-opacity="0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4272"
|
||||
x1="23.688"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x2="23.688"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
y1="11.319"
|
||||
y2="26.357">
|
||||
<stop
|
||||
id="stop4276"
|
||||
stop-color="#fff"
|
||||
stop-opacity=".2549"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop4278"
|
||||
stop-color="#fff"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2553"
|
||||
y2="11.781"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y1="31.965"
|
||||
x2="21.748"
|
||||
x1="33.431">
|
||||
<stop
|
||||
id="stop2557"
|
||||
stop-color="#fff"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop2561"
|
||||
stop-color="#e6e6e6"
|
||||
offset=".5" />
|
||||
<stop
|
||||
id="stop2563"
|
||||
stop-color="#fff"
|
||||
offset=".75" />
|
||||
<stop
|
||||
id="stop2565"
|
||||
stop-color="#e1e1e1"
|
||||
offset=".84167" />
|
||||
<stop
|
||||
id="stop2559"
|
||||
stop-color="#fff"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient6907"
|
||||
y2="16.743"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y1="15.868"
|
||||
x2="8.8953"
|
||||
x1="14.752">
|
||||
<stop
|
||||
id="stop6903"
|
||||
stop-color="#3465a4"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop6905"
|
||||
stop-color="#3465a4"
|
||||
stop-opacity="0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient6931"
|
||||
y2="21.118"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y1="18.25"
|
||||
x2="7"
|
||||
x1="12.25">
|
||||
<stop
|
||||
id="stop6927"
|
||||
stop-color="#204a87"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop6929"
|
||||
stop-color="#204a87"
|
||||
stop-opacity="0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient6971"
|
||||
y2="36.437"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y1="31.431"
|
||||
x2="28.061"
|
||||
x1="28.061">
|
||||
<stop
|
||||
id="stop6967"
|
||||
stop-color="#ddd"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop6969"
|
||||
stop-color="#fdfdfd"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5027"
|
||||
id="linearGradient3248"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.7744,0,0,1.9697,-1892.2,-872.89)"
|
||||
x1="302.86"
|
||||
y1="366.65"
|
||||
x2="302.86"
|
||||
y2="609.51" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient3250"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.7744,0,0,1.9697,-1891.6,-872.89)"
|
||||
cx="605.71"
|
||||
cy="486.65"
|
||||
r="117.14" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient3252"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-2.7744,0,0,1.9697,112.76,-872.89)"
|
||||
cx="605.71"
|
||||
cy="486.65"
|
||||
r="117.14" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4234"
|
||||
id="linearGradient3254"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
x1="7.6046"
|
||||
y1="28.481"
|
||||
x2="36.183"
|
||||
y2="40.944" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#radialGradient4250"
|
||||
id="radialGradient3256"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.2862,0.7817,-0.71078,1.1696,-2.3543,0.24814)"
|
||||
cx="15.571"
|
||||
cy="2.9585"
|
||||
r="20.936" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4209"
|
||||
id="linearGradient3258"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0.79549,3.7992)"
|
||||
x1="7.0625"
|
||||
y1="35.281"
|
||||
x2="24.688"
|
||||
y2="35.281" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4242"
|
||||
id="linearGradient3260"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
x1="12.277"
|
||||
y1="37.206"
|
||||
x2="12.222"
|
||||
y2="33.759" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4272"
|
||||
id="linearGradient3262"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
x1="23.688"
|
||||
y1="11.319"
|
||||
x2="23.688"
|
||||
y2="26.357" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4260"
|
||||
id="linearGradient3264"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0,5.125)"
|
||||
x1="12.378"
|
||||
y1="4.4331"
|
||||
x2="44.096"
|
||||
y2="47.621" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2553"
|
||||
id="linearGradient3266"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="33.431"
|
||||
y1="31.965"
|
||||
x2="21.748"
|
||||
y2="11.781" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#radialGradient8668"
|
||||
id="radialGradient3268"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.1302,0,0,-0.40769251,48.062716,1046.2254)"
|
||||
cx="24.837"
|
||||
cy="36.421"
|
||||
r="15.645" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6971"
|
||||
id="linearGradient3270"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(51.972416,1005.3761)"
|
||||
x1="28.061"
|
||||
y1="31.431"
|
||||
x2="28.061"
|
||||
y2="36.437" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6"
|
||||
inkscape:cx="76.804753"
|
||||
inkscape:cy="13.198134"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1028"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata3832">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Maximillian Merlin</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1007.3622)">
|
||||
<g
|
||||
id="layer1-7"
|
||||
transform="matrix(-0.25019951,0,0,0.28877175,123.44112,917.40972)"
|
||||
style="fill:#696969">
|
||||
<g
|
||||
id="g3257"
|
||||
transform="matrix(1.9175,0,0,1.9175,-607.19,-179.09)"
|
||||
style="fill:#696969">
|
||||
<path
|
||||
id="path3224"
|
||||
d="m 563.06,260.72 -1.25,0.16 -40.15,4.87 -1.66,0.22 0.38,1.62 c 3.78,16.93 -0.59,34.07 -2.88,51.57 l -0.22,1.84 1.81,-0.16 42,-3 1.25,-0.06 0.16,-1.25 c 2.13,-17.86 6.92,-36.12 0.94,-54.62 l -0.38,-1.19 z m -2.18,3.28 c 4.96,16.72 -1.56,33.17 -3.72,50.47 l -35.63,2.78 c 2.25,-16.14 7.03,-29.55 3.78,-46.19 L 560.88,264 z"
|
||||
style="fill:#696969;fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3237"
|
||||
d="m 531.39,275.61 23.34,-4.6"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3243"
|
||||
d="m 532.1,280.91 22.27,-2.83"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3247"
|
||||
d="m 531.92,285.86 22.89,-1.95"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3249"
|
||||
d="m 530.15,292.84 24.22,-2.12"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3251"
|
||||
d="m 529.45,297.53 22.98,-0.8"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3253"
|
||||
d="m 528.65,304.24 22.45,-2.56"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3255"
|
||||
d="m 527.5,309.37 22.81,-1.77"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<rect
|
||||
style="color:#000000;fill:#00ffff;fill-opacity:0;fill-rule:nonzero;stroke:none;stroke-width:0.42527184;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect3032"
|
||||
width="44.57473"
|
||||
height="44.57473"
|
||||
x="0.18852967"
|
||||
y="1007.5989" />
|
||||
<rect
|
||||
style="color:#000000;fill:#00ffff;fill-opacity:0;fill-rule:nonzero;stroke:none;stroke-width:0.42527184;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect3032-4"
|
||||
width="44.57473"
|
||||
height="44.57473"
|
||||
x="84.498352"
|
||||
y="1050.0748" />
|
||||
<g
|
||||
id="g3322"
|
||||
transform="translate(-46.607143,-3.5714285)">
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
width="744.09448"
|
||||
height="1052.3622"
|
||||
transform="translate(0.5864354,0.4607839)"
|
||||
xlink:href="#rect899"
|
||||
id="use1503" />
|
||||
<path
|
||||
d="m 75.506508,1023.3478 1.372845,5.4631 -14.094975,-1.152 2.35e-4,7.2772 14.094975,-1.152 -1.372845,5.1249 13.761293,-7.6113 -13.761293,-7.9499 z"
|
||||
id="rect899"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#d3d3d3;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.77974033;stroke-linecap:round;stroke-linejoin:round" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After (image error) Size: 16 KiB |
163
interface/resources/icons/stop-script.svg
Normal file
163
interface/resources/icons/stop-script.svg
Normal file
|
@ -0,0 +1,163 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="45"
|
||||
height="45"
|
||||
id="svg3827"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.1 r9760"
|
||||
sodipodi:docname="stop-script.svg">
|
||||
<defs
|
||||
id="defs3829" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6"
|
||||
inkscape:cx="15.598703"
|
||||
inkscape:cy="22.861751"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1028"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata3832">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Maximillian Merlin</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1007.3622)">
|
||||
<g
|
||||
id="layer1-7"
|
||||
transform="matrix(-0.25019951,0,0,0.28877175,123.44112,917.40972)"
|
||||
style="fill:#696969">
|
||||
<g
|
||||
id="g3257"
|
||||
transform="matrix(1.9175,0,0,1.9175,-607.19,-179.09)"
|
||||
style="fill:#696969">
|
||||
<path
|
||||
id="path3224"
|
||||
d="m 563.06,260.72 -1.25,0.16 -40.15,4.87 -1.66,0.22 0.38,1.62 c 3.78,16.93 -0.59,34.07 -2.88,51.57 l -0.22,1.84 1.81,-0.16 42,-3 1.25,-0.06 0.16,-1.25 c 2.13,-17.86 6.92,-36.12 0.94,-54.62 l -0.38,-1.19 z m -2.18,3.28 c 4.96,16.72 -1.56,33.17 -3.72,50.47 l -35.63,2.78 c 2.25,-16.14 7.03,-29.55 3.78,-46.19 L 560.88,264 z"
|
||||
style="fill:#696969;fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3237"
|
||||
d="m 531.39,275.61 23.34,-4.6"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3243"
|
||||
d="m 532.1,280.91 22.27,-2.83"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3247"
|
||||
d="m 531.92,285.86 22.89,-1.95"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3249"
|
||||
d="m 530.15,292.84 24.22,-2.12"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3251"
|
||||
d="m 529.45,297.53 22.98,-0.8"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3253"
|
||||
d="m 528.65,304.24 22.45,-2.56"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3255"
|
||||
d="m 527.5,309.37 22.81,-1.77"
|
||||
style="fill:#696969;stroke:#000000;stroke-width:1px"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<rect
|
||||
style="color:#000000;fill:#00ffff;fill-opacity:0;fill-rule:nonzero;stroke:none;stroke-width:0.42527184;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect3032"
|
||||
width="44.57473"
|
||||
height="44.57473"
|
||||
x="0.18852967"
|
||||
y="1007.5989" />
|
||||
<g
|
||||
id="stop"
|
||||
transform="matrix(0.08804464,0,0,0.0856179,29.060719,1033.5397)">
|
||||
<g
|
||||
id="g3004">
|
||||
<path
|
||||
d="M 0,-150 H 62.132 L 150,-62.132 V 62.128 L 62.132,150 H -62.128 L -149,62.132 V -62.128 L -61.132,-150 H 1 0 z"
|
||||
id="stop_octagon"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#e81108" />
|
||||
</g>
|
||||
<g
|
||||
id="g3007"
|
||||
transform="scale(0.95,0.95)">
|
||||
<path
|
||||
d="M 0,-142.5 H 59.025 L 142.5,-59.025 V 59.025 L 59.025,142.5 H -59.025 L -141.549,59.025 V -59.025 L -58.074,-142.5 H 0.951 0.001 z"
|
||||
id="stop_octagon_1_"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:none;stroke:#ffffff;stroke-width:5" />
|
||||
</g>
|
||||
<g
|
||||
id="g3010"
|
||||
transform="scale(1,1.45)">
|
||||
<g
|
||||
id="g3012"
|
||||
style="fill:#ffffff;enable-background:new">
|
||||
<path
|
||||
id="path3014"
|
||||
d="m -124.2,12.152 8.489,-0.742 c 0.401,3.402 1.337,6.192 2.806,8.373 1.469,2.18 3.75,3.943 6.842,5.288 3.092,1.345 6.571,2.018 10.437,2.018 3.433,0 6.463,-0.51 9.092,-1.53 2.628,-1.021 4.584,-2.42 5.868,-4.198 1.283,-1.778 1.925,-3.718 1.925,-5.821 0,-2.134 -0.619,-3.997 -1.855,-5.59 -1.237,-1.592 -3.278,-2.93 -6.123,-4.013 -1.825,-0.711 -5.861,-1.816 -12.107,-3.317 -6.247,-1.5 -10.623,-2.914 -13.127,-4.244 -3.247,-1.7 -5.667,-3.811 -7.26,-6.332 -1.593,-2.52 -2.389,-5.342 -2.389,-8.465 0,-3.433 0.974,-6.641 2.922,-9.625 1.948,-2.984 4.793,-5.249 8.535,-6.796 3.741,-1.546 7.901,-2.319 12.478,-2.319 5.04,0 9.486,0.812 13.336,2.435 3.85,1.623 6.811,4.012 8.883,7.167 2.071,3.154 3.185,6.726 3.34,10.715 l -8.628,0.65 c -0.464,-4.298 -2.034,-7.545 -4.708,-9.741 -2.675,-2.195 -6.626,-3.293 -11.852,-3.293 -5.443,0 -9.409,0.997 -11.898,2.992 -2.489,1.995 -3.734,4.4 -3.734,7.213 0,2.443 0.881,4.453 2.644,6.03 1.731,1.577 6.254,3.194 13.568,4.847 7.313,1.655 12.331,3.101 15.053,4.337 3.958,1.825 6.88,4.136 8.767,6.935 1.886,2.799 2.83,6.023 2.83,9.672 0,3.618 -1.037,7.028 -3.108,10.228 -2.072,3.201 -5.049,5.69 -8.93,7.468 -3.881,1.778 -8.25,2.667 -13.104,2.667 -6.154,0 -11.311,-0.897 -15.47,-2.691 -4.159,-1.793 -7.422,-4.492 -9.788,-8.094 -2.37,-3.604 -3.62,-7.678 -3.74,-12.224 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3016"
|
||||
d="m -40.473,34 v -59.978 h -22.405 v -8.025 h 53.901 v 8.025 H -31.475 V 34 h -8.998 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3018"
|
||||
d="m -4.198,0.88 c 0,-11.287 3.03,-20.124 9.092,-26.51 6.061,-6.385 13.885,-9.579 23.472,-9.579 6.277,0 11.937,1.5 16.978,4.5 5.04,3 8.883,7.182 11.527,12.547 2.644,5.366 3.966,11.45 3.966,18.253 0,6.896 -1.392,13.066 -4.175,18.508 -2.783,5.443 -6.726,9.564 -11.829,12.362 -5.103,2.799 -10.607,4.198 -16.514,4.198 -6.401,0 -12.123,-1.546 -17.163,-4.639 C 6.115,27.428 2.296,23.207 -0.302,17.856 -2.899,12.508 -4.198,6.848 -4.198,0.88 z m 9.277,0.139 c 0,8.195 2.203,14.651 6.61,19.366 4.407,4.716 9.934,7.074 16.583,7.074 6.772,0 12.346,-2.381 16.722,-7.143 4.376,-4.762 6.564,-11.519 6.564,-20.271 0,-5.535 -0.936,-10.367 -2.807,-14.496 -1.871,-4.129 -4.608,-7.329 -8.21,-9.602 -3.603,-2.273 -7.646,-3.41 -12.13,-3.41 -6.371,0 -11.852,2.188 -16.444,6.564 -4.592,4.377 -6.888,11.682 -6.888,21.918 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path3020"
|
||||
d="m 72.433,34 v -68.003 h 25.652 c 4.515,0 7.962,0.217 10.344,0.65 3.34,0.557 6.138,1.616 8.396,3.178 2.257,1.562 4.074,3.75 5.45,6.564 1.376,2.815 2.064,5.907 2.064,9.277 0,5.783 -1.84,10.677 -5.52,14.681 -3.681,4.005 -10.329,6.007 -19.946,6.007 H 81.431 V 34 h -8.999 z m 8.999,-35.672 h 17.581 c 5.813,0 9.942,-1.082 12.385,-3.247 2.442,-2.164 3.665,-5.21 3.665,-9.138 0,-2.845 -0.719,-5.28 -2.157,-7.306 -1.438,-2.025 -3.333,-3.363 -5.682,-4.012 -1.516,-0.401 -4.314,-0.603 -8.396,-0.603 H 81.436 v 24.306 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After (image error) Size: 8 KiB |
|
@ -356,6 +356,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
QMutexLocker locker(&_settingsMutex);
|
||||
_previousScriptLocation = _settings->value("LastScriptLocation", QVariant("")).toString();
|
||||
}
|
||||
//When -url in command line, teleport to location
|
||||
urlGoTo(argc, constArgv);
|
||||
}
|
||||
|
||||
Application::~Application() {
|
||||
|
@ -797,6 +799,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
if (activeWindow() == _window) {
|
||||
bool isShifted = event->modifiers().testFlag(Qt::ShiftModifier);
|
||||
bool isMeta = event->modifiers().testFlag(Qt::ControlModifier);
|
||||
bool isOption = event->modifiers().testFlag(Qt::AltModifier);
|
||||
switch (event->key()) {
|
||||
break;
|
||||
case Qt::Key_BracketLeft:
|
||||
|
@ -820,6 +823,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
break;
|
||||
|
||||
case Qt::Key_E:
|
||||
case Qt::Key_PageUp:
|
||||
if (!_myAvatar->getDriveKeys(UP)) {
|
||||
_myAvatar->jump();
|
||||
}
|
||||
|
@ -831,6 +835,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
break;
|
||||
|
||||
case Qt::Key_C:
|
||||
case Qt::Key_PageDown:
|
||||
_myAvatar->setDriveKeys(DOWN, 1.f);
|
||||
break;
|
||||
|
||||
|
@ -839,9 +844,11 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
break;
|
||||
|
||||
case Qt::Key_S:
|
||||
if (isShifted && isMeta) {
|
||||
if (isShifted && isMeta && !isOption) {
|
||||
Menu::getInstance()->triggerOption(MenuOption::SuppressShortTimings);
|
||||
} else if (!isShifted && isMeta) {
|
||||
} else if (isOption && !isShifted && !isMeta) {
|
||||
Menu::getInstance()->triggerOption(MenuOption::ScriptEditor);
|
||||
} else if (!isOption && !isShifted && isMeta) {
|
||||
takeSnapshot();
|
||||
} else {
|
||||
_myAvatar->setDriveKeys(BACK, 1.f);
|
||||
|
@ -1017,10 +1024,12 @@ void Application::keyReleaseEvent(QKeyEvent* event) {
|
|||
|
||||
switch (event->key()) {
|
||||
case Qt::Key_E:
|
||||
case Qt::Key_PageUp:
|
||||
_myAvatar->setDriveKeys(UP, 0.f);
|
||||
break;
|
||||
|
||||
case Qt::Key_C:
|
||||
case Qt::Key_PageDown:
|
||||
_myAvatar->setDriveKeys(DOWN, 0.f);
|
||||
break;
|
||||
|
||||
|
@ -1679,8 +1688,12 @@ void Application::init() {
|
|||
_audioReflector.setMyAvatar(getAvatar());
|
||||
_audioReflector.setVoxels(_voxels.getTree());
|
||||
_audioReflector.setAudio(getAudio());
|
||||
_audioReflector.setAvatarManager(&_avatarManager);
|
||||
|
||||
connect(getAudio(), &Audio::processInboundAudio, &_audioReflector, &AudioReflector::processInboundAudio,Qt::DirectConnection);
|
||||
connect(getAudio(), &Audio::processLocalAudio, &_audioReflector, &AudioReflector::processLocalAudio,Qt::DirectConnection);
|
||||
connect(getAudio(), &Audio::preProcessOriginalInboundAudio, &_audioReflector,
|
||||
&AudioReflector::preProcessOriginalInboundAudio,Qt::DirectConnection);
|
||||
|
||||
// save settings when avatar changes
|
||||
connect(_myAvatar, &MyAvatar::transformChanged, this, &Application::bumpSettings);
|
||||
|
@ -2201,7 +2214,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
int packetLength = endOfQueryPacket - queryPacket;
|
||||
|
||||
// make sure we still have an active socket
|
||||
nodeList->writeDatagram(reinterpret_cast<const char*>(queryPacket), packetLength, node);
|
||||
nodeList->writeUnverifiedDatagram(reinterpret_cast<const char*>(queryPacket), packetLength, node);
|
||||
|
||||
// Feed number of bytes to corresponding channel of the bandwidth meter
|
||||
_bandwidthMeter.outputStream(BandwidthMeter::VOXELS).updateValue(packetLength);
|
||||
|
@ -2638,6 +2651,8 @@ void Application::displayOverlay() {
|
|||
audioMeterY,
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::Mirror));
|
||||
|
||||
_audio.renderScope(_glWidget->width(), _glWidget->height());
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
if (isClipping) {
|
||||
glColor3f(1, 0, 0);
|
||||
|
@ -2728,7 +2743,7 @@ void Application::displayOverlay() {
|
|||
(Menu::getInstance()->isOptionChecked(MenuOption::Stats) &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth))
|
||||
? 80 : 20;
|
||||
drawText(_glWidget->width() - 100, _glWidget->height() - timerBottom, 0.30f, 1.0f, 0.f, frameTimer, WHITE_TEXT);
|
||||
drawText(_glWidget->width() - 100, _glWidget->height() - timerBottom, 0.30f, 0.0f, 0, frameTimer, WHITE_TEXT);
|
||||
}
|
||||
|
||||
_overlays.render2D();
|
||||
|
@ -3020,6 +3035,7 @@ void Application::resetSensors() {
|
|||
_mouseX = _glWidget->width() / 2;
|
||||
_mouseY = _glWidget->height() / 2;
|
||||
|
||||
_faceplus.reset();
|
||||
_faceshift.reset();
|
||||
_visage.reset();
|
||||
|
||||
|
@ -3111,7 +3127,7 @@ void Application::nodeKilled(SharedNodePointer node) {
|
|||
VoxelPositionSize rootDetails;
|
||||
voxelDetailsForCode(rootCode, rootDetails);
|
||||
|
||||
printf("voxel server going away...... v[%f, %f, %f, %f]\n",
|
||||
qDebug("voxel server going away...... v[%f, %f, %f, %f]",
|
||||
rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
|
||||
|
||||
// Add the jurisditionDetails object to the list of "fade outs"
|
||||
|
@ -3142,7 +3158,7 @@ void Application::nodeKilled(SharedNodePointer node) {
|
|||
VoxelPositionSize rootDetails;
|
||||
voxelDetailsForCode(rootCode, rootDetails);
|
||||
|
||||
printf("particle server going away...... v[%f, %f, %f, %f]\n",
|
||||
qDebug("particle server going away...... v[%f, %f, %f, %f]",
|
||||
rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
|
||||
|
||||
// Add the jurisditionDetails object to the list of "fade outs"
|
||||
|
@ -3223,7 +3239,7 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin
|
|||
|
||||
|
||||
if (jurisdiction->find(nodeUUID) == jurisdiction->end()) {
|
||||
printf("stats from new server... v[%f, %f, %f, %f]\n",
|
||||
qDebug("stats from new server... v[%f, %f, %f, %f]",
|
||||
rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s);
|
||||
|
||||
// Add the jurisditionDetails object to the list of "fade outs"
|
||||
|
@ -3295,13 +3311,14 @@ void Application::stopAllScripts() {
|
|||
bumpSettings();
|
||||
}
|
||||
|
||||
void Application::stopScript(const QString &scriptName)
|
||||
{
|
||||
_scriptEnginesHash.value(scriptName)->stop();
|
||||
qDebug() << "stopping script..." << scriptName;
|
||||
_scriptEnginesHash.remove(scriptName);
|
||||
_runningScriptsWidget->setRunningScripts(getRunningScripts());
|
||||
bumpSettings();
|
||||
void Application::stopScript(const QString &scriptName) {
|
||||
if (_scriptEnginesHash.contains(scriptName)) {
|
||||
_scriptEnginesHash.value(scriptName)->stop();
|
||||
qDebug() << "stopping script..." << scriptName;
|
||||
_scriptEnginesHash.remove(scriptName);
|
||||
_runningScriptsWidget->setRunningScripts(getRunningScripts());
|
||||
bumpSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::reloadAllScripts() {
|
||||
|
@ -3362,7 +3379,10 @@ void Application::uploadSkeleton() {
|
|||
uploadFST(false);
|
||||
}
|
||||
|
||||
void Application::loadScript(const QString& scriptName) {
|
||||
ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScriptFromEditor) {
|
||||
if(loadScriptFromEditor && _scriptEnginesHash.contains(scriptName) && !_scriptEnginesHash[scriptName]->isFinished()){
|
||||
return _scriptEnginesHash[scriptName];
|
||||
}
|
||||
|
||||
// start the script on a new thread...
|
||||
ScriptEngine* scriptEngine = new ScriptEngine(QUrl(scriptName), &_controllerScriptingInterface);
|
||||
|
@ -3370,7 +3390,7 @@ void Application::loadScript(const QString& scriptName) {
|
|||
|
||||
if (!scriptEngine->hasScript()) {
|
||||
qDebug() << "Application::loadScript(), script failed to load...";
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
_runningScriptsWidget->setRunningScripts(getRunningScripts());
|
||||
|
||||
|
@ -3418,8 +3438,12 @@ void Application::loadScript(const QString& scriptName) {
|
|||
workerThread->start();
|
||||
|
||||
// restore the main window's active state
|
||||
_window->activateWindow();
|
||||
if (!loadScriptFromEditor) {
|
||||
_window->activateWindow();
|
||||
}
|
||||
bumpSettings();
|
||||
|
||||
return scriptEngine;
|
||||
}
|
||||
|
||||
void Application::loadDialog() {
|
||||
|
@ -3561,3 +3585,38 @@ void Application::takeSnapshot() {
|
|||
|
||||
Snapshot::saveSnapshot(_glWidget, _myAvatar);
|
||||
}
|
||||
|
||||
void Application::urlGoTo(int argc, const char * constArgv[]) {
|
||||
//Gets the url (hifi://domain/destination/orientation)
|
||||
QString customUrl = getCmdOption(argc, constArgv, "-url");
|
||||
|
||||
if (customUrl.startsWith("hifi://")) {
|
||||
QStringList urlParts = customUrl.remove(0, CUSTOM_URL_SCHEME.length() + 2).split('/', QString::SkipEmptyParts);
|
||||
if (urlParts.count() > 1) {
|
||||
// if url has 2 or more parts, the first one is domain name
|
||||
QString domain = urlParts[0];
|
||||
|
||||
// second part is either a destination coordinate or
|
||||
// a place name
|
||||
QString destination = urlParts[1];
|
||||
|
||||
// any third part is an avatar orientation.
|
||||
QString orientation = urlParts.count() > 2 ? urlParts[2] : QString();
|
||||
|
||||
Menu::goToDomain(domain);
|
||||
|
||||
// goto either @user, #place, or x-xx,y-yy,z-zz
|
||||
// style co-ordinate.
|
||||
Menu::goTo(destination);
|
||||
|
||||
if (!orientation.isEmpty()) {
|
||||
// location orientation
|
||||
Menu::goToOrientation(orientation);
|
||||
}
|
||||
} else if (urlParts.count() == 1) {
|
||||
// location coordinates or place name
|
||||
QString destination = urlParts[0];
|
||||
Menu::goTo(destination);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,7 +121,7 @@ public:
|
|||
~Application();
|
||||
|
||||
void restoreSizeAndPosition();
|
||||
void loadScript(const QString& fileNameString);
|
||||
ScriptEngine* loadScript(const QString& fileNameString, bool loadScriptFromEditor = false);
|
||||
void loadScripts();
|
||||
void storeSizeAndPosition();
|
||||
void clearScriptsBeforeRunning();
|
||||
|
@ -129,6 +129,7 @@ public:
|
|||
void initializeGL();
|
||||
void paintGL();
|
||||
void resizeGL(int width, int height);
|
||||
void urlGoTo(int argc, const char * constArgv[]);
|
||||
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
void keyReleaseEvent(QKeyEvent* event);
|
||||
|
@ -246,6 +247,7 @@ public:
|
|||
void skipVersion(QString latestVersion);
|
||||
|
||||
QStringList getRunningScripts() { return _scriptEnginesHash.keys(); }
|
||||
ScriptEngine* getScriptEngine(QString scriptHash) { return _scriptEnginesHash.contains(scriptHash) ? _scriptEnginesHash[scriptHash] : NULL; }
|
||||
|
||||
signals:
|
||||
|
||||
|
|
|
@ -92,7 +92,14 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) :
|
|||
_processSpatialAudio(false),
|
||||
_spatialAudioStart(0),
|
||||
_spatialAudioFinish(0),
|
||||
_spatialAudioRingBuffer(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL, true) // random access mode
|
||||
_spatialAudioRingBuffer(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL, true), // random access mode
|
||||
_scopeEnabled(false),
|
||||
_scopeEnabledPause(false),
|
||||
_scopeInputOffset(0),
|
||||
_scopeOutputOffset(0),
|
||||
_scopeInput(SAMPLES_PER_SCOPE_WIDTH * sizeof(int16_t), 0),
|
||||
_scopeOutputLeft(SAMPLES_PER_SCOPE_WIDTH * sizeof(int16_t), 0),
|
||||
_scopeOutputRight(SAMPLES_PER_SCOPE_WIDTH * sizeof(int16_t), 0)
|
||||
{
|
||||
// clear the array of locally injected samples
|
||||
memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL);
|
||||
|
@ -575,6 +582,14 @@ void Audio::handleAudioInput() {
|
|||
processProceduralAudio(monoAudioSamples, NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
||||
}
|
||||
|
||||
if (_scopeEnabled && !_scopeEnabledPause) {
|
||||
unsigned int numMonoAudioChannels = 1;
|
||||
unsigned int monoAudioChannel = 0;
|
||||
addBufferToScope(_scopeInput, _scopeInputOffset, monoAudioSamples, monoAudioChannel, numMonoAudioChannels);
|
||||
_scopeInputOffset += NETWORK_SAMPLES_PER_FRAME;
|
||||
_scopeInputOffset %= SAMPLES_PER_SCOPE_WIDTH;
|
||||
}
|
||||
|
||||
NodeList* nodeList = NodeList::getInstance();
|
||||
SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer);
|
||||
|
||||
|
@ -784,6 +799,7 @@ void Audio::processReceivedAudio(const QByteArray& audioByteArray) {
|
|||
_ringBuffer.readSamples((int16_t*)buffer.data(), numNetworkOutputSamples);
|
||||
// Accumulate direct transmission of audio from sender to receiver
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingIncludeOriginal)) {
|
||||
emit preProcessOriginalInboundAudio(sampleTime, buffer, _desiredOutputFormat);
|
||||
addSpatialAudioToBuffer(sampleTime, buffer, numNetworkOutputSamples);
|
||||
}
|
||||
|
||||
|
@ -812,6 +828,30 @@ void Audio::processReceivedAudio(const QByteArray& audioByteArray) {
|
|||
if (_outputDevice) {
|
||||
_outputDevice->write(outputBuffer);
|
||||
}
|
||||
|
||||
if (_scopeEnabled && !_scopeEnabledPause) {
|
||||
unsigned int numAudioChannels = _desiredOutputFormat.channelCount();
|
||||
int16_t* samples = ringBufferSamples;
|
||||
for (int numSamples = numNetworkOutputSamples / numAudioChannels; numSamples > 0; numSamples -= NETWORK_SAMPLES_PER_FRAME) {
|
||||
|
||||
unsigned int audioChannel = 0;
|
||||
addBufferToScope(
|
||||
_scopeOutputLeft,
|
||||
_scopeOutputOffset,
|
||||
samples, audioChannel, numAudioChannels);
|
||||
|
||||
audioChannel = 1;
|
||||
addBufferToScope(
|
||||
_scopeOutputRight,
|
||||
_scopeOutputOffset,
|
||||
samples, audioChannel, numAudioChannels);
|
||||
|
||||
_scopeOutputOffset += NETWORK_SAMPLES_PER_FRAME;
|
||||
_scopeOutputOffset %= SAMPLES_PER_SCOPE_WIDTH;
|
||||
samples += NETWORK_SAMPLES_PER_FRAME * numAudioChannels;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] ringBufferSamples;
|
||||
}
|
||||
}
|
||||
|
@ -1018,6 +1058,140 @@ void Audio::renderToolBox(int x, int y, bool boxed) {
|
|||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void Audio::toggleScopePause() {
|
||||
_scopeEnabledPause = !_scopeEnabledPause;
|
||||
}
|
||||
|
||||
void Audio::toggleScope() {
|
||||
_scopeEnabled = !_scopeEnabled;
|
||||
if (_scopeEnabled) {
|
||||
static const int width = SAMPLES_PER_SCOPE_WIDTH;
|
||||
_scopeInputOffset = 0;
|
||||
_scopeOutputOffset = 0;
|
||||
memset(_scopeInput.data(), 0, width * sizeof(int16_t));
|
||||
memset(_scopeOutputLeft.data(), 0, width * sizeof(int16_t));
|
||||
memset(_scopeOutputRight.data(), 0, width * sizeof(int16_t));
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::addBufferToScope(
|
||||
QByteArray& byteArray, unsigned int frameOffset, const int16_t* source, unsigned int sourceChannel, unsigned int sourceNumberOfChannels) {
|
||||
|
||||
// Constant multiplier to map sample value to vertical size of scope
|
||||
float multiplier = (float)MULTIPLIER_SCOPE_HEIGHT / logf(2.0f);
|
||||
|
||||
// Temporary variable receives sample value
|
||||
float sample;
|
||||
|
||||
// Temporary variable receives mapping of sample value
|
||||
int16_t value;
|
||||
|
||||
// Short int pointer to mapped samples in byte array
|
||||
int16_t* destination = (int16_t*) byteArray.data();
|
||||
|
||||
for (int i = 0; i < NETWORK_SAMPLES_PER_FRAME; i++) {
|
||||
|
||||
sample = (float)source[i * sourceNumberOfChannels + sourceChannel];
|
||||
|
||||
if (sample > 0) {
|
||||
value = (int16_t)(multiplier * logf(sample));
|
||||
} else if (sample < 0) {
|
||||
value = (int16_t)(-multiplier * logf(-sample));
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
destination[i + frameOffset] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::renderScope(int width, int height) {
|
||||
|
||||
if (!_scopeEnabled)
|
||||
return;
|
||||
|
||||
static const float backgroundColor[4] = { 0.2f, 0.2f, 0.2f, 0.6f };
|
||||
static const float gridColor[4] = { 0.3f, 0.3f, 0.3f, 0.6f };
|
||||
static const float inputColor[4] = { 0.3f, .7f, 0.3f, 0.6f };
|
||||
static const float outputLeftColor[4] = { 0.7f, .3f, 0.3f, 0.6f };
|
||||
static const float outputRightColor[4] = { 0.3f, .3f, 0.7f, 0.6f };
|
||||
static const int gridRows = 2;
|
||||
static const int gridCols = 5;
|
||||
|
||||
int x = (width - SAMPLES_PER_SCOPE_WIDTH) / 2;
|
||||
int y = (height - SAMPLES_PER_SCOPE_HEIGHT) / 2;
|
||||
int w = SAMPLES_PER_SCOPE_WIDTH;
|
||||
int h = SAMPLES_PER_SCOPE_HEIGHT;
|
||||
|
||||
renderBackground(backgroundColor, x, y, w, h);
|
||||
renderGrid(gridColor, x, y, w, h, gridRows, gridCols);
|
||||
renderLineStrip(inputColor, x, y, w, _scopeInputOffset, _scopeInput);
|
||||
renderLineStrip(outputLeftColor, x, y, w, _scopeOutputOffset, _scopeOutputLeft);
|
||||
renderLineStrip(outputRightColor, x, y, w, _scopeOutputOffset, _scopeOutputRight);
|
||||
}
|
||||
|
||||
void Audio::renderBackground(const float* color, int x, int y, int width, int height) {
|
||||
|
||||
glColor4fv(color);
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
glVertex2i(x, y);
|
||||
glVertex2i(x + width, y);
|
||||
glVertex2i(x + width, y + height);
|
||||
glVertex2i(x , y + height);
|
||||
|
||||
glEnd();
|
||||
glColor4f(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
void Audio::renderGrid(const float* color, int x, int y, int width, int height, int rows, int cols) {
|
||||
|
||||
glColor4fv(color);
|
||||
glBegin(GL_LINES);
|
||||
|
||||
int dx = width / cols;
|
||||
int dy = height / rows;
|
||||
int tx = x;
|
||||
int ty = y;
|
||||
|
||||
// Draw horizontal grid lines
|
||||
for (int i = rows + 1; --i >= 0; ) {
|
||||
glVertex2i(x, ty);
|
||||
glVertex2i(x + width, ty);
|
||||
ty += dy;
|
||||
}
|
||||
// Draw vertical grid lines
|
||||
for (int i = cols + 1; --i >= 0; ) {
|
||||
glVertex2i(tx, y);
|
||||
glVertex2i(tx, y + height);
|
||||
tx += dx;
|
||||
}
|
||||
glEnd();
|
||||
glColor4f(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
void Audio::renderLineStrip(const float* color, int x, int y, int n, int offset, const QByteArray& byteArray) {
|
||||
|
||||
glColor4fv(color);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
|
||||
int16_t sample;
|
||||
int16_t* samples = ((int16_t*) byteArray.data()) + offset;
|
||||
y += SAMPLES_PER_SCOPE_HEIGHT / 2;
|
||||
for (int i = n - offset; --i >= 0; ) {
|
||||
sample = *samples++;
|
||||
glVertex2i(x++, y - sample);
|
||||
}
|
||||
samples = (int16_t*) byteArray.data();
|
||||
for (int i = offset; --i >= 0; ) {
|
||||
sample = *samples++;
|
||||
glVertex2i(x++, y - sample);
|
||||
}
|
||||
glEnd();
|
||||
glColor4f(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
bool Audio::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo) {
|
||||
bool supportedFormat = false;
|
||||
|
||||
|
@ -1067,7 +1241,6 @@ bool Audio::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo)
|
|||
|
||||
delete _audioOutput;
|
||||
_audioOutput = NULL;
|
||||
_numInputCallbackBytes = 0;
|
||||
|
||||
_loopbackOutputDevice = NULL;
|
||||
delete _loopbackAudioOutput;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <QtCore/QVector>
|
||||
#include <QtMultimedia/QAudioFormat>
|
||||
#include <QVector>
|
||||
#include <QByteArray>
|
||||
|
||||
#include <AbstractAudioInterface.h>
|
||||
#include <AudioRingBuffer.h>
|
||||
|
@ -67,6 +68,7 @@ public:
|
|||
bool mousePressEvent(int x, int y);
|
||||
|
||||
void renderToolBox(int x, int y, bool boxed);
|
||||
void renderScope(int width, int height);
|
||||
|
||||
int getNetworkSampleRate() { return SAMPLE_RATE; }
|
||||
int getNetworkBufferLengthSamplesPerChannel() { return NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; }
|
||||
|
@ -83,6 +85,8 @@ public slots:
|
|||
void toggleMute();
|
||||
void toggleAudioNoiseReduction();
|
||||
void toggleToneInjection();
|
||||
void toggleScope();
|
||||
void toggleScopePause();
|
||||
void toggleAudioSpatialProcessing();
|
||||
|
||||
virtual void handleAudioByteArray(const QByteArray& audioByteArray);
|
||||
|
@ -99,6 +103,7 @@ public slots:
|
|||
|
||||
signals:
|
||||
bool muteToggled();
|
||||
void preProcessOriginalInboundAudio(unsigned int sampleTime, QByteArray& samples, const QAudioFormat& format);
|
||||
void processInboundAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format);
|
||||
void processLocalAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format);
|
||||
|
||||
|
@ -195,6 +200,29 @@ private:
|
|||
int calculateNumberOfFrameSamples(int numBytes);
|
||||
float calculateDeviceToNetworkInputRatio(int numBytes);
|
||||
|
||||
// Audio scope methods for data acquisition
|
||||
void addBufferToScope(
|
||||
QByteArray& byteArray, unsigned int frameOffset, const int16_t* source, unsigned int sourceChannel, unsigned int sourceNumberOfChannels);
|
||||
|
||||
// Audio scope methods for rendering
|
||||
void renderBackground(const float* color, int x, int y, int width, int height);
|
||||
void renderGrid(const float* color, int x, int y, int width, int height, int rows, int cols);
|
||||
void renderLineStrip(const float* color, int x, int y, int n, int offset, const QByteArray& byteArray);
|
||||
|
||||
// Audio scope data
|
||||
static const unsigned int NETWORK_SAMPLES_PER_FRAME = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
|
||||
static const unsigned int FRAMES_PER_SCOPE = 5;
|
||||
static const unsigned int SAMPLES_PER_SCOPE_WIDTH = FRAMES_PER_SCOPE * NETWORK_SAMPLES_PER_FRAME;
|
||||
static const unsigned int MULTIPLIER_SCOPE_HEIGHT = 20;
|
||||
static const unsigned int SAMPLES_PER_SCOPE_HEIGHT = 2 * 15 * MULTIPLIER_SCOPE_HEIGHT;
|
||||
bool _scopeEnabled;
|
||||
bool _scopeEnabledPause;
|
||||
int _scopeInputOffset;
|
||||
int _scopeOutputOffset;
|
||||
QByteArray _scopeInput;
|
||||
QByteArray _scopeOutputLeft;
|
||||
QByteArray _scopeOutputRight;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ const float SLIGHTLY_SHORT = 0.999f; // slightly inside the distance so we're on
|
|||
|
||||
const float DEFAULT_ABSORPTION_RATIO = 0.125; // 12.5% is absorbed
|
||||
const float DEFAULT_DIFFUSION_RATIO = 0.125; // 12.5% is diffused
|
||||
const float DEFAULT_ORIGINAL_ATTENUATION = 1.0f;
|
||||
const float DEFAULT_ECHO_ATTENUATION = 1.0f;
|
||||
|
||||
AudioReflector::AudioReflector(QObject* parent) :
|
||||
QObject(parent),
|
||||
|
@ -36,6 +38,8 @@ AudioReflector::AudioReflector(QObject* parent) :
|
|||
_diffusionFanout(DEFAULT_DIFFUSION_FANOUT),
|
||||
_absorptionRatio(DEFAULT_ABSORPTION_RATIO),
|
||||
_diffusionRatio(DEFAULT_DIFFUSION_RATIO),
|
||||
_originalSourceAttenuation(DEFAULT_ORIGINAL_ATTENUATION),
|
||||
_allEchoesAttenuation(DEFAULT_ECHO_ATTENUATION),
|
||||
_withDiffusion(false),
|
||||
_lastPreDelay(DEFAULT_PRE_DELAY),
|
||||
_lastSoundMsPerMeter(DEFAULT_MS_DELAY_PER_METER),
|
||||
|
@ -43,20 +47,29 @@ AudioReflector::AudioReflector(QObject* parent) :
|
|||
_lastLocalAudioAttenuationFactor(DEFAULT_LOCAL_ATTENUATION_FACTOR),
|
||||
_lastDiffusionFanout(DEFAULT_DIFFUSION_FANOUT),
|
||||
_lastAbsorptionRatio(DEFAULT_ABSORPTION_RATIO),
|
||||
_lastDiffusionRatio(DEFAULT_DIFFUSION_RATIO)
|
||||
_lastDiffusionRatio(DEFAULT_DIFFUSION_RATIO),
|
||||
_lastDontDistanceAttenuate(false),
|
||||
_lastAlternateDistanceAttenuate(false)
|
||||
{
|
||||
_reflections = 0;
|
||||
_diffusionPathCount = 0;
|
||||
_averageAttenuation = 0.0f;
|
||||
_maxAttenuation = 0.0f;
|
||||
_minAttenuation = 0.0f;
|
||||
_averageDelay = 0;
|
||||
_maxDelay = 0;
|
||||
_minDelay = 0;
|
||||
_officialAverageAttenuation = _averageAttenuation = 0.0f;
|
||||
_officialMaxAttenuation = _maxAttenuation = 0.0f;
|
||||
_officialMinAttenuation = _minAttenuation = 0.0f;
|
||||
_officialAverageDelay = _averageDelay = 0;
|
||||
_officialMaxDelay = _maxDelay = 0;
|
||||
_officialMinDelay = _minDelay = 0;
|
||||
_inboundEchoesCount = 0;
|
||||
_inboundEchoesSuppressedCount = 0;
|
||||
_localEchoesCount = 0;
|
||||
_localEchoesSuppressedCount = 0;
|
||||
}
|
||||
|
||||
bool AudioReflector::haveAttributesChanged() {
|
||||
bool withDiffusion = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions);
|
||||
bool dontDistanceAttenuate = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingDontDistanceAttenuate);
|
||||
bool alternateDistanceAttenuate = Menu::getInstance()->isOptionChecked(
|
||||
MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate);
|
||||
|
||||
bool attributesChange = (_withDiffusion != withDiffusion
|
||||
|| _lastPreDelay != _preDelay
|
||||
|
@ -64,7 +77,9 @@ bool AudioReflector::haveAttributesChanged() {
|
|||
|| _lastDistanceAttenuationScalingFactor != _distanceAttenuationScalingFactor
|
||||
|| _lastDiffusionFanout != _diffusionFanout
|
||||
|| _lastAbsorptionRatio != _absorptionRatio
|
||||
|| _lastDiffusionRatio != _diffusionRatio);
|
||||
|| _lastDiffusionRatio != _diffusionRatio
|
||||
|| _lastDontDistanceAttenuate != dontDistanceAttenuate
|
||||
|| _lastAlternateDistanceAttenuate != alternateDistanceAttenuate);
|
||||
|
||||
if (attributesChange) {
|
||||
_withDiffusion = withDiffusion;
|
||||
|
@ -74,6 +89,8 @@ bool AudioReflector::haveAttributesChanged() {
|
|||
_lastDiffusionFanout = _diffusionFanout;
|
||||
_lastAbsorptionRatio = _absorptionRatio;
|
||||
_lastDiffusionRatio = _diffusionRatio;
|
||||
_lastDontDistanceAttenuate = dontDistanceAttenuate;
|
||||
_lastAlternateDistanceAttenuate = alternateDistanceAttenuate;
|
||||
}
|
||||
|
||||
return attributesChange;
|
||||
|
@ -107,19 +124,47 @@ float AudioReflector::getDelayFromDistance(float distance) {
|
|||
|
||||
// attenuation = from the Audio Mixer
|
||||
float AudioReflector::getDistanceAttenuationCoefficient(float distance) {
|
||||
const float DISTANCE_SCALE = 2.5f;
|
||||
const float GEOMETRIC_AMPLITUDE_SCALAR = 0.3f;
|
||||
const float DISTANCE_LOG_BASE = 2.5f;
|
||||
const float DISTANCE_SCALE_LOG = logf(DISTANCE_SCALE) / logf(DISTANCE_LOG_BASE);
|
||||
|
||||
|
||||
bool doDistanceAttenuation = !Menu::getInstance()->isOptionChecked(
|
||||
MenuOption::AudioSpatialProcessingDontDistanceAttenuate);
|
||||
|
||||
bool originalFormula = !Menu::getInstance()->isOptionChecked(
|
||||
MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate);
|
||||
|
||||
float distanceSquareToSource = distance * distance;
|
||||
|
||||
float distanceCoefficient = 1.0f;
|
||||
|
||||
if (doDistanceAttenuation) {
|
||||
|
||||
if (originalFormula) {
|
||||
const float DISTANCE_SCALE = 2.5f;
|
||||
const float GEOMETRIC_AMPLITUDE_SCALAR = 0.3f;
|
||||
const float DISTANCE_LOG_BASE = 2.5f;
|
||||
const float DISTANCE_SCALE_LOG = logf(DISTANCE_SCALE) / logf(DISTANCE_LOG_BASE);
|
||||
|
||||
float distanceSquareToSource = distance * distance;
|
||||
|
||||
// calculate the distance coefficient using the distance to this node
|
||||
float distanceCoefficient = powf(GEOMETRIC_AMPLITUDE_SCALAR,
|
||||
DISTANCE_SCALE_LOG +
|
||||
(0.5f * logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1);
|
||||
|
||||
distanceCoefficient = std::min(1.0f, distanceCoefficient * getDistanceAttenuationScalingFactor());
|
||||
// calculate the distance coefficient using the distance to this node
|
||||
distanceCoefficient = powf(GEOMETRIC_AMPLITUDE_SCALAR,
|
||||
DISTANCE_SCALE_LOG +
|
||||
(0.5f * logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1);
|
||||
distanceCoefficient = std::min(1.0f, distanceCoefficient * getDistanceAttenuationScalingFactor());
|
||||
} else {
|
||||
|
||||
// From Fred: If we wanted something that would produce a tail that could go up to 5 seconds in a
|
||||
// really big room, that would suggest the sound still has to be in the audible after traveling about
|
||||
// 1500 meters. If it’s a sound of average volume, we probably have about 30 db, or 5 base2 orders
|
||||
// of magnitude we can drop down before the sound becomes inaudible. (That’s approximate headroom
|
||||
// based on a few sloppy assumptions.) So we could try a factor like 1 / (2^(D/300)) for starters.
|
||||
// 1 / (2^(D/300))
|
||||
const float DISTANCE_BASE = 2.0f;
|
||||
const float DISTANCE_DENOMINATOR = 300.0f;
|
||||
const float DISTANCE_NUMERATOR = 300.0f;
|
||||
distanceCoefficient = DISTANCE_NUMERATOR / powf(DISTANCE_BASE, (distance / DISTANCE_DENOMINATOR ));
|
||||
distanceCoefficient = std::min(1.0f, distanceCoefficient * getDistanceAttenuationScalingFactor());
|
||||
}
|
||||
}
|
||||
|
||||
return distanceCoefficient;
|
||||
}
|
||||
|
@ -236,11 +281,13 @@ void AudioReflector::injectAudiblePoint(AudioSource source, const AudiblePoint&
|
|||
rightSample = originalSamplesData[(sample * NUMBER_OF_CHANNELS) + 1];
|
||||
}
|
||||
|
||||
attenuatedLeftSamplesData[sample * NUMBER_OF_CHANNELS] = leftSample * leftEarAttenuation;
|
||||
attenuatedLeftSamplesData[sample * NUMBER_OF_CHANNELS] =
|
||||
leftSample * leftEarAttenuation * _allEchoesAttenuation;
|
||||
attenuatedLeftSamplesData[sample * NUMBER_OF_CHANNELS + 1] = 0;
|
||||
|
||||
attenuatedRightSamplesData[sample * NUMBER_OF_CHANNELS] = 0;
|
||||
attenuatedRightSamplesData[sample * NUMBER_OF_CHANNELS + 1] = rightSample * rightEarAttenuation;
|
||||
attenuatedRightSamplesData[sample * NUMBER_OF_CHANNELS + 1] =
|
||||
rightSample * rightEarAttenuation * _allEchoesAttenuation;
|
||||
}
|
||||
|
||||
// now inject the attenuated array with the appropriate delay
|
||||
|
@ -249,9 +296,25 @@ void AudioReflector::injectAudiblePoint(AudioSource source, const AudiblePoint&
|
|||
|
||||
_audio->addSpatialAudioToBuffer(sampleTimeLeft, attenuatedLeftSamples, totalNumberOfSamples);
|
||||
_audio->addSpatialAudioToBuffer(sampleTimeRight, attenuatedRightSamples, totalNumberOfSamples);
|
||||
|
||||
_injectedEchoes++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AudioReflector::preProcessOriginalInboundAudio(unsigned int sampleTime,
|
||||
QByteArray& samples, const QAudioFormat& format) {
|
||||
|
||||
if (_originalSourceAttenuation != 1.0f) {
|
||||
int numberOfSamples = (samples.size() / sizeof(int16_t));
|
||||
int16_t* sampleData = (int16_t*)samples.data();
|
||||
for (int i = 0; i < numberOfSamples; i++) {
|
||||
sampleData[i] = sampleData[i] * _originalSourceAttenuation;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AudioReflector::processLocalAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio)) {
|
||||
const int NUM_CHANNELS_INPUT = 1;
|
||||
|
@ -272,6 +335,8 @@ void AudioReflector::processLocalAudio(unsigned int sampleTime, const QByteArray
|
|||
_localAudioDelays.clear();
|
||||
_localEchoesSuppressed.clear();
|
||||
echoAudio(LOCAL_AUDIO, sampleTime, stereoInputData, outputFormat);
|
||||
_localEchoesCount = _localAudioDelays.size();
|
||||
_localEchoesSuppressedCount = _localEchoesSuppressed.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -280,9 +345,13 @@ void AudioReflector::processInboundAudio(unsigned int sampleTime, const QByteArr
|
|||
_inboundAudioDelays.clear();
|
||||
_inboundEchoesSuppressed.clear();
|
||||
echoAudio(INBOUND_AUDIO, sampleTime, samples, format);
|
||||
_inboundEchoesCount = _inboundAudioDelays.size();
|
||||
_inboundEchoesSuppressedCount = _inboundEchoesSuppressed.size();
|
||||
}
|
||||
|
||||
void AudioReflector::echoAudio(AudioSource source, unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format) {
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
_maxDelay = 0;
|
||||
_maxAttenuation = 0.0f;
|
||||
_minDelay = std::numeric_limits<int>::max();
|
||||
|
@ -292,14 +361,20 @@ void AudioReflector::echoAudio(AudioSource source, unsigned int sampleTime, cons
|
|||
_totalAttenuation = 0.0f;
|
||||
_attenuationCount = 0;
|
||||
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
// depending on if we're processing local or external audio, pick the correct points vector
|
||||
QVector<AudiblePoint>& audiblePoints = source == INBOUND_AUDIO ? _inboundAudiblePoints : _localAudiblePoints;
|
||||
|
||||
int injectCalls = 0;
|
||||
_injectedEchoes = 0;
|
||||
foreach(const AudiblePoint& audiblePoint, audiblePoints) {
|
||||
injectCalls++;
|
||||
injectAudiblePoint(source, audiblePoint, samples, sampleTime, format.sampleRate());
|
||||
}
|
||||
|
||||
/*
|
||||
qDebug() << "injectCalls=" << injectCalls;
|
||||
qDebug() << "_injectedEchoes=" << _injectedEchoes;
|
||||
*/
|
||||
|
||||
_averageDelay = _delayCount == 0 ? 0 : _totalDelay / _delayCount;
|
||||
_averageAttenuation = _attenuationCount == 0 ? 0 : _totalAttenuation / _attenuationCount;
|
||||
|
@ -308,6 +383,14 @@ void AudioReflector::echoAudio(AudioSource source, unsigned int sampleTime, cons
|
|||
_minDelay = 0.0f;
|
||||
_minAttenuation = 0.0f;
|
||||
}
|
||||
|
||||
_officialMaxDelay = _maxDelay;
|
||||
_officialMinDelay = _minDelay;
|
||||
_officialMaxAttenuation = _maxAttenuation;
|
||||
_officialMinAttenuation = _minAttenuation;
|
||||
_officialAverageDelay = _averageDelay;
|
||||
_officialAverageAttenuation = _averageAttenuation;
|
||||
|
||||
}
|
||||
|
||||
void AudioReflector::drawVector(const glm::vec3& start, const glm::vec3& end, const glm::vec3& color) {
|
||||
|
@ -359,6 +442,19 @@ void AudioReflector::addAudioPath(AudioSource source, const glm::vec3& origin, c
|
|||
audioPaths.push_back(path);
|
||||
}
|
||||
|
||||
// NOTE: This is a prototype of an eventual utility that will identify the speaking sources for the inbound audio
|
||||
// stream. It's not currently called but will be added soon.
|
||||
void AudioReflector::identifyAudioSources() {
|
||||
// looking for audio sources....
|
||||
foreach (const AvatarSharedPointer& avatarPointer, _avatarManager->getAvatarHash()) {
|
||||
Avatar* avatar = static_cast<Avatar*>(avatarPointer.data());
|
||||
if (!avatar->isInitialized()) {
|
||||
continue;
|
||||
}
|
||||
qDebug() << "avatar["<< avatar <<"] loudness:" << avatar->getAudioLoudness();
|
||||
}
|
||||
}
|
||||
|
||||
void AudioReflector::calculateAllReflections() {
|
||||
// only recalculate when we've moved, or if the attributes have changed
|
||||
// TODO: what about case where new voxels are added in front of us???
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
// Created by Brad Hefta-Gaub on 4/2/2014
|
||||
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef interface_AudioReflector_h
|
||||
#define interface_AudioReflector_h
|
||||
|
@ -15,6 +18,7 @@
|
|||
|
||||
#include "Audio.h"
|
||||
#include "avatar/MyAvatar.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
|
||||
enum AudioSource {
|
||||
LOCAL_AUDIO,
|
||||
|
@ -69,25 +73,27 @@ public:
|
|||
void setVoxels(VoxelTree* voxels) { _voxels = voxels; }
|
||||
void setMyAvatar(MyAvatar* myAvatar) { _myAvatar = myAvatar; }
|
||||
void setAudio(Audio* audio) { _audio = audio; }
|
||||
void setAvatarManager(AvatarManager* avatarManager) { _avatarManager = avatarManager; }
|
||||
|
||||
void render(); /// must be called in the application render loop
|
||||
|
||||
void preProcessOriginalInboundAudio(unsigned int sampleTime, QByteArray& samples, const QAudioFormat& format);
|
||||
void processInboundAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format);
|
||||
void processLocalAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format);
|
||||
|
||||
public slots:
|
||||
// statistics
|
||||
int getReflections() const { return _reflections; }
|
||||
float getAverageDelayMsecs() const { return _averageDelay; }
|
||||
float getAverageAttenuation() const { return _averageAttenuation; }
|
||||
float getMaxDelayMsecs() const { return _maxDelay; }
|
||||
float getMaxAttenuation() const { return _maxAttenuation; }
|
||||
float getMinDelayMsecs() const { return _minDelay; }
|
||||
float getMinAttenuation() const { return _minAttenuation; }
|
||||
float getAverageDelayMsecs() const { return _officialAverageDelay; }
|
||||
float getAverageAttenuation() const { return _officialAverageAttenuation; }
|
||||
float getMaxDelayMsecs() const { return _officialMaxDelay; }
|
||||
float getMaxAttenuation() const { return _officialMaxAttenuation; }
|
||||
float getMinDelayMsecs() const { return _officialMinDelay; }
|
||||
float getMinAttenuation() const { return _officialMinAttenuation; }
|
||||
float getDelayFromDistance(float distance);
|
||||
int getDiffusionPathCount() const { return _diffusionPathCount; }
|
||||
int getEchoesInjected() const { return _inboundAudioDelays.size() + _localAudioDelays.size(); }
|
||||
int getEchoesSuppressed() const { return _inboundEchoesSuppressed.size() + _localEchoesSuppressed.size(); }
|
||||
int getEchoesInjected() const { return _inboundEchoesCount + _localEchoesCount; }
|
||||
int getEchoesSuppressed() const { return _inboundEchoesSuppressedCount + _localEchoesSuppressedCount; }
|
||||
|
||||
/// ms of delay added to all echos
|
||||
float getPreDelay() const { return _preDelay; }
|
||||
|
@ -126,12 +132,19 @@ public slots:
|
|||
float getReflectiveRatio() const { return (1.0f - (_absorptionRatio + _diffusionRatio)); }
|
||||
void setReflectiveRatio(float ratio);
|
||||
|
||||
// wet/dry mix - these don't affect any reflection calculations, only the final mix volumes
|
||||
float getOriginalSourceAttenuation() const { return _originalSourceAttenuation; }
|
||||
void setOriginalSourceAttenuation(float value) { _originalSourceAttenuation = value; }
|
||||
float getEchoesAttenuation() const { return _allEchoesAttenuation; }
|
||||
void setEchoesAttenuation(float value) { _allEchoesAttenuation = value; }
|
||||
|
||||
signals:
|
||||
|
||||
private:
|
||||
VoxelTree* _voxels; // used to access voxel scene
|
||||
MyAvatar* _myAvatar; // access to listener
|
||||
Audio* _audio; // access to audio API
|
||||
AvatarManager* _avatarManager; // access to avatar manager API
|
||||
|
||||
// Helpers for drawing
|
||||
void drawVector(const glm::vec3& start, const glm::vec3& end, const glm::vec3& color);
|
||||
|
@ -147,11 +160,18 @@ private:
|
|||
float _averageDelay;
|
||||
float _maxDelay;
|
||||
float _minDelay;
|
||||
float _officialAverageDelay;
|
||||
float _officialMaxDelay;
|
||||
float _officialMinDelay;
|
||||
int _attenuationCount;
|
||||
float _totalAttenuation;
|
||||
float _averageAttenuation;
|
||||
float _maxAttenuation;
|
||||
float _minAttenuation;
|
||||
float _officialAverageAttenuation;
|
||||
float _officialMaxAttenuation;
|
||||
float _officialMinAttenuation;
|
||||
|
||||
|
||||
glm::vec3 _listenerPosition;
|
||||
glm::vec3 _origin;
|
||||
|
@ -161,11 +181,15 @@ private:
|
|||
QVector<AudiblePoint> _inboundAudiblePoints; /// the audible points that have been calculated from the inbound audio paths
|
||||
QMap<float, float> _inboundAudioDelays; /// delay times for currently injected audio points
|
||||
QVector<float> _inboundEchoesSuppressed; /// delay times for currently injected audio points
|
||||
int _inboundEchoesCount;
|
||||
int _inboundEchoesSuppressedCount;
|
||||
|
||||
QVector<AudioPath*> _localAudioPaths; /// audio paths we're processing for local audio
|
||||
QVector<AudiblePoint> _localAudiblePoints; /// the audible points that have been calculated from the local audio paths
|
||||
QMap<float, float> _localAudioDelays; /// delay times for currently injected audio points
|
||||
QVector<float> _localEchoesSuppressed; /// delay times for currently injected audio points
|
||||
int _localEchoesCount;
|
||||
int _localEchoesSuppressedCount;
|
||||
|
||||
// adds a sound source to begin an audio path trace, these can be the initial sound sources with their directional properties,
|
||||
// as well as diffusion sound sources
|
||||
|
@ -182,6 +206,7 @@ private:
|
|||
void calculateAllReflections();
|
||||
int countDiffusionPaths();
|
||||
glm::vec3 getFaceNormal(BoxFace face);
|
||||
void identifyAudioSources();
|
||||
|
||||
void injectAudiblePoint(AudioSource source, const AudiblePoint& audiblePoint, const QByteArray& samples, unsigned int sampleTime, int sampleRate);
|
||||
void echoAudio(AudioSource source, unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format);
|
||||
|
@ -197,13 +222,16 @@ private:
|
|||
float _distanceAttenuationScalingFactor;
|
||||
float _localAudioAttenuationFactor;
|
||||
float _combFilterWindow;
|
||||
|
||||
int _diffusionFanout; // number of points of diffusion from each reflection point
|
||||
|
||||
// all elements have the same material for now...
|
||||
float _absorptionRatio;
|
||||
float _diffusionRatio;
|
||||
float _reflectiveRatio;
|
||||
|
||||
// wet/dry mix - these don't affect any reflection calculations, only the final mix volumes
|
||||
float _originalSourceAttenuation; /// each sample of original signal will be multiplied by this
|
||||
float _allEchoesAttenuation; /// each sample of all echo signals will be multiplied by this
|
||||
|
||||
// remember the last known values at calculation
|
||||
bool haveAttributesChanged();
|
||||
|
@ -216,6 +244,10 @@ private:
|
|||
int _lastDiffusionFanout;
|
||||
float _lastAbsorptionRatio;
|
||||
float _lastDiffusionRatio;
|
||||
bool _lastDontDistanceAttenuate;
|
||||
bool _lastAlternateDistanceAttenuate;
|
||||
|
||||
int _injectedEchoes;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ Camera::Camera() :
|
|||
_idealPosition(0.0f, 0.0f, 0.0f),
|
||||
_targetPosition(0.0f, 0.0f, 0.0f),
|
||||
_fieldOfView(DEFAULT_FIELD_OF_VIEW_DEGREES),
|
||||
_aspectRatio(16.f/9.f),
|
||||
_aspectRatio(16.0f/9.0f),
|
||||
_nearClip(0.08f), // default
|
||||
_farClip(50.0f * TREE_SCALE), // default
|
||||
_upShift(0.0f),
|
||||
|
@ -94,8 +94,8 @@ void Camera::updateFollowMode(float deltaTime) {
|
|||
|
||||
// derive t from tightness
|
||||
float t = _tightness * _modeShift * deltaTime;
|
||||
if (t > 1.0) {
|
||||
t = 1.0;
|
||||
if (t > 1.0f) {
|
||||
t = 1.0f;
|
||||
}
|
||||
|
||||
// handle keepLookingAt
|
||||
|
|
|
@ -78,7 +78,7 @@ void DatagramProcessor::processDatagrams() {
|
|||
OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow();
|
||||
int flightTime = arrivedAt - sentAt;
|
||||
|
||||
printf("got PacketType_VOXEL_DATA, sequence:%d flightTime:%d\n", sequence, flightTime);
|
||||
qDebug("got PacketType_VOXEL_DATA, sequence:%d flightTime:%d", sequence, flightTime);
|
||||
}
|
||||
|
||||
SharedNodePointer matchedNode = NodeList::getInstance()->sendingNodeForPacket(incomingPacket);
|
||||
|
|
|
@ -196,6 +196,7 @@ Menu::Menu() :
|
|||
|
||||
QMenu* toolsMenu = addMenu("Tools");
|
||||
addActionToQMenuAndActionHash(toolsMenu, MenuOption::MetavoxelEditor, 0, this, SLOT(showMetavoxelEditor()));
|
||||
addActionToQMenuAndActionHash(toolsMenu, MenuOption::ScriptEditor, Qt::ALT | Qt::Key_S, this, SLOT(showScriptEditor()));
|
||||
|
||||
#ifdef HAVE_QXMPP
|
||||
_chatAction = addActionToQMenuAndActionHash(toolsMenu,
|
||||
|
@ -260,6 +261,9 @@ Menu::Menu() :
|
|||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Bandwidth, 0, true);
|
||||
addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, this, SLOT(bandwidthDetails()));
|
||||
addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0, this, SLOT(octreeStatsDetails()));
|
||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::AudioScope, 0, false,
|
||||
appInstance->getAudio(),
|
||||
SLOT(toggleScope()));
|
||||
|
||||
QMenu* developerMenu = addMenu("Developer");
|
||||
|
||||
|
@ -316,7 +320,8 @@ Menu::Menu() :
|
|||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Visage, 0, true,
|
||||
appInstance->getVisage(), SLOT(updateEnabled()));
|
||||
#endif
|
||||
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::GlowWhenSpeaking, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::ChatCircling, 0, false);
|
||||
|
||||
QMenu* handOptionsMenu = developerMenu->addMenu("Hand Options");
|
||||
|
@ -385,6 +390,11 @@ Menu::Menu() :
|
|||
false,
|
||||
appInstance->getAudio(),
|
||||
SLOT(toggleToneInjection()));
|
||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioScopePause,
|
||||
Qt::CTRL | Qt::Key_P,
|
||||
false,
|
||||
appInstance->getAudio(),
|
||||
SLOT(toggleScopePause()));
|
||||
|
||||
QMenu* spatialAudioMenu = audioDebugMenu->addMenu("Spatial Audio");
|
||||
|
||||
|
@ -430,6 +440,14 @@ Menu::Menu() :
|
|||
Qt::CTRL | Qt::SHIFT | Qt::Key_A,
|
||||
true);
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingDontDistanceAttenuate,
|
||||
Qt::CTRL | Qt::SHIFT | Qt::Key_Y,
|
||||
false);
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate,
|
||||
Qt::CTRL | Qt::SHIFT | Qt::Key_U,
|
||||
false);
|
||||
|
||||
addActionToQMenuAndActionHash(developerMenu, MenuOption::PasteToVoxel,
|
||||
Qt::CTRL | Qt::SHIFT | Qt::Key_V,
|
||||
this,
|
||||
|
@ -1127,6 +1145,13 @@ void Menu::showMetavoxelEditor() {
|
|||
_MetavoxelEditor->raise();
|
||||
}
|
||||
|
||||
void Menu::showScriptEditor() {
|
||||
if(!_ScriptEditor || !_ScriptEditor->isVisible()) {
|
||||
_ScriptEditor = new ScriptEditorWindow();
|
||||
}
|
||||
_ScriptEditor->raise();
|
||||
}
|
||||
|
||||
void Menu::showChat() {
|
||||
QMainWindow* mainWindow = Application::getInstance()->getWindow();
|
||||
if (!_chatWindow) {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "location/LocationManager.h"
|
||||
#include "ui/PreferencesDialog.h"
|
||||
#include "ui/ChatWindow.h"
|
||||
#include "ui/ScriptEditorWindow.h"
|
||||
|
||||
const float ADJUST_LOD_DOWN_FPS = 40.0;
|
||||
const float ADJUST_LOD_UP_FPS = 55.0;
|
||||
|
@ -135,10 +136,10 @@ public:
|
|||
|
||||
void removeAction(QMenu* menu, const QString& actionName);
|
||||
|
||||
bool goToDestination(QString destination);
|
||||
void goToOrientation(QString orientation);
|
||||
void goToDomain(const QString newDomain);
|
||||
void goTo(QString destination);
|
||||
bool static goToDestination(QString destination);
|
||||
void static goToOrientation(QString orientation);
|
||||
void static goToDomain(const QString newDomain);
|
||||
void static goTo(QString destination);
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -178,6 +179,7 @@ private slots:
|
|||
void cycleFrustumRenderMode();
|
||||
void runTests();
|
||||
void showMetavoxelEditor();
|
||||
void showScriptEditor();
|
||||
void showChat();
|
||||
void toggleChat();
|
||||
void audioMuteToggled();
|
||||
|
@ -229,6 +231,7 @@ private:
|
|||
FrustumDrawMode _frustumDrawMode;
|
||||
ViewFrustumOffset _viewFrustumOffset;
|
||||
QPointer<MetavoxelEditor> _MetavoxelEditor;
|
||||
QPointer<ScriptEditorWindow> _ScriptEditor;
|
||||
QPointer<ChatWindow> _chatWindow;
|
||||
OctreeStatsDialog* _octreeStatsDialog;
|
||||
LodToolsDialog* _lodToolsDialog;
|
||||
|
@ -257,8 +260,9 @@ namespace MenuOption {
|
|||
const QString AmbientOcclusion = "Ambient Occlusion";
|
||||
const QString Atmosphere = "Atmosphere";
|
||||
const QString AudioNoiseReduction = "Audio Noise Reduction";
|
||||
const QString AudioScope = "Audio Scope";
|
||||
const QString AudioScopePause = "Pause Audio Scope";
|
||||
const QString AudioToneInjection = "Inject Test Tone";
|
||||
|
||||
const QString AudioSpatialProcessing = "Audio Spatial Processing";
|
||||
const QString AudioSpatialProcessingHeadOriented = "Head Oriented";
|
||||
const QString AudioSpatialProcessingIncludeOriginal = "Includes Network Original";
|
||||
|
@ -269,6 +273,10 @@ namespace MenuOption {
|
|||
const QString AudioSpatialProcessingSlightlyRandomSurfaces = "Slightly Random Surfaces";
|
||||
const QString AudioSpatialProcessingStereoSource = "Stereo Source";
|
||||
const QString AudioSpatialProcessingWithDiffusions = "With Diffusions";
|
||||
const QString AudioSpatialProcessingDontDistanceAttenuate = "Don't calculate distance attenuation";
|
||||
const QString AudioSpatialProcessingAlternateDistanceAttenuate = "Alternate distance attenuation";
|
||||
|
||||
|
||||
|
||||
const QString Avatars = "Avatars";
|
||||
const QString Bandwidth = "Bandwidth Display";
|
||||
|
@ -301,6 +309,7 @@ namespace MenuOption {
|
|||
const QString Fullscreen = "Fullscreen";
|
||||
const QString FullscreenMirror = "Fullscreen Mirror";
|
||||
const QString GlowMode = "Cycle Glow Mode";
|
||||
const QString GlowWhenSpeaking = "Glow When Speaking";
|
||||
const QString GoHome = "Go Home";
|
||||
const QString GoTo = "Go To...";
|
||||
const QString GoToDomain = "Go To Domain...";
|
||||
|
@ -341,6 +350,7 @@ namespace MenuOption {
|
|||
const QString ResetAvatarSize = "Reset Avatar Size";
|
||||
const QString RunningScripts = "Running Scripts";
|
||||
const QString RunTimingTests = "Run Timing Tests";
|
||||
const QString ScriptEditor = "Script Editor...";
|
||||
const QString SettingsExport = "Export Settings";
|
||||
const QString SettingsImport = "Import Settings";
|
||||
const QString Shadows = "Shadows";
|
||||
|
|
|
@ -34,6 +34,7 @@ static const QString TEXDIR_FIELD = "texdir";
|
|||
static const QString LOD_FIELD = "lod";
|
||||
|
||||
static const QString S3_URL = "http://highfidelity-public.s3-us-west-1.amazonaws.com";
|
||||
static const QString DATA_SERVER_URL = "https://data-web.highfidelity.io";
|
||||
static const QString MODEL_URL = "/api/v1/models";
|
||||
|
||||
static const QString SETTING_NAME = "LastModelUploadLocation";
|
||||
|
@ -201,14 +202,14 @@ void ModelUploader::send() {
|
|||
|
||||
JSONCallbackParameters callbackParams;
|
||||
callbackParams.jsonCallbackReceiver = this;
|
||||
callbackParams.jsonCallbackMethod = "uploadSuccess";
|
||||
callbackParams.jsonCallbackMethod = "checkJSON";
|
||||
callbackParams.errorCallbackReceiver = this;
|
||||
callbackParams.errorCallbackMethod = "uploadFailed";
|
||||
callbackParams.updateReciever = this;
|
||||
callbackParams.updateSlot = SLOT(uploadUpdate(qint64, qint64));
|
||||
|
||||
AccountManager::getInstance().authenticatedRequest(MODEL_URL, QNetworkAccessManager::PostOperation, callbackParams, QByteArray(), _dataMultiPart);
|
||||
_dataMultiPart = NULL;
|
||||
AccountManager::getInstance().authenticatedRequest(MODEL_URL + "/" + QFileInfo(_url).baseName(),
|
||||
QNetworkAccessManager::GetOperation,
|
||||
callbackParams);
|
||||
|
||||
qDebug() << "Sending model...";
|
||||
_progressDialog = new QDialog();
|
||||
_progressBar = new QProgressBar(_progressDialog);
|
||||
|
@ -226,6 +227,61 @@ void ModelUploader::send() {
|
|||
_progressBar = NULL;
|
||||
}
|
||||
|
||||
void ModelUploader::checkJSON(const QJsonObject& jsonResponse) {
|
||||
if (jsonResponse.contains("status") && jsonResponse.value("status").toString() == "success") {
|
||||
qDebug() << "status : success";
|
||||
JSONCallbackParameters callbackParams;
|
||||
callbackParams.jsonCallbackReceiver = this;
|
||||
callbackParams.jsonCallbackMethod = "uploadSuccess";
|
||||
callbackParams.errorCallbackReceiver = this;
|
||||
callbackParams.errorCallbackMethod = "uploadFailed";
|
||||
callbackParams.updateReciever = this;
|
||||
callbackParams.updateSlot = SLOT(uploadUpdate(qint64, qint64));
|
||||
|
||||
if (jsonResponse.contains("exists") && jsonResponse.value("exists").toBool()) {
|
||||
qDebug() << "exists : true";
|
||||
if (jsonResponse.contains("can_update") && jsonResponse.value("can_update").toBool()) {
|
||||
qDebug() << "can_update : true";
|
||||
|
||||
AccountManager::getInstance().authenticatedRequest(MODEL_URL + "/" + QFileInfo(_url).baseName(),
|
||||
QNetworkAccessManager::PutOperation,
|
||||
callbackParams,
|
||||
QByteArray(),
|
||||
_dataMultiPart);
|
||||
_dataMultiPart = NULL;
|
||||
} else {
|
||||
qDebug() << "can_update : false";
|
||||
if (_progressDialog) {
|
||||
_progressDialog->reject();
|
||||
}
|
||||
QMessageBox::warning(NULL,
|
||||
QString("ModelUploader::checkJSON()"),
|
||||
QString("This model already exist and is own by someone else."),
|
||||
QMessageBox::Ok);
|
||||
deleteLater();
|
||||
}
|
||||
} else {
|
||||
qDebug() << "exists : false";
|
||||
AccountManager::getInstance().authenticatedRequest(MODEL_URL,
|
||||
QNetworkAccessManager::PostOperation,
|
||||
callbackParams,
|
||||
QByteArray(),
|
||||
_dataMultiPart);
|
||||
_dataMultiPart = NULL;
|
||||
}
|
||||
} else {
|
||||
qDebug() << "status : failed";
|
||||
if (_progressDialog) {
|
||||
_progressDialog->reject();
|
||||
}
|
||||
QMessageBox::warning(NULL,
|
||||
QString("ModelUploader::checkJSON()"),
|
||||
QString("Something went wrong with the data-server."),
|
||||
QMessageBox::Ok);
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void ModelUploader::uploadUpdate(qint64 bytesSent, qint64 bytesTotal) {
|
||||
if (_progressDialog) {
|
||||
_progressBar->setRange(0, bytesTotal);
|
||||
|
@ -249,11 +305,11 @@ void ModelUploader::uploadFailed(QNetworkReply::NetworkError errorCode, const QS
|
|||
if (_progressDialog) {
|
||||
_progressDialog->reject();
|
||||
}
|
||||
qDebug() << "Model upload failed (" << errorCode << "): " << errorString;
|
||||
QMessageBox::warning(NULL,
|
||||
QString("ModelUploader::uploadFailed()"),
|
||||
QString("There was a problem with your upload, please try again later."),
|
||||
QMessageBox::Ok);
|
||||
qDebug() << "Model upload failed (" << errorCode << "): " << errorString;
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ public slots:
|
|||
void send();
|
||||
|
||||
private slots:
|
||||
void checkJSON(const QJsonObject& jsonResponse);
|
||||
void uploadUpdate(qint64 bytesSent, qint64 bytesTotal);
|
||||
void uploadSuccess(const QJsonObject& jsonResponse);
|
||||
void uploadFailed(QNetworkReply::NetworkError errorCode, const QString& errorString);
|
||||
|
|
95
interface/src/ScriptHighlighting.cpp
Normal file
95
interface/src/ScriptHighlighting.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
//
|
||||
// ScriptHighlighting.cpp
|
||||
// interface/src
|
||||
//
|
||||
// Created by Thijs Wenker on 4/15/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ScriptHighlighting.h"
|
||||
#include <QTextDocument>
|
||||
|
||||
ScriptHighlighting::ScriptHighlighting(QTextDocument* parent) :
|
||||
QSyntaxHighlighter(parent)
|
||||
{
|
||||
_keywordRegex = QRegExp("\\b(break|case|catch|continue|debugger|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|this|throw|try|typeof|var|void|while|with)\\b");
|
||||
_qoutedTextRegex = QRegExp("\".*\"");
|
||||
_multiLineCommentBegin = QRegExp("/\\*");
|
||||
_multiLineCommentEnd = QRegExp("\\*/");
|
||||
_numberRegex = QRegExp("[0-9]+(\\.[0-9]+){0,1}");
|
||||
_singleLineComment = QRegExp("//[^\n]*");
|
||||
_truefalseRegex = QRegExp("\\b(true|false)\\b");
|
||||
}
|
||||
|
||||
void ScriptHighlighting::highlightBlock(const QString& text) {
|
||||
this->highlightKeywords(text);
|
||||
this->formatNumbers(text);
|
||||
this->formatTrueFalse(text);
|
||||
this->formatQoutedText(text);
|
||||
this->formatComments(text);
|
||||
}
|
||||
|
||||
void ScriptHighlighting::highlightKeywords(const QString& text) {
|
||||
int index = _keywordRegex.indexIn(text);
|
||||
while (index >= 0) {
|
||||
int length = _keywordRegex.matchedLength();
|
||||
setFormat(index, length, Qt::blue);
|
||||
index = _keywordRegex.indexIn(text, index + length);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptHighlighting::formatComments(const QString& text) {
|
||||
|
||||
setCurrentBlockState(BlockStateClean);
|
||||
|
||||
int start = (previousBlockState() != BlockStateInMultiComment) ? text.indexOf(_multiLineCommentBegin) : 0;
|
||||
|
||||
while (start > -1) {
|
||||
int end = text.indexOf(_multiLineCommentEnd, start);
|
||||
int length = (end == -1 ? text.length() : (end + _multiLineCommentEnd.matchedLength())) - start;
|
||||
setFormat(start, length, Qt::lightGray);
|
||||
start = text.indexOf(_multiLineCommentBegin, start + length);
|
||||
if (end == -1) {
|
||||
setCurrentBlockState(BlockStateInMultiComment);
|
||||
}
|
||||
}
|
||||
|
||||
int index = _singleLineComment.indexIn(text);
|
||||
while (index >= 0) {
|
||||
int length = _singleLineComment.matchedLength();
|
||||
setFormat(index, length, Qt::lightGray);
|
||||
index = _singleLineComment.indexIn(text, index + length);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptHighlighting::formatQoutedText(const QString& text){
|
||||
int index = _qoutedTextRegex.indexIn(text);
|
||||
while (index >= 0) {
|
||||
int length = _qoutedTextRegex.matchedLength();
|
||||
setFormat(index, length, Qt::red);
|
||||
index = _qoutedTextRegex.indexIn(text, index + length);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptHighlighting::formatNumbers(const QString& text){
|
||||
int index = _numberRegex.indexIn(text);
|
||||
while (index >= 0) {
|
||||
int length = _numberRegex.matchedLength();
|
||||
setFormat(index, length, Qt::green);
|
||||
index = _numberRegex.indexIn(text, index + length);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptHighlighting::formatTrueFalse(const QString& text){
|
||||
int index = _truefalseRegex.indexIn(text);
|
||||
while (index >= 0) {
|
||||
int length = _truefalseRegex.matchedLength();
|
||||
QFont* font = new QFont(this->document()->defaultFont());
|
||||
font->setBold(true);
|
||||
setFormat(index, length, *font);
|
||||
index = _truefalseRegex.indexIn(text, index + length);
|
||||
}
|
||||
}
|
46
interface/src/ScriptHighlighting.h
Normal file
46
interface/src/ScriptHighlighting.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// ScriptHighlighting.h
|
||||
// interface/src
|
||||
//
|
||||
// Created by Thijs Wenker on 4/15/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_ScriptHighlighting_h
|
||||
#define hifi_ScriptHighlighting_h
|
||||
|
||||
#include <QSyntaxHighlighter>
|
||||
|
||||
class ScriptHighlighting : public QSyntaxHighlighter {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScriptHighlighting(QTextDocument* parent = NULL);
|
||||
|
||||
enum BlockState {
|
||||
BlockStateClean,
|
||||
BlockStateInMultiComment
|
||||
};
|
||||
|
||||
protected:
|
||||
void highlightBlock(const QString& text);
|
||||
void highlightKeywords(const QString& text);
|
||||
void formatComments(const QString& text);
|
||||
void formatQoutedText(const QString& text);
|
||||
void formatNumbers(const QString& text);
|
||||
void formatTrueFalse(const QString& text);
|
||||
|
||||
private:
|
||||
QRegExp _keywordRegex;
|
||||
QRegExp _qoutedTextRegex;
|
||||
QRegExp _multiLineCommentBegin;
|
||||
QRegExp _multiLineCommentEnd;
|
||||
QRegExp _numberRegex;
|
||||
QRegExp _singleLineComment;
|
||||
QRegExp _truefalseRegex;
|
||||
};
|
||||
|
||||
#endif // hifi_ScriptHighlighting_h
|
|
@ -63,7 +63,7 @@ void eulerToOrthonormals(glm::vec3 * angles, glm::vec3 * front, glm::vec3 * righ
|
|||
}
|
||||
|
||||
void printVector(glm::vec3 vec) {
|
||||
printf("%4.2f, %4.2f, %4.2f\n", vec.x, vec.y, vec.z);
|
||||
qDebug("%4.2f, %4.2f, %4.2f", vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
// Return the azimuth angle (in radians) between two points.
|
||||
|
|
|
@ -56,7 +56,6 @@ Avatar::Avatar() :
|
|||
_mouseRayOrigin(0.0f, 0.0f, 0.0f),
|
||||
_mouseRayDirection(0.0f, 0.0f, 0.0f),
|
||||
_moving(false),
|
||||
_owningAvatarMixer(),
|
||||
_collisionFlags(0),
|
||||
_initialized(false),
|
||||
_shouldRenderBillboard(true)
|
||||
|
@ -212,9 +211,14 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
|||
const float GLOW_DISTANCE = 20.0f;
|
||||
const float GLOW_MAX_LOUDNESS = 2500.0f;
|
||||
const float MAX_GLOW = 0.5f;
|
||||
const float GLOW_FROM_AVERAGE_LOUDNESS = ((this == Application::getInstance()->getAvatar())
|
||||
? 0.0f
|
||||
: MAX_GLOW * getHeadData()->getAudioLoudness() / GLOW_MAX_LOUDNESS);
|
||||
|
||||
float GLOW_FROM_AVERAGE_LOUDNESS = ((this == Application::getInstance()->getAvatar())
|
||||
? 0.0f
|
||||
: MAX_GLOW * getHeadData()->getAudioLoudness() / GLOW_MAX_LOUDNESS);
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::GlowWhenSpeaking)) {
|
||||
GLOW_FROM_AVERAGE_LOUDNESS = 0.0f;
|
||||
}
|
||||
|
||||
Glower glower(_moving && distanceToTarget > GLOW_DISTANCE && renderMode == NORMAL_RENDER_MODE
|
||||
? 1.0f
|
||||
: GLOW_FROM_AVERAGE_LOUDNESS);
|
||||
|
@ -685,6 +689,11 @@ void Avatar::setBillboard(const QByteArray& billboard) {
|
|||
}
|
||||
|
||||
int Avatar::parseDataAtOffset(const QByteArray& packet, int offset) {
|
||||
if (!_initialized) {
|
||||
// now that we have data for this Avatar we are go for init
|
||||
init();
|
||||
}
|
||||
|
||||
// change in position implies movement
|
||||
glm::vec3 oldPosition = _position;
|
||||
|
||||
|
|
|
@ -99,9 +99,6 @@ public:
|
|||
|
||||
/// Returns the distance to use as a LOD parameter.
|
||||
float getLODDistance() const;
|
||||
|
||||
Node* getOwningAvatarMixer() { return _owningAvatarMixer.data(); }
|
||||
void setOwningAvatarMixer(const QWeakPointer<Node>& owningAvatarMixer) { _owningAvatarMixer = owningAvatarMixer; }
|
||||
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
|
||||
|
@ -177,7 +174,6 @@ protected:
|
|||
glm::vec3 _mouseRayDirection;
|
||||
float _stringLength;
|
||||
bool _moving; ///< set when position is changing
|
||||
QWeakPointer<Node> _owningAvatarMixer;
|
||||
|
||||
uint32_t _collisionFlags;
|
||||
|
||||
|
|
|
@ -51,14 +51,16 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
// simulate avatars
|
||||
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
||||
while (avatarIterator != _avatarHash.end()) {
|
||||
Avatar* avatar = static_cast<Avatar*>(avatarIterator.value().data());
|
||||
if (avatar == static_cast<Avatar*>(_myAvatar.data()) || !avatar->isInitialized()) {
|
||||
AvatarSharedPointer sharedAvatar = avatarIterator.value();
|
||||
Avatar* avatar = reinterpret_cast<Avatar*>(sharedAvatar.data());
|
||||
|
||||
if (sharedAvatar == _myAvatar || !avatar->isInitialized()) {
|
||||
// DO NOT update _myAvatar! Its update has already been done earlier in the main loop.
|
||||
// DO NOT update uninitialized Avatars
|
||||
++avatarIterator;
|
||||
continue;
|
||||
}
|
||||
if (avatar->getOwningAvatarMixer()) {
|
||||
if (!shouldKillAvatar(sharedAvatar)) {
|
||||
// this avatar's mixer is still around, go ahead and simulate it
|
||||
avatar->simulate(deltaTime);
|
||||
avatar->setMouseRay(mouseOrigin, mouseDirection);
|
||||
|
@ -127,127 +129,12 @@ void AvatarManager::renderAvatarFades(const glm::vec3& cameraPosition, Avatar::R
|
|||
}
|
||||
}
|
||||
|
||||
AvatarSharedPointer AvatarManager::matchingOrNewAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
AvatarSharedPointer matchingAvatar = _avatarHash.value(sessionUUID);
|
||||
|
||||
if (!matchingAvatar) {
|
||||
// construct a new Avatar for this node
|
||||
Avatar* avatar = new Avatar();
|
||||
avatar->setOwningAvatarMixer(mixerWeakPointer);
|
||||
|
||||
// insert the new avatar into our hash
|
||||
matchingAvatar = AvatarSharedPointer(avatar);
|
||||
_avatarHash.insert(sessionUUID, matchingAvatar);
|
||||
|
||||
qDebug() << "Adding avatar with sessionUUID " << sessionUUID << "to AvatarManager hash.";
|
||||
}
|
||||
|
||||
return matchingAvatar;
|
||||
}
|
||||
|
||||
void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
switch (packetTypeForPacket(datagram)) {
|
||||
case PacketTypeBulkAvatarData:
|
||||
processAvatarDataPacket(datagram, mixerWeakPointer);
|
||||
break;
|
||||
case PacketTypeAvatarIdentity:
|
||||
processAvatarIdentityPacket(datagram, mixerWeakPointer);
|
||||
break;
|
||||
case PacketTypeAvatarBillboard:
|
||||
processAvatarBillboardPacket(datagram, mixerWeakPointer);
|
||||
break;
|
||||
case PacketTypeKillAvatar:
|
||||
processKillAvatar(datagram);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarManager::processAvatarDataPacket(const QByteArray &datagram, const QWeakPointer<Node> &mixerWeakPointer) {
|
||||
int bytesRead = numBytesForPacketHeader(datagram);
|
||||
|
||||
// enumerate over all of the avatars in this packet
|
||||
// only add them if mixerWeakPointer points to something (meaning that mixer is still around)
|
||||
while (bytesRead < datagram.size() && mixerWeakPointer.data()) {
|
||||
QUuid sessionUUID = QUuid::fromRfc4122(datagram.mid(bytesRead, NUM_BYTES_RFC4122_UUID));
|
||||
bytesRead += NUM_BYTES_RFC4122_UUID;
|
||||
|
||||
AvatarSharedPointer matchingAvatarData = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
|
||||
|
||||
// have the matching (or new) avatar parse the data from the packet
|
||||
bytesRead += matchingAvatarData->parseDataAtOffset(datagram, bytesRead);
|
||||
|
||||
Avatar* matchingAvatar = reinterpret_cast<Avatar*>(matchingAvatarData.data());
|
||||
|
||||
if (!matchingAvatar->isInitialized()) {
|
||||
// now that we have AvatarData for this Avatar we are go for init
|
||||
matchingAvatar->init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarManager::processAvatarIdentityPacket(const QByteArray &packet, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
// setup a data stream to parse the packet
|
||||
QDataStream identityStream(packet);
|
||||
identityStream.skipRawData(numBytesForPacketHeader(packet));
|
||||
|
||||
QUuid sessionUUID;
|
||||
|
||||
while (!identityStream.atEnd()) {
|
||||
|
||||
QUrl faceMeshURL, skeletonURL;
|
||||
QString displayName;
|
||||
identityStream >> sessionUUID >> faceMeshURL >> skeletonURL >> displayName;
|
||||
|
||||
// mesh URL for a UUID, find avatar in our list
|
||||
AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
|
||||
if (matchingAvatar) {
|
||||
Avatar* avatar = static_cast<Avatar*>(matchingAvatar.data());
|
||||
|
||||
if (avatar->getFaceModelURL() != faceMeshURL) {
|
||||
avatar->setFaceModelURL(faceMeshURL);
|
||||
}
|
||||
|
||||
if (avatar->getSkeletonModelURL() != skeletonURL) {
|
||||
avatar->setSkeletonModelURL(skeletonURL);
|
||||
}
|
||||
|
||||
if (avatar->getDisplayName() != displayName) {
|
||||
avatar->setDisplayName(displayName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarManager::processAvatarBillboardPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
int headerSize = numBytesForPacketHeader(packet);
|
||||
QUuid sessionUUID = QUuid::fromRfc4122(QByteArray::fromRawData(packet.constData() + headerSize, NUM_BYTES_RFC4122_UUID));
|
||||
|
||||
AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
|
||||
if (matchingAvatar) {
|
||||
Avatar* avatar = static_cast<Avatar*>(matchingAvatar.data());
|
||||
QByteArray billboard = packet.mid(headerSize + NUM_BYTES_RFC4122_UUID);
|
||||
if (avatar->getBillboard() != billboard) {
|
||||
avatar->setBillboard(billboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarManager::processKillAvatar(const QByteArray& datagram) {
|
||||
// read the node id
|
||||
QUuid sessionUUID = QUuid::fromRfc4122(datagram.mid(numBytesForPacketHeader(datagram), NUM_BYTES_RFC4122_UUID));
|
||||
|
||||
// remove the avatar with that UUID from our hash, if it exists
|
||||
AvatarHash::iterator matchedAvatar = _avatarHash.find(sessionUUID);
|
||||
if (matchedAvatar != _avatarHash.end()) {
|
||||
erase(matchedAvatar);
|
||||
}
|
||||
AvatarSharedPointer AvatarManager::newSharedAvatar() {
|
||||
return AvatarSharedPointer(new Avatar());
|
||||
}
|
||||
|
||||
AvatarHash::iterator AvatarManager::erase(const AvatarHash::iterator& iterator) {
|
||||
if (iterator.key() != MY_AVATAR_KEY) {
|
||||
qDebug() << "Removing Avatar with UUID" << iterator.key() << "from AvatarManager hash.";
|
||||
if (reinterpret_cast<Avatar*>(iterator.value().data())->isInitialized()) {
|
||||
_avatarFades.push_back(iterator.value());
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
class MyAvatar;
|
||||
|
||||
class AvatarManager : public QObject, public AvatarHashMap {
|
||||
class AvatarManager : public AvatarHashMap {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AvatarManager(QObject* parent = 0);
|
||||
|
@ -35,23 +35,15 @@ public:
|
|||
void renderAvatars(Avatar::RenderMode renderMode, bool selfAvatarOnly = false);
|
||||
|
||||
void clearOtherAvatars();
|
||||
|
||||
public slots:
|
||||
void processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
|
||||
private:
|
||||
AvatarManager(const AvatarManager& other);
|
||||
|
||||
AvatarSharedPointer matchingOrNewAvatar(const QUuid& nodeUUID, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
|
||||
void processAvatarDataPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
void processAvatarIdentityPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
void processAvatarBillboardPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
void processKillAvatar(const QByteArray& datagram);
|
||||
|
||||
void simulateAvatarFades(float deltaTime);
|
||||
void renderAvatarFades(const glm::vec3& cameraPosition, Avatar::RenderMode renderMode);
|
||||
|
||||
AvatarSharedPointer newSharedAvatar();
|
||||
|
||||
// virtual override
|
||||
AvatarHash::iterator erase(const AvatarHash::iterator& iterator);
|
||||
|
||||
|
|
|
@ -432,7 +432,7 @@ void MyAvatar::renderDebugBodyPoints() {
|
|||
glm::vec3 headPosition(getHead()->getEyePosition());
|
||||
float torsoToHead = glm::length(headPosition - torsoPosition);
|
||||
glm::vec3 position;
|
||||
printf("head-above-torso %.2f, scale = %0.2f\n", torsoToHead, getScale());
|
||||
qDebug("head-above-torso %.2f, scale = %0.2f", torsoToHead, getScale());
|
||||
|
||||
// Torso Sphere
|
||||
position = torsoPosition;
|
||||
|
|
|
@ -41,8 +41,15 @@ void Faceplus::init() {
|
|||
updateEnabled();
|
||||
}
|
||||
|
||||
void Faceplus::setState(const glm::quat& headRotation, float estimatedEyePitch, float estimatedEyeYaw,
|
||||
const QVector<float>& blendshapeCoefficients) {
|
||||
void Faceplus::reset() {
|
||||
if (_enabled) {
|
||||
QMetaObject::invokeMethod(_reader, "reset");
|
||||
}
|
||||
}
|
||||
|
||||
void Faceplus::setState(const glm::vec3& headTranslation, const glm::quat& headRotation,
|
||||
float estimatedEyePitch, float estimatedEyeYaw, const QVector<float>& blendshapeCoefficients) {
|
||||
_headTranslation = headTranslation;
|
||||
_headRotation = headRotation;
|
||||
_estimatedEyePitch = estimatedEyePitch;
|
||||
_estimatedEyeYaw = estimatedEyeYaw;
|
||||
|
@ -150,7 +157,7 @@ FaceplusReader::~FaceplusReader() {
|
|||
|
||||
void FaceplusReader::init() {
|
||||
#ifdef HAVE_FACEPLUS
|
||||
if (!faceplus_init("VGA")) {
|
||||
if (!faceplus_init("hHD")) {
|
||||
qDebug() << "Failed to initialized Faceplus.";
|
||||
return;
|
||||
}
|
||||
|
@ -191,7 +198,8 @@ void FaceplusReader::init() {
|
|||
}
|
||||
}
|
||||
_blendshapeCoefficients.resize(maxIndex + 1);
|
||||
|
||||
_referenceInitialized = false;
|
||||
|
||||
QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection);
|
||||
#endif
|
||||
}
|
||||
|
@ -203,10 +211,24 @@ void FaceplusReader::shutdown() {
|
|||
|
||||
void FaceplusReader::update() {
|
||||
#ifdef HAVE_FACEPLUS
|
||||
if (!(faceplus_synchronous_track() && faceplus_current_output_vector(_outputVector.data()))) {
|
||||
float x, y, rotation, scale;
|
||||
if (!(faceplus_synchronous_track() && faceplus_current_face_location(&x, &y, &rotation, &scale) && !glm::isnan(x) &&
|
||||
faceplus_current_output_vector(_outputVector.data()))) {
|
||||
QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
if (!_referenceInitialized) {
|
||||
_referenceX = x;
|
||||
_referenceY = y;
|
||||
_referenceScale = scale;
|
||||
_referenceInitialized = true;
|
||||
}
|
||||
const float TRANSLATION_SCALE = 10.0f;
|
||||
const float REFERENCE_DISTANCE = 10.0f;
|
||||
float depthScale = _referenceScale / scale;
|
||||
float z = REFERENCE_DISTANCE * (depthScale - 1.0f);
|
||||
glm::vec3 headTranslation((x - _referenceX) * depthScale * TRANSLATION_SCALE,
|
||||
(y - _referenceY) * depthScale * TRANSLATION_SCALE, z);
|
||||
glm::quat headRotation(glm::radians(glm::vec3(-_outputVector.at(_headRotationIndices[0]),
|
||||
_outputVector.at(_headRotationIndices[1]), -_outputVector.at(_headRotationIndices[2]))));
|
||||
float estimatedEyePitch = (_outputVector.at(_leftEyeRotationIndices[0]) +
|
||||
|
@ -222,10 +244,16 @@ void FaceplusReader::update() {
|
|||
}
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(Application::getInstance()->getFaceplus(), "setState", Q_ARG(const glm::quat&, headRotation),
|
||||
Q_ARG(float, estimatedEyePitch), Q_ARG(float, estimatedEyeYaw), Q_ARG(const QVector<float>&, _blendshapeCoefficients));
|
||||
QMetaObject::invokeMethod(Application::getInstance()->getFaceplus(), "setState", Q_ARG(const glm::vec3&, headTranslation),
|
||||
Q_ARG(const glm::quat&, headRotation), Q_ARG(float, estimatedEyePitch), Q_ARG(float, estimatedEyeYaw),
|
||||
Q_ARG(const QVector<float>&, _blendshapeCoefficients));
|
||||
|
||||
QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FaceplusReader::reset() {
|
||||
#ifdef HAVE_FACEPLUS
|
||||
_referenceInitialized = false;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -30,11 +30,12 @@ public:
|
|||
virtual ~Faceplus();
|
||||
|
||||
void init();
|
||||
|
||||
void reset();
|
||||
|
||||
bool isActive() const { return _active; }
|
||||
|
||||
Q_INVOKABLE void setState(const glm::quat& headRotation, float estimatedEyePitch, float estimatedEyeYaw,
|
||||
const QVector<float>& blendshapeCoefficients);
|
||||
Q_INVOKABLE void setState(const glm::vec3& headTranslation, const glm::quat& headRotation,
|
||||
float estimatedEyePitch, float estimatedEyeYaw, const QVector<float>& blendshapeCoefficients);
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -63,6 +64,7 @@ public:
|
|||
Q_INVOKABLE void init();
|
||||
Q_INVOKABLE void shutdown();
|
||||
Q_INVOKABLE void update();
|
||||
Q_INVOKABLE void reset();
|
||||
|
||||
private:
|
||||
|
||||
|
@ -72,6 +74,10 @@ private:
|
|||
int _headRotationIndices[3];
|
||||
int _leftEyeRotationIndices[2];
|
||||
int _rightEyeRotationIndices[2];
|
||||
float _referenceX;
|
||||
float _referenceY;
|
||||
float _referenceScale;
|
||||
bool _referenceInitialized;
|
||||
QVector<float> _blendshapeCoefficients;
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -96,7 +96,7 @@ void SixenseManager::update(float deltaTime) {
|
|||
hand->getPalms().push_back(newPalm);
|
||||
palm = &(hand->getPalms()[hand->getNumPalms() - 1]);
|
||||
palm->setSixenseID(data->controller_index);
|
||||
printf("Found new Sixense controller, ID %i\n", data->controller_index);
|
||||
qDebug("Found new Sixense controller, ID %i", data->controller_index);
|
||||
}
|
||||
|
||||
palm->setActive(true);
|
||||
|
|
|
@ -60,11 +60,11 @@ Model::SkinLocations Model::_skinNormalMapLocations;
|
|||
Model::SkinLocations Model::_skinShadowLocations;
|
||||
|
||||
void Model::setScale(const glm::vec3& scale) {
|
||||
glm::vec3 deltaScale = _scale - scale;
|
||||
float scaleLength = glm::length(_scale);
|
||||
float relativeDeltaScale = glm::length(_scale - scale) / scaleLength;
|
||||
|
||||
// decreased epsilon because this wasn't handling scale changes of 0.01
|
||||
const float SMALLER_EPSILON = EPSILON * 0.0001f;
|
||||
if (glm::length2(deltaScale) > SMALLER_EPSILON) {
|
||||
const float ONE_PERCENT = 0.01f;
|
||||
if (relativeDeltaScale > ONE_PERCENT || scaleLength < EPSILON) {
|
||||
_scale = scale;
|
||||
rebuildShapes();
|
||||
}
|
||||
|
@ -468,20 +468,56 @@ void Model::clearShapes() {
|
|||
|
||||
void Model::rebuildShapes() {
|
||||
clearShapes();
|
||||
|
||||
if (_jointStates.isEmpty()) {
|
||||
|
||||
if (!_geometry) {
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure all the joints are updated correctly before we try to create their shapes
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
updateJointState(i);
|
||||
}
|
||||
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
|
||||
if (geometry.joints.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int numJoints = geometry.joints.size();
|
||||
QVector<glm::mat4> transforms;
|
||||
transforms.fill(glm::mat4(), numJoints);
|
||||
QVector<glm::quat> combinedRotations;
|
||||
combinedRotations.fill(glm::quat(), numJoints);
|
||||
QVector<bool> shapeIsSet;
|
||||
shapeIsSet.fill(false, numJoints);
|
||||
int rootIndex = 0;
|
||||
|
||||
float uniformScale = extractUniformScale(_scale);
|
||||
glm::quat inverseRotation = glm::inverse(_rotation);
|
||||
glm::vec3 rootPosition(0.f);
|
||||
int numShapesSet = 0;
|
||||
int lastNumShapesSet = -1;
|
||||
while (numShapesSet < numJoints && numShapesSet != lastNumShapesSet) {
|
||||
lastNumShapesSet = numShapesSet;
|
||||
for (int i = 0; i < numJoints; ++i) {
|
||||
if (shapeIsSet[i]) {
|
||||
continue;
|
||||
}
|
||||
const FBXJoint& joint = geometry.joints[i];
|
||||
int parentIndex = joint.parentIndex;
|
||||
if (parentIndex == -1) {
|
||||
rootIndex = i;
|
||||
glm::mat4 baseTransform = glm::mat4_cast(_rotation) * uniformScale * glm::translate(_offset);
|
||||
glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
|
||||
transforms[i] = baseTransform * geometry.offset * glm::translate(joint.translation) * joint.preTransform *
|
||||
glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
combinedRotations[i] = _rotation * combinedRotation;
|
||||
++numShapesSet;
|
||||
shapeIsSet[i] = true;
|
||||
} else if (shapeIsSet[parentIndex]) {
|
||||
glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
|
||||
transforms[i] = transforms[parentIndex] * glm::translate(joint.translation) * joint.preTransform *
|
||||
glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
combinedRotations[i] = combinedRotations[parentIndex] * combinedRotation;
|
||||
++numShapesSet;
|
||||
shapeIsSet[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// joint shapes
|
||||
Extents totalExtents;
|
||||
|
@ -489,48 +525,70 @@ void Model::rebuildShapes() {
|
|||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
const FBXJoint& joint = geometry.joints[i];
|
||||
|
||||
glm::vec3 jointToShapeOffset = uniformScale * (_jointStates[i].combinedRotation * joint.shapePosition);
|
||||
glm::vec3 worldPosition = extractTranslation(_jointStates[i].transform) + jointToShapeOffset + _translation;
|
||||
glm::vec3 worldPosition = extractTranslation(transforms[i]);
|
||||
Extents shapeExtents;
|
||||
shapeExtents.reset();
|
||||
|
||||
if (joint.parentIndex == -1) {
|
||||
rootPosition = worldPosition;
|
||||
}
|
||||
|
||||
float radius = uniformScale * joint.boneRadius;
|
||||
float halfHeight = 0.5f * uniformScale * joint.distanceToParent;
|
||||
if (joint.shapeType == Shape::CAPSULE_SHAPE && halfHeight > EPSILON) {
|
||||
Shape::Type type = joint.shapeType;
|
||||
if (type == Shape::CAPSULE_SHAPE && halfHeight < EPSILON) {
|
||||
// this capsule is effectively a sphere
|
||||
type = Shape::SPHERE_SHAPE;
|
||||
}
|
||||
if (type == Shape::CAPSULE_SHAPE) {
|
||||
CapsuleShape* capsule = new CapsuleShape(radius, halfHeight);
|
||||
capsule->setPosition(worldPosition);
|
||||
capsule->setRotation(_jointStates[i].combinedRotation * joint.shapeRotation);
|
||||
capsule->setRotation(combinedRotations[i] * joint.shapeRotation);
|
||||
_jointShapes.push_back(capsule);
|
||||
|
||||
glm::vec3 endPoint;
|
||||
capsule->getEndPoint(endPoint);
|
||||
glm::vec3 startPoint;
|
||||
capsule->getStartPoint(startPoint);
|
||||
glm::vec3 axis = (halfHeight + radius) * glm::normalize(endPoint - startPoint);
|
||||
|
||||
// add some points that bound a sphere at the center of the capsule
|
||||
glm::vec3 axis = glm::vec3(radius);
|
||||
shapeExtents.addPoint(worldPosition + axis);
|
||||
shapeExtents.addPoint(worldPosition - axis);
|
||||
} else {
|
||||
|
||||
// add the two furthest surface points of the capsule
|
||||
axis = (halfHeight + radius) * glm::normalize(endPoint - startPoint);
|
||||
shapeExtents.addPoint(worldPosition + axis);
|
||||
shapeExtents.addPoint(worldPosition - axis);
|
||||
|
||||
totalExtents.addExtents(shapeExtents);
|
||||
} else if (type == Shape::SPHERE_SHAPE) {
|
||||
SphereShape* sphere = new SphereShape(radius, worldPosition);
|
||||
_jointShapes.push_back(sphere);
|
||||
|
||||
glm::vec3 axis = glm::vec3(radius);
|
||||
shapeExtents.addPoint(worldPosition + axis);
|
||||
shapeExtents.addPoint(worldPosition - axis);
|
||||
totalExtents.addExtents(shapeExtents);
|
||||
} else {
|
||||
// this shape type is not handled and the joint shouldn't collide,
|
||||
// however we must have a shape for each joint,
|
||||
// so we make a bogus sphere with zero radius.
|
||||
// TODO: implement collision groups for more control over what collides with what
|
||||
SphereShape* sphere = new SphereShape(0.f, worldPosition);
|
||||
_jointShapes.push_back(sphere);
|
||||
}
|
||||
totalExtents.addExtents(shapeExtents);
|
||||
}
|
||||
|
||||
// bounding shape
|
||||
// NOTE: we assume that the longest side of totalExtents is the yAxis
|
||||
glm::vec3 diagonal = totalExtents.maximum - totalExtents.minimum;
|
||||
float capsuleRadius = 0.25f * (diagonal.x + diagonal.z); // half the average of x and z
|
||||
// the radius is half the RMS of the X and Z sides:
|
||||
float capsuleRadius = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z));
|
||||
_boundingShape.setRadius(capsuleRadius);
|
||||
_boundingShape.setHalfHeight(0.5f * diagonal.y - capsuleRadius);
|
||||
|
||||
glm::quat inverseRotation = glm::inverse(_rotation);
|
||||
glm::vec3 rootPosition = extractTranslation(transforms[rootIndex]);
|
||||
_boundingShapeLocalOffset = inverseRotation * (0.5f * (totalExtents.maximum + totalExtents.minimum) - rootPosition);
|
||||
_boundingShape.setPosition(_translation - _rotation * _boundingShapeLocalOffset);
|
||||
_boundingShape.setRotation(_rotation);
|
||||
}
|
||||
|
||||
void Model::updateShapePositions() {
|
||||
|
@ -557,6 +615,7 @@ void Model::updateShapePositions() {
|
|||
_boundingRadius = sqrtf(_boundingRadius);
|
||||
_shapesAreDirty = false;
|
||||
_boundingShape.setPosition(rootPosition + _rotation * _boundingShapeLocalOffset);
|
||||
_boundingShape.setRotation(_rotation);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ void ClipboardScriptingInterface::exportVoxel(float x, float y, float z, float s
|
|||
}
|
||||
|
||||
bool ClipboardScriptingInterface::importVoxels() {
|
||||
qDebug() << "[DEBUG] Importing ... ";
|
||||
qDebug() << "Importing ... ";
|
||||
QEventLoop loop;
|
||||
connect(Application::getInstance(), SIGNAL(importDone()), &loop, SLOT(quit()));
|
||||
emit readyToImport();
|
||||
|
|
158
interface/src/ui/ScriptEditorWidget.cpp
Normal file
158
interface/src/ui/ScriptEditorWidget.cpp
Normal file
|
@ -0,0 +1,158 @@
|
|||
//
|
||||
// ScriptEditorWidget.cpp
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Thijs Wenker on 4/14/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ui_scriptEditorWidget.h"
|
||||
#include "ScriptEditorWidget.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QFrame>
|
||||
#include <QLayoutItem>
|
||||
#include <QMainWindow>
|
||||
#include <QMessageBox>
|
||||
#include <QPalette>
|
||||
#include <QScrollBar>
|
||||
#include <QSizePolicy>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
#include "Application.h"
|
||||
#include "ScriptHighlighting.h"
|
||||
|
||||
ScriptEditorWidget::ScriptEditorWidget() :
|
||||
_scriptEditorWidgetUI(new Ui::ScriptEditorWidget),
|
||||
_scriptEngine(NULL)
|
||||
{
|
||||
_scriptEditorWidgetUI->setupUi(this);
|
||||
|
||||
connect(_scriptEditorWidgetUI->scriptEdit->document(), SIGNAL(modificationChanged(bool)), this, SIGNAL(scriptModified()));
|
||||
connect(_scriptEditorWidgetUI->scriptEdit->document(), SIGNAL(contentsChanged()), this, SLOT(onScriptModified()));
|
||||
|
||||
// remove the title bar (see the Qt docs on setTitleBarWidget)
|
||||
setTitleBarWidget(new QWidget());
|
||||
QFontMetrics fm(_scriptEditorWidgetUI->scriptEdit->font());
|
||||
_scriptEditorWidgetUI->scriptEdit->setTabStopWidth(fm.width('0') * 4);
|
||||
ScriptHighlighting* highlighting = new ScriptHighlighting(_scriptEditorWidgetUI->scriptEdit->document());
|
||||
QTimer::singleShot(0, _scriptEditorWidgetUI->scriptEdit, SLOT(setFocus()));
|
||||
}
|
||||
|
||||
ScriptEditorWidget::~ScriptEditorWidget() {
|
||||
delete _scriptEditorWidgetUI;
|
||||
}
|
||||
|
||||
void ScriptEditorWidget::onScriptModified() {
|
||||
if(_scriptEditorWidgetUI->onTheFlyCheckBox->isChecked() && isRunning()) {
|
||||
setRunning(false);
|
||||
setRunning(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool ScriptEditorWidget::isModified() {
|
||||
return _scriptEditorWidgetUI->scriptEdit->document()->isModified();
|
||||
}
|
||||
|
||||
bool ScriptEditorWidget::isRunning() {
|
||||
return (_scriptEngine != NULL) ? _scriptEngine->isRunning() : false;
|
||||
}
|
||||
|
||||
bool ScriptEditorWidget::setRunning(bool run) {
|
||||
if (run && !save()) {
|
||||
return false;
|
||||
}
|
||||
// Clean-up old connections.
|
||||
disconnect(this, SLOT(onScriptError(const QString&)));
|
||||
disconnect(this, SLOT(onScriptPrint(const QString&)));
|
||||
|
||||
if (run) {
|
||||
_scriptEngine = Application::getInstance()->loadScript(_currentScript, true);
|
||||
connect(_scriptEngine, SIGNAL(runningStateChanged()), this, SIGNAL(runningStateChanged()));
|
||||
|
||||
// Make new connections.
|
||||
connect(_scriptEngine, SIGNAL(errorMessage(const QString&)), this, SLOT(onScriptError(const QString&)));
|
||||
connect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(onScriptPrint(const QString&)));
|
||||
} else {
|
||||
Application::getInstance()->stopScript(_currentScript);
|
||||
_scriptEngine = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScriptEditorWidget::saveFile(const QString &scriptPath) {
|
||||
QFile file(scriptPath);
|
||||
if (!file.open(QFile::WriteOnly | QFile::Text)) {
|
||||
QMessageBox::warning(this, tr("Interface"), tr("Cannot write script %1:\n%2.").arg(scriptPath)
|
||||
.arg(file.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream out(&file);
|
||||
out << _scriptEditorWidgetUI->scriptEdit->toPlainText();
|
||||
|
||||
setScriptFile(scriptPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptEditorWidget::loadFile(const QString& scriptPath) {
|
||||
QFile file(scriptPath);
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QMessageBox::warning(this, tr("Interface"), tr("Cannot read script %1:\n%2.").arg(scriptPath).arg(file.errorString()));
|
||||
return;
|
||||
}
|
||||
|
||||
QTextStream in(&file);
|
||||
_scriptEditorWidgetUI->scriptEdit->setPlainText(in.readAll());
|
||||
|
||||
setScriptFile(scriptPath);
|
||||
|
||||
disconnect(this, SLOT(onScriptError(const QString&)));
|
||||
disconnect(this, SLOT(onScriptPrint(const QString&)));
|
||||
|
||||
_scriptEngine = Application::getInstance()->getScriptEngine(scriptPath);
|
||||
if (_scriptEngine != NULL) {
|
||||
connect(_scriptEngine, SIGNAL(runningStateChanged()), this, SIGNAL(runningStateChanged()));
|
||||
connect(_scriptEngine, SIGNAL(errorMessage(const QString&)), this, SLOT(onScriptError(const QString&)));
|
||||
connect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(onScriptPrint(const QString&)));
|
||||
}
|
||||
}
|
||||
|
||||
bool ScriptEditorWidget::save() {
|
||||
return _currentScript.isEmpty() ? saveAs() : saveFile(_currentScript);
|
||||
}
|
||||
|
||||
bool ScriptEditorWidget::saveAs() {
|
||||
QString fileName = QFileDialog::getSaveFileName(this, tr("Save script"), QString(), tr("Javascript (*.js)"));
|
||||
return !fileName.isEmpty() ? saveFile(fileName) : false;
|
||||
}
|
||||
|
||||
void ScriptEditorWidget::setScriptFile(const QString& scriptPath) {
|
||||
_currentScript = scriptPath;
|
||||
_scriptEditorWidgetUI->scriptEdit->document()->setModified(false);
|
||||
setWindowModified(false);
|
||||
|
||||
emit scriptnameChanged();
|
||||
}
|
||||
|
||||
bool ScriptEditorWidget::questionSave() {
|
||||
if (_scriptEditorWidgetUI->scriptEdit->document()->isModified()) {
|
||||
QMessageBox::StandardButton button = QMessageBox::warning(this, tr("Interface"),
|
||||
tr("The script has been modified.\nDo you want to save your changes?"), QMessageBox::Save | QMessageBox::Discard |
|
||||
QMessageBox::Cancel, QMessageBox::Save);
|
||||
return button == QMessageBox::Save ? save() : (button == QMessageBox::Cancel ? false : true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptEditorWidget::onScriptError(const QString& message) {
|
||||
_scriptEditorWidgetUI->debugText->appendPlainText("ERROR: " + message);
|
||||
}
|
||||
|
||||
void ScriptEditorWidget::onScriptPrint(const QString& message) {
|
||||
_scriptEditorWidgetUI->debugText->appendPlainText("> " + message);
|
||||
}
|
57
interface/src/ui/ScriptEditorWidget.h
Normal file
57
interface/src/ui/ScriptEditorWidget.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// ScriptEditorWidget.h
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Thijs Wenker on 4/14/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_ScriptEditorWidget_h
|
||||
#define hifi_ScriptEditorWidget_h
|
||||
|
||||
#include <QDockWidget>
|
||||
#include "ScriptEditorWidget.h"
|
||||
#include "ScriptEngine.h"
|
||||
|
||||
namespace Ui {
|
||||
class ScriptEditorWidget;
|
||||
}
|
||||
|
||||
class ScriptEditorWidget : public QDockWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScriptEditorWidget();
|
||||
~ScriptEditorWidget();
|
||||
|
||||
bool isModified();
|
||||
bool isRunning();
|
||||
bool setRunning(bool run);
|
||||
bool saveFile(const QString& scriptPath);
|
||||
void loadFile(const QString& scriptPath);
|
||||
void setScriptFile(const QString& scriptPath);
|
||||
bool save();
|
||||
bool saveAs();
|
||||
bool questionSave();
|
||||
const QString getScriptName() const { return _currentScript; };
|
||||
|
||||
signals:
|
||||
void runningStateChanged();
|
||||
void scriptnameChanged();
|
||||
void scriptModified();
|
||||
|
||||
private slots:
|
||||
void onScriptError(const QString& message);
|
||||
void onScriptPrint(const QString& message);
|
||||
void onScriptModified();
|
||||
|
||||
private:
|
||||
Ui::ScriptEditorWidget* _scriptEditorWidgetUI;
|
||||
ScriptEngine* _scriptEngine;
|
||||
QString _currentScript;
|
||||
};
|
||||
|
||||
#endif // hifi_ScriptEditorWidget_h
|
200
interface/src/ui/ScriptEditorWindow.cpp
Normal file
200
interface/src/ui/ScriptEditorWindow.cpp
Normal file
|
@ -0,0 +1,200 @@
|
|||
//
|
||||
// ScriptEditorWindow.cpp
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Thijs Wenker on 4/14/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ui_scriptEditorWindow.h"
|
||||
#include "ScriptEditorWindow.h"
|
||||
#include "ScriptEditorWidget.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QFrame>
|
||||
#include <QLayoutItem>
|
||||
#include <QMainWindow>
|
||||
#include <QMessageBox>
|
||||
#include <QPalette>
|
||||
#include <QScrollBar>
|
||||
#include <QShortcut>
|
||||
#include <QSizePolicy>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
#include "Application.h"
|
||||
#include "FlowLayout.h"
|
||||
|
||||
ScriptEditorWindow::ScriptEditorWindow() :
|
||||
_ScriptEditorWindowUI(new Ui::ScriptEditorWindow),
|
||||
_loadMenu(new QMenu),
|
||||
_saveMenu(new QMenu)
|
||||
{
|
||||
_ScriptEditorWindowUI->setupUi(this);
|
||||
show();
|
||||
addScriptEditorWidget("New script");
|
||||
connect(_loadMenu, SIGNAL(aboutToShow()), this, SLOT(loadMenuAboutToShow()));
|
||||
_ScriptEditorWindowUI->loadButton->setMenu(_loadMenu);
|
||||
|
||||
_saveMenu->addAction("Save as..", this, SLOT(saveScriptAsClicked()), Qt::CTRL | Qt::SHIFT | Qt::Key_S);
|
||||
|
||||
_ScriptEditorWindowUI->saveButton->setMenu(_saveMenu);
|
||||
|
||||
connect(new QShortcut(QKeySequence("Ctrl+N"), this), SIGNAL(activated()), this, SLOT(newScriptClicked()));
|
||||
connect(new QShortcut(QKeySequence("Ctrl+S"), this), SIGNAL(activated()), this, SLOT(saveScriptClicked()));
|
||||
connect(new QShortcut(QKeySequence("Ctrl+O"), this), SIGNAL(activated()), this, SLOT(loadScriptClicked()));
|
||||
connect(new QShortcut(QKeySequence("F5"), this), SIGNAL(activated()), this, SLOT(toggleRunScriptClicked()));
|
||||
}
|
||||
|
||||
ScriptEditorWindow::~ScriptEditorWindow() {
|
||||
delete _ScriptEditorWindowUI;
|
||||
}
|
||||
|
||||
void ScriptEditorWindow::setRunningState(bool run) {
|
||||
if (_ScriptEditorWindowUI->tabWidget->currentIndex() != -1) {
|
||||
static_cast<ScriptEditorWidget*>(_ScriptEditorWindowUI->tabWidget->currentWidget())->setRunning(run);
|
||||
}
|
||||
this->updateButtons();
|
||||
}
|
||||
|
||||
void ScriptEditorWindow::updateButtons() {
|
||||
_ScriptEditorWindowUI->toggleRunButton->setEnabled(_ScriptEditorWindowUI->tabWidget->currentIndex() != -1);
|
||||
_ScriptEditorWindowUI->toggleRunButton->setIcon(_ScriptEditorWindowUI->tabWidget->currentIndex() != -1 &&
|
||||
static_cast<ScriptEditorWidget*>(_ScriptEditorWindowUI->tabWidget->currentWidget())->isRunning() ?
|
||||
QIcon("../resources/icons/stop-script.svg") : QIcon("../resources/icons/start-script.svg"));
|
||||
}
|
||||
|
||||
void ScriptEditorWindow::loadScriptMenu(const QString& scriptName) {
|
||||
addScriptEditorWidget("loading...")->loadFile(scriptName);
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
void ScriptEditorWindow::loadScriptClicked() {
|
||||
QString scriptName = QFileDialog::getOpenFileName(this, tr("Interface"), QString(), tr("Javascript (*.js)"));
|
||||
if (!scriptName.isEmpty()) {
|
||||
addScriptEditorWidget("loading...")->loadFile(scriptName);
|
||||
updateButtons();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEditorWindow::loadMenuAboutToShow() {
|
||||
_loadMenu->clear();
|
||||
QStringList runningScripts = Application::getInstance()->getRunningScripts();
|
||||
if (runningScripts.count() > 0) {
|
||||
QSignalMapper* signalMapper = new QSignalMapper(this);
|
||||
foreach (const QString& runningScript, runningScripts) {
|
||||
QAction* runningScriptAction = new QAction(runningScript, _loadMenu);
|
||||
connect(runningScriptAction, SIGNAL(triggered()), signalMapper, SLOT(map()));
|
||||
signalMapper->setMapping(runningScriptAction, runningScript);
|
||||
_loadMenu->addAction(runningScriptAction);
|
||||
}
|
||||
connect(signalMapper, SIGNAL(mapped(const QString &)), this, SLOT(loadScriptMenu(const QString&)));
|
||||
} else {
|
||||
QAction* naAction = new QAction("(no running scripts)", _loadMenu);
|
||||
naAction->setDisabled(true);
|
||||
_loadMenu->addAction(naAction);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEditorWindow::newScriptClicked() {
|
||||
addScriptEditorWidget(QString("New script"));
|
||||
}
|
||||
|
||||
void ScriptEditorWindow::toggleRunScriptClicked() {
|
||||
this->setRunningState(!(_ScriptEditorWindowUI->tabWidget->currentIndex() !=-1
|
||||
&& static_cast<ScriptEditorWidget*>(_ScriptEditorWindowUI->tabWidget->currentWidget())->isRunning()));
|
||||
}
|
||||
|
||||
void ScriptEditorWindow::saveScriptClicked() {
|
||||
if (_ScriptEditorWindowUI->tabWidget->currentIndex() != -1) {
|
||||
ScriptEditorWidget* currentScriptWidget = static_cast<ScriptEditorWidget*>(_ScriptEditorWindowUI->tabWidget
|
||||
->currentWidget());
|
||||
currentScriptWidget->save();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEditorWindow::saveScriptAsClicked() {
|
||||
if (_ScriptEditorWindowUI->tabWidget->currentIndex() != -1) {
|
||||
ScriptEditorWidget* currentScriptWidget = static_cast<ScriptEditorWidget*>(_ScriptEditorWindowUI->tabWidget
|
||||
->currentWidget());
|
||||
currentScriptWidget->saveAs();
|
||||
}
|
||||
}
|
||||
|
||||
ScriptEditorWidget* ScriptEditorWindow::addScriptEditorWidget(QString title) {
|
||||
ScriptEditorWidget* newScriptEditorWidget = new ScriptEditorWidget();
|
||||
connect(newScriptEditorWidget, SIGNAL(scriptnameChanged()), this, SLOT(updateScriptNameOrStatus()));
|
||||
connect(newScriptEditorWidget, SIGNAL(scriptModified()), this, SLOT(updateScriptNameOrStatus()));
|
||||
connect(newScriptEditorWidget, SIGNAL(runningStateChanged()), this, SLOT(updateButtons()));
|
||||
_ScriptEditorWindowUI->tabWidget->addTab(newScriptEditorWidget, title);
|
||||
_ScriptEditorWindowUI->tabWidget->setCurrentWidget(newScriptEditorWidget);
|
||||
newScriptEditorWidget->setUpdatesEnabled(true);
|
||||
newScriptEditorWidget->adjustSize();
|
||||
return newScriptEditorWidget;
|
||||
}
|
||||
|
||||
void ScriptEditorWindow::tabSwitched(int tabIndex) {
|
||||
this->updateButtons();
|
||||
if (_ScriptEditorWindowUI->tabWidget->currentIndex() != -1) {
|
||||
ScriptEditorWidget* currentScriptWidget = static_cast<ScriptEditorWidget*>(_ScriptEditorWindowUI->tabWidget
|
||||
->currentWidget());
|
||||
QString modifiedStar = (currentScriptWidget->isModified() ? "*" : "");
|
||||
if (currentScriptWidget->getScriptName().length() > 0) {
|
||||
this->setWindowTitle("Script Editor [" + currentScriptWidget->getScriptName() + modifiedStar + "]");
|
||||
} else {
|
||||
this->setWindowTitle("Script Editor [New script" + modifiedStar + "]");
|
||||
}
|
||||
} else {
|
||||
this->setWindowTitle("Script Editor");
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEditorWindow::tabCloseRequested(int tabIndex) {
|
||||
ScriptEditorWidget* closingScriptWidget = static_cast<ScriptEditorWidget*>(_ScriptEditorWindowUI->tabWidget
|
||||
->widget(tabIndex));
|
||||
if(closingScriptWidget->questionSave()) {
|
||||
_ScriptEditorWindowUI->tabWidget->removeTab(tabIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEditorWindow::closeEvent(QCloseEvent *event) {
|
||||
bool unsaved_docs_warning = false;
|
||||
for (int i = 0; i < _ScriptEditorWindowUI->tabWidget->count(); i++){
|
||||
if(static_cast<ScriptEditorWidget*>(_ScriptEditorWindowUI->tabWidget->widget(i))->isModified()){
|
||||
unsaved_docs_warning = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!unsaved_docs_warning || QMessageBox::warning(this, tr("Interface"),
|
||||
tr("There are some unsaved scripts, are you sure you want to close the editor? Changes will be lost!"),
|
||||
QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Discard) {
|
||||
event->accept();
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEditorWindow::updateScriptNameOrStatus() {
|
||||
ScriptEditorWidget* source = static_cast<ScriptEditorWidget*>(QObject::sender());
|
||||
QString modifiedStar = (source->isModified()? "*" : "");
|
||||
if (source->getScriptName().length() > 0) {
|
||||
for (int i = 0; i < _ScriptEditorWindowUI->tabWidget->count(); i++){
|
||||
if (_ScriptEditorWindowUI->tabWidget->widget(i) == source) {
|
||||
_ScriptEditorWindowUI->tabWidget->setTabText(i, modifiedStar + QFileInfo(source->getScriptName()).fileName());
|
||||
_ScriptEditorWindowUI->tabWidget->setTabToolTip(i, source->getScriptName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_ScriptEditorWindowUI->tabWidget->currentWidget() == source) {
|
||||
if (source->getScriptName().length() > 0) {
|
||||
this->setWindowTitle("Script Editor [" + source->getScriptName() + modifiedStar + "]");
|
||||
} else {
|
||||
this->setWindowTitle("Script Editor [New script" + modifiedStar + "]");
|
||||
}
|
||||
}
|
||||
}
|
54
interface/src/ui/ScriptEditorWindow.h
Normal file
54
interface/src/ui/ScriptEditorWindow.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// ScriptEditorWindow.h
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Thijs Wenker on 4/14/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_ScriptEditorWindow_h
|
||||
#define hifi_ScriptEditorWindow_h
|
||||
|
||||
#include "ScriptEditorWidget.h"
|
||||
|
||||
namespace Ui {
|
||||
class ScriptEditorWindow;
|
||||
}
|
||||
|
||||
class ScriptEditorWindow : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScriptEditorWindow();
|
||||
~ScriptEditorWindow();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent* event);
|
||||
|
||||
private:
|
||||
Ui::ScriptEditorWindow* _ScriptEditorWindowUI;
|
||||
QMenu* _loadMenu;
|
||||
QMenu* _saveMenu;
|
||||
|
||||
ScriptEditorWidget* addScriptEditorWidget(QString title);
|
||||
void setRunningState(bool run);
|
||||
void setScriptName(const QString& scriptName);
|
||||
|
||||
private slots:
|
||||
void loadScriptMenu(const QString& scriptName);
|
||||
void loadScriptClicked();
|
||||
void newScriptClicked();
|
||||
void toggleRunScriptClicked();
|
||||
void saveScriptClicked();
|
||||
void saveScriptAsClicked();
|
||||
void loadMenuAboutToShow();
|
||||
void tabSwitched(int tabIndex);
|
||||
void tabCloseRequested(int tabIndex);
|
||||
void updateScriptNameOrStatus();
|
||||
void updateButtons();
|
||||
};
|
||||
|
||||
#endif // hifi_ScriptEditorWindow_h
|
|
@ -171,6 +171,9 @@ void Stats::display(
|
|||
|
||||
unsigned int backgroundColor = 0x33333399;
|
||||
int verticalOffset = 0, lines = 0;
|
||||
float scale = 0.10f;
|
||||
float rotation = 0.0f;
|
||||
int font = 2;
|
||||
|
||||
QLocale locale(QLocale::English);
|
||||
std::stringstream voxelStats;
|
||||
|
@ -198,11 +201,11 @@ void Stats::display(
|
|||
sprintf(framesPerSecond, "Framerate: %3.0f FPS", fps);
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, serverNodes, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, serverNodes, color);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarNodes, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarNodes, color);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, framesPerSecond, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, framesPerSecond, color);
|
||||
|
||||
if (_expanded) {
|
||||
char packetsPerSecondString[30];
|
||||
|
@ -211,9 +214,9 @@ void Stats::display(
|
|||
sprintf(averageMegabitsPerSecond, "Mbps: %3.2f", (float)bytesPerSecond * 8.f / 1000000.f);
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, packetsPerSecondString, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, packetsPerSecondString, color);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, averageMegabitsPerSecond, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, averageMegabitsPerSecond, color);
|
||||
}
|
||||
|
||||
verticalOffset = 0;
|
||||
|
@ -258,7 +261,7 @@ void Stats::display(
|
|||
"Buffer msecs %.1f",
|
||||
(float) (audio->getNetworkBufferLengthSamplesPerChannel() + (float) audio->getJitterBufferSamples()) /
|
||||
(float) audio->getNetworkSampleRate() * 1000.f);
|
||||
drawText(30, glWidget->height() - 22, 0.10f, 0.f, 2.f, audioJitter, color);
|
||||
drawText(30, glWidget->height() - 22, scale, rotation, font, audioJitter, color);
|
||||
|
||||
|
||||
char audioPing[30];
|
||||
|
@ -271,18 +274,18 @@ void Stats::display(
|
|||
sprintf(voxelAvgPing, "Voxel avg ping: %d", pingVoxel);
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, audioPing, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, audioPing, color);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarPing, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarPing, color);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, voxelAvgPing, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, voxelAvgPing, color);
|
||||
|
||||
if (_expanded) {
|
||||
char voxelMaxPing[30];
|
||||
sprintf(voxelMaxPing, "Voxel max ping: %d", pingVoxelMax);
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, voxelMaxPing, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, voxelMaxPing, color);
|
||||
}
|
||||
|
||||
verticalOffset = 0;
|
||||
|
@ -306,11 +309,11 @@ void Stats::display(
|
|||
char avatarMixerStats[200];
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarPosition, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarPosition, color);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarVelocity, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarVelocity, color);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarBodyYaw, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarBodyYaw, color);
|
||||
|
||||
if (_expanded) {
|
||||
SharedNodePointer avatarMixer = NodeList::getInstance()->soloNodeOfType(NodeType::AvatarMixer);
|
||||
|
@ -323,7 +326,7 @@ void Stats::display(
|
|||
}
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarMixerStats, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarMixerStats, color);
|
||||
|
||||
stringstream downloads;
|
||||
downloads << "Downloads: ";
|
||||
|
@ -333,7 +336,7 @@ void Stats::display(
|
|||
downloads << "(" << ResourceCache::getPendingRequestCount() << " pending)";
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, downloads.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, downloads.str().c_str(), color);
|
||||
}
|
||||
|
||||
verticalOffset = 0;
|
||||
|
@ -343,7 +346,7 @@ void Stats::display(
|
|||
|
||||
lines = _expanded ? 12 : 3;
|
||||
if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessing)) {
|
||||
lines += 8; // spatial audio processing adds 1 spacing line and 7 extra lines of info
|
||||
lines += 9; // spatial audio processing adds 1 spacing line and 8 extra lines of info
|
||||
}
|
||||
|
||||
drawBackground(backgroundColor, horizontalOffset, 0, glWidget->width() - horizontalOffset, lines * STATS_PELS_PER_LINE + 10);
|
||||
|
@ -354,7 +357,7 @@ void Stats::display(
|
|||
voxelStats.str("");
|
||||
voxelStats << "Voxels Memory Nodes: " << VoxelTreeElement::getTotalMemoryUsage() / 1000000.f << "MB";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
|
||||
voxelStats.str("");
|
||||
voxelStats <<
|
||||
|
@ -364,14 +367,14 @@ void Stats::display(
|
|||
voxelStats << " / GPU: " << voxels->getVoxelMemoryUsageGPU() / 1000000.f << "MB";
|
||||
}
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
|
||||
// Voxel Rendering
|
||||
voxelStats.str("");
|
||||
voxelStats.precision(4);
|
||||
voxelStats << "Voxel Rendering Slots Max: " << voxels->getMaxVoxels() / 1000.f << "K";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
voxelStats.str("");
|
||||
|
@ -379,7 +382,7 @@ void Stats::display(
|
|||
voxelStats << "Drawn: " << voxels->getVoxelsWritten() / 1000.f << "K " <<
|
||||
"Abandoned: " << voxels->getAbandonedVoxels() / 1000.f << "K ";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
|
||||
// iterate all the current voxel stats, and list their sending modes, and total voxel counts
|
||||
std::stringstream sendingMode("");
|
||||
|
@ -424,7 +427,7 @@ void Stats::display(
|
|||
sendingMode << " <SCENE STABLE>";
|
||||
}
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)sendingMode.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)sendingMode.str().c_str(), color);
|
||||
}
|
||||
|
||||
// Incoming packets
|
||||
|
@ -435,7 +438,7 @@ void Stats::display(
|
|||
voxelStats << "Voxel Packets to Process: " << qPrintable(packetsString)
|
||||
<< " [Recent Max: " << qPrintable(maxString) << "]";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
if (_resetRecentMaxPacketsSoon && voxelPacketsToProcess > 0) {
|
||||
|
@ -458,7 +461,7 @@ void Stats::display(
|
|||
voxelStats.str("");
|
||||
voxelStats << "Server voxels: " << qPrintable(serversTotalString);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
|
||||
if (_expanded) {
|
||||
QString serversInternalString = locale.toString((uint)totalInternal);
|
||||
|
@ -469,7 +472,7 @@ void Stats::display(
|
|||
"Internal: " << qPrintable(serversInternalString) << " " <<
|
||||
"Leaves: " << qPrintable(serversLeavesString) << "";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
unsigned long localTotal = VoxelTreeElement::getNodeCount();
|
||||
|
@ -479,7 +482,7 @@ void Stats::display(
|
|||
voxelStats.str("");
|
||||
voxelStats << "Local voxels: " << qPrintable(localTotalString);
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
|
||||
if (_expanded) {
|
||||
unsigned long localInternal = VoxelTreeElement::getInternalNodeCount();
|
||||
|
@ -492,7 +495,7 @@ void Stats::display(
|
|||
"Internal: " << qPrintable(localInternalString) << " " <<
|
||||
"Leaves: " << qPrintable(localLeavesString) << "";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0, 2, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
// LOD Details
|
||||
|
@ -501,7 +504,7 @@ void Stats::display(
|
|||
QString displayLODDetails = Menu::getInstance()->getLODFeedbackText();
|
||||
voxelStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed());
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
}
|
||||
|
||||
|
||||
|
@ -526,7 +529,7 @@ void Stats::display(
|
|||
);
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, reflectionsStatus, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color);
|
||||
|
||||
float preDelay = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay) ?
|
||||
audioReflector->getPreDelay() : 0.0f;
|
||||
|
@ -539,16 +542,25 @@ void Stats::display(
|
|||
audioReflector->getSoundMsPerMeter());
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, reflectionsStatus, color);
|
||||
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color);
|
||||
|
||||
bool distanceAttenuationDisabled = Menu::getInstance()->isOptionChecked(
|
||||
MenuOption::AudioSpatialProcessingDontDistanceAttenuate);
|
||||
|
||||
sprintf(reflectionsStatus, "Attenuation: average %5.3f, max %5.3f, min %5.3f, Factor: %5.3f",
|
||||
bool alternateDistanceAttenuationEnabled = Menu::getInstance()->isOptionChecked(
|
||||
MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate);
|
||||
|
||||
sprintf(reflectionsStatus, "Attenuation: average %5.3f, max %5.3f, min %5.3f, %s: %5.3f",
|
||||
audioReflector->getAverageAttenuation(),
|
||||
audioReflector->getMaxAttenuation(),
|
||||
audioReflector->getMinAttenuation(),
|
||||
(distanceAttenuationDisabled ? "Distance Factor [DISABLED]" :
|
||||
alternateDistanceAttenuationEnabled ? "Distance Factor [ALTERNATE]" : "Distance Factor [STANARD]"),
|
||||
audioReflector->getDistanceAttenuationScalingFactor());
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, reflectionsStatus, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color);
|
||||
|
||||
sprintf(reflectionsStatus, "Local Audio: %s Attenuation: %5.3f",
|
||||
(Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio)
|
||||
|
@ -556,7 +568,7 @@ void Stats::display(
|
|||
audioReflector->getLocalAudioAttenuationFactor());
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, reflectionsStatus, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color);
|
||||
|
||||
bool diffusionEnabled = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions);
|
||||
int fanout = diffusionEnabled ? audioReflector->getDiffusionFanout() : 0;
|
||||
|
@ -565,7 +577,7 @@ void Stats::display(
|
|||
(diffusionEnabled ? "yes" : "no"), fanout, diffusionPaths);
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, reflectionsStatus, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color);
|
||||
|
||||
const float AS_PERCENT = 100.0f;
|
||||
float reflectiveRatio = audioReflector->getReflectiveRatio() * AS_PERCENT;
|
||||
|
@ -575,13 +587,20 @@ void Stats::display(
|
|||
reflectiveRatio, diffusionRatio, absorptionRatio);
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, reflectionsStatus, color);
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color);
|
||||
|
||||
sprintf(reflectionsStatus, "Comb Filter Window: %5.3f ms, Allowed: %d, Suppressed: %d",
|
||||
audioReflector->getCombFilterWindow(),
|
||||
audioReflector->getEchoesInjected(),
|
||||
audioReflector->getEchoesSuppressed());
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color);
|
||||
|
||||
sprintf(reflectionsStatus, "Wet/Dry Mix: Original: %5.3f Echoes: %5.3f",
|
||||
audioReflector->getOriginalSourceAttenuation(),
|
||||
audioReflector->getEchoesAttenuation());
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, reflectionsStatus, color);
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ void Cube3DOverlay::render() {
|
|||
if (_isSolid) {
|
||||
glutSolidCube(_size);
|
||||
} else {
|
||||
glLineWidth(_lineWidth);
|
||||
glutWireCube(_size);
|
||||
}
|
||||
glPopMatrix();
|
||||
|
|
|
@ -106,7 +106,7 @@ private:
|
|||
/// Copy constructor prohibited.
|
||||
///
|
||||
Primitive(
|
||||
const Primitive& prim
|
||||
const Primitive& copy
|
||||
);
|
||||
|
||||
// SPI methods are defined here
|
||||
|
@ -153,14 +153,14 @@ public:
|
|||
/// Configuration dependency injection constructor.
|
||||
///
|
||||
Cube(
|
||||
float x,
|
||||
float y,
|
||||
float z,
|
||||
float s,
|
||||
unsigned char r,
|
||||
unsigned char g,
|
||||
unsigned char b,
|
||||
unsigned char faces
|
||||
float x, ///< Cube location on X-axis
|
||||
float y, ///< Cube location on Y-axis
|
||||
float z, ///< Cube location on Z-axis
|
||||
float s, ///< Cube size
|
||||
unsigned char r, ///< Cube red color component
|
||||
unsigned char g, ///< Cube green color component
|
||||
unsigned char b, ///< Cube blue color component
|
||||
unsigned char faces ///< Bitmask of faces of cube excluded from construction
|
||||
);
|
||||
|
||||
~Cube();
|
||||
|
@ -172,36 +172,48 @@ private:
|
|||
const Cube& cube
|
||||
);
|
||||
|
||||
/// Cube initialization
|
||||
///
|
||||
void init(
|
||||
float x,
|
||||
float y,
|
||||
float z,
|
||||
float s,
|
||||
unsigned char r,
|
||||
unsigned char g,
|
||||
unsigned char b,
|
||||
unsigned char faceExclusions
|
||||
float x, ///< Cube location on X-axis
|
||||
float y, ///< Cube location on Y-axis
|
||||
float z, ///< Cube location on Z-axis
|
||||
float s, ///< Cube size
|
||||
unsigned char r, ///< Cube red color component
|
||||
unsigned char g, ///< Cube green color component
|
||||
unsigned char b, ///< Cube blue color component
|
||||
unsigned char faceExclusions ///< Bitmask of faces of cube excluded from construction
|
||||
);
|
||||
|
||||
/// Cube termination
|
||||
///
|
||||
void terminate();
|
||||
|
||||
/// Initialize cube's vertex list
|
||||
///
|
||||
void initializeVertices(
|
||||
float x,
|
||||
float y,
|
||||
float z,
|
||||
float s,
|
||||
unsigned char r,
|
||||
unsigned char g,
|
||||
unsigned char b,
|
||||
unsigned char faceExclusions
|
||||
float x, ///< Cube location on X-axis
|
||||
float y, ///< Cube location on Y-axis
|
||||
float z, ///< Cube location on Z-axis
|
||||
float s, ///< Cube size
|
||||
unsigned char r, ///< Cube red color component
|
||||
unsigned char g, ///< Cube green color component
|
||||
unsigned char b, ///< Cube blue color component
|
||||
unsigned char faceExclusions ///< Bitmask of faces of cube excluded from construction
|
||||
);
|
||||
|
||||
/// Terminate cube's vertex list
|
||||
///
|
||||
void terminateVertices();
|
||||
|
||||
/// Initialize cube's triangle list
|
||||
///
|
||||
void initializeTris(
|
||||
unsigned char faceExclusions
|
||||
);
|
||||
|
||||
/// Terminate cube's triangle list
|
||||
///
|
||||
void terminateTris();
|
||||
|
||||
// SPI virtual override methods go here
|
||||
|
@ -219,11 +231,11 @@ private:
|
|||
|
||||
unsigned long _cpuMemoryUsage; ///< Memory allocation of object
|
||||
|
||||
static const int _sNumFacesPerCube = 6;
|
||||
static const int _sNumVerticesPerCube = 24;
|
||||
static unsigned char _sFaceIndexToHalfSpaceMask[6];
|
||||
static float _sVertexIndexToConstructionVector[24][3];
|
||||
static float _sVertexIndexToNormalVector[6][3];
|
||||
static const int _sNumFacesPerCube = 6; ///< Number of faces per cube
|
||||
static const int _sNumVerticesPerCube = 24; ///< Number of vertices per cube
|
||||
static unsigned char _sFaceIndexToHalfSpaceMask[6]; ///< index to bitmask map
|
||||
static float _sVertexIndexToConstructionVector[24][3]; ///< Vertex index to construction vector map
|
||||
static float _sVertexIndexToNormalVector[6][3]; ///< Vertex index to normal vector map
|
||||
|
||||
};
|
||||
|
||||
|
@ -242,13 +254,13 @@ public:
|
|||
/// Add primitive to renderer database.
|
||||
///
|
||||
int add(
|
||||
Primitive* primitive ///< Pointer to primitive
|
||||
Primitive* primitive ///< Primitive instance to be added
|
||||
);
|
||||
|
||||
/// Remove primitive from renderer database.
|
||||
///
|
||||
void remove(
|
||||
int id ///< Primitive id
|
||||
int id ///< Primitive id to be removed
|
||||
);
|
||||
|
||||
/// Clear all primitives from renderer database
|
||||
|
@ -278,7 +290,7 @@ private:
|
|||
/// Copy constructor prohibited.
|
||||
///
|
||||
Renderer(
|
||||
const Renderer& primitive
|
||||
const Renderer& copy
|
||||
);
|
||||
|
||||
// SPI methods are defined here
|
||||
|
@ -286,10 +298,10 @@ private:
|
|||
/// Add primitive to renderer database.
|
||||
/// Service implementer to provide private override for this method
|
||||
/// in derived class
|
||||
/// @return primitive id
|
||||
/// @return Primitive id
|
||||
///
|
||||
virtual int vAdd(
|
||||
Primitive* primitive ///< Pointer to primitive
|
||||
Primitive* primitive ///< Primitive instance to be added
|
||||
) = 0;
|
||||
|
||||
/// Remove primitive from renderer database.
|
||||
|
@ -297,7 +309,7 @@ private:
|
|||
/// in derived class
|
||||
///
|
||||
virtual void vRemove(
|
||||
int id ///< Primitive id
|
||||
int id ///< Primitive id
|
||||
) = 0;
|
||||
|
||||
/// Clear all primitives from renderer database
|
||||
|
@ -332,7 +344,7 @@ public:
|
|||
/// Configuration dependency injection constructor.
|
||||
///
|
||||
PrimitiveRenderer(
|
||||
int maxCount
|
||||
int maxCount ///< Max count
|
||||
);
|
||||
|
||||
~PrimitiveRenderer();
|
||||
|
@ -365,39 +377,39 @@ private:
|
|||
/// Construct the elements of the faces of the primitive.
|
||||
///
|
||||
void constructElements(
|
||||
Primitive* primitive
|
||||
Primitive* primitive ///< Primitive instance
|
||||
);
|
||||
|
||||
/// Deconstruct the elements of the faces of the primitive.
|
||||
///
|
||||
void deconstructElements(
|
||||
Primitive* primitive
|
||||
Primitive* primitive ///< Primitive instance
|
||||
);
|
||||
|
||||
/// Deconstruct the triangle element from the GL buffer.
|
||||
///
|
||||
void deconstructTriElement(
|
||||
int idx
|
||||
int idx ///< Triangle element index
|
||||
);
|
||||
|
||||
/// Deconstruct the vertex element from the GL buffer.
|
||||
///
|
||||
void deconstructVertexElement(
|
||||
int idx
|
||||
int idx ///< Vertex element index
|
||||
);
|
||||
|
||||
/// Transfer the vertex element to the GL buffer.
|
||||
///
|
||||
void transferVertexElement(
|
||||
int idx,
|
||||
VertexElement *vertex
|
||||
int idx, ///< Vertex element index
|
||||
VertexElement *vertex ///< Vertex element instance
|
||||
);
|
||||
|
||||
/// Transfer the triangle element to the GL buffer.
|
||||
///
|
||||
void transferTriElement(
|
||||
int idx,
|
||||
int tri[3]
|
||||
int idx, ///< Triangle element index
|
||||
int tri[3] ///< Triangle element data
|
||||
);
|
||||
|
||||
/// Get available primitive index.
|
||||
|
@ -424,13 +436,13 @@ private:
|
|||
/// Add primitive to renderer database.
|
||||
///
|
||||
int vAdd(
|
||||
Primitive* primitive
|
||||
Primitive* primitive ///< Primitive instance to be added
|
||||
);
|
||||
|
||||
/// Remove primitive from renderer database.
|
||||
///
|
||||
void vRemove(
|
||||
int id
|
||||
int id ///< Primitive id to be removed
|
||||
);
|
||||
|
||||
/// Clear all primitives from renderer database
|
||||
|
@ -451,7 +463,7 @@ private:
|
|||
|
||||
private:
|
||||
|
||||
int _maxCount;
|
||||
int _maxCount; ///< Maximum count of tris
|
||||
|
||||
// GL related parameters
|
||||
|
||||
|
@ -479,8 +491,8 @@ private:
|
|||
|
||||
// Statistics parameters, not necessary for proper operation
|
||||
|
||||
unsigned long _gpuMemoryUsage;
|
||||
unsigned long _cpuMemoryUsage;
|
||||
unsigned long _gpuMemoryUsage; ///< GPU memory used by this instance
|
||||
unsigned long _cpuMemoryUsage; ///< CPU memory used by this instance
|
||||
|
||||
|
||||
static const int _sIndicesPerTri = 3;
|
||||
|
|
|
@ -117,7 +117,7 @@ void VoxelSystem::elementDeleted(OctreeElement* element) {
|
|||
forceRemoveNodeFromArrays(voxel);
|
||||
} else {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) {
|
||||
printf("VoxelSystem::elementDeleted() while _voxelsInWriteArrays==0, is that expected? \n");
|
||||
qDebug("VoxelSystem::elementDeleted() while _voxelsInWriteArrays==0, is that expected? ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -938,6 +938,8 @@ void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart,
|
|||
}
|
||||
|
||||
void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) {
|
||||
static unsigned int lockForReadAttempt = 0;
|
||||
static unsigned int lockForWriteAttempt = 0;
|
||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||
"copyWrittenDataToReadArrays()");
|
||||
|
||||
|
@ -946,7 +948,9 @@ void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) {
|
|||
// time around, the only side effect is the VBOs won't be updated this frame
|
||||
const int WAIT_FOR_LOCK_IN_MS = 5;
|
||||
if (_readArraysLock.tryLockForWrite(WAIT_FOR_LOCK_IN_MS)) {
|
||||
lockForWriteAttempt = 0;
|
||||
if (_writeArraysLock.tryLockForRead(WAIT_FOR_LOCK_IN_MS)) {
|
||||
lockForReadAttempt = 0;
|
||||
if (_voxelsDirty && _voxelsUpdated) {
|
||||
if (fullVBOs) {
|
||||
copyWrittenDataToReadArraysFullVBOs();
|
||||
|
@ -956,11 +960,19 @@ void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) {
|
|||
}
|
||||
_writeArraysLock.unlock();
|
||||
} else {
|
||||
qDebug() << "couldn't get _writeArraysLock.LockForRead()...";
|
||||
lockForReadAttempt++;
|
||||
// only report error of first failure
|
||||
if (lockForReadAttempt == 1) {
|
||||
qDebug() << "couldn't get _writeArraysLock.LockForRead()...";
|
||||
}
|
||||
}
|
||||
_readArraysLock.unlock();
|
||||
} else {
|
||||
qDebug() << "couldn't get _readArraysLock.LockForWrite()...";
|
||||
lockForWriteAttempt++;
|
||||
// only report error of first failure
|
||||
if (lockForWriteAttempt == 1) {
|
||||
qDebug() << "couldn't get _readArraysLock.LockForWrite()...";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1683,11 +1695,12 @@ bool VoxelSystem::inspectForExteriorOcclusionsOperation(OctreeElement* element,
|
|||
|
||||
//qDebug("Completely occupied voxel at %f %f %f size: %f", v.x, v.y, v.z, s);
|
||||
|
||||
// TODO: All of the exterior faces of this voxel element are
|
||||
// occluders, which means that this element is completely
|
||||
// occupied. Hence, the subtree from this node could be
|
||||
// pruned and replaced by a leaf voxel, if the visible
|
||||
// properties of the children are the same
|
||||
// All of the exterior faces of this voxel element are
|
||||
// occluders, which means that this element is completely
|
||||
// occupied. Hence, the subtree from this node could be
|
||||
// pruned and replaced by a leaf voxel, if the visible
|
||||
// properties of the children are the same
|
||||
|
||||
} else if (exteriorOcclusions != OctreeElement::HalfSpace::None) {
|
||||
//const glm::vec3& v = voxel->getCorner();
|
||||
//float s = voxel->getScale();
|
||||
|
|
148
interface/ui/scriptEditorWidget.ui
Normal file
148
interface/ui/scriptEditorWidget.ui
Normal file
|
@ -0,0 +1,148 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ScriptEditorWidget</class>
|
||||
<widget class="QDockWidget" name="ScriptEditorWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>691</width>
|
||||
<height>549</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>541</width>
|
||||
<height>238</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">font-family: Helvetica, Arial, sans-serif;</string>
|
||||
</property>
|
||||
<property name="features">
|
||||
<set>QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable</set>
|
||||
</property>
|
||||
<property name="allowedAreas">
|
||||
<set>Qt::NoDockWidgetArea</set>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Edit Script</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="5,0,1">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="scriptEdit">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier</family>
|
||||
<pointsize>9</pointsize>
|
||||
<weight>50</weight>
|
||||
<italic>false</italic>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">font: 9pt "Courier";</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Debug Log:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="onTheFlyCheckBox">
|
||||
<property name="text">
|
||||
<string>Run on the fly (Careful: Any valid change made to the code will run immediately)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="clearButton">
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="debugText">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">font: 8pt "Courier";</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>clearButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>debugText</receiver>
|
||||
<slot>clear()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>663</x>
|
||||
<y>447</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>350</x>
|
||||
<y>501</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
331
interface/ui/scriptEditorWindow.ui
Normal file
331
interface/ui/scriptEditorWindow.ui
Normal file
|
@ -0,0 +1,331 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ScriptEditorWindow</class>
|
||||
<widget class="QWidget" name="ScriptEditorWindow">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>706</width>
|
||||
<height>682</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Script Editor</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">font-family: Helvetica, Arial, sans-serif;</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,0">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetNoConstraint</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QToolButton" name="newButton">
|
||||
<property name="toolTip">
|
||||
<string>New Script (Ctrl+N)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>New</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>../resources/icons/new-script.svg</normaloff>
|
||||
<normalon>../resources/icons/new-script.svg</normalon>../resources/icons/new-script.svg</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="loadButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Load Script (Ctrl+O)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>../resources/icons/load-script.svg</normaloff>../resources/icons/load-script.svg</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonIconOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="saveButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::NoContextMenu</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Save Script (Ctrl+S)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>../resources/icons/save-script.svg</normaloff>../resources/icons/save-script.svg</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoRepeatDelay">
|
||||
<number>316</number>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="toggleRunButton">
|
||||
<property name="toolTip">
|
||||
<string>Toggle Run Script (F5)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Run/Stop</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>../resources/icons/start-script.svg</normaloff>../resources/icons/start-script.svg</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>80</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="tabPosition">
|
||||
<enum>QTabWidget::West</enum>
|
||||
</property>
|
||||
<property name="tabShape">
|
||||
<enum>QTabWidget::Triangular</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="elideMode">
|
||||
<enum>Qt::ElideNone</enum>
|
||||
</property>
|
||||
<property name="tabsClosable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="movable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>saveButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>ScriptEditorWindow</receiver>
|
||||
<slot>saveScriptClicked()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>236</x>
|
||||
<y>10</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>199</x>
|
||||
<y>264</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>toggleRunButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>ScriptEditorWindow</receiver>
|
||||
<slot>toggleRunScriptClicked()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>330</x>
|
||||
<y>10</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>199</x>
|
||||
<y>264</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>newButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>ScriptEditorWindow</receiver>
|
||||
<slot>newScriptClicked()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>58</x>
|
||||
<y>10</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>199</x>
|
||||
<y>264</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>loadButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>ScriptEditorWindow</receiver>
|
||||
<slot>loadScriptClicked()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>85</x>
|
||||
<y>10</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>199</x>
|
||||
<y>264</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>tabWidget</sender>
|
||||
<signal>currentChanged(int)</signal>
|
||||
<receiver>ScriptEditorWindow</receiver>
|
||||
<slot>tabSwitched(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>352</x>
|
||||
<y>360</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>352</x>
|
||||
<y>340</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>tabWidget</sender>
|
||||
<signal>tabCloseRequested(int)</signal>
|
||||
<receiver>ScriptEditorWindow</receiver>
|
||||
<slot>tabCloseRequested(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>352</x>
|
||||
<y>360</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>352</x>
|
||||
<y>340</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -67,21 +67,25 @@ Sound::Sound(float volume, float frequency, float duration, float decay, QObject
|
|||
}
|
||||
|
||||
Sound::Sound(const QUrl& sampleURL, QObject* parent) :
|
||||
QObject(parent)
|
||||
QObject(parent),
|
||||
_hasDownloaded(false)
|
||||
{
|
||||
// assume we have a QApplication or QCoreApplication instance and use the
|
||||
// QNetworkAccess manager to grab the raw audio file at the given URL
|
||||
|
||||
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
|
||||
connect(manager, SIGNAL(finished(QNetworkReply*)),
|
||||
this, SLOT(replyFinished(QNetworkReply*)));
|
||||
|
||||
qDebug() << "Requesting audio file" << sampleURL.toDisplayString();
|
||||
manager->get(QNetworkRequest(sampleURL));
|
||||
|
||||
QNetworkReply* soundDownload = manager->get(QNetworkRequest(sampleURL));
|
||||
connect(soundDownload, &QNetworkReply::finished, this, &Sound::replyFinished);
|
||||
connect(soundDownload, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(replyError(QNetworkReply::NetworkError)));
|
||||
}
|
||||
|
||||
void Sound::replyFinished(QNetworkReply* reply) {
|
||||
void Sound::replyFinished() {
|
||||
|
||||
QNetworkReply* reply = reinterpret_cast<QNetworkReply*>(sender());
|
||||
|
||||
// replace our byte array with the downloaded data
|
||||
QByteArray rawAudioByteArray = reply->readAll();
|
||||
|
||||
|
@ -108,6 +112,13 @@ void Sound::replyFinished(QNetworkReply* reply) {
|
|||
} else {
|
||||
qDebug() << "Network reply without 'Content-Type'.";
|
||||
}
|
||||
|
||||
_hasDownloaded = true;
|
||||
}
|
||||
|
||||
void Sound::replyError(QNetworkReply::NetworkError code) {
|
||||
QNetworkReply* reply = reinterpret_cast<QNetworkReply*>(sender());
|
||||
qDebug() << "Error downloading sound file at" << reply->url().toString() << "-" << reply->errorString();
|
||||
}
|
||||
|
||||
void Sound::downSample(const QByteArray& rawAudioByteArray) {
|
||||
|
|
|
@ -13,25 +13,30 @@
|
|||
#define hifi_Sound_h
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class QNetworkReply;
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
class Sound : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool downloaded READ hasDownloaded)
|
||||
public:
|
||||
Sound(const QUrl& sampleURL, QObject* parent = NULL);
|
||||
Sound(float volume, float frequency, float duration, float decay, QObject* parent = NULL);
|
||||
|
||||
bool hasDownloaded() const { return _hasDownloaded; }
|
||||
|
||||
const QByteArray& getByteArray() { return _byteArray; }
|
||||
|
||||
private:
|
||||
QByteArray _byteArray;
|
||||
|
||||
bool _hasDownloaded;
|
||||
|
||||
void downSample(const QByteArray& rawAudioByteArray);
|
||||
void interpretAsWav(const QByteArray& inputAudioByteArray, QByteArray& outputAudioByteArray);
|
||||
|
||||
private slots:
|
||||
void replyFinished(QNetworkReply* reply);
|
||||
void replyFinished();
|
||||
void replyError(QNetworkReply::NetworkError code);
|
||||
};
|
||||
|
||||
#endif // hifi_Sound_h
|
||||
|
|
|
@ -51,7 +51,9 @@ AvatarData::AvatarData() :
|
|||
_displayNameTargetAlpha(0.0f),
|
||||
_displayNameAlpha(0.0f),
|
||||
_billboard(),
|
||||
_errorLogExpiry(0)
|
||||
_errorLogExpiry(0),
|
||||
_owningAvatarMixer(),
|
||||
_lastUpdateTimer()
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -193,6 +195,10 @@ bool AvatarData::shouldLogError(const quint64& now) {
|
|||
|
||||
// read data in packet starting at byte offset and return number of bytes parsed
|
||||
int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) {
|
||||
|
||||
// reset the last heard timer since we have new data for this AvatarData
|
||||
_lastUpdateTimer.restart();
|
||||
|
||||
// lazily allocate memory for HeadData in case we're not an Avatar instance
|
||||
if (!_headData) {
|
||||
_headData = new HeadData(this);
|
||||
|
|
|
@ -32,6 +32,7 @@ typedef unsigned long long quint64;
|
|||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include <QtCore/QElapsedTimer>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QObject>
|
||||
|
@ -44,6 +45,7 @@ typedef unsigned long long quint64;
|
|||
|
||||
#include <CollisionInfo.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <Node.h>
|
||||
|
||||
#include "HeadData.h"
|
||||
#include "HandData.h"
|
||||
|
@ -95,13 +97,14 @@ class AvatarData : public QObject {
|
|||
Q_PROPERTY(float audioLoudness READ getAudioLoudness WRITE setAudioLoudness)
|
||||
Q_PROPERTY(float audioAverageLoudness READ getAudioAverageLoudness WRITE setAudioAverageLoudness)
|
||||
|
||||
Q_PROPERTY(QString displayName READ getDisplayName WRITE setDisplayName)
|
||||
Q_PROPERTY(QString faceModelURL READ getFaceModelURLFromScript WRITE setFaceModelURLFromScript)
|
||||
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript)
|
||||
Q_PROPERTY(QString billboardURL READ getBillboardURL WRITE setBillboardFromURL)
|
||||
|
||||
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
||||
|
||||
Q_PROPERTY(QUuid sessionUUID READ getSessionUUID);
|
||||
Q_PROPERTY(QUuid sessionUUID READ getSessionUUID)
|
||||
public:
|
||||
AvatarData();
|
||||
virtual ~AvatarData();
|
||||
|
@ -220,6 +223,11 @@ public:
|
|||
QString getSkeletonModelURLFromScript() const { return _skeletonModelURL.toString(); }
|
||||
void setSkeletonModelURLFromScript(const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); }
|
||||
|
||||
Node* getOwningAvatarMixer() { return _owningAvatarMixer.data(); }
|
||||
void setOwningAvatarMixer(const QWeakPointer<Node>& owningAvatarMixer) { _owningAvatarMixer = owningAvatarMixer; }
|
||||
|
||||
QElapsedTimer& getLastUpdateTimer() { return _lastUpdateTimer; }
|
||||
|
||||
virtual float getBoundingRadius() const { return 1.f; }
|
||||
|
||||
static void setNetworkAccessManager(QNetworkAccessManager* sharedAccessManager) { networkAccessManager = sharedAccessManager; }
|
||||
|
@ -278,7 +286,10 @@ protected:
|
|||
static QNetworkAccessManager* networkAccessManager;
|
||||
|
||||
quint64 _errorLogExpiry; ///< time in future when to log an error
|
||||
|
||||
|
||||
QWeakPointer<Node> _owningAvatarMixer;
|
||||
QElapsedTimer _lastUpdateTimer;
|
||||
|
||||
/// Loads the joint indices, names from the FST file (if any)
|
||||
virtual void updateJointMappings();
|
||||
|
||||
|
|
|
@ -9,11 +9,14 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <PacketHeaders.h>
|
||||
|
||||
#include "AvatarHashMap.h"
|
||||
|
||||
AvatarHashMap::AvatarHashMap() :
|
||||
_avatarHash()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void AvatarHashMap::insert(const QUuid& id, AvatarSharedPointer avatar) {
|
||||
|
@ -22,6 +25,150 @@ void AvatarHashMap::insert(const QUuid& id, AvatarSharedPointer avatar) {
|
|||
}
|
||||
|
||||
AvatarHash::iterator AvatarHashMap::erase(const AvatarHash::iterator& iterator) {
|
||||
qDebug() << "Removing Avatar with UUID" << iterator.key() << "from AvatarHashMap.";
|
||||
return _avatarHash.erase(iterator);
|
||||
}
|
||||
|
||||
const qint64 AVATAR_SILENCE_THRESHOLD_MSECS = 5 * 1000;
|
||||
|
||||
bool AvatarHashMap::shouldKillAvatar(const AvatarSharedPointer& sharedAvatar) {
|
||||
return (sharedAvatar->getOwningAvatarMixer() == NULL
|
||||
|| sharedAvatar->getLastUpdateTimer().elapsed() > AVATAR_SILENCE_THRESHOLD_MSECS);
|
||||
}
|
||||
|
||||
void AvatarHashMap::processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
switch (packetTypeForPacket(datagram)) {
|
||||
case PacketTypeBulkAvatarData:
|
||||
processAvatarDataPacket(datagram, mixerWeakPointer);
|
||||
break;
|
||||
case PacketTypeAvatarIdentity:
|
||||
processAvatarIdentityPacket(datagram, mixerWeakPointer);
|
||||
break;
|
||||
case PacketTypeAvatarBillboard:
|
||||
processAvatarBillboardPacket(datagram, mixerWeakPointer);
|
||||
break;
|
||||
case PacketTypeKillAvatar:
|
||||
processKillAvatar(datagram);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool AvatarHashMap::containsAvatarWithDisplayName(const QString& displayName) {
|
||||
|
||||
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
||||
while (avatarIterator != _avatarHash.end()) {
|
||||
AvatarSharedPointer sharedAvatar = avatarIterator.value();
|
||||
if (avatarIterator.value()->getDisplayName() == displayName) {
|
||||
// this is a match
|
||||
// check if this avatar should still be around
|
||||
if (!shouldKillAvatar(sharedAvatar)) {
|
||||
// we have a match, return true
|
||||
return true;
|
||||
} else {
|
||||
// we should remove this avatar, do that now
|
||||
erase(avatarIterator);
|
||||
}
|
||||
|
||||
break;
|
||||
} else {
|
||||
++avatarIterator;
|
||||
}
|
||||
}
|
||||
|
||||
// return false, no match
|
||||
return false;
|
||||
}
|
||||
|
||||
AvatarSharedPointer AvatarHashMap::newSharedAvatar() {
|
||||
return AvatarSharedPointer(new AvatarData());
|
||||
}
|
||||
|
||||
AvatarSharedPointer AvatarHashMap::matchingOrNewAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
AvatarSharedPointer matchingAvatar = _avatarHash.value(sessionUUID);
|
||||
|
||||
if (!matchingAvatar) {
|
||||
// insert the new avatar into our hash
|
||||
matchingAvatar = newSharedAvatar();
|
||||
|
||||
qDebug() << "Adding avatar with sessionUUID " << sessionUUID << "to AvatarHashMap.";
|
||||
_avatarHash.insert(sessionUUID, matchingAvatar);
|
||||
|
||||
matchingAvatar->setOwningAvatarMixer(mixerWeakPointer);
|
||||
}
|
||||
|
||||
return matchingAvatar;
|
||||
}
|
||||
|
||||
void AvatarHashMap::processAvatarDataPacket(const QByteArray &datagram, const QWeakPointer<Node> &mixerWeakPointer) {
|
||||
int bytesRead = numBytesForPacketHeader(datagram);
|
||||
|
||||
// enumerate over all of the avatars in this packet
|
||||
// only add them if mixerWeakPointer points to something (meaning that mixer is still around)
|
||||
while (bytesRead < datagram.size() && mixerWeakPointer.data()) {
|
||||
QUuid sessionUUID = QUuid::fromRfc4122(datagram.mid(bytesRead, NUM_BYTES_RFC4122_UUID));
|
||||
bytesRead += NUM_BYTES_RFC4122_UUID;
|
||||
|
||||
AvatarSharedPointer matchingAvatarData = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
|
||||
|
||||
// have the matching (or new) avatar parse the data from the packet
|
||||
bytesRead += matchingAvatarData->parseDataAtOffset(datagram, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarHashMap::processAvatarIdentityPacket(const QByteArray &packet, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
// setup a data stream to parse the packet
|
||||
QDataStream identityStream(packet);
|
||||
identityStream.skipRawData(numBytesForPacketHeader(packet));
|
||||
|
||||
QUuid sessionUUID;
|
||||
|
||||
while (!identityStream.atEnd()) {
|
||||
|
||||
QUrl faceMeshURL, skeletonURL;
|
||||
QString displayName;
|
||||
identityStream >> sessionUUID >> faceMeshURL >> skeletonURL >> displayName;
|
||||
|
||||
// mesh URL for a UUID, find avatar in our list
|
||||
AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
|
||||
if (matchingAvatar) {
|
||||
|
||||
if (matchingAvatar->getFaceModelURL() != faceMeshURL) {
|
||||
matchingAvatar->setFaceModelURL(faceMeshURL);
|
||||
}
|
||||
|
||||
if (matchingAvatar->getSkeletonModelURL() != skeletonURL) {
|
||||
matchingAvatar->setSkeletonModelURL(skeletonURL);
|
||||
}
|
||||
|
||||
if (matchingAvatar->getDisplayName() != displayName) {
|
||||
matchingAvatar->setDisplayName(displayName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarHashMap::processAvatarBillboardPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||
int headerSize = numBytesForPacketHeader(packet);
|
||||
QUuid sessionUUID = QUuid::fromRfc4122(QByteArray::fromRawData(packet.constData() + headerSize, NUM_BYTES_RFC4122_UUID));
|
||||
|
||||
AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
|
||||
if (matchingAvatar) {
|
||||
QByteArray billboard = packet.mid(headerSize + NUM_BYTES_RFC4122_UUID);
|
||||
if (matchingAvatar->getBillboard() != billboard) {
|
||||
matchingAvatar->setBillboard(billboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarHashMap::processKillAvatar(const QByteArray& datagram) {
|
||||
// read the node id
|
||||
QUuid sessionUUID = QUuid::fromRfc4122(datagram.mid(numBytesForPacketHeader(datagram), NUM_BYTES_RFC4122_UUID));
|
||||
|
||||
// remove the avatar with that UUID from our hash, if it exists
|
||||
AvatarHash::iterator matchedAvatar = _avatarHash.find(sessionUUID);
|
||||
if (matchedAvatar != _avatarHash.end()) {
|
||||
erase(matchedAvatar);
|
||||
}
|
||||
}
|
|
@ -16,12 +16,15 @@
|
|||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QUuid>
|
||||
|
||||
#include <Node.h>
|
||||
|
||||
#include "AvatarData.h"
|
||||
|
||||
typedef QSharedPointer<AvatarData> AvatarSharedPointer;
|
||||
typedef QHash<QUuid, AvatarSharedPointer> AvatarHash;
|
||||
|
||||
class AvatarHashMap {
|
||||
class AvatarHashMap : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AvatarHashMap();
|
||||
|
||||
|
@ -29,9 +32,23 @@ public:
|
|||
int size() const { return _avatarHash.size(); }
|
||||
|
||||
virtual void insert(const QUuid& id, AvatarSharedPointer avatar);
|
||||
|
||||
public slots:
|
||||
void processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
bool containsAvatarWithDisplayName(const QString& displayName);
|
||||
|
||||
protected:
|
||||
virtual AvatarHash::iterator erase(const AvatarHash::iterator& iterator);
|
||||
|
||||
bool shouldKillAvatar(const AvatarSharedPointer& sharedAvatar);
|
||||
|
||||
virtual AvatarSharedPointer newSharedAvatar();
|
||||
AvatarSharedPointer matchingOrNewAvatar(const QUuid& nodeUUID, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
|
||||
void processAvatarDataPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
void processAvatarIdentityPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
void processAvatarBillboardPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
|
||||
void processKillAvatar(const QByteArray& datagram);
|
||||
|
||||
AvatarHash _avatarHash;
|
||||
};
|
||||
|
|
|
@ -1624,7 +1624,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
}
|
||||
float radiusScale = extractUniformScale(joint.transform * fbxCluster.inverseBindMatrix);
|
||||
JointShapeInfo& jointShapeInfo = jointShapeInfos[jointIndex];
|
||||
jointShapeInfo.boneBegin = rotateMeshToJoint * (radiusScale * (boneBegin - boneEnd));
|
||||
|
||||
float totalWeight = 0.0f;
|
||||
for (int j = 0; j < cluster.indices.size(); j++) {
|
||||
|
@ -1686,7 +1685,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
}
|
||||
}
|
||||
float radiusScale = extractUniformScale(joint.transform * firstFBXCluster.inverseBindMatrix);
|
||||
jointShapeInfo.boneBegin = rotateMeshToJoint * (radiusScale * (boneBegin - boneEnd));
|
||||
|
||||
glm::vec3 averageVertex(0.f);
|
||||
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
|
||||
|
@ -1722,6 +1720,14 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
FBXJoint& joint = geometry.joints[i];
|
||||
JointShapeInfo& jointShapeInfo = jointShapeInfos[i];
|
||||
|
||||
if (joint.parentIndex == -1) {
|
||||
jointShapeInfo.boneBegin = glm::vec3(0.0f);
|
||||
} else {
|
||||
const FBXJoint& parentJoint = geometry.joints[joint.parentIndex];
|
||||
glm::quat inverseRotation = glm::inverse(extractRotation(joint.transform));
|
||||
jointShapeInfo.boneBegin = inverseRotation * (extractTranslation(parentJoint.transform) - extractTranslation(joint.transform));
|
||||
}
|
||||
|
||||
// we use a capsule if the joint ANY mesh vertices successfully projected onto the bone
|
||||
// AND its boneRadius is not too close to zero
|
||||
bool collideLikeCapsule = jointShapeInfo.numProjectedVertices > 0
|
||||
|
@ -1733,12 +1739,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
joint.shapeType = Shape::CAPSULE_SHAPE;
|
||||
} else {
|
||||
// collide the joint like a sphere
|
||||
joint.shapeType = Shape::SPHERE_SHAPE;
|
||||
if (jointShapeInfo.numVertices > 0) {
|
||||
jointShapeInfo.averageVertex /= (float)jointShapeInfo.numVertices;
|
||||
joint.shapePosition = jointShapeInfo.averageVertex;
|
||||
} else {
|
||||
joint.shapePosition = glm::vec3(0.f);
|
||||
joint.shapeType = Shape::SPHERE_SHAPE;
|
||||
}
|
||||
if (jointShapeInfo.numProjectedVertices == 0
|
||||
&& jointShapeInfo.numVertices > 0) {
|
||||
|
@ -1747,6 +1753,15 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
jointShapeInfo.averageRadius /= (float)jointShapeInfo.numVertices;
|
||||
joint.boneRadius = jointShapeInfo.averageRadius;
|
||||
}
|
||||
|
||||
float distanceFromEnd = glm::length(joint.shapePosition);
|
||||
float distanceFromBegin = glm::distance(joint.shapePosition, jointShapeInfo.boneBegin);
|
||||
if (distanceFromEnd > joint.distanceToParent && distanceFromBegin > joint.distanceToParent) {
|
||||
// The shape is further from both joint endpoints than the endpoints are from each other
|
||||
// which probably means the model has a bad transform somewhere. We disable this shape
|
||||
// by setting its type to UNKNOWN_SHAPE.
|
||||
joint.shapeType = Shape::UNKNOWN_SHAPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
geometry.palmDirection = parseVec3(mapping.value("palmDirection", "0, -1, 0").toString());
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include <QVariant>
|
||||
#include <QVector>
|
||||
|
||||
#include <Shape.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
|
@ -91,7 +93,7 @@ public:
|
|||
QString name;
|
||||
glm::vec3 shapePosition; // in joint frame
|
||||
glm::quat shapeRotation; // in joint frame
|
||||
int shapeType;
|
||||
Shape::Type shapeType;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -227,7 +227,30 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const SharedNo
|
|||
}
|
||||
}
|
||||
|
||||
writeDatagram(datagram, *destinationSockAddr, destinationNode->getConnectionSecret());
|
||||
return writeDatagram(datagram, *destinationSockAddr, destinationNode->getConnectionSecret());
|
||||
}
|
||||
|
||||
// didn't have a destinationNode to send to, return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
qint64 LimitedNodeList::writeUnverifiedDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode,
|
||||
const HifiSockAddr& overridenSockAddr) {
|
||||
if (destinationNode) {
|
||||
// if we don't have an ovveriden address, assume they want to send to the node's active socket
|
||||
const HifiSockAddr* destinationSockAddr = &overridenSockAddr;
|
||||
if (overridenSockAddr.isNull()) {
|
||||
if (destinationNode->getActiveSocket()) {
|
||||
// use the node's active socket as the destination socket
|
||||
destinationSockAddr = destinationNode->getActiveSocket();
|
||||
} else {
|
||||
// we don't have a socket to send to, return 0
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// don't use the node secret!
|
||||
return writeDatagram(datagram, *destinationSockAddr, QUuid());
|
||||
}
|
||||
|
||||
// didn't have a destinationNode to send to, return 0
|
||||
|
@ -243,6 +266,11 @@ qint64 LimitedNodeList::writeDatagram(const char* data, qint64 size, const Share
|
|||
return writeDatagram(QByteArray(data, size), destinationNode, overridenSockAddr);
|
||||
}
|
||||
|
||||
qint64 LimitedNodeList::writeUnverifiedDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode,
|
||||
const HifiSockAddr& overridenSockAddr) {
|
||||
return writeUnverifiedDatagram(QByteArray(data, size), destinationNode, overridenSockAddr);
|
||||
}
|
||||
|
||||
void LimitedNodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet) {
|
||||
// the node decided not to do anything with this packet
|
||||
// if it comes from a known source we should keep that node alive
|
||||
|
|
|
@ -66,10 +66,17 @@ public:
|
|||
|
||||
qint64 writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode,
|
||||
const HifiSockAddr& overridenSockAddr = HifiSockAddr());
|
||||
|
||||
qint64 writeUnverifiedDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode,
|
||||
const HifiSockAddr& overridenSockAddr = HifiSockAddr());
|
||||
|
||||
qint64 writeUnverifiedDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr);
|
||||
qint64 writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode,
|
||||
const HifiSockAddr& overridenSockAddr = HifiSockAddr());
|
||||
|
||||
qint64 writeUnverifiedDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode,
|
||||
const HifiSockAddr& overridenSockAddr = HifiSockAddr());
|
||||
|
||||
void(*linkedDataCreateCallback)(Node *);
|
||||
|
||||
NodeHash getNodeHash();
|
||||
|
|
|
@ -46,7 +46,7 @@ const HifiSockAddr& Logging::socket() {
|
|||
// use the first IP address
|
||||
_logstashSocket.setAddress(hostInfo.addresses().first());
|
||||
} else {
|
||||
printf("Failed to lookup logstash IP - will try again on next log attempt.\n");
|
||||
qDebug("Failed to lookup logstash IP - will try again on next log attempt.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>()
|
|||
<< PacketTypeDomainServerRequireDTLS << PacketTypeDomainConnectRequest
|
||||
<< PacketTypeDomainList << PacketTypeDomainListRequest
|
||||
<< PacketTypeCreateAssignment << PacketTypeRequestAssignment << PacketTypeStunResponse
|
||||
<< PacketTypeNodeJsonStats;
|
||||
<< PacketTypeNodeJsonStats << PacketTypeVoxelQuery << PacketTypeParticleQuery;
|
||||
|
||||
const int NUM_BYTES_MD5_HASH = 16;
|
||||
const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID;
|
||||
|
|
|
@ -471,8 +471,8 @@ void Octree::processRemoveOctreeElementsBitstream(const unsigned char* bitstream
|
|||
int codeLength = numberOfThreeBitSectionsInCode(voxelCode, maxSize);
|
||||
|
||||
if (codeLength == OVERFLOWED_OCTCODE_BUFFER) {
|
||||
printf("WARNING! Got remove voxel bitstream that would overflow buffer in numberOfThreeBitSectionsInCode(), ");
|
||||
printf("bailing processing of packet!\n");
|
||||
qDebug("WARNING! Got remove voxel bitstream that would overflow buffer in numberOfThreeBitSectionsInCode(),"
|
||||
" bailing processing of packet!");
|
||||
break;
|
||||
}
|
||||
int voxelDataSize = bytesRequiredForCodeLength(codeLength) + SIZE_OF_COLOR_DATA;
|
||||
|
@ -482,7 +482,7 @@ void Octree::processRemoveOctreeElementsBitstream(const unsigned char* bitstream
|
|||
voxelCode += voxelDataSize;
|
||||
atByte += voxelDataSize;
|
||||
} else {
|
||||
printf("WARNING! Got remove voxel bitstream that would overflow buffer, bailing processing!\n");
|
||||
qDebug("WARNING! Got remove voxel bitstream that would overflow buffer, bailing processing!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1404,7 +1404,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* node,
|
|||
outputBits(childrenExistInPacketBits, false, true);
|
||||
printf(" childrenColored:");
|
||||
outputBits(childrenColoredBits, false, true);
|
||||
printf("\n");
|
||||
qDebug("");
|
||||
**/
|
||||
|
||||
// if we were unable to fit this level in our packet, then rewind and add it to the node bag for
|
||||
|
@ -1620,7 +1620,7 @@ void Octree::copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinat
|
|||
}
|
||||
|
||||
void dumpSetContents(const char* name, std::set<unsigned char*> set) {
|
||||
printf("set %s has %ld elements\n", name, set.size());
|
||||
qDebug("set %s has %ld elements", name, set.size());
|
||||
/*
|
||||
for (std::set<unsigned char*>::iterator i = set.begin(); i != set.end(); ++i) {
|
||||
printOctalCode(*i);
|
||||
|
|
|
@ -129,17 +129,17 @@ public:
|
|||
printf("StopReason: ");
|
||||
switch (stopReason) {
|
||||
default:
|
||||
case UNKNOWN: printf("UNKNOWN\n"); break;
|
||||
case UNKNOWN: qDebug("UNKNOWN"); break;
|
||||
|
||||
case DIDNT_FIT: printf("DIDNT_FIT\n"); break;
|
||||
case NULL_NODE: printf("NULL_NODE\n"); break;
|
||||
case TOO_DEEP: printf("TOO_DEEP\n"); break;
|
||||
case OUT_OF_JURISDICTION: printf("OUT_OF_JURISDICTION\n"); break;
|
||||
case LOD_SKIP: printf("LOD_SKIP\n"); break;
|
||||
case OUT_OF_VIEW: printf("OUT_OF_VIEW\n"); break;
|
||||
case WAS_IN_VIEW: printf("WAS_IN_VIEW\n"); break;
|
||||
case NO_CHANGE: printf("NO_CHANGE\n"); break;
|
||||
case OCCLUDED: printf("OCCLUDED\n"); break;
|
||||
case DIDNT_FIT: qDebug("DIDNT_FIT"); break;
|
||||
case NULL_NODE: qDebug("NULL_NODE"); break;
|
||||
case TOO_DEEP: qDebug("TOO_DEEP"); break;
|
||||
case OUT_OF_JURISDICTION: qDebug("OUT_OF_JURISDICTION"); break;
|
||||
case LOD_SKIP: qDebug("LOD_SKIP"); break;
|
||||
case OUT_OF_VIEW: qDebug("OUT_OF_VIEW"); break;
|
||||
case WAS_IN_VIEW: qDebug("WAS_IN_VIEW"); break;
|
||||
case NO_CHANGE: qDebug("NO_CHANGE"); break;
|
||||
case OCCLUDED: qDebug("OCCLUDED"); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -37,7 +37,7 @@ OctreeEditPacketSender::OctreeEditPacketSender() :
|
|||
_serverJurisdictions(NULL),
|
||||
_sequenceNumber(0),
|
||||
_maxPacketSize(MAX_PACKET_SIZE) {
|
||||
//printf("OctreeEditPacketSender::OctreeEditPacketSender() [%p] created... \n", this);
|
||||
//qDebug("OctreeEditPacketSender::OctreeEditPacketSender() [%p] created... ", this);
|
||||
}
|
||||
|
||||
OctreeEditPacketSender::~OctreeEditPacketSender() {
|
||||
|
@ -53,7 +53,7 @@ OctreeEditPacketSender::~OctreeEditPacketSender() {
|
|||
_preServerPackets.erase(_preServerPackets.begin());
|
||||
}
|
||||
_pendingPacketsLock.unlock();
|
||||
//printf("OctreeEditPacketSender::~OctreeEditPacketSender() [%p] destroyed... \n", this);
|
||||
//qDebug("OctreeEditPacketSender::~OctreeEditPacketSender() [%p] destroyed... ", this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ void OctreeElement::calculateAABox() {
|
|||
void OctreeElement::deleteChildAtIndex(int childIndex) {
|
||||
OctreeElement* childAt = getChildAtIndex(childIndex);
|
||||
if (childAt) {
|
||||
//printf("deleteChildAtIndex()... about to call delete childAt=%p\n",childAt);
|
||||
//qDebug("deleteChildAtIndex()... about to call delete childAt=%p",childAt);
|
||||
delete childAt;
|
||||
setChildAtIndex(childIndex, NULL);
|
||||
_isDirty = true;
|
||||
|
@ -1315,7 +1315,7 @@ OctreeElement* OctreeElement::getOrCreateChildElementAt(float x, float y, float
|
|||
float halfOurScale = ourScale / 2.0f;
|
||||
|
||||
if(s > ourScale) {
|
||||
printf("UNEXPECTED -- OctreeElement::getOrCreateChildElementAt() s=[%f] > ourScale=[%f] \n", s, ourScale);
|
||||
qDebug("UNEXPECTED -- OctreeElement::getOrCreateChildElementAt() s=[%f] > ourScale=[%f] ", s, ourScale);
|
||||
}
|
||||
|
||||
if (s > halfOurScale) {
|
||||
|
|
|
@ -16,13 +16,21 @@ OctreeElementBag::OctreeElementBag() :
|
|||
_bagElements()
|
||||
{
|
||||
OctreeElement::addDeleteHook(this);
|
||||
_hooked = true;
|
||||
};
|
||||
|
||||
OctreeElementBag::~OctreeElementBag() {
|
||||
OctreeElement::removeDeleteHook(this);
|
||||
unhookNotifications();
|
||||
deleteAll();
|
||||
}
|
||||
|
||||
void OctreeElementBag::unhookNotifications() {
|
||||
if (_hooked) {
|
||||
OctreeElement::removeDeleteHook(this);
|
||||
_hooked = false;
|
||||
}
|
||||
}
|
||||
|
||||
void OctreeElementBag::elementDeleted(OctreeElement* element) {
|
||||
remove(element); // note: remove can safely handle nodes that aren't in it, so we don't need to check contains()
|
||||
}
|
||||
|
|
|
@ -36,8 +36,11 @@ public:
|
|||
void deleteAll();
|
||||
virtual void elementDeleted(OctreeElement* element);
|
||||
|
||||
void unhookNotifications();
|
||||
|
||||
private:
|
||||
QSet<OctreeElement*> _bagElements;
|
||||
bool _hooked;
|
||||
};
|
||||
|
||||
#endif // hifi_OctreeElementBag_h
|
||||
|
|
|
@ -221,7 +221,7 @@ void OctreeHeadlessViewer::queryOctree() {
|
|||
int packetLength = endOfQueryPacket - queryPacket;
|
||||
|
||||
// make sure we still have an active socket
|
||||
nodeList->writeDatagram(reinterpret_cast<const char*>(queryPacket), packetLength, node);
|
||||
nodeList->writeUnverifiedDatagram(reinterpret_cast<const char*>(queryPacket), packetLength, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ const unsigned char* OctreePacketData::getFinalizedData() {
|
|||
|
||||
if (_dirty) {
|
||||
if (_debug) {
|
||||
printf("getFinalizedData() _compressedBytes=%d _bytesInUse=%d\n",_compressedBytes, _bytesInUse);
|
||||
qDebug("getFinalizedData() _compressedBytes=%d _bytesInUse=%d",_compressedBytes, _bytesInUse);
|
||||
}
|
||||
compressContent();
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ int OctreePacketData::getFinalizedSize() {
|
|||
|
||||
if (_dirty) {
|
||||
if (_debug) {
|
||||
printf("getFinalizedSize() _compressedBytes=%d _bytesInUse=%d\n",_compressedBytes, _bytesInUse);
|
||||
qDebug("getFinalizedSize() _compressedBytes=%d _bytesInUse=%d",_compressedBytes, _bytesInUse);
|
||||
}
|
||||
compressContent();
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ void OctreePacketData::discardLevel(LevelDetails key) {
|
|||
_totalBytesOfColor -= reduceBytesOfColor;
|
||||
|
||||
if (_debug) {
|
||||
printf("discardLevel() BEFORE _dirty=%s bytesInLevel=%d _compressedBytes=%d _bytesInUse=%d\n",
|
||||
qDebug("discardLevel() BEFORE _dirty=%s bytesInLevel=%d _compressedBytes=%d _bytesInUse=%d",
|
||||
debug::valueOf(_dirty), bytesInLevel, _compressedBytes, _bytesInUse);
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@ void OctreePacketData::discardLevel(LevelDetails key) {
|
|||
_dirty = true;
|
||||
|
||||
if (_debug) {
|
||||
printf("discardLevel() AFTER _dirty=%s bytesInLevel=%d _compressedBytes=%d _bytesInUse=%d\n",
|
||||
qDebug("discardLevel() AFTER _dirty=%s bytesInLevel=%d _compressedBytes=%d _bytesInUse=%d",
|
||||
debug::valueOf(_dirty), bytesInLevel, _compressedBytes, _bytesInUse);
|
||||
}
|
||||
}
|
||||
|
@ -413,13 +413,13 @@ void OctreePacketData::loadFinalizedContent(const unsigned char* data, int lengt
|
|||
}
|
||||
} else {
|
||||
if (_debug) {
|
||||
printf("OctreePacketData::loadCompressedContent()... length = 0, nothing to do...\n");
|
||||
qDebug("OctreePacketData::loadCompressedContent()... length = 0, nothing to do...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OctreePacketData::debugContent() {
|
||||
printf("OctreePacketData::debugContent()... COMPRESSED DATA.... size=%d\n",_compressedBytes);
|
||||
qDebug("OctreePacketData::debugContent()... COMPRESSED DATA.... size=%d",_compressedBytes);
|
||||
int perline=0;
|
||||
for (int i = 0; i < _compressedBytes; i++) {
|
||||
printf("%.2x ",_compressed[i]);
|
||||
|
@ -431,7 +431,7 @@ void OctreePacketData::debugContent() {
|
|||
}
|
||||
printf("\n");
|
||||
|
||||
printf("OctreePacketData::debugContent()... UNCOMPRESSED DATA.... size=%d\n",_bytesInUse);
|
||||
qDebug("OctreePacketData::debugContent()... UNCOMPRESSED DATA.... size=%d",_bytesInUse);
|
||||
perline=0;
|
||||
for (int i = 0; i < _bytesInUse; i++) {
|
||||
printf("%.2x ",_uncompressed[i]);
|
||||
|
|
|
@ -263,12 +263,12 @@ bool OctreeProjectedPolygon::pointInside(const glm::vec2& point, bool* matchesVe
|
|||
}
|
||||
|
||||
void OctreeProjectedPolygon::printDebugDetails() const {
|
||||
printf("OctreeProjectedPolygon...");
|
||||
printf(" minX=%f maxX=%f minY=%f maxY=%f\n", getMinX(), getMaxX(), getMinY(), getMaxY());
|
||||
printf(" vertex count=%d distance=%f\n", getVertexCount(), getDistance());
|
||||
qDebug("OctreeProjectedPolygon..."
|
||||
" minX=%f maxX=%f minY=%f maxY=%f", getMinX(), getMaxX(), getMinY(), getMaxY());
|
||||
qDebug(" vertex count=%d distance=%f", getVertexCount(), getDistance());
|
||||
for (int i = 0; i < getVertexCount(); i++) {
|
||||
glm::vec2 point = getVertex(i);
|
||||
printf(" vertex[%d] = %f, %f \n", i, point.x, point.y);
|
||||
qDebug(" vertex[%d] = %f, %f ", i, point.x, point.y);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include "Plane.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void Plane::set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) {
|
||||
|
@ -61,6 +63,6 @@ float Plane::distance(const glm::vec3 &point) const {
|
|||
}
|
||||
|
||||
void Plane::print() const {
|
||||
printf("Plane - point (x=%f y=%f z=%f) normal (x=%f y=%f z=%f) d=%f\n",
|
||||
qDebug("Plane - point (x=%f y=%f z=%f) normal (x=%f y=%f z=%f) d=%f",
|
||||
_point.x, _point.y, _point.z, _normal.x, _normal.y, _normal.z, _dCoefficient);
|
||||
}
|
||||
|
|
|
@ -130,9 +130,11 @@ void ViewFrustum::calculate() {
|
|||
|
||||
// Also calculate our projection matrix in case people want to project points...
|
||||
// Projection matrix : Field of View, ratio, display range : near to far
|
||||
glm::mat4 projection = glm::perspective(_fieldOfView, _aspectRatio, _nearClip, _farClip);
|
||||
glm::vec3 lookAt = _position + _direction;
|
||||
glm::mat4 view = glm::lookAt(_position, lookAt, _up);
|
||||
const float CLIP_NUDGE = 1.0f;
|
||||
float farClip = (_farClip != _nearClip) ? _farClip : _nearClip + CLIP_NUDGE; // don't allow near and far to be equal
|
||||
glm::mat4 projection = glm::perspective(_fieldOfView, _aspectRatio, _nearClip, farClip);
|
||||
glm::vec3 lookAt = _position + _direction;
|
||||
glm::mat4 view = glm::lookAt(_position, lookAt, _up);
|
||||
|
||||
// Our ModelViewProjection : multiplication of our 3 matrices (note: model is identity, so we can drop it)
|
||||
_ourModelViewProjectionMatrix = projection * view; // Remember, matrix multiplication is the other way around
|
||||
|
|
|
@ -146,7 +146,7 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const {
|
|||
|
||||
bool success = packetData->appendValue(getID());
|
||||
|
||||
//printf("Particle::appendParticleData()... getID()=%d\n", getID());
|
||||
//qDebug("Particle::appendParticleData()... getID()=%d", getID());
|
||||
|
||||
if (success) {
|
||||
success = packetData->appendValue(getAge());
|
||||
|
@ -541,15 +541,15 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr
|
|||
}
|
||||
|
||||
void Particle::debugDump() const {
|
||||
printf("Particle id :%u\n", _id);
|
||||
printf(" age:%f\n", getAge());
|
||||
printf(" edited ago:%f\n", getEditedAgo());
|
||||
printf(" should die:%s\n", debug::valueOf(getShouldDie()));
|
||||
printf(" position:%f,%f,%f\n", _position.x, _position.y, _position.z);
|
||||
printf(" radius:%f\n", getRadius());
|
||||
printf(" velocity:%f,%f,%f\n", _velocity.x, _velocity.y, _velocity.z);
|
||||
printf(" gravity:%f,%f,%f\n", _gravity.x, _gravity.y, _gravity.z);
|
||||
printf(" color:%d,%d,%d\n", _color[0], _color[1], _color[2]);
|
||||
qDebug("Particle id :%u", _id);
|
||||
qDebug(" age:%f", getAge());
|
||||
qDebug(" edited ago:%f", getEditedAgo());
|
||||
qDebug(" should die:%s", debug::valueOf(getShouldDie()));
|
||||
qDebug(" position:%f,%f,%f", _position.x, _position.y, _position.z);
|
||||
qDebug(" radius:%f", getRadius());
|
||||
qDebug(" velocity:%f,%f,%f", _velocity.x, _velocity.y, _velocity.z);
|
||||
qDebug(" gravity:%f,%f,%f", _gravity.x, _gravity.y, _gravity.z);
|
||||
qDebug(" color:%d,%d,%d", _color[0], _color[1], _color[2]);
|
||||
}
|
||||
|
||||
bool Particle::encodeParticleEditMessageDetails(PacketType command, ParticleID id, const ParticleProperties& properties,
|
||||
|
@ -732,9 +732,9 @@ bool Particle::encodeParticleEditMessageDetails(PacketType command, ParticleID i
|
|||
|
||||
bool wantDebugging = false;
|
||||
if (wantDebugging) {
|
||||
printf("encodeParticleEditMessageDetails()....\n");
|
||||
printf("Particle id :%u\n", id.id);
|
||||
printf(" nextID:%u\n", _nextID);
|
||||
qDebug("encodeParticleEditMessageDetails()....");
|
||||
qDebug("Particle id :%u", id.id);
|
||||
qDebug(" nextID:%u", _nextID);
|
||||
}
|
||||
|
||||
// cleanup
|
||||
|
@ -844,7 +844,7 @@ void Particle::update(const quint64& now) {
|
|||
// handle damping
|
||||
glm::vec3 dampingResistance = _velocity * _damping;
|
||||
_velocity -= dampingResistance * timeElapsed;
|
||||
//printf("applying damping to Particle timeElapsed=%f\n",timeElapsed);
|
||||
//qDebug("applying damping to Particle timeElapsed=%f",timeElapsed);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ bool ParticleTreeElement::updateParticle(const Particle& particle) {
|
|||
bool localOlder = thisParticle.getLastUpdated() < particle.getLastUpdated();
|
||||
if (changedOnServer || localOlder) {
|
||||
if (wantDebug) {
|
||||
printf("local particle [id:%d] %s and %s than server particle by %d, particle.isNewlyCreated()=%s\n",
|
||||
qDebug("local particle [id:%d] %s and %s than server particle by %d, particle.isNewlyCreated()=%s",
|
||||
particle.getID(), (changedOnServer ? "CHANGED" : "same"),
|
||||
(localOlder ? "OLDER" : "NEWER"),
|
||||
difference, debug::valueOf(particle.isNewlyCreated()) );
|
||||
|
@ -150,8 +150,8 @@ bool ParticleTreeElement::updateParticle(const Particle& particle) {
|
|||
thisParticle.copyChangedProperties(particle);
|
||||
} else {
|
||||
if (wantDebug) {
|
||||
printf(">>> IGNORING SERVER!!! Would've caused jutter! <<< "
|
||||
"local particle [id:%d] %s and %s than server particle by %d, particle.isNewlyCreated()=%s\n",
|
||||
qDebug(">>> IGNORING SERVER!!! Would've caused jutter! <<< "
|
||||
"local particle [id:%d] %s and %s than server particle by %d, particle.isNewlyCreated()=%s",
|
||||
particle.getID(), (changedOnServer ? "CHANGED" : "same"),
|
||||
(localOlder ? "OLDER" : "NEWER"),
|
||||
difference, debug::valueOf(particle.isNewlyCreated()) );
|
||||
|
|
|
@ -43,6 +43,11 @@ static QScriptValue soundConstructor(QScriptContext* context, QScriptEngine* eng
|
|||
return soundScriptValue;
|
||||
}
|
||||
|
||||
static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine){
|
||||
qDebug() << "script:print()<<" << context->argument(0).toString();
|
||||
engine->evaluate("Script.print('" + context->argument(0).toString() + "')");
|
||||
return QScriptValue();
|
||||
}
|
||||
|
||||
ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString,
|
||||
AbstractControllerScriptingInterface* controllerScriptingInterface) :
|
||||
|
@ -115,6 +120,7 @@ ScriptEngine::ScriptEngine(const QUrl& scriptURL,
|
|||
_scriptContents = in.readAll();
|
||||
} else {
|
||||
qDebug() << "ERROR Loading file:" << fileName;
|
||||
emit errorMessage("ERROR Loading file:" + fileName);
|
||||
}
|
||||
} else {
|
||||
QNetworkAccessManager* networkManager = new QNetworkAccessManager(this);
|
||||
|
@ -156,6 +162,14 @@ void ScriptEngine::setAvatarData(AvatarData* avatarData, const QString& objectNa
|
|||
registerGlobalObject(objectName, _avatarData);
|
||||
}
|
||||
|
||||
void ScriptEngine::setAvatarHashMap(AvatarHashMap* avatarHashMap, const QString& objectName) {
|
||||
// remove the old Avatar property, if it exists
|
||||
_engine.globalObject().setProperty(objectName, QScriptValue());
|
||||
|
||||
// give the script engine the new avatar hash map
|
||||
registerGlobalObject(objectName, avatarHashMap);
|
||||
}
|
||||
|
||||
bool ScriptEngine::setScriptContents(const QString& scriptContents, const QString& fileNameString) {
|
||||
if (_isRunning) {
|
||||
return false;
|
||||
|
@ -192,6 +206,9 @@ void ScriptEngine::init() {
|
|||
qScriptRegisterSequenceMetaType<QVector<glm::quat> >(&_engine);
|
||||
qScriptRegisterSequenceMetaType<QVector<QString> >(&_engine);
|
||||
|
||||
QScriptValue printConstructorValue = _engine.newFunction(debugPrint);
|
||||
_engine.globalObject().setProperty("print", printConstructorValue);
|
||||
|
||||
QScriptValue soundConstructorValue = _engine.newFunction(soundConstructor);
|
||||
QScriptValue soundMetaObject = _engine.newQMetaObject(&Sound::staticMetaObject, soundConstructorValue);
|
||||
_engine.globalObject().setProperty("Sound", soundMetaObject);
|
||||
|
@ -238,6 +255,7 @@ void ScriptEngine::evaluate() {
|
|||
if (_engine.hasUncaughtException()) {
|
||||
int line = _engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << result.toString();
|
||||
emit errorMessage("Uncaught exception at line" + QString::number(line) + ":" + result.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,11 +276,14 @@ void ScriptEngine::run() {
|
|||
init();
|
||||
}
|
||||
_isRunning = true;
|
||||
emit runningStateChanged();
|
||||
|
||||
QScriptValue result = _engine.evaluate(_scriptContents);
|
||||
if (_engine.hasUncaughtException()) {
|
||||
int line = _engine.uncaughtExceptionLineNumber();
|
||||
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << result.toString();
|
||||
emit errorMessage("Uncaught exception at line" + QString::number(line) + ":" + result.toString());
|
||||
}
|
||||
|
||||
timeval startTime;
|
||||
|
@ -393,6 +414,7 @@ void ScriptEngine::run() {
|
|||
if (_engine.hasUncaughtException()) {
|
||||
int line = _engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << _engine.uncaughtException().toString();
|
||||
emit errorMessage("Uncaught exception at line" + QString::number(line) + ":" + _engine.uncaughtException().toString());
|
||||
}
|
||||
}
|
||||
emit scriptEnding();
|
||||
|
@ -428,10 +450,12 @@ void ScriptEngine::run() {
|
|||
emit finished(_fileNameString);
|
||||
|
||||
_isRunning = false;
|
||||
emit runningStateChanged();
|
||||
}
|
||||
|
||||
void ScriptEngine::stop() {
|
||||
_isFinished = true;
|
||||
emit runningStateChanged();
|
||||
}
|
||||
|
||||
void ScriptEngine::timerFired() {
|
||||
|
@ -502,6 +526,10 @@ QUrl ScriptEngine::resolveInclude(const QString& include) const {
|
|||
return url;
|
||||
}
|
||||
|
||||
void ScriptEngine::print(const QString& message) {
|
||||
emit printedMessage(message);
|
||||
}
|
||||
|
||||
void ScriptEngine::include(const QString& includeFile) {
|
||||
QUrl url = resolveInclude(includeFile);
|
||||
QString includeContents;
|
||||
|
@ -515,6 +543,7 @@ void ScriptEngine::include(const QString& includeFile) {
|
|||
includeContents = in.readAll();
|
||||
} else {
|
||||
qDebug() << "ERROR Loading file:" << fileName;
|
||||
emit errorMessage("ERROR Loading file:" + fileName);
|
||||
}
|
||||
} else {
|
||||
QNetworkAccessManager* networkManager = new QNetworkAccessManager(this);
|
||||
|
@ -530,5 +559,6 @@ void ScriptEngine::include(const QString& includeFile) {
|
|||
if (_engine.hasUncaughtException()) {
|
||||
int line = _engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at (" << includeFile << ") line" << line << ":" << result.toString();
|
||||
emit errorMessage("Uncaught exception at (" + includeFile + ") line" + QString::number(line) + ":" + result.toString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
#include <VoxelsScriptingInterface.h>
|
||||
|
||||
#include <AvatarData.h>
|
||||
#include <AvatarHashMap.h>
|
||||
|
||||
#include "AnimationCache.h"
|
||||
#include "AbstractControllerScriptingInterface.h"
|
||||
|
@ -63,6 +64,7 @@ public:
|
|||
bool isAvatar() const { return _isAvatar; }
|
||||
|
||||
void setAvatarData(AvatarData* avatarData, const QString& objectName);
|
||||
void setAvatarHashMap(AvatarHashMap* avatarHashMap, const QString& objectName);
|
||||
|
||||
bool isListeningToAudioStream() const { return _isListeningToAudioStream; }
|
||||
void setIsListeningToAudioStream(bool isListeningToAudioStream) { _isListeningToAudioStream = isListeningToAudioStream; }
|
||||
|
@ -78,6 +80,9 @@ public:
|
|||
|
||||
bool hasScript() const { return !_scriptContents.isEmpty(); }
|
||||
|
||||
bool isFinished() const { return _isFinished; }
|
||||
bool isRunning() const { return _isRunning; }
|
||||
|
||||
public slots:
|
||||
void stop();
|
||||
|
||||
|
@ -86,12 +91,16 @@ public slots:
|
|||
void clearInterval(QObject* timer) { stopTimer(reinterpret_cast<QTimer*>(timer)); }
|
||||
void clearTimeout(QObject* timer) { stopTimer(reinterpret_cast<QTimer*>(timer)); }
|
||||
void include(const QString& includeFile);
|
||||
void print(const QString& message);
|
||||
|
||||
signals:
|
||||
void update(float deltaTime);
|
||||
void scriptEnding();
|
||||
void finished(const QString& fileNameString);
|
||||
void cleanupMenuItem(const QString& menuItemString);
|
||||
void printedMessage(const QString& message);
|
||||
void errorMessage(const QString& message);
|
||||
void runningStateChanged();
|
||||
|
||||
protected:
|
||||
QString _scriptContents;
|
||||
|
|
|
@ -36,6 +36,9 @@ public:
|
|||
void setUndoStack(QUndoStack* undoStack) { _undoStack = undoStack; }
|
||||
|
||||
public slots:
|
||||
|
||||
/// provide the world scale
|
||||
const int getTreeScale() const { return TREE_SCALE; }
|
||||
|
||||
/// checks the local voxel tree for a voxel at the specified location and scale
|
||||
/// \param x the x-coordinate of the voxel (in meter units)
|
||||
|
|
|
@ -20,7 +20,7 @@ void addCornersAndAxisLines(VoxelTree* tree) {
|
|||
float voxelSize = 0.5f / TREE_SCALE;
|
||||
|
||||
// Now some more examples... a little more complex
|
||||
printf("creating corner points...\n");
|
||||
qDebug("creating corner points...");
|
||||
tree->createVoxel(0 , 0 , 0 , voxelSize, 255, 255 ,255);
|
||||
tree->createVoxel(1.0 - voxelSize, 0 , 0 , voxelSize, 255, 0 ,0 );
|
||||
tree->createVoxel(0 , 1.0 - voxelSize, 0 , voxelSize, 0 , 255 ,0 );
|
||||
|
@ -29,11 +29,11 @@ void addCornersAndAxisLines(VoxelTree* tree) {
|
|||
tree->createVoxel(0 , 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 0 , 255 ,255);
|
||||
tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 0 , voxelSize, 255, 255 ,0 );
|
||||
tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 255, 255 ,255);
|
||||
printf("DONE creating corner points...\n");
|
||||
qDebug("DONE creating corner points...");
|
||||
}
|
||||
|
||||
void addSurfaceScene(VoxelTree * tree) {
|
||||
printf("adding surface scene...\n");
|
||||
qDebug("adding surface scene...");
|
||||
float voxelSize = 1.f / (8 * TREE_SCALE);
|
||||
|
||||
// color 1= blue, color 2=green
|
||||
|
@ -57,5 +57,5 @@ void addSurfaceScene(VoxelTree * tree) {
|
|||
}
|
||||
}
|
||||
}
|
||||
printf("DONE adding surface scene...\n");
|
||||
qDebug("DONE adding surface scene...");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue