diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index a1a2b7c1b5..ce724d7368 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -82,6 +82,9 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri } _assignmentServerSocket = HifiSockAddr(_assignmentServerHostname, assignmentServerPort, true); + if (_assignmentServerSocket.isNull()) { + qCCritical(assignment_client) << "PAGE: Couldn't resolve domain server address" << _assignmentServerHostname; + } _assignmentServerSocket.setObjectName("AssignmentServer"); nodeList->setAssignmentServerSocket(_assignmentServerSocket); @@ -183,16 +186,21 @@ void AssignmentClient::sendAssignmentRequest() { // we want to check again for the local domain-server port in case the DS has restarted quint16 localAssignmentServerPort; if (nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, localAssignmentServerPort)) { - if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { - qCDebug(assignment_client) << "Port for local assignment server read from shared memory is" - << localAssignmentServerPort; + if (localAssignmentServerPort == 0) { + qCWarning(assignment_client) << "ALERT: Server port from shared memory is 0"; + } else { + if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { + qCDebug(assignment_client) << "Port for local assignment server read from shared memory is" + << localAssignmentServerPort; - _assignmentServerSocket.setPort(localAssignmentServerPort); - nodeList->setAssignmentServerSocket(_assignmentServerSocket); + _assignmentServerSocket.setPort(localAssignmentServerPort); + nodeList->setAssignmentServerSocket(_assignmentServerSocket); + } } } else { - qCWarning(assignment_client) << "Failed to read local assignment server port from shared memory" - << "- will send assignment request to previous assignment server socket."; + qCWarning(assignment_client) << "ALERT: Failed to read local assignment server port from shared memory (" + << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY + << ")- will send assignment request to previous assignment server socket."; } } @@ -250,7 +258,7 @@ void AssignmentClient::handleCreateAssignmentPacket(QSharedPointer<ReceivedMessa // Starts an event loop, and emits workerThread->started() workerThread->start(); } else { - qCWarning(assignment_client) << "Received an assignment that could not be unpacked. Re-requesting."; + qCWarning(assignment_client) << "ALERT: Received an assignment that could not be unpacked. Re-requesting."; } } diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 6601be849f..4c7f71a7aa 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -33,7 +33,7 @@ const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor const int WAIT_FOR_CHILD_MSECS = 1000; #ifdef Q_OS_WIN -HANDLE PROCESS_GROUP = createProcessGroup(); +void* PROCESS_GROUP = createProcessGroup(); #endif AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmentClientForks, diff --git a/assignment-client/src/AssignmentFactory.cpp b/assignment-client/src/AssignmentFactory.cpp index 405039d833..ceab285763 100644 --- a/assignment-client/src/AssignmentFactory.cpp +++ b/assignment-client/src/AssignmentFactory.cpp @@ -24,7 +24,9 @@ ThreadedAssignment* AssignmentFactory::unpackAssignment(ReceivedMessage& message) { quint8 packedType; - message.peekPrimitive(&packedType); + if (message.peekPrimitive(&packedType) != sizeof(packedType)) { + return nullptr; + } Assignment::Type unpackedType = (Assignment::Type) packedType; diff --git a/assignment-client/src/entities/EntityTreeHeadlessViewer.h b/assignment-client/src/entities/EntityTreeHeadlessViewer.h index f4d5911821..a8503510e0 100644 --- a/assignment-client/src/entities/EntityTreeHeadlessViewer.h +++ b/assignment-client/src/entities/EntityTreeHeadlessViewer.h @@ -24,6 +24,9 @@ class EntitySimulation; /**jsdoc + * The <code>EntityViewer</code> API provides a headless viewer for assignment client scripts, so that they can "see" entities + * in order for them to be available in the {@link Entities} API. + * * @namespace EntityViewer * * @hifi-assignment-client diff --git a/assignment-client/src/octree/OctreeHeadlessViewer.h b/assignment-client/src/octree/OctreeHeadlessViewer.h index 67a81b1d2a..2debf2cb84 100644 --- a/assignment-client/src/octree/OctreeHeadlessViewer.h +++ b/assignment-client/src/octree/OctreeHeadlessViewer.h @@ -28,6 +28,7 @@ public: public slots: /**jsdoc + * Updates the entities currently in view. * @function EntityViewer.queryOctree */ void queryOctree(); @@ -36,26 +37,30 @@ public slots: // setters for camera attributes /**jsdoc + * Sets the position of the view frustum. * @function EntityViewer.setPosition - * @param {Vec3} position + * @param {Vec3} position - The position of the view frustum. */ void setPosition(const glm::vec3& position) { _hasViewFrustum = true; _viewFrustum.setPosition(position); } /**jsdoc + * Sets the orientation of the view frustum. * @function EntityViewer.setOrientation - * @param {Quat} orientation + * @param {Quat} orientation - The orientation of the view frustum. */ void setOrientation(const glm::quat& orientation) { _hasViewFrustum = true; _viewFrustum.setOrientation(orientation); } /**jsdoc + * Sets the radius of the center "keyhole" in the view frustum. * @function EntityViewer.setCenterRadius - * @param {number} radius + * @param {number} radius - The radius of the center "keyhole" in the view frustum. */ void setCenterRadius(float radius) { _hasViewFrustum = true; _viewFrustum.setCenterRadius(radius); } /**jsdoc + * Sets the radius of the center "keyhole" in the view frustum. * @function EntityViewer.setKeyholeRadius - * @param {number} radius + * @param {number} radius - The radius of the center "keyhole" in the view frustum. * @deprecated This function is deprecated and will be removed. Use {@link EntityViewer.setCenterRadius|setCenterRadius} * instead. */ @@ -66,33 +71,38 @@ public slots: /**jsdoc * @function EntityViewer.setVoxelSizeScale - * @param {number} sizeScale + * @param {number} sizeScale - The voxel size scale. + * @deprecated This function is deprecated and will be removed. */ void setVoxelSizeScale(float sizeScale) { _octreeQuery.setOctreeSizeScale(sizeScale) ; } /**jsdoc * @function EntityViewer.setBoundaryLevelAdjust - * @param {number} boundaryLevelAdjust + * @param {number} boundaryLevelAdjust - The boundary level adjust factor. + * @deprecated This function is deprecated and will be removed. */ void setBoundaryLevelAdjust(int boundaryLevelAdjust) { _octreeQuery.setBoundaryLevelAdjust(boundaryLevelAdjust); } /**jsdoc + * Sets the maximum number of entity packets to receive from the domain server per second. * @function EntityViewer.setMaxPacketsPerSecond - * @param {number} maxPacketsPerSecond + * @param {number} maxPacketsPerSecond - The maximum number of entity packets to receive per second. */ void setMaxPacketsPerSecond(int maxPacketsPerSecond) { _octreeQuery.setMaxQueryPacketsPerSecond(maxPacketsPerSecond); } // getters for camera attributes /**jsdoc + * Gets the position of the view frustum. * @function EntityViewer.getPosition - * @returns {Vec3} + * @returns {Vec3} The position of the view frustum. */ const glm::vec3& getPosition() const { return _viewFrustum.getPosition(); } /**jsdoc + * Gets the orientation of the view frustum. * @function EntityViewer.getOrientation - * @returns {Quat} + * @returns {Quat} The orientation of the view frustum. */ const glm::quat& getOrientation() const { return _viewFrustum.getOrientation(); } @@ -101,26 +111,30 @@ public slots: /**jsdoc * @function EntityViewer.getVoxelSizeScale - * @returns {number} + * @returns {number} The voxel size scale. + * @deprecated This function is deprecated and will be removed. */ float getVoxelSizeScale() const { return _octreeQuery.getOctreeSizeScale(); } /**jsdoc * @function EntityViewer.getBoundaryLevelAdjust - * @returns {number} + * @returns {number} The boundary level adjust factor. + * @deprecated This function is deprecated and will be removed. */ int getBoundaryLevelAdjust() const { return _octreeQuery.getBoundaryLevelAdjust(); } /**jsdoc + * Gets the maximum number of entity packets to receive from the domain server per second. * @function EntityViewer.getMaxPacketsPerSecond - * @returns {number} + * @returns {number} The maximum number of entity packets to receive per second. */ int getMaxPacketsPerSecond() const { return _octreeQuery.getMaxQueryPacketsPerSecond(); } /**jsdoc + * Gets the number of nodes in the octree. * @function EntityViewer.getOctreeElementsCount - * @returns {number} + * @returns {number} The number of nodes in the octree. */ unsigned getOctreeElementsCount() const { return _tree->getOctreeElementsCount(); } diff --git a/cmake/ports/webrtc/portfile.cmake b/cmake/ports/webrtc/portfile.cmake index 3f2fb7a6ab..b5b46723bd 100644 --- a/cmake/ports/webrtc/portfile.cmake +++ b/cmake/ports/webrtc/portfile.cmake @@ -14,9 +14,9 @@ elseif (WIN32) elseif (APPLE) vcpkg_download_distfile( WEBRTC_SOURCE_ARCHIVE - URLS https://hifi-public.s3.amazonaws.com/seth/webrtc-20190626-osx.tar.gz - SHA512 fc70cec1b5ee87395137b7090f424e2fc2300fc17d744d5ffa1cf7aa0e0f1a069a9d72ba1ad2fb4a640ebeb6c218bda24351ba0083e1ff96c4a4b5032648a9d2 - FILENAME webrtc-20190626-osx.tar.gz + URLS https://hifi-public.s3.amazonaws.com/seth/webrtc-m78-osx.tar.gz + SHA512 8b547da921cc96f5c22b4253a1c9e707971bb627898fbdb6b238ef1318c7d2512e878344885c936d4bd6a66005cc5b63dfc3fa5ddd14f17f378dcaa17b5e25df + FILENAME webrtc-m78-osx.tar.gz ) else () # else Linux desktop diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4766353eba..421741b0a2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -252,6 +252,7 @@ #if defined(Q_OS_WIN) #include <VersionHelpers.h> +#include <Windows.h> // On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU // FIXME seems to be broken. @@ -532,6 +533,11 @@ bool isDomainURL(QUrl url) { } #ifdef Q_OS_WIN +static const UINT UWM_IDENTIFY_INSTANCES = + RegisterWindowMessage("UWM_IDENTIFY_INSTANCES_{8AB82783-B74A-4258-955B-8188C22AA0D6}_" + qgetenv("USERNAME")); +static const UINT UWM_SHOW_APPLICATION = + RegisterWindowMessage("UWM_SHOW_APPLICATION_{71123FD6-3DA8-4DC1-9C27-8A12A6250CBA}_" + qgetenv("USERNAME")); + class MyNativeEventFilter : public QAbstractNativeEventFilter { public: static MyNativeEventFilter& getInstance() { @@ -4957,7 +4963,7 @@ extern "C" { CCHAR NumberOfProcessors; }; - NTSYSCALLAPI NTSTATUS NTAPI NtQuerySystemInformation( + NTSYSCALLAPI LONG NTAPI NtQuerySystemInformation( _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, _Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation, _In_ ULONG SystemInformationLength, @@ -4966,12 +4972,12 @@ extern "C" { } template <typename T> -NTSTATUS NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, T& t) { +LONG NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, T& t) { return NtQuerySystemInformation(SystemInformationClass, &t, (ULONG)sizeof(T), nullptr); } template <typename T> -NTSTATUS NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, std::vector<T>& t) { +LONG NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, std::vector<T>& t) { return NtQuerySystemInformation(SystemInformationClass, t.data(), (ULONG)(sizeof(T) * t.size()), nullptr); } diff --git a/interface/src/Application.h b/interface/src/Application.h index af2348d1e9..e3334d12d6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -91,12 +91,6 @@ namespace controller { class StateController; } -#ifdef Q_OS_WIN -static const UINT UWM_IDENTIFY_INSTANCES = - RegisterWindowMessage("UWM_IDENTIFY_INSTANCES_{8AB82783-B74A-4258-955B-8188C22AA0D6}_" + qgetenv("USERNAME")); -static const UINT UWM_SHOW_APPLICATION = - RegisterWindowMessage("UWM_SHOW_APPLICATION_{71123FD6-3DA8-4DC1-9C27-8A12A6250CBA}_" + qgetenv("USERNAME")); -#endif static const QString RUNNING_MARKER_FILENAME = "Interface.running"; static const QString SCRIPTS_SWITCH = "scripts"; diff --git a/interface/src/FancyCamera.h b/interface/src/FancyCamera.h index 0cfe147138..f7be71e053 100644 --- a/interface/src/FancyCamera.h +++ b/interface/src/FancyCamera.h @@ -20,7 +20,7 @@ class FancyCamera : public Camera { /**jsdoc * The <code>Camera</code> API provides access to the "camera" that defines your view in desktop and HMD display modes. - * The High Fidelity camera has axes <code>x</code> = right, <code>y</code> = up, </code>-z</code> = forward. + * The High Fidelity camera has axes <code>x</code> = right, <code>y</code> = up, <code>-z</code> = forward. * * @namespace Camera * diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 89fec3c812..b66bc9c1c4 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -829,7 +829,7 @@ Menu::Menu() { // Help > Release Notes action = addActionToQMenuAndActionHash(helpMenu, "Release Notes"); connect(action, &QAction::triggered, qApp, [] { - QDesktopServices::openUrl(QUrl("http://steamcommunity.com/games/390540/announcements/")); + QDesktopServices::openUrl(QUrl("https://docs.highfidelity.com/release-notes.html")); }); // Help > Report a Bug! diff --git a/interface/src/SpeechRecognizer.h b/interface/src/SpeechRecognizer.h index 7e2acdb8ac..ae35f63a35 100644 --- a/interface/src/SpeechRecognizer.h +++ b/interface/src/SpeechRecognizer.h @@ -23,6 +23,10 @@ #include <DependencyManager.h> /**jsdoc + * The <code>SpeechRecognizer</code> API provides facilities to recognize voice commands. + * <p>Speech recognition is enabled or disabled via the Developer > Scripting > Enable Speech Control API menu item or + * the {@link SpeechRecognizer.setEnabled} method.</p> + * * @namespace SpeechRecognizer * * @hifi-interface @@ -40,36 +44,86 @@ public: public slots: /**jsdoc + * Enables or disables speech recognition. * @function SpeechRecognizer.setEnabled - * @param {boolean} enabled + * @param {boolean} enabled - <code>true</code> to enable speech recognition, <code>false</code> to disable. */ void setEnabled(bool enabled); /**jsdoc + * Adds a voice command to the speech recognizer. * @function SpeechRecognizer.addCommand - * @param {string} command + * @param {string} command - The voice command to recognize. */ void addCommand(const QString& command); /**jsdoc + * Removes a voice command from the speech recognizer. * @function SpeechRecognizer.removeCommand - * @param {string} command + * @param {string} command - The voice command to stop recognizing. */ void removeCommand(const QString& command); signals: /**jsdoc + * Triggered when a voice command has been recognized. * @function SpeechRecognizer.commandRecognized - * @param {string} command + * @param {string} command - The voice command recognized. * @returns {Signal} + * @example <caption>Turn your avatar upon voice command.</caption> + * var TURN_LEFT = "turn left"; + * var TURN_RIGHT = "turn right"; + * var TURN_RATE = 0.5; + * var TURN_DURATION = 1000; // ms + * var turnRate = 0; + * + * function getTurnRate() { + * return turnRate; + * } + * + * var MAPPING_NAME = "com.highfidelity.controllers.example.speechRecognizer"; + * var mapping = Controller.newMapping(MAPPING_NAME); + * + * mapping.from(getTurnRate).to(Controller.Actions.Yaw); + * Controller.enableMapping(MAPPING_NAME); + * + * function onCommandRecognized(command) { + * print("Speech command: " + command); + * switch (command) { + * case TURN_LEFT: + * turnRate = -TURN_RATE; + * break; + * case TURN_RIGHT: + * turnRate = TURN_RATE; + * break; + * } + * Script.setTimeout(function () { + * turnRate = 0; + * }, TURN_DURATION); + * } + * + * SpeechRecognizer.addCommand(TURN_LEFT); + * SpeechRecognizer.addCommand(TURN_RIGHT); + * SpeechRecognizer.commandRecognized.connect(onCommandRecognized); + * + * Script.scriptEnding.connect(function () { + * Controller.disableMapping(MAPPING_NAME); + * SpeechRecognizer.removeCommand(TURN_LEFT); + * SpeechRecognizer.removeCommand(TURN_RIGHT); + * }); */ void commandRecognized(const QString& command); /**jsdoc + * Triggered when speech recognition is enabled or disabled. * @function SpeechRecognizer.enabledUpdated - * @param {boolean} enabled + * @param {boolean} enabled - <code>true</code> if speech recognition is enabled, <code>false</code> if it is disabled. * @returns {Signal} + * @example <caption>Report when speech recognition is enabled or disabled.</caption> + * SpeechRecognizer.enabledUpdated.connect(function (enabled) { + * print("Speech recognition: " + (enabled ? "enabled" : "disabled")); + * }); */ void enabledUpdated(bool enabled); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index de6ae526b4..6c9b62cfcf 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2175,7 +2175,7 @@ static float lookAtCostFunction(const glm::vec3& myForward, const glm::vec3& myP } void MyAvatar::computeMyLookAtTarget(const AvatarHash& hash) { - glm::vec3 myForward = getHead()->getFinalOrientationInWorldFrame() * IDENTITY_FORWARD; + glm::vec3 myForward = _lookAtYaw * IDENTITY_FORWARD; glm::vec3 myPosition = getHead()->getEyePosition(); CameraMode mode = qApp->getCamera().getMode(); if (mode == CAMERA_MODE_FIRST_PERSON) { @@ -2553,7 +2553,7 @@ void MyAvatar::clearWornAvatarEntities() { } /**jsdoc - * Information about an avatar entity. + * <p>Information about an avatar entity.</p> * <table> * <thead> * <tr><th>Property</th><th>Type</th><th>Description</th></tr> @@ -3560,7 +3560,7 @@ void MyAvatar::updateOrientation(float deltaTime) { if (faceForward || _shouldTurnToFaceCamera) { const float REORIENT_FORWARD_BLEND = 0.25f; const float REORIENT_TURN_BLEND = 0.03f; - const float DIAGONAL_TURN_BLEND = 0.02f; + const float DIAGONAL_TURN_BLEND = 0.1f; float blend = (_shouldTurnToFaceCamera ? REORIENT_TURN_BLEND : REORIENT_FORWARD_BLEND) * timeScale; if (blend > 1.0f) { blend = 1.0f; @@ -3772,7 +3772,8 @@ glm::vec3 MyAvatar::scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 rig // Desktop mode. direction = (zSpeed * forward) + (xSpeed * right); CameraMode mode = qApp->getCamera().getMode(); - if ((mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_FIRST_PERSON || mode == CAMERA_MODE_SELFIE) && zSpeed != 0.0f && xSpeed != 0.0f){ + if ((mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_FIRST_PERSON || mode == CAMERA_MODE_SELFIE) && + zSpeed != 0.0f && xSpeed != 0.0f && !isFlying()){ direction = (zSpeed * forward); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index a7ba639461..0f139ddbff 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -170,10 +170,12 @@ class MyAvatar : public Avatar { * collision. It can be a mono or stereo 16-bit WAV file running at either 24kHz or 48kHz. The latter is down-sampled * by the audio mixer, so all audio effectively plays back at a 24khz. 48kHz RAW files are also supported. * @property {number} audioListenerMode=0 - Specifies the listening position when hearing spatialized audio. Must be one - * of the following property values:<br /> - * <code>Myavatar.audioListenerModeHead</code><br /> - * <code>Myavatar.audioListenerModeCamera</code><br /> - * <code>Myavatar.audioListenerModeCustom</code> + * of the following property values: + * <ul> + * <li><code>MyAvatar.audioListenerModeHead</code></li> + * <li><code>MyAvatar.audioListenerModeCamera</code></li> + * <li><code>MyAvatar.audioListenerModeCustom</code></li> + * </ul> * @property {number} audioListenerModeHead=0 - The audio listening position is at the avatar's head. <em>Read-only.</em> * @property {number} audioListenerModeCamera=1 - The audio listening position is at the camera. <em>Read-only.</em> * @property {number} audioListenerModeCustom=2 - The audio listening position is at a the position specified by set by the @@ -182,8 +184,8 @@ class MyAvatar : public Avatar { * property value is <code>audioListenerModeCustom</code>. * @property {Quat} customListenOrientation=Quat.IDENTITY - The listening orientation used when the * <code>audioListenerMode</code> property value is <code>audioListenerModeCustom</code>. - * @property {boolean} hasScriptedBlendshapes=false - <code>true</code> to transmit blendshapes over the network.<br /> - * <strong>Note:</strong> Currently doesn't work. Use {@link MyAvatar.setForceFaceTrackerConnected} instead. + * @property {boolean} hasScriptedBlendshapes=false - <code>true</code> to transmit blendshapes over the network. + * <p><strong>Note:</strong> Currently doesn't work. Use {@link MyAvatar.setForceFaceTrackerConnected} instead.</p> * @property {boolean} hasProceduralBlinkFaceMovement=true - <code>true</code> if procedural blinking is turned on. * @property {boolean} hasProceduralEyeFaceMovement=true - <code>true</code> if procedural eye movement is turned on. * @property {boolean} hasAudioEnabledFaceMovement=true - <code>true</code> to move the mouth blendshapes with voice audio @@ -241,8 +243,8 @@ class MyAvatar : public Avatar { * @property {boolean} useAdvancedMovementControls - Returns and sets the value of the Interface setting, Settings > * Controls > Walking. Note: Setting the value has no effect unless Interface is restarted. * @property {boolean} showPlayArea - Returns and sets the value of the Interface setting, Settings > Controls > Show room - * boundaries while teleporting.<br /> - * <strong>Note:</strong> Setting the value has no effect unless Interface is restarted. + * boundaries while teleporting. + * <p><strong>Note:</strong> Setting the value has no effect unless Interface is restarted.</p> * * @property {number} yawSpeed=75 - The mouse X sensitivity value in Settings > General. <em>Read-only.</em> * @property {number} pitchSpeed=50 - The mouse Y sensitivity value in Settings > General. <em>Read-only.</em> @@ -491,9 +493,10 @@ public: * <tr><td><code>2</code></td><td>Auto</td><td>Interface detects when the user is standing or seated in the real world. * Avatar leaning is disabled when the user is sitting (i.e., avatar always recenters), and avatar leaning is enabled * when the user is standing (i.e., avatar leans, then if leans too far it recenters).</td></tr> - * <tr><td><code>3</code></td><td>DisableHMDLean</td><td>Both avatar leaning and recentering are disabled regardless of + * <tr><td><code>3</code></td><td>DisableHMDLean</td><td><p>Both avatar leaning and recentering are disabled regardless of * what the user is doing in the real world and no matter what their avatar is doing in the virtual world. Enables - * the avatar to sit on the floor when the user sits on the floor.<br /><strong>Note:</strong> Experimental.</td></tr> + * the avatar to sit on the floor when the user sits on the floor.</p> + * <p><strong>Note:</strong> Experimental.</p></td></tr> * </tbody> * </table> * @typedef {number} MyAvatar.SitStandModelType @@ -782,7 +785,7 @@ public: * additional properties specified when adding the different handlers.</p> * <p>A handler may change a value from <code>animStateDictionaryIn</code> or add different values in the * <code>animStateDictionaryOut</code> returned. Any property values set in <code>animStateDictionaryOut</code> will - * override those of the internal animation machinery.</p. + * override those of the internal animation machinery.</p> * @function MyAvatar.addAnimationStateHandler * @param {function} handler - The animation state handler function to add. * @param {Array<string>|null} propertiesList - The list of {@link MyAvatar.AnimStateDictionary|AnimStateDictionary} diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 9af1d07309..5ca4d18a45 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -36,6 +36,7 @@ #include "Profile.h" #ifdef Q_OS_WIN +#include <Windows.h> extern "C" { typedef int(__stdcall * CHECKMINSPECPROC) (); } diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index ddc1fe376c..3a7b67a8e9 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -78,17 +78,17 @@ PickFilter getPickFilter(unsigned int filter) { * @property {boolean} [enabled=false] - <code>true</code> if this pick should start enabled, <code>false</code> if it should * start disabled. Disabled picks do not update their pick results. * @property {FilterFlags} [filter=0] - The filter for this pick to use. Construct using {@link Picks} FilterFlags property - * values (e.g., <code>Picks.PICK_DOMAIN_ENTTITIES</code>) combined with <code>|</code> (bitwise OR) operators. + * values (e.g., <code>Picks.PICK_DOMAIN_ENTITIES</code>) combined with <code>|</code> (bitwise OR) operators. * @property {number} [maxDistance=0.0] - The maximum distance at which this pick will intersect. A value of <code>0.0</code> * means no maximum. * @property {Uuid} [parentID] - The ID of the parent: an avatar, an entity, or another pick. * @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, an avatar joint. - * A value of <code>0</code> means no joint.<br /> - * <em>Used only if <code>parentID</code> is specified.</em> + * A value of <code>0</code> means no joint. + * <p><em>Used only if <code>parentID</code> is specified.</em></p> * @property {string} [joint] - <code>"Mouse"</code> parents the pick to the mouse; <code>"Avatar"</code> parents the pick to * the user's avatar head; a joint name parents to the joint in the user's avatar; otherwise, the pick is "static", not - * parented to anything.<br /> - * <em>Used only if <code>parentID</code> is not specified.</em> + * parented to anything. + * <p><em>Used only if <code>parentID</code> is not specified.</em></p> * @property {Vec3} [position=Vec3.ZERO] - The offset of the ray origin from its parent if parented, otherwise the ray origin * in world coordinates. * @property {Vec3} [posOffset] - Synonym for <code>position</code>. @@ -164,7 +164,7 @@ std::shared_ptr<PickQuery> PickScriptingInterface::buildRayPick(const QVariantMa * @property {boolean} [enabled=false] - <code>true</code> if this pick should start enabled, <code>false</code> if it should * start disabled. Disabled picks do not update their pick results. * @property {number} [filter=0] - The filter for this pick to use. Construct using {@link Picks} FilterFlags property - * values (e.g., <code>Picks.PICK_DOMAIN_ENTTITIES</code>) combined with <code>|</code> (bitwise OR) operators. + * values (e.g., <code>Picks.PICK_DOMAIN_ENTITIES</code>) combined with <code>|</code> (bitwise OR) operators. * <p><strong>Note:</strong> Stylus picks do not intersect avatars or the HUD.</p> * @property {number} [maxDistance=0.0] - The maximum distance at which this pick will intersect. A value of <code>0.0</code> * means no maximum. @@ -212,17 +212,17 @@ std::shared_ptr<PickQuery> PickScriptingInterface::buildStylusPick(const QVarian * @property {boolean} [enabled=false] - <code>true</code> if this pick should start enabled, <code>false</code> if it should * start disabled. Disabled picks do not update their pick results. * @property {number} [filter=0] - The filter for this pick to use. Construct using {@link Picks} FilterFlags property - * values (e.g., <code>Picks.PICK_DOMAIN_ENTTITIES</code>) combined with <code>|</code> (bitwise OR) operators. + * values (e.g., <code>Picks.PICK_DOMAIN_ENTITIES</code>) combined with <code>|</code> (bitwise OR) operators. * @property {number} [maxDistance=0.0] - The maximum distance at which this pick will intersect. A value of <code>0.0</code> * means no maximum. * @property {Uuid} [parentID] - The ID of the parent: an avatar, an entity, or another pick. * @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, an avatar joint. - * A value of <code>0</code> means no joint.<br /> - * <em>Used only if <code>parentID</code> is specified.</em> + * A value of <code>0</code> means no joint. + * <p><em>Used only if <code>parentID</code> is specified.</em></p> * @property {string} [joint] - <code>"Mouse"</code> parents the pick to the mouse; <code>"Avatar"</code> parents the pick to * the user's avatar head; a joint name parents to the joint in the user's avatar; otherwise, the pick is "static", not * parented to anything. - * <em>Used only if <code>parentID</code> is not specified.</em> + * <p><em>Used only if <code>parentID</code> is not specified.</em></p> * @property {Vec3} [position=Vec3.ZERO] - The offset of the parabola origin from its parent if parented, otherwise the * parabola origin in world coordinates. * @property {Vec3} [posOffset] - Synonym for <code>position</code>. @@ -321,18 +321,18 @@ std::shared_ptr<PickQuery> PickScriptingInterface::buildParabolaPick(const QVari * @property {boolean} [enabled=false] - <code>true</code> if this pick should start enabled, <code>false</code> if it should * start disabled. Disabled picks do not update their pick results. * @property {FilterFlags} [filter=0] - The filter for this pick to use. Construct using {@link Picks} FilterFlags property - * values (e.g., <code>Picks.PICK_DOMAIN_ENTTITIES</code>) combined with <code>|</code> (bitwise OR) operators. + * values (e.g., <code>Picks.PICK_DOMAIN_ENTITIES</code>) combined with <code>|</code> (bitwise OR) operators. * <p><strong>Note:</strong> Collision picks do not intersect the HUD.</p> * @property {number} [maxDistance=0.0] - The maximum distance at which this pick will intersect. A value of <code>0.0</code> * means no maximum. * @property {Uuid} [parentID] - The ID of the parent: an avatar, an entity, or another pick. * @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, an avatar joint. - * A value of <code>0</code> means no joint.<br /> - * <em>Used only if <code>parentID</code> is specified.</em> + * A value of <code>0</code> means no joint. + * <p><em>Used only if <code>parentID</code> is specified.</em></p> * @property {string} [joint] - <code>"Mouse"</code> parents the pick to the mouse; <code>"Avatar"</code> parents the pick to * the user's avatar head; a joint name parents to the joint in the user's avatar; otherwise, the pick is "static", not - * parented to anything.<br /> - * <em>Used only if <code>parentID</code> is not specified.</em> + * parented to anything. + * <p><em>Used only if <code>parentID</code> is not specified.</em></p> * @property {boolean} [scaleWithParent=true] - <code>true</code> to scale the pick's dimensions and threshold according to the * scale of the parent. * @@ -344,9 +344,11 @@ std::shared_ptr<PickQuery> PickScriptingInterface::buildParabolaPick(const QVari * the collision region. The depth is in world coordinates but scales with the parent if defined. * @property {CollisionMask} [collisionGroup=8] - The type of objects the collision region collides as. Objects whose collision * masks overlap with the region's collision group are considered to be colliding with the region. - * @property {PickType} pickType - The type of pick when getting these properties from {@link Picks.getPickProperties} or {@link Picks.getPickScriptParameters}. A collision pick's type is {@link PickType.Collision}. - * @property {Vec3} baseScale - Returned from {@link Picks.getPickProperties} when the pick has a parent with varying scale (usually an avatar or an entity). - * Its value is the original scale of the parent at the moment the pick was created, and is used to rescale the pick, and/or the pointer which owns this pick, if any. + * @property {PickType} pickType - The type of pick when getting these properties from {@link Picks.getPickProperties} or + * {@link Picks.getPickScriptParameters}. A collision pick's type is {@link PickType.Collision}. + * @property {Vec3} baseScale - Returned from {@link Picks.getPickProperties} when the pick has a parent with varying scale + * (usually an avatar or an entity). Its value is the original scale of the parent at the moment the pick was created, and + * is used to rescale the pick, and/or the pointer which owns this pick, if any. */ std::shared_ptr<PickQuery> PickScriptingInterface::buildCollisionPick(const QVariantMap& propMap) { bool enabled = false; diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h index 72b28bbc47..e26b91b9a2 100644 --- a/interface/src/raypick/PickScriptingInterface.h +++ b/interface/src/raypick/PickScriptingInterface.h @@ -287,7 +287,7 @@ public slots: /**jsdoc * @function Picks.PICK_ENTITIES * @deprecated This function is deprecated and will be removed. Use the <code>Picks.PICK_DOMAIN_ENTITIES | - * Picks.PICK_AVATAR_ENTITIES</cpode> properties expression instead. + * Picks.PICK_AVATAR_ENTITIES</code> properties expression instead. * @returns {number} */ static constexpr unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); } diff --git a/interface/src/raypick/PointerScriptingInterface.h b/interface/src/raypick/PointerScriptingInterface.h index 0eed8b4741..2d2f3f6dae 100644 --- a/interface/src/raypick/PointerScriptingInterface.h +++ b/interface/src/raypick/PointerScriptingInterface.h @@ -41,7 +41,7 @@ public: * @property {Controller.Standard|Controller.Actions|function} action - The controller output or function that triggers the * events on the entity or overlay. If a function, it must return a number <code>>= 1.0</code> to start the action * and <code>< 1.0</code> to terminate the action. - * @property {string} button - Which button to trigger. + * @property {string} button - Which button to trigger: * <ul> * <li><code>"Primary"</code>, <code>"Secondary"</code>, and <code>"Tertiary"</code> cause {@link Entities} and * {@link Overlays} mouse pointer events. Other button names also cause mouse events but the <code>button</code> diff --git a/interface/src/scripting/AccountServicesScriptingInterface.h b/interface/src/scripting/AccountServicesScriptingInterface.h index b188b4e63b..3ad637d0e6 100644 --- a/interface/src/scripting/AccountServicesScriptingInterface.h +++ b/interface/src/scripting/AccountServicesScriptingInterface.h @@ -50,12 +50,14 @@ class AccountServicesScriptingInterface : public QObject { * <code>"Unknown user"</code>. <em>Read-only.</em> * @property {boolean} loggedIn - <code>true</code> if the user is logged in, otherwise <code>false</code>. * <em>Read-only.</em> - * @property {string} findableBy - The user's visibility to other users:<br /> - * <code>"none"</code> - user appears offline.<br /> - * <code>"friends"</code> - user is visible only to friends.<br /> - * <code>"connections"</code> - user is visible to friends and connections.<br /> - * <code>"all"</code> - user is visible to everyone. - * @property {string} metaverseServerURL - The metaverse server that the user is authenticated against when logged in + * @property {string} findableBy - The user's visibility to other users: + * <ul> + * <li><code>"none"</code> — user appears offline.</li> + * <li><code>"friends"</code> — user is visible only to friends.</li> + * <li><code>"connections"</code> — user is visible to friends and connections.</li> + * <li><code>"all"</code> — user is visible to everyone.</li> + * </ul> + * @property {string} metaverseServerURL - The metaverse server that the user is authenticated against when logged in * — typically <code>"https://metaverse.highfidelity.com"</code>. <em>Read-only.</em> */ @@ -160,11 +162,13 @@ signals: /**jsdoc * Triggered when the user's visibility to others changes. * @function AccountServices.findableByChanged - * @param {string} findableBy - The user's visibility to other people:<br /> - * <code>"none"</code> - user appears offline.<br /> - * <code>"friends"</code> - user is visible only to friends.<br /> - * <code>"connections"</code> - user is visible to friends and connections.<br /> - * <code>"all"</code> - user is visible to everyone. + * @param {string} findableBy - The user's visibility to other people: + * <ul> + * <li><code>"none"</code> — user appears offline.</li> + * <li><code>"friends"</code> — user is visible only to friends.</li> + * <li><code>"connections"</code> — user is visible to friends and connections.</li> + * <li><code>"all"</code> — user is visible to everyone.</li> + * </ul> * @returns {Signal} * @example <caption>Report when your visiblity changes.</caption> * AccountServices.findableByChanged.connect(function (findableBy) { diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 4fb631463e..f65791335d 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -168,7 +168,6 @@ class ScriptEngine; * <td><code>startFarTrigger</code><br /><code>continueFarTrigger</code><br /><code>stopFarTrigger</code></td> * <td>These methods are called when a user is more than 0.3m away from the entity, the entity is triggerable, and the * user starts, continues, or stops squeezing the trigger.</td> - * </td> * <td>A light switch that can be toggled on and off from a distance.</td> * </tr> * <tr> @@ -217,25 +216,25 @@ class ScriptEngine; * * @property {Controller.Actions} Actions - Predefined actions on Interface and the user's avatar. These can be used as end * points in a {@link RouteObject} mapping. A synonym for <code>Controller.Hardware.Actions</code>. - * <em>Read-only.</em><br /><br /> - * Default mappings are provided from the <code>Controller.Hardware.Keyboard</code> and <code>Controller.Standard</code> to - * actions in + * <em>Read-only.</em> + * <p>Default mappings are provided from the <code>Controller.Hardware.Keyboard</code> and <code>Controller.Standard</code> + * to actions in * <a href="https://github.com/highfidelity/hifi/blob/master/interface/resources/controllers/keyboardMouse.json"> * keyboardMouse.json</a> and * <a href="https://github.com/highfidelity/hifi/blob/master/interface/resources/controllers/standard.json"> - * standard.json</a>, respectively. + * standard.json</a>, respectively.</p> * * @property {Controller.Hardware} Hardware - Standard and hardware-specific controller and computer outputs, plus predefined * actions on Interface and the user's avatar. The outputs can be mapped to <code>Actions</code> or functions in a - * {@link RouteObject} mapping. Additionally, hardware-specific controller outputs can be mapped to <code>Standard</code> - * controller outputs. <em>Read-only.</em> + * {@link RouteObject} mapping. Additionally, hardware-specific controller outputs can be mapped to + * <code>Controller.Standard</code> controller outputs. <em>Read-only.</em> * * @property {Controller.Standard} Standard - Standard controller outputs that can be mapped to <code>Actions</code> or - * functions in a {@link RouteObject} mapping. <em>Read-only.</em><br /><br /> - * Each hardware device has a mapping from its outputs to <code>Controller.Standard</code> items, specified in a JSON file. + * functions in a {@link RouteObject} mapping. <em>Read-only.</em> + * <p>Each hardware device has a mapping from its outputs to <code>Controller.Standard</code> items, specified in a JSON file. * For example, <a href="https://github.com/highfidelity/hifi/blob/master/interface/resources/controllers/leapmotion.json"> * leapmotion.json</a> and - * <a href="https://github.com/highfidelity/hifi/blob/master/interface/resources/controllers/vive.json">vive.json</a>. + * <a href="https://github.com/highfidelity/hifi/blob/master/interface/resources/controllers/vive.json">vive.json</a>.</p> */ /// handles scripting of input controller commands from JS diff --git a/interface/src/scripting/DesktopScriptingInterface.cpp b/interface/src/scripting/DesktopScriptingInterface.cpp index 874b3fa42d..95d3bae332 100644 --- a/interface/src/scripting/DesktopScriptingInterface.cpp +++ b/interface/src/scripting/DesktopScriptingInterface.cpp @@ -31,10 +31,10 @@ * @property {InteractiveWindow.DockArea} RIGHT - Dock to the right edge of the Interface window. */ /**jsdoc - * A docking location of an <code>InteractiveWindow</code>. + * <p>A docking location of an <code>InteractiveWindow</code>.</p> * <table> * <thead> - * <tr><th>Value</th><th>Name</p><th>Description</th> + * <tr><th>Value</th><th>Name</th><th>Description</th></tr> * </thead> * <tbody> * <tr><td><code>0</code></td><td>TOP</td><td>Dock to the top edge of the Interface window.</td></tr> @@ -73,10 +73,10 @@ int DesktopScriptingInterface::getHeight() { * own separate window. */ /**jsdoc - * A display mode for an <code>InteractiveWindow</code>. + * <p>A display mode for an <code>InteractiveWindow</code>.</p> * <table> * <thead> - * <tr><th>Value</th><th>Name</p><th>Description</th> + * <tr><th>Value</th><th>Name</th><th>Description</th></tr> * </thead> * <tbody> * <tr><td><code>0</code></td><td>VIRTUAL</td><td>The window is displayed inside Interface: in the desktop window in diff --git a/interface/src/scripting/MenuScriptingInterface.h b/interface/src/scripting/MenuScriptingInterface.h index 6c2634b1de..110df8dd06 100644 --- a/interface/src/scripting/MenuScriptingInterface.h +++ b/interface/src/scripting/MenuScriptingInterface.h @@ -24,7 +24,8 @@ class MenuItemProperties; * <h3>Groupings</h3> * * <p>A "grouping" provides a way to group a set of menus or menu items together so that they can all be set visible or invisible - * as a group.</p> There is currently only one available group: <code>"Developer"</code>. This grouping can be toggled in the + * as a group.</p> + * <p>There is currently only one available group: <code>"Developer"</code>. This grouping can be toggled in the * "Settings" menu.</p> * <p>If a menu item doesn't belong to a group, it is always displayed.</p> * diff --git a/interface/src/scripting/SelectionScriptingInterface.cpp b/interface/src/scripting/SelectionScriptingInterface.cpp index 5856188868..d2147ac5cc 100644 --- a/interface/src/scripting/SelectionScriptingInterface.cpp +++ b/interface/src/scripting/SelectionScriptingInterface.cpp @@ -44,7 +44,7 @@ SelectionScriptingInterface::SelectionScriptingInterface() { } /**jsdoc - * The type of a specific item in a selection list. + * <p>The type of a specific item in a selection list.</p> * <table> * <thead> * <tr><th>Value</th><th>Description</th></tr> diff --git a/interface/src/scripting/WalletScriptingInterface.h b/interface/src/scripting/WalletScriptingInterface.h index 3ef9c7953a..e9535ceb4e 100644 --- a/interface/src/scripting/WalletScriptingInterface.h +++ b/interface/src/scripting/WalletScriptingInterface.h @@ -42,7 +42,7 @@ public: * @property {WalletScriptingInterface.WalletStatus} walletStatus - The status of the user's wallet. <em>Read-only.</em> * @property {boolean} limitedCommerce - <code>true</code> if Interface is running in limited commerce mode. In limited commerce * mode, certain Interface functionalities are disabled, e.g., users can't buy items that are not free from the Marketplace. - * The Oculus Store version of Interface runs in limited commerce mode. <em>Read-only.</em> + * The Oculus Store and Steam versions of Interface run in limited commerce mode. <em>Read-only.</em> */ class WalletScriptingInterface : public QObject, public Dependency { Q_OBJECT @@ -73,9 +73,9 @@ public: /**jsdoc * Check that a certified avatar entity is owned by the avatar whose entity it is. The result of the check is provided via * the {@link WalletScriptingInterface.ownershipVerificationSuccess|ownershipVerificationSuccess} and - * {@link WalletScriptingInterface.ownershipVerificationFailed|ownershipVerificationFailed} signals.<br /> - * <strong>Warning:</strong> Neither of these signals are triggered if the entity is not an avatar entity or is not - * certified. + * {@link WalletScriptingInterface.ownershipVerificationFailed|ownershipVerificationFailed} signals. + * <p><strong>Warning:</strong> Neither of these signals are triggered if the entity is not an avatar entity or is not + * certified.</p> * @function WalletScriptingInterface.proveAvatarEntityOwnershipVerification * @param {Uuid} entityID - The avatar entity's ID. * @example <caption>Check the ownership of all nearby certified avatar entities.</caption> diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 6207b22cb8..341b012c2d 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -326,10 +326,10 @@ public slots: * full resolution is used (window dimensions in desktop mode; HMD display dimensions in HMD mode), otherwise one of the * dimensions is adjusted in order to match the aspect ratio. * @param {string} [filename=""] - If a filename is not provided, the image is saved as "hifi-snap-by-<user - * name>-on-YYYY-MM-DD_HH-MM-SS".<br /> - * Still images are saved in JPEG or PNG format according to the extension provided — <code>".jpg"</code>, + * name>-on-YYYY-MM-DD_HH-MM-SS". + * <p>Still images are saved in JPEG or PNG format according to the extension provided — <code>".jpg"</code>, * <code>".jpeg"</code>, or <code>".png"</code> — or if not provided then in JPEG format with an extension of - * <code>".jpg"</code>. Animated images are saved in GIF format. + * <code>".jpg"</code>. Animated images are saved in GIF format.</p> * * @example <caption>Using the snapshot function and signals.</caption> * function onStillSnapshotTaken(path, notify) { @@ -365,10 +365,10 @@ public slots: * @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken} * signal. * @param {string} [filename=""] - If a filename is not provided, the image is saved as "hifi-snap-by-<user - * name>-on-YYYY-MM-DD_HH-MM-SS".<br /> - * Images are saved in JPEG or PNG format according to the extension provided — <code>".jpg"</code>, + * name>-on-YYYY-MM-DD_HH-MM-SS". + * <p>Images are saved in JPEG or PNG format according to the extension provided — <code>".jpg"</code>, * <code>".jpeg"</code>, or <code>".png"</code> — or if not provided then in JPEG format with an extension of - * <code>".jpg"</code>. + * <code>".jpg"</code>.</p> */ void takeSecondaryCameraSnapshot(const bool& notify = true, const QString& filename = QString()); @@ -384,10 +384,10 @@ public slots: * @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken} * signal. * @param {string} [filename=""] - If a filename is not provided, the image is saved as "hifi-snap-by-<user - * name>-on-YYYY-MM-DD_HH-MM-SS".<br /> - * Images are saved in JPEG or PNG format according to the extension provided — <code>".jpg"</code>, + * name>-on-YYYY-MM-DD_HH-MM-SS". + * <p>Images are saved in JPEG or PNG format according to the extension provided — <code>".jpg"</code>, * <code>".jpeg"</code>, or <code>".png"</code> — or if not provided then in JPEG format with an extension of - * <code>".jpg"</code>. + * <code>".jpg"</code>.</p> */ void takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const bool& cubemapOutputFormat = false, const bool& notify = true, const QString& filename = QString()); @@ -515,13 +515,13 @@ public slots: /**jsdoc * Opens a URL in the Interface window or other application, depending on the URL's scheme. The following schemes are - * supported:<br /> + * supported: * <ul> * <li><code>hifi</code>: Navigate to the URL in Interface.</li> * <li><code>hifiapp</code>: Open a system app in Interface.</li> * </ul> - * Other schemes will either be handled by the OS (e.g. <code>http</code>, <code>https</code>, or <code>mailto</code>) or - * will display a dialog asking the user to confirm that they want to try to open the URL. + * <p>Other schemes will either be handled by the OS (e.g. <code>http</code>, <code>https</code>, or <code>mailto</code>) or + * will display a dialog asking the user to confirm that they want to try to open the URL.</p> * @function Window.openUrl * @param {string} url - The URL to open. */ @@ -623,8 +623,8 @@ private slots: signals: /**jsdoc - * Triggered when you change the domain you're visiting. <strong>Warning:</strong> Is not emitted if you go to a domain - * that isn't running. + * Triggered when you change the domain you're visiting. + * <p><strong>Warning:</strong> Is not emitted if you go to a domain that isn't running.</p> * @function Window.domainChanged * @param {string} domainURL - The domain's URL. * @returns {Signal} diff --git a/interface/src/ui/InteractiveWindow.h b/interface/src/ui/InteractiveWindow.h index 70077a27b0..ba53684173 100644 --- a/interface/src/ui/InteractiveWindow.h +++ b/interface/src/ui/InteractiveWindow.h @@ -56,8 +56,8 @@ namespace InteractiveWindowEnums { Q_NAMESPACE /**jsdoc - * A set of flags controlling <code>InteractiveWindow</code> behavior. The value is constructed by using the - * <code>|</code> (bitwise OR) operator on the individual flag values.<br /> + * <p>A set of flags controlling <code>InteractiveWindow</code> behavior. The value is constructed by using the + * <code>|</code> (bitwise OR) operator on the individual flag values.</p> * <table> * <thead> * <tr><th>Flag Name</th><th>Value</th><th>Description</th></tr> diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 100711d69b..5e43c5df8d 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -1346,49 +1346,48 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * <td>Some text.</td> * <td>{@link Overlays.OverlayProperties-Text|OverlayProperties-Text}</td></tr> * <tr><td><code>"cube"</code></td><td>3D</td> - * <td>A cube. A <code>"shape"</code> overlay can also be used to create a cube.<br/> - * <span class="important">Deprecated.</span> - * </td> + * <td><p>A cube. A <code>"shape"</code> overlay can also be used to create a cube.</p> + * <p class="important">Deprecated.</p></td> * <td>{@link Overlays.OverlayProperties-Cube|OverlayProperties-Cube}</td></tr> * <tr><td><code>"sphere"</code></td><td>3D</td> - * <td>A sphere. A <code>"shape"</code> overlay can also be used to create a sphere.<br/> - * <span class="important">Deprecated.</span></td> + * <td><p>A sphere. A <code>"shape"</code> overlay can also be used to create a sphere.</p> + * <p class="important">Deprecated.</p></td> * <td>{@link Overlays.OverlayProperties-Sphere|OverlayProperties-Sphere}</td></tr> * <tr><td><code>"shape"</code></td><td>3D</td> - * <td>A geometric shape, such as a cube, sphere, or cylinder.<br/> - * <span class="important">Deprecated.</span></td> + * <td><p>A geometric shape, such as a cube, sphere, or cylinder.</p> + * <p class="important">Deprecated.</p></td> * <td>{@link Overlays.OverlayProperties-Shape|OverlayProperties-Shape}</td></tr> * <tr><td><code>"model"</code></td><td>3D</td> - * <td>A model.<br/> - * <span class="important">Deprecated.</span></td> + * <td><p>A model.</p> + * <p class="important">Deprecated.</p></td> * <td>{@link Overlays.OverlayProperties-Model|OverlayProperties-Model}</td></tr> * <tr><td><code>"image3d"</code></td><td>3D</td> - * <td>An image. Synonym: <code>"billboard"</code>.<br/> - * <span class="important">Deprecated.</span></td> + * <td><p>An image. Synonym: <code>"billboard"</code>.</p> + * <p class="important">Deprecated.</p></td> * <td>{@link Overlays.OverlayProperties-Image3D|OverlayProperties-Image3D}</td></tr> * <tr><td><code>"rectangle3d"</code></td><td>3D</td> - * <td>A rectangle.<br/> - * <span class="important">Deprecated.</span></td> + * <td><p>A rectangle.</p> + * <p class="important">Deprecated.</p></td> * <td>{@link Overlays.OverlayProperties-Rectangle3D|OverlayProperties-Rectangle3D}</td></tr> * <tr><td><code>"text3d"</code></td><td>3D</td> - * <td>Some text.<br/> - * <span class="important">Deprecated.</span></td> + * <td><p>Some text.</p> + * <p class="important">Deprecated.</p></td> * <td>{@link Overlays.OverlayProperties-Text3D|OverlayProperties-Text3D}</td></tr> * <tr><td><code>"web3d"</code></td><td>3D</td> - * <td>Web content.<br/> - * <span class="important">Deprecated.</span></td> + * <td><p>Web content.</p> + * <p class="important">Deprecated.</p></td> * <td>{@link Overlays.OverlayProperties-Web3D|OverlayProperties-Web3D}</td></tr> * <tr><td><code>"line3d"</code></td><td>3D</td> - * <td>A line.<br/> - * <span class="important">Deprecated.</span></td> + * <td><p>A line.</p> + * <p class="important">Deprecated.</p></td> * <td>{@link Overlays.OverlayProperties-Line3D|OverlayProperties-Line3D}</td></tr> * <tr><td><code>"grid"</code></td><td>3D</td> - * <td>A grid of lines in a plane.<br/> - * <span class="important">Deprecated.</span></td> + * <td><p>A grid of lines in a plane.</p> + * <p class="important">Deprecated.</p></td> * <td>{@link Overlays.OverlayProperties-Grid|OverlayProperties-Grid}</td></tr> * <tr><td><code>"circle3d"</code></td><td>3D</td> - * <td>A circle.<br/> - * <span class="important">Deprecated.</span></td> + * <td><p>A circle.</p> + * <p class="important">Deprecated.</p></td> * <td>{@link Overlays.OverlayProperties-Circle3D|OverlayProperties-Circle3D}</td></tr> * </tbody> * </table> @@ -1410,17 +1409,17 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * @see {@link Overlays.OverlayProperties-Rectangle|OverlayProperties-Rectangle} * @see {@link Overlays.OverlayProperties-Image|OverlayProperties-Image} * @see {@link Overlays.OverlayProperties-Text|OverlayProperties-Text} - * @see {@link Overlays.OverlayProperties-Cube|OverlayProperties-Cube} <span class="important">Deprecated.</span> - * @see {@link Overlays.OverlayProperties-Sphere|OverlayProperties-Sphere} <span class="important">Deprecated.</span> - * @see {@link Overlays.OverlayProperties-Shape|OverlayProperties-Shape} <span class="important">Deprecated.</span> - * @see {@link Overlays.OverlayProperties-Model|OverlayProperties-Model} <span class="important">Deprecated.</span> - * @see {@link Overlays.OverlayProperties-Rectangle3D|OverlayProperties-Rectangle3D} <span class="important">Deprecated.</span> - * @see {@link Overlays.OverlayProperties-Image3D|OverlayProperties-Image3D} <span class="important">Deprecated.</span> - * @see {@link Overlays.OverlayProperties-Text3D|OverlayProperties-Text3D} <span class="important">Deprecated.</span> - * @see {@link Overlays.OverlayProperties-Web3D|OverlayProperties-Web3D} <span class="important">Deprecated.</span> - * @see {@link Overlays.OverlayProperties-Line3D|OverlayProperties-Line3D} <span class="important">Deprecated.</span> - * @see {@link Overlays.OverlayProperties-Grid|OverlayProperties-Grid} <span class="important">Deprecated.</span> - * @see {@link Overlays.OverlayProperties-Circle3D|OverlayProperties-Circle3D} <span class="important">Deprecated.</span> + * @see {@link Overlays.OverlayProperties-Cube|OverlayProperties-Cube} — <span class="important">Deprecated.</span> + * @see {@link Overlays.OverlayProperties-Sphere|OverlayProperties-Sphere} — <span class="important">Deprecated.</span> + * @see {@link Overlays.OverlayProperties-Shape|OverlayProperties-Shape} — <span class="important">Deprecated.</span> + * @see {@link Overlays.OverlayProperties-Model|OverlayProperties-Model} — <span class="important">Deprecated.</span> + * @see {@link Overlays.OverlayProperties-Rectangle3D|OverlayProperties-Rectangle3D} — <span class="important">Deprecated.</span> + * @see {@link Overlays.OverlayProperties-Image3D|OverlayProperties-Image3D} — <span class="important">Deprecated.</span> + * @see {@link Overlays.OverlayProperties-Text3D|OverlayProperties-Text3D} — <span class="important">Deprecated.</span> + * @see {@link Overlays.OverlayProperties-Web3D|OverlayProperties-Web3D} — <span class="important">Deprecated.</span> + * @see {@link Overlays.OverlayProperties-Line3D|OverlayProperties-Line3D} — <span class="important">Deprecated.</span> + * @see {@link Overlays.OverlayProperties-Grid|OverlayProperties-Grid} — <span class="important">Deprecated.</span> + * @see {@link Overlays.OverlayProperties-Circle3D|OverlayProperties-Circle3D} — <span class="important">Deprecated.</span> */ /**jsdoc @@ -1502,11 +1501,11 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from * <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period. * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @@ -1520,7 +1519,7 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>. * @property {boolean} isSolid=false - <code>true</code> if the overlay is rendered as a solid, <code>false</code> if it is * rendered as a wire frame. - * Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>. + * Synonyms: <code>solid</code>, <code>isFilled</code>, and <code>filled</code>. * Antonyms: <code>isWire</code> and <code>wire</code>. * @property {boolean} ignorePickIntersection=false - <code>true</code> if {@link Picks} ignore the overlay, <code>false</code> * if they don't. @@ -1550,11 +1549,11 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from * <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period. * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @@ -1568,7 +1567,7 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>. * @property {boolean} isSolid=false - <code>true</code> if the overlay is rendered as a solid, <code>false</code> if it is * rendered as a wire frame. - * Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>. + * Synonyms: <code>solid</code>, <code>isFilled</code>, and <code>filled</code>. * Antonyms: <code>isWire</code> and <code>wire</code>. * @property {boolean} ignorePickIntersection=false - <code>true</code> if {@link Picks} ignore the overlay, <code>false</code> * if they don't. @@ -1599,11 +1598,11 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from * <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period. * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @@ -1617,7 +1616,7 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>. * @property {boolean} isSolid=false - <code>true</code> if the overlay is rendered as a solid, <code>false</code> if it is * rendered as a wire frame. - * Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>. + * Synonyms: <code>solid</code>, <code>isFilled</code>, and <code>filled</code>. * Antonyms: <code>isWire</code> and <code>wire</code>. * @property {boolean} ignorePickIntersection=false - <code>true</code> if {@link Picks} ignore the overlay, <code>false</code> * if they don't. @@ -1641,7 +1640,7 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * <tr><th>Value</th><th>Dimensions</th><th>Description</th></tr> * </thead> * <tbody> - * <tr><td><code>"Circle"</code></td><td>2D</td><td>A circle oriented in 3D.</td></td></tr> + * <tr><td><code>"Circle"</code></td><td>2D</td><td>A circle oriented in 3D.</td></tr> * <tr><td><code>"Cone"</code></td><td>3D</td><td></td></tr> * <tr><td><code>"Cube"</code></td><td>3D</td><td></td></tr> * <tr><td><code>"Cylinder"</code></td><td>3D</td><td></td></tr> @@ -1674,11 +1673,11 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from * <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period. * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @@ -1692,7 +1691,7 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>. * @property {boolean} isSolid=false - <code>true</code> if the overlay is rendered as a solid, <code>false</code> if it is * rendered as a wire frame. - * Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>. + * Synonyms: <code>solid</code>, <code>isFilled</code>, and <code>filled</code>. * Antonyms: <code>isWire</code> and <code>wire</code>. * @property {boolean} ignorePickIntersection=false - <code>true</code> if {@link Picks} ignore the overlay, <code>false</code> * if they don't. @@ -1761,17 +1760,17 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * @property {Color} color=255,255,255 - The color of the overlay text. Synonym: <code>textColor</code>. * @property {number} alpha=0.7 - The opacity of the overlay text, <code>0.0</code> – <code>1.0</code>. * <p><em>Currently not used; use <code>textAlpha</code> instead.</em></p> - * <CURRENTLY BROKEN> + * @comment CURRENTLY BROKEN * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from * <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period. * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @@ -1811,11 +1810,11 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from * <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period. * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @@ -1857,11 +1856,11 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from * <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period. * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @@ -1916,41 +1915,45 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * HUD surface. * @property {boolean} grabbable=false - <code>true</code> if the overlay can be grabbed, <code>false</code> if it can't be. * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. + * <p><em>Currently doesn't work.</em></p> + * @comment CURRENTLY BROKEN * @property {number} parentJointIndex=65535 - Integer value specifying the joint of the entity or avatar that the entity is * parented to if <code>parentID</code> is set. Use 65535 or -1 to parent to the parent's position and orientation rather * than a joint. * * @property {Uuid} endParentID=null - The avatar, entity, or overlay that the end point of the line is parented to. * <p><em>Currently doesn't work.</em></p> - * <CURRENTLY BROKEN> + * @comment CURRENTLY BROKEN * @property {number} endParentJointIndex=65535 - Integer value specifying the skeleton joint that the end point of the line is * attached to if <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint". * <p><em>Currently doesn't work.</em></p> - * <CURRENTLY BROKEN> + * @comment CURRENTLY BROKEN * @property {Vec3} start - The start point of the line. Synonyms: <code>startPoint</code> and <code>p1</code>. - * <p><em>If <code>parentID<code> is set, use <code>localStart</code> to set the local position of the start point.</em></p> - * <CURRENTLY BROKEN> + * <p><strong>Note:</strong> If <code>parentID</code> is set, use <code>localStart</code> to set the local position of the + * start point.</p> * @property {Vec3} end - The end point of the line. Synonyms: <code>endPoint</code> and <code>p2</code>. - * <p><em>If <code>parentID<code> is set, use <code>localEnd</code> to set the local position of the end point.</em></p> - * <CURRENTLY BROKEN> + * <p><strong>Note:</strong> If <code>parentID</code> is set, use <code>localEnd</code> to set the local position of the + * end point.</p> * @property {Vec3} localStart - The local position of the overlay relative to its parent if the overlay has a * <code>parentID</code> set, otherwise the same value as <code>start</code>. - * <CURRENTLY BROKEN> + * <p><em>Currently doesn't work.</em></p> + * @comment CURRENTLY BROKEN * @property {Vec3} localEnd - The local position of the overlay relative to its parent if the overlay has a * <code>endParentID</code> set, otherwise the same value as <code>end</code>. - * <CURRENTLY BROKEN> + * <p><em>Currently doesn't work.</em></p> + * @comment CURRENTLY BROKEN * @property {number} length - The length of the line, in meters. This can be set after creating a line with start and end * points. * <p><em>Currently doesn't work.</em></p> - * <CURRENTLY BROKEN> + * @comment CURRENTLY BROKEN * @property {number} glow=0 - If <code>glow > 0</code>, the line is rendered with a glow. * @property {number} lineWidth=0.02 - Width of the line, in meters. * <p><em>You can set this property's value but currently cannot retrieve its value. Use the <code>strokeWidths</code> - * property to retrieve its value instead.</p> + * property to retrieve its value instead.</em></p> */ /**jsdoc @@ -1967,11 +1970,11 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from * <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period. * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @@ -2010,11 +2013,11 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from * <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period. * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise * used.) * @@ -2029,7 +2032,7 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) { * <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>. * @property {boolean} isSolid=false - <code>true</code> if the overlay is rendered as a solid, <code>false</code> if it is * rendered as a wire frame. - * Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>. + * Synonyms: <code>solid</code>, <code>isFilled</code>, and <code>filled</code>. * Antonyms: <code>isWire</code> and <code>wire</code>. * @property {boolean} ignorePickIntersection=false - <code>true</code> if {@link Picks} ignore the overlay, <code>false</code> * if they don't. diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index 8d3f898e67..bcad7867cc 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -63,7 +63,7 @@ public: * <p>Specifies the initial conditions of the IK solver.</p> * <table> * <thead> - * <tr><th>Value</th><th>Name</p><th>Description</th> + * <tr><th>Value</th><th>Name</th><th>Description</th> * </thead> * <tbody> * <tr><td><code>0</code></td><td>RelaxToUnderPoses</td><td>This is a blend: it is 15/16 <code>PreviousSolution</code> @@ -73,12 +73,14 @@ public: * <tr><td><code>1</code></td><td>RelaxToLimitCenterPoses</td><td>This is a blend: it is 15/16 * <code>PreviousSolution</code> and 1/16 <code>LimitCenterPoses</code>. This should converge quickly because it is * close to the previous solution, but still provides the benefits of avoiding limb locking.</td></tr> - * <tr><td><code>2</code></td><td>PreviousSolution</td><td>The IK system will begin to solve from the same position and - * orientations for each joint that was the result from the previous frame.<br /> - * Pros: As the end effectors typically do not move much from frame to frame, this is likely to converge quickly - * to a valid solution.<br /> - * Cons: If the previous solution resulted in an awkward or uncomfortable posture, the next frame will also be - * awkward and uncomfortable. It can also result in locked elbows and knees.</td></tr> + * <tr><td><code>2</code></td><td>PreviousSolution</td><td> + * <p>The IK system will begin to solve from the same position and orientations for each joint that was the result + * from the previous frame.</p> + * <p>Pros: As the end effectors typically do not move much from frame to frame, this is likely to converge quickly + * to a valid solution.</p> + * <p>Cons: If the previous solution resulted in an awkward or uncomfortable posture, the next frame will also be + * awkward and uncomfortable. It can also result in locked elbows and knees.</p> + * </td></tr> * <tr><td><code>3</code></td><td>UnderPoses</td><td>The IK occurs at one of the top-most layers. It has access to the * full posture that was computed via canned animations and blends. We call this animated set of poses the "under * pose". The under poses are what would be visible if IK was completely disabled. Using the under poses as the diff --git a/libraries/animation/src/AnimOverlay.h b/libraries/animation/src/AnimOverlay.h index 1ad4e100db..d5e114a2d2 100644 --- a/libraries/animation/src/AnimOverlay.h +++ b/libraries/animation/src/AnimOverlay.h @@ -28,7 +28,7 @@ public: * <p>Specifies sets of joints.</p> * <table> * <thead> - * <tr><th>Value</th><th>Name</p><th>Description</th> + * <tr><th>Value</th><th>Name</th><th>Description</th> * </thead> * <tbody> * <tr><td><code>0</code></td><td>FullBodyBoneSet</td><td>All joints.</td></tr> diff --git a/libraries/animation/src/IKTarget.h b/libraries/animation/src/IKTarget.h index 331acedd4e..a56f5578b3 100644 --- a/libraries/animation/src/IKTarget.h +++ b/libraries/animation/src/IKTarget.h @@ -20,14 +20,14 @@ public: * <p>An IK target type.</p> * <table> * <thead> - * <tr><th>Value</th><th>Name</p><th>Description</th> + * <tr><th>Value</th><th>Name</th><th>Description</th> * </thead> * <tbody> * <tr><td><code>0</code></td><td>RotationAndPosition</td><td>Attempt to reach the rotation and position end * effector.</td></tr> * <tr><td><code>1</code></td><td>RotationOnly</td><td>Attempt to reach the end effector rotation only.</td></tr> - * <tr><td><code>2</code></td><td>HmdHead</td><td>A special mode of IK that would attempt to prevent unnecessary - * bending of the spine.<br /> + * <tr><td><code>2</code></td><td>HmdHead</td><td> + * <p>A special mode of IK that would attempt to prevent unnecessary bending of the spine.</p> * <p class="important">Deprecated: This target type is deprecated and will be removed.</p></td></tr> * <tr><td><code>3</code></td><td>HipsRelativeRotationAndPosition</td><td>Attempt to reach a rotation and position end * effector that is not in absolute rig coordinates but is offset by the avatar hips translation.</td></tr> diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index d63c2d6a9b..42980f47a7 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -95,7 +95,7 @@ static const QString MAIN_STATE_MACHINE_RIGHT_HAND_POSITION("mainStateMachineRig * <p><strong>Warning:</strong> These properties are subject to change. * <table> * <thead> - * <tr><th>Name</th><th>Type</p><th>Description</th> + * <tr><th>Name</th><th>Type</th><th>Description</th> * </thead> * <tbody> * <tr><td><code>userAnimNone</code></td><td>boolean</td><td><code>true</code> when no user overrideAnimation is diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 75a7693de8..7a2ea5321f 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -545,7 +545,7 @@ void Avatar::relayJointDataToChildren() { } /**jsdoc - * An avatar has different types of data simulated at different rates, in Hz. + * <p>An avatar has different types of data simulated at different rates, in Hz.</p> * * <table> * <thead> diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index b969449d5e..610f34ed45 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -470,7 +470,7 @@ public: /**jsdoc * Sets the joint of the entity or avatar that the avatar is parented to. * @function MyAvatar.setParentJointIndex - * @param {number} parentJointIndex - he joint of the entity or avatar that the avatar should be parented to. Use + * @param {number} parentJointIndex - The joint of the entity or avatar that the avatar should be parented to. Use * <code>65535</code> or <code>-1</code> to parent to the entity or avatar's position and orientation rather than a * joint. */ diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index a91154ff15..710bfb8d2a 100755 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1445,7 +1445,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } /**jsdoc - * The avatar mixer data comprises different types of data, with the data rates of each being tracked in kbps. + * <p>The avatar mixer data comprises different types of data, with the data rates of each being tracked in kbps.</p> * * <table> * <thead> @@ -1550,7 +1550,7 @@ float AvatarData::getDataRate(const QString& rateName) const { } /**jsdoc - * The avatar mixer data comprises different types of data updated at different rates, in Hz. + * <p>The avatar mixer data comprises different types of data updated at different rates, in Hz.</p> * * <table> * <thead> diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 59a2e2a53e..df0783ef4b 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -1277,9 +1277,9 @@ public: * @param {number} [scale=1.0] - The scale to apply to the model. * @param {boolean} [isSoft=false] - If the model has a skeleton, set this to <code>true</code> so that the bones of the * attached model's skeleton are rotated to fit the avatar's current pose. <code>isSoft</code> is used, for example, - * to have clothing that moves with the avatar.<br /> - * If <code>true</code>, the <code>translation</code>, <code>rotation</code>, and <code>scale</code> parameters are - * ignored. + * to have clothing that moves with the avatar. + * <p>If <code>true</code>, the <code>translation</code>, <code>rotation</code>, and <code>scale</code> parameters are + * ignored.</p> * @param {boolean} [allowDuplicates=false] - If <code>true</code> then more than one copy of any particular model may be * attached to the same joint; if <code>false</code> then the same model cannot be attached to the same joint. * @param {boolean} [useSaved=true] - <em>Not used.</em> diff --git a/libraries/controllers/src/controllers/Actions.cpp b/libraries/controllers/src/controllers/Actions.cpp index 40011f2682..6be0a5a800 100644 --- a/libraries/controllers/src/controllers/Actions.cpp +++ b/libraries/controllers/src/controllers/Actions.cpp @@ -44,7 +44,7 @@ namespace controller { * <tr><th>Property</th><th>Type</th><th>Data</th><th>Description</th></tr> * </thead> * <tbody> - * <tr><td colSpan=4><strong>Avatar Movement</strong></td> + * <tr><td colSpan=4><strong>Avatar Movement</strong></td></tr> * <tr><td><code>TranslateX</code></td><td>number</td><td>number</td><td>Move the user's avatar in the direction of its * x-axis, if the camera isn't in independent or mirror modes.</td></tr> * <tr><td><code>TranslateY</code></td><td>number</td><td>number</td><td>Move the user's avatar in the direction of its @@ -71,7 +71,7 @@ namespace controller { * step increment, if the camera isn't in independent or mirror modes.</td></tr> * <tr><td><code>StepRoll</code></td><td>number</td><td>number</td><td>No action.</td></tr> * - * <tr><td colSpan=4><strong>Avatar Skeleton</strong></td> + * <tr><td colSpan=4><strong>Avatar Skeleton</strong></td></tr> * <tr><td><code>Hips</code></td><td>number</td><td>{@link Pose}</td><td>Set the hips pose of the user's avatar. * </td></tr> * <tr><td><code>Spine2</code></td><td>number</td><td>{@link Pose}</td><td>Set the spine2 pose of the user's avatar. @@ -171,7 +171,7 @@ namespace controller { * <tr><td><code>RightFoot</code></td><td>number</td><td>{@link Pose}</td><td>Set the right foot pose of the user's * avatar.</td></tr> * - * <tr><td colSpan=4><strong><strong>Application</strong></td> + * <tr><td colSpan=4><strong>Application</strong></td></tr> * <tr><td><code>BoomIn</code></td><td>number</td><td>number</td><td>Zoom camera in from third person toward first * person view.</td></tr> * <tr><td><code>BoomOut</code></td><td>number</td><td>number</td><td>Zoom camera out from first person to third @@ -212,7 +212,7 @@ namespace controller { * <tr><td><code>SecondaryAction</code></td><td>number</td><td>number</td><td><span class="important">Deprecated: This * action is deprecated and will be removed. It takes no action.</span></td></tr> * - * <tr><td colSpan=4><strong>Aliases</strong></td> + * <tr><td colSpan=4><strong>Aliases</strong></td></tr> * <tr><td><code>Backward</code></td><td>number</td><td>number</td><td>Alias for <code>TranslateZ</code> in the * positive direction.</td></tr> * <tr><td><code>Forward</code></td><td>number</td><td>number</td><td>Alias for <code>TranslateZ</code> in the negative @@ -234,7 +234,7 @@ namespace controller { * <tr><td><code>YawRight</code></td><td>number</td><td>number</td><td>Alias for <code>Yaw</code> in the negative * direction.</td></tr> * - * <tr><td colSpan=4><strong>Deprecated Aliases</strong></td> + * <tr><td colSpan=4><strong>Deprecated Aliases</strong></td></tr> * <tr><td><code>LEFT_HAND</code></td><td>number</td><td>{@link Pose}</td><td><span class="important">Deprecated: This * action is deprecated and will be removed. Use <code>LeftHand</code> instead.</span></td></tr> * <tr><td><code>RIGHT_HAND</code></td><td>number</td><td>{@link Pose}</td><td><span class="important">Deprecated: This @@ -282,7 +282,7 @@ namespace controller { * <tr><td><code>ACTION2</code></td><td>number</td><td>number</td><td><span class="important">Deprecated: This * action is deprecated and will be removed. Use <code>SecondaryAction</code> instead.</span></td></tr> * - * <tr><td colSpan=4><strong>Deprecated Trackers</strong></td> + * <tr><td colSpan=4><strong>Deprecated Trackers</strong></td><tr> * <tr><td><code>TrackedObject00</code></td><td>number</td><td>{@link Pose}</td><td><span class="important">Deprecated: * This action is deprecated and will be removed. It takes no action.</span></td></tr> * <tr><td><code>TrackedObject01</code></td><td>number</td><td>{@link Pose}</td><td><span class="important">Deprecated: diff --git a/libraries/controllers/src/controllers/StandardController.cpp b/libraries/controllers/src/controllers/StandardController.cpp index dbc92cc7e5..ae592485dc 100644 --- a/libraries/controllers/src/controllers/StandardController.cpp +++ b/libraries/controllers/src/controllers/StandardController.cpp @@ -33,7 +33,7 @@ void StandardController::focusOutEvent() { * identifying each output. <em>Read-only.</em></p> * <p>These outputs can be mapped to actions or functions in a {@link RouteObject} mapping. The data value provided by each * control is either a number or a {@link Pose}. Numbers are typically normalized to <code>0.0</code> or <code>1.0</code> for - * button states, the range <code>0.0</code> – </code>1.0</code> for unidirectional scales, and the range + * button states, the range <code>0.0</code> – <code>1.0</code> for unidirectional scales, and the range * <code>-1.0</code> – <code>1.0</code> for bidirectional scales.</p> * <p>Each hardware device has a mapping from its outputs to a subset of <code>Controller.Standard</code> items, specified in a * JSON file. For example, @@ -118,8 +118,7 @@ void StandardController::focusOutEvent() { * button.</td></tr> * <tr><td><code>RightThumbUp</code></td><td>number</td><td>number</td><td>Right thumb not touching primary or secondary * thumb buttons.</td></tr> - * <tr><td><code>LeftPrimaryIndex</code></td><td>number</td><td>number</td><td>Left primary index control - * pressed.</em></td></tr> + * <tr><td><code>LeftPrimaryIndex</code></td><td>number</td><td>number</td><td>Left primary index control pressed.</td></tr> * <tr><td><code>LeftSecondaryIndex</code></td><td>number</td><td>number</td><td>Left secondary index control pressed. * </td></tr> * <tr><td><code>RightPrimaryIndex</code></td><td>number</td><td>number</td><td>Right primary index control pressed. diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h index f0a823a3de..5a8fd3083d 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h @@ -86,7 +86,7 @@ class UserInputMapper; * @typedef {object} Controller.MappingJSONRoute * @property {string|Controller.MappingJSONAxis} from - The name of a {@link Controller.Hardware} property or an axis made from * them. If a property name, the leading <code>"Controller.Hardware."</code> can be omitted. - * @property {boolean} [peek=false] - If <codd>true</code>, then peeking is enabled per {@link RouteObject#peek}. + * @property {boolean} [peek=false] - If <code>true</code>, then peeking is enabled per {@link RouteObject#peek}. * @property {boolean} [debug=false] - If <code>true</code>, then debug is enabled per {@link RouteObject#debug}. * @property {string|string[]} [when=[]] - One or more numeric {@link Controller.Hardware} property names which are evaluated * as booleans and ANDed together. Prepend a property name with a <code>!</code> to do a logical NOT. The leading @@ -135,8 +135,8 @@ public: /**jsdoc * Creates a new {@link RouteObject} from a controller output, ready to be mapped to a standard control, action, or - * function.<br /> - * This is a QML-specific version of {@link MappingObject#from|from}: use this version in QML files. + * function. + * <p>This is a QML-specific version of {@link MappingObject#from|from}: use this version in QML files.</p> * @function MappingObject#fromQml * @param {Controller.Standard|Controller.Hardware|function} source - The controller output or function that is the source * of the route data. If a function, it must return a number or a {@link Pose} value as the route data. @@ -146,8 +146,8 @@ public: /**jsdoc * Creates a new {@link RouteObject} from two numeric {@link Controller.Hardware} outputs, one applied in the negative - * direction and the other in the positive direction, ready to be mapped to a standard control, action, or function.<br /> - * This is a QML-specific version of {@link MappingObject#makeAxis|makeAxis}: use this version in QML files. + * direction and the other in the positive direction, ready to be mapped to a standard control, action, or function. + * <p>This is a QML-specific version of {@link MappingObject#makeAxis|makeAxis}: use this version in QML files.</p> * @function MappingObject#makeAxisQml * @param {Controller.Hardware} source1 - The first, negative-direction controller output. * @param {Controller.Hardware} source2 - The second, positive-direction controller output. @@ -189,8 +189,8 @@ public: Q_INVOKABLE QObject* makeAxis(const QScriptValue& source1, const QScriptValue& source2); /**jsdoc - * Enables or disables the mapping. When enabled, the routes in the mapping take effect.<br /> - * Synonymous with {@link Controller.enableMapping}. + * Enables or disables the mapping. When enabled, the routes in the mapping take effect. + * <p>Synonymous with {@link Controller.enableMapping}.</p> * @function MappingObject#enable * @param {boolean} enable=true - If <code>true</code> then the mapping is enabled, otherwise it is disabled. * @returns {MappingObject} The mapping object, so that further routes can be added. @@ -198,8 +198,8 @@ public: Q_INVOKABLE QObject* enable(bool enable = true); /**jsdoc - * Disables the mapping. When disabled, the routes in the mapping have no effect.<br /> - * Synonymous with {@link Controller.disableMapping}. + * Disables the mapping. When disabled, the routes in the mapping have no effect. + * <p>Synonymous with {@link Controller.disableMapping}.</p> * @function MappingObject#disable * @returns {MappingObject} The mapping object, so that further routes can be added. */ diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h index e7ff04d72c..f1b36cfec5 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h @@ -52,8 +52,8 @@ class RouteBuilderProxy : public QObject { /**jsdoc * Terminates the route with a standard control, an action, or a script function. The output value from the route is - * sent to the specified destination.<br /> - * This is a QML-specific version of {@link MappingObject#to|to}: use this version in QML files. + * sent to the specified destination. + * <p>This is a QML-specific version of {@link MappingObject#to|to}: use this version in QML files.</p> * @function RouteObject#toQml * @param {Controller.Standard|Controller.Actions|function} destination - The standard control, action, or JavaScript * function that the route output is mapped to. For a function, the parameter can be either the name of the function or @@ -64,8 +64,8 @@ class RouteBuilderProxy : public QObject { /**jsdoc * Processes the route only if a condition is satisfied. The condition is evaluated before the route input is read, and * the input is read only if the condition is <code>true</code>. Thus, if the condition is not met then subsequent - * routes using the same input are processed.<br /> - * This is a QML-specific version of {@link MappingObject#to|to}: use this version in QML files. + * routes using the same input are processed. + * <p>This is a QML-specific version of {@link MappingObject#when|when}: use this version in QML files.</p> * @function RouteObject#whenQml * @param {condition|condition[]} expression - <p>A <code>condition</code> may be a:</p> * <ul> diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp index d3cb602e5b..a1138b3018 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp @@ -15,10 +15,10 @@ #include <QtCore/QTimer> #include <QtCore/QThread> -#include <QtWidgets/QApplication> -#include <QtWidgets/QDesktopWidget> +#include <QtGui/QGuiApplication> +#include <QtGui/QScreen> #include <QtGui/QWindow> -#include <QQuickWindow> +#include <QtQuick/QQuickWindow> #include <DebugDraw.h> #include <shared/QtHelpers.h> @@ -177,9 +177,35 @@ QPointF CompositorHelper::getMouseEventPosition(QMouseEvent* event) { return event->localPos(); } +static bool isWindowActive() { + for (const auto& window : QGuiApplication::topLevelWindows()) { + if (window->isActive()) { + return true; + } + } + return false; +} + bool CompositorHelper::shouldCaptureMouse() const { + if (!_allowMouseCapture) { + return false; + } + + if (!isHMD()) { + return false; + } + + + if (!isWindowActive()) { + return false; + } + + if (ui::Menu::isSomeSubmenuShown()) { + return false; + } + // if we're in HMD mode, and some window of ours is active, but we're not currently showing a popup menu - return _allowMouseCapture && isHMD() && QApplication::activeWindow() && !ui::Menu::isSomeSubmenuShown(); + return true; } void CompositorHelper::setAllowMouseCapture(bool capture) { @@ -206,9 +232,9 @@ void CompositorHelper::handleLeaveEvent() { mainWidgetFrame.moveTopLeft(topLeftScreen); } QRect uncoveredRect = mainWidgetFrame; - foreach(QWidget* widget, QApplication::topLevelWidgets()) { - if (widget->isWindow() && widget->isVisible() && widget != mainWidget) { - QRect widgetFrame = widget->frameGeometry(); + for(QWindow* window : QGuiApplication::topLevelWindows()) { + if (window->isVisible() && window != mainWidget->windowHandle()) { + QRect widgetFrame = window->frameGeometry(); if (widgetFrame.intersects(uncoveredRect)) { QRect intersection = uncoveredRect & widgetFrame; if (intersection.top() > uncoveredRect.top()) { @@ -292,7 +318,7 @@ glm::vec2 CompositorHelper::getReticleMaximumPosition() const { if (isHMD()) { result = VIRTUAL_SCREEN_SIZE; } else { - QRect rec = QApplication::desktop()->screenGeometry(); + QRect rec = QGuiApplication::primaryScreen()->geometry(); result = glm::vec2(rec.right(), rec.bottom()); } return result; @@ -308,8 +334,8 @@ void CompositorHelper::sendFakeMouseEvent() { // in HMD mode we need to fake our mouse moves... QPoint globalPos(_reticlePositionInHMD.x, _reticlePositionInHMD.y); auto button = Qt::NoButton; - auto buttons = QApplication::mouseButtons(); - auto modifiers = QApplication::keyboardModifiers(); + auto buttons = QGuiApplication::mouseButtons(); + auto modifiers = QGuiApplication::keyboardModifiers(); QMouseEvent event(QEvent::MouseMove, globalPos, button, buttons, modifiers); _fakeMouseEvent = true; qApp->sendEvent(_renderingWidget, &event); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 74d36101db..f601b99779 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -13,6 +13,7 @@ #include <gl/Config.h> #include <QtCore/QCoreApplication> +#include <QtCore/QBuffer> #include <QtCore/QThread> #include <QtCore/QTimer> #include <QtCore/QFileInfo> @@ -36,6 +37,7 @@ #include <shaders/Shaders.h> #include <gpu/gl/GLShared.h> #include <gpu/gl/GLBackend.h> +#include <gpu/gl/GLTexelFormat.h> #include <GeometryCache.h> #include <CursorManager.h> @@ -371,7 +373,7 @@ void OpenGLDisplayPlugin::customizeContext() { auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha(); cursorData.texture->setUsage(usage.build()); cursorData.texture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); - cursorData.texture->assignStoredMip(0, image.byteCount(), image.constBits()); + cursorData.texture->assignStoredMip(0, image.sizeInBytes(), image.constBits()); cursorData.texture->setAutoGenerateMips(true); } } @@ -475,30 +477,48 @@ void OpenGLDisplayPlugin::submitFrame(const gpu::FramePointer& newFrame) { }); } +ktx::StoragePointer textureToKtx(const gpu::Texture& texture) { + ktx::Header header; + { + auto gpuDims = texture.getDimensions(); + header.pixelWidth = gpuDims.x; + header.pixelHeight = gpuDims.y; + header.pixelDepth = 0; + } + + { + auto gltexelformat = gpu::gl::GLTexelFormat::evalGLTexelFormat(texture.getStoredMipFormat()); + header.glInternalFormat = gltexelformat.internalFormat; + header.glFormat = gltexelformat.format; + header.glBaseInternalFormat = gltexelformat.format; + header.glType = gltexelformat.type; + header.glTypeSize = 1; + header.numberOfMipmapLevels = 1 + texture.getMaxMip(); + } + + auto memKtx = ktx::KTX::createBare(header); + auto storage = memKtx->_storage; + uint32_t faceCount = std::max(header.numberOfFaces, 1u); + uint32_t mipCount = std::max(header.numberOfMipmapLevels, 1u); + for (uint32_t mip = 0; mip < mipCount; ++mip) { + for (uint32_t face = 0; face < faceCount; ++face) { + const auto& image = memKtx->_images[mip]; + auto& faceBytes = const_cast<gpu::Byte*&>(image._faceBytes[face]); + if (texture.isStoredMipFaceAvailable(mip, face)) { + auto storedImage = texture.accessStoredMipFace(mip, face); + auto storedSize = storedImage->size(); + memcpy(faceBytes, storedImage->data(), storedSize); + } + } + } + return storage; +} + void OpenGLDisplayPlugin::captureFrame(const std::string& filename) const { withOtherThreadContext([&] { using namespace gpu; - auto glBackend = const_cast<OpenGLDisplayPlugin&>(*this).getGLBackend(); - FramebufferPointer framebuffer{ Framebuffer::create("captureFramebuffer") }; - TextureCapturer captureLambda = [&](const std::string& filename, const gpu::TexturePointer& texture, uint16 layer) { - QImage image; - if (texture->getUsageType() == TextureUsageType::STRICT_RESOURCE) { - image = QImage{ 1, 1, QImage::Format_ARGB32 }; - auto storedImage = texture->accessStoredMipFace(0, 0); - memcpy(image.bits(), storedImage->data(), image.sizeInBytes()); - //if (texture == textureCache->getWhiteTexture()) { - //} else if (texture == textureCache->getBlackTexture()) { - //} else if (texture == textureCache->getBlueTexture()) { - //} else if (texture == textureCache->getGrayTexture()) { - } else { - ivec4 rect = { 0, 0, texture->getWidth(), texture->getHeight() }; - framebuffer->setRenderBuffer(0, texture, layer); - glBackend->syncGPUObject(*framebuffer); - - image = QImage{ rect.z, rect.w, QImage::Format_ARGB32 }; - glBackend->downloadFramebuffer(framebuffer, rect, image); - } - QImageWriter(filename.c_str()).write(image); + TextureCapturer captureLambda = [&](const gpu::TexturePointer& texture)->storage::StoragePointer { + return textureToKtx(*texture); }; if (_currentFrame) { diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 722ab341f7..0c8b661980 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -290,7 +290,7 @@ void HmdDisplayPlugin::internalPresent() { _previewTexture->setSource("HMD Preview Texture"); _previewTexture->setUsage(gpu::Texture::Usage::Builder().withColor().build()); _previewTexture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); - _previewTexture->assignStoredMip(0, image.byteCount(), image.constBits()); + _previewTexture->assignStoredMip(0, image.sizeInBytes(), image.constBits()); _previewTexture->setAutoGenerateMips(true); auto viewport = getViewportForSourceSize(uvec2(_previewTexture->getDimensions())); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 52738bb6cd..ab3f4c5243 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -168,47 +168,52 @@ void EntityTreeRenderer::resetEntitiesScriptEngine() { entityScriptingInterface->setEntitiesScriptEngine(entitiesScriptEngineProvider); // Connect mouse events to entity script callbacks - connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { - _entitiesScriptEngine->callEntityScriptMethod(entityID, "mousePressOnEntity", event); - }); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseDoublePressOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { - _entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseDoublePressOnEntity", event); - }); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { - _entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseMoveOnEntity", event); - // FIXME: this is a duplicate of mouseMoveOnEntity, but it seems like some scripts might use this naming - _entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseMoveEvent", event); - }); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { - _entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseReleaseOnEntity", event); - }); + if (!_mouseAndPreloadSignalHandlersConnected) { + + connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "mousePressOnEntity", event); + }); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseDoublePressOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseDoublePressOnEntity", event); + }); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseMoveOnEntity", event); + // FIXME: this is a duplicate of mouseMoveOnEntity, but it seems like some scripts might use this naming + _entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseMoveEvent", event); + }); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "mouseReleaseOnEntity", event); + }); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickDownOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { - _entitiesScriptEngine->callEntityScriptMethod(entityID, "clickDownOnEntity", event); - }); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::holdingClickOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { - _entitiesScriptEngine->callEntityScriptMethod(entityID, "holdingClickOnEntity", event); - }); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickReleaseOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { - _entitiesScriptEngine->callEntityScriptMethod(entityID, "clickReleaseOnEntity", event); - }); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickDownOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "clickDownOnEntity", event); + }); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::holdingClickOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "holdingClickOnEntity", event); + }); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickReleaseOnEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "clickReleaseOnEntity", event); + }); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { - _entitiesScriptEngine->callEntityScriptMethod(entityID, "hoverEnterEntity", event); - }); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverOverEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { - _entitiesScriptEngine->callEntityScriptMethod(entityID, "hoverOverEntity", event); - }); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { - _entitiesScriptEngine->callEntityScriptMethod(entityID, "hoverLeaveEntity", event); - }); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "hoverEnterEntity", event); + }); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverOverEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "hoverOverEntity", event); + }); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, _entitiesScriptEngine.data(), [&](const EntityItemID& entityID, const PointerEvent& event) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "hoverLeaveEntity", event); + }); - connect(_entitiesScriptEngine.data(), &ScriptEngine::entityScriptPreloadFinished, [&](const EntityItemID& entityID) { - EntityItemPointer entity = getTree()->findEntityByID(entityID); - if (entity) { - entity->setScriptHasFinishedPreload(true); - } - }); + connect(_entitiesScriptEngine.data(), &ScriptEngine::entityScriptPreloadFinished, [&](const EntityItemID& entityID) { + EntityItemPointer entity = getTree()->findEntityByID(entityID); + if (entity) { + entity->setScriptHasFinishedPreload(true); + } + }); + + _mouseAndPreloadSignalHandlersConnected = true; + } } void EntityTreeRenderer::stopDomainAndNonOwnedEntities() { diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index b9fda690dd..6dbaedc123 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -210,6 +210,8 @@ private: std::function<RayToEntityIntersectionResult(unsigned int)> _getPrevRayPickResultOperator; std::function<void(unsigned int, bool)> _setPrecisionPickingOperator; + bool _mouseAndPreloadSignalHandlersConnected { false }; + class LayeredZone { public: LayeredZone(std::shared_ptr<ZoneEntityItem> zone) : zone(zone), id(zone->getID()), volume(zone->getVolumeEstimate()) {} diff --git a/libraries/entities/src/EntityDynamicInterface.cpp b/libraries/entities/src/EntityDynamicInterface.cpp index 69d771db22..9c73217bef 100644 --- a/libraries/entities/src/EntityDynamicInterface.cpp +++ b/libraries/entities/src/EntityDynamicInterface.cpp @@ -130,8 +130,8 @@ variables. These argument variables are used by the code which is run when bull * <tr><td><code>"ball-socket"</code></td><td>Object constraint</td> * <td>Connects two entities with a ball and socket joint.</td> * <td>{@link Entities.ActionArguments-BallSocket}</td></tr> - * <tr><td><code>"spring"</code></td><td colspan="3">Synonym for <code>"tractor"</code>. - * <span class="important">Deprecated.</span></td></tr> + * <tr><td><code>"spring"</code></td><td> </td><td>Synonym for <code>"tractor"</code>. + * <p class="important">Deprecated.</p></td><td> </td></tr> * </tbody> * </table> * @typedef {string} Entities.ActionType diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 5cb5ddbbfa..2b8f2b4c14 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -940,7 +940,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} materialMappingRot=0 - How much to rotate the material within the parent's UV-space, in degrees. * @property {boolean} materialRepeat=true - <code>true</code> if the material repeats, <code>false</code> if it doesn't. If * <code>false</code>, fragments outside of texCoord 0 – 1 will be discarded. Works in both <code>"uv"</code> and - * </code>"projected"</code> modes. + * <code>"projected"</code> modes. * @example <caption>Color a sphere using a Material entity.</caption> * var entityID = Entities.addEntity({ * type: "Sphere", @@ -1213,10 +1213,10 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * <code>dimensions / voxelVolumesize</code>. * @property {string} voxelData="ABAAEAAQAAAAHgAAEAB42u3BAQ0AAADCoPdPbQ8HFAAAAPBuEAAAAQ==" - Base-64 encoded compressed dump of * the PolyVox data. This property is typically not used in scripts directly; rather, functions that manipulate a PolyVox - * entity update it.<br /> - * The size of this property increases with the size and complexity of the PolyVox entity, with the size depending on how + * entity update it. + * <p>The size of this property increases with the size and complexity of the PolyVox entity, with the size depending on how * the particular entity's voxels compress. Because this property value has to fit within a High Fidelity datagram packet, - * there is a limit to the size and complexity of a PolyVox entity; edits which would result in an overflow are rejected. + * there is a limit to the size and complexity of a PolyVox entity; edits which would result in an overflow are rejected.</p> * @property {Entities.PolyVoxSurfaceStyle} voxelSurfaceStyle=2 - The style of rendering the voxels' surface and how * neighboring PolyVox entities are joined. * @property {string} xTextureURL="" - The URL of the texture to map to surfaces perpendicular to the entity's local x-axis. @@ -1305,7 +1305,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} bottomMargin=0.0 - The bottom margin, in meters. * @property {boolean} unlit=false - <code>true</code> if the entity is unaffected by lighting, <code>false</code> if it is lit * by the key light and local lights. - * @property {string} font="" - The font to render the text with. It can be one of the following: <code>"Courier"</code, + * @property {string} font="" - The font to render the text with. It can be one of the following: <code>"Courier"</code>, * <code>"Inconsolata"</code>, <code>"Roboto"</code>, <code>"Timeless"</code>, or a path to a .sdff file. * @property {Entities.TextEffect} textEffect="none" - The effect that is applied to the text. * @property {Color} textEffectColor=255,255,255 - The color of the effect. diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 7cfdc8a68d..3305d9ba00 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -666,7 +666,7 @@ QScriptValue EntityScriptingInterface::getMultipleEntityProperties(QScriptContex const int ARGUMENT_EXTENDED_DESIRED_PROPERTIES = 1; auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); - const auto entityIDs = qScriptValueToValue<QVector<QUuid>>(context->argument(ARGUMENT_ENTITY_IDS)); + const auto entityIDs = qscriptvalue_cast<QVector<QUuid>>(context->argument(ARGUMENT_ENTITY_IDS)); return entityScriptingInterface->getMultipleEntityPropertiesInternal(engine, entityIDs, context->argument(ARGUMENT_EXTENDED_DESIRED_PROPERTIES)); } @@ -716,7 +716,7 @@ QScriptValue EntityScriptingInterface::getMultipleEntityPropertiesInternal(QScri psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::FlagsActive); } - EntityPropertyFlags desiredProperties = qScriptValueToValue<EntityPropertyFlags>(extendedDesiredProperties); + EntityPropertyFlags desiredProperties = qscriptvalue_cast<EntityPropertyFlags>(extendedDesiredProperties); bool needsScriptSemantics = desiredProperties.getHasProperty(PROP_POSITION) || desiredProperties.getHasProperty(PROP_ROTATION) || desiredProperties.getHasProperty(PROP_LOCAL_POSITION) || diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 7c3fd2536d..fb1ec56503 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -106,8 +106,9 @@ public: * "domain" entities, travel to different domains with a user as "avatar" entities, or be visible only to an individual user as * "local" entities (a.k.a. "overlays"). * - * <p>Note: For Interface scripts, the entities available to scripts are those that Interface has displayed and so knows - * about.</p> + * <p>Note: For Interface, avatar, and client entity scripts, the entities available to scripts are those that Interface has + * displayed and so knows about. For assignment client scripts, the entities available are those that are "seen" by the + * {@link EntityViewer}. For entity server scripts, all entities are available.</p> * * <h3>Entity Methods</h3> * @@ -1871,7 +1872,7 @@ public slots: /**jsdoc * Called when a {@link Entities.getMeshes} call is complete. * @callback Entities~getMeshesCallback - * @param {MeshProxy[]} meshes - If <code>success<</code> is <code>true</code>, a {@link MeshProxy} per mesh in the + * @param {MeshProxy[]} meshes - If <code>success</code> is <code>true</code>, a {@link MeshProxy} per mesh in the * <code>Model</code> or <code>PolyVox</code> entity; otherwise <code>undefined</code>. * @param {boolean} success - <code>true</code> if the {@link Entities.getMeshes} call was successful, <code>false</code> * otherwise. The call may be unsuccessful if the requested entity could not be found. diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 4106eb8054..7f72c3f761 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -46,18 +46,18 @@ public: * See also, the <code>"Box"</code> and <code>"Sphere"</code> entity types.</td> * <td>{@link Entities.EntityProperties-Shape|EntityProperties-Shape}</td></tr> * <tr><td><code>"Box"</code></td><td>A rectangular prism. This is a synonym of <code>"Shape"</code> for the case - * where the entity's <code>shape</code> property value is <code>"Cube"</code>.<br /> - * If an entity is created with its <code>type</code> + * where the entity's <code>shape</code> property value is <code>"Cube"</code>. + * <p>If an entity is created with its <code>type</code> * set to <code>"Box"</code> it will always be created with a <code>shape</code> property value of * <code>"Cube"</code>. If an entity of type <code>Shape</code> or <code>Sphere</code> has its <code>shape</code> set - * to <code>"Cube"</code> then its <code>type</code> will be reported as <code>"Box"</code>. + * to <code>"Cube"</code> then its <code>type</code> will be reported as <code>"Box"</code>.</p></td> * <td>{@link Entities.EntityProperties-Box|EntityProperties-Box}</td></tr> * <tr><td><code>"Sphere"</code></td><td>A sphere. This is a synonym of <code>"Shape"</code> for the case - * where the entity's <code>shape</code> property value is <code>"Sphere"</code>.<br /> - * If an entity is created with its <code>type</code> + * where the entity's <code>shape</code> property value is <code>"Sphere"</code>. + * <p>If an entity is created with its <code>type</code> * set to <code>"Sphere"</code> it will always be created with a <code>shape</code> property value of * <code>"Sphere"</code>. If an entity of type <code>Box</code> or <code>Shape</code> has its <code>shape</code> set - * to <code>"Sphere"</code> then its <code>type</code> will be reported as <code>"Sphere"</code>. + * to <code>"Sphere"</code> then its <code>type</code> will be reported as <code>"Sphere"</code>.</td> * <td>{@link Entities.EntityProperties-Sphere|EntityProperties-Sphere}</td></tr> * <tr><td><code>"Model"</code></td><td>A mesh model from a glTF, FBX, or OBJ file.</td> * <td>{@link Entities.EntityProperties-Model|EntityProperties-Model}</td></tr> diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 4f1d871158..0d7b498752 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1859,7 +1859,7 @@ bool GLTFSerializer::readArray(const hifi::ByteArray& bin, int byteOffset, int c break; default: qWarning(modelformat) << "Unknown accessorType: " << accessorType; - blobstream.unsetDevice(); + blobstream.setDevice(nullptr); return false; } for (int i = 0; i < count; ++i) { @@ -1869,13 +1869,13 @@ bool GLTFSerializer::readArray(const hifi::ByteArray& bin, int byteOffset, int c blobstream >> value; outarray.push_back(value); } else { - blobstream.unsetDevice(); + blobstream.setDevice(nullptr); return false; } } } - blobstream.unsetDevice(); + blobstream.setDevice(nullptr); return true; } template<typename T> diff --git a/libraries/gpu/src/gpu/FrameIO.cpp b/libraries/gpu/src/gpu/FrameIO.cpp new file mode 100644 index 0000000000..a0f21df881 --- /dev/null +++ b/libraries/gpu/src/gpu/FrameIO.cpp @@ -0,0 +1,136 @@ +// +// Created by Bradley Austin Davis on 2019/10/03 +// Copyright 2013-2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "FrameIO.h" +#include <shared/Storage.h> +#include <stdexcept> + +using namespace gpu::hfb; + +static bool skip(const uint8_t*& ptr, size_t& remaining, uint32_t size) { + if (remaining < size) { + return false; + } + ptr += size; + remaining -= size; + return true; +} + +template <typename T> +static bool read(const uint8_t*& ptr, size_t& remaining, T& output) { + uint32_t readSize = (uint32_t)sizeof(T); + if (remaining < readSize) { + return false; + } + memcpy(&output, ptr, readSize); + return skip(ptr, remaining, readSize); +} + +Descriptor::Descriptor(const StoragePointer& storage) : storage(storage) { + const auto* const start = storage->data(); + const auto* ptr = storage->data(); + auto remaining = storage->size(); + + try { + // Can't parse files more than 4GB + if (remaining > UINT32_MAX) { + throw std::runtime_error("File too large"); + } + + if (!read(ptr, remaining, header)) { + throw std::runtime_error("Couldn't read binary header"); + } + + if (header.length != storage->size()) { + throw std::runtime_error("Header/Actual size mismatch"); + } + + while (remaining != 0) { + chunks.emplace_back(); + auto& chunk = chunks.back(); + ChunkHeader& chunkHeader = chunk; + if (!read(ptr, remaining, chunkHeader)) { + throw std::runtime_error("Coulnd't read chunk header"); + } + chunk.offset = (uint32_t)(ptr - start); + if (chunk.end() > storage->size()) { + throw std::runtime_error("Chunk too large for file"); + } + if (!skip(ptr, remaining, chunk.length)) { + throw std::runtime_error("Skip chunk data failed"); + } + } + } catch (const std::runtime_error&) { + // LOG somnething + header.magic = 0; + } +} + +size_t Chunk::end() const { + size_t result = offset; + result += length; + return result; +} + +StoragePointer Descriptor::getChunk(uint32_t chunkIndex) const { + if (chunkIndex >= chunks.size()) { + return {}; + } + const auto& chunk = chunks[chunkIndex]; + if (chunk.end() > storage->size()) { + return {}; + } + return storage->createView(chunk.length, chunk.offset); +} + +static void writeUint(uint8_t*& dest, uint32_t value) { + memcpy(dest, &value, sizeof(uint32_t)); + dest += sizeof(uint32_t); +} + +template <typename T> +static void writeChunk(uint8_t*& dest, uint32_t chunkType, const T& chunkData) { + uint32_t chunkSize = static_cast<uint32_t>(chunkData.size()); + writeUint(dest, chunkSize); + writeUint(dest, chunkType); + memcpy(dest, chunkData.data(), chunkSize); + dest += chunkSize; +} + +void gpu::hfb::writeFrame(const std::string& filename, + const std::string& json, + const Buffer& binaryBuffer, + const StorageBuilders& ktxBuilders) { + uint32_t strLen = (uint32_t)json.size(); + uint32_t size = gpu::hfb::HEADER_SIZE + gpu::hfb::CHUNK_HEADER_SIZE + strLen; + size += gpu::hfb::CHUNK_HEADER_SIZE + (uint32_t)binaryBuffer.size(); + for (const auto& builder : ktxBuilders) { + auto storage = builder(); + if (storage) { + size += gpu::hfb::CHUNK_HEADER_SIZE + (uint32_t)storage->size(); + } + } + + auto outputConst = storage::FileStorage::create(filename.c_str(), size, nullptr); + auto output = std::const_pointer_cast<storage::Storage>(outputConst); + auto ptr = output->mutableData(); + writeUint(ptr, gpu::hfb::MAGIC); + writeUint(ptr, gpu::hfb::VERSION); + writeUint(ptr, size); + writeChunk(ptr, gpu::hfb::CHUNK_TYPE_JSON, json); + writeChunk(ptr, gpu::hfb::CHUNK_TYPE_BIN, binaryBuffer); + for (const auto& builder : ktxBuilders) { + static StoragePointer EMPTY_STORAGE{ std::make_shared<storage::MemoryStorage>(0, nullptr) }; + auto storage = builder(); + if (!storage) { + storage = EMPTY_STORAGE; + } + writeChunk(ptr, gpu::hfb::CHUNK_TYPE_KTX, *storage); + } + assert((ptr - output->data()) == size); +} diff --git a/libraries/gpu/src/gpu/FrameIO.h b/libraries/gpu/src/gpu/FrameIO.h index 4de4cf5fe7..cf653cc4ae 100644 --- a/libraries/gpu/src/gpu/FrameIO.h +++ b/libraries/gpu/src/gpu/FrameIO.h @@ -12,17 +12,72 @@ #include "Forward.h" #include "Format.h" +#include <shared/Storage.h> + #include <functional> namespace gpu { -using TextureCapturer = std::function<void(const std::string&, const TexturePointer&, uint16 layer)>; -using TextureLoader = std::function<void(const std::string&, const TexturePointer&, uint16 layer)>; +using TextureCapturer = std::function<storage::StoragePointer(const TexturePointer&)>; +//using TextureLoader = std::function<void(const storage::StoragePointer& storage, const TexturePointer&)>; void writeFrame(const std::string& filename, const FramePointer& frame, const TextureCapturer& capturer = nullptr); -FramePointer readFrame(const std::string& filename, uint32_t externalTexture, const TextureLoader& loader = nullptr); +FramePointer readFrame(const std::string& filename, uint32_t externalTexture); -using IndexOptimizer = std::function<void(Primitive, uint32_t faceCount, uint32_t indexCount, uint32_t* indices )>; -void optimizeFrame(const std::string& filename, const IndexOptimizer& optimizer); +namespace hfb { + +using Storage = storage::Storage; +using StoragePointer = storage::Pointer; +using StorageBuilders = storage::Builders; + +constexpr const char* const EXTENSION{ ".hfb" }; +constexpr uint32_t HEADER_SIZE{ sizeof(uint32_t) * 3 }; +constexpr uint32_t CHUNK_HEADER_SIZE = sizeof(uint32_t) * 2; +constexpr uint32_t MAGIC{ 0x49464948 }; +constexpr uint32_t VERSION{ 0x01 }; +constexpr uint32_t CHUNK_TYPE_JSON{ 0x4E4F534A }; +constexpr uint32_t CHUNK_TYPE_KTX{ 0x0058544b }; +constexpr uint32_t CHUNK_TYPE_BIN{ 0x004E4942 }; +constexpr uint32_t CHUNK_TYPE_PNG{ 0x00474E50 }; + +using Buffer = std::vector<uint8_t>; + +struct Header { + uint32_t magic{ 0 }; + uint32_t version{ 0 }; + uint32_t length{ 0 }; +}; + +struct ChunkHeader { + uint32_t length{ 0 }; + uint32_t type{ 0 }; +}; + +struct Chunk : public ChunkHeader { + uint32_t offset{ 0 }; + + size_t end() const; +}; + +using Chunks = std::vector<Chunk>; + +struct Descriptor { + using Pointer = std::shared_ptr<Descriptor>; + + Header header; + Chunks chunks; + StoragePointer storage; + + Descriptor(const StoragePointer& storage); + operator bool() const { return header.magic == MAGIC; } + StoragePointer getChunk(uint32_t chunk) const; +}; + +void writeFrame(const std::string& filename, + const std::string& json, + const Buffer& binaryBuffer, + const StorageBuilders& pngBuffers); + +} // namespace hfb } // namespace gpu diff --git a/libraries/gpu/src/gpu/FrameIOKeys.h b/libraries/gpu/src/gpu/FrameIOKeys.h index 5d5f8a5bd9..1a98d0decd 100644 --- a/libraries/gpu/src/gpu/FrameIOKeys.h +++ b/libraries/gpu/src/gpu/FrameIOKeys.h @@ -11,128 +11,130 @@ namespace gpu { namespace keys { -static const char* binary = "binary"; -static const char* L00 = "L00"; -static const char* L1m1 = "L1m1"; -static const char* L10 = "L10"; -static const char* L11 = "L11"; -static const char* L2m2 = "L2m2"; -static const char* L2m1 = "L2m1"; -static const char* L20 = "L20"; -static const char* L21 = "L21"; -static const char* L22 = "L22"; -static const char* eyeProjections = "eyeProjections"; -static const char* eyeViews = "eyeViews"; -static const char* alphaToCoverageEnable = "alphaToCoverageEnable"; -static const char* antialisedLineEnable = "antialisedLineEnable"; -static const char* attributes = "attributes"; -static const char* batches = "batches"; -static const char* blendFunction = "blendFunction"; -static const char* borderColor = "borderColor"; -static const char* bufferMask = "bufferMask"; -static const char* buffers = "buffers"; -static const char* capturedTextures = "capturedTextures"; -static const char* channel = "channel"; -static const char* colorAttachments = "colorAttachments"; -static const char* colorWriteMask = "colorWriteMask"; -static const char* commands = "commands"; -static const char* comparisonFunction = "comparisonFunction"; -static const char* cullMode = "cullMode"; -static const char* data = "data"; -static const char* depth = "depth"; -static const char* depthBias = "depthBias"; -static const char* depthBiasSlopeScale = "depthBiasSlopeScale"; -static const char* depthClampEnable = "depthClampEnable"; -static const char* depthStencilAttachment = "depthStencilAttachment"; -static const char* depthTest = "depthTest"; -static const char* drawCallInfos = "drawCallInfos"; -static const char* drawcallUniform = "drawcallUniform"; -static const char* drawcallUniformReset = "drawcallUniformReset"; -static const char* element = "element"; -static const char* fillMode = "fillMode"; -static const char* filter = "filter"; -static const char* formats = "formats"; -static const char* frameIndex = "frameIndex"; -static const char* framebuffer = "framebuffer"; -static const char* framebuffers = "framebuffers"; -static const char* frequency = "frequency"; -static const char* frontFaceClockwise = "frontFaceClockwise"; -static const char* height = "height"; -static const char* id = "id"; -static const char* ktxFile = "ktxFile"; -static const char* layers = "layers"; -static const char* maxAnisotropy = "maxAnisotropy"; -static const char* maxMip = "maxMip"; -static const char* minMip = "minMip"; -static const char* mipOffset = "mipOffset"; -static const char* mips = "mips"; -static const char* multisampleEnable = "multisampleEnable"; -static const char* name = "name"; -static const char* namedData = "namedData"; -static const char* names = "names"; -static const char* objects = "objects"; -static const char* offset = "offset"; -static const char* pipelines = "pipelines"; -static const char* pose = "pose"; -static const char* profileRanges = "profileRanges"; -static const char* program = "program"; -static const char* programs = "programs"; -static const char* projectionJitter = "projectionJitter"; -static const char* queries = "queries"; -static const char* sampleCount = "sampleCount"; -static const char* sampleMask = "sampleMask"; -static const char* sampler = "sampler"; -static const char* samples = "samples"; -static const char* scissorEnable = "scissorEnable"; -static const char* shaders = "shaders"; -static const char* size = "size"; -static const char* skybox = "skybox"; -static const char* slot = "slot"; -static const char* source = "source"; -static const char* state = "state"; -static const char* stencilActivation = "stencilActivation"; -static const char* stencilTestBack = "stencilTestBack"; -static const char* stencilTestFront = "stencilTestFront"; -static const char* stereo = "stereo"; -static const char* subresource = "subresource"; -static const char* swapchains = "swapchains"; -static const char* texelFormat = "texelFormat"; -static const char* texture = "texture"; -static const char* textureTables = "textureTables"; -static const char* textures = "textures"; -static const char* transforms = "transforms"; -static const char* type = "type"; -static const char* usageType = "usageType"; -static const char* view = "view"; -static const char* width = "width"; -static const char* wrapModeU = "wrapModeU"; -static const char* wrapModeV = "wrapModeV"; -static const char* wrapModeW = "wrapModeW"; +constexpr const char* binary = "binary"; +constexpr const char* L00 = "L00"; +constexpr const char* L1m1 = "L1m1"; +constexpr const char* L10 = "L10"; +constexpr const char* L11 = "L11"; +constexpr const char* L2m2 = "L2m2"; +constexpr const char* L2m1 = "L2m1"; +constexpr const char* L20 = "L20"; +constexpr const char* L21 = "L21"; +constexpr const char* L22 = "L22"; + +constexpr const char* eyeProjections = "eyeProjections"; +constexpr const char* eyeViews = "eyeViews"; +constexpr const char* alphaToCoverageEnable = "alphaToCoverageEnable"; +constexpr const char* antialisedLineEnable = "antialisedLineEnable"; +constexpr const char* attributes = "attributes"; +constexpr const char* batches = "batches"; +constexpr const char* blendFunction = "blendFunction"; +constexpr const char* borderColor = "borderColor"; +constexpr const char* bufferMask = "bufferMask"; +constexpr const char* buffers = "buffers"; +constexpr const char* capturedTextures = "capturedTextures"; +constexpr const char* channel = "channel"; +constexpr const char* chunk = "chunk"; +constexpr const char* colorAttachments = "colorAttachments"; +constexpr const char* colorWriteMask = "colorWriteMask"; +constexpr const char* commands = "commands"; +constexpr const char* comparisonFunction = "comparisonFunction"; +constexpr const char* cullMode = "cullMode"; +constexpr const char* data = "data"; +constexpr const char* depth = "depth"; +constexpr const char* depthBias = "depthBias"; +constexpr const char* depthBiasSlopeScale = "depthBiasSlopeScale"; +constexpr const char* depthClampEnable = "depthClampEnable"; +constexpr const char* depthStencilAttachment = "depthStencilAttachment"; +constexpr const char* depthTest = "depthTest"; +constexpr const char* drawCallInfos = "drawCallInfos"; +constexpr const char* drawcallUniform = "drawcallUniform"; +constexpr const char* drawcallUniformReset = "drawcallUniformReset"; +constexpr const char* element = "element"; +constexpr const char* fillMode = "fillMode"; +constexpr const char* filter = "filter"; +constexpr const char* formats = "formats"; +constexpr const char* frameIndex = "frameIndex"; +constexpr const char* framebuffer = "framebuffer"; +constexpr const char* framebuffers = "framebuffers"; +constexpr const char* frequency = "frequency"; +constexpr const char* frontFaceClockwise = "frontFaceClockwise"; +constexpr const char* height = "height"; +constexpr const char* id = "id"; +constexpr const char* ktxFile = "ktxFile"; +constexpr const char* layers = "layers"; +constexpr const char* maxAnisotropy = "maxAnisotropy"; +constexpr const char* maxMip = "maxMip"; +constexpr const char* minMip = "minMip"; +constexpr const char* mipOffset = "mipOffset"; +constexpr const char* mips = "mips"; +constexpr const char* multisampleEnable = "multisampleEnable"; +constexpr const char* name = "name"; +constexpr const char* namedData = "namedData"; +constexpr const char* names = "names"; +constexpr const char* objects = "objects"; +constexpr const char* offset = "offset"; +constexpr const char* pipelines = "pipelines"; +constexpr const char* pose = "pose"; +constexpr const char* profileRanges = "profileRanges"; +constexpr const char* program = "program"; +constexpr const char* programs = "programs"; +constexpr const char* projectionJitter = "projectionJitter"; +constexpr const char* queries = "queries"; +constexpr const char* sampleCount = "sampleCount"; +constexpr const char* sampleMask = "sampleMask"; +constexpr const char* sampler = "sampler"; +constexpr const char* samples = "samples"; +constexpr const char* scissorEnable = "scissorEnable"; +constexpr const char* shaders = "shaders"; +constexpr const char* size = "size"; +constexpr const char* skybox = "skybox"; +constexpr const char* slot = "slot"; +constexpr const char* source = "source"; +constexpr const char* state = "state"; +constexpr const char* stencilActivation = "stencilActivation"; +constexpr const char* stencilTestBack = "stencilTestBack"; +constexpr const char* stencilTestFront = "stencilTestFront"; +constexpr const char* stereo = "stereo"; +constexpr const char* subresource = "subresource"; +constexpr const char* swapchains = "swapchains"; +constexpr const char* texelFormat = "texelFormat"; +constexpr const char* texture = "texture"; +constexpr const char* textureTables = "textureTables"; +constexpr const char* textures = "textures"; +constexpr const char* transforms = "transforms"; +constexpr const char* type = "type"; +constexpr const char* usageType = "usageType"; +constexpr const char* view = "view"; +constexpr const char* width = "width"; +constexpr const char* wrapModeU = "wrapModeU"; +constexpr const char* wrapModeV = "wrapModeV"; +constexpr const char* wrapModeW = "wrapModeW"; -static const char* backWriteMask = "backWriteMask"; -static const char* frontWriteMask = "frontWriteMask"; -static const char* reference = "reference"; -static const char* readMask = "readMask"; -static const char* failOp = "failOp"; -static const char* depthFailOp = "depthFailOp"; -static const char* passOp = "passOp"; -static const char* enabled = "enabled"; -static const char* blend = "blend"; -static const char* flags = "flags"; -static const char* writeMask = "writeMask"; -static const char* function = "function"; -static const char* sourceColor = "sourceColor"; -static const char* sourceAlpha = "sourceAlpha"; -static const char* destColor = "destColor"; -static const char* destAlpha = "destAlpha"; -static const char* opColor = "opColor"; -static const char* opAlpha = "opAlpha"; -static const char* enable = "enable"; -static const char* contextDisable = "contextDisable"; +constexpr const char* backWriteMask = "backWriteMask"; +constexpr const char* frontWriteMask = "frontWriteMask"; +constexpr const char* reference = "reference"; +constexpr const char* readMask = "readMask"; +constexpr const char* failOp = "failOp"; +constexpr const char* depthFailOp = "depthFailOp"; +constexpr const char* passOp = "passOp"; +constexpr const char* enabled = "enabled"; +constexpr const char* blend = "blend"; +constexpr const char* flags = "flags"; +constexpr const char* writeMask = "writeMask"; +constexpr const char* function = "function"; +constexpr const char* sourceColor = "sourceColor"; +constexpr const char* sourceAlpha = "sourceAlpha"; +constexpr const char* destColor = "destColor"; +constexpr const char* destAlpha = "destAlpha"; +constexpr const char* opColor = "opColor"; +constexpr const char* opAlpha = "opAlpha"; +constexpr const char* enable = "enable"; +constexpr const char* contextDisable = "contextDisable"; -static const char* COMMAND_NAMES[] = { +constexpr const char* COMMAND_NAMES[] = { "draw", "drawIndexed", "drawInstanced", diff --git a/libraries/gpu/src/gpu/FrameReader.cpp b/libraries/gpu/src/gpu/FrameReader.cpp index 740ec2b26f..d636c6aaca 100644 --- a/libraries/gpu/src/gpu/FrameReader.cpp +++ b/libraries/gpu/src/gpu/FrameReader.cpp @@ -10,9 +10,7 @@ #include <nlohmann/json.hpp> #include <unordered_map> -#include <QtCore/QFileInfo> -#include <QtCore/QDir> - +#include <shared/FileUtils.h> #include <ktx/KTX.h> #include "Frame.h" #include "Batch.h" @@ -22,24 +20,18 @@ namespace gpu { using json = nlohmann::json; +using StoragePointer = storage::StoragePointer; +using FileStorage = storage::FileStorage; class Deserializer { public: - static std::string getBaseName(const std::string& filename) { - static const std::string ext{ ".json" }; - if (std::string::npos != filename.rfind(ext)) { - return filename.substr(0, filename.size() - ext.size()); - } - return filename; - } - static std::string getBaseDir(const std::string& filename) { std::string result; if (0 == filename.find("assets:")) { auto lastSlash = filename.rfind('/'); result = filename.substr(0, lastSlash + 1); } else { - result = QFileInfo(filename.c_str()).absoluteDir().canonicalPath().toStdString(); + result = FileUtils::getParentPath(filename.c_str()).toStdString(); if (*result.rbegin() != '/') { result += '/'; } @@ -47,15 +39,17 @@ public: return result; } - Deserializer(const std::string& filename, uint32_t externalTexture, const TextureLoader& loader) : - basename(getBaseName(filename)), basedir(getBaseDir(filename)), externalTexture(externalTexture), textureLoader(loader) { + Deserializer(const std::string& filename_, uint32_t externalTexture = 0) : + filename(filename_), basedir(getBaseDir(filename_)), mappedFile(std::make_shared<FileStorage>(filename.c_str())), + externalTexture(externalTexture) { + descriptor = std::make_shared<hfb::Descriptor>(mappedFile); } - const std::string basename; + const std::string filename; const std::string basedir; - std::string binaryFile; + const StoragePointer mappedFile; const uint32_t externalTexture; - TextureLoader textureLoader; + hfb::Descriptor::Pointer descriptor; std::vector<ShaderPointer> shaders; std::vector<ShaderPointer> programs; std::vector<TexturePointer> textures; @@ -69,10 +63,13 @@ public: std::vector<QueryPointer> queries; json frameNode; FramePointer readFrame(); - void optimizeFrame(const IndexOptimizer& optimizer); FramePointer deserializeFrame(); + std::string getStringChunk(size_t chunkIndex) { + auto storage = descriptor->getChunk((uint32_t)chunkIndex); + return std::string{ (const char*)storage->data(), storage->size() }; + } void readBuffers(const json& node); @@ -148,12 +145,11 @@ public: } template <typename T, typename TT = T> - static bool readBatchCacheTransformed(typename Batch::Cache<T>::Vector& dest, - const json& node, - const std::string& name, - std::function<TT(const json&)> f = [](const json& node) -> TT { - return node.get<TT>(); - }) { + static bool readBatchCacheTransformed( + typename Batch::Cache<T>::Vector& dest, + const json& node, + const std::string& name, + std::function<TT(const json&)> f = [](const json& node) -> TT { return node.get<TT>(); }) { if (node.count(name)) { const auto& arrayNode = node[name]; for (const auto& entry : arrayNode) { @@ -230,12 +226,8 @@ public: static void readCommand(const json& node, Batch& batch); }; -FramePointer readFrame(const std::string& filename, uint32_t externalTexture, const TextureLoader& loader) { - return Deserializer(filename, externalTexture, loader).readFrame(); -} - -void optimizeFrame(const std::string& filename, const IndexOptimizer& optimizer) { - return Deserializer(filename, 0, {}).optimizeFrame(optimizer); +FramePointer readFrame(const std::string& filename, uint32_t externalTexture) { + return Deserializer(filename, externalTexture).readFrame(); } } // namespace gpu @@ -243,9 +235,9 @@ void optimizeFrame(const std::string& filename, const IndexOptimizer& optimizer) using namespace gpu; void Deserializer::readBuffers(const json& buffersNode) { - storage::FileStorage mappedFile(binaryFile.c_str()); - const auto mappedSize = mappedFile.size(); - const auto* mapped = mappedFile.data(); + const auto& binaryChunk = descriptor->chunks[1]; + const auto* mapped = mappedFile->data() + binaryChunk.offset; + const auto mappedSize = binaryChunk.length; size_t bufferCount = buffersNode.size(); buffers.reserve(buffersNode.size()); size_t offset = 0; @@ -311,6 +303,8 @@ Sampler Deserializer::readSampler(const json& node) { return result; } +constexpr uint32_t INVALID_CHUNK_INDEX{ (uint32_t)-1 }; + TexturePointer Deserializer::readTexture(const json& node, uint32_t external) { if (node.is_null()) { return nullptr; @@ -319,8 +313,17 @@ TexturePointer Deserializer::readTexture(const json& node, uint32_t external) { std::string source; readOptional(source, node, keys::source); + uint32_t chunkIndex = INVALID_CHUNK_INDEX; + readOptional(chunkIndex, node, keys::chunk); + std::string ktxFile; readOptional(ktxFile, node, keys::ktxFile); + if (!ktxFile.empty()) { + if (!FileUtils::exists(ktxFile.c_str())) { + qDebug() << "Warning" << ktxFile.c_str() << " not found, ignoring"; + ktxFile = {}; + } + } Element ktxTexelFormat, ktxMipFormat; if (!ktxFile.empty()) { // If we get a texture that starts with ":" we need to re-route it to the resources directory @@ -330,8 +333,8 @@ TexturePointer Deserializer::readTexture(const json& node, uint32_t external) { frameReaderPath.replace("libraries/gpu/src/gpu/framereader.cpp", "interface/resources", Qt::CaseInsensitive); ktxFile.replace(0, 1, frameReaderPath.toStdString()); } - if (QFileInfo(ktxFile.c_str()).isRelative()) { - ktxFile = basedir + ktxFile; + if (FileUtils::isRelative(ktxFile.c_str())) { + ktxFile = basedir + "/" + ktxFile; } ktx::StoragePointer ktxStorage{ new storage::FileStorage(ktxFile.c_str()) }; auto ktxObject = ktx::KTX::create(ktxStorage); @@ -364,12 +367,14 @@ TexturePointer Deserializer::readTexture(const json& node, uint32_t external) { auto& texture = *result; readOptional(texture._source, node, keys::source); - if (!ktxFile.empty()) { - if (QFileInfo(ktxFile.c_str()).isRelative()) { - ktxFile = basedir + "/" + ktxFile; - } + + if (chunkIndex != INVALID_CHUNK_INDEX) { + auto ktxChunk = descriptor->getChunk(chunkIndex); + texture.setKtxBacking(ktxChunk); + } else if (!ktxFile.empty()) { + texture.setSource(ktxFile); texture.setKtxBacking(ktxFile); - } + } return result; } @@ -405,11 +410,11 @@ ShaderPointer Deserializer::readShader(const json& node) { // FIXME support procedural shaders Shader::Type type = node[keys::type]; std::string name = node[keys::name]; - // Using the serialized ID is bad, because it's generated at - // cmake time, and can change across platforms or when + // Using the serialized ID is bad, because it's generated at + // cmake time, and can change across platforms or when // shaders are added or removed // uint32_t id = node[keys::id]; - + uint32_t id = shadersIdsByName[name]; ShaderPointer result; switch (type) { @@ -555,11 +560,15 @@ StatePointer readState(const json& node) { State::Data data; Deserializer::readOptionalTransformed<State::Flags>(data.flags, node, keys::flags, &readStateFlags); - Deserializer::readOptionalTransformed<State::BlendFunction>(data.blendFunction, node, keys::blendFunction, &readBlendFunction); + Deserializer::readOptionalTransformed<State::BlendFunction>(data.blendFunction, node, keys::blendFunction, + &readBlendFunction); Deserializer::readOptionalTransformed<State::DepthTest>(data.depthTest, node, keys::depthTest, &readDepthTest); - Deserializer::readOptionalTransformed<State::StencilActivation>(data.stencilActivation, node, keys::stencilActivation, &readStencilActivation); - Deserializer::readOptionalTransformed<State::StencilTest>(data.stencilTestFront, node, keys::stencilTestFront, &readStencilTest); - Deserializer::readOptionalTransformed<State::StencilTest>(data.stencilTestBack, node, keys::stencilTestBack, &readStencilTest); + Deserializer::readOptionalTransformed<State::StencilActivation>(data.stencilActivation, node, keys::stencilActivation, + &readStencilActivation); + Deserializer::readOptionalTransformed<State::StencilTest>(data.stencilTestFront, node, keys::stencilTestFront, + &readStencilTest); + Deserializer::readOptionalTransformed<State::StencilTest>(data.stencilTestBack, node, keys::stencilTestBack, + &readStencilTest); Deserializer::readOptional(data.colorWriteMask, node, keys::colorWriteMask); Deserializer::readOptional(data.cullMode, node, keys::cullMode); Deserializer::readOptional(data.depthBias, node, keys::depthBias); @@ -799,25 +808,15 @@ StereoState readStereoState(const json& node) { FramePointer Deserializer::deserializeFrame() { - { - std::string filename{ basename + ".json" }; - storage::FileStorage mappedFile(filename.c_str()); - frameNode = json::parse(std::string((const char*)mappedFile.data(), mappedFile.size())); + if (!descriptor.operator bool()) { + return {}; } + frameNode = json::parse(getStringChunk(0)); + FramePointer result = std::make_shared<Frame>(); auto& frame = *result; - if (frameNode[keys::binary].is_string()) { - binaryFile = frameNode[keys::binary]; - if (QFileInfo(binaryFile.c_str()).isRelative()) { - binaryFile = basedir + "/" + binaryFile; - } - } else { - binaryFile = basename + ".bin"; - } - - if (frameNode.count(keys::buffers)) { readBuffers(frameNode[keys::buffers]); } @@ -830,19 +829,7 @@ FramePointer Deserializer::deserializeFrame() { formats = readArray<Stream::FormatPointer>(frameNode, keys::formats, [](const json& node) { return readFormat(node); }); - auto textureReader = [this](const json& node) { return readTexture(node, externalTexture); }; - textures = readArray<TexturePointer>(frameNode, keys::textures, textureReader); - if (textureLoader) { - std::vector<uint32_t> capturedTextures = readNumericVector<uint32_t>(frameNode[keys::capturedTextures]); - for (const auto& index : capturedTextures) { - const auto& texturePointer = textures[index]; - uint16 layers = std::max<uint16>(texturePointer->getNumSlices(), 1); - for (uint16 layer = 0; layer < layers; ++layer) { - std::string filename = basename + "." + std::to_string(index) + "." + std::to_string(layer) + ".png"; - textureLoader(filename, texturePointer, layer); - } - } - } + textures = readArray<TexturePointer>(frameNode, keys::textures, [this](const json& node) { return readTexture(node, externalTexture); }); // Must come after textures auto textureTableReader = [this](const json& node) { return readTextureTable(node); }; @@ -868,87 +855,22 @@ FramePointer Deserializer::deserializeFrame() { } } + for (uint32_t i = 0; i < textures.size(); ++i) { + const auto& texturePtr = textures[i]; + if (!texturePtr) { + continue; + } + const auto& texture = *texturePtr; + if (texture.getUsageType() == gpu::TextureUsageType::RESOURCE && texture.source().empty()) { + qDebug() << "Empty source "; + } + } + return result; } - - FramePointer Deserializer::readFrame() { auto result = deserializeFrame(); result->finish(); return result; } - -void Deserializer::optimizeFrame(const IndexOptimizer& optimizer) { - auto result = deserializeFrame(); - auto& frame = *result; - - - // optimize the index buffers? - struct CurrentIndexBuffer { - Offset offset{ 0 }; - BufferPointer buffer; - Type type{ gpu::Type::INT32 }; - Primitive primitve{ Primitive::TRIANGLES }; - uint32_t numIndices{ 0 }; - uint32_t startIndex{ 0 }; - }; - - std::vector<CurrentIndexBuffer> captured; - for (auto& batch : frame.batches) { - - CurrentIndexBuffer currentIndexBuffer; - batch->forEachCommand([&](Batch::Command cmd, const Batch::Param* params){ - switch(cmd) { - case Batch::Command::COMMAND_setIndexBuffer: - currentIndexBuffer.offset = params[0]._size; - currentIndexBuffer.buffer = batch->_buffers.get(params[1]._int); - currentIndexBuffer.type = (Type)params[2]._int; - break; - - case Batch::Command::COMMAND_drawIndexed: - currentIndexBuffer.startIndex = params[0]._int; - currentIndexBuffer.numIndices = params[1]._int; - currentIndexBuffer.primitve = (Primitive)params[2]._int; - captured.emplace_back(currentIndexBuffer); - break; - - case Batch::Command::COMMAND_drawIndexedInstanced: - currentIndexBuffer.startIndex = params[1]._int; - currentIndexBuffer.numIndices = params[2]._int; - currentIndexBuffer.primitve = (Primitive)params[3]._int; - captured.emplace_back(currentIndexBuffer); - break; - - default: - break; - } - }); - } - - - std::string optimizedBinaryFile = basename + "_optimized.bin"; - QFile(binaryFile.c_str()).copy(optimizedBinaryFile.c_str()); - { - storage::FileStorage mappedFile(optimizedBinaryFile.c_str()); - std::set<BufferPointer> uniqueBuffers; - for (const auto& capturedIndexData : captured) { - if (uniqueBuffers.count(capturedIndexData.buffer)) { - continue; - } - uniqueBuffers.insert(capturedIndexData.buffer); - auto bufferOffset = bufferOffsets[capturedIndexData.buffer]; - auto& buffer = *capturedIndexData.buffer; - const auto& count = capturedIndexData.numIndices; - auto indices = (uint32_t*)buffer.editData(); - optimizer(capturedIndexData.primitve, count / 3, count, indices); - memcpy(mappedFile.mutableData() + bufferOffset, indices, sizeof(uint32_t) * count); - } - } - frameNode[keys::binary] = optimizedBinaryFile; - { - std::string frameJson = frameNode.dump(); - std::string filename = basename + "_optimized.json"; - storage::FileStorage::create(filename.c_str(), frameJson.size(), (const uint8_t*)frameJson.data()); - } -} diff --git a/libraries/gpu/src/gpu/FrameWriter.cpp b/libraries/gpu/src/gpu/FrameWriter.cpp index f348827385..761f37a620 100644 --- a/libraries/gpu/src/gpu/FrameWriter.cpp +++ b/libraries/gpu/src/gpu/FrameWriter.cpp @@ -20,7 +20,7 @@ using json = nlohmann::json; class Serializer { public: - const std::string basename; + const std::string filename; const TextureCapturer textureCapturer; std::unordered_map<ShaderPointer, uint32_t> shaderMap; std::unordered_map<ShaderPointer, uint32_t> programMap; @@ -32,8 +32,11 @@ public: std::unordered_map<FramebufferPointer, uint32_t> framebufferMap; std::unordered_map<SwapChainPointer, uint32_t> swapchainMap; std::unordered_map<QueryPointer, uint32_t> queryMap; + std::unordered_set<TexturePointer> captureTextures; + hfb::Buffer binaryBuffer; + hfb::StorageBuilders ktxBuilders; - Serializer(const std::string& basename, const TextureCapturer& capturer) : basename(basename), textureCapturer(capturer) {} + Serializer(const std::string& basename, const TextureCapturer& capturer) : filename(basename + hfb::EXTENSION), textureCapturer(capturer) {} template <typename T> static uint32_t getGlobalIndex(const T& value, std::unordered_map<T, uint32_t>& map) { @@ -129,7 +132,7 @@ public: json writeProgram(const ShaderPointer& program); json writeNamedBatchData(const Batch::NamedBatchData& namedData); - json writeCapturableTextures(const Frame& frame); + void findCapturableTextures(const Frame& frame); void writeBinaryBlob(); static std::string toBase64(const std::vector<uint8_t>& v); static json writeIrradiance(const SHPointer& irradiance); @@ -146,7 +149,7 @@ public: static json writeTransform(const Transform& t) { return writeMat4(t.getMatrix()); } static json writeCommand(size_t index, const Batch& batch); static json writeSampler(const Sampler& sampler); - static json writeTexture(const TexturePointer& texture); + json writeTexture(const TexturePointer& texture); static json writeFormat(const Stream::FormatPointer& format); static json writeQuery(const QueryPointer& query); static json writeShader(const ShaderPointer& shader); @@ -389,9 +392,17 @@ json Serializer::writeTexture(const TexturePointer& texturePointer) { const auto* storage = texture._storage.get(); const auto* ktxStorage = dynamic_cast<const Texture::KtxStorage*>(storage); if (ktxStorage) { - result[keys::ktxFile] = ktxStorage->_filename; - } else { - // TODO serialize the backing storage + result[keys::chunk] = 2 + ktxBuilders.size(); + auto filename = ktxStorage->_filename; + ktxBuilders.push_back([=] { + return std::make_shared<storage::FileStorage>(filename.c_str()); + }); + } else if (textureCapturer && captureTextures.count(texturePointer) != 0) { + result[keys::chunk] = 2 + ktxBuilders.size(); + auto storage = textureCapturer(texturePointer); + ktxBuilders.push_back([=] { + return storage; + }); } } return result; @@ -673,14 +684,8 @@ json Serializer::writeQuery(const QueryPointer& queryPointer) { return result; } -json Serializer::writeCapturableTextures(const Frame& frame) { - if (!textureCapturer) { - return json::array(); - } - +void Serializer::findCapturableTextures(const Frame& frame) { std::unordered_set<TexturePointer> writtenRenderbuffers; - std::unordered_set<TexturePointer> captureTextures; - auto maybeCaptureTexture = [&](const TexturePointer& texture) { // Not a valid texture if (!texture) { @@ -755,20 +760,6 @@ json Serializer::writeCapturableTextures(const Frame& frame) { } } } - - json result = json::array(); - for (const auto& texture : captureTextures) { - if (textureCapturer) { - auto index = textureMap[texture]; - auto layers = std::max<uint16>(texture->getNumSlices(), 1); - for (uint16 layer = 0; layer < layers; ++layer) { - std::string textureFilename = basename + "." + std::to_string(index) + "." + std::to_string(layer) + ".png"; - textureCapturer(textureFilename, texture, layer); - } - result.push_back(index); - } - } - return result; } void Serializer::writeFrame(const Frame& frame) { @@ -780,7 +771,7 @@ void Serializer::writeFrame(const Frame& frame) { } frameNode[keys::stereo] = writeStereoState(frame.stereoState); - frameNode[keys::capturedTextures] = writeCapturableTextures(frame); + findCapturableTextures(frame); frameNode[keys::frameIndex] = frame.frameIndex; frameNode[keys::view] = writeMat4(frame.view); frameNode[keys::pose] = writeMat4(frame.pose); @@ -797,35 +788,21 @@ void Serializer::writeFrame(const Frame& frame) { // Serialize textures and buffers last, since the maps they use can be populated by some of the above code // Serialize textures - serializeMap(frameNode, keys::textures, textureMap, writeTexture); + serializeMap(frameNode, keys::textures, textureMap, std::bind(&Serializer::writeTexture, this, _1)); // Serialize buffers serializeMap(frameNode, keys::buffers, bufferMap, writeBuffer); - { - std::string frameJson = frameNode.dump(); - std::string filename = basename + ".json"; - storage::FileStorage::create(filename.c_str(), frameJson.size(), (const uint8_t*)frameJson.data()); - } - writeBinaryBlob(); - frameNode[keys::binary] = basename + ".bin"; + + hfb::writeFrame(filename, frameNode.dump(), binaryBuffer, ktxBuilders); } void Serializer::writeBinaryBlob() { const auto buffers = mapToVector(bufferMap); auto accumulator = [](size_t total, const BufferPointer& buffer) { return total + (buffer ? buffer->getSize() : 0); }; size_t totalSize = std::accumulate(buffers.begin(), buffers.end(), (size_t)0, accumulator); - - const auto blobFilename = basename + ".bin"; - QFile file(blobFilename.c_str()); - if (!file.open(QFile::ReadWrite | QIODevice::Truncate)) { - throw std::runtime_error("Unable to open file for writing"); - } - if (!file.resize(totalSize)) { - throw std::runtime_error("Unable to resize file"); - } - - auto mapped = file.map(0, totalSize); + binaryBuffer.resize(totalSize); + auto mapped = binaryBuffer.data(); size_t offset = 0; for (const auto& bufferPointer : buffers) { @@ -838,7 +815,4 @@ void Serializer::writeBinaryBlob() { memcpy(mapped + offset, bufferData, bufferSize); offset += bufferSize; } - if (!file.unmap(mapped)) { - throw std::runtime_error("Unable to unmap file"); - } } diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 5e2485941d..debedf02a5 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -343,6 +343,7 @@ public: class KtxStorage : public Storage { public: + KtxStorage(const storage::StoragePointer& storage); KtxStorage(const std::string& filename); KtxStorage(const cache::FilePointer& file); PixelsPointer getMipFace(uint16 level, uint8 face = 0) const override; @@ -366,6 +367,7 @@ public: static std::vector<std::pair<std::shared_ptr<storage::FileStorage>, std::shared_ptr<std::mutex>>> _cachedKtxFiles; static std::mutex _cachedKtxFilesMutex; + storage::StoragePointer _storage; std::string _filename; cache::FilePointer _cacheEntry; std::atomic<uint8_t> _minMipLevelAvailable; @@ -543,6 +545,7 @@ public: Size getStoredSize() const; void setStorage(std::unique_ptr<Storage>& newStorage); + void setKtxBacking(const storage::StoragePointer& storage); void setKtxBacking(const std::string& filename); void setKtxBacking(const cache::FilePointer& cacheEntry); diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index f471baf2c7..a5cea3e60e 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -159,7 +159,31 @@ struct IrradianceKTXPayload { }; const std::string IrradianceKTXPayload::KEY{ "hifi.irradianceSH" }; -KtxStorage::KtxStorage(const cache::FilePointer& cacheEntry) : KtxStorage(cacheEntry->getFilepath()) { +KtxStorage::KtxStorage(const storage::StoragePointer& storage) : _storage(storage) { + auto ktxPointer = ktx::KTX::create(storage); + _ktxDescriptor.reset(new ktx::KTXDescriptor(ktxPointer->toDescriptor())); + if (_ktxDescriptor->images.size() < _ktxDescriptor->header.numberOfMipmapLevels) { + qWarning() << "Bad images found in ktx"; + } + + _offsetToMinMipKV = _ktxDescriptor->getValueOffsetForKey(ktx::HIFI_MIN_POPULATED_MIP_KEY); + if (_offsetToMinMipKV) { + auto data = storage->data() + ktx::KTX_HEADER_SIZE + _offsetToMinMipKV; + _minMipLevelAvailable = *data; + } else { + // Assume all mip levels are available + _minMipLevelAvailable = 0; + } + + // now that we know the ktx, let's get the header info to configure this Texture::Storage: + Format mipFormat = Format::COLOR_BGRA_32; + Format texelFormat = Format::COLOR_SRGBA_32; + if (Texture::evalTextureFormat(_ktxDescriptor->header, mipFormat, texelFormat)) { + _format = mipFormat; + } +} + +KtxStorage::KtxStorage(const cache::FilePointer& cacheEntry) : KtxStorage(cacheEntry->getFilepath()) { _cacheEntry = cacheEntry; } @@ -228,28 +252,31 @@ void KtxStorage::releaseOpenKtxFiles() { PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const { auto faceOffset = _ktxDescriptor->getMipFaceTexelsOffset(level, face); auto faceSize = _ktxDescriptor->getMipFaceTexelsSize(level, face); + storage::StoragePointer storageView; if (faceSize != 0 && faceOffset != 0) { - std::lock_guard<std::mutex> lock(*_cacheFileMutex); - auto file = maybeOpenFile(); - if (file) { - auto storageView = file->createView(faceSize, faceOffset); - if (storageView) { - return storageView->toMemoryStorage(); - } else { - qWarning() << "Failed to get a valid storageView for faceSize=" << faceSize << " faceOffset=" << faceOffset << "out of valid file " << QString::fromStdString(_filename); - } + if (_storage) { + storageView = _storage->createView(faceSize, faceOffset); } else { - qWarning() << "Failed to get a valid file out of maybeOpenFile " << QString::fromStdString(_filename); + std::lock_guard<std::mutex> lock(*_cacheFileMutex); + auto file = maybeOpenFile(); + if (file) { + storageView = file->createView(faceSize, faceOffset); + } else { + qWarning() << "Failed to get a valid file out of maybeOpenFile " << QString::fromStdString(_filename); + } } } - return nullptr; + if (!storageView) { + qWarning() << "Failed to get a valid storageView for faceSize=" << faceSize << " faceOffset=" << faceOffset + << "out of valid file " << QString::fromStdString(_filename); + } + return storageView->toMemoryStorage(); } Size KtxStorage::getMipFaceSize(uint16 level, uint8 face) const { return _ktxDescriptor->getMipFaceTexelsSize(level, face); } - bool KtxStorage::isMipAvailable(uint16 level, uint8 face) const { return level >= _minMipLevelAvailable; } @@ -271,7 +298,7 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor auto& imageDesc = _ktxDescriptor->images[level]; if (storage->size() != imageDesc._imageSize) { qWarning() << "Invalid image size: " << storage->size() << ", expected: " << imageDesc._imageSize - << ", level: " << level << ", filename: " << QString::fromStdString(_filename); + << ", level: " << level << ", filename: " << QString::fromStdString(_filename); return; } @@ -311,8 +338,7 @@ void KtxStorage::assignMipFaceData(uint16 level, uint8 face, const storage::Stor throw std::runtime_error("Invalid call"); } -bool validKtx(const std::string& filename) { - ktx::StoragePointer storage { new storage::FileStorage(filename.c_str()) }; +bool validKtx(const storage::StoragePointer& storage) { auto ktxPointer = ktx::KTX::create(storage); if (!ktxPointer) { return false; @@ -320,6 +346,21 @@ bool validKtx(const std::string& filename) { return true; } +bool validKtx(const std::string& filename) { + ktx::StoragePointer storage{ new storage::FileStorage(filename.c_str()) }; + return validKtx(storage); +} + +void Texture::setKtxBacking(const storage::StoragePointer& storage) { + // Check the KTX file for validity before using it as backing storage + if (!validKtx(storage)) { + return; + } + + auto newBacking = std::unique_ptr<Storage>(new KtxStorage(storage)); + setStorage(newBacking); +} + void Texture::setKtxBacking(const std::string& filename) { // Check the KTX file for validity before using it as backing storage if (!validKtx(filename)) { @@ -355,7 +396,7 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { // Set Dimensions uint32_t numFaces = 1; switch (texture.getType()) { - case TEX_1D: { + case TEX_1D: { if (texture.isArray()) { header.set1DArray(texture.getWidth(), texture.getNumSlices()); } else { @@ -363,7 +404,7 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { } break; } - case TEX_2D: { + case TEX_2D: { if (texture.isArray()) { header.set2DArray(texture.getWidth(), texture.getHeight(), texture.getNumSlices()); } else { @@ -371,7 +412,7 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { } break; } - case TEX_3D: { + case TEX_3D: { if (texture.isArray()) { header.set3DArray(texture.getWidth(), texture.getHeight(), texture.getDepth(), texture.getNumSlices()); } else { @@ -379,7 +420,7 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { } break; } - case TEX_CUBE: { + case TEX_CUBE: { if (texture.isArray()) { header.setCubeArray(texture.getWidth(), texture.getHeight(), texture.getNumSlices()); } else { @@ -388,8 +429,8 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { numFaces = Texture::CUBE_FACE_COUNT; break; } - default: - return nullptr; + default: + return nullptr; } // Number level of mips coming diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 2ef83e42d8..eb84521f5c 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -20,7 +20,7 @@ size_t Image::getByteCount() const { if (_format == Format_RGBAF) { return sizeof(FloatPixels::value_type) * _floatData.size(); } else { - return _packedData.byteCount(); + return _packedData.sizeInBytes(); } } diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index 0a6c76e456..b1746951bb 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -225,7 +225,7 @@ controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevic * * <table> * <thead> - * <tr><th>Property</th><th>Type</th><td>Data</th><th>Description</th></tr> + * <tr><th>Property</th><th>Type</th><th>Data</th><th>Description</th></tr> * </thead> * <tbody> * <tr><td><code>0</code> – <code>9</code></td><td>number</td><td>number</td><td>A "0" – "1" key on the @@ -275,13 +275,15 @@ controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevic * <tr><td><code>MouseWheelLeft</code></td><td>number</td><td>number</td><td>The mouse wheel rotated left. The data value * is the number of units rotated (typically <code>1.0</code>).</td></tr> * <tr><td><code>MouseWheelUp</code></td><td>number</td><td>number</td><td>The mouse wheel rotated up. The data value - * is the number of units rotated (typically <code>1.0</code>).<br /> - * <strong>Warning:</strong> The mouse wheel in an ordinary mouse generates left/right wheel events instead of - * up/down.</td></tr> + * is the number of units rotated (typically <code>1.0</code>). + * <p><strong>Warning:</strong> The mouse wheel in an ordinary mouse generates left/right wheel events instead of + * up/down.</p> + * </td></tr> * <tr><td><code>MouseWheelDown</code></td><td>number</td><td>number</td><td>The mouse wheel rotated down. The data value - * is the number of units rotated (typically <code>1.0</code>).<br /> - * <strong>Warning:</strong> The mouse wheel in an ordinary mouse generates left/right wheel events instead of - * up/down.</td></tr> + * is the number of units rotated (typically <code>1.0</code>). + * <p><strong>Warning:</strong> The mouse wheel in an ordinary mouse generates left/right wheel events instead of + * up/down.</p> + * </td></tr> * <tr><td><code>TouchpadRight</code></td><td>number</td><td>number</td><td>The average touch on a touch-enabled device * moved right. The data value is how far the average position of all touch points moved.</td></tr> * <tr><td><code>TouchpadLeft</code></td><td>number</td><td>number</td><td>The average touch on a touch-enabled device diff --git a/libraries/ktx/src/ktx/KTX.h b/libraries/ktx/src/ktx/KTX.h index d755a482e3..0165113ec5 100644 --- a/libraries/ktx/src/ktx/KTX.h +++ b/libraries/ktx/src/ktx/KTX.h @@ -96,7 +96,7 @@ namespace ktx { using GLBaseInternalFormat = khronos::gl::texture::BaseInternalFormat; using Storage = storage::Storage; - using StoragePointer = std::shared_ptr<Storage>; + using StoragePointer = std::shared_ptr<const Storage>; struct ImageDescriptor; using ImageDescriptors = std::vector<ImageDescriptor>; diff --git a/libraries/midi/src/Midi.h b/libraries/midi/src/Midi.h index dd2b5fd678..5b7c82d6da 100644 --- a/libraries/midi/src/Midi.h +++ b/libraries/midi/src/Midi.h @@ -23,7 +23,7 @@ /**jsdoc * The <code>Midi</code> API provides the ability to connect Interface with musical instruments and other external or virtual * devices via the MIDI protocol. For further information and examples, see the tutorial: - * <a href="https://docs.highfidelity.com/en/rc81/script/midi-tutorial.html">Use MIDI to Control Your Environment</a>.</p> + * <a href="https://docs.highfidelity.com/script/midi-tutorial.html">Use MIDI to Control Your Environment</a>. * * <p><strong>Note:</strong> Only works on Windows.</p> * diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 8187c23f71..31bda960ec 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -188,11 +188,11 @@ public slots: /**jsdoc * Takes you to a specified metaverse address. * @function location.handleLookupString - * @param {string} address - The address to go to: a <code>"hifi://"<code> address, an IP address (e.g., - * <code>"127.0.0.1"</code> or <code>"localhost"</code>), a domain name, a named path on a domain (starts with - * <code>"/"</code>), a position or position and orientation, or a user (starts with <code>"@"</code>). + * @param {string} address - The address to go to: a <code>"hifi://"</code> address, an IP address (e.g., + * <code>"127.0.0.1"</code> or <code>"localhost"</code>), a domain name, a named path on a domain (starts with + * <code>"/"</code>), a position or position and orientation, or a user (starts with <code>"@"</code>). * @param {boolean} [fromSuggestions=false] - Set to <code>true</code> if the address is obtained from the "Goto" dialog. - * Helps ensure that user's location history is correctly maintained. + * Helps ensure that user's location history is correctly maintained. */ void handleLookupString(const QString& lookupString, bool fromSuggestions = false); @@ -259,7 +259,7 @@ public slots: /**jsdoc * Checks if going back to the previous location is possible. * @function location.canGoBack - * @returns <code>true</code> if going back is possible, <code>false</code> if it isn't. + * @returns {boolean} <code>true</code> if going back is possible, <code>false</code> if it isn't. */ bool canGoBack() const; diff --git a/libraries/networking/src/HifiSockAddr.cpp b/libraries/networking/src/HifiSockAddr.cpp index a1bfcdd275..086dd08489 100644 --- a/libraries/networking/src/HifiSockAddr.cpp +++ b/libraries/networking/src/HifiSockAddr.cpp @@ -17,6 +17,13 @@ #include "NetworkLogging.h" +#ifdef WIN32 +#include <winsock2.h> +#include <WS2tcpip.h> +#else +#include <netinet/in.h> +#endif + int hifiSockAddrMetaTypeId = qRegisterMetaType<HifiSockAddr>(); HifiSockAddr::HifiSockAddr() : diff --git a/libraries/networking/src/HifiSockAddr.h b/libraries/networking/src/HifiSockAddr.h index 3c753f0434..dcf7f9a6a9 100644 --- a/libraries/networking/src/HifiSockAddr.h +++ b/libraries/networking/src/HifiSockAddr.h @@ -15,12 +15,7 @@ #include <cstdint> #include <string> -#ifdef WIN32 -#include <winsock2.h> -#include <WS2tcpip.h> -#else -#include <netinet/in.h> -#endif +struct sockaddr; #include <QtNetwork/QHostInfo> diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index ecf2218e2f..d867b49b30 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -38,6 +38,12 @@ #include "udt/Packet.h" #include "HMACAuth.h" +#if defined(Q_OS_WIN) +#include <winsock.h> +#else +#include <arpa/inet.h> +#endif + static Setting::Handle<quint16> LIMITED_NODELIST_LOCAL_PORT("LimitedNodeList.LocalPort", 0); using namespace std::chrono_literals; @@ -1329,7 +1335,8 @@ void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* p qCDebug(networking) << "Wrote local listening port" << localPort << "to shared memory at key" << key; } else { - qWarning() << "ALERT: Failed to create and attach to shared memory to share local port with assignment-client children."; + qWarning() << "ALERT: Failed to create and attach to shared memory to share local port with assignment-client children:" + << sharedPortMem->errorString(); } } @@ -1337,7 +1344,8 @@ void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* p bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, quint16& localPort) { QSharedMemory sharedMem(key); if (!sharedMem.attach(QSharedMemory::ReadOnly)) { - qCWarning(networking) << "Could not attach to shared memory at key" << key; + qCWarning(networking) << "Could not attach to shared memory at key" << key + << ":" << sharedMem.errorString(); return false; } else { sharedMem.lock(); diff --git a/libraries/networking/src/MessagesClient.h b/libraries/networking/src/MessagesClient.h index b97c6d8360..7f2714e5ea 100644 --- a/libraries/networking/src/MessagesClient.h +++ b/libraries/networking/src/MessagesClient.h @@ -57,10 +57,10 @@ public: * @param {string} channel - The channel to send the message on. * @param {string} message - The message to send. * @param {boolean} [localOnly=false] - If <code>false</code> then the message is sent to all Interface, client entity, - * server entity, and assignment client scripts in the domain.<br /> - * If <code>true</code> then: if sent from an Interface or client entity script it is received by all Interface and + * server entity, and assignment client scripts in the domain. + * <p>If <code>true</code> then: if sent from an Interface or client entity script it is received by all Interface and * client entity scripts; if sent from a server entity script it is received by all entity server scripts; and if sent - * from an assignment client script it is received only by that same assignment client script. + * from an assignment client script it is received only by that same assignment client script.</p> * @example <caption>Send and receive a message.</caption> * // Receiving script. * var channelName = "com.highfidelity.example.messages-example"; @@ -105,10 +105,10 @@ public: * @param {object} data - The data to send. The data is handled as a byte stream, for example, as may be provided via a * JavaScript <code>Int8Array</code> object. * @param {boolean} [localOnly=false] - If <code>false</code> then the message is sent to all Interface, client entity, - * server entity, and assignment client scripts in the domain.<br /> - * If <code>true</code> then: if sent from an Interface or client entity script it is received by all Interface and + * server entity, and assignment client scripts in the domain. + * <p>If <code>true</code> then: if sent from an Interface or client entity script it is received by all Interface and * client entity scripts; if sent from a server entity script it is received by all entity server scripts; and if sent - * from an assignment client script it is received only by that same assignment client script. + * from an assignment client script it is received only by that same assignment client script.</p> * @example <caption>Send and receive data.</caption> * // Receiving script. * var channelName = "com.highfidelity.example.messages-example"; diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index 2d99f3649b..017855d628 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -31,6 +31,14 @@ using namespace udt; +#ifdef WIN32 +#include <winsock2.h> +#include <WS2tcpip.h> +#else +#include <netinet/in.h> +#endif + + Socket::Socket(QObject* parent, bool shouldChangeSocketOptions) : QObject(parent), _udpSocket(parent), diff --git a/libraries/plugins/src/plugins/SteamClientPlugin.h b/libraries/plugins/src/plugins/SteamClientPlugin.h index 2124d16b5e..07e320f8eb 100644 --- a/libraries/plugins/src/plugins/SteamClientPlugin.h +++ b/libraries/plugins/src/plugins/SteamClientPlugin.h @@ -41,13 +41,16 @@ public: }; /**jsdoc + * The <code>Steam</code> API provides facilities for working with the Steam version of Interface. + * * @namespace Steam * * @hifi-interface * @hifi-client-entity * @hifi-avatar * - * @property {boolean} running - <em>Read-only.</em> + * @property {boolean} running - <code>true</code> if Interface is running under Steam, <code>false</code> if it isn't. + * <em>Read-only.</em> */ class SteamScriptingInterface : public QObject { @@ -61,13 +64,22 @@ public: public slots: /**jsdoc + * Gets whether Interface is running under Steam. * @function Steam.isRunning - * @returns {boolean} + * @returns {boolean} <code>true</code> if Interface is running under Steam, <code>false</code> if it isn't. */ bool isRunning() const { return _plugin && _plugin->isRunning(); } /**jsdoc + * Opens Steam's "Choose Friends to invite" dialog if Interface is running under Steam. * @function Steam.openInviteOverlay + * @example <caption>Invite Steam friends to join you in High Fidelity.</caption> + * if (Steam.running) { + * print("Invite Steam friends to joint you..."); + * Steam.openInviteOverlay(); + * } else { + * print("Interface isn't running under Steam."); + * } */ void openInviteOverlay() const { if (_plugin) { _plugin->openInviteOverlay(); } } diff --git a/libraries/render-utils/src/text/Font.cpp b/libraries/render-utils/src/text/Font.cpp index f9ca9d4cae..5cb5709252 100644 --- a/libraries/render-utils/src/text/Font.cpp +++ b/libraries/render-utils/src/text/Font.cpp @@ -258,7 +258,7 @@ void Font::read(QIODevice& in) { _texture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_POINT_MAG_LINEAR)); _texture->setStoredMipFormat(formatMip); - _texture->assignStoredMip(0, image.byteCount(), image.constBits()); + _texture->assignStoredMip(0, image.sizeInBytes(), image.constBits()); } void Font::setupGPU() { diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index 859f343ec5..ce93921403 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -17,6 +17,8 @@ #include <QString> /**jsdoc + * The <code>File</code> API provides some facilities for working with the file system. + * * @namespace File * * @hifi-interface @@ -35,37 +37,69 @@ public: public slots: /**jsdoc + * Extracts a filename from a URL, where the filename is specified in the query part of the URL as <code>filename=</code>. * @function File.convertUrlToPath - * @param {string} url - * @returns {string} + * @param {string} url - The URL to extract the filename from. + * @returns {string} The filename specified in the URL; an empty string if no filename is specified. + * @example <caption>Extract a filename from a URL.</caption> + * var url = "http://domain.tld/path/page.html?filename=file.ext"; + * print("File name: " + File.convertUrlToPath(url)); // file.ext */ QString convertUrlToPath(QUrl url); /**jsdoc + * Unzips a file in the local file system to a new, unique temporary directory. * @function File.runUnzip - * @param {string} path - * @param {string} url - * @param {boolean} autoAdd - * @param {boolean} isZip - * @param {boolean} isBlocks + * @param {string} path - The path of the zip file in the local file system. May have a leading <code>"file:///"</code>. + * Need not have a <code>".zip"</code> extension if it is in a temporary directory (as created by + * {@link File.getTempDir|getTempDir}). + * @param {string} url - <em>Not used.</em> + * @param {boolean} autoAdd - <em>Not used by user scripts.</em> The value is simply passed through to the + * {@link File.unzipResult|unzipResult} signal. + * @param {boolean} isZip - Set to <code>true</code> if <code>path</code> has a <code>".zip"</code> extension, + * <code>false</code> if it doesn't (but should still be treated as a zip file). + * @param {boolean} isBlocks - <em>Not used by user scripts.</em> The value is simply passed through to the + * {@link File.unzipResult|unzipResult} signal. + * @example <caption>Select and unzip a file.</caption> + * File.unzipResult.connect(function (zipFile, unzipFiles, autoAdd, isZip, isBlocks) { + * print("File.unzipResult()"); + * print("- zipFile: " + zipFile); + * print("- unzipFiles(" + unzipFiles.length + "): " + unzipFiles); + * print("- autoAdd: " + autoAdd); + * print("- isZip: " + isZip); + * print("- isBlocks: " + isBlocks); + * }); + * + * var zipFile = Window.browse("Select a Zip File", "", "*.zip"); + * if (zipFile) { + * File.runUnzip(zipFile, "", false, true, false); + * } else { + * print("Zip file not selected."); + * } */ void runUnzip(QString path, QUrl url, bool autoAdd, bool isZip, bool isBlocks); /**jsdoc + * Creates a new, unique directory for temporary use. * @function File.getTempDir - * @returns {string} + * @returns {string} The path of the newly created temporary directory. + * @example <caption>Create a temporary directory.</caption> + * print("New temporary directory: " + File.getTempDir()); */ QString getTempDir(); signals: /**jsdoc + * Triggered when {@link File.runUnzip|runUnzip} completes. * @function File.unzipResult - * @param {string} zipFile - * @param {string} unzipFile - * @param {boolean} autoAdd - * @param {boolean} isZip - * @param {boolean} isBlocks + * @param {string} zipFile - The file that was unzipped. + * @param {string[]} unzipFiles - The paths of the unzipped files in a newly created temporary directory. Includes entries + * for any subdirectories created. An empty array if the <code>zipFile</code> could not be unzipped. + * @param {boolean} autoAdd - The value that {@link File.runUnzip|runUnzip} was called with. + * @param {boolean} isZip - <code>true</code> if {@link File.runUnzip|runUnzip} was called with <code>isZip == true</code>, + * unless there is no FBX or OBJ file in the unzipped file(s) in which case the value is <code>false</code>. + * @param {boolean} isBlocks - The value that {@link File.runUnzip|runUnzip} was called with. * @returns {Signal} */ void unzipResult(QString zipFile, QStringList unzipFile, bool autoAdd, bool isZip, bool isBlocks); diff --git a/libraries/script-engine/src/Quat.h b/libraries/script-engine/src/Quat.h index 0a5e58ac26..44abe62b24 100644 --- a/libraries/script-engine/src/Quat.h +++ b/libraries/script-engine/src/Quat.h @@ -223,7 +223,7 @@ public slots: /**jsdoc * Gets the "front" direction that the camera would face if its orientation was set to the quaternion value. * This is a synonym for {@link Quat(0).getForward|Quat.getForward}. - * The High Fidelity camera has axes <code>x</code> = right, <code>y</code> = up, </code>-z</code> = forward. + * The High Fidelity camera has axes <code>x</code> = right, <code>y</code> = up, <code>-z</code> = forward. * @function Quat(0).getFront * @param {Quat} orientation - A quaternion representing an orientation. * @returns {Vec3} The negative z-axis rotated by <code>orientation</code>. @@ -233,7 +233,7 @@ public slots: /**jsdoc * Gets the "forward" direction that the camera would face if its orientation was set to the quaternion value. * This is a synonym for {@link Quat(0).getFront|Quat.getFront}. - * The High Fidelity camera has axes <code>x</code> = right, <code>y</code> = up, </code>-z</code> = forward. + * The High Fidelity camera has axes <code>x</code> = right, <code>y</code> = up, <code>-z</code> = forward. * @function Quat(0).getForward * @param {Quat} orientation - A quaternion representing an orientation. * @returns {Vec3} The negative z-axis rotated by <code>orientation</code>. @@ -245,7 +245,7 @@ public slots: /**jsdoc * Gets the "right" direction that the camera would have if its orientation was set to the quaternion value. - * The High Fidelity camera has axes <code>x</code> = right, <code>y</code> = up, </code>-z</code> = forward. + * The High Fidelity camera has axes <code>x</code> = right, <code>y</code> = up, <code>-z</code> = forward. * @function Quat(0).getRight * @param {Quat} orientation - A quaternion representing an orientation. * @returns {Vec3} The x-axis rotated by <code>orientation</code>. @@ -254,7 +254,7 @@ public slots: /**jsdoc * Gets the "up" direction that the camera would have if its orientation was set to the quaternion value. - * The High Fidelity camera has axes <code>x</code> = right, <code>y</code> = up, </code>-z</code> = forward. + * The High Fidelity camera has axes <code>x</code> = right, <code>y</code> = up, <code>-z</code> = forward. * @function Quat(0).getUp * @param {Quat} orientation - A quaternion representing an orientation. * @returns {Vec3} The y-axis rotated by <code>orientation</code>. @@ -405,8 +405,9 @@ public slots: void print(const QString& label, const glm::quat& q, bool asDegrees = false); /**jsdoc - * Tests whether two quaternions are equal. <strong>Note:</strong> The quaternions must be exactly equal in order for - * <code>true</code> to be returned; it is often better to use {@link Quat(0).dot|Quat.dot} and test for closeness to +/-1. + * Tests whether two quaternions are equal. + * <p><strong>Note:</strong> The quaternions must be exactly equal in order for <code>true</code> to be returned; it is + * often better to use {@link Quat(0).dot|Quat.dot} and test for closeness to +/-1.</p> * @function Quat(0).equal * @param {Quat} q1 - The first quaternion. * @param {Quat} q2 - The second quaternion. diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 8337d1911a..4cf4a9fc42 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -1027,8 +1027,8 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& }; /**jsdoc - * The name of an entity event. When the entity event occurs, any function that has been registered for that event via - * {@link Script.addEventHandler} is called with parameters per the entity event. + * <p>The name of an entity event. When the entity event occurs, any function that has been registered for that event via + * {@link Script.addEventHandler} is called with parameters per the entity event.</p> * <table> * <thead> * <tr><th>Event Name</th><th>Entity Event</th></tr> diff --git a/libraries/shared/src/MovingPercentile.cpp b/libraries/shared/src/MovingPercentile.cpp index 5bcdbb5e80..427f7f2078 100644 --- a/libraries/shared/src/MovingPercentile.cpp +++ b/libraries/shared/src/MovingPercentile.cpp @@ -46,13 +46,13 @@ void MovingPercentile::updatePercentile(qint64 sample) { // swap new sample with neighbors in _samplesSorted until it's in sorted order // try swapping up first, then down. element will only be swapped one direction. while (newSampleIndex < _samplesSorted.size() - 1 && sample > _samplesSorted[newSampleIndex + 1]) { - _samplesSorted.swap(newSampleIndex, newSampleIndex + 1); - _sampleIds.swap(newSampleIndex, newSampleIndex + 1); + std::swap(_samplesSorted[newSampleIndex], _samplesSorted[newSampleIndex + 1]); + std::swap(_sampleIds[newSampleIndex], _sampleIds[newSampleIndex + 1]); newSampleIndex++; } while (newSampleIndex > 0 && sample < _samplesSorted[newSampleIndex - 1]) { - _samplesSorted.swap(newSampleIndex, newSampleIndex - 1); - _sampleIds.swap(newSampleIndex, newSampleIndex - 1); + std::swap(_samplesSorted[newSampleIndex], _samplesSorted[newSampleIndex - 1]); + std::swap(_sampleIds[newSampleIndex], _sampleIds[newSampleIndex - 1]); newSampleIndex--; } diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 39def1cab9..f14be72a71 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -22,6 +22,7 @@ #include <unordered_map> #include <chrono> +#include <QtCore/QOperatingSystemVersion> #include <glm/glm.hpp> #ifdef Q_OS_WIN @@ -793,15 +794,7 @@ void printSystemInformation() { qCDebug(shared).noquote() << "\tKernel Type: " << QSysInfo::kernelType(); qCDebug(shared).noquote() << "\tKernel Version: " << QSysInfo::kernelVersion(); - auto macVersion = QSysInfo::macVersion(); - if (macVersion != QSysInfo::MV_None) { - qCDebug(shared) << "\tMac Version: " << macVersion; - } - - auto windowsVersion = QSysInfo::windowsVersion(); - if (windowsVersion != QSysInfo::WV_None) { - qCDebug(shared) << "\tWindows Version: " << windowsVersion; - } + qCDebug(shared) << "\tOS Version: " << QOperatingSystemVersion::current(); #ifdef Q_OS_WIN SYSTEM_INFO si; diff --git a/libraries/shared/src/shared/FileUtils.cpp b/libraries/shared/src/shared/FileUtils.cpp index f2a4925351..164af091de 100644 --- a/libraries/shared/src/shared/FileUtils.cpp +++ b/libraries/shared/src/shared/FileUtils.cpp @@ -21,6 +21,7 @@ #include <QtCore/QUrl> #include <QtCore/QTextStream> #include <QtCore/QRegularExpression> +#include <QtCore/QFileSelector> #include <QtGui/QDesktopServices> @@ -176,3 +177,15 @@ bool FileUtils::canCreateFile(const QString& fullPath) { } return true; } + +QString FileUtils::getParentPath(const QString& fullPath) { + return QFileInfo(fullPath).absoluteDir().canonicalPath(); +} + +bool FileUtils::exists(const QString& fileName) { + return QFileInfo(fileName).exists(); +} + +bool FileUtils::isRelative(const QString& fileName) { + return QFileInfo(fileName).isRelative(); +} diff --git a/libraries/shared/src/shared/FileUtils.h b/libraries/shared/src/shared/FileUtils.h index 2f5e11f005..d4ff819e75 100644 --- a/libraries/shared/src/shared/FileUtils.h +++ b/libraries/shared/src/shared/FileUtils.h @@ -12,20 +12,23 @@ #ifndef hifi_FileUtils_h #define hifi_FileUtils_h -#include <QString> -#include <QtCore/QFileSelector> +#include <QtCore/QString> + class FileUtils { public: static const QStringList& getFileSelectors(); static QString selectFile(const QString& fileName); static void locateFile(const QString& fileName); + static bool exists(const QString& fileName); + static bool isRelative(const QString& fileName); static QString standardPath(QString subfolder); static QString readFile(const QString& filename); static QStringList readLines(const QString& filename, QString::SplitBehavior splitBehavior = QString::KeepEmptyParts); static QString replaceDateTimeTokens(const QString& path); static QString computeDocumentPath(const QString& path); static bool canCreateFile(const QString& fullPath); + static QString getParentPath(const QString& fullPath); }; #endif // hifi_FileUtils_h diff --git a/libraries/shared/src/shared/Storage.h b/libraries/shared/src/shared/Storage.h index 0e5032bb62..6a2cecf8b9 100644 --- a/libraries/shared/src/shared/Storage.h +++ b/libraries/shared/src/shared/Storage.h @@ -10,15 +10,22 @@ #ifndef hifi_Storage_h #define hifi_Storage_h -#include <stdint.h> +#include <cstdint> #include <vector> #include <memory> -#include <QFile> -#include <QString> +#include <functional> + +#include <QtCore/QFile> +#include <QtCore/QString> namespace storage { class Storage; - using StoragePointer = std::shared_ptr<const Storage>; + using Pointer = std::shared_ptr<const Storage>; + using StoragePointer = Pointer; + // A function that can construct storage, useful for creating a list of + // things that can become storage without requiring that they all be instantiated at once + using Builder = std::function<StoragePointer()>; + using Builders = std::vector<Builder>; // Abstract class to represent memory that stored _somewhere_ (in system memory or in a file, for example) class Storage : public std::enable_shared_from_this<Storage> { diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 71d48c9a18..7e6be9b53e 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -18,6 +18,7 @@ #include <QtCore/qjsondocument.h> #include <QtCore/qjsonobject.h> #include <QtCore/qjsonvalue.h> +#include <QtCore/QRegularExpression> #include <shared/JSONHelpers.h> #include "SettingHandle.h" @@ -189,7 +190,7 @@ public: * @returns {object[]} */ Q_INVOKABLE QObjectList getSubConfigs() const { - auto list = findChildren<JobConfig*>(QRegExp(".*"), Qt::FindDirectChildrenOnly); + auto list = findChildren<JobConfig*>(QRegularExpression(".*"), Qt::FindDirectChildrenOnly); QObjectList returned; for (int i = 0; i < list.size(); i++) { returned.push_back(list[i]); diff --git a/libraries/ui/src/InfoView.cpp b/libraries/ui/src/InfoView.cpp index 650d43831c..478401c6f8 100644 --- a/libraries/ui/src/InfoView.cpp +++ b/libraries/ui/src/InfoView.cpp @@ -56,10 +56,10 @@ void InfoView::show(const QString& path, bool firstOrChangedOnly, QString urlQue const QString lastVersion = infoVersion.get(); const QString version = fetchVersion(url); // If we have version information stored - if (lastVersion != QString::null) { + if (!lastVersion.isNull()) { // Check to see the document version. If it's valid and matches // the stored version, we're done, so exit - if (version == QString::null || version == lastVersion) { + if (version.isNull() || version == lastVersion) { return; } } diff --git a/libraries/ui/src/MainWindow.cpp b/libraries/ui/src/MainWindow.cpp index 124e25675a..ffa9bacbaa 100644 --- a/libraries/ui/src/MainWindow.cpp +++ b/libraries/ui/src/MainWindow.cpp @@ -11,8 +11,8 @@ #include "MainWindow.h" -#include <QApplication> -#include <QDesktopWidget> +#include <QtGui/QGuiApplication> +#include <QtGui/QScreen> #include <QEvent> #include <QMoveEvent> #include <QResizeEvent> @@ -22,8 +22,8 @@ #include <QDragEnterEvent> #include <QDropEvent> #include <QMimeData> -#include <QWindow> -#include <QDebug> +#include <QtGui/QWindow> +#include <QtCore/QDebug> #include "ui/Logging.h" #include "DockWidget.h" @@ -60,7 +60,7 @@ QWindow* MainWindow::findMainWindow() { void MainWindow::restoreGeometry() { // Did not use setGeometry() on purpose, // see http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application - QRect windowGeometry = qApp->desktop()->availableGeometry(); + QRect windowGeometry = QGuiApplication::primaryScreen()->availableGeometry(); #if defined(Q_OS_MAC) windowGeometry.setSize((windowGeometry.size() * 0.5f)); #endif diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index 75b08ba44f..040bb750d0 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -330,7 +330,6 @@ QObject* TabletScriptingInterface::getFlags() { // static const char* TABLET_HOME_SOURCE_URL = "hifi/tablet/TabletHome.qml"; -static const char* WEB_VIEW_SOURCE_URL = "hifi/tablet/TabletWebView.qml"; static const char* VRMENU_SOURCE_URL = "hifi/tablet/TabletMenu.qml"; class TabletRootWindow : public QmlWindowClass { @@ -827,58 +826,24 @@ void TabletProxy::loadWebScreenOnTop(const QVariant& url) { void TabletProxy::loadWebScreenOnTop(const QVariant& url, const QString& injectJavaScriptUrl) { bool localSafeContext = hifi::scripting::isLocalAccessSafeThread(); if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "loadHTMLSourceImpl", Q_ARG(QVariant, url), Q_ARG(QString, injectJavaScriptUrl), Q_ARG(bool, localSafeContext)); + QMetaObject::invokeMethod(this, "loadHTMLSourceOnTopImpl", Q_ARG(QString, url.toString()), Q_ARG(QString, injectJavaScriptUrl), Q_ARG(bool, false), Q_ARG(bool, localSafeContext)); return; } - loadHTMLSourceImpl(url, injectJavaScriptUrl, localSafeContext); -} - - - -void TabletProxy::loadHTMLSourceImpl(const QVariant& url, const QString& injectJavaScriptUrl, bool localSafeContext) { - if (QThread::currentThread() != thread()) { - qCWarning(uiLogging) << __FUNCTION__ << "may not be called directly by scripts"; - return; - - } - - - QObject* root = nullptr; - if (!_toolbarMode && _qmlTabletRoot) { - root = _qmlTabletRoot; - } else if (_toolbarMode && _desktopWindow) { - root = _desktopWindow->asQuickItem(); - } - - if (root) { - if (localSafeContext) { - hifi::scripting::setLocalAccessSafeThread(true); - } - QMetaObject::invokeMethod(root, "loadQMLOnTop", Q_ARG(const QVariant&, QVariant(WEB_VIEW_SOURCE_URL))); - QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); - if (_toolbarMode && _desktopWindow) { - QMetaObject::invokeMethod(root, "setResizable", Q_ARG(const QVariant&, QVariant(false))); - } - QMetaObject::invokeMethod(root, "loadWebOnTop", Q_ARG(const QVariant&, QVariant(url)), Q_ARG(const QVariant&, QVariant(injectJavaScriptUrl))); - hifi::scripting::setLocalAccessSafeThread(false); - } - _state = State::Web; + loadHTMLSourceOnTopImpl(url.toString(), injectJavaScriptUrl, false, localSafeContext); } void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase) { bool localSafeContext = hifi::scripting::isLocalAccessSafeThread(); if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "loadHTMLSourceImpl", Q_ARG(QString, url), Q_ARG(QString, injectedJavaScriptUrl), Q_ARG(bool, loadOtherBase), Q_ARG(bool, localSafeContext)); + QMetaObject::invokeMethod(this, "loadHTMLSourceOnTopImpl", Q_ARG(QString, url), Q_ARG(QString, injectedJavaScriptUrl), Q_ARG(bool, loadOtherBase), Q_ARG(bool, localSafeContext)); return; } - - loadHTMLSourceImpl(url, injectedJavaScriptUrl, loadOtherBase, localSafeContext); + loadHTMLSourceOnTopImpl(url, injectedJavaScriptUrl, loadOtherBase, localSafeContext); } -void TabletProxy::loadHTMLSourceImpl(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase, bool localSafeContext) { - +void TabletProxy::loadHTMLSourceOnTopImpl(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase, bool localSafeContext) { QObject* root = nullptr; if (!_toolbarMode && _qmlTabletRoot) { root = _qmlTabletRoot; @@ -911,7 +876,6 @@ void TabletProxy::loadHTMLSourceImpl(const QString& url, const QString& injected _initialWebPathParams.first = injectedJavaScriptUrl; _initialWebPathParams.second = loadOtherBase; _initialScreen = true; - } } diff --git a/libraries/ui/src/ui/TabletScriptingInterface.h b/libraries/ui/src/ui/TabletScriptingInterface.h index 58596d6d92..88d4ebe267 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.h +++ b/libraries/ui/src/ui/TabletScriptingInterface.h @@ -69,7 +69,7 @@ class TabletScriptingInterface : public QObject, public Dependency { public: /**jsdoc - * Standard tablet sounds. + * <p>Standard tablet sounds.</p> * <table> * <thead> * <tr><th>Value</th><th>Description</th></tr> @@ -273,7 +273,9 @@ public: Q_INVOKABLE void gotoHomeScreen(); /**jsdoc - * Opens a web page or app on the tablet. + * Opens a web app or page in addition to any current app. In tablet mode, the app or page is displayed over the top of the + * current app; in toolbar mode, the app is opened in a new window that replaces any current window open. If in tablet + * mode, the app or page can be closed using {@link TabletProxy#returnToPreviousApp}. * @function TabletProxy#gotoWebScreen * @param {string} url - The URL of the web page or app. * @param {string} [injectedJavaScriptUrl=""] - The URL of JavaScript to inject into the web page. @@ -294,29 +296,31 @@ public: Q_INVOKABLE void loadQMLSource(const QVariant& path, bool resizable = false); /**jsdoc - * Internal function, do not call from scripts * @function TabletProxy#loadQMLSourceImpl + * @deprecated This function is deprecated and will be removed. */ + // Internal function, do not call from scripts. Q_INVOKABLE void loadQMLSourceImpl(const QVariant& path, bool resizable, bool localSafeContext); - /**jsdoc - * Internal function, do not call from scripts - * @function TabletProxy#loadHTMLSourceImpl + /**jsdoc + * @function TabletProxy#loadHTMLSourceOnTopImpl + * @deprecated This function is deprecated and will be removed. */ - Q_INVOKABLE void loadHTMLSourceImpl(const QVariant& url, const QString& injectJavaScriptUrl, bool localSafeContext); + // Internal function, do not call from scripts. + Q_INVOKABLE void loadHTMLSourceOnTopImpl(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase, bool localSafeContext); - /**jsdoc - * Internal function, do not call from scripts - * @function TabletProxy#loadHTMLSourceImpl - */ - Q_INVOKABLE void loadHTMLSourceImpl(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase, bool localSafeContext); - - /**jsdoc - * Internal function, do not call from scripts + /**jsdoc * @function TabletProxy#returnToPreviousAppImpl + * @deprecated This function is deprecated and will be removed. */ + // Internal function, do not call from scripts. Q_INVOKABLE void returnToPreviousAppImpl(bool localSafeContext); + /**jsdoc + *@function TabletProxy#loadQMLOnTopImpl + * @deprecated This function is deprecated and will be removed. + */ + // Internal function, do not call from scripts. Q_INVOKABLE void loadQMLOnTopImpl(const QVariant& path, bool localSafeContext); // FIXME: This currently relies on a script initializing the tablet (hence the bool denoting success); @@ -355,8 +359,8 @@ public: /**jsdoc * Opens a web app or page in addition to any current app. In tablet mode, the app or page is displayed over the top of the - * current app; in toolbar mode, the app is opened in a new window. If in tablet mode, the app or page can be closed using - * {@link TabletProxy#returnToPreviousApp}. + * current app; in toolbar mode, the app is opened in a new window that replaces any current window open. If in tablet + * mode, the app or page can be closed using {@link TabletProxy#returnToPreviousApp}. * @function TabletProxy#loadWebScreenOnTop * @param {string} path - The URL of the web page or HTML app. * @param {string} [injectedJavaScriptURL=""] - The URL of JavaScript to inject into the web page. diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 14830f3f04..c1431fa4b2 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -50,13 +50,13 @@ QString OculusControllerManager::configurationLayout() { void OculusControllerManager::setConfigurationSettings(const QJsonObject configurationSettings) { if (configurationSettings.contains("trackControllersInOculusHome")) { - _touch->_trackControllersInOculusHome.set(configurationSettings["trackControllersInOculusHome"].toBool()); + _trackControllersInOculusHome.set(configurationSettings["trackControllersInOculusHome"].toBool()); } } QJsonObject OculusControllerManager::configurationSettings() { QJsonObject configurationSettings; - configurationSettings["trackControllersInOculusHome"] = _touch->_trackControllersInOculusHome.get(); + configurationSettings["trackControllersInOculusHome"] = _trackControllersInOculusHome.get(); return configurationSettings; } @@ -232,7 +232,7 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, quint64 currentTime = usecTimestampNow(); static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked | ovrStatus_PositionTracked; bool hasInputFocus = ovr::hasInputFocus(); - bool trackControllersInOculusHome = _trackControllersInOculusHome.get(); + bool trackControllersInOculusHome = _parent._trackControllersInOculusHome.get(); auto tracking = ovr::getTrackingState(); // ovr_GetTrackingState(_parent._session, 0, false); ovr::for_each_hand([&](ovrHandType hand) { ++numTrackedControllers; diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h index ea32eace61..7d1d176a56 100644 --- a/plugins/oculus/src/OculusControllerManager.h +++ b/plugins/oculus/src/OculusControllerManager.h @@ -98,7 +98,6 @@ private: float _leftHapticStrength { 0.0f }; float _rightHapticDuration { 0.0f }; float _rightHapticStrength { 0.0f }; - Setting::Handle<bool> _trackControllersInOculusHome { "trackControllersInOculusHome", false }; mutable std::recursive_mutex _lock; std::map<int, bool> _lostTracking; std::map<int, quint64> _regainTrackingDeadline; @@ -109,6 +108,7 @@ private: void checkForConnectedDevices(); + Setting::Handle<bool> _trackControllersInOculusHome { "trackControllersInOculusHome", false }; ovrInputState _remoteInputState {}; ovrInputState _touchInputState {}; RemoteDevice::Pointer _remote; diff --git a/scripts/+android_interface/defaultScripts.js b/scripts/+android_interface/defaultScripts.js index 8b3082d81a..a02f98b193 100644 --- a/scripts/+android_interface/defaultScripts.js +++ b/scripts/+android_interface/defaultScripts.js @@ -127,3 +127,8 @@ Script.scriptEnding.connect(function() { }); Menu.menuItemEvent.connect(menuItemEvent); + +var ANDROID_UI_AUTO_LOD_ADJUST = false; +var ANDROID_UI_LOD_ANGLE_DEG = 0.248; +LODManager.automaticLODAdjust = ANDROID_UI_AUTO_LOD_ADJUST; +LODManager.lodAngleDeg = ANDROID_UI_LOD_ANGLE_DEG; diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index 6f0dd40493..7f78d2477f 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -71,23 +71,63 @@ if (Menu.menuExists(MENU_CATEGORY) && !Menu.menuItemExists(MENU_CATEGORY, MENU_I } function loadSeparateDefaults() { + var currentlyRunningScripts = ScriptDiscoveryService.getRunning(); + for (var i in DEFAULT_SCRIPTS_SEPARATE) { - Script.load(DEFAULT_SCRIPTS_SEPARATE[i]); + var shouldLoadCurrentDefaultScript = true; + + for (var j = 0; j < currentlyRunningScripts.length; j++) { + var currentRunningScriptObject = currentlyRunningScripts[j]; + var currentDefaultScriptName = DEFAULT_SCRIPTS_SEPARATE[i].substr((DEFAULT_SCRIPTS_SEPARATE[i].lastIndexOf("/") + 1), DEFAULT_SCRIPTS_SEPARATE[i].length); + if (currentDefaultScriptName === currentRunningScriptObject.name) { + shouldLoadCurrentDefaultScript = false; + } + } + + if (shouldLoadCurrentDefaultScript) { + Script.load(DEFAULT_SCRIPTS_SEPARATE[i]); + } } } function runDefaultsTogether() { - for (var i in DEFAULT_SCRIPTS_COMBINED) { - Script.include(DEFAULT_SCRIPTS_COMBINED[i]); + var currentlyRunningScripts = ScriptDiscoveryService.getRunning(); + + for (var i = 0; i < DEFAULT_SCRIPTS_COMBINED.length; i++) { + var shouldIncludeCurrentDefaultScript = true; + + for (var j = 0; j < currentlyRunningScripts.length; j++) { + var currentRunningScriptObject = currentlyRunningScripts[j]; + var currentDefaultScriptName = DEFAULT_SCRIPTS_COMBINED[i].substr((DEFAULT_SCRIPTS_COMBINED[i].lastIndexOf("/") + 1), DEFAULT_SCRIPTS_COMBINED[i].length); + if (currentDefaultScriptName === currentRunningScriptObject.name) { + shouldIncludeCurrentDefaultScript = false; + } + } + + if (shouldIncludeCurrentDefaultScript) { + Script.include(DEFAULT_SCRIPTS_COMBINED[i]); + } } - loadSeparateDefaults(); } function runDefaultsSeparately() { + var currentlyRunningScripts = ScriptDiscoveryService.getRunning(); + for (var i in DEFAULT_SCRIPTS_COMBINED) { - Script.load(DEFAULT_SCRIPTS_COMBINED[i]); + var shouldLoadCurrentDefaultScript = true; + + for (var j = 0; j < currentlyRunningScripts.length; j++) { + var currentRunningScriptObject = currentlyRunningScripts[j]; + var currentDefaultScriptName = DEFAULT_SCRIPTS_COMBINED[i].substr((DEFAULT_SCRIPTS_COMBINED[i].lastIndexOf("/") + 1), DEFAULT_SCRIPTS_COMBINED[i].length); + if (currentDefaultScriptName === currentRunningScriptObject.name) { + shouldLoadCurrentDefaultScript = false; + } + } + + if (shouldLoadCurrentDefaultScript) { + Script.load(DEFAULT_SCRIPTS_COMBINED[i]); + } } - loadSeparateDefaults(); } // start all scripts @@ -99,6 +139,7 @@ if (Menu.isOptionChecked(MENU_ITEM)) { // include all default scripts into this ScriptEngine runDefaultsTogether(); } +loadSeparateDefaults(); function menuItemEvent(menuItem) { if (menuItem === MENU_ITEM) { diff --git a/scripts/simplifiedUI/ui/simplifiedNametag/resources/modules/nameTagListManager.js b/scripts/simplifiedUI/ui/simplifiedNametag/resources/modules/nameTagListManager.js index a38ba129db..c073a06589 100644 --- a/scripts/simplifiedUI/ui/simplifiedNametag/resources/modules/nameTagListManager.js +++ b/scripts/simplifiedUI/ui/simplifiedNametag/resources/modules/nameTagListManager.js @@ -22,6 +22,31 @@ var SECONDS_IN_MINUTE = 60; // Delete after 5 minutes in case a nametag is hanging around in on mode var ALWAYS_ON_MAX_LIFETIME_IN_SECONDS = 5 * SECONDS_IN_MINUTE; +// ************************************* +// START STARTUP/SHUTDOWN +// ************************************* +// #region STARTUP/SHUTDOWN + + +// Connect the camera mode updated signal on startup +function startup() { + Camera.modeUpdated.connect(handleCameraModeChanged); + cameraModeUpdatedSignalConnected = true; + + Script.scriptEnding.connect(shutdown); +} + +startup(); + +function shutdown() { + maybeDisconnectCameraModeUpdatedSignal(); +} + + +// ************************************* +// END STARTUP/SHUTDOWN +// ************************************* + // ************************************* // START UTILTY // ************************************* @@ -197,6 +222,27 @@ function toggleInterval() { } +// Disconnect the camera mode updated signal if we have one connected for the selfie mode +var cameraModeUpdatedSignalConnected = false; +function maybeDisconnectCameraModeUpdatedSignal() { + if (cameraModeUpdatedSignalConnected) { + Camera.modeUpdated.disconnect(handleCameraModeChanged); + cameraModeUpdatedSignalConnected = false; + } +} + + +// Turn on the nametag for yourself if you are in selfie mode, other wise delete it +function handleCameraModeChanged(mode) { + if (mode === "selfie") { + if (avatarNametagMode === "alwaysOn") { + add(MyAvatar.sessionUUID); + } + } else { + maybeRemove(MyAvatar.sessionUUID); + } +} + // Handle checking to see if we should add or delete nametags in persistent mode var alwaysOnAvatarDistanceCheck = false; var DISTANCE_CHECK_INTERVAL_MS = 1000; @@ -215,6 +261,10 @@ function handleAlwaysOnMode(shouldTurnOnAlwaysOnMode) { }); maybeClearAlwaysOnAvatarDistanceCheck(); alwaysOnAvatarDistanceCheck = Script.setInterval(maybeAddOrRemoveIntervalCheck, DISTANCE_CHECK_INTERVAL_MS); + + if (Camera.mode === "selfie") { + add(MyAvatar.sessionUUID); + } } } diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index cf365a4119..f0d3ec0c03 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -595,6 +595,10 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Controller.disableMapping(MAPPING_NAME); _this.pointerManager.removePointers(); Pointers.removePointer(this.mouseRayPointer); + Overlays.mouseReleaseOnOverlay.disconnect(mouseReleaseOnOverlay); + Overlays.mousePressOnOverlay.disconnect(mousePress); + Entities.mousePressOnEntity.disconnect(mousePress); + Messages.messageReceived.disconnect(controllerDispatcher.handleMessage); }; } diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index fd74786a5e..4942ecbd63 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -19,41 +19,31 @@ function(check_test name) endfunction() if (BUILD_TOOLS) + set(ALL_TOOLS + udt-test + vhacd-util + gpu-frame-player + ice-client + ktx-tool + ac-client + skeleton-dump + atp-client + oven + ) + # Allow different tools for stable builds if (STABLE_BUILD) - set(ALL_TOOLS - udt-test - vhacd-util - frame-optimizer - gpu-frame-player - ice-client - ktx-tool - ac-client - skeleton-dump - atp-client - oven - ) else() - set(ALL_TOOLS - udt-test - vhacd-util - frame-optimizer - gpu-frame-player - ice-client - ktx-tool - ac-client - skeleton-dump - atp-client - oven - nitpick - ) + list(APPEND ALL_TOOLS nitpick) endif() foreach(TOOL ${ALL_TOOLS}) check_test(${TOOL}) if (${BUILD_TOOL_RESULT}) add_subdirectory(${TOOL}) - set_target_properties(${TOOL} PROPERTIES FOLDER "Tools") + if (TARGET ${TOOL}) + set_target_properties(${TOOL} PROPERTIES FOLDER "Tools") + endif() endif() endforeach() endif() diff --git a/tools/ci-scripts/postbuild.py b/tools/ci-scripts/postbuild.py index b93ed5a664..9cab709c54 100644 --- a/tools/ci-scripts/postbuild.py +++ b/tools/ci-scripts/postbuild.py @@ -17,14 +17,12 @@ WIPE_PATHS = [] if sys.platform == "win32": WIPE_PATHS = [ - 'jsdoc', - 'resources/serverless' + 'jsdoc' ] elif sys.platform == "darwin": INTERFACE_BUILD_PATH = os.path.join(INTERFACE_BUILD_PATH, "Interface.app", "Contents", "Resources") WIPE_PATHS = [ - 'jsdoc', - 'serverless' + 'jsdoc' ] @@ -81,9 +79,6 @@ def fixupMacZip(filename): # ignore the nitpick app if newFilename.startswith('nitpick.app'): continue - # ignore the serverless content - if newFilename.startswith('interface.app/Contents/Resources/serverless'): - continue # if we made it here, include the file in the output buffer = inzip.read(entry.filename) entry.filename = newFilename diff --git a/tools/frame-optimizer/CMakeLists.txt b/tools/frame-optimizer/CMakeLists.txt deleted file mode 100644 index cc268c5baf..0000000000 --- a/tools/frame-optimizer/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -set(TARGET_NAME frame-optimizer) - -setup_memory_debugger() -setup_hifi_project(Gui Widgets) -link_hifi_libraries(shared ktx shaders gpu ) -package_libraries_for_deployment() diff --git a/tools/frame-optimizer/src/main.cpp b/tools/frame-optimizer/src/main.cpp deleted file mode 100644 index a4200c3d97..0000000000 --- a/tools/frame-optimizer/src/main.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// -// Created by Bradley Austin Davis on 2018/10/14 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include <QtCore/QCoreApplication> - -#ifdef Q_OS_WIN -#include <Windows.h> -#endif - -#include <iostream> -#include <gpu/FrameIO.h> -#include <gpu/Texture.h> - - -gpu::IndexOptimizer optimizer= [](gpu::Primitive primitive, uint32_t faceCount, uint32_t indexCount, uint32_t* indices ) { - // FIXME add a triangle index optimizer here -}; - - -void messageHandler(QtMsgType type, const QMessageLogContext &, const QString & message) { - auto messageStr = message.toStdString(); -#ifdef Q_OS_WIN - OutputDebugStringA(messageStr.c_str()); - OutputDebugStringA("\n"); -#endif - std::cerr << messageStr << std::endl; -} - -int main(int argc, char** argv) { - QCoreApplication app(argc, argv); - qInstallMessageHandler(messageHandler); - gpu::optimizeFrame("D:/Frames/20190112_1647.json", optimizer); - return 0; -} diff --git a/tools/gpu-frame-player/src/PlayerWindow.cpp b/tools/gpu-frame-player/src/PlayerWindow.cpp index e74caddd5e..8e7f730181 100644 --- a/tools/gpu-frame-player/src/PlayerWindow.cpp +++ b/tools/gpu-frame-player/src/PlayerWindow.cpp @@ -8,6 +8,8 @@ #include "PlayerWindow.h" +#include <QtCore/QByteArray> +#include <QtCore/QBuffer> #include <QtGui/QResizeEvent> #include <QtGui/QImageReader> #include <QtGui/QScreen> @@ -55,7 +57,7 @@ void PlayerWindow::loadFrame() { } } - QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open File"), openDir, tr("GPU Frames (*.json)")); + QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open File"), openDir, tr("GPU Frames (*.hfb)")); if (fileName.isNull()) { return; } @@ -104,17 +106,8 @@ void PlayerWindow::resizeEvent(QResizeEvent* ev) { _renderThread.resize(ev->size()); } -void PlayerWindow::textureLoader(const std::string& filename, const gpu::TexturePointer& texture, uint16_t layer) { - QImage image; - QImageReader(filename.c_str()).read(&image); - if (layer > 0) { - return; - } - texture->assignStoredMip(0, image.byteCount(), image.constBits()); -} - void PlayerWindow::loadFrame(const QString& path) { - auto frame = gpu::readFrame(path.toStdString(), _renderThread._externalTexture, &PlayerWindow::textureLoader); + auto frame = gpu::readFrame(path.toStdString(), _renderThread._externalTexture); if (frame) { _renderThread.submitFrame(frame); if (!_renderThread.isThreaded()) { diff --git a/tools/gpu-frame-player/src/PlayerWindow.h b/tools/gpu-frame-player/src/PlayerWindow.h index 4dfbca0855..a519fd9339 100644 --- a/tools/gpu-frame-player/src/PlayerWindow.h +++ b/tools/gpu-frame-player/src/PlayerWindow.h @@ -28,7 +28,7 @@ protected: void loadFrame(const QString& path); private: - static void textureLoader(const std::string& filename, const gpu::TexturePointer& texture, uint16_t layer); + static void textureLoader(const std::vector<uint8_t>& filename, const gpu::TexturePointer& texture, uint16_t layer); QSettings _settings; RenderThread _renderThread; }; diff --git a/tools/jsdoc/hifi-jsdoc-template/static/styles/jsdoc.css b/tools/jsdoc/hifi-jsdoc-template/static/styles/jsdoc.css index 2386f88586..dd67a4da20 100644 --- a/tools/jsdoc/hifi-jsdoc-template/static/styles/jsdoc.css +++ b/tools/jsdoc/hifi-jsdoc-template/static/styles/jsdoc.css @@ -96,7 +96,7 @@ h6 .paramHeading, .typeDef h3.propsHeading, h3.subHeading { - font-size: .9rem; + font-size: 1rem; font-family: "Proxima Nova"; font-weight: bold; border-bottom: solid 1px #ddd; @@ -108,9 +108,9 @@ h4.name padding-bottom: 0px; } -h5, .container-overview .subsection-title -{ - font-size: 13px; +h5, .container-overview .subsection-title { + font-size: 1rem; + font-family: "Proxima Nova"; font-weight: bold; margin-bottom: 5px; } @@ -143,6 +143,14 @@ td { border: solid #c7cccb 1px; } +td > p:first-child, td > ul:first-child { + margin-top: 0; +} + +td > p:last-child, td > ul:last-child { + margin-bottom: 0; +} + article table thead tr th, article table tbody tr td, article table tbody tr td p { font-size: .89rem; line-height: 20px; @@ -538,7 +546,7 @@ header { .prettyprint code { - font-size: 0.9em; + font-size: .95em; line-height: 18px; display: block; padding: 4px 12px; @@ -596,11 +604,6 @@ header { font-size: 100%; } -.params td.description > p:first-child, .props td.description > p:first-child { - margin-top: 0; - padding-top: 0; -} - span.param-type, .params td .param-type, .param-type dd { color: #606; font-family: Consolas, Monaco, 'Andale Mono', monospace diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/container.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/container.tmpl index 5c149fa434..fccf5f7d31 100644 --- a/tools/jsdoc/hifi-jsdoc-template/tmpl/container.tmpl +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/container.tmpl @@ -63,11 +63,13 @@ <section> <article> + <div class="container-overview"> - <?js if (doc.kind === 'module' && doc.modules) { ?> + <?js if (isGlobalPage) { ?> + <?js } else if (doc.kind === 'module' && doc.modules) { ?> <?js if (doc.description) { ?> <h3>Description</h3> - <p><?js= doc.description ?></p> + <div><?js= doc.description ?></div> <?js } ?> <?js doc.modules.forEach(function(module) { ?> @@ -75,7 +77,8 @@ <?js }) ?> <?js } else if (doc.kind === 'class' || (doc.kind === 'namespace' && doc.signature)) { ?> <h3>Description</h3> - <p><?js= doc.description ?></p> + <div><?js= doc.description ?></div> + <?js= self.partial('details.tmpl', doc) ?> <table> <thead> <tr> @@ -84,15 +87,15 @@ </thead> <tbody> <tr> - <td><code><?js= (doc.kind === 'class' ? 'new ' : '') + doc.name + (doc.signature || '') ?></code><p /> + <td><code><?js= (doc.kind === 'class' ? 'new ' : '') + doc.name + (doc.signature || '') ?></code> <?js if (doc.params) { ?> <h3 class="paramHeading">Parameters</h3> <?js= self.partial('params.tmpl', doc.params) ?> <?js } ?> + </td> </tr> </tbody> </table> - <?js= self.partial('details.tmpl', doc) ?> <?js if (doc.examples && doc.examples.length) { ?> <h3>Example<?js= doc.examples.length > 1? 's':'' ?></h3> @@ -101,7 +104,7 @@ <?js } else { ?> <h3>Description</h3> <?js if (doc.description) { ?> - <p><?js= doc.description ?></p> + <div><?js= doc.description ?></div> <?js } ?> <?js if (doc.examples && doc.examples.length) { ?> @@ -264,6 +267,7 @@ <?js methods.forEach(function(m) { ?> <?js= self.partial('method.tmpl', m) ?> <?js }); ?> + </div> <?js } ?> <?js @@ -276,12 +280,10 @@ <?js signals.forEach(function(s) { ?> <?js= self.partial('signal.tmpl', s) ?> <?js }); ?> + </div> <?js } ?> - - </article> - - + </article> </section> <?js } ?> <?js }); ?> diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/description.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/description.tmpl new file mode 100644 index 0000000000..0e0ad27b37 --- /dev/null +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/description.tmpl @@ -0,0 +1,15 @@ +<?js + var description = obj; + var self = this; + var descriptionRegExp = new RegExp('<(p|ul|div|table)[^>]*>', 'i'); + var descriptionIndex = description.search(descriptionRegExp); +?> + +<?js if (descriptionIndex === -1) { ?> + <p><?js= description ?></p> +<?js } else if (descriptionIndex !== 0) { ?> + <p><?js= description.slice(0, descriptionIndex) ?></p> + <?js= description.slice(descriptionIndex) ?> +<?js } else { ?> + <?js= description ?> +<?js } ?> diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/details.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/details.tmpl index 0661ee3e50..afb0e9464c 100644 --- a/tools/jsdoc/hifi-jsdoc-template/tmpl/details.tmpl +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/details.tmpl @@ -31,113 +31,113 @@ if (data.defaultvalue && (data.defaultvaluetype === 'object' || data.defaultvalu <?js if (data.version) {?> <p>Version:</p> - <p><ul class="dummy"><li><?js= version ?></li></ul></p> + <div><ul class="dummy"><li><?js= version ?></li></ul></div> <?js } ?> <?js if (data.since) {?> <p>Since:</p> - <p><ul class="dummy"><li><?js= since ?></li></ul></p> + <div><ul class="dummy"><li><?js= since ?></li></ul></div> <?js } ?> <?js if (data.inherited && data.inherits && !data.overrides) { ?> <p>Inherited From:</p> - <p><ul class="dummy"><li> + <div><ul class="dummy"><li> <?js= this.linkto(data.inherits, this.htmlsafe(data.inherits)) ?> - </li></ul></p> + </li></ul></div> <?js } ?> <?js if (data.overrides) { ?> <p>Overrides:</p> - <p><ul class="dummy"><li> + <div><ul class="dummy"><li> <?js= this.linkto(data.overrides, this.htmlsafe(data.overrides)) ?> - </li></ul></p> + </li></ul></div> <?js } ?> <?js if (data.implementations && data.implementations.length) { ?> <p>Implementations:</p> - <p><ul> + <div><ul> <?js data.implementations.forEach(function(impl) { ?> <li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li> <?js }); ?> - </ul></p> + </ul></div> <?js } ?> <?js if (data.implements && data.implements.length) { ?> <p>Implements:</p> - <p><ul> + <div><ul> <?js data.implements.forEach(function(impl) { ?> <li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li> <?js }); ?> - </ul></p> + </ul></div> <?js } ?> <?js if (data.mixes && data.mixes.length) { ?> <p>Mixes In:</p> - <p><ul> + <div><ul> <?js data.mixes.forEach(function(a) { ?> <li><?js= self.linkto(a, a) ?></li> <?js }); ?> - </ul></p> + </ul></div> <?js } ?> <?js if (data.author && author.length) {?> <p>Author:</p> - <p> + <div> <ul><?js author.forEach(function(a) { ?> <li><?js= self.resolveAuthorLinks(a) ?></li> <?js }); ?></ul> - </p> + </div> <?js } ?> <?js if (data.copyright) {?> <p>Copyright:</p> - <p><ul class="dummy"><li><?js= copyright ?></li></ul></p> + <div><ul class="dummy"><li><?js= copyright ?></li></ul></div> <?js } ?> <?js if (data.license) {?> <p>License:</p> - <p><ul class="dummy"><li><?js= license ?></li></ul></p> + <div><ul class="dummy"><li><?js= license ?></li></ul></div> <?js } ?> <?js if (data.defaultvalue) {?> <p>Default Value:</p> - <p><ul class="dummy"> - <li<?js= defaultObjectClass ?>><?js= data.defaultvalue ?></li> - </ul></p> + <div><ul class="dummy"> + <li><?js= defaultObjectClass ?>><?js= data.defaultvalue ?></li> + </ul></div> <?js } ?> <?js if (data.meta && self.outputSourceFiles) {?> <p>Source:</p> - <p><ul class="dummy"><li> + <div><ul class="dummy"><li> <?js= self.linkto(meta.shortpath) ?>, <?js= self.linkto(meta.shortpath, 'line ' + meta.lineno, null, 'line' + meta.lineno) ?> - </li></ul></p> + </li></ul></div> <?js } ?> <?js if (data.tutorials && tutorials.length) {?> <p>Tutorials:</p> - <p> + <div> <ul><?js tutorials.forEach(function(t) { ?> <li><?js= self.tutoriallink(t) ?></li> <?js }); ?></ul> - </p> + </div> <?js } ?> <?js if (data.see && see.length) {?> <p class="see">See:</p> - <p> + <div> <ul><?js see.forEach(function(s) { ?> <li><?js= self.linkto(s) ?></li> <?js }); ?></ul> - </p> + </div> <?js } ?> <?js if (data.todo && todo.length) {?> <p>To Do:</p> - <p> + <div> <ul><?js todo.forEach(function(t) { ?> <li><?js= t ?></li> <?js }); ?></ul> - </p> + </div> <?js } ?> diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/example.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/example.tmpl index e1b06d0a46..ea70a150c5 100644 --- a/tools/jsdoc/hifi-jsdoc-template/tmpl/example.tmpl +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/example.tmpl @@ -29,113 +29,113 @@ if (data.defaultvalue && (data.defaultvaluetype === 'object' || data.defaultvalu <?js if (data.version) {?> <p>Version:</p> - <p><ul class="dummy"><li><?js= version ?></li></ul></p> + <div><ul class="dummy"><li><?js= version ?></li></ul></div> <?js } ?> <?js if (data.since) {?> <p>Since:</p> - <p><ul class="dummy"><li><?js= since ?></li></ul></p> + <div><ul class="dummy"><li><?js= since ?></li></ul></div> <?js } ?> <?js if (data.inherited && data.inherits && !data.overrides) { ?> <p>Inherited From:</p> - <p><ul class="dummy"><li> + <div><ul class="dummy"><li> <?js= this.linkto(data.inherits, this.htmlsafe(data.inherits)) ?> - </li></ul></p> + </li></ul></div> <?js } ?> <?js if (data.overrides) { ?> <p>Overrides:</p> - <p><ul class="dummy"><li> + <div><ul class="dummy"><li> <?js= this.linkto(data.overrides, this.htmlsafe(data.overrides)) ?> - </li></ul></p> + </li></ul></div> <?js } ?> <?js if (data.implementations && data.implementations.length) { ?> <p>Implementations:</p> - <p><ul> + <div><ul> <?js data.implementations.forEach(function(impl) { ?> <li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li> <?js }); ?> - </ul></p> + </ul></div> <?js } ?> <?js if (data.implements && data.implements.length) { ?> <p>Implements:</p> - <p><ul> + <div><ul> <?js data.implements.forEach(function(impl) { ?> <li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li> <?js }); ?> - </ul></p> + </ul></div> <?js } ?> <?js if (data.mixes && data.mixes.length) { ?> <p>Mixes In:</p> - <p><ul> + <div><ul> <?js data.mixes.forEach(function(a) { ?> <li><?js= self.linkto(a, a) ?></li> <?js }); ?> - </ul></p> + </ul></div> <?js } ?> <?js if (data.author && author.length) {?> <p>Author:</p> - <p> + <div> <ul><?js author.forEach(function(a) { ?> <li><?js= self.resolveAuthorLinks(a) ?></li> <?js }); ?></ul> - </p> + </div> <?js } ?> <?js if (data.copyright) {?> <p>Copyright:</p> - <p><ul class="dummy"><li><?js= copyright ?></li></ul></p> + <div><ul class="dummy"><li><?js= copyright ?></li></ul></div> <?js } ?> <?js if (data.license) {?> <p>License:</p> - <p><ul class="dummy"><li><?js= license ?></li></ul></p> + <div><ul class="dummy"><li><?js= license ?></li></ul></div> <?js } ?> <?js if (data.defaultvalue) {?> <p>Default Value:</p> - <p><ul class="dummy"> - <li<?js= defaultObjectClass ?>><?js= data.defaultvalue ?></li> - </ul></p> + <div><ul class="dummy"> + <li><?js= defaultObjectClass ?>><?js= data.defaultvalue ?></li> + </ul></div> <?js } ?> <?js if (data.meta && self.outputSourceFiles) {?> <p>Source:</p> - <p><ul class="dummy"><li> + <div><ul class="dummy"><li> <?js= self.linkto(meta.shortpath) ?>, <?js= self.linkto(meta.shortpath, 'line ' + meta.lineno, null, 'line' + meta.lineno) ?> - </li></ul></p> + </li></ul></div> <?js } ?> <?js if (data.tutorials && tutorials.length) {?> <p>Tutorials:</p> - <p> + <div> <ul><?js tutorials.forEach(function(t) { ?> <li><?js= self.tutoriallink(t) ?></li> <?js }); ?></ul> - </p> + </div> <?js } ?> <?js if (data.see && see.length) {?> <p class="see">See:</p> - <p> + <div> <ul><?js see.forEach(function(s) { ?> <li><?js= self.linkto(s) ?></li> <?js }); ?></ul> - </p> + </div> <?js } ?> <?js if (data.todo && todo.length) {?> <p>To Do:</p> - <p> + <div> <ul><?js todo.forEach(function(t) { ?> <li><?js= t ?></li> <?js }); ?></ul> - </p> + </div> <?js } ?> diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/members.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/members.tmpl index eef64c1f3f..6a870b4cda 100644 --- a/tools/jsdoc/hifi-jsdoc-template/tmpl/members.tmpl +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/members.tmpl @@ -16,7 +16,7 @@ var self = this; <tr> <td> <?js if (data.description) { ?> - <p><?js= data.description ?></p> + <?js= self.partial('description.tmpl', data.description) ?> <?js } else { ?> <p style="color:red;"> </p> <?js } ?> diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/method.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/method.tmpl index 8db1df8a77..1542ca1806 100644 --- a/tools/jsdoc/hifi-jsdoc-template/tmpl/method.tmpl +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/method.tmpl @@ -12,8 +12,9 @@ var self = this; Returns: <span style="font-weight: normal;"> <?js returns.forEach(function(r) { ?> <?js= self.partial('returns.tmpl', r) ?> - <?js }); - } ?></span> + <?js }); ?> + </span> + <?js } ?> <?js if (data.kind === 'typedef' && data.type && data.type.names) { ?> <br />Type: <?js= self.partial('type.tmpl', data.type.names) ?> <?js } ?> @@ -24,23 +25,23 @@ var self = this; <tr> <td> <?js if (data.kind !== 'module' && !data.hideconstructor) { ?> - <p> - <?js= data.description ?> - <?js= this.partial('details.tmpl', data) ?> - </p> + <?js if (data.description) { ?> + <?js= self.partial('description.tmpl', data.description) ?> + <?js } ?> + <?js= this.partial('details.tmpl', data) ?> <?js } else { ?> <p style="color:red;"> </p> <?js } ?> <?js if (data.exceptions && exceptions.length) { ?> - <h3 class="subHeading">Throws:</h3> + <h3 class="subHeading">Throws</h3> <?js if (exceptions.length > 1) { ?><ul><?js exceptions.forEach(function(r) { ?> <li><?js= self.partial('exceptions.tmpl', r) ?></li> <?js }); ?></ul><?js } else { exceptions.forEach(function(r) { ?> - <p><?js= self.partial('exceptions.tmpl', r) ?></p> + <?js= self.partial('exceptions.tmpl', r) ?> <?js }); } } ?> diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/methodList.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/methodList.tmpl index 7d88cd5e51..982c231fd9 100644 --- a/tools/jsdoc/hifi-jsdoc-template/tmpl/methodList.tmpl +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/methodList.tmpl @@ -29,11 +29,9 @@ var self = this; </td> <td> <?js if (data.description) { ?> - <?js= description ?> - <?js= this.partial('details.tmpl', data) ?> - <?js } else { ?> - <?js= this.partial('details.tmpl', data) ?> + <?js= this.partial('description.tmpl', data.description) ?> <?js } ?> + <?js= this.partial('details.tmpl', data) ?> </td> </tr> <?js } ?> diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/params.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/params.tmpl index e994e42bfa..dd9f5f7ee7 100644 --- a/tools/jsdoc/hifi-jsdoc-template/tmpl/params.tmpl +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/params.tmpl @@ -120,10 +120,15 @@ </td> <?js } ?> - <td class="description last"><?js= param.description ?><?js if (param.subparams) { ?> - <h6>Properties</h6> - <?js= self.partial('params.tmpl', param.subparams) ?> - <?js } ?></td> + <td class="description last"> + <?js if (param.description) { ?> + <?js= self.partial('description.tmpl', param.description) ?> + <?js } ?> + <?js if (param.subparams) { ?> + <h6>Properties</h6> + <?js= self.partial('params.tmpl', param.subparams) ?> + <?js } ?> + </td> </tr> <?js }); ?> diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/properties.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/properties.tmpl index 5c83a7d587..31717ed63b 100644 --- a/tools/jsdoc/hifi-jsdoc-template/tmpl/properties.tmpl +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/properties.tmpl @@ -87,7 +87,9 @@ <?js } ?> <td class="description last"> - <?js= prop.description ?> + <?js if (prop.description) { ?> + <?js= self.partial('description.tmpl', prop.description) ?> + <?js } ?> <?js if (props.hasDefault) {?> <?js if (typeof prop.defaultvalue !== 'undefined') { ?> <p><b>Default Value:</b> <?js= self.htmlsafe(prop.defaultvalue) ?> </p> diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/signal.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/signal.tmpl index 00bf7122e1..76d6f78948 100644 --- a/tools/jsdoc/hifi-jsdoc-template/tmpl/signal.tmpl +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/signal.tmpl @@ -25,23 +25,23 @@ var self = this; <tr> <td> <?js if (data.kind !== 'module' && !data.hideconstructor) { ?> - <p> - <?js= data.description ?> - <?js= this.partial('details.tmpl', data) ?> - </p> + <?js if (data.description) { ?> + <?js= self.partial('description.tmpl', data.description) ?> + <?js } ?> + <?js= this.partial('details.tmpl', data) ?> <?js } else { ?> <p style="color:red;"> </p> <?js } ?> <?js if (data.exceptions && exceptions.length) { ?> - <h3 class="subHeading">Throws:</h3> + <h3 class="subHeading">Throws</h3> <?js if (exceptions.length > 1) { ?><ul><?js exceptions.forEach(function(r) { ?> <li><?js= self.partial('exceptions.tmpl', r) ?></li> <?js }); ?></ul><?js } else { exceptions.forEach(function(r) { ?> - <p><?js= self.partial('exceptions.tmpl', r) ?></p> + <?js= self.partial('exceptions.tmpl', r) ?> <?js }); } } ?> diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/signalList.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/signalList.tmpl index c5fdefc7d8..98b0892122 100644 --- a/tools/jsdoc/hifi-jsdoc-template/tmpl/signalList.tmpl +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/signalList.tmpl @@ -13,12 +13,10 @@ var self = this; <code><?js= (kind === 'class' ? 'new ' : '') + name + (data.signatureHead || '') ?></code></a> </td> <td> - <?js if (data.description) { ?> - <?js= description ?> - <?js= this.partial('details.tmpl', data) ?> - <?js } else { ?> + <?js if (data.description) { ?> + <?js= this.partial('description.tmpl', description) ?> + <?js } ?> <?js= this.partial('details.tmpl', data) ?> - <?js } ?> </td> </tr> <?js } ?>