mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 12:52:45 +02:00
Merge branch 'master' into proceduralMesh
This commit is contained in:
commit
3d05a954bc
55 changed files with 1457 additions and 509 deletions
|
@ -138,7 +138,7 @@ public:
|
|||
/// 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 override;
|
||||
|
||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||
Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||
|
||||
/**jsdoc
|
||||
* @comment Uses the base class's JSDoc.
|
||||
|
|
|
@ -358,7 +358,7 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo
|
|||
nodeData->setNodeVersion(it->second.getNodeVersion());
|
||||
nodeData->setHardwareAddress(nodeConnection.hardwareAddress);
|
||||
nodeData->setMachineFingerprint(nodeConnection.machineFingerprint);
|
||||
|
||||
nodeData->setLastDomainCheckinTimestamp(nodeConnection.lastPingTimestamp);
|
||||
nodeData->setWasAssigned(true);
|
||||
|
||||
// cleanup the PendingAssignedNodeData for this assignment now that it's connecting
|
||||
|
@ -499,6 +499,9 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
|
|||
// set the machine fingerprint passed in the connect request
|
||||
nodeData->setMachineFingerprint(nodeConnection.machineFingerprint);
|
||||
|
||||
// set the last ping timestamp passed in the connect request
|
||||
nodeData->setLastDomainCheckinTimestamp(nodeConnection.lastPingTimestamp);
|
||||
|
||||
// also add an interpolation to DomainServerNodeData so that servers can get username in stats
|
||||
nodeData->addOverrideForKey(USERNAME_UUID_REPLACEMENT_STATS_KEY,
|
||||
uuidStringWithoutCurlyBraces(newNode->getUUID()), username);
|
||||
|
|
|
@ -1068,6 +1068,8 @@ void DomainServer::processListRequestPacket(QSharedPointer<ReceivedMessage> mess
|
|||
// update the connecting hostname in case it has changed
|
||||
nodeData->setPlaceName(nodeRequestData.placeName);
|
||||
|
||||
nodeData->setLastDomainCheckinTimestamp(nodeRequestData.lastPingTimestamp);
|
||||
|
||||
sendDomainListToNode(sendingNode, message->getSenderSockAddr());
|
||||
}
|
||||
|
||||
|
@ -1174,6 +1176,10 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
|||
|
||||
DomainServerNodeData* nodeData = static_cast<DomainServerNodeData*>(node->getLinkedData());
|
||||
|
||||
domainListStream << nodeData->getLastDomainCheckinTimestamp();
|
||||
|
||||
domainListStream << usecTimestampNow();
|
||||
|
||||
// store the nodeInterestSet on this DomainServerNodeData, in case it has changed
|
||||
auto& nodeInterestSet = nodeData->getNodeInterestSet();
|
||||
|
||||
|
|
|
@ -61,6 +61,9 @@ public:
|
|||
void setMachineFingerprint(const QUuid& machineFingerprint) { _machineFingerprint = machineFingerprint; }
|
||||
const QUuid& getMachineFingerprint() { return _machineFingerprint; }
|
||||
|
||||
void setLastDomainCheckinTimestamp(quint64 lastDomainCheckinTimestamp) { _lastDomainCheckinTimestamp = lastDomainCheckinTimestamp; }
|
||||
quint64 getLastDomainCheckinTimestamp() { return _lastDomainCheckinTimestamp; }
|
||||
|
||||
void addOverrideForKey(const QString& key, const QString& value, const QString& overrideValue);
|
||||
void removeOverrideForKey(const QString& key, const QString& value);
|
||||
|
||||
|
@ -93,7 +96,7 @@ private:
|
|||
QString _nodeVersion;
|
||||
QString _hardwareAddress;
|
||||
QUuid _machineFingerprint;
|
||||
|
||||
quint64 _lastDomainCheckinTimestamp;
|
||||
QString _placeName;
|
||||
|
||||
bool _wasAssigned { false };
|
||||
|
|
|
@ -36,6 +36,8 @@ NodeConnectionData NodeConnectionData::fromDataStream(QDataStream& dataStream, c
|
|||
// now the machine fingerprint
|
||||
dataStream >> newHeader.machineFingerprint;
|
||||
}
|
||||
|
||||
dataStream >> newHeader.lastPingTimestamp;
|
||||
|
||||
dataStream >> newHeader.nodeType
|
||||
>> newHeader.publicSockAddr >> newHeader.localSockAddr
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
bool isConnectRequest = true);
|
||||
|
||||
QUuid connectUUID;
|
||||
quint64 lastPingTimestamp{ 0 };
|
||||
NodeType_t nodeType;
|
||||
HifiSockAddr publicSockAddr;
|
||||
HifiSockAddr localSockAddr;
|
||||
|
|
|
@ -58,7 +58,8 @@ Rectangle {
|
|||
if (isLoggedIn) {
|
||||
Commerce.getWalletStatus();
|
||||
} else {
|
||||
// Show some error to the user
|
||||
errorText.text = "There was a problem while retrieving your inventory. " +
|
||||
"Please try closing and re-opening the Avatar app.\n\nLogin status result: " + isLoggedIn;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,11 +67,19 @@ Rectangle {
|
|||
if (walletStatus === 5) {
|
||||
getInventory();
|
||||
} else {
|
||||
// Show some error to the user
|
||||
errorText.text = "There was a problem while retrieving your inventory. " +
|
||||
"Please try closing and re-opening the Avatar app.\n\nWallet status result: " + walletStatus;
|
||||
}
|
||||
}
|
||||
|
||||
onInventoryResult: {
|
||||
if (result.status !== "success") {
|
||||
errorText.text = "There was a problem while retrieving your inventory. " +
|
||||
"Please try closing and re-opening the Avatar app.\n\nInventory status: " + result.status + "\nMessage: " + result.message;
|
||||
} else if (result.data && result.data.assets && result.data.assets.length === 0) {
|
||||
errorText.text = "You have not created any avatars yet! Create an avatar with the Avatar Creator, then close and re-open the Avatar App."
|
||||
}
|
||||
|
||||
avatarAppInventoryModel.handlePage(result.status !== "success" && result.message, result);
|
||||
root.updatePreviewUrl();
|
||||
}
|
||||
|
@ -172,7 +181,7 @@ Rectangle {
|
|||
anchors.bottom: parent.bottom
|
||||
|
||||
AnimatedImage {
|
||||
visible: !inventoryContentsList.visible
|
||||
visible: !inventoryContentsList.visible && !errorText.visible
|
||||
anchors.centerIn: parent
|
||||
width: 72
|
||||
height: width
|
||||
|
@ -181,7 +190,7 @@ Rectangle {
|
|||
|
||||
ListView {
|
||||
id: inventoryContentsList
|
||||
visible: avatarAppInventoryModel.count !== 0
|
||||
visible: avatarAppInventoryModel.count !== 0 && !errorText.visible
|
||||
interactive: contentItem.height > height
|
||||
clip: true
|
||||
model: avatarAppInventoryModel
|
||||
|
@ -196,6 +205,18 @@ Rectangle {
|
|||
standaloneIncompatible: model.standalone_incompatible
|
||||
}
|
||||
}
|
||||
|
||||
HifiStylesUit.GraphikRegular {
|
||||
id: errorText
|
||||
text: ""
|
||||
visible: text !== ""
|
||||
anchors.fill: parent
|
||||
size: 22
|
||||
color: simplifiedUI.colors.text.white
|
||||
wrapMode: Text.Wrap
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ Flickable {
|
|||
id: root
|
||||
contentWidth: parent.width
|
||||
contentHeight: audioColumnLayout.height
|
||||
topMargin: 16
|
||||
bottomMargin: 16
|
||||
topMargin: 24
|
||||
bottomMargin: 24
|
||||
clip: true
|
||||
|
||||
function changePeakValuesEnabled(enabled) {
|
||||
|
@ -73,14 +73,23 @@ Flickable {
|
|||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
height: 30
|
||||
labelText: "People Volume"
|
||||
from: -60
|
||||
to: 10
|
||||
from: simplifiedUI.numericConstants.mutedValue
|
||||
to: 20.0
|
||||
defaultValue: 0.0
|
||||
value: AudioScriptingInterface.getAvatarGain()
|
||||
stepSize: 5.0
|
||||
value: AudioScriptingInterface.avatarGain
|
||||
live: true
|
||||
function updatePeopleGain(sliderValue) {
|
||||
if (AudioScriptingInterface.avatarGain !== sliderValue) {
|
||||
AudioScriptingInterface.avatarGain = sliderValue;
|
||||
}
|
||||
}
|
||||
onValueChanged: {
|
||||
if (AudioScriptingInterface.getAvatarGain() != peopleVolume.value) {
|
||||
AudioScriptingInterface.setAvatarGain(peopleVolume.value);
|
||||
updatePeopleGain(value);
|
||||
}
|
||||
onPressedChanged: {
|
||||
if (!pressed) {
|
||||
updatePeopleGain(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,14 +101,24 @@ Flickable {
|
|||
Layout.topMargin: 2
|
||||
height: 30
|
||||
labelText: "Environment Volume"
|
||||
from: -60
|
||||
to: 10
|
||||
from: simplifiedUI.numericConstants.mutedValue
|
||||
to: 20.0
|
||||
defaultValue: 0.0
|
||||
value: AudioScriptingInterface.getInjectorGain()
|
||||
stepSize: 5.0
|
||||
value: AudioScriptingInterface.serverInjectorGain
|
||||
live: true
|
||||
function updateEnvironmentGain(sliderValue) {
|
||||
if (AudioScriptingInterface.serverInjectorGain !== sliderValue) {
|
||||
AudioScriptingInterface.serverInjectorGain = sliderValue;
|
||||
AudioScriptingInterface.localInjectorGain = sliderValue;
|
||||
}
|
||||
}
|
||||
onValueChanged: {
|
||||
if (AudioScriptingInterface.getInjectorGain() != environmentVolume.value) {
|
||||
AudioScriptingInterface.setInjectorGain(environmentVolume.value);
|
||||
updateEnvironmentGain(value);
|
||||
}
|
||||
onPressedChanged: {
|
||||
if (!pressed) {
|
||||
updateEnvironmentGain(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,14 +130,23 @@ Flickable {
|
|||
Layout.topMargin: 2
|
||||
height: 30
|
||||
labelText: "System Sound Volume"
|
||||
from: -60
|
||||
to: 10
|
||||
from: simplifiedUI.numericConstants.mutedValue
|
||||
to: 20.0
|
||||
defaultValue: 0.0
|
||||
value: AudioScriptingInterface.getSystemInjectorGain()
|
||||
stepSize: 5.0
|
||||
value: AudioScriptingInterface.systemInjectorGain
|
||||
live: true
|
||||
function updateSystemGain(sliderValue) {
|
||||
if (AudioScriptingInterface.systemInjectorGain !== sliderValue) {
|
||||
AudioScriptingInterface.systemInjectorGain = sliderValue;
|
||||
}
|
||||
}
|
||||
onValueChanged: {
|
||||
if (AudioScriptingInterface.getSystemInjectorGain() != systemSoundVolume.value) {
|
||||
AudioScriptingInterface.setSystemInjectorGain(systemSoundVolume.value);
|
||||
updateSystemGain(value);
|
||||
}
|
||||
onPressedChanged: {
|
||||
if (!pressed) {
|
||||
updateSystemGain(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -189,7 +217,7 @@ Flickable {
|
|||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
interactive: false
|
||||
height: contentItem.height
|
||||
spacing: 4
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
clip: true
|
||||
model: AudioScriptingInterface.devices.input
|
||||
delegate: Item {
|
||||
|
@ -200,6 +228,8 @@ Flickable {
|
|||
id: inputDeviceCheckbox
|
||||
anchors.left: parent.left
|
||||
width: parent.width - inputLevel.width
|
||||
height: paintedHeight
|
||||
wrapLabel: false
|
||||
checked: selectedDesktop
|
||||
text: model.devicename
|
||||
ButtonGroup.group: inputDeviceButtonGroup
|
||||
|
@ -288,7 +318,7 @@ Flickable {
|
|||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
interactive: false
|
||||
height: contentItem.height
|
||||
spacing: 4
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
clip: true
|
||||
model: AudioScriptingInterface.devices.output
|
||||
delegate: Item {
|
||||
|
@ -299,8 +329,10 @@ Flickable {
|
|||
id: outputDeviceCheckbox
|
||||
anchors.left: parent.left
|
||||
width: parent.width
|
||||
height: paintedHeight
|
||||
checked: selectedDesktop
|
||||
text: model.devicename
|
||||
wrapLabel: false
|
||||
ButtonGroup.group: outputDeviceButtonGroup
|
||||
onClicked: {
|
||||
AudioScriptingInterface.setOutputDevice(model.info, false); // `false` argument for Desktop mode setting
|
||||
|
|
|
@ -20,8 +20,8 @@ Flickable {
|
|||
id: root
|
||||
contentWidth: parent.width
|
||||
contentHeight: generalColumnLayout.height
|
||||
topMargin: 16
|
||||
bottomMargin: 16
|
||||
topMargin: 24
|
||||
bottomMargin: 24
|
||||
clip: true
|
||||
|
||||
onAvatarNametagModeChanged: {
|
||||
|
@ -63,6 +63,7 @@ Flickable {
|
|||
ColumnLayout {
|
||||
id: avatarNameTagsRadioButtonGroup
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
|
||||
SimplifiedControls.RadioButton {
|
||||
id: avatarNameTagsOff
|
||||
|
@ -110,6 +111,7 @@ Flickable {
|
|||
ColumnLayout {
|
||||
id: performanceRadioButtonGroup
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
|
||||
SimplifiedControls.RadioButton {
|
||||
id: performanceLow
|
||||
|
@ -157,6 +159,7 @@ Flickable {
|
|||
ColumnLayout {
|
||||
id: cameraRadioButtonGroup
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
|
||||
SimplifiedControls.RadioButton {
|
||||
id: firstPerson
|
||||
|
|
|
@ -19,8 +19,8 @@ Flickable {
|
|||
id: root
|
||||
contentWidth: parent.width
|
||||
contentHeight: vrColumnLayout.height
|
||||
topMargin: 16
|
||||
bottomMargin: 16
|
||||
topMargin: 24
|
||||
bottomMargin: 24
|
||||
clip: true
|
||||
|
||||
function changePeakValuesEnabled(enabled) {
|
||||
|
@ -70,6 +70,7 @@ Flickable {
|
|||
id: controlsRadioButtonGroup
|
||||
width: parent.width
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
|
||||
ButtonGroup { id: controlsButtonGroup }
|
||||
|
||||
|
@ -202,7 +203,7 @@ Flickable {
|
|||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
interactive: false
|
||||
height: contentItem.height
|
||||
spacing: 4
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
clip: true
|
||||
model: AudioScriptingInterface.devices.input
|
||||
delegate: Item {
|
||||
|
@ -301,7 +302,7 @@ Flickable {
|
|||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
interactive: false
|
||||
height: contentItem.height
|
||||
spacing: 4
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
clip: true
|
||||
model: AudioScriptingInterface.devices.output
|
||||
delegate: Item {
|
||||
|
|
|
@ -147,7 +147,7 @@ QtObject {
|
|||
}
|
||||
|
||||
readonly property color darkSeparator: "#595959"
|
||||
readonly property color darkBackground: "#1A1A1A"
|
||||
readonly property color darkBackground: "#000000"
|
||||
readonly property color darkBackgroundHighlight: "#575757"
|
||||
readonly property color highlightOnDark: Qt.rgba(1, 1, 1, 0.2)
|
||||
readonly property color white: "#FFFFFF"
|
||||
|
@ -182,9 +182,10 @@ QtObject {
|
|||
}
|
||||
|
||||
readonly property QtObject settings: QtObject {
|
||||
property real subtitleTopMargin: 2
|
||||
property real settingsGroupTopMargin: 10
|
||||
property real spacingBetweenSettings: 48
|
||||
property int subtitleTopMargin: 2
|
||||
property int settingsGroupTopMargin: 24
|
||||
property int spacingBetweenSettings: 48
|
||||
property int spacingBetweenRadiobuttons: 14
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,4 +221,8 @@ QtObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
readonly property QtObject numericConstants: QtObject {
|
||||
readonly property real mutedValue: -60.0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,6 @@ RadioButton {
|
|||
|
||||
contentItem: Text {
|
||||
id: radioButtonLabel
|
||||
height: root.radioButtonRadius
|
||||
font.pixelSize: 14
|
||||
font.family: "Graphik"
|
||||
font.weight: Font.Normal
|
||||
|
@ -99,5 +98,6 @@ RadioButton {
|
|||
enabled: root.enabled
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
leftPadding: radioButtonIndicator.width + root.labelLeftMargin
|
||||
topPadding: -3 // For perfect alignment when using Graphik
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ Item {
|
|||
property alias live: sliderControl.live
|
||||
property alias stepSize: sliderControl.stepSize
|
||||
property alias snapMode: sliderControl.snapMode
|
||||
property alias pressed: sliderControl.pressed
|
||||
property real defaultValue: 0.0
|
||||
|
||||
HifiStylesUit.GraphikRegular {
|
||||
|
|
|
@ -203,7 +203,10 @@ Rectangle {
|
|||
|
||||
Image {
|
||||
id: outputDeviceButton
|
||||
property bool outputMuted: false
|
||||
property bool outputMuted: AudioScriptingInterface.avatarGain === simplifiedUI.numericConstants.mutedValue &&
|
||||
AudioScriptingInterface.serverInjectorGain === simplifiedUI.numericConstants.mutedValue &&
|
||||
AudioScriptingInterface.localInjectorGain === simplifiedUI.numericConstants.mutedValue &&
|
||||
AudioScriptingInterface.systemInjectorGain === simplifiedUI.numericConstants.mutedValue
|
||||
source: outputDeviceButton.outputMuted ? "./images/outputDeviceMuted.svg" : "./images/outputDeviceLoud.svg"
|
||||
anchors.centerIn: parent
|
||||
width: 20
|
||||
|
@ -228,13 +231,16 @@ Rectangle {
|
|||
}
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
outputDeviceButton.outputMuted = !outputDeviceButton.outputMuted;
|
||||
|
||||
if (!outputDeviceButton.outputMuted && !AudioScriptingInterface.muted) {
|
||||
AudioScriptingInterface.muted = true;
|
||||
}
|
||||
|
||||
sendToScript({
|
||||
"source": "SimplifiedTopBar.qml",
|
||||
"method": "setOutputMuted",
|
||||
"data": {
|
||||
"outputMuted": outputDeviceButton.outputMuted
|
||||
"outputMuted": !outputDeviceButton.outputMuted
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -242,6 +248,69 @@ Rectangle {
|
|||
}
|
||||
|
||||
|
||||
Item {
|
||||
id: statusButtonContainer
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: outputDeviceButtonContainer.right
|
||||
anchors.leftMargin: 8
|
||||
width: 36
|
||||
height: width
|
||||
|
||||
Rectangle {
|
||||
id: statusButton
|
||||
property string currentStatus
|
||||
anchors.centerIn: parent
|
||||
anchors.horizontalCenterOffset: 1
|
||||
anchors.verticalCenterOffset: 2
|
||||
width: 13
|
||||
height: width
|
||||
radius: width/2
|
||||
visible: false
|
||||
}
|
||||
|
||||
ColorOverlay {
|
||||
anchors.fill: statusButton
|
||||
opacity: statusButton.currentStatus ? 1 : 0
|
||||
source: statusButton
|
||||
color: if (statusButton.currentStatus === "busy") {
|
||||
"#ff001a"
|
||||
} else if (statusButton.currentStatus === "available") {
|
||||
"#009036"
|
||||
} else if (statusButton.currentStatus) {
|
||||
"#ffed00"
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: focusIcon
|
||||
source: "./images/focus.svg"
|
||||
opacity: statusButtonMouseArea.containsMouse ? 1.0 : (statusButton.currentStatus === "busy" ? 0.7 : 0.3)
|
||||
anchors.centerIn: parent
|
||||
width: 36
|
||||
height: 20
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: statusButtonMouseArea
|
||||
anchors.fill: parent
|
||||
enabled: statusButton.currentStatus
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
Tablet.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
|
||||
sendToScript({
|
||||
"source": "SimplifiedTopBar.qml",
|
||||
"method": "toggleStatus"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Item {
|
||||
id: hmdButtonContainer
|
||||
|
@ -280,11 +349,6 @@ Rectangle {
|
|||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
var displayPluginCount = Window.getDisplayPluginCount();
|
||||
if (HMD.active) {
|
||||
// This next line seems backwards and shouldn't be necessary - the NOTIFY handler should
|
||||
// result in `displayModeImage.source` changing automatically - but that's not working.
|
||||
// This is working. So, I'm keeping it.
|
||||
displayModeImage.source = "./images/vrMode.svg";
|
||||
|
||||
// Switch to desktop mode - selects first VR display plugin
|
||||
for (var i = 0; i < displayPluginCount; i++) {
|
||||
if (!Window.isDisplayPluginHmd(i)) {
|
||||
|
@ -293,11 +357,6 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// This next line seems backwards and shouldn't be necessary - the NOTIFY handler should
|
||||
// result in `displayModeImage.source` changing automatically - but that's not working.
|
||||
// This is working. So, I'm keeping it.
|
||||
displayModeImage.source = "./images/desktopMode.svg";
|
||||
|
||||
// Switch to VR mode - selects first HMD display plugin
|
||||
for (var i = 0; i < displayPluginCount; i++) {
|
||||
if (Window.isDisplayPluginHmd(i)) {
|
||||
|
@ -397,8 +456,8 @@ Rectangle {
|
|||
}
|
||||
break;
|
||||
|
||||
case "updateOutputMuted":
|
||||
outputDeviceButton.outputMuted = message.data.outputMuted;
|
||||
case "updateStatusButton":
|
||||
statusButton.currentStatus = message.data.currentStatus;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="32" height="19.001" fill="none" version="1.1" viewBox="0 0 32 19.001" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<path d="m7 19h-3.542c-0.46115 0.0089-0.91905-0.0192-1.3443-0.2001-0.42525-0.1808-0.80846-0.4496-1.125-0.7892-0.3234-0.3355-0.57737-0.7329-0.74698-1.1691-0.16962-0.4362-0.25146-0.9023-0.24076-1.3709v-5.47c-0.0066251-0.46326 0.078429-0.92318 0.25019-1.3526 0.17176-0.42944 0.42674-0.81971 0.74988-1.1478 0.32313-0.32808 0.70786-0.58732 1.1316-0.76244 0.42368-0.17511 0.87772-0.26255 1.3353-0.25716h1.4718c0.03732-0.87492 0.24704-1.7335 0.61682-2.5251s0.89216-1.5005 1.5364-2.0849c1.2696-1.2214 3.1558-1.8924 4.9071-1.87l8 2.2471e-5c1.7402-0.025877 3.6023 0.64637 4.8546 1.87 1.2793 1.2015 2.0626 2.8482 2.1927 4.61h1.3178c0.946-0.01712 1.8609 0.3419 2.5484 1 0.3479 0.31321 0.625 0.69864 0.8125 1.13 0.1875 0.43142 0.2809 0.89867 0.274 1.37v5.47c0.0037 0.4767-0.091 0.9488-0.2781 1.3863-0.1871 0.4374-0.376 0.8397-0.7219 1.163-0.3346 0.3376-0.5167 0.5951-0.9542 0.7753-0.4376 0.1803-1.2083 0.2298-1.6807 0.2247h-3.3624v-12.049c0.0051-0.65734-0.1179-1.3092-0.362-1.9184-0.2441-0.60915-0.6044-1.1636-1.0603-1.6316-0.4213-0.48067-0.9384-0.86553-1.5173-1.1292-0.5788-0.26371-1.4283-0.27101-2.0631-0.27147h-8c-0.6475-0.00706-1.4451-0.00352-2.0378 0.26031-0.59274 0.26384-1.1231 0.65262-1.5556 1.1404-0.45594 0.46802-0.81626 1.0225-1.0603 1.6316-0.24406 0.60916-0.35129 1.261-0.34623 1.9184zm-3.4717-2h1.4717v-8.4793h-1.4717c-0.92847 0-1.5283 0.49-1.5283 1.48v5.47c0.01975 0.99 0.59981 1.5293 1.5283 1.5293zm26.472-6.9993c8e-3 -0.84434-0.6554-1.4883-1.5049-1.48h-1.4478v8.4793h1.4478c0.8319 0.0109 1.5175-0.722 1.5049-1.5293z" fill="#fff"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 5.2 KiB |
|
@ -49,17 +49,13 @@
|
|||
#include "DeferredLightingEffect.h"
|
||||
#include "PickManager.h"
|
||||
|
||||
#include "LightingModel.h"
|
||||
#include "AmbientOcclusionEffect.h"
|
||||
#include "RenderShadowTask.h"
|
||||
#include "AntialiasingEffect.h"
|
||||
|
||||
#include "scripting/SettingsScriptingInterface.h"
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
#include "SpeechRecognizer.h"
|
||||
#endif
|
||||
|
||||
#include "MeshPartPayload.h"
|
||||
#include "scripting/RenderScriptingInterface.h"
|
||||
|
||||
extern bool DEV_DECIMATE_TEXTURES;
|
||||
|
||||
|
@ -369,45 +365,14 @@ Menu::Menu() {
|
|||
// Developer > Render >>>
|
||||
MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render");
|
||||
|
||||
action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AntiAliasing, 0, true);
|
||||
connect(action, &QAction::triggered, [action] {
|
||||
auto renderConfig = qApp->getRenderEngine()->getConfiguration();
|
||||
if (renderConfig) {
|
||||
auto mainViewJitterCamConfig = renderConfig->getConfig<JitterSample>("RenderMainView.JitterCam");
|
||||
auto mainViewAntialiasingConfig = renderConfig->getConfig<Antialiasing>("RenderMainView.Antialiasing");
|
||||
if (mainViewJitterCamConfig && mainViewAntialiasingConfig) {
|
||||
if (action->isChecked()) {
|
||||
mainViewJitterCamConfig->play();
|
||||
mainViewAntialiasingConfig->setDebugFXAA(false);
|
||||
} else {
|
||||
mainViewJitterCamConfig->none();
|
||||
mainViewAntialiasingConfig->setDebugFXAA(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AntiAliasing, 0, RenderScriptingInterface::getInstance()->getAntialiasingEnabled(),
|
||||
RenderScriptingInterface::getInstance(), SLOT(setAntialiasingEnabled(bool)));
|
||||
|
||||
action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Shadows, 0, true);
|
||||
connect(action, &QAction::triggered, [action] {
|
||||
auto renderConfig = qApp->getRenderEngine()->getConfiguration();
|
||||
if (renderConfig) {
|
||||
auto lightingModelConfig = renderConfig->getConfig<MakeLightingModel>("RenderMainView.LightingModel");
|
||||
if (lightingModelConfig) {
|
||||
lightingModelConfig->setShadow(action->isChecked());
|
||||
}
|
||||
}
|
||||
});
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Shadows, 0, RenderScriptingInterface::getInstance()->getShadowsEnabled(),
|
||||
RenderScriptingInterface::getInstance(), SLOT(setShadowsEnabled(bool)));
|
||||
|
||||
action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AmbientOcclusion, 0, false);
|
||||
connect(action, &QAction::triggered, [action] {
|
||||
auto renderConfig = qApp->getRenderEngine()->getConfiguration();
|
||||
if (renderConfig) {
|
||||
auto lightingModelConfig = renderConfig->getConfig<MakeLightingModel>("RenderMainView.LightingModel");
|
||||
if (lightingModelConfig) {
|
||||
lightingModelConfig->setAmbientOcclusion(action->isChecked());
|
||||
}
|
||||
}
|
||||
});
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AmbientOcclusion, 0, RenderScriptingInterface::getInstance()->getAmbientOcclusionEnabled(),
|
||||
RenderScriptingInterface::getInstance(), SLOT(setAmbientOcclusionEnabled(bool)));
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::WorldAxes);
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DefaultSkybox, 0, true);
|
||||
|
|
|
@ -2367,6 +2367,11 @@ void MyAvatar::clearJointsData() {
|
|||
}
|
||||
|
||||
void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setSkeletonModelURL", Q_ARG(const QUrl&, skeletonModelURL));
|
||||
return;
|
||||
}
|
||||
|
||||
_skeletonModelChangeCount++;
|
||||
int skeletonModelChangeCount = _skeletonModelChangeCount;
|
||||
|
||||
|
|
|
@ -2409,7 +2409,7 @@ private:
|
|||
void updateEyeContactTarget(float deltaTime);
|
||||
|
||||
// These are made private for MyAvatar so that you will use the "use" methods instead
|
||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||
Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||
|
||||
virtual void updatePalms() override {}
|
||||
void lateUpdatePalms();
|
||||
|
|
|
@ -75,6 +75,7 @@ int main(int argc, const char* argv[]) {
|
|||
QCommandLineOption helpOption = parser.addHelpOption();
|
||||
|
||||
QCommandLineOption urlOption("url", "", "value");
|
||||
QCommandLineOption noLauncherOption("no-launcher", "Do not execute the launcher");
|
||||
QCommandLineOption noUpdaterOption("no-updater", "Do not show auto-updater");
|
||||
QCommandLineOption checkMinSpecOption("checkMinSpec", "Check if machine meets minimum specifications");
|
||||
QCommandLineOption runServerOption("runServer", "Whether to run the server");
|
||||
|
@ -84,6 +85,7 @@ int main(int argc, const char* argv[]) {
|
|||
QCommandLineOption overrideScriptsPathOption(SCRIPTS_SWITCH, "set scripts <path>", "path");
|
||||
|
||||
parser.addOption(urlOption);
|
||||
parser.addOption(noLauncherOption);
|
||||
parser.addOption(noUpdaterOption);
|
||||
parser.addOption(checkMinSpecOption);
|
||||
parser.addOption(runServerOption);
|
||||
|
@ -106,6 +108,49 @@ int main(int argc, const char* argv[]) {
|
|||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
QString applicationPath;
|
||||
{
|
||||
// A temporary application instance is needed to get the location of the running executable
|
||||
// Tests using high_resolution_clock show that this takes about 30-50 microseconds (on my machine, YMMV)
|
||||
// If we wanted to avoid the QCoreApplication, we would need to write our own
|
||||
// cross-platform implementation.
|
||||
QCoreApplication tempApp(argc, const_cast<char**>(argv));
|
||||
applicationPath = QCoreApplication::applicationDirPath();
|
||||
}
|
||||
|
||||
static const QString APPLICATION_CONFIG_FILENAME = "config.json";
|
||||
QDir applicationDir(applicationPath);
|
||||
QFile configFile(applicationDir.filePath(APPLICATION_CONFIG_FILENAME));
|
||||
|
||||
if (configFile.exists()) {
|
||||
if (!configFile.open(QIODevice::ReadOnly)) {
|
||||
qWarning() << "Found application config, but could not open it";
|
||||
} else {
|
||||
auto contents = configFile.readAll();
|
||||
QJsonParseError error;
|
||||
|
||||
auto doc = QJsonDocument::fromJson(contents, &error);
|
||||
if (error.error) {
|
||||
qWarning() << "Found application config, but could not parse it: " << error.errorString();
|
||||
} else {
|
||||
static const QString LAUNCHER_PATH_KEY = "launcherPath";
|
||||
QString launcherPath = doc.object()[LAUNCHER_PATH_KEY].toString();
|
||||
if (!launcherPath.isEmpty()) {
|
||||
if (!parser.isSet(noLauncherOption)) {
|
||||
qDebug() << "Found a launcherPath in application config. Starting launcher.";
|
||||
QProcess launcher;
|
||||
launcher.setProgram(launcherPath);
|
||||
launcher.startDetached();
|
||||
return 0;
|
||||
} else {
|
||||
qDebug() << "Found a launcherPath in application config, but the launcher"
|
||||
" has been suppressed. Continuing normal execution.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Early check for --traceFile argument
|
||||
auto tracer = DependencyManager::set<tracing::Tracer>();
|
||||
const char * traceFile = nullptr;
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
//
|
||||
|
||||
#include "SafeLanding.h"
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "EntityTreeRenderer.h"
|
||||
|
@ -35,24 +34,26 @@ bool SafeLanding::SequenceLessThan::operator()(const int& a, const int& b) const
|
|||
}
|
||||
|
||||
void SafeLanding::startEntitySequence(QSharedPointer<EntityTreeRenderer> entityTreeRenderer) {
|
||||
auto entityTree = entityTreeRenderer->getTree();
|
||||
|
||||
if (entityTree) {
|
||||
Locker lock(_lock);
|
||||
_entityTree = entityTree;
|
||||
_trackedEntities.clear();
|
||||
_trackingEntities = true;
|
||||
_maxTrackedEntityCount = 0;
|
||||
connect(std::const_pointer_cast<EntityTree>(_entityTree).get(),
|
||||
&EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity);
|
||||
connect(std::const_pointer_cast<EntityTree>(_entityTree).get(),
|
||||
&EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity);
|
||||
if (!entityTreeRenderer.isNull()) {
|
||||
auto entityTree = entityTreeRenderer->getTree();
|
||||
if (entityTree) {
|
||||
Locker lock(_lock);
|
||||
_entityTreeRenderer = entityTreeRenderer;
|
||||
_trackedEntities.clear();
|
||||
_trackingEntities = true;
|
||||
_maxTrackedEntityCount = 0;
|
||||
connect(std::const_pointer_cast<EntityTree>(entityTree).get(),
|
||||
&EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity, Qt::DirectConnection);
|
||||
connect(std::const_pointer_cast<EntityTree>(entityTree).get(),
|
||||
&EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity);
|
||||
|
||||
_sequenceNumbers.clear();
|
||||
_initialStart = INVALID_SEQUENCE;
|
||||
_initialEnd = INVALID_SEQUENCE;
|
||||
_startTime = usecTimestampNow();
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(&ElevatedPriority);
|
||||
_sequenceNumbers.clear();
|
||||
_initialStart = INVALID_SEQUENCE;
|
||||
_initialEnd = INVALID_SEQUENCE;
|
||||
_startTime = usecTimestampNow();
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(&ElevatedPriority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,7 +71,12 @@ void SafeLanding::stopEntitySequence() {
|
|||
void SafeLanding::addTrackedEntity(const EntityItemID& entityID) {
|
||||
if (_trackingEntities) {
|
||||
Locker lock(_lock);
|
||||
EntityItemPointer entity = _entityTree->findEntityByID(entityID);
|
||||
|
||||
if (_entityTreeRenderer.isNull() || _entityTreeRenderer->getTree() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityItemPointer entity = _entityTreeRenderer->getTree()->findEntityByID(entityID);
|
||||
|
||||
if (entity && !entity->isLocalEntity() && entity->getCreated() < _startTime) {
|
||||
|
||||
|
@ -111,7 +117,7 @@ bool SafeLanding::isLoadSequenceComplete() {
|
|||
Locker lock(_lock);
|
||||
_initialStart = INVALID_SEQUENCE;
|
||||
_initialEnd = INVALID_SEQUENCE;
|
||||
_entityTree = nullptr;
|
||||
_entityTreeRenderer.clear();
|
||||
_trackingEntities = false; // Don't track anything else that comes in.
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(StandardPriority);
|
||||
}
|
||||
|
@ -158,7 +164,7 @@ bool SafeLanding::isSequenceNumbersComplete() {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool isEntityPhysicsReady(const EntityItemPointer& entity) {
|
||||
bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) {
|
||||
if (entity && !entity->getCollisionless()) {
|
||||
const auto& entityType = entity->getType();
|
||||
if (entityType == EntityTypes::Model) {
|
||||
|
@ -168,7 +174,10 @@ bool isEntityPhysicsReady(const EntityItemPointer& entity) {
|
|||
bool hasAABox;
|
||||
entity->getAABox(hasAABox);
|
||||
if (hasAABox && downloadedCollisionTypes.count(modelEntity->getShapeType()) != 0) {
|
||||
return (!entity->shouldBePhysical() || entity->isInPhysicsSimulation() || modelEntity->computeShapeFailedToLoad());
|
||||
auto space = _entityTreeRenderer->getWorkloadSpace();
|
||||
uint8_t region = space ? space->getRegion(entity->getSpaceIndex()) : (uint8_t)workload::Region::INVALID;
|
||||
bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical();
|
||||
return (!shouldBePhysical || entity->isInPhysicsSimulation() || modelEntity->computeShapeFailedToLoad());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,13 +38,14 @@ private slots:
|
|||
|
||||
private:
|
||||
bool isSequenceNumbersComplete();
|
||||
bool isEntityPhysicsReady(const EntityItemPointer& entity);
|
||||
void debugDumpSequenceIDs() const;
|
||||
bool isEntityLoadingComplete();
|
||||
|
||||
std::mutex _lock;
|
||||
using Locker = std::lock_guard<std::mutex>;
|
||||
bool _trackingEntities { false };
|
||||
EntityTreePointer _entityTree;
|
||||
QSharedPointer<EntityTreeRenderer> _entityTreeRenderer;
|
||||
using EntityMap = std::map<EntityItemID, EntityItemPointer>;
|
||||
EntityMap _trackedEntities;
|
||||
|
||||
|
|
|
@ -400,10 +400,19 @@ void Audio::setReverbOptions(const AudioEffectOptions* options) {
|
|||
}
|
||||
|
||||
void Audio::setAvatarGain(float gain) {
|
||||
bool changed = false;
|
||||
if (getAvatarGain() != gain) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
// ask the NodeList to set the master avatar gain
|
||||
DependencyManager::get<NodeList>()->setAvatarGain(QUuid(), gain);
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
emit avatarGainChanged(gain);
|
||||
}
|
||||
}
|
||||
|
||||
float Audio::getAvatarGain() {
|
||||
|
@ -413,10 +422,19 @@ float Audio::getAvatarGain() {
|
|||
}
|
||||
|
||||
void Audio::setInjectorGain(float gain) {
|
||||
bool changed = false;
|
||||
if (getInjectorGain() != gain) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
// ask the NodeList to set the audio injector gain
|
||||
DependencyManager::get<NodeList>()->setInjectorGain(gain);
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
emit serverInjectorGainChanged(gain);
|
||||
}
|
||||
}
|
||||
|
||||
float Audio::getInjectorGain() {
|
||||
|
@ -426,6 +444,11 @@ float Audio::getInjectorGain() {
|
|||
}
|
||||
|
||||
void Audio::setLocalInjectorGain(float gain) {
|
||||
bool changed = false;
|
||||
if (getLocalInjectorGain() != gain) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
if (_localInjectorGain != gain) {
|
||||
_localInjectorGain = gain;
|
||||
|
@ -436,6 +459,11 @@ void Audio::setLocalInjectorGain(float gain) {
|
|||
DependencyManager::get<AudioClient>()->setLocalInjectorGain(gain);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (changed) {
|
||||
emit localInjectorGainChanged(gain);
|
||||
}
|
||||
}
|
||||
|
||||
float Audio::getLocalInjectorGain() {
|
||||
|
@ -445,6 +473,11 @@ float Audio::getLocalInjectorGain() {
|
|||
}
|
||||
|
||||
void Audio::setSystemInjectorGain(float gain) {
|
||||
bool changed = false;
|
||||
if (getSystemInjectorGain() != gain) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
if (_systemInjectorGain != gain) {
|
||||
_systemInjectorGain = gain;
|
||||
|
@ -455,6 +488,10 @@ void Audio::setSystemInjectorGain(float gain) {
|
|||
DependencyManager::get<AudioClient>()->setSystemInjectorGain(gain);
|
||||
}
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
emit systemInjectorGainChanged(gain);
|
||||
}
|
||||
}
|
||||
|
||||
float Audio::getSystemInjectorGain() {
|
||||
|
|
|
@ -66,6 +66,10 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable {
|
|||
* @property {boolean} pushToTalkHMD - <code>true</code> if HMD push-to-talk is enabled, otherwise <code>false</code>.
|
||||
* @property {boolean} pushingToTalk - <code>true</code> if the user is currently pushing-to-talk, otherwise
|
||||
* <code>false</code>.
|
||||
* @property {float} avatarGain - The gain (relative volume) that avatars' voices are played at. This gain is used at the server.
|
||||
* @property {float} localInjectorGain - The gain (relative volume) that local injectors (local environment sounds) are played at.
|
||||
* @property {float} serverInjectorGain - The gain (relative volume) that server injectors (server environment sounds) are played at. This gain is used at the server.
|
||||
* @property {float} systemInjectorGain - The gain (relative volume) that system sounds are played at.
|
||||
*
|
||||
* @comment The following properties are from AudioScriptingInterface.h.
|
||||
* @property {boolean} isStereoInput - <code>true</code> if the input audio is being used in stereo, otherwise
|
||||
|
@ -90,6 +94,10 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable {
|
|||
Q_PROPERTY(bool pushToTalkDesktop READ getPTTDesktop WRITE setPTTDesktop NOTIFY pushToTalkDesktopChanged)
|
||||
Q_PROPERTY(bool pushToTalkHMD READ getPTTHMD WRITE setPTTHMD NOTIFY pushToTalkHMDChanged)
|
||||
Q_PROPERTY(bool pushingToTalk READ getPushingToTalk WRITE setPushingToTalk NOTIFY pushingToTalkChanged)
|
||||
Q_PROPERTY(float avatarGain READ getAvatarGain WRITE setAvatarGain NOTIFY avatarGainChanged)
|
||||
Q_PROPERTY(float localInjectorGain READ getLocalInjectorGain WRITE setLocalInjectorGain NOTIFY localInjectorGainChanged)
|
||||
Q_PROPERTY(float serverInjectorGain READ getInjectorGain WRITE setInjectorGain NOTIFY serverInjectorGainChanged)
|
||||
Q_PROPERTY(float systemInjectorGain READ getSystemInjectorGain WRITE setSystemInjectorGain NOTIFY systemInjectorGainChanged)
|
||||
|
||||
public:
|
||||
static QString AUDIO;
|
||||
|
@ -412,6 +420,38 @@ signals:
|
|||
*/
|
||||
void pushingToTalkChanged(bool talking);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the avatar gain changes.
|
||||
* @function Audio.avatarGainChanged
|
||||
* @param {float} gain - The new avatar gain value.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void avatarGainChanged(float gain);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the local injector gain changes.
|
||||
* @function Audio.localInjectorGainChanged
|
||||
* @param {float} gain - The new local injector gain value.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void localInjectorGainChanged(float gain);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the server injector gain changes.
|
||||
* @function Audio.serverInjectorGainChanged
|
||||
* @param {float} gain - The new server injector gain value.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void serverInjectorGainChanged(float gain);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the system injector gain changes.
|
||||
* @function Audio.systemInjectorGainChanged
|
||||
* @param {float} gain - The new system injector gain value.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void systemInjectorGainChanged(float gain);
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
//
|
||||
#include "RenderScriptingInterface.h"
|
||||
|
||||
#include "LightingModel.h"
|
||||
#include "AntialiasingEffect.h"
|
||||
|
||||
const QString DEFERRED = "deferred";
|
||||
const QString FORWARD = "forward";
|
||||
|
||||
|
@ -17,6 +20,9 @@ RenderScriptingInterface* RenderScriptingInterface::getInstance() {
|
|||
|
||||
RenderScriptingInterface::RenderScriptingInterface() {
|
||||
setRenderMethod((render::Args::RenderMethod)_renderMethodSetting.get() == render::Args::RenderMethod::DEFERRED ? DEFERRED : FORWARD);
|
||||
setShadowsEnabled(_shadowsEnabledSetting.get());
|
||||
setAmbientOcclusionEnabled(_ambientOcclusionEnabledSetting.get());
|
||||
setAntialiasingEnabled(_antialiasingEnabledSetting.get());
|
||||
}
|
||||
|
||||
QString RenderScriptingInterface::getRenderMethod() {
|
||||
|
@ -24,6 +30,11 @@ QString RenderScriptingInterface::getRenderMethod() {
|
|||
}
|
||||
|
||||
void RenderScriptingInterface::setRenderMethod(const QString& renderMethod) {
|
||||
render::Args::RenderMethod newMethod = renderMethod == FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED;
|
||||
if (_renderMethodSetting.get() == newMethod) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setRenderMethod", Q_ARG(const QString&, renderMethod));
|
||||
return;
|
||||
|
@ -31,14 +42,81 @@ void RenderScriptingInterface::setRenderMethod(const QString& renderMethod) {
|
|||
|
||||
auto config = dynamic_cast<task::SwitchConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.DeferredForwardSwitch"));
|
||||
if (config) {
|
||||
if (renderMethod == DEFERRED) {
|
||||
_renderMethodSetting.set(render::Args::RenderMethod::DEFERRED);
|
||||
config->setBranch(render::Args::RenderMethod::DEFERRED);
|
||||
emit config->dirtyEnabled();
|
||||
} else if (renderMethod == FORWARD) {
|
||||
_renderMethodSetting.set(render::Args::RenderMethod::FORWARD);
|
||||
config->setBranch(render::Args::RenderMethod::FORWARD);
|
||||
emit config->dirtyEnabled();
|
||||
_renderMethodSetting.set(newMethod);
|
||||
config->setBranch(newMethod);
|
||||
emit config->dirtyEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderScriptingInterface::getShadowsEnabled() {
|
||||
return _shadowsEnabledSetting.get();
|
||||
}
|
||||
|
||||
void RenderScriptingInterface::setShadowsEnabled(bool enabled) {
|
||||
if (_shadowsEnabledSetting.get() == enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setShadowsEnabled", Q_ARG(bool, enabled));
|
||||
return;
|
||||
}
|
||||
|
||||
auto lightingModelConfig = qApp->getRenderEngine()->getConfiguration()->getConfig<MakeLightingModel>("RenderMainView.LightingModel");
|
||||
if (lightingModelConfig) {
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::Shadows, enabled);
|
||||
_shadowsEnabledSetting.set(enabled);
|
||||
lightingModelConfig->setShadow(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderScriptingInterface::getAmbientOcclusionEnabled() {
|
||||
return _ambientOcclusionEnabledSetting.get();
|
||||
}
|
||||
|
||||
void RenderScriptingInterface::setAmbientOcclusionEnabled(bool enabled) {
|
||||
if (_ambientOcclusionEnabledSetting.get() == enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setAmbientOcclusionEnabled", Q_ARG(bool, enabled));
|
||||
return;
|
||||
}
|
||||
|
||||
auto lightingModelConfig = qApp->getRenderEngine()->getConfiguration()->getConfig<MakeLightingModel>("RenderMainView.LightingModel");
|
||||
if (lightingModelConfig) {
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::AmbientOcclusion, enabled);
|
||||
_ambientOcclusionEnabledSetting.set(enabled);
|
||||
lightingModelConfig->setAmbientOcclusion(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderScriptingInterface::getAntialiasingEnabled() {
|
||||
return _antialiasingEnabledSetting.get();
|
||||
}
|
||||
|
||||
void RenderScriptingInterface::setAntialiasingEnabled(bool enabled) {
|
||||
if (_antialiasingEnabledSetting.get() == enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setAntialiasingEnabled", Q_ARG(bool, enabled));
|
||||
return;
|
||||
}
|
||||
|
||||
auto mainViewJitterCamConfig = qApp->getRenderEngine()->getConfiguration()->getConfig<JitterSample>("RenderMainView.JitterCam");
|
||||
auto mainViewAntialiasingConfig = qApp->getRenderEngine()->getConfiguration()->getConfig<Antialiasing>("RenderMainView.Antialiasing");
|
||||
if (mainViewJitterCamConfig && mainViewAntialiasingConfig) {
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::AntiAliasing, enabled);
|
||||
_antialiasingEnabledSetting.set(enabled);
|
||||
if (enabled) {
|
||||
mainViewJitterCamConfig->play();
|
||||
mainViewAntialiasingConfig->setDebugFXAA(false);
|
||||
} else {
|
||||
mainViewJitterCamConfig->none();
|
||||
mainViewAntialiasingConfig->setDebugFXAA(true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,6 +26,9 @@
|
|||
class RenderScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString renderMethod READ getRenderMethod WRITE setRenderMethod)
|
||||
Q_PROPERTY(bool shadowsEnabled READ getShadowsEnabled WRITE setShadowsEnabled)
|
||||
Q_PROPERTY(bool ambientOcclusionEnabled READ getAmbientOcclusionEnabled WRITE setAmbientOcclusionEnabled)
|
||||
Q_PROPERTY(bool antialiasingEnabled READ getAntialiasingEnabled WRITE setAntialiasingEnabled)
|
||||
|
||||
public:
|
||||
RenderScriptingInterface();
|
||||
|
@ -37,8 +40,8 @@ public slots:
|
|||
* Get a config for a job by name
|
||||
* @function Render.getConfig
|
||||
* @param {string} name - Can be:
|
||||
* - <job_name>. Search for the first job named job_name traversing the the sub graph of task and jobs (from this task as root)
|
||||
* - <parent_name>.[<sub_parent_names>.]<job_name>. Allows you to first look for the parent_name job (from this task as root) and then search from there for the
|
||||
* - <job_name>: Search for the first job named job_name traversing the the sub graph of task and jobs (from this task as root)
|
||||
* - <parent_name>.[<sub_parent_names>.]<job_name>: Allows you to first look for the parent_name job (from this task as root) and then search from there for the
|
||||
* optional sub_parent_names and finally from there looking for the job_name (assuming every job in the path is found)
|
||||
* @returns {object} The sub job config.
|
||||
*/
|
||||
|
@ -58,8 +61,53 @@ public slots:
|
|||
*/
|
||||
void setRenderMethod(const QString& renderMethod);
|
||||
|
||||
/**jsdoc
|
||||
* Whether or not shadows are enabled
|
||||
* @function Render.getShadowsEnabled
|
||||
* @returns {bool} <code>true</code> if shadows are enabled, otherwise <code>false</code>
|
||||
*/
|
||||
bool getShadowsEnabled();
|
||||
|
||||
/**jsdoc
|
||||
* Enables or disables shadows
|
||||
* @function Render.setShadowsEnabled
|
||||
* @param {bool} enabled - <code>true</code> to enable shadows, <code>false</code> to disable them
|
||||
*/
|
||||
void setShadowsEnabled(bool enabled);
|
||||
|
||||
/**jsdoc
|
||||
* Whether or not ambient occlusion is enabled
|
||||
* @function Render.getAmbientOcclusionEnabled
|
||||
* @returns {bool} <code>true</code> if ambient occlusion is enabled, otherwise <code>false</code>
|
||||
*/
|
||||
bool getAmbientOcclusionEnabled();
|
||||
|
||||
/**jsdoc
|
||||
* Enables or disables ambient occlusion
|
||||
* @function Render.setAmbientOcclusionEnabled
|
||||
* @param {bool} enabled - <code>true</code> to enable ambient occlusion, <code>false</code> to disable it
|
||||
*/
|
||||
void setAmbientOcclusionEnabled(bool enabled);
|
||||
|
||||
/**jsdoc
|
||||
* Whether or not anti-aliasing is enabled
|
||||
* @function Render.getAntialiasingEnabled
|
||||
* @returns {bool} <code>true</code> if anti-aliasing is enabled, otherwise <code>false</code>
|
||||
*/
|
||||
bool getAntialiasingEnabled();
|
||||
|
||||
/**jsdoc
|
||||
* Enables or disables anti-aliasing
|
||||
* @function Render.setAntialiasingEnabled
|
||||
* @param {bool} enabled - <code>true</code> to enable anti-aliasing, <code>false</code> to disable it
|
||||
*/
|
||||
void setAntialiasingEnabled(bool enabled);
|
||||
|
||||
private:
|
||||
Setting::Handle<int> _renderMethodSetting { "renderMethod", RENDER_FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED };
|
||||
Setting::Handle<bool> _shadowsEnabledSetting { "shadowsEnabled", true };
|
||||
Setting::Handle<bool> _ambientOcclusionEnabledSetting { "ambientOcclusionEnabled", false };
|
||||
Setting::Handle<bool> _antialiasingEnabledSetting { "antialiasingEnabled", true };
|
||||
};
|
||||
|
||||
#endif // hifi_RenderScriptingInterface_h
|
||||
|
|
|
@ -44,13 +44,14 @@ SelectionScriptingInterface::SelectionScriptingInterface() {
|
|||
}
|
||||
|
||||
/**jsdoc
|
||||
* The type of a specific item in a selection list.
|
||||
* <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>"avatar"</code></td><td>The item is an avatar.</td></tr>
|
||||
* <tr><td><code>"entity"</code></td><td>The item is an entity.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} Selection.ItemType
|
||||
|
@ -245,9 +246,10 @@ void SelectionScriptingInterface::printList(const QString& listName) {
|
|||
}
|
||||
|
||||
/**jsdoc
|
||||
* A selection list.
|
||||
* @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[]} avatars - The IDs of the avatars in the selection list.
|
||||
* @property {Uuid[]} entities - The IDs of the entities in the selection list.
|
||||
*/
|
||||
QVariantMap SelectionScriptingInterface::getSelectedItemsList(const QString& listName) const {
|
||||
QReadLocker lock(&_selectionListsLock);
|
||||
|
@ -438,18 +440,19 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
|
|||
}
|
||||
|
||||
/**jsdoc
|
||||
* The highlighting style of a selection list.
|
||||
* @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.
|
||||
* @property {Color} outlineUnoccludedColor=255,178,51 - Unoccluded outline color.
|
||||
* @property {Color} outlineOccludedColor=255,178,51 - Occluded outline color.
|
||||
* @property {Color} fillUnoccludedColor=51,178,255 - Unoccluded fill color.
|
||||
* @property {Color} fillOccludedColor=51,178,255 - Occluded fill color.
|
||||
* @property {number} outlineUnoccludedAlpha=0.9 - Unoccluded outline alpha, range <code>0.0</code> – <code>1.0</code>.
|
||||
* @property {number} outlineOccludedAlpha=0.9 - Occluded outline alpha, range <code>0.0</code> – <code>1.0</code>.
|
||||
* @property {number} fillUnoccludedAlpha=0.0 - Unoccluded fill alpha, range <code>0.0</code> – <code>1.0</code>.
|
||||
* @property {number} fillOccludedAlpha=0.0 - Occluded fill alpha, range <code>0.0</code> – <code>1.0</code>.
|
||||
* @property {number} outlineWidth=2 - Width of the outline, in pixels.
|
||||
* @property {boolean} isOutlineSmooth=false - <code>true</code> to fade the outside edge of the outline, <code>false</code>
|
||||
* to have a sharp edge.
|
||||
*/
|
||||
QVariantMap SelectionHighlightStyle::toVariantMap() const {
|
||||
QVariantMap properties;
|
||||
|
|
|
@ -77,47 +77,45 @@ protected:
|
|||
};
|
||||
|
||||
/**jsdoc
|
||||
* The <code>Selection</code> API provides a means of grouping together avatars and entities in named lists.
|
||||
* The <code>Selection</code> API provides a means of grouping together and highlighting avatars and entities in named lists.
|
||||
*
|
||||
* @namespace Selection
|
||||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @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.
|
||||
* @example <caption>Outline an entity when it is grabbed by the mouse or a controller.</caption>
|
||||
* // Create an entity and copy the following script into the entity's "Script URL" field.
|
||||
* // Move the entity behind another entity to see the occluded outline.
|
||||
* (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;
|
||||
* }
|
||||
* var LIST_NAME = "SelectionExample",
|
||||
* ITEM_TYPE = "entity",
|
||||
* HIGHLIGHT_STYLE = {
|
||||
* outlineUnoccludedColor: { red: 0, green: 180, blue: 239 },
|
||||
* outlineUnoccludedAlpha: 0.5,
|
||||
* outlineOccludedColor: { red: 239, green: 180, blue: 0 },
|
||||
* outlineOccludedAlpha: 0.5,
|
||||
* outlineWidth: 4
|
||||
* };
|
||||
*
|
||||
* Selection.enableListHighlight(LIST_NAME, HIGHLIGHT_STYLE);
|
||||
*
|
||||
* this.startNearGrab = function (entityID) {
|
||||
* Selection.addToSelectedItemsList(LIST_NAME, ITEM_TYPE, entityID);
|
||||
* };
|
||||
*
|
||||
* _this.releaseGrab = function(entityID){
|
||||
* if (prevID !== 0) {
|
||||
* Selection.removeFromSelectedItemsList("contextOverlayHighlightList", listType, prevID);
|
||||
* prevID = 0;
|
||||
* }
|
||||
*
|
||||
* this.startDistanceGrab = function (entityID) {
|
||||
* Selection.addToSelectedItemsList(LIST_NAME, ITEM_TYPE, entityID);
|
||||
* };
|
||||
*
|
||||
* var cleanup = function(){
|
||||
* Entities.findEntities(MyAvatar.position, 1000).forEach(function(entity) {
|
||||
* try {
|
||||
* Selection.removeListFromMap(listName);
|
||||
* } catch (e) {
|
||||
* print("Error cleaning up.");
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* this.releaseGrab = function (entityID) {
|
||||
* Selection.removeFromSelectedItemsList(LIST_NAME, ITEM_TYPE, entityID);
|
||||
* };
|
||||
*
|
||||
* Script.scriptEnding.connect(cleanup);
|
||||
*
|
||||
* Script.scriptEnding.connect(function () {
|
||||
* Selection.removeListFromMap(LIST_NAME);
|
||||
* });
|
||||
* });
|
||||
*/
|
||||
class SelectionScriptingInterface : public QObject, public Dependency {
|
||||
|
@ -127,121 +125,119 @@ public:
|
|||
SelectionScriptingInterface();
|
||||
|
||||
/**jsdoc
|
||||
* Get the names of all the selection lists.
|
||||
* @function Selection.getListNames
|
||||
* @returns {list[]} An array of names of all the selection lists.
|
||||
*/
|
||||
* Gets the names of all current selection lists.
|
||||
* @function Selection.getListNames
|
||||
* @returns {string[]} The names of all current selection lists.
|
||||
* @example <caption>List all the current selection lists.</caption>
|
||||
* print("Selection lists: " + Selection.getListNames());
|
||||
*/
|
||||
Q_INVOKABLE QStringList getListNames() const;
|
||||
|
||||
/**jsdoc
|
||||
* Delete a named selection list.
|
||||
* @function Selection.removeListFromMap
|
||||
* @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>.
|
||||
*/
|
||||
* Deletes a selection list.
|
||||
* @function Selection.removeListFromMap
|
||||
* @param {string} listName - The name of the selection list to delete.
|
||||
* @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 to a selection list.
|
||||
* @function Selection.addToSelectedItemsList
|
||||
* @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>.
|
||||
*/
|
||||
* Adds an item to a selection list. The list is created if it doesn't exist.
|
||||
* @function Selection.addToSelectedItemsList
|
||||
* @param {string} listName - The name of the selection list to add the item to.
|
||||
* @param {Selection.ItemType} itemType - The type of item being added.
|
||||
* @param {Uuid} itemID - The ID of the item to add.
|
||||
* @returns {boolean} <code>true</code> if the item was successfully added or already existed in the list, otherwise
|
||||
* <code>false</code>.
|
||||
*/
|
||||
Q_INVOKABLE bool addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id);
|
||||
|
||||
/**jsdoc
|
||||
* Remove an item from a selection list.
|
||||
* @function Selection.removeFromSelectedItemsList
|
||||
* @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.
|
||||
*/
|
||||
* Removes an item from a selection list.
|
||||
* @function Selection.removeFromSelectedItemsList
|
||||
* @param {string} listName - The name of the selection list to remove the item from.
|
||||
* @param {Selection.ItemType} itemType - The type of item being removed.
|
||||
* @param {Uuid} itemID - The ID of the item to remove.
|
||||
* @returns {boolean} <code>true</code> if the item was successfully removed or was not in the list, otherwise
|
||||
* <code>false</code>.
|
||||
*/
|
||||
Q_INVOKABLE bool removeFromSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id);
|
||||
|
||||
/**jsdoc
|
||||
* Remove all items from a selection.
|
||||
* @function Selection.clearSelectedItemsList
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> if the item was successfully cleared, otherwise <code>false</code>.
|
||||
*/
|
||||
* Removes all items from a selection list.
|
||||
* @function Selection.clearSelectedItemsList
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> always.
|
||||
*/
|
||||
Q_INVOKABLE bool clearSelectedItemsList(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Print out the list of avatars and entities in a selection to the <em>debug log</em> (not the script log).
|
||||
* @function Selection.printList
|
||||
* @param {string} listName - The name of the selection list.
|
||||
*/
|
||||
* Prints the list of avatars and entities in a selection to the program log (but not the Script Log window).
|
||||
* @function Selection.printList
|
||||
* @param {string} listName - The name of the selection list.
|
||||
*/
|
||||
Q_INVOKABLE void printList(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Get the list of avatars and entities stored in a selection list.
|
||||
* @function Selection.getSelectedItemsList
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {Selection.SelectedItemsList} The content of a selection list. If the list name doesn't exist, the function
|
||||
* returns an empty object with no properties.
|
||||
*/
|
||||
* Gets the list of avatars and entities in a selection list.
|
||||
* @function Selection.getSelectedItemsList
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {Selection.SelectedItemsList} The content of the selection list if the list exists, otherwise an empty object.
|
||||
*/
|
||||
Q_INVOKABLE QVariantMap getSelectedItemsList(const QString& listName) const;
|
||||
|
||||
/**jsdoc
|
||||
* Get the names of the highlighted selection lists.
|
||||
* @function Selection.getHighlightedListNames
|
||||
* @returns {string[]} An array of names of the selection list currently highlight enabled.
|
||||
*/
|
||||
* Gets the names of all current selection lists that have highlighting enabled.
|
||||
* @function Selection.getHighlightedListNames
|
||||
* @returns {string[]} The names of the selection lists that currently have highlighting enabled.
|
||||
*/
|
||||
Q_INVOKABLE QStringList getHighlightedListNames() const;
|
||||
|
||||
/**jsdoc
|
||||
* 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 {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.
|
||||
*/
|
||||
* Enables highlighting for a selection list. All items in or subsequently added to the list are displayed with the
|
||||
* highlight effect specified. The method can be called multiple times with different values in the style to modify the
|
||||
* highlighting.
|
||||
* <p>Note: This function implicitly calls {@link Selection.enableListToScene|enableListToScene}.</p>
|
||||
* @function Selection.enableListHighlight
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @param {Selection.HighlightStyle} highlightStyle - The highlight style.
|
||||
* @returns {boolean} <code>true</code> always.
|
||||
*/
|
||||
Q_INVOKABLE bool enableListHighlight(const QString& listName, const QVariantMap& highlightStyle);
|
||||
|
||||
/**jsdoc
|
||||
* 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 {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>.
|
||||
*/
|
||||
* Disables highlighting for a selection list.
|
||||
* <p>Note: This function implicitly calls {@link Selection.disableListToScene|disableListToScene}.</p>
|
||||
* @function Selection.disableListHighlight
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> always.
|
||||
*/
|
||||
Q_INVOKABLE bool disableListHighlight(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* 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 {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>.
|
||||
*/
|
||||
* Enables scene selection for a selection list. All items in or subsequently added to the list are sent to a scene
|
||||
* selection in the rendering engine for debugging purposes.
|
||||
* @function Selection.enableListToScene
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> always.
|
||||
*/
|
||||
Q_INVOKABLE bool enableListToScene(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Disable scene selection for the named selection.
|
||||
* 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 {string} listName - The name of the selection list.
|
||||
* @returns {boolean} true if the selection was successfully disabled on the scene, false otherwise.
|
||||
*/
|
||||
* Disables scene selection for a selection list.
|
||||
* @function Selection.disableListToScene
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> always.
|
||||
*/
|
||||
Q_INVOKABLE bool disableListToScene(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* 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 {string} listName - The name of the selection list.
|
||||
* @returns {Selection.HighlightStyle} highlight style
|
||||
*/
|
||||
* Gets the current highlighting style for a selection list.
|
||||
* @function Selection.getListHighlightStyle
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {Selection.HighlightStyle} The highlight style of the selection list if the list exists and highlighting is
|
||||
* enabled, otherwise an empty object.
|
||||
*/
|
||||
Q_INVOKABLE QVariantMap getListHighlightStyle(const QString& listName) const;
|
||||
|
||||
|
||||
|
@ -253,7 +249,7 @@ public:
|
|||
|
||||
signals:
|
||||
/**jsdoc
|
||||
* Triggered when a list's content changes.
|
||||
* Triggered when a selection list's content changes or the list is deleted.
|
||||
* @function Selection.selectedItemsListChanged
|
||||
* @param {string} listName - The name of the selection list that changed.
|
||||
* @returns {Signal}
|
||||
|
@ -276,7 +272,6 @@ private:
|
|||
void setupHandler(const QString& selectionName);
|
||||
void removeHandler(const QString& selectionName);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_SelectionScriptingInterface_h
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
#include <QString>
|
||||
|
||||
/**jsdoc
|
||||
* The Settings API provides a facility to store and retrieve values that persist between Interface runs.
|
||||
* The <code>Settings</code> API provides a facility to store and retrieve values that persist between Interface runs.
|
||||
*
|
||||
* @namespace Settings
|
||||
*
|
||||
* @hifi-interface
|
||||
|
@ -33,7 +34,7 @@ public:
|
|||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* Retrieve the value from a named setting.
|
||||
* Retrieves the value from a named setting.
|
||||
* @function Settings.getValue
|
||||
* @param {string} key - The name of the setting.
|
||||
* @param {string|number|boolean|object} [defaultValue=""] - The value to return if the setting doesn't exist.
|
||||
|
@ -50,8 +51,8 @@ public slots:
|
|||
QVariant getValue(const QString& setting, const QVariant& defaultValue);
|
||||
|
||||
/**jsdoc
|
||||
* Store a value in a named setting. If the setting already exists its value is overwritten, otherwise a new setting is
|
||||
* created. If the value is set to <code>null</code> or <code>undefined</code>, the setting is deleted.
|
||||
* Stores a value in a named setting. If the setting already exists, its value is overwritten. If the value is
|
||||
* <code>null</code> or <code>undefined</code>, the setting is deleted.
|
||||
* @function Settings.setValue
|
||||
* @param {string} key - The name of the setting. Be sure to use a unique name if creating a new setting.
|
||||
* @param {string|number|boolean|object|undefined} value - The value to store in the setting. If <code>null</code> or
|
||||
|
|
|
@ -313,8 +313,9 @@ public slots:
|
|||
* Takes a snapshot of the current Interface view from the primary camera. When a still image only is captured,
|
||||
* {@link Window.stillSnapshotTaken|stillSnapshotTaken} is emitted; when a still image plus moving images are captured,
|
||||
* {@link Window.processingGifStarted|processingGifStarted} and {@link Window.processingGifCompleted|processingGifCompleted}
|
||||
* are emitted. The path to store the snapshots and the length of the animated GIF to capture are specified in Settings >
|
||||
* General > Snapshots.
|
||||
* are emitted.
|
||||
* <p>Snapshots are saved to the path specified in Settings > General > Snapshots, which can be accessed via the
|
||||
* {@link Snapshot} API.</p>
|
||||
*
|
||||
* @function Window.takeSnapshot
|
||||
* @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken}
|
||||
|
@ -351,13 +352,15 @@ public slots:
|
|||
* var notify = true;
|
||||
* var animated = true;
|
||||
* var aspect = 1920 / 1080;
|
||||
* var filename = "";
|
||||
* var filename = "example-snapshot";
|
||||
* Window.takeSnapshot(notify, animated, aspect, filename);
|
||||
*/
|
||||
void takeSnapshot(bool notify = true, bool includeAnimated = false, float aspectRatio = 0.0f, const QString& filename = QString());
|
||||
|
||||
/**jsdoc
|
||||
* Takes a still snapshot of the current view from the secondary camera that can be set up through the {@link Render} API.
|
||||
* <p>Snapshots are saved to the path specified in Settings > General > Snapshots, which can be accessed via the
|
||||
* {@link Snapshot} API.</p>
|
||||
* @function Window.takeSecondaryCameraSnapshot
|
||||
* @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken}
|
||||
* signal.
|
||||
|
@ -372,6 +375,8 @@ public slots:
|
|||
/**jsdoc
|
||||
* Takes a 360° snapshot at a given position for the secondary camera. The secondary camera does not need to have been
|
||||
* set up.
|
||||
* <p>Snapshots are saved to the path specified in Settings > General > Snapshots, which can be accessed via the
|
||||
* {@link Snapshot} API.</p>
|
||||
* @function Window.takeSecondaryCamera360Snapshot
|
||||
* @param {Vec3} cameraPosition - The position of the camera for the snapshot.
|
||||
* @param {boolean} [cubemapOutputFormat=false] - If <code>true</code> then the snapshot is saved as a cube map image,
|
||||
|
|
|
@ -38,6 +38,10 @@ private:
|
|||
|
||||
|
||||
/**jsdoc
|
||||
* The <code>Snapshot</code> API provides access to the path that snapshots are saved to. This path is that provided in
|
||||
* Settings > General > Snapshots. Snapshots may be taken using <code>Window</code> API functions such as
|
||||
* {@link Window.takeSnapshot}.
|
||||
*
|
||||
* @namespace Snapshot
|
||||
*
|
||||
* @hifi-interface
|
||||
|
@ -64,23 +68,31 @@ public:
|
|||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the path that snapshots are saved to is changed.
|
||||
* @function Snapshot.snapshotLocationSet
|
||||
* @param {string} location
|
||||
* @param {string} location - The new snapshots location.
|
||||
* @returns {Signal}
|
||||
* @example <caption>Report when the snapshots location is changed.</caption>
|
||||
* // Run this script then change the snapshots location in Settings > General > Snapshots.
|
||||
* Snapshot.snapshotLocationSet.connect(function (path) {
|
||||
* print("New snapshot location: " + path);
|
||||
* });
|
||||
*/
|
||||
void snapshotLocationSet(const QString& value);
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* Gets the path that snapshots are saved to.
|
||||
* @function Snapshot.getSnapshotsLocation
|
||||
* @returns {string}
|
||||
* @returns {string} The path to save snapshots to.
|
||||
*/
|
||||
Q_INVOKABLE QString getSnapshotsLocation();
|
||||
|
||||
/**jsdoc
|
||||
* Sets the path that snapshots are saved to.
|
||||
* @function Snapshot.setSnapshotsLocation
|
||||
* @param {String} location
|
||||
* @param {String} location - The path to save snapshots to.
|
||||
*/
|
||||
Q_INVOKABLE void setSnapshotsLocation(const QString& location);
|
||||
|
||||
|
|
|
@ -314,10 +314,11 @@ class Stats : public QQuickItem {
|
|||
STATS_PROPERTY(QVector3D, parabolaPicksUpdated, QVector3D(0, 0, 0))
|
||||
STATS_PROPERTY(QVector3D, collisionPicksUpdated, QVector3D(0, 0, 0))
|
||||
|
||||
#ifdef DEBUG_EVENT_QUEUE
|
||||
STATS_PROPERTY(bool, eventQueueDebuggingOn, true)
|
||||
STATS_PROPERTY(int, mainThreadQueueDepth, -1);
|
||||
STATS_PROPERTY(int, nodeListThreadQueueDepth, -1);
|
||||
|
||||
#ifdef DEBUG_EVENT_QUEUE
|
||||
STATS_PROPERTY(bool, eventQueueDebuggingOn, true)
|
||||
#else
|
||||
STATS_PROPERTY(bool, eventQueueDebuggingOn, false)
|
||||
#endif // DEBUG_EVENT_QUEUE
|
||||
|
|
|
@ -339,7 +339,7 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE glm::quat jointToWorldRotation(const glm::quat& rotation, const int jointIndex = -1) const;
|
||||
|
||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||
Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;
|
||||
|
||||
void updateDisplayNameAlpha(bool showDisplayName);
|
||||
|
|
|
@ -1209,7 +1209,7 @@ public:
|
|||
const QString& getDisplayName() const { return _displayName; }
|
||||
const QString& getSessionDisplayName() const { return _sessionDisplayName; }
|
||||
bool getLookAtSnappingEnabled() const { return _lookAtSnappingEnabled; }
|
||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
||||
Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
||||
|
||||
virtual void setDisplayName(const QString& displayName);
|
||||
virtual void setSessionDisplayName(const QString& sessionDisplayName) {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// These properties have JSDoc documentation in HMDScriptingInterface.h.
|
||||
class AbstractHMDScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool active READ isHMDMode NOTIFY mountedChanged)
|
||||
Q_PROPERTY(bool active READ isHMDMode NOTIFY displayModeChanged)
|
||||
Q_PROPERTY(float ipd READ getIPD)
|
||||
Q_PROPERTY(float eyeHeight READ getEyeHeight)
|
||||
Q_PROPERTY(float playerHeight READ getPlayerHeight)
|
||||
|
|
|
@ -363,7 +363,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
ShapeType type = getShapeType();
|
||||
|
||||
auto model = getModel();
|
||||
if (!model) {
|
||||
if (!model || !model->isLoaded()) {
|
||||
type = SHAPE_TYPE_NONE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1770,6 +1770,7 @@ signals:
|
|||
/**jsdoc
|
||||
* Triggered on the client that is the physics simulation owner during the collision of two entities. Note: Isn't triggered
|
||||
* for a collision with an avatar.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.collisionWithEntity
|
||||
* @param {Uuid} idA - The ID of one entity in the collision. For an entity script, this is the ID of the entity containing
|
||||
* the script.
|
||||
|
@ -1882,6 +1883,7 @@ signals:
|
|||
/**jsdoc
|
||||
* Triggered when a mouse button is clicked while the mouse cursor is on an entity, or a controller trigger is fully
|
||||
* pressed while its laser is on an entity.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.mousePressOnEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that was pressed.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1906,6 +1908,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Repeatedly triggered while the mouse cursor or controller laser moves on an entity.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.mouseMoveOnEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that was moved on.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1916,6 +1919,7 @@ signals:
|
|||
/**jsdoc
|
||||
* Triggered when a mouse button is released after clicking on an entity or the controller trigger is partly or fully
|
||||
* released after pressing on an entity, even if the mouse pointer or controller laser has moved off the entity.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.mouseReleaseOnEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that was originally pressed.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1942,6 +1946,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Triggered when a mouse button is clicked while the mouse cursor is on an entity. Note: Not triggered by controller.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.clickDownOnEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that was clicked.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1952,6 +1957,7 @@ signals:
|
|||
/**jsdoc
|
||||
* Repeatedly triggered while a mouse button continues to be held after clicking an entity, even if the mouse cursor has
|
||||
* moved off the entity. Note: Not triggered by controller.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.holdingClickOnEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that was originally clicked.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1962,6 +1968,7 @@ signals:
|
|||
/**jsdoc
|
||||
* Triggered when a mouse button is released after clicking on an entity, even if the mouse cursor has moved off the
|
||||
* entity. Note: Not triggered by controller.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.clickReleaseOnEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that was originally clicked.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1971,6 +1978,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Triggered when the mouse cursor or controller laser starts hovering on an entity.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.hoverEnterEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that is being hovered.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1980,6 +1988,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Repeatedly triggered when the mouse cursor or controller laser moves while hovering over an entity.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.hoverOverEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that is being hovered.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1989,6 +1998,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Triggered when the mouse cursor or controller laser stops hovering over an entity.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.hoverLeaveEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that was being hovered.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1999,6 +2009,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Triggered when an avatar enters an entity.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.enterEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that the avatar entered.
|
||||
* @returns {Signal}
|
||||
|
@ -2032,6 +2043,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Triggered when an avatar leaves an entity.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.leaveEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that the avatar left.
|
||||
* @returns {Signal}
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace baker {
|
|||
class GetModelPartsTask {
|
||||
public:
|
||||
using Input = hfm::Model::Pointer;
|
||||
using Output = VaryingSet6<std::vector<hfm::Mesh>, hifi::URL, baker::MeshIndicesToModelNames, baker::BlendshapesPerMesh, QHash<QString, hfm::Material>, std::vector<hfm::Joint>>;
|
||||
using Output = VaryingSet5<std::vector<hfm::Mesh>, hifi::URL, baker::MeshIndicesToModelNames, baker::BlendshapesPerMesh, std::vector<hfm::Joint>>;
|
||||
using JobModel = Job::ModelIO<GetModelPartsTask, Input, Output>;
|
||||
|
||||
void run(const BakeContextPointer& context, const Input& input, Output& output) {
|
||||
|
@ -40,8 +40,7 @@ namespace baker {
|
|||
for (int i = 0; i < hfmModelIn->meshes.size(); i++) {
|
||||
blendshapesPerMesh.push_back(hfmModelIn->meshes[i].blendshapes.toStdVector());
|
||||
}
|
||||
output.edit4() = hfmModelIn->materials;
|
||||
output.edit5() = hfmModelIn->joints.toStdVector();
|
||||
output.edit4() = hfmModelIn->joints.toStdVector();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -134,17 +133,16 @@ namespace baker {
|
|||
const auto url = modelPartsIn.getN<GetModelPartsTask::Output>(1);
|
||||
const auto meshIndicesToModelNames = modelPartsIn.getN<GetModelPartsTask::Output>(2);
|
||||
const auto blendshapesPerMeshIn = modelPartsIn.getN<GetModelPartsTask::Output>(3);
|
||||
const auto materials = modelPartsIn.getN<GetModelPartsTask::Output>(4);
|
||||
const auto jointsIn = modelPartsIn.getN<GetModelPartsTask::Output>(5);
|
||||
const auto jointsIn = modelPartsIn.getN<GetModelPartsTask::Output>(4);
|
||||
|
||||
// Calculate normals and tangents for meshes and blendshapes if they do not exist
|
||||
// Note: Normals are never calculated here for OBJ models. OBJ files optionally define normals on a per-face basis, so for consistency normals are calculated beforehand in OBJSerializer.
|
||||
const auto normalsPerMesh = model.addJob<CalculateMeshNormalsTask>("CalculateMeshNormals", meshesIn);
|
||||
const auto calculateMeshTangentsInputs = CalculateMeshTangentsTask::Input(normalsPerMesh, meshesIn, materials).asVarying();
|
||||
const auto calculateMeshTangentsInputs = CalculateMeshTangentsTask::Input(normalsPerMesh, meshesIn).asVarying();
|
||||
const auto tangentsPerMesh = model.addJob<CalculateMeshTangentsTask>("CalculateMeshTangents", calculateMeshTangentsInputs);
|
||||
const auto calculateBlendshapeNormalsInputs = CalculateBlendshapeNormalsTask::Input(blendshapesPerMeshIn, meshesIn).asVarying();
|
||||
const auto normalsPerBlendshapePerMesh = model.addJob<CalculateBlendshapeNormalsTask>("CalculateBlendshapeNormals", calculateBlendshapeNormalsInputs);
|
||||
const auto calculateBlendshapeTangentsInputs = CalculateBlendshapeTangentsTask::Input(normalsPerBlendshapePerMesh, blendshapesPerMeshIn, meshesIn, materials).asVarying();
|
||||
const auto calculateBlendshapeTangentsInputs = CalculateBlendshapeTangentsTask::Input(normalsPerBlendshapePerMesh, blendshapesPerMeshIn, meshesIn).asVarying();
|
||||
const auto tangentsPerBlendshapePerMesh = model.addJob<CalculateBlendshapeTangentsTask>("CalculateBlendshapeTangents", calculateBlendshapeTangentsInputs);
|
||||
|
||||
// Build the graphics::MeshPointer for each hfm::Mesh
|
||||
|
|
|
@ -19,7 +19,6 @@ void CalculateBlendshapeTangentsTask::run(const baker::BakeContextPointer& conte
|
|||
const auto& normalsPerBlendshapePerMesh = input.get0();
|
||||
const auto& blendshapesPerMesh = input.get1();
|
||||
const auto& meshes = input.get2();
|
||||
const auto& materials = input.get3();
|
||||
auto& tangentsPerBlendshapePerMeshOut = output;
|
||||
|
||||
tangentsPerBlendshapePerMeshOut.reserve(normalsPerBlendshapePerMesh.size());
|
||||
|
@ -30,16 +29,6 @@ void CalculateBlendshapeTangentsTask::run(const baker::BakeContextPointer& conte
|
|||
tangentsPerBlendshapePerMeshOut.emplace_back();
|
||||
auto& tangentsPerBlendshapeOut = tangentsPerBlendshapePerMeshOut[tangentsPerBlendshapePerMeshOut.size()-1];
|
||||
|
||||
// Check if we actually need to calculate the tangents, or just append empty arrays
|
||||
bool needTangents = false;
|
||||
for (const auto& meshPart : mesh.parts) {
|
||||
auto materialIt = materials.find(meshPart.materialID);
|
||||
if (materialIt != materials.end() && (*materialIt).needTangentSpace()) {
|
||||
needTangents = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < blendshapes.size(); j++) {
|
||||
const auto& blendshape = blendshapes[j];
|
||||
const auto& tangentsIn = blendshape.tangents;
|
||||
|
@ -53,8 +42,8 @@ void CalculateBlendshapeTangentsTask::run(const baker::BakeContextPointer& conte
|
|||
continue;
|
||||
}
|
||||
|
||||
// Check if we can and should calculate tangents (we need normals to calculate the tangents)
|
||||
if (normals.empty() || !needTangents) {
|
||||
// Check if we can calculate tangents (we need normals and texcoords to calculate the tangents)
|
||||
if (normals.empty() || normals.size() != (size_t)mesh.texCoords.size()) {
|
||||
continue;
|
||||
}
|
||||
tangentsOut.resize(normals.size());
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
// Calculate blendshape tangents if not already present in the blendshape
|
||||
class CalculateBlendshapeTangentsTask {
|
||||
public:
|
||||
using Input = baker::VaryingSet4<std::vector<baker::NormalsPerBlendshape>, baker::BlendshapesPerMesh, std::vector<hfm::Mesh>, QHash<QString, hfm::Material>>;
|
||||
using Input = baker::VaryingSet3<std::vector<baker::NormalsPerBlendshape>, baker::BlendshapesPerMesh, std::vector<hfm::Mesh>>;
|
||||
using Output = std::vector<baker::TangentsPerBlendshape>;
|
||||
using JobModel = baker::Job::ModelIO<CalculateBlendshapeTangentsTask, Input, Output>;
|
||||
|
||||
|
|
|
@ -13,21 +13,9 @@
|
|||
|
||||
#include "ModelMath.h"
|
||||
|
||||
bool needTangents(const hfm::Mesh& mesh, const QHash<QString, hfm::Material>& materials) {
|
||||
// Check if we actually need to calculate the tangents
|
||||
for (const auto& meshPart : mesh.parts) {
|
||||
auto materialIt = materials.find(meshPart.materialID);
|
||||
if (materialIt != materials.end() && (*materialIt).needTangentSpace()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CalculateMeshTangentsTask::run(const baker::BakeContextPointer& context, const Input& input, Output& output) {
|
||||
const auto& normalsPerMesh = input.get0();
|
||||
const std::vector<hfm::Mesh>& meshes = input.get1();
|
||||
const auto& materials = input.get2();
|
||||
auto& tangentsPerMeshOut = output;
|
||||
|
||||
tangentsPerMeshOut.reserve(meshes.size());
|
||||
|
@ -39,10 +27,10 @@ void CalculateMeshTangentsTask::run(const baker::BakeContextPointer& context, co
|
|||
auto& tangentsOut = tangentsPerMeshOut[tangentsPerMeshOut.size()-1];
|
||||
|
||||
// Check if we already have tangents and therefore do not need to do any calculation
|
||||
// Otherwise confirm if we have the normals needed, and need to calculate the tangents
|
||||
// Otherwise confirm if we have the normals and texcoords needed
|
||||
if (!tangentsIn.empty()) {
|
||||
tangentsOut = tangentsIn.toStdVector();
|
||||
} else if (!normals.empty() && needTangents(mesh, materials)) {
|
||||
} else if (!normals.empty() && mesh.vertices.size() == mesh.texCoords.size()) {
|
||||
tangentsOut.resize(normals.size());
|
||||
baker::calculateTangents(mesh,
|
||||
[&mesh, &normals, &tangentsOut](int firstIndex, int secondIndex, glm::vec3* outVertices, glm::vec2* outTexCoords, glm::vec3& outNormal) {
|
||||
|
|
|
@ -22,7 +22,7 @@ class CalculateMeshTangentsTask {
|
|||
public:
|
||||
using NormalsPerMesh = std::vector<std::vector<glm::vec3>>;
|
||||
|
||||
using Input = baker::VaryingSet3<baker::NormalsPerMesh, std::vector<hfm::Mesh>, QHash<QString, hfm::Material>>;
|
||||
using Input = baker::VaryingSet2<baker::NormalsPerMesh, std::vector<hfm::Mesh>>;
|
||||
using Output = baker::TangentsPerMesh;
|
||||
using JobModel = baker::Job::ModelIO<CalculateMeshTangentsTask, Input, Output>;
|
||||
|
||||
|
|
|
@ -91,10 +91,10 @@ NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort)
|
|||
connect(accountManager.data(), &AccountManager::newKeypair, this, &NodeList::sendDomainServerCheckIn);
|
||||
|
||||
// clear out NodeList when login is finished and we know our new username
|
||||
connect(accountManager.data(), SIGNAL(usernameChanged(QString)) , this, SLOT(reset()));
|
||||
connect(accountManager.data(), &AccountManager::usernameChanged , this, [this]{ reset("Username changed"); });
|
||||
|
||||
// clear our NodeList when logout is requested
|
||||
connect(accountManager.data(), SIGNAL(logoutComplete()) , this, SLOT(reset()));
|
||||
connect(accountManager.data(), &AccountManager::logoutComplete , this, [this]{ reset("Logged out"); });
|
||||
|
||||
// anytime we get a new node we will want to attempt to punch to it
|
||||
connect(this, &LimitedNodeList::nodeAdded, this, &NodeList::startNodeHolePunch);
|
||||
|
@ -412,6 +412,8 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
packetStream << FingerprintUtils::getMachineFingerprint();
|
||||
}
|
||||
|
||||
packetStream << usecTimestampNow();
|
||||
|
||||
// pack our data to send to the domain-server including
|
||||
// the hostname information (so the domain-server can see which place name we came in on)
|
||||
packetStream << _ownerType.load() << publicSockAddr << localSockAddr << _nodeTypesOfInterest.toList();
|
||||
|
@ -618,32 +620,14 @@ void NodeList::processDomainServerConnectionTokenPacket(QSharedPointer<ReceivedM
|
|||
}
|
||||
|
||||
void NodeList::processDomainServerList(QSharedPointer<ReceivedMessage> message) {
|
||||
if (_domainHandler.getSockAddr().isNull()) {
|
||||
qWarning() << "IGNORING DomainList packet while not connected to a Domain Server";
|
||||
// refuse to process this packet if we aren't currently connected to the DS
|
||||
return;
|
||||
}
|
||||
|
||||
// this is a packet from the domain server, reset the count of un-replied check-ins
|
||||
_domainHandler.clearPendingCheckins();
|
||||
|
||||
// emit our signal so listeners know we just heard from the DS
|
||||
emit receivedDomainServerList();
|
||||
|
||||
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::ReceiveDSList);
|
||||
|
||||
// parse header information
|
||||
QDataStream packetStream(message->getMessage());
|
||||
|
||||
// grab the domain's ID from the beginning of the packet
|
||||
QUuid domainUUID;
|
||||
packetStream >> domainUUID;
|
||||
|
||||
if (_domainHandler.isConnected() && _domainHandler.getUUID() != domainUUID) {
|
||||
// Recieved packet from different domain.
|
||||
qWarning() << "IGNORING DomainList packet from" << domainUUID << "while connected to" << _domainHandler.getUUID();
|
||||
return;
|
||||
}
|
||||
|
||||
Node::LocalID domainLocalID;
|
||||
packetStream >> domainLocalID;
|
||||
|
||||
|
@ -654,6 +638,57 @@ void NodeList::processDomainServerList(QSharedPointer<ReceivedMessage> message)
|
|||
packetStream >> newUUID;
|
||||
packetStream >> newLocalID;
|
||||
|
||||
// pull the permissions/right/privileges for this node out of the stream
|
||||
NodePermissions newPermissions;
|
||||
packetStream >> newPermissions;
|
||||
setPermissions(newPermissions);
|
||||
// Is packet authentication enabled?
|
||||
bool isAuthenticated;
|
||||
packetStream >> isAuthenticated;
|
||||
setAuthenticatePackets(isAuthenticated);
|
||||
|
||||
quint64 connectRequestTimestamp;
|
||||
quint64 now = usecTimestampNow();
|
||||
packetStream >> connectRequestTimestamp;
|
||||
quint64 pingLagTime = (now - connectRequestTimestamp) / USECS_PER_MSEC;
|
||||
quint64 domainServerPingReceiveTime;
|
||||
|
||||
packetStream >> domainServerPingReceiveTime;
|
||||
quint64 domainServerRequestLag = (domainServerPingReceiveTime - connectRequestTimestamp) / USECS_PER_MSEC;
|
||||
quint64 domainServerResponseLag = (now - domainServerPingReceiveTime) / USECS_PER_MSEC;
|
||||
|
||||
if (_domainHandler.getSockAddr().isNull()) {
|
||||
qWarning(networking) << "IGNORING DomainList packet while not connected to a Domain Server: sent " << pingLagTime << " msec ago.";
|
||||
qWarning(networking) << "DomainList request lag (with skew): " << domainServerRequestLag << "msec";
|
||||
qWarning(networking) << "DomainList response lag (with skew): " << domainServerResponseLag << "msec";
|
||||
// refuse to process this packet if we aren't currently connected to the DS
|
||||
return;
|
||||
}
|
||||
|
||||
// warn if ping lag is getting long
|
||||
if (pingLagTime > MSECS_PER_SECOND) {
|
||||
qCDebug(networking) << "DomainList ping is lagging: " << pingLagTime << "msec";
|
||||
qCDebug(networking) << "DomainList request lag (with skew): " << domainServerRequestLag << "msec";
|
||||
qCDebug(networking) << "DomainList response lag (with skew): " << domainServerResponseLag << "msec";
|
||||
}
|
||||
|
||||
// this is a packet from the domain server, reset the count of un-replied check-ins
|
||||
_domainHandler.clearPendingCheckins();
|
||||
|
||||
// emit our signal so listeners know we just heard from the DS
|
||||
emit receivedDomainServerList();
|
||||
|
||||
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::ReceiveDSList);
|
||||
|
||||
if (_domainHandler.isConnected() && _domainHandler.getUUID() != domainUUID) {
|
||||
// Recieved packet from different domain.
|
||||
qWarning() << "IGNORING DomainList packet from" << domainUUID << "while connected to"
|
||||
<< _domainHandler.getUUID() << ": sent " << pingLagTime << " msec ago.";
|
||||
qWarning(networking) << "DomainList request lag (with skew): " << domainServerRequestLag << "msec";
|
||||
qWarning(networking) << "DomainList response lag (with skew): " << domainServerResponseLag << "msec";
|
||||
return;
|
||||
}
|
||||
|
||||
// when connected, if the session ID or local ID were not null and changed, we should reset
|
||||
auto currentLocalID = getSessionLocalID();
|
||||
auto currentSessionID = getSessionUUID();
|
||||
|
@ -684,15 +719,6 @@ void NodeList::processDomainServerList(QSharedPointer<ReceivedMessage> message)
|
|||
DependencyManager::get<AddressManager>()->lookupShareableNameForDomainID(domainUUID);
|
||||
}
|
||||
|
||||
// pull the permissions/right/privileges for this node out of the stream
|
||||
NodePermissions newPermissions;
|
||||
packetStream >> newPermissions;
|
||||
setPermissions(newPermissions);
|
||||
// Is packet authentication enabled?
|
||||
bool isAuthenticated;
|
||||
packetStream >> isAuthenticated;
|
||||
setAuthenticatePackets(isAuthenticated);
|
||||
|
||||
// pull each node in the packet
|
||||
while (packetStream.device()->pos() < message->getSize()) {
|
||||
parseNodeFromPacketStream(packetStream);
|
||||
|
|
|
@ -27,7 +27,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::StunResponse:
|
||||
return 17;
|
||||
case PacketType::DomainList:
|
||||
return static_cast<PacketVersion>(DomainListVersion::AuthenticationOptional);
|
||||
return static_cast<PacketVersion>(DomainListVersion::HasTimestamp);
|
||||
case PacketType::EntityAdd:
|
||||
case PacketType::EntityClone:
|
||||
case PacketType::EntityEdit:
|
||||
|
@ -72,7 +72,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
return static_cast<PacketVersion>(DomainConnectionDeniedVersion::IncludesExtraInfo);
|
||||
|
||||
case PacketType::DomainConnectRequest:
|
||||
return static_cast<PacketVersion>(DomainConnectRequestVersion::AlwaysHasMachineFingerprint);
|
||||
return static_cast<PacketVersion>(DomainConnectRequestVersion::HasTimestamp);
|
||||
|
||||
case PacketType::DomainServerAddedNode:
|
||||
return static_cast<PacketVersion>(DomainServerAddedNodeVersion::PermissionsGrid);
|
||||
|
|
|
@ -344,7 +344,8 @@ enum class DomainConnectRequestVersion : PacketVersion {
|
|||
HasProtocolVersions,
|
||||
HasMACAddress,
|
||||
HasMachineFingerprint,
|
||||
AlwaysHasMachineFingerprint
|
||||
AlwaysHasMachineFingerprint,
|
||||
HasTimestamp
|
||||
};
|
||||
|
||||
enum class DomainConnectionDeniedVersion : PacketVersion {
|
||||
|
@ -363,7 +364,8 @@ enum class DomainListVersion : PacketVersion {
|
|||
PermissionsGrid,
|
||||
GetUsernameFromUUIDSupport,
|
||||
GetMachineFingerprintFromUUIDSupport,
|
||||
AuthenticationOptional
|
||||
AuthenticationOptional,
|
||||
HasTimestamp
|
||||
};
|
||||
|
||||
enum class AudioVersion : PacketVersion {
|
||||
|
|
|
@ -9,15 +9,51 @@
|
|||
#include "LinuxPlatform.h"
|
||||
#include "platformJsonKeys.h"
|
||||
#include <GPUIdent.h>
|
||||
|
||||
#include <thread>
|
||||
using namespace platform;
|
||||
|
||||
static void getLCpuId( uint32_t* p, uint32_t ax )
|
||||
{
|
||||
|
||||
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
||||
__asm __volatile
|
||||
( "movl %%ebx, %%esi\n\t"
|
||||
"cpuid\n\t"
|
||||
"xchgl %%ebx, %%esi"
|
||||
: "=a" (p[0]), "=S" (p[1]),
|
||||
"=c" (p[2]), "=d" (p[3])
|
||||
: "0" (ax)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LinuxInstance::enumerateCpu() {
|
||||
json cpu = {};
|
||||
|
||||
uint32_t cpuInfo[4]={0,0,0,0};
|
||||
char CPUBrandString[16];
|
||||
char CPUModelString[16];
|
||||
char CPUClockString[16];
|
||||
uint32_t nExIds;
|
||||
getLCpuId(cpuInfo, 0x80000000);
|
||||
nExIds = cpuInfo[0];
|
||||
|
||||
for (uint32_t i = 0x80000000; i <= nExIds; ++i) {
|
||||
getLCpuId(cpuInfo, i);
|
||||
// Interpret CPU brand string
|
||||
if (i == 0x80000002) {
|
||||
memcpy(CPUBrandString, cpuInfo, sizeof(cpuInfo));
|
||||
} else if (i == 0x80000003) {
|
||||
memcpy(CPUModelString, cpuInfo, sizeof(cpuInfo));
|
||||
} else if (i == 0x80000004) {
|
||||
memcpy(CPUClockString, cpuInfo, sizeof(cpuInfo));
|
||||
}
|
||||
}
|
||||
|
||||
cpu["cpuBrand"] = "";
|
||||
cpu["cpuModel"] = "";
|
||||
cpu["cpuClockSpeed"] = "";
|
||||
cpu["cpuNumCores"] = "";
|
||||
cpu["cpuBrand"] = CPUBrandString;
|
||||
cpu["cpuModel"] = CPUModelString;
|
||||
cpu["cpuClockSpeed"] = CPUClockString;
|
||||
cpu["cpuNumCores"] = std::thread::hardware_concurrency();
|
||||
|
||||
_cpu.push_back(cpu);
|
||||
}
|
||||
|
|
|
@ -378,6 +378,8 @@ void JitterSample::configure(const Config& config) {
|
|||
}
|
||||
} else if (config.stop) {
|
||||
_sampleSequence.currentIndex = -1;
|
||||
} else {
|
||||
_sampleSequence.currentIndex = config.getIndex();
|
||||
}
|
||||
_scale = config.scale;
|
||||
}
|
||||
|
@ -392,10 +394,10 @@ void JitterSample::run(const render::RenderContextPointer& renderContext, Output
|
|||
}
|
||||
}
|
||||
|
||||
jitter.x = 0.0f;
|
||||
jitter.y = 0.0f;
|
||||
if (current >= 0) {
|
||||
jitter = _sampleSequence.offsets[current];
|
||||
} else {
|
||||
jitter = glm::vec2(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,6 @@ public:
|
|||
void setDebugFXAA(bool debug) { debugFXAAX = (debug ? 0.0f : 1.0f); emit dirty();}
|
||||
bool debugFXAA() const { return (debugFXAAX == 0.0f ? true : false); }
|
||||
|
||||
|
||||
float blend{ 0.25f };
|
||||
float sharpen{ 0.05f };
|
||||
|
||||
|
|
|
@ -248,7 +248,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
|
||||
// Debugging task is happening in the "over" layer after tone mapping and just before HUD
|
||||
{ // Debug the bounds of the rendered items, still look at the zbuffer
|
||||
const auto extraDebugBuffers = RenderDeferredTaskDebug::ExtraBuffers(linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, ambientOcclusionFramebuffer, scatteringResource, velocityBuffer);
|
||||
const auto extraDebugBuffers = RenderDeferredTaskDebug::ExtraBuffers(linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, ambientOcclusionUniforms, scatteringResource, velocityBuffer);
|
||||
const auto debugInputs = RenderDeferredTaskDebug::Input(fetchedItems, shadowTaskOutputs, lightingStageInputs, lightClusters, prepareDeferredOutputs, extraDebugBuffers,
|
||||
deferredFrameTransform, jitter, lightingModel).asVarying();
|
||||
task.addJob<RenderDeferredTaskDebug>("DebugRenderDeferredTask", debugInputs);
|
||||
|
|
|
@ -987,6 +987,31 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString&
|
|||
};
|
||||
};
|
||||
|
||||
/**jsdoc
|
||||
* The name of an entity event. When the entity event occurs, any function that has been registered for that event via
|
||||
* {@link Script.addEventHandler} is called with parameters per the entity event.
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Event Name</th><th>Entity Event</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>"enterEntity"</code></td><td>{@link Entities.enterEntity}</td></tr>
|
||||
* <tr><td><code>"leaveEntity"</code></td><td>{@link Entities.leaveEntity}</td></tr>
|
||||
* <tr><td><code>"mousePressOnEntity"</code></td><td>{@link Entities.mousePressOnEntity}</td></tr>
|
||||
* <tr><td><code>"mouseMoveOnEntity"</code></td><td>{@link Entities.mouseMoveOnEntity}</td></tr>
|
||||
* <tr><td><code>"mouseReleaseOnEntity"</code></td><td>{@link Entities.mouseReleaseOnEntity}</td></tr>
|
||||
* <tr><td><code>"clickDownOnEntity"</code></td><td>{@link Entities.clickDownOnEntity}</td></tr>
|
||||
* <tr><td><code>"holdingClickOnEntity"</code></td><td>{@link Entities.holdingClickOnEntity}</td></tr>
|
||||
* <tr><td><code>"clickReleaseOnEntity"</code></td><td>{@link Entities.clickReleaseOnEntity}</td></tr>
|
||||
* <tr><td><code>"hoverEnterEntity"</code></td><td>{@link Entities.hoverEnterEntity}</td></tr>
|
||||
* <tr><td><code>"hoverOverEntity"</code></td><td>{@link Entities.hoverOverEntity}</td></tr>
|
||||
* <tr><td><code>"hoverLeaveEntity"</code></td><td>{@link Entities.hoverLeaveEntity}</td></tr>
|
||||
* <tr><td><code>"collisionWithEntity"</code></td><td>{@link Entities.collisionWithEntity}</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
*
|
||||
* @typedef {string} Script.EntityEvent
|
||||
*/
|
||||
connect(entities.data(), &EntityScriptingInterface::enterEntity, this, makeSingleEntityHandler("enterEntity"));
|
||||
connect(entities.data(), &EntityScriptingInterface::leaveEntity, this, makeSingleEntityHandler("leaveEntity"));
|
||||
|
||||
|
@ -2147,7 +2172,7 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString&
|
|||
}
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the script starts for a user.
|
||||
* Triggered when the script starts for a user. See also, {@link Script.entityScriptPreloadFinished}.
|
||||
* <p>Note: Can only be connected to via <code>this.preload = function (...) { ... }</code> in the entity script.</p>
|
||||
* <table><tr><th>Available in:</th><td>Client Entity Scripts</td><td>Server Entity Scripts</td></tr></table>
|
||||
* @function Entities.preload
|
||||
|
@ -2161,7 +2186,7 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString&
|
|||
* this.entityID = entityID;
|
||||
* print("Entity ID: " + this.entityID);
|
||||
* };
|
||||
* );
|
||||
* });
|
||||
*
|
||||
* var entityID = Entities.addEntity({
|
||||
* type: "Box",
|
||||
|
|
|
@ -100,6 +100,8 @@ public:
|
|||
};
|
||||
|
||||
/**jsdoc
|
||||
* The <code>Script</code> API provides facilities for working with scripts.
|
||||
*
|
||||
* @namespace Script
|
||||
*
|
||||
* @hifi-interface
|
||||
|
@ -108,7 +110,14 @@ public:
|
|||
* @hifi-server-entity
|
||||
* @hifi-assignment-client
|
||||
*
|
||||
* @property {string} context
|
||||
* @property {string} context - The context that the script is running in:
|
||||
* <ul>
|
||||
* <li><code>"client"</code>: An Interface or avatar script.</li>
|
||||
* <li><code>"entity_client"</code>: A client entity script.</li>
|
||||
* <li><code>"entity_server"</code>: A server entity script.</li>
|
||||
* <li><code>"agent"</code>: An assignment client script.</li>
|
||||
* </ul>
|
||||
* <em>Read-only.</em>
|
||||
*/
|
||||
class ScriptEngine : public BaseScriptEngine, public EntitiesScriptEngineProvider {
|
||||
Q_OBJECT
|
||||
|
@ -150,9 +159,19 @@ public:
|
|||
QList<EntityItemID> getListOfEntityScriptIDs();
|
||||
|
||||
/**jsdoc
|
||||
* Stop the current script.
|
||||
* Stops and unloads the current script.
|
||||
* <p><strong>Warning:</strong> If an assignment client script, the script gets restarted after stopping.</p>
|
||||
* @function Script.stop
|
||||
* @param {boolean} [marshal=false]
|
||||
* @param {boolean} [marshal=false] - Marshal.
|
||||
* <p class="important">Deprecated: This parameter is deprecated and will be removed.</p>
|
||||
* @example <caption>Stop a script after 5s.</caption>
|
||||
* Script.setInterval(function () {
|
||||
* print("Hello");
|
||||
* }, 1000);
|
||||
*
|
||||
* Script.setTimeout(function () {
|
||||
* Script.stop(true);
|
||||
* }, 5000);
|
||||
*/
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE - this is intended to be a public interface for Agent scripts, and local scripts, but not for EntityScripts
|
||||
|
@ -167,18 +186,20 @@ public:
|
|||
|
||||
/**jsdoc
|
||||
* @function Script.registerGlobalObject
|
||||
* @param {string} name
|
||||
* @param {object} object
|
||||
* @param {string} name - Name.
|
||||
* @param {object} object - Object.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
/// 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=""]
|
||||
* @param {string} name - Name.
|
||||
* @param {function} getter - Getter.
|
||||
* @param {function} setter - Setter.
|
||||
* @param {string} [parent=""] - Parent.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
/// registers a global getter/setter
|
||||
Q_INVOKABLE void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
|
||||
|
@ -186,19 +207,21 @@ public:
|
|||
|
||||
/**jsdoc
|
||||
* @function Script.registerFunction
|
||||
* @param {string} name
|
||||
* @param {object} function
|
||||
* @param {number} [numArguments=-1]
|
||||
* @param {string} name - Name.
|
||||
* @param {function} function - Function.
|
||||
* @param {number} [numArguments=-1] - Number of arguments.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
/// 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]
|
||||
* @param {string} parent - Parent.
|
||||
* @param {string} name - Name.
|
||||
* @param {function} function - Function.
|
||||
* @param {number} [numArguments=-1] - Number of arguments.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
/// 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,
|
||||
|
@ -206,27 +229,30 @@ public:
|
|||
|
||||
/**jsdoc
|
||||
* @function Script.registerValue
|
||||
* @param {string} name
|
||||
* @param {object} value
|
||||
* @param {string} name - Name.
|
||||
* @param {object} value - Value.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
/// 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}
|
||||
* @param {string} program - Program.
|
||||
* @param {string} filename - File name.
|
||||
* @param {number} [lineNumber=-1] - Line number.
|
||||
* @returns {object} Object.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
/// 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}
|
||||
* @param {object} locals - Locals.
|
||||
* @param {object} program - Program.
|
||||
* @returns {object} Object.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE QScriptValue evaluateInClosure(const QScriptValue& locals, const QScriptProgram& program);
|
||||
|
||||
|
@ -237,38 +263,53 @@ public:
|
|||
bool hasValidScriptSuffix(const QString& scriptFileName);
|
||||
|
||||
/**jsdoc
|
||||
* Gets the context that the script is running in: Interface/avatar, client entity, server entity, or assignment client.
|
||||
* @function Script.getContext
|
||||
* @returns {string}
|
||||
* @returns {string} The context that the script is running in:
|
||||
* <ul>
|
||||
* <li><code>"client"</code>: An Interface or avatar script.</li>
|
||||
* <li><code>"entity_client"</code>: A client entity script.</li>
|
||||
* <li><code>"entity_server"</code>: A server entity script.</li>
|
||||
* <li><code>"agent"</code>: An assignment client script.</li>
|
||||
* </ul>
|
||||
*/
|
||||
Q_INVOKABLE QString getContext() const;
|
||||
|
||||
/**jsdoc
|
||||
* Checks whether the script is running as an Interface or avatar script.
|
||||
* @function Script.isClientScript
|
||||
* @returns {boolean}
|
||||
* @returns {boolean} <code>true</code> if the script is running as an Interface or avatar script, <code>false</code> if it
|
||||
* isn't.
|
||||
*/
|
||||
Q_INVOKABLE bool isClientScript() const { return _context == CLIENT_SCRIPT; }
|
||||
|
||||
/**jsdoc
|
||||
* Checks whether the application was compiled as a debug build.
|
||||
* @function Script.isDebugMode
|
||||
* @returns {boolean}
|
||||
* @returns {boolean} <code>true</code> if the application was compiled as a debug build, <code>false</code> if it was
|
||||
* compiled as a release build.
|
||||
*/
|
||||
Q_INVOKABLE bool isDebugMode() const;
|
||||
|
||||
/**jsdoc
|
||||
* Checks whether the script is running as a client entity script.
|
||||
* @function Script.isEntityClientScript
|
||||
* @returns {boolean}
|
||||
* @returns {boolean} <code>true</code> if the script is running as a client entity script, <code>false</code> if it isn't.
|
||||
*/
|
||||
Q_INVOKABLE bool isEntityClientScript() const { return _context == ENTITY_CLIENT_SCRIPT; }
|
||||
|
||||
/**jsdoc
|
||||
* Checks whether the script is running as a server entity script.
|
||||
* @function Script.isEntityServerScript
|
||||
* @returns {boolean}
|
||||
* @returns {boolean} <code>true</code> if the script is running as a server entity script, <code>false</code> if it isn't.
|
||||
*/
|
||||
Q_INVOKABLE bool isEntityServerScript() const { return _context == ENTITY_SERVER_SCRIPT; }
|
||||
|
||||
/**jsdoc
|
||||
* Checks whether the script is running as an assignment client script.
|
||||
* @function Script.isAgentScript
|
||||
* @returns {boolean}
|
||||
* @returns {boolean} <code>true</code> if the script is running as an assignment client script, <code>false</code> if it
|
||||
* isn't.
|
||||
*/
|
||||
Q_INVOKABLE bool isAgentScript() const { return _context == AGENT_SCRIPT; }
|
||||
|
||||
|
@ -276,25 +317,42 @@ public:
|
|||
// NOTE - these are intended to be public interfaces available to scripts
|
||||
|
||||
/**jsdoc
|
||||
* Adds a function to the list of functions called when an entity event occurs on a particular entity.
|
||||
* @function Script.addEventHandler
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} eventName
|
||||
* @param {function} handler
|
||||
* @param {Uuid} entityID - The ID of the entity.
|
||||
* @param {Script.EntityEvent} eventName - The name of the entity event.
|
||||
* @param {function} handler - The function to call when the entity event occurs on the entity. It can be either the name
|
||||
* of a function or an in-line definition.
|
||||
* @example <caption>Report when a mouse press occurs on a particular entity.</caption>
|
||||
* var entityID = Entities.addEntity({
|
||||
* type: "Box",
|
||||
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -5 })),
|
||||
* dimensions: { x: 0.5, y: 0.5, z: 0.5 },
|
||||
* lifetime: 300 // Delete after 5 minutes.
|
||||
* });
|
||||
*
|
||||
* function reportMousePress(entityID, event) {
|
||||
* print("Mouse pressed on entity: " + JSON.stringify(event));
|
||||
* }
|
||||
*
|
||||
* Script.addEventHandler(entityID, "mousePressOnEntity", reportMousePress);
|
||||
*/
|
||||
Q_INVOKABLE void addEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler);
|
||||
|
||||
/**jsdoc
|
||||
* Removes a function from the list of functions called when an entity event occurs on a particular entity.
|
||||
* @function Script.removeEventHandler
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} eventName
|
||||
* @param {function} handler
|
||||
* @param {Uuid} entityID - The ID of the entity.
|
||||
* @param {Script.EntityEvent} eventName - The name of the entity event.
|
||||
* @param {function} handler - The name of the function to no longer call when the entity event occurs on the entity.
|
||||
*/
|
||||
Q_INVOKABLE void removeEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler);
|
||||
|
||||
/**jsdoc
|
||||
* Start a new Interface or entity script.
|
||||
* Starts running another script in Interface.
|
||||
* <table><tr><th>Available in:</th><td>Interface Scripts</td><td>Avatar Scripts</td></tr></table>
|
||||
* @function Script.load
|
||||
* @param {string} filename - The URL of the script to load. Can be relative to the current script.
|
||||
* @param {string} filename - The URL of the script to load. This can be relative to the current script's URL.
|
||||
* @example <caption>Load a script from another script.</caption>
|
||||
* // First file: scriptA.js
|
||||
* print("This is script A");
|
||||
|
@ -303,7 +361,7 @@ public:
|
|||
* print("This is script B");
|
||||
* Script.load("scriptA.js");
|
||||
*
|
||||
* // If you run scriptB.js you should see both scripts in the running scripts list.
|
||||
* // If you run scriptB.js you should see both scripts in the Running Scripts dialog.
|
||||
* // And you should see the following output:
|
||||
* // This is script B
|
||||
* // This is script A
|
||||
|
@ -311,22 +369,24 @@ public:
|
|||
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).
|
||||
* Includes 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
|
||||
* @variation 0
|
||||
* @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.
|
||||
* @param {function} [callback=null] - The function to call back when the scripts have been included. It can be either the
|
||||
* name of a function or an in-line definition.
|
||||
*/
|
||||
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
|
||||
* Includes 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.
|
||||
* @param {string} filename - The URL of the script to include. It can be relative to the current script.
|
||||
* @param {function} [callback=null] - The function to call back when the script has been included. It can be either the
|
||||
* name of a function or an in-line definition.
|
||||
* @example <caption>Include a script file asynchronously.</caption>
|
||||
* // First file: scriptA.js
|
||||
* print("This is script A");
|
||||
|
@ -349,16 +409,21 @@ public:
|
|||
// MODULE related methods
|
||||
|
||||
/**jsdoc
|
||||
* Provides access to methods or objects provided in an external JavaScript or JSON file.
|
||||
* See {@link https://docs.highfidelity.com/script/js-tips.html} for further details.
|
||||
* @function Script.require
|
||||
* @param {string} module
|
||||
* @param {string} module - The module to use. May be a JavaScript file or the name of a system module such as
|
||||
* <code>"sppUi"</code>.
|
||||
*/
|
||||
Q_INVOKABLE QScriptValue require(const QString& moduleId);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.resetModuleCache
|
||||
* @param {boolean} [deleteScriptCache=false]
|
||||
* @param {boolean} [deleteScriptCache=false] - Delete script cache.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE void resetModuleCache(bool deleteScriptCache = false);
|
||||
|
||||
QScriptValue currentModule();
|
||||
bool registerModuleWithParent(const QScriptValue& module, const QScriptValue& parent);
|
||||
QScriptValue newModule(const QString& modulePath, const QScriptValue& parent = QScriptValue());
|
||||
|
@ -366,53 +431,53 @@ public:
|
|||
QScriptValue instantiateModule(const QScriptValue& module, const QString& sourceCode);
|
||||
|
||||
/**jsdoc
|
||||
* Call a function at a set interval.
|
||||
* Calls a function repeatedly, 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 {function} function - The function to call. This can be either the name of a function or an in-line definition.
|
||||
* @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}.
|
||||
* @returns {object} A handle to the interval timer. This can be used in {@link Script.clearInterval}.
|
||||
* @example <caption>Print a message every second.</caption>
|
||||
* Script.setInterval(function () {
|
||||
* print("Timer fired");
|
||||
* print("Interval timer fired");
|
||||
* }, 1000);
|
||||
*/
|
||||
Q_INVOKABLE QObject* setInterval(const QScriptValue& function, int intervalMS);
|
||||
|
||||
/**jsdoc
|
||||
* Call a function after a delay.
|
||||
* Calls a function once, 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 {function} function - The function to call. This can be either the name of a function or an in-line definition.
|
||||
* @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>
|
||||
* @returns {object} A handle to the timeout timer. This can be used in {@link Script.clearTimeout}.
|
||||
* @example <caption>Print a message once, after a second.</caption>
|
||||
* Script.setTimeout(function () {
|
||||
* print("Timer fired");
|
||||
* print("Timeout timer fired");
|
||||
* }, 1000);
|
||||
*/
|
||||
Q_INVOKABLE QObject* setTimeout(const QScriptValue& function, int timeoutMS);
|
||||
|
||||
/**jsdoc
|
||||
* Stop an interval timer set by {@link Script.setInterval|setInterval}.
|
||||
* Stops an interval timer set by {@link Script.setInterval|setInterval}.
|
||||
* @function Script.clearInterval
|
||||
* @param {object} timer - The interval timer to clear.
|
||||
* @param {object} timer - The interval timer to stop.
|
||||
* @example <caption>Stop an interval timer.</caption>
|
||||
* // Print a message every second.
|
||||
* var timer = Script.setInterval(function () {
|
||||
* print("Timer fired");
|
||||
* print("Interval timer fired");
|
||||
* }, 1000);
|
||||
*
|
||||
* // Stop the timer after 10 seconds.
|
||||
* Script.setTimeout(function () {
|
||||
* print("Stop timer");
|
||||
* print("Stop interval 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}.
|
||||
* Stops a timeout timer set by {@link Script.setTimeout|setTimeout}.
|
||||
* @function Script.clearTimeout
|
||||
* @param {object} timer - The timeout timer to clear.
|
||||
* @param {object} timer - The timeout timer to stop.
|
||||
* @example <caption>Stop a timeout timer.</caption>
|
||||
* // Print a message after two seconds.
|
||||
* var timer = Script.setTimeout(function () {
|
||||
|
@ -425,34 +490,53 @@ public:
|
|||
Q_INVOKABLE void clearTimeout(QObject* timer) { stopTimer(reinterpret_cast<QTimer*>(timer)); }
|
||||
|
||||
/**jsdoc
|
||||
* Prints a message to the program log.
|
||||
* <p>Alternatively, you can use {@link print}, {@link console.log}, or one of the other {@link console} methods.</p>
|
||||
* @function Script.print
|
||||
* @param {string} message
|
||||
* @param {string} message - The message to print.
|
||||
*/
|
||||
/**jsdoc
|
||||
* Prints a message to the program log.
|
||||
* <p>This is an alias of {@link Script.print}.</p>
|
||||
* @function print
|
||||
* @param {string} message - The message to print.
|
||||
*/
|
||||
Q_INVOKABLE void print(const QString& message);
|
||||
|
||||
/**jsdoc
|
||||
* Resolve a relative path to an absolute path.
|
||||
* Resolves a relative path to an absolute path. The relative path is relative to the script's location.
|
||||
* @function Script.resolvePath
|
||||
* @param {string} path - The relative path to resolve.
|
||||
* @returns {string} The absolute path.
|
||||
* @example <caption>Report the directory and filename of the running script.</caption>
|
||||
* print(Script.resolvePath(""));
|
||||
* @example <caption>Report the directory of the running script.</caption>
|
||||
* print(Script.resolvePath("."));
|
||||
* @example <caption>Report the path to a file located relative to the running script.</caption>
|
||||
* print(Script.resolvePath("../assets/sounds/hello.wav"));
|
||||
*/
|
||||
Q_INVOKABLE QUrl resolvePath(const QString& path) const;
|
||||
|
||||
/**jsdoc
|
||||
* Gets the path to the resources directory for QML files.
|
||||
* @function Script.resourcesPath
|
||||
* @returns {string}
|
||||
* @returns {string} The path to the resources directory for QML files.
|
||||
*/
|
||||
Q_INVOKABLE QUrl resourcesPath() const;
|
||||
|
||||
/**jsdoc
|
||||
* Starts timing a section of code in order to send usage data about it to High Fidelity. Shouldn't be used outside of the
|
||||
* standard scripts.
|
||||
* @function Script.beginProfileRange
|
||||
* @param {string} label
|
||||
* @param {string} label - A name that identifies the section of code.
|
||||
*/
|
||||
Q_INVOKABLE void beginProfileRange(const QString& label) const;
|
||||
|
||||
/**jsdoc
|
||||
* Finishes timing a section of code in order to send usage data about it to High Fidelity. Shouldn't be used outside of
|
||||
* the standard scripts.
|
||||
* @function Script.endProfileRange
|
||||
* @param {string} label
|
||||
* @param {string} label - A name that identifies the section of code.
|
||||
*/
|
||||
Q_INVOKABLE void endProfileRange(const QString& label) const;
|
||||
|
||||
|
@ -460,9 +544,10 @@ public:
|
|||
// Entity Script Related methods
|
||||
|
||||
/**jsdoc
|
||||
* Checks whether an entity has an entity script running.
|
||||
* @function Script.isEntityScriptRunning
|
||||
* @param {Uuid} entityID
|
||||
* @returns {boolean}
|
||||
* @param {Uuid} entityID - The ID of the entity.
|
||||
* @returns {boolean} <code>true</code> if the entity has an entity script running, <code>false</code> if it doesn't.
|
||||
*/
|
||||
Q_INVOKABLE bool isEntityScriptRunning(const EntityItemID& entityID) {
|
||||
QReadLocker locker { &_entityScriptsLock };
|
||||
|
@ -474,60 +559,71 @@ public:
|
|||
|
||||
/**jsdoc
|
||||
* @function Script.loadEntityScript
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} script
|
||||
* @param {boolean} forceRedownload
|
||||
* @param {Uuid} entityID - Entity ID.
|
||||
* @param {string} script - Script.
|
||||
* @param {boolean} forceRedownload - Force re-download.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE void loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.unloadEntityScript
|
||||
* @param {Uuid} entityID
|
||||
* @param {boolean} [shouldRemoveFromMap=false]
|
||||
* @param {Uuid} entityID - Entity ID.
|
||||
* @param {boolean} [shouldRemoveFromMap=false] - Should remove from map.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE void unloadEntityScript(const EntityItemID& entityID, bool shouldRemoveFromMap = false); // will call unload method
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.unloadAllEntityScripts
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE void unloadAllEntityScripts();
|
||||
|
||||
/**jsdoc
|
||||
* Calls a method in an entity script.
|
||||
* @function Script.callEntityScriptMethod
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} methodName
|
||||
* @param {string[]} parameters
|
||||
* @param {Uuid} [remoteCallerID=Uuid.NULL]
|
||||
* @param {Uuid} entityID - The ID of the entity running the entity script.
|
||||
* @param {string} methodName - The name of the method to call.
|
||||
* @param {string[]} [parameters=[]] - The parameters to call the specified method with.
|
||||
* @param {Uuid} [remoteCallerID=Uuid.NULL] - An ID that identifies the caller.
|
||||
*/
|
||||
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName,
|
||||
const QStringList& params = QStringList(),
|
||||
const QUuid& remoteCallerID = QUuid()) override;
|
||||
|
||||
/**jsdoc
|
||||
* Calls a method in an entity script.
|
||||
* @function Script.callEntityScriptMethod
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} methodName
|
||||
* @param {PointerEvent} event
|
||||
* @param {Uuid} entityID - Entity ID.
|
||||
* @param {string} methodName - Method name.
|
||||
* @param {PointerEvent} event - Pointer event.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const PointerEvent& event);
|
||||
|
||||
/**jsdoc
|
||||
* Calls a method in an entity script.
|
||||
* @function Script.callEntityScriptMethod
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} methodName
|
||||
* @param {Uuid} otherID
|
||||
* @param {Collision} collision
|
||||
* @param {Uuid} entityID - Entity ID.
|
||||
* @param {string} methodName - Method name.
|
||||
* @param {Uuid} otherID - Other entity ID.
|
||||
* @param {Collision} collision - Collision.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision);
|
||||
|
||||
/**jsdoc
|
||||
* Manually runs the JavaScript garbage collector which reclaims memory by disposing of objects that are no longer
|
||||
* reachable.
|
||||
* @function Script.requestGarbageCollection
|
||||
*/
|
||||
Q_INVOKABLE void requestGarbageCollection() { collectGarbage(); }
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.generateUUID
|
||||
* @returns {Uuid}
|
||||
* @returns {Uuid} A new UUID.
|
||||
* @deprecated This function is deprecated and will be removed. Use {@link Uuid.generate} instead.
|
||||
*/
|
||||
Q_INVOKABLE QUuid generateUUID() { return QUuid::createUuid(); }
|
||||
|
||||
|
@ -573,7 +669,7 @@ public slots:
|
|||
|
||||
/**jsdoc
|
||||
* @function Script.callAnimationStateHandler
|
||||
* @param {function} callback - Callback.
|
||||
* @param {function} callback - Callback function.
|
||||
* @param {object} parameters - Parameters.
|
||||
* @param {string[]} names - Names.
|
||||
* @param {boolean} useNames - Use names.
|
||||
|
@ -584,7 +680,8 @@ public slots:
|
|||
|
||||
/**jsdoc
|
||||
* @function Script.updateMemoryCost
|
||||
* @param {number} deltaSize
|
||||
* @param {number} deltaSize - Delta size.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
void updateMemoryCost(const qint64&);
|
||||
|
||||
|
@ -592,31 +689,37 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* @function Script.scriptLoaded
|
||||
* @param {string} filename
|
||||
* @param {string} filename - File name.
|
||||
* @returns {Signal}
|
||||
* @deprecated This signal is deprecated and will be removed.
|
||||
*/
|
||||
void scriptLoaded(const QString& scriptFilename);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.errorLoadingScript
|
||||
* @param {string} filename
|
||||
* @param {string} filename - File name.
|
||||
* @returns {Signal}
|
||||
* @deprecated This signal is deprecated and will be removed.
|
||||
*/
|
||||
void errorLoadingScript(const QString& scriptFilename);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered regularly at a system-determined frequency.
|
||||
* Triggered frequently at a system-determined interval.
|
||||
* @function Script.update
|
||||
* @param {number} deltaTime - The time since the last update, in s.
|
||||
* @returns {Signal}
|
||||
* @example <caption>Report script update intervals.</caption>
|
||||
* Script.update.connect(function (deltaTime) {
|
||||
* print("Update: " + deltaTime);
|
||||
* });
|
||||
*/
|
||||
void update(float deltaTime);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the script is ending.
|
||||
* Triggered when the script is stopping.
|
||||
* @function Script.scriptEnding
|
||||
* @returns {Signal}
|
||||
* @example <caption>Connect to the <code>scriptEnding</code> signal.</caption>
|
||||
* @example <caption>Report when a script is stopping.</caption>
|
||||
* print("Script started");
|
||||
*
|
||||
* Script.scriptEnding.connect(function () {
|
||||
|
@ -632,52 +735,60 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* @function Script.finished
|
||||
* @param {string} filename
|
||||
* @param {object} engine
|
||||
* @param {string} filename - File name.
|
||||
* @param {object} engine - Engine.
|
||||
* @returns {Signal}
|
||||
* @deprecated This signal is deprecated and will be removed.
|
||||
*/
|
||||
void finished(const QString& fileNameString, ScriptEnginePointer);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.cleanupMenuItem
|
||||
* @param {string} menuItem
|
||||
* @param {string} menuItem - Menu item.
|
||||
* @returns {Signal}
|
||||
* @deprecated This signal is deprecated and will be removed.
|
||||
*/
|
||||
void cleanupMenuItem(const QString& menuItemString);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when a script prints a message to the program log via {@link Script.print}, {@link print},
|
||||
* {@link console.log}, {@link console.info}, {@link console.warn}, {@link console.error}, or {@link console.debug}.
|
||||
* @function Script.printedMessage
|
||||
* @param {string} message
|
||||
* @param {string} scriptName
|
||||
* @param {string} message - The message.
|
||||
* @param {string} scriptName - The name of the script that generated the message.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void printedMessage(const QString& message, const QString& scriptName);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when a script generates an error or {@link console.error} is called.
|
||||
* @function Script.errorMessage
|
||||
* @param {string} message
|
||||
* @param {string} scriptName
|
||||
* @param {string} message - The error message.
|
||||
* @param {string} scriptName - The name of the script that generated the error message.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void errorMessage(const QString& message, const QString& scriptName);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when a script generates a warning or {@link console.warn} is called.
|
||||
* @function Script.warningMessage
|
||||
* @param {string} message
|
||||
* @param {string} scriptName
|
||||
* @param {string} message - The warning message.
|
||||
* @param {string} scriptName - The name of the script that generated the warning message.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void warningMessage(const QString& message, const QString& scriptName);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when a script generates an information message or {@link console.info} is called.
|
||||
* @function Script.infoMessage
|
||||
* @param {string} message
|
||||
* @param {string} scriptName
|
||||
* @param {string} message - The information message.
|
||||
* @param {string} scriptName - The name of the script that generated the information message.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void infoMessage(const QString& message, const QString& scriptName);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the running state of the script changes, e.g., from running to stopping.
|
||||
* @function Script.runningStateChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
@ -686,26 +797,30 @@ signals:
|
|||
/**jsdoc
|
||||
* @function Script.clearDebugWindow
|
||||
* @returns {Signal}
|
||||
* @deprecated This signal is deprecated and will be removed.
|
||||
*/
|
||||
void clearDebugWindow();
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.loadScript
|
||||
* @param {string} scriptName
|
||||
* @param {boolean} isUserLoaded
|
||||
* @param {string} scriptName - Script name.
|
||||
* @param {boolean} isUserLoaded - Is user loaded.
|
||||
* @returns {Signal}
|
||||
* @deprecated This signal is deprecated and will be removed.
|
||||
*/
|
||||
void loadScript(const QString& scriptName, bool isUserLoaded);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.reloadScript
|
||||
* @param {string} scriptName
|
||||
* @param {boolean} isUserLoaded
|
||||
* @param {string} scriptName - Script name.
|
||||
* @param {boolean} isUserLoaded - Is user loaded.
|
||||
* @returns {Signal}
|
||||
* @deprecated This signal is deprecated and will be removed.
|
||||
*/
|
||||
void reloadScript(const QString& scriptName, bool isUserLoaded);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the script has stopped.
|
||||
* @function Script.doneRunning
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
@ -714,14 +829,35 @@ signals:
|
|||
/**jsdoc
|
||||
* @function Script.entityScriptDetailsUpdated
|
||||
* @returns {Signal}
|
||||
* @deprecated This signal is deprecated and will be removed.
|
||||
*/
|
||||
// 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();
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the script starts for the user. See also, {@link Entities.preload}.
|
||||
* <table><tr><th>Available in:</th><td>Client Entity Scripts</td><td>Server Entity Scripts</td></tr></table>
|
||||
* @function Script.entityScriptPreloadFinished
|
||||
* @param {Uuid} entityID - The ID of the entity that the script is running in.
|
||||
* @returns {Signal}
|
||||
* @example <caption>Get the ID of the entity that a client entity script is running in.</caption>
|
||||
* var entityScript = (function () {
|
||||
* this.entityID = Uuid.NULL;
|
||||
*
|
||||
* Script.entityScriptPreloadFinished.connect(function (entityID) {
|
||||
* this.entityID = entityID;
|
||||
* print("Entity ID: " + this.entityID);
|
||||
* });
|
||||
*
|
||||
* var entityID = Entities.addEntity({
|
||||
* type: "Box",
|
||||
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -5 })),
|
||||
* dimensions: { x: 0.5, y: 0.5, z: 0.5 },
|
||||
* color: { red: 255, green: 0, blue: 0 },
|
||||
* script: "(" + entityScript + ")", // Could host the script on a Web server instead.
|
||||
* lifetime: 300 // Delete after 5 minutes.
|
||||
* });
|
||||
*/
|
||||
// Emitted when an entity script has finished running preload
|
||||
void entityScriptPreloadFinished(const EntityItemID& entityID);
|
||||
|
@ -731,16 +867,18 @@ protected:
|
|||
|
||||
/**jsdoc
|
||||
* @function Script.executeOnScriptThread
|
||||
* @param {object} function
|
||||
* @param {ConnectionType} [type=2]
|
||||
* @param {function} function - Function.
|
||||
* @param {ConnectionType} [type=2] - Connection type.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
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}
|
||||
* @param {string} module - Module.
|
||||
* @param {string} [relativeTo=""] - Relative to.
|
||||
* @returns {string} Result.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
// 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;"
|
||||
|
@ -763,12 +901,13 @@ protected:
|
|||
|
||||
/**jsdoc
|
||||
* @function Script.entityScriptContentAvailable
|
||||
* @param {Uuid} entityID
|
||||
* @param {string} scriptOrURL
|
||||
* @param {string} contents
|
||||
* @param {boolean} isURL
|
||||
* @param {boolean} success
|
||||
* @param {string} status
|
||||
* @param {Uuid} entityID - Entity ID.
|
||||
* @param {string} scriptOrURL - Path.
|
||||
* @param {string} contents - Contents.
|
||||
* @param {boolean} isURL - Is a URL.
|
||||
* @param {boolean} success - Success.
|
||||
* @param {string} status - Status.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE void entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success, const QString& status);
|
||||
|
||||
|
|
|
@ -31,8 +31,32 @@ public:
|
|||
|
||||
BaseScriptEngine() {}
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.lintScript
|
||||
* @param {string} sourceCode - Source code.
|
||||
* @param {string} fileName - File name.
|
||||
* @param {number} [lineNumber=1] - Line number.
|
||||
* @returns {object} Object.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE QScriptValue lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1);
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.makeError
|
||||
* @param {object} [other] - Other.
|
||||
* @param {string} [type="Error"] - Error.
|
||||
* @returns {object} Object.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE QScriptValue makeError(const QScriptValue& other = QScriptValue(), const QString& type = "Error");
|
||||
|
||||
/**jsdoc
|
||||
* @function Script.formatExecption
|
||||
* @param {object} exception - Exception.
|
||||
* @param {boolean} inludeExtendeDetails - Include extended details.
|
||||
* @returns {string} String.
|
||||
* @deprecated This function is deprecated and will be removed.
|
||||
*/
|
||||
Q_INVOKABLE QString formatException(const QScriptValue& exception, bool includeExtendedDetails);
|
||||
|
||||
QScriptValue cloneUncaughtException(const QString& detail = QString());
|
||||
|
@ -48,6 +72,25 @@ public:
|
|||
// helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways
|
||||
static bool IS_THREADSAFE_INVOCATION(const QThread *thread, const QString& method);
|
||||
signals:
|
||||
/**jsdoc
|
||||
* @function Script.signalHandlerException
|
||||
* @param {object} exception - Exception.
|
||||
* @returns {Signal}
|
||||
* @deprecated This signal is deprecated and will be removed.
|
||||
*/
|
||||
// Script.signalHandlerException is exposed by QScriptEngine.
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when a script generates an unhandled exception.
|
||||
* @function Script.unhandledException
|
||||
* @param {object} exception - The details of the exception.
|
||||
* @returns {Signal}
|
||||
* @example <caption>Report the details of an unhandled exception.</caption>
|
||||
* Script.unhandledException.connect(function (exception) {
|
||||
* print("Unhandled exception: " + JSON.stringify(exception));
|
||||
* });
|
||||
* var properties = JSON.parse("{ x: 1"); // Invalid JSON string.
|
||||
*/
|
||||
void unhandledException(const QScriptValue& exception);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
|
||||
#endif
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
#include "SharedLogging.h"
|
||||
|
||||
GPUIdent GPUIdent::_instance {};
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
//
|
||||
// simplifiedStatusIndicator.js
|
||||
//
|
||||
// Created by Robin Wilson on 2019-05-17
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
|
||||
function simplifiedStatusIndicator(properties) {
|
||||
var that = this;
|
||||
var DEBUG = false;
|
||||
|
||||
// #region HEARTBEAT
|
||||
|
||||
// Send heartbeat with updates to database
|
||||
// When this stops, the database will set status to offline
|
||||
var HEARTBEAT_TIMEOUT_MS = 5000,
|
||||
heartbeat;
|
||||
function startHeartbeatTimer() {
|
||||
if (heartbeat) {
|
||||
Script.clearTimeout(heartbeat);
|
||||
heartbeat = false;
|
||||
}
|
||||
|
||||
heartbeat = Script.setTimeout(function() {
|
||||
heartbeat = false;
|
||||
getStatus(setStatus);
|
||||
}, HEARTBEAT_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
// #endregion HEARTBEAT
|
||||
|
||||
|
||||
// #region SEND/GET STATUS REQUEST
|
||||
|
||||
function setStatusExternally(newStatus) {
|
||||
if (!newStatus) {
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus(newStatus);
|
||||
}
|
||||
|
||||
|
||||
var request = Script.require('request').request,
|
||||
REQUEST_URL = "https://highfidelity.co/api/statusIndicator/";
|
||||
function setStatus(newStatus) {
|
||||
if (heartbeat) {
|
||||
Script.clearTimeout(heartbeat);
|
||||
heartbeat = false;
|
||||
}
|
||||
|
||||
if (newStatus && currentStatus !== newStatus) {
|
||||
currentStatus = newStatus;
|
||||
that.statusChanged();
|
||||
}
|
||||
|
||||
var queryParamString = "type=heartbeat";
|
||||
queryParamString += "&username=" + AccountServices.username;
|
||||
|
||||
var displayNameToSend = MyAvatar.sessionDisplayName;
|
||||
if (displayNameToSend === "") {
|
||||
displayNameToSend = MyAvatar.displayName;
|
||||
}
|
||||
queryParamString += "&displayName=" + displayNameToSend;
|
||||
queryParamString += "&status=" + currentStatus;
|
||||
queryParamString += "&organization=" + location.hostname;
|
||||
|
||||
var uri = REQUEST_URL + "?" + queryParamString;
|
||||
|
||||
if (DEBUG) {
|
||||
console.log("simplifiedStatusIndicator: setStatus: " + uri);
|
||||
}
|
||||
|
||||
request({
|
||||
uri: uri
|
||||
}, function (error, response) {
|
||||
startHeartbeatTimer();
|
||||
|
||||
if (error || !response || response.status !== "success") {
|
||||
console.error("Error with setStatus: " + JSON.stringify(response));
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Get status from database
|
||||
function getStatus(callback) {
|
||||
var queryParamString = "type=getStatus";
|
||||
queryParamString += "&username=" + AccountServices.username;
|
||||
|
||||
var uri = REQUEST_URL + "?" + queryParamString;
|
||||
|
||||
if (DEBUG) {
|
||||
console.log("simplifiedStatusIndicator: getStatus: " + uri);
|
||||
}
|
||||
|
||||
request({
|
||||
uri: uri
|
||||
}, function (error, response) {
|
||||
if (error || !response || response.status !== "success") {
|
||||
console.error("Error with getStatus: " + JSON.stringify(response));
|
||||
} else if (response.data.userStatus.toLowerCase() !== "offline") {
|
||||
if (response.data.userStatus !== currentStatus) {
|
||||
currentStatus = response.data.userStatus;
|
||||
that.statusChanged();
|
||||
}
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function getLocalStatus() {
|
||||
return currentStatus;
|
||||
}
|
||||
|
||||
// #endregion SEND/GET STATUS REQUEST
|
||||
|
||||
|
||||
// #region SIGNALS
|
||||
|
||||
var currentStatus = "available"; // Default is available
|
||||
function toggleStatus() {
|
||||
if (currentStatus === "busy") {
|
||||
currentStatus = "available";
|
||||
// Else if current status is "available" OR anything else (custom)
|
||||
} else {
|
||||
currentStatus = "busy";
|
||||
}
|
||||
|
||||
that.statusChanged();
|
||||
|
||||
setStatus();
|
||||
}
|
||||
|
||||
|
||||
// When avatar becomes active from being away
|
||||
// Set status back to previousStatus
|
||||
function onWentActive() {
|
||||
if (currentStatus !== previousStatus) {
|
||||
currentStatus = previousStatus;
|
||||
that.statusChanged();
|
||||
}
|
||||
setStatus();
|
||||
}
|
||||
|
||||
|
||||
// When avatar goes away, set status to busy
|
||||
var previousStatus;
|
||||
function onWentAway() {
|
||||
previousStatus = currentStatus;
|
||||
if (currentStatus !== "busy") {
|
||||
currentStatus = "busy";
|
||||
that.statusChanged();
|
||||
}
|
||||
setStatus();
|
||||
}
|
||||
|
||||
|
||||
// Domain changed update avatar location
|
||||
function onDomainChanged() {
|
||||
var queryParamString = "type=updateEmployee";
|
||||
queryParamString += "&username=" + AccountServices.username;
|
||||
queryParamString += "&location=unknown";
|
||||
|
||||
var uri = REQUEST_URL + "?" + queryParamString;
|
||||
|
||||
if (DEBUG) {
|
||||
console.log("simplifiedStatusIndicator: onDomainChanged: " + uri);
|
||||
}
|
||||
|
||||
request({
|
||||
uri: uri
|
||||
}, function (error, response) {
|
||||
if (error || !response || response.status !== "success") {
|
||||
console.error("Error with onDomainChanged: " + JSON.stringify(response));
|
||||
} else {
|
||||
// successfully sent updateLocation
|
||||
if (DEBUG) {
|
||||
console.log("simplifiedStatusIndicator: Successfully updated location after domain change.");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function statusChanged() {
|
||||
|
||||
}
|
||||
|
||||
// #endregion SIGNALS
|
||||
|
||||
|
||||
// #region APP LIFETIME
|
||||
|
||||
// Creates the app button and sets up signals and hearbeat
|
||||
function startup() {
|
||||
MyAvatar.wentAway.connect(onWentAway);
|
||||
MyAvatar.wentActive.connect(onWentActive);
|
||||
MyAvatar.displayNameChanged.connect(setStatus);
|
||||
Window.domainChanged.connect(onDomainChanged);
|
||||
|
||||
getStatus(setStatus);
|
||||
}
|
||||
|
||||
|
||||
// Cleans up timeouts, signals, and overlays
|
||||
function unload() {
|
||||
MyAvatar.wentAway.disconnect(onWentAway);
|
||||
MyAvatar.wentActive.disconnect(onWentActive);
|
||||
MyAvatar.displayNameChanged.disconnect(setStatus);
|
||||
Window.domainChanged.disconnect(onDomainChanged);
|
||||
if (heartbeat) {
|
||||
Script.clearTimeout(heartbeat);
|
||||
heartbeat = false;
|
||||
}
|
||||
}
|
||||
|
||||
// #endregion APP LIFETIME
|
||||
|
||||
that.startup = startup;
|
||||
that.unload = unload;
|
||||
that.toggleStatus = toggleStatus;
|
||||
that.setStatus = setStatus;
|
||||
that.getLocalStatus = getLocalStatus;
|
||||
that.statusChanged = statusChanged;
|
||||
|
||||
// Overwrite with the given properties
|
||||
var overwriteableKeys = ["statusChanged"];
|
||||
Object.keys(properties).forEach(function (key) {
|
||||
if (overwriteableKeys.indexOf(key) > -1) {
|
||||
that[key] = properties[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = simplifiedStatusIndicator;
|
|
@ -238,40 +238,57 @@ function updateOutputDeviceMutedOverlay(isMuted) {
|
|||
}
|
||||
|
||||
|
||||
var savedAvatarGain = Audio.getAvatarGain();
|
||||
var savedInjectorGain = Audio.getInjectorGain();
|
||||
var savedLocalInjectorGain = Audio.getLocalInjectorGain();
|
||||
var savedSystemInjectorGain = Audio.getSystemInjectorGain();
|
||||
var savedAvatarGain = Audio.avatarGain;
|
||||
var savedServerInjectorGain = Audio.serverInjectorGain;
|
||||
var savedLocalInjectorGain = Audio.localInjectorGain;
|
||||
var savedSystemInjectorGain = Audio.systemInjectorGain;
|
||||
var MUTED_VALUE_DB = -60; // This should always match `SimplifiedConstants.qml` -> numericConstants -> mutedValue!
|
||||
function setOutputMuted(outputMuted) {
|
||||
updateOutputDeviceMutedOverlay(outputMuted);
|
||||
|
||||
if (outputMuted) {
|
||||
savedAvatarGain = Audio.getAvatarGain();
|
||||
savedInjectorGain = Audio.getInjectorGain();
|
||||
savedLocalInjectorGain = Audio.getLocalInjectorGain();
|
||||
savedSystemInjectorGain = Audio.getSystemInjectorGain();
|
||||
savedAvatarGain = Audio.avatarGain;
|
||||
savedServerInjectorGain = Audio.serverInjectorGain;
|
||||
savedLocalInjectorGain = Audio.localInjectorGain;
|
||||
savedSystemInjectorGain = Audio.systemInjectorGain;
|
||||
|
||||
Audio.setAvatarGain(-60);
|
||||
Audio.setInjectorGain(-60);
|
||||
Audio.setLocalInjectorGain(-60);
|
||||
Audio.setSystemInjectorGain(-60);
|
||||
Audio.avatarGain = MUTED_VALUE_DB;
|
||||
Audio.serverInjectorGain = MUTED_VALUE_DB;
|
||||
Audio.localInjectorGain = MUTED_VALUE_DB;
|
||||
Audio.systemInjectorGain = MUTED_VALUE_DB;
|
||||
} else {
|
||||
if (savedAvatarGain === -60) {
|
||||
if (savedAvatarGain === MUTED_VALUE_DB) {
|
||||
savedAvatarGain = 0;
|
||||
}
|
||||
Audio.setAvatarGain(savedAvatarGain);
|
||||
if (savedInjectorGain === -60) {
|
||||
savedInjectorGain = 0;
|
||||
Audio.avatarGain = savedAvatarGain;
|
||||
if (savedServerInjectorGain === MUTED_VALUE_DB) {
|
||||
savedServerInjectorGain = 0;
|
||||
}
|
||||
Audio.setInjectorGain(savedInjectorGain);
|
||||
if (savedLocalInjectorGain === -60) {
|
||||
Audio.serverInjectorGain = savedServerInjectorGain;
|
||||
if (savedLocalInjectorGain === MUTED_VALUE_DB) {
|
||||
savedLocalInjectorGain = 0;
|
||||
}
|
||||
Audio.setLocalInjectorGain(savedLocalInjectorGain);
|
||||
if (savedSystemInjectorGain === -60) {
|
||||
Audio.localInjectorGain = savedLocalInjectorGain;
|
||||
if (savedSystemInjectorGain === MUTED_VALUE_DB) {
|
||||
savedSystemInjectorGain = 0;
|
||||
}
|
||||
Audio.setSystemInjectorGain(savedSystemInjectorGain);
|
||||
Audio.systemInjectorGain = savedSystemInjectorGain;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var WAIT_FOR_TOP_BAR_MS = 1000;
|
||||
function sendLocalStatusToQml() {
|
||||
var currentStatus = si.getLocalStatus();
|
||||
|
||||
if (topBarWindow && currentStatus) {
|
||||
topBarWindow.sendToQml({
|
||||
"source": "simplifiedUI.js",
|
||||
"method": "updateStatusButton",
|
||||
"data": {
|
||||
"currentStatus": currentStatus
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Script.setTimeout(sendLocalStatusToQml, WAIT_FOR_TOP_BAR_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,6 +312,10 @@ function onMessageFromTopBar(message) {
|
|||
setOutputMuted(message.data.outputMuted);
|
||||
break;
|
||||
|
||||
case "toggleStatus":
|
||||
si.toggleStatus();
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log("Unrecognized message from " + TOP_BAR_MESSAGE_SOURCE + ": " + JSON.stringify(message));
|
||||
break;
|
||||
|
@ -312,7 +333,10 @@ function onTopBarClosed() {
|
|||
|
||||
|
||||
function isOutputMuted() {
|
||||
return Audio.getAvatarGain() === -60 && Audio.getInjectorGain() === -60 && Audio.getLocalInjectorGain() === -60 && Audio.getSystemInjectorGain() === -60;
|
||||
return Audio.avatarGain === MUTED_VALUE_DB &&
|
||||
Audio.serverInjectorGain === MUTED_VALUE_DB &&
|
||||
Audio.localInjectorGain === MUTED_VALUE_DB &&
|
||||
Audio.systemInjectorGain === MUTED_VALUE_DB;
|
||||
}
|
||||
|
||||
|
||||
|
@ -346,13 +370,11 @@ function loadSimplifiedTopBar() {
|
|||
topBarWindow.fromQml.connect(onMessageFromTopBar);
|
||||
topBarWindow.closed.connect(onTopBarClosed);
|
||||
|
||||
topBarWindow.sendToQml({
|
||||
"source": "simplifiedUI.js",
|
||||
"method": "updateOutputMuted",
|
||||
"data": {
|
||||
"outputMuted": isOutputMuted()
|
||||
}
|
||||
})
|
||||
// The eventbridge takes a nonzero time to initialize, so we have to wait a bit
|
||||
// for the QML to load and for that to happen before updating the UI.
|
||||
Script.setTimeout(function() {
|
||||
sendLocalStatusToQml();
|
||||
}, WAIT_FOR_TOP_BAR_MS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -435,7 +457,20 @@ function ensureFirstPersonCameraInHMD(isHMDMode) {
|
|||
}
|
||||
}
|
||||
|
||||
var simplifiedNametag = Script.require("./simplifiedNametag/simplifiedNametag.js");
|
||||
|
||||
function onStatusChanged() {
|
||||
sendLocalStatusToQml();
|
||||
}
|
||||
|
||||
|
||||
function maybeUpdateOutputDeviceMutedOverlay() {
|
||||
updateOutputDeviceMutedOverlay(isOutputMuted());
|
||||
}
|
||||
|
||||
|
||||
var simplifiedNametag = Script.require("./simplifiedNametag/simplifiedNametag.js?" + Date.now());
|
||||
var SimplifiedStatusIndicator = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js?" + Date.now());
|
||||
var si;
|
||||
var oldShowAudioTools;
|
||||
var oldShowBubbleTools;
|
||||
var keepExistingUIAndScriptsSetting = Settings.getValue("simplifiedUI/keepExistingUIAndScripts", false);
|
||||
|
@ -456,11 +491,19 @@ function startup() {
|
|||
loadSimplifiedTopBar();
|
||||
|
||||
simplifiedNametag.create();
|
||||
si = new SimplifiedStatusIndicator({
|
||||
statusChanged: onStatusChanged
|
||||
});
|
||||
si.startup();
|
||||
updateInputDeviceMutedOverlay(Audio.muted);
|
||||
updateOutputDeviceMutedOverlay(isOutputMuted());
|
||||
Audio.mutedDesktopChanged.connect(onDesktopInputDeviceMutedChanged);
|
||||
Window.geometryChanged.connect(onGeometryChanged);
|
||||
HMD.displayModeChanged.connect(ensureFirstPersonCameraInHMD);
|
||||
Audio.avatarGainChanged.connect(maybeUpdateOutputDeviceMutedOverlay);
|
||||
Audio.localInjectorGainChanged.connect(maybeUpdateOutputDeviceMutedOverlay);
|
||||
Audio.serverInjectorGainChanged.connect(maybeUpdateOutputDeviceMutedOverlay);
|
||||
Audio.systemInjectorGainChanged.connect(maybeUpdateOutputDeviceMutedOverlay);
|
||||
|
||||
oldShowAudioTools = AvatarInputs.showAudioTools;
|
||||
AvatarInputs.showAudioTools = false;
|
||||
|
@ -506,10 +549,15 @@ function shutdown() {
|
|||
maybeDeleteOutputDeviceMutedOverlay();
|
||||
|
||||
simplifiedNametag.destroy();
|
||||
si.unload();
|
||||
|
||||
Audio.mutedDesktopChanged.disconnect(onDesktopInputDeviceMutedChanged);
|
||||
Window.geometryChanged.disconnect(onGeometryChanged);
|
||||
HMD.displayModeChanged.disconnect(ensureFirstPersonCameraInHMD);
|
||||
Audio.avatarGainChanged.disconnect(maybeUpdateOutputDeviceMutedOverlay);
|
||||
Audio.localInjectorGainChanged.disconnect(maybeUpdateOutputDeviceMutedOverlay);
|
||||
Audio.serverInjectorGainChanged.disconnect(maybeUpdateOutputDeviceMutedOverlay);
|
||||
Audio.systemInjectorGainChanged.disconnect(maybeUpdateOutputDeviceMutedOverlay);
|
||||
|
||||
AvatarInputs.showAudioTools = oldShowAudioTools;
|
||||
AvatarInputs.showBubbleTools = oldShowBubbleTools;
|
||||
|
|
Loading…
Reference in a new issue