mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 08:49:05 +02:00
Merge branch 'mm_1e08633' into android_places_goto
This commit is contained in:
commit
55e64ceb55
60 changed files with 1290 additions and 603 deletions
|
@ -14,8 +14,8 @@ Should you choose not to install Qt5 via a package manager that handles dependen
|
||||||
|
|
||||||
Install qt:
|
Install qt:
|
||||||
```bash
|
```bash
|
||||||
wget http://debian.highfidelity.com/pool/h/hi/hifi-qt5.10.1_5.10.1_amd64.deb
|
wget http://debian.highfidelity.com/pool/h/hi/hifiqt5.10.1_5.10.1_amd64.deb
|
||||||
sudo dpkg -i hifi-qt5.10.1_5.10.1_amd64.deb
|
sudo dpkg -i hifiqt5.10.1_5.10.1_amd64.deb
|
||||||
```
|
```
|
||||||
|
|
||||||
Install build dependencies:
|
Install build dependencies:
|
||||||
|
|
|
@ -611,22 +611,14 @@ bool DomainServer::isPacketVerified(const udt::Packet& packet) {
|
||||||
// let the NodeList do its checks now (but pass it the sourceNode so it doesn't need to look it up again)
|
// let the NodeList do its checks now (but pass it the sourceNode so it doesn't need to look it up again)
|
||||||
return nodeList->isPacketVerifiedWithSource(packet, sourceNode.data());
|
return nodeList->isPacketVerifiedWithSource(packet, sourceNode.data());
|
||||||
} else {
|
} else {
|
||||||
static const QString UNKNOWN_REGEX = "Packet of type \\d+ \\([\\sa-zA-Z:]+\\) received from unmatched IP for UUID";
|
HIFI_FDEBUG("Packet of type" << headerType
|
||||||
static QString repeatedMessage
|
<< "received from unmatched IP for UUID" << uuidStringWithoutCurlyBraces(sourceID));
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(UNKNOWN_REGEX);
|
|
||||||
|
|
||||||
qDebug() << "Packet of type" << headerType
|
|
||||||
<< "received from unmatched IP for UUID" << uuidStringWithoutCurlyBraces(sourceID);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
static const QString UNKNOWN_REGEX = "Packet of type \\d+ \\([\\sa-zA-Z:]+\\) received from unknown node with UUID";
|
HIFI_FDEBUG("Packet of type" << headerType
|
||||||
static QString repeatedMessage
|
<< "received from unknown node with UUID" << uuidStringWithoutCurlyBraces(sourceID));
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(UNKNOWN_REGEX);
|
|
||||||
|
|
||||||
qDebug() << "Packet of type" << headerType
|
|
||||||
<< "received from unknown node with UUID" << uuidStringWithoutCurlyBraces(sourceID);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1242,31 +1234,16 @@ void DomainServer::processRequestAssignmentPacket(QSharedPointer<ReceivedMessage
|
||||||
|
|
||||||
auto it = find_if(_acSubnetWhitelist.begin(), _acSubnetWhitelist.end(), isHostAddressInSubnet);
|
auto it = find_if(_acSubnetWhitelist.begin(), _acSubnetWhitelist.end(), isHostAddressInSubnet);
|
||||||
if (it == _acSubnetWhitelist.end()) {
|
if (it == _acSubnetWhitelist.end()) {
|
||||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex(
|
HIFI_FDEBUG("Received an assignment connect request from a disallowed ip address:"
|
||||||
"Received an assignment connect request from a disallowed ip address: [^ ]+");
|
<< senderAddr.toString());
|
||||||
qDebug() << "Received an assignment connect request from a disallowed ip address:"
|
|
||||||
<< senderAddr.toString();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Suppress these for Assignment::AgentType to once per 5 seconds
|
static bool printedAssignmentTypeMessage = false;
|
||||||
static QElapsedTimer noisyMessageTimer;
|
if (!printedAssignmentTypeMessage && requestAssignment.getType() != Assignment::AgentType) {
|
||||||
static bool wasNoisyTimerStarted = false;
|
printedAssignmentTypeMessage = true;
|
||||||
|
|
||||||
if (!wasNoisyTimerStarted) {
|
|
||||||
noisyMessageTimer.start();
|
|
||||||
wasNoisyTimerStarted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const qint64 NOISY_MESSAGE_INTERVAL_MSECS = 5 * 1000;
|
|
||||||
|
|
||||||
if (requestAssignment.getType() != Assignment::AgentType
|
|
||||||
|| noisyMessageTimer.elapsed() > NOISY_MESSAGE_INTERVAL_MSECS) {
|
|
||||||
static QString repeatedMessage = LogHandler::getInstance().addOnlyOnceMessageRegex
|
|
||||||
("Received a request for assignment type [^ ]+ from [^ ]+");
|
|
||||||
qDebug() << "Received a request for assignment type" << requestAssignment.getType()
|
qDebug() << "Received a request for assignment type" << requestAssignment.getType()
|
||||||
<< "from" << message->getSenderSockAddr();
|
<< "from" << message->getSenderSockAddr();
|
||||||
noisyMessageTimer.restart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedAssignmentPointer assignmentToDeploy = deployableAssignmentForRequest(requestAssignment);
|
SharedAssignmentPointer assignmentToDeploy = deployableAssignmentForRequest(requestAssignment);
|
||||||
|
@ -1300,13 +1277,11 @@ void DomainServer::processRequestAssignmentPacket(QSharedPointer<ReceivedMessage
|
||||||
_gatekeeper.addPendingAssignedNode(uniqueAssignment.getUUID(), assignmentToDeploy->getUUID(),
|
_gatekeeper.addPendingAssignedNode(uniqueAssignment.getUUID(), assignmentToDeploy->getUUID(),
|
||||||
requestAssignment.getWalletUUID(), requestAssignment.getNodeVersion());
|
requestAssignment.getWalletUUID(), requestAssignment.getNodeVersion());
|
||||||
} else {
|
} else {
|
||||||
if (requestAssignment.getType() != Assignment::AgentType
|
static bool printedAssignmentRequestMessage = false;
|
||||||
|| noisyMessageTimer.elapsed() > NOISY_MESSAGE_INTERVAL_MSECS) {
|
if (!printedAssignmentRequestMessage && requestAssignment.getType() != Assignment::AgentType) {
|
||||||
static QString repeatedMessage = LogHandler::getInstance().addOnlyOnceMessageRegex
|
printedAssignmentRequestMessage = true;
|
||||||
("Unable to fulfill assignment request of type [^ ]+ from [^ ]+");
|
|
||||||
qDebug() << "Unable to fulfill assignment request of type" << requestAssignment.getType()
|
qDebug() << "Unable to fulfill assignment request of type" << requestAssignment.getType()
|
||||||
<< "from" << message->getSenderSockAddr();
|
<< "from" << message->getSenderSockAddr();
|
||||||
noisyMessageTimer.restart();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1552,10 +1527,12 @@ void DomainServer::sendICEServerAddressToMetaverseAPI() {
|
||||||
callbackParameters.jsonCallbackReceiver = this;
|
callbackParameters.jsonCallbackReceiver = this;
|
||||||
callbackParameters.jsonCallbackMethod = "handleSuccessfulICEServerAddressUpdate";
|
callbackParameters.jsonCallbackMethod = "handleSuccessfulICEServerAddressUpdate";
|
||||||
|
|
||||||
static QString repeatedMessage = LogHandler::getInstance().addOnlyOnceMessageRegex
|
static bool printedIceServerMessage = false;
|
||||||
("Updating ice-server address in High Fidelity Metaverse API to [^ \n]+");
|
if (!printedIceServerMessage) {
|
||||||
|
printedIceServerMessage = true;
|
||||||
qDebug() << "Updating ice-server address in High Fidelity Metaverse API to"
|
qDebug() << "Updating ice-server address in High Fidelity Metaverse API to"
|
||||||
<< (_iceServerSocket.isNull() ? "" : _iceServerSocket.getAddress().toString());
|
<< (_iceServerSocket.isNull() ? "" : _iceServerSocket.getAddress().toString());
|
||||||
|
}
|
||||||
|
|
||||||
static const QString DOMAIN_ICE_ADDRESS_UPDATE = "/api/v1/domains/%1/ice_server_address";
|
static const QString DOMAIN_ICE_ADDRESS_UPDATE = "/api/v1/domains/%1/ice_server_address";
|
||||||
|
|
||||||
|
|
|
@ -180,8 +180,9 @@ else ()
|
||||||
add_executable(${TARGET_NAME} ${INTERFACE_SRCS} ${QM})
|
add_executable(${TARGET_NAME} ${INTERFACE_SRCS} ${QM})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
if (BUILD_TOOLS AND NPM_EXECUTABLE)
|
if (BUILD_TOOLS AND NPM_EXECUTABLE)
|
||||||
# require JSDoc to be build before interface is deployed (Console Auto-complete)
|
# require JSDoc to be build before interface is deployed
|
||||||
add_dependencies(resources jsdoc)
|
add_dependencies(resources jsdoc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -322,6 +323,13 @@ if (APPLE)
|
||||||
"${RESOURCES_DEV_DIR}/scripts"
|
"${RESOURCES_DEV_DIR}/scripts"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# copy JSDoc files beside the executable
|
||||||
|
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||||
|
"${CMAKE_SOURCE_DIR}/tools/jsdoc/out"
|
||||||
|
"${RESOURCES_DEV_DIR}/jsdoc"
|
||||||
|
)
|
||||||
|
|
||||||
# call the fixup_interface macro to add required bundling commands for installation
|
# call the fixup_interface macro to add required bundling commands for installation
|
||||||
fixup_interface()
|
fixup_interface()
|
||||||
|
|
||||||
|
@ -350,6 +358,13 @@ else()
|
||||||
"${RESOURCES_DEV_DIR}/serverless/tutorial.json"
|
"${RESOURCES_DEV_DIR}/serverless/tutorial.json"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# copy JSDoc files beside the executable
|
||||||
|
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||||
|
"${CMAKE_SOURCE_DIR}/tools/jsdoc/out"
|
||||||
|
"${INTERFACE_EXEC_DIR}/jsdoc"
|
||||||
|
)
|
||||||
|
|
||||||
# link target to external libraries
|
# link target to external libraries
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib)
|
target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib)
|
||||||
|
|
|
@ -1267,9 +1267,32 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
// Make sure the window is set to the correct size by processing the pending events
|
// Make sure the window is set to the correct size by processing the pending events
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
_glWidget->createContext();
|
_glWidget->createContext();
|
||||||
_glWidget->makeCurrent();
|
|
||||||
|
|
||||||
|
// Create the main thread context, the GPU backend, and the display plugins
|
||||||
initializeGL();
|
initializeGL();
|
||||||
|
qCDebug(interfaceapp, "Initialized Display.");
|
||||||
|
// Create the rendering engine. This can be slow on some machines due to lots of
|
||||||
|
// GPU pipeline creation.
|
||||||
|
initializeRenderEngine();
|
||||||
|
qCDebug(interfaceapp, "Initialized Render Engine.");
|
||||||
|
|
||||||
|
// Initialize the user interface and menu system
|
||||||
|
// Needs to happen AFTER the render engine initialization to access its configuration
|
||||||
|
initializeUi();
|
||||||
|
|
||||||
|
init();
|
||||||
|
qCDebug(interfaceapp, "init() complete.");
|
||||||
|
|
||||||
|
// create thread for parsing of octree data independent of the main network and rendering threads
|
||||||
|
_octreeProcessor.initialize(_enableProcessOctreeThread);
|
||||||
|
connect(&_octreeProcessor, &OctreePacketProcessor::packetVersionMismatch, this, &Application::notifyPacketVersionMismatch);
|
||||||
|
_entityEditSender.initialize(_enableProcessOctreeThread);
|
||||||
|
|
||||||
|
_idleLoopStdev.reset();
|
||||||
|
|
||||||
|
// update before the first render
|
||||||
|
update(0);
|
||||||
|
|
||||||
// Make sure we don't time out during slow operations at startup
|
// Make sure we don't time out during slow operations at startup
|
||||||
updateHeartbeat();
|
updateHeartbeat();
|
||||||
|
|
||||||
|
@ -2435,48 +2458,47 @@ void Application::initializeGL() {
|
||||||
_isGLInitialized = true;
|
_isGLInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a shared canvas / context for the Chromium processes
|
|
||||||
_glWidget->makeCurrent();
|
_glWidget->makeCurrent();
|
||||||
|
glClearColor(0.2f, 0.2f, 0.2f, 1);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
_glWidget->swapBuffers();
|
||||||
|
|
||||||
#if !defined(DISABLE_QML)
|
// Build an offscreen GL context for the main thread.
|
||||||
// Chromium rendering uses some GL functions that prevent nSight from capturing
|
_offscreenContext = new OffscreenGLCanvas();
|
||||||
// frames, so we only create the shared context if nsight is NOT active.
|
_offscreenContext->setObjectName("MainThreadContext");
|
||||||
if (!nsightActive()) {
|
_offscreenContext->create(_glWidget->qglContext());
|
||||||
_chromiumShareContext = new OffscreenGLCanvas();
|
if (!_offscreenContext->makeCurrent()) {
|
||||||
_chromiumShareContext->setObjectName("ChromiumShareContext");
|
qFatal("Unable to make offscreen context current");
|
||||||
_chromiumShareContext->create(_glWidget->qglContext());
|
|
||||||
_chromiumShareContext->makeCurrent();
|
|
||||||
if (!_chromiumShareContext->makeCurrent()) {
|
|
||||||
qCWarning(interfaceapp, "Unable to make chromium shared context current");
|
|
||||||
}
|
}
|
||||||
qt_gl_set_global_share_context(_chromiumShareContext->getContext());
|
_offscreenContext->doneCurrent();
|
||||||
} else {
|
_offscreenContext->setThreadContext();
|
||||||
qCWarning(interfaceapp) << "nSIGHT detected, disabling chrome rendering";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Build a shared canvas / context for the QML rendering
|
// Move the GL widget context to the render event handler thread
|
||||||
_glWidget->makeCurrent();
|
_renderEventHandler = new RenderEventHandler(_glWidget->qglContext());
|
||||||
_qmlShareContext = new OffscreenGLCanvas();
|
if (!_offscreenContext->makeCurrent()) {
|
||||||
_qmlShareContext->setObjectName("QmlShareContext");
|
qFatal("Unable to make offscreen context current");
|
||||||
_qmlShareContext->create(_glWidget->qglContext());
|
|
||||||
if (!_qmlShareContext->makeCurrent()) {
|
|
||||||
qCWarning(interfaceapp, "Unable to make QML shared context current");
|
|
||||||
}
|
}
|
||||||
OffscreenQmlSurface::setSharedContext(_qmlShareContext->getContext());
|
|
||||||
_qmlShareContext->doneCurrent();
|
|
||||||
|
|
||||||
|
// Create the GPU backend
|
||||||
|
|
||||||
|
// Requires the window context, because that's what's used in the actual rendering
|
||||||
|
// and the GPU backend will make things like the VAO which cannot be shared across
|
||||||
|
// contexts
|
||||||
_glWidget->makeCurrent();
|
_glWidget->makeCurrent();
|
||||||
gpu::Context::init<gpu::gl::GLBackend>();
|
gpu::Context::init<gpu::gl::GLBackend>();
|
||||||
qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK,
|
qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK,
|
||||||
QVariant::fromValue((void*)(&gpu::gl::GLBackend::makeProgram)));
|
QVariant::fromValue((void*)(&gpu::gl::GLBackend::makeProgram)));
|
||||||
_gpuContext = std::make_shared<gpu::Context>();
|
|
||||||
// The gpu context can make child contexts for transfers, so
|
|
||||||
// we need to restore primary rendering context
|
|
||||||
_glWidget->makeCurrent();
|
_glWidget->makeCurrent();
|
||||||
|
_gpuContext = std::make_shared<gpu::Context>();
|
||||||
|
|
||||||
initDisplay();
|
// Restore the default main thread context
|
||||||
qCDebug(interfaceapp, "Initialized Display.");
|
_offscreenContext->makeCurrent();
|
||||||
|
|
||||||
|
updateDisplayMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::initializeRenderEngine() {
|
||||||
|
_offscreenContext->makeCurrent();
|
||||||
|
|
||||||
// FIXME: on low end systems os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread.
|
// FIXME: on low end systems os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread.
|
||||||
DeadlockWatchdogThread::withPause([&] {
|
DeadlockWatchdogThread::withPause([&] {
|
||||||
|
@ -2493,66 +2515,44 @@ void Application::initializeGL() {
|
||||||
// Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success.
|
// Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success.
|
||||||
DependencyManager::get<GeometryCache>()->initializeShapePipelines();
|
DependencyManager::get<GeometryCache>()->initializeShapePipelines();
|
||||||
});
|
});
|
||||||
|
|
||||||
_offscreenContext = new OffscreenGLCanvas();
|
|
||||||
_offscreenContext->setObjectName("MainThreadContext");
|
|
||||||
_offscreenContext->create(_glWidget->qglContext());
|
|
||||||
if (!_offscreenContext->makeCurrent()) {
|
|
||||||
qFatal("Unable to make offscreen context current");
|
|
||||||
}
|
|
||||||
_offscreenContext->doneCurrent();
|
|
||||||
_offscreenContext->setThreadContext();
|
|
||||||
_renderEventHandler = new RenderEventHandler(_glWidget->qglContext());
|
|
||||||
|
|
||||||
// The UI can't be created until the primary OpenGL
|
|
||||||
// context is created, because it needs to share
|
|
||||||
// texture resources
|
|
||||||
// Needs to happen AFTER the render engine initialization to access its configuration
|
|
||||||
if (!_offscreenContext->makeCurrent()) {
|
|
||||||
qFatal("Unable to make offscreen context current");
|
|
||||||
}
|
|
||||||
|
|
||||||
initializeUi();
|
|
||||||
qCDebug(interfaceapp, "Initialized Offscreen UI.");
|
|
||||||
|
|
||||||
if (!_offscreenContext->makeCurrent()) {
|
|
||||||
qFatal("Unable to make offscreen context current");
|
|
||||||
}
|
|
||||||
init();
|
|
||||||
qCDebug(interfaceapp, "init() complete.");
|
|
||||||
|
|
||||||
// create thread for parsing of octree data independent of the main network and rendering threads
|
|
||||||
_octreeProcessor.initialize(_enableProcessOctreeThread);
|
|
||||||
connect(&_octreeProcessor, &OctreePacketProcessor::packetVersionMismatch, this, &Application::notifyPacketVersionMismatch);
|
|
||||||
_entityEditSender.initialize(_enableProcessOctreeThread);
|
|
||||||
|
|
||||||
_idleLoopStdev.reset();
|
|
||||||
|
|
||||||
|
|
||||||
// Restore the primary GL content for the main thread
|
|
||||||
if (!_offscreenContext->makeCurrent()) {
|
|
||||||
qFatal("Unable to make offscreen context current");
|
|
||||||
}
|
|
||||||
|
|
||||||
// update before the first render
|
|
||||||
update(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void setupPreferences();
|
extern void setupPreferences();
|
||||||
|
|
||||||
void Application::initializeUi() {
|
void Application::initializeUi() {
|
||||||
|
// Build a shared canvas / context for the Chromium processes
|
||||||
|
#if !defined(DISABLE_QML)
|
||||||
|
// Chromium rendering uses some GL functions that prevent nSight from capturing
|
||||||
|
// frames, so we only create the shared context if nsight is NOT active.
|
||||||
|
if (!nsightActive()) {
|
||||||
|
_chromiumShareContext = new OffscreenGLCanvas();
|
||||||
|
_chromiumShareContext->setObjectName("ChromiumShareContext");
|
||||||
|
_chromiumShareContext->create(_offscreenContext->getContext());
|
||||||
|
if (!_chromiumShareContext->makeCurrent()) {
|
||||||
|
qCWarning(interfaceapp, "Unable to make chromium shared context current");
|
||||||
|
}
|
||||||
|
qt_gl_set_global_share_context(_chromiumShareContext->getContext());
|
||||||
|
_chromiumShareContext->doneCurrent();
|
||||||
|
// Restore the GL widget context
|
||||||
|
_offscreenContext->makeCurrent();
|
||||||
|
} else {
|
||||||
|
qCWarning(interfaceapp) << "nSIGHT detected, disabling chrome rendering";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Build a shared canvas / context for the QML rendering
|
||||||
|
_qmlShareContext = new OffscreenGLCanvas();
|
||||||
|
_qmlShareContext->setObjectName("QmlShareContext");
|
||||||
|
_qmlShareContext->create(_offscreenContext->getContext());
|
||||||
|
if (!_qmlShareContext->makeCurrent()) {
|
||||||
|
qCWarning(interfaceapp, "Unable to make QML shared context current");
|
||||||
|
}
|
||||||
|
OffscreenQmlSurface::setSharedContext(_qmlShareContext->getContext());
|
||||||
|
_qmlShareContext->doneCurrent();
|
||||||
|
// Restore the GL widget context
|
||||||
|
_offscreenContext->makeCurrent();
|
||||||
// Make sure all QML surfaces share the main thread GL context
|
// Make sure all QML surfaces share the main thread GL context
|
||||||
OffscreenQmlSurface::setSharedContext(_offscreenContext->getContext());
|
OffscreenQmlSurface::setSharedContext(_offscreenContext->getContext());
|
||||||
OffscreenQmlSurface::addWhitelistContextHandler(QUrl{ "OverlayWindowTest.qml" },
|
|
||||||
[](QQmlContext* context) {
|
|
||||||
qDebug() << "Whitelist OverlayWindow worked";
|
|
||||||
context->setContextProperty("OverlayWindowTestString", "TestWorked");
|
|
||||||
});
|
|
||||||
OffscreenQmlSurface::addWhitelistContextHandler(QUrl{ "hifi/audio/Audio.qml" },
|
|
||||||
[](QQmlContext* context) {
|
|
||||||
qDebug() << "QQQ" << __FUNCTION__ << "Whitelist Audio worked";
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
AddressBarDialog::registerType();
|
AddressBarDialog::registerType();
|
||||||
ErrorDialog::registerType();
|
ErrorDialog::registerType();
|
||||||
|
@ -2658,6 +2658,10 @@ void Application::initializeUi() {
|
||||||
auto offscreenSurfaceCache = DependencyManager::get<OffscreenQmlSurfaceCache>();
|
auto offscreenSurfaceCache = DependencyManager::get<OffscreenQmlSurfaceCache>();
|
||||||
offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1);
|
offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1);
|
||||||
offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2);
|
offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2);
|
||||||
|
|
||||||
|
// Now that the menu is instantiated, ensure the display plugin menu is properly updated
|
||||||
|
updateDisplayMode();
|
||||||
|
flushMenuUpdates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4628,11 +4632,8 @@ QVector<EntityItemID> Application::pasteEntities(float x, float y, float z) {
|
||||||
return _entityClipboard->sendEntities(&_entityEditSender, getEntities()->getTree(), x, y, z);
|
return _entityClipboard->sendEntities(&_entityEditSender, getEntities()->getTree(), x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::initDisplay() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::init() {
|
void Application::init() {
|
||||||
|
_offscreenContext->makeCurrent();
|
||||||
// Make sure Login state is up to date
|
// Make sure Login state is up to date
|
||||||
DependencyManager::get<DialogsManager>()->toggleLoginDialog();
|
DependencyManager::get<DialogsManager>()->toggleLoginDialog();
|
||||||
if (!DISABLE_DEFERRED) {
|
if (!DISABLE_DEFERRED) {
|
||||||
|
@ -4838,7 +4839,7 @@ void Application::updateThreads(float deltaTime) {
|
||||||
|
|
||||||
void Application::toggleOverlays() {
|
void Application::toggleOverlays() {
|
||||||
auto menu = Menu::getInstance();
|
auto menu = Menu::getInstance();
|
||||||
menu->setIsOptionChecked(MenuOption::Overlays, menu->isOptionChecked(MenuOption::Overlays));
|
menu->setIsOptionChecked(MenuOption::Overlays, !menu->isOptionChecked(MenuOption::Overlays));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setOverlaysVisible(bool visible) {
|
void Application::setOverlaysVisible(bool visible) {
|
||||||
|
@ -5277,12 +5278,12 @@ void Application::update(float deltaTime) {
|
||||||
QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
|
QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
|
||||||
|
|
||||||
{
|
{
|
||||||
PROFILE_RANGE(simulation_physics, "Physics");
|
PROFILE_RANGE(simulation_physics, "Simulation");
|
||||||
PerformanceTimer perfTimer("physics");
|
PerformanceTimer perfTimer("simulation");
|
||||||
if (_physicsEnabled) {
|
if (_physicsEnabled) {
|
||||||
{
|
{
|
||||||
PROFILE_RANGE(simulation_physics, "PreStep");
|
PROFILE_RANGE(simulation_physics, "PrePhysics");
|
||||||
PerformanceTimer perfTimer("preStep)");
|
PerformanceTimer perfTimer("prePhysics)");
|
||||||
{
|
{
|
||||||
const VectorOfMotionStates& motionStates = _entitySimulation->getObjectsToRemoveFromPhysics();
|
const VectorOfMotionStates& motionStates = _entitySimulation->getObjectsToRemoveFromPhysics();
|
||||||
_physicsEngine->removeObjects(motionStates);
|
_physicsEngine->removeObjects(motionStates);
|
||||||
|
@ -5316,17 +5317,18 @@ void Application::update(float deltaTime) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
PROFILE_RANGE(simulation_physics, "Step");
|
PROFILE_RANGE(simulation_physics, "StepPhysics");
|
||||||
PerformanceTimer perfTimer("step");
|
PerformanceTimer perfTimer("stepPhysics");
|
||||||
getEntities()->getTree()->withWriteLock([&] {
|
getEntities()->getTree()->withWriteLock([&] {
|
||||||
_physicsEngine->stepSimulation();
|
_physicsEngine->stepSimulation();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
PROFILE_RANGE(simulation_physics, "PostStep");
|
|
||||||
PerformanceTimer perfTimer("postStep");
|
|
||||||
if (_physicsEngine->hasOutgoingChanges()) {
|
if (_physicsEngine->hasOutgoingChanges()) {
|
||||||
// grab the collision events BEFORE handleOutgoingChanges() because at this point
|
{
|
||||||
|
PROFILE_RANGE(simulation_physics, "PostPhysics");
|
||||||
|
PerformanceTimer perfTimer("postPhysics");
|
||||||
|
// grab the collision events BEFORE handleChangedMotionStates() because at this point
|
||||||
// we have a better idea of which objects we own or should own.
|
// we have a better idea of which objects we own or should own.
|
||||||
auto& collisionEvents = _physicsEngine->getCollisionEvents();
|
auto& collisionEvents = _physicsEngine->getCollisionEvents();
|
||||||
|
|
||||||
|
@ -5343,7 +5345,7 @@ void Application::update(float deltaTime) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!_aboutToQuit) {
|
if (!_aboutToQuit) {
|
||||||
// handleCollisionEvents() AFTER handleOutgoingChanges()
|
// handleCollisionEvents() AFTER handleChangedMotionStates()
|
||||||
{
|
{
|
||||||
PROFILE_RANGE(simulation_physics, "CollisionEvents");
|
PROFILE_RANGE(simulation_physics, "CollisionEvents");
|
||||||
avatarManager->handleCollisionEvents(collisionEvents);
|
avatarManager->handleCollisionEvents(collisionEvents);
|
||||||
|
@ -5351,10 +5353,6 @@ void Application::update(float deltaTime) {
|
||||||
// deadlock.)
|
// deadlock.)
|
||||||
_entitySimulation->handleCollisionEvents(collisionEvents);
|
_entitySimulation->handleCollisionEvents(collisionEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: the getEntities()->update() call below will wait for lock
|
|
||||||
// and will simulate entity motion (the EntityTree has been given an EntitySimulation).
|
|
||||||
getEntities()->update(true); // update the models...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -5364,12 +5362,19 @@ void Application::update(float deltaTime) {
|
||||||
|
|
||||||
if (PerformanceTimer::isActive() &&
|
if (PerformanceTimer::isActive() &&
|
||||||
Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) &&
|
Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) &&
|
||||||
Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsSimulationTiming)) {
|
Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsTiming)) {
|
||||||
_physicsEngine->harvestPerformanceStats();
|
_physicsEngine->harvestPerformanceStats();
|
||||||
}
|
}
|
||||||
// NOTE: the PhysicsEngine stats are written to stdout NOT to Qt log framework
|
// NOTE: the PhysicsEngine stats are written to stdout NOT to Qt log framework
|
||||||
_physicsEngine->dumpStatsIfNecessary();
|
_physicsEngine->dumpStatsIfNecessary();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_aboutToQuit) {
|
||||||
|
// NOTE: the getEntities()->update() call below will wait for lock
|
||||||
|
// and will provide non-physical entity motion
|
||||||
|
getEntities()->update(true); // update the models...
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// update the rendering without any simulation
|
// update the rendering without any simulation
|
||||||
|
@ -6032,9 +6037,7 @@ bool Application::nearbyEntitiesAreReadyForPhysics() {
|
||||||
bool result = true;
|
bool result = true;
|
||||||
foreach (EntityItemPointer entity, entities) {
|
foreach (EntityItemPointer entity, entities) {
|
||||||
if (entity->shouldBePhysical() && !entity->isReadyToComputeShape()) {
|
if (entity->shouldBePhysical() && !entity->isReadyToComputeShape()) {
|
||||||
static QString repeatedMessage =
|
HIFI_FCDEBUG(interfaceapp(), "Physics disabled until entity loads: " << entity->getID() << entity->getName());
|
||||||
LogHandler::getInstance().addRepeatedMessageRegex("Physics disabled until entity loads: .*");
|
|
||||||
qCDebug(interfaceapp) << "Physics disabled until entity loads: " << entity->getID() << entity->getName();
|
|
||||||
// don't break here because we want all the relevant entities to start their downloads
|
// don't break here because we want all the relevant entities to start their downloads
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
@ -7524,11 +7527,24 @@ void Application::updateDisplayMode() {
|
||||||
qFatal("Attempted to switch display plugins from a non-main thread");
|
qFatal("Attempted to switch display plugins from a non-main thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto menu = Menu::getInstance();
|
|
||||||
auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins();
|
auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins();
|
||||||
|
|
||||||
|
// Once time initialization code
|
||||||
static std::once_flag once;
|
static std::once_flag once;
|
||||||
std::call_once(once, [&] {
|
std::call_once(once, [&] {
|
||||||
|
foreach(auto displayPlugin, displayPlugins) {
|
||||||
|
displayPlugin->setContext(_gpuContext);
|
||||||
|
QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged,
|
||||||
|
[this](const QSize& size) { resizeGL(); });
|
||||||
|
QObject::connect(displayPlugin.get(), &DisplayPlugin::resetSensorsRequested, this, &Application::requestReset);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Once time initialization code that depends on the UI being available
|
||||||
|
auto menu = Menu::getInstance();
|
||||||
|
if (menu) {
|
||||||
|
static std::once_flag onceUi;
|
||||||
|
std::call_once(onceUi, [&] {
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
// first sort the plugins into groupings: standard, advanced, developer
|
// first sort the plugins into groupings: standard, advanced, developer
|
||||||
|
@ -7557,23 +7573,20 @@ void Application::updateDisplayMode() {
|
||||||
|
|
||||||
foreach(auto displayPlugin, standard) {
|
foreach(auto displayPlugin, standard) {
|
||||||
addDisplayPluginToMenu(displayPlugin, first);
|
addDisplayPluginToMenu(displayPlugin, first);
|
||||||
auto displayPluginName = displayPlugin->getName();
|
|
||||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) {
|
|
||||||
resizeGL();
|
|
||||||
});
|
|
||||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::resetSensorsRequested, this, &Application::requestReset);
|
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// after all plugins have been added to the menu, add a separator to the menu
|
// after all plugins have been added to the menu, add a separator to the menu
|
||||||
auto menu = Menu::getInstance();
|
|
||||||
auto parent = menu->getMenu(MenuOption::OutputMenu);
|
auto parent = menu->getMenu(MenuOption::OutputMenu);
|
||||||
parent->addSeparator();
|
parent->addSeparator();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Default to the first item on the list, in case none of the menu items match
|
// Default to the first item on the list, in case none of the menu items match
|
||||||
DisplayPluginPointer newDisplayPlugin = displayPlugins.at(0);
|
DisplayPluginPointer newDisplayPlugin = displayPlugins.at(0);
|
||||||
|
if (menu) {
|
||||||
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
|
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
|
||||||
QString name = displayPlugin->getName();
|
QString name = displayPlugin->getName();
|
||||||
QAction* action = menu->getActionForOption(name);
|
QAction* action = menu->getActionForOption(name);
|
||||||
|
@ -7586,13 +7599,19 @@ void Application::updateDisplayMode() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (newDisplayPlugin == _displayPlugin) {
|
if (newDisplayPlugin == _displayPlugin) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setDisplayPlugin(newDisplayPlugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::setDisplayPlugin(DisplayPluginPointer newDisplayPlugin) {
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
auto desktop = offscreenUi->getDesktop();
|
auto desktop = offscreenUi->getDesktop();
|
||||||
|
auto menu = Menu::getInstance();
|
||||||
|
|
||||||
// Make the switch atomic from the perspective of other threads
|
// Make the switch atomic from the perspective of other threads
|
||||||
{
|
{
|
||||||
|
@ -7613,6 +7632,8 @@ void Application::updateDisplayMode() {
|
||||||
bool active = newDisplayPlugin->activate();
|
bool active = newDisplayPlugin->activate();
|
||||||
|
|
||||||
if (!active) {
|
if (!active) {
|
||||||
|
auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins();
|
||||||
|
|
||||||
// If the new plugin fails to activate, fallback to last display
|
// If the new plugin fails to activate, fallback to last display
|
||||||
qWarning() << "Failed to activate display: " << newDisplayPlugin->getName();
|
qWarning() << "Failed to activate display: " << newDisplayPlugin->getName();
|
||||||
newDisplayPlugin = oldDisplayPlugin;
|
newDisplayPlugin = oldDisplayPlugin;
|
||||||
|
@ -7633,13 +7654,6 @@ void Application::updateDisplayMode() {
|
||||||
if (!active) {
|
if (!active) {
|
||||||
qFatal("Failed to activate fallback plugin");
|
qFatal("Failed to activate fallback plugin");
|
||||||
}
|
}
|
||||||
|
|
||||||
// We've changed the selection - it should be reflected in the menu
|
|
||||||
QAction* action = menu->getActionForOption(newDisplayPlugin->getName());
|
|
||||||
if (!action) {
|
|
||||||
qFatal("Failed to find activated plugin");
|
|
||||||
}
|
|
||||||
action->setChecked(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
offscreenUi->resize(fromGlm(newDisplayPlugin->getRecommendedUiSize()));
|
offscreenUi->resize(fromGlm(newDisplayPlugin->getRecommendedUiSize()));
|
||||||
|
@ -7666,6 +7680,12 @@ void Application::updateDisplayMode() {
|
||||||
getMyAvatar()->reset(false);
|
getMyAvatar()->reset(false);
|
||||||
|
|
||||||
// switch to first person if entering hmd and setting is checked
|
// switch to first person if entering hmd and setting is checked
|
||||||
|
if (menu) {
|
||||||
|
QAction* action = menu->getActionForOption(newDisplayPlugin->getName());
|
||||||
|
if (action) {
|
||||||
|
action->setChecked(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (isHmd && menu->isOptionChecked(MenuOption::FirstPersonHMD)) {
|
if (isHmd && menu->isOptionChecked(MenuOption::FirstPersonHMD)) {
|
||||||
menu->setIsOptionChecked(MenuOption::FirstPerson, true);
|
menu->setIsOptionChecked(MenuOption::FirstPerson, true);
|
||||||
cameraMenuChanged();
|
cameraMenuChanged();
|
||||||
|
@ -7674,6 +7694,7 @@ void Application::updateDisplayMode() {
|
||||||
// Remove the mirror camera option from menu if in HMD mode
|
// Remove the mirror camera option from menu if in HMD mode
|
||||||
auto mirrorAction = menu->getActionForOption(MenuOption::FullscreenMirror);
|
auto mirrorAction = menu->getActionForOption(MenuOption::FullscreenMirror);
|
||||||
mirrorAction->setVisible(!isHmd);
|
mirrorAction->setVisible(!isHmd);
|
||||||
|
}
|
||||||
|
|
||||||
Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
|
Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
|
||||||
}
|
}
|
||||||
|
@ -7749,15 +7770,18 @@ void Application::unresponsiveApplication() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setActiveDisplayPlugin(const QString& pluginName) {
|
void Application::setActiveDisplayPlugin(const QString& pluginName) {
|
||||||
auto menu = Menu::getInstance();
|
DisplayPluginPointer newDisplayPlugin;
|
||||||
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
|
for (DisplayPluginPointer displayPlugin : PluginManager::getInstance()->getDisplayPlugins()) {
|
||||||
QString name = displayPlugin->getName();
|
QString name = displayPlugin->getName();
|
||||||
QAction* action = menu->getActionForOption(name);
|
|
||||||
if (pluginName == name) {
|
if (pluginName == name) {
|
||||||
action->setChecked(true);
|
newDisplayPlugin = displayPlugin;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateDisplayMode();
|
|
||||||
|
if (newDisplayPlugin) {
|
||||||
|
setDisplayPlugin(newDisplayPlugin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::handleLocalServerConnection() const {
|
void Application::handleLocalServerConnection() const {
|
||||||
|
|
|
@ -145,6 +145,7 @@ public:
|
||||||
Q_INVOKABLE QString getUserAgent();
|
Q_INVOKABLE QString getUserAgent();
|
||||||
|
|
||||||
void initializeGL();
|
void initializeGL();
|
||||||
|
void initializeRenderEngine();
|
||||||
void initializeUi();
|
void initializeUi();
|
||||||
|
|
||||||
void updateCamera(RenderArgs& renderArgs, float deltaTime);
|
void updateCamera(RenderArgs& renderArgs, float deltaTime);
|
||||||
|
@ -444,6 +445,7 @@ private slots:
|
||||||
static void packetSent(quint64 length);
|
static void packetSent(quint64 length);
|
||||||
static void addingEntityWithCertificate(const QString& certificateID, const QString& placeName);
|
static void addingEntityWithCertificate(const QString& certificateID, const QString& placeName);
|
||||||
void updateDisplayMode();
|
void updateDisplayMode();
|
||||||
|
void setDisplayPlugin(DisplayPluginPointer newPlugin);
|
||||||
void domainConnectionRefused(const QString& reasonMessage, int reason, const QString& extraInfo);
|
void domainConnectionRefused(const QString& reasonMessage, int reason, const QString& extraInfo);
|
||||||
|
|
||||||
void addAssetToWorldCheckModelSize();
|
void addAssetToWorldCheckModelSize();
|
||||||
|
@ -456,7 +458,6 @@ private slots:
|
||||||
void switchDisplayMode();
|
void switchDisplayMode();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void initDisplay();
|
|
||||||
void init();
|
void init();
|
||||||
bool handleKeyEventForFocusedEntityOrOverlay(QEvent* event);
|
bool handleKeyEventForFocusedEntityOrOverlay(QEvent* event);
|
||||||
bool handleFileOpenEvent(QFileOpenEvent* event);
|
bool handleFileOpenEvent(QFileOpenEvent* event);
|
||||||
|
|
|
@ -87,10 +87,8 @@ EntityDynamicPointer InterfaceDynamicFactory::factoryBA(EntityItemPointer ownerE
|
||||||
if (dynamic) {
|
if (dynamic) {
|
||||||
dynamic->deserialize(data);
|
dynamic->deserialize(data);
|
||||||
if (dynamic->lifetimeIsOver()) {
|
if (dynamic->lifetimeIsOver()) {
|
||||||
static QString repeatedMessage =
|
HIFI_FDEBUG("InterfaceDynamicFactory::factoryBA lifetimeIsOver during dynamic creation --"
|
||||||
LogHandler::getInstance().addRepeatedMessageRegex(".*factoryBA lifetimeIsOver during dynamic creation.*");
|
<< dynamic->getExpires() << "<" << usecTimestampNow());
|
||||||
qDebug() << "InterfaceDynamicFactory::factoryBA lifetimeIsOver during dynamic creation --"
|
|
||||||
<< dynamic->getExpires() << "<" << usecTimestampNow();
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -683,11 +683,12 @@ Menu::Menu() {
|
||||||
qApp, SLOT(enablePerfStats(bool)));
|
qApp, SLOT(enablePerfStats(bool)));
|
||||||
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::OnlyDisplayTopTen, 0, true);
|
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::OnlyDisplayTopTen, 0, true);
|
||||||
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandUpdateTiming, 0, false);
|
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandUpdateTiming, 0, false);
|
||||||
|
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandSimulationTiming, 0, false);
|
||||||
|
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandPhysicsTiming, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarTiming, 0, false);
|
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarTiming, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarSimulateTiming, 0, false);
|
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarSimulateTiming, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandOtherAvatarTiming, 0, false);
|
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandOtherAvatarTiming, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandPaintGLTiming, 0, false);
|
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandPaintGLTiming, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandPhysicsSimulationTiming, 0, false);
|
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::FrameTimer);
|
addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::FrameTimer);
|
||||||
addActionToQMenuAndActionHash(timingMenu, MenuOption::RunTimingTests, 0, qApp, SLOT(runTests()));
|
addActionToQMenuAndActionHash(timingMenu, MenuOption::RunTimingTests, 0, qApp, SLOT(runTests()));
|
||||||
|
|
|
@ -105,7 +105,8 @@ namespace MenuOption {
|
||||||
const QString ExpandMyAvatarTiming = "Expand /myAvatar";
|
const QString ExpandMyAvatarTiming = "Expand /myAvatar";
|
||||||
const QString ExpandOtherAvatarTiming = "Expand /otherAvatar";
|
const QString ExpandOtherAvatarTiming = "Expand /otherAvatar";
|
||||||
const QString ExpandPaintGLTiming = "Expand /paintGL";
|
const QString ExpandPaintGLTiming = "Expand /paintGL";
|
||||||
const QString ExpandPhysicsSimulationTiming = "Expand /physics";
|
const QString ExpandSimulationTiming = "Expand /simulation";
|
||||||
|
const QString ExpandPhysicsTiming = "Expand /physics";
|
||||||
const QString ExpandUpdateTiming = "Expand /update";
|
const QString ExpandUpdateTiming = "Expand /update";
|
||||||
const QString FirstPerson = "First Person";
|
const QString FirstPerson = "First Person";
|
||||||
const QString FirstPersonHMD = "Enter First Person Mode in HMD";
|
const QString FirstPersonHMD = "Enter First Person Mode in HMD";
|
||||||
|
|
|
@ -60,8 +60,8 @@ Stats::Stats(QQuickItem* parent) : QQuickItem(parent) {
|
||||||
bool Stats::includeTimingRecord(const QString& name) {
|
bool Stats::includeTimingRecord(const QString& name) {
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails)) {
|
||||||
if (name.startsWith("/idle/update/")) {
|
if (name.startsWith("/idle/update/")) {
|
||||||
if (name.startsWith("/idle/update/physics/")) {
|
if (name.startsWith("/idle/update/simulation/")) {
|
||||||
return Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsSimulationTiming);
|
return Menu::getInstance()->isOptionChecked(MenuOption::ExpandSimulationTiming);
|
||||||
} else if (name.startsWith("/idle/update/myAvatar/")) {
|
} else if (name.startsWith("/idle/update/myAvatar/")) {
|
||||||
if (name.startsWith("/idle/update/myAvatar/simulate/")) {
|
if (name.startsWith("/idle/update/myAvatar/simulate/")) {
|
||||||
return Menu::getInstance()->isOptionChecked(MenuOption::ExpandMyAvatarSimulateTiming);
|
return Menu::getInstance()->isOptionChecked(MenuOption::ExpandMyAvatarSimulateTiming);
|
||||||
|
@ -75,8 +75,8 @@ bool Stats::includeTimingRecord(const QString& name) {
|
||||||
return Menu::getInstance()->isOptionChecked(MenuOption::ExpandPaintGLTiming);
|
return Menu::getInstance()->isOptionChecked(MenuOption::ExpandPaintGLTiming);
|
||||||
} else if (name.startsWith("/paintGL/")) {
|
} else if (name.startsWith("/paintGL/")) {
|
||||||
return Menu::getInstance()->isOptionChecked(MenuOption::ExpandPaintGLTiming);
|
return Menu::getInstance()->isOptionChecked(MenuOption::ExpandPaintGLTiming);
|
||||||
} else if (name.startsWith("step/")) {
|
} else if (name.startsWith("physics/")) {
|
||||||
return Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsSimulationTiming);
|
return Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsTiming);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -479,7 +479,14 @@ void Stats::updateStats(bool force) {
|
||||||
float dt = (float)itr.value().getMovingAverage() / (float)USECS_PER_MSEC;
|
float dt = (float)itr.value().getMovingAverage() / (float)USECS_PER_MSEC;
|
||||||
_gameUpdateStats = QString("/idle/update = %1 ms").arg(dt);
|
_gameUpdateStats = QString("/idle/update = %1 ms").arg(dt);
|
||||||
|
|
||||||
QVector<QString> categories = { "devices", "physics", "otherAvatars", "MyAvatar", "misc" };
|
QVector<QString> categories = {
|
||||||
|
"devices",
|
||||||
|
"MyAvatar",
|
||||||
|
"otherAvatars",
|
||||||
|
"pickManager",
|
||||||
|
"pointerManager",
|
||||||
|
"simulation"
|
||||||
|
};
|
||||||
for (int32_t j = 0; j < categories.size(); ++j) {
|
for (int32_t j = 0; j < categories.size(); ++j) {
|
||||||
QString recordKey = "/idle/update/" + categories[j];
|
QString recordKey = "/idle/update/" + categories[j];
|
||||||
itr = allRecords.find(recordKey);
|
itr = allRecords.find(recordKey);
|
||||||
|
|
|
@ -39,9 +39,6 @@ AudioRingBufferTemplate<T>::AudioRingBufferTemplate(int numFrameSamples, int num
|
||||||
_nextOutput = _buffer;
|
_nextOutput = _buffer;
|
||||||
_endOfLastWrite = _buffer;
|
_endOfLastWrite = _buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString repeatedOverflowMessage = LogHandler::getInstance().addRepeatedMessageRegex(RING_BUFFER_OVERFLOW_DEBUG);
|
|
||||||
static QString repeatedDroppedMessage = LogHandler::getInstance().addRepeatedMessageRegex(DROPPED_SILENT_DEBUG);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -154,6 +151,11 @@ int AudioRingBufferTemplate<T>::appendData(char *data, int maxSize) {
|
||||||
return numReadSamples * SampleSize;
|
return numReadSamples * SampleSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int repeatedOverflowMessageID = 0;
|
||||||
|
std::once_flag messageIDFlag;
|
||||||
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
int AudioRingBufferTemplate<T>::writeData(const char* data, int maxSize) {
|
int AudioRingBufferTemplate<T>::writeData(const char* data, int maxSize) {
|
||||||
// only copy up to the number of samples we have capacity for
|
// only copy up to the number of samples we have capacity for
|
||||||
|
@ -167,7 +169,9 @@ int AudioRingBufferTemplate<T>::writeData(const char* data, int maxSize) {
|
||||||
_nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, samplesToDelete);
|
_nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, samplesToDelete);
|
||||||
_overflowCount++;
|
_overflowCount++;
|
||||||
|
|
||||||
qCDebug(audio) << qPrintable(RING_BUFFER_OVERFLOW_DEBUG);
|
std::call_once(messageIDFlag, [](int* id) { *id = LogHandler::getInstance().newRepeatedMessageID(); },
|
||||||
|
&repeatedOverflowMessageID);
|
||||||
|
HIFI_FCDEBUG_ID(audio(), repeatedOverflowMessageID, RING_BUFFER_OVERFLOW_DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_endOfLastWrite + numWriteSamples > _buffer + _bufferLength) {
|
if (_endOfLastWrite + numWriteSamples > _buffer + _bufferLength) {
|
||||||
|
@ -224,7 +228,7 @@ int AudioRingBufferTemplate<T>::addSilentSamples(int silentSamples) {
|
||||||
if (numWriteSamples > samplesRoomFor) {
|
if (numWriteSamples > samplesRoomFor) {
|
||||||
numWriteSamples = samplesRoomFor;
|
numWriteSamples = samplesRoomFor;
|
||||||
|
|
||||||
qCDebug(audio) << qPrintable(DROPPED_SILENT_DEBUG);
|
HIFI_FCDEBUG(audio(), DROPPED_SILENT_DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_endOfLastWrite + numWriteSamples > _buffer + _bufferLength) {
|
if (_endOfLastWrite + numWriteSamples > _buffer + _bufferLength) {
|
||||||
|
@ -275,7 +279,10 @@ int AudioRingBufferTemplate<T>::writeSamples(ConstIterator source, int maxSample
|
||||||
int samplesToDelete = samplesToCopy - samplesRoomFor;
|
int samplesToDelete = samplesToCopy - samplesRoomFor;
|
||||||
_nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, samplesToDelete);
|
_nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, samplesToDelete);
|
||||||
_overflowCount++;
|
_overflowCount++;
|
||||||
qCDebug(audio) << qPrintable(RING_BUFFER_OVERFLOW_DEBUG);
|
|
||||||
|
std::call_once(messageIDFlag, [](int* id) { *id = LogHandler::getInstance().newRepeatedMessageID(); },
|
||||||
|
&repeatedOverflowMessageID);
|
||||||
|
HIFI_FCDEBUG_ID(audio(), repeatedOverflowMessageID, RING_BUFFER_OVERFLOW_DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sample* bufferLast = _buffer + _bufferLength - 1;
|
Sample* bufferLast = _buffer + _bufferLength - 1;
|
||||||
|
@ -297,7 +304,10 @@ int AudioRingBufferTemplate<T>::writeSamplesWithFade(ConstIterator source, int m
|
||||||
int samplesToDelete = samplesToCopy - samplesRoomFor;
|
int samplesToDelete = samplesToCopy - samplesRoomFor;
|
||||||
_nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, samplesToDelete);
|
_nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, samplesToDelete);
|
||||||
_overflowCount++;
|
_overflowCount++;
|
||||||
qCDebug(audio) << qPrintable(RING_BUFFER_OVERFLOW_DEBUG);
|
|
||||||
|
std::call_once(messageIDFlag, [](int* id) { *id = LogHandler::getInstance().newRepeatedMessageID(); },
|
||||||
|
&repeatedOverflowMessageID);
|
||||||
|
HIFI_FCDEBUG_ID(audio(), repeatedOverflowMessageID, RING_BUFFER_OVERFLOW_DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sample* bufferLast = _buffer + _bufferLength - 1;
|
Sample* bufferLast = _buffer + _bufferLength - 1;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include <glm/detail/func_common.hpp>
|
#include <glm/detail/func_common.hpp>
|
||||||
#include <QtCore/QDataStream>
|
#include <QtCore/QDataStream>
|
||||||
|
#include <QtCore/QLoggingCategory>
|
||||||
|
|
||||||
#include <LogHandler.h>
|
#include <LogHandler.h>
|
||||||
#include <Node.h>
|
#include <Node.h>
|
||||||
|
@ -80,10 +81,7 @@ int PositionalAudioStream::parsePositionalData(const QByteArray& positionalByteA
|
||||||
|
|
||||||
// if the client sends us a bad position, flag it so that we don't consider this stream for mixing
|
// if the client sends us a bad position, flag it so that we don't consider this stream for mixing
|
||||||
if (glm::isnan(_position.x) || glm::isnan(_position.y) || glm::isnan(_position.z)) {
|
if (glm::isnan(_position.x) || glm::isnan(_position.y) || glm::isnan(_position.z)) {
|
||||||
static const QString INVALID_POSITION_REGEX = "PositionalAudioStream unpacked invalid position for node";
|
HIFI_FDEBUG("PositionalAudioStream unpacked invalid position for node" << uuidStringWithoutCurlyBraces(getNodeID()) );
|
||||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex(INVALID_POSITION_REGEX);
|
|
||||||
|
|
||||||
qDebug() << "PositionalAudioStream unpacked invalid position for node" << uuidStringWithoutCurlyBraces(getNodeID());
|
|
||||||
|
|
||||||
_hasValidPosition = false;
|
_hasValidPosition = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -56,10 +56,8 @@ glm::mat4 StereoDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& basePr
|
||||||
|
|
||||||
static const QString FRAMERATE = DisplayPlugin::MENU_PATH() + ">Framerate";
|
static const QString FRAMERATE = DisplayPlugin::MENU_PATH() + ">Framerate";
|
||||||
|
|
||||||
std::vector<QAction*> _screenActions;
|
|
||||||
bool StereoDisplayPlugin::internalActivate() {
|
bool StereoDisplayPlugin::internalActivate() {
|
||||||
auto screens = qApp->screens();
|
auto screens = qApp->screens();
|
||||||
_screenActions.resize(screens.size());
|
|
||||||
for (int i = 0; i < screens.size(); ++i) {
|
for (int i = 0; i < screens.size(); ++i) {
|
||||||
auto screen = screens.at(i);
|
auto screen = screens.at(i);
|
||||||
QString name = QString("Screen %1: %2").arg(i + 1).arg(screen->name());
|
QString name = QString("Screen %1: %2").arg(i + 1).arg(screen->name());
|
||||||
|
@ -67,9 +65,9 @@ bool StereoDisplayPlugin::internalActivate() {
|
||||||
if (screen == qApp->primaryScreen()) {
|
if (screen == qApp->primaryScreen()) {
|
||||||
checked = true;
|
checked = true;
|
||||||
}
|
}
|
||||||
auto action = _container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), name,
|
const uint32_t screenIndex = i;
|
||||||
[this](bool clicked) { updateScreen(); }, true, checked, "Screens");
|
_container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), name,
|
||||||
_screenActions[i] = action;
|
[=](bool clicked) { updateScreen(screenIndex); }, true, checked, "Screens");
|
||||||
}
|
}
|
||||||
|
|
||||||
_container->removeMenu(FRAMERATE);
|
_container->removeMenu(FRAMERATE);
|
||||||
|
@ -80,18 +78,12 @@ bool StereoDisplayPlugin::internalActivate() {
|
||||||
return Parent::internalActivate();
|
return Parent::internalActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StereoDisplayPlugin::updateScreen() {
|
void StereoDisplayPlugin::updateScreen(uint32_t i) {
|
||||||
for (uint32_t i = 0; i < _screenActions.size(); ++i) {
|
|
||||||
if (_screenActions[i]->isChecked()) {
|
|
||||||
_screen = qApp->screens().at(i);
|
_screen = qApp->screens().at(i);
|
||||||
_container->setFullscreen(_screen);
|
_container->setFullscreen(_screen);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StereoDisplayPlugin::internalDeactivate() {
|
void StereoDisplayPlugin::internalDeactivate() {
|
||||||
_screenActions.clear();
|
|
||||||
_container->unsetFullscreen();
|
_container->unsetFullscreen();
|
||||||
Parent::internalDeactivate();
|
Parent::internalDeactivate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
virtual bool internalActivate() override;
|
virtual bool internalActivate() override;
|
||||||
virtual void internalDeactivate() override;
|
virtual void internalDeactivate() override;
|
||||||
void updateScreen();
|
void updateScreen(uint32_t i);
|
||||||
|
|
||||||
float _ipd{ 0.064f };
|
float _ipd{ 0.064f };
|
||||||
QScreen* _screen;
|
QScreen* _screen;
|
||||||
|
|
|
@ -2193,10 +2193,8 @@ void EntityItem::deserializeActionsInternal() {
|
||||||
entity->addActionInternal(simulation, action);
|
entity->addActionInternal(simulation, action);
|
||||||
updated << actionID;
|
updated << actionID;
|
||||||
} else {
|
} else {
|
||||||
static QString repeatedMessage =
|
HIFI_FCDEBUG(entities(), "EntityItem::deserializeActionsInternal -- action creation failed for"
|
||||||
LogHandler::getInstance().addRepeatedMessageRegex(".*action creation failed for.*");
|
<< getID() << _name); // getName();
|
||||||
qCDebug(entities) << "EntityItem::deserializeActionsInternal -- action creation failed for"
|
|
||||||
<< getID() << _name; // getName();
|
|
||||||
removeActionInternal(actionID, nullptr);
|
removeActionInternal(actionID, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,11 @@ void EntityTree::eraseAllOctreeElements(bool createNewRoot) {
|
||||||
|
|
||||||
resetClientEditStats();
|
resetClientEditStats();
|
||||||
clearDeletedEntities();
|
clearDeletedEntities();
|
||||||
|
|
||||||
|
{
|
||||||
|
QWriteLocker locker(&_needsParentFixupLock);
|
||||||
|
_needsParentFixup.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTree::readBitstreamToTree(const unsigned char* bitstream,
|
void EntityTree::readBitstreamToTree(const unsigned char* bitstream,
|
||||||
|
@ -1645,11 +1650,9 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
|
||||||
_recentlyDeletedEntityItemIDs.insert(usecTimestampNow(), entityItemID);
|
_recentlyDeletedEntityItemIDs.insert(usecTimestampNow(), entityItemID);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
static QString repeatedMessage =
|
HIFI_FCDEBUG(entities(), "Edit failed. [" << message.getType() <<"] " <<
|
||||||
LogHandler::getInstance().addRepeatedMessageRegex("^Edit failed.*");
|
|
||||||
qCDebug(entities) << "Edit failed. [" << message.getType() <<"] " <<
|
|
||||||
"entity id:" << entityItemID <<
|
"entity id:" << entityItemID <<
|
||||||
"existingEntity pointer:" << existingEntity.get();
|
"existingEntity pointer:" << existingEntity.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -566,20 +566,20 @@ glm::vec3 FBXReader::normalizeDirForPacking(const glm::vec3& dir) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
|
void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
|
||||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("buildModelMesh failed -- .*");
|
|
||||||
|
|
||||||
unsigned int totalSourceIndices = 0;
|
unsigned int totalSourceIndices = 0;
|
||||||
foreach(const FBXMeshPart& part, extractedMesh.parts) {
|
foreach(const FBXMeshPart& part, extractedMesh.parts) {
|
||||||
totalSourceIndices += (part.quadTrianglesIndices.size() + part.triangleIndices.size());
|
totalSourceIndices += (part.quadTrianglesIndices.size() + part.triangleIndices.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int repeatMessageID = LogHandler::getInstance().newRepeatedMessageID();
|
||||||
|
|
||||||
if (!totalSourceIndices) {
|
if (!totalSourceIndices) {
|
||||||
qCDebug(modelformat) << "buildModelMesh failed -- no indices, url = " << url;
|
HIFI_FCDEBUG_ID(modelformat(), repeatMessageID, "buildModelMesh failed -- no indices, url = " << url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extractedMesh.vertices.size() == 0) {
|
if (extractedMesh.vertices.size() == 0) {
|
||||||
qCDebug(modelformat) << "buildModelMesh failed -- no vertices, url = " << url;
|
HIFI_FCDEBUG_ID(modelformat(), repeatMessageID, "buildModelMesh failed -- no vertices, url = " << url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,10 @@ void GLWidget::createContext() {
|
||||||
_context->doneCurrent();
|
_context->doneCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLWidget::swapBuffers() {
|
||||||
|
_context->swapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
bool GLWidget::makeCurrent() {
|
bool GLWidget::makeCurrent() {
|
||||||
gl::Context::makeCurrent(_context->qglContext(), windowHandle());
|
gl::Context::makeCurrent(_context->qglContext(), windowHandle());
|
||||||
return _context->makeCurrent();
|
return _context->makeCurrent();
|
||||||
|
|
|
@ -32,6 +32,7 @@ public:
|
||||||
void createContext();
|
void createContext();
|
||||||
bool makeCurrent();
|
bool makeCurrent();
|
||||||
void doneCurrent();
|
void doneCurrent();
|
||||||
|
void swapBuffers();
|
||||||
gl::Context* context() { return _context; }
|
gl::Context* context() { return _context; }
|
||||||
QOpenGLContext* qglContext();
|
QOpenGLContext* qglContext();
|
||||||
|
|
||||||
|
|
|
@ -277,13 +277,8 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
|
||||||
emit dataReceived(sendingNodeType, packet.getPayloadSize());
|
emit dataReceived(sendingNodeType, packet.getPayloadSize());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
static const QString UNSOLICITED_REPLICATED_REGEX =
|
HIFI_FCDEBUG(networking(), "Replicated packet of type" << headerType
|
||||||
"Replicated packet of type \\d+ \\([\\sa-zA-Z:]+\\) received from unknown upstream";
|
<< "received from unknown upstream" << packet.getSenderSockAddr());
|
||||||
static QString repeatedMessage
|
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(UNSOLICITED_REPLICATED_REGEX);
|
|
||||||
|
|
||||||
qCDebug(networking) << "Replicated packet of type" << headerType
|
|
||||||
<< "received from unknown upstream" << packet.getSenderSockAddr();
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -345,12 +340,8 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
static const QString UNKNOWN_REGEX = "Packet of type \\d+ \\([\\sa-zA-Z:]+\\) received from unknown node with UUID";
|
HIFI_FCDEBUG(networking(),
|
||||||
static QString repeatedMessage
|
"Packet of type" << headerType << "received from unknown node with UUID" << uuidStringWithoutCurlyBraces(sourceID));
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(UNKNOWN_REGEX);
|
|
||||||
|
|
||||||
qCDebug(networking) << "Packet of type" << headerType
|
|
||||||
<< "received from unknown node with UUID" << uuidStringWithoutCurlyBraces(sourceID);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,8 +90,8 @@ NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort)
|
||||||
// assume that we may need to send a new DS check in anytime a new keypair is generated
|
// assume that we may need to send a new DS check in anytime a new keypair is generated
|
||||||
connect(accountManager.data(), &AccountManager::newKeypair, this, &NodeList::sendDomainServerCheckIn);
|
connect(accountManager.data(), &AccountManager::newKeypair, this, &NodeList::sendDomainServerCheckIn);
|
||||||
|
|
||||||
// clear out NodeList when login is finished
|
// clear out NodeList when login is finished and we know our new username
|
||||||
connect(accountManager.data(), SIGNAL(loginComplete(const QUrl&)) , this, SLOT(reset()));
|
connect(accountManager.data(), SIGNAL(usernameChanged(QString)) , this, SLOT(reset()));
|
||||||
|
|
||||||
// clear our NodeList when logout is requested
|
// clear our NodeList when logout is requested
|
||||||
connect(accountManager.data(), SIGNAL(logoutComplete()) , this, SLOT(reset()));
|
connect(accountManager.data(), SIGNAL(logoutComplete()) , this, SLOT(reset()));
|
||||||
|
|
|
@ -89,10 +89,7 @@ SequenceNumberStats::ArrivalInfo SequenceNumberStats::sequenceNumberReceived(qui
|
||||||
} else if (absGap > MAX_REASONABLE_SEQUENCE_GAP) {
|
} else if (absGap > MAX_REASONABLE_SEQUENCE_GAP) {
|
||||||
arrivalInfo._status = Unreasonable;
|
arrivalInfo._status = Unreasonable;
|
||||||
|
|
||||||
static const QString UNREASONABLE_SEQUENCE_REGEX { "unreasonable sequence number: \\d+ previous: \\d+" };
|
HIFI_FCDEBUG(networking(), "unreasonable sequence number:" << incoming << "previous:" << _lastReceivedSequence);
|
||||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex(UNREASONABLE_SEQUENCE_REGEX);
|
|
||||||
|
|
||||||
qCDebug(networking) << "unreasonable sequence number:" << incoming << "previous:" << _lastReceivedSequence;
|
|
||||||
|
|
||||||
_stats._unreasonable++;
|
_stats._unreasonable++;
|
||||||
|
|
||||||
|
@ -154,10 +151,7 @@ SequenceNumberStats::ArrivalInfo SequenceNumberStats::sequenceNumberReceived(qui
|
||||||
|
|
||||||
arrivalInfo._status = Unreasonable;
|
arrivalInfo._status = Unreasonable;
|
||||||
|
|
||||||
static const QString UNREASONABLE_SEQUENCE_REGEX { "unreasonable sequence number: \\d+ \\(possible duplicate\\)" };
|
HIFI_FCDEBUG(networking(), "unreasonable sequence number:" << incoming << "(possible duplicate)");
|
||||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex(UNREASONABLE_SEQUENCE_REGEX);
|
|
||||||
|
|
||||||
qCDebug(networking) << "unreasonable sequence number:" << incoming << "(possible duplicate)";
|
|
||||||
|
|
||||||
_stats._unreasonable++;
|
_stats._unreasonable++;
|
||||||
|
|
||||||
|
|
|
@ -107,8 +107,7 @@ Packet::Packet(std::unique_ptr<char[]> data, qint64 size, const HifiSockAddr& se
|
||||||
QString::number(getMessagePartNumber()));
|
QString::number(getMessagePartNumber()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Unobfuscating packet .*");
|
HIFI_FCDEBUG(networking(), debugString);
|
||||||
qCDebug(networking) << qPrintable(debugString);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
obfuscate(NoObfuscation); // Undo obfuscation
|
obfuscate(NoObfuscation); // Undo obfuscation
|
||||||
|
|
|
@ -479,8 +479,7 @@ bool SendQueue::maybeResendPacket() {
|
||||||
debugString = debugString.arg(QString::number(resendPacket.getMessageNumber()),
|
debugString = debugString.arg(QString::number(resendPacket.getMessageNumber()),
|
||||||
QString::number(resendPacket.getMessagePartNumber()));
|
QString::number(resendPacket.getMessagePartNumber()));
|
||||||
}
|
}
|
||||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Obfuscating packet .*");
|
HIFI_FDEBUG(debugString);
|
||||||
qCritical() << qPrintable(debugString);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Create copy of the packet
|
// Create copy of the packet
|
||||||
|
|
|
@ -229,11 +229,7 @@ qint64 Socket::writeDatagram(const QByteArray& datagram, const HifiSockAddr& soc
|
||||||
|
|
||||||
if (bytesWritten < 0) {
|
if (bytesWritten < 0) {
|
||||||
// when saturating a link this isn't an uncommon message - suppress it so it doesn't bomb the debug
|
// when saturating a link this isn't an uncommon message - suppress it so it doesn't bomb the debug
|
||||||
static const QString WRITE_ERROR_REGEX = "Socket::writeDatagram QAbstractSocket::NetworkError - Unable to send a message";
|
HIFI_FCDEBUG(networking(), "Socket::writeDatagram" << _udpSocket.error() << "-" << qPrintable(_udpSocket.errorString()) );
|
||||||
static QString repeatedMessage
|
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(WRITE_ERROR_REGEX);
|
|
||||||
|
|
||||||
qCDebug(networking) << "Socket::writeDatagram" << _udpSocket.error() << "-" << qPrintable(_udpSocket.errorString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytesWritten;
|
return bytesWritten;
|
||||||
|
@ -517,11 +513,7 @@ std::vector<HifiSockAddr> Socket::getConnectionSockAddrs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Socket::handleSocketError(QAbstractSocket::SocketError socketError) {
|
void Socket::handleSocketError(QAbstractSocket::SocketError socketError) {
|
||||||
static const QString SOCKET_REGEX = "udt::Socket error - ";
|
HIFI_FCDEBUG(networking(), "udt::Socket error - " << socketError << _udpSocket.errorString());
|
||||||
static QString repeatedMessage
|
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(SOCKET_REGEX);
|
|
||||||
|
|
||||||
qCDebug(networking) << "udt::Socket error - " << socketError << _udpSocket.errorString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Socket::handleStateChanged(QAbstractSocket::SocketState socketState) {
|
void Socket::handleStateChanged(QAbstractSocket::SocketState socketState) {
|
||||||
|
|
|
@ -121,11 +121,7 @@ void Octree::recurseTreeWithPostOperation(const RecurseOctreeOperation& operatio
|
||||||
void Octree::recurseElementWithOperation(const OctreeElementPointer& element, const RecurseOctreeOperation& operation, void* extraData,
|
void Octree::recurseElementWithOperation(const OctreeElementPointer& element, const RecurseOctreeOperation& operation, void* extraData,
|
||||||
int recursionCount) {
|
int recursionCount) {
|
||||||
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
||||||
static QString repeatedMessage
|
HIFI_FCDEBUG(octree(), "Octree::recurseElementWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(
|
|
||||||
"Octree::recurseElementWithOperation\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
|
||||||
|
|
||||||
qCDebug(octree) << "Octree::recurseElementWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,11 +139,7 @@ void Octree::recurseElementWithOperation(const OctreeElementPointer& element, co
|
||||||
void Octree::recurseElementWithPostOperation(const OctreeElementPointer& element, const RecurseOctreeOperation& operation,
|
void Octree::recurseElementWithPostOperation(const OctreeElementPointer& element, const RecurseOctreeOperation& operation,
|
||||||
void* extraData, int recursionCount) {
|
void* extraData, int recursionCount) {
|
||||||
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
||||||
static QString repeatedMessage
|
HIFI_FCDEBUG(octree(), "Octree::recurseElementWithPostOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(
|
|
||||||
"Octree::recurseElementWithPostOperation\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
|
||||||
|
|
||||||
qCDebug(octree) << "Octree::recurseElementWithPostOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,11 +165,7 @@ void Octree::recurseElementWithOperationDistanceSorted(const OctreeElementPointe
|
||||||
const glm::vec3& point, void* extraData, int recursionCount) {
|
const glm::vec3& point, void* extraData, int recursionCount) {
|
||||||
|
|
||||||
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
||||||
static QString repeatedMessage
|
HIFI_FCDEBUG(octree(), "Octree::recurseElementWithOperationDistanceSorted() reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(
|
|
||||||
"Octree::recurseElementWithOperationDistanceSorted\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
|
||||||
|
|
||||||
qCDebug(octree) << "Octree::recurseElementWithOperationDistanceSorted() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,11 +203,7 @@ void Octree::recurseTreeWithOperator(RecurseOctreeOperator* operatorObject) {
|
||||||
bool Octree::recurseElementWithOperator(const OctreeElementPointer& element,
|
bool Octree::recurseElementWithOperator(const OctreeElementPointer& element,
|
||||||
RecurseOctreeOperator* operatorObject, int recursionCount) {
|
RecurseOctreeOperator* operatorObject, int recursionCount) {
|
||||||
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
||||||
static QString repeatedMessage
|
HIFI_FCDEBUG(octree(), "Octree::recurseElementWithOperator() reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(
|
|
||||||
"Octree::recurseElementWithOperator\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
|
||||||
|
|
||||||
qCDebug(octree) << "Octree::recurseElementWithOperator() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,11 +269,7 @@ OctreeElementPointer Octree::createMissingElement(const OctreeElementPointer& la
|
||||||
const unsigned char* codeToReach, int recursionCount) {
|
const unsigned char* codeToReach, int recursionCount) {
|
||||||
|
|
||||||
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
||||||
static QString repeatedMessage
|
HIFI_FCDEBUG(octree(), "Octree::createMissingElement() reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(
|
|
||||||
"Octree::createMissingElement\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
|
||||||
|
|
||||||
qCDebug(octree) << "Octree::createMissingElement() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
|
|
||||||
return lastParentElement;
|
return lastParentElement;
|
||||||
}
|
}
|
||||||
int indexOfNewChild = branchIndexWithDescendant(lastParentElement->getOctalCode(), codeToReach);
|
int indexOfNewChild = branchIndexWithDescendant(lastParentElement->getOctalCode(), codeToReach);
|
||||||
|
@ -446,16 +426,9 @@ void Octree::readBitstreamToTree(const unsigned char * bitstream, uint64_t buffe
|
||||||
(unsigned char *)bitstreamAt, NULL);
|
(unsigned char *)bitstreamAt, NULL);
|
||||||
int numberOfThreeBitSectionsInStream = numberOfThreeBitSectionsInCode(bitstreamAt, bufferSizeBytes);
|
int numberOfThreeBitSectionsInStream = numberOfThreeBitSectionsInCode(bitstreamAt, bufferSizeBytes);
|
||||||
if (numberOfThreeBitSectionsInStream > UNREASONABLY_DEEP_RECURSION) {
|
if (numberOfThreeBitSectionsInStream > UNREASONABLY_DEEP_RECURSION) {
|
||||||
static QString repeatedMessage
|
HIFI_FCDEBUG(octree(), "UNEXPECTED: parsing of the octal code would make UNREASONABLY_DEEP_RECURSION... "
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(
|
|
||||||
"UNEXPECTED: parsing of the octal code would make UNREASONABLY_DEEP_RECURSION... "
|
|
||||||
"numberOfThreeBitSectionsInStream: \\d+ This buffer is corrupt. Returning."
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
qCDebug(octree) << "UNEXPECTED: parsing of the octal code would make UNREASONABLY_DEEP_RECURSION... "
|
|
||||||
"numberOfThreeBitSectionsInStream:" << numberOfThreeBitSectionsInStream <<
|
"numberOfThreeBitSectionsInStream:" << numberOfThreeBitSectionsInStream <<
|
||||||
"This buffer is corrupt. Returning.";
|
"This buffer is corrupt. Returning.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -401,11 +401,7 @@ OctreeElementPointer OctreeElement::addChildAtIndex(int childIndex) {
|
||||||
bool OctreeElement::safeDeepDeleteChildAtIndex(int childIndex, int recursionCount) {
|
bool OctreeElement::safeDeepDeleteChildAtIndex(int childIndex, int recursionCount) {
|
||||||
bool deleteApproved = false;
|
bool deleteApproved = false;
|
||||||
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
||||||
static QString repeatedMessage
|
HIFI_FCDEBUG(octree(), "OctreeElement::safeDeepDeleteChildAtIndex() reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(
|
|
||||||
"OctreeElement::safeDeepDeleteChildAtIndex\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
|
||||||
|
|
||||||
qCDebug(octree) << "OctreeElement::safeDeepDeleteChildAtIndex() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
|
|
||||||
return deleteApproved;
|
return deleteApproved;
|
||||||
}
|
}
|
||||||
OctreeElementPointer childToDelete = getChildAtIndex(childIndex);
|
OctreeElementPointer childToDelete = getChildAtIndex(childIndex);
|
||||||
|
|
|
@ -636,12 +636,8 @@ void OctreeSceneStats::trackIncomingOctreePacket(ReceivedMessage& message, bool
|
||||||
const qint64 MAX_RESONABLE_FLIGHT_TIME = 200 * USECS_PER_SECOND; // 200 seconds is more than enough time for a packet to arrive
|
const qint64 MAX_RESONABLE_FLIGHT_TIME = 200 * USECS_PER_SECOND; // 200 seconds is more than enough time for a packet to arrive
|
||||||
const qint64 MIN_RESONABLE_FLIGHT_TIME = -1 * (qint64)USECS_PER_SECOND; // more than 1 second of "reverse flight time" would be unreasonable
|
const qint64 MIN_RESONABLE_FLIGHT_TIME = -1 * (qint64)USECS_PER_SECOND; // more than 1 second of "reverse flight time" would be unreasonable
|
||||||
if (flightTime > MAX_RESONABLE_FLIGHT_TIME || flightTime < MIN_RESONABLE_FLIGHT_TIME) {
|
if (flightTime > MAX_RESONABLE_FLIGHT_TIME || flightTime < MIN_RESONABLE_FLIGHT_TIME) {
|
||||||
static QString repeatedMessage
|
HIFI_FCDEBUG(octree(), "ignoring unreasonable packet... flightTime:" << flightTime
|
||||||
= LogHandler::getInstance().addRepeatedMessageRegex(
|
<< "nodeClockSkewUsec:" << nodeClockSkewUsec << "usecs");
|
||||||
"ignoring unreasonable packet... flightTime: -?\\d+ nodeClockSkewUsec: -?\\d+ usecs");
|
|
||||||
|
|
||||||
qCDebug(octree) << "ignoring unreasonable packet... flightTime:" << flightTime
|
|
||||||
<< "nodeClockSkewUsec:" << nodeClockSkewUsec << "usecs";;
|
|
||||||
return; // ignore any packets that are unreasonable
|
return; // ignore any packets that are unreasonable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ protected:
|
||||||
//
|
//
|
||||||
// (2) For locally owned simulation: we store the last values sent to the server, integrated forward over time
|
// (2) For locally owned simulation: we store the last values sent to the server, integrated forward over time
|
||||||
// according to how we think the server doing it. We calculate the error between the true local transform
|
// according to how we think the server doing it. We calculate the error between the true local transform
|
||||||
// and the remote to decide when to send another update.
|
// and the remote to decide whether to send another update or not.
|
||||||
//
|
//
|
||||||
glm::vec3 _serverPosition; // in simulation-frame (not world-frame)
|
glm::vec3 _serverPosition; // in simulation-frame (not world-frame)
|
||||||
glm::quat _serverRotation;
|
glm::quat _serverRotation;
|
||||||
|
|
|
@ -47,19 +47,22 @@ ObjectActionTractor::~ObjectActionTractor() {
|
||||||
bool ObjectActionTractor::getTarget(float deltaTimeStep, glm::quat& rotation, glm::vec3& position,
|
bool ObjectActionTractor::getTarget(float deltaTimeStep, glm::quat& rotation, glm::vec3& position,
|
||||||
glm::vec3& linearVelocity, glm::vec3& angularVelocity,
|
glm::vec3& linearVelocity, glm::vec3& angularVelocity,
|
||||||
float& linearTimeScale, float& angularTimeScale) {
|
float& linearTimeScale, float& angularTimeScale) {
|
||||||
SpatiallyNestablePointer other = getOther();
|
bool success { true };
|
||||||
|
EntityItemPointer other = std::dynamic_pointer_cast<EntityItem>(getOther());
|
||||||
withReadLock([&]{
|
withReadLock([&]{
|
||||||
linearTimeScale = _linearTimeScale;
|
linearTimeScale = _linearTimeScale;
|
||||||
angularTimeScale = _angularTimeScale;
|
angularTimeScale = _angularTimeScale;
|
||||||
|
|
||||||
if (!_otherID.isNull()) {
|
if (!_otherID.isNull()) {
|
||||||
if (other) {
|
if (other && other->isReadyToComputeShape()) {
|
||||||
rotation = _desiredRotationalTarget * other->getWorldOrientation();
|
rotation = _desiredRotationalTarget * other->getWorldOrientation();
|
||||||
position = other->getWorldOrientation() * _desiredPositionalTarget + other->getWorldPosition();
|
position = other->getWorldOrientation() * _desiredPositionalTarget + other->getWorldPosition();
|
||||||
} else {
|
} else {
|
||||||
// we should have an "other" but can't find it, so disable the tractor.
|
// we should have an "other" but can't find it, or its collision shape isn't loaded,
|
||||||
|
// so disable the tractor.
|
||||||
linearTimeScale = FLT_MAX;
|
linearTimeScale = FLT_MAX;
|
||||||
angularTimeScale = FLT_MAX;
|
angularTimeScale = FLT_MAX;
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rotation = _desiredRotationalTarget;
|
rotation = _desiredRotationalTarget;
|
||||||
|
@ -68,7 +71,7 @@ bool ObjectActionTractor::getTarget(float deltaTimeStep, glm::quat& rotation, gl
|
||||||
linearVelocity = glm::vec3();
|
linearVelocity = glm::vec3();
|
||||||
angularVelocity = glm::vec3();
|
angularVelocity = glm::vec3();
|
||||||
});
|
});
|
||||||
return true;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) {
|
bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) {
|
||||||
|
@ -122,6 +125,8 @@ bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) {
|
||||||
linearTractorCount++;
|
linearTractorCount++;
|
||||||
position += positionForAction;
|
position += positionForAction;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return false; // we don't have both entities loaded, so don't do anything
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,12 +85,11 @@ btTypedConstraint* ObjectConstraintBallSocket::getConstraint() {
|
||||||
return constraint;
|
return constraint;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString repeatedBallSocketNoRigidBody = LogHandler::getInstance().addRepeatedMessageRegex(
|
static int repeatMessageID = LogHandler::getInstance().newRepeatedMessageID();
|
||||||
"ObjectConstraintBallSocket::getConstraint -- no rigidBody.*");
|
|
||||||
|
|
||||||
btRigidBody* rigidBodyA = getRigidBody();
|
btRigidBody* rigidBodyA = getRigidBody();
|
||||||
if (!rigidBodyA) {
|
if (!rigidBodyA) {
|
||||||
qCDebug(physics) << "ObjectConstraintBallSocket::getConstraint -- no rigidBodyA";
|
HIFI_FCDEBUG_ID(physics(), repeatMessageID, "ObjectConstraintBallSocket::getConstraint -- no rigidBodyA");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +98,7 @@ btTypedConstraint* ObjectConstraintBallSocket::getConstraint() {
|
||||||
|
|
||||||
btRigidBody* rigidBodyB = getOtherRigidBody(otherEntityID);
|
btRigidBody* rigidBodyB = getOtherRigidBody(otherEntityID);
|
||||||
if (!rigidBodyB) {
|
if (!rigidBodyB) {
|
||||||
qCDebug(physics) << "ObjectConstraintBallSocket::getConstraint -- no rigidBodyB";
|
HIFI_FCDEBUG_ID(physics(), repeatMessageID, "ObjectConstraintBallSocket::getConstraint -- no rigidBodyB");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,12 +96,11 @@ btTypedConstraint* ObjectConstraintConeTwist::getConstraint() {
|
||||||
return constraint;
|
return constraint;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString repeatedConeTwistNoRigidBody = LogHandler::getInstance().addRepeatedMessageRegex(
|
static int repeatMessageID = LogHandler::getInstance().newRepeatedMessageID();
|
||||||
"ObjectConstraintConeTwist::getConstraint -- no rigidBody.*");
|
|
||||||
|
|
||||||
btRigidBody* rigidBodyA = getRigidBody();
|
btRigidBody* rigidBodyA = getRigidBody();
|
||||||
if (!rigidBodyA) {
|
if (!rigidBodyA) {
|
||||||
qCDebug(physics) << "ObjectConstraintConeTwist::getConstraint -- no rigidBodyA";
|
HIFI_FCDEBUG_ID(physics(), repeatMessageID, "ObjectConstraintConeTwist::getConstraint -- no rigidBodyA");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +129,7 @@ btTypedConstraint* ObjectConstraintConeTwist::getConstraint() {
|
||||||
|
|
||||||
btRigidBody* rigidBodyB = getOtherRigidBody(otherEntityID);
|
btRigidBody* rigidBodyB = getOtherRigidBody(otherEntityID);
|
||||||
if (!rigidBodyB) {
|
if (!rigidBodyB) {
|
||||||
qCDebug(physics) << "ObjectConstraintConeTwist::getConstraint -- no rigidBodyB";
|
HIFI_FCDEBUG_ID(physics(), repeatMessageID, "ObjectConstraintConeTwist::getConstraint -- no rigidBodyB");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,12 +95,11 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() {
|
||||||
return constraint;
|
return constraint;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString repeatedHingeNoRigidBody = LogHandler::getInstance().addRepeatedMessageRegex(
|
static int repeatMessageID = LogHandler::getInstance().newRepeatedMessageID();
|
||||||
"ObjectConstraintHinge::getConstraint -- no rigidBody.*");
|
|
||||||
|
|
||||||
btRigidBody* rigidBodyA = getRigidBody();
|
btRigidBody* rigidBodyA = getRigidBody();
|
||||||
if (!rigidBodyA) {
|
if (!rigidBodyA) {
|
||||||
qCDebug(physics) << "ObjectConstraintHinge::getConstraint -- no rigidBodyA";
|
HIFI_FCDEBUG_ID(physics(), repeatMessageID, "ObjectConstraintHinge::getConstraint -- no rigidBodyA");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +114,7 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() {
|
||||||
// This hinge is between two entities... find the other rigid body.
|
// This hinge is between two entities... find the other rigid body.
|
||||||
btRigidBody* rigidBodyB = getOtherRigidBody(otherEntityID);
|
btRigidBody* rigidBodyB = getOtherRigidBody(otherEntityID);
|
||||||
if (!rigidBodyB) {
|
if (!rigidBodyB) {
|
||||||
qCDebug(physics) << "ObjectConstraintHinge::getConstraint -- no rigidBodyB";
|
HIFI_FCDEBUG_ID(physics(), repeatMessageID, "ObjectConstraintHinge::getConstraint -- no rigidBodyB");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,12 +87,11 @@ btTypedConstraint* ObjectConstraintSlider::getConstraint() {
|
||||||
return constraint;
|
return constraint;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString repeatedSliderNoRigidBody = LogHandler::getInstance().addRepeatedMessageRegex(
|
static int repeatMessageID = LogHandler::getInstance().newRepeatedMessageID();
|
||||||
"ObjectConstraintSlider::getConstraint -- no rigidBody.*");
|
|
||||||
|
|
||||||
btRigidBody* rigidBodyA = getRigidBody();
|
btRigidBody* rigidBodyA = getRigidBody();
|
||||||
if (!rigidBodyA) {
|
if (!rigidBodyA) {
|
||||||
qCDebug(physics) << "ObjectConstraintSlider::getConstraint -- no rigidBodyA";
|
HIFI_FCDEBUG_ID(physics(), repeatMessageID, "ObjectConstraintSlider::getConstraint -- no rigidBodyA");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +120,7 @@ btTypedConstraint* ObjectConstraintSlider::getConstraint() {
|
||||||
|
|
||||||
btRigidBody* rigidBodyB = getOtherRigidBody(otherEntityID);
|
btRigidBody* rigidBodyB = getOtherRigidBody(otherEntityID);
|
||||||
if (!rigidBodyB) {
|
if (!rigidBodyB) {
|
||||||
qCDebug(physics) << "ObjectConstraintSlider::getConstraint -- no rigidBodyB";
|
HIFI_FCDEBUG_ID(physics(), repeatMessageID, "ObjectConstraintSlider::getConstraint -- no rigidBodyB");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ void PhysicalEntitySimulation::init(
|
||||||
|
|
||||||
// begin EntitySimulation overrides
|
// begin EntitySimulation overrides
|
||||||
void PhysicalEntitySimulation::updateEntitiesInternal(uint64_t now) {
|
void PhysicalEntitySimulation::updateEntitiesInternal(uint64_t now) {
|
||||||
// Do nothing here because the "internal" update the PhysicsEngine::stepSimualtion() which is done elsewhere.
|
// Do nothing here because the "internal" update the PhysicsEngine::stepSimulation() which is done elsewhere.
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) {
|
void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) {
|
||||||
|
|
|
@ -413,7 +413,7 @@ void PhysicsEngine::harvestPerformanceStats() {
|
||||||
if (QString(itr->Get_Current_Name()) == "stepSimulation") {
|
if (QString(itr->Get_Current_Name()) == "stepSimulation") {
|
||||||
itr->Enter_Child(childIndex);
|
itr->Enter_Child(childIndex);
|
||||||
StatsHarvester harvester;
|
StatsHarvester harvester;
|
||||||
harvester.recurse(itr, "step/");
|
harvester.recurse(itr, "physics/");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
itr->Next();
|
itr->Next();
|
||||||
|
|
|
@ -126,9 +126,6 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext,
|
||||||
if (defaultSkyboxAmbientTexture) {
|
if (defaultSkyboxAmbientTexture) {
|
||||||
sceneKeyLight->setAmbientSphere(defaultSkyboxAmbientTexture->getIrradiance());
|
sceneKeyLight->setAmbientSphere(defaultSkyboxAmbientTexture->getIrradiance());
|
||||||
sceneKeyLight->setAmbientMap(defaultSkyboxAmbientTexture);
|
sceneKeyLight->setAmbientMap(defaultSkyboxAmbientTexture);
|
||||||
} else {
|
|
||||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex(
|
|
||||||
"Failed to get a valid Default Skybox Ambient Texture ? probably because it couldn't be find during initialization step");
|
|
||||||
}
|
}
|
||||||
// fall through: render defaults skybox
|
// fall through: render defaults skybox
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -41,6 +41,11 @@ void render::renderItems(const RenderContextPointer& renderContext, const ItemBo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int repeatedInvalidKeyMessageID = 0;
|
||||||
|
std::once_flag messageIDFlag;
|
||||||
|
}
|
||||||
|
|
||||||
void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, const Item& item, const ShapeKey& globalKey) {
|
void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, const Item& item, const ShapeKey& globalKey) {
|
||||||
assert(item.getKey().isShape());
|
assert(item.getKey().isShape());
|
||||||
auto key = item.getShapeKey() | globalKey;
|
auto key = item.getShapeKey() | globalKey;
|
||||||
|
@ -55,9 +60,9 @@ void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, cons
|
||||||
} else if (key.hasOwnPipeline()) {
|
} else if (key.hasOwnPipeline()) {
|
||||||
item.render(args);
|
item.render(args);
|
||||||
} else {
|
} else {
|
||||||
qCDebug(renderlogging) << "Item could not be rendered with invalid key" << key;
|
std::call_once(messageIDFlag, [](int* id) { *id = LogHandler::getInstance().newRepeatedMessageID(); },
|
||||||
static QString repeatedCouldNotBeRendered = LogHandler::getInstance().addRepeatedMessageRegex(
|
&repeatedInvalidKeyMessageID);
|
||||||
"Item could not be rendered with invalid key.*");
|
HIFI_FCDEBUG_ID(renderlogging(), repeatedInvalidKeyMessageID, "Item could not be rendered with invalid key" << key);
|
||||||
}
|
}
|
||||||
args->_itemShapeKey = 0;
|
args->_itemShapeKey = 0;
|
||||||
}
|
}
|
||||||
|
@ -108,9 +113,9 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext,
|
||||||
} else if (key.hasOwnPipeline()) {
|
} else if (key.hasOwnPipeline()) {
|
||||||
ownPipelineBucket.push_back( std::make_tuple(item, key) );
|
ownPipelineBucket.push_back( std::make_tuple(item, key) );
|
||||||
} else {
|
} else {
|
||||||
static QString repeatedCouldNotBeRendered = LogHandler::getInstance().addRepeatedMessageRegex(
|
std::call_once(messageIDFlag, [](int* id) { *id = LogHandler::getInstance().newRepeatedMessageID(); },
|
||||||
"Item could not be rendered with invalid key.*");
|
&repeatedInvalidKeyMessageID);
|
||||||
qCDebug(renderlogging) << "Item could not be rendered with invalid key" << key;
|
HIFI_FCDEBUG_ID(renderlogging(), repeatedInvalidKeyMessageID, "Item could not be rendered with invalid key" << key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
|
|
||||||
QMutex LogHandler::_mutex;
|
QMutex LogHandler::_mutex(QMutex::Recursive);
|
||||||
|
|
||||||
LogHandler& LogHandler::getInstance() {
|
LogHandler& LogHandler::getInstance() {
|
||||||
static LogHandler staticInstance;
|
static LogHandler staticInstance;
|
||||||
|
@ -36,6 +36,9 @@ LogHandler::LogHandler() {
|
||||||
// when the log handler is first setup we should print our timezone
|
// when the log handler is first setup we should print our timezone
|
||||||
QString timezoneString = "Time zone: " + QDateTime::currentDateTime().toString("t");
|
QString timezoneString = "Time zone: " + QDateTime::currentDateTime().toString("t");
|
||||||
printMessage(LogMsgType::LogInfo, QMessageLogContext(), timezoneString);
|
printMessage(LogMsgType::LogInfo, QMessageLogContext(), timezoneString);
|
||||||
|
|
||||||
|
// make sure we setup the repeated message flusher, but do it on the LogHandler thread
|
||||||
|
QMetaObject::invokeMethod(this, "setupRepeatedMessageFlusher");
|
||||||
}
|
}
|
||||||
|
|
||||||
LogHandler::~LogHandler() {
|
LogHandler::~LogHandler() {
|
||||||
|
@ -91,58 +94,25 @@ void LogHandler::setShouldDisplayMilliseconds(bool shouldDisplayMilliseconds) {
|
||||||
|
|
||||||
void LogHandler::flushRepeatedMessages() {
|
void LogHandler::flushRepeatedMessages() {
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&_mutex);
|
||||||
for(auto& message: _repeatedMessages) {
|
|
||||||
|
|
||||||
if (message.messageCount > 1) {
|
// New repeat-suppress scheme:
|
||||||
QString repeatMessage = QString("%1 repeated log entries matching \"%2\" - Last entry: \"%3\"")
|
for (int m = 0; m < (int)_repeatedMessageRecords.size(); ++m) {
|
||||||
.arg(message.messageCount - 1)
|
int repeatCount = _repeatedMessageRecords[m].repeatCount;
|
||||||
.arg(message.regexp.pattern())
|
if (repeatCount > 1) {
|
||||||
.arg(message.lastMessage);
|
QString repeatLogMessage = QString().setNum(repeatCount) + " repeated log entries - Last entry: \""
|
||||||
|
+ _repeatedMessageRecords[m].repeatString + "\"";
|
||||||
QMessageLogContext emptyContext;
|
printMessage(LogSuppressed, QMessageLogContext(), repeatLogMessage);
|
||||||
lock.unlock();
|
_repeatedMessageRecords[m].repeatCount = 0;
|
||||||
printMessage(LogSuppressed, emptyContext, repeatMessage);
|
_repeatedMessageRecords[m].repeatString = QString();
|
||||||
lock.relock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message.messageCount = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& context, const QString& message) {
|
QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& context, const QString& message) {
|
||||||
QMutexLocker lock(&_mutex);
|
|
||||||
if (message.isEmpty()) {
|
if (message.isEmpty()) {
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
QMutexLocker lock(&_mutex);
|
||||||
if (type == LogDebug) {
|
|
||||||
// for debug messages, check if this matches any of our regexes for repeated log messages
|
|
||||||
for (auto& repeatRegex : _repeatedMessages) {
|
|
||||||
if (repeatRegex.regexp.indexIn(message) != -1) {
|
|
||||||
// If we've printed the first one then return out.
|
|
||||||
if (repeatRegex.messageCount++ == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
repeatRegex.lastMessage = message;
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == LogDebug) {
|
|
||||||
// see if this message is one we should only print once
|
|
||||||
for (auto& onceOnly : _onetimeMessages) {
|
|
||||||
if (onceOnly.regexp.indexIn(message) != -1) {
|
|
||||||
if (onceOnly.messageCount++ == 0) {
|
|
||||||
// we have a match and haven't yet printed this message.
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// We've already printed this message, don't print it again.
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// log prefix is in the following format
|
// log prefix is in the following format
|
||||||
// [TIMESTAMP] [DEBUG] [PID] [TID] [TARGET] logged string
|
// [TIMESTAMP] [DEBUG] [PID] [TID] [TARGET] logged string
|
||||||
|
@ -199,21 +169,27 @@ void LogHandler::setupRepeatedMessageFlusher() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString& LogHandler::addRepeatedMessageRegex(const QString& regexString) {
|
int LogHandler::newRepeatedMessageID() {
|
||||||
// make sure we setup the repeated message flusher, but do it on the LogHandler thread
|
|
||||||
QMetaObject::invokeMethod(this, "setupRepeatedMessageFlusher");
|
|
||||||
|
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&_mutex);
|
||||||
RepeatedMessage repeatRecord;
|
int newMessageId = _currentMessageID;
|
||||||
repeatRecord.regexp = QRegExp(regexString);
|
++_currentMessageID;
|
||||||
_repeatedMessages.push_back(repeatRecord);
|
RepeatedMessageRecord newRecord { 0, QString() };
|
||||||
return regexString;
|
_repeatedMessageRecords.push_back(newRecord);
|
||||||
|
return newMessageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString& LogHandler::addOnlyOnceMessageRegex(const QString& regexString) {
|
void LogHandler::printRepeatedMessage(int messageID, LogMsgType type, const QMessageLogContext& context,
|
||||||
|
const QString& message) {
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&_mutex);
|
||||||
OnceOnlyMessage onetimeMessage;
|
if (messageID >= _currentMessageID) {
|
||||||
onetimeMessage.regexp = QRegExp(regexString);
|
return;
|
||||||
_onetimeMessages.push_back(onetimeMessage);
|
}
|
||||||
return regexString;
|
|
||||||
|
if (_repeatedMessageRecords[messageID].repeatCount == 0) {
|
||||||
|
printMessage(type, context, message);
|
||||||
|
} else {
|
||||||
|
_repeatedMessageRecords[messageID].repeatString = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
++_repeatedMessageRecords[messageID].repeatCount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,8 @@ public:
|
||||||
/// prints various process, message type, and time information
|
/// prints various process, message type, and time information
|
||||||
static void verboseMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message);
|
static void verboseMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message);
|
||||||
|
|
||||||
const QString& addRepeatedMessageRegex(const QString& regexString);
|
int newRepeatedMessageID();
|
||||||
const QString& addOnlyOnceMessageRegex(const QString& regexString);
|
void printRepeatedMessage(int messageID, LogMsgType type, const QMessageLogContext& context, const QString &message);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void setupRepeatedMessageFlusher();
|
void setupRepeatedMessageFlusher();
|
||||||
|
@ -68,20 +68,40 @@ private:
|
||||||
bool _shouldOutputThreadID { false };
|
bool _shouldOutputThreadID { false };
|
||||||
bool _shouldDisplayMilliseconds { false };
|
bool _shouldDisplayMilliseconds { false };
|
||||||
|
|
||||||
struct RepeatedMessage {
|
int _currentMessageID { 0 };
|
||||||
QRegExp regexp;
|
struct RepeatedMessageRecord {
|
||||||
int messageCount { 0 };
|
int repeatCount;
|
||||||
QString lastMessage;
|
QString repeatString;
|
||||||
};
|
};
|
||||||
std::vector<RepeatedMessage> _repeatedMessages;
|
std::vector<RepeatedMessageRecord> _repeatedMessageRecords;
|
||||||
|
|
||||||
struct OnceOnlyMessage {
|
|
||||||
QRegExp regexp;
|
|
||||||
int messageCount { 0 };
|
|
||||||
};
|
|
||||||
std::vector<OnceOnlyMessage> _onetimeMessages;
|
|
||||||
|
|
||||||
static QMutex _mutex;
|
static QMutex _mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define HIFI_FCDEBUG(category, message) \
|
||||||
|
do { \
|
||||||
|
if (category.isDebugEnabled()) { \
|
||||||
|
static int repeatedMessageID_ = LogHandler::getInstance().newRepeatedMessageID(); \
|
||||||
|
QString logString_; \
|
||||||
|
QDebug debugStringReceiver_(&logString_); \
|
||||||
|
debugStringReceiver_ << message; \
|
||||||
|
LogHandler::getInstance().printRepeatedMessage(repeatedMessageID_, LogDebug, QMessageLogContext(__FILE__, \
|
||||||
|
__LINE__, __func__, category().categoryName()), logString_); \
|
||||||
|
} \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
#define HIFI_FDEBUG(message) HIFI_FCDEBUG((*QLoggingCategory::defaultCategory()), message)
|
||||||
|
|
||||||
|
#define HIFI_FCDEBUG_ID(category, messageID, message) \
|
||||||
|
do { \
|
||||||
|
if (category.isDebugEnabled()) { \
|
||||||
|
QString logString_; \
|
||||||
|
QDebug debugStringReceiver_(&logString_); \
|
||||||
|
debugStringReceiver_ << message; \
|
||||||
|
LogHandler::getInstance().printRepeatedMessage(messageID, LogDebug, QMessageLogContext(__FILE__, \
|
||||||
|
__LINE__, __func__, category().categoryName()), logString_); \
|
||||||
|
} \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
#define HIFI_FDEBUG_ID(messageID, message) HIFI_FCDEBUG_ID((*QLoggingCategory::defaultCategory()), messageID, message)
|
||||||
|
|
||||||
#endif // hifi_LogHandler_h
|
#endif // hifi_LogHandler_h
|
||||||
|
|
|
@ -34,17 +34,43 @@ PluginContainer::~PluginContainer() {
|
||||||
INSTANCE = nullptr;
|
INSTANCE = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MenuCache {
|
||||||
|
QSet<QString> menus;
|
||||||
|
struct Item {
|
||||||
|
QString path;
|
||||||
|
std::function<void(bool)> onClicked;
|
||||||
|
bool checkable;
|
||||||
|
bool checked;
|
||||||
|
QString groupName;
|
||||||
|
};
|
||||||
|
QHash<QString, Item> items;
|
||||||
|
std::map<QString, QActionGroup*> _exclusiveGroups;
|
||||||
|
|
||||||
void PluginContainer::addMenu(const QString& menuName) {
|
void addMenu(ui::Menu* menu, const QString& menuName) {
|
||||||
getPrimaryMenu()->addMenu(menuName);
|
if (!menu) {
|
||||||
|
menus.insert(menuName);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PluginContainer::removeMenu(const QString& menuName) {
|
flushCache(menu);
|
||||||
getPrimaryMenu()->removeMenu(menuName);
|
menu->addMenu(menuName);
|
||||||
}
|
}
|
||||||
|
|
||||||
QAction* PluginContainer::addMenuItem(PluginType type, const QString& path, const QString& name, std::function<void(bool)> onClicked, bool checkable, bool checked, const QString& groupName) {
|
void removeMenu(ui::Menu* menu, const QString& menuName) {
|
||||||
auto menu = getPrimaryMenu();
|
if (!menu) {
|
||||||
|
menus.remove(menuName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flushCache(menu);
|
||||||
|
menu->removeMenu(menuName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addMenuItem(ui::Menu* menu, const QString& path, const QString& name, std::function<void(bool)> onClicked, bool checkable, bool checked, const QString& groupName) {
|
||||||
|
if (!menu) {
|
||||||
|
items[name] = Item{ path, onClicked, checkable, checked, groupName };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flushCache(menu);
|
||||||
MenuWrapper* parentItem = menu->getMenu(path);
|
MenuWrapper* parentItem = menu->getMenu(path);
|
||||||
QAction* action = menu->addActionToQMenuAndActionHash(parentItem, name);
|
QAction* action = menu->addActionToQMenuAndActionHash(parentItem, name);
|
||||||
if (!groupName.isEmpty()) {
|
if (!groupName.isEmpty()) {
|
||||||
|
@ -62,20 +88,86 @@ QAction* PluginContainer::addMenuItem(PluginType type, const QString& path, cons
|
||||||
});
|
});
|
||||||
action->setCheckable(checkable);
|
action->setCheckable(checkable);
|
||||||
action->setChecked(checked);
|
action->setChecked(checked);
|
||||||
|
}
|
||||||
|
void removeMenuItem(ui::Menu* menu, const QString& menuName, const QString& menuItemName) {
|
||||||
|
if (!menu) {
|
||||||
|
items.remove(menuItemName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flushCache(menu);
|
||||||
|
menu->removeMenuItem(menuName, menuItemName);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isOptionChecked(ui::Menu* menu, const QString& name) {
|
||||||
|
if (!menu) {
|
||||||
|
return items.contains(name) && items[name].checked;
|
||||||
|
}
|
||||||
|
flushCache(menu);
|
||||||
|
return menu->isOptionChecked(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setIsOptionChecked(ui::Menu* menu, const QString& name, bool checked) {
|
||||||
|
if (!menu) {
|
||||||
|
if (items.contains(name)) {
|
||||||
|
items[name].checked = checked;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flushCache(menu);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void flushCache(ui::Menu* menu) {
|
||||||
|
if (!menu) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
static bool flushed = false;
|
||||||
|
if (flushed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flushed = true;
|
||||||
|
for (const auto& menuName : menus) {
|
||||||
|
addMenu(menu, menuName);
|
||||||
|
}
|
||||||
|
menus.clear();
|
||||||
|
|
||||||
|
for (const auto& menuItemName : items.keys()) {
|
||||||
|
const auto menuItem = items[menuItemName];
|
||||||
|
addMenuItem(menu, menuItem.path, menuItemName, menuItem.onClicked, menuItem.checkable, menuItem.checked, menuItem.groupName);
|
||||||
|
}
|
||||||
|
items.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static MenuCache& getMenuCache() {
|
||||||
|
static MenuCache cache;
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PluginContainer::addMenu(const QString& menuName) {
|
||||||
|
getMenuCache().addMenu(getPrimaryMenu(), menuName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PluginContainer::removeMenu(const QString& menuName) {
|
||||||
|
getMenuCache().removeMenu(getPrimaryMenu(), menuName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PluginContainer::addMenuItem(PluginType type, const QString& path, const QString& name, std::function<void(bool)> onClicked, bool checkable, bool checked, const QString& groupName) {
|
||||||
|
getMenuCache().addMenuItem(getPrimaryMenu(), path, name, onClicked, checkable, checked, groupName);
|
||||||
if (type == PluginType::DISPLAY_PLUGIN) {
|
if (type == PluginType::DISPLAY_PLUGIN) {
|
||||||
_currentDisplayPluginActions.push_back({ path, name });
|
_currentDisplayPluginActions.push_back({ path, name });
|
||||||
} else {
|
} else {
|
||||||
_currentInputPluginActions.push_back({ path, name });
|
_currentInputPluginActions.push_back({ path, name });
|
||||||
}
|
}
|
||||||
return action;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PluginContainer::removeMenuItem(const QString& menuName, const QString& menuItem) {
|
void PluginContainer::removeMenuItem(const QString& menuName, const QString& menuItem) {
|
||||||
getPrimaryMenu()->removeMenuItem(menuName, menuItem);
|
getMenuCache().removeMenuItem(getPrimaryMenu(), menuName, menuItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PluginContainer::isOptionChecked(const QString& name) {
|
bool PluginContainer::isOptionChecked(const QString& name) {
|
||||||
return getPrimaryMenu()->isOptionChecked(name);
|
return getMenuCache().isOptionChecked(getPrimaryMenu(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PluginContainer::setIsOptionChecked(const QString& path, bool checked) {
|
void PluginContainer::setIsOptionChecked(const QString& path, bool checked) {
|
||||||
|
@ -161,3 +253,7 @@ void PluginContainer::setBoolSetting(const QString& settingName, bool value) {
|
||||||
Setting::Handle<bool> settingValue(settingName, value);
|
Setting::Handle<bool> settingValue(settingName, value);
|
||||||
return settingValue.set(value);
|
return settingValue.set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PluginContainer::flushMenuUpdates() {
|
||||||
|
getMenuCache().flushCache(getPrimaryMenu());
|
||||||
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ public:
|
||||||
|
|
||||||
void addMenu(const QString& menuName);
|
void addMenu(const QString& menuName);
|
||||||
void removeMenu(const QString& menuName);
|
void removeMenu(const QString& menuName);
|
||||||
QAction* addMenuItem(PluginType pluginType, const QString& path, const QString& name, std::function<void(bool)> onClicked, bool checkable = false, bool checked = false, const QString& groupName = "");
|
void addMenuItem(PluginType pluginType, const QString& path, const QString& name, std::function<void(bool)> onClicked, bool checkable = false, bool checked = false, const QString& groupName = "");
|
||||||
void removeMenuItem(const QString& menuName, const QString& menuItem);
|
void removeMenuItem(const QString& menuName, const QString& menuItem);
|
||||||
bool isOptionChecked(const QString& name);
|
bool isOptionChecked(const QString& name);
|
||||||
void setIsOptionChecked(const QString& path, bool checked);
|
void setIsOptionChecked(const QString& path, bool checked);
|
||||||
|
@ -77,9 +77,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void flushMenuUpdates();
|
||||||
QVector<QPair<QString, QString>> _currentDisplayPluginActions;
|
QVector<QPair<QString, QString>> _currentDisplayPluginActions;
|
||||||
QVector<QPair<QString, QString>> _currentInputPluginActions;
|
QVector<QPair<QString, QString>> _currentInputPluginActions;
|
||||||
std::map<QString, QActionGroup*> _exclusiveGroups;
|
|
||||||
QRect _savedGeometry { 10, 120, 800, 600 };
|
QRect _savedGeometry { 10, 120, 800, 600 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
controllerDispatcherPlugins:true, controllerDispatcherPluginsNeedSort:true,
|
controllerDispatcherPlugins:true, controllerDispatcherPluginsNeedSort:true,
|
||||||
LEFT_HAND, RIGHT_HAND, NEAR_GRAB_PICK_RADIUS, DEFAULT_SEARCH_SPHERE_DISTANCE, DISPATCHER_PROPERTIES,
|
LEFT_HAND, RIGHT_HAND, NEAR_GRAB_PICK_RADIUS, DEFAULT_SEARCH_SPHERE_DISTANCE, DISPATCHER_PROPERTIES,
|
||||||
getGrabPointSphereOffset, HMD, MyAvatar, Messages, findHandChildEntities, Picks, PickType, Pointers, COLORS_GRAB_SEARCHING_HALF_SQUEEZE
|
getGrabPointSphereOffset, HMD, MyAvatar, Messages, findHandChildEntities, Picks, PickType, Pointers, COLORS_GRAB_SEARCHING_HALF_SQUEEZE
|
||||||
COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, TRIGGER_ON_VALUE, PointerManager
|
COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, TRIGGER_ON_VALUE, PointerManager, print
|
||||||
|
Selection, DISPATCHER_HOVERING_LIST, DISPATCHER_HOVERING_STYLE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
controllerDispatcherPlugins = {};
|
controllerDispatcherPlugins = {};
|
||||||
|
@ -123,6 +124,9 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
return getControllerWorldLocation(Controller.Standard.RightHand, true);
|
return getControllerWorldLocation(Controller.Standard.RightHand, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Selection.enableListHighlight(DISPATCHER_HOVERING_LIST, DISPATCHER_HOVERING_STYLE);
|
||||||
|
Selection.enableListToScene(DISPATCHER_HOVERING_LIST);
|
||||||
|
|
||||||
this.updateTimings = function () {
|
this.updateTimings = function () {
|
||||||
_this.intervalCount++;
|
_this.intervalCount++;
|
||||||
var thisInterval = Date.now();
|
var thisInterval = Date.now();
|
||||||
|
@ -477,6 +481,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
Controller.disableMapping(MAPPING_NAME);
|
Controller.disableMapping(MAPPING_NAME);
|
||||||
_this.pointerManager.removePointers();
|
_this.pointerManager.removePointers();
|
||||||
Pointers.removePointer(this.mouseRayPick);
|
Pointers.removePointer(this.mouseRayPick);
|
||||||
|
Selection.disableListHighlight(DISPATCHER_HOVERING_LIST);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function mouseReleaseOnOverlay(overlayID, event) {
|
function mouseReleaseOnOverlay(overlayID, event) {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
getControllerJointIndex, enableDispatcherModule, disableDispatcherModule,
|
getControllerJointIndex, enableDispatcherModule, disableDispatcherModule,
|
||||||
Messages, makeDispatcherModuleParameters, makeRunningValues, Settings, entityHasActions,
|
Messages, makeDispatcherModuleParameters, makeRunningValues, Settings, entityHasActions,
|
||||||
Vec3, Overlays, flatten, Xform, getControllerWorldLocation, ensureDynamic, entityIsCloneable,
|
Vec3, Overlays, flatten, Xform, getControllerWorldLocation, ensureDynamic, entityIsCloneable,
|
||||||
cloneEntity, DISPATCHER_PROPERTIES, TEAR_AWAY_DISTANCE, Uuid
|
cloneEntity, DISPATCHER_PROPERTIES, TEAR_AWAY_DISTANCE, Uuid, unhighlightTargetEntity
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.include("/~/system/libraries/Xform.js");
|
Script.include("/~/system/libraries/Xform.js");
|
||||||
|
@ -483,7 +483,13 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
||||||
this.dropGestureReset();
|
this.dropGestureReset();
|
||||||
this.clearEquipHaptics();
|
this.clearEquipHaptics();
|
||||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||||
|
unhighlightTargetEntity(this.targetEntityID);
|
||||||
|
var message = {
|
||||||
|
hand: this.hand,
|
||||||
|
entityID: this.targetEntityID
|
||||||
|
};
|
||||||
|
|
||||||
|
Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message));
|
||||||
var grabbedProperties = Entities.getEntityProperties(this.targetEntityID);
|
var grabbedProperties = Entities.getEntityProperties(this.targetEntityID);
|
||||||
|
|
||||||
// if an object is "equipped" and has a predefined offset, use it.
|
// if an object is "equipped" and has a predefined offset, use it.
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD,
|
PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD,
|
||||||
DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic,
|
DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic,
|
||||||
getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI
|
getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI
|
||||||
Picks, makeLaserLockInfo Xform, makeLaserParams, AddressManager, getEntityParents, Selection
|
Picks, makeLaserLockInfo Xform, makeLaserParams, AddressManager, getEntityParents, Selection, DISPATCHER_HOVERING_LIST
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
|
@ -103,6 +103,7 @@ Script.include("/~/system/libraries/Xform.js");
|
||||||
this.contextOverlayTimer = false;
|
this.contextOverlayTimer = false;
|
||||||
this.previousCollisionStatus = false;
|
this.previousCollisionStatus = false;
|
||||||
this.locked = false;
|
this.locked = false;
|
||||||
|
this.highlightedEntity = null;
|
||||||
this.reticleMinX = MARGIN;
|
this.reticleMinX = MARGIN;
|
||||||
this.reticleMaxX;
|
this.reticleMaxX;
|
||||||
this.reticleMinY = MARGIN;
|
this.reticleMinY = MARGIN;
|
||||||
|
@ -402,6 +403,9 @@ Script.include("/~/system/libraries/Xform.js");
|
||||||
if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE ||
|
if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE ||
|
||||||
this.notPointingAtEntity(controllerData) || this.targetIsNull()) {
|
this.notPointingAtEntity(controllerData) || this.targetIsNull()) {
|
||||||
this.endNearGrabAction();
|
this.endNearGrabAction();
|
||||||
|
Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity",
|
||||||
|
this.highlightedEntity);
|
||||||
|
this.highlightedEntity = null;
|
||||||
return makeRunningValues(false, [], []);
|
return makeRunningValues(false, [], []);
|
||||||
}
|
}
|
||||||
this.intersectionDistance = controllerData.rayPicks[this.hand].distance;
|
this.intersectionDistance = controllerData.rayPicks[this.hand].distance;
|
||||||
|
@ -450,7 +454,9 @@ Script.include("/~/system/libraries/Xform.js");
|
||||||
if (rayPickInfo.type === Picks.INTERSECTED_ENTITY) {
|
if (rayPickInfo.type === Picks.INTERSECTED_ENTITY) {
|
||||||
if (controllerData.triggerClicks[this.hand]) {
|
if (controllerData.triggerClicks[this.hand]) {
|
||||||
var entityID = rayPickInfo.objectID;
|
var entityID = rayPickInfo.objectID;
|
||||||
|
Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity",
|
||||||
|
this.highlightedEntity);
|
||||||
|
this.highlightedEntity = null;
|
||||||
var targetProps = Entities.getEntityProperties(entityID, [
|
var targetProps = Entities.getEntityProperties(entityID, [
|
||||||
"dynamic", "shapeType", "position",
|
"dynamic", "shapeType", "position",
|
||||||
"rotation", "dimensions", "density",
|
"rotation", "dimensions", "density",
|
||||||
|
@ -498,7 +504,30 @@ Script.include("/~/system/libraries/Xform.js");
|
||||||
this.startFarGrabAction(controllerData, targetProps);
|
this.startFarGrabAction(controllerData, targetProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!this.entityWithContextOverlay) {
|
} else {
|
||||||
|
var targetEntityID = rayPickInfo.objectID;
|
||||||
|
if (this.highlightedEntity !== targetEntityID) {
|
||||||
|
Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity",
|
||||||
|
this.highlightedEntity);
|
||||||
|
var selectionTargetProps = Entities.getEntityProperties(targetEntityID, [
|
||||||
|
"dynamic", "shapeType", "position",
|
||||||
|
"rotation", "dimensions", "density",
|
||||||
|
"userData", "locked", "type", "href"
|
||||||
|
]);
|
||||||
|
|
||||||
|
var selectionTargetObject = new TargetObject(targetEntityID, selectionTargetProps);
|
||||||
|
selectionTargetObject.parentProps = getEntityParents(selectionTargetProps);
|
||||||
|
var selectionTargetEntity = selectionTargetObject.getTargetEntity();
|
||||||
|
|
||||||
|
if (entityIsGrabbable(selectionTargetEntity.props) ||
|
||||||
|
entityIsGrabbable(selectionTargetObject.entityProps)) {
|
||||||
|
|
||||||
|
Selection.addToSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", rayPickInfo.objectID);
|
||||||
|
}
|
||||||
|
this.highlightedEntity = rayPickInfo.objectID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.entityWithContextOverlay) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
|
|
||||||
if (_this.potentialEntityWithContextOverlay !== rayPickInfo.objectID) {
|
if (_this.potentialEntityWithContextOverlay !== rayPickInfo.objectID) {
|
||||||
|
@ -532,6 +561,7 @@ Script.include("/~/system/libraries/Xform.js");
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (this.distanceRotating) {
|
} else if (this.distanceRotating) {
|
||||||
this.distanceRotate(otherFarGrabModule);
|
this.distanceRotate(otherFarGrabModule);
|
||||||
}
|
}
|
||||||
|
@ -545,6 +575,9 @@ Script.include("/~/system/libraries/Xform.js");
|
||||||
if (disableModule) {
|
if (disableModule) {
|
||||||
if (disableModule.disableModules) {
|
if (disableModule.disableModules) {
|
||||||
this.endNearGrabAction();
|
this.endNearGrabAction();
|
||||||
|
Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity",
|
||||||
|
this.highlightedEntity);
|
||||||
|
this.highlightedEntity = null;
|
||||||
return makeRunningValues(false, [], []);
|
return makeRunningValues(false, [], []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
//
|
||||||
|
// highlightNearbyEntities.js
|
||||||
|
//
|
||||||
|
// Created by Dante Ruiz 2018-4-10
|
||||||
|
// Copyright 2017 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
|
||||||
|
|
||||||
|
|
||||||
|
/* global Script, Controller, RIGHT_HAND, LEFT_HAND, MyAvatar, getGrabPointSphereOffset,
|
||||||
|
makeRunningValues, Entities, enableDispatcherModule, disableDispatcherModule, makeDispatcherModuleParameters,
|
||||||
|
PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD,
|
||||||
|
DEFAULT_SEARCH_SPHERE_DISTANCE, getGrabbableData, makeLaserParams, entityIsCloneable, Messages, print
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
|
Script.include("/~/system/libraries/controllers.js");
|
||||||
|
Script.include("/~/system/libraries/cloneEntityUtils.js");
|
||||||
|
var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
|
|
||||||
|
function differenceInArrays(firstArray, secondArray) {
|
||||||
|
var differenceArray = firstArray.filter(function(element) {
|
||||||
|
return secondArray.indexOf(element) < 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return differenceArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
function HighlightNearbyEntities(hand) {
|
||||||
|
this.hand = hand;
|
||||||
|
this.otherHand = hand === dispatcherUtils.RIGHT_HAND ? dispatcherUtils.LEFT_HAND :
|
||||||
|
dispatcherUtils.RIGHT_HAND;
|
||||||
|
this.highlightedEntities = [];
|
||||||
|
|
||||||
|
this.parameters = dispatcherUtils.makeDispatcherModuleParameters(
|
||||||
|
480,
|
||||||
|
this.hand === dispatcherUtils.RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||||
|
[],
|
||||||
|
100);
|
||||||
|
|
||||||
|
|
||||||
|
this.isGrabable = function(controllerData, props) {
|
||||||
|
var canGrabEntity = false;
|
||||||
|
if (dispatcherUtils.entityIsGrabbable(props) || entityIsCloneable(props)) {
|
||||||
|
// if we've attempted to grab a child, roll up to the root of the tree
|
||||||
|
var groupRootProps = dispatcherUtils.findGroupParent(controllerData, props);
|
||||||
|
canGrabEntity = true;
|
||||||
|
if (!dispatcherUtils.entityIsGrabbable(groupRootProps)) {
|
||||||
|
canGrabEntity = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return canGrabEntity;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.hasHyperLink = function(props) {
|
||||||
|
return (props.href !== "" && props.href !== undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.removeEntityFromHighlightList = function(entityID) {
|
||||||
|
var index = this.highlightedEntities.indexOf(entityID);
|
||||||
|
if (index > -1) {
|
||||||
|
this.highlightedEntities.splice(index, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getOtherModule = function() {
|
||||||
|
var otherModule = this.hand === dispatcherUtils.RIGHT_HAND ? leftHighlightNearbyEntities :
|
||||||
|
rightHighlightNearbyEntities;
|
||||||
|
return otherModule;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getOtherHandHighlightedEntities = function() {
|
||||||
|
return this.getOtherModule().highlightedEntities;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.highlightEntities = function(controllerData) {
|
||||||
|
var nearbyEntitiesProperties = controllerData.nearbyEntityProperties[this.hand];
|
||||||
|
var otherHandHighlightedEntities = this.getOtherHandHighlightedEntities();
|
||||||
|
var newHighlightedEntities = [];
|
||||||
|
var sensorScaleFactor = MyAvatar.sensorToWorldScale;
|
||||||
|
for (var i = 0; i < nearbyEntitiesProperties.length; i++) {
|
||||||
|
var props = nearbyEntitiesProperties[i];
|
||||||
|
if (props.distance > dispatcherUtils.NEAR_GRAB_RADIUS * sensorScaleFactor) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (this.isGrabable(controllerData, props) || this.hasHyperLink(props)) {
|
||||||
|
dispatcherUtils.highlightTargetEntity(props.id);
|
||||||
|
newHighlightedEntities.push(props.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var unhighlightEntities = differenceInArrays(this.highlightedEntities, newHighlightedEntities);
|
||||||
|
|
||||||
|
unhighlightEntities.forEach(function(entityID) {
|
||||||
|
if (otherHandHighlightedEntities.indexOf(entityID) < 0 ) {
|
||||||
|
dispatcherUtils.unhighlightTargetEntity(entityID);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.highlightedEntities = newHighlightedEntities;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.isReady = function(controllerData) {
|
||||||
|
this.highlightEntities(controllerData);
|
||||||
|
return dispatcherUtils.makeRunningValues(false, [], []);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.run = function(controllerData) {
|
||||||
|
return this.isReady(controllerData);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var handleMessage = function(channel, message, sender) {
|
||||||
|
var data;
|
||||||
|
if (sender === MyAvatar.sessionUUID) {
|
||||||
|
if (channel === 'Hifi-unhighlight-entity') {
|
||||||
|
try {
|
||||||
|
data = JSON.parse(message);
|
||||||
|
|
||||||
|
var hand = data.hand;
|
||||||
|
if (hand === dispatcherUtils.LEFT_HAND) {
|
||||||
|
leftHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID);
|
||||||
|
} else if (hand === dispatcherUtils.RIGHT_HAND) {
|
||||||
|
rightHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print("Failed to parse message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var leftHighlightNearbyEntities = new HighlightNearbyEntities(dispatcherUtils.LEFT_HAND);
|
||||||
|
var rightHighlightNearbyEntities = new HighlightNearbyEntities(dispatcherUtils.RIGHT_HAND);
|
||||||
|
|
||||||
|
dispatcherUtils.enableDispatcherModule("LeftHighlightNearbyEntities", leftHighlightNearbyEntities);
|
||||||
|
dispatcherUtils.enableDispatcherModule("RightHighlightNearbyEntities", rightHighlightNearbyEntities);
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
dispatcherUtils.disableDispatcherModule("LeftHighlightNearbyEntities");
|
||||||
|
dispatcherUtils.disableDispatcherModule("RightHighlightNearbyEntities");
|
||||||
|
}
|
||||||
|
Messages.subscribe('Hifi-unhighlight-entity');
|
||||||
|
Messages.messageReceived.connect(handleMessage);
|
||||||
|
Script.scriptEnding.connect(cleanup);
|
||||||
|
}());
|
|
@ -0,0 +1,77 @@
|
||||||
|
//
|
||||||
|
// mouseHighlightEntities.js
|
||||||
|
//
|
||||||
|
// scripts/system/controllers/controllerModules/
|
||||||
|
//
|
||||||
|
// Created by Dante Ruiz 2018-4-11
|
||||||
|
// Copyright 2017 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
|
||||||
|
//
|
||||||
|
|
||||||
|
/* jslint bitwise: true */
|
||||||
|
|
||||||
|
/* global Script, print, Entities, Picks, HMD */
|
||||||
|
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
|
|
||||||
|
function MouseHighlightEntities() {
|
||||||
|
this.highlightedEntity = null;
|
||||||
|
|
||||||
|
this.parameters = dispatcherUtils.makeDispatcherModuleParameters(
|
||||||
|
5,
|
||||||
|
["mouse"],
|
||||||
|
[],
|
||||||
|
100);
|
||||||
|
|
||||||
|
this.isReady = function(controllerData) {
|
||||||
|
if (HMD.active) {
|
||||||
|
if (this.highlightedEntity) {
|
||||||
|
dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity);
|
||||||
|
this.highlightedEntity = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var pickResult = controllerData.mouseRayPick;
|
||||||
|
if (pickResult.type === Picks.INTERSECTED_ENTITY) {
|
||||||
|
var targetEntityID = pickResult.objectID;
|
||||||
|
|
||||||
|
if (this.highlightedEntity !== targetEntityID) {
|
||||||
|
var targetProps = Entities.getEntityProperties(targetEntityID, [
|
||||||
|
"dynamic", "shapeType", "position",
|
||||||
|
"rotation", "dimensions", "density",
|
||||||
|
"userData", "locked", "type", "href"
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (this.highlightedEntity) {
|
||||||
|
dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity);
|
||||||
|
this.highlightedEntity = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dispatcherUtils.entityIsGrabbable(targetProps)) {
|
||||||
|
// highlight entity
|
||||||
|
dispatcherUtils.highlightTargetEntity(targetEntityID);
|
||||||
|
this.highlightedEntity = targetEntityID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dispatcherUtils.makeRunningValues(false, [], []);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.run = function(controllerData) {
|
||||||
|
return this.isReady(controllerData);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var mouseHighlightEntities = new MouseHighlightEntities();
|
||||||
|
dispatcherUtils.enableDispatcherModule("MouseHighlightEntities", mouseHighlightEntities);
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
dispatcherUtils.disableDispatcherModule("MouseHighlightEntities");
|
||||||
|
}
|
||||||
|
Script.scriptEnding.connect(cleanup);
|
||||||
|
})();
|
|
@ -10,7 +10,7 @@
|
||||||
propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, entityIsGrabbable,
|
propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, entityIsGrabbable,
|
||||||
Quat, Vec3, MSECS_PER_SEC, getControllerWorldLocation, makeDispatcherModuleParameters, makeRunningValues,
|
Quat, Vec3, MSECS_PER_SEC, getControllerWorldLocation, makeDispatcherModuleParameters, makeRunningValues,
|
||||||
TRIGGER_OFF_VALUE, NEAR_GRAB_RADIUS, findGroupParent, entityIsCloneable, propsAreCloneDynamic, cloneEntity,
|
TRIGGER_OFF_VALUE, NEAR_GRAB_RADIUS, findGroupParent, entityIsCloneable, propsAreCloneDynamic, cloneEntity,
|
||||||
HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE
|
HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, unhighlightTargetEntity
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
|
@ -114,6 +114,13 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
||||||
|
|
||||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||||
Entities.callEntityMethod(this.targetEntityID, "startNearGrab", args);
|
Entities.callEntityMethod(this.targetEntityID, "startNearGrab", args);
|
||||||
|
unhighlightTargetEntity(this.targetEntityID);
|
||||||
|
var message = {
|
||||||
|
hand: this.hand,
|
||||||
|
entityID: this.targetEntityID
|
||||||
|
};
|
||||||
|
|
||||||
|
Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message));
|
||||||
};
|
};
|
||||||
|
|
||||||
// this is for when the action is going to time-out
|
// this is for when the action is going to time-out
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS,
|
TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS,
|
||||||
findGroupParent, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic, HAPTIC_PULSE_STRENGTH,
|
findGroupParent, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic, HAPTIC_PULSE_STRENGTH,
|
||||||
HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, findHandChildEntities, TEAR_AWAY_DISTANCE, MSECS_PER_SEC, TEAR_AWAY_CHECK_TIME,
|
HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, findHandChildEntities, TEAR_AWAY_DISTANCE, MSECS_PER_SEC, TEAR_AWAY_CHECK_TIME,
|
||||||
TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox
|
TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Selection, DISPATCHER_HOVERING_LIST, Uuid,
|
||||||
|
highlightTargetEntity, unhighlightTargetEntity
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
|
@ -34,6 +35,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
||||||
this.autoUnequipCounter = 0;
|
this.autoUnequipCounter = 0;
|
||||||
this.lastUnexpectedChildrenCheckTime = 0;
|
this.lastUnexpectedChildrenCheckTime = 0;
|
||||||
this.robbed = false;
|
this.robbed = false;
|
||||||
|
this.highlightedEntity = null;
|
||||||
|
|
||||||
this.parameters = makeDispatcherModuleParameters(
|
this.parameters = makeDispatcherModuleParameters(
|
||||||
500,
|
500,
|
||||||
|
@ -87,7 +89,13 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
||||||
|
|
||||||
this.startNearParentingGrabEntity = function (controllerData, targetProps) {
|
this.startNearParentingGrabEntity = function (controllerData, targetProps) {
|
||||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||||
|
unhighlightTargetEntity(this.targetEntityID);
|
||||||
|
var message = {
|
||||||
|
hand: this.hand,
|
||||||
|
entityID: this.targetEntityID
|
||||||
|
};
|
||||||
|
|
||||||
|
Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message));
|
||||||
var handJointIndex;
|
var handJointIndex;
|
||||||
// if (this.ignoreIK) {
|
// if (this.ignoreIK) {
|
||||||
// handJointIndex = this.controllerJointIndex;
|
// handJointIndex = this.controllerJointIndex;
|
||||||
|
@ -158,6 +166,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
||||||
grabbedEntity: this.targetEntityID,
|
grabbedEntity: this.targetEntityID,
|
||||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||||
}));
|
}));
|
||||||
|
unhighlightTargetEntity(this.targetEntityID);
|
||||||
this.grabbing = false;
|
this.grabbing = false;
|
||||||
this.targetEntityID = null;
|
this.targetEntityID = null;
|
||||||
this.robbed = false;
|
this.robbed = false;
|
||||||
|
@ -280,6 +289,8 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
||||||
return makeRunningValues(false, [], []); // let nearActionGrabEntity handle it
|
return makeRunningValues(false, [], []); // let nearActionGrabEntity handle it
|
||||||
} else {
|
} else {
|
||||||
this.targetEntityID = targetProps.id;
|
this.targetEntityID = targetProps.id;
|
||||||
|
this.highlightedEntity = this.targetEntityID;
|
||||||
|
highlightTargetEntity(this.targetEntityID);
|
||||||
return makeRunningValues(true, [this.targetEntityID], []);
|
return makeRunningValues(true, [this.targetEntityID], []);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -300,6 +311,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
||||||
var props = controllerData.nearbyEntityPropertiesByID[this.targetEntityID];
|
var props = controllerData.nearbyEntityPropertiesByID[this.targetEntityID];
|
||||||
if (!props) {
|
if (!props) {
|
||||||
// entity was deleted
|
// entity was deleted
|
||||||
|
unhighlightTargetEntity(this.targetEntityID);
|
||||||
this.grabbing = false;
|
this.grabbing = false;
|
||||||
this.targetEntityID = null;
|
this.targetEntityID = null;
|
||||||
this.hapticTargetID = null;
|
this.hapticTargetID = null;
|
||||||
|
@ -321,6 +333,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
||||||
var readiness = this.isReady(controllerData);
|
var readiness = this.isReady(controllerData);
|
||||||
if (!readiness.active) {
|
if (!readiness.active) {
|
||||||
this.robbed = false;
|
this.robbed = false;
|
||||||
|
unhighlightTargetEntity(this.highlightedEntity);
|
||||||
return readiness;
|
return readiness;
|
||||||
}
|
}
|
||||||
if (controllerData.triggerClicks[this.hand] || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) {
|
if (controllerData.triggerClicks[this.hand] || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
|
|
||||||
/* global Script, Entities, MyAvatar, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, getGrabbableData,
|
/* global Script, Entities, MyAvatar, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, getGrabbableData,
|
||||||
Vec3, TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS
|
Vec3, TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS, unhighlightTargetEntity
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
|
@ -55,6 +55,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
this.startNearTrigger = function (controllerData) {
|
this.startNearTrigger = function (controllerData) {
|
||||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||||
Entities.callEntityMethod(this.targetEntityID, "startNearTrigger", args);
|
Entities.callEntityMethod(this.targetEntityID, "startNearTrigger", args);
|
||||||
|
unhighlightTargetEntity(this.targetEntityID);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.continueNearTrigger = function (controllerData) {
|
this.continueNearTrigger = function (controllerData) {
|
||||||
|
|
|
@ -32,7 +32,9 @@ var CONTOLLER_SCRIPTS = [
|
||||||
"controllerModules/hudOverlayPointer.js",
|
"controllerModules/hudOverlayPointer.js",
|
||||||
"controllerModules/mouseHMD.js",
|
"controllerModules/mouseHMD.js",
|
||||||
"controllerModules/scaleEntity.js",
|
"controllerModules/scaleEntity.js",
|
||||||
"controllerModules/nearGrabHyperLinkEntity.js"
|
"controllerModules/highlightNearbyEntities.js",
|
||||||
|
"controllerModules/nearGrabHyperLinkEntity.js",
|
||||||
|
"controllerModules/mouseHighlightEntities.js"
|
||||||
];
|
];
|
||||||
|
|
||||||
var DEBUG_MENU_ITEM = "Debug defaultScripts.js";
|
var DEBUG_MENU_ITEM = "Debug defaultScripts.js";
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
/* global MyAvatar, Entities, Script, Camera, Vec3, Reticle, Overlays, getEntityCustomData, Messages, Quat, Controller,
|
/* global MyAvatar, Entities, Script, Camera, Vec3, Reticle, Overlays, getEntityCustomData, Messages, Quat, Controller,
|
||||||
isInEditMode, HMD entityIsGrabbable, Picks, PickType, Pointers*/
|
isInEditMode, HMD entityIsGrabbable, Picks, PickType, Pointers, unhighlightTargetEntity*/
|
||||||
|
|
||||||
|
|
||||||
(function() { // BEGIN LOCAL_SCOPE
|
(function() { // BEGIN LOCAL_SCOPE
|
||||||
|
@ -354,6 +354,7 @@ Grabber.prototype.pressEvent = function(event) {
|
||||||
|
|
||||||
Pointers.setRenderState(this.mouseRayEntities, "grabbed");
|
Pointers.setRenderState(this.mouseRayEntities, "grabbed");
|
||||||
Pointers.setLockEndUUID(this.mouseRayEntities, pickResults.objectID, false);
|
Pointers.setLockEndUUID(this.mouseRayEntities, pickResults.objectID, false);
|
||||||
|
unhighlightTargetEntity(pickResults.objectID);
|
||||||
|
|
||||||
mouse.startDrag(event);
|
mouse.startDrag(event);
|
||||||
|
|
||||||
|
|
|
@ -452,19 +452,48 @@ var toolBar = (function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handles any edit mode updates required when domains have switched
|
||||||
|
function checkEditPermissionsAndUpdate() {
|
||||||
|
if ((createButton === null) || (createButton === undefined)) {
|
||||||
|
//--EARLY EXIT--( nothing to safely update )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified());
|
||||||
|
createButton.editProperties({
|
||||||
|
icon: (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON),
|
||||||
|
captionColor: (hasRezPermissions ? "#ffffff" : "#888888"),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!hasRezPermissions && isActive) {
|
||||||
|
that.setActive(false);
|
||||||
|
tablet.gotoHomeScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function initialize() {
|
function initialize() {
|
||||||
Script.scriptEnding.connect(cleanup);
|
Script.scriptEnding.connect(cleanup);
|
||||||
Window.domainChanged.connect(function () {
|
Window.domainChanged.connect(function () {
|
||||||
|
if (isActive) {
|
||||||
|
tablet.gotoHomeScreen();
|
||||||
|
}
|
||||||
that.setActive(false);
|
that.setActive(false);
|
||||||
that.clearEntityList();
|
that.clearEntityList();
|
||||||
|
checkEditPermissionsAndUpdate();
|
||||||
});
|
});
|
||||||
|
|
||||||
Entities.canAdjustLocksChanged.connect(function (canAdjustLocks) {
|
Entities.canAdjustLocksChanged.connect(function (canAdjustLocks) {
|
||||||
if (isActive && !canAdjustLocks) {
|
if (isActive && !canAdjustLocks) {
|
||||||
that.setActive(false);
|
that.setActive(false);
|
||||||
}
|
}
|
||||||
|
checkEditPermissionsAndUpdate();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Entities.canRezChanged.connect(checkEditPermissionsAndUpdate);
|
||||||
|
Entities.canRezTmpChanged.connect(checkEditPermissionsAndUpdate);
|
||||||
|
Entities.canRezCertifiedChanged.connect(checkEditPermissionsAndUpdate);
|
||||||
|
Entities.canRezTmpCertifiedChanged.connect(checkEditPermissionsAndUpdate);
|
||||||
|
|
||||||
var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified());
|
var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified());
|
||||||
var createButtonIconRsrc = (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON);
|
var createButtonIconRsrc = (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON);
|
||||||
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
@ -850,37 +879,18 @@ function handleOverlaySelectionToolUpdates(channel, message, sender) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles any edit mode updates required when domains have switched
|
|
||||||
function handleDomainChange() {
|
|
||||||
if ( (createButton === null) || (createButton === undefined) ){
|
|
||||||
//--EARLY EXIT--( nothing to safely update )
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified());
|
|
||||||
createButton.editProperties({
|
|
||||||
icon: (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON),
|
|
||||||
captionColor: (hasRezPermissions ? "#ffffff" : "#888888"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleMessagesReceived(channel, message, sender) {
|
function handleMessagesReceived(channel, message, sender) {
|
||||||
switch( channel ){
|
switch( channel ){
|
||||||
case 'entityToolUpdates': {
|
case 'entityToolUpdates': {
|
||||||
handleOverlaySelectionToolUpdates( channel, message, sender );
|
handleOverlaySelectionToolUpdates( channel, message, sender );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'Toolbar-DomainChanged': {
|
|
||||||
handleDomainChange();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
default: {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Messages.subscribe('Toolbar-DomainChanged');
|
|
||||||
Messages.subscribe("entityToolUpdates");
|
Messages.subscribe("entityToolUpdates");
|
||||||
Messages.messageReceived.connect(handleMessagesReceived);
|
Messages.messageReceived.connect(handleMessagesReceived);
|
||||||
|
|
||||||
|
@ -1314,8 +1324,6 @@ Script.scriptEnding.connect(function () {
|
||||||
|
|
||||||
Messages.messageReceived.disconnect(handleMessagesReceived);
|
Messages.messageReceived.disconnect(handleMessagesReceived);
|
||||||
Messages.unsubscribe("entityToolUpdates");
|
Messages.unsubscribe("entityToolUpdates");
|
||||||
// Messages.unsubscribe("Toolbar-DomainChanged"); // Do not unsubscribe because the shapes.js app also subscribes and
|
|
||||||
// Messages.subscribe works script engine-wide which would mess things up if they're both run in the same engine.
|
|
||||||
createButton = null;
|
createButton = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2331,6 +2339,11 @@ var PopupMenu = function () {
|
||||||
Controller.mousePressEvent.disconnect(self.mousePressEvent);
|
Controller.mousePressEvent.disconnect(self.mousePressEvent);
|
||||||
Controller.mouseMoveEvent.disconnect(self.mouseMoveEvent);
|
Controller.mouseMoveEvent.disconnect(self.mouseMoveEvent);
|
||||||
Controller.mouseReleaseEvent.disconnect(self.mouseReleaseEvent);
|
Controller.mouseReleaseEvent.disconnect(self.mouseReleaseEvent);
|
||||||
|
|
||||||
|
Entities.canRezChanged.disconnect(checkEditPermissionsAndUpdate);
|
||||||
|
Entities.canRezTmpChanged.disconnect(checkEditPermissionsAndUpdate);
|
||||||
|
Entities.canRezCertifiedChanged.disconnect(checkEditPermissionsAndUpdate);
|
||||||
|
Entities.canRezTmpCertifiedChanged.disconnect(checkEditPermissionsAndUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.mousePressEvent.connect(self.mousePressEvent);
|
Controller.mousePressEvent.connect(self.mousePressEvent);
|
||||||
|
|
|
@ -677,7 +677,6 @@ window.onload = function () {
|
||||||
shareForUrl("p1");
|
shareForUrl("p1");
|
||||||
appendShareBar("p1", messageOptions.isLoggedIn, messageOptions.canShare, true, false, false, messageOptions.canBlast);
|
appendShareBar("p1", messageOptions.isLoggedIn, messageOptions.canShare, true, false, false, messageOptions.canBlast);
|
||||||
document.getElementById("p1").classList.remove("processingGif");
|
document.getElementById("p1").classList.remove("processingGif");
|
||||||
document.getElementById("snap-button").disabled = false;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
imageCount = message.image_data.length;
|
imageCount = message.image_data.length;
|
||||||
|
@ -685,6 +684,7 @@ window.onload = function () {
|
||||||
addImage(element, messageOptions.isLoggedIn, messageOptions.canShare, false, false, false, false, true);
|
addImage(element, messageOptions.isLoggedIn, messageOptions.canShare, false, false, false, false, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
document.getElementById("snap-button").disabled = false;
|
||||||
break;
|
break;
|
||||||
case 'captureSettings':
|
case 'captureSettings':
|
||||||
handleCaptureSetting(message.setting);
|
handleCaptureSetting(message.setting);
|
||||||
|
@ -728,10 +728,8 @@ function takeSnapshot() {
|
||||||
type: "snapshot",
|
type: "snapshot",
|
||||||
action: "takeSnapshot"
|
action: "takeSnapshot"
|
||||||
}));
|
}));
|
||||||
if (document.getElementById('stillAndGif').checked === true) {
|
|
||||||
document.getElementById("snap-button").disabled = true;
|
document.getElementById("snap-button").disabled = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function isPrintDisabled() {
|
function isPrintDisabled() {
|
||||||
var printElement = document.getElementById('print-icon');
|
var printElement = document.getElementById('print-icon');
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
|
|
||||||
/* global module, Camera, HMD, MyAvatar, controllerDispatcherPlugins:true, Quat, Vec3, Overlays, Xform,
|
/* global module, Camera, HMD, MyAvatar, controllerDispatcherPlugins:true, Quat, Vec3, Overlays, Xform,
|
||||||
|
Selection,
|
||||||
MSECS_PER_SEC:true , LEFT_HAND:true, RIGHT_HAND:true, FORBIDDEN_GRAB_TYPES:true,
|
MSECS_PER_SEC:true , LEFT_HAND:true, RIGHT_HAND:true, FORBIDDEN_GRAB_TYPES:true,
|
||||||
HAPTIC_PULSE_STRENGTH:true, HAPTIC_PULSE_DURATION:true, ZERO_VEC:true, ONE_VEC:true,
|
HAPTIC_PULSE_STRENGTH:true, HAPTIC_PULSE_DURATION:true, ZERO_VEC:true, ONE_VEC:true,
|
||||||
DEFAULT_REGISTRATION_POINT:true, INCHES_TO_METERS:true,
|
DEFAULT_REGISTRATION_POINT:true, INCHES_TO_METERS:true,
|
||||||
|
@ -22,6 +23,8 @@
|
||||||
DISPATCHER_PROPERTIES:true,
|
DISPATCHER_PROPERTIES:true,
|
||||||
HAPTIC_PULSE_STRENGTH:true,
|
HAPTIC_PULSE_STRENGTH:true,
|
||||||
HAPTIC_PULSE_DURATION:true,
|
HAPTIC_PULSE_DURATION:true,
|
||||||
|
DISPATCHER_HOVERING_LIST:true,
|
||||||
|
DISPATCHER_HOVERING_STYLE:true,
|
||||||
Entities,
|
Entities,
|
||||||
makeDispatcherModuleParameters:true,
|
makeDispatcherModuleParameters:true,
|
||||||
makeRunningValues:true,
|
makeRunningValues:true,
|
||||||
|
@ -49,7 +52,10 @@
|
||||||
TEAR_AWAY_DISTANCE:true,
|
TEAR_AWAY_DISTANCE:true,
|
||||||
TEAR_AWAY_COUNT:true,
|
TEAR_AWAY_COUNT:true,
|
||||||
TEAR_AWAY_CHECK_TIME:true,
|
TEAR_AWAY_CHECK_TIME:true,
|
||||||
distanceBetweenPointAndEntityBoundingBox:true
|
distanceBetweenPointAndEntityBoundingBox:true,
|
||||||
|
highlightTargetEntity:true,
|
||||||
|
clearHighlightedEntities:true,
|
||||||
|
unhighlightTargetEntity:true
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MSECS_PER_SEC = 1000.0;
|
MSECS_PER_SEC = 1000.0;
|
||||||
|
@ -88,6 +94,19 @@ NEAR_GRAB_RADIUS = 1.0;
|
||||||
TEAR_AWAY_DISTANCE = 0.1; // ungrab an entity if its bounding-box moves this far from the hand
|
TEAR_AWAY_DISTANCE = 0.1; // ungrab an entity if its bounding-box moves this far from the hand
|
||||||
TEAR_AWAY_COUNT = 2; // multiply by TEAR_AWAY_CHECK_TIME to know how long the item must be away
|
TEAR_AWAY_COUNT = 2; // multiply by TEAR_AWAY_CHECK_TIME to know how long the item must be away
|
||||||
TEAR_AWAY_CHECK_TIME = 0.15; // seconds, duration between checks
|
TEAR_AWAY_CHECK_TIME = 0.15; // seconds, duration between checks
|
||||||
|
DISPATCHER_HOVERING_LIST = "dispactherHoveringList";
|
||||||
|
DISPATCHER_HOVERING_STYLE = {
|
||||||
|
isOutlineSmooth: true,
|
||||||
|
outlineWidth: 0,
|
||||||
|
outlineUnoccludedColor: {red: 255, green: 128, blue: 128},
|
||||||
|
outlineUnoccludedAlpha: 0.0,
|
||||||
|
outlineOccludedColor: {red: 255, green: 128, blue: 128},
|
||||||
|
outlineOccludedAlpha:0.0,
|
||||||
|
fillUnoccludedColor: {red: 255, green: 255, blue: 255},
|
||||||
|
fillUnoccludedAlpha: 0.12,
|
||||||
|
fillOccludedColor: {red: 255, green: 255, blue: 255},
|
||||||
|
fillOccludedAlpha: 0.0
|
||||||
|
};
|
||||||
|
|
||||||
DISPATCHER_PROPERTIES = [
|
DISPATCHER_PROPERTIES = [
|
||||||
"position",
|
"position",
|
||||||
|
@ -220,6 +239,18 @@ entityIsGrabbable = function (props) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clearHighlightedEntities = function() {
|
||||||
|
Selection.clearSelectedItemsList(DISPATCHER_HOVERING_LIST);
|
||||||
|
};
|
||||||
|
|
||||||
|
highlightTargetEntity = function(entityID) {
|
||||||
|
Selection.addToSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", entityID);
|
||||||
|
};
|
||||||
|
|
||||||
|
unhighlightTargetEntity = function(entityID) {
|
||||||
|
Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", entityID);
|
||||||
|
};
|
||||||
|
|
||||||
entityIsDistanceGrabbable = function(props) {
|
entityIsDistanceGrabbable = function(props) {
|
||||||
if (!entityIsGrabbable(props)) {
|
if (!entityIsGrabbable(props)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -389,7 +420,11 @@ if (typeof module !== 'undefined') {
|
||||||
makeDispatcherModuleParameters: makeDispatcherModuleParameters,
|
makeDispatcherModuleParameters: makeDispatcherModuleParameters,
|
||||||
enableDispatcherModule: enableDispatcherModule,
|
enableDispatcherModule: enableDispatcherModule,
|
||||||
disableDispatcherModule: disableDispatcherModule,
|
disableDispatcherModule: disableDispatcherModule,
|
||||||
|
highlightTargetEntity: highlightTargetEntity,
|
||||||
|
unhighlightTargetEntity: unhighlightTargetEntity,
|
||||||
|
clearHighlightedEntities: clearHighlightedEntities,
|
||||||
makeRunningValues: makeRunningValues,
|
makeRunningValues: makeRunningValues,
|
||||||
|
findGroupParent: findGroupParent,
|
||||||
LEFT_HAND: LEFT_HAND,
|
LEFT_HAND: LEFT_HAND,
|
||||||
RIGHT_HAND: RIGHT_HAND,
|
RIGHT_HAND: RIGHT_HAND,
|
||||||
BUMPER_ON_VALUE: BUMPER_ON_VALUE,
|
BUMPER_ON_VALUE: BUMPER_ON_VALUE,
|
||||||
|
@ -400,6 +435,7 @@ if (typeof module !== 'undefined') {
|
||||||
projectOntoOverlayXYPlane: projectOntoOverlayXYPlane,
|
projectOntoOverlayXYPlane: projectOntoOverlayXYPlane,
|
||||||
projectOntoEntityXYPlane: projectOntoEntityXYPlane,
|
projectOntoEntityXYPlane: projectOntoEntityXYPlane,
|
||||||
TRIGGER_OFF_VALUE: TRIGGER_OFF_VALUE,
|
TRIGGER_OFF_VALUE: TRIGGER_OFF_VALUE,
|
||||||
TRIGGER_ON_VALUE: TRIGGER_ON_VALUE
|
TRIGGER_ON_VALUE: TRIGGER_ON_VALUE,
|
||||||
|
DISPATCHER_HOVERING_LIST: DISPATCHER_HOVERING_LIST
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,7 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
/* global HIFI_PUBLIC_BUCKET, SPACE_LOCAL, Script, SelectionManager */
|
/* global SPACE_LOCAL, SelectionManager */
|
||||||
|
|
||||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
|
||||||
|
|
||||||
SPACE_LOCAL = "local";
|
SPACE_LOCAL = "local";
|
||||||
SPACE_WORLD = "world";
|
SPACE_WORLD = "world";
|
||||||
|
@ -50,6 +48,7 @@ SelectionManager = (function() {
|
||||||
messageParsed = JSON.parse(message);
|
messageParsed = JSON.parse(message);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
print("ERROR: entitySelectionTool.handleEntitySelectionToolUpdates - got malformed message: " + message);
|
print("ERROR: entitySelectionTool.handleEntitySelectionToolUpdates - got malformed message: " + message);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (messageParsed.method === "selectEntity") {
|
if (messageParsed.method === "selectEntity") {
|
||||||
|
@ -155,6 +154,20 @@ SelectionManager = (function() {
|
||||||
that._update(true);
|
that._update(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
that.duplicateSelection = function() {
|
||||||
|
var duplicatedEntityIDs = [];
|
||||||
|
Object.keys(that.savedProperties).forEach(function(otherEntityID) {
|
||||||
|
var properties = that.savedProperties[otherEntityID];
|
||||||
|
if (!properties.locked && (!properties.clientOnly || properties.owningAvatarID === MyAvatar.sessionUUID)) {
|
||||||
|
duplicatedEntityIDs.push({
|
||||||
|
entityID: Entities.addEntity(properties),
|
||||||
|
properties: properties
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return duplicatedEntityIDs;
|
||||||
|
}
|
||||||
|
|
||||||
that._update = function(selectionUpdated) {
|
that._update = function(selectionUpdated) {
|
||||||
var properties = null;
|
var properties = null;
|
||||||
if (that.selections.length === 0) {
|
if (that.selections.length === 0) {
|
||||||
|
@ -443,7 +456,7 @@ SelectionDisplay = (function() {
|
||||||
solid: true,
|
solid: true,
|
||||||
visible: false,
|
visible: false,
|
||||||
ignoreRayIntersection: true,
|
ignoreRayIntersection: true,
|
||||||
drawInFront: true,
|
drawInFront: true
|
||||||
}
|
}
|
||||||
var handleStretchXPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
|
var handleStretchXPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel);
|
||||||
Overlays.editOverlay(handleStretchXPanel, { color : COLOR_RED });
|
Overlays.editOverlay(handleStretchXPanel, { color : COLOR_RED });
|
||||||
|
@ -749,6 +762,7 @@ SelectionDisplay = (function() {
|
||||||
} else if (overlay === handleTranslateZCylinder) {
|
} else if (overlay === handleTranslateZCylinder) {
|
||||||
return handleTranslateZCone;
|
return handleTranslateZCone;
|
||||||
}
|
}
|
||||||
|
return Uuid.NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
// FUNCTION: MOUSE MOVE EVENT
|
// FUNCTION: MOUSE MOVE EVENT
|
||||||
|
@ -1038,13 +1052,13 @@ SelectionDisplay = (function() {
|
||||||
var toCameraDistance = getDistanceToCamera(position);
|
var toCameraDistance = getDistanceToCamera(position);
|
||||||
|
|
||||||
var localRotationX = Quat.fromPitchYawRollDegrees(0, 0, -90);
|
var localRotationX = Quat.fromPitchYawRollDegrees(0, 0, -90);
|
||||||
rotationX = Quat.multiply(rotation, localRotationX);
|
var rotationX = Quat.multiply(rotation, localRotationX);
|
||||||
worldRotationX = rotationX;
|
worldRotationX = rotationX;
|
||||||
var localRotationY = Quat.fromPitchYawRollDegrees(0, 90, 0);
|
var localRotationY = Quat.fromPitchYawRollDegrees(0, 90, 0);
|
||||||
rotationY = Quat.multiply(rotation, localRotationY);
|
var rotationY = Quat.multiply(rotation, localRotationY);
|
||||||
worldRotationY = rotationY;
|
worldRotationY = rotationY;
|
||||||
var localRotationZ = Quat.fromPitchYawRollDegrees(90, 0, 0);
|
var localRotationZ = Quat.fromPitchYawRollDegrees(90, 0, 0);
|
||||||
rotationZ = Quat.multiply(rotation, localRotationZ);
|
var rotationZ = Quat.multiply(rotation, localRotationZ);
|
||||||
worldRotationZ = rotationZ;
|
worldRotationZ = rotationZ;
|
||||||
|
|
||||||
// in HMD we clamp the overlays to the bounding box for now so lasers can hit them
|
// in HMD we clamp the overlays to the bounding box for now so lasers can hit them
|
||||||
|
@ -1260,10 +1274,9 @@ SelectionDisplay = (function() {
|
||||||
dimensions: stretchPanelXDimensions
|
dimensions: stretchPanelXDimensions
|
||||||
});
|
});
|
||||||
var stretchPanelYDimensions = Vec3.subtract(scaleLTNCubePositionRotated, scaleRTFCubePositionRotated);
|
var stretchPanelYDimensions = Vec3.subtract(scaleLTNCubePositionRotated, scaleRTFCubePositionRotated);
|
||||||
var tempX = Math.abs(stretchPanelYDimensions.x);
|
|
||||||
stretchPanelYDimensions.x = Math.abs(stretchPanelYDimensions.z);
|
stretchPanelYDimensions.x = Math.abs(stretchPanelYDimensions.z);
|
||||||
stretchPanelYDimensions.y = STRETCH_PANEL_WIDTH;
|
stretchPanelYDimensions.y = STRETCH_PANEL_WIDTH;
|
||||||
stretchPanelYDimensions.z = tempX;
|
stretchPanelYDimensions.z = Math.abs(stretchPanelYDimensions.x);
|
||||||
var stretchPanelYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x:0, y:dimensions.y / 2, z:0 }));
|
var stretchPanelYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x:0, y:dimensions.y / 2, z:0 }));
|
||||||
Overlays.editOverlay(handleStretchYPanel, {
|
Overlays.editOverlay(handleStretchYPanel, {
|
||||||
position: stretchPanelYPosition,
|
position: stretchPanelYPosition,
|
||||||
|
@ -1271,9 +1284,8 @@ SelectionDisplay = (function() {
|
||||||
dimensions: stretchPanelYDimensions
|
dimensions: stretchPanelYDimensions
|
||||||
});
|
});
|
||||||
var stretchPanelZDimensions = Vec3.subtract(scaleLTNCubePositionRotated, scaleRBFCubePositionRotated);
|
var stretchPanelZDimensions = Vec3.subtract(scaleLTNCubePositionRotated, scaleRBFCubePositionRotated);
|
||||||
var tempX = Math.abs(stretchPanelZDimensions.x);
|
|
||||||
stretchPanelZDimensions.x = Math.abs(stretchPanelZDimensions.y);
|
stretchPanelZDimensions.x = Math.abs(stretchPanelZDimensions.y);
|
||||||
stretchPanelZDimensions.y = tempX;
|
stretchPanelZDimensions.y = Math.abs(stretchPanelZDimensions.x);
|
||||||
stretchPanelZDimensions.z = STRETCH_PANEL_WIDTH;
|
stretchPanelZDimensions.z = STRETCH_PANEL_WIDTH;
|
||||||
var stretchPanelZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x:0, y:0, z:dimensions.z / 2 }));
|
var stretchPanelZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x:0, y:0, z:dimensions.z / 2 }));
|
||||||
Overlays.editOverlay(handleStretchZPanel, {
|
Overlays.editOverlay(handleStretchZPanel, {
|
||||||
|
@ -1519,17 +1531,7 @@ SelectionDisplay = (function() {
|
||||||
// copy of the selected entities and move the _original_ entities, not
|
// copy of the selected entities and move the _original_ entities, not
|
||||||
// the new ones.
|
// the new ones.
|
||||||
if (event.isAlt || doClone) {
|
if (event.isAlt || doClone) {
|
||||||
duplicatedEntityIDs = [];
|
duplicatedEntityIDs = SelectionManager.duplicateSelection();
|
||||||
for (var otherEntityID in SelectionManager.savedProperties) {
|
|
||||||
var properties = SelectionManager.savedProperties[otherEntityID];
|
|
||||||
if (!properties.locked) {
|
|
||||||
var entityID = Entities.addEntity(properties);
|
|
||||||
duplicatedEntityIDs.push({
|
|
||||||
entityID: entityID,
|
|
||||||
properties: properties
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
duplicatedEntityIDs = null;
|
duplicatedEntityIDs = null;
|
||||||
}
|
}
|
||||||
|
@ -1690,17 +1692,7 @@ SelectionDisplay = (function() {
|
||||||
// copy of the selected entities and move the _original_ entities, not
|
// copy of the selected entities and move the _original_ entities, not
|
||||||
// the new ones.
|
// the new ones.
|
||||||
if (event.isAlt) {
|
if (event.isAlt) {
|
||||||
duplicatedEntityIDs = [];
|
duplicatedEntityIDs = SelectionManager.duplicateSelection();
|
||||||
for (var otherEntityID in SelectionManager.savedProperties) {
|
|
||||||
var properties = SelectionManager.savedProperties[otherEntityID];
|
|
||||||
if (!properties.locked) {
|
|
||||||
var entityID = Entities.addEntity(properties);
|
|
||||||
duplicatedEntityIDs.push({
|
|
||||||
entityID: entityID,
|
|
||||||
properties: properties
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
duplicatedEntityIDs = null;
|
duplicatedEntityIDs = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -275,7 +275,7 @@ function onMessage(message) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var POLAROID_PRINT_SOUND = SoundCache.getSound(Script.resolvePath("assets/sounds/sound-print-photo.wav"));
|
var POLAROID_PRINT_SOUND = SoundCache.getSound(Script.resourcesPath() + "sounds/snapshot/sound-print-photo.wav");
|
||||||
var POLAROID_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/alan/dev/Test/snapshot.fbx';
|
var POLAROID_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/alan/dev/Test/snapshot.fbx';
|
||||||
|
|
||||||
function printToPolaroid(image_url) {
|
function printToPolaroid(image_url) {
|
||||||
|
@ -347,7 +347,7 @@ function fillImageDataFromPrevious() {
|
||||||
story_id: previousStillSnapStoryID,
|
story_id: previousStillSnapStoryID,
|
||||||
blastButtonDisabled: previousStillSnapBlastingDisabled,
|
blastButtonDisabled: previousStillSnapBlastingDisabled,
|
||||||
hifiButtonDisabled: previousStillSnapHifiSharingDisabled,
|
hifiButtonDisabled: previousStillSnapHifiSharingDisabled,
|
||||||
errorPath: Script.resolvePath(Script.resourcesPath() + 'snapshot/img/no-image.jpg')
|
errorPath: Script.resourcesPath() + 'snapshot/img/no-image.jpg'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (previousAnimatedSnapPath !== "") {
|
if (previousAnimatedSnapPath !== "") {
|
||||||
|
@ -356,7 +356,7 @@ function fillImageDataFromPrevious() {
|
||||||
story_id: previousAnimatedSnapStoryID,
|
story_id: previousAnimatedSnapStoryID,
|
||||||
blastButtonDisabled: previousAnimatedSnapBlastingDisabled,
|
blastButtonDisabled: previousAnimatedSnapBlastingDisabled,
|
||||||
hifiButtonDisabled: previousAnimatedSnapHifiSharingDisabled,
|
hifiButtonDisabled: previousAnimatedSnapHifiSharingDisabled,
|
||||||
errorPath: Script.resolvePath(Script.resourcesPath() + 'snapshot/img/no-image.jpg')
|
errorPath: Script.resourcesPath() + 'snapshot/img/no-image.jpg'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -473,7 +473,7 @@ function takeSnapshot() {
|
||||||
Menu.setIsOptionChecked("Overlays", false);
|
Menu.setIsOptionChecked("Overlays", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var snapActivateSound = SoundCache.getSound(Script.resolvePath("../../resources/sounds/snap.wav"));
|
var snapActivateSound = SoundCache.getSound(Script.resourcesPath() + "sounds/snapshot/snap.wav");
|
||||||
|
|
||||||
// take snapshot (with no notification)
|
// take snapshot (with no notification)
|
||||||
Script.setTimeout(function () {
|
Script.setTimeout(function () {
|
||||||
|
@ -596,7 +596,7 @@ function processingGifStarted(pathStillSnapshot) {
|
||||||
snapshotOptions = {
|
snapshotOptions = {
|
||||||
containsGif: true,
|
containsGif: true,
|
||||||
processingGif: true,
|
processingGif: true,
|
||||||
loadingGifPath: Script.resolvePath(Script.resourcesPath() + 'icons/loadingDark.gif'),
|
loadingGifPath: Script.resourcesPath() + 'icons/loadingDark.gif',
|
||||||
canShare: canShare,
|
canShare: canShare,
|
||||||
isLoggedIn: isLoggedIn
|
isLoggedIn: isLoggedIn
|
||||||
};
|
};
|
||||||
|
|
296
tools/hfudt.lua
296
tools/hfudt.lua
|
@ -19,6 +19,7 @@ local f_message_part_number = ProtoField.uint32("hfudt.message_part_number", "Me
|
||||||
local f_type = ProtoField.uint8("hfudt.type", "Type", base.DEC)
|
local f_type = ProtoField.uint8("hfudt.type", "Type", base.DEC)
|
||||||
local f_version = ProtoField.uint8("hfudt.version", "Version", base.DEC)
|
local f_version = ProtoField.uint8("hfudt.version", "Version", base.DEC)
|
||||||
local f_type_text = ProtoField.string("hfudt.type_text", "TypeText")
|
local f_type_text = ProtoField.string("hfudt.type_text", "TypeText")
|
||||||
|
local f_sender_id = ProtoField.guid("hfudt.sender_id", "Sender ID", base.DEC)
|
||||||
|
|
||||||
-- create the fields for control packets in HFUDT
|
-- create the fields for control packets in HFUDT
|
||||||
local f_control_type = ProtoField.uint16("hfudt.control_type", "Control Type", base.DEC)
|
local f_control_type = ProtoField.uint16("hfudt.control_type", "Control Type", base.DEC)
|
||||||
|
@ -28,11 +29,29 @@ local f_control_sub_sequence = ProtoField.uint32("hfudt.control_sub_sequence", "
|
||||||
local f_nak_sequence_number = ProtoField.uint32("hfudt.nak_sequence_number", "NAKed Sequence Number", base.DEC)
|
local f_nak_sequence_number = ProtoField.uint32("hfudt.nak_sequence_number", "NAKed Sequence Number", base.DEC)
|
||||||
local f_nak_range_end = ProtoField.uint32("hfudt.nak_range_end", "NAK Range End", base.DEC)
|
local f_nak_range_end = ProtoField.uint32("hfudt.nak_range_end", "NAK Range End", base.DEC)
|
||||||
|
|
||||||
|
-- avatar data fields
|
||||||
|
local f_avatar_data_id = ProtoField.guid("hfudt.avatar_id", "Avatar ID", base.DEC)
|
||||||
|
local f_avatar_data_has_flags = ProtoField.string("hfudt.avatar_has_flags", "Has Flags")
|
||||||
|
local f_avatar_data_position = ProtoField.string("hfudt.avatar_data_position", "Position")
|
||||||
|
local f_avatar_data_dimensions = ProtoField.string("hfudt.avatar_data_dimensions", "Dimensions")
|
||||||
|
local f_avatar_data_offset = ProtoField.string("hfudt.avatar_data_offset", "Offset")
|
||||||
|
local f_avatar_data_look_at_position = ProtoField.string("hfudt.avatar_data_look_at_position", "Look At Position")
|
||||||
|
local f_avatar_data_audio_loudness = ProtoField.string("hfudt.avatar_data_audio_loudness", "Audio Loudness")
|
||||||
|
local f_avatar_data_additional_flags = ProtoField.string("hfudt.avatar_data_additional_flags", "Additional Flags")
|
||||||
|
local f_avatar_data_parent_id = ProtoField.guid("hfudt.avatar_data_parent_id", "Parent ID")
|
||||||
|
local f_avatar_data_parent_joint_index = ProtoField.string("hfudt.avatar_data_parent_joint_index", "Parent Joint Index")
|
||||||
|
local f_avatar_data_local_position = ProtoField.string("hfudt.avatar_data_local_position", "Local Position")
|
||||||
|
local f_avatar_data_valid_rotations = ProtoField.string("hfudt.avatar_data_valid_rotations", "Valid Rotations")
|
||||||
|
local f_avatar_data_valid_translations = ProtoField.string("hfudt.avatar_data_valid_translations", "Valid Translations")
|
||||||
|
local f_avatar_data_default_rotations = ProtoField.string("hfudt.avatar_data_default_rotations", "Valid Default")
|
||||||
|
local f_avatar_data_default_translations = ProtoField.string("hfudt.avatar_data_default_translations", "Valid Default")
|
||||||
|
|
||||||
local SEQUENCE_NUMBER_MASK = 0x07FFFFFF
|
local SEQUENCE_NUMBER_MASK = 0x07FFFFFF
|
||||||
|
|
||||||
p_hfudt.fields = {
|
p_hfudt.fields = {
|
||||||
f_length,
|
f_length,
|
||||||
f_control_bit, f_reliable_bit, f_message_bit, f_sequence_number, f_type, f_type_text, f_version,
|
f_control_bit, f_reliable_bit, f_message_bit, f_sequence_number, f_type, f_type_text, f_version,
|
||||||
|
f_sender_id, f_avatar_data_id, f_avatar_data_parent_id,
|
||||||
f_message_position, f_message_number, f_message_part_number, f_obfuscation_level,
|
f_message_position, f_message_number, f_message_part_number, f_obfuscation_level,
|
||||||
f_control_type, f_control_type_text, f_control_sub_sequence, f_ack_sequence_number, f_nak_sequence_number, f_nak_range_end,
|
f_control_type, f_control_type_text, f_control_sub_sequence, f_ack_sequence_number, f_nak_sequence_number, f_nak_range_end,
|
||||||
f_data
|
f_data
|
||||||
|
@ -261,10 +280,50 @@ function p_hfudt.dissector (buf, pinfo, root)
|
||||||
-- read the version
|
-- read the version
|
||||||
subtree:add(f_version, buf(payload_offset + 1, 1):le_uint())
|
subtree:add(f_version, buf(payload_offset + 1, 1):le_uint())
|
||||||
|
|
||||||
data_length = buf:len() - (payload_offset + 2)
|
-- read node GUID
|
||||||
|
local sender_id = buf(payload_offset + 2, 16)
|
||||||
|
subtree:add(f_sender_id, sender_id)
|
||||||
|
|
||||||
-- pull the data that is the rest of the packet
|
local i = payload_offset + 18
|
||||||
subtree:add(f_data, buf(payload_offset + 2, data_length))
|
|
||||||
|
-- skip MD6 checksum + 16 bytes
|
||||||
|
i = i + 16
|
||||||
|
|
||||||
|
-- AvatarData or BulkAvatarDataPacket
|
||||||
|
if packet_type == 6 or packet_type == 11 then
|
||||||
|
|
||||||
|
local avatar_data
|
||||||
|
if packet_type == 6 then
|
||||||
|
-- AvatarData packet
|
||||||
|
|
||||||
|
-- avatar_id is same as sender_id
|
||||||
|
subtree:add(f_avatar_data_id, sender_id)
|
||||||
|
|
||||||
|
-- uint16 sequence_number
|
||||||
|
local sequence_number = buf(i, 2):le_uint()
|
||||||
|
i = i + 2
|
||||||
|
|
||||||
|
local avatar_data_packet_len = buf:len() - i
|
||||||
|
avatar_data = decode_avatar_data_packet(buf(i, avatar_data_packet_len))
|
||||||
|
i = i + avatar_data_packet_len
|
||||||
|
|
||||||
|
add_avatar_data_subtrees(avatar_data)
|
||||||
|
|
||||||
|
else
|
||||||
|
-- BulkAvatarData packet
|
||||||
|
while i < buf:len() do
|
||||||
|
-- avatar_id is first 16 bytes
|
||||||
|
subtree:add(f_avatar_data_id, buf(i, 16))
|
||||||
|
i = i + 16
|
||||||
|
|
||||||
|
local avatar_data_packet_len = buf:len() - i
|
||||||
|
avatar_data = decode_avatar_data_packet(buf(i, avatar_data_packet_len))
|
||||||
|
i = i + avatar_data_packet_len
|
||||||
|
|
||||||
|
add_avatar_data_subtrees(avatar_data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- return the size of the header
|
-- return the size of the header
|
||||||
|
@ -272,6 +331,237 @@ function p_hfudt.dissector (buf, pinfo, root)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function add_avatar_data_subtrees(avatar_data)
|
||||||
|
if avatar_data["has_flags"] then
|
||||||
|
subtree:add(f_avatar_data_has_flags, avatar_data["has_flags"])
|
||||||
|
end
|
||||||
|
if avatar_data["position"] then
|
||||||
|
subtree:add(f_avatar_data_position, avatar_data["position"])
|
||||||
|
end
|
||||||
|
if avatar_data["dimensions"] then
|
||||||
|
subtree:add(f_avatar_data_dimensions, avatar_data["dimensions"])
|
||||||
|
end
|
||||||
|
if avatar_data["offset"] then
|
||||||
|
subtree:add(f_avatar_data_offset, avatar_data["offset"])
|
||||||
|
end
|
||||||
|
if avatar_data["look_at_position"] then
|
||||||
|
subtree:add(f_avatar_data_look_at_position, avatar_data["look_at_position"])
|
||||||
|
end
|
||||||
|
if avatar_data["audio_loudness"] then
|
||||||
|
subtree:add(f_avatar_data_audio_loudness, avatar_data["audio_loudness"])
|
||||||
|
end
|
||||||
|
if avatar_data["additional_flags"] then
|
||||||
|
subtree:add(f_avatar_data_additional_flags, avatar_data["additional_flags"])
|
||||||
|
end
|
||||||
|
if avatar_data["parent_id"] then
|
||||||
|
subtree:add(f_avatar_data_parent_id, avatar_data["parent_id"])
|
||||||
|
end
|
||||||
|
if avatar_data["parent_joint_index"] then
|
||||||
|
subtree:add(f_avatar_data_parent_joint_index, avatar_data["parent_joint_index"])
|
||||||
|
end
|
||||||
|
if avatar_data["local_position"] then
|
||||||
|
subtree:add(f_avatar_data_local_position, avatar_data["local_position"])
|
||||||
|
end
|
||||||
|
if avatar_data["valid_rotations"] then
|
||||||
|
subtree:add(f_avatar_data_valid_rotations, avatar_data["valid_rotations"])
|
||||||
|
end
|
||||||
|
if avatar_data["valid_translations"] then
|
||||||
|
subtree:add(f_avatar_data_valid_translations, avatar_data["valid_translations"])
|
||||||
|
end
|
||||||
|
if avatar_data["default_rotations"] then
|
||||||
|
subtree:add(f_avatar_data_default_rotations, avatar_data["default_rotations"])
|
||||||
|
end
|
||||||
|
if avatar_data["default_translations"] then
|
||||||
|
subtree:add(f_avatar_data_default_translations, avatar_data["default_translations"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function decode_vec3(buf)
|
||||||
|
local i = 0
|
||||||
|
local x = buf(i, 4):le_float()
|
||||||
|
i = i + 4
|
||||||
|
local y = buf(i, 4):le_float()
|
||||||
|
i = i + 4
|
||||||
|
local z = buf(i, 4):le_float()
|
||||||
|
i = i + 4
|
||||||
|
return {x, y, z}
|
||||||
|
end
|
||||||
|
|
||||||
|
function decode_validity_bits(buf, num_bits)
|
||||||
|
-- first pass, decode each bit into an array of booleans
|
||||||
|
local i = 0
|
||||||
|
local bit = 0
|
||||||
|
local booleans = {}
|
||||||
|
for n = 1, num_bits do
|
||||||
|
local value = (bit32.band(buf(i, 1):uint(), bit32.lshift(1, bit)) ~= 0)
|
||||||
|
booleans[#booleans + 1] = value
|
||||||
|
bit = bit + 1
|
||||||
|
if bit == 8 then
|
||||||
|
i = i + 1
|
||||||
|
bit = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- second pass, create a list of indices whos booleans are true
|
||||||
|
local result = {}
|
||||||
|
for n = 1, #booleans do
|
||||||
|
if booleans[n] then
|
||||||
|
result[#result + 1] = n
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function decode_avatar_data_packet(buf)
|
||||||
|
|
||||||
|
local i = 0
|
||||||
|
local result = {}
|
||||||
|
|
||||||
|
-- uint16 has_flags
|
||||||
|
local has_flags = buf(i, 2):le_uint()
|
||||||
|
i = i + 2
|
||||||
|
|
||||||
|
local has_global_position = (bit32.band(has_flags, 1) ~= 0)
|
||||||
|
local has_bounding_box = (bit32.band(has_flags, 2) ~= 0)
|
||||||
|
local has_orientation = (bit32.band(has_flags, 4) ~= 0)
|
||||||
|
local has_scale = (bit32.band(has_flags, 8) ~= 0)
|
||||||
|
local has_look_at_position = (bit32.band(has_flags, 16) ~= 0)
|
||||||
|
local has_audio_loudness = (bit32.band(has_flags, 32) ~= 0)
|
||||||
|
local has_sensor_to_world_matrix = (bit32.band(has_flags, 64) ~= 0)
|
||||||
|
local has_additional_flags = (bit32.band(has_flags, 128) ~= 0)
|
||||||
|
local has_parent_info = (bit32.band(has_flags, 256) ~= 0)
|
||||||
|
local has_local_position = (bit32.band(has_flags, 512) ~= 0)
|
||||||
|
local has_face_tracker_info = (bit32.band(has_flags, 1024) ~= 0)
|
||||||
|
local has_joint_data = (bit32.band(has_flags, 2048) ~= 0)
|
||||||
|
local has_joint_default_pose_flags = (bit32.band(has_flags, 4096) ~= 0)
|
||||||
|
|
||||||
|
result["has_flags"] = string.format("HasFlags: 0x%x", has_flags)
|
||||||
|
|
||||||
|
if has_global_position then
|
||||||
|
local position = decode_vec3(buf(i, 12))
|
||||||
|
result["position"] = string.format("Position: %.3f, %.3f, %.3f", position[1], position[2], position[3])
|
||||||
|
i = i + 12
|
||||||
|
end
|
||||||
|
|
||||||
|
if has_bounding_box then
|
||||||
|
local dimensions = decode_vec3(buf(i, 12))
|
||||||
|
i = i + 12
|
||||||
|
local offset = decode_vec3(buf(i, 12))
|
||||||
|
i = i + 12
|
||||||
|
result["dimensions"] = string.format("Dimensions: %.3f, %.3f, %.3f", dimensions[1], dimensions[2], dimensions[3])
|
||||||
|
result["offset"] = string.format("Offset: %.3f, %.3f, %.3f", offset[1], offset[2], offset[3])
|
||||||
|
end
|
||||||
|
|
||||||
|
if has_orientation then
|
||||||
|
-- TODO: orientation is hard to decode...
|
||||||
|
i = i + 6
|
||||||
|
end
|
||||||
|
|
||||||
|
if has_scale then
|
||||||
|
-- TODO: scale is hard to decode...
|
||||||
|
i = i + 2
|
||||||
|
end
|
||||||
|
|
||||||
|
if has_look_at_position then
|
||||||
|
local look_at = decode_vec3(buf(i, 12))
|
||||||
|
i = i + 12
|
||||||
|
result["look_at_position"] = string.format("Look At Position: %.3f, %.3f, %.3f", look_at[1], look_at[2], look_at[3])
|
||||||
|
end
|
||||||
|
|
||||||
|
if has_audio_loudness then
|
||||||
|
local loudness = buf(i, 1):uint()
|
||||||
|
i = i + 1
|
||||||
|
result["audio_loudness"] = string.format("Audio Loudness: %d", loudness)
|
||||||
|
end
|
||||||
|
|
||||||
|
if has_sensor_to_world_matrix then
|
||||||
|
-- TODO: sensor to world matrix is hard to decode
|
||||||
|
i = i + 20
|
||||||
|
end
|
||||||
|
|
||||||
|
if has_additional_flags then
|
||||||
|
local flags = buf(i, 1):uint()
|
||||||
|
i = i + 1
|
||||||
|
result["additional_flags"] = string.format("Additional Flags: 0x%x", flags)
|
||||||
|
end
|
||||||
|
|
||||||
|
if has_parent_info then
|
||||||
|
local parent_id = buf(i, 16)
|
||||||
|
i = i + 16
|
||||||
|
local parent_joint_index = buf(i, 2):le_int()
|
||||||
|
i = i + 2
|
||||||
|
result["parent_id"] = parent_id
|
||||||
|
result["parent_joint_index"] = string.format("Parent Joint Index: %d", parent_joint_index)
|
||||||
|
end
|
||||||
|
|
||||||
|
if has_local_position then
|
||||||
|
local local_pos = decode_vec3(buf(i, 12))
|
||||||
|
i = i + 12
|
||||||
|
result["local_position"] = string.format("Local Position: %.3f, %.3f, %.3f", local_pos[1], local_pos[2], local_pos[3])
|
||||||
|
end
|
||||||
|
|
||||||
|
if has_face_tracker_info then
|
||||||
|
local left_eye_blink = buf(i, 4):le_float()
|
||||||
|
i = i + 4
|
||||||
|
local right_eye_blink = buf(i, 4):le_float()
|
||||||
|
i = i + 4
|
||||||
|
local average_loudness = buf(i, 4):le_float()
|
||||||
|
i = i + 4
|
||||||
|
local brow_audio_lift = buf(i, 4):le_float()
|
||||||
|
i = i + 4
|
||||||
|
local num_blendshape_coefficients = buf(i, 1):uint()
|
||||||
|
i = i + 1
|
||||||
|
local blendshape_coefficients = {}
|
||||||
|
for n = 1, num_blendshape_coefficients do
|
||||||
|
blendshape_coefficients[n] = buf(i, 4):le_float()
|
||||||
|
i = i + 4
|
||||||
|
end
|
||||||
|
-- TODO: insert blendshapes into result
|
||||||
|
end
|
||||||
|
|
||||||
|
if has_joint_data then
|
||||||
|
|
||||||
|
local num_joints = buf(i, 1):uint()
|
||||||
|
i = i + 1
|
||||||
|
local num_validity_bytes = math.ceil(num_joints / 8)
|
||||||
|
|
||||||
|
local indices = decode_validity_bits(buf(i, num_validity_bytes), num_joints)
|
||||||
|
i = i + num_validity_bytes
|
||||||
|
result["valid_rotations"] = "Valid Rotations: " .. string.format("(%d/%d) {", #indices, num_joints) .. table.concat(indices, ", ") .. "}"
|
||||||
|
|
||||||
|
-- TODO: skip rotations for now
|
||||||
|
i = i + #indices * 6
|
||||||
|
|
||||||
|
indices = decode_validity_bits(buf(i, num_validity_bytes), num_joints)
|
||||||
|
i = i + num_validity_bytes
|
||||||
|
result["valid_translations"] = "Valid Translations: " .. string.format("(%d/%d) {", #indices, num_joints) .. table.concat(indices, ", ") .. "}"
|
||||||
|
|
||||||
|
-- TODO: skip translations for now
|
||||||
|
i = i + #indices * 6
|
||||||
|
|
||||||
|
-- TODO: skip hand controller data
|
||||||
|
i = i + 24
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
if has_joint_default_pose_flags then
|
||||||
|
local num_joints = buf(i, 1):uint()
|
||||||
|
i = i + 1
|
||||||
|
local num_validity_bytes = math.ceil(num_joints / 8)
|
||||||
|
|
||||||
|
local indices = decode_validity_bits(buf(i, num_validity_bytes), num_joints)
|
||||||
|
i = i + num_validity_bytes
|
||||||
|
result["default_rotations"] = "Default Rotations: " .. string.format("(%d/%d) {", #indices, num_joints) .. table.concat(indices, ", ") .. "}"
|
||||||
|
|
||||||
|
indices = decode_validity_bits(buf(i, num_validity_bytes), num_joints)
|
||||||
|
i = i + num_validity_bytes
|
||||||
|
result["default_translations"] = "Default Translations: " .. string.format("(%d/%d) {", #indices, num_joints) .. table.concat(indices, ", ") .. "}"
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
function p_hfudt.init()
|
function p_hfudt.init()
|
||||||
local udp_dissector_table = DissectorTable.get("udp.port")
|
local udp_dissector_table = DissectorTable.get("udp.port")
|
||||||
|
|
||||||
|
|
|
@ -13,5 +13,5 @@ file(TO_NATIVE_PATH ${JSDOC_WORKING_DIR} NATIVE_JSDOC_WORKING_DIR)
|
||||||
add_custom_command(TARGET ${TARGET_NAME}
|
add_custom_command(TARGET ${TARGET_NAME}
|
||||||
COMMAND ${NPM_EXECUTABLE} --no-progress install && ${JSDOC_PATH} ${NATIVE_JSDOC_WORKING_DIR} -c ${JSDOC_CONFIG_PATH} -d ${OUTPUT_DIR}
|
COMMAND ${NPM_EXECUTABLE} --no-progress install && ${JSDOC_PATH} ${NATIVE_JSDOC_WORKING_DIR} -c ${JSDOC_CONFIG_PATH} -d ${OUTPUT_DIR}
|
||||||
WORKING_DIRECTORY ${JSDOC_WORKING_DIR}
|
WORKING_DIRECTORY ${JSDOC_WORKING_DIR}
|
||||||
COMMENT "generate the JSDoc JSON for the JSConsole auto-completer"
|
COMMENT "generate the JSDoc JSON"
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue