mirror of
https://github.com/overte-org/overte.git
synced 2025-04-23 04:33:34 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into oldPropsFilters
This commit is contained in:
commit
8364f64d4d
346 changed files with 6771 additions and 3537 deletions
android/app
assignment-client
interface
CMakeLists.txt
resources
meshes
qml
CurrentAPI.qmlToolWindow.qml
controls-uit
controls
dialogs
hifi
Desktop.qmlNameCard.qmlPal.qml
commerce
inspectionCertificate
wallet
overlays
tablet
src
Application.cppApplication.hLODManager.cppLODManager.hMenu.cppMenu.h
avatar
commerce
scripting
AccountScriptingInterface.cppAccountScriptingInterface.hAccountServicesScriptingInterface.cppAccountServicesScriptingInterface.hWindowScriptingInterface.cppWindowScriptingInterface.h
ui/overlays
Base3DOverlay.cppCircle3DOverlay.cppCube3DOverlay.cppGrid3DOverlay.cppImage3DOverlay.cppLine3DOverlay.cppModelOverlay.cppOverlay.cppOverlay.hOverlayPanel.cppOverlayPanel.hOverlays.cppOverlays.hOverlaysPayload.cppPanelAttachable.cppPanelAttachable.hRectangle3DOverlay.cppShape3DOverlay.cppSphere3DOverlay.cppText3DOverlay.cppWeb3DOverlay.cpp
libraries
|
@ -11,7 +11,7 @@ link_hifi_libraries(
|
|||
physics
|
||||
audio audio-client
|
||||
ui midi controllers pointers
|
||||
model model-networking fbx animation
|
||||
graphics model-networking fbx animation
|
||||
entities entities-renderer
|
||||
avatars avatars-renderer
|
||||
ui-plugins input-plugins
|
||||
|
|
|
@ -11,7 +11,7 @@ setup_memory_debugger()
|
|||
|
||||
# link in the shared libraries
|
||||
link_hifi_libraries(
|
||||
audio avatars octree gpu model fbx entities
|
||||
audio avatars octree gpu graphics fbx entities
|
||||
networking animation recording shared script-engine embedded-webserver
|
||||
controllers physics plugins midi image
|
||||
)
|
||||
|
|
|
@ -343,7 +343,6 @@ void Agent::scriptRequestFinished() {
|
|||
|
||||
void Agent::executeScript() {
|
||||
_scriptEngine = scriptEngineFactory(ScriptEngine::AGENT_SCRIPT, _scriptContents, _payload);
|
||||
_scriptEngine->setParent(this); // be the parent of the script engine so it gets moved when we do
|
||||
|
||||
DependencyManager::get<RecordingScriptingInterface>()->setScriptEngine(_scriptEngine);
|
||||
|
||||
|
@ -439,7 +438,7 @@ void Agent::executeScript() {
|
|||
encodedBuffer = audio;
|
||||
}
|
||||
|
||||
AbstractAudioInterface::emitAudioPacket(encodedBuffer.data(), encodedBuffer.size(), audioSequenceNumber,
|
||||
AbstractAudioInterface::emitAudioPacket(encodedBuffer.data(), encodedBuffer.size(), audioSequenceNumber, false,
|
||||
audioTransform, scriptedAvatar->getWorldPosition(), glm::vec3(0),
|
||||
packetType, _selectedCodecName);
|
||||
});
|
||||
|
|
|
@ -275,17 +275,28 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) {
|
|||
if (micStreamIt == _audioStreams.end()) {
|
||||
// we don't have a mic stream yet, so add it
|
||||
|
||||
// read the channel flag to see if our stream is stereo or not
|
||||
// hop past the sequence number that leads the packet
|
||||
message.seek(sizeof(quint16));
|
||||
|
||||
quint8 channelFlag;
|
||||
message.readPrimitive(&channelFlag);
|
||||
// pull the codec string from the packet
|
||||
auto codecString = message.readString();
|
||||
|
||||
bool isStereo = channelFlag == 1;
|
||||
// determine if the stream is stereo or not
|
||||
bool isStereo;
|
||||
if (packetType == PacketType::SilentAudioFrame
|
||||
|| packetType == PacketType::ReplicatedSilentAudioFrame) {
|
||||
quint16 numSilentSamples;
|
||||
message.readPrimitive(&numSilentSamples);
|
||||
isStereo = numSilentSamples == AudioConstants::NETWORK_FRAME_SAMPLES_STEREO;
|
||||
} else {
|
||||
quint8 channelFlag;
|
||||
message.readPrimitive(&channelFlag);
|
||||
isStereo = channelFlag == 1;
|
||||
}
|
||||
|
||||
auto avatarAudioStream = new AvatarAudioStream(isStereo, AudioMixer::getStaticJitterFrames());
|
||||
avatarAudioStream->setupCodec(_codec, _selectedCodecName, AudioConstants::MONO);
|
||||
qCDebug(audio) << "creating new AvatarAudioStream... codec:" << _selectedCodecName;
|
||||
avatarAudioStream->setupCodec(_codec, _selectedCodecName, isStereo ? AudioConstants::STEREO : AudioConstants::MONO);
|
||||
qCDebug(audio) << "creating new AvatarAudioStream... codec:" << _selectedCodecName << "isStereo:" << isStereo;
|
||||
|
||||
connect(avatarAudioStream, &InboundAudioStream::mismatchedAudioCodec,
|
||||
this, &AudioMixerClientData::handleMismatchAudioFormat);
|
||||
|
@ -324,7 +335,7 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) {
|
|||
|
||||
#if INJECTORS_SUPPORT_CODECS
|
||||
injectorStream->setupCodec(_codec, _selectedCodecName, isStereo ? AudioConstants::STEREO : AudioConstants::MONO);
|
||||
qCDebug(audio) << "creating new injectorStream... codec:" << _selectedCodecName;
|
||||
qCDebug(audio) << "creating new injectorStream... codec:" << _selectedCodecName << "isStereo:" << isStereo;
|
||||
#endif
|
||||
|
||||
auto emplaced = _audioStreams.emplace(
|
||||
|
@ -567,7 +578,8 @@ void AudioMixerClientData::setupCodec(CodecPluginPointer codec, const QString& c
|
|||
|
||||
auto avatarAudioStream = getAvatarAudioStream();
|
||||
if (avatarAudioStream) {
|
||||
avatarAudioStream->setupCodec(codec, codecName, AudioConstants::MONO);
|
||||
avatarAudioStream->setupCodec(codec, codecName, avatarAudioStream->isStereo() ? AudioConstants::STEREO : AudioConstants::MONO);
|
||||
qCDebug(audio) << "setting AvatarAudioStream... codec:" << _selectedCodecName << "isStereo:" << avatarAudioStream->isStereo();
|
||||
}
|
||||
|
||||
#if INJECTORS_SUPPORT_CODECS
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <udt/PacketHeaders.h>
|
||||
|
||||
#include "AudioLogging.h"
|
||||
#include "AvatarAudioStream.h"
|
||||
|
||||
AvatarAudioStream::AvatarAudioStream(bool isStereo, int numStaticJitterFrames) :
|
||||
|
@ -41,6 +42,15 @@ int AvatarAudioStream::parseStreamProperties(PacketType type, const QByteArray&
|
|||
_ringBuffer.resizeForFrameSize(isStereo
|
||||
? AudioConstants::NETWORK_FRAME_SAMPLES_STEREO
|
||||
: AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
|
||||
// restart the codec
|
||||
if (_codec) {
|
||||
if (_decoder) {
|
||||
_codec->releaseDecoder(_decoder);
|
||||
}
|
||||
_decoder = _codec->createDecoder(AudioConstants::SAMPLE_RATE, isStereo ? AudioConstants::STEREO : AudioConstants::MONO);
|
||||
}
|
||||
qCDebug(audio) << "resetting AvatarAudioStream... codec:" << _selectedCodecName << "isStereo:" << isStereo;
|
||||
|
||||
_isStereo = isStereo;
|
||||
}
|
||||
|
||||
|
|
|
@ -116,8 +116,9 @@ public:
|
|||
void setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, const uint64_t& time);
|
||||
|
||||
QVector<JointData>& getLastOtherAvatarSentJoints(QUuid otherAvatar) {
|
||||
_lastOtherAvatarSentJoints[otherAvatar].resize(_avatar->getJointCount());
|
||||
return _lastOtherAvatarSentJoints[otherAvatar];
|
||||
auto& lastOtherAvatarSentJoints = _lastOtherAvatarSentJoints[otherAvatar];
|
||||
lastOtherAvatarSentJoints.resize(_avatar->getJointCount());
|
||||
return lastOtherAvatarSentJoints;
|
||||
}
|
||||
|
||||
void queuePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node);
|
||||
|
|
|
@ -201,7 +201,7 @@ endif()
|
|||
|
||||
# link required hifi libraries
|
||||
link_hifi_libraries(
|
||||
shared octree ktx gpu gl procedural model render
|
||||
shared octree ktx gpu gl procedural graphics render
|
||||
pointers
|
||||
recording fbx networking model-networking entities avatars trackers
|
||||
audio audio-client animation script-engine physics
|
||||
|
|
Binary file not shown.
642
interface/resources/qml/CurrentAPI.qml
Normal file
642
interface/resources/qml/CurrentAPI.qml
Normal file
|
@ -0,0 +1,642 @@
|
|||
//
|
||||
// ScriptAPI.qml
|
||||
//
|
||||
// Created by Luis Cuenca on 12/18/2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import "styles-uit"
|
||||
import "controls-uit" as HifiControls
|
||||
|
||||
Item {
|
||||
id: root
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
property var hideQtMethods: true
|
||||
|
||||
property var maxUpdateValues: 20
|
||||
property var maxReloadValues: 200
|
||||
property var apiMembers: []
|
||||
property var membersWithValues: []
|
||||
property var isReloading: false
|
||||
property var evaluatingIdx: -1
|
||||
property Component scrollSlider
|
||||
property Component keyboard
|
||||
|
||||
Rectangle {
|
||||
color: "white"
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
}
|
||||
|
||||
FontLoader { id: ralewayRegular; source: pathToFonts + "fonts/Raleway-Regular.ttf"; }
|
||||
|
||||
Timer {
|
||||
id: updateList
|
||||
interval: 200
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: {
|
||||
scrollSlider.y = 0;
|
||||
list.contentY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: topBar
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
width: parent.width
|
||||
height: 50
|
||||
HifiControls.GlyphButton {
|
||||
id: search
|
||||
enabled: true
|
||||
glyph: hifi.glyphs.search
|
||||
color: hifi.colors.text
|
||||
size: 48
|
||||
width: 50
|
||||
height: 50
|
||||
onClicked: {
|
||||
addListElements(searchBar.text);
|
||||
focus = true;
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.GlyphButton {
|
||||
id: back;
|
||||
enabled: true;
|
||||
glyph: hifi.glyphs.backward
|
||||
color: hifi.colors.text
|
||||
size: 48
|
||||
width: 30
|
||||
height: 50
|
||||
anchors.margins: 2
|
||||
onClicked: {
|
||||
var text = searchBar.text;
|
||||
var chain = text.split(".");
|
||||
if (chain.length > 2) {
|
||||
var result = chain[0]+".";
|
||||
for (var i = 1; i < chain.length-2; i++) {
|
||||
result += chain[i] + ".";
|
||||
}
|
||||
result += chain[chain.length-2];
|
||||
searchBar.text = result;
|
||||
} else {
|
||||
searchBar.text = (chain.length > 1) ? chain[0] : "";
|
||||
}
|
||||
if (chain.length > 1) {
|
||||
addListElements(searchBar.text);
|
||||
} else {
|
||||
addListElements();
|
||||
}
|
||||
focus = true;
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: searchBar
|
||||
focus: true
|
||||
font.pixelSize: 16
|
||||
width: 2*(parent.width-back.width-search.width-reload.width-update.width-evaluate.width-addMember.width-16)/3
|
||||
height: parent.height
|
||||
font.family: ralewayRegular.name
|
||||
placeholderText: "Search"
|
||||
onAccepted: {
|
||||
console.log("Enter Pressed");
|
||||
search.clicked();
|
||||
}
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus && HMD.mounted) {
|
||||
keyboard.raised = true;
|
||||
} else {
|
||||
keyboard.raised = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
id: addMember;
|
||||
enabled: true;
|
||||
text: "+"
|
||||
width: 50
|
||||
height: 50
|
||||
anchors.margins: 2
|
||||
onClicked: {
|
||||
addNewMember();
|
||||
updateList.start();
|
||||
focus = true;
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
id: evaluate;
|
||||
enabled: true;
|
||||
text: "Eval"
|
||||
width: 50
|
||||
height: 50
|
||||
anchors.margins: 2
|
||||
onClicked: {
|
||||
evaluateMember();
|
||||
focus = true;
|
||||
}
|
||||
}
|
||||
TextField {
|
||||
id: valueBar
|
||||
focus: true
|
||||
font.pixelSize: 16
|
||||
width: (parent.width-back.width-search.width-reload.width-update.width-evaluate.width-addMember.width-16)/3
|
||||
height: parent.height
|
||||
font.family: ralewayRegular.name
|
||||
placeholderText: "Value"
|
||||
textColor: "#4466DD"
|
||||
anchors.margins: 2
|
||||
}
|
||||
|
||||
HifiControls.GlyphButton {
|
||||
id: reload;
|
||||
enabled: false;
|
||||
glyph: hifi.glyphs.reload
|
||||
color: hifi.colors.text
|
||||
size: 48
|
||||
width: 50
|
||||
height: 50
|
||||
anchors.margins: 2
|
||||
onClicked: {
|
||||
reloadListValues();
|
||||
focus = true;
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.GlyphButton {
|
||||
id: update;
|
||||
enabled: false;
|
||||
glyph: hifi.glyphs.playback_play
|
||||
size: 48
|
||||
width: 50
|
||||
height: 50
|
||||
anchors.margins: 2
|
||||
onClicked: {
|
||||
if (isReloading) {
|
||||
update.glyph = hifi.glyphs.playback_play
|
||||
isReloading = false;
|
||||
stopReload();
|
||||
} else {
|
||||
update.glyph = hifi.glyphs.stop_square
|
||||
isReloading = true;
|
||||
startReload();
|
||||
}
|
||||
focus = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: memberModel
|
||||
}
|
||||
|
||||
Component {
|
||||
id: memberDelegate
|
||||
|
||||
Row {
|
||||
id: memberRow
|
||||
property var isMainKey: apiType === "class";
|
||||
spacing: 10
|
||||
Rectangle {
|
||||
width: isMainKey ? 20 : 40;
|
||||
height: parent.height
|
||||
}
|
||||
|
||||
RalewayRegular {
|
||||
text: apiMember
|
||||
size: !isMainKey ? 16 : 22
|
||||
MouseArea {
|
||||
width: list.width
|
||||
height: parent.height
|
||||
onClicked: {
|
||||
searchBar.text = apiType=="function()" ? apiMember + "()" : apiMember;
|
||||
valueBar.text = !apiValue ? "" : apiValue;
|
||||
list.currentIndex = index;
|
||||
evaluatingIdx = index;
|
||||
}
|
||||
onDoubleClicked: {
|
||||
if (apiType === "class") {
|
||||
addListElements(apiMember+".");
|
||||
} else {
|
||||
isolateElement(evaluatingIdx);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RalewayRegular {
|
||||
text: apiType
|
||||
size: 14
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
}
|
||||
|
||||
RalewayRegular {
|
||||
text: !apiValue ? "" : apiValue;
|
||||
size: 16
|
||||
color: "#4466DD"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: membersBackground
|
||||
anchors {
|
||||
left: parent.left; right: parent.right; top: topBar.bottom; bottom: parent.bottom;
|
||||
margins: hifi.dimensions.contentMargin.x
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y + 40
|
||||
}
|
||||
color: "white"
|
||||
radius: 4
|
||||
|
||||
ListView {
|
||||
id: list
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: scrollBar.left
|
||||
bottom: parent.bottom
|
||||
margins: 4
|
||||
}
|
||||
clip: true
|
||||
cacheBuffer: 4000
|
||||
model: memberModel
|
||||
delegate: memberDelegate
|
||||
highlightMoveDuration: 0
|
||||
|
||||
highlight: Rectangle {
|
||||
anchors {
|
||||
left: parent ? parent.left : undefined
|
||||
right: parent ? parent.right : undefined
|
||||
leftMargin: hifi.dimensions.borderWidth
|
||||
rightMargin: hifi.dimensions.borderWidth
|
||||
}
|
||||
color: "#BBDDFF"
|
||||
}
|
||||
onMovementStarted: {
|
||||
scrollSlider.manual = true;
|
||||
}
|
||||
onMovementEnded: {
|
||||
if (list.contentHeight > list.height) {
|
||||
var range = list.contentY/(list.contentHeight-list.height);
|
||||
range = range > 1 ? 1 : range;
|
||||
var idx = Math.round((list.count-1)*range);
|
||||
scrollSlider.positionSlider(idx);
|
||||
}
|
||||
scrollSlider.manual = false;
|
||||
returnToBounds()
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: scrollBar
|
||||
|
||||
property bool scrolling: list.contentHeight > list.height
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
topMargin: 4
|
||||
bottomMargin: 4
|
||||
}
|
||||
width: scrolling ? 18 : 0
|
||||
radius: 4
|
||||
color: hifi.colors.baseGrayShadow
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
onClicked: {
|
||||
var index = scrollSlider.y * (list.count - 1) / (scrollBar.height - scrollSlider.height);
|
||||
index = Math.round(index);
|
||||
var scrollAmount = Math.round(list.count/10);
|
||||
index = index + (mouse.y <= scrollSlider.y ? -scrollAmount : scrollAmount);
|
||||
if (index < 0) {
|
||||
index = 0;
|
||||
}
|
||||
if (index > list.count - 1) {
|
||||
index = list.count - 1;
|
||||
}
|
||||
scrollSlider.positionSlider(index);
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: scrollSlider
|
||||
|
||||
property var manual: false
|
||||
|
||||
function positionSlider(index){
|
||||
y = index*(scrollBar.height - scrollSlider.height)/(list.count - 1);
|
||||
}
|
||||
|
||||
anchors {
|
||||
right: parent.right
|
||||
rightMargin: 3
|
||||
}
|
||||
width: 12
|
||||
height: (list.height / list.contentHeight) * list.height
|
||||
radius: width / 4
|
||||
color: "white"
|
||||
|
||||
visible: scrollBar.scrolling;
|
||||
|
||||
onYChanged: {
|
||||
var index = y * (list.count - 1) / (scrollBar.height - scrollSlider.height);
|
||||
index = Math.round(index);
|
||||
if (!manual) {
|
||||
list.positionViewAtIndex(index, ListView.Visible);
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
drag.target: scrollSlider
|
||||
drag.axis: Drag.YAxis
|
||||
drag.minimumY: 0
|
||||
drag.maximumY: scrollBar.height - scrollSlider.height
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.GlyphButton {
|
||||
id: clipboard;
|
||||
enabled: true;
|
||||
glyph: hifi.glyphs.scriptNew
|
||||
size: 38
|
||||
width: 50
|
||||
height: 50
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.margins: 2
|
||||
anchors.leftMargin: 8
|
||||
onClicked: {
|
||||
var buffer = "";
|
||||
for (var i = 0; i < memberModel.count; i++) {
|
||||
var datarow = memberModel.get(i);
|
||||
buffer += "\n" + datarow.apiMember + " " + datarow.apiType + " " + datarow.apiValue;
|
||||
}
|
||||
Window.copyToClipboard(buffer);
|
||||
focus = true;
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
id: debug;
|
||||
enabled: true;
|
||||
text: "Debug Script"
|
||||
width: 120
|
||||
height: 50
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.margins: 2
|
||||
anchors.rightMargin: 8
|
||||
onClicked: {
|
||||
sendToScript({type: "selectScript"});
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.CheckBox {
|
||||
id: hideQt
|
||||
boxSize: 25
|
||||
boxRadius: 3
|
||||
checked: true
|
||||
anchors.left: clipboard.right
|
||||
anchors.leftMargin: 8
|
||||
anchors.verticalCenter: clipboard.verticalCenter
|
||||
anchors.margins: 2
|
||||
onClicked: {
|
||||
hideQtMethods = checked;
|
||||
addListElements();
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Label {
|
||||
id: hideLabel
|
||||
anchors.left: hideQt.right
|
||||
anchors.verticalCenter: clipboard.verticalCenter
|
||||
anchors.margins: 2
|
||||
font.pixelSize: 15
|
||||
text: "Hide Qt Methods"
|
||||
}
|
||||
|
||||
HifiControls.Keyboard {
|
||||
id: keyboard;
|
||||
raised: false;
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
console.log(event.nativeScanCode);
|
||||
if (event.key == Qt.Key_Left) {
|
||||
keyboard.raised = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addNewMember() {
|
||||
apiMembers.push({member: searchBar.text, type: "user", value: valueBar.text, hasValue: true});
|
||||
var data = {'memberIndex': apiMembers.length-1, 'apiMember': searchBar.text, 'apiType':"user", 'apiValue': valueBar.text};
|
||||
memberModel.insert(0, data);
|
||||
computeMembersWithValues();
|
||||
}
|
||||
|
||||
function evaluateMember() {
|
||||
sendToScript({type: "evaluateMember", data:{member: searchBar.text, index: evaluatingIdx}});
|
||||
}
|
||||
|
||||
function getValuesToRefresh() {
|
||||
var valuesToRefresh = [];
|
||||
for (var i = 0; i < membersWithValues.length; i++) {
|
||||
var index = membersWithValues[i];
|
||||
var row = memberModel.get(index);
|
||||
valuesToRefresh.push({index: index, member: (row.apiType == "function()") ? row.apiMember+"()" : row.apiMember, value: row.apiValue});
|
||||
}
|
||||
return valuesToRefresh;
|
||||
}
|
||||
|
||||
|
||||
function reloadListValues(){
|
||||
var valuesToRefresh = getValuesToRefresh();
|
||||
sendToScript({type: "refreshValues", data:valuesToRefresh});
|
||||
}
|
||||
|
||||
function startReload(){
|
||||
var valuesToRefresh = getValuesToRefresh();
|
||||
sendToScript({type: "startRefreshValues", data:valuesToRefresh});
|
||||
}
|
||||
|
||||
function stopReload(){
|
||||
sendToScript({type: "stopRefreshValues"});
|
||||
}
|
||||
|
||||
function refreshValues(data) {
|
||||
var buffer = "";
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var row = memberModel.get(data[i].index);
|
||||
row.apiValue = data[i].value;
|
||||
apiMembers[row.memberIndex].value = data[i].value;
|
||||
memberModel.set(data[i].index, row);
|
||||
buffer += "\n" + apiMembers[row.memberIndex].member + " : " + data[i].value;
|
||||
}
|
||||
print(buffer);
|
||||
}
|
||||
|
||||
|
||||
function fromScript(message) {
|
||||
if (message.type === "methods") {
|
||||
apiMembers = message.data;
|
||||
if (ScriptDiscoveryService.debugScriptUrl != "") {
|
||||
addListElements("GlobalDebugger");
|
||||
if (memberModel.count == 0) {
|
||||
addListElements();
|
||||
}
|
||||
} else {
|
||||
addListElements();
|
||||
}
|
||||
|
||||
} else if (message.type === "debugMethods") {
|
||||
addListElements("GlobalDebugger");
|
||||
} else if (message.type === "refreshValues") {
|
||||
refreshValues(message.data);
|
||||
} else if (message.type === "evaluateMember") {
|
||||
valueBar.text = message.data.value;
|
||||
var selrow = memberModel.get(message.data.index);
|
||||
if (selrow.apiMember === searchBar.text || selrow.apiMember === searchBar.text + "()") {
|
||||
selrow.apiValue = message.data.value;
|
||||
apiMembers[selrow.memberIndex].value = message.data.value;
|
||||
apiMembers[selrow.memberIndex].hasValue = true;
|
||||
memberModel.set(message.data.index, selrow);
|
||||
}
|
||||
} else if (message.type === "selectScript") {
|
||||
if (message.data.length > 0) {
|
||||
ScriptDiscoveryService.debugScriptUrl = message.data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getFilterPairs(filter){
|
||||
var filteredArray = [];
|
||||
var filterChain;
|
||||
filterChain = filter.split(" ");
|
||||
for (var i = 0; i < filterChain.length; i++) {
|
||||
filterChain[i] = filterChain[i].toUpperCase();
|
||||
}
|
||||
var matchPairs = [];
|
||||
|
||||
for (var i = 0; i < apiMembers.length; i++) {
|
||||
if (filterChain != undefined) {
|
||||
var found = 0;
|
||||
var memberComp = apiMembers[i].member.toUpperCase();
|
||||
for (var j = 0; j < filterChain.length; j++) {
|
||||
found += memberComp.indexOf(filterChain[j]) >= 0 ? 1 : 0;
|
||||
}
|
||||
if (found === 0) {
|
||||
continue;
|
||||
}
|
||||
matchPairs.push({index: i, found: found, member: apiMembers[i].member});
|
||||
}
|
||||
}
|
||||
|
||||
matchPairs.sort(function(a, b){
|
||||
if(a.found > b.found) return -1;
|
||||
if(a.found < b.found) return 1;
|
||||
if(a.member > b.member) return 1;
|
||||
if(a.member < b.member) return -1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
return matchPairs;
|
||||
}
|
||||
|
||||
function isolateElement(index) {
|
||||
var oldElement = memberModel.get(index);
|
||||
var newElement = {memberIndex: oldElement.memberIndex, apiMember: oldElement.apiMember, apiType: oldElement.apiType, apiValue: oldElement.apiValue};
|
||||
membersWithValues = apiMembers[oldElement.memberIndex].hasValue ? [0] : [];
|
||||
memberModel.remove(0, memberModel.count);
|
||||
memberModel.append(newElement);
|
||||
}
|
||||
|
||||
function computeMembersWithValues() {
|
||||
membersWithValues = [];
|
||||
for (var i = 0; i < memberModel.count; i++) {
|
||||
var idx = memberModel.get(i).memberIndex;
|
||||
if (apiMembers[idx].hasValue) {
|
||||
membersWithValues.push(i);
|
||||
}
|
||||
}
|
||||
update.enabled = membersWithValues.length <= maxUpdateValues;
|
||||
reload.enabled = membersWithValues.length <= maxReloadValues;
|
||||
}
|
||||
|
||||
function addListElements(filter) {
|
||||
valueBar.text = "";
|
||||
memberModel.remove(0, memberModel.count);
|
||||
|
||||
var filteredArray = (filter != undefined) ? [] : apiMembers;
|
||||
var matchPairs;
|
||||
if (filter != undefined) {
|
||||
matchPairs = getFilterPairs(filter);
|
||||
for (var i = 0; i < matchPairs.length; i++) {
|
||||
if (matchPairs[i].found < matchPairs[0].found) {
|
||||
break;
|
||||
}
|
||||
var idx = matchPairs[i].index;
|
||||
filteredArray.push(apiMembers[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < filteredArray.length; i++) {
|
||||
var data = {'memberIndex': matchPairs ? matchPairs[i].index : i,
|
||||
'apiMember': filteredArray[i].member,
|
||||
'apiType': filteredArray[i].type,
|
||||
'apiValue': filteredArray[i].value};
|
||||
|
||||
if (hideQtMethods) {
|
||||
var chain = data.apiMember.split(".");
|
||||
var method = chain[chain.length-1];
|
||||
if (method != "destroyed" &&
|
||||
method != "objectName" &&
|
||||
method != "objectNameChanged") {
|
||||
memberModel.append(data);
|
||||
}
|
||||
} else {
|
||||
memberModel.append(data);
|
||||
}
|
||||
}
|
||||
|
||||
computeMembersWithValues();
|
||||
|
||||
if (isReloading) {
|
||||
update.glyph = hifi.glyphs.playback_play
|
||||
isReloading = false;
|
||||
stopReload();
|
||||
}
|
||||
|
||||
if (memberModel.count > 0) {
|
||||
scrollSlider.y = 0;
|
||||
list.contentY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
signal sendToScript(var message);
|
||||
}
|
|
@ -1,256 +0,0 @@
|
|||
//
|
||||
// ToolWindow.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 12 Jan 2016
|
||||
// Copyright 2016 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
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtWebEngine 1.1
|
||||
import QtWebChannel 1.0
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
import "windows"
|
||||
import "controls-uit"
|
||||
import "styles-uit"
|
||||
|
||||
|
||||
ScrollingWindow {
|
||||
id: toolWindow
|
||||
resizable: true
|
||||
objectName: "ToolWindow"
|
||||
destroyOnCloseButton: false
|
||||
destroyOnHidden: false
|
||||
closable: true
|
||||
shown: false
|
||||
title: "Edit"
|
||||
property alias tabView: tabView
|
||||
implicitWidth: 520; implicitHeight: 695
|
||||
minSize: Qt.vector2d(456, 500)
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
onParentChanged: {
|
||||
if (parent) {
|
||||
x = 120;
|
||||
y = 120;
|
||||
}
|
||||
}
|
||||
|
||||
onShownChanged: {
|
||||
keyboardEnabled = HMD.active;
|
||||
}
|
||||
|
||||
Settings {
|
||||
category: "ToolWindow.Position"
|
||||
property alias x: toolWindow.x
|
||||
property alias y: toolWindow.y
|
||||
}
|
||||
|
||||
Item {
|
||||
id: toolWindowTabViewItem
|
||||
height: pane.scrollHeight
|
||||
width: pane.contentWidth
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
|
||||
TabView {
|
||||
id: tabView
|
||||
width: pane.contentWidth
|
||||
// Pane height so that don't use Window's scrollbars otherwise tabs may be scrolled out of view.
|
||||
height: pane.scrollHeight
|
||||
property int tabCount: 0
|
||||
|
||||
Repeater {
|
||||
model: 4
|
||||
Tab {
|
||||
// Force loading of the content even if the tab is not visible
|
||||
// (required for letting the C++ code access the webview)
|
||||
active: true
|
||||
enabled: false
|
||||
property string originalUrl: ""
|
||||
|
||||
WebView {
|
||||
id: webView
|
||||
anchors.fill: parent
|
||||
enabled: false
|
||||
Component.onCompleted: {
|
||||
webChannel.registerObject("eventBridge", eventBridge);
|
||||
webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper);
|
||||
}
|
||||
|
||||
onEnabledChanged: toolWindow.updateVisiblity()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
style: TabViewStyle {
|
||||
|
||||
frame: Rectangle { // Background shown before content loads.
|
||||
anchors.fill: parent
|
||||
color: hifi.colors.baseGray
|
||||
}
|
||||
|
||||
frameOverlap: 0
|
||||
|
||||
tab: Rectangle {
|
||||
implicitWidth: text.width
|
||||
implicitHeight: 3 * text.height
|
||||
color: styleData.selected ? hifi.colors.black : hifi.colors.tabBackgroundDark
|
||||
|
||||
RalewayRegular {
|
||||
id: text
|
||||
text: styleData.title
|
||||
font.capitalization: Font.AllUppercase
|
||||
size: hifi.fontSizes.tabName
|
||||
width: tabView.tabCount > 1 ? styleData.availableWidth / tabView.tabCount : implicitWidth + 2 * hifi.dimensions.contentSpacing.x
|
||||
elide: Text.ElideRight
|
||||
color: styleData.selected ? hifi.colors.primaryHighlight : hifi.colors.lightGrayText
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
Rectangle { // Separator.
|
||||
width: 1
|
||||
height: parent.height
|
||||
color: hifi.colors.black
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
visible: styleData.index > 0
|
||||
|
||||
Rectangle {
|
||||
width: 1
|
||||
height: 1
|
||||
color: hifi.colors.baseGray
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle { // Active underline.
|
||||
width: parent.width - (styleData.index > 0 ? 1 : 0)
|
||||
height: 1
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
color: styleData.selected ? hifi.colors.primaryHighlight : hifi.colors.baseGray
|
||||
}
|
||||
}
|
||||
|
||||
tabOverlap: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateVisiblity() {
|
||||
if (visible) {
|
||||
for (var i = 0; i < tabView.count; ++i) {
|
||||
if (tabView.getTab(i).enabled) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
shown = false;
|
||||
}
|
||||
}
|
||||
|
||||
function findIndexForUrl(source) {
|
||||
for (var i = 0; i < tabView.count; ++i) {
|
||||
var tab = tabView.getTab(i);
|
||||
if (tab.originalUrl === source) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function findTabForUrl(source) {
|
||||
var index = findIndexForUrl(source);
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
return tabView.getTab(index);
|
||||
}
|
||||
|
||||
function showTabForUrl(source, newVisible) {
|
||||
var index = findIndexForUrl(source);
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var tab = tabView.getTab(index);
|
||||
if (newVisible) {
|
||||
toolWindow.shown = true
|
||||
tab.enabled = true
|
||||
} else {
|
||||
tab.enabled = false;
|
||||
updateVisiblity();
|
||||
}
|
||||
}
|
||||
|
||||
function findFreeTab() {
|
||||
for (var i = 0; i < tabView.count; ++i) {
|
||||
var tab = tabView.getTab(i);
|
||||
if (tab && (!tab.originalUrl || tab.originalUrl === "")) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function removeTabForUrl(source) {
|
||||
var index = findIndexForUrl(source);
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var tab = tabView.getTab(index);
|
||||
tab.title = "";
|
||||
tab.enabled = false;
|
||||
tab.originalUrl = "";
|
||||
tab.item.url = "about:blank";
|
||||
tab.item.enabled = false;
|
||||
tabView.tabCount--;
|
||||
}
|
||||
|
||||
function addWebTab(properties) {
|
||||
if (!properties.source) {
|
||||
console.warn("Attempted to open Web Tool Pane without URL");
|
||||
return;
|
||||
}
|
||||
|
||||
var existingTabIndex = findIndexForUrl(properties.source);
|
||||
if (existingTabIndex >= 0) {
|
||||
var tab = tabView.getTab(existingTabIndex);
|
||||
return tab.item;
|
||||
}
|
||||
|
||||
var freeTabIndex = findFreeTab();
|
||||
if (freeTabIndex === -1) {
|
||||
console.warn("Unable to add new tab");
|
||||
return;
|
||||
}
|
||||
|
||||
if (properties.width) {
|
||||
tabView.width = Math.min(Math.max(tabView.width, properties.width), toolWindow.maxSize.x);
|
||||
}
|
||||
|
||||
if (properties.height) {
|
||||
tabView.height = Math.min(Math.max(tabView.height, properties.height), toolWindow.maxSize.y);
|
||||
}
|
||||
|
||||
var tab = tabView.getTab(freeTabIndex);
|
||||
tab.title = properties.title || "Unknown";
|
||||
tab.enabled = true;
|
||||
tab.originalUrl = properties.source;
|
||||
|
||||
var result = tab.item;
|
||||
result.enabled = true;
|
||||
tabView.tabCount++;
|
||||
result.url = properties.source;
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -45,18 +45,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
mouse.accepted = true;
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
|
||||
webEntity.synthesizeKeyPress(glyph);
|
||||
webEntity.synthesizeKeyPress(glyph, mirrorText);
|
||||
|
||||
if (toggle) {
|
||||
toggled = !toggled;
|
||||
}
|
||||
}
|
||||
|
||||
onDoubleClicked: {
|
||||
mouse.accepted = true;
|
||||
}
|
||||
|
@ -94,6 +82,14 @@ Item {
|
|||
|
||||
onReleased: {
|
||||
if (containsMouse) {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
|
||||
webEntity.synthesizeKeyPress(glyph);
|
||||
webEntity.synthesizeKeyPress(glyph, mirrorText);
|
||||
|
||||
if (toggle) {
|
||||
toggled = !toggled;
|
||||
}
|
||||
keyItem.state = "mouseOver";
|
||||
} else {
|
||||
if (toggled) {
|
||||
|
|
|
@ -27,10 +27,12 @@ TextField {
|
|||
property bool hasRoundedBorder: false
|
||||
property bool error: false;
|
||||
property bool hasClearButton: false;
|
||||
property string leftPlaceholderGlyph: "";
|
||||
|
||||
placeholderText: textField.placeholderText
|
||||
|
||||
FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; }
|
||||
FontLoader { id: hifiGlyphs; source: "../../fonts/hifi-glyphs.ttf"; }
|
||||
font.family: firaSansSemiBold.name
|
||||
font.pixelSize: hifi.fontSizes.textFieldInput
|
||||
font.italic: textField.text == ""
|
||||
|
@ -54,6 +56,7 @@ TextField {
|
|||
}
|
||||
|
||||
style: TextFieldStyle {
|
||||
id: style;
|
||||
textColor: {
|
||||
if (isLightColorScheme) {
|
||||
if (textField.activeFocus) {
|
||||
|
@ -102,6 +105,16 @@ TextField {
|
|||
border.width: textField.activeFocus || hasRoundedBorder || textField.error ? 1 : 0
|
||||
radius: isSearchField ? textField.height / 2 : (hasRoundedBorder ? 4 : 0)
|
||||
|
||||
HiFiGlyphs {
|
||||
text: textField.leftPlaceholderGlyph;
|
||||
color: textColor;
|
||||
size: hifi.fontSizes.textFieldSearchIcon;
|
||||
anchors.left: parent.left;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
anchors.leftMargin: hifi.dimensions.textPadding - 2;
|
||||
visible: text;
|
||||
}
|
||||
|
||||
HiFiGlyphs {
|
||||
text: hifi.glyphs.search
|
||||
color: textColor
|
||||
|
@ -132,7 +145,7 @@ TextField {
|
|||
placeholderTextColor: isFaintGrayColorScheme ? hifi.colors.lightGrayText : hifi.colors.lightGray
|
||||
selectedTextColor: hifi.colors.black
|
||||
selectionColor: hifi.colors.primaryHighlight
|
||||
padding.left: (isSearchField ? textField.height - 2 : 0) + hifi.dimensions.textPadding
|
||||
padding.left: ((isSearchField || textField.leftPlaceholderGlyph !== "") ? textField.height - 2 : 0) + hifi.dimensions.textPadding
|
||||
padding.right: (hasClearButton ? textField.height - 2 : 0) + hifi.dimensions.textPadding
|
||||
}
|
||||
|
||||
|
|
|
@ -41,9 +41,9 @@ Item {
|
|||
onNewViewRequestedCallback: {
|
||||
// desktop is not defined for web-entities or tablet
|
||||
if (typeof desktop !== "undefined") {
|
||||
desktop.openBrowserWindow(request, profile);
|
||||
desktop.openBrowserWindow(request, webViewCoreProfile);
|
||||
} else {
|
||||
tabletRoot.openBrowserWindow(request, profile);
|
||||
tabletRoot.openBrowserWindow(request, webViewCoreProfile);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,15 @@ ModalWindow {
|
|||
|
||||
signal selectedFile(var file);
|
||||
signal canceled();
|
||||
|
||||
signal selected(int button);
|
||||
function click(button) {
|
||||
clickedButton = button;
|
||||
selected(button);
|
||||
destroy();
|
||||
}
|
||||
|
||||
property int clickedButton: OriginalDialogs.StandardButton.NoButton;
|
||||
|
||||
Component.onCompleted: {
|
||||
console.log("Helper " + helper + " drives " + drives);
|
||||
|
||||
|
@ -628,7 +636,10 @@ ModalWindow {
|
|||
case Qt.Key_Backtab:
|
||||
event.accepted = false;
|
||||
break;
|
||||
|
||||
case Qt.Key_Escape:
|
||||
event.accepted = true;
|
||||
root.click(OriginalDialogs.StandardButton.Cancel);
|
||||
break;
|
||||
default:
|
||||
if (addToPrefix(event)) {
|
||||
event.accepted = true
|
||||
|
@ -793,7 +804,11 @@ ModalWindow {
|
|||
case Qt.Key_Home:
|
||||
event.accepted = d.navigateHome();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case Qt.Key_Escape:
|
||||
event.accepted = true;
|
||||
root.click(OriginalDialogs.StandardButton.Cancel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
//
|
||||
// AvatarBrowser.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 30 Aug 2015
|
||||
// Copyright 2015 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
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtWebChannel 1.0
|
||||
import QtWebEngine 1.2
|
||||
|
||||
import "../../windows"
|
||||
import "../../controls-uit"
|
||||
import "../../styles-uit"
|
||||
|
||||
Window {
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
width: 900; height: 700
|
||||
resizable: true
|
||||
modality: Qt.ApplicationModal
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
|
||||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: true
|
||||
property bool punctuationMode: false
|
||||
|
||||
BaseWebView {
|
||||
id: webview
|
||||
url: Account.metaverseServerURL + "/marketplace?category=avatars"
|
||||
focus: true
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: keyboard.top
|
||||
}
|
||||
|
||||
// Create a global EventBridge object for raiseAndLowerKeyboard.
|
||||
WebEngineScript {
|
||||
id: createGlobalEventBridge
|
||||
sourceCode: eventBridgeJavaScriptToInject
|
||||
injectionPoint: WebEngineScript.DocumentCreation
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// Detect when may want to raise and lower keyboard.
|
||||
WebEngineScript {
|
||||
id: raiseAndLowerKeyboard
|
||||
injectionPoint: WebEngineScript.Deferred
|
||||
sourceUrl: resourceDirectoryUrl + "html/raiseAndLowerKeyboard.js"
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard ]
|
||||
|
||||
Component.onCompleted: {
|
||||
webChannel.registerObject("eventBridge", eventBridge);
|
||||
webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
Keyboard {
|
||||
id: keyboard
|
||||
raised: parent.keyboardEnabled && parent.keyboardRaised
|
||||
numeric: parent.punctuationMode
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
keyboardEnabled = HMD.active;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -99,25 +99,9 @@ Preference {
|
|||
leftMargin: dataTextField.acceptableInput ? hifi.dimensions.contentSpacing.x : 0
|
||||
}
|
||||
onClicked: {
|
||||
if (typeof desktop !== "undefined") {
|
||||
// Load dialog via OffscreenUi so that JavaScript EventBridge is available.
|
||||
root.browser = OffscreenUi.load("dialogs/preferences/AvatarBrowser.qml");
|
||||
root.browser.windowDestroyed.connect(function(){
|
||||
root.browser = null;
|
||||
});
|
||||
} else {
|
||||
root.browser = tabletAvatarBrowserBuilder.createObject(tabletRoot);
|
||||
|
||||
// Make dialog modal.
|
||||
tabletRoot.openModal = root.browser;
|
||||
}
|
||||
ApplicationInterface.loadAvatarBrowser();
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: tabletAvatarBrowserBuilder;
|
||||
TabletAvatarBrowser { }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,10 +22,6 @@ OriginalDesktop.Desktop {
|
|||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
|
||||
// The tool window, one instance
|
||||
property alias toolWindow: toolWindow
|
||||
ToolWindow { id: toolWindow }
|
||||
|
||||
Action {
|
||||
text: "Open Browser"
|
||||
shortcut: "Ctrl+B"
|
||||
|
|
|
@ -50,7 +50,7 @@ Item {
|
|||
id: avatarImage
|
||||
visible: profileUrl !== "" && userName !== "";
|
||||
// Size
|
||||
height: isMyCard ? 70 : 42;
|
||||
height: isMyCard ? 84 : 42;
|
||||
width: visible ? height : 0;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: isMyCard ? 0 : 8;
|
||||
|
@ -520,7 +520,7 @@ Item {
|
|||
Slider {
|
||||
id: gainSlider
|
||||
// Size
|
||||
width: thisNameCard.width;
|
||||
width: isMyCard ? thisNameCard.width - 20 : thisNameCard.width;
|
||||
height: 14
|
||||
// Anchors
|
||||
anchors.verticalCenter: nameCardVUMeter.verticalCenter;
|
||||
|
|
|
@ -28,7 +28,7 @@ Rectangle {
|
|||
// Properties
|
||||
property bool debug: false;
|
||||
property int myCardWidth: width - upperRightInfoContainer.width;
|
||||
property int myCardHeight: 80;
|
||||
property int myCardHeight: 100;
|
||||
property int rowHeight: 60;
|
||||
property int actionButtonWidth: 55;
|
||||
property int locationColumnWidth: 170;
|
||||
|
|
|
@ -145,7 +145,7 @@ Rectangle {
|
|||
// Title text
|
||||
RalewayRegular {
|
||||
id: popText;
|
||||
text: "PROOF OF PURCHASE";
|
||||
text: "Proof of Provenance";
|
||||
// Text size
|
||||
size: 16;
|
||||
// Anchors
|
||||
|
@ -155,7 +155,7 @@ Rectangle {
|
|||
anchors.right: titleBarText.right;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.baseGray;
|
||||
color: hifi.colors.darkGray;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -182,7 +182,7 @@ Rectangle {
|
|||
anchors.rightMargin: 16;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.baseGray;
|
||||
color: hifi.colors.darkGray;
|
||||
}
|
||||
RalewaySemiBold {
|
||||
id: itemName;
|
||||
|
@ -196,7 +196,7 @@ Rectangle {
|
|||
anchors.right: itemNameHeader.right;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.blueAccent;
|
||||
color: hifi.colors.white;
|
||||
elide: Text.ElideRight;
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
|
@ -205,7 +205,7 @@ Rectangle {
|
|||
sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', marketplaceUrl: root.marketplaceUrl});
|
||||
}
|
||||
onEntered: itemName.color = hifi.colors.blueHighlight;
|
||||
onExited: itemName.color = hifi.colors.blueAccent;
|
||||
onExited: itemName.color = hifi.colors.white;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,7 +223,7 @@ Rectangle {
|
|||
anchors.rightMargin: 16;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.lightGray;
|
||||
color: hifi.colors.darkGray;
|
||||
}
|
||||
RalewayRegular {
|
||||
id: ownedBy;
|
||||
|
@ -236,7 +236,7 @@ Rectangle {
|
|||
anchors.left: ownedByHeader.left;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.darkGray;
|
||||
color: hifi.colors.white;
|
||||
elide: Text.ElideRight;
|
||||
}
|
||||
AnonymousProRegular {
|
||||
|
@ -252,7 +252,7 @@ Rectangle {
|
|||
anchors.leftMargin: 6;
|
||||
anchors.right: ownedByHeader.right;
|
||||
// Style
|
||||
color: hifi.colors.lightGray;
|
||||
color: hifi.colors.white;
|
||||
elide: Text.ElideRight;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ Rectangle {
|
|||
anchors.rightMargin: 16;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.lightGray;
|
||||
color: hifi.colors.darkGray;
|
||||
}
|
||||
AnonymousProRegular {
|
||||
id: edition;
|
||||
|
@ -285,7 +285,7 @@ Rectangle {
|
|||
anchors.right: editionHeader.right;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.darkGray;
|
||||
color: hifi.colors.white;
|
||||
}
|
||||
|
||||
RalewayRegular {
|
||||
|
@ -302,7 +302,7 @@ Rectangle {
|
|||
anchors.rightMargin: 16;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.lightGray;
|
||||
color: hifi.colors.darkGray;
|
||||
}
|
||||
AnonymousProRegular {
|
||||
id: dateOfPurchase;
|
||||
|
@ -316,7 +316,7 @@ Rectangle {
|
|||
anchors.right: dateOfPurchaseHeader.right;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.darkGray;
|
||||
color: hifi.colors.white;
|
||||
}
|
||||
|
||||
RalewayRegular {
|
||||
|
@ -349,7 +349,7 @@ Rectangle {
|
|||
|
||||
// "Cancel" button
|
||||
HifiControlsUit.Button {
|
||||
color: hifi.buttons.noneBorderless;
|
||||
color: hifi.buttons.noneBorderlessWhite;
|
||||
colorScheme: hifi.colorSchemes.light;
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
|
|
Binary file not shown.
Before ![]() (image error) Size: 63 KiB After ![]() (image error) Size: 62 KiB ![]() ![]() |
|
@ -25,7 +25,6 @@ Item {
|
|||
|
||||
id: root;
|
||||
property string keyFilePath;
|
||||
property bool showDebugButtons: true;
|
||||
|
||||
Connections {
|
||||
target: Commerce;
|
||||
|
@ -55,37 +54,6 @@ Item {
|
|||
// Style
|
||||
color: hifi.colors.blueHighlight;
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
id: clearCachedPassphraseButton;
|
||||
visible: root.showDebugButtons;
|
||||
color: hifi.buttons.black;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: parent.top;
|
||||
anchors.left: helpTitleText.right;
|
||||
anchors.leftMargin: 20;
|
||||
height: 40;
|
||||
width: 150;
|
||||
text: "DBG: Clear Pass";
|
||||
onClicked: {
|
||||
Commerce.setPassphrase("");
|
||||
sendSignalToWallet({method: 'passphraseReset'});
|
||||
}
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
id: resetButton;
|
||||
visible: root.showDebugButtons;
|
||||
color: hifi.buttons.red;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: clearCachedPassphraseButton.top;
|
||||
anchors.left: clearCachedPassphraseButton.right;
|
||||
height: 40;
|
||||
width: 150;
|
||||
text: "DBG: RST Wallet";
|
||||
onClicked: {
|
||||
Commerce.reset();
|
||||
sendSignalToWallet({method: 'walletReset'});
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: helpModel;
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
//
|
||||
// SendMoney.qml
|
||||
// qml/hifi/commerce/wallet
|
||||
//
|
||||
// SendMoney
|
||||
//
|
||||
// Created by Zach Fox on 2017-08-18
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import Hifi 1.0 as Hifi
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import "../../../styles-uit"
|
||||
import "../../../controls-uit" as HifiControlsUit
|
||||
import "../../../controls" as HifiControls
|
||||
|
||||
// references XXX from root context
|
||||
|
||||
Item {
|
||||
HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
|
||||
Connections {
|
||||
target: Commerce;
|
||||
}
|
||||
|
||||
// "Unavailable"
|
||||
RalewayRegular {
|
||||
text: "You currently cannot send money to other High Fidelity users.";
|
||||
// Anchors
|
||||
anchors.fill: parent;
|
||||
// Text size
|
||||
size: 24;
|
||||
// Style
|
||||
color: hifi.colors.faintGray;
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
|
||||
//
|
||||
// FUNCTION DEFINITIONS START
|
||||
//
|
||||
//
|
||||
// Function Name: fromScript()
|
||||
//
|
||||
// Relevant Variables:
|
||||
// None
|
||||
//
|
||||
// Arguments:
|
||||
// message: The message sent from the JavaScript.
|
||||
// Messages are in format "{method, params}", like json-rpc.
|
||||
//
|
||||
// Description:
|
||||
// Called when a message is received from a script.
|
||||
//
|
||||
function fromScript(message) {
|
||||
switch (message.method) {
|
||||
default:
|
||||
console.log('Unrecognized message from wallet.js:', JSON.stringify(message));
|
||||
}
|
||||
}
|
||||
signal sendSignalToWallet(var msg);
|
||||
//
|
||||
// FUNCTION DEFINITIONS END
|
||||
//
|
||||
}
|
|
@ -19,8 +19,7 @@ import "../../../styles-uit"
|
|||
import "../../../controls-uit" as HifiControlsUit
|
||||
import "../../../controls" as HifiControls
|
||||
import "../common" as HifiCommerceCommon
|
||||
|
||||
// references XXX from root context
|
||||
import "./sendMoney"
|
||||
|
||||
Rectangle {
|
||||
HifiConstants { id: hifi; }
|
||||
|
@ -316,18 +315,29 @@ Rectangle {
|
|||
|
||||
Connections {
|
||||
onSendSignalToWallet: {
|
||||
sendToScript(msg);
|
||||
if (msg.method === 'transactionHistory_usernameLinkClicked') {
|
||||
userInfoViewer.url = msg.usernameLink;
|
||||
userInfoViewer.visible = true;
|
||||
} else {
|
||||
sendToScript(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SendMoney {
|
||||
id: sendMoney;
|
||||
z: 997;
|
||||
visible: root.activeView === "sendMoney";
|
||||
anchors.top: titleBarContainer.bottom;
|
||||
anchors.bottom: tabButtonsContainer.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.fill: parent;
|
||||
parentAppTitleBarHeight: titleBarContainer.height;
|
||||
parentAppNavBarHeight: tabButtonsContainer.height;
|
||||
|
||||
Connections {
|
||||
onSendSignalToWallet: {
|
||||
sendToScript(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Security {
|
||||
|
@ -497,7 +507,7 @@ Rectangle {
|
|||
Rectangle {
|
||||
id: sendMoneyButtonContainer;
|
||||
visible: !walletSetup.visible;
|
||||
color: hifi.colors.black;
|
||||
color: root.activeView === "sendMoney" ? hifi.colors.blueAccent : hifi.colors.black;
|
||||
anchors.top: parent.top;
|
||||
anchors.left: exchangeMoneyButtonContainer.right;
|
||||
anchors.bottom: parent.bottom;
|
||||
|
@ -513,7 +523,7 @@ Rectangle {
|
|||
anchors.top: parent.top;
|
||||
anchors.topMargin: -2;
|
||||
// Style
|
||||
color: hifi.colors.lightGray50;
|
||||
color: root.activeView === "sendMoney" || sendMoneyTabMouseArea.containsMouse ? hifi.colors.white : hifi.colors.blueHighlight;
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
|
@ -528,12 +538,24 @@ Rectangle {
|
|||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 4;
|
||||
// Style
|
||||
color: hifi.colors.lightGray50;
|
||||
color: root.activeView === "sendMoney" || sendMoneyTabMouseArea.containsMouse ? hifi.colors.white : hifi.colors.blueHighlight;
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignTop;
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: sendMoneyTabMouseArea;
|
||||
anchors.fill: parent;
|
||||
hoverEnabled: enabled;
|
||||
onClicked: {
|
||||
root.activeView = "sendMoney";
|
||||
tabButtonsContainer.resetTabButtonColors();
|
||||
}
|
||||
onEntered: parent.color = hifi.colors.blueHighlight;
|
||||
onExited: parent.color = root.activeView === "sendMoney" ? hifi.colors.blueAccent : hifi.colors.black;
|
||||
}
|
||||
}
|
||||
|
||||
// "SECURITY" tab button
|
||||
|
@ -665,9 +687,16 @@ Rectangle {
|
|||
// TAB BUTTONS END
|
||||
//
|
||||
|
||||
HifiControls.TabletWebView {
|
||||
id: userInfoViewer;
|
||||
z: 998;
|
||||
anchors.fill: parent;
|
||||
visible: false;
|
||||
}
|
||||
|
||||
Item {
|
||||
id: keyboardContainer;
|
||||
z: 998;
|
||||
z: 999;
|
||||
visible: keyboard.raised;
|
||||
property bool punctuationMode: false;
|
||||
anchors {
|
||||
|
@ -713,6 +742,13 @@ Rectangle {
|
|||
case 'inspectionCertificate_resetCert':
|
||||
// NOP
|
||||
break;
|
||||
case 'updateConnections':
|
||||
sendMoney.updateConnections(message.connections);
|
||||
break;
|
||||
case 'selectRecipient':
|
||||
case 'updateSelectedRecipientUsername':
|
||||
sendMoney.fromScript(message);
|
||||
break;
|
||||
default:
|
||||
console.log('Unrecognized message from wallet.js:', JSON.stringify(message));
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@ import "../../../styles-uit"
|
|||
import "../../../controls-uit" as HifiControlsUit
|
||||
import "../../../controls" as HifiControls
|
||||
|
||||
// references XXX from root context
|
||||
|
||||
Item {
|
||||
HifiConstants { id: hifi; }
|
||||
|
||||
|
@ -32,6 +30,20 @@ Item {
|
|||
property int currentHistoryPage: 1;
|
||||
property var pagesAlreadyAdded: new Array();
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
transactionHistoryModel.clear();
|
||||
Commerce.balance();
|
||||
initialHistoryReceived = false;
|
||||
root.currentHistoryPage = 1;
|
||||
root.noMoreHistoryData = false;
|
||||
root.historyRequestPending = true;
|
||||
Commerce.history(root.currentHistoryPage);
|
||||
} else {
|
||||
refreshTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Commerce;
|
||||
|
||||
|
@ -189,20 +201,6 @@ Item {
|
|||
color: hifi.colors.white;
|
||||
// Alignment
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
transactionHistoryModel.clear();
|
||||
Commerce.balance();
|
||||
initialHistoryReceived = false;
|
||||
root.currentHistoryPage = 1;
|
||||
root.noMoreHistoryData = false;
|
||||
root.historyRequestPending = true;
|
||||
Commerce.history(root.currentHistoryPage);
|
||||
} else {
|
||||
refreshTimer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "balance" text below field
|
||||
|
@ -384,8 +382,8 @@ Item {
|
|||
height: visible ? parent.height : 0;
|
||||
|
||||
AnonymousProRegular {
|
||||
id: dateText;
|
||||
text: model.created_at ? getFormattedDate(model.created_at * 1000) : "";
|
||||
id: hfcText;
|
||||
text: model.hfc_text || '';
|
||||
// Style
|
||||
size: 18;
|
||||
anchors.left: parent.left;
|
||||
|
@ -393,28 +391,33 @@ Item {
|
|||
anchors.topMargin: 15;
|
||||
width: 118;
|
||||
height: paintedHeight;
|
||||
color: hifi.colors.blueAccent;
|
||||
wrapMode: Text.WordWrap;
|
||||
font.bold: true;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignRight;
|
||||
}
|
||||
|
||||
AnonymousProRegular {
|
||||
id: transactionText;
|
||||
text: model.text ? (model.status === "invalidated" ? ("INVALIDATED: " + model.text) : model.text) : "";
|
||||
text: model.transaction_text ? (model.status === "invalidated" ? ("INVALIDATED: " + model.transaction_text) : model.transaction_text) : "";
|
||||
size: 18;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 15;
|
||||
anchors.left: dateText.right;
|
||||
anchors.left: hfcText.right;
|
||||
anchors.leftMargin: 20;
|
||||
anchors.right: parent.right;
|
||||
height: paintedHeight;
|
||||
color: model.status === "invalidated" ? hifi.colors.redAccent : hifi.colors.baseGrayHighlight;
|
||||
linkColor: hifi.colors.blueAccent;
|
||||
wrapMode: Text.WordWrap;
|
||||
font.strikeout: model.status === "invalidated";
|
||||
|
||||
onLinkActivated: {
|
||||
sendSignalToWallet({method: 'transactionHistory_linkClicked', marketplaceLink: link});
|
||||
if (link.indexOf("users/") !== -1) {
|
||||
sendSignalToWallet({method: 'transactionHistory_usernameLinkClicked', usernameLink: link});
|
||||
} else {
|
||||
sendSignalToWallet({method: 'transactionHistory_linkClicked', marketplaceLink: link});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
//
|
||||
// ConnectionItem.qml
|
||||
// qml/hifi/commerce/wallet/sendMoney
|
||||
//
|
||||
// ConnectionItem
|
||||
//
|
||||
// Created by Zach Fox on 2018-01-09
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import Hifi 1.0 as Hifi
|
||||
import QtQuick 2.5
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import "../../../../styles-uit"
|
||||
import "../../../../controls-uit" as HifiControlsUit
|
||||
import "../../../../controls" as HifiControls
|
||||
import "../../wallet" as HifiWallet
|
||||
|
||||
Item {
|
||||
HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
property bool isSelected: false;
|
||||
property string userName;
|
||||
property string profilePicUrl;
|
||||
|
||||
height: 65;
|
||||
width: parent.width;
|
||||
|
||||
Rectangle {
|
||||
id: mainContainer;
|
||||
// Style
|
||||
color: root.isSelected ? hifi.colors.faintGray : hifi.colors.white;
|
||||
// Size
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.top: parent.top;
|
||||
height: root.height;
|
||||
|
||||
Item {
|
||||
id: avatarImage;
|
||||
visible: profileUrl !== "" && userName !== "";
|
||||
// Size
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 36;
|
||||
height: root.height - 15;
|
||||
width: visible ? height : 0;
|
||||
clip: true;
|
||||
Image {
|
||||
id: userImage;
|
||||
source: root.profilePicUrl !== "" ? ((0 === root.profilePicUrl.indexOf("http")) ?
|
||||
root.profilePicUrl : (Account.metaverseServerURL + root.profilePicUrl)) : "";
|
||||
mipmap: true;
|
||||
// Anchors
|
||||
anchors.fill: parent
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: Item {
|
||||
width: userImage.width;
|
||||
height: userImage.height;
|
||||
Rectangle {
|
||||
anchors.centerIn: parent;
|
||||
width: userImage.width; // This works because userImage is square
|
||||
height: width;
|
||||
radius: width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
AnimatedImage {
|
||||
source: "../../../../../icons/profilePicLoading.gif"
|
||||
anchors.fill: parent;
|
||||
visible: userImage.status != Image.Ready;
|
||||
}
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
id: userName;
|
||||
anchors.left: avatarImage.right;
|
||||
anchors.leftMargin: 16;
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.right: chooseButton.visible ? chooseButton.left : parent.right;
|
||||
anchors.rightMargin: chooseButton.visible ? 10 : 0;
|
||||
// Text size
|
||||
size: 20;
|
||||
// Style
|
||||
color: hifi.colors.baseGray;
|
||||
text: root.userName;
|
||||
elide: Text.ElideRight;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignLeft;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
|
||||
// "Choose" button
|
||||
HifiControlsUit.Button {
|
||||
id: chooseButton;
|
||||
visible: root.isSelected;
|
||||
color: hifi.buttons.blue;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 24;
|
||||
height: root.height - 20;
|
||||
width: 110;
|
||||
text: "CHOOSE";
|
||||
onClicked: {
|
||||
var msg = { method: 'chooseConnection', userName: root.userName, profilePicUrl: root.profilePicUrl };
|
||||
sendToSendMoney(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// FUNCTION DEFINITIONS START
|
||||
//
|
||||
signal sendToSendMoney(var msg);
|
||||
//
|
||||
// FUNCTION DEFINITIONS END
|
||||
//
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
//
|
||||
// RecipientDisplay.qml
|
||||
// qml/hifi/commerce/wallet/sendMoney
|
||||
//
|
||||
// RecipientDisplay
|
||||
//
|
||||
// Created by Zach Fox on 2018-01-11
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import Hifi 1.0 as Hifi
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Controls 2.2
|
||||
import QtGraphicalEffects 1.0
|
||||
import "../../../../styles-uit"
|
||||
import "../../../../controls-uit" as HifiControlsUit
|
||||
import "../../../../controls" as HifiControls
|
||||
import "../../common" as HifiCommerceCommon
|
||||
|
||||
Item {
|
||||
HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
|
||||
property bool isDisplayingNearby; // as opposed to 'connections'
|
||||
property string displayName;
|
||||
property string userName;
|
||||
property string profilePic;
|
||||
|
||||
Item {
|
||||
visible: root.isDisplayingNearby;
|
||||
anchors.fill: parent;
|
||||
|
||||
RalewaySemiBold {
|
||||
id: recipientDisplayName;
|
||||
text: root.displayName;
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 12;
|
||||
height: parent.height/2;
|
||||
// Text size
|
||||
size: 18;
|
||||
// Style
|
||||
color: hifi.colors.baseGray;
|
||||
verticalAlignment: Text.AlignBottom;
|
||||
elide: Text.ElideRight;
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
text: root.userName;
|
||||
// Anchors
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.left: recipientDisplayName.anchors.left;
|
||||
anchors.leftMargin: recipientDisplayName.anchors.leftMargin;
|
||||
anchors.right: recipientDisplayName.anchors.right;
|
||||
anchors.rightMargin: recipientDisplayName.anchors.rightMargin;
|
||||
height: parent.height/2;
|
||||
// Text size
|
||||
size: 16;
|
||||
// Style
|
||||
color: hifi.colors.baseGray;
|
||||
verticalAlignment: Text.AlignTop;
|
||||
elide: Text.ElideRight;
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
visible: !root.isDisplayingNearby;
|
||||
anchors.fill: parent;
|
||||
|
||||
Image {
|
||||
id: userImage;
|
||||
source: root.profilePic;
|
||||
mipmap: true;
|
||||
// Anchors
|
||||
anchors.left: parent.left;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
height: parent.height - 36;
|
||||
width: height;
|
||||
layer.enabled: true;
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: Item {
|
||||
width: userImage.width;
|
||||
height: userImage.height;
|
||||
Rectangle {
|
||||
anchors.centerIn: parent;
|
||||
width: userImage.width; // This works because userImage is square
|
||||
height: width;
|
||||
radius: width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
text: root.userName;
|
||||
// Anchors
|
||||
anchors.left: userImage.right;
|
||||
anchors.leftMargin: 8;
|
||||
anchors.right: parent.right;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
height: parent.height - 4;
|
||||
// Text size
|
||||
size: 16;
|
||||
// Style
|
||||
color: hifi.colors.baseGray;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
elide: Text.ElideRight;
|
||||
}
|
||||
}
|
||||
}
|
1502
interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml
Normal file
1502
interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml
Normal file
File diff suppressed because it is too large
Load diff
|
@ -7,7 +7,7 @@ import "."
|
|||
Overlay {
|
||||
id: root
|
||||
|
||||
Image {
|
||||
AnimatedImage {
|
||||
id: image
|
||||
property bool scaleFix: true
|
||||
property real xStart: 0
|
||||
|
|
|
@ -62,7 +62,8 @@ StackView {
|
|||
|
||||
var callback = rpcCalls[message.id];
|
||||
if (!callback) {
|
||||
console.log('No callback for message fromScript', JSON.stringify(message));
|
||||
// FIXME: We often recieve very long messages here, the logging of which is drastically slowing down the main thread
|
||||
//console.log('No callback for message fromScript', JSON.stringify(message));
|
||||
return;
|
||||
}
|
||||
delete rpcCalls[message.id];
|
||||
|
|
|
@ -188,8 +188,10 @@ Item {
|
|||
|
||||
TabletButton {
|
||||
id: tabletButton
|
||||
scale: wrapper.hovered ? 1.25 : wrapper.containsMouse ? 0.75 : 1.0
|
||||
Behavior on scale { NumberAnimation { duration: 200; easing.type: Easing.Linear } }
|
||||
|
||||
// Temporarily disable magnification
|
||||
// scale: wrapper.hovered ? 1.25 : wrapper.containsMouse ? 0.75 : 1.0
|
||||
// Behavior on scale { NumberAnimation { duration: 200; easing.type: Easing.Linear } }
|
||||
|
||||
anchors.centerIn: parent
|
||||
gridView: wrapper.GridView.view
|
||||
|
|
|
@ -22,7 +22,6 @@ Item {
|
|||
anchors.fill: parent
|
||||
id: d
|
||||
objectName: "stack"
|
||||
initialItem: topMenu
|
||||
|
||||
property var menuStack: []
|
||||
property var topMenu: null;
|
||||
|
|
|
@ -106,7 +106,7 @@ Item {
|
|||
if (isWebPage) {
|
||||
var webUrl = tabletApps.get(currentApp).appWebUrl;
|
||||
var scriptUrl = tabletApps.get(currentApp).scriptUrl;
|
||||
loadSource("TabletWebView.qml");
|
||||
loadSource("hifi/tablet/TabletWebView.qml");
|
||||
loadWebUrl(webUrl, scriptUrl);
|
||||
} else {
|
||||
loader.load(tabletApps.get(currentApp).appUrl);
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
//
|
||||
// TabletAvatarBrowser.qml
|
||||
//
|
||||
// Created by David Rowe on 14 Mar 2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtWebChannel 1.0
|
||||
import QtWebEngine 1.2
|
||||
|
||||
import "../../../../windows"
|
||||
import "../../../../controls-uit"
|
||||
import "../../../../styles-uit"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
objectName: "ModelBrowserDialog"
|
||||
|
||||
property string title: "Attachment Model"
|
||||
|
||||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
BaseWebView {
|
||||
id: webview
|
||||
url: (Account.metaverseServerURL + "/marketplace?category=avatars")
|
||||
focus: true
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: footer.top
|
||||
}
|
||||
|
||||
// Create a global EventBridge object for raiseAndLowerKeyboard.
|
||||
WebEngineScript {
|
||||
id: createGlobalEventBridge
|
||||
sourceCode: eventBridgeJavaScriptToInject
|
||||
injectionPoint: WebEngineScript.DocumentCreation
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// Detect when may want to raise and lower keyboard.
|
||||
WebEngineScript {
|
||||
id: raiseAndLowerKeyboard
|
||||
injectionPoint: WebEngineScript.Deferred
|
||||
sourceUrl: resourceDirectoryUrl + "html/raiseAndLowerKeyboard.js"
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard ]
|
||||
|
||||
Component.onCompleted: {
|
||||
webChannel.registerObject("eventBridge", eventBridge);
|
||||
webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: footer
|
||||
height: 40
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: keyboard.top
|
||||
}
|
||||
|
||||
color: hifi.colors.baseGray
|
||||
|
||||
Row {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
right: parent.right
|
||||
rightMargin: hifi.dimensions.contentMargin.x
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Cancel"
|
||||
color: hifi.buttons.white
|
||||
onClicked: root.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keyboard {
|
||||
id: keyboard
|
||||
|
||||
raised: parent.keyboardEnabled && parent.keyboardRaised
|
||||
numeric: parent.punctuationMode
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
keyboardEnabled = HMD.active;
|
||||
}
|
||||
}
|
|
@ -157,7 +157,7 @@
|
|||
#include "scripting/AssetMappingsScriptingInterface.h"
|
||||
#include "scripting/ClipboardScriptingInterface.h"
|
||||
#include "scripting/DesktopScriptingInterface.h"
|
||||
#include "scripting/GlobalServicesScriptingInterface.h"
|
||||
#include "scripting/AccountServicesScriptingInterface.h"
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include "scripting/MenuScriptingInterface.h"
|
||||
#include "scripting/SettingsScriptingInterface.h"
|
||||
|
@ -2093,6 +2093,11 @@ void Application::cleanupBeforeQuit() {
|
|||
DependencyManager::destroy<AudioInjectorManager>();
|
||||
DependencyManager::destroy<AudioScriptingInterface>();
|
||||
|
||||
// The PointerManager must be destroyed before the PickManager because when a Pointer is deleted,
|
||||
// it accesses the PickManager to delete its associated Pick
|
||||
DependencyManager::destroy<PointerManager>();
|
||||
DependencyManager::destroy<PickManager>();
|
||||
|
||||
qCDebug(interfaceapp) << "Application::cleanupBeforeQuit() complete";
|
||||
}
|
||||
|
||||
|
@ -2287,7 +2292,7 @@ void Application::initializeUi() {
|
|||
QUrl{ "hifi/commerce/wallet/SecurityImageChange.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/SecurityImageModel.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/SecurityImageSelection.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/SendMoney.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/sendMoney/SendMoney.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/Wallet.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/WalletHome.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/WalletSetup.qml" },
|
||||
|
@ -2376,9 +2381,11 @@ void Application::initializeUi() {
|
|||
surfaceContext->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());
|
||||
surfaceContext->setContextProperty("InputConfiguration", DependencyManager::get<InputConfiguration>().data());
|
||||
|
||||
surfaceContext->setContextProperty("Account", GlobalServicesScriptingInterface::getInstance());
|
||||
surfaceContext->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||
surfaceContext->setContextProperty("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||
surfaceContext->setContextProperty("AccountServices", AccountServicesScriptingInterface::getInstance());
|
||||
|
||||
surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
|
||||
surfaceContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
|
||||
surfaceContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
|
||||
surfaceContext->setContextProperty("AvatarManager", DependencyManager::get<AvatarManager>().data());
|
||||
surfaceContext->setContextProperty("UndoStack", &_undoStackScriptingInterface);
|
||||
|
@ -2444,7 +2451,7 @@ void Application::initializeUi() {
|
|||
offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2);
|
||||
}
|
||||
|
||||
void Application::updateCamera(RenderArgs& renderArgs) {
|
||||
void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) {
|
||||
PROFILE_RANGE(render, __FUNCTION__);
|
||||
PerformanceTimer perfTimer("updateCamera");
|
||||
|
||||
|
@ -2459,6 +2466,7 @@ void Application::updateCamera(RenderArgs& renderArgs) {
|
|||
// Using the latter will cause the camera to wobble with idle animations,
|
||||
// or with changes from the face tracker
|
||||
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||
_thirdPersonHMDCameraBoomValid= false;
|
||||
if (isHMDMode()) {
|
||||
mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||
_myCamera.setPosition(extractTranslation(camMat));
|
||||
|
@ -2471,12 +2479,25 @@ void Application::updateCamera(RenderArgs& renderArgs) {
|
|||
}
|
||||
else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||
if (isHMDMode()) {
|
||||
auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||
_myCamera.setOrientation(glm::normalize(glmExtractRotation(hmdWorldMat)));
|
||||
_myCamera.setPosition(extractTranslation(hmdWorldMat) +
|
||||
myAvatar->getWorldOrientation() * boomOffset);
|
||||
|
||||
if (!_thirdPersonHMDCameraBoomValid) {
|
||||
const glm::vec3 CAMERA_OFFSET = glm::vec3(0.0f, 0.0f, 0.7f);
|
||||
_thirdPersonHMDCameraBoom = cancelOutRollAndPitch(myAvatar->getHMDSensorOrientation()) * CAMERA_OFFSET;
|
||||
_thirdPersonHMDCameraBoomValid = true;
|
||||
}
|
||||
|
||||
glm::mat4 thirdPersonCameraSensorToWorldMatrix = myAvatar->getSensorToWorldMatrix();
|
||||
|
||||
const glm::vec3 cameraPos = myAvatar->getHMDSensorPosition() + _thirdPersonHMDCameraBoom * myAvatar->getBoomLength();
|
||||
glm::mat4 sensorCameraMat = createMatFromQuatAndPos(myAvatar->getHMDSensorOrientation(), cameraPos);
|
||||
glm::mat4 worldCameraMat = thirdPersonCameraSensorToWorldMatrix * sensorCameraMat;
|
||||
|
||||
_myCamera.setOrientation(glm::normalize(glmExtractRotation(worldCameraMat)));
|
||||
_myCamera.setPosition(extractTranslation(worldCameraMat));
|
||||
}
|
||||
else {
|
||||
_thirdPersonHMDCameraBoomValid = false;
|
||||
|
||||
_myCamera.setOrientation(myAvatar->getHead()->getOrientation());
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
|
||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||
|
@ -2489,6 +2510,7 @@ void Application::updateCamera(RenderArgs& renderArgs) {
|
|||
}
|
||||
}
|
||||
else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
_thirdPersonHMDCameraBoomValid= false;
|
||||
if (isHMDMode()) {
|
||||
auto mirrorBodyOrientation = myAvatar->getWorldOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f));
|
||||
|
||||
|
@ -2523,6 +2545,7 @@ void Application::updateCamera(RenderArgs& renderArgs) {
|
|||
renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
|
||||
}
|
||||
else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) {
|
||||
_thirdPersonHMDCameraBoomValid= false;
|
||||
EntityItemPointer cameraEntity = _myCamera.getCameraEntityPointer();
|
||||
if (cameraEntity != nullptr) {
|
||||
if (isHMDMode()) {
|
||||
|
@ -4333,8 +4356,9 @@ void Application::updateLOD(float deltaTime) const {
|
|||
float presentTime = getActiveDisplayPlugin()->getAveragePresentTime();
|
||||
float engineRunTime = (float)(_renderEngine->getConfiguration().get()->getCPURunTime());
|
||||
float gpuTime = getGPUContext()->getFrameTimerGPUAverage();
|
||||
float maxRenderTime = glm::max(gpuTime, glm::max(presentTime, engineRunTime));
|
||||
DependencyManager::get<LODManager>()->autoAdjustLOD(maxRenderTime, deltaTime);
|
||||
auto lodManager = DependencyManager::get<LODManager>();
|
||||
lodManager->setRenderTimes(presentTime, engineRunTime, gpuTime);
|
||||
lodManager->autoAdjustLOD(deltaTime);
|
||||
} else {
|
||||
DependencyManager::get<LODManager>()->resetLODAdjust();
|
||||
}
|
||||
|
@ -5099,7 +5123,8 @@ void Application::update(float deltaTime) {
|
|||
_postUpdateLambdas.clear();
|
||||
}
|
||||
|
||||
editRenderArgs([this](AppRenderArgs& appRenderArgs) {
|
||||
|
||||
editRenderArgs([this, deltaTime](AppRenderArgs& appRenderArgs) {
|
||||
PerformanceTimer perfTimer("editRenderArgs");
|
||||
appRenderArgs._headPose= getHMDSensorPose();
|
||||
|
||||
|
@ -5146,7 +5171,7 @@ void Application::update(float deltaTime) {
|
|||
resizeGL();
|
||||
}
|
||||
|
||||
this->updateCamera(appRenderArgs._renderArgs);
|
||||
this->updateCamera(appRenderArgs._renderArgs, deltaTime);
|
||||
appRenderArgs._eyeToWorld = _myCamera.getTransform();
|
||||
appRenderArgs._isStereo = false;
|
||||
|
||||
|
@ -5448,7 +5473,7 @@ void Application::clearDomainOctreeDetails() {
|
|||
|
||||
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
||||
|
||||
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DEFAULT);
|
||||
skyStage->setBackgroundMode(graphics::SunSkyStage::SKY_DEFAULT);
|
||||
|
||||
DependencyManager::get<AnimationCache>()->clearUnusedResources();
|
||||
DependencyManager::get<ModelCache>()->clearUnusedResources();
|
||||
|
@ -5758,10 +5783,11 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
|||
scriptEngine->registerGlobalObject("ModelCache", DependencyManager::get<ModelCache>().data());
|
||||
scriptEngine->registerGlobalObject("SoundCache", DependencyManager::get<SoundCache>().data());
|
||||
|
||||
scriptEngine->registerGlobalObject("Account", GlobalServicesScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("DialogsManager", _dialogsManagerScriptingInterface);
|
||||
|
||||
scriptEngine->registerGlobalObject("GlobalServices", GlobalServicesScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||
scriptEngine->registerGlobalObject("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||
scriptEngine->registerGlobalObject("AccountServices", AccountServicesScriptingInterface::getInstance());
|
||||
qScriptRegisterMetaType(scriptEngine.data(), DownloadInfoResultToScriptValue, DownloadInfoResultFromScriptValue);
|
||||
|
||||
scriptEngine->registerGlobalObject("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
|
||||
|
@ -6161,7 +6187,7 @@ void Application::showAssetServerWidget(QString filePath) {
|
|||
if (!hmd->getShouldShowTablet() && !isHMDMode()) {
|
||||
DependencyManager::get<OffscreenUi>()->show(url, "AssetServer", startUpload);
|
||||
} else {
|
||||
static const QUrl url("hifi/dialogs/TabletAssetServer.qml");
|
||||
static const QUrl url("../dialogs/TabletAssetServer.qml");
|
||||
tablet->pushOntoStack(url);
|
||||
}
|
||||
}
|
||||
|
@ -6790,6 +6816,15 @@ void Application::loadAddAvatarBookmarkDialog() const {
|
|||
avatarBookmarks->addBookmark();
|
||||
}
|
||||
|
||||
void Application::loadAvatarBrowser() const {
|
||||
auto tablet = dynamic_cast<TabletProxy*>(DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system"));
|
||||
// construct the url to the marketplace item
|
||||
QString url = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/marketplace?category=avatars";
|
||||
QString MARKETPLACES_INJECT_SCRIPT_PATH = "file:///" + qApp->applicationDirPath() + "/scripts/system/html/js/marketplacesInject.js";
|
||||
tablet->gotoWebScreen(url, MARKETPLACES_INJECT_SCRIPT_PATH);
|
||||
DependencyManager::get<HMDScriptingInterface>()->openTablet();
|
||||
}
|
||||
|
||||
void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio) {
|
||||
postLambdaEvent([notify, includeAnimated, aspectRatio, this] {
|
||||
// Get a screenshot and save it
|
||||
|
@ -6807,7 +6842,8 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa
|
|||
|
||||
void Application::takeSecondaryCameraSnapshot() {
|
||||
postLambdaEvent([this] {
|
||||
Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot());
|
||||
QString snapshotPath = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot());
|
||||
emit DependencyManager::get<WindowScriptingInterface>()->stillSnapshotTaken(snapshotPath, true);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -7371,11 +7407,13 @@ void Application::updateThreadPoolCount() const {
|
|||
}
|
||||
|
||||
void Application::updateSystemTabletMode() {
|
||||
qApp->setProperty(hifi::properties::HMD, isHMDMode());
|
||||
if (isHMDMode()) {
|
||||
DependencyManager::get<TabletScriptingInterface>()->setToolbarMode(getHmdTabletBecomesToolbarSetting());
|
||||
} else {
|
||||
DependencyManager::get<TabletScriptingInterface>()->setToolbarMode(getDesktopTabletBecomesToolbarSetting());
|
||||
if (_settingsLoaded) {
|
||||
qApp->setProperty(hifi::properties::HMD, isHMDMode());
|
||||
if (isHMDMode()) {
|
||||
DependencyManager::get<TabletScriptingInterface>()->setToolbarMode(getHmdTabletBecomesToolbarSetting());
|
||||
} else {
|
||||
DependencyManager::get<TabletScriptingInterface>()->setToolbarMode(getDesktopTabletBecomesToolbarSetting());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
#include "UndoStackScriptingInterface.h"
|
||||
|
||||
#include <procedural/ProceduralSkybox.h>
|
||||
#include <model/Skybox.h>
|
||||
#include <graphics/Skybox.h>
|
||||
#include <ModelScriptingInterface.h>
|
||||
#include "FrameTimingsScriptingInterface.h"
|
||||
|
||||
|
@ -146,7 +146,7 @@ public:
|
|||
void initializeGL();
|
||||
void initializeUi();
|
||||
|
||||
void updateCamera(RenderArgs& renderArgs);
|
||||
void updateCamera(RenderArgs& renderArgs, float deltaTime);
|
||||
void paintGL();
|
||||
void resizeGL();
|
||||
|
||||
|
@ -270,7 +270,7 @@ public:
|
|||
void takeSecondaryCameraSnapshot();
|
||||
void shareSnapshot(const QString& filename, const QUrl& href = QUrl(""));
|
||||
|
||||
model::SkyboxPointer getDefaultSkybox() const { return _defaultSkybox; }
|
||||
graphics::SkyboxPointer getDefaultSkybox() const { return _defaultSkybox; }
|
||||
gpu::TexturePointer getDefaultSkyboxTexture() const { return _defaultSkyboxTexture; }
|
||||
gpu::TexturePointer getDefaultSkyboxAmbientTexture() const { return _defaultSkyboxAmbientTexture; }
|
||||
|
||||
|
@ -309,6 +309,7 @@ public slots:
|
|||
void toggleEntityScriptServerLogDialog();
|
||||
Q_INVOKABLE void showAssetServerWidget(QString filePath = "");
|
||||
Q_INVOKABLE void loadAddAvatarBookmarkDialog() const;
|
||||
Q_INVOKABLE void loadAvatarBrowser() const;
|
||||
Q_INVOKABLE SharedSoundPointer getSampleSound() const;
|
||||
|
||||
void showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const QString& name) const;
|
||||
|
@ -666,7 +667,7 @@ private:
|
|||
|
||||
ConnectionMonitor _connectionMonitor;
|
||||
|
||||
model::SkyboxPointer _defaultSkybox { new ProceduralSkybox() } ;
|
||||
graphics::SkyboxPointer _defaultSkybox { new ProceduralSkybox() } ;
|
||||
gpu::TexturePointer _defaultSkyboxTexture;
|
||||
gpu::TexturePointer _defaultSkyboxAmbientTexture;
|
||||
|
||||
|
@ -695,6 +696,9 @@ private:
|
|||
void startHMDStandBySession();
|
||||
void endHMDSession();
|
||||
|
||||
glm::vec3 _thirdPersonHMDCameraBoom { 0.0f, 0.0f, -1.0f };
|
||||
bool _thirdPersonHMDCameraBoomValid { true };
|
||||
|
||||
QUrl _avatarOverrideUrl;
|
||||
bool _saveAvatarOverrideUrl { false };
|
||||
QObject* _renderEventHandler{ nullptr };
|
||||
|
|
|
@ -26,43 +26,50 @@ Setting::Handle<float> hmdLODDecreaseFPS("hmdLODDecreaseFPS", DEFAULT_HMD_LOD_DO
|
|||
LODManager::LODManager() {
|
||||
}
|
||||
|
||||
float LODManager::getLODDecreaseFPS() {
|
||||
float LODManager::getLODDecreaseFPS() const {
|
||||
if (qApp->isHMDMode()) {
|
||||
return getHMDLODDecreaseFPS();
|
||||
}
|
||||
return getDesktopLODDecreaseFPS();
|
||||
}
|
||||
|
||||
float LODManager::getLODIncreaseFPS() {
|
||||
float LODManager::getLODIncreaseFPS() const {
|
||||
if (qApp->isHMDMode()) {
|
||||
return getHMDLODIncreaseFPS();
|
||||
}
|
||||
return getDesktopLODIncreaseFPS();
|
||||
}
|
||||
|
||||
// We use a "time-weighted running average" of the renderTime and compare it against min/max thresholds
|
||||
// We use a "time-weighted running average" of the maxRenderTime and compare it against min/max thresholds
|
||||
// to determine if we should adjust the level of detail (LOD).
|
||||
//
|
||||
// A time-weighted running average has a timescale which determines how fast the average tracks the measured
|
||||
// value in real-time. Given a step-function in the mesured value, and assuming measurements happen
|
||||
// faster than the runningAverage is computed, the error between the value and its runningAverage will be
|
||||
// reduced by 1/e every timescale of real-time that passes.
|
||||
const float LOD_ADJUST_RUNNING_AVG_TIMESCALE = 0.1f; // sec
|
||||
const float LOD_ADJUST_RUNNING_AVG_TIMESCALE = 0.08f; // sec
|
||||
//
|
||||
// Assuming the measured value is affected by logic invoked by the runningAverage bumping up against its
|
||||
// thresholds, we expect the adjustment to introduce a step-function. We want the runningAverage to settle
|
||||
// to the new value BEFORE we test it aginst its thresholds again. Hence we test on a period that is a few
|
||||
// multiples of the running average timescale:
|
||||
const uint64_t LOD_AUTO_ADJUST_PERIOD = 5 * (uint64_t)(LOD_ADJUST_RUNNING_AVG_TIMESCALE * (float)USECS_PER_MSEC); // usec
|
||||
const uint64_t LOD_AUTO_ADJUST_PERIOD = 4 * (uint64_t)(LOD_ADJUST_RUNNING_AVG_TIMESCALE * (float)USECS_PER_MSEC); // usec
|
||||
|
||||
const float LOD_AUTO_ADJUST_DECREMENT_FACTOR = 0.8f;
|
||||
const float LOD_AUTO_ADJUST_INCREMENT_FACTOR = 1.2f;
|
||||
|
||||
void LODManager::autoAdjustLOD(float renderTime, float realTimeDelta) {
|
||||
// compute time-weighted running average renderTime
|
||||
void LODManager::setRenderTimes(float presentTime, float engineRunTime, float gpuTime) {
|
||||
_presentTime = presentTime;
|
||||
_engineRunTime = engineRunTime;
|
||||
_gpuTime = gpuTime;
|
||||
}
|
||||
|
||||
void LODManager::autoAdjustLOD(float realTimeDelta) {
|
||||
float maxRenderTime = glm::max(glm::max(_presentTime, _engineRunTime), _gpuTime);
|
||||
// compute time-weighted running average maxRenderTime
|
||||
// Note: we MUST clamp the blend to 1.0 for stability
|
||||
float blend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE) ? realTimeDelta / LOD_ADJUST_RUNNING_AVG_TIMESCALE : 1.0f;
|
||||
_avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * renderTime; // msec
|
||||
_avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * maxRenderTime; // msec
|
||||
if (!_automaticLODAdjust) {
|
||||
// early exit
|
||||
return;
|
||||
|
@ -84,6 +91,10 @@ void LODManager::autoAdjustLOD(float renderTime, float realTimeDelta) {
|
|||
<< "targetFPS =" << getLODDecreaseFPS()
|
||||
<< "octreeSizeScale =" << _octreeSizeScale;
|
||||
emit LODDecreased();
|
||||
// Assuming the LOD adjustment will work: we optimistically reset _avgRenderTime
|
||||
// to provide an FPS just above the decrease threshold. It will drift close to its
|
||||
// true value after a few LOD_ADJUST_TIMESCALEs and we'll adjust again as necessary.
|
||||
_avgRenderTime = (float)MSECS_PER_SECOND / (getLODDecreaseFPS() + 1.0f);
|
||||
}
|
||||
_decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD;
|
||||
}
|
||||
|
@ -105,6 +116,10 @@ void LODManager::autoAdjustLOD(float renderTime, float realTimeDelta) {
|
|||
<< "targetFPS =" << getLODDecreaseFPS()
|
||||
<< "octreeSizeScale =" << _octreeSizeScale;
|
||||
emit LODIncreased();
|
||||
// Assuming the LOD adjustment will work: we optimistically reset _avgRenderTime
|
||||
// to provide an FPS just below the increase threshold. It will drift close to its
|
||||
// true value after a few LOD_ADJUST_TIMESCALEs and we'll adjust again as necessary.
|
||||
_avgRenderTime = (float)MSECS_PER_SECOND / (getLODIncreaseFPS() - 1.0f);
|
||||
}
|
||||
_increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD;
|
||||
}
|
||||
|
@ -119,11 +134,6 @@ void LODManager::autoAdjustLOD(float renderTime, float realTimeDelta) {
|
|||
if (lodToolsDialog) {
|
||||
lodToolsDialog->reloadSliders();
|
||||
}
|
||||
// Assuming the LOD adjustment will work: we optimistically reset _avgRenderTime
|
||||
// to be at middle of target zone. It will drift close to its true value within
|
||||
// about three few LOD_ADJUST_TIMESCALEs and we'll adjust again as necessary.
|
||||
float expectedFPS = 0.5f * (getLODIncreaseFPS() + getLODDecreaseFPS());
|
||||
_avgRenderTime = MSECS_PER_SECOND / expectedFPS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,6 +141,18 @@ void LODManager::resetLODAdjust() {
|
|||
_decreaseFPSExpiry = _increaseFPSExpiry = usecTimestampNow() + LOD_AUTO_ADJUST_PERIOD;
|
||||
}
|
||||
|
||||
float LODManager::getLODLevel() const {
|
||||
// simpleLOD is a linearized and normalized number that represents how much LOD is being applied.
|
||||
// It ranges from:
|
||||
// 1.0 = normal (max) level of detail
|
||||
// 0.0 = min level of detail
|
||||
// In other words: as LOD "drops" the value of simpleLOD will also "drop", and it cannot go lower than 0.0.
|
||||
const float LOG_MIN_LOD_RATIO = logf(ADJUST_LOD_MIN_SIZE_SCALE / ADJUST_LOD_MAX_SIZE_SCALE);
|
||||
float power = logf(_octreeSizeScale / ADJUST_LOD_MAX_SIZE_SCALE);
|
||||
float simpleLOD = (LOG_MIN_LOD_RATIO - power) / LOG_MIN_LOD_RATIO;
|
||||
return simpleLOD;
|
||||
}
|
||||
|
||||
const float MIN_DECREASE_FPS = 0.5f;
|
||||
|
||||
void LODManager::setDesktopLODDecreaseFPS(float fps) {
|
||||
|
|
|
@ -37,7 +37,7 @@ class AABox;
|
|||
class LODManager : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
|
||||
public:
|
||||
Q_INVOKABLE void setAutomaticLODAdjust(bool value) { _automaticLODAdjust = value; }
|
||||
Q_INVOKABLE bool getAutomaticLODAdjust() const { return _automaticLODAdjust; }
|
||||
|
@ -49,34 +49,56 @@ public:
|
|||
Q_INVOKABLE void setHMDLODDecreaseFPS(float value);
|
||||
Q_INVOKABLE float getHMDLODDecreaseFPS() const;
|
||||
Q_INVOKABLE float getHMDLODIncreaseFPS() const;
|
||||
|
||||
|
||||
// User Tweakable LOD Items
|
||||
Q_INVOKABLE QString getLODFeedbackText();
|
||||
Q_INVOKABLE void setOctreeSizeScale(float sizeScale);
|
||||
Q_INVOKABLE float getOctreeSizeScale() const { return _octreeSizeScale; }
|
||||
|
||||
|
||||
Q_INVOKABLE void setBoundaryLevelAdjust(int boundaryLevelAdjust);
|
||||
Q_INVOKABLE int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
|
||||
|
||||
Q_INVOKABLE float getLODDecreaseFPS();
|
||||
Q_INVOKABLE float getLODIncreaseFPS();
|
||||
|
||||
|
||||
Q_INVOKABLE float getLODDecreaseFPS() const;
|
||||
Q_INVOKABLE float getLODIncreaseFPS() const;
|
||||
|
||||
Q_PROPERTY(float presentTime READ getPresentTime)
|
||||
Q_PROPERTY(float engineRunTime READ getEngineRunTime)
|
||||
Q_PROPERTY(float gpuTime READ getGPUTime)
|
||||
Q_PROPERTY(float avgRenderTime READ getAverageRenderTime)
|
||||
Q_PROPERTY(float fps READ getMaxTheoreticalFPS)
|
||||
Q_PROPERTY(float lodLevel READ getLODLevel)
|
||||
|
||||
Q_PROPERTY(float lodDecreaseFPS READ getLODDecreaseFPS)
|
||||
Q_PROPERTY(float lodIncreaseFPS READ getLODIncreaseFPS)
|
||||
|
||||
float getPresentTime() const { return _presentTime; }
|
||||
float getEngineRunTime() const { return _engineRunTime; }
|
||||
float getGPUTime() const { return _gpuTime; }
|
||||
|
||||
static bool shouldRender(const RenderArgs* args, const AABox& bounds);
|
||||
void autoAdjustLOD(float renderTime, float realTimeDelta);
|
||||
|
||||
void setRenderTimes(float presentTime, float engineRunTime, float gpuTime);
|
||||
void autoAdjustLOD(float realTimeDelta);
|
||||
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
void resetLODAdjust();
|
||||
|
||||
|
||||
float getAverageRenderTime() const { return _avgRenderTime; };
|
||||
float getMaxTheoreticalFPS() const { return (float)MSECS_PER_SECOND / _avgRenderTime; };
|
||||
float getLODLevel() const;
|
||||
|
||||
signals:
|
||||
void LODIncreased();
|
||||
void LODDecreased();
|
||||
|
||||
|
||||
private:
|
||||
LODManager();
|
||||
|
||||
|
||||
bool _automaticLODAdjust = true;
|
||||
float _avgRenderTime { 0.0f };
|
||||
float _presentTime { 0.0f }; // msec
|
||||
float _engineRunTime { 0.0f }; // msec
|
||||
float _gpuTime { 0.0f }; // msec
|
||||
float _avgRenderTime { 0.0f }; // msec
|
||||
float _desktopMaxRenderTime { DEFAULT_DESKTOP_MAX_RENDER_TIME };
|
||||
float _hmdMaxRenderTime { DEFAULT_HMD_MAX_RENDER_TIME };
|
||||
|
||||
|
|
|
@ -574,8 +574,6 @@ Menu::Menu() {
|
|||
avatar.get(), SLOT(setEnableMeshVisible(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::DisableEyelidAdjustment, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::TurnWithHead, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::UseAnimPreAndPostRotations, 0, true,
|
||||
avatar.get(), SLOT(setUseAnimPreAndPostRotations(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::EnableInverseKinematics, 0, true,
|
||||
avatar.get(), SLOT(setEnableInverseKinematics(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSensorToWorldMatrix, 0, false,
|
||||
|
@ -758,6 +756,14 @@ Menu::Menu() {
|
|||
// Developer > Stats
|
||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Stats);
|
||||
|
||||
// Developer > API Debugger
|
||||
action = addActionToQMenuAndActionHash(developerMenu, "API Debugger");
|
||||
connect(action, &QAction::triggered, [] {
|
||||
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||
QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
|
||||
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/utilities/tools/currentAPI.js");
|
||||
scriptEngines->loadScript(defaultScriptsLoc.toString());
|
||||
});
|
||||
|
||||
#if 0 /// -------------- REMOVED FOR NOW --------------
|
||||
addDisabledActionAndSeparator(navigateMenu, "History");
|
||||
|
|
|
@ -194,7 +194,6 @@ namespace MenuOption {
|
|||
const QString TurnWithHead = "Turn using Head";
|
||||
const QString UseAudioForMouth = "Use Audio for Mouth";
|
||||
const QString UseCamera = "Use Camera";
|
||||
const QString UseAnimPreAndPostRotations = "Use Anim Pre and Post Rotations";
|
||||
const QString VelocityFilter = "Velocity Filter";
|
||||
const QString VisibleToEveryone = "Everyone";
|
||||
const QString VisibleToFriends = "Friends";
|
||||
|
|
|
@ -537,6 +537,7 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
// we've achived our final adjusted position and rotation for the avatar
|
||||
// and all of its joints, now update our attachements.
|
||||
Avatar::simulateAttachments(deltaTime);
|
||||
relayJointDataToChildren();
|
||||
|
||||
if (!_skeletonModel->hasSkeleton()) {
|
||||
// All the simulation that can be done has been done
|
||||
|
@ -1061,11 +1062,6 @@ void MyAvatar::setEnableMeshVisible(bool isEnabled) {
|
|||
_skeletonModel->setVisibleInScene(isEnabled, qApp->getMain3DScene());
|
||||
}
|
||||
|
||||
void MyAvatar::setUseAnimPreAndPostRotations(bool isEnabled) {
|
||||
AnimClip::usePreAndPostPoseFromAnim = isEnabled;
|
||||
reset(true);
|
||||
}
|
||||
|
||||
void MyAvatar::setEnableInverseKinematics(bool isEnabled) {
|
||||
_skeletonModel->getRig().setEnableInverseKinematics(isEnabled);
|
||||
}
|
||||
|
@ -1929,7 +1925,7 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) {
|
|||
_prevShouldDrawHead = shouldDrawHead;
|
||||
}
|
||||
|
||||
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.3f;
|
||||
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.47f;
|
||||
|
||||
bool MyAvatar::cameraInsideHead(const glm::vec3& cameraPosition) const {
|
||||
return glm::length(cameraPosition - getHeadPosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getModelScale());
|
||||
|
@ -2100,7 +2096,7 @@ void MyAvatar::updateActionMotor(float deltaTime) {
|
|||
_actionMotorVelocity = motorSpeed * direction;
|
||||
} else {
|
||||
// we're interacting with a floor --> simple horizontal speed and exponential decay
|
||||
_actionMotorVelocity = getSensorToWorldScale() * DEFAULT_AVATAR_MAX_WALKING_SPEED * direction;
|
||||
_actionMotorVelocity = getSensorToWorldScale() * _walkSpeed.get() * direction;
|
||||
}
|
||||
|
||||
float boomChange = getDriveKey(ZOOM);
|
||||
|
@ -2692,6 +2688,14 @@ float MyAvatar::getUserEyeHeight() const {
|
|||
return userHeight - userHeight * ratio;
|
||||
}
|
||||
|
||||
float MyAvatar::getWalkSpeed() const {
|
||||
return _walkSpeed.get();
|
||||
}
|
||||
|
||||
void MyAvatar::setWalkSpeed(float value) {
|
||||
_walkSpeed.set(value);
|
||||
}
|
||||
|
||||
glm::vec3 MyAvatar::getPositionForAudio() {
|
||||
switch (_audioListenerMode) {
|
||||
case AudioListenerMode::FROM_HEAD:
|
||||
|
@ -2799,14 +2803,9 @@ void MyAvatar::FollowHelper::decrementTimeRemaining(float dt) {
|
|||
}
|
||||
|
||||
bool MyAvatar::FollowHelper::shouldActivateRotation(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const {
|
||||
auto cameraMode = qApp->getCamera().getMode();
|
||||
if (cameraMode == CAMERA_MODE_THIRD_PERSON) {
|
||||
return false;
|
||||
} else {
|
||||
const float FOLLOW_ROTATION_THRESHOLD = cosf(PI / 6.0f); // 30 degrees
|
||||
glm::vec2 bodyFacing = getFacingDir2D(currentBodyMatrix);
|
||||
return glm::dot(-myAvatar.getHeadControllerFacingMovingAverage(), bodyFacing) < FOLLOW_ROTATION_THRESHOLD;
|
||||
}
|
||||
const float FOLLOW_ROTATION_THRESHOLD = cosf(PI / 6.0f); // 30 degrees
|
||||
glm::vec2 bodyFacing = getFacingDir2D(currentBodyMatrix);
|
||||
return glm::dot(-myAvatar.getHeadControllerFacingMovingAverage(), bodyFacing) < FOLLOW_ROTATION_THRESHOLD;
|
||||
}
|
||||
|
||||
bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const {
|
||||
|
|
|
@ -163,6 +163,8 @@ class MyAvatar : public Avatar {
|
|||
|
||||
Q_PROPERTY(QUuid SELF_ID READ getSelfID CONSTANT)
|
||||
|
||||
Q_PROPERTY(float walkSpeed READ getWalkSpeed WRITE setWalkSpeed);
|
||||
|
||||
const QString DOMINANT_LEFT_HAND = "left";
|
||||
const QString DOMINANT_RIGHT_HAND = "right";
|
||||
|
||||
|
@ -557,6 +559,9 @@ public:
|
|||
|
||||
const QUuid& getSelfID() const { return AVATAR_SELF_ID; }
|
||||
|
||||
void setWalkSpeed(float value);
|
||||
float getWalkSpeed() const;
|
||||
|
||||
public slots:
|
||||
void increaseSize();
|
||||
void decreaseSize();
|
||||
|
@ -594,7 +599,6 @@ public slots:
|
|||
|
||||
bool getEnableMeshVisible() const { return _skeletonModel->isVisible(); }
|
||||
void setEnableMeshVisible(bool isEnabled);
|
||||
void setUseAnimPreAndPostRotations(bool isEnabled);
|
||||
void setEnableInverseKinematics(bool isEnabled);
|
||||
|
||||
QUrl getAnimGraphOverrideUrl() const; // thread-safe
|
||||
|
@ -841,6 +845,9 @@ private:
|
|||
|
||||
// height of user in sensor space, when standing erect.
|
||||
ThreadSafeValueCache<float> _userHeight { DEFAULT_AVATAR_HEIGHT };
|
||||
|
||||
// max unscaled forward movement speed
|
||||
ThreadSafeValueCache<float> _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED };
|
||||
};
|
||||
|
||||
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);
|
||||
|
|
|
@ -34,7 +34,6 @@ Rig::CharacterControllerState convertCharacterControllerState(CharacterControlle
|
|||
}
|
||||
|
||||
static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) {
|
||||
|
||||
glm::mat4 worldToSensorMat = glm::inverse(myAvatar->getSensorToWorldMatrix());
|
||||
|
||||
// check for pinned hips.
|
||||
|
@ -106,7 +105,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
if (avatarHeadPose.isValid()) {
|
||||
AnimPose pose(avatarHeadPose.getRotation(), avatarHeadPose.getTranslation());
|
||||
params.primaryControllerPoses[Rig::PrimaryControllerType_Head] = avatarToRigPose * pose;
|
||||
params.primaryControllerActiveFlags[Rig::PrimaryControllerType_Head] = true;
|
||||
params.primaryControllerFlags[Rig::PrimaryControllerType_Head] = (uint8_t)Rig::ControllerFlags::Enabled;
|
||||
} else {
|
||||
// even though full head IK is disabled, the rig still needs the head orientation to rotate the head up and
|
||||
// down in desktop mode.
|
||||
|
@ -114,7 +113,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
// postMult 180 is necessary to convert head from -z forward to z forward.
|
||||
glm::quat headRot = Quaternions::Y_180 * head->getFinalOrientationInLocalFrame() * Quaternions::Y_180;
|
||||
params.primaryControllerPoses[Rig::PrimaryControllerType_Head] = AnimPose(glm::vec3(1.0f), headRot, glm::vec3(0.0f));
|
||||
params.primaryControllerActiveFlags[Rig::PrimaryControllerType_Head] = false;
|
||||
params.primaryControllerFlags[Rig::PrimaryControllerType_Head] = 0;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -135,10 +134,10 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
if (controllerPose.isValid()) {
|
||||
AnimPose pose(controllerPose.getRotation(), controllerPose.getTranslation());
|
||||
params.primaryControllerPoses[pair.second] = avatarToRigPose * pose;
|
||||
params.primaryControllerActiveFlags[pair.second] = true;
|
||||
params.primaryControllerFlags[pair.second] = (uint8_t)Rig::ControllerFlags::Enabled;
|
||||
} else {
|
||||
params.primaryControllerPoses[pair.second] = AnimPose::identity;
|
||||
params.primaryControllerActiveFlags[pair.second] = false;
|
||||
params.primaryControllerFlags[pair.second] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,15 +165,15 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
if (controllerPose.isValid()) {
|
||||
AnimPose pose(controllerPose.getRotation(), controllerPose.getTranslation());
|
||||
params.secondaryControllerPoses[pair.second] = avatarToRigPose * pose;
|
||||
params.secondaryControllerActiveFlags[pair.second] = true;
|
||||
params.secondaryControllerFlags[pair.second] = (uint8_t)Rig::ControllerFlags::Enabled;
|
||||
} else {
|
||||
params.secondaryControllerPoses[pair.second] = AnimPose::identity;
|
||||
params.secondaryControllerActiveFlags[pair.second] = false;
|
||||
params.secondaryControllerFlags[pair.second] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// if hips are not under direct control, estimate the hips position.
|
||||
if (avatarHeadPose.isValid() && !params.primaryControllerActiveFlags[Rig::PrimaryControllerType_Hips]) {
|
||||
if (avatarHeadPose.isValid() && !(params.primaryControllerFlags[Rig::PrimaryControllerType_Hips] & (uint8_t)Rig::ControllerFlags::Enabled)) {
|
||||
bool isFlying = (myAvatar->getCharacterController()->getState() == CharacterController::State::Hover || myAvatar->getCharacterController()->computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS);
|
||||
|
||||
if (!_prevHipsValid) {
|
||||
|
@ -200,7 +199,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
AnimPose sensorToRigPose(invRigMat * myAvatar->getSensorToWorldMatrix());
|
||||
|
||||
params.primaryControllerPoses[Rig::PrimaryControllerType_Hips] = sensorToRigPose * hips;
|
||||
params.primaryControllerActiveFlags[Rig::PrimaryControllerType_Hips] = true;
|
||||
params.primaryControllerFlags[Rig::PrimaryControllerType_Hips] = (uint8_t)Rig::ControllerFlags::Enabled | (uint8_t)Rig::ControllerFlags::Estimated;
|
||||
|
||||
} else {
|
||||
_prevHipsValid = false;
|
||||
|
|
|
@ -46,6 +46,8 @@ Handler(buy)
|
|||
Handler(receiveAt)
|
||||
Handler(balance)
|
||||
Handler(inventory)
|
||||
Handler(transferHfcToNode)
|
||||
Handler(transferHfcToUsername)
|
||||
|
||||
void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request) {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
|
@ -116,23 +118,64 @@ void Ledger::inventory(const QStringList& keys) {
|
|||
keysQuery("inventory", "inventorySuccess", "inventoryFailure");
|
||||
}
|
||||
|
||||
QString amountString(const QString& label, const QString&color, const QJsonValue& moneyValue, const QJsonValue& certsValue) {
|
||||
int money = moneyValue.toInt();
|
||||
int certs = certsValue.toInt();
|
||||
if (money <= 0 && certs <= 0) {
|
||||
return QString();
|
||||
QString hfcString(const QJsonValue& sentValue, const QJsonValue& receivedValue) {
|
||||
int sent = sentValue.toInt();
|
||||
int received = receivedValue.toInt();
|
||||
if (sent <= 0 && received <= 0) {
|
||||
return QString("-");
|
||||
}
|
||||
QString result(QString("<font color='#%1'> %2").arg(color, label));
|
||||
if (money > 0) {
|
||||
result += QString(" %1 HFC").arg(money);
|
||||
}
|
||||
if (certs > 0) {
|
||||
if (money > 0) {
|
||||
result += QString(",");
|
||||
QString result;
|
||||
if (sent > 0) {
|
||||
result += QString("<font color='#B70A37'>-%1 HFC</font>").arg(sent);
|
||||
if (received > 0) {
|
||||
result += QString("<br>");
|
||||
}
|
||||
result += QString((certs == 1) ? " %1 certificate" : " %1 certificates").arg(certs);
|
||||
}
|
||||
return result + QString("</font>");
|
||||
if (received > 0) {
|
||||
result += QString("<font color='#3AA38F'>%1 HFC</font>").arg(received);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static const QString USER_PAGE_BASE_URL = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/users/";
|
||||
static const QStringList KNOWN_USERS(QStringList() << "highfidelity" << "marketplace");
|
||||
QString userLink(const QString& username) {
|
||||
if (username.isEmpty()) {
|
||||
return QString("someone");
|
||||
}
|
||||
if (KNOWN_USERS.contains(username)) {
|
||||
return username;
|
||||
}
|
||||
return QString("<a href=\"%1%2\">%2</a>").arg(USER_PAGE_BASE_URL, username);
|
||||
}
|
||||
|
||||
QString transactionString(const QJsonObject& valueObject) {
|
||||
int sentCerts = valueObject["sent_certs"].toInt();
|
||||
int receivedCerts = valueObject["received_certs"].toInt();
|
||||
int sent = valueObject["sent_money"].toInt();
|
||||
int dateInteger = valueObject["created_at"].toInt();
|
||||
QString message = valueObject["message"].toString();
|
||||
QDateTime createdAt(QDateTime::fromSecsSinceEpoch(dateInteger, Qt::UTC));
|
||||
QString result;
|
||||
|
||||
if (sentCerts <= 0 && receivedCerts <= 0) {
|
||||
// this is an hfc transfer.
|
||||
if (sent > 0) {
|
||||
QString recipient = userLink(valueObject["recipient_name"].toString());
|
||||
result += QString("Money sent to %1").arg(recipient);
|
||||
} else {
|
||||
QString sender = userLink(valueObject["sender_name"].toString());
|
||||
result += QString("Money from %1").arg(sender);
|
||||
}
|
||||
if (!message.isEmpty()) {
|
||||
result += QString("<br>with memo: <i>\"%1\"</i>").arg(message);
|
||||
}
|
||||
} else {
|
||||
result += valueObject["message"].toString();
|
||||
}
|
||||
// no matter what we append a smaller date to the bottom of this...
|
||||
|
||||
result += QString("<br><font size='-2' color='#1080B8'>%1").arg(createdAt.toLocalTime().toString(Qt::DefaultLocaleShortDate));
|
||||
return result;
|
||||
}
|
||||
|
||||
static const QString MARKETPLACE_ITEMS_BASE_URL = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/marketplace/items/";
|
||||
|
@ -155,16 +198,13 @@ void Ledger::historySuccess(QNetworkReply& reply) {
|
|||
|
||||
// TODO: do this with 0 copies if possible
|
||||
for (auto it = historyArray.begin(); it != historyArray.end(); it++) {
|
||||
// We have 2 text fields to synthesize, the one on the left is a listing
|
||||
// of the HFC in/out of your wallet. The one on the right contains an explaination
|
||||
// of the transaction. That could be just the memo (if it is a regular purchase), or
|
||||
// more text (plus the optional memo) if an hfc transfer
|
||||
auto valueObject = (*it).toObject();
|
||||
QString sent = amountString("sent", "EA4C5F", valueObject["sent_money"], valueObject["sent_certs"]);
|
||||
QString received = amountString("received", "1FC6A6", valueObject["received_money"], valueObject["received_certs"]);
|
||||
|
||||
// turns out on my machine, toLocalTime convert to some weird timezone, yet the
|
||||
// systemTimeZone is correct. To avoid a strange bug with other's systems too, lets
|
||||
// be explicit
|
||||
QDateTime createdAt = QDateTime::fromSecsSinceEpoch(valueObject["created_at"].toInt(), Qt::UTC);
|
||||
QDateTime localCreatedAt = createdAt.toTimeZone(QTimeZone::systemTimeZone());
|
||||
valueObject["text"] = QString("%1%2%3").arg(valueObject["message"].toString(), sent, received);
|
||||
valueObject["hfc_text"] = hfcString(valueObject["sent_money"], valueObject["received_money"]);
|
||||
valueObject["transaction_text"] = transactionString(valueObject);
|
||||
newHistoryArray.push_back(valueObject);
|
||||
}
|
||||
// now copy the rest of the json -- this is inefficient
|
||||
|
@ -189,13 +229,6 @@ void Ledger::history(const QStringList& keys, const int& pageNumber) {
|
|||
keysQuery("history", "historySuccess", "historyFailure", params);
|
||||
}
|
||||
|
||||
// The api/failResponse is called just for the side effect of logging.
|
||||
void Ledger::resetSuccess(QNetworkReply& reply) { apiResponse("reset", reply); }
|
||||
void Ledger::resetFailure(QNetworkReply& reply) { failResponse("reset", reply); }
|
||||
void Ledger::reset() {
|
||||
send("reset_user_hfc_account", "resetSuccess", "resetFailure", QNetworkAccessManager::PutOperation, AccountManagerAuth::Required, QJsonObject());
|
||||
}
|
||||
|
||||
void Ledger::accountSuccess(QNetworkReply& reply) {
|
||||
// lets set the appropriate stuff in the wallet now
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
|
@ -205,11 +238,17 @@ void Ledger::accountSuccess(QNetworkReply& reply) {
|
|||
auto salt = QByteArray::fromBase64(data["salt"].toString().toUtf8());
|
||||
auto iv = QByteArray::fromBase64(data["iv"].toString().toUtf8());
|
||||
auto ckey = QByteArray::fromBase64(data["ckey"].toString().toUtf8());
|
||||
QString remotePublicKey = data["public_key"].toString();
|
||||
|
||||
wallet->setSalt(salt);
|
||||
wallet->setIv(iv);
|
||||
wallet->setCKey(ckey);
|
||||
|
||||
QStringList localPublicKeys = wallet->listPublicKeys();
|
||||
if (remotePublicKey.isEmpty() && !localPublicKeys.isEmpty()) {
|
||||
receiveAt(localPublicKeys.first(), "");
|
||||
}
|
||||
|
||||
// none of the hfc account info should be emitted
|
||||
emit accountResult(QJsonObject{ {"status", "success"} });
|
||||
}
|
||||
|
@ -268,3 +307,25 @@ void Ledger::certificateInfo(const QString& certificateId) {
|
|||
request["certificate_id"] = certificateId;
|
||||
send(endpoint, "certificateInfoSuccess", "certificateInfoFailure", QNetworkAccessManager::PutOperation, AccountManagerAuth::None, request);
|
||||
}
|
||||
|
||||
void Ledger::transferHfcToNode(const QString& hfc_key, const QString& nodeID, const int& amount, const QString& optionalMessage) {
|
||||
QJsonObject transaction;
|
||||
transaction["public_key"] = hfc_key;
|
||||
transaction["node_id"] = nodeID;
|
||||
transaction["quantity"] = amount;
|
||||
transaction["message"] = optionalMessage;
|
||||
QJsonDocument transactionDoc{ transaction };
|
||||
auto transactionString = transactionDoc.toJson(QJsonDocument::Compact);
|
||||
signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_node", "transferHfcToNodeSuccess", "transferHfcToNodeFailure");
|
||||
}
|
||||
|
||||
void Ledger::transferHfcToUsername(const QString& hfc_key, const QString& username, const int& amount, const QString& optionalMessage) {
|
||||
QJsonObject transaction;
|
||||
transaction["public_key"] = hfc_key;
|
||||
transaction["username"] = username;
|
||||
transaction["quantity"] = amount;
|
||||
transaction["message"] = optionalMessage;
|
||||
QJsonDocument transactionDoc{ transaction };
|
||||
auto transactionString = transactionDoc.toJson(QJsonDocument::Compact);
|
||||
signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_user", "transferHfcToUsernameSuccess", "transferHfcToUsernameFailure");
|
||||
}
|
||||
|
|
|
@ -31,9 +31,10 @@ public:
|
|||
void inventory(const QStringList& keys);
|
||||
void history(const QStringList& keys, const int& pageNumber);
|
||||
void account();
|
||||
void reset();
|
||||
void updateLocation(const QString& asset_id, const QString location, const bool controlledFailure = false);
|
||||
void certificateInfo(const QString& certificateId);
|
||||
void transferHfcToNode(const QString& hfc_key, const QString& nodeID, const int& amount, const QString& optionalMessage);
|
||||
void transferHfcToUsername(const QString& hfc_key, const QString& username, const int& amount, const QString& optionalMessage);
|
||||
|
||||
enum CertificateStatus {
|
||||
CERTIFICATE_STATUS_UNKNOWN = 0,
|
||||
|
@ -52,6 +53,8 @@ signals:
|
|||
void accountResult(QJsonObject result);
|
||||
void locationUpdateResult(QJsonObject result);
|
||||
void certificateInfoResult(QJsonObject result);
|
||||
void transferHfcToNodeResult(QJsonObject result);
|
||||
void transferHfcToUsernameResult(QJsonObject result);
|
||||
|
||||
void updateCertificateStatus(const QString& certID, uint certStatus);
|
||||
|
||||
|
@ -66,14 +69,16 @@ public slots:
|
|||
void inventoryFailure(QNetworkReply& reply);
|
||||
void historySuccess(QNetworkReply& reply);
|
||||
void historyFailure(QNetworkReply& reply);
|
||||
void resetSuccess(QNetworkReply& reply);
|
||||
void resetFailure(QNetworkReply& reply);
|
||||
void accountSuccess(QNetworkReply& reply);
|
||||
void accountFailure(QNetworkReply& reply);
|
||||
void updateLocationSuccess(QNetworkReply& reply);
|
||||
void updateLocationFailure(QNetworkReply& reply);
|
||||
void certificateInfoSuccess(QNetworkReply& reply);
|
||||
void certificateInfoFailure(QNetworkReply& reply);
|
||||
void transferHfcToNodeSuccess(QNetworkReply& reply);
|
||||
void transferHfcToNodeFailure(QNetworkReply& reply);
|
||||
void transferHfcToUsernameSuccess(QNetworkReply& reply);
|
||||
void transferHfcToUsernameFailure(QNetworkReply& reply);
|
||||
|
||||
private:
|
||||
QJsonObject apiResponse(const QString& label, QNetworkReply& reply);
|
||||
|
|
|
@ -29,6 +29,8 @@ QmlCommerce::QmlCommerce() {
|
|||
connect(wallet.data(), &Wallet::walletStatusResult, this, &QmlCommerce::walletStatusResult);
|
||||
connect(ledger.data(), &Ledger::certificateInfoResult, this, &QmlCommerce::certificateInfoResult);
|
||||
connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus);
|
||||
connect(ledger.data(), &Ledger::transferHfcToNodeResult, this, &QmlCommerce::transferHfcToNodeResult);
|
||||
connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult);
|
||||
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() {
|
||||
|
@ -128,18 +130,6 @@ void QmlCommerce::generateKeyPair() {
|
|||
getWalletAuthenticatedStatus();
|
||||
}
|
||||
|
||||
void QmlCommerce::reset() {
|
||||
auto ledger = DependencyManager::get<Ledger>();
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
ledger->reset();
|
||||
wallet->reset();
|
||||
}
|
||||
|
||||
void QmlCommerce::resetLocalWalletOnly() {
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
wallet->reset();
|
||||
}
|
||||
|
||||
void QmlCommerce::account() {
|
||||
auto ledger = DependencyManager::get<Ledger>();
|
||||
ledger->account();
|
||||
|
@ -149,3 +139,27 @@ void QmlCommerce::certificateInfo(const QString& certificateId) {
|
|||
auto ledger = DependencyManager::get<Ledger>();
|
||||
ledger->certificateInfo(certificateId);
|
||||
}
|
||||
|
||||
void QmlCommerce::transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage) {
|
||||
auto ledger = DependencyManager::get<Ledger>();
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
QStringList keys = wallet->listPublicKeys();
|
||||
if (keys.count() == 0) {
|
||||
QJsonObject result{ { "status", "fail" },{ "message", "Uninitialized Wallet." } };
|
||||
return emit buyResult(result);
|
||||
}
|
||||
QString key = keys[0];
|
||||
ledger->transferHfcToNode(key, nodeID, amount, optionalMessage);
|
||||
}
|
||||
|
||||
void QmlCommerce::transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage) {
|
||||
auto ledger = DependencyManager::get<Ledger>();
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
QStringList keys = wallet->listPublicKeys();
|
||||
if (keys.count() == 0) {
|
||||
QJsonObject result{ { "status", "fail" },{ "message", "Uninitialized Wallet." } };
|
||||
return emit buyResult(result);
|
||||
}
|
||||
QString key = keys[0];
|
||||
ledger->transferHfcToUsername(key, username, amount, optionalMessage);
|
||||
}
|
||||
|
|
|
@ -45,6 +45,9 @@ signals:
|
|||
|
||||
void updateCertificateStatus(const QString& certID, uint certStatus);
|
||||
|
||||
void transferHfcToNodeResult(QJsonObject result);
|
||||
void transferHfcToUsernameResult(QJsonObject result);
|
||||
|
||||
protected:
|
||||
Q_INVOKABLE void getWalletStatus();
|
||||
|
||||
|
@ -62,11 +65,12 @@ protected:
|
|||
Q_INVOKABLE void inventory();
|
||||
Q_INVOKABLE void history(const int& pageNumber);
|
||||
Q_INVOKABLE void generateKeyPair();
|
||||
Q_INVOKABLE void reset();
|
||||
Q_INVOKABLE void resetLocalWalletOnly();
|
||||
Q_INVOKABLE void account();
|
||||
|
||||
Q_INVOKABLE void certificateInfo(const QString& certificateId);
|
||||
|
||||
Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage);
|
||||
Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage);
|
||||
};
|
||||
|
||||
#endif // hifi_QmlCommerce_h
|
||||
|
|
|
@ -144,15 +144,13 @@ bool writeKeys(const char* filename, EC_KEY* keys) {
|
|||
if ((fp = fopen(filename, "wt"))) {
|
||||
if (!PEM_write_EC_PUBKEY(fp, keys)) {
|
||||
fclose(fp);
|
||||
qCDebug(commerce) << "failed to write public key";
|
||||
QFile(QString(filename)).remove();
|
||||
qCCritical(commerce) << "failed to write public key";
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (!PEM_write_ECPrivateKey(fp, keys, EVP_des_ede3_cbc(), NULL, 0, passwordCallback, NULL)) {
|
||||
fclose(fp);
|
||||
qCDebug(commerce) << "failed to write private key";
|
||||
QFile(QString(filename)).remove();
|
||||
qCCritical(commerce) << "failed to write private key";
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -168,7 +166,8 @@ bool writeKeys(const char* filename, EC_KEY* keys) {
|
|||
QPair<QByteArray*, QByteArray*> generateECKeypair() {
|
||||
|
||||
EC_KEY* keyPair = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
QPair<QByteArray*, QByteArray*> retval;
|
||||
QPair<QByteArray*, QByteArray*> retval{};
|
||||
|
||||
EC_KEY_set_asn1_flag(keyPair, OPENSSL_EC_NAMED_CURVE);
|
||||
if (!EC_KEY_generate_key(keyPair)) {
|
||||
qCDebug(commerce) << "Error generating EC Keypair -" << ERR_get_error();
|
||||
|
@ -517,6 +516,9 @@ bool Wallet::generateKeyPair() {
|
|||
|
||||
qCInfo(commerce) << "Generating keypair.";
|
||||
auto keyPair = generateECKeypair();
|
||||
if (!keyPair.first) {
|
||||
return false;
|
||||
}
|
||||
|
||||
writeBackupInstructions();
|
||||
|
||||
|
@ -653,20 +655,6 @@ QString Wallet::getKeyFilePath() {
|
|||
}
|
||||
}
|
||||
|
||||
void Wallet::reset() {
|
||||
_publicKeys.clear();
|
||||
|
||||
delete _securityImage;
|
||||
_securityImage = nullptr;
|
||||
|
||||
// tell the provider we got nothing
|
||||
updateImageProvider();
|
||||
_passphrase->clear();
|
||||
|
||||
|
||||
QFile keyFile(keyFilePath());
|
||||
keyFile.remove();
|
||||
}
|
||||
bool Wallet::writeWallet(const QString& newPassphrase) {
|
||||
EC_KEY* keys = readKeys(keyFilePath().toStdString().c_str());
|
||||
if (keys) {
|
||||
|
|
|
@ -49,8 +49,6 @@ public:
|
|||
bool walletIsAuthenticatedWithPassphrase();
|
||||
bool changePassphrase(const QString& newPassphrase);
|
||||
|
||||
void reset();
|
||||
|
||||
void getWalletStatus();
|
||||
enum WalletStatus {
|
||||
WALLET_STATUS_NOT_LOGGED_IN = 0,
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
//
|
||||
// AccountScriptingInterface.cpp
|
||||
// interface/src/scripting
|
||||
//
|
||||
// Created by Stojce Slavkovski on 6/07/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AccountManager.h"
|
||||
|
||||
#include "AccountScriptingInterface.h"
|
||||
#include "GlobalServicesScriptingInterface.h"
|
||||
|
||||
AccountScriptingInterface* AccountScriptingInterface::getInstance() {
|
||||
static AccountScriptingInterface sharedInstance;
|
||||
return &sharedInstance;
|
||||
}
|
||||
|
||||
bool AccountScriptingInterface::isLoggedIn() {
|
||||
return GlobalServicesScriptingInterface::getInstance()->isLoggedIn();
|
||||
}
|
||||
|
||||
void AccountScriptingInterface::logOut() {
|
||||
GlobalServicesScriptingInterface::getInstance()->logOut();
|
||||
}
|
||||
|
||||
bool AccountScriptingInterface::loggedIn() const {
|
||||
return GlobalServicesScriptingInterface::getInstance()->loggedIn();
|
||||
}
|
||||
|
||||
QString AccountScriptingInterface::getUsername() {
|
||||
return GlobalServicesScriptingInterface::getInstance()->getUsername();
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
//
|
||||
// AccountScriptingInterface.h
|
||||
// interface/src/scripting
|
||||
//
|
||||
// Created by Stojce Slavkovski on 6/07/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_AccountScriptingInterface_h
|
||||
#define hifi_AccountScriptingInterface_h
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class AccountScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
/**jsdoc
|
||||
* @namespace Account
|
||||
* @property username {String} username if user is logged in, otherwise it returns "Unknown user"
|
||||
*/
|
||||
Q_PROPERTY(QString username READ getUsername)
|
||||
Q_PROPERTY(bool loggedIn READ loggedIn)
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when username has changed.
|
||||
* @function Account.usernameChanged
|
||||
* @return {Signal}
|
||||
*/
|
||||
void usernameChanged();
|
||||
void loggedInChanged(bool loggedIn);
|
||||
|
||||
public slots:
|
||||
static AccountScriptingInterface* getInstance();
|
||||
|
||||
/**jsdoc
|
||||
* Returns the username for the currently logged in High Fidelity metaverse account.
|
||||
* @function Account.getUsername
|
||||
* @return {string} username if user is logged in, otherwise it returns "Unknown user"
|
||||
*/
|
||||
QString getUsername();
|
||||
|
||||
/**jsdoc
|
||||
* Determine if the user is logged into the High Fidleity metaverse.
|
||||
* @function Account.isLoggedIn
|
||||
* @return {bool} true when user is logged into the High Fidelity metaverse.
|
||||
*/
|
||||
bool isLoggedIn();
|
||||
void logOut();
|
||||
|
||||
public:
|
||||
AccountScriptingInterface(QObject* parent = nullptr) {}
|
||||
bool loggedIn() const;
|
||||
};
|
||||
|
||||
#endif // hifi_AccountScriptingInterface_h
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// GlobalServicesScriptingInterface.cpp
|
||||
// AccountServicesScriptingInterface.cpp
|
||||
// interface/src/scripting
|
||||
//
|
||||
// Created by Thijs Wenker on 9/10/14.
|
||||
|
@ -14,41 +14,41 @@
|
|||
#include "DiscoverabilityManager.h"
|
||||
#include "ResourceCache.h"
|
||||
|
||||
#include "GlobalServicesScriptingInterface.h"
|
||||
#include "AccountServicesScriptingInterface.h"
|
||||
|
||||
GlobalServicesScriptingInterface::GlobalServicesScriptingInterface() {
|
||||
AccountServicesScriptingInterface::AccountServicesScriptingInterface() {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
connect(accountManager.data(), &AccountManager::usernameChanged, this, &GlobalServicesScriptingInterface::onUsernameChanged);
|
||||
connect(accountManager.data(), &AccountManager::logoutComplete, this, &GlobalServicesScriptingInterface::loggedOut);
|
||||
connect(accountManager.data(), &AccountManager::loginComplete, this, &GlobalServicesScriptingInterface::connected);
|
||||
connect(accountManager.data(), &AccountManager::usernameChanged, this, &AccountServicesScriptingInterface::onUsernameChanged);
|
||||
connect(accountManager.data(), &AccountManager::logoutComplete, this, &AccountServicesScriptingInterface::loggedOut);
|
||||
connect(accountManager.data(), &AccountManager::loginComplete, this, &AccountServicesScriptingInterface::connected);
|
||||
|
||||
_downloading = false;
|
||||
QTimer* checkDownloadTimer = new QTimer(this);
|
||||
connect(checkDownloadTimer, &QTimer::timeout, this, &GlobalServicesScriptingInterface::checkDownloadInfo);
|
||||
connect(checkDownloadTimer, &QTimer::timeout, this, &AccountServicesScriptingInterface::checkDownloadInfo);
|
||||
const int CHECK_DOWNLOAD_INTERVAL = MSECS_PER_SECOND / 2;
|
||||
checkDownloadTimer->start(CHECK_DOWNLOAD_INTERVAL);
|
||||
|
||||
auto discoverabilityManager = DependencyManager::get<DiscoverabilityManager>();
|
||||
connect(discoverabilityManager.data(), &DiscoverabilityManager::discoverabilityModeChanged,
|
||||
this, &GlobalServicesScriptingInterface::discoverabilityModeChanged);
|
||||
this, &AccountServicesScriptingInterface::discoverabilityModeChanged);
|
||||
|
||||
_loggedIn = isLoggedIn();
|
||||
emit loggedInChanged(_loggedIn);
|
||||
}
|
||||
|
||||
GlobalServicesScriptingInterface::~GlobalServicesScriptingInterface() {
|
||||
AccountServicesScriptingInterface::~AccountServicesScriptingInterface() {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
disconnect(accountManager.data(), &AccountManager::usernameChanged, this, &GlobalServicesScriptingInterface::onUsernameChanged);
|
||||
disconnect(accountManager.data(), &AccountManager::logoutComplete, this, &GlobalServicesScriptingInterface::loggedOut);
|
||||
disconnect(accountManager.data(), &AccountManager::loginComplete, this, &GlobalServicesScriptingInterface::connected);
|
||||
disconnect(accountManager.data(), &AccountManager::usernameChanged, this, &AccountServicesScriptingInterface::onUsernameChanged);
|
||||
disconnect(accountManager.data(), &AccountManager::logoutComplete, this, &AccountServicesScriptingInterface::loggedOut);
|
||||
disconnect(accountManager.data(), &AccountManager::loginComplete, this, &AccountServicesScriptingInterface::connected);
|
||||
}
|
||||
|
||||
GlobalServicesScriptingInterface* GlobalServicesScriptingInterface::getInstance() {
|
||||
static GlobalServicesScriptingInterface sharedInstance;
|
||||
AccountServicesScriptingInterface* AccountServicesScriptingInterface::getInstance() {
|
||||
static AccountServicesScriptingInterface sharedInstance;
|
||||
return &sharedInstance;
|
||||
}
|
||||
|
||||
const QString GlobalServicesScriptingInterface::getUsername() const {
|
||||
const QString AccountServicesScriptingInterface::getUsername() const {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
if (accountManager->isLoggedIn()) {
|
||||
return accountManager->getAccountInfo().getUsername();
|
||||
|
@ -57,31 +57,31 @@ const QString GlobalServicesScriptingInterface::getUsername() const {
|
|||
}
|
||||
}
|
||||
|
||||
bool GlobalServicesScriptingInterface::isLoggedIn() {
|
||||
bool AccountServicesScriptingInterface::isLoggedIn() {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
return accountManager->isLoggedIn();
|
||||
}
|
||||
|
||||
bool GlobalServicesScriptingInterface::checkAndSignalForAccessToken() {
|
||||
bool AccountServicesScriptingInterface::checkAndSignalForAccessToken() {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
return accountManager->checkAndSignalForAccessToken();
|
||||
}
|
||||
|
||||
void GlobalServicesScriptingInterface::logOut() {
|
||||
void AccountServicesScriptingInterface::logOut() {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
return accountManager->logout();
|
||||
}
|
||||
|
||||
void GlobalServicesScriptingInterface::loggedOut() {
|
||||
emit GlobalServicesScriptingInterface::disconnected(QString("logout"));
|
||||
void AccountServicesScriptingInterface::loggedOut() {
|
||||
emit AccountServicesScriptingInterface::disconnected(QString("logout"));
|
||||
}
|
||||
|
||||
QString GlobalServicesScriptingInterface::getFindableBy() const {
|
||||
QString AccountServicesScriptingInterface::getFindableBy() const {
|
||||
auto discoverabilityManager = DependencyManager::get<DiscoverabilityManager>();
|
||||
return DiscoverabilityManager::findableByString(discoverabilityManager->getDiscoverabilityMode());
|
||||
}
|
||||
|
||||
void GlobalServicesScriptingInterface::setFindableBy(const QString& discoverabilityMode) {
|
||||
void AccountServicesScriptingInterface::setFindableBy(const QString& discoverabilityMode) {
|
||||
auto discoverabilityManager = DependencyManager::get<DiscoverabilityManager>();
|
||||
if (discoverabilityMode.toLower() == "none") {
|
||||
discoverabilityManager->setDiscoverabilityMode(Discoverability::None);
|
||||
|
@ -96,11 +96,11 @@ void GlobalServicesScriptingInterface::setFindableBy(const QString& discoverabil
|
|||
}
|
||||
}
|
||||
|
||||
void GlobalServicesScriptingInterface::discoverabilityModeChanged(Discoverability::Mode discoverabilityMode) {
|
||||
void AccountServicesScriptingInterface::discoverabilityModeChanged(Discoverability::Mode discoverabilityMode) {
|
||||
emit findableByChanged(DiscoverabilityManager::findableByString(discoverabilityMode));
|
||||
}
|
||||
|
||||
void GlobalServicesScriptingInterface::onUsernameChanged(const QString& username) {
|
||||
void AccountServicesScriptingInterface::onUsernameChanged(const QString& username) {
|
||||
_loggedIn = (username != QString());
|
||||
emit myUsernameChanged(username);
|
||||
emit loggedInChanged(_loggedIn);
|
||||
|
@ -135,7 +135,7 @@ void DownloadInfoResultFromScriptValue(const QScriptValue& object, DownloadInfoR
|
|||
result.pending = object.property("pending").toVariant().toFloat();
|
||||
}
|
||||
|
||||
DownloadInfoResult GlobalServicesScriptingInterface::getDownloadInfo() {
|
||||
DownloadInfoResult AccountServicesScriptingInterface::getDownloadInfo() {
|
||||
DownloadInfoResult result;
|
||||
foreach(const auto& resource, ResourceCache::getLoadingRequests()) {
|
||||
result.downloading.append(resource->getProgress() * 100.0f);
|
||||
|
@ -144,7 +144,7 @@ DownloadInfoResult GlobalServicesScriptingInterface::getDownloadInfo() {
|
|||
return result;
|
||||
}
|
||||
|
||||
void GlobalServicesScriptingInterface::checkDownloadInfo() {
|
||||
void AccountServicesScriptingInterface::checkDownloadInfo() {
|
||||
DownloadInfoResult downloadInfo = getDownloadInfo();
|
||||
bool downloading = downloadInfo.downloading.count() > 0 || downloadInfo.pending > 0;
|
||||
|
||||
|
@ -155,7 +155,7 @@ void GlobalServicesScriptingInterface::checkDownloadInfo() {
|
|||
}
|
||||
}
|
||||
|
||||
void GlobalServicesScriptingInterface::updateDownloadInfo() {
|
||||
void AccountServicesScriptingInterface::updateDownloadInfo() {
|
||||
emit downloadInfoChanged(getDownloadInfo());
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// GlobalServicesScriptingInterface.h
|
||||
// AccountServicesScriptingInterface.h
|
||||
// interface/src/scripting
|
||||
//
|
||||
// Created by Thijs Wenker on 9/10/14.
|
||||
|
@ -9,8 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_GlobalServicesScriptingInterface_h
|
||||
#define hifi_GlobalServicesScriptingInterface_h
|
||||
#ifndef hifi_AccountServicesScriptingInterface_h
|
||||
#define hifi_AccountServicesScriptingInterface_h
|
||||
|
||||
#include <QObject>
|
||||
#include <QScriptContext>
|
||||
|
@ -32,7 +32,7 @@ Q_DECLARE_METATYPE(DownloadInfoResult)
|
|||
QScriptValue DownloadInfoResultToScriptValue(QScriptEngine* engine, const DownloadInfoResult& result);
|
||||
void DownloadInfoResultFromScriptValue(const QScriptValue& object, DownloadInfoResult& result);
|
||||
|
||||
class GlobalServicesScriptingInterface : public QObject {
|
||||
class AccountServicesScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString username READ getUsername NOTIFY myUsernameChanged)
|
||||
|
@ -41,7 +41,7 @@ class GlobalServicesScriptingInterface : public QObject {
|
|||
Q_PROPERTY(QUrl metaverseServerURL READ getMetaverseServerURL)
|
||||
|
||||
public:
|
||||
static GlobalServicesScriptingInterface* getInstance();
|
||||
static AccountServicesScriptingInterface* getInstance();
|
||||
|
||||
const QString getUsername() const;
|
||||
bool loggedIn() const { return _loggedIn; }
|
||||
|
@ -74,11 +74,11 @@ signals:
|
|||
void loggedInChanged(bool loggedIn);
|
||||
|
||||
private:
|
||||
GlobalServicesScriptingInterface();
|
||||
~GlobalServicesScriptingInterface();
|
||||
AccountServicesScriptingInterface();
|
||||
~AccountServicesScriptingInterface();
|
||||
|
||||
bool _downloading;
|
||||
bool _loggedIn{ false };
|
||||
};
|
||||
|
||||
#endif // hifi_GlobalServicesScriptingInterface_h
|
||||
#endif // hifi_AccountServicesScriptingInterface_h
|
|
@ -49,6 +49,8 @@ void CustomPromptResultFromScriptValue(const QScriptValue& object, CustomPromptR
|
|||
WindowScriptingInterface::WindowScriptingInterface() {
|
||||
const DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();
|
||||
connect(&domainHandler, &DomainHandler::connectedToDomain, this, &WindowScriptingInterface::domainChanged);
|
||||
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &WindowScriptingInterface::disconnectedFromDomain);
|
||||
|
||||
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &WindowScriptingInterface::domainConnectionRefused);
|
||||
|
||||
connect(qApp, &Application::svoImportRequested, [this](const QString& urlString) {
|
||||
|
@ -134,6 +136,10 @@ void WindowScriptingInterface::promptAsync(const QString& message, const QString
|
|||
});
|
||||
}
|
||||
|
||||
void WindowScriptingInterface::disconnectedFromDomain() {
|
||||
emit domainChanged("");
|
||||
}
|
||||
|
||||
CustomPromptResult WindowScriptingInterface::customPrompt(const QVariant& config) {
|
||||
CustomPromptResult result;
|
||||
bool ok = false;
|
||||
|
@ -176,10 +182,6 @@ bool WindowScriptingInterface::isPointOnDesktopWindow(QVariant point) {
|
|||
return offscreenUi->isPointOnDesktopWindow(point);
|
||||
}
|
||||
|
||||
glm::vec2 WindowScriptingInterface::getDeviceSize() const {
|
||||
return qApp->getDeviceSize();
|
||||
}
|
||||
|
||||
/// Makes sure that the reticle is visible, use this in blocking forms that require a reticle and
|
||||
/// might be in same thread as a script that sets the reticle to invisible
|
||||
void WindowScriptingInterface::ensureReticleVisible() const {
|
||||
|
@ -389,11 +391,15 @@ QString WindowScriptingInterface::checkVersion() {
|
|||
}
|
||||
|
||||
int WindowScriptingInterface::getInnerWidth() {
|
||||
return qApp->getWindow()->geometry().width();
|
||||
return qApp->getDeviceSize().x;
|
||||
}
|
||||
|
||||
int WindowScriptingInterface::getInnerHeight() {
|
||||
return qApp->getWindow()->geometry().height();
|
||||
return qApp->getDeviceSize().y;
|
||||
}
|
||||
|
||||
glm::vec2 WindowScriptingInterface::getDeviceSize() const {
|
||||
return qApp->getDeviceSize();
|
||||
}
|
||||
|
||||
int WindowScriptingInterface::getX() {
|
||||
|
@ -405,6 +411,11 @@ int WindowScriptingInterface::getY() {
|
|||
}
|
||||
|
||||
void WindowScriptingInterface::copyToClipboard(const QString& text) {
|
||||
if (QThread::currentThread() != qApp->thread()) {
|
||||
QMetaObject::invokeMethod(this, "copyToClipboard", Q_ARG(QString, text));
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Copying";
|
||||
QApplication::clipboard()->setText(text);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// WindowScriptingInterface.cpp
|
||||
// WindowScriptingInterface.h
|
||||
// interface/src/scripting
|
||||
//
|
||||
// Created by Ryan Huffman on 4/29/14.
|
||||
|
@ -42,7 +42,7 @@ void CustomPromptResultFromScriptValue(const QScriptValue& object, CustomPromptR
|
|||
* @property {number} innerWidth - The width of the drawable area of the Interface window (i.e., without borders or other
|
||||
* chrome), in pixels. <em>Read-only.</em>
|
||||
* @property {number} innerHeight - The height of the drawable area of the Interface window (i.e., without borders or other
|
||||
* chrome) plus the height of the menu bar, in pixels. <em>Read-only.</em>
|
||||
* chrome), in pixels. <em>Read-only.</em>
|
||||
* @property {object} location - Provides facilities for working with your current metaverse location. See {@link location}.
|
||||
* @property {number} x - The x coordinate of the top left corner of the Interface window on the display. <em>Read-only.</em>
|
||||
* @property {number} y - The y coordinate of the top left corner of the Interface window on the display. <em>Read-only.</em>
|
||||
|
@ -54,6 +54,7 @@ class WindowScriptingInterface : public QObject, public Dependency {
|
|||
Q_PROPERTY(int innerHeight READ getInnerHeight)
|
||||
Q_PROPERTY(int x READ getX)
|
||||
Q_PROPERTY(int y READ getY)
|
||||
|
||||
public:
|
||||
WindowScriptingInterface();
|
||||
~WindowScriptingInterface();
|
||||
|
@ -143,7 +144,7 @@ public slots:
|
|||
|
||||
/**jsdoc
|
||||
* Prompt the user for input in a custom, modal dialog.
|
||||
* @deprecated This funtion is deprecated and will be removed.
|
||||
* @deprecated This function is deprecated and will soon be removed.
|
||||
* @function Window.customPrompt
|
||||
* @param {object} config - Configures the modal dialog.
|
||||
* @returns {object} The user's response.
|
||||
|
@ -300,7 +301,7 @@ public slots:
|
|||
/**jsdoc
|
||||
* Get Interface's build number.
|
||||
* @function Window.checkVersion
|
||||
* @returns {string} - Interface's build number.
|
||||
* @returns {string} Interface's build number.
|
||||
*/
|
||||
QString checkVersion();
|
||||
|
||||
|
@ -326,7 +327,7 @@ public slots:
|
|||
* full resolution is used (window dimensions in desktop mode; HMD display dimensions in HMD mode), otherwise one of the
|
||||
* dimensions is adjusted in order to match the aspect ratio.
|
||||
* @example <caption>Using the snapshot function and signals.</caption>
|
||||
* function onStillSnapshottaken(path, notify) {
|
||||
* function onStillSnapshotTaken(path, notify) {
|
||||
* print("Still snapshot taken: " + path);
|
||||
* print("Notify: " + notify);
|
||||
* }
|
||||
|
@ -339,7 +340,7 @@ public slots:
|
|||
* print("Animated snapshot taken: " + animatedPath);
|
||||
* }
|
||||
*
|
||||
* Window.stillSnapshotTaken.connect(onStillSnapshottaken);
|
||||
* Window.stillSnapshotTaken.connect(onStillSnapshotTaken);
|
||||
* Window.processingGifStarted.connect(onProcessingGifStarted);
|
||||
* Window.processingGifCompleted.connect(onProcessingGifCompleted);
|
||||
*
|
||||
|
@ -515,6 +516,7 @@ public slots:
|
|||
|
||||
private slots:
|
||||
void onMessageBoxSelected(int button);
|
||||
void disconnectedFromDomain();
|
||||
|
||||
signals:
|
||||
|
||||
|
@ -553,7 +555,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Triggered when a still snapshot has been taken by calling {@link Window.takeSnapshot|takeSnapshot} with
|
||||
* <code>includeAnimated = false</code>.
|
||||
* <code>includeAnimated = false</code> or {@link Window.takeSecondaryCameraSnapshot|takeSecondaryCameraSnapshot}.
|
||||
* @function Window.stillSnapshotTaken
|
||||
* @param {string} pathStillSnapshot - The path and name of the snapshot image file.
|
||||
* @param {boolean} notify - The value of the <code>notify</code> parameter that {@link Window.takeSnapshot|takeSnapshot}
|
||||
|
|
|
@ -210,8 +210,8 @@ void Base3DOverlay::setProperties(const QVariantMap& originalProperties) {
|
|||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>,
|
||||
* <code>filled</code>, and <code>filed</code>. Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>.
|
||||
* @property {boolean} ignoreRayIntersection=false - If <code>true</code>,
|
||||
|
|
|
@ -386,8 +386,6 @@ void Circle3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
||||
* rotating as you move your avatar.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
|
@ -397,10 +395,8 @@ void Circle3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>,
|
||||
* <code>filled</code>, and <code>filed</code>. Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* <strong>Deprecated:</strong> The erroneous property spelling "<code>filed</code>" is deprecated and support for it will
|
||||
* be removed.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>.
|
||||
* @property {boolean} ignoreRayIntersection=false - If <code>true</code>,
|
||||
|
|
|
@ -154,8 +154,6 @@ void Cube3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
||||
* rotating as you move your avatar.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
|
@ -165,10 +163,8 @@ void Cube3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>,
|
||||
* <code>filled</code>, and <code>filed</code>. Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* <strong>Deprecated:</strong> The erroneous property spelling "<code>filed</code>" is deprecated and support for it will
|
||||
* be removed.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>.
|
||||
* @property {boolean} ignoreRayIntersection=false - If <code>true</code>,
|
||||
|
|
|
@ -132,8 +132,6 @@ void Grid3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
||||
* rotating as you move your avatar.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
|
@ -143,10 +141,8 @@ void Grid3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>,
|
||||
* <code>filled</code>, and <code>filed</code>. Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* <strong>Deprecated:</strong> The erroneous property spelling "<code>filed</code>" is deprecated and support for it will
|
||||
* be removed.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>.
|
||||
* @property {boolean} ignoreRayIntersection=false - If <code>true</code>,
|
||||
|
|
|
@ -208,8 +208,6 @@ void Image3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
||||
* rotating as you move your avatar.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
|
@ -219,10 +217,8 @@ void Image3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>,
|
||||
* <code>filled</code>, and <code>filed</code>. Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* <strong>Deprecated:</strong> The erroneous property spelling "<code>filed</code>" is deprecated and support for it will
|
||||
* be removed.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>.
|
||||
* @property {boolean} ignoreRayIntersection=false - If <code>true</code>,
|
||||
|
|
|
@ -275,8 +275,6 @@ void Line3DOverlay::setProperties(const QVariantMap& originalProperties) {
|
|||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
||||
* rotating as you move your avatar.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
|
@ -286,10 +284,8 @@ void Line3DOverlay::setProperties(const QVariantMap& originalProperties) {
|
|||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>,
|
||||
* <code>filled</code>, and <code>filed</code>. Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* <strong>Deprecated:</strong> The erroneous property spelling "<code>filed</code>" is deprecated and support for it will
|
||||
* be removed.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>.
|
||||
* @property {boolean} ignoreRayIntersection=false - If <code>true</code>,
|
||||
|
|
|
@ -306,8 +306,6 @@ vectorType ModelOverlay::mapJoints(mapFunction<itemType> function) const {
|
|||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
||||
* rotating as you move your avatar.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
|
@ -317,10 +315,8 @@ vectorType ModelOverlay::mapJoints(mapFunction<itemType> function) const {
|
|||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>,
|
||||
* <code>filled</code>, and <code>filed</code>. Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* <strong>Deprecated:</strong> The erroneous property spelling "<code>filed</code>" is deprecated and support for it will
|
||||
* be removed.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>.
|
||||
* @property {boolean} ignoreRayIntersection=false - If <code>true</code>,
|
||||
|
|
|
@ -31,8 +31,7 @@ Overlay::Overlay() :
|
|||
_alphaPulse(0.0f),
|
||||
_colorPulse(0.0f),
|
||||
_color(DEFAULT_OVERLAY_COLOR),
|
||||
_visible(true),
|
||||
_anchor(NO_ANCHOR)
|
||||
_visible(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -49,8 +48,7 @@ Overlay::Overlay(const Overlay* overlay) :
|
|||
_alphaPulse(overlay->_alphaPulse),
|
||||
_colorPulse(overlay->_colorPulse),
|
||||
_color(overlay->_color),
|
||||
_visible(overlay->_visible),
|
||||
_anchor(overlay->_anchor)
|
||||
_visible(overlay->_visible)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -92,13 +90,6 @@ void Overlay::setProperties(const QVariantMap& properties) {
|
|||
bool visible = properties["visible"].toBool();
|
||||
setVisible(visible);
|
||||
}
|
||||
|
||||
if (properties["anchor"].isValid()) {
|
||||
QString property = properties["anchor"].toString();
|
||||
if (property == "MyAvatar") {
|
||||
setAnchor(MY_AVATAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// JSDoc for copying to @typedefs of overlay types that inherit Overlay.
|
||||
|
@ -119,8 +110,6 @@ void Overlay::setProperties(const QVariantMap& properties) {
|
|||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
||||
* rotating as you move your avatar.
|
||||
*/
|
||||
QVariant Overlay::getProperty(const QString& property) {
|
||||
if (property == "type") {
|
||||
|
@ -150,9 +139,6 @@ QVariant Overlay::getProperty(const QString& property) {
|
|||
if (property == "visible") {
|
||||
return _visible;
|
||||
}
|
||||
if (property == "anchor") {
|
||||
return _anchor == MY_AVATAR ? "MyAvatar" : "";
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
|
|
@ -26,11 +26,6 @@ class Overlay : public QObject {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Anchor {
|
||||
NO_ANCHOR,
|
||||
MY_AVATAR
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Overlay> Pointer;
|
||||
typedef render::Payload<Overlay> Payload;
|
||||
typedef std::shared_ptr<render::Item::PayloadInterface> PayloadPointer;
|
||||
|
@ -63,7 +58,6 @@ public:
|
|||
virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; };
|
||||
xColor getColor();
|
||||
float getAlpha();
|
||||
Anchor getAnchor() const { return _anchor; }
|
||||
|
||||
float getPulseMax() const { return _pulseMax; }
|
||||
float getPulseMin() const { return _pulseMin; }
|
||||
|
@ -78,7 +72,6 @@ public:
|
|||
void setDrawHUDLayer(bool drawHUDLayer);
|
||||
void setColor(const xColor& color) { _color = color; }
|
||||
void setAlpha(float alpha) { _alpha = alpha; }
|
||||
void setAnchor(Anchor anchor) { _anchor = anchor; }
|
||||
|
||||
void setPulseMax(float value) { _pulseMax = value; }
|
||||
void setPulseMin(float value) { _pulseMin = value; }
|
||||
|
@ -118,7 +111,6 @@ protected:
|
|||
|
||||
xColor _color;
|
||||
bool _visible; // should the overlay be drawn at all
|
||||
Anchor _anchor;
|
||||
|
||||
unsigned int _stackOrder { 0 };
|
||||
|
||||
|
|
|
@ -1,190 +0,0 @@
|
|||
//
|
||||
// OverlayPanel.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// Created by Zander Otavka on 7/2/15.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "OverlayPanel.h"
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
|
||||
#include <QVariant>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <EntityScriptingInterface.h>
|
||||
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "avatar/MyAvatar.h"
|
||||
#include "Base3DOverlay.h"
|
||||
|
||||
PropertyBinding::PropertyBinding(QString avatar, QUuid entity) :
|
||||
avatar(avatar),
|
||||
entity(entity)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant propertyBindingToVariant(const PropertyBinding& value) {
|
||||
QVariantMap obj;
|
||||
|
||||
if (value.avatar == "MyAvatar") {
|
||||
obj["avatar"] = "MyAvatar";
|
||||
} else if (!value.entity.isNull()) {
|
||||
obj["entity"] = value.entity;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void propertyBindingFromVariant(const QVariant& objectVar, PropertyBinding& value) {
|
||||
auto object = objectVar.toMap();
|
||||
auto avatar = object["avatar"];
|
||||
auto entity = object["entity"];
|
||||
|
||||
if (avatar.isValid() && !avatar.isNull()) {
|
||||
value.avatar = avatar.toString();
|
||||
} else if (entity.isValid() && !entity.isNull()) {
|
||||
value.entity = entity.toUuid();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OverlayPanel::addChild(OverlayID childId) {
|
||||
if (!_children.contains(childId)) {
|
||||
_children.append(childId);
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayPanel::removeChild(OverlayID childId) {
|
||||
if (_children.contains(childId)) {
|
||||
_children.removeOne(childId);
|
||||
}
|
||||
}
|
||||
|
||||
QVariant OverlayPanel::getProperty(const QString &property) {
|
||||
if (property == "anchorPosition") {
|
||||
return vec3toVariant(getAnchorPosition());
|
||||
}
|
||||
if (property == "anchorPositionBinding") {
|
||||
return propertyBindingToVariant(PropertyBinding(_anchorPositionBindMyAvatar ?
|
||||
"MyAvatar" : "",
|
||||
_anchorPositionBindEntity));
|
||||
}
|
||||
if (property == "anchorRotation") {
|
||||
return quatToVariant(getAnchorRotation());
|
||||
}
|
||||
if (property == "anchorRotationBinding") {
|
||||
return propertyBindingToVariant(PropertyBinding(_anchorRotationBindMyAvatar ?
|
||||
"MyAvatar" : "",
|
||||
_anchorRotationBindEntity));
|
||||
}
|
||||
if (property == "anchorScale") {
|
||||
return vec3toVariant(getAnchorScale());
|
||||
}
|
||||
if (property == "visible") {
|
||||
return getVisible();
|
||||
}
|
||||
if (property == "children") {
|
||||
QVariantList array;
|
||||
for (int i = 0; i < _children.length(); i++) {
|
||||
array.append(OverlayIDtoScriptValue(nullptr, _children[i]).toVariant());
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
auto value = Billboardable::getProperty(property);
|
||||
if (value.isValid()) {
|
||||
return value;
|
||||
}
|
||||
return PanelAttachable::getProperty(property);
|
||||
}
|
||||
|
||||
void OverlayPanel::setProperties(const QVariantMap& properties) {
|
||||
PanelAttachable::setProperties(properties);
|
||||
Billboardable::setProperties(properties);
|
||||
|
||||
auto anchorPosition = properties["anchorPosition"];
|
||||
if (anchorPosition.isValid()) {
|
||||
setAnchorPosition(vec3FromVariant(anchorPosition));
|
||||
}
|
||||
|
||||
auto anchorPositionBinding = properties["anchorPositionBinding"];
|
||||
if (anchorPositionBinding.isValid()) {
|
||||
PropertyBinding binding = {};
|
||||
propertyBindingFromVariant(anchorPositionBinding, binding);
|
||||
_anchorPositionBindMyAvatar = binding.avatar == "MyAvatar";
|
||||
_anchorPositionBindEntity = binding.entity;
|
||||
}
|
||||
|
||||
auto anchorRotation = properties["anchorRotation"];
|
||||
if (anchorRotation.isValid()) {
|
||||
setAnchorRotation(quatFromVariant(anchorRotation));
|
||||
}
|
||||
|
||||
auto anchorRotationBinding = properties["anchorRotationBinding"];
|
||||
if (anchorRotationBinding.isValid()) {
|
||||
PropertyBinding binding = {};
|
||||
propertyBindingFromVariant(anchorPositionBinding, binding);
|
||||
_anchorRotationBindMyAvatar = binding.avatar == "MyAvatar";
|
||||
_anchorRotationBindEntity = binding.entity;
|
||||
}
|
||||
|
||||
auto anchorScale = properties["anchorScale"];
|
||||
if (anchorScale.isValid()) {
|
||||
setAnchorScale(vec3FromVariant(anchorScale));
|
||||
}
|
||||
|
||||
auto visible = properties["visible"];
|
||||
if (visible.isValid()) {
|
||||
setVisible(visible.toBool());
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayPanel::applyTransformTo(Transform& transform, bool force) {
|
||||
if (force || usecTimestampNow() > _transformExpiry) {
|
||||
PanelAttachable::applyTransformTo(transform, true);
|
||||
if (!getParentPanel()) {
|
||||
if (_anchorPositionBindMyAvatar) {
|
||||
transform.setTranslation(DependencyManager::get<AvatarManager>()->getMyAvatar()
|
||||
->getPosition());
|
||||
} else if (!_anchorPositionBindEntity.isNull()) {
|
||||
EntityTreePointer entityTree = DependencyManager::get<EntityScriptingInterface>()->getEntityTree();
|
||||
entityTree->withReadLock([&] {
|
||||
EntityItemPointer foundEntity = entityTree->findEntityByID(_anchorPositionBindEntity);
|
||||
if (foundEntity) {
|
||||
transform.setTranslation(foundEntity->getPosition());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
transform.setTranslation(getAnchorPosition());
|
||||
}
|
||||
|
||||
if (_anchorRotationBindMyAvatar) {
|
||||
transform.setRotation(DependencyManager::get<AvatarManager>()->getMyAvatar()
|
||||
->getOrientation());
|
||||
} else if (!_anchorRotationBindEntity.isNull()) {
|
||||
EntityTreePointer entityTree = DependencyManager::get<EntityScriptingInterface>()->getEntityTree();
|
||||
entityTree->withReadLock([&] {
|
||||
EntityItemPointer foundEntity = entityTree->findEntityByID(_anchorRotationBindEntity);
|
||||
if (foundEntity) {
|
||||
transform.setRotation(foundEntity->getRotation());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
transform.setRotation(getAnchorRotation());
|
||||
}
|
||||
|
||||
transform.setScale(getAnchorScale());
|
||||
|
||||
transform.postTranslate(getOffsetPosition());
|
||||
transform.postRotate(getOffsetRotation());
|
||||
transform.postScale(getOffsetScale());
|
||||
}
|
||||
pointTransformAtCamera(transform, getOffsetRotation());
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,86 +0,0 @@
|
|||
//
|
||||
// OverlayPanel.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// Created by Zander Otavka on 7/2/15.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_OverlayPanel_h
|
||||
#define hifi_OverlayPanel_h
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <QUuid>
|
||||
|
||||
#include "PanelAttachable.h"
|
||||
#include "Billboardable.h"
|
||||
#include "Overlay.h"
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
class PropertyBinding {
|
||||
public:
|
||||
PropertyBinding() {}
|
||||
PropertyBinding(QString avatar, QUuid entity);
|
||||
QString avatar;
|
||||
QUuid entity;
|
||||
};
|
||||
|
||||
QVariant propertyBindingToVariant(const PropertyBinding& value);
|
||||
void propertyBindingFromVariant(const QVariant& object, PropertyBinding& value);
|
||||
|
||||
|
||||
class OverlayPanel : public QObject, public PanelAttachable, public Billboardable {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
typedef std::shared_ptr<OverlayPanel> Pointer;
|
||||
|
||||
void init(QScriptEngine* scriptEngine) { _scriptEngine = scriptEngine; }
|
||||
|
||||
// getters
|
||||
glm::vec3 getAnchorPosition() const { return _anchorTransform.getTranslation(); }
|
||||
glm::quat getAnchorRotation() const { return _anchorTransform.getRotation(); }
|
||||
glm::vec3 getAnchorScale() const { return _anchorTransform.getScale(); }
|
||||
bool getVisible() const { return _visible; }
|
||||
|
||||
// setters
|
||||
void setAnchorPosition(const glm::vec3& position) { _anchorTransform.setTranslation(position); }
|
||||
void setAnchorRotation(const glm::quat& rotation) { _anchorTransform.setRotation(rotation); }
|
||||
void setAnchorScale(float scale) { _anchorTransform.setScale(scale); }
|
||||
void setAnchorScale(const glm::vec3& scale) { _anchorTransform.setScale(scale); }
|
||||
void setVisible(bool visible) { _visible = visible; }
|
||||
|
||||
const QList<OverlayID>& getChildren() { return _children; }
|
||||
void addChild(OverlayID childId);
|
||||
void removeChild(OverlayID childId);
|
||||
OverlayID popLastChild() { return _children.takeLast(); }
|
||||
|
||||
void setProperties(const QVariantMap& properties);
|
||||
QVariant getProperty(const QString& property);
|
||||
|
||||
virtual void applyTransformTo(Transform& transform, bool force = false) override;
|
||||
|
||||
private:
|
||||
Transform _anchorTransform;
|
||||
|
||||
bool _anchorPositionBindMyAvatar = false;
|
||||
QUuid _anchorPositionBindEntity;
|
||||
|
||||
bool _anchorRotationBindMyAvatar = false;
|
||||
QUuid _anchorRotationBindEntity;
|
||||
|
||||
bool _visible = true;
|
||||
QList<OverlayID> _children;
|
||||
|
||||
QScriptEngine* _scriptEngine;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // hifi_OverlayPanel_h
|
|
@ -68,16 +68,10 @@ void Overlays::cleanupAllOverlays() {
|
|||
foreach(Overlay::Pointer overlay, overlaysWorld) {
|
||||
_overlaysToDelete.push_back(overlay);
|
||||
}
|
||||
#if OVERLAY_PANELS
|
||||
_panels.clear();
|
||||
#endif
|
||||
cleanupOverlaysToDelete();
|
||||
}
|
||||
|
||||
void Overlays::init() {
|
||||
#if OVERLAY_PANELS
|
||||
_scriptEngine = new QScriptEngine();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Overlays::update(float deltatime) {
|
||||
|
@ -300,12 +294,6 @@ OverlayID Overlays::cloneOverlay(OverlayID id) {
|
|||
|
||||
if (thisOverlay) {
|
||||
OverlayID cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone(), [](Overlay* ptr) { ptr->deleteLater(); }));
|
||||
#if OVERLAY_PANELS
|
||||
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(thisOverlay);
|
||||
if (attachable && attachable->getParentPanel()) {
|
||||
attachable->getParentPanel()->addChild(cloneId);
|
||||
}
|
||||
#endif
|
||||
return cloneId;
|
||||
}
|
||||
|
||||
|
@ -381,15 +369,6 @@ void Overlays::deleteOverlay(OverlayID id) {
|
|||
}
|
||||
}
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlayToDelete);
|
||||
if (attachable && attachable->getParentPanel()) {
|
||||
attachable->getParentPanel()->removeChild(id);
|
||||
attachable->setParentPanel(nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
_overlaysToDelete.push_back(overlayToDelete);
|
||||
emit overlayDeleted(id);
|
||||
}
|
||||
|
@ -424,49 +403,6 @@ QObject* Overlays::getOverlayObject(OverlayID id) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
OverlayID Overlays::getParentPanel(OverlayID childId) const {
|
||||
Overlay::Pointer overlay = getOverlay(childId);
|
||||
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(overlay);
|
||||
if (attachable) {
|
||||
return _panels.key(attachable->getParentPanel());
|
||||
} else if (_panels.contains(childId)) {
|
||||
return _panels.key(getPanel(childId)->getParentPanel());
|
||||
}
|
||||
return UNKNOWN_OVERLAY_ID;
|
||||
}
|
||||
|
||||
void Overlays::setParentPanel(OverlayID childId, OverlayID panelId) {
|
||||
auto attachable = std::dynamic_pointer_cast<PanelAttachable>(getOverlay(childId));
|
||||
if (attachable) {
|
||||
if (_panels.contains(panelId)) {
|
||||
auto panel = getPanel(panelId);
|
||||
panel->addChild(childId);
|
||||
attachable->setParentPanel(panel);
|
||||
} else {
|
||||
auto panel = attachable->getParentPanel();
|
||||
if (panel) {
|
||||
panel->removeChild(childId);
|
||||
attachable->setParentPanel(nullptr);
|
||||
}
|
||||
}
|
||||
} else if (_panels.contains(childId)) {
|
||||
OverlayPanel::Pointer child = getPanel(childId);
|
||||
if (_panels.contains(panelId)) {
|
||||
auto panel = getPanel(panelId);
|
||||
panel->addChild(childId);
|
||||
child->setParentPanel(panel);
|
||||
} else {
|
||||
auto panel = child->getParentPanel();
|
||||
if (panel) {
|
||||
panel->removeChild(childId);
|
||||
child->setParentPanel(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) {
|
||||
if (!_enabled) {
|
||||
return UNKNOWN_OVERLAY_ID;
|
||||
|
@ -717,62 +653,6 @@ QSizeF Overlays::textSize(OverlayID id, const QString& text) {
|
|||
return QSizeF(0.0f, 0.0f);
|
||||
}
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
OverlayID Overlays::addPanel(OverlayPanel::Pointer panel) {
|
||||
QWriteLocker lock(&_lock);
|
||||
|
||||
OverlayID thisID = QUuid::createUuid();
|
||||
_panels[thisID] = panel;
|
||||
|
||||
return thisID;
|
||||
}
|
||||
|
||||
OverlayID Overlays::addPanel(const QVariant& properties) {
|
||||
OverlayPanel::Pointer panel = std::make_shared<OverlayPanel>();
|
||||
panel->init(_scriptEngine);
|
||||
panel->setProperties(properties.toMap());
|
||||
return addPanel(panel);
|
||||
}
|
||||
|
||||
void Overlays::editPanel(OverlayID panelId, const QVariant& properties) {
|
||||
if (_panels.contains(panelId)) {
|
||||
_panels[panelId]->setProperties(properties.toMap());
|
||||
}
|
||||
}
|
||||
|
||||
OverlayPropertyResult Overlays::getPanelProperty(OverlayID panelId, const QString& property) {
|
||||
OverlayPropertyResult result;
|
||||
if (_panels.contains(panelId)) {
|
||||
OverlayPanel::Pointer thisPanel = getPanel(panelId);
|
||||
QReadLocker lock(&_lock);
|
||||
result.value = thisPanel->getProperty(property);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void Overlays::deletePanel(OverlayID panelId) {
|
||||
OverlayPanel::Pointer panelToDelete;
|
||||
|
||||
{
|
||||
QWriteLocker lock(&_lock);
|
||||
if (_panels.contains(panelId)) {
|
||||
panelToDelete = _panels.take(panelId);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (!panelToDelete->getChildren().isEmpty()) {
|
||||
OverlayID childId = panelToDelete->popLastChild();
|
||||
deleteOverlay(childId);
|
||||
deletePanel(childId);
|
||||
}
|
||||
|
||||
emit panelDeleted(panelId);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Overlays::isAddedOverlay(OverlayID id) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
bool result;
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "Overlay.h"
|
||||
|
||||
#include "PanelAttachable.h"
|
||||
#include "OverlayPanel.h"
|
||||
|
||||
class PickRay;
|
||||
|
||||
|
@ -93,9 +92,6 @@ public:
|
|||
void enable();
|
||||
|
||||
Overlay::Pointer getOverlay(OverlayID id) const;
|
||||
#if OVERLAY_PANELS
|
||||
OverlayPanel::Pointer getPanel(OverlayID id) const { return _panels[id]; }
|
||||
#endif
|
||||
|
||||
/// adds an overlay that's already been created
|
||||
OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); }
|
||||
|
@ -233,6 +229,7 @@ public slots:
|
|||
/**jsdoc
|
||||
* Get the overlay script object.
|
||||
* @function Overlays.getOverlayObject
|
||||
* @deprecated This function is deprecated and will soon be removed.
|
||||
* @param {Uuid} overlayID - The ID of the overlay to get the script object of.
|
||||
* @returns {object} The script object for the overlay if found.
|
||||
*/
|
||||
|
@ -467,30 +464,6 @@ public slots:
|
|||
*/
|
||||
bool isAddedOverlay(OverlayID id);
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
OverlayID getParentPanel(OverlayID childId) const;
|
||||
void setParentPanel(OverlayID childId, OverlayID panelId);
|
||||
|
||||
/// adds a panel that has already been created
|
||||
OverlayID addPanel(OverlayPanel::Pointer panel);
|
||||
|
||||
/// creates and adds a panel based on a set of properties
|
||||
OverlayID addPanel(const QVariant& properties);
|
||||
|
||||
/// edit the properties of a panel
|
||||
void editPanel(OverlayID panelId, const QVariant& properties);
|
||||
|
||||
/// get a property of a panel
|
||||
OverlayPropertyResult getPanelProperty(OverlayID panelId, const QString& property);
|
||||
|
||||
/// deletes a panel and all child overlays
|
||||
void deletePanel(OverlayID panelId);
|
||||
|
||||
/// return true if there is a panel with that id else false
|
||||
bool isAddedPanel(OverlayID id) { return _panels.contains(id); }
|
||||
|
||||
#endif
|
||||
|
||||
/**jsdoc
|
||||
* Generate a mouse press event on an overlay.
|
||||
* @function Overlays.sendMousePressOnOverlay
|
||||
|
@ -611,10 +584,6 @@ signals:
|
|||
*/
|
||||
void overlayDeleted(OverlayID id);
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
void panelDeleted(OverlayID id);
|
||||
#endif
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when a mouse press event occurs on an overlay. Only occurs for 3D overlays (unless you use
|
||||
* {@link Overlays.sendMousePressOnOverlay|sendMousePressOnOverlay} for a 2D overlay).
|
||||
|
@ -731,15 +700,9 @@ private:
|
|||
QMap<OverlayID, Overlay::Pointer> _overlaysHUD;
|
||||
QMap<OverlayID, Overlay::Pointer> _overlaysWorld;
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
QMap<OverlayID, OverlayPanel::Pointer> _panels;
|
||||
#endif
|
||||
QList<Overlay::Pointer> _overlaysToDelete;
|
||||
unsigned int _stackOrder { 1 };
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
QScriptEngine* _scriptEngine;
|
||||
#endif
|
||||
bool _enabled = true;
|
||||
|
||||
PointerEvent calculateOverlayPointerEvent(OverlayID overlayID, PickRay ray, RayToOverlayIntersectionResult rayPickResult,
|
||||
|
|
|
@ -65,23 +65,7 @@ namespace render {
|
|||
}
|
||||
template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) {
|
||||
if (args) {
|
||||
if (overlay->getAnchor() == Overlay::MY_AVATAR) {
|
||||
auto batch = args->_batch;
|
||||
auto avatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
glm::quat myAvatarRotation = avatar->getWorldOrientation();
|
||||
glm::vec3 myAvatarPosition = avatar->getWorldPosition();
|
||||
float angle = glm::degrees(glm::angle(myAvatarRotation));
|
||||
glm::vec3 axis = glm::axis(myAvatarRotation);
|
||||
float myAvatarScale = avatar->getModelScale();
|
||||
Transform transform = Transform();
|
||||
transform.setTranslation(myAvatarPosition);
|
||||
transform.setRotation(glm::angleAxis(angle, axis));
|
||||
transform.setScale(myAvatarScale);
|
||||
batch->setModelTransform(transform);
|
||||
overlay->render(args);
|
||||
} else {
|
||||
overlay->render(args);
|
||||
}
|
||||
overlay->render(args);
|
||||
}
|
||||
}
|
||||
template <> const ShapeKey shapeGetShapeKey(const Overlay::Pointer& overlay) {
|
||||
|
|
|
@ -13,18 +13,8 @@
|
|||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "OverlayPanel.h"
|
||||
|
||||
bool PanelAttachable::getParentVisible() const {
|
||||
#if OVERLAY_PANELS
|
||||
if (getParentPanel()) {
|
||||
return getParentPanel()->getVisible() && getParentPanel()->getParentVisible();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// JSDoc for copying to @typedefs of overlay types that inherit PanelAttachable.
|
||||
|
@ -67,15 +57,6 @@ bool PanelAttachable::applyTransformTo(Transform& transform, bool force) {
|
|||
if (force || usecTimestampNow() > _transformExpiry) {
|
||||
const quint64 TRANSFORM_UPDATE_PERIOD = 100000; // frequency is 10 Hz
|
||||
_transformExpiry = usecTimestampNow() + TRANSFORM_UPDATE_PERIOD;
|
||||
#if OVERLAY_PANELS
|
||||
if (getParentPanel()) {
|
||||
getParentPanel()->applyTransformTo(transform, true);
|
||||
transform.postTranslate(getOffsetPosition());
|
||||
transform.postRotate(getOffsetRotation());
|
||||
transform.postScale(getOffsetScale());
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
#ifndef hifi_PanelAttachable_h
|
||||
#define hifi_PanelAttachable_h
|
||||
|
||||
#define OVERLAY_PANELS 0
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
@ -44,18 +42,12 @@ class OverlayPanel;
|
|||
class PanelAttachable {
|
||||
public:
|
||||
// getters
|
||||
#if OVERLAY_PANELS
|
||||
std::shared_ptr<OverlayPanel> getParentPanel() const { return _parentPanel; }
|
||||
#endif
|
||||
glm::vec3 getOffsetPosition() const { return _offset.getTranslation(); }
|
||||
glm::quat getOffsetRotation() const { return _offset.getRotation(); }
|
||||
glm::vec3 getOffsetScale() const { return _offset.getScale(); }
|
||||
bool getParentVisible() const;
|
||||
|
||||
// setters
|
||||
#if OVERLAY_PANELS
|
||||
void setParentPanel(std::shared_ptr<OverlayPanel> panel) { _parentPanel = panel; }
|
||||
#endif
|
||||
void setOffsetPosition(const glm::vec3& position) { _offset.setTranslation(position); }
|
||||
void setOffsetRotation(const glm::quat& rotation) { _offset.setRotation(rotation); }
|
||||
void setOffsetScale(float scale) { _offset.setScale(scale); }
|
||||
|
@ -71,9 +63,6 @@ protected:
|
|||
quint64 _transformExpiry = 0;
|
||||
|
||||
private:
|
||||
#if OVERLAY_PANELS
|
||||
std::shared_ptr<OverlayPanel> _parentPanel = nullptr;
|
||||
#endif
|
||||
Transform _offset;
|
||||
};
|
||||
|
||||
|
|
|
@ -127,8 +127,6 @@ const render::ShapeKey Rectangle3DOverlay::getShapeKey() {
|
|||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
||||
* rotating as you move your avatar.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
|
@ -138,10 +136,8 @@ const render::ShapeKey Rectangle3DOverlay::getShapeKey() {
|
|||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>,
|
||||
* <code>filled</code>, and <code>filed</code>. Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* <strong>Deprecated:</strong> The erroneous property spelling "<code>filed</code>" is deprecated and support for it will
|
||||
* be removed.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>.
|
||||
* @property {boolean} ignoreRayIntersection=false - If <code>true</code>,
|
||||
|
|
|
@ -128,8 +128,6 @@ void Shape3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
||||
* rotating as you move your avatar.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
|
@ -139,10 +137,8 @@ void Shape3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>,
|
||||
* <code>filled</code>, and <code>filed</code>. Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* <strong>Deprecated:</strong> The erroneous property spelling "<code>filed</code>" is deprecated and support for it will
|
||||
* be removed.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>.
|
||||
* @property {boolean} ignoreRayIntersection=false - If <code>true</code>,
|
||||
|
|
|
@ -47,8 +47,6 @@ Sphere3DOverlay::Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay) :
|
|||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
||||
* rotating as you move your avatar.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
|
@ -58,10 +56,8 @@ Sphere3DOverlay::Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay) :
|
|||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>,
|
||||
* <code>filled</code>, and <code>filed</code>. Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* <strong>Deprecated:</strong> The erroneous property spelling "<code>filed</code>" is deprecated and support for it will
|
||||
* be removed.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>.
|
||||
* @property {boolean} ignoreRayIntersection=false - If <code>true</code>,
|
||||
|
|
|
@ -224,8 +224,6 @@ void Text3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
||||
* rotating as you move your avatar.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
|
@ -235,10 +233,8 @@ void Text3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>,
|
||||
* <code>filled</code>, and <code>filed</code>. Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* <strong>Deprecated:</strong> The erroneous property spelling "<code>filed</code>" is deprecated and support for it will
|
||||
* be removed.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>.
|
||||
* @property {boolean} ignoreRayIntersection=false - If <code>true</code>,
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
#include "ui/DomainConnectionModel.h"
|
||||
#include "ui/AvatarInputs.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "scripting/GlobalServicesScriptingInterface.h"
|
||||
#include "scripting/AccountServicesScriptingInterface.h"
|
||||
#include <plugins/InputConfiguration.h>
|
||||
#include "ui/Snapshot.h"
|
||||
#include "SoundCache.h"
|
||||
|
@ -192,7 +192,10 @@ void Web3DOverlay::setupQmlSurface() {
|
|||
|
||||
_webSurface->getSurfaceContext()->setContextProperty("offscreenFlags", flags);
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Account", GlobalServicesScriptingInterface::getInstance());
|
||||
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||
_webSurface->getSurfaceContext()->setContextProperty("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AccountServices", AccountServicesScriptingInterface::getInstance());
|
||||
|
||||
// in Qt 5.10.0 there is already an "Audio" object in the QML context
|
||||
// though I failed to find it (from QtMultimedia??). So.. let it be "AudioScriptingInterface"
|
||||
|
@ -208,7 +211,6 @@ void Web3DOverlay::setupQmlSurface() {
|
|||
_webSurface->getSurfaceContext()->setContextProperty("OctreeStats", DependencyManager::get<OctreeStatsProvider>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("DCModel", DependencyManager::get<DomainConnectionModel>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("InputConfiguration", DependencyManager::get<InputConfiguration>().data());
|
||||
|
@ -222,10 +224,6 @@ void Web3DOverlay::setupQmlSurface() {
|
|||
|
||||
_webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../");
|
||||
|
||||
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data());
|
||||
// mark the TabletProxy object as cpp ownership.
|
||||
QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");
|
||||
_webSurface->getSurfaceContext()->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership);
|
||||
// Override min fps for tablet UI, for silky smooth scrolling
|
||||
setMaxFPS(90);
|
||||
}
|
||||
|
@ -486,8 +484,6 @@ void Web3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* @property {string} anchor="" - If set to <code>"MyAvatar"</code> then the overlay is attached to your avatar, moving and
|
||||
* rotating as you move your avatar.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
|
@ -497,10 +493,8 @@ void Web3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>,
|
||||
* <code>filled</code>, and <code>filed</code>. Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* <strong>Deprecated:</strong> The erroneous property spelling "<code>filed</code>" is deprecated and support for it will
|
||||
* be removed.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>.
|
||||
* @property {boolean} ignoreRayIntersection=false - If <code>true</code>,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
set(TARGET_NAME animation)
|
||||
setup_hifi_library(Network Script)
|
||||
link_hifi_libraries(shared model fbx)
|
||||
link_hifi_libraries(shared graphics fbx)
|
||||
include_hifi_library_headers(networking)
|
||||
include_hifi_library_headers(gpu)
|
||||
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
#include "AnimationLogging.h"
|
||||
#include "AnimUtil.h"
|
||||
|
||||
bool AnimClip::usePreAndPostPoseFromAnim = true;
|
||||
|
||||
AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag) :
|
||||
AnimNode(AnimNode::Type::Clip, id),
|
||||
_startFrame(startFrame),
|
||||
|
@ -138,14 +136,8 @@ void AnimClip::copyFromNetworkAnim() {
|
|||
if (skeletonJoint >= 0 && skeletonJoint < skeletonJointCount) {
|
||||
|
||||
AnimPose preRot, postRot;
|
||||
if (usePreAndPostPoseFromAnim) {
|
||||
preRot = animSkeleton.getPreRotationPose(animJoint);
|
||||
postRot = animSkeleton.getPostRotationPose(animJoint);
|
||||
} else {
|
||||
// In order to support Blender, which does not have preRotation FBX support, we use the models defaultPose as the reference frame for the animations.
|
||||
preRot = AnimPose(glm::vec3(1.0f), _skeleton->getRelativeBindPose(skeletonJoint).rot(), glm::vec3());
|
||||
postRot = AnimPose::identity;
|
||||
}
|
||||
preRot = animSkeleton.getPreRotationPose(animJoint);
|
||||
postRot = animSkeleton.getPostRotationPose(animJoint);
|
||||
|
||||
// cancel out scale
|
||||
preRot.scale() = glm::vec3(1.0f);
|
||||
|
|
|
@ -25,8 +25,6 @@ class AnimClip : public AnimNode {
|
|||
public:
|
||||
friend class AnimTests;
|
||||
|
||||
static bool usePreAndPostPoseFromAnim;
|
||||
|
||||
AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag);
|
||||
virtual ~AnimClip() override;
|
||||
|
||||
|
|
|
@ -591,19 +591,31 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const
|
|||
glm::vec3 d = basePose.trans() - topPose.trans();
|
||||
float dLen = glm::length(d);
|
||||
if (dLen > EPSILON) {
|
||||
|
||||
glm::vec3 dUnit = d / dLen;
|
||||
glm::vec3 e = midPose.xformVector(target.getPoleReferenceVector());
|
||||
|
||||
// if mid joint is straight use the reference vector to compute eProj, otherwise use reference vector.
|
||||
// however if mid joint angle is in between the two blend between both solutions.
|
||||
vec3 u = normalize(basePose.trans() - midPose.trans());
|
||||
vec3 v = normalize(topPose.trans() - midPose.trans());
|
||||
|
||||
const float LERP_THRESHOLD = 3.05433f; // 175 deg
|
||||
const float BENT_THRESHOLD = 2.96706f; // 170 deg
|
||||
|
||||
float jointAngle = acos(dot(u, v));
|
||||
if (jointAngle < BENT_THRESHOLD) {
|
||||
glm::vec3 midPoint = topPose.trans() + d * 0.5f;
|
||||
e = normalize(midPose.trans() - midPoint);
|
||||
} else if (jointAngle < LERP_THRESHOLD) {
|
||||
glm::vec3 midPoint = topPose.trans() + d * 0.5f;
|
||||
float alpha = (jointAngle - LERP_THRESHOLD) / (BENT_THRESHOLD - LERP_THRESHOLD);
|
||||
e = lerp(e, normalize(midPose.trans() - midPoint), alpha);
|
||||
}
|
||||
|
||||
glm::vec3 eProj = e - glm::dot(e, dUnit) * dUnit;
|
||||
float eProjLen = glm::length(eProj);
|
||||
|
||||
const float MIN_EPROJ_LEN = 0.5f;
|
||||
if (eProjLen < MIN_EPROJ_LEN) {
|
||||
glm::vec3 midPoint = topPose.trans() + d * 0.5f;
|
||||
e = midPose.trans() - midPoint;
|
||||
eProj = e - glm::dot(e, dUnit) * dUnit;
|
||||
eProjLen = glm::length(eProj);
|
||||
}
|
||||
|
||||
glm::vec3 p = target.getPoleVector();
|
||||
glm::vec3 pProj = p - glm::dot(p, dUnit) * dUnit;
|
||||
float pProjLen = glm::length(pProj);
|
||||
|
@ -634,16 +646,27 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const
|
|||
|
||||
AnimPose geomToWorldPose = AnimPose(context.getRigToWorldMatrix() * context.getGeometryToRigMatrix());
|
||||
|
||||
glm::vec3 dUnit = d / dLen;
|
||||
glm::vec3 e = midPose.xformVector(target.getPoleReferenceVector());
|
||||
glm::vec3 eProj = e - glm::dot(e, dUnit) * dUnit;
|
||||
float eProjLen = glm::length(eProj);
|
||||
const float MIN_EPROJ_LEN = 0.5f;
|
||||
if (eProjLen < MIN_EPROJ_LEN) {
|
||||
|
||||
// if mid joint is straight use the reference vector to compute eProj, otherwise use reference vector.
|
||||
// however if mid joint angle is in between the two blend between both solutions.
|
||||
vec3 u = normalize(basePose.trans() - midPose.trans());
|
||||
vec3 v = normalize(topPose.trans() - midPose.trans());
|
||||
|
||||
const float LERP_THRESHOLD = 3.05433f; // 175 deg
|
||||
const float BENT_THRESHOLD = 2.96706f; // 170 deg
|
||||
|
||||
float jointAngle = acos(dot(u, v));
|
||||
glm::vec4 eColor = RED;
|
||||
if (jointAngle < BENT_THRESHOLD) {
|
||||
glm::vec3 midPoint = topPose.trans() + d * 0.5f;
|
||||
e = midPose.trans() - midPoint;
|
||||
eProj = e - glm::dot(e, dUnit) * dUnit;
|
||||
eProjLen = glm::length(eProj);
|
||||
e = normalize(midPose.trans() - midPoint);
|
||||
eColor = GREEN;
|
||||
} else if (jointAngle < LERP_THRESHOLD) {
|
||||
glm::vec3 midPoint = topPose.trans() + d * 0.5f;
|
||||
float alpha = (jointAngle - LERP_THRESHOLD) / (BENT_THRESHOLD - LERP_THRESHOLD);
|
||||
e = lerp(e, normalize(midPose.trans() - midPoint), alpha);
|
||||
eColor = YELLOW;
|
||||
}
|
||||
|
||||
glm::vec3 p = target.getPoleVector();
|
||||
|
@ -655,7 +678,7 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const
|
|||
YELLOW);
|
||||
DebugDraw::getInstance().drawRay(geomToWorldPose.xformPoint(midPoint),
|
||||
geomToWorldPose.xformPoint(midPoint + PROJ_VECTOR_LEN * glm::normalize(e)),
|
||||
RED);
|
||||
eColor);
|
||||
DebugDraw::getInstance().drawRay(geomToWorldPose.xformPoint(midPoint),
|
||||
geomToWorldPose.xformPoint(midPoint + POLE_VECTOR_LEN * glm::normalize(p)),
|
||||
BLUE);
|
||||
|
@ -1232,7 +1255,7 @@ void AnimInverseKinematics::initConstraints() {
|
|||
// / /
|
||||
// O--O O--O
|
||||
|
||||
loadDefaultPoses(_skeleton->getRelativeBindPoses());
|
||||
loadDefaultPoses(_skeleton->getRelativeDefaultPoses());
|
||||
|
||||
int numJoints = (int)_defaultRelativePoses.size();
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ AnimManipulator::~AnimManipulator() {
|
|||
}
|
||||
|
||||
const AnimPoseVec& AnimManipulator::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) {
|
||||
return overlay(animVars, context, dt, triggersOut, _skeleton->getRelativeBindPoses());
|
||||
return overlay(animVars, context, dt, triggersOut, _skeleton->getRelativeDefaultPoses());
|
||||
}
|
||||
|
||||
const AnimPoseVec& AnimManipulator::overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) {
|
||||
|
|
|
@ -76,3 +76,5 @@ AnimPose::operator glm::mat4() const {
|
|||
return glm::mat4(glm::vec4(xAxis, 0.0f), glm::vec4(yAxis, 0.0f),
|
||||
glm::vec4(zAxis, 0.0f), glm::vec4(_trans, 1.0f));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -56,14 +56,6 @@ int AnimSkeleton::getChainDepth(int jointIndex) const {
|
|||
}
|
||||
}
|
||||
|
||||
const AnimPose& AnimSkeleton::getAbsoluteBindPose(int jointIndex) const {
|
||||
return _absoluteBindPoses[jointIndex];
|
||||
}
|
||||
|
||||
const AnimPose& AnimSkeleton::getRelativeBindPose(int jointIndex) const {
|
||||
return _relativeBindPoses[jointIndex];
|
||||
}
|
||||
|
||||
const AnimPose& AnimSkeleton::getRelativeDefaultPose(int jointIndex) const {
|
||||
return _relativeDefaultPoses[jointIndex];
|
||||
}
|
||||
|
@ -164,8 +156,6 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints)
|
|||
_joints = joints;
|
||||
_jointsSize = (int)joints.size();
|
||||
// build a cache of bind poses
|
||||
_absoluteBindPoses.reserve(_jointsSize);
|
||||
_relativeBindPoses.reserve(_jointsSize);
|
||||
|
||||
// build a chache of default poses
|
||||
_absoluteDefaultPoses.reserve(_jointsSize);
|
||||
|
@ -192,28 +182,6 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints)
|
|||
} else {
|
||||
_absoluteDefaultPoses.push_back(relDefaultPose);
|
||||
}
|
||||
|
||||
// build relative and absolute bind poses
|
||||
if (_joints[i].bindTransformFoundInCluster) {
|
||||
// Use the FBXJoint::bindTransform, which is absolute model coordinates
|
||||
// i.e. not relative to it's parent.
|
||||
AnimPose absoluteBindPose(_joints[i].bindTransform);
|
||||
_absoluteBindPoses.push_back(absoluteBindPose);
|
||||
if (parentIndex >= 0) {
|
||||
AnimPose inverseParentAbsoluteBindPose = _absoluteBindPoses[parentIndex].inverse();
|
||||
_relativeBindPoses.push_back(inverseParentAbsoluteBindPose * absoluteBindPose);
|
||||
} else {
|
||||
_relativeBindPoses.push_back(absoluteBindPose);
|
||||
}
|
||||
} else {
|
||||
// use default transform instead
|
||||
_relativeBindPoses.push_back(relDefaultPose);
|
||||
if (parentIndex >= 0) {
|
||||
_absoluteBindPoses.push_back(_absoluteBindPoses[parentIndex] * relDefaultPose);
|
||||
} else {
|
||||
_absoluteBindPoses.push_back(relDefaultPose);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _jointsSize; i++) {
|
||||
|
@ -251,8 +219,6 @@ void AnimSkeleton::dump(bool verbose) const {
|
|||
qCDebug(animation) << " {";
|
||||
qCDebug(animation) << " index =" << i;
|
||||
qCDebug(animation) << " name =" << getJointName(i);
|
||||
qCDebug(animation) << " absBindPose =" << getAbsoluteBindPose(i);
|
||||
qCDebug(animation) << " relBindPose =" << getRelativeBindPose(i);
|
||||
qCDebug(animation) << " absDefaultPose =" << getAbsoluteDefaultPose(i);
|
||||
qCDebug(animation) << " relDefaultPose =" << getRelativeDefaultPose(i);
|
||||
if (verbose) {
|
||||
|
@ -287,8 +253,6 @@ void AnimSkeleton::dump(const AnimPoseVec& poses) const {
|
|||
qCDebug(animation) << " {";
|
||||
qCDebug(animation) << " index =" << i;
|
||||
qCDebug(animation) << " name =" << getJointName(i);
|
||||
qCDebug(animation) << " absBindPose =" << getAbsoluteBindPose(i);
|
||||
qCDebug(animation) << " relBindPose =" << getRelativeBindPose(i);
|
||||
qCDebug(animation) << " absDefaultPose =" << getAbsoluteDefaultPose(i);
|
||||
qCDebug(animation) << " relDefaultPose =" << getRelativeDefaultPose(i);
|
||||
qCDebug(animation) << " pose =" << poses[i];
|
||||
|
|
|
@ -30,13 +30,6 @@ public:
|
|||
int getNumJoints() const;
|
||||
int getChainDepth(int jointIndex) const;
|
||||
|
||||
// absolute pose, not relative to parent
|
||||
const AnimPose& getAbsoluteBindPose(int jointIndex) const;
|
||||
|
||||
// relative to parent pose
|
||||
const AnimPose& getRelativeBindPose(int jointIndex) const;
|
||||
const AnimPoseVec& getRelativeBindPoses() const { return _relativeBindPoses; }
|
||||
|
||||
// the default poses are the orientations of the joints on frame 0.
|
||||
const AnimPose& getRelativeDefaultPose(int jointIndex) const;
|
||||
const AnimPoseVec& getRelativeDefaultPoses() const { return _relativeDefaultPoses; }
|
||||
|
@ -72,8 +65,6 @@ protected:
|
|||
|
||||
std::vector<FBXJoint> _joints;
|
||||
int _jointsSize { 0 };
|
||||
AnimPoseVec _absoluteBindPoses;
|
||||
AnimPoseVec _relativeBindPoses;
|
||||
AnimPoseVec _relativeDefaultPoses;
|
||||
AnimPoseVec _absoluteDefaultPoses;
|
||||
AnimPoseVec _relativePreRotationPoses;
|
||||
|
|
|
@ -179,7 +179,7 @@ void Rig::restoreRoleAnimation(const QString& role) {
|
|||
} else {
|
||||
qCWarning(animation) << "Rig::restoreRoleAnimation could not find role " << role;
|
||||
}
|
||||
|
||||
|
||||
auto statesIter = _roleAnimStates.find(role);
|
||||
if (statesIter != _roleAnimStates.end()) {
|
||||
_roleAnimStates.erase(statesIter);
|
||||
|
@ -1050,52 +1050,6 @@ void Rig::updateAnimations(float deltaTime, const glm::mat4& rootTransform, cons
|
|||
}
|
||||
}
|
||||
|
||||
void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::quat& targetRotation, float priority,
|
||||
const QVector<int>& freeLineage, glm::mat4 rootTransform) {
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
bool Rig::restoreJointPosition(int jointIndex, float fraction, float priority, const QVector<int>& freeLineage) {
|
||||
ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
float Rig::getLimbLength(int jointIndex, const QVector<int>& freeLineage,
|
||||
const glm::vec3 scale, const QVector<FBXJoint>& fbxJoints) const {
|
||||
ASSERT(false);
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
glm::quat Rig::setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority) {
|
||||
ASSERT(false);
|
||||
return glm::quat();
|
||||
}
|
||||
|
||||
glm::vec3 Rig::getJointDefaultTranslationInConstrainedFrame(int jointIndex) {
|
||||
ASSERT(false);
|
||||
return glm::vec3();
|
||||
}
|
||||
|
||||
glm::quat Rig::setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation, float priority, float mix) {
|
||||
ASSERT(false);
|
||||
return glm::quat();
|
||||
}
|
||||
|
||||
bool Rig::getJointRotationInConstrainedFrame(int jointIndex, glm::quat& quatOut) const {
|
||||
ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
void Rig::clearJointStatePriorities() {
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) {
|
||||
ASSERT(false);
|
||||
return glm::quat();
|
||||
}
|
||||
|
||||
|
||||
void Rig::updateFromEyeParameters(const EyeParameters& params) {
|
||||
updateEyeJoint(params.leftEyeJointIndex, params.modelTranslation, params.modelRotation, params.eyeLookAt, params.eyeSaccade);
|
||||
updateEyeJoint(params.rightEyeJointIndex, params.modelTranslation, params.modelRotation, params.eyeLookAt, params.eyeSaccade);
|
||||
|
@ -1265,7 +1219,8 @@ glm::vec3 Rig::deflectHandFromTorso(const glm::vec3& handPosition, const FBXJoin
|
|||
return position;
|
||||
}
|
||||
|
||||
void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool leftArmEnabled, bool rightArmEnabled, float dt,
|
||||
void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated,
|
||||
bool leftArmEnabled, bool rightArmEnabled, float dt,
|
||||
const AnimPose& leftHandPose, const AnimPose& rightHandPose,
|
||||
const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo,
|
||||
const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo) {
|
||||
|
@ -1279,7 +1234,7 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
|
|||
glm::vec3 handPosition = leftHandPose.trans();
|
||||
glm::quat handRotation = leftHandPose.rot();
|
||||
|
||||
if (!hipsEnabled) {
|
||||
if (!hipsEnabled || hipsEstimated) {
|
||||
// prevent the hand IK targets from intersecting the torso
|
||||
handPosition = deflectHandFromTorso(handPosition, hipsShapeInfo, spineShapeInfo, spine1ShapeInfo, spine2ShapeInfo);
|
||||
}
|
||||
|
@ -1326,7 +1281,7 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
|
|||
glm::vec3 handPosition = rightHandPose.trans();
|
||||
glm::quat handRotation = rightHandPose.rot();
|
||||
|
||||
if (!hipsEnabled) {
|
||||
if (!hipsEnabled || hipsEstimated) {
|
||||
// prevent the hand IK targets from intersecting the torso
|
||||
handPosition = deflectHandFromTorso(handPosition, hipsShapeInfo, spineShapeInfo, spine1ShapeInfo, spine2ShapeInfo);
|
||||
}
|
||||
|
@ -1550,20 +1505,20 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo
|
|||
_animVars.set("isTalking", params.isTalking);
|
||||
_animVars.set("notIsTalking", !params.isTalking);
|
||||
|
||||
bool headEnabled = params.primaryControllerActiveFlags[PrimaryControllerType_Head];
|
||||
bool leftHandEnabled = params.primaryControllerActiveFlags[PrimaryControllerType_LeftHand];
|
||||
bool rightHandEnabled = params.primaryControllerActiveFlags[PrimaryControllerType_RightHand];
|
||||
bool hipsEnabled = params.primaryControllerActiveFlags[PrimaryControllerType_Hips];
|
||||
bool leftFootEnabled = params.primaryControllerActiveFlags[PrimaryControllerType_LeftFoot];
|
||||
bool rightFootEnabled = params.primaryControllerActiveFlags[PrimaryControllerType_RightFoot];
|
||||
bool spine2Enabled = params.primaryControllerActiveFlags[PrimaryControllerType_Spine2];
|
||||
|
||||
bool leftArmEnabled = params.secondaryControllerActiveFlags[SecondaryControllerType_LeftArm];
|
||||
bool rightArmEnabled = params.secondaryControllerActiveFlags[SecondaryControllerType_RightArm];
|
||||
bool headEnabled = params.primaryControllerFlags[PrimaryControllerType_Head] & (uint8_t)ControllerFlags::Enabled;
|
||||
bool leftHandEnabled = params.primaryControllerFlags[PrimaryControllerType_LeftHand] & (uint8_t)ControllerFlags::Enabled;
|
||||
bool rightHandEnabled = params.primaryControllerFlags[PrimaryControllerType_RightHand] & (uint8_t)ControllerFlags::Enabled;
|
||||
bool hipsEnabled = params.primaryControllerFlags[PrimaryControllerType_Hips] & (uint8_t)ControllerFlags::Enabled;
|
||||
bool hipsEstimated = params.primaryControllerFlags[PrimaryControllerType_Hips] & (uint8_t)ControllerFlags::Estimated;
|
||||
bool leftFootEnabled = params.primaryControllerFlags[PrimaryControllerType_LeftFoot] & (uint8_t)ControllerFlags::Enabled;
|
||||
bool rightFootEnabled = params.primaryControllerFlags[PrimaryControllerType_RightFoot] & (uint8_t)ControllerFlags::Enabled;
|
||||
bool spine2Enabled = params.primaryControllerFlags[PrimaryControllerType_Spine2] & (uint8_t)ControllerFlags::Enabled;
|
||||
bool leftArmEnabled = params.secondaryControllerFlags[SecondaryControllerType_LeftArm] & (uint8_t)ControllerFlags::Enabled;
|
||||
bool rightArmEnabled = params.secondaryControllerFlags[SecondaryControllerType_RightArm] & (uint8_t)ControllerFlags::Enabled;
|
||||
|
||||
updateHead(headEnabled, hipsEnabled, params.primaryControllerPoses[PrimaryControllerType_Head]);
|
||||
|
||||
updateHands(leftHandEnabled, rightHandEnabled, hipsEnabled, leftArmEnabled, rightArmEnabled, dt,
|
||||
updateHands(leftHandEnabled, rightHandEnabled, hipsEnabled, hipsEstimated, leftArmEnabled, rightArmEnabled, dt,
|
||||
params.primaryControllerPoses[PrimaryControllerType_LeftHand], params.primaryControllerPoses[PrimaryControllerType_RightHand],
|
||||
params.hipsShapeInfo, params.spineShapeInfo, params.spine1ShapeInfo, params.spine2ShapeInfo);
|
||||
|
||||
|
@ -1623,7 +1578,7 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo
|
|||
for (int i = 0; i < (int)NumSecondaryControllerTypes; i++) {
|
||||
int index = indexOfJoint(secondaryControllerJointNames[i]);
|
||||
if (index >= 0) {
|
||||
if (params.secondaryControllerActiveFlags[i]) {
|
||||
if (params.secondaryControllerFlags[i] & (uint8_t)ControllerFlags::Enabled) {
|
||||
ikNode->setSecondaryTargetInRigFrame(index, params.secondaryControllerPoses[i]);
|
||||
} else {
|
||||
ikNode->clearSecondaryTarget(index);
|
||||
|
@ -1731,6 +1686,14 @@ glm::mat4 Rig::getJointTransform(int jointIndex) const {
|
|||
}
|
||||
}
|
||||
|
||||
AnimPose Rig::getJointPose(int jointIndex) const {
|
||||
if (isIndexValid(jointIndex)) {
|
||||
return _internalPoseSet._absolutePoses[jointIndex];
|
||||
} else {
|
||||
return AnimPose::identity;
|
||||
}
|
||||
}
|
||||
|
||||
void Rig::copyJointsIntoJointData(QVector<JointData>& jointDataVec) const {
|
||||
|
||||
const AnimPose geometryToRigPose(_geometryToRigTransform);
|
||||
|
|
|
@ -69,11 +69,16 @@ public:
|
|||
NumSecondaryControllerTypes
|
||||
};
|
||||
|
||||
enum class ControllerFlags : uint8_t {
|
||||
Enabled = 0x01,
|
||||
Estimated = 0x02
|
||||
};
|
||||
|
||||
struct ControllerParameters {
|
||||
AnimPose primaryControllerPoses[NumPrimaryControllerTypes]; // rig space
|
||||
bool primaryControllerActiveFlags[NumPrimaryControllerTypes];
|
||||
uint8_t primaryControllerFlags[NumPrimaryControllerTypes];
|
||||
AnimPose secondaryControllerPoses[NumSecondaryControllerTypes]; // rig space
|
||||
bool secondaryControllerActiveFlags[NumSecondaryControllerTypes];
|
||||
uint8_t secondaryControllerFlags[NumSecondaryControllerTypes];
|
||||
bool isTalking;
|
||||
FBXJointShapeInfo hipsShapeInfo;
|
||||
FBXJointShapeInfo spineShapeInfo;
|
||||
|
@ -159,6 +164,7 @@ public:
|
|||
|
||||
// rig space
|
||||
glm::mat4 getJointTransform(int jointIndex) const;
|
||||
AnimPose getJointPose(int jointIndex) const;
|
||||
|
||||
// Start or stop animations as needed.
|
||||
void computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation, CharacterControllerState ccState);
|
||||
|
@ -166,36 +172,6 @@ public:
|
|||
// Regardless of who started the animations or how many, update the joints.
|
||||
void updateAnimations(float deltaTime, const glm::mat4& rootTransform, const glm::mat4& rigToWorldTransform);
|
||||
|
||||
// legacy
|
||||
void inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::quat& targetRotation, float priority,
|
||||
const QVector<int>& freeLineage, glm::mat4 rootTransform);
|
||||
|
||||
// legacy
|
||||
bool restoreJointPosition(int jointIndex, float fraction, float priority, const QVector<int>& freeLineage);
|
||||
|
||||
// legacy
|
||||
float getLimbLength(int jointIndex, const QVector<int>& freeLineage,
|
||||
const glm::vec3 scale, const QVector<FBXJoint>& fbxJoints) const;
|
||||
|
||||
// legacy
|
||||
glm::quat setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority);
|
||||
|
||||
// legacy
|
||||
glm::vec3 getJointDefaultTranslationInConstrainedFrame(int jointIndex);
|
||||
|
||||
// legacy
|
||||
glm::quat setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation,
|
||||
float priority, float mix = 1.0f);
|
||||
|
||||
// legacy
|
||||
bool getJointRotationInConstrainedFrame(int jointIndex, glm::quat& rotOut) const;
|
||||
|
||||
// legacy
|
||||
glm::quat getJointDefaultRotationInParentFrame(int jointIndex);
|
||||
|
||||
// legacy
|
||||
void clearJointStatePriorities();
|
||||
|
||||
void updateFromControllerParameters(const ControllerParameters& params, float dt);
|
||||
void updateFromEyeParameters(const EyeParameters& params);
|
||||
|
||||
|
@ -251,7 +227,8 @@ protected:
|
|||
void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut);
|
||||
|
||||
void updateHead(bool headEnabled, bool hipsEnabled, const AnimPose& headMatrix);
|
||||
void updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool leftArmEnabled, bool rightArmEnabled, float dt,
|
||||
void updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated,
|
||||
bool leftArmEnabled, bool rightArmEnabled, float dt,
|
||||
const AnimPose& leftHandPose, const AnimPose& rightHandPose,
|
||||
const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo,
|
||||
const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo);
|
||||
|
@ -338,7 +315,7 @@ protected:
|
|||
float firstFrame;
|
||||
float lastFrame;
|
||||
};
|
||||
|
||||
|
||||
struct RoleAnimState {
|
||||
RoleAnimState() {}
|
||||
RoleAnimState(const QString& roleId, const QString& urlIn, float fpsIn, bool loopIn, float firstFrameIn, float lastFrameIn) :
|
||||
|
|
|
@ -782,7 +782,7 @@ void AudioClient::selectAudioFormat(const QString& selectedCodecName) {
|
|||
|
||||
_selectedCodecName = selectedCodecName;
|
||||
|
||||
qCDebug(audioclient) << "Selected Codec:" << _selectedCodecName;
|
||||
qCDebug(audioclient) << "Selected Codec:" << _selectedCodecName << "isStereoInput:" << _isStereoInput;
|
||||
|
||||
// release any old codec encoder/decoder first...
|
||||
if (_codec && _encoder) {
|
||||
|
@ -797,7 +797,7 @@ void AudioClient::selectAudioFormat(const QString& selectedCodecName) {
|
|||
if (_selectedCodecName == plugin->getName()) {
|
||||
_codec = plugin;
|
||||
_receivedAudioStream.setupCodec(plugin, _selectedCodecName, AudioConstants::STEREO);
|
||||
_encoder = plugin->createEncoder(AudioConstants::SAMPLE_RATE, AudioConstants::MONO);
|
||||
_encoder = plugin->createEncoder(AudioConstants::SAMPLE_RATE, _isStereoInput ? AudioConstants::STEREO : AudioConstants::MONO);
|
||||
qCDebug(audioclient) << "Selected Codec Plugin:" << _codec.get();
|
||||
break;
|
||||
}
|
||||
|
@ -1079,7 +1079,7 @@ void AudioClient::handleAudioInput(QByteArray& audioBuffer) {
|
|||
encodedBuffer = audioBuffer;
|
||||
}
|
||||
|
||||
emitAudioPacket(encodedBuffer.data(), encodedBuffer.size(), _outgoingAvatarAudioSequenceNumber,
|
||||
emitAudioPacket(encodedBuffer.data(), encodedBuffer.size(), _outgoingAvatarAudioSequenceNumber, _isStereoInput,
|
||||
audioTransform, avatarBoundingBoxCorner, avatarBoundingBoxScale,
|
||||
packetType, _selectedCodecName);
|
||||
_stats.sentPacket();
|
||||
|
@ -1382,7 +1382,16 @@ void AudioClient::setIsStereoInput(bool isStereoInput) {
|
|||
_desiredInputFormat.setChannelCount(1);
|
||||
}
|
||||
|
||||
// change in channel count for desired input format, restart the input device
|
||||
// restart the codec
|
||||
if (_codec) {
|
||||
if (_encoder) {
|
||||
_codec->releaseEncoder(_encoder);
|
||||
}
|
||||
_encoder = _codec->createEncoder(AudioConstants::SAMPLE_RATE, _isStereoInput ? AudioConstants::STEREO : AudioConstants::MONO);
|
||||
}
|
||||
qCDebug(audioclient) << "Reset Codec:" << _selectedCodecName << "isStereoInput:" << _isStereoInput;
|
||||
|
||||
// restart the input device
|
||||
switchInputToAudioDevice(_inputDeviceInfo);
|
||||
}
|
||||
}
|
||||
|
@ -1418,7 +1427,7 @@ void AudioClient::outputFormatChanged() {
|
|||
_receivedAudioStream.outputFormatChanged(_outputFormat.sampleRate(), OUTPUT_CHANNEL_COUNT);
|
||||
}
|
||||
|
||||
bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo, bool isShutdownRequest) {
|
||||
bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest) {
|
||||
qCDebug(audioclient) << __FUNCTION__ << "inputDeviceInfo: [" << inputDeviceInfo.deviceName() << "]";
|
||||
bool supportedFormat = false;
|
||||
|
||||
|
@ -1601,7 +1610,7 @@ void AudioClient::outputNotify() {
|
|||
}
|
||||
}
|
||||
|
||||
bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo, bool isShutdownRequest) {
|
||||
bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest) {
|
||||
qCDebug(audioclient) << "AudioClient::switchOutputToAudioDevice() outputDeviceInfo: [" << outputDeviceInfo.deviceName() << "]";
|
||||
bool supportedFormat = false;
|
||||
|
||||
|
|
|
@ -378,8 +378,8 @@ private:
|
|||
|
||||
void handleLocalEchoAndReverb(QByteArray& inputByteArray);
|
||||
|
||||
bool switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo, bool isShutdownRequest = false);
|
||||
bool switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo, bool isShutdownRequest = false);
|
||||
bool switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest = false);
|
||||
bool switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest = false);
|
||||
|
||||
// Callback acceleration dependent calculations
|
||||
int calculateNumberOfInputCallbackBytes(const QAudioFormat& format) const;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "AudioConstants.h"
|
||||
|
||||
void AbstractAudioInterface::emitAudioPacket(const void* audioData, size_t bytes, quint16& sequenceNumber,
|
||||
void AbstractAudioInterface::emitAudioPacket(const void* audioData, size_t bytes, quint16& sequenceNumber, bool isStereo,
|
||||
const Transform& transform, glm::vec3 avatarBoundingBoxCorner, glm::vec3 avatarBoundingBoxScale,
|
||||
PacketType packetType, QString codecName) {
|
||||
static std::mutex _mutex;
|
||||
|
@ -30,9 +30,6 @@ void AbstractAudioInterface::emitAudioPacket(const void* audioData, size_t bytes
|
|||
Locker lock(_mutex);
|
||||
auto audioPacket = NLPacket::create(packetType);
|
||||
|
||||
// FIXME - this is not a good way to determine stereoness with codecs....
|
||||
quint8 isStereo = bytes == AudioConstants::NETWORK_FRAME_BYTES_STEREO ? 1 : 0;
|
||||
|
||||
// write sequence number
|
||||
auto sequence = sequenceNumber++;
|
||||
audioPacket->writePrimitive(sequence);
|
||||
|
@ -48,7 +45,8 @@ void AbstractAudioInterface::emitAudioPacket(const void* audioData, size_t bytes
|
|||
audioPacket->writePrimitive(numSilentSamples);
|
||||
} else {
|
||||
// set the mono/stereo byte
|
||||
audioPacket->writePrimitive(isStereo);
|
||||
quint8 channelFlag = isStereo ? 1 : 0;
|
||||
audioPacket->writePrimitive(channelFlag);
|
||||
}
|
||||
|
||||
// pack the three float positions
|
||||
|
|
|
@ -29,7 +29,7 @@ class AbstractAudioInterface : public QObject {
|
|||
public:
|
||||
AbstractAudioInterface(QObject* parent = 0) : QObject(parent) {};
|
||||
|
||||
static void emitAudioPacket(const void* audioData, size_t bytes, quint16& sequenceNumber,
|
||||
static void emitAudioPacket(const void* audioData, size_t bytes, quint16& sequenceNumber, bool isStereo,
|
||||
const Transform& transform, glm::vec3 avatarBoundingBoxCorner, glm::vec3 avatarBoundingBoxScale,
|
||||
PacketType packetType, QString codecName = QString(""));
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
set(TARGET_NAME avatars-renderer)
|
||||
AUTOSCRIBE_SHADER_LIB(gpu model render render-utils)
|
||||
AUTOSCRIBE_SHADER_LIB(gpu graphics render render-utils)
|
||||
setup_hifi_library(Widgets Network Script)
|
||||
link_hifi_libraries(shared gpu model animation model-networking script-engine render render-utils image trackers entities-renderer)
|
||||
link_hifi_libraries(shared gpu graphics animation model-networking script-engine render render-utils image trackers entities-renderer)
|
||||
include_hifi_library_headers(avatars)
|
||||
include_hifi_library_headers(networking)
|
||||
include_hifi_library_headers(fbx)
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <shared/Camera.h>
|
||||
#include <SoftAttachmentModel.h>
|
||||
#include <render/TransitionStage.h>
|
||||
#include "ModelEntityItem.h"
|
||||
#include "RenderableModelEntityItem.h"
|
||||
|
||||
#include "Logging.h"
|
||||
|
||||
|
@ -326,13 +328,15 @@ void Avatar::updateAvatarEntities() {
|
|||
AvatarEntityIDs recentlyDettachedAvatarEntities = getAndClearRecentlyDetachedIDs();
|
||||
if (!recentlyDettachedAvatarEntities.empty()) {
|
||||
// only lock this thread when absolutely necessary
|
||||
AvatarEntityMap avatarEntityData;
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
foreach (auto entityID, recentlyDettachedAvatarEntities) {
|
||||
if (!_avatarEntityData.contains(entityID)) {
|
||||
entityTree->deleteEntity(entityID, true, true);
|
||||
}
|
||||
}
|
||||
avatarEntityData = _avatarEntityData;
|
||||
});
|
||||
foreach (auto entityID, recentlyDettachedAvatarEntities) {
|
||||
if (!avatarEntityData.contains(entityID)) {
|
||||
entityTree->deleteEntity(entityID, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
// remove stale data hashes
|
||||
foreach (auto entityID, recentlyDettachedAvatarEntities) {
|
||||
|
@ -347,6 +351,65 @@ void Avatar::updateAvatarEntities() {
|
|||
setAvatarEntityDataChanged(false);
|
||||
}
|
||||
|
||||
void Avatar::relayJointDataToChildren() {
|
||||
forEachChild([&](SpatiallyNestablePointer child) {
|
||||
if (child->getNestableType() == NestableType::Entity) {
|
||||
auto modelEntity = std::dynamic_pointer_cast<RenderableModelEntityItem>(child);
|
||||
if (modelEntity) {
|
||||
if (modelEntity->getRelayParentJoints()) {
|
||||
if (!modelEntity->getJointMapCompleted() || _reconstructSoftEntitiesJointMap) {
|
||||
QStringList modelJointNames = modelEntity->getJointNames();
|
||||
int numJoints = modelJointNames.count();
|
||||
std::vector<int> map;
|
||||
map.reserve(numJoints);
|
||||
for (int jointIndex = 0; jointIndex < numJoints; jointIndex++) {
|
||||
QString jointName = modelJointNames.at(jointIndex);
|
||||
int avatarJointIndex = getJointIndex(jointName);
|
||||
glm::quat jointRotation;
|
||||
glm::vec3 jointTranslation;
|
||||
if (avatarJointIndex < 0) {
|
||||
jointRotation = modelEntity->getAbsoluteJointRotationInObjectFrame(jointIndex);
|
||||
jointTranslation = modelEntity->getAbsoluteJointTranslationInObjectFrame(jointIndex);
|
||||
map.push_back(-1);
|
||||
} else {
|
||||
int jointIndex = getJointIndex(jointName);
|
||||
jointRotation = getJointRotation(jointIndex);
|
||||
jointTranslation = getJointTranslation(jointIndex);
|
||||
map.push_back(avatarJointIndex);
|
||||
}
|
||||
modelEntity->setLocalJointRotation(jointIndex, jointRotation);
|
||||
modelEntity->setLocalJointTranslation(jointIndex, jointTranslation);
|
||||
}
|
||||
modelEntity->setJointMap(map);
|
||||
} else {
|
||||
QStringList modelJointNames = modelEntity->getJointNames();
|
||||
int numJoints = modelJointNames.count();
|
||||
for (int jointIndex = 0; jointIndex < numJoints; jointIndex++) {
|
||||
int avatarJointIndex = modelEntity->avatarJointIndex(jointIndex);
|
||||
glm::quat jointRotation;
|
||||
glm::vec3 jointTranslation;
|
||||
if (avatarJointIndex >=0) {
|
||||
jointRotation = getJointRotation(avatarJointIndex);
|
||||
jointTranslation = getJointTranslation(avatarJointIndex);
|
||||
} else {
|
||||
jointRotation = modelEntity->getAbsoluteJointRotationInObjectFrame(jointIndex);
|
||||
jointTranslation = modelEntity->getAbsoluteJointTranslationInObjectFrame(jointIndex);
|
||||
}
|
||||
modelEntity->setLocalJointRotation(jointIndex, jointRotation);
|
||||
modelEntity->setLocalJointTranslation(jointIndex, jointTranslation);
|
||||
}
|
||||
}
|
||||
Transform avatarTransform = _skeletonModel->getTransform();
|
||||
avatarTransform.setScale(_skeletonModel->getScale());
|
||||
modelEntity->setOverrideTransform(avatarTransform, _skeletonModel->getOffset());
|
||||
modelEntity->simulateRelayedJoints();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
_reconstructSoftEntitiesJointMap = false;
|
||||
}
|
||||
|
||||
void Avatar::simulate(float deltaTime, bool inView) {
|
||||
PROFILE_RANGE(simulation, "simulate");
|
||||
|
||||
|
@ -379,6 +442,7 @@ void Avatar::simulate(float deltaTime, bool inView) {
|
|||
}
|
||||
head->setScale(getModelScale());
|
||||
head->simulate(deltaTime);
|
||||
relayJointDataToChildren();
|
||||
} else {
|
||||
// a non-full update is still required so that the position, rotation, scale and bounds of the skeletonModel are updated.
|
||||
_skeletonModel->simulate(deltaTime, false);
|
||||
|
@ -1197,6 +1261,7 @@ void Avatar::setModelURLFinished(bool success) {
|
|||
invalidateJointIndicesCache();
|
||||
|
||||
_isAnimatingScale = true;
|
||||
_reconstructSoftEntitiesJointMap = true;
|
||||
|
||||
if (!success && _skeletonModelURL != AvatarData::defaultFullAvatarModelUrl()) {
|
||||
const int MAX_SKELETON_DOWNLOAD_ATTEMPTS = 4; // NOTE: we don't want to be as generous as ResourceCache is, we only want 4 attempts
|
||||
|
|
|
@ -330,6 +330,7 @@ protected:
|
|||
|
||||
// protected methods...
|
||||
bool isLookingAtMe(AvatarSharedPointer avatar) const;
|
||||
void relayJointDataToChildren();
|
||||
|
||||
void fade(render::Transaction& transaction, render::Transition::Type type);
|
||||
|
||||
|
@ -382,6 +383,7 @@ protected:
|
|||
bool _isAnimatingScale { false };
|
||||
bool _mustFadeIn { false };
|
||||
bool _isFading { false };
|
||||
bool _reconstructSoftEntitiesJointMap { false };
|
||||
float _modelScale { 1.0f };
|
||||
|
||||
static int _jointConesID;
|
||||
|
|
|
@ -237,30 +237,14 @@ bool SkeletonModel::getRightHandPosition(glm::vec3& position) const {
|
|||
return getJointPositionInWorldFrame(getRightHandJointIndex(), position);
|
||||
}
|
||||
|
||||
bool SkeletonModel::restoreLeftHandPosition(float fraction, float priority) {
|
||||
return restoreJointPosition(getLeftHandJointIndex(), fraction, priority);
|
||||
}
|
||||
|
||||
bool SkeletonModel::getLeftShoulderPosition(glm::vec3& position) const {
|
||||
return getJointPositionInWorldFrame(getLastFreeJointIndex(getLeftHandJointIndex()), position);
|
||||
}
|
||||
|
||||
float SkeletonModel::getLeftArmLength() const {
|
||||
return getLimbLength(getLeftHandJointIndex());
|
||||
}
|
||||
|
||||
bool SkeletonModel::restoreRightHandPosition(float fraction, float priority) {
|
||||
return restoreJointPosition(getRightHandJointIndex(), fraction, priority);
|
||||
}
|
||||
|
||||
bool SkeletonModel::getRightShoulderPosition(glm::vec3& position) const {
|
||||
return getJointPositionInWorldFrame(getLastFreeJointIndex(getRightHandJointIndex()), position);
|
||||
}
|
||||
|
||||
float SkeletonModel::getRightArmLength() const {
|
||||
return getLimbLength(getRightHandJointIndex());
|
||||
}
|
||||
|
||||
bool SkeletonModel::getHeadPosition(glm::vec3& headPosition) const {
|
||||
return isActive() && getJointPositionInWorldFrame(getFBXGeometry().headJointIndex, headPosition);
|
||||
}
|
||||
|
|
|
@ -57,11 +57,6 @@ public:
|
|||
/// \return true whether or not the position was found
|
||||
bool getRightHandPosition(glm::vec3& position) const;
|
||||
|
||||
/// Restores some fraction of the default position of the left hand.
|
||||
/// \param fraction the fraction of the default position to restore
|
||||
/// \return whether or not the left hand joint was found
|
||||
bool restoreLeftHandPosition(float fraction = 1.0f, float priority = 1.0f);
|
||||
|
||||
/// Gets the position of the left shoulder.
|
||||
/// \return whether or not the left shoulder joint was found
|
||||
bool getLeftShoulderPosition(glm::vec3& position) const;
|
||||
|
@ -69,18 +64,10 @@ public:
|
|||
/// Returns the extended length from the left hand to its last free ancestor.
|
||||
float getLeftArmLength() const;
|
||||
|
||||
/// Restores some fraction of the default position of the right hand.
|
||||
/// \param fraction the fraction of the default position to restore
|
||||
/// \return whether or not the right hand joint was found
|
||||
bool restoreRightHandPosition(float fraction = 1.0f, float priority = 1.0f);
|
||||
|
||||
/// Gets the position of the right shoulder.
|
||||
/// \return whether or not the right shoulder joint was found
|
||||
bool getRightShoulderPosition(glm::vec3& position) const;
|
||||
|
||||
/// Returns the extended length from the right hand to its first free ancestor.
|
||||
float getRightArmLength() const;
|
||||
|
||||
/// Returns the position of the head joint.
|
||||
/// \return whether or not the head was found
|
||||
bool getHeadPosition(glm::vec3& headPosition) const;
|
||||
|
|
|
@ -530,9 +530,13 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
|
||||
destinationBuffer += numValidityBytes; // Move pointer past the validity bytes
|
||||
|
||||
// sentJointDataOut and lastSentJointData might be the same vector
|
||||
// build sentJointDataOut locally and then swap it at the end.
|
||||
QVector<JointData> localSentJointDataOut;
|
||||
if (sentJointDataOut) {
|
||||
sentJointDataOut->resize(_jointData.size()); // Make sure the destination is resized before using it
|
||||
localSentJointDataOut.resize(numJoints); // Make sure the destination is resized before using it
|
||||
}
|
||||
|
||||
float minRotationDOT = !distanceAdjust ? AVATAR_MIN_ROTATION_DOT : getDistanceBasedMinRotationDOT(viewerPosition);
|
||||
|
||||
for (int i = 0; i < _jointData.size(); i++) {
|
||||
|
@ -552,8 +556,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, data.rotation);
|
||||
|
||||
if (sentJointDataOut) {
|
||||
auto jointDataOut = *sentJointDataOut;
|
||||
jointDataOut[i].rotation = data.rotation;
|
||||
localSentJointDataOut[i].rotation = data.rotation;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -602,8 +605,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
packFloatVec3ToSignedTwoByteFixed(destinationBuffer, data.translation, TRANSLATION_COMPRESSION_RADIX);
|
||||
|
||||
if (sentJointDataOut) {
|
||||
auto jointDataOut = *sentJointDataOut;
|
||||
jointDataOut[i].translation = data.translation;
|
||||
localSentJointDataOut[i].translation = data.translation;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -646,6 +648,11 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
if (outboundDataRateOut) {
|
||||
outboundDataRateOut->jointDataRate.increment(numBytes);
|
||||
}
|
||||
|
||||
if (sentJointDataOut) {
|
||||
// Push new sent joint data to sentJointDataOut
|
||||
sentJointDataOut->swap(localSentJointDataOut);
|
||||
}
|
||||
}
|
||||
|
||||
int avatarDataSize = destinationBuffer - startPosition;
|
||||
|
|
|
@ -358,7 +358,7 @@ class AvatarData : public QObject, public SpatiallyNestable {
|
|||
Q_PROPERTY(QString displayName READ getDisplayName WRITE setDisplayName NOTIFY displayNameChanged)
|
||||
// sessionDisplayName is sanitized, defaulted version displayName that is defined by the AvatarMixer rather than by Interface clients.
|
||||
// The result is unique among all avatars present at the time.
|
||||
Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName)
|
||||
Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName NOTIFY sessionDisplayNameChanged)
|
||||
Q_PROPERTY(bool lookAtSnappingEnabled MEMBER _lookAtSnappingEnabled NOTIFY lookAtSnappingChanged)
|
||||
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript)
|
||||
Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData WRITE setAttachmentData)
|
||||
|
@ -685,6 +685,7 @@ public:
|
|||
|
||||
signals:
|
||||
void displayNameChanged();
|
||||
void sessionDisplayNameChanged();
|
||||
void lookAtSnappingChanged(bool enabled);
|
||||
void sessionUUIDChanged();
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ ScriptAvatarData::ScriptAvatarData(AvatarSharedPointer avatarData) :
|
|||
_avatarData(avatarData)
|
||||
{
|
||||
QObject::connect(avatarData.get(), &AvatarData::displayNameChanged, this, &ScriptAvatarData::displayNameChanged);
|
||||
QObject::connect(avatarData.get(), &AvatarData::sessionDisplayNameChanged, this, &ScriptAvatarData::sessionDisplayNameChanged);
|
||||
QObject::connect(avatarData.get(), &AvatarData::lookAtSnappingChanged, this, &ScriptAvatarData::lookAtSnappingChanged);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ class ScriptAvatarData : public QObject {
|
|||
//
|
||||
Q_PROPERTY(QUuid sessionUUID READ getSessionUUID)
|
||||
Q_PROPERTY(QString displayName READ getDisplayName NOTIFY displayNameChanged)
|
||||
Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName)
|
||||
Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName NOTIFY sessionDisplayNameChanged)
|
||||
Q_PROPERTY(bool isReplicated READ getIsReplicated)
|
||||
Q_PROPERTY(bool lookAtSnappingEnabled READ getLookAtSnappingEnabled NOTIFY lookAtSnappingChanged)
|
||||
|
||||
|
@ -131,6 +131,7 @@ public:
|
|||
|
||||
signals:
|
||||
void displayNameChanged();
|
||||
void sessionDisplayNameChanged();
|
||||
void lookAtSnappingChanged(bool enabled);
|
||||
|
||||
public slots:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
set(TARGET_NAME baking)
|
||||
setup_hifi_library(Concurrent)
|
||||
|
||||
link_hifi_libraries(shared model networking ktx image fbx)
|
||||
link_hifi_libraries(shared graphics networking ktx image fbx)
|
||||
include_hifi_library_headers(gpu)
|
||||
|
||||
add_dependency_external_projects(draco)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue