mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge branch 'master' of https://github.com/highfidelity/hifi into workload
This commit is contained in:
commit
5db3eee4ad
86 changed files with 4658 additions and 791 deletions
|
@ -20,6 +20,7 @@ To produce an executable installer on Windows, the following are required:
|
|||
- [Inetc Plug-in for Nullsoft](http://nsis.sourceforge.net/Inetc_plug-in) - 1.0
|
||||
- [NSISpcre Plug-in for Nullsoft](http://nsis.sourceforge.net/NSISpcre_plug-in) - 1.0
|
||||
- [nsisSlideshow Plug-in for Nullsoft](http://nsis.sourceforge.net/NsisSlideshow_plug-in) - 1.7
|
||||
- [Nsisunz plug-in for Nullsoft](http://nsis.sourceforge.net/Nsisunz_plug-in)
|
||||
|
||||
Run the `package` target to create an executable installer using the Nullsoft Scriptable Install System.
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content)
|
|||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC66-v4.zip
|
||||
URL_MD5 d4f42f630986c83427ff39e1fe9908c6
|
||||
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC67-v2.zip
|
||||
URL_MD5 2c69a1df69816b4b0b81630396fbd36e
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
|
|
|
@ -1005,6 +1005,23 @@ Function HandlePostInstallOptions
|
|||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
Function OptionallyDownloadCampaignServerless
|
||||
${If} $CampaignName != ""
|
||||
InitPluginsDir
|
||||
|
||||
NSISdl::download_quiet http://cdn.highfidelity.com/installer/serverless/$CampaignName.zip $PLUGINSDIR\$CampaignName.zip
|
||||
|
||||
${If} ${FileExists} $PLUGINSDIR\$CampaignName.zip
|
||||
; replace the installed serverless content with the campaign content
|
||||
|
||||
RMDir /r "$INSTDIR\resources\serverless"
|
||||
CreateDirectory "$INSTDIR\resources\serverless"
|
||||
nsisunz::Unzip "$PLUGINSDIR\$CampaignName.zip" "$INSTDIR\resources\serverless"
|
||||
${EndIf}
|
||||
|
||||
${Endif}
|
||||
FunctionEnd
|
||||
|
||||
;--------------------------------
|
||||
;Installer Sections
|
||||
|
||||
|
@ -1158,6 +1175,9 @@ Section "-Core installation"
|
|||
|
||||
@CPACK_NSIS_EXTRA_INSTALL_COMMANDS@
|
||||
|
||||
; see if we have a campaign that we might need to grab special content for
|
||||
Call OptionallyDownloadCampaignServerless
|
||||
|
||||
; Handle whichever post install options were set
|
||||
Call HandlePostInstallOptions
|
||||
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
#include <DependencyManager.h>
|
||||
#include "Bookmarks.h"
|
||||
|
||||
/**jsdoc
|
||||
* This API helps manage adding and deleting Avatar bookmarks
|
||||
*/
|
||||
|
||||
class AvatarBookmarks: public Bookmarks, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
@ -23,6 +27,15 @@ public:
|
|||
AvatarBookmarks();
|
||||
void setupMenus(Menu* menubar, MenuWrapper* menu) override;
|
||||
|
||||
/**jsdoc
|
||||
* Add the current Avatar to your Avatar Bookmarks
|
||||
* @function AvatarBookmarks.addBookMark
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarBookmarks.deleteBookMark
|
||||
*/
|
||||
|
||||
public slots:
|
||||
void addBookmark();
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//
|
||||
//
|
||||
// Bookmarks.h
|
||||
// interface/src
|
||||
//
|
||||
|
@ -48,6 +48,10 @@ protected:
|
|||
bool _isMenuSorted;
|
||||
|
||||
protected slots:
|
||||
/**jsdoc
|
||||
* Delete
|
||||
* @function AvatarBookmarks.deleteBookmark
|
||||
*/
|
||||
void deleteBookmark();
|
||||
|
||||
private:
|
||||
|
|
|
@ -9,6 +9,11 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/**jsdoc
|
||||
* The LOD class manages your Level of Detail functions within interface
|
||||
* @namespace LODManager
|
||||
*/
|
||||
|
||||
#ifndef hifi_LODManager_h
|
||||
#define hifi_LODManager_h
|
||||
|
||||
|
@ -39,28 +44,125 @@ class LODManager : public QObject, public Dependency {
|
|||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.setAutomaticLODAdjust
|
||||
* @param {boolean} value
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void setAutomaticLODAdjust(bool value) { _automaticLODAdjust = value; }
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.getAutomaticLODAdjust
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE bool getAutomaticLODAdjust() const { return _automaticLODAdjust; }
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.setDesktopLODDecreaseFPS
|
||||
* @param {float} value
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void setDesktopLODDecreaseFPS(float value);
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.getDesktopLODDecreaseFPS
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE float getDesktopLODDecreaseFPS() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.getDesktopLODIncreaseFPS
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE float getDesktopLODIncreaseFPS() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.setHMDLODDecreaseFPS
|
||||
* @param {number} value
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void setHMDLODDecreaseFPS(float value);
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.getHMDLODDecreaseFPS
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE float getHMDLODDecreaseFPS() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.getHMDLODIncreaseFPS
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE float getHMDLODIncreaseFPS() const;
|
||||
|
||||
// User Tweakable LOD Items
|
||||
/**jsdoc
|
||||
* @function LODManager.getLODFeedbackText
|
||||
* @returns {string}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE QString getLODFeedbackText();
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.setOctreeSizeScale
|
||||
* @param {number} sizeScale
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void setOctreeSizeScale(float sizeScale);
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.getOctreeSizeScale
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE float getOctreeSizeScale() const { return _octreeSizeScale; }
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.setBoundaryLevelAdjust
|
||||
* @param {number} boundaryLevelAdjust
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void setBoundaryLevelAdjust(int boundaryLevelAdjust);
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.getBoundaryLevelAdjust
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.getLODDecreaseFPS
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE float getLODDecreaseFPS() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.getLODIncreaseFPS
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE float getLODIncreaseFPS() const;
|
||||
|
||||
/**jsdoc
|
||||
* @namespace LODManager
|
||||
* @property presentTime {number}
|
||||
* @property engineRunTime {number}
|
||||
* @property gpuTime {number}
|
||||
* @property avgRenderTime {number}
|
||||
* @property fps {number}
|
||||
* @property lodLevel {number}
|
||||
* @property lodDecreaseFPS {number}
|
||||
* @property lodIncreaseFPS {number}
|
||||
*/
|
||||
|
||||
Q_PROPERTY(float presentTime READ getPresentTime)
|
||||
Q_PROPERTY(float engineRunTime READ getEngineRunTime)
|
||||
Q_PROPERTY(float gpuTime READ getGPUTime)
|
||||
|
@ -88,7 +190,19 @@ public:
|
|||
float getLODLevel() const;
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.LODIncreased
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void LODIncreased();
|
||||
|
||||
/**jsdoc
|
||||
* @function LODManager.LODDecreased
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void LODDecreased();
|
||||
|
||||
private:
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
|
||||
#include <DependencyManager.h>
|
||||
|
||||
/**jsdoc
|
||||
* @namespace SpeechRecognizer
|
||||
*/
|
||||
class SpeechRecognizer : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
@ -31,12 +34,39 @@ public:
|
|||
bool getEnabled() const { return _enabled; }
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function SpeechRecognizer.setEnabled
|
||||
* @param {boolean} enabled
|
||||
*/
|
||||
void setEnabled(bool enabled);
|
||||
|
||||
/**jsdoc
|
||||
* @function SpeechRecognizer.addCommand
|
||||
* @param {string} command
|
||||
*/
|
||||
void addCommand(const QString& command);
|
||||
|
||||
/**jsdoc
|
||||
* @function SpeechRecognizer.removeCommand
|
||||
* @param {string} command
|
||||
*/
|
||||
void removeCommand(const QString& command);
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function SpeechRecognizer.commandRecognized
|
||||
* @param {string} command
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void commandRecognized(const QString& command);
|
||||
|
||||
/**jsdoc
|
||||
* @function SpeechRecognizer.enabledUpdated
|
||||
* @param {boolean} enabled
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void enabledUpdated(bool enabled);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -25,6 +25,17 @@ class AudioScope : public QObject, public Dependency {
|
|||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
/**jsdoc
|
||||
* The AudioScope API helps control the Audio Scope features in Interface
|
||||
* @namespace AudioScope
|
||||
* @property {int} scopeInput
|
||||
* @property {int} scopeOutputLeft
|
||||
* @property {int} scopeOutputRight
|
||||
* @property {int} triggerInput
|
||||
* @property {int} triggerOutputLeft
|
||||
* @property {int} triggerOutputRight
|
||||
*/
|
||||
|
||||
Q_PROPERTY(QVector<int> scopeInput READ getScopeInput)
|
||||
Q_PROPERTY(QVector<int> scopeOutputLeft READ getScopeOutputLeft)
|
||||
Q_PROPERTY(QVector<int> scopeOutputRight READ getScopeOutputRight)
|
||||
|
@ -40,42 +51,192 @@ public:
|
|||
void reallocateScope(int frames);
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.toggle
|
||||
*/
|
||||
|
||||
void toggle() { setVisible(!_isEnabled); }
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.setVisible
|
||||
* @param {boolean} visible
|
||||
*/
|
||||
|
||||
void setVisible(bool visible);
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.getVisible
|
||||
* @param {boolean} visible
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
bool getVisible() const { return _isEnabled; }
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.togglePause
|
||||
*/
|
||||
|
||||
void togglePause() { setPause(!_isPaused); }
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.setPause
|
||||
* @param {boolean}
|
||||
*/
|
||||
|
||||
void setPause(bool paused) { _isPaused = paused; emit pauseChanged(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.getPause
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
bool getPause() { return _isPaused; }
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.toggleTrigger
|
||||
*/
|
||||
|
||||
void toggleTrigger() { _autoTrigger = !_autoTrigger; }
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.getAutoTrigger
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
bool getAutoTrigger() { return _autoTrigger; }
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.setAutoTrigger
|
||||
* @param {boolean} autoTrigger
|
||||
*/
|
||||
|
||||
void setAutoTrigger(bool autoTrigger) { _isTriggered = false; _autoTrigger = autoTrigger; }
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.setTriggerValues
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
*/
|
||||
|
||||
void setTriggerValues(int x, int y) { _triggerValues.x = x; _triggerValues.y = y; }
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.setTriggered
|
||||
* @param {boolean} triggered
|
||||
*/
|
||||
|
||||
void setTriggered(bool triggered) { _isTriggered = triggered; }
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.getTriggered
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
bool getTriggered() { return _isTriggered; }
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.getFramesPerSecond
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
float getFramesPerSecond();
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.getFramesPerScope
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
int getFramesPerScope() { return _framesPerScope; }
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.selectAudioScopeFiveFrames
|
||||
*/
|
||||
|
||||
void selectAudioScopeFiveFrames();
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.selectAudioScopeTwentyFrames
|
||||
*/
|
||||
|
||||
void selectAudioScopeTwentyFrames();
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.selectAudioScopeFiftyFrames
|
||||
*/
|
||||
|
||||
void selectAudioScopeFiftyFrames();
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.getScopeInput
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
QVector<int> getScopeInput() { return _scopeInputData; };
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.getScopeOutputLeft
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
QVector<int> getScopeOutputLeft() { return _scopeOutputLeftData; };
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.getScopeOutputRight
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
QVector<int> getScopeOutputRight() { return _scopeOutputRightData; };
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.getTriggerInput
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
QVector<int> getTriggerInput() { return _triggerInputData; };
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.getTriggerOutputLeft
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
QVector<int> getTriggerOutputLeft() { return _triggerOutputLeftData; };
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.getTriggerOutputRight
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
QVector<int> getTriggerOutputRight() { return _triggerOutputRightData; };
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.setLocalEcho
|
||||
* @parm {boolean} serverEcho
|
||||
*/
|
||||
|
||||
void setLocalEcho(bool serverEcho);
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.setServerEcho
|
||||
* @parm {boolean} serverEcho
|
||||
*/
|
||||
|
||||
void setServerEcho(bool serverEcho);
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.pauseChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void pauseChanged();
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioScope.triggered
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void triggered();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -27,12 +27,86 @@
|
|||
#include "AvatarMotionState.h"
|
||||
#include "MyAvatar.h"
|
||||
|
||||
/**jsdoc
|
||||
* The AvatarManager API has properties and methods which manage Avatars within the same domain.
|
||||
* @namespace AvatarManager
|
||||
*/
|
||||
|
||||
class AvatarManager : public AvatarHashMap {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
|
||||
// JSDOCS Copied over from AvatarHashMap (see AvatarHashMap.h for reason)
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.getAvatarIdentifiers
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.getAvatarsInRange
|
||||
* @param {Vec3} position
|
||||
* @param {float} rangeMeters
|
||||
* @returns {string[]}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.getAvatar
|
||||
* @param {string} avatarID
|
||||
* @returns {ScriptAvatarData}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.avatarAddedEvent
|
||||
* @param {string} sessionUUID
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.avatarRemovedEvent
|
||||
* @param {string} sessionUUID
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.avatarSessionChangedEvent
|
||||
* @param {string} sessionUUID
|
||||
* @param {string} oldUUID
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.isAvatarInRange
|
||||
* @param {string} position
|
||||
* @param {string} range
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.sessionUUIDChanged
|
||||
* @param {string} sessionUUID
|
||||
* @param {string} oldUUID
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.processAvatarDataPacket
|
||||
* @param {} message
|
||||
* @param {} sendingNode
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.processAvatarIdentityPacket
|
||||
* @param {} message
|
||||
* @param {} sendingNode
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.processKillAvatar
|
||||
* @param {} message
|
||||
* @param {} sendingNode
|
||||
*/
|
||||
|
||||
/// Registers the script types associated with the avatar manager.
|
||||
static void registerMetaTypes(QScriptEngine* engine);
|
||||
|
||||
|
@ -43,6 +117,12 @@ public:
|
|||
std::shared_ptr<MyAvatar> getMyAvatar() { return _myAvatar; }
|
||||
glm::vec3 getMyAvatarPosition() const { return _myAvatar->getWorldPosition(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.getAvatar
|
||||
* @param {string} avatarID
|
||||
* @returns {}
|
||||
*/
|
||||
|
||||
// Null/Default-constructed QUuids will return MyAvatar
|
||||
Q_INVOKABLE virtual ScriptAvatarData* getAvatar(QUuid avatarID) override { return new ScriptAvatar(getAvatarBySessionID(avatarID)); }
|
||||
|
||||
|
@ -66,24 +146,82 @@ public:
|
|||
void handleChangedMotionStates(const VectorOfMotionStates& motionStates);
|
||||
void handleCollisionEvents(const CollisionEvents& collisionEvents);
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.getAvatarDataRate
|
||||
* @param {string} sessionID
|
||||
* @param {string} [rateName=""]
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE float getAvatarDataRate(const QUuid& sessionID, const QString& rateName = QString("")) const;
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.getAvatarUpdateRate
|
||||
* @param {string} sessionID
|
||||
* @param {string} [rateName=""]
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE float getAvatarUpdateRate(const QUuid& sessionID, const QString& rateName = QString("")) const;
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.getAvatarSimulationRate
|
||||
* @param {string} sessionID
|
||||
* @param {string} [rateName=""]
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE float getAvatarSimulationRate(const QUuid& sessionID, const QString& rateName = QString("")) const;
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.findRayIntersection
|
||||
* @param {PickRay} ray
|
||||
* @param {} avatarIdsToInclude
|
||||
* @param {} avatarIdsToDiscard
|
||||
* @returns {RayToAvatarIntersectionResult}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray,
|
||||
const QScriptValue& avatarIdsToInclude = QScriptValue(),
|
||||
const QScriptValue& avatarIdsToDiscard = QScriptValue());
|
||||
/**jsdoc
|
||||
* @function AvatarManager.findRayIntersectionVector
|
||||
* @param {PickRay} ray
|
||||
* @param {} avatarsToInclude
|
||||
* @param {} avatarIdsToDiscard
|
||||
* @returns {RayToAvatarIntersectionResult}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersectionVector(const PickRay& ray,
|
||||
const QVector<EntityItemID>& avatarsToInclude,
|
||||
const QVector<EntityItemID>& avatarsToDiscard);
|
||||
|
||||
// TODO: remove this HACK once we settle on optimal default sort coefficients
|
||||
/**jsdoc
|
||||
* @function AvatarManager.getAvatarSortCoefficient
|
||||
* @param {string} name
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE float getAvatarSortCoefficient(const QString& name);
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.setAvatarSortCoefficient
|
||||
* @param {string} name
|
||||
* @param {string} value
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void setAvatarSortCoefficient(const QString& name, const QScriptValue& value);
|
||||
|
||||
float getMyAvatarSendRate() const { return _myAvatarSendRate.rate(); }
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarManager.updateAvatarRenderStatus
|
||||
* @param {boolean} shouldRenderAvatars
|
||||
*/
|
||||
|
||||
void updateAvatarRenderStatus(bool shouldRenderAvatars);
|
||||
|
||||
private:
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -26,6 +26,11 @@
|
|||
|
||||
#include <trackers/FaceTracker.h>
|
||||
|
||||
/**jsdoc
|
||||
* The FaceTracker API helps manage facial tracking hardware.
|
||||
* @namespace FaceTracker
|
||||
*/
|
||||
|
||||
class DdeFaceTracker : public FaceTracker, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
@ -57,7 +62,18 @@ public:
|
|||
void setEyeClosingThreshold(float eyeClosingThreshold);
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function FaceTracker.setEnabled
|
||||
* @param {boolean} enabled
|
||||
*/
|
||||
|
||||
void setEnabled(bool enabled) override;
|
||||
|
||||
/**jsdoc
|
||||
* @function FaceTracker.calibrate
|
||||
*/
|
||||
|
||||
void calibrate();
|
||||
|
||||
private slots:
|
||||
|
|
|
@ -34,7 +34,17 @@ void DownloadInfoResultFromScriptValue(const QScriptValue& object, DownloadInfoR
|
|||
|
||||
class AccountServicesScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* The AccountServices API contains helper functions related to user connectivity
|
||||
*
|
||||
* @namespace AccountServices
|
||||
* @property {string} username
|
||||
* @property {boolean} loggedIn
|
||||
* @property {string} findableBy
|
||||
* @property {string} metaverseServerURL
|
||||
*/
|
||||
|
||||
Q_PROPERTY(QString username READ getUsername NOTIFY myUsernameChanged)
|
||||
Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loggedInChanged)
|
||||
Q_PROPERTY(QString findableBy READ getFindableBy WRITE setFindableBy NOTIFY findableByChanged)
|
||||
|
@ -48,11 +58,38 @@ public:
|
|||
QUrl getMetaverseServerURL() { return DependencyManager::get<AccountManager>()->getMetaverseServerURL(); }
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function AccountServices.getDownloadInfo
|
||||
* @returns {DownloadInfoResult}
|
||||
*/
|
||||
|
||||
DownloadInfoResult getDownloadInfo();
|
||||
|
||||
/**jsdoc
|
||||
* @function AccountServices.updateDownloadInfo
|
||||
*/
|
||||
|
||||
void updateDownloadInfo();
|
||||
|
||||
/**jsdoc
|
||||
* @function AccountServices.isLoggedIn
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
bool isLoggedIn();
|
||||
|
||||
/**jsdoc
|
||||
* @function AccountServices.checkAndSignalForAccessToken
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
bool checkAndSignalForAccessToken();
|
||||
|
||||
/**jsdoc
|
||||
* @function AccountServices.logOut
|
||||
*/
|
||||
|
||||
void logOut();
|
||||
|
||||
private slots:
|
||||
|
@ -66,11 +103,52 @@ private slots:
|
|||
void onUsernameChanged(const QString& username);
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function AccountServices.connected
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void connected();
|
||||
|
||||
/**jsdoc
|
||||
* @function AccountServices.disconnected
|
||||
* @params {string} reason
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void disconnected(const QString& reason);
|
||||
|
||||
/**jsdoc
|
||||
* @function AccountServices.myUsernameChanged
|
||||
* @params {string} username
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void myUsernameChanged(const QString& username);
|
||||
|
||||
/**jsdoc
|
||||
* @function AccountServices.downloadInfoChanged
|
||||
* @params {} info
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void downloadInfoChanged(DownloadInfoResult info);
|
||||
|
||||
/**jsdoc
|
||||
* @function AccountServices.findableByChanged
|
||||
* @params {string} discoverabilityMode
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void findableByChanged(const QString& discoverabilityMode);
|
||||
|
||||
/**jsdoc
|
||||
* @function AccountServices.loggedInChanged
|
||||
* @params {boolean} loggedIn
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void loggedInChanged(bool loggedIn);
|
||||
|
||||
private:
|
||||
|
|
|
@ -25,6 +25,18 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable {
|
|||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
/**jsdoc
|
||||
* The Audio API features tools to help control audio contexts and settings.
|
||||
*
|
||||
* @namespace Audio
|
||||
* @property {boolean} muted
|
||||
* @property {boolean} noiseReduction
|
||||
* @property {boolean} inputVolume
|
||||
* @property {boolean} inputLevel
|
||||
* @property {string} context
|
||||
* @property {} devices
|
||||
*/
|
||||
|
||||
Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
|
||||
Q_PROPERTY(bool noiseReduction READ noiseReductionEnabled WRITE enableNoiseReduction NOTIFY noiseReductionChanged)
|
||||
Q_PROPERTY(float inputVolume READ getInputVolume WRITE setInputVolume NOTIFY inputVolumeChanged)
|
||||
|
@ -49,24 +61,111 @@ public:
|
|||
|
||||
void showMicMeter(bool show);
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.setInputDevice
|
||||
* @param {} device
|
||||
* @param {boolean} isHMD
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void setInputDevice(const QAudioDeviceInfo& device, bool isHMD);
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.setOutputDevice
|
||||
* @param {} device
|
||||
* @param {boolean} isHMD
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void setOutputDevice(const QAudioDeviceInfo& device, bool isHMD);
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.setReverb
|
||||
* @param {boolean} enable
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void setReverb(bool enable);
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.setReverbOptions
|
||||
* @param {} options
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void setReverbOptions(const AudioEffectOptions* options);
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.setReverbOptions
|
||||
* @param {string} filename
|
||||
*/
|
||||
|
||||
Q_INVOKABLE bool startRecording(const QString& filename);
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.stopRecording
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void stopRecording();
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.getRecording
|
||||
*/
|
||||
|
||||
Q_INVOKABLE bool getRecording();
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.nop
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void nop();
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.nop
|
||||
* @param {bool} isMuted
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void mutedChanged(bool isMuted);
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.noiseReductionChanged
|
||||
* @param {bool} isEnabled
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void noiseReductionChanged(bool isEnabled);
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.inputVolumeChanged
|
||||
* @param {float} volume
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void inputVolumeChanged(float volume);
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.inputLevelChanged
|
||||
* @param {float} level
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void inputLevelChanged(float level);
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.contextChanged
|
||||
* @param {string} context
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void contextChanged(const QString& context);
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function Audio.onContextChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void onContextChanged();
|
||||
|
||||
private slots:
|
||||
|
|
|
@ -15,6 +15,11 @@
|
|||
#include <QObject>
|
||||
#include <DependencyManager.h>
|
||||
|
||||
/**jsdoc
|
||||
* The GooglePoly API allows you to interact with Google Poly models direct from inside High Fidelity.
|
||||
* @namespace GooglePoly
|
||||
*/
|
||||
|
||||
class GooglePolyScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -22,15 +27,84 @@ public:
|
|||
GooglePolyScriptingInterface();
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function GooglePoly.setAPIKey
|
||||
* @param {string} key
|
||||
*/
|
||||
|
||||
void setAPIKey(const QString& key);
|
||||
|
||||
/**jsdoc
|
||||
* @function GooglePoly.getAssetList
|
||||
* @param {string} keyword
|
||||
* @param {string} category
|
||||
* @param {string} format
|
||||
* @returns {string}
|
||||
*/
|
||||
|
||||
QString getAssetList(const QString& keyword, const QString& category, const QString& format);
|
||||
|
||||
/**jsdoc
|
||||
* @function GooglePoly.getFBX
|
||||
* @param {string} keyword
|
||||
* @param {string} category
|
||||
* @returns {string}
|
||||
*/
|
||||
|
||||
QString getFBX(const QString& keyword, const QString& category);
|
||||
|
||||
/**jsdoc
|
||||
* @function GooglePoly.getOBJ
|
||||
* @param {string} keyword
|
||||
* @param {string} category
|
||||
* @returns {string}
|
||||
*/
|
||||
|
||||
QString getOBJ(const QString& keyword, const QString& category);
|
||||
QString getBlocks(const QString& keyword, const QString& categoryy);
|
||||
|
||||
/**jsdoc
|
||||
* @function GooglePoly.getBlocks
|
||||
* @param {string} keyword
|
||||
* @param {string} category
|
||||
* @returns {string}
|
||||
*/
|
||||
|
||||
QString getBlocks(const QString& keyword, const QString& category);
|
||||
|
||||
/**jsdoc
|
||||
* @function GooglePoly.getGLTF
|
||||
* @param {string} keyword
|
||||
* @param {string} category
|
||||
* @returns {string}
|
||||
*/
|
||||
|
||||
QString getGLTF(const QString& keyword, const QString& category);
|
||||
|
||||
/**jsdoc
|
||||
* @function GooglePoly.getGLTF2
|
||||
* @param {string} keyword
|
||||
* @param {string} category
|
||||
* @returns {string}
|
||||
*/
|
||||
|
||||
QString getGLTF2(const QString& keyword, const QString& category);
|
||||
|
||||
/**jsdoc
|
||||
* @function GooglePoly.getTilt
|
||||
* @param {string} keyword
|
||||
* @param {string} category
|
||||
* @returns {string}
|
||||
*/
|
||||
|
||||
QString getTilt(const QString& keyword, const QString& category);
|
||||
|
||||
/**jsdoc
|
||||
* @function GooglePoly.getModelInfo
|
||||
* @param {string} input
|
||||
* @returns {string}
|
||||
*/
|
||||
|
||||
QString getModelInfo(const QString& input);
|
||||
|
||||
private:
|
||||
|
|
|
@ -56,6 +56,19 @@ bool GameplayObjects::removeFromGameplayObjects(const OverlayID& overlayID) {
|
|||
SelectionScriptingInterface::SelectionScriptingInterface() {
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>"avatar"</code></td><td></td></tr>
|
||||
* <tr><td><code>"entity"</code></td><td></td></tr>
|
||||
* <tr><td><code>"overlay"</code></td><td></td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} Selection.ItemType
|
||||
*/
|
||||
bool SelectionScriptingInterface::addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id) {
|
||||
if (itemType == "avatar") {
|
||||
return addToGameplayObjects(listName, (QUuid)id);
|
||||
|
@ -255,6 +268,12 @@ void SelectionScriptingInterface::printList(const QString& listName) {
|
|||
}
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* @typedef {object} Selection.SelectedItemsList
|
||||
* @property {Uuid[]} avatars - The IDs of the avatars in the selection.
|
||||
* @property {Uuid[]} entities - The IDs of the entities in the selection.
|
||||
* @property {Uuid[]} overlays - The IDs of the overlays in the selection.
|
||||
*/
|
||||
QVariantMap SelectionScriptingInterface::getSelectedItemsList(const QString& listName) const {
|
||||
QReadLocker lock(&_selectionListsLock);
|
||||
QVariantMap list;
|
||||
|
@ -461,6 +480,20 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* @typedef {object} Selection.HighlightStyle
|
||||
* @property {Color} outlineUnoccludedColor - Color of the specified highlight region.
|
||||
* @property {Color} outlineOccludedColor - ""
|
||||
* @property {Color} fillUnoccludedColor- ""
|
||||
* @property {Color} fillOccludedColor- ""
|
||||
* @property {number} outlineUnoccludedAlpha - Alpha value ranging from <code>0.0</code> (not visible) to <code>1.0</code>
|
||||
* (fully opaque) for the specified highlight region.
|
||||
* @property {number} outlineOccludedAlpha - ""
|
||||
* @property {number} fillUnoccludedAlpha - ""
|
||||
* @property {number} fillOccludedAlpha - ""
|
||||
* @property {number} outlineWidth - Width of the outline, in pixels.
|
||||
* @property {boolean} isOutlineSmooth - <code>true</code> to enable outline smooth fall-off.
|
||||
*/
|
||||
QVariantMap SelectionHighlightStyle::toVariantMap() const {
|
||||
QVariantMap properties;
|
||||
|
||||
|
|
|
@ -82,6 +82,46 @@ protected:
|
|||
render::HighlightStyle _style;
|
||||
};
|
||||
|
||||
/**jsdoc
|
||||
* The <code>Selection</code> API provides a means of grouping together avatars, entities, and overlays in named lists.
|
||||
* @namespace Selection
|
||||
*
|
||||
* @example <caption>Outline an entity when it is grabbed by a controller.</caption>
|
||||
* // Create a box and copy the following text into the entity's "Script URL" field.
|
||||
* (function () {
|
||||
* print("Starting highlight script...............");
|
||||
* var _this = this;
|
||||
* var prevID = 0;
|
||||
* var listName = "contextOverlayHighlightList";
|
||||
* var listType = "entity";
|
||||
*
|
||||
* _this.startNearGrab = function(entityID){
|
||||
* if (prevID !== entityID) {
|
||||
* Selection.addToSelectedItemsList(listName, listType, entityID);
|
||||
* prevID = entityID;
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* _this.releaseGrab = function(entityID){
|
||||
* if (prevID !== 0) {
|
||||
* Selection.removeFromSelectedItemsList("contextOverlayHighlightList", listType, prevID);
|
||||
* prevID = 0;
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* var cleanup = function(){
|
||||
* Entities.findEntities(MyAvatar.position, 1000).forEach(function(entity) {
|
||||
* try {
|
||||
* Selection.removeListFromMap(listName);
|
||||
* } catch (e) {
|
||||
* print("Error cleaning up.");
|
||||
* }
|
||||
* });
|
||||
* };
|
||||
*
|
||||
* Script.scriptEnding.connect(cleanup);
|
||||
* });
|
||||
*/
|
||||
class SelectionScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -89,138 +129,120 @@ public:
|
|||
SelectionScriptingInterface();
|
||||
|
||||
/**jsdoc
|
||||
* Query the names of all the selection lists
|
||||
* Get the names of all the selection lists.
|
||||
* @function Selection.getListNames
|
||||
* @return An array of names of all the selection lists
|
||||
* @return {list[]} An array of names of all the selection lists.
|
||||
*/
|
||||
Q_INVOKABLE QStringList getListNames() const;
|
||||
|
||||
/**jsdoc
|
||||
* Removes a named selection from the list of selections.
|
||||
* Delete a named selection list.
|
||||
* @function Selection.removeListFromMap
|
||||
* @param listName {string} name of the selection
|
||||
* @returns {bool} true if the selection existed and was successfully removed.
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> if the selection existed and was successfully removed, otherwise <code>false</code>.
|
||||
*/
|
||||
Q_INVOKABLE bool removeListFromMap(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Add an item in a selection.
|
||||
* Add an item to a selection list.
|
||||
* @function Selection.addToSelectedItemsList
|
||||
* @param listName {string} name of the selection
|
||||
* @param itemType {string} the type of the item (one of "avatar", "entity" or "overlay")
|
||||
* @param id {EntityID} the Id of the item to add to the selection
|
||||
* @returns {bool} true if the item was successfully added.
|
||||
* @param {string} listName - The name of the selection list to add the item to.
|
||||
* @param {Selection.ItemType} itemType - The type of the item being added.
|
||||
* @param {Uuid} id - The ID of the item to add to the selection.
|
||||
* @returns {boolean} <code>true</code> if the item was successfully added, otherwise <code>false</code>.
|
||||
*/
|
||||
Q_INVOKABLE bool addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id);
|
||||
/**jsdoc
|
||||
* Remove an item from a selection.
|
||||
* Remove an item from a selection list.
|
||||
* @function Selection.removeFromSelectedItemsList
|
||||
* @param listName {string} name of the selection
|
||||
* @param itemType {string} the type of the item (one of "avatar", "entity" or "overlay")
|
||||
* @param id {EntityID} the Id of the item to remove
|
||||
* @returns {bool} true if the item was successfully removed.
|
||||
* @param {string} listName - The name of the selection list to remove the item from.
|
||||
* @param {Selection.ItemType} itemType - The type of the item being removed.
|
||||
* @param {Uuid} id - The ID of the item to remove.
|
||||
* @returns {boolean} <code>true</code> if the item was successfully removed, otherwise <code>false</code>.
|
||||
* <codefalse</code> is returned if the list doesn't contain any data.
|
||||
*/
|
||||
Q_INVOKABLE bool removeFromSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id);
|
||||
/**jsdoc
|
||||
* Remove all items from a selection.
|
||||
* @function Selection.clearSelectedItemsList
|
||||
* @param listName {string} name of the selection
|
||||
* @returns {bool} true if the item was successfully cleared.
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> if the item was successfully cleared, otherwise <code>false</code>.
|
||||
*/
|
||||
Q_INVOKABLE bool clearSelectedItemsList(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Prints out the list of avatars, entities and overlays stored in a particular selection.
|
||||
* Print out the list of avatars, entities, and overlays in a selection to the <em>debug log</em> (not the script log).
|
||||
* @function Selection.printList
|
||||
* @param listName {string} name of the selection
|
||||
* @param {string} listName - The name of the selection list.
|
||||
*/
|
||||
Q_INVOKABLE void printList(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Query the list of avatars, entities and overlays stored in a particular selection.
|
||||
* Get the list of avatars, entities, and overlays stored in a selection list.
|
||||
* @function Selection.getList
|
||||
* @param listName {string} name of the selection
|
||||
* @return a js object describing the content of a selection list with the following properties:
|
||||
* - "entities": [ and array of the entityID of the entities in the selection]
|
||||
* - "avatars": [ and array of the avatarID of the avatars in the selection]
|
||||
* - "overlays": [ and array of the overlayID of the overlays in the selection]
|
||||
* If the list name doesn't exist, the function returns an empty js object with no properties.
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @return {Selection.SelectedItemsList} The content of a selection list. If the list name doesn't exist, the function
|
||||
* returns an empty object with no properties.
|
||||
*/
|
||||
Q_INVOKABLE QVariantMap getSelectedItemsList(const QString& listName) const;
|
||||
|
||||
/**jsdoc
|
||||
* Query the names of the highlighted selection lists
|
||||
* Get the names of the highlighted selection lists.
|
||||
* @function Selection.getHighlightedListNames
|
||||
* @return An array of names of the selection list currently highlight enabled
|
||||
* @return {string[]} An array of names of the selection list currently highlight enabled.
|
||||
*/
|
||||
Q_INVOKABLE QStringList getHighlightedListNames() const;
|
||||
|
||||
/**jsdoc
|
||||
* Enable highlighting for the named selection.
|
||||
* If the Selection doesn't exist, it will be created.
|
||||
* All objects in the list will be displayed with the highlight effect as specified from the highlightStyle.
|
||||
* The function can be called several times with different values in the style to modify it.
|
||||
*
|
||||
* Enable highlighting for a selection list.
|
||||
* If the selection list doesn't exist, it will be created.
|
||||
* All objects in the list will be displayed with the highlight effect specified.
|
||||
* The function can be called several times with different values in the style to modify it.<br />
|
||||
* Note: This function implicitly calls {@link Selection.enableListToScene}.
|
||||
* @function Selection.enableListHighlight
|
||||
* @param listName {string} name of the selection
|
||||
* @param highlightStyle {jsObject} highlight style fields (see Selection.getListHighlightStyle for a detailed description of the highlightStyle).
|
||||
* @returns {bool} true if the selection was successfully enabled for highlight.
|
||||
*
|
||||
* Note: This function will implicitly call Selection.enableListToScene
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @param {Selection.HighlightStyle} highlightStyle - The highlight style.
|
||||
* @returns {boolean} true if the selection was successfully enabled for highlight.
|
||||
*/
|
||||
Q_INVOKABLE bool enableListHighlight(const QString& listName, const QVariantMap& highlightStyle);
|
||||
|
||||
/**jsdoc
|
||||
* Disable highlighting for the named selection.
|
||||
* If the Selection doesn't exist or wasn't enabled for highliting then nothing happens simply returning false.
|
||||
*
|
||||
* Disable highlighting for the selection list.
|
||||
* If the selection list doesn't exist or wasn't enabled for highlighting then nothing happens and <code>false</code> is
|
||||
* returned.<br />
|
||||
* Note: This function implicitly calls {@link Selection.disableListToScene}.
|
||||
* @function Selection.disableListHighlight
|
||||
* @param listName {string} name of the selection
|
||||
* @returns {bool} true if the selection was successfully disabled for highlight, false otherwise.
|
||||
*
|
||||
* Note: This function will implicitly call Selection.disableListToScene
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> if the selection was successfully disabled for highlight, otherwise
|
||||
* <code>false</code>.
|
||||
*/
|
||||
Q_INVOKABLE bool disableListHighlight(const QString& listName);
|
||||
/**jsdoc
|
||||
* Enable scene selection for the named selection.
|
||||
* Enable scene selection for the selection list.
|
||||
* If the Selection doesn't exist, it will be created.
|
||||
* All objects in the list will be sent to a scene selection.
|
||||
*
|
||||
* @function Selection.enableListToScene
|
||||
* @param listName {string} name of the selection
|
||||
* @returns {bool} true if the selection was successfully enabled on the scene.
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> if the selection was successfully enabled on the scene, otherwise <code>false</code>.
|
||||
*/
|
||||
Q_INVOKABLE bool enableListToScene(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Disable scene selection for the named selection.
|
||||
* If the Selection doesn't exist or wasn't enabled on the scene then nothing happens simply returning false.
|
||||
*
|
||||
* If the selection list doesn't exist or wasn't enabled on the scene then nothing happens and <code>false</code> is
|
||||
* returned.
|
||||
* @function Selection.disableListToScene
|
||||
* @param listName {string} name of the selection
|
||||
* @returns {bool} true if the selection was successfully disabled on the scene, false otherwise.
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} true if the selection was successfully disabled on the scene, false otherwise.
|
||||
*/
|
||||
Q_INVOKABLE bool disableListToScene(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Query the highlight style values for the named selection.
|
||||
* If the Selection doesn't exist or hasn't been highlight enabled yet, it will return an empty object.
|
||||
* Otherwise, the jsObject describes the highlight style properties:
|
||||
* - outlineUnoccludedColor: {xColor} Color of the specified highlight region
|
||||
* - outlineOccludedColor: {xColor} "
|
||||
* - fillUnoccludedColor: {xColor} "
|
||||
* - fillOccludedColor: {xColor} "
|
||||
*
|
||||
* - outlineUnoccludedAlpha: {float} Alpha value ranging from 0.0 (not visible) to 1.0 (fully opaque) for the specified highlight region
|
||||
* - outlineOccludedAlpha: {float} "
|
||||
* - fillUnoccludedAlpha: {float} "
|
||||
* - fillOccludedAlpha: {float} "
|
||||
*
|
||||
* - outlineWidth: {float} width of the outline expressed in pixels
|
||||
* - isOutlineSmooth: {bool} true to enable oultine smooth falloff
|
||||
*
|
||||
* Get the highlight style values for the a selection list.
|
||||
* If the selection doesn't exist or hasn't been highlight enabled yet, an empty object is returned.
|
||||
* @function Selection.getListHighlightStyle
|
||||
* @param listName {string} name of the selection
|
||||
* @returns {jsObject} highlight style as described above
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {Selection.HighlightStyle} highlight style
|
||||
*/
|
||||
Q_INVOKABLE QVariantMap getListHighlightStyle(const QString& listName) const;
|
||||
|
||||
|
@ -232,6 +254,12 @@ public:
|
|||
void onSelectedItemsListChanged(const QString& listName);
|
||||
|
||||
signals:
|
||||
/**jsoc
|
||||
* Triggered when a list's content changes.
|
||||
* @function Selection.selectedItemsListChanged
|
||||
* @param {string} listName - The name of the selection list that changed.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void selectedItemsListChanged(const QString& listName);
|
||||
|
||||
private:
|
||||
|
|
|
@ -23,6 +23,15 @@ class AvatarInputs : public QObject {
|
|||
Q_OBJECT
|
||||
HIFI_QML_DECL
|
||||
|
||||
/**jsdoc
|
||||
* API to help manage your Avatar's input
|
||||
* @namespace AvatarInputs
|
||||
* @param {boolean} cameraEnabled
|
||||
* @param {boolean} cameraMuted
|
||||
* @param {boolean} isHMD
|
||||
* @param {boolean} showAudioTools
|
||||
*/
|
||||
|
||||
AI_PROPERTY(bool, cameraEnabled, false)
|
||||
AI_PROPERTY(bool, cameraMuted, false)
|
||||
AI_PROPERTY(bool, isHMD, false)
|
||||
|
@ -31,22 +40,70 @@ class AvatarInputs : public QObject {
|
|||
|
||||
public:
|
||||
static AvatarInputs* getInstance();
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarInputs.loudnessToAudioLevel
|
||||
* @param {number} loudness
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE float loudnessToAudioLevel(float loudness);
|
||||
AvatarInputs(QObject* parent = nullptr);
|
||||
void update();
|
||||
bool showAudioTools() const { return _showAudioTools; }
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarInputs.setShowAudioTools
|
||||
* @param {boolean} showAudioTools
|
||||
*/
|
||||
|
||||
void setShowAudioTools(bool showAudioTools);
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarInputs.cameraEnabledChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void cameraEnabledChanged();
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarInputs.cameraMutedChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void cameraMutedChanged();
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarInputs.isHMDChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void isHMDChanged();
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarInputs.showAudioToolsChanged
|
||||
* @param {boolean} show
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void showAudioToolsChanged(bool show);
|
||||
|
||||
protected:
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarInputs.resetSensors
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void resetSensors();
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarInputs.toggleCameraMute
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void toggleCameraMute();
|
||||
|
||||
private:
|
||||
|
|
|
@ -331,16 +331,20 @@ void Web3DOverlay::render(RenderArgs* args) {
|
|||
renderTransform.setScale(1.0f);
|
||||
batch.setModelTransform(renderTransform);
|
||||
|
||||
// Turn off jitter for these entities
|
||||
batch.pushProjectionJitter();
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (color.a < OPAQUE_ALPHA_THRESHOLD) {
|
||||
geometryCache->bindWebBrowserProgram(batch, true);
|
||||
} else {
|
||||
geometryCache->bindWebBrowserProgram(batch);
|
||||
}
|
||||
|
||||
vec2 halfSize = vec2(size.x, size.y) / 2.0f;
|
||||
geometryCache->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color, _geometryId);
|
||||
batch.popProjectionJitter(); // Restore jitter
|
||||
batch.setResourceTexture(0, nullptr); // restore default white color after me
|
||||
|
||||
}
|
||||
|
||||
Transform Web3DOverlay::evalRenderTransform() {
|
||||
|
|
|
@ -20,6 +20,11 @@
|
|||
#include <FBXReader.h>
|
||||
#include <ResourceCache.h>
|
||||
|
||||
/**jsdoc
|
||||
* API to manage Animation Cache resources
|
||||
* @namespace AnimationCache
|
||||
*/
|
||||
|
||||
class Animation;
|
||||
|
||||
typedef QSharedPointer<Animation> AnimationPointer;
|
||||
|
@ -29,19 +34,80 @@ class AnimationCache : public ResourceCache, public Dependency {
|
|||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
// Copied over from ResourceCache (see ResourceCache.h for reason)
|
||||
|
||||
/**jsdoc
|
||||
* @namespace AnimationCache
|
||||
* @augments ResourceCache
|
||||
* @property numTotal {number} total number of total resources
|
||||
* @property numCached {number} total number of cached resource
|
||||
* @property sizeTotal {number} size in bytes of all resources
|
||||
* @property sizeCached {number} size in bytes of all cached resources
|
||||
*/
|
||||
|
||||
public:
|
||||
/**jsdoc
|
||||
* Returns the total number of resources
|
||||
* @function AnimationCache.getNumTotalResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total size in bytes of all resources
|
||||
* @function AnimationCache.getSizeTotalResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total number of cached resources
|
||||
* @function AnimationCache.getNumCachedResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total size in bytes of cached resources
|
||||
* @function AnimationCache.getSizeCachedResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns list of all resource urls
|
||||
* @function AnimationCache.getResourceList
|
||||
* @returns {string[]}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Asynchronously loads a resource from the spedified URL and returns it.
|
||||
* @param url {string} url of resource to load
|
||||
* @param fallback {string} fallback URL if load of the desired url fails
|
||||
* @function AnimationCache.getResource
|
||||
* @returns {Resource}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Prefetches a resource.
|
||||
* @param url {string} url of resource to load
|
||||
* @function AnimationCache.prefetch
|
||||
* @returns {Resource}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @param {number} deltaSize
|
||||
* @function AnimationCache.updateTotalSize
|
||||
* @returns {Resource}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function AnimationCache.dirty
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns animation resource for particular animation
|
||||
* @function AnimationCache.getAnimation
|
||||
* @param url {string} url to load
|
||||
* @return {Resource} animation
|
||||
* @returns {Resource} animation
|
||||
*/
|
||||
|
||||
Q_INVOKABLE AnimationPointer getAnimation(const QString& url) { return getAnimation(QUrl(url)); }
|
||||
Q_INVOKABLE AnimationPointer getAnimation(const QUrl& url);
|
||||
|
||||
|
|
|
@ -38,6 +38,49 @@ class MixedProcessedAudioStream;
|
|||
|
||||
class AudioStreamStatsInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
/**jsdoc
|
||||
* Audio stats from the Audio Mixer
|
||||
* @namespace AudioStats.mixerStream
|
||||
* @param {number} lossRate
|
||||
* @param {number} lossCount
|
||||
* @param {number} lossRateWindow
|
||||
* @param {number} lossCountWindow
|
||||
* @param {number} framesDesired
|
||||
* @param {number} framesAvailable
|
||||
* @param {number} framesAvailableAvg
|
||||
* @param {number} unplayedMsMax
|
||||
* @param {number} starveCount
|
||||
* @param {number} lastStarveDurationCount
|
||||
* @param {number} dropCount
|
||||
* @param {number} overflowCount
|
||||
* @param {number} timegapMsMax
|
||||
* @param {number} timegapMsAvg
|
||||
* @param {number} timegapMsMaxWindow
|
||||
* @param {number} timegapMsAvgWindow
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Audio stats from the Client Mixer
|
||||
* @namespace AudioStats.clientMixer
|
||||
* @param {number} lossRate
|
||||
* @param {number} lossCount
|
||||
* @param {number} lossRateWindow
|
||||
* @param {number} lossCountWindow
|
||||
* @param {number} framesDesired
|
||||
* @param {number} framesAvailable
|
||||
* @param {number} framesAvailableAvg
|
||||
* @param {number} unplayedMsMax
|
||||
* @param {number} starveCount
|
||||
* @param {number} lastStarveDurationCount
|
||||
* @param {number} dropCount
|
||||
* @param {number} overflowCount
|
||||
* @param {number} timegapMsMax
|
||||
* @param {number} timegapMsAvg
|
||||
* @param {number} timegapMsMaxWindow
|
||||
* @param {number} timegapMsAvgWindow
|
||||
*/
|
||||
|
||||
AUDIO_PROPERTY(float, lossRate)
|
||||
AUDIO_PROPERTY(float, lossCount)
|
||||
AUDIO_PROPERTY(float, lossRateWindow)
|
||||
|
@ -68,6 +111,20 @@ private:
|
|||
|
||||
class AudioStatsInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
/**jsdoc
|
||||
* Audio stats from the client
|
||||
* @namespace AudioStats
|
||||
* @param {number} pingMs
|
||||
* @param {number} inputReadMsMax
|
||||
* @param {number} inputUnplayedMsMax
|
||||
* @param {number} outputUnplayedMsMax
|
||||
* @param {number} sentTimegapMsMax
|
||||
* @param {number} sentTimegapMsAvg
|
||||
* @param {number} sentTimegapMsMaxWindow
|
||||
* @param {number} sentTimegapMsAvgWindow
|
||||
*/
|
||||
|
||||
AUDIO_PROPERTY(float, pingMs);
|
||||
|
||||
AUDIO_PROPERTY(float, inputReadMsMax);
|
||||
|
@ -97,8 +154,26 @@ public:
|
|||
void updateInjectorStreams(const QHash<QUuid, AudioStreamStats>& stats);
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioStats.mixerStreamChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void mixerStreamChanged();
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioStats.clientStreamChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void clientStreamChanged();
|
||||
|
||||
/**jsdoc
|
||||
* @function AudioStats.injectorStreamsChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void injectorStreamsChanged();
|
||||
|
||||
private:
|
||||
|
|
|
@ -16,12 +16,97 @@
|
|||
|
||||
#include "Sound.h"
|
||||
|
||||
/**jsdoc
|
||||
* API to manage Sound Cache resources
|
||||
* @namespace SoundCache
|
||||
*/
|
||||
|
||||
|
||||
/// Scriptable interface for sound loading.
|
||||
class SoundCache : public ResourceCache, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
// Copied over from ResourceCache (see ResourceCache.h for reason)
|
||||
|
||||
/**jsdoc
|
||||
* @namespace SoundCache
|
||||
* @property numTotal {number} total number of total resources
|
||||
* @property numCached {number} total number of cached resource
|
||||
* @property sizeTotal {number} size in bytes of all resources
|
||||
* @property sizeCached {number} size in bytes of all cached resources
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total number of resources
|
||||
* @function SoundCache.getNumTotalResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total size in bytes of all resources
|
||||
* @function SoundCache.getSizeTotalResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total number of cached resources
|
||||
* @function SoundCache.getNumCachedResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total size in bytes of cached resources
|
||||
* @function SoundCache.getSizeCachedResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns list of all resource urls
|
||||
* @function SoundCache.getResourceList
|
||||
* @returns {string[]}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns animation resource for particular animation
|
||||
* @function SoundCache.getAnimation
|
||||
* @param url {string} url to load
|
||||
* @returns {Resource} animation
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Asynchronously loads a resource from the spedified URL and returns it.
|
||||
* @param url {string} url of resource to load
|
||||
* @param fallback {string} fallback URL if load of the desired url fails
|
||||
* @function SoundCache.getResource
|
||||
* @returns {Resource}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Prefetches a resource.
|
||||
* @param url {string} url of resource to load
|
||||
* @function SoundCache.prefetch
|
||||
* @returns {Resource}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @param {number} deltaSize
|
||||
* @function SoundCache.updateTotalSize
|
||||
* @returns {Resource}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function SoundCache.dirty
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function SoundCache.getSound
|
||||
* @param {string} url
|
||||
* @returns {}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE SharedSoundPointer getSound(const QUrl& url);
|
||||
protected:
|
||||
virtual QSharedPointer<Resource> createResource(const QUrl& url, const QSharedPointer<Resource>& fallback,
|
||||
|
|
|
@ -57,15 +57,7 @@ using AvatarPhysicsCallback = std::function<void(uint32_t)>;
|
|||
class Avatar : public AvatarData, public scriptable::ModelProvider {
|
||||
Q_OBJECT
|
||||
|
||||
/**jsdoc
|
||||
* An avatar is representation of yourself or another user. The Avatar API can be used to query or manipulate the avatar of a user.
|
||||
* NOTE: Avatar extends AvatarData, see those namespace for more properties/methods.
|
||||
*
|
||||
* @namespace Avatar
|
||||
* @augments AvatarData
|
||||
*
|
||||
* @property skeletonOffset {Vec3} can be used to apply a translation offset between the avatar's position and the registration point of the 3d model.
|
||||
*/
|
||||
// This property has JSDoc in MyAvatar.h.
|
||||
Q_PROPERTY(glm::vec3 skeletonOffset READ getSkeletonOffset WRITE setSkeletonOffset)
|
||||
|
||||
public:
|
||||
|
@ -128,14 +120,25 @@ public:
|
|||
virtual int getJointIndex(const QString& name) const override;
|
||||
virtual QStringList getJointNames() const override;
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getDefaultJointRotation
|
||||
* @param {number} index
|
||||
* @returns {Quat}
|
||||
*/
|
||||
Q_INVOKABLE virtual glm::quat getDefaultJointRotation(int index) const;
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getDefaultJointTranslation
|
||||
* @param {number} index
|
||||
* @returns {Vec3}
|
||||
*/
|
||||
Q_INVOKABLE virtual glm::vec3 getDefaultJointTranslation(int index) const;
|
||||
|
||||
/**jsdoc
|
||||
* Provides read only access to the default joint rotations in avatar coordinates.
|
||||
* The default pose of the avatar is defined by the position and orientation of all bones
|
||||
* in the avatar's model file. Typically this is a t-pose.
|
||||
* @function Avatar.getAbsoluteDefaultJointRotationInObjectFrame
|
||||
* in the avatar's model file. Typically this is a T-pose.
|
||||
* @function MyAvatar.getAbsoluteDefaultJointRotationInObjectFrame
|
||||
* @param index {number} index number
|
||||
* @returns {Quat} The rotation of this joint in avatar coordinates.
|
||||
*/
|
||||
|
@ -144,8 +147,8 @@ public:
|
|||
/**jsdoc
|
||||
* Provides read only access to the default joint translations in avatar coordinates.
|
||||
* The default pose of the avatar is defined by the position and orientation of all bones
|
||||
* in the avatar's model file. Typically this is a t-pose.
|
||||
* @function Avatar.getAbsoluteDefaultJointTranslationInObjectFrame
|
||||
* in the avatar's model file. Typically this is a T-pose.
|
||||
* @function MyAvatar.getAbsoluteDefaultJointTranslationInObjectFrame
|
||||
* @param index {number} index number
|
||||
* @returns {Vec3} The position of this joint in avatar coordinates.
|
||||
*/
|
||||
|
@ -170,14 +173,65 @@ public:
|
|||
|
||||
virtual void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) { }
|
||||
|
||||
/**jsdoc
|
||||
* Set the offset applied to the current avatar. The offset adjusts the position that the avatar is rendered. For example,
|
||||
* with an offset of <code>{ x: 0, y: 0.1, z: 0 }</code>, your avatar will appear to be raised off the ground slightly.
|
||||
* @function MyAvatar.setSkeletonOffset
|
||||
* @param {Vec3} offset - The skeleton offset to set.
|
||||
* @example <caption>Raise your avatar off the ground a little.</caption>
|
||||
* // Raise your avatar off the ground a little.
|
||||
* MyAvatar.setSkeletonOffset({ x: 0, y: 0.1: z: 0 });
|
||||
*
|
||||
* // Restore its offset after 5s.
|
||||
* Script.setTimeout(function () {
|
||||
* MyAvatar.setSkeletonOffset(Vec3.ZERO);
|
||||
* }, 5000);
|
||||
*/
|
||||
Q_INVOKABLE void setSkeletonOffset(const glm::vec3& offset);
|
||||
|
||||
/**jsdoc
|
||||
* Get the offset applied to the current avatar. The offset adjusts the position that the avatar is rendered. For example,
|
||||
* with an offset of <code>{ x: 0, y: 0.1, z: 0 }</code>, your avatar will appear to be raised off the ground slightly.
|
||||
* @function MyAvatar.getSkeletonOffset
|
||||
* @returns {Vec3} The current skeleton offset.
|
||||
* @example <caption>Report your avatar's current skeleton offset.</caption>
|
||||
* print(JSON.stringify(MyAvatar.getSkeletonOffset());
|
||||
*/
|
||||
Q_INVOKABLE glm::vec3 getSkeletonOffset() { return _skeletonOffset; }
|
||||
|
||||
virtual glm::vec3 getSkeletonPosition() const;
|
||||
|
||||
/**jsdoc
|
||||
* Get the position of a joint in the current avatar.
|
||||
* @function MyAvatar.getJointPosition
|
||||
* @param {number} index - The index of the joint.
|
||||
* @returns {Vec3} The position of the joint in world coordinates.
|
||||
*/
|
||||
Q_INVOKABLE glm::vec3 getJointPosition(int index) const;
|
||||
|
||||
/**jsdoc
|
||||
* Get the position of a joint in the current avatar.
|
||||
* @function MyAvatar.getJointPosition
|
||||
* @param {string} name - The name of the joint.
|
||||
* @returns {Vec3} The position of the joint in world coordinates.
|
||||
* @example <caption>Report the position of your avatar's hips.</caption>
|
||||
* print(JSON.stringify(MyAvatar.getJointPosition("Hips")));
|
||||
*/
|
||||
Q_INVOKABLE glm::vec3 getJointPosition(const QString& name) const;
|
||||
|
||||
/**jsdoc
|
||||
* Get the position of the current avatar's neck in world coordinates.
|
||||
* @function MyAvatar.getNeckPosition
|
||||
* @returns {Vec3} The position of the neck in world coordinates.
|
||||
* @example <caption>Report the position of your avatar's neck.</caption>
|
||||
* print(JSON.stringify(MyAvatar.getNeckPosition()));
|
||||
*/
|
||||
Q_INVOKABLE glm::vec3 getNeckPosition() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getAcceleration
|
||||
* @returns {Vec3}
|
||||
*/
|
||||
Q_INVOKABLE glm::vec3 getAcceleration() const { return _acceleration; }
|
||||
|
||||
/// Scales a world space position vector relative to the avatar position and scale
|
||||
|
@ -201,24 +255,47 @@ public:
|
|||
void setPositionViaScript(const glm::vec3& position) override;
|
||||
void setOrientationViaScript(const glm::quat& orientation) override;
|
||||
|
||||
// these call through to the SpatiallyNestable versions, but they are here to expose these to javascript.
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getParentID
|
||||
* @returns {Uuid}
|
||||
*/
|
||||
// This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript.
|
||||
Q_INVOKABLE virtual const QUuid getParentID() const override { return SpatiallyNestable::getParentID(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.setParentID
|
||||
* @param {Uuid} parentID
|
||||
*/
|
||||
// This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript.
|
||||
Q_INVOKABLE virtual void setParentID(const QUuid& parentID) override;
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getParentJointIndex
|
||||
* @returns {number}
|
||||
*/
|
||||
// This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript.
|
||||
Q_INVOKABLE virtual quint16 getParentJointIndex() const override { return SpatiallyNestable::getParentJointIndex(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.setParentJointIndex
|
||||
* @param {number} parentJointIndex
|
||||
*/
|
||||
// This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript.
|
||||
Q_INVOKABLE virtual void setParentJointIndex(quint16 parentJointIndex) override;
|
||||
|
||||
/**jsdoc
|
||||
* Information about a single joint in an Avatar's skeleton hierarchy.
|
||||
* @typedef Avatar.SkeletonJoint
|
||||
* @property {string} name - name of joint
|
||||
* @property {number} index - joint index
|
||||
* @property {number} parentIndex - index of this joint's parent (-1 if no parent)
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns an array of joints, where each joint is an object containing name, index and parentIndex fields.
|
||||
* @function Avatar.getSkeleton
|
||||
* @returns {Avatar.SkeletonJoint[]} returns a list of information about each joint in this avatar's skeleton.
|
||||
* Returns an array of joints, where each joint is an object containing name, index, and parentIndex fields.
|
||||
* @function MyAvatar.getSkeleton
|
||||
* @returns {MyAvatar.SkeletonJoint[]} A list of information about each joint in this avatar's skeleton.
|
||||
*/
|
||||
/**jsdoc
|
||||
* Information about a single joint in an Avatar's skeleton hierarchy.
|
||||
* @typedef MyAvatar.SkeletonJoint
|
||||
* @property {string} name - Joint name.
|
||||
* @property {number} index - Joint index.
|
||||
* @property {number} parentIndex - Index of this joint's parent (-1 if no parent).
|
||||
*/
|
||||
Q_INVOKABLE QList<QVariant> getSkeleton();
|
||||
|
||||
|
@ -235,6 +312,11 @@ public:
|
|||
void setTargetScale(float targetScale) override;
|
||||
float getTargetScale() const { return _targetScale; }
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getSimulationRate
|
||||
* @param {string} [rateName=""]
|
||||
* @returns {number}
|
||||
*/
|
||||
Q_INVOKABLE float getSimulationRate(const QString& rateName = QString("")) const;
|
||||
|
||||
bool hasNewJointData() const { return _hasNewJointData; }
|
||||
|
@ -256,6 +338,7 @@ public:
|
|||
bool isFading() const { return _isFading; }
|
||||
void updateFadingStatus(render::ScenePointer scene);
|
||||
|
||||
// JSDoc is in AvatarData.h.
|
||||
Q_INVOKABLE virtual float getEyeHeight() const override;
|
||||
|
||||
// returns eye height of avatar in meters, ignoring avatar scale.
|
||||
|
@ -282,16 +365,57 @@ public slots:
|
|||
|
||||
// FIXME - these should be migrated to use Pose data instead
|
||||
// thread safe, will return last valid palm from cache
|
||||
|
||||
/**jsdoc
|
||||
* Get the position of the left palm in world coordinates.
|
||||
* @function MyAvatar.getLeftPalmPosition
|
||||
* @returns {Vec3} The position of the left palm in world coordinates.
|
||||
* @example <caption>Report the position of your avatar's left palm.</caption>
|
||||
* print(JSON.stringify(MyAvatar.getLeftPalmPosition()));
|
||||
*/
|
||||
glm::vec3 getLeftPalmPosition() const;
|
||||
|
||||
/**jsdoc
|
||||
* Get the rotation of the left palm in world coordinates.
|
||||
* @function MyAvatar.getLeftPalmRotation
|
||||
* @returns {Vec3} The rotation of the left palm in world coordinates.
|
||||
* @example <caption>Report the rotation of your avatar's left palm.</caption>
|
||||
* print(JSON.stringify(MyAvatar.getLeftPalmRotation()));
|
||||
*/
|
||||
glm::quat getLeftPalmRotation() const;
|
||||
/**jsdoc
|
||||
* Get the position of the right palm in world coordinates.
|
||||
* @function MyAvatar.getRightPalmPosition
|
||||
* @returns {Vec3} The position of the right palm in world coordinates.
|
||||
* @example <caption>Report the position of your avatar's right palm.</caption>
|
||||
* print(JSON.stringify(MyAvatar.getRightPalmPosition()));
|
||||
*/
|
||||
glm::vec3 getRightPalmPosition() const;
|
||||
|
||||
/**jsdoc
|
||||
* Get the rotation of the right palm in world coordinates.
|
||||
* @function MyAvatar.getRightPalmRotation
|
||||
* @returns {Vec3} The rotation of the right palm in world coordinates.
|
||||
* @example <caption>Report the rotation of your avatar's right palm.</caption>
|
||||
* print(JSON.stringify(MyAvatar.getRightPalmRotation()));
|
||||
*/
|
||||
glm::quat getRightPalmRotation() const;
|
||||
|
||||
// hooked up to Model::setURLFinished signal
|
||||
void setModelURLFinished(bool success);
|
||||
|
||||
// hooked up to Model::rigReady & rigReset signals
|
||||
/**jsdoc
|
||||
* @function MyAvatar.rigReady
|
||||
* @returns {Signal}
|
||||
*/
|
||||
// Hooked up to Model::rigReady signal
|
||||
void rigReady();
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.rigReset
|
||||
* @returns {Signal}
|
||||
*/
|
||||
// Jooked up to Model::rigReset signal
|
||||
void rigReset();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -2362,6 +2362,15 @@ glm::vec3 AvatarData::getAbsoluteJointTranslationInObjectFrame(int index) const
|
|||
return glm::vec3();
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* @typedef MyAvatar.AttachmentData
|
||||
* @property {string} modelUrl
|
||||
* @property {string} jointName
|
||||
* @property {Vec3} translation
|
||||
* @property {Vec3} rotation
|
||||
* @property {number} scale
|
||||
* @property {boolean} soft
|
||||
*/
|
||||
QVariant AttachmentData::toVariant() const {
|
||||
QVariantMap result;
|
||||
result["modelUrl"] = modelURL;
|
||||
|
|
|
@ -353,6 +353,7 @@ public:
|
|||
class AvatarData : public QObject, public SpatiallyNestable {
|
||||
Q_OBJECT
|
||||
|
||||
// The following properties have JSDoc in MyAvatar.h.
|
||||
Q_PROPERTY(glm::vec3 position READ getWorldPosition WRITE setPositionViaScript)
|
||||
Q_PROPERTY(float scale READ getTargetScale WRITE setTargetScale)
|
||||
Q_PROPERTY(float density READ getDensity)
|
||||
|
@ -505,7 +506,7 @@ public:
|
|||
/**jsdoc
|
||||
* returns the minimum scale allowed for this avatar in the current domain.
|
||||
* This value can change as the user changes avatars or when changing domains.
|
||||
* @function AvatarData.getDomainMinScale
|
||||
* @function MyAvatar.getDomainMinScale
|
||||
* @returns {number} minimum scale allowed for this avatar in the current domain.
|
||||
*/
|
||||
Q_INVOKABLE float getDomainMinScale() const;
|
||||
|
@ -513,7 +514,7 @@ public:
|
|||
/**jsdoc
|
||||
* returns the maximum scale allowed for this avatar in the current domain.
|
||||
* This value can change as the user changes avatars or when changing domains.
|
||||
* @function AvatarData.getDomainMaxScale
|
||||
* @function MyAvatar.getDomainMaxScale
|
||||
* @returns {number} maximum scale allowed for this avatar in the current domain.
|
||||
*/
|
||||
Q_INVOKABLE float getDomainMaxScale() const;
|
||||
|
@ -529,16 +530,16 @@ public:
|
|||
/**jsdoc
|
||||
* Provides read only access to the current eye height of the avatar.
|
||||
* This height is only an estimate and might be incorrect for avatars that are missing standard joints.
|
||||
* @function AvatarData.getEyeHeight
|
||||
* @returns {number} eye height of avatar in meters
|
||||
* @function MyAvatar.getEyeHeight
|
||||
* @returns {number} Eye height of avatar in meters.
|
||||
*/
|
||||
Q_INVOKABLE virtual float getEyeHeight() const { return _targetScale * getUnscaledEyeHeight(); }
|
||||
|
||||
/**jsdoc
|
||||
* Provides read only access to the current height of the avatar.
|
||||
* This height is only an estimate and might be incorrect for avatars that are missing standard joints.
|
||||
* @function AvatarData.getHeight
|
||||
* @returns {number} height of avatar in meters
|
||||
* @function MyAvatar.getHeight
|
||||
* @returns {number} Height of avatar in meters.
|
||||
*/
|
||||
Q_INVOKABLE virtual float getHeight() const;
|
||||
|
||||
|
@ -547,49 +548,372 @@ public:
|
|||
void setDomainMinimumHeight(float domainMinimumHeight);
|
||||
void setDomainMaximumHeight(float domainMaximumHeight);
|
||||
|
||||
// Hand State
|
||||
/**jsdoc
|
||||
* @function MyAvatar.setHandState
|
||||
* @param {string} state
|
||||
*/
|
||||
Q_INVOKABLE void setHandState(char s) { _handState = s; }
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getHandState
|
||||
* @returns {string}
|
||||
*/
|
||||
Q_INVOKABLE char getHandState() const { return _handState; }
|
||||
|
||||
const QVector<JointData>& getRawJointData() const { return _jointData; }
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.setRawJointData
|
||||
* @param {JointData[]} data
|
||||
*/
|
||||
Q_INVOKABLE void setRawJointData(QVector<JointData> data);
|
||||
|
||||
/**jsdoc
|
||||
* Set a specific joint's rotation and position relative to its parent.
|
||||
* <p>Setting joint data completely overrides/replaces all motion from the default animation system including inverse
|
||||
* kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints,
|
||||
* the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate
|
||||
* joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set
|
||||
* the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.</p>
|
||||
* @function MyAvatar.setJointData
|
||||
* @param {number} index - The index of the joint.
|
||||
* @param {Quat} rotation - The rotation of the joint relative to its parent.
|
||||
* @param {Vec3} translation - The translation of the joint relative to its parent.
|
||||
* @example <caption>Set your avatar to it's default T-pose for a while.<br />
|
||||
* <img alt="Avatar in T-pose" src="https://docs.highfidelity.com/user/pages/06.api-reference/25.myavatar/t-pose.png" />
|
||||
* </caption>
|
||||
* // Set all joint translations and rotations to defaults.
|
||||
* var i, length, rotation, translation;
|
||||
* for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) {
|
||||
* rotation = MyAvatar.getDefaultJointRotation(i);
|
||||
* translation = MyAvatar.getDefaultJointTranslation(i);
|
||||
* MyAvatar.setJointData(i, rotation, translation);
|
||||
* }
|
||||
*
|
||||
* // Restore your avatar's motion after 5s.
|
||||
* Script.setTimeout(function () {
|
||||
* MyAvatar.clearJointsData();
|
||||
* }, 5000);
|
||||
*/
|
||||
Q_INVOKABLE virtual void setJointData(int index, const glm::quat& rotation, const glm::vec3& translation);
|
||||
|
||||
/**jsdoc
|
||||
* Set a specific joint's rotation relative to its parent.
|
||||
* <p>Setting joint data completely overrides/replaces all motion from the default animation system including inverse
|
||||
* kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints,
|
||||
* the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate
|
||||
* joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set
|
||||
* the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.</p>
|
||||
* @function MyAvatar.setJointRotation
|
||||
* @param {number} index - The index of the joint.
|
||||
* @param {Quat} rotation - The rotation of the joint relative to its parent.
|
||||
*/
|
||||
Q_INVOKABLE virtual void setJointRotation(int index, const glm::quat& rotation);
|
||||
|
||||
/**jsdoc
|
||||
* Set a specific joint's translation relative to its parent.
|
||||
* <p>Setting joint data completely overrides/replaces all motion from the default animation system including inverse
|
||||
* kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints,
|
||||
* the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate
|
||||
* joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set
|
||||
* the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.</p>
|
||||
* @function MyAvatar.setJointTranslation
|
||||
* @param {number} index - The index of the joint.
|
||||
* @param {Vec3} translation - The translation of the joint relative to its parent.
|
||||
*/
|
||||
Q_INVOKABLE virtual void setJointTranslation(int index, const glm::vec3& translation);
|
||||
|
||||
/**jsdoc
|
||||
* Clear joint translations and rotations set by script for a specific joint. This restores all motion from the default
|
||||
* animation system including inverse kinematics for that joint.
|
||||
* <p>Note: This is slightly faster than the function variation that specifies the joint name.</p>
|
||||
* @function MyAvatar.clearJointData
|
||||
* @param {number} index - The index of the joint.
|
||||
*/
|
||||
Q_INVOKABLE virtual void clearJointData(int index);
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.isJointDataValid
|
||||
* @param {number} index
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool isJointDataValid(int index) const;
|
||||
|
||||
/**jsdoc
|
||||
* Get the rotation of a joint relative to its parent. For information on the joint hierarchy used, see
|
||||
* <a href="https://docs.highfidelity.com/create-and-explore/avatars/avatar-standards">Avatar Standards</a>.
|
||||
* @function MyAvatar.getJointRotation
|
||||
* @param {number} index - The index of the joint.
|
||||
* @returns {Quat} The rotation of the joint relative to its parent.
|
||||
*/
|
||||
Q_INVOKABLE virtual glm::quat getJointRotation(int index) const;
|
||||
|
||||
/**jsdoc
|
||||
* Get the translation of a joint relative to its parent. For information on the joint hierarchy used, see
|
||||
* <a href="https://docs.highfidelity.com/create-and-explore/avatars/avatar-standards">Avatar Standards</a>.
|
||||
* @function MyAvatar.getJointTranslation
|
||||
* @param {number} index - The index of the joint.
|
||||
* @returns {Vec3} The translation of the joint relative to its parent.
|
||||
*/
|
||||
Q_INVOKABLE virtual glm::vec3 getJointTranslation(int index) const;
|
||||
|
||||
/**jsdoc
|
||||
* Set a specific joint's rotation and position relative to its parent.
|
||||
* <p>Setting joint data completely overrides/replaces all motion from the default animation system including inverse
|
||||
* kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints,
|
||||
* the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate
|
||||
* joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set
|
||||
* the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.</p>
|
||||
* @function MyAvatar.setJointData
|
||||
* @param {string} name - The name of the joint.
|
||||
* @param {Quat} rotation - The rotation of the joint relative to its parent.
|
||||
* @param {Vec3} translation - The translation of the joint relative to its parent.
|
||||
*/
|
||||
Q_INVOKABLE virtual void setJointData(const QString& name, const glm::quat& rotation, const glm::vec3& translation);
|
||||
|
||||
/**jsdoc
|
||||
* Set a specific joint's rotation relative to its parent.
|
||||
* <p>Setting joint data completely overrides/replaces all motion from the default animation system including inverse
|
||||
* kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints,
|
||||
* the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate
|
||||
* joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set
|
||||
* the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.</p>
|
||||
* @function MyAvatar.setJointRotation
|
||||
* @param {string} name - The name of the joint.
|
||||
* @param {Quat} rotation - The rotation of the joint relative to its parent.
|
||||
* @example <caption>Set your avatar to its default T-pose then rotate its right arm.<br />
|
||||
* <img alt="Avatar in T-pose with arm rotated"
|
||||
* src="https://docs.highfidelity.com/user/pages/06.api-reference/25.myavatar/armpose.png" /></caption>
|
||||
* // Set all joint translations and rotations to defaults.
|
||||
* var i, length, rotation, translation;
|
||||
* for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) {
|
||||
* rotation = MyAvatar.getDefaultJointRotation(i);
|
||||
* translation = MyAvatar.getDefaultJointTranslation(i);
|
||||
* MyAvatar.setJointData(i, rotation, translation);
|
||||
* }
|
||||
*
|
||||
* // Rotate the right arm.
|
||||
* var newArmRotation = { x: 0.47, y: 0.22, z: -0.02, w: 0.87 };
|
||||
* MyAvatar.setJointRotation("RightArm", newArmRotation);
|
||||
*
|
||||
* // Restore your avatar's motion after 5s.
|
||||
* Script.setTimeout(function () {
|
||||
* MyAvatar.clearJointsData();
|
||||
* }, 5000);
|
||||
*/
|
||||
Q_INVOKABLE virtual void setJointRotation(const QString& name, const glm::quat& rotation);
|
||||
|
||||
/**jsdoc
|
||||
* Set a specific joint's translation relative to its parent.
|
||||
* <p>Setting joint data completely overrides/replaces all motion from the default animation system including inverse
|
||||
* kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints,
|
||||
* the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate
|
||||
* joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set
|
||||
* the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.</p>
|
||||
* @function MyAvatar.setJointTranslation
|
||||
* @param {string} name - The name of the joint.
|
||||
* @param {Vec3} translation - The translation of the joint relative to its parent.
|
||||
* @example <caption>Stretch your avatar's neck. Depending on the avatar you are using, you will either see a gap between
|
||||
* the head and body or you will see the neck stretched.<br />
|
||||
* <img alt="Avatar with neck stretched"
|
||||
* src="https://docs.highfidelity.com/user/pages/06.api-reference/25.myavatar/stretched-neck.png" /></caption>
|
||||
* // Stretch your avatar's neck.
|
||||
* MyAvatar.setJointTranslation("Neck", { x: 0, y: 25, z: 0 });
|
||||
*
|
||||
* // Restore your avatar's neck after 5s.
|
||||
* Script.setTimeout(function () {
|
||||
* MyAvatar.clearJointData("Neck");
|
||||
* }, 5000);
|
||||
*/
|
||||
Q_INVOKABLE virtual void setJointTranslation(const QString& name, const glm::vec3& translation);
|
||||
|
||||
/**jsdoc
|
||||
* Clear joint translations and rotations set by script for a specific joint. This restores all motion from the default
|
||||
* animation system including inverse kinematics for that joint.
|
||||
* <p>Note: This is slightly slower than the function variation that specifies the joint index.</p>
|
||||
* @function MyAvatar.clearJointData
|
||||
* @param {string} name - The name of the joint.
|
||||
* @example <caption>Offset and restore the position of your avatar's head.</caption>
|
||||
* // Move your avatar's head up by 25cm from where it should be.
|
||||
* MyAvatar.setJointTranslation("Neck", { x: 0, y: 0.25, z: 0 });
|
||||
*
|
||||
* // Restore your avatar's head to its default position after 5s.
|
||||
* Script.setTimeout(function () {
|
||||
* MyAvatar.clearJointData("Neck");
|
||||
* }, 5000);
|
||||
*/
|
||||
Q_INVOKABLE virtual void clearJointData(const QString& name);
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.isJointDataValid
|
||||
* @param {string} name
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE virtual bool isJointDataValid(const QString& name) const;
|
||||
|
||||
/**jsdoc
|
||||
* Get the rotation of a joint relative to its parent. For information on the joint hierarchy used, see
|
||||
* <a href="https://docs.highfidelity.com/create-and-explore/avatars/avatar-standards">Avatar Standards</a>.
|
||||
* @function MyAvatar.getJointRotation
|
||||
* @param {string} name - The name of the joint.
|
||||
* @returns {Quat} The rotation of the joint relative to its parent.
|
||||
* @example <caption>Report the rotation of your avatar's hips joint.</caption>
|
||||
* print(JSON.stringify(MyAvatar.getJointRotation("Hips")));
|
||||
*/
|
||||
Q_INVOKABLE virtual glm::quat getJointRotation(const QString& name) const;
|
||||
|
||||
/**jsdoc
|
||||
* Get the translation of a joint relative to its parent. For information on the joint hierarchy used, see
|
||||
* <a href="https://docs.highfidelity.com/create-and-explore/avatars/avatar-standards">Avatar Standards</a>.
|
||||
* @function MyAvatar.getJointTranslation
|
||||
* @param {number} name - The name of the joint.
|
||||
* @returns {Vec3} The translation of the joint relative to its parent.
|
||||
* @example <caption>Report the translation of your avatar's hips joint.</caption>
|
||||
* print(JSON.stringify(MyAvatar.getJointRotation("Hips")));
|
||||
*/
|
||||
Q_INVOKABLE virtual glm::vec3 getJointTranslation(const QString& name) const;
|
||||
|
||||
/**jsdoc
|
||||
* Get the rotations of all joints in the current avatar. Each joint's rotation is relative to its parent joint.
|
||||
* @function MyAvatar.getJointRotations
|
||||
* @returns {Quat[]} The rotations of all joints relative to each's parent. The values are in the same order as the array
|
||||
* returned by {@link MyAvatar.getJointNames}.
|
||||
* @example <caption>Report the rotations of all your avatar's joints.</caption>
|
||||
* print(JSON.stringify(MyAvatar.getJointRotations()));
|
||||
*/
|
||||
Q_INVOKABLE virtual QVector<glm::quat> getJointRotations() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getJointTranslations
|
||||
* @returns {Vec3[]}
|
||||
*/
|
||||
Q_INVOKABLE virtual QVector<glm::vec3> getJointTranslations() const;
|
||||
|
||||
/**jsdoc
|
||||
* Set the rotations of all joints in the current avatar. Each joint's rotation is relative to its parent joint.
|
||||
* <p>Setting joint data completely overrides/replaces all motion from the default animation system including inverse
|
||||
* kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints,
|
||||
* the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate
|
||||
* joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set
|
||||
* the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.</p>
|
||||
* @function MyAvatar.setJointRotations
|
||||
* @param {Quat[]} jointRotations - The rotations for all joints in the avatar. The values are in the same order as the
|
||||
* array returned by {@link MyAvatar.getJointNames}.
|
||||
* @example <caption>Set your avatar to its default T-pose then rotate its right arm.<br />
|
||||
* <img alt="Avatar in T-pose" src="https://docs.highfidelity.com/user/pages/06.api-reference/25.myavatar/armpose.png" />
|
||||
* </caption>
|
||||
* // Set all joint translations and rotations to defaults.
|
||||
* var i, length, rotation, translation;
|
||||
* for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) {
|
||||
* rotation = MyAvatar.getDefaultJointRotation(i);
|
||||
* translation = MyAvatar.getDefaultJointTranslation(i);
|
||||
* MyAvatar.setJointData(i, rotation, translation);
|
||||
* }
|
||||
*
|
||||
* // Get all join rotations.
|
||||
* var jointRotations = MyAvatar.getJointRotations();
|
||||
*
|
||||
* // Update the rotation of the right arm in the array.
|
||||
* jointRotations[MyAvatar.getJointIndex("RightArm")] = { x: 0.47, y: 0.22, z: -0.02, w: 0.87 };
|
||||
*
|
||||
* // Update all joint rotations.
|
||||
* MyAvatar.setJointRotations(jointRotations);
|
||||
*
|
||||
* // Restore your avatar's motion after 5s.
|
||||
* Script.setTimeout(function () {
|
||||
* MyAvatar.clearJointsData();
|
||||
* }, 5000);
|
||||
*/
|
||||
Q_INVOKABLE virtual void setJointRotations(const QVector<glm::quat>& jointRotations);
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.setJointTranslations
|
||||
* @param {Vec3[]} translations
|
||||
*/
|
||||
Q_INVOKABLE virtual void setJointTranslations(const QVector<glm::vec3>& jointTranslations);
|
||||
|
||||
/**jsdoc
|
||||
* Clear all joint translations and rotations that have been set by script. This restores all motion from the default
|
||||
* animation system including inverse kinematics for all joints.
|
||||
* @function MyAvatar.clearJointsData
|
||||
* @example <caption>Set your avatar to it's default T-pose for a while.</caption>
|
||||
* // Set all joint translations and rotations to defaults.
|
||||
* var i, length, rotation, translation;
|
||||
* for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) {
|
||||
* rotation = MyAvatar.getDefaultJointRotation(i);
|
||||
* translation = MyAvatar.getDefaultJointTranslation(i);
|
||||
* MyAvatar.setJointData(i, rotation, translation);
|
||||
* }
|
||||
*
|
||||
* // Restore your avatar's motion after 5s.
|
||||
* Script.setTimeout(function () {
|
||||
* MyAvatar.clearJointsData();
|
||||
* }, 5000);
|
||||
*/
|
||||
Q_INVOKABLE virtual void clearJointsData();
|
||||
|
||||
/**jsdoc
|
||||
* Get the joint index for a named joint. The joint index value is the position of the joint in the array returned by
|
||||
* {@link MyAvatar.getJointNames}.
|
||||
* @function MyAvatar.getJointIndex
|
||||
* @param {string} name - The name of the joint.
|
||||
* @returns {number} The index of the joint.
|
||||
* @example <caption>Report the index of your avatar's left arm joint.</caption>
|
||||
* print(JSON.stringify(MyAvatar.getJointIndex("LeftArm"));
|
||||
*/
|
||||
/// Returns the index of the joint with the specified name, or -1 if not found/unknown.
|
||||
Q_INVOKABLE virtual int getJointIndex(const QString& name) const;
|
||||
|
||||
/**jsdoc
|
||||
* Get the names of all the joints in the current avatar.
|
||||
* @function MyAvatar.getJointNames
|
||||
* @returns {string[]} The joint names.
|
||||
* @example <caption>Report the names of all the joints in your current avatar.</caption>
|
||||
* print(JSON.stringify(MyAvatar.getJointNames()));
|
||||
*/
|
||||
Q_INVOKABLE virtual QStringList getJointNames() const;
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.setBlendshape
|
||||
* @param {string} name
|
||||
* @param {number} value
|
||||
*/
|
||||
Q_INVOKABLE void setBlendshape(QString name, float val) { _headData->setBlendshape(name, val); }
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getAttachmentsVariant
|
||||
* @returns {object}
|
||||
*/
|
||||
// FIXME: Can this name be improved? Can it be deprecated?
|
||||
Q_INVOKABLE QVariantList getAttachmentsVariant() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.setAttachmentsVariant
|
||||
* @param {object} variant
|
||||
*/
|
||||
// FIXME: Can this name be improved? Can it be deprecated?
|
||||
Q_INVOKABLE void setAttachmentsVariant(const QVariantList& variant);
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.updateAvatarEntity
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} entityData
|
||||
*/
|
||||
Q_INVOKABLE void updateAvatarEntity(const QUuid& entityID, const QByteArray& entityData);
|
||||
/**jsdoc
|
||||
* @function MyAvatar.clearAvatarEntity
|
||||
* @param {Uuid} entityID
|
||||
*/
|
||||
Q_INVOKABLE void clearAvatarEntity(const QUuid& entityID);
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.setForceFaceTrackerConnected
|
||||
* @param {boolean} connected
|
||||
*/
|
||||
Q_INVOKABLE void setForceFaceTrackerConnected(bool connected) { _forceFaceTrackerConnected = connected; }
|
||||
|
||||
// key state
|
||||
|
@ -627,15 +951,96 @@ public:
|
|||
markIdentityDataChanged();
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* Get information about all models currently attached to your avatar.
|
||||
* @function MyAvatar.getAttachmentData
|
||||
* @returns {MyAvatar.AttachmentData[]} Information about all models attached to your avatar.
|
||||
* @example <caption>Report the URLs of all current attachments.</caption>
|
||||
* var attachments = MyAvatar.getaAttachmentData();
|
||||
* for (var i = 0; i < attachments.length; i++) {
|
||||
* print (attachments[i].modelURL);
|
||||
* }
|
||||
*/
|
||||
Q_INVOKABLE QVector<AttachmentData> getAttachmentData() const;
|
||||
|
||||
/**jsdoc
|
||||
* Set all models currently attached to your avatar. For example, if you retrieve attachment data using
|
||||
* {@link MyAvatar.getAttachmentData}, make changes to it, and then want to update your avatar's attachments per the
|
||||
* changed data. You can also remove all attachments by using setting <code>attachmentData</code> to <code>null</code>.
|
||||
* @function MyAvatar.setAttachmentData
|
||||
* @param {MyAvatar.AttachmentData[]} attachmentData - The attachment data defining the models to have attached to your avatar. Use
|
||||
* <code>null</code> to remove all attachments.
|
||||
* @example <caption>Remove a hat attachment if your avatar is wearing it.</caption>
|
||||
* var hatURL = "https://s3.amazonaws.com/hifi-public/tony/cowboy-hat.fbx";
|
||||
* var attachments = MyAvatar.getAttachmentData();
|
||||
*
|
||||
* for (var i = 0; i < attachments.length; i++) {
|
||||
* if (attachments[i].modelURL === hatURL) {
|
||||
* attachments.splice(i, 1);
|
||||
* MyAvatar.setAttachmentData(attachments);
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
Q_INVOKABLE virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData);
|
||||
|
||||
/**jsdoc
|
||||
* Attach a model to your avatar. For example, you can give your avatar a hat to wear, a guitar to hold, or a surfboard to
|
||||
* stand on.
|
||||
* <p>Note: Attached models are models only; they are not entities and can not be manipulated using the {@link Entities} API.
|
||||
* Nor can you use this function to attach an entity (such as a sphere or a box) to your avatar.</p>
|
||||
* @function MyAvatar.attach
|
||||
* @param {string} modelURL - The URL of the model to attach. Models can be .FBX or .OBJ format.
|
||||
* @param {string} [jointName=""] - The name of the avatar joint (see {@link MyAvatar.getJointNames}) to attach the model
|
||||
* to.
|
||||
* @param {Vec3} [translation=Vec3.ZERO] - The offset to apply to the model relative to the joint position.
|
||||
* @param {Quat} [rotation=Quat.IDENTITY] - The rotation to apply to the model relative to the joint orientation.
|
||||
* @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 be 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.
|
||||
* @param {boolean} [allowDuplicates=false]
|
||||
* @param {boolean} [useSaved=true]
|
||||
* @example <caption>Attach a cowboy hat to your avatar's head.</caption>
|
||||
* var attachment = {
|
||||
* modelURL: "https://s3.amazonaws.com/hifi-public/tony/cowboy-hat.fbx",
|
||||
* jointName: "Head",
|
||||
* translation: {"x": 0, "y": 0.25, "z": 0},
|
||||
* rotation: {"x": 0, "y": 0, "z": 0, "w": 1},
|
||||
* scale: 1,
|
||||
* isSoft: false
|
||||
* };
|
||||
*
|
||||
* MyAvatar.attach(attachment.modelURL,
|
||||
* attachment.jointName,
|
||||
* attachment.translation,
|
||||
* attachment.rotation,
|
||||
* attachment.scale,
|
||||
* attachment.isSoft);
|
||||
*/
|
||||
Q_INVOKABLE virtual void attach(const QString& modelURL, const QString& jointName = QString(),
|
||||
const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(),
|
||||
float scale = 1.0f, bool isSoft = false,
|
||||
bool allowDuplicates = false, bool useSaved = true);
|
||||
|
||||
/**jsdoc
|
||||
* Detach the most recently attached instance of a particular model from either a specific joint or any joint.
|
||||
* @function MyAvatar.detachOne
|
||||
* @param {string} modelURL - The URL of the model to detach.
|
||||
* @param {string} [jointName=""] - The name of the joint to detach the model from. If <code>""</code>, then the most
|
||||
* recently attached model is removed from which ever joint it was attached to.
|
||||
*/
|
||||
Q_INVOKABLE void detachOne(const QString& modelURL, const QString& jointName = QString());
|
||||
|
||||
/**jsdoc
|
||||
* Detach all instances of a particular model from either a specific joint or all joints.
|
||||
* @function MyAvatar.detachAll
|
||||
* @param {string} modelURL - The URL of the model to detach.
|
||||
* @param {string} [jointName=""] - The name of the joint to detach the model from. If <code>""</code>, then the model is
|
||||
* detached from all joints.
|
||||
*/
|
||||
Q_INVOKABLE void detachAll(const QString& modelURL, const QString& jointName = QString());
|
||||
|
||||
QString getSkeletonModelURLFromScript() const { return _skeletonModelURL.toString(); }
|
||||
|
@ -657,19 +1062,63 @@ public:
|
|||
glm::vec3 getClientGlobalPosition() const { return _globalPosition; }
|
||||
glm::vec3 getGlobalBoundingBoxCorner() const { return _globalPosition + _globalBoundingBoxOffset - _globalBoundingBoxDimensions; }
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getAvatarEntityData
|
||||
* @returns {object}
|
||||
*/
|
||||
Q_INVOKABLE AvatarEntityMap getAvatarEntityData() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.setAvatarEntityData
|
||||
* @param {object} avatarEntityData
|
||||
*/
|
||||
Q_INVOKABLE void setAvatarEntityData(const AvatarEntityMap& avatarEntityData);
|
||||
|
||||
virtual void setAvatarEntityDataChanged(bool value) { _avatarEntityDataChanged = value; }
|
||||
void insertDetachedEntityID(const QUuid entityID);
|
||||
AvatarEntityIDs getAndClearRecentlyDetachedIDs();
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getSensorToWorldMatrix
|
||||
* @returns {Mat4}
|
||||
*/
|
||||
// thread safe
|
||||
Q_INVOKABLE glm::mat4 getSensorToWorldMatrix() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getSensorToWorldScale
|
||||
* @returns {number}
|
||||
*/
|
||||
// thread safe
|
||||
Q_INVOKABLE float getSensorToWorldScale() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getControllerLeftHandMatrix
|
||||
* @returns {Mat4}
|
||||
*/
|
||||
// thread safe
|
||||
Q_INVOKABLE glm::mat4 getControllerLeftHandMatrix() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getControllerRightHandMatrix
|
||||
* @returns {Mat4}
|
||||
*/
|
||||
// thread safe
|
||||
Q_INVOKABLE glm::mat4 getControllerRightHandMatrix() const;
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getDataRate
|
||||
* @param {string} [rateName=""]
|
||||
* @returns {number}
|
||||
*/
|
||||
Q_INVOKABLE float getDataRate(const QString& rateName = QString("")) const;
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getUpdateRate
|
||||
* @param {string} [rateName=""]
|
||||
* @returns {number}
|
||||
*/
|
||||
Q_INVOKABLE float getUpdateRate(const QString& rateName = QString("")) const;
|
||||
|
||||
int getJointCount() const { return _jointData.size(); }
|
||||
|
@ -705,17 +1154,60 @@ public:
|
|||
virtual void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {}
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.displayNameChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void displayNameChanged();
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.sessionDisplayNameChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void sessionDisplayNameChanged();
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.skeletonModelURLChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void skeletonModelURLChanged();
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.lookAtSnappingChanged
|
||||
* @param {boolean} enabled
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void lookAtSnappingChanged(bool enabled);
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.sessionUUIDChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void sessionUUIDChanged();
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.sendAvatarDataPacket
|
||||
* @param {boolean} [sendAll=false]
|
||||
*/
|
||||
void sendAvatarDataPacket(bool sendAll = false);
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.sendIdentityPacket
|
||||
*/
|
||||
void sendIdentityPacket();
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.setJointMappingsFromNetworkReply
|
||||
*/
|
||||
void setJointMappingsFromNetworkReply();
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.setSessionUUID
|
||||
* @param {Uuid} sessionUUID
|
||||
*/
|
||||
virtual void setSessionUUID(const QUuid& sessionUUID) {
|
||||
if (sessionUUID != getID()) {
|
||||
if (sessionUUID == QUuid()) {
|
||||
|
@ -727,13 +1219,45 @@ public slots:
|
|||
}
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getAbsoluteJointRotationInObjectFrame
|
||||
* @param {number} index
|
||||
* @returns {Quat}
|
||||
*/
|
||||
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getAbsoluteJointTranslationInObjectFrame
|
||||
* @param {number} index
|
||||
* @returns {Vec3}
|
||||
*/
|
||||
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.setAbsoluteJointRotationInObjectFrame
|
||||
* @param {number} index
|
||||
* @param {Quat} rotation
|
||||
* @returns {boolean}
|
||||
*/
|
||||
virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override { return false; }
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.setAbsoluteJointTranslationInObjectFrame
|
||||
* @param {number} index
|
||||
* @param {Vec3} translation
|
||||
* @returns {boolean}
|
||||
*/
|
||||
virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override { return false; }
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.getTargetScale
|
||||
* @returns {number}
|
||||
*/
|
||||
float getTargetScale() const { return _targetScale; } // why is this a slot?
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.resetLastSent
|
||||
*/
|
||||
void resetLastSent() { _lastToByteArray = 0; }
|
||||
|
||||
protected:
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
#ifndef hifi_AvatarHashMap_h
|
||||
#define hifi_AvatarHashMap_h
|
||||
|
||||
|
@ -29,6 +30,15 @@
|
|||
|
||||
#include "AvatarData.h"
|
||||
|
||||
/**jsdoc
|
||||
* The AvatarHashMap API deals with functionality related to Avatar information and connectivity
|
||||
* @namespace AvatarHashMap
|
||||
*/
|
||||
|
||||
// JSDoc 3.5.5 doesn't augment @property definitions.
|
||||
// These functions are being copied into Avatar classes which inherit the AvatarHashMap
|
||||
|
||||
|
||||
class AvatarHashMap : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
@ -39,9 +49,28 @@ public:
|
|||
int size() { return _avatarHash.size(); }
|
||||
|
||||
// Currently, your own avatar will be included as the null avatar id.
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarHashMap.getAvatarIdentifiers
|
||||
*/
|
||||
|
||||
Q_INVOKABLE QVector<QUuid> getAvatarIdentifiers();
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarHashMap.getAvatarsInRange
|
||||
* @param {Vec3} position
|
||||
* @param {float} rangeMeters
|
||||
* @returns {string[]}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE QVector<QUuid> getAvatarsInRange(const glm::vec3& position, float rangeMeters) const;
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarHashMap.getAvatar
|
||||
* @param {string} avatarID
|
||||
* @returns {ScriptAvatarData}
|
||||
*/
|
||||
|
||||
// Null/Default-constructed QUuids will return MyAvatar
|
||||
Q_INVOKABLE virtual ScriptAvatarData* getAvatar(QUuid avatarID) { return new ScriptAvatarData(getAvatarBySessionID(avatarID)); }
|
||||
|
||||
|
@ -49,18 +78,75 @@ public:
|
|||
int numberOfAvatarsInRange(const glm::vec3& position, float rangeMeters);
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarHashMap.avatarAddedEvent
|
||||
* @param {string} sessionUUID
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void avatarAddedEvent(const QUuid& sessionUUID);
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarHashMap.avatarRemovedEvent
|
||||
* @param {string} sessionUUID
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void avatarRemovedEvent(const QUuid& sessionUUID);
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarHashMap.avatarSessionChangedEvent
|
||||
* @param {string} sessionUUID
|
||||
* @param {string} oldUUID
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void avatarSessionChangedEvent(const QUuid& sessionUUID,const QUuid& oldUUID);
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarHashMap.isAvatarInRange
|
||||
* @param {string} position
|
||||
* @param {string} range
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
bool isAvatarInRange(const glm::vec3 & position, const float range);
|
||||
|
||||
protected slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarHashMap.sessionUUIDChanged
|
||||
* @param {string} sessionUUID
|
||||
* @param {string} oldUUID
|
||||
*/
|
||||
|
||||
void sessionUUIDChanged(const QUuid& sessionUUID, const QUuid& oldUUID);
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarHashMap.processAvatarDataPacket
|
||||
* @param {} message
|
||||
* @param {} sendingNode
|
||||
*/
|
||||
|
||||
void processAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarHashMap.processAvatarIdentityPacket
|
||||
* @param {} message
|
||||
* @param {} sendingNode
|
||||
*/
|
||||
|
||||
void processAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||
|
||||
/**jsdoc
|
||||
* @function AvatarHashMap.processKillAvatar
|
||||
* @param {} message
|
||||
* @param {} sendingNode
|
||||
*/
|
||||
|
||||
void processKillAvatar(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -172,6 +172,17 @@ private:
|
|||
ReticleInterface* _reticleInterface { nullptr };
|
||||
};
|
||||
|
||||
/**jsdoc
|
||||
* @namespace Reticle
|
||||
* @property {boolean} allowMouseCapture
|
||||
* @property {number} depth
|
||||
* @property {Vec2} maximumPosition
|
||||
* @property {boolean} mouseCaptured
|
||||
* @property {boolean} pointingAtSystemOverlay
|
||||
* @property {Vec2} position
|
||||
* @property {number} scale
|
||||
* @property {boolean} visible
|
||||
*/
|
||||
// Scripting interface available to control the Reticle
|
||||
class ReticleInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -187,25 +198,82 @@ class ReticleInterface : public QObject {
|
|||
public:
|
||||
ReticleInterface(CompositorHelper* outer) : QObject(outer), _compositor(outer) {}
|
||||
|
||||
/**jsdoc
|
||||
* @function Reticle.isMouseCaptured
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool isMouseCaptured() { return _compositor->shouldCaptureMouse(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Reticle.getAllowMouseCapture
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool getAllowMouseCapture() { return _compositor->getAllowMouseCapture(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Reticle.setAllowMouseCapture
|
||||
* @param {boolean} allowMouseCaptured
|
||||
*/
|
||||
Q_INVOKABLE void setAllowMouseCapture(bool value) { return _compositor->setAllowMouseCapture(value); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Reticle.isPointingAtSystemOverlay
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool isPointingAtSystemOverlay() { return !_compositor->getReticleOverDesktop(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Reticle.getVisible
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool getVisible() { return _compositor->getReticleVisible(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Reticle.setVisible
|
||||
* @param {boolean} visible
|
||||
*/
|
||||
Q_INVOKABLE void setVisible(bool visible) { _compositor->setReticleVisible(visible); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Reticle.getDepth
|
||||
* @returns {number}
|
||||
*/
|
||||
Q_INVOKABLE float getDepth() { return _compositor->getReticleDepth(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Reticle.setDepth
|
||||
* @param {number} depth
|
||||
*/
|
||||
Q_INVOKABLE void setDepth(float depth) { _compositor->setReticleDepth(depth); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Reticle.getScale
|
||||
* @returns {number}
|
||||
*/
|
||||
Q_INVOKABLE float getScale() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function Reticle.setScale
|
||||
* @param {number} scale
|
||||
*/
|
||||
Q_INVOKABLE void setScale(float scale);
|
||||
|
||||
/**jsdoc
|
||||
* @function Reticle.getPosition
|
||||
* @returns {Vec2}
|
||||
*/
|
||||
Q_INVOKABLE QVariant getPosition() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function Reticle.setPosition
|
||||
* @param {Vec2} position
|
||||
*/
|
||||
Q_INVOKABLE void setPosition(QVariant position);
|
||||
|
||||
/**jsdoc
|
||||
* @function Reticle.getMaximumPosition
|
||||
* @returns {Vec2}
|
||||
*/
|
||||
Q_INVOKABLE glm::vec2 getMaximumPosition() { return _compositor->getReticleMaximumPosition(); }
|
||||
|
||||
private:
|
||||
|
|
|
@ -249,8 +249,11 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
|
|||
batch.setResourceTexture(0, _texture);
|
||||
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
|
||||
// Turn off jitter for these entities
|
||||
batch.pushProjectionJitter();
|
||||
DependencyManager::get<GeometryCache>()->bindWebBrowserProgram(batch, fadeRatio < OPAQUE_ALPHA_THRESHOLD);
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, fadeRatio), _geometryId);
|
||||
batch.popProjectionJitter();
|
||||
}
|
||||
|
||||
bool WebEntityRenderer::hasWebSurface() {
|
||||
|
|
|
@ -766,6 +766,36 @@ QVector<QUuid> EntityScriptingInterface::findEntitiesByType(const QString entity
|
|||
return result;
|
||||
}
|
||||
|
||||
QVector<QUuid> EntityScriptingInterface::findEntitiesByName(const QString entityName, const glm::vec3& center, float radius, bool caseSensitiveSearch) const {
|
||||
|
||||
QVector<QUuid> result;
|
||||
if (_entityTree) {
|
||||
QVector<EntityItemPointer> entities;
|
||||
_entityTree->withReadLock([&] {
|
||||
_entityTree->findEntities(center, radius, entities);
|
||||
});
|
||||
|
||||
if (caseSensitiveSearch) {
|
||||
foreach(EntityItemPointer entity, entities) {
|
||||
if (entity->getName() == entityName) {
|
||||
result << entity->getEntityItemID();
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
QString entityNameLowerCase = entityName.toLower();
|
||||
|
||||
foreach(EntityItemPointer entity, entities) {
|
||||
QString entityItemLowerCase = entity->getName().toLower();
|
||||
if (entityItemLowerCase == entityNameLowerCase) {
|
||||
result << entity->getEntityItemID();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(const PickRay& ray, bool precisionPicking,
|
||||
const QScriptValue& entityIdsToInclude, const QScriptValue& entityIdsToDiscard, bool visibleOnly, bool collidableOnly) {
|
||||
QVector<EntityItemID> entitiesToInclude = qVectorEntityItemIDFromScriptValue(entityIdsToInclude);
|
||||
|
|
|
@ -387,6 +387,21 @@ public slots:
|
|||
/// this function will not find any entities in script engine contexts which don't have access to entities
|
||||
Q_INVOKABLE QVector<QUuid> findEntitiesByType(const QString entityType, const glm::vec3& center, float radius) const;
|
||||
|
||||
/**jsdoc
|
||||
* Find all entities of a particular name that intersect a sphere defined by a center point and radius.
|
||||
* @function Entities.findEntitiesByName
|
||||
* @param {Entities.EntityType} entityName - The name of the entity to search for.
|
||||
* @param {Vec3} center - The point about which to search.
|
||||
* @param {number} radius - The radius within which to search.
|
||||
* @param {bool} caseSensitiveSearch - Choose whether to to return case sensitive results back.
|
||||
* @returns {Uuid[]} An array of entity IDs of the specified type that intersect the search sphere. The array is empty if
|
||||
* no entities could be found.
|
||||
* @example <caption>Get back a list of entities</caption>
|
||||
* var entityIDs = Entities.findEntitiesByName("Light-Target", MyAvatar.position, 10, false);
|
||||
* print("Number of Entities with the name Light-Target " + entityIDs.length);
|
||||
*/
|
||||
Q_INVOKABLE QVector<QUuid> findEntitiesByName(const QString entityName, const glm::vec3& center, float radius, bool caseSensitiveSearch = false ) const;
|
||||
|
||||
/**jsdoc
|
||||
* Find the first entity intersected by a {@link PickRay}. <code>Light</code> and <code>Zone</code> entities are not
|
||||
* intersected unless they've been configured as pickable using {@link Entities.setLightsArePickable|setLightsArePickable}
|
||||
|
|
|
@ -44,8 +44,9 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
|||
|
||||
(&::gpu::gl::GLBackend::do_setModelTransform),
|
||||
(&::gpu::gl::GLBackend::do_setViewTransform),
|
||||
(&::gpu::gl::GLBackend::do_setProjectionTransform),
|
||||
(&::gpu::gl::GLBackend::do_setViewportTransform),
|
||||
(&::gpu::gl::GLBackend::do_setProjectionTransform),
|
||||
(&::gpu::gl::GLBackend::do_setProjectionJitter),
|
||||
(&::gpu::gl::GLBackend::do_setViewportTransform),
|
||||
(&::gpu::gl::GLBackend::do_setDepthRangeTransform),
|
||||
|
||||
(&::gpu::gl::GLBackend::do_setPipeline),
|
||||
|
@ -166,7 +167,18 @@ void GLBackend::renderPassTransfer(const Batch& batch) {
|
|||
case Batch::COMMAND_drawIndexedInstanced:
|
||||
case Batch::COMMAND_multiDrawIndirect:
|
||||
case Batch::COMMAND_multiDrawIndexedIndirect:
|
||||
_transform.preUpdate(_commandIndex, _stereo);
|
||||
{
|
||||
Vec2u outputSize{ 1,1 };
|
||||
|
||||
if (_output._framebuffer) {
|
||||
outputSize.x = _output._framebuffer->getWidth();
|
||||
outputSize.y = _output._framebuffer->getHeight();
|
||||
} else if (glm::dot(_transform._projectionJitter, _transform._projectionJitter)>0.0f) {
|
||||
qCWarning(gpugllogging) << "Jittering needs to have a frame buffer to be set";
|
||||
}
|
||||
|
||||
_transform.preUpdate(_commandIndex, _stereo, outputSize);
|
||||
}
|
||||
break;
|
||||
|
||||
case Batch::COMMAND_disableContextStereo:
|
||||
|
@ -179,8 +191,10 @@ void GLBackend::renderPassTransfer(const Batch& batch) {
|
|||
|
||||
case Batch::COMMAND_setViewportTransform:
|
||||
case Batch::COMMAND_setViewTransform:
|
||||
case Batch::COMMAND_setProjectionTransform: {
|
||||
CommandCall call = _commandCalls[(*command)];
|
||||
case Batch::COMMAND_setProjectionTransform:
|
||||
case Batch::COMMAND_setProjectionJitter:
|
||||
{
|
||||
CommandCall call = _commandCalls[(*command)];
|
||||
(this->*(call))(batch, *offset);
|
||||
break;
|
||||
}
|
||||
|
@ -254,6 +268,8 @@ void GLBackend::render(const Batch& batch) {
|
|||
if (!batch.isStereoEnabled()) {
|
||||
_stereo._enable = false;
|
||||
}
|
||||
// Reset jitter
|
||||
_transform._projectionJitter = Vec2(0.0f, 0.0f);
|
||||
|
||||
{
|
||||
PROFILE_RANGE(render_gpu_gl_detail, "Transfer");
|
||||
|
|
|
@ -126,6 +126,7 @@ public:
|
|||
virtual void do_setModelTransform(const Batch& batch, size_t paramOffset) final;
|
||||
virtual void do_setViewTransform(const Batch& batch, size_t paramOffset) final;
|
||||
virtual void do_setProjectionTransform(const Batch& batch, size_t paramOffset) final;
|
||||
virtual void do_setProjectionJitter(const Batch& batch, size_t paramOffset) final;
|
||||
virtual void do_setViewportTransform(const Batch& batch, size_t paramOffset) final;
|
||||
virtual void do_setDepthRangeTransform(const Batch& batch, size_t paramOffset) final;
|
||||
|
||||
|
@ -367,6 +368,7 @@ protected:
|
|||
Mat4 _projection;
|
||||
Vec4i _viewport { 0, 0, 1, 1 };
|
||||
Vec2 _depthRange { 0.0f, 1.0f };
|
||||
Vec2 _projectionJitter{ 0.0f, 0.0f };
|
||||
bool _invalidView { false };
|
||||
bool _invalidProj { false };
|
||||
bool _invalidViewport { false };
|
||||
|
@ -379,7 +381,7 @@ protected:
|
|||
mutable List::const_iterator _camerasItr;
|
||||
mutable size_t _currentCameraOffset{ INVALID_OFFSET };
|
||||
|
||||
void preUpdate(size_t commandIndex, const StereoState& stereo);
|
||||
void preUpdate(size_t commandIndex, const StereoState& stereo, Vec2u framebufferSize);
|
||||
void update(size_t commandIndex, const StereoState& stereo) const;
|
||||
void bindCurrentCamera(int stereoSide) const;
|
||||
} _transform;
|
||||
|
|
|
@ -28,6 +28,12 @@ void GLBackend::do_setProjectionTransform(const Batch& batch, size_t paramOffset
|
|||
_transform._invalidProj = true;
|
||||
}
|
||||
|
||||
void GLBackend::do_setProjectionJitter(const Batch& batch, size_t paramOffset) {
|
||||
_transform._projectionJitter.x = batch._params[paramOffset]._float;
|
||||
_transform._projectionJitter.y = batch._params[paramOffset+1]._float;
|
||||
_transform._invalidProj = true;
|
||||
}
|
||||
|
||||
void GLBackend::do_setViewportTransform(const Batch& batch, size_t paramOffset) {
|
||||
memcpy(&_transform._viewport, batch.readData(batch._params[paramOffset]._uint), sizeof(Vec4i));
|
||||
|
||||
|
@ -90,7 +96,7 @@ void GLBackend::syncTransformStateCache() {
|
|||
_transform._enabledDrawcallInfoBuffer = false;
|
||||
}
|
||||
|
||||
void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const StereoState& stereo) {
|
||||
void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const StereoState& stereo, Vec2u framebufferSize) {
|
||||
// Check all the dirty flags and update the state accordingly
|
||||
if (_invalidViewport) {
|
||||
_camera._viewport = glm::vec4(_viewport);
|
||||
|
@ -117,20 +123,21 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo
|
|||
|
||||
if (_invalidView || _invalidProj || _invalidViewport) {
|
||||
size_t offset = _cameraUboSize * _cameras.size();
|
||||
Vec2 finalJitter = _projectionJitter / Vec2(framebufferSize);
|
||||
_cameraOffsets.push_back(TransformStageState::Pair(commandIndex, offset));
|
||||
|
||||
if (stereo.isStereo()) {
|
||||
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||
_cameras.push_back(CameraBufferElement(_camera.getEyeCamera(0, stereo, _view), _camera.getEyeCamera(1, stereo, _view)));
|
||||
_cameras.push_back(CameraBufferElement(_camera.getEyeCamera(0, stereo, _view, finalJitter), _camera.getEyeCamera(1, stereo, _view, finalJitter)));
|
||||
#else
|
||||
_cameras.push_back((_camera.getEyeCamera(0, stereo, _view)));
|
||||
_cameras.push_back((_camera.getEyeCamera(1, stereo, _view)));
|
||||
_cameras.push_back((_camera.getEyeCamera(0, stereo, _view, finalJitter)));
|
||||
_cameras.push_back((_camera.getEyeCamera(1, stereo, _view, finalJitter)));
|
||||
#endif
|
||||
} else {
|
||||
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||
_cameras.push_back(CameraBufferElement(_camera.recomputeDerived(_view)));
|
||||
_cameras.push_back(CameraBufferElement(_camera.getMonoCamera(_view, finalJitter)));
|
||||
#else
|
||||
_cameras.push_back((_camera.recomputeDerived(_view)));
|
||||
_cameras.push_back((_camera.getMonoCamera(_view, finalJitter)));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -265,6 +265,22 @@ void Batch::setProjectionTransform(const Mat4& proj) {
|
|||
_params.emplace_back(cacheData(sizeof(Mat4), &proj));
|
||||
}
|
||||
|
||||
void Batch::setProjectionJitter(float jx, float jy) {
|
||||
_projectionJitter.x = jx;
|
||||
_projectionJitter.y = jy;
|
||||
pushProjectionJitter(jx, jy);
|
||||
}
|
||||
|
||||
void Batch::pushProjectionJitter(float jx, float jy) {
|
||||
ADD_COMMAND(setProjectionJitter);
|
||||
_params.emplace_back(jx);
|
||||
_params.emplace_back(jy);
|
||||
}
|
||||
|
||||
void Batch::popProjectionJitter() {
|
||||
pushProjectionJitter(_projectionJitter.x, _projectionJitter.y);
|
||||
}
|
||||
|
||||
void Batch::setViewportTransform(const Vec4i& viewport) {
|
||||
ADD_COMMAND(setViewportTransform);
|
||||
|
||||
|
|
|
@ -167,6 +167,10 @@ public:
|
|||
void resetViewTransform() { setViewTransform(Transform(), false); }
|
||||
void setViewTransform(const Transform& view, bool camera = true);
|
||||
void setProjectionTransform(const Mat4& proj);
|
||||
void setProjectionJitter(float jx = 0.0f, float jy = 0.0f);
|
||||
// Very simple 1 level stack management of jitter.
|
||||
void pushProjectionJitter(float jx = 0.0f, float jy = 0.0f);
|
||||
void popProjectionJitter();
|
||||
// Viewport is xy = low left corner in framebuffer, zw = width height of the viewport, expressed in pixels
|
||||
void setViewportTransform(const Vec4i& viewport);
|
||||
void setDepthRangeTransform(float nearDepth, float farDepth);
|
||||
|
@ -292,8 +296,9 @@ public:
|
|||
|
||||
COMMAND_setModelTransform,
|
||||
COMMAND_setViewTransform,
|
||||
COMMAND_setProjectionTransform,
|
||||
COMMAND_setViewportTransform,
|
||||
COMMAND_setProjectionTransform,
|
||||
COMMAND_setProjectionJitter,
|
||||
COMMAND_setViewportTransform,
|
||||
COMMAND_setDepthRangeTransform,
|
||||
|
||||
COMMAND_setPipeline,
|
||||
|
@ -496,6 +501,7 @@ public:
|
|||
|
||||
NamedBatchDataMap _namedData;
|
||||
|
||||
glm::vec2 _projectionJitter{ 0.0f, 0.0f };
|
||||
bool _enableStereo{ true };
|
||||
bool _enableSkybox { false };
|
||||
|
||||
|
|
|
@ -41,15 +41,19 @@ vec3 color_LinearToYCoCg(vec3 rgb) {
|
|||
);
|
||||
}
|
||||
|
||||
vec3 color_YCoCgToLinear(vec3 ycocg) {
|
||||
vec3 color_YCoCgToUnclampedLinear(vec3 ycocg) {
|
||||
// R = Y + Co - Cg
|
||||
// G = Y + Cg
|
||||
// B = Y - Co - Cg
|
||||
return clamp(vec3(
|
||||
return vec3(
|
||||
ycocg.x + ycocg.y - ycocg.z,
|
||||
ycocg.x + ycocg.z,
|
||||
ycocg.x - ycocg.y - ycocg.z
|
||||
), vec3(0.0), vec3(1.0));
|
||||
);
|
||||
}
|
||||
|
||||
vec3 color_YCoCgToLinear(vec3 ycocg) {
|
||||
return clamp(color_YCoCgToUnclampedLinear(ycocg), vec3(0.0), vec3(1.0));
|
||||
}
|
||||
|
||||
<@func declareColorWheel()@>
|
||||
|
|
|
@ -222,7 +222,7 @@ const Backend::TransformCamera& Backend::TransformCamera::recomputeDerived(const
|
|||
return *this;
|
||||
}
|
||||
|
||||
Backend::TransformCamera Backend::TransformCamera::getEyeCamera(int eye, const StereoState& _stereo, const Transform& xformView) const {
|
||||
Backend::TransformCamera Backend::TransformCamera::getEyeCamera(int eye, const StereoState& _stereo, const Transform& xformView, Vec2 normalizedJitter) const {
|
||||
TransformCamera result = *this;
|
||||
Transform offsetTransform = xformView;
|
||||
if (!_stereo._skybox) {
|
||||
|
@ -231,6 +231,9 @@ Backend::TransformCamera Backend::TransformCamera::getEyeCamera(int eye, const S
|
|||
// FIXME: If "skybox" the ipd is set to 0 for now, let s try to propose a better solution for this in the future
|
||||
}
|
||||
result._projection = _stereo._eyeProjections[eye];
|
||||
normalizedJitter.x *= 2.0f;
|
||||
result._projection[2][0] += normalizedJitter.x;
|
||||
result._projection[2][1] += normalizedJitter.y;
|
||||
result.recomputeDerived(offsetTransform);
|
||||
|
||||
result._stereoInfo = Vec4(1.0f, (float)eye, 0.0f, 0.0f);
|
||||
|
@ -238,6 +241,14 @@ Backend::TransformCamera Backend::TransformCamera::getEyeCamera(int eye, const S
|
|||
return result;
|
||||
}
|
||||
|
||||
Backend::TransformCamera Backend::TransformCamera::getMonoCamera(const Transform& xformView, Vec2 normalizedJitter) const {
|
||||
TransformCamera result = *this;
|
||||
result._projection[2][0] += normalizedJitter.x;
|
||||
result._projection[2][1] += normalizedJitter.y;
|
||||
result.recomputeDerived(xformView);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Counters for Buffer and Texture usage in GPU/Context
|
||||
|
||||
ContextMetricSize Backend::freeGPUMemSize;
|
||||
|
|
|
@ -64,19 +64,16 @@ public:
|
|||
virtual void recycle() const = 0;
|
||||
virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0;
|
||||
|
||||
// UBO class... layout MUST match the layout in Transform.slh
|
||||
class TransformCamera {
|
||||
public:
|
||||
mutable Mat4 _view;
|
||||
mutable Mat4 _viewInverse;
|
||||
mutable Mat4 _projectionViewUntranslated;
|
||||
Mat4 _projection;
|
||||
mutable Mat4 _projectionInverse;
|
||||
Vec4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.
|
||||
mutable Vec4 _stereoInfo;
|
||||
// Shared header between C++ and GLSL
|
||||
#include "TransformCamera_shared.slh"
|
||||
|
||||
class TransformCamera : public _TransformCamera {
|
||||
public:
|
||||
const Backend::TransformCamera& recomputeDerived(const Transform& xformView) const;
|
||||
TransformCamera getEyeCamera(int eye, const StereoState& stereo, const Transform& xformView) const;
|
||||
// Jitter should be divided by framebuffer size
|
||||
TransformCamera getMonoCamera(const Transform& xformView, Vec2 normalizedJitter) const;
|
||||
// Jitter should be divided by framebuffer size
|
||||
TransformCamera getEyeCamera(int eye, const StereoState& stereo, const Transform& xformView, Vec2 normalizedJitter) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -136,7 +133,6 @@ protected:
|
|||
friend class Context;
|
||||
mutable ContextStats _stats;
|
||||
StereoState _stereo;
|
||||
|
||||
};
|
||||
|
||||
class Context {
|
||||
|
|
|
@ -11,20 +11,14 @@
|
|||
<@def GPU_TRANSFORM_STATE_SLH@>
|
||||
|
||||
<@func declareStandardCameraTransform()@>
|
||||
struct TransformCamera {
|
||||
mat4 _view;
|
||||
mat4 _viewInverse;
|
||||
mat4 _projectionViewUntranslated;
|
||||
mat4 _projection;
|
||||
mat4 _projectionInverse;
|
||||
vec4 _viewport;
|
||||
vec4 _stereoInfo;
|
||||
};
|
||||
<@include gpu/TransformCamera_shared.slh@>
|
||||
|
||||
#define TransformCamera _TransformCamera
|
||||
|
||||
layout(std140) uniform transformCameraBuffer {
|
||||
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||
TransformCamera _camera[2];
|
||||
TransformCamera _camera[2];
|
||||
#else
|
||||
TransformCamera _camera;
|
||||
#endif
|
||||
|
|
26
libraries/gpu/src/gpu/TransformCamera_shared.slh
Normal file
26
libraries/gpu/src/gpu/TransformCamera_shared.slh
Normal file
|
@ -0,0 +1,26 @@
|
|||
// glsl / C++ compatible source as interface for FadeEffect
|
||||
#ifdef __cplusplus
|
||||
# define _MAT4 Mat4
|
||||
# define _VEC4 Vec4
|
||||
# define _MUTABLE mutable
|
||||
#else
|
||||
# define _MAT4 mat4
|
||||
# define _VEC4 vec4
|
||||
# define _MUTABLE
|
||||
#endif
|
||||
|
||||
struct _TransformCamera {
|
||||
_MUTABLE _MAT4 _view;
|
||||
_MUTABLE _MAT4 _viewInverse;
|
||||
_MUTABLE _MAT4 _projectionViewUntranslated;
|
||||
_MAT4 _projection;
|
||||
_MUTABLE _MAT4 _projectionInverse;
|
||||
_VEC4 _viewport; // Public value is int but float in the shader to stay in floats for all the transform computations.
|
||||
_MUTABLE _VEC4 _stereoInfo;
|
||||
};
|
||||
|
||||
// <@if 1@>
|
||||
// Trigger Scribe include
|
||||
// <@endif@> <!def that !>
|
||||
//
|
||||
|
|
@ -21,6 +21,11 @@
|
|||
#include "FBXReader.h"
|
||||
#include "TextureCache.h"
|
||||
|
||||
/**jsdoc
|
||||
* API to manage Model Cache resources
|
||||
* @namespace ModelCache
|
||||
*/
|
||||
|
||||
// Alias instead of derive to avoid copying
|
||||
|
||||
class NetworkTexture;
|
||||
|
@ -136,7 +141,73 @@ class ModelCache : public ResourceCache, public Dependency {
|
|||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/**jsdoc
|
||||
* @namespace ModelCache
|
||||
* @property numTotal {number} total number of total resources
|
||||
* @property numCached {number} total number of cached resource
|
||||
* @property sizeTotal {number} size in bytes of all resources
|
||||
* @property sizeCached {number} size in bytes of all cached resources
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total number of resources
|
||||
* @function ModelCache.getNumTotalResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total size in bytes of all resources
|
||||
* @function ModelCache.getSizeTotalResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total number of cached resources
|
||||
* @function ModelCache.getNumCachedResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total size in bytes of cached resources
|
||||
* @function ModelCache.getSizeCachedResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns list of all resource urls
|
||||
* @function ModelCache.getResourceList
|
||||
* @returns {string[]}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Asynchronously loads a resource from the spedified URL and returns it.
|
||||
* @param url {string} url of resource to load
|
||||
* @param fallback {string} fallback URL if load of the desired url fails
|
||||
* @function ModelCache.getResource
|
||||
* @returns {Resource}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Prefetches a resource.
|
||||
* @param url {string} url of resource to load
|
||||
* @function ModelCache.prefetch
|
||||
* @returns {Resource}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @param {number} deltaSize
|
||||
* @function ModelCache.updateTotalSize
|
||||
* @returns {Resource}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function ModelCache.dirty
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
GeometryResource::Pointer getGeometryResource(const QUrl& url,
|
||||
const QVariantHash& mapping = QVariantHash(),
|
||||
const QUrl& textureBaseUrl = QUrl());
|
||||
|
|
|
@ -137,12 +137,90 @@ using NetworkTexturePointer = QSharedPointer<NetworkTexture>;
|
|||
|
||||
Q_DECLARE_METATYPE(QWeakPointer<NetworkTexture>)
|
||||
|
||||
/**jsdoc
|
||||
* API to manage Texture Cache resources
|
||||
* @namespace TextureCache
|
||||
*/
|
||||
|
||||
/// Stores cached textures, including render-to-texture targets.
|
||||
class TextureCache : public ResourceCache, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
// Copied over from ResourceCache (see ResourceCache.h for reason)
|
||||
|
||||
/**jsdoc
|
||||
* @namespace TextureCache
|
||||
* @property numTotal {number} total number of total resources
|
||||
* @property numCached {number} total number of cached resource
|
||||
* @property sizeTotal {number} size in bytes of all resources
|
||||
* @property sizeCached {number} size in bytes of all cached resources
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total number of resources
|
||||
* @function TextureCache.getNumTotalResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total size in bytes of all resources
|
||||
* @function TextureCache.getSizeTotalResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total number of cached resources
|
||||
* @function TextureCache.getNumCachedResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns the total size in bytes of cached resources
|
||||
* @function TextureCache.getSizeCachedResources
|
||||
* @returns {number}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns list of all resource urls
|
||||
* @function TextureCache.getResourceList
|
||||
* @returns {string[]}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Returns animation resource for particular animation
|
||||
* @function TextureCache.getAnimation
|
||||
* @param url {string} url to load
|
||||
* @returns {Resource} animation
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Asynchronously loads a resource from the spedified URL and returns it.
|
||||
* @param url {string} url of resource to load
|
||||
* @param fallback {string} fallback URL if load of the desired url fails
|
||||
* @function TextureCache.getResource
|
||||
* @returns {Resource}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Prefetches a resource.
|
||||
* @param url {string} url of resource to load
|
||||
* @function TextureCache.prefetch
|
||||
* @returns {Resource}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @param {number} deltaSize
|
||||
* @function TextureCache.updateTotalSize
|
||||
* @returns {Resource}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* @function TextureCache.dirty
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
/// Returns the ID of the permutation/normal texture used for Perlin noise shader programs. This texture
|
||||
/// has two lines: the first, a set of random numbers in [0, 255] to be used as permutation offsets, and
|
||||
/// the second, a set of random unit vectors to be used as noise gradients.
|
||||
|
@ -180,6 +258,10 @@ public:
|
|||
static const int DEFAULT_SPECTATOR_CAM_HEIGHT { 1024 };
|
||||
|
||||
signals:
|
||||
/**jsdoc
|
||||
* @function TextureCache.spectatorCameraFramebufferReset
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void spectatorCameraFramebufferReset();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
//
|
||||
// HMACAuth.cpp
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Simon Walton on 3/19/2018.
|
||||
// Copyright 2018 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 <openssl/opensslv.h>
|
||||
#include <openssl/hmac.h>
|
||||
|
||||
#include "HMACAuth.h"
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000
|
||||
HMACAuth::HMACAuth(AuthMethod authMethod)
|
||||
: _hmacContext(HMAC_CTX_new())
|
||||
, _authMethod(authMethod) { }
|
||||
|
||||
HMACAuth::~HMACAuth()
|
||||
{
|
||||
HMAC_CTX_free(_hmacContext);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
HMACAuth::HMACAuth(AuthMethod authMethod)
|
||||
: _hmacContext(new HMAC_CTX())
|
||||
, _authMethod(authMethod) {
|
||||
HMAC_CTX_init(_hmacContext);
|
||||
}
|
||||
|
||||
HMACAuth::~HMACAuth() {
|
||||
HMAC_CTX_cleanup(_hmacContext);
|
||||
delete _hmacContext;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool HMACAuth::setKey(const char* keyValue, int keyLen) {
|
||||
const EVP_MD* sslStruct = nullptr;
|
||||
|
||||
switch (_authMethod) {
|
||||
case MD5:
|
||||
sslStruct = EVP_md5();
|
||||
break;
|
||||
|
||||
case SHA1:
|
||||
sslStruct = EVP_sha1();
|
||||
break;
|
||||
|
||||
case SHA224:
|
||||
sslStruct = EVP_sha224();
|
||||
break;
|
||||
|
||||
case SHA256:
|
||||
sslStruct = EVP_sha256();
|
||||
break;
|
||||
|
||||
case RIPEMD160:
|
||||
sslStruct = EVP_ripemd160();
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
QMutexLocker lock(&_lock);
|
||||
return (bool) HMAC_Init_ex(_hmacContext, keyValue, keyLen, sslStruct, nullptr);
|
||||
}
|
||||
|
||||
bool HMACAuth::setKey(const QUuid& uidKey) {
|
||||
const QByteArray rfcBytes(uidKey.toRfc4122());
|
||||
return setKey(rfcBytes.constData(), rfcBytes.length());
|
||||
}
|
||||
|
||||
bool HMACAuth::addData(const char* data, int dataLen) {
|
||||
QMutexLocker lock(&_lock);
|
||||
return (bool) HMAC_Update(_hmacContext, reinterpret_cast<const unsigned char*>(data), dataLen);
|
||||
}
|
||||
|
||||
HMACAuth::HMACHash HMACAuth::result() {
|
||||
HMACHash hashValue(EVP_MAX_MD_SIZE);
|
||||
unsigned int hashLen;
|
||||
QMutexLocker lock(&_lock);
|
||||
HMAC_Final(_hmacContext, &hashValue[0], &hashLen);
|
||||
hashValue.resize((size_t) hashLen);
|
||||
// Clear state for possible reuse.
|
||||
HMAC_Init_ex(_hmacContext, nullptr, 0, nullptr, nullptr);
|
||||
return hashValue;
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
//
|
||||
// HMACAuth.h
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Simon Walton on 3/19/2018.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_HMACAuth_h
|
||||
#define hifi_HMACAuth_h
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <QtCore/QMutex>
|
||||
|
||||
class QUuid;
|
||||
|
||||
class HMACAuth {
|
||||
public:
|
||||
enum AuthMethod { MD5, SHA1, SHA224, SHA256, RIPEMD160 };
|
||||
using HMACHash = std::vector<unsigned char>;
|
||||
|
||||
explicit HMACAuth(AuthMethod authMethod = MD5);
|
||||
~HMACAuth();
|
||||
|
||||
bool setKey(const char* keyValue, int keyLen);
|
||||
bool setKey(const QUuid& uidKey);
|
||||
bool addData(const char* data, int dataLen);
|
||||
HMACHash result();
|
||||
|
||||
private:
|
||||
QMutex _lock;
|
||||
struct hmac_ctx_st* _hmacContext;
|
||||
AuthMethod _authMethod;
|
||||
};
|
||||
|
||||
#endif // hifi_HMACAuth_h
|
|
@ -36,7 +36,6 @@
|
|||
#include "HifiSockAddr.h"
|
||||
#include "NetworkLogging.h"
|
||||
#include "udt/Packet.h"
|
||||
#include "HMACAuth.h"
|
||||
|
||||
static Setting::Handle<quint16> LIMITED_NODELIST_LOCAL_PORT("LimitedNodeList.LocalPort", 0);
|
||||
|
||||
|
@ -331,7 +330,7 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
|
|||
if (verifiedPacket && !ignoreVerification) {
|
||||
|
||||
QByteArray packetHeaderHash = NLPacket::verificationHashInHeader(packet);
|
||||
QByteArray expectedHash = NLPacket::hashForPacketAndHMAC(packet, sourceNode->getAuthenticateHash());
|
||||
QByteArray expectedHash = NLPacket::hashForPacketAndSecret(packet, sourceNode->getConnectionSecret());
|
||||
|
||||
// check if the md5 hash in the header matches the hash we would expect
|
||||
if (packetHeaderHash != expectedHash) {
|
||||
|
@ -371,15 +370,15 @@ void LimitedNodeList::collectPacketStats(const NLPacket& packet) {
|
|||
_numCollectedBytes += packet.getDataSize();
|
||||
}
|
||||
|
||||
void LimitedNodeList::fillPacketHeader(const NLPacket& packet, HMACAuth* hmacAuth) {
|
||||
void LimitedNodeList::fillPacketHeader(const NLPacket& packet, const QUuid& connectionSecret) {
|
||||
if (!PacketTypeEnum::getNonSourcedPackets().contains(packet.getType())) {
|
||||
packet.writeSourceID(getSessionLocalID());
|
||||
}
|
||||
|
||||
if (hmacAuth
|
||||
if (!connectionSecret.isNull()
|
||||
&& !PacketTypeEnum::getNonSourcedPackets().contains(packet.getType())
|
||||
&& !PacketTypeEnum::getNonVerifiedPackets().contains(packet.getType())) {
|
||||
packet.writeVerificationHash(*hmacAuth);
|
||||
packet.writeVerificationHashGivenSecret(connectionSecret);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -395,17 +394,17 @@ qint64 LimitedNodeList::sendUnreliablePacket(const NLPacket& packet, const Node&
|
|||
emit dataSent(destinationNode.getType(), packet.getDataSize());
|
||||
destinationNode.recordBytesSent(packet.getDataSize());
|
||||
|
||||
return sendUnreliablePacket(packet, *destinationNode.getActiveSocket(), &destinationNode.getAuthenticateHash());
|
||||
return sendUnreliablePacket(packet, *destinationNode.getActiveSocket(), destinationNode.getConnectionSecret());
|
||||
}
|
||||
|
||||
qint64 LimitedNodeList::sendUnreliablePacket(const NLPacket& packet, const HifiSockAddr& sockAddr,
|
||||
HMACAuth* hmacAuth) {
|
||||
const QUuid& connectionSecret) {
|
||||
Q_ASSERT(!packet.isPartOfMessage());
|
||||
Q_ASSERT_X(!packet.isReliable(), "LimitedNodeList::sendUnreliablePacket",
|
||||
"Trying to send a reliable packet unreliably.");
|
||||
|
||||
collectPacketStats(packet);
|
||||
fillPacketHeader(packet, hmacAuth);
|
||||
fillPacketHeader(packet, connectionSecret);
|
||||
|
||||
return _nodeSocket.writePacket(packet, sockAddr);
|
||||
}
|
||||
|
@ -418,7 +417,7 @@ qint64 LimitedNodeList::sendPacket(std::unique_ptr<NLPacket> packet, const Node&
|
|||
emit dataSent(destinationNode.getType(), packet->getDataSize());
|
||||
destinationNode.recordBytesSent(packet->getDataSize());
|
||||
|
||||
return sendPacket(std::move(packet), *activeSocket, &destinationNode.getAuthenticateHash());
|
||||
return sendPacket(std::move(packet), *activeSocket, destinationNode.getConnectionSecret());
|
||||
} else {
|
||||
qCDebug(networking) << "LimitedNodeList::sendPacket called without active socket for node" << destinationNode << "- not sending";
|
||||
return ERROR_SENDING_PACKET_BYTES;
|
||||
|
@ -426,18 +425,18 @@ qint64 LimitedNodeList::sendPacket(std::unique_ptr<NLPacket> packet, const Node&
|
|||
}
|
||||
|
||||
qint64 LimitedNodeList::sendPacket(std::unique_ptr<NLPacket> packet, const HifiSockAddr& sockAddr,
|
||||
HMACAuth* hmacAuth) {
|
||||
const QUuid& connectionSecret) {
|
||||
Q_ASSERT(!packet->isPartOfMessage());
|
||||
if (packet->isReliable()) {
|
||||
collectPacketStats(*packet);
|
||||
fillPacketHeader(*packet, hmacAuth);
|
||||
fillPacketHeader(*packet, connectionSecret);
|
||||
|
||||
auto size = packet->getDataSize();
|
||||
_nodeSocket.writePacket(std::move(packet), sockAddr);
|
||||
|
||||
return size;
|
||||
} else {
|
||||
return sendUnreliablePacket(*packet, sockAddr, hmacAuth);
|
||||
return sendUnreliablePacket(*packet, sockAddr, connectionSecret);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -446,14 +445,13 @@ qint64 LimitedNodeList::sendUnreliableUnorderedPacketList(NLPacketList& packetLi
|
|||
|
||||
if (activeSocket) {
|
||||
qint64 bytesSent = 0;
|
||||
auto& connectionHash = destinationNode.getAuthenticateHash();
|
||||
auto connectionSecret = destinationNode.getConnectionSecret();
|
||||
|
||||
// close the last packet in the list
|
||||
packetList.closeCurrentPacket();
|
||||
|
||||
while (!packetList._packets.empty()) {
|
||||
bytesSent += sendPacket(packetList.takeFront<NLPacket>(), *activeSocket,
|
||||
&connectionHash);
|
||||
bytesSent += sendPacket(packetList.takeFront<NLPacket>(), *activeSocket, connectionSecret);
|
||||
}
|
||||
|
||||
emit dataSent(destinationNode.getType(), bytesSent);
|
||||
|
@ -466,14 +464,14 @@ qint64 LimitedNodeList::sendUnreliableUnorderedPacketList(NLPacketList& packetLi
|
|||
}
|
||||
|
||||
qint64 LimitedNodeList::sendUnreliableUnorderedPacketList(NLPacketList& packetList, const HifiSockAddr& sockAddr,
|
||||
HMACAuth* hmacAuth) {
|
||||
const QUuid& connectionSecret) {
|
||||
qint64 bytesSent = 0;
|
||||
|
||||
// close the last packet in the list
|
||||
packetList.closeCurrentPacket();
|
||||
|
||||
while (!packetList._packets.empty()) {
|
||||
bytesSent += sendPacket(packetList.takeFront<NLPacket>(), sockAddr, hmacAuth);
|
||||
bytesSent += sendPacket(packetList.takeFront<NLPacket>(), sockAddr, connectionSecret);
|
||||
}
|
||||
|
||||
return bytesSent;
|
||||
|
@ -501,7 +499,7 @@ qint64 LimitedNodeList::sendPacketList(std::unique_ptr<NLPacketList> packetList,
|
|||
for (std::unique_ptr<udt::Packet>& packet : packetList->_packets) {
|
||||
NLPacket* nlPacket = static_cast<NLPacket*>(packet.get());
|
||||
collectPacketStats(*nlPacket);
|
||||
fillPacketHeader(*nlPacket, &destinationNode.getAuthenticateHash());
|
||||
fillPacketHeader(*nlPacket, destinationNode.getConnectionSecret());
|
||||
}
|
||||
|
||||
return _nodeSocket.writePacketList(std::move(packetList), *activeSocket);
|
||||
|
@ -524,7 +522,7 @@ qint64 LimitedNodeList::sendPacket(std::unique_ptr<NLPacket> packet, const Node&
|
|||
auto& destinationSockAddr = (overridenSockAddr.isNull()) ? *destinationNode.getActiveSocket()
|
||||
: overridenSockAddr;
|
||||
|
||||
return sendPacket(std::move(packet), destinationSockAddr, &destinationNode.getAuthenticateHash());
|
||||
return sendPacket(std::move(packet), destinationSockAddr, destinationNode.getConnectionSecret());
|
||||
}
|
||||
|
||||
int LimitedNodeList::updateNodeWithDataFromPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
||||
|
|
|
@ -138,17 +138,19 @@ public:
|
|||
// use sendUnreliablePacket to send an unreliable packet (that you do not need to move)
|
||||
// either to a node (via its active socket) or to a manual sockaddr
|
||||
qint64 sendUnreliablePacket(const NLPacket& packet, const Node& destinationNode);
|
||||
qint64 sendUnreliablePacket(const NLPacket& packet, const HifiSockAddr& sockAddr, HMACAuth* hmacAuth = nullptr);
|
||||
qint64 sendUnreliablePacket(const NLPacket& packet, const HifiSockAddr& sockAddr,
|
||||
const QUuid& connectionSecret = QUuid());
|
||||
|
||||
// use sendPacket to send a moved unreliable or reliable NL packet to a node's active socket or manual sockaddr
|
||||
qint64 sendPacket(std::unique_ptr<NLPacket> packet, const Node& destinationNode);
|
||||
qint64 sendPacket(std::unique_ptr<NLPacket> packet, const HifiSockAddr& sockAddr, HMACAuth* hmacAuth = nullptr);
|
||||
qint64 sendPacket(std::unique_ptr<NLPacket> packet, const HifiSockAddr& sockAddr,
|
||||
const QUuid& connectionSecret = QUuid());
|
||||
|
||||
// use sendUnreliableUnorderedPacketList to unreliably send separate packets from the packet list
|
||||
// either to a node's active socket or to a manual sockaddr
|
||||
qint64 sendUnreliableUnorderedPacketList(NLPacketList& packetList, const Node& destinationNode);
|
||||
qint64 sendUnreliableUnorderedPacketList(NLPacketList& packetList, const HifiSockAddr& sockAddr,
|
||||
HMACAuth* hmacAuth = nullptr);
|
||||
const QUuid& connectionSecret = QUuid());
|
||||
|
||||
// use sendPacketList to send reliable packet lists (ordered or unordered) to a node's active socket
|
||||
// or to a manual sock addr
|
||||
|
@ -370,7 +372,7 @@ protected:
|
|||
qint64 writePacket(const NLPacket& packet, const HifiSockAddr& destinationSockAddr,
|
||||
const QUuid& connectionSecret = QUuid());
|
||||
void collectPacketStats(const NLPacket& packet);
|
||||
void fillPacketHeader(const NLPacket& packet, HMACAuth* hmacAuth = nullptr);
|
||||
void fillPacketHeader(const NLPacket& packet, const QUuid& connectionSecret = QUuid());
|
||||
|
||||
void setLocalSocket(const HifiSockAddr& sockAddr);
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
|
||||
#include "NLPacket.h"
|
||||
|
||||
#include "HMACAuth.h"
|
||||
|
||||
int NLPacket::localHeaderSize(PacketType type) {
|
||||
bool nonSourced = PacketTypeEnum::getNonSourcedPackets().contains(type);
|
||||
bool nonVerified = PacketTypeEnum::getNonVerifiedPackets().contains(type);
|
||||
|
@ -152,14 +150,18 @@ QByteArray NLPacket::verificationHashInHeader(const udt::Packet& packet) {
|
|||
return QByteArray(packet.getData() + offset, NUM_BYTES_MD5_HASH);
|
||||
}
|
||||
|
||||
QByteArray NLPacket::hashForPacketAndHMAC(const udt::Packet& packet, HMACAuth& hash) {
|
||||
QByteArray NLPacket::hashForPacketAndSecret(const udt::Packet& packet, const QUuid& connectionSecret) {
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
|
||||
int offset = Packet::totalHeaderSize(packet.isPartOfMessage()) + sizeof(PacketType) + sizeof(PacketVersion)
|
||||
+ NUM_BYTES_LOCALID + NUM_BYTES_MD5_HASH;
|
||||
|
||||
// add the packet payload and the connection UUID
|
||||
hash.addData(packet.getData() + offset, packet.getDataSize() - offset);
|
||||
auto hashResult { hash.result() };
|
||||
return QByteArray((const char*) hashResult.data(), (int) hashResult.size());
|
||||
hash.addData(connectionSecret.toRfc4122());
|
||||
|
||||
// return the hash
|
||||
return hash.result();
|
||||
}
|
||||
|
||||
void NLPacket::writeTypeAndVersion() {
|
||||
|
@ -212,14 +214,14 @@ void NLPacket::writeSourceID(LocalID sourceID) const {
|
|||
_sourceID = sourceID;
|
||||
}
|
||||
|
||||
void NLPacket::writeVerificationHash(HMACAuth& hmacAuth) const {
|
||||
void NLPacket::writeVerificationHashGivenSecret(const QUuid& connectionSecret) const {
|
||||
Q_ASSERT(!PacketTypeEnum::getNonSourcedPackets().contains(_type) &&
|
||||
!PacketTypeEnum::getNonVerifiedPackets().contains(_type));
|
||||
|
||||
auto offset = Packet::totalHeaderSize(isPartOfMessage()) + sizeof(PacketType) + sizeof(PacketVersion)
|
||||
+ NUM_BYTES_LOCALID;
|
||||
|
||||
QByteArray verificationHash = hashForPacketAndHMAC(*this, hmacAuth);
|
||||
QByteArray verificationHash = hashForPacketAndSecret(*this, connectionSecret);
|
||||
|
||||
memcpy(_packet.get() + offset, verificationHash.data(), verificationHash.size());
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
#include "udt/Packet.h"
|
||||
|
||||
class HMACAuth;
|
||||
|
||||
class NLPacket : public udt::Packet {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -71,7 +69,7 @@ public:
|
|||
|
||||
static LocalID sourceIDInHeader(const udt::Packet& packet);
|
||||
static QByteArray verificationHashInHeader(const udt::Packet& packet);
|
||||
static QByteArray hashForPacketAndHMAC(const udt::Packet& packet, HMACAuth& hash);
|
||||
static QByteArray hashForPacketAndSecret(const udt::Packet& packet, const QUuid& connectionSecret);
|
||||
|
||||
PacketType getType() const { return _type; }
|
||||
void setType(PacketType type);
|
||||
|
@ -80,9 +78,9 @@ public:
|
|||
void setVersion(PacketVersion version);
|
||||
|
||||
LocalID getSourceID() const { return _sourceID; }
|
||||
|
||||
|
||||
void writeSourceID(LocalID sourceID) const;
|
||||
void writeVerificationHash(HMACAuth& hmacAuth) const;
|
||||
void writeVerificationHashGivenSecret(const QUuid& connectionSecret) const;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -86,10 +86,10 @@ NodeType_t NodeType::fromString(QString type) {
|
|||
|
||||
|
||||
Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket,
|
||||
const HifiSockAddr& localSocket, QObject* parent) :
|
||||
const HifiSockAddr& localSocket, QObject* parent) :
|
||||
NetworkPeer(uuid, publicSocket, localSocket, parent),
|
||||
_type(type),
|
||||
_authenticateHash(new HMACAuth), _pingMs(-1), // "Uninitialized"
|
||||
_pingMs(-1), // "Uninitialized"
|
||||
_clockSkewUsec(0),
|
||||
_mutex(),
|
||||
_clockSkewMovingPercentile(30, 0.8f) // moving 80th percentile of 30 samples
|
||||
|
@ -108,7 +108,6 @@ void Node::setType(char type) {
|
|||
_symmetricSocket.setObjectName(typeString);
|
||||
}
|
||||
|
||||
|
||||
void Node::updateClockSkewUsec(qint64 clockSkewSample) {
|
||||
_clockSkewMovingPercentile.updatePercentile(clockSkewSample);
|
||||
_clockSkewUsec = (quint64)_clockSkewMovingPercentile.getValueAtPercentile();
|
||||
|
@ -195,12 +194,3 @@ QDebug operator<<(QDebug debug, const Node& node) {
|
|||
debug.nospace() << node.getPublicSocket() << "/" << node.getLocalSocket();
|
||||
return debug.nospace();
|
||||
}
|
||||
|
||||
void Node::setConnectionSecret(const QUuid& connectionSecret) {
|
||||
if (_connectionSecret == connectionSecret) {
|
||||
return;
|
||||
}
|
||||
|
||||
_connectionSecret = connectionSecret;
|
||||
_authenticateHash->setKey(_connectionSecret);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include "SimpleMovingAverage.h"
|
||||
#include "MovingPercentile.h"
|
||||
#include "NodePermissions.h"
|
||||
#include "HMACAuth.h"
|
||||
|
||||
class Node : public NetworkPeer {
|
||||
Q_OBJECT
|
||||
|
@ -56,8 +55,7 @@ public:
|
|||
void setIsUpstream(bool isUpstream) { _isUpstream = isUpstream; }
|
||||
|
||||
const QUuid& getConnectionSecret() const { return _connectionSecret; }
|
||||
void setConnectionSecret(const QUuid& connectionSecret);
|
||||
HMACAuth& getAuthenticateHash() const { return *_authenticateHash; }
|
||||
void setConnectionSecret(const QUuid& connectionSecret) { _connectionSecret = connectionSecret; }
|
||||
|
||||
NodeData* getLinkedData() const { return _linkedData.get(); }
|
||||
void setLinkedData(std::unique_ptr<NodeData> linkedData) { _linkedData = std::move(linkedData); }
|
||||
|
@ -99,7 +97,6 @@ private:
|
|||
NodeType_t _type;
|
||||
|
||||
QUuid _connectionSecret;
|
||||
std::unique_ptr<HMACAuth> _authenticateHash;
|
||||
std::unique_ptr<NodeData> _linkedData;
|
||||
bool _isReplicated { false };
|
||||
int _pingMs;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//
|
||||
//
|
||||
// ResourceCache.h
|
||||
// libraries/shared/src
|
||||
//
|
||||
|
@ -85,9 +85,7 @@ private:
|
|||
|
||||
/// Wrapper to expose resources to JS/QML
|
||||
class ScriptableResource : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QUrl url READ getURL)
|
||||
Q_PROPERTY(int state READ getState NOTIFY stateChanged)
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @constructor Resource
|
||||
|
@ -95,6 +93,12 @@ class ScriptableResource : public QObject {
|
|||
* @property state {Resource.State} current loading state
|
||||
*/
|
||||
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QUrl url READ getURL)
|
||||
Q_PROPERTY(int state READ getState NOTIFY stateChanged)
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/**jsdoc
|
||||
|
@ -181,11 +185,8 @@ Q_DECLARE_METATYPE(ScriptableResource*);
|
|||
/// Base class for resource caches.
|
||||
class ResourceCache : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(size_t numTotal READ getNumTotalResources NOTIFY dirty)
|
||||
Q_PROPERTY(size_t numCached READ getNumCachedResources NOTIFY dirty)
|
||||
Q_PROPERTY(size_t sizeTotal READ getSizeTotalResources NOTIFY dirty)
|
||||
Q_PROPERTY(size_t sizeCached READ getSizeCachedResources NOTIFY dirty)
|
||||
|
||||
// JSDoc 3.5.5 doesn't augment @property definitions.
|
||||
// These functions are being copied into the different exposed cache classes
|
||||
/**jsdoc
|
||||
* @namespace ResourceCache
|
||||
* @property numTotal {number} total number of total resources
|
||||
|
@ -193,6 +194,10 @@ class ResourceCache : public QObject {
|
|||
* @property sizeTotal {number} size in bytes of all resources
|
||||
* @property sizeCached {number} size in bytes of all cached resources
|
||||
*/
|
||||
Q_PROPERTY(size_t numTotal READ getNumTotalResources NOTIFY dirty)
|
||||
Q_PROPERTY(size_t numCached READ getNumCachedResources NOTIFY dirty)
|
||||
Q_PROPERTY(size_t sizeTotal READ getSizeTotalResources NOTIFY dirty)
|
||||
Q_PROPERTY(size_t sizeCached READ getSizeCachedResources NOTIFY dirty)
|
||||
|
||||
public:
|
||||
/**jsdoc
|
||||
|
|
|
@ -91,7 +91,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::Ping:
|
||||
return static_cast<PacketVersion>(PingVersion::IncludeConnectionID);
|
||||
default:
|
||||
return 19;
|
||||
return 20;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -187,7 +187,8 @@ const int AntialiasingPass_DepthMapSlot = 3;
|
|||
const int AntialiasingPass_NextMapSlot = 4;
|
||||
|
||||
|
||||
Antialiasing::Antialiasing() {
|
||||
Antialiasing::Antialiasing(bool isSharpenEnabled) :
|
||||
_isSharpenEnabled{ isSharpenEnabled } {
|
||||
_antialiasingBuffers = std::make_shared<gpu::FramebufferSwapChain>(2U);
|
||||
}
|
||||
|
||||
|
@ -282,8 +283,11 @@ const gpu::PipelinePointer& Antialiasing::getDebugBlendPipeline() {
|
|||
}
|
||||
|
||||
void Antialiasing::configure(const Config& config) {
|
||||
_sharpen = config.sharpen;
|
||||
_params.edit().blend = config.blend;
|
||||
_sharpen = config.sharpen * 0.25f;
|
||||
if (!_isSharpenEnabled) {
|
||||
_sharpen = 0.0f;
|
||||
}
|
||||
_params.edit().blend = config.blend * config.blend;
|
||||
_params.edit().covarianceGamma = config.covarianceGamma;
|
||||
|
||||
_params.edit().setConstrainColor(config.constrainColor);
|
||||
|
@ -328,11 +332,11 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const
|
|||
|
||||
if (!_antialiasingBuffers->get(0)) {
|
||||
// Link the antialiasing FBO to texture
|
||||
auto format = sourceBuffer->getRenderBuffer(0)->getTexelFormat();
|
||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
auto& antiAliasingBuffer = _antialiasingBuffers->edit(i);
|
||||
antiAliasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("antialiasing"));
|
||||
auto format = gpu::Element::COLOR_SRGBA_32; // DependencyManager::get<FramebufferCache>()->getLightingTexture()->getTexelFormat();
|
||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR);
|
||||
_antialiasingTextures[i] = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, defaultSampler);
|
||||
antiAliasingBuffer->setRenderBuffer(0, _antialiasingTextures[i]);
|
||||
}
|
||||
|
@ -380,8 +384,6 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const
|
|||
batch.setResourceTexture(AntialiasingPass_VelocityMapSlot, nullptr);
|
||||
batch.setResourceTexture(AntialiasingPass_NextMapSlot, nullptr);
|
||||
});
|
||||
|
||||
args->popViewFrustum();
|
||||
}
|
||||
|
||||
|
||||
|
@ -495,7 +497,7 @@ void JitterSample::configure(const Config& config) {
|
|||
_scale = config.scale;
|
||||
}
|
||||
|
||||
void JitterSample::run(const render::RenderContextPointer& renderContext) {
|
||||
void JitterSample::run(const render::RenderContextPointer& renderContext, Output& jitter) {
|
||||
auto& current = _sampleSequence.currentIndex;
|
||||
if (!_freeze) {
|
||||
if (current >= 0) {
|
||||
|
@ -504,39 +506,7 @@ void JitterSample::run(const render::RenderContextPointer& renderContext) {
|
|||
current = -1;
|
||||
}
|
||||
}
|
||||
auto args = renderContext->args;
|
||||
auto viewFrustum = args->getViewFrustum();
|
||||
|
||||
auto jit = _sampleSequence.offsets[(current < 0 ? SEQUENCE_LENGTH : current)];
|
||||
auto width = (float)args->_viewport.z;
|
||||
auto height = (float)args->_viewport.w;
|
||||
|
||||
auto jx = 2.0f * jit.x / width;
|
||||
auto jy = 2.0f * jit.y / height;
|
||||
|
||||
if (!args->isStereo()) {
|
||||
auto projMat = viewFrustum.getProjection();
|
||||
|
||||
projMat[2][0] += jx;
|
||||
projMat[2][1] += jy;
|
||||
|
||||
viewFrustum.setProjection(projMat);
|
||||
viewFrustum.calculate();
|
||||
args->pushViewFrustum(viewFrustum);
|
||||
} else {
|
||||
mat4 projMats[2];
|
||||
args->_context->getStereoProjections(projMats);
|
||||
|
||||
jx *= 2.0f;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
auto& projMat = projMats[i];
|
||||
projMat[2][0] += jx;
|
||||
projMat[2][1] += jy;
|
||||
}
|
||||
|
||||
args->_context->setStereoProjections(projMats);
|
||||
}
|
||||
jitter = _sampleSequence.offsets[(current < 0 ? SEQUENCE_LENGTH : current)];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -58,14 +58,15 @@ class JitterSample {
|
|||
public:
|
||||
|
||||
enum {
|
||||
SEQUENCE_LENGTH = 128
|
||||
SEQUENCE_LENGTH = 64
|
||||
};
|
||||
|
||||
using Config = JitterSampleConfig;
|
||||
using JobModel = render::Job::Model<JitterSample, Config>;
|
||||
using Output = glm::vec2;
|
||||
using JobModel = render::Job::ModelO<JitterSample, Output, Config>;
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext);
|
||||
void run(const render::RenderContextPointer& renderContext, Output& jitter);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -105,11 +106,11 @@ class AntialiasingConfig : public render::Job::Config {
|
|||
public:
|
||||
AntialiasingConfig() : render::Job::Config(true) {}
|
||||
|
||||
float blend{ 0.05f };
|
||||
float sharpen{ 0.15f };
|
||||
float blend{ 0.25f };
|
||||
float sharpen{ 0.05f };
|
||||
|
||||
bool constrainColor{ true };
|
||||
float covarianceGamma{ 0.9f };
|
||||
float covarianceGamma{ 0.65f };
|
||||
bool feedbackColor{ false };
|
||||
|
||||
float debugX{ 0.0f };
|
||||
|
@ -131,7 +132,7 @@ signals:
|
|||
|
||||
struct TAAParams {
|
||||
float nope{ 0.0f };
|
||||
float blend{ 0.05f };
|
||||
float blend{ 0.15f };
|
||||
float covarianceGamma{ 1.0f };
|
||||
float debugShowVelocityThreshold{ 1.0f };
|
||||
|
||||
|
@ -168,7 +169,7 @@ public:
|
|||
using Config = AntialiasingConfig;
|
||||
using JobModel = render::Job::ModelI<Antialiasing, Inputs, Config>;
|
||||
|
||||
Antialiasing();
|
||||
Antialiasing(bool isSharpenEnabled = true);
|
||||
~Antialiasing();
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
|
||||
|
@ -189,6 +190,7 @@ private:
|
|||
TAAParamsBuffer _params;
|
||||
float _sharpen{ 0.15f };
|
||||
int _sharpenLoc{ -1 };
|
||||
bool _isSharpenEnabled{ true };
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
uniform sampler2D blurMap0;
|
||||
uniform sampler2D blurMap1;
|
||||
uniform sampler2D blurMap2;
|
||||
uniform float intensity;
|
||||
uniform vec3 intensity;
|
||||
|
||||
in vec2 varTexCoord0;
|
||||
out vec4 outFragColor;
|
||||
|
@ -23,5 +23,5 @@ void main(void) {
|
|||
vec4 blur1 = texture(blurMap1, varTexCoord0);
|
||||
vec4 blur2 = texture(blurMap2, varTexCoord0);
|
||||
|
||||
outFragColor = vec4((blur0.rgb+blur1.rgb+blur2.rgb)*intensity, 1.0f);
|
||||
outFragColor = vec4(blur0.rgb*intensity.x + blur1.rgb*intensity.y + blur2.rgb*intensity.z, 1.0f);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons
|
|||
|
||||
if (!_outputBuffer || _outputBuffer->getSize() != bufferSize) {
|
||||
auto colorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(inputBuffer->getTexelFormat(), bufferSize.x, bufferSize.y,
|
||||
gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
|
||||
gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT, gpu::Sampler::WRAP_CLAMP)));
|
||||
|
||||
_outputBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("BloomThreshold"));
|
||||
_outputBuffer->setRenderBuffer(0, colorTexture);
|
||||
|
@ -93,12 +93,14 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons
|
|||
outputs = _outputBuffer;
|
||||
}
|
||||
|
||||
BloomApply::BloomApply() {
|
||||
BloomApply::BloomApply() : _intensities{ 1.0f, 1.0f, 1.0f } {
|
||||
|
||||
}
|
||||
|
||||
void BloomApply::configure(const Config& config) {
|
||||
_intensity = config.intensity;
|
||||
_intensities.x = config.intensity / 3.0f;
|
||||
_intensities.y = _intensities.x;
|
||||
_intensities.z = _intensities.x;
|
||||
}
|
||||
|
||||
void BloomApply::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) {
|
||||
|
@ -106,10 +108,10 @@ void BloomApply::run(const render::RenderContextPointer& renderContext, const In
|
|||
assert(renderContext->args->hasViewFrustum());
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
static auto BLUR0_SLOT = 0;
|
||||
static auto BLUR1_SLOT = 1;
|
||||
static auto BLUR2_SLOT = 2;
|
||||
static auto INTENSITY_SLOT = 3;
|
||||
static const auto BLUR0_SLOT = 0;
|
||||
static const auto BLUR1_SLOT = 1;
|
||||
static const auto BLUR2_SLOT = 2;
|
||||
static const auto INTENSITY_SLOT = 3;
|
||||
|
||||
if (!_pipeline) {
|
||||
auto vs = gpu::StandardShaderLib::getDrawTransformUnitQuadVS();
|
||||
|
@ -149,7 +151,7 @@ void BloomApply::run(const render::RenderContextPointer& renderContext, const In
|
|||
batch.setResourceTexture(BLUR0_SLOT, blur0FB->getRenderBuffer(0));
|
||||
batch.setResourceTexture(BLUR1_SLOT, blur1FB->getRenderBuffer(0));
|
||||
batch.setResourceTexture(BLUR2_SLOT, blur2FB->getRenderBuffer(0));
|
||||
batch._glUniform1f(INTENSITY_SLOT, _intensity / 3.0f);
|
||||
batch._glUniform3f(INTENSITY_SLOT, _intensities.x, _intensities.y, _intensities.z);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
});
|
||||
}
|
||||
|
@ -306,19 +308,19 @@ float BloomConfig::getIntensity() const {
|
|||
void BloomConfig::setSize(float value) {
|
||||
std::string blurName{ "BloomBlurN" };
|
||||
auto sigma = 0.5f+value*3.5f;
|
||||
auto task = static_cast<render::Task::TaskConcept*>(_task);
|
||||
|
||||
for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) {
|
||||
blurName.back() = '0' + i;
|
||||
auto task = static_cast<render::Task::TaskConcept*>(_task);
|
||||
auto blurJobIt = task->editJob(blurName);
|
||||
assert(blurJobIt != task->_jobs.end());
|
||||
auto& gaussianBlur = blurJobIt->edit<render::BlurGaussian>();
|
||||
auto gaussianBlurParams = gaussianBlur.getParameters();
|
||||
gaussianBlurParams->setFilterGaussianTaps(5, sigma);
|
||||
// Gaussian blur increases at each level to have a slower rolloff on the edge
|
||||
// of the response
|
||||
sigma *= 1.5f;
|
||||
gaussianBlurParams->setFilterGaussianTaps(9, sigma);
|
||||
}
|
||||
auto blurJobIt = task->getJob("BloomApply");
|
||||
assert(blurJobIt != task->_jobs.end());
|
||||
blurJobIt->getConfiguration()->setProperty("sigma", sigma);
|
||||
}
|
||||
|
||||
Bloom::Bloom() {
|
||||
|
@ -350,7 +352,7 @@ void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying
|
|||
// Mix all blur levels at quarter resolution
|
||||
const auto applyInput = BloomApply::Inputs(bloomInputBuffer, blurFB0, blurFB1, blurFB2).asVarying();
|
||||
task.addJob<BloomApply>("BloomApply", applyInput);
|
||||
// And them blend result in additive manner on top of final color buffer
|
||||
// And then blend result in additive manner on top of final color buffer
|
||||
const auto drawInput = BloomDraw::Inputs(frameBuffer, bloomInputBuffer).asVarying();
|
||||
task.addJob<BloomDraw>("BloomDraw", drawInput);
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
|
||||
BloomConfig() : render::Task::Config(false) {}
|
||||
|
||||
float size{ 0.8f };
|
||||
float size{ 0.7f };
|
||||
|
||||
void setIntensity(float value);
|
||||
float getIntensity() const;
|
||||
|
@ -41,7 +41,7 @@ class BloomThresholdConfig : public render::Job::Config {
|
|||
|
||||
public:
|
||||
|
||||
float threshold{ 1.25f };
|
||||
float threshold{ 0.9f };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
|
@ -71,10 +71,12 @@ private:
|
|||
class BloomApplyConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float intensity MEMBER intensity NOTIFY dirty)
|
||||
Q_PROPERTY(float sigma MEMBER sigma NOTIFY dirty)
|
||||
|
||||
public:
|
||||
|
||||
float intensity{ 0.8f };
|
||||
float intensity{ 0.25f };
|
||||
float sigma{ 1.0f };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
|
@ -94,7 +96,7 @@ public:
|
|||
private:
|
||||
|
||||
gpu::PipelinePointer _pipeline;
|
||||
float _intensity{ 1.0f };
|
||||
glm::vec3 _intensities;
|
||||
};
|
||||
|
||||
class BloomDraw {
|
||||
|
|
|
@ -18,7 +18,7 @@ DeferredFrameTransform::DeferredFrameTransform() {
|
|||
_frameTransformBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(FrameTransform), (const gpu::Byte*) &frameTransform));
|
||||
}
|
||||
|
||||
void DeferredFrameTransform::update(RenderArgs* args) {
|
||||
void DeferredFrameTransform::update(RenderArgs* args, glm::vec2 jitter) {
|
||||
|
||||
// Update the depth info with near and far (same for stereo)
|
||||
auto nearZ = args->getViewFrustum().getNearClip();
|
||||
|
@ -38,12 +38,23 @@ void DeferredFrameTransform::update(RenderArgs* args) {
|
|||
|
||||
args->getViewFrustum().evalProjectionMatrix(frameTransformBuffer.projectionMono);
|
||||
|
||||
// There may be some sort of mismatch here if the viewport size isn't the same as the frame buffer size as
|
||||
// jitter is normalized by frame buffer size in TransformCamera. But we should be safe.
|
||||
jitter.x /= args->_viewport.z;
|
||||
jitter.y /= args->_viewport.w;
|
||||
|
||||
// Running in stereo ?
|
||||
bool isStereo = args->isStereo();
|
||||
if (!isStereo) {
|
||||
frameTransformBuffer.projection[0] = frameTransformBuffer.projectionMono;
|
||||
frameTransformBuffer.projectionUnjittered[0] = frameTransformBuffer.projectionMono;
|
||||
frameTransformBuffer.invProjectionUnjittered[0] = glm::inverse(frameTransformBuffer.projectionUnjittered[0]);
|
||||
|
||||
frameTransformBuffer.stereoInfo = glm::vec4(0.0f, (float)args->_viewport.z, 0.0f, 0.0f);
|
||||
frameTransformBuffer.invpixelInfo = glm::vec4(1.0f / args->_viewport.z, 1.0f / args->_viewport.w, 0.0f, 0.0f);
|
||||
|
||||
frameTransformBuffer.projection[0] = frameTransformBuffer.projectionUnjittered[0];
|
||||
frameTransformBuffer.projection[0][2][0] += jitter.x;
|
||||
frameTransformBuffer.projection[0][2][1] += jitter.y;
|
||||
frameTransformBuffer.invProjection[0] = glm::inverse(frameTransformBuffer.projection[0]);
|
||||
} else {
|
||||
|
||||
|
@ -52,22 +63,28 @@ void DeferredFrameTransform::update(RenderArgs* args) {
|
|||
args->_context->getStereoProjections(projMats);
|
||||
args->_context->getStereoViews(eyeViews);
|
||||
|
||||
jitter.x *= 2.0f;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
// Compose the mono Eye space to Stereo clip space Projection Matrix
|
||||
auto sideViewMat = projMats[i] * eyeViews[i];
|
||||
frameTransformBuffer.projection[i] = sideViewMat;
|
||||
frameTransformBuffer.invProjection[i] = glm::inverse(sideViewMat);
|
||||
}
|
||||
frameTransformBuffer.projectionUnjittered[i] = sideViewMat;
|
||||
frameTransformBuffer.invProjectionUnjittered[i] = glm::inverse(sideViewMat);
|
||||
|
||||
frameTransformBuffer.projection[i] = frameTransformBuffer.projectionUnjittered[i];
|
||||
frameTransformBuffer.projection[i][2][0] += jitter.x;
|
||||
frameTransformBuffer.projection[i][2][1] += jitter.y;
|
||||
frameTransformBuffer.invProjection[i] = glm::inverse(frameTransformBuffer.projection[i]);
|
||||
}
|
||||
|
||||
frameTransformBuffer.stereoInfo = glm::vec4(1.0f, (float)(args->_viewport.z >> 1), 0.0f, 1.0f);
|
||||
frameTransformBuffer.invpixelInfo = glm::vec4(1.0f / (float)(args->_viewport.z >> 1), 1.0f / args->_viewport.w, 0.0f, 0.0f);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateDeferredFrameTransform::run(const render::RenderContextPointer& renderContext, DeferredFrameTransformPointer& frameTransform) {
|
||||
void GenerateDeferredFrameTransform::run(const render::RenderContextPointer& renderContext, const Input& jitter, Output& frameTransform) {
|
||||
if (!frameTransform) {
|
||||
frameTransform = std::make_shared<DeferredFrameTransform>();
|
||||
}
|
||||
frameTransform->update(renderContext->args);
|
||||
frameTransform->update(renderContext->args, jitter);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
|
||||
DeferredFrameTransform();
|
||||
|
||||
void update(RenderArgs* args);
|
||||
void update(RenderArgs* args, glm::vec2 jitter);
|
||||
|
||||
UniformBufferView getFrameTransformBuffer() const { return _frameTransformBuffer; }
|
||||
|
||||
|
@ -43,16 +43,20 @@ protected:
|
|||
glm::vec4 depthInfo;
|
||||
// Stereo info is { isStereoFrame, halfWidth }
|
||||
glm::vec4 stereoInfo{ 0.0 };
|
||||
// Mono proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space
|
||||
glm::mat4 projection[2];
|
||||
// Inverse proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space
|
||||
glm::mat4 invProjection[2];
|
||||
// THe mono projection for sure
|
||||
// Mono proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space
|
||||
glm::mat4 projection[2];
|
||||
// Inverse proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space
|
||||
glm::mat4 invProjection[2];
|
||||
// THe mono projection for sure
|
||||
glm::mat4 projectionMono;
|
||||
// Inv View matrix from eye space (mono) to world space
|
||||
glm::mat4 invView;
|
||||
// View matrix from world space to eye space (mono)
|
||||
glm::mat4 view;
|
||||
// Mono proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space without jittering
|
||||
glm::mat4 projectionUnjittered[2];
|
||||
// Inverse proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space without jittering
|
||||
glm::mat4 invProjectionUnjittered[2];
|
||||
|
||||
FrameTransform() {}
|
||||
};
|
||||
|
@ -68,11 +72,14 @@ using DeferredFrameTransformPointer = std::shared_ptr<DeferredFrameTransform>;
|
|||
|
||||
class GenerateDeferredFrameTransform {
|
||||
public:
|
||||
using JobModel = render::Job::ModelO<GenerateDeferredFrameTransform, DeferredFrameTransformPointer>;
|
||||
|
||||
using Input = glm::vec2;
|
||||
using Output = DeferredFrameTransformPointer;
|
||||
using JobModel = render::Job::ModelIO<GenerateDeferredFrameTransform, Input, Output>;
|
||||
|
||||
GenerateDeferredFrameTransform() {}
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, DeferredFrameTransformPointer& frameTransform);
|
||||
void run(const render::RenderContextPointer& renderContext, const Input& jitter, Output& frameTransform);
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
|
@ -35,6 +35,8 @@ struct DeferredFrameTransform {
|
|||
mat4 _projectionMono;
|
||||
mat4 _viewInverse;
|
||||
mat4 _view;
|
||||
mat4 _projectionUnJittered[2];
|
||||
mat4 _invProjectionUnJittered[2];
|
||||
};
|
||||
|
||||
uniform deferredFrameTransformBuffer {
|
||||
|
@ -62,6 +64,12 @@ mat4 getProjection(int side) {
|
|||
mat4 getProjectionMono() {
|
||||
return frameTransform._projectionMono;
|
||||
}
|
||||
mat4 getUnjitteredProjection(int side) {
|
||||
return frameTransform._projectionUnJittered[side];
|
||||
}
|
||||
mat4 getUnjitteredInvProjection(int side) {
|
||||
return frameTransform._invProjectionUnJittered[side];
|
||||
}
|
||||
|
||||
// positive near distance of the projection
|
||||
float getProjectionNear() {
|
||||
|
@ -138,6 +146,14 @@ vec3 evalEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {
|
|||
return eyePos.xyz / eyePos.w;
|
||||
}
|
||||
|
||||
vec3 evalUnjitteredEyePositionFromZdb(int side, float Zdb, vec2 texcoord) {
|
||||
// compute the view space position using the depth
|
||||
vec3 clipPos;
|
||||
clipPos.xyz = vec3(texcoord.xy, Zdb) * 2.0 - 1.0;
|
||||
vec4 eyePos = frameTransform._invProjectionUnJittered[side] * vec4(clipPos.xyz, 1.0);
|
||||
return eyePos.xyz / eyePos.w;
|
||||
}
|
||||
|
||||
vec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {
|
||||
float Zdb = evalZdbFromZeye(Zeye);
|
||||
return evalEyePositionFromZdb(side, Zdb, texcoord);
|
||||
|
|
|
@ -2207,7 +2207,7 @@ static void buildWebShader(const gpu::ShaderPointer& vertShader, const gpu::Shad
|
|||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
PrepareStencil::testMaskDrawShapeNoAA(*state);
|
||||
|
||||
pipelinePointerOut = gpu::Pipeline::create(shaderPointerOut, state);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
<@if not MODEL_MATERIAL_TEXTURES_SLH@>
|
||||
<@def MODEL_MATERIAL_TEXTURES_SLH@>
|
||||
|
||||
|
||||
<@func declareMaterialTexMapArrayBuffer()@>
|
||||
|
||||
const int MAX_TEXCOORDS = 2;
|
||||
|
@ -48,6 +47,8 @@ TexMapArray getTexMapArray() {
|
|||
|
||||
<@func declareMaterialTextures(withAlbedo, withRoughness, withNormal, withMetallic, withEmissive, withOcclusion, withScattering)@>
|
||||
|
||||
#define TAA_TEXTURE_LOD_BIAS -1.0
|
||||
|
||||
<@include gpu/TextureTable.slh@>
|
||||
|
||||
#ifdef GPU_TEXTURE_TABLE_BINDLESS
|
||||
|
@ -66,6 +67,7 @@ TextureTable(0, matTex);
|
|||
<@if withAlbedo@>
|
||||
#define albedoMap 0
|
||||
vec4 fetchAlbedoMap(vec2 uv) {
|
||||
// Should take into account TAA_TEXTURE_LOD_BIAS?
|
||||
return tableTexValue(matTex, albedoMap, uv);
|
||||
}
|
||||
<@endif@>
|
||||
|
@ -73,6 +75,7 @@ vec4 fetchAlbedoMap(vec2 uv) {
|
|||
<@if withRoughness@>
|
||||
#define roughnessMap 4
|
||||
float fetchRoughnessMap(vec2 uv) {
|
||||
// Should take into account TAA_TEXTURE_LOD_BIAS?
|
||||
return tableTexValue(matTex, roughnessMap, uv).r;
|
||||
}
|
||||
<@endif@>
|
||||
|
@ -80,6 +83,7 @@ float fetchRoughnessMap(vec2 uv) {
|
|||
<@if withNormal@>
|
||||
#define normalMap 1
|
||||
vec3 fetchNormalMap(vec2 uv) {
|
||||
// Should take into account TAA_TEXTURE_LOD_BIAS?
|
||||
return tableTexValue(matTex, normalMap, uv).xyz;
|
||||
}
|
||||
<@endif@>
|
||||
|
@ -87,6 +91,7 @@ vec3 fetchNormalMap(vec2 uv) {
|
|||
<@if withMetallic@>
|
||||
#define metallicMap 2
|
||||
float fetchMetallicMap(vec2 uv) {
|
||||
// Should take into account TAA_TEXTURE_LOD_BIAS?
|
||||
return tableTexValue(matTex, metallicMap, uv).r;
|
||||
}
|
||||
<@endif@>
|
||||
|
@ -94,6 +99,7 @@ float fetchMetallicMap(vec2 uv) {
|
|||
<@if withEmissive@>
|
||||
#define emissiveMap 3
|
||||
vec3 fetchEmissiveMap(vec2 uv) {
|
||||
// Should take into account TAA_TEXTURE_LOD_BIAS?
|
||||
return tableTexValue(matTex, emissiveMap, uv).rgb;
|
||||
}
|
||||
<@endif@>
|
||||
|
@ -119,14 +125,14 @@ float fetchScatteringMap(vec2 uv) {
|
|||
<@if withAlbedo@>
|
||||
uniform sampler2D albedoMap;
|
||||
vec4 fetchAlbedoMap(vec2 uv) {
|
||||
return texture(albedoMap, uv);
|
||||
return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
<@if withRoughness@>
|
||||
uniform sampler2D roughnessMap;
|
||||
float fetchRoughnessMap(vec2 uv) {
|
||||
return (texture(roughnessMap, uv).r);
|
||||
return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
|
@ -134,7 +140,7 @@ float fetchRoughnessMap(vec2 uv) {
|
|||
uniform sampler2D normalMap;
|
||||
vec3 fetchNormalMap(vec2 uv) {
|
||||
// unpack normal, swizzle to get into hifi tangent space with Y axis pointing out
|
||||
vec2 t = 2.0 * (texture(normalMap, uv).rg - vec2(0.5, 0.5));
|
||||
vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));
|
||||
vec2 t2 = t*t;
|
||||
return vec3(t.x, sqrt(1.0 - t2.x - t2.y), t.y);
|
||||
}
|
||||
|
@ -143,14 +149,14 @@ vec3 fetchNormalMap(vec2 uv) {
|
|||
<@if withMetallic@>
|
||||
uniform sampler2D metallicMap;
|
||||
float fetchMetallicMap(vec2 uv) {
|
||||
return (texture(metallicMap, uv).r);
|
||||
return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
<@if withEmissive@>
|
||||
uniform sampler2D emissiveMap;
|
||||
vec3 fetchEmissiveMap(vec2 uv) {
|
||||
return texture(emissiveMap, uv).rgb;
|
||||
return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
|
@ -164,7 +170,7 @@ float fetchOcclusionMap(vec2 uv) {
|
|||
<@if withScattering@>
|
||||
uniform sampler2D scatteringMap;
|
||||
float fetchScatteringMap(vec2 uv) {
|
||||
float scattering = texture(scatteringMap, uv).r; // boolean scattering for now
|
||||
float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now
|
||||
return max(((scattering - 0.1) / 0.9), 0.0);
|
||||
return texture(scatteringMap, uv).r; // boolean scattering for now
|
||||
}
|
||||
|
@ -234,8 +240,8 @@ vec3 fetchLightmapMap(vec2 uv) {
|
|||
vec3 normalizedTangent = normalize(<$interpolatedTangent$>.xyz);
|
||||
vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent);
|
||||
// attenuate the normal map divergence from the mesh normal based on distance
|
||||
// The attenuation range [20,100] meters from the eye is arbitrary for now
|
||||
vec3 localNormal = mix(<$fetchedNormal$>, vec3(0.0, 1.0, 0.0), smoothstep(20.0, 100.0, (-<$fragPosES$>).z));
|
||||
// The attenuation range [30,100] meters from the eye is arbitrary for now
|
||||
vec3 localNormal = mix(<$fetchedNormal$>, vec3(0.0, 1.0, 0.0), smoothstep(30.0, 100.0, (-<$fragPosES$>).z));
|
||||
<$normal$> = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z);
|
||||
}
|
||||
<@endfunc@>
|
||||
|
|
|
@ -46,6 +46,7 @@ void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs&
|
|||
|
||||
const auto& inItems = inputs.get0();
|
||||
const auto& lightingModel = inputs.get1();
|
||||
const auto jitter = inputs.get2();
|
||||
|
||||
config->setNumDrawn((int)inItems.size());
|
||||
emit config->numDrawnChanged();
|
||||
|
@ -75,7 +76,8 @@ void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs&
|
|||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
batch.setProjectionJitter(jitter.x, jitter.y);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
// Setup lighting model for all items;
|
||||
batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer());
|
||||
|
|
|
@ -60,7 +60,7 @@ protected:
|
|||
|
||||
class DrawOverlay3D {
|
||||
public:
|
||||
using Inputs = render::VaryingSet2 <render::ItemBounds, LightingModelPointer>;
|
||||
using Inputs = render::VaryingSet3<render::ItemBounds, LightingModelPointer, glm::vec2>;
|
||||
|
||||
using Config = DrawOverlay3DConfig;
|
||||
using JobModel = render::Job::ModelI<DrawOverlay3D, Inputs, Config>;
|
||||
|
|
|
@ -95,10 +95,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
|
||||
fadeEffect->build(task, opaques);
|
||||
|
||||
task.addJob<JitterSample>("JitterCam");
|
||||
const auto jitter = task.addJob<JitterSample>("JitterCam");
|
||||
|
||||
// Prepare deferred, generate the shared Deferred Frame Transform
|
||||
const auto deferredFrameTransform = task.addJob<GenerateDeferredFrameTransform>("DeferredFrameTransform");
|
||||
const auto deferredFrameTransform = task.addJob<GenerateDeferredFrameTransform>("DeferredFrameTransform", jitter);
|
||||
const auto lightingModel = task.addJob<MakeLightingModel>("LightingModel");
|
||||
|
||||
|
||||
|
@ -116,12 +116,11 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<PrepareStencil>("PrepareStencil", primaryFramebuffer);
|
||||
|
||||
// Render opaque objects in DeferredBuffer
|
||||
const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).asVarying();
|
||||
const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel, jitter).asVarying();
|
||||
task.addJob<DrawStateSortDeferred>("DrawOpaqueDeferred", opaqueInputs, shapePlumber);
|
||||
|
||||
task.addJob<EndGPURangeTimer>("OpaqueRangeTimer", opaqueRangeTimer);
|
||||
|
||||
|
||||
// Opaque all rendered
|
||||
|
||||
// Linear Depth Pass
|
||||
|
@ -188,8 +187,37 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<DebugLightClusters>("DebugLightClusters", debugLightClustersInputs);
|
||||
}
|
||||
|
||||
const auto outlineRangeTimer = task.addJob<BeginGPURangeTimer>("BeginHighlightRangeTimer", "Highlight");
|
||||
// Select items that need to be outlined
|
||||
const auto selectionBaseName = "contextOverlayHighlightList";
|
||||
const auto selectedItems = addSelectItemJobs(task, selectionBaseName, metas, opaques, transparents);
|
||||
|
||||
const auto outlineInputs = DrawHighlightTask::Inputs(items.get0(), deferredFramebuffer, lightingFramebuffer, deferredFrameTransform).asVarying();
|
||||
task.addJob<DrawHighlightTask>("DrawHighlight", outlineInputs);
|
||||
|
||||
task.addJob<EndGPURangeTimer>("HighlightRangeTimer", outlineRangeTimer);
|
||||
|
||||
const auto overlaysInFrontRangeTimer = task.addJob<BeginGPURangeTimer>("BeginOverlaysInFrontRangeTimer", "BeginOverlaysInFrontRangeTimer");
|
||||
|
||||
// Layered Overlays
|
||||
const auto filteredOverlaysOpaque = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredOpaque", overlayOpaques, Item::LAYER_3D_FRONT);
|
||||
const auto filteredOverlaysTransparent = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredTransparent", overlayTransparents, Item::LAYER_3D_FRONT);
|
||||
const auto overlaysInFrontOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(0);
|
||||
const auto overlaysInFrontTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(0);
|
||||
|
||||
const auto overlayInFrontOpaquesInputs = DrawOverlay3D::Inputs(overlaysInFrontOpaque, lightingModel, jitter).asVarying();
|
||||
const auto overlayInFrontTransparentsInputs = DrawOverlay3D::Inputs(overlaysInFrontTransparent, lightingModel, jitter).asVarying();
|
||||
task.addJob<DrawOverlay3D>("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true);
|
||||
task.addJob<DrawOverlay3D>("DrawOverlayInFrontTransparent", overlayInFrontTransparentsInputs, false);
|
||||
|
||||
task.addJob<EndGPURangeTimer>("OverlaysInFrontRangeTimer", overlaysInFrontRangeTimer);
|
||||
|
||||
const auto toneAndPostRangeTimer = task.addJob<BeginGPURangeTimer>("BeginToneAndPostRangeTimer", "PostToneOverlaysAntialiasing");
|
||||
|
||||
// AA job before bloom to limit flickering
|
||||
const auto antialiasingInputs = Antialiasing::Inputs(deferredFrameTransform, lightingFramebuffer, linearDepthTarget, velocityBuffer).asVarying();
|
||||
task.addJob<Antialiasing>("Antialiasing", antialiasingInputs);
|
||||
|
||||
// Add bloom
|
||||
const auto bloomInputs = Bloom::Inputs(deferredFrameTransform, lightingFramebuffer).asVarying();
|
||||
task.addJob<Bloom>("Bloom", bloomInputs);
|
||||
|
@ -198,16 +226,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer).asVarying();
|
||||
task.addJob<ToneMappingDeferred>("ToneMapping", toneMappingInputs);
|
||||
|
||||
const auto outlineRangeTimer = task.addJob<BeginGPURangeTimer>("BeginHighlightRangeTimer", "Highlight");
|
||||
// Select items that need to be outlined
|
||||
const auto selectionBaseName = "contextOverlayHighlightList";
|
||||
const auto selectedItems = addSelectItemJobs(task, selectionBaseName, metas, opaques, transparents);
|
||||
|
||||
const auto outlineInputs = DrawHighlightTask::Inputs(items.get0(), deferredFramebuffer, primaryFramebuffer, deferredFrameTransform).asVarying();
|
||||
task.addJob<DrawHighlightTask>("DrawHighlight", outlineInputs);
|
||||
|
||||
task.addJob<EndGPURangeTimer>("HighlightRangeTimer", outlineRangeTimer);
|
||||
|
||||
{ // Debug the bounds of the rendered items, still look at the zbuffer
|
||||
task.addJob<DrawBounds>("DrawMetaBounds", metas);
|
||||
task.addJob<DrawBounds>("DrawOpaqueBounds", opaques);
|
||||
|
@ -230,26 +248,11 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<DrawBounds>("DrawSelectionBounds", selectedItems);
|
||||
}
|
||||
|
||||
// Layered Overlays
|
||||
const auto filteredOverlaysOpaque = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredOpaque", overlayOpaques, Item::LAYER_3D_FRONT);
|
||||
const auto filteredOverlaysTransparent = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredTransparent", overlayTransparents, Item::LAYER_3D_FRONT);
|
||||
const auto overlaysInFrontOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(0);
|
||||
const auto overlaysInFrontTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(0);
|
||||
|
||||
const auto overlayInFrontOpaquesInputs = DrawOverlay3D::Inputs(overlaysInFrontOpaque, lightingModel).asVarying();
|
||||
const auto overlayInFrontTransparentsInputs = DrawOverlay3D::Inputs(overlaysInFrontTransparent, lightingModel).asVarying();
|
||||
task.addJob<DrawOverlay3D>("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true);
|
||||
task.addJob<DrawOverlay3D>("DrawOverlayInFrontTransparent", overlayInFrontTransparentsInputs, false);
|
||||
|
||||
{ // Debug the bounds of the rendered Overlay items that are marked drawInFront, still look at the zbuffer
|
||||
task.addJob<DrawBounds>("DrawOverlayInFrontOpaqueBounds", overlaysInFrontOpaque);
|
||||
task.addJob<DrawBounds>("DrawOverlayInFrontTransparentBounds", overlaysInFrontTransparent);
|
||||
}
|
||||
|
||||
// AA job
|
||||
const auto antialiasingInputs = Antialiasing::Inputs(deferredFrameTransform, primaryFramebuffer, linearDepthTarget, velocityBuffer).asVarying();
|
||||
task.addJob<Antialiasing>("Antialiasing", antialiasingInputs);
|
||||
|
||||
// Debugging stages
|
||||
{
|
||||
// Debugging Deferred buffer job
|
||||
|
@ -285,9 +288,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
|
||||
const auto overlaysHUDOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(1);
|
||||
const auto overlaysHUDTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(1);
|
||||
const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f));
|
||||
|
||||
const auto overlayHUDOpaquesInputs = DrawOverlay3D::Inputs(overlaysHUDOpaque, lightingModel).asVarying();
|
||||
const auto overlayHUDTransparentsInputs = DrawOverlay3D::Inputs(overlaysHUDTransparent, lightingModel).asVarying();
|
||||
const auto overlayHUDOpaquesInputs = DrawOverlay3D::Inputs(overlaysHUDOpaque, lightingModel, nullJitter).asVarying();
|
||||
const auto overlayHUDTransparentsInputs = DrawOverlay3D::Inputs(overlaysHUDTransparent, lightingModel, nullJitter).asVarying();
|
||||
task.addJob<DrawOverlay3D>("DrawOverlayHUDOpaque", overlayHUDOpaquesInputs, true);
|
||||
task.addJob<DrawOverlay3D>("DrawOverlayHUDTransparent", overlayHUDTransparentsInputs, false);
|
||||
|
||||
|
@ -379,6 +383,7 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const
|
|||
|
||||
const auto& inItems = inputs.get0();
|
||||
const auto& lightingModel = inputs.get1();
|
||||
const auto jitter = inputs.get2();
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
|
@ -395,6 +400,7 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const
|
|||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setProjectionJitter(jitter.x, jitter.y);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
// Setup lighting model for all items;
|
||||
|
|
|
@ -81,7 +81,7 @@ protected:
|
|||
|
||||
class DrawStateSortDeferred {
|
||||
public:
|
||||
using Inputs = render::VaryingSet2<render::ItemBounds, LightingModelPointer>;
|
||||
using Inputs = render::VaryingSet3<render::ItemBounds, LightingModelPointer, glm::vec2>;
|
||||
|
||||
using Config = DrawStateSortConfig;
|
||||
using JobModel = render::Job::ModelI<DrawStateSortDeferred, Inputs, Config>;
|
||||
|
|
|
@ -35,6 +35,9 @@ void main(void) {
|
|||
pixels[7] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(0,1), 0);
|
||||
pixels[8] = texelFetch(colorTexture, ivec2(gl_FragCoord.xy)+ivec2(1,1), 0);
|
||||
|
||||
sharpenedPixel = pixels[4]*7.8 - (pixels[1]+pixels[3]+pixels[5]+pixels[7]) - (pixels[0]+pixels[2]+pixels[6]+pixels[8])*0.7;
|
||||
outFragColor = mix(pixels[4], sharpenedPixel, sharpenIntensity);
|
||||
sharpenedPixel = pixels[4]*6.8 - (pixels[1]+pixels[3]+pixels[5]+pixels[7]) - (pixels[0]+pixels[2]+pixels[6]+pixels[8])*0.7;
|
||||
|
||||
vec4 minColor = max(vec4(0), pixels[4]-vec4(0.5));
|
||||
vec4 maxColor = pixels[4]+vec4(0.5);
|
||||
outFragColor = clamp(pixels[4] + sharpenedPixel * sharpenIntensity, minColor, maxColor);
|
||||
}
|
||||
|
|
|
@ -20,14 +20,15 @@ uniform vec4 Color;
|
|||
in vec3 _normalWS;
|
||||
in vec2 _texCoord0;
|
||||
|
||||
const float gamma = 2.2;
|
||||
const float smoothing = 32.0;
|
||||
#define TAA_TEXTURE_LOD_BIAS -3.0
|
||||
|
||||
const float interiorCutoff = 0.8;
|
||||
const float outlineExpansion = 0.2;
|
||||
const float taaBias = pow(2.0, TAA_TEXTURE_LOD_BIAS);
|
||||
|
||||
void main() {
|
||||
float evalSDF(vec2 texCoord) {
|
||||
// retrieve signed distance
|
||||
float sdf = texture(Font, _texCoord0).g;
|
||||
float sdf = textureLod(Font, texCoord, TAA_TEXTURE_LOD_BIAS).g;
|
||||
if (Outline) {
|
||||
if (sdf > interiorCutoff) {
|
||||
sdf = 1.0 - sdf;
|
||||
|
@ -35,12 +36,22 @@ void main() {
|
|||
sdf += outlineExpansion;
|
||||
}
|
||||
}
|
||||
// perform adaptive anti-aliasing of the edges
|
||||
// The larger we're rendering, the less anti-aliasing we need
|
||||
float s = smoothing * length(fwidth(_texCoord0));
|
||||
float w = clamp(s, 0.0, 0.5);
|
||||
float a = smoothstep(0.5 - w, 0.5 + w, sdf);
|
||||
|
||||
// Rely on TAA for anti-aliasing
|
||||
return step(0.5, sdf);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 dxTexCoord = dFdx(_texCoord0) * 0.5 * taaBias;
|
||||
vec2 dyTexCoord = dFdy(_texCoord0) * 0.5 * taaBias;
|
||||
|
||||
// Perform 4x supersampling for anisotropic filtering
|
||||
float a;
|
||||
a = evalSDF(_texCoord0);
|
||||
a += evalSDF(_texCoord0+dxTexCoord);
|
||||
a += evalSDF(_texCoord0+dyTexCoord);
|
||||
a += evalSDF(_texCoord0+dxTexCoord+dyTexCoord);
|
||||
a *= 0.25;
|
||||
|
||||
// discard if invisible
|
||||
if (a < 0.01) {
|
||||
discard;
|
||||
|
|
|
@ -76,47 +76,39 @@ vec2 taa_getRegionFXAA() {
|
|||
#define USE_YCOCG 1
|
||||
|
||||
vec4 taa_fetchColor(sampler2D map, vec2 uv) {
|
||||
vec4 c = texture(map, uv);
|
||||
// Apply rapid pseudo tonemapping as TAA is applied to a tonemapped image, using luminance as weight, as proposed in
|
||||
// https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf
|
||||
float lum = dot(vec3(0.3,0.5,0.2),c.rgb);
|
||||
c.rgb = c.rgb / (1.0+lum);
|
||||
#if USE_YCOCG
|
||||
vec4 c = texture(map, uv);
|
||||
return vec4(color_LinearToYCoCg(c.rgb), c.a);
|
||||
return vec4(color_LinearToYCoCg(c.rgb), c.a);
|
||||
#else
|
||||
return texture(map, uv);
|
||||
return c;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec3 taa_resolveColor(vec3 color) {
|
||||
#if USE_YCOCG
|
||||
return color_YCoCgToLinear(color);
|
||||
#else
|
||||
return color;
|
||||
color = max(vec3(0), color_YCoCgToUnclampedLinear(color));
|
||||
#endif
|
||||
// Apply rapid inverse tonemapping, using luminance as weight, as proposed in
|
||||
// https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf
|
||||
float lum = dot(vec3(0.3,0.5,0.2),color.rgb);
|
||||
color = color / (1.0-lum);
|
||||
return color;
|
||||
}
|
||||
|
||||
vec4 taa_fetchSourceMap(vec2 uv) {
|
||||
#if USE_YCOCG
|
||||
vec4 c = texture(sourceMap, uv);
|
||||
return vec4(color_LinearToYCoCg(c.rgb), c.a);
|
||||
#else
|
||||
return texture(sourceMap, uv);
|
||||
#endif
|
||||
return taa_fetchColor(sourceMap, uv);
|
||||
}
|
||||
|
||||
vec4 taa_fetchHistoryMap(vec2 uv) {
|
||||
#if USE_YCOCG
|
||||
vec4 c = texture(historyMap, uv);
|
||||
return vec4(color_LinearToYCoCg(c.rgb), c.a);
|
||||
#else
|
||||
return texture(historyMap, uv);
|
||||
#endif
|
||||
return taa_fetchColor(historyMap, uv);
|
||||
}
|
||||
|
||||
vec4 taa_fetchNextMap(vec2 uv) {
|
||||
#if USE_YCOCG
|
||||
vec4 c = texture(nextMap, uv);
|
||||
return vec4(color_LinearToYCoCg(c.rgb), c.a);
|
||||
#else
|
||||
return texture(nextMap, uv);
|
||||
#endif
|
||||
return taa_fetchColor(nextMap, uv);
|
||||
}
|
||||
|
||||
vec2 taa_fetchVelocityMap(vec2 uv) {
|
||||
|
|
|
@ -28,11 +28,11 @@ void main(void) {
|
|||
float Zdb = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;
|
||||
|
||||
// The position of the pixel fragment in Eye space then in world space
|
||||
vec3 eyePos = evalEyePositionFromZdb(stereoSide.x, Zdb, texcoordPos);
|
||||
vec3 eyePos = evalUnjitteredEyePositionFromZdb(stereoSide.x, Zdb, texcoordPos);
|
||||
vec3 worldPos = (getViewInverse() * vec4(eyePos, 1.0)).xyz;
|
||||
|
||||
vec3 prevEyePos = (getPreviousView() * vec4(worldPos, 1.0)).xyz;
|
||||
vec4 prevClipPos = (frameTransform._projection[stereoSide.x] * vec4(prevEyePos, 1.0));
|
||||
vec4 prevClipPos = (getUnjitteredProjection(stereoSide.x) * vec4(prevEyePos, 1.0));
|
||||
vec2 prevUV = 0.5 * (prevClipPos.xy / prevClipPos.w) + vec2(0.5);
|
||||
|
||||
//vec2 imageSize = getWidthHeight(0);
|
||||
|
|
|
@ -163,7 +163,7 @@ bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFra
|
|||
//if (sourceFramebuffer->hasDepthStencil()) {
|
||||
// _blurredFramebuffer->setDepthStencilBuffer(sourceFramebuffer->getDepthStencilBuffer(), sourceFramebuffer->getDepthStencilBufferFormat());
|
||||
//}
|
||||
auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT);
|
||||
auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT, gpu::Sampler::WRAP_CLAMP);
|
||||
auto blurringTarget = gpu::Texture::createRenderBuffer(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), blurBufferSize.x, blurBufferSize.y, gpu::Texture::SINGLE_MIP, blurringSampler);
|
||||
_blurredFramebuffer->setRenderBuffer(0, blurringTarget);
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFra
|
|||
/* if (sourceFramebuffer->hasDepthStencil()) {
|
||||
_outputFramebuffer->setDepthStencilBuffer(sourceFramebuffer->getDepthStencilBuffer(), sourceFramebuffer->getDepthStencilBufferFormat());
|
||||
}*/
|
||||
auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT);
|
||||
auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT, gpu::Sampler::WRAP_CLAMP);
|
||||
auto blurringTarget = gpu::Texture::createRenderBuffer(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), blurBufferSize.x, blurBufferSize.y, gpu::Texture::SINGLE_MIP, blurringSampler);
|
||||
_outputFramebuffer->setRenderBuffer(0, blurringTarget);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <QtNetwork/QNetworkDiskCache>
|
||||
|
||||
/**jsdoc
|
||||
* The Assets API allows you to communicate with the Asset Browser
|
||||
* @namespace Assets
|
||||
*/
|
||||
class AssetScriptingInterface : public BaseAssetScriptingInterface, QScriptable {
|
||||
|
@ -53,8 +54,7 @@ public:
|
|||
/**jsdoc
|
||||
* Download data from the connected domain's asset server.
|
||||
* @function Assets.downloadData
|
||||
* @static
|
||||
* @param url {string} url of asset to download, must be atp scheme url.
|
||||
* @param url {string} URL of asset to download, must be ATP scheme URL.
|
||||
* @param callback {Assets~downloadDataCallback}
|
||||
*/
|
||||
|
||||
|
@ -69,7 +69,6 @@ public:
|
|||
/**jsdoc
|
||||
* Sets up a path to hash mapping within the connected domain's asset server
|
||||
* @function Assets.setMapping
|
||||
* @static
|
||||
* @param path {string}
|
||||
* @param hash {string}
|
||||
* @param callback {Assets~setMappingCallback}
|
||||
|
@ -80,12 +79,12 @@ public:
|
|||
* @callback Assets~setMappingCallback
|
||||
* @param {string} error
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void setMapping(QString path, QString hash, QScriptValue callback);
|
||||
|
||||
/**jsdoc
|
||||
* Look up a path to hash mapping within the connected domain's asset server
|
||||
* @function Assets.getMapping
|
||||
* @static
|
||||
* @param path {string}
|
||||
* @param callback {Assets~getMappingCallback}
|
||||
*/
|
||||
|
@ -93,11 +92,26 @@ public:
|
|||
/**jsdoc
|
||||
* Called when getMapping is complete.
|
||||
* @callback Assets~getMappingCallback
|
||||
* @param error {string} error description if the path could not be resolved; otherwise a null value.
|
||||
* @param assetID {string} hash value if found, else an empty string
|
||||
* @param error {string} error description if the path could not be resolved; otherwise a null value.
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Called when getMapping is complete.
|
||||
* @callback Assets~getMappingCallback
|
||||
* @param assetID {string} hash value if found, else an empty string
|
||||
* @param error {string} error description if the path could not be resolved; otherwise a null value.
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void getMapping(QString path, QScriptValue callback);
|
||||
|
||||
/**jsdoc
|
||||
* @function Assets.setBakingEnabled
|
||||
* @param path {string}
|
||||
* @param enabled {boolean}
|
||||
* @param callback {}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void setBakingEnabled(QString path, bool enabled, QScriptValue callback);
|
||||
|
||||
#if (PR_BUILD || DEV_BUILD)
|
||||
|
@ -110,31 +124,35 @@ public:
|
|||
* @param {URL|Assets.GetOptions} options An atp: style URL, hash, or relative mapped path; or an {@link Assets.GetOptions} object with request parameters
|
||||
* @param {Assets~getAssetCallback} scope[callback] A scope callback function to receive (error, results) values
|
||||
*/
|
||||
/**jsdoc
|
||||
* A set of properties that can be passed to {@link Assets.getAsset}.
|
||||
* @typedef {Object} Assets.GetOptions
|
||||
* @property {URL} [url] an "atp:" style URL, hash, or relative mapped path to fetch
|
||||
* @property {string} [responseType=text] the desired reponse type (text | arraybuffer | json)
|
||||
* @property {boolean} [decompress=false] whether to attempt gunzip decompression on the fetched data
|
||||
* See: {@link Assets.putAsset} and its .compress=true option
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* A set of properties that can be passed to {@link Assets.getAsset}.
|
||||
* @typedef {Object} Assets.GetOptions
|
||||
* @property {URL} [url] an "atp:" style URL, hash, or relative mapped path to fetch
|
||||
* @property {string} [responseType=text] the desired reponse type (text | arraybuffer | json)
|
||||
* @property {boolean} [decompress=false] whether to attempt gunzip decompression on the fetched data
|
||||
* See: {@link Assets.putAsset} and its .compress=true option
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Called when Assets.getAsset is complete.
|
||||
* @callback Assets~getAssetCallback
|
||||
* @param {string} error - contains error message or null value if no error occured fetching the asset
|
||||
* @param {Asset~getAssetResult} result - result object containing, on success containing asset metadata and contents
|
||||
*/
|
||||
/**jsdoc
|
||||
* Result value returned by {@link Assets.getAsset}.
|
||||
* @typedef {Object} Assets~getAssetResult
|
||||
* @property {url} [url] the resolved "atp:" style URL for the fetched asset
|
||||
* @property {string} [hash] the resolved hash for the fetched asset
|
||||
* @property {string|ArrayBuffer|Object} [response] response data (possibly converted per .responseType value)
|
||||
* @property {string} [responseType] response type (text | arraybuffer | json)
|
||||
* @property {string} [contentType] detected asset mime-type (autodetected)
|
||||
* @property {number} [byteLength] response data size in bytes
|
||||
* @property {number} [decompressed] flag indicating whether data was decompressed
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Result value returned by {@link Assets.getAsset}.
|
||||
* @typedef {Object} Assets~getAssetResult
|
||||
* @property {url} [url] the resolved "atp:" style URL for the fetched asset
|
||||
* @property {string} [hash] the resolved hash for the fetched asset
|
||||
* @property {string|ArrayBuffer|Object} [response] response data (possibly converted per .responseType value)
|
||||
* @property {string} [responseType] response type (text | arraybuffer | json)
|
||||
* @property {string} [contentType] detected asset mime-type (autodetected)
|
||||
* @property {number} [byteLength] response data size in bytes
|
||||
* @property {number} [decompressed] flag indicating whether data was decompressed
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void getAsset(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||
|
||||
/**jsdoc
|
||||
|
@ -143,46 +161,131 @@ public:
|
|||
* @param {Assets.PutOptions} options A PutOptions object with upload parameters
|
||||
* @param {Assets~putAssetCallback} scope[callback] A scoped callback function invoked with (error, results)
|
||||
*/
|
||||
/**jsdoc
|
||||
* A set of properties that can be passed to {@link Assets.putAsset}.
|
||||
* @typedef {Object} Assets.PutOptions
|
||||
* @property {ArrayBuffer|string} [data] byte buffer or string value representing the new asset's content
|
||||
* @property {string} [path=null] ATP path mapping to automatically create (upon successful upload to hash)
|
||||
* @property {boolean} [compress=false] whether to gzip compress data before uploading
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* A set of properties that can be passed to {@link Assets.putAsset}.
|
||||
* @typedef {Object} Assets.PutOptions
|
||||
* @property {ArrayBuffer|string} [data] byte buffer or string value representing the new asset's content
|
||||
* @property {string} [path=null] ATP path mapping to automatically create (upon successful upload to hash)
|
||||
* @property {boolean} [compress=false] whether to gzip compress data before uploading
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Called when Assets.putAsset is complete.
|
||||
* @callback Assets~puttAssetCallback
|
||||
* @param {string} error - contains error message (or null value if no error occured while uploading/mapping the new asset)
|
||||
* @param {Asset~putAssetResult} result - result object containing error or result status of asset upload
|
||||
*/
|
||||
/**jsdoc
|
||||
* Result value returned by {@link Assets.putAsset}.
|
||||
* @typedef {Object} Assets~putAssetResult
|
||||
* @property {url} [url] the resolved "atp:" style URL for the uploaded asset (based on .path if specified, otherwise on the resulting ATP hash)
|
||||
* @property {string} [path] the uploaded asset's resulting ATP path (or undefined if no path mapping was assigned)
|
||||
* @property {string} [hash] the uploaded asset's resulting ATP hash
|
||||
* @property {boolean} [compressed] flag indicating whether the data was compressed before upload
|
||||
* @property {number} [byteLength] flag indicating final byte size of the data uploaded to the ATP server
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* Result value returned by {@link Assets.putAsset}.
|
||||
* @typedef {Object} Assets~putAssetResult
|
||||
* @property {url} [url] the resolved "atp:" style URL for the uploaded asset (based on .path if specified, otherwise on the resulting ATP hash)
|
||||
* @property {string} [path] the uploaded asset's resulting ATP path (or undefined if no path mapping was assigned)
|
||||
* @property {string} [hash] the uploaded asset's resulting ATP hash
|
||||
* @property {boolean} [compressed] flag indicating whether the data was compressed before upload
|
||||
* @property {number} [byteLength] flag indicating final byte size of the data uploaded to the ATP server
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void putAsset(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||
|
||||
/**jsdoc
|
||||
* @function Assets.deleteAsset
|
||||
* @property {} options
|
||||
* @property {} scope
|
||||
* @property {} [callback = ""]
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void deleteAsset(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||
|
||||
/**jsdoc
|
||||
* @function Assets.resolveAsset
|
||||
* @property {} options
|
||||
* @property {} scope
|
||||
* @property {} [callback = ""]
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void resolveAsset(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||
|
||||
/**jsdoc
|
||||
* @function Assets.decompressData
|
||||
* @property {} options
|
||||
* @property {} scope
|
||||
* @property {} [callback = ""]
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void decompressData(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||
|
||||
/**jsdoc
|
||||
* @function Assets.compressData
|
||||
* @property {} options
|
||||
* @property {} scope
|
||||
* @property {} [callback = ""]
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void compressData(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||
|
||||
/**jsdoc
|
||||
* @function Assets.initializeCache
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE bool initializeCache() { return Parent::initializeCache(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Assets.canWriteCacheValue
|
||||
* @property {string} url
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
Q_INVOKABLE bool canWriteCacheValue(const QUrl& url);
|
||||
|
||||
/**jsdoc
|
||||
* @function Assets.getCacheStatus
|
||||
* @property {} scope
|
||||
* @property {} [callback = ""]
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void getCacheStatus(QScriptValue scope, QScriptValue callback = QScriptValue()) {
|
||||
jsPromiseReady(Parent::getCacheStatus(), scope, callback);
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* @function Assets.queryCacheMeta
|
||||
* @property {} options
|
||||
* @property {} scope
|
||||
* @property {} [callback = ""]
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void queryCacheMeta(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||
|
||||
/**jsdoc
|
||||
* @function Assets.loadFromCache
|
||||
* @property {} options
|
||||
* @property {} scope
|
||||
* @property {} [callback = ""]
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void loadFromCache(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||
|
||||
/**jsdoc
|
||||
* @function Assets.saveToCache
|
||||
* @property {} options
|
||||
* @property {} scope
|
||||
* @property {} [callback = ""]
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void saveToCache(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||
|
||||
/**jsdoc
|
||||
* @function Assets.saveToCache
|
||||
* @property {} url
|
||||
* @property {} data
|
||||
* @property {} metadata
|
||||
* @property {} scope
|
||||
* @property {} [callback = ""]
|
||||
*/
|
||||
|
||||
Q_INVOKABLE void saveToCache(const QUrl& url, const QByteArray& data, const QVariantMap& metadata,
|
||||
QScriptValue scope, QScriptValue callback = QScriptValue());
|
||||
protected:
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
class QScriptEngine;
|
||||
class QScriptValue;
|
||||
|
||||
/**jsdoc
|
||||
* @namespace Recording
|
||||
*/
|
||||
class RecordingScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -32,43 +35,196 @@ public:
|
|||
void setScriptEngine(QSharedPointer<BaseScriptEngine> scriptEngine) { _scriptEngine = scriptEngine; }
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.loadRecording
|
||||
* @param {string} url
|
||||
* @param {Recording~loadRecordingCallback} [callback=null]
|
||||
*/
|
||||
/**jsdoc
|
||||
* Called when {@link Recording.loadRecording} is complete.
|
||||
* @callback Recording~loadRecordingCallback
|
||||
* @param {boolean} success
|
||||
* @param {string} url
|
||||
*/
|
||||
void loadRecording(const QString& url, QScriptValue callback = QScriptValue());
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.startPlaying
|
||||
*/
|
||||
void startPlaying();
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.pausePlayer
|
||||
*/
|
||||
void pausePlayer();
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.stopPlaying
|
||||
*/
|
||||
void stopPlaying();
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.isPlaying
|
||||
* @returns {boolean}
|
||||
*/
|
||||
bool isPlaying() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.isPaused
|
||||
* @returns {boolean}
|
||||
*/
|
||||
bool isPaused() const;
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.playerElapsed
|
||||
* @returns {number}
|
||||
*/
|
||||
float playerElapsed() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.playerLength
|
||||
* @returns {number}
|
||||
*/
|
||||
float playerLength() const;
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.setPlayerVolume
|
||||
* @param {number} volume
|
||||
*/
|
||||
void setPlayerVolume(float volume);
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.setPlayerAudioOffset
|
||||
* @param {number} audioOffset
|
||||
*/
|
||||
void setPlayerAudioOffset(float audioOffset);
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.setPlayerTime
|
||||
* @param {number} time
|
||||
*/
|
||||
void setPlayerTime(float time);
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.setPlayerLoop
|
||||
* @param {boolean} loop
|
||||
*/
|
||||
void setPlayerLoop(bool loop);
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.setPlayerUseDisplayName
|
||||
* @param {boolean} useDisplayName
|
||||
*/
|
||||
void setPlayerUseDisplayName(bool useDisplayName);
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.setPlayerUseAttachments
|
||||
* @param {boolean} useAttachments
|
||||
*/
|
||||
void setPlayerUseAttachments(bool useAttachments);
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.setPlayerUseHeadModel
|
||||
* @param {boolean} useHeadModel
|
||||
* @todo <strong>Note:</strong> This function currently has no effect.
|
||||
*/
|
||||
void setPlayerUseHeadModel(bool useHeadModel);
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.setPlayerUseSkeletonModel
|
||||
* @param {boolean} useSkeletonModel
|
||||
* @todo <strong>Note:</strong> This function currently doesn't work.
|
||||
*/
|
||||
void setPlayerUseSkeletonModel(bool useSkeletonModel);
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.setPlayFromCurrentLocation
|
||||
* @param {boolean} playFromCurrentLocation
|
||||
*/
|
||||
void setPlayFromCurrentLocation(bool playFromCurrentLocation);
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.getPlayerUseDisplayName
|
||||
* @returns {boolean}
|
||||
*/
|
||||
bool getPlayerUseDisplayName() { return _useDisplayName; }
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.getPlayerUseAttachments
|
||||
* @returns {boolean}
|
||||
*/
|
||||
bool getPlayerUseAttachments() { return _useAttachments; }
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.getPlayerUseHeadModel
|
||||
* @returns {boolean}
|
||||
*/
|
||||
bool getPlayerUseHeadModel() { return _useHeadModel; }
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.getPlayerUseSkeletonModel
|
||||
* @returns {boolean}
|
||||
*/
|
||||
bool getPlayerUseSkeletonModel() { return _useSkeletonModel; }
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.getPlayFromCurrentLocation
|
||||
* @returns {boolean}
|
||||
*/
|
||||
bool getPlayFromCurrentLocation() { return _playFromCurrentLocation; }
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.startRecording
|
||||
*/
|
||||
void startRecording();
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.stopRecording
|
||||
*/
|
||||
void stopRecording();
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.isRecording
|
||||
* @returns {boolean}
|
||||
*/
|
||||
bool isRecording() const;
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.recorderElapsed
|
||||
* @returns {number}
|
||||
*/
|
||||
float recorderElapsed() const;
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.getDefaultRecordingSaveDirectory
|
||||
* @returns {string}
|
||||
*/
|
||||
QString getDefaultRecordingSaveDirectory();
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.saveRecording
|
||||
* @param {string} filename
|
||||
*/
|
||||
void saveRecording(const QString& filename);
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.saveRecordingToAsset
|
||||
* @param {function} getClipAtpUrl
|
||||
*/
|
||||
bool saveRecordingToAsset(QScriptValue getClipAtpUrl);
|
||||
|
||||
/**jsdoc
|
||||
* @function Recording.loadLastRecording
|
||||
*/
|
||||
void loadLastRecording();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -19,6 +19,13 @@
|
|||
|
||||
// TODO: if QT moc ever supports nested classes, subclass these to the interface instead of namespacing
|
||||
namespace SceneScripting {
|
||||
|
||||
/**jsdoc
|
||||
* @typedef Scene.Stage.Location
|
||||
* @property {number} longitude
|
||||
* @property {number} latitude
|
||||
* @property {number} altitude
|
||||
*/
|
||||
class Location : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -41,6 +48,11 @@ namespace SceneScripting {
|
|||
};
|
||||
using LocationPointer = std::unique_ptr<Location>;
|
||||
|
||||
/**jsdoc
|
||||
* @typedef Scene.Stage.Time
|
||||
* @property {number} hour
|
||||
* @property {number} day
|
||||
*/
|
||||
class Time : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -60,6 +72,13 @@ namespace SceneScripting {
|
|||
};
|
||||
using TimePointer = std::unique_ptr<Time>;
|
||||
|
||||
/**jsdoc
|
||||
* @typedef Scene.Stage.KeyLight
|
||||
* @property {Vec3} color
|
||||
* @property {number} intensity
|
||||
* @property {number} ambientIntensity
|
||||
* @property {Vec3} direction
|
||||
*/
|
||||
class KeyLight : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -91,6 +110,14 @@ namespace SceneScripting {
|
|||
};
|
||||
using KeyLightPointer = std::unique_ptr<KeyLight>;
|
||||
|
||||
/**jsdoc
|
||||
* @class Scene.Stage
|
||||
* @property {string} backgroundMode
|
||||
* @property {Scene.Stage.KeyLight} keyLight
|
||||
* @property {Scene.Stage.Location} location
|
||||
* @property {boolean} sunModel
|
||||
* @property {Scene.Stage.Time} time
|
||||
*/
|
||||
class Stage : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -99,10 +126,22 @@ namespace SceneScripting {
|
|||
: _skyStage{ skyStage },
|
||||
_location{ new Location{ skyStage } }, _time{ new Time{ skyStage } }, _keyLight{ new KeyLight{ skyStage } }{}
|
||||
|
||||
/**jsdoc
|
||||
* @function Scene.Stage.setOrientation
|
||||
* @param {Quat} orientation
|
||||
*/
|
||||
Q_INVOKABLE void setOrientation(const glm::quat& orientation) const;
|
||||
|
||||
Q_PROPERTY(Location* location READ getLocation)
|
||||
|
||||
Location* getLocation() const { return _location.get(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Scene.Stage.setLocation
|
||||
* @param {number} longitude
|
||||
* @param {number} latitude
|
||||
* @param {number} altitude
|
||||
*/
|
||||
Q_INVOKABLE void setLocation(float longitude, float latitude, float altitude);
|
||||
|
||||
Q_PROPERTY(Time* time READ getTime)
|
||||
|
@ -130,10 +169,15 @@ namespace SceneScripting {
|
|||
using StagePointer = std::unique_ptr<Stage>;
|
||||
};
|
||||
|
||||
/**jsdoc
|
||||
* @namespace Scene
|
||||
* @property {boolean} shouldRenderAvatars
|
||||
* @property {boolean} shouldRenderEntities
|
||||
* @property {Scene.Stage} stage
|
||||
*/
|
||||
class SceneScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
|
||||
public:
|
||||
Q_PROPERTY(bool shouldRenderAvatars READ shouldRenderAvatars WRITE setShouldRenderAvatars)
|
||||
|
@ -149,7 +193,19 @@ public:
|
|||
graphics::SunSkyStagePointer getSkyStage() const;
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function Scene.shouldRenderAvatarsChanged
|
||||
* @param {boolean} shouldRenderAvatars
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void shouldRenderAvatarsChanged(bool shouldRenderAvatars);
|
||||
|
||||
/**jsdoc
|
||||
* @function Scene.shouldRenderEntitiesChanged
|
||||
* @param {boolean} shouldRenderEntities
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void shouldRenderEntitiesChanged(bool shouldRenderEntities);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -87,6 +87,10 @@ public:
|
|||
QUrl definingSandboxURL { QUrl("about:EntityScript") };
|
||||
};
|
||||
|
||||
/**jsdoc
|
||||
* @namespace Script
|
||||
* @property {string} context
|
||||
*/
|
||||
class ScriptEngine : public BaseScriptEngine, public EntitiesScriptEngineProvider {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString context READ getContext)
|
||||
|
@ -115,6 +119,11 @@ public:
|
|||
|
||||
QString getFilename() const;
|
||||
|
||||
/**jsdoc
|
||||
* Stop the current script.
|
||||
* @function Script.stop
|
||||
* @param {boolean} [marshal=false]
|
||||
*/
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE - this is intended to be a public interface for Agent scripts, and local scripts, but not for EntityScripts
|
||||
Q_INVOKABLE void stop(bool marshal = false);
|
||||
|
@ -126,26 +135,69 @@ public:
|
|||
// NOTE - these are NOT intended to be public interfaces available to scripts, the are only Q_INVOKABLE so we can
|
||||
// properly ensure they are only called on the correct thread
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.registerGlobalObject
|
||||
* @param {string} name
|
||||
* @param {object} object
|
||||
*/
|
||||
/// registers a global object by name
|
||||
Q_INVOKABLE void registerGlobalObject(const QString& name, QObject* object);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.registerGetterSetter
|
||||
* @param {string} name
|
||||
* @param {object} getter
|
||||
* @param {object} setter
|
||||
* @param {string} [parent=""]
|
||||
*/
|
||||
/// registers a global getter/setter
|
||||
Q_INVOKABLE void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
|
||||
QScriptEngine::FunctionSignature setter, const QString& parent = QString(""));
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.registerFunction
|
||||
* @param {string} name
|
||||
* @param {object} function
|
||||
* @param {number} [numArguments=-1]
|
||||
*/
|
||||
/// register a global function
|
||||
Q_INVOKABLE void registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.registerFunction
|
||||
* @param {string} parent
|
||||
* @param {string} name
|
||||
* @param {object} function
|
||||
* @param {number} [numArguments=-1]
|
||||
*/
|
||||
/// register a function as a method on a previously registered global object
|
||||
Q_INVOKABLE void registerFunction(const QString& parent, const QString& name, QScriptEngine::FunctionSignature fun,
|
||||
int numArguments = -1);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.registerValue
|
||||
* @param {string} name
|
||||
* @param {object} value
|
||||
*/
|
||||
/// registers a global object by name
|
||||
Q_INVOKABLE void registerValue(const QString& valueName, QScriptValue value);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.evaluate
|
||||
* @param {string} program
|
||||
* @param {string} filename
|
||||
* @param {number} [lineNumber=-1]
|
||||
* @returns {object}
|
||||
*/
|
||||
/// evaluate some code in the context of the ScriptEngine and return the result
|
||||
Q_INVOKABLE QScriptValue evaluate(const QString& program, const QString& fileName, int lineNumber = 1); // this is also used by the script tool widget
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.evaluateInClosure
|
||||
* @param {object} locals
|
||||
* @param {object} program
|
||||
* @returns {object}
|
||||
*/
|
||||
Q_INVOKABLE QScriptValue evaluateInClosure(const QScriptValue& locals, const QScriptProgram& program);
|
||||
|
||||
/// if the script engine is not already running, this will download the URL and start the process of seting it up
|
||||
|
@ -154,24 +206,122 @@ public:
|
|||
void loadURL(const QUrl& scriptURL, bool reload);
|
||||
bool hasValidScriptSuffix(const QString& scriptFileName);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.getContext
|
||||
* @returns {string}
|
||||
*/
|
||||
Q_INVOKABLE QString getContext() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.isClientScript
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool isClientScript() const { return _context == CLIENT_SCRIPT; }
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.isEntityClientScript
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool isEntityClientScript() const { return _context == ENTITY_CLIENT_SCRIPT; }
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.isEntityServerScript
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool isEntityServerScript() const { return _context == ENTITY_SERVER_SCRIPT; }
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.isAgentScript
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool isAgentScript() const { return _context == AGENT_SCRIPT; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE - these are intended to be public interfaces available to scripts
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.addEventHandler
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} eventName
|
||||
* @param {function} handler
|
||||
*/
|
||||
Q_INVOKABLE void addEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.removeEventHandler
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} eventName
|
||||
* @param {function} handler
|
||||
*/
|
||||
Q_INVOKABLE void removeEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler);
|
||||
|
||||
/**jsdoc
|
||||
* Start a new Interface or entity script.
|
||||
* @function Script.load
|
||||
* @param {string} filename - The URL of the script to load. Can be relative to the current script.
|
||||
* @example <caption>Load a script from another script.</caption>
|
||||
* // First file: scriptA.js
|
||||
* print("This is script A");
|
||||
*
|
||||
* // Second file: scriptB.js
|
||||
* print("This is script B");
|
||||
* Script.load("scriptA.js");
|
||||
*
|
||||
* // If you run scriptB.js you should see both scripts in the running scripts list.
|
||||
* // And you should see the following output:
|
||||
* // This is script B
|
||||
* // This is script A
|
||||
*/
|
||||
Q_INVOKABLE void load(const QString& loadfile);
|
||||
|
||||
/**jsdoc
|
||||
* Include JavaScript from other files in the current script. If a callback is specified the files are loaded and included
|
||||
* asynchronously, otherwise they are included synchronously (i.e., script execution blocks while the files are included).
|
||||
* @function Script.include
|
||||
* @param {string[]} filenames - The URLs of the scripts to include. Each can be relative to the current script.
|
||||
* @param {function} [callback=null] - The function to call back when the scripts have been included. Can be an in-line
|
||||
* function or the name of a function.
|
||||
*/
|
||||
Q_INVOKABLE void include(const QStringList& includeFiles, QScriptValue callback = QScriptValue());
|
||||
|
||||
/**jsdoc
|
||||
* Include JavaScript from another file in the current script. If a callback is specified the file is loaded and included
|
||||
* asynchronously, otherwise it is included synchronously (i.e., script execution blocks while the file is included).
|
||||
* @function Script.include
|
||||
* @param {string} filename - The URL of the script to include. Can be relative to the current script.
|
||||
* @param {function} [callback=null] - The function to call back when the script has been included. Can be an in-line
|
||||
* function or the name of a function.
|
||||
* @example <caption>Include a script file asynchronously.</caption>
|
||||
* // First file: scriptA.js
|
||||
* print("This is script A");
|
||||
*
|
||||
* // Second file: scriptB.js
|
||||
* print("This is script B");
|
||||
* Script.include("scriptA.js", function () {
|
||||
* print("Script A has been included");
|
||||
* });
|
||||
*
|
||||
* // If you run scriptB.js you should see only scriptB.js in the running scripts list.
|
||||
* // And you should see the following output:
|
||||
* // This is script B
|
||||
* // This is script A
|
||||
* // Script A has been included
|
||||
*/
|
||||
Q_INVOKABLE void include(const QString& includeFile, QScriptValue callback = QScriptValue());
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// MODULE related methods
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.require
|
||||
* @param {string} module
|
||||
*/
|
||||
Q_INVOKABLE QScriptValue require(const QString& moduleId);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.resetModuleCache
|
||||
* @param {boolean} [deleteScriptCache=false]
|
||||
*/
|
||||
Q_INVOKABLE void resetModuleCache(bool deleteScriptCache = false);
|
||||
QScriptValue currentModule();
|
||||
bool registerModuleWithParent(const QScriptValue& module, const QScriptValue& parent);
|
||||
|
@ -179,34 +329,168 @@ public:
|
|||
QVariantMap fetchModuleSource(const QString& modulePath, const bool forceDownload = false);
|
||||
QScriptValue instantiateModule(const QScriptValue& module, const QString& sourceCode);
|
||||
|
||||
/**jsdoc
|
||||
* Call a function at a set interval.
|
||||
* @function Script.setInterval
|
||||
* @param {function} function - The function to call. Can be an in-line function or the name of a function.
|
||||
* @param {number} interval - The interval at which to call the function, in ms.
|
||||
* @returns {object} A handle to the interval timer. Can be used by {@link Script.clearInterval}.
|
||||
* @example <caption>Print a message every second.</caption>
|
||||
* Script.setInterval(function () {
|
||||
* print("Timer fired");
|
||||
* }, 1000);
|
||||
*/
|
||||
Q_INVOKABLE QObject* setInterval(const QScriptValue& function, int intervalMS);
|
||||
|
||||
/**jsdoc
|
||||
* Call a function after a delay.
|
||||
* @function Script.setTimeout
|
||||
* @param {function} function - The function to call. Can be an in-line function or the name of a function.
|
||||
* @param {number} timeout - The delay after which to call the function, in ms.
|
||||
* @returns {object} A handle to the timeout timer. Can be used by {@link Script.clearTimeout}.
|
||||
* @example <caption>Print a message after a second.</caption>
|
||||
* Script.setTimeout(function () {
|
||||
* print("Timer fired");
|
||||
* }, 1000);
|
||||
*/
|
||||
Q_INVOKABLE QObject* setTimeout(const QScriptValue& function, int timeoutMS);
|
||||
|
||||
/**jsdoc
|
||||
* Stop an interval timer set by {@link Script.setInterval|setInterval}.
|
||||
* @function Script.clearInterval
|
||||
* @param {object} timer - The interval timer to clear.
|
||||
* @example <caption>Stop an interval timer.</caption>
|
||||
* // Print a message every second.
|
||||
* var timer = Script.setInterval(function () {
|
||||
* print("Timer fired");
|
||||
* }, 1000);
|
||||
*
|
||||
* // Stop the timer after 10 seconds.
|
||||
* Script.setTimeout(function () {
|
||||
* print("Stop timer");
|
||||
* Script.clearInterval(timer);
|
||||
* }, 10000);
|
||||
*/
|
||||
Q_INVOKABLE void clearInterval(QObject* timer) { stopTimer(reinterpret_cast<QTimer*>(timer)); }
|
||||
|
||||
/**jsdoc
|
||||
* Clear a timeout timer set by {@link Script.setTimeout|setTimeout}.
|
||||
* @function Script.clearTimeout
|
||||
* @param {object} timer - The timeout timer to clear.
|
||||
* @example <caption>Stop a timeout timer.</caption>
|
||||
* // Print a message after two seconds.
|
||||
* var timer = Script.setTimeout(function () {
|
||||
* print("Timer fired");
|
||||
* }, 2000);
|
||||
*
|
||||
* // Uncomment the following line to stop the timer from firing.
|
||||
* //Script.clearTimeout(timer);
|
||||
*/
|
||||
Q_INVOKABLE void clearTimeout(QObject* timer) { stopTimer(reinterpret_cast<QTimer*>(timer)); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.print
|
||||
* @param {string} message
|
||||
*/
|
||||
Q_INVOKABLE void print(const QString& message);
|
||||
|
||||
/**jsdoc
|
||||
* Resolve a relative path to an absolute path.
|
||||
* @function Script.resolvePath
|
||||
* @param {string} path - The relative path to resolve.
|
||||
* @returns {string} The absolute path.
|
||||
*/
|
||||
Q_INVOKABLE QUrl resolvePath(const QString& path) const;
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.resourcesPath
|
||||
* @returns {string}
|
||||
*/
|
||||
Q_INVOKABLE QUrl resourcesPath() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.beginProfileRange
|
||||
* @param {string} label
|
||||
*/
|
||||
Q_INVOKABLE void beginProfileRange(const QString& label) const;
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.endProfileRange
|
||||
* @param {string} label
|
||||
*/
|
||||
Q_INVOKABLE void endProfileRange(const QString& label) const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Entity Script Related methods
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.isEntityScriptRunning
|
||||
* @param {Uuid} entityID
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool isEntityScriptRunning(const EntityItemID& entityID) {
|
||||
return _entityScripts.contains(entityID) && _entityScripts[entityID].status == EntityScriptStatus::RUNNING;
|
||||
}
|
||||
QVariant cloneEntityScriptDetails(const EntityItemID& entityID);
|
||||
QFuture<QVariant> getLocalEntityScriptDetails(const EntityItemID& entityID) override;
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.loadEntityScript
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} script
|
||||
* @param {boolean} forceRedownload
|
||||
*/
|
||||
Q_INVOKABLE void loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.unloadEntityScript
|
||||
* @param {Uuid} entityID
|
||||
* @param {boolean} [shouldRemoveFromMap=false]
|
||||
*/
|
||||
Q_INVOKABLE void unloadEntityScript(const EntityItemID& entityID, bool shouldRemoveFromMap = false); // will call unload method
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.unloadAllEntityScripts
|
||||
*/
|
||||
Q_INVOKABLE void unloadAllEntityScripts();
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.callEntityScriptMethod
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} methodName
|
||||
* @param {string[]} parameters
|
||||
* @param {Uuid} [remoteCallerID=Uuid.NULL]
|
||||
*/
|
||||
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName,
|
||||
const QStringList& params = QStringList(),
|
||||
const QUuid& remoteCallerID = QUuid()) override;
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.callEntityScriptMethod
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} methodName
|
||||
* @param {PointerEvent} event
|
||||
*/
|
||||
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const PointerEvent& event);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.callEntityScriptMethod
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} methodName
|
||||
* @param {Uuid} otherID
|
||||
* @param {Collision} collision
|
||||
*/
|
||||
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.requestGarbageCollection
|
||||
*/
|
||||
Q_INVOKABLE void requestGarbageCollection() { collectGarbage(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.generateUUID
|
||||
* @returns {Uuid}
|
||||
*/
|
||||
Q_INVOKABLE QUuid generateUUID() { return QUuid::createUuid(); }
|
||||
|
||||
bool isFinished() const { return _isFinished; } // used by Application and ScriptWidget
|
||||
|
@ -239,33 +523,170 @@ public:
|
|||
bool getEntityScriptDetails(const EntityItemID& entityID, EntityScriptDetails &details) const;
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.callAnimationStateHandler
|
||||
* @param {function} callback
|
||||
* @param {object} parameters
|
||||
* @param {string[]} names
|
||||
* @param {boolean} useNames
|
||||
* @param {object} resultHandler
|
||||
*/
|
||||
void callAnimationStateHandler(QScriptValue callback, AnimVariantMap parameters, QStringList names, bool useNames, AnimVariantResultHandler resultHandler);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.updateMemoryCost
|
||||
* @param {number} deltaSize
|
||||
*/
|
||||
void updateMemoryCost(const qint64&);
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.scriptLoaded
|
||||
* @param {string} filename
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void scriptLoaded(const QString& scriptFilename);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.errorLoadingScript
|
||||
* @param {string} filename
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void errorLoadingScript(const QString& scriptFilename);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered regularly at a system-determined frequency.
|
||||
* @function Script.update
|
||||
* @param {number} deltaTime - The time since the last update, in s.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void update(float deltaTime);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the script is ending.
|
||||
* @function Script.scriptEnding
|
||||
* @returns {Signal}
|
||||
* @example <caption>Connect to the <code>scriptEnding</code> signal.</caption>
|
||||
* print("Script started");
|
||||
*
|
||||
* Script.scriptEnding.connect(function () {
|
||||
* print("Script ending");
|
||||
* });
|
||||
*
|
||||
* Script.setTimeout(function () {
|
||||
* print("Stopping script");
|
||||
* Script.stop();
|
||||
* }, 1000);
|
||||
*/
|
||||
void scriptEnding();
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.finished
|
||||
* @param {string} filename
|
||||
* @param {object} engine
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void finished(const QString& fileNameString, ScriptEnginePointer);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.cleanupMenuItem
|
||||
* @param {string} menuItem
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void cleanupMenuItem(const QString& menuItemString);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.printedMessage
|
||||
* @param {string} message
|
||||
* @param {string} scriptName
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void printedMessage(const QString& message, const QString& scriptName);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.errorMessage
|
||||
* @param {string} message
|
||||
* @param {string} scriptName
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void errorMessage(const QString& message, const QString& scriptName);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.warningMessage
|
||||
* @param {string} message
|
||||
* @param {string} scriptName
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void warningMessage(const QString& message, const QString& scriptName);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.infoMessage
|
||||
* @param {string} message
|
||||
* @param {string} scriptName
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void infoMessage(const QString& message, const QString& scriptName);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.runningStateChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void runningStateChanged();
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.clearDebugWindow
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void clearDebugWindow();
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.loadScript
|
||||
* @param {string} scriptName
|
||||
* @param {boolean} isUserLoaded
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void loadScript(const QString& scriptName, bool isUserLoaded);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.reloadScript
|
||||
* @param {string} scriptName
|
||||
* @param {boolean} isUserLoaded
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void reloadScript(const QString& scriptName, bool isUserLoaded);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.doneRunning
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void doneRunning();
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.entityScriptDetailsUpdated
|
||||
* @returns {Signal}
|
||||
*/
|
||||
// Emitted when an entity script is added or removed, or when the status of an entity
|
||||
// script is updated (goes from RUNNING to ERROR_RUNNING_SCRIPT, for example)
|
||||
void entityScriptDetailsUpdated();
|
||||
|
||||
protected:
|
||||
void init();
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.executeOnScriptThread
|
||||
* @param {object} function
|
||||
* @param {ConnectionType} [type=2]
|
||||
*/
|
||||
Q_INVOKABLE void executeOnScriptThread(std::function<void()> function, const Qt::ConnectionType& type = Qt::QueuedConnection );
|
||||
|
||||
/**jsdoc
|
||||
* @function Script._requireResolve
|
||||
* @param {string} module
|
||||
* @param {string} [relativeTo=""]
|
||||
* @returns {string}
|
||||
*/
|
||||
// note: this is not meant to be called directly, but just to have QMetaObject take care of wiring it up in general;
|
||||
// then inside of init() we just have to do "Script.require.resolve = Script._requireResolve;"
|
||||
Q_INVOKABLE QString _requireResolve(const QString& moduleId, const QString& relativeTo = QString());
|
||||
|
@ -285,6 +706,16 @@ protected:
|
|||
|
||||
QHash<EntityItemID, RegisteredEventHandlers> _registeredHandlers;
|
||||
void forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, QScriptValueList eventHanderArgs);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.entityScriptContentAvailable
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} scriptOrURL
|
||||
* @param {string} contents
|
||||
* @param {boolean} isURL
|
||||
* @param {boolean} success
|
||||
* @param {string} status
|
||||
*/
|
||||
Q_INVOKABLE void entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success, const QString& status);
|
||||
|
||||
EntityItemID currentEntityIdentifier {}; // Contains the defining entity script entity id during execution, if any. Empty for interface script execution.
|
||||
|
|
|
@ -27,6 +27,14 @@
|
|||
|
||||
class ScriptEngine;
|
||||
|
||||
/**jsdoc
|
||||
* @namespace ScriptDiscoveryService
|
||||
* @property {string} debugScriptUrl
|
||||
* @property {string} defaultScriptsPath
|
||||
* @property {ScriptsModel} scriptsModel
|
||||
* @property {ScriptsModelFilter} scriptsModelFilter
|
||||
*/
|
||||
|
||||
class NativeScriptInitializers : public ScriptInitializerMixin {
|
||||
public:
|
||||
bool registerNativeScriptInitializer(NativeScriptInitializer initializer) override;
|
||||
|
@ -63,18 +71,64 @@ public:
|
|||
|
||||
QString getDefaultScriptsLocation() const;
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.loadOneScript
|
||||
* @param {string} filename
|
||||
*/
|
||||
Q_INVOKABLE void loadOneScript(const QString& scriptFilename);
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.loadScript
|
||||
* @param {string} [filename=""]
|
||||
* @param {boolean} [isUserLoaded=true]
|
||||
* @param {boolean} [loadScriptFromEditor=false]
|
||||
* @param {boolean} [activateMainWindow=false]
|
||||
* @param {boolean} [reload=false]
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE ScriptEnginePointer loadScript(const QUrl& scriptFilename = QString(),
|
||||
bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false);
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.stopScript
|
||||
* @param {string} scriptHash
|
||||
* @param {boolean} [restart=false]
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool stopScript(const QString& scriptHash, bool restart = false);
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.reloadAllScripts
|
||||
*/
|
||||
Q_INVOKABLE void reloadAllScripts();
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.stopAllScripts
|
||||
* @param {boolean} [restart=false]
|
||||
*/
|
||||
Q_INVOKABLE void stopAllScripts(bool restart = false);
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.getRunning
|
||||
* @returns {object[]}
|
||||
*/
|
||||
Q_INVOKABLE QVariantList getRunning();
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.getPublic
|
||||
* @returns {object[]}
|
||||
*/
|
||||
Q_INVOKABLE QVariantList getPublic();
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.getLocal
|
||||
* @returns {object[]}
|
||||
*/
|
||||
Q_INVOKABLE QVariantList getLocal();
|
||||
|
||||
// FIXME: Move to other Q_PROPERTY declarations.
|
||||
Q_PROPERTY(QString defaultScriptsPath READ getDefaultScriptsLocation)
|
||||
|
||||
void defaultScriptsLocationOverridden(bool overridden) { _defaultScriptsLocationOverridden = overridden; };
|
||||
|
@ -86,25 +140,120 @@ public:
|
|||
void addScriptEngine(ScriptEnginePointer);
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.scriptCountChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void scriptCountChanged();
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.scriptsReloading
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void scriptsReloading();
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.scriptLoadError
|
||||
* @param {string} filename
|
||||
* @param {string} error
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void scriptLoadError(const QString& filename, const QString& error);
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.printedMessage
|
||||
* @param {string} message
|
||||
* @param {string} engineName
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void printedMessage(const QString& message, const QString& engineName);
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.errorMessage
|
||||
* @param {string} message
|
||||
* @param {string} engineName
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void errorMessage(const QString& message, const QString& engineName);
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.warningMessage
|
||||
* @param {string} message
|
||||
* @param {string} engineName
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void warningMessage(const QString& message, const QString& engineName);
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.infoMessage
|
||||
* @param {string} message
|
||||
* @param {string} engineName
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void infoMessage(const QString& message, const QString& engineName);
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.errorLoadingScript
|
||||
* @param {string} url
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void errorLoadingScript(const QString& url);
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.clearDebugWindow
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void clearDebugWindow();
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.onPrintedMessage
|
||||
* @param {string} message
|
||||
* @param {string} scriptName
|
||||
*/
|
||||
void onPrintedMessage(const QString& message, const QString& scriptName);
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.onErrorMessage
|
||||
* @param {string} message
|
||||
* @param {string} scriptName
|
||||
*/
|
||||
void onErrorMessage(const QString& message, const QString& scriptName);
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.onWarningMessage
|
||||
* @param {string} message
|
||||
* @param {string} scriptName
|
||||
*/
|
||||
void onWarningMessage(const QString& message, const QString& scriptName);
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.onInfoMessage
|
||||
* @param {string} message
|
||||
* @param {string} scriptName
|
||||
*/
|
||||
void onInfoMessage(const QString& message, const QString& scriptName);
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.onErrorLoadingScript
|
||||
* @param {string} url
|
||||
*/
|
||||
void onErrorLoadingScript(const QString& url);
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.onClearDebugWindow
|
||||
*/
|
||||
void onClearDebugWindow();
|
||||
|
||||
protected slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptDiscoveryService.onScriptFinished
|
||||
* @param {string} filename
|
||||
* @param {object} engine
|
||||
*/
|
||||
void onScriptFinished(const QString& fileNameString, ScriptEnginePointer engine);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -63,17 +63,68 @@ public:
|
|||
TreeNodeFolder(const QString& foldername, TreeNodeFolder* parent);
|
||||
};
|
||||
|
||||
/**jsdoc
|
||||
* <p>Provided as a property of {@link ScriptDiscoveryService}.</p>
|
||||
* <p>Has properties and functions below in addition to those of <a href="http://doc.qt.io/qt-5/qabstractitemmodel.html">
|
||||
* http://doc.qt.io/qt-5/qabstractitemmodel.html</a>.</p>
|
||||
* @class ScriptsModel
|
||||
*/
|
||||
class ScriptsModel : public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScriptsModel(QObject* parent = NULL);
|
||||
~ScriptsModel();
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptsModel.index
|
||||
* @param {number} row
|
||||
* @param {number} column
|
||||
* @param {QModelIndex} parent
|
||||
* @returns {QModelIndex}
|
||||
*/
|
||||
QModelIndex index(int row, int column, const QModelIndex& parent) const override;
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptsModel.parent
|
||||
* @param {QModelIndex} child
|
||||
* @returns {QModelIndex}
|
||||
*/
|
||||
QModelIndex parent(const QModelIndex& child) const override;
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptsModel.data
|
||||
* @param {QModelIndex} index
|
||||
* @param {number} [role=0]
|
||||
* returns {string}
|
||||
*/
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptsModel.rowCount
|
||||
* @param {QmodelIndex} [parent=null]
|
||||
* @returns {number}
|
||||
*/
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptsModel.columnCount
|
||||
* @param {QmodelIndex} [parent=null]
|
||||
* @returns {number}
|
||||
*/
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptsModel.getTreeNodeFromIndex
|
||||
* @param {QmodelIndex} index
|
||||
* @returns {TreeNodeBase}
|
||||
*/
|
||||
TreeNodeBase* getTreeNodeFromIndex(const QModelIndex& index) const;
|
||||
|
||||
/**jsdoc
|
||||
* @function ScriptsModel.getFolderNodes
|
||||
* @param {TreeNodeFolder} parent
|
||||
* @returns {TreeNodeBase[]}
|
||||
*/
|
||||
QList<TreeNodeBase*> getFolderNodes(TreeNodeFolder* parent) const;
|
||||
|
||||
enum Role {
|
||||
|
|
|
@ -15,6 +15,12 @@
|
|||
#include "ScriptsModel.h"
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
/**jsdoc
|
||||
* <p>Provided as a property of {@link ScriptDiscoveryService}.</p>
|
||||
* <p>Has properties and functions per <a href="http://doc.qt.io/qt-5/qsortfilterproxymodel.html">
|
||||
* http://doc.qt.io/qt-5/qsortfilterproxymodel.html</a>.</p>
|
||||
* @class ScriptsModelFilter
|
||||
*/
|
||||
class ScriptsModelFilter : public QSortFilterProxyModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
|
|
@ -17,8 +17,12 @@
|
|||
#include <DependencyManager.h>
|
||||
|
||||
/**jsdoc
|
||||
* @namespace Users
|
||||
*/
|
||||
* @namespace Users
|
||||
* @property {boolean} canKick - <code>true</code> if the domain server allows the node or avatar to kick (ban) avatars,
|
||||
* otherwise <code>false</code>. <em>Read-only.</em>
|
||||
* @property {boolean} requestsDomainListData - <code>true</code> if the avatar requests extra data from the mixers (such as
|
||||
* positional data of an avatar you've ignored). <em>Read-only.</em>
|
||||
*/
|
||||
class UsersScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
@ -32,126 +36,151 @@ public:
|
|||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* Ignore another user.
|
||||
* @function Users.ignore
|
||||
* @param {nodeID} nodeID The node or session ID of the user you want to ignore.
|
||||
* @param {bool} enable True for ignored; false for un-ignored.
|
||||
*/
|
||||
* Personally ignore another user, making them disappear for you and you disappear for them.
|
||||
* @function Users.ignore
|
||||
* @param {Uuid} nodeID The node or session ID of the user you want to ignore.
|
||||
* @param {boolean} enable True for ignored; false for un-ignored.
|
||||
*/
|
||||
void ignore(const QUuid& nodeID, bool ignoreEnabled = true);
|
||||
|
||||
/**jsdoc
|
||||
* Gets a bool containing whether you have ignored the given Avatar UUID.
|
||||
* @function Users.getIgnoreStatus
|
||||
* @param {nodeID} nodeID The node or session ID of the user whose ignore status you want.
|
||||
*/
|
||||
* Get whether or not you have ignored the node with the given UUID.
|
||||
* @function Users.getIgnoreStatus
|
||||
* @param {Uuid} nodeID The node or session ID of the user whose ignore status you want.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
bool getIgnoreStatus(const QUuid& nodeID);
|
||||
|
||||
/**jsdoc
|
||||
* Mute another user for you and you only.
|
||||
* @function Users.personalMute
|
||||
* @param {nodeID} nodeID The node or session ID of the user you want to mute.
|
||||
* @param {bool} enable True for enabled; false for disabled.
|
||||
*/
|
||||
* Mute another user for you and you only. They won't be able to hear you, and you won't be able to hear them.
|
||||
* @function Users.personalMute
|
||||
* @param {Uuid} nodeID The node or session ID of the user you want to mute.
|
||||
* @param {boolean} muteEnabled True for enabled; false for disabled.
|
||||
*/
|
||||
void personalMute(const QUuid& nodeID, bool muteEnabled = true);
|
||||
|
||||
/**jsdoc
|
||||
* Requests a bool containing whether you have personally muted the given Avatar UUID.
|
||||
* @function Users.requestPersonalMuteStatus
|
||||
* @param {nodeID} nodeID The node or session ID of the user whose personal mute status you want.
|
||||
*/
|
||||
* Get whether or not you have personally muted the node with the given UUID.
|
||||
* @function Users.requestPersonalMuteStatus
|
||||
* @param {Uuid} nodeID The node or session ID of the user whose personal mute status you want.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
bool getPersonalMuteStatus(const QUuid& nodeID);
|
||||
|
||||
/**jsdoc
|
||||
* Sets an avatar's gain for you and you only.
|
||||
* Units are Decibels (dB)
|
||||
* @function Users.setAvatarGain
|
||||
* @param {nodeID} nodeID The node or session ID of the user whose gain you want to modify, or null to set the master gain.
|
||||
* @param {float} gain The gain of the avatar you'd like to set. Units are dB.
|
||||
* Sets an avatar's gain for you and you only.
|
||||
* Units are Decibels (dB)
|
||||
* @function Users.setAvatarGain
|
||||
* @param {Uuid} nodeID The node or session ID of the user whose gain you want to modify, or null to set the master gain.
|
||||
* @param {number} gain The gain of the avatar you'd like to set. Units are dB.
|
||||
*/
|
||||
void setAvatarGain(const QUuid& nodeID, float gain);
|
||||
|
||||
/**jsdoc
|
||||
* Gets an avatar's gain for you and you only.
|
||||
* @function Users.getAvatarGain
|
||||
* @param {nodeID} nodeID The node or session ID of the user whose gain you want to get, or null to get the master gain.
|
||||
* @return {float} gain (in dB)
|
||||
* Gets an avatar's gain for you and you only.
|
||||
* @function Users.getAvatarGain
|
||||
* @param {Uuid} nodeID The node or session ID of the user whose gain you want to get, or null to get the master gain.
|
||||
* @returns {number} gain (in dB)
|
||||
*/
|
||||
float getAvatarGain(const QUuid& nodeID);
|
||||
|
||||
/**jsdoc
|
||||
* Kick another user.
|
||||
* @function Users.kick
|
||||
* @param {nodeID} nodeID The node or session ID of the user you want to kick.
|
||||
*/
|
||||
* Kick/ban another user. Removes them from the server and prevents them from returning. Bans by either user name (if
|
||||
* available) or machine fingerprint otherwise. This will only do anything if you're an admin of the domain you're in.
|
||||
* @function Users.kick
|
||||
* @param {Uuid} nodeID The node or session ID of the user you want to kick.
|
||||
*/
|
||||
void kick(const QUuid& nodeID);
|
||||
|
||||
/**jsdoc
|
||||
* Mute another user for everyone.
|
||||
* @function Users.mute
|
||||
* @param {nodeID} nodeID The node or session ID of the user you want to mute.
|
||||
*/
|
||||
* Mutes another user's microphone for everyone. Not permanent; the silenced user can unmute themselves with the UNMUTE
|
||||
* button in their HUD. This will only do anything if you're an admin of the domain you're in.
|
||||
* @function Users.mute
|
||||
* @param {Uuid} nodeID The node or session ID of the user you want to mute.
|
||||
*/
|
||||
void mute(const QUuid& nodeID);
|
||||
|
||||
/**jsdoc
|
||||
* Returns a string containing the username associated with the given Avatar UUID
|
||||
* Get the user name and machine fingerprint associated with the given UUID. This will only do anything if you're an admin
|
||||
* of the domain you're in.
|
||||
* @function Users.getUsernameFromID
|
||||
* @param {nodeID} nodeID The node or session ID of the user whose username you want.
|
||||
* @param {Uuid} nodeID The node or session ID of the user whose username you want.
|
||||
*/
|
||||
void requestUsernameFromID(const QUuid& nodeID);
|
||||
|
||||
/**jsdoc
|
||||
* Returns `true` if the DomainServer will allow this Node/Avatar to make kick
|
||||
* @function Users.getCanKick
|
||||
* @return {bool} `true` if the client can kick other users, `false` if not.
|
||||
*/
|
||||
* Returns `true` if the DomainServer will allow this Node/Avatar to make kick.
|
||||
* @function Users.getCanKick
|
||||
* @returns {boolean} <code>true</code> if the domain server allows the client to kick (ban) other users, otherwise
|
||||
* <code>false</code>.
|
||||
*/
|
||||
bool getCanKick();
|
||||
|
||||
/**jsdoc
|
||||
* Toggle the state of the ignore in radius feature
|
||||
* @function Users.toggleIgnoreRadius
|
||||
*/
|
||||
* Toggle the state of the space bubble feature.
|
||||
* @function Users.toggleIgnoreRadius
|
||||
*/
|
||||
void toggleIgnoreRadius();
|
||||
|
||||
/**jsdoc
|
||||
* Enables the ignore radius feature.
|
||||
* @function Users.enableIgnoreRadius
|
||||
*/
|
||||
* Enables the space bubble feature.
|
||||
* @function Users.enableIgnoreRadius
|
||||
*/
|
||||
void enableIgnoreRadius();
|
||||
|
||||
/**jsdoc
|
||||
* Disables the ignore radius feature.
|
||||
* @function Users.disableIgnoreRadius
|
||||
*/
|
||||
* Disables the space bubble feature.
|
||||
* @function Users.disableIgnoreRadius
|
||||
*/
|
||||
void disableIgnoreRadius();
|
||||
|
||||
/**jsdoc
|
||||
* Returns `true` if the ignore in radius feature is enabled
|
||||
* @function Users.getIgnoreRadiusEnabled
|
||||
* @return {bool} `true` if the ignore in radius feature is enabled, `false` if not.
|
||||
*/
|
||||
* Returns `true` if the space bubble feature is enabled.
|
||||
* @function Users.getIgnoreRadiusEnabled
|
||||
* @returns {boolean} <code>true</code> if the space bubble is enabled, otherwise <code>false</code>.
|
||||
*/
|
||||
bool getIgnoreRadiusEnabled();
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function Users.canKickChanged
|
||||
* @param {boolean} canKick
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void canKickChanged(bool canKick);
|
||||
|
||||
/**jsdoc
|
||||
* @function Users.ignoreRadiusEnabledChanged
|
||||
* @param {boolean} isEnabled
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void ignoreRadiusEnabledChanged(bool isEnabled);
|
||||
|
||||
/**jsdoc
|
||||
* Notifies scripts that another user has entered the ignore radius
|
||||
* @function Users.enteredIgnoreRadius
|
||||
*/
|
||||
* Notifies scripts that another user has entered the ignore radius.
|
||||
* @function Users.enteredIgnoreRadius
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void enteredIgnoreRadius();
|
||||
|
||||
/**jsdoc
|
||||
* Notifies scripts of the username and machine fingerprint associated with a UUID.
|
||||
* Username and machineFingerprint will be their default constructor output if the requesting user isn't an admin.
|
||||
* @function Users.usernameFromIDReply
|
||||
* Notifies scripts of the user name and machine fingerprint associated with a UUID.
|
||||
* Username and machineFingerprint will be their default constructor output if the requesting user isn't an admin.
|
||||
* @function Users.usernameFromIDReply
|
||||
* @param {Uuid} nodeID
|
||||
* @param {string} userName
|
||||
* @param {string} machineFingerprint
|
||||
* @param {boolean} isAdmin
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void usernameFromIDReply(const QString& nodeID, const QString& username, const QString& machineFingerprint, bool isAdmin);
|
||||
|
||||
/**jsdoc
|
||||
* Notifies scripts that a user has disconnected from the domain
|
||||
* Notifies scripts that a user has disconnected from the domain.
|
||||
* @function Users.avatarDisconnected
|
||||
* @param {nodeID} NodeID The session ID of the avatar that has disconnected
|
||||
* @param {Uuid} nodeID The session ID of the avatar that has disconnected.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void avatarDisconnected(const QUuid& nodeID);
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <SettingHandle.h>
|
||||
|
||||
/// Base class for face trackers (DDE, BinaryVR).
|
||||
|
||||
class FaceTracker : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -58,11 +59,34 @@ public:
|
|||
QVector<float>& coefficients);
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function FaceTracker.muteToggled
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
||||
void muteToggled();
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* @function FaceTracker.setEnabled
|
||||
* @param {boolean} enabled
|
||||
*/
|
||||
|
||||
virtual void setEnabled(bool enabled) = 0;
|
||||
|
||||
/**jsdoc
|
||||
* @function FaceTracker.toggleMute
|
||||
*/
|
||||
|
||||
void toggleMute();
|
||||
|
||||
/**jsdoc
|
||||
* @function FaceTracker.getMuted
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
bool getMuted() { return _isMuted; }
|
||||
|
||||
protected:
|
||||
|
|
|
@ -44,6 +44,23 @@ class OffscreenQmlSurface;
|
|||
class TabletScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
/**jsdoc
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>0</code></td><td>Button click.</td></tr>
|
||||
* <tr><td><code>1</code></td><td>Button hover.</td></tr>
|
||||
* <tr><td><code>2</code></td><td>Tablet open.</td></tr>
|
||||
* <tr><td><code>3</code></td><td>Tablet hands in.</td></tr>
|
||||
* <tr><td><code>4</code></td><td>Tablet hands out.</td></tr>
|
||||
* <tr><td><code>5</code></td><td>Last.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {number} Tablet.AudioEvents
|
||||
*/
|
||||
enum TabletAudioEvents { ButtonClick, ButtonHover, TabletOpen, TabletHandsIn, TabletHandsOut, Last};
|
||||
Q_ENUM(TabletAudioEvents)
|
||||
|
||||
|
@ -58,14 +75,19 @@ public:
|
|||
void setToolbarScriptingInterface(ToolbarScriptingInterface* toolbarScriptingInterface) { _toolbarScriptingInterface = toolbarScriptingInterface; }
|
||||
|
||||
/**jsdoc
|
||||
* Creates or retruns a new TabletProxy and returns it.
|
||||
* Creates or returns a new TabletProxy and returns it.
|
||||
* @function Tablet.getTablet
|
||||
* @param name {String} tablet name
|
||||
* @return {TabletProxy} tablet instance
|
||||
* @param {string} name - Tablet name.
|
||||
* @returns {TabletProxy} Tablet instance.
|
||||
*/
|
||||
Q_INVOKABLE TabletProxy* getTablet(const QString& tabletId);
|
||||
|
||||
void preloadSounds();
|
||||
|
||||
/**jsdoc
|
||||
* @function Tablet.playSound
|
||||
* @param {Tablet.AudioEvents} sound
|
||||
*/
|
||||
Q_INVOKABLE void playSound(TabletAudioEvents aEvent);
|
||||
|
||||
void setToolbarMode(bool toolbarMode);
|
||||
|
@ -79,8 +101,8 @@ public:
|
|||
QObject* getFlags();
|
||||
signals:
|
||||
/**jsdoc
|
||||
* Signaled when a tablet message or dialog is created
|
||||
* @function TabletProxy#tabletNotification
|
||||
* Triggered when a tablet message or dialog is created.
|
||||
* @function Tablet.tabletNotification
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void tabletNotification();
|
||||
|
@ -98,6 +120,9 @@ protected:
|
|||
bool _toolbarMode { false };
|
||||
};
|
||||
|
||||
/**jsdoc
|
||||
* @typedef {object} TabletProxy#ButtonList
|
||||
*/
|
||||
class TabletButtonListModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -151,9 +176,12 @@ Q_DECLARE_METATYPE(TabletButtonsProxyModel*);
|
|||
|
||||
/**jsdoc
|
||||
* @class TabletProxy
|
||||
* @property name {string} READ_ONLY: name of this tablet
|
||||
* @property toolbarMode {bool} - used to transition this tablet into and out of toolbar mode.
|
||||
* @property {string} name - Name of this tablet. <em>Read-only.</em>
|
||||
* @property {boolean} toolbarMode - Used to transition this tablet into and out of toolbar mode.
|
||||
* When tablet is in toolbar mode, all its buttons will appear in a floating toolbar.
|
||||
* @property {boolean} landscape
|
||||
* @property {boolean} tabletShown <em>Read-only.</em>
|
||||
* @property {TabletProxy#ButtonList} buttons <em>Read-only.</em>
|
||||
*/
|
||||
class TabletProxy : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -172,88 +200,136 @@ public:
|
|||
bool getToolbarMode() const { return _toolbarMode; }
|
||||
void setToolbarMode(bool toolbarMode);
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function TabletProxy#gotoMenuScreen
|
||||
* @param {string} [submenu=""]
|
||||
*/
|
||||
Q_INVOKABLE void gotoMenuScreen(const QString& submenu = "");
|
||||
Q_INVOKABLE void initialScreen(const QVariant& url);
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* transition to the home screen
|
||||
* @function TabletProxy#initialScreen
|
||||
* @param {string} url
|
||||
*/
|
||||
Q_INVOKABLE void initialScreen(const QVariant& url);
|
||||
|
||||
/**jsdoc
|
||||
* Transition to the home screen.
|
||||
* @function TabletProxy#gotoHomeScreen
|
||||
*/
|
||||
Q_INVOKABLE void gotoHomeScreen();
|
||||
|
||||
/**jsdoc
|
||||
* show the specified web url on the tablet.
|
||||
* Show the specified Web url on the tablet.
|
||||
* @function TabletProxy#gotoWebScreen
|
||||
* @param url {string} url of web page.
|
||||
* @param [injectedJavaScriptUrl] {string} optional url to an additional JS script to inject into the web page.
|
||||
* @param {string} url - URL of web page.
|
||||
* @param {string} [injectedJavaScriptUrl=""] - URL to an additional JS script to inject into the web page.
|
||||
* @param {boolean} [loadOtherBase=false]
|
||||
*/
|
||||
Q_INVOKABLE void gotoWebScreen(const QString& url);
|
||||
Q_INVOKABLE void gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase = false);
|
||||
|
||||
/**jsdoc
|
||||
* @function TabletProxy#loadQMLSource
|
||||
* @param {string} path
|
||||
* @param {boolean} [resizable=false]
|
||||
*/
|
||||
Q_INVOKABLE void loadQMLSource(const QVariant& path, bool resizable = false);
|
||||
// FIXME: This currently relies on a script initializing the tablet (hence the bool denoting success);
|
||||
// it should be initialized internally so it cannot fail
|
||||
Q_INVOKABLE bool pushOntoStack(const QVariant& path);
|
||||
Q_INVOKABLE void popFromStack();
|
||||
|
||||
Q_INVOKABLE void loadQMLOnTop(const QVariant& path);
|
||||
Q_INVOKABLE void loadWebScreenOnTop(const QVariant& url);
|
||||
Q_INVOKABLE void loadWebScreenOnTop(const QVariant& url, const QString& injectedJavaScriptUrl);
|
||||
Q_INVOKABLE void returnToPreviousApp();
|
||||
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* Check if the tablet has a message dialog open
|
||||
* @function TabletProxy#pushOntoStack
|
||||
* @param {string} path
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool pushOntoStack(const QVariant& path);
|
||||
|
||||
/**jsdoc
|
||||
* @function TabletProxy#popFromStack
|
||||
*/
|
||||
Q_INVOKABLE void popFromStack();
|
||||
|
||||
/**jsdoc
|
||||
* @function TabletProxy#loadQMLOnTop
|
||||
* @param {string} path
|
||||
*/
|
||||
Q_INVOKABLE void loadQMLOnTop(const QVariant& path);
|
||||
|
||||
/**jsdoc
|
||||
* @function TabletProxy#loadWebScreenOnTop
|
||||
* @param {string} path
|
||||
* @param {string} [injectedJavaScriptURL=""]
|
||||
*/
|
||||
Q_INVOKABLE void loadWebScreenOnTop(const QVariant& url);
|
||||
Q_INVOKABLE void loadWebScreenOnTop(const QVariant& url, const QString& injectedJavaScriptUrl);
|
||||
|
||||
/**jsdoc
|
||||
* @function TabletProxy#returnToPreviousApp
|
||||
*/
|
||||
Q_INVOKABLE void returnToPreviousApp();
|
||||
|
||||
/**jsdoc
|
||||
* Check if the tablet has a message dialog open.
|
||||
* @function TabletProxy#isMessageDialogOpen
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool isMessageDialogOpen();
|
||||
|
||||
/**jsdoc
|
||||
* Creates a new button, adds it to this and returns it.
|
||||
* @function TabletProxy#addButton
|
||||
* @param properties {Object} button properties UI_TABLET_HACK: enumerate these when we figure out what they should be!
|
||||
* @param {object} properties - Button properties.
|
||||
* @returns {TabletButtonProxy}
|
||||
*/
|
||||
//FIXME: UI_TABLET_HACK: enumerate the button properties when we figure out what they should be!
|
||||
Q_INVOKABLE TabletButtonProxy* addButton(const QVariant& properties);
|
||||
|
||||
/**jsdoc
|
||||
* removes button from the tablet
|
||||
* @function TabletProxy.removeButton
|
||||
* @param tabletButtonProxy {TabletButtonProxy} button to be removed
|
||||
* Removes a button from the tablet.
|
||||
* @function TabletProxy#removeButton
|
||||
* @param {TabletButtonProxy} button - The button to be removed
|
||||
*/
|
||||
Q_INVOKABLE void removeButton(TabletButtonProxy* tabletButtonProxy);
|
||||
|
||||
/**jsdoc
|
||||
* Used to send an event to the html/js embedded in the tablet
|
||||
* Used to send an event to the HTML/JavaScript embedded in the tablet.
|
||||
* @function TabletProxy#emitScriptEvent
|
||||
* @param msg {object|string}
|
||||
* @param {object|string} message
|
||||
*/
|
||||
Q_INVOKABLE void emitScriptEvent(const QVariant& msg);
|
||||
|
||||
/**jsdoc
|
||||
* Used to send an event to the qml embedded in the tablet
|
||||
* Used to send an event to the QML embedded in the tablet.
|
||||
* @function TabletProxy#sendToQml
|
||||
* @param msg {object|string}
|
||||
* @param {object|string} message
|
||||
*/
|
||||
Q_INVOKABLE void sendToQml(const QVariant& msg);
|
||||
|
||||
/**jsdoc
|
||||
* Check if the tablet is on the homescreen
|
||||
* @function TabletProxy#onHomeScreen()
|
||||
* Check if the tablet is on the home screen.
|
||||
* @function TabletProxy#onHomeScreen
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool onHomeScreen();
|
||||
|
||||
/**jsdoc
|
||||
* set tablet into our out of landscape mode
|
||||
* Set tablet into or out of landscape mode.
|
||||
* @function TabletProxy#setLandscape
|
||||
* @param landscape {bool} true for landscape, false for portrait
|
||||
* @param {boolean} landscape - <code>true</code> for landscape, <ode>false</code> for portrait.
|
||||
*/
|
||||
Q_INVOKABLE void setLandscape(bool landscape) { _landscape = landscape; }
|
||||
|
||||
/**jsdoc
|
||||
* @function TabletProxy#getLandscape
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool getLandscape() { return _landscape; }
|
||||
|
||||
/**jsdoc
|
||||
* @function TabletProxy#isPathLoaded
|
||||
* @param {string} path
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Q_INVOKABLE bool isPathLoaded(const QVariant& path);
|
||||
|
||||
QQuickItem* getTabletRoot() const { return _qmlTabletRoot; }
|
||||
|
@ -268,17 +344,17 @@ public:
|
|||
|
||||
signals:
|
||||
/**jsdoc
|
||||
* Signaled when this tablet receives an event from the html/js embedded in the tablet
|
||||
* Signaled when this tablet receives an event from the html/js embedded in the tablet.
|
||||
* @function TabletProxy#webEventReceived
|
||||
* @param msg {object|string}
|
||||
* @param {object|string} message
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void webEventReceived(QVariant msg);
|
||||
|
||||
/**jsdoc
|
||||
* Signaled when this tablet receives an event from the qml embedded in the tablet
|
||||
* Signaled when this tablet receives an event from the qml embedded in the tablet.
|
||||
* @function TabletProxy#fromQml
|
||||
* @param msg {object|string}
|
||||
* @param {object|string} message
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void fromQml(QVariant msg);
|
||||
|
@ -286,18 +362,21 @@ signals:
|
|||
/**jsdoc
|
||||
* Signaled when this tablet screen changes.
|
||||
* @function TabletProxy#screenChanged
|
||||
* @param type {string} - "Home", "Web", "Menu", "QML", "Closed"
|
||||
* @param url {string} - only valid for Web and QML.
|
||||
* @param type {string} - "Home", "Web", "Menu", "QML", "Closed".
|
||||
* @param url {string} - Only valid for Web and QML.
|
||||
*/
|
||||
void screenChanged(QVariant type, QVariant url);
|
||||
|
||||
/**jsdoc
|
||||
* Signaled when the tablet becomes visible or becomes invisible
|
||||
* @function TabletProxy#isTabletShownChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
* Signaled when the tablet becomes visible or becomes invisible.
|
||||
* @function TabletProxy#isTabletShownChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void tabletShownChanged();
|
||||
|
||||
/**jsdoc
|
||||
* @function TabletProxy#toolbarModeChanged
|
||||
*/
|
||||
void toolbarModeChanged();
|
||||
|
||||
protected slots:
|
||||
|
@ -331,7 +410,8 @@ Q_DECLARE_METATYPE(TabletProxy*);
|
|||
|
||||
/**jsdoc
|
||||
* @class TabletButtonProxy
|
||||
* @property uuid {QUuid} READ_ONLY: uniquely identifies this button
|
||||
* @property {Uuid} uuid - Uniquely identifies this button. <em>Read-only.</em>
|
||||
* @property {TabletButtonProxy.ButtonProperties} properties
|
||||
*/
|
||||
class TabletButtonProxy : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -344,48 +424,55 @@ public:
|
|||
QUuid getUuid() const { return _uuid; }
|
||||
|
||||
/**jsdoc
|
||||
* Returns the current value of this button's properties
|
||||
* Returns the current value of this button's properties.
|
||||
* @function TabletButtonProxy#getProperties
|
||||
* @returns {ButtonProperties}
|
||||
* @returns {TabletButtonProxy.ButtonProperties}
|
||||
*/
|
||||
Q_INVOKABLE QVariantMap getProperties();
|
||||
|
||||
/**jsdoc
|
||||
* Replace the values of some of this button's properties
|
||||
* Replace the values of some of this button's properties.
|
||||
* @function TabletButtonProxy#editProperties
|
||||
* @param {ButtonProperties} properties - set of properties to change
|
||||
* @param {TabletButtonProxy.ButtonProperties} properties - Set of properties to change.
|
||||
*/
|
||||
Q_INVOKABLE void editProperties(const QVariantMap& properties);
|
||||
|
||||
signals:
|
||||
/**jsdoc
|
||||
* Signaled when this button has been clicked on by the user.
|
||||
* Triggered when this button has been clicked on by the user.
|
||||
* @function TabletButtonProxy#clicked
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void clicked();
|
||||
|
||||
/**jsdoc
|
||||
* @function TabletButtonProxy#propertiesChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void propertiesChanged();
|
||||
|
||||
protected:
|
||||
QUuid _uuid;
|
||||
int _stableOrder;
|
||||
|
||||
/**jsdoc
|
||||
* @typedef TabletButtonProxy.ButtonProperties
|
||||
* @property {string} icon - URL to button icon. (50 x 50)
|
||||
* @property {string} hoverIcon - URL to button icon, displayed during mouse hover. (50 x 50)
|
||||
* @property {string} activeHoverIcon - URL to button icon used when button is active, and during mouse hover. (50 x 50)
|
||||
* @property {string} activeIcon - URL to button icon used when button is active. (50 x 50)
|
||||
* @property {string} text - Button caption.
|
||||
* @property {string} hoverText - Button caption when button is not-active but during mouse hover.
|
||||
* @property {string} activeText - Button caption when button is active.
|
||||
* @property {string} activeHoverText - Button caption when button is active and during mouse hover.
|
||||
* @property {boolean} isActive - <code>true</code> when button is active.
|
||||
* @property {number} sortOrder - Determines sort order on tablet. lower numbers will appear before larger numbers.
|
||||
* Default is 100.
|
||||
*/
|
||||
// FIXME: There are additional properties.
|
||||
QVariantMap _properties;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(TabletButtonProxy*);
|
||||
|
||||
/**jsdoc
|
||||
* @typedef TabletButtonProxy.ButtonProperties
|
||||
* @property {string} icon - url to button icon. (50 x 50)
|
||||
* @property {string} hoverIcon - url to button icon, displayed during mouse hover. (50 x 50)
|
||||
* @property {string} activeHoverIcon - url to button icon used when button is active, and during mouse hover. (50 x 50)
|
||||
* @property {string} activeIcon - url to button icon used when button is active. (50 x 50)
|
||||
* @property {string} text - button caption
|
||||
* @property {string} hoverText - button caption when button is not-active but during mouse hover.
|
||||
* @property {string} activeText - button caption when button is active
|
||||
* @property {string} activeHoverText - button caption when button is active and during mouse hover.
|
||||
* @property {string} isActive - true when button is active.
|
||||
* @property {number} sortOrder - determines sort order on tablet. lower numbers will appear before larger numbers. default is 100
|
||||
*/
|
||||
|
||||
#endif // hifi_TabletScriptingInterface_h
|
||||
|
|
|
@ -98,6 +98,7 @@ Rectangle {
|
|||
property: "covarianceGamma"
|
||||
max: 1.5
|
||||
min: 0.5
|
||||
height: 38
|
||||
}
|
||||
Separator {}
|
||||
HifiControls.CheckBox {
|
||||
|
@ -114,6 +115,7 @@ Rectangle {
|
|||
property: "blend"
|
||||
max: 1.0
|
||||
min: 0.0
|
||||
height: 38
|
||||
}
|
||||
|
||||
ConfigSlider {
|
||||
|
@ -162,6 +164,7 @@ Rectangle {
|
|||
property: "debugShowVelocityThreshold"
|
||||
max: 50
|
||||
min: 0.0
|
||||
height: 38
|
||||
}
|
||||
ConfigSlider {
|
||||
label: qsTr("Debug Orb Zoom")
|
||||
|
@ -170,6 +173,7 @@ Rectangle {
|
|||
property: "debugOrbZoom"
|
||||
max: 32.0
|
||||
min: 1.0
|
||||
height: 38
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,9 +93,10 @@ Item {
|
|||
integral: false
|
||||
config: root.config
|
||||
property: "intensity"
|
||||
max: 5.0
|
||||
max: 1.0
|
||||
min: 0.0
|
||||
width: 280
|
||||
height:38
|
||||
}
|
||||
ConfigSlider {
|
||||
label: "Size"
|
||||
|
@ -105,6 +106,7 @@ Item {
|
|||
max: 1.0
|
||||
min: 0.0
|
||||
width: 280
|
||||
height:38
|
||||
}
|
||||
ConfigSlider {
|
||||
label: "Threshold"
|
||||
|
@ -114,6 +116,7 @@ Item {
|
|||
max: 2.0
|
||||
min: 0.0
|
||||
width: 280
|
||||
height:38
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,6 @@ var window = new OverlayWindow({
|
|||
title: 'Bloom',
|
||||
source: qml,
|
||||
width: 285,
|
||||
height: 170,
|
||||
height: 210,
|
||||
});
|
||||
window.closed.connect(function() { Script.stop(); });
|
|
@ -838,11 +838,31 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
|||
}
|
||||
};
|
||||
|
||||
var deleteEntity = function(entityID) {
|
||||
if (rightEquipEntity.targetEntityID === entityID) {
|
||||
rightEquipEntity.endEquipEntity();
|
||||
}
|
||||
if (leftEquipEntity.targetEntityID === entityID) {
|
||||
leftEquipEntity.endEquipEntity();
|
||||
}
|
||||
};
|
||||
|
||||
var clearEntities = function() {
|
||||
if (rightEquipEntity.targetEntityID) {
|
||||
rightEquipEntity.endEquipEntity();
|
||||
}
|
||||
if (leftEquipEntity.targetEntityID) {
|
||||
leftEquipEntity.endEquipEntity();
|
||||
}
|
||||
};
|
||||
|
||||
Messages.subscribe('Hifi-Hand-Grab');
|
||||
Messages.subscribe('Hifi-Hand-Drop');
|
||||
Messages.messageReceived.connect(handleMessage);
|
||||
Controller.mousePressEvent.connect(onMousePress);
|
||||
Controller.keyPressEvent.connect(onKeyPress);
|
||||
Entities.deletingEntity.connect(deleteEntity);
|
||||
Entities.clearingEntities.connect(clearEntities);
|
||||
|
||||
var leftEquipEntity = new EquipEntity(LEFT_HAND);
|
||||
var rightEquipEntity = new EquipEntity(RIGHT_HAND);
|
||||
|
@ -859,6 +879,8 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
|||
Messages.messageReceived.disconnect(handleMessage);
|
||||
Controller.mousePressEvent.disconnect(onMousePress);
|
||||
Controller.keyPressEvent.disconnect(onKeyPress);
|
||||
Entities.deletingEntity.disconnect(deleteEntity);
|
||||
Entities.clearingEntities.disconnect(clearEntities);
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
||||
|
|
|
@ -98,7 +98,7 @@ void TestWindow::beginFrame() {
|
|||
_preparePrimaryFramebuffer.run(_renderContext, primaryFramebuffer);
|
||||
|
||||
DeferredFrameTransformPointer frameTransform;
|
||||
_generateDeferredFrameTransform.run(_renderContext, frameTransform);
|
||||
_generateDeferredFrameTransform.run(_renderContext, glm::vec2(0.0f, 0.0f), frameTransform);
|
||||
|
||||
LightingModelPointer lightingModel;
|
||||
_generateLightingModel.run(_renderContext, lightingModel);
|
||||
|
|
|
@ -17,12 +17,22 @@ exports.handlers = {
|
|||
// directories to scan for jsdoc comments
|
||||
var dirList = [
|
||||
'../../interface/src',
|
||||
'../../interface/src/assets',
|
||||
'../../interface/src/audio',
|
||||
'../../interface/src/avatar',
|
||||
'../../interface/src/commerce',
|
||||
'../../interface/src/devices',
|
||||
'../../interface/src/java',
|
||||
'../../interface/src/networking',
|
||||
'../../interface/src/ui/',
|
||||
'../../interface/src/scripting',
|
||||
'../../interface/src/ui/overlays',
|
||||
'../../interface/src/raypick',
|
||||
'../../libraries/animation/src',
|
||||
'../../libraries/audio-client/src',
|
||||
'../../libraries/audio/src',
|
||||
'../../libraries/avatars/src',
|
||||
'../../libraries/avatars-renderer/src/avatars-renderer',
|
||||
'../../libraries/controllers/src/controllers/',
|
||||
'../../libraries/controllers/src/controllers/impl/',
|
||||
'../../libraries/display-plugins/src/display-plugins/',
|
||||
|
@ -37,6 +47,7 @@ exports.handlers = {
|
|||
'../../libraries/script-engine/src',
|
||||
'../../libraries/shared/src',
|
||||
'../../libraries/shared/src/shared',
|
||||
'../../libraries/ui/src/ui',
|
||||
'../../plugins/oculus/src',
|
||||
'../../plugins/openvr/src',
|
||||
];
|
||||
|
|
Loading…
Reference in a new issue