Merge branch 'master' of github.com:highfidelity/hifi into textToSpeech
|
@ -69,10 +69,10 @@ void ScriptableAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
|||
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
||||
}
|
||||
|
||||
static AnimPose composeAnimPose(const FBXJoint& fbxJoint, const glm::quat rotation, const glm::vec3 translation) {
|
||||
static AnimPose composeAnimPose(const HFMJoint& joint, const glm::quat rotation, const glm::vec3 translation) {
|
||||
glm::mat4 translationMat = glm::translate(translation);
|
||||
glm::mat4 rotationMat = glm::mat4_cast(fbxJoint.preRotation * rotation * fbxJoint.postRotation);
|
||||
glm::mat4 finalMat = translationMat * fbxJoint.preTransform * rotationMat * fbxJoint.postTransform;
|
||||
glm::mat4 rotationMat = glm::mat4_cast(joint.preRotation * rotation * joint.postRotation);
|
||||
glm::mat4 finalMat = translationMat * joint.preTransform * rotationMat * joint.postTransform;
|
||||
return AnimPose(finalMat);
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ void ScriptableAvatar::update(float deltatime) {
|
|||
// Run animation
|
||||
if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0 && !_bind.isNull() && _bind->isLoaded()) {
|
||||
if (!_animSkeleton) {
|
||||
_animSkeleton = std::make_shared<AnimSkeleton>(_bind->getGeometry());
|
||||
_animSkeleton = std::make_shared<AnimSkeleton>(_bind->getHFMModel());
|
||||
}
|
||||
float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps;
|
||||
if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) {
|
||||
|
@ -93,7 +93,7 @@ void ScriptableAvatar::update(float deltatime) {
|
|||
}
|
||||
_animationDetails.currentFrame = currentFrame;
|
||||
|
||||
const QVector<FBXJoint>& modelJoints = _bind->getGeometry().joints;
|
||||
const QVector<HFMJoint>& modelJoints = _bind->getHFMModel().joints;
|
||||
QStringList animationJointNames = _animation->getJointNames();
|
||||
|
||||
const int nJoints = modelJoints.size();
|
||||
|
@ -102,8 +102,8 @@ void ScriptableAvatar::update(float deltatime) {
|
|||
}
|
||||
|
||||
const int frameCount = _animation->getFrames().size();
|
||||
const FBXAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
|
||||
const FBXAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
|
||||
const HFMAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
|
||||
const HFMAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
|
||||
const float frameFraction = glm::fract(currentFrame);
|
||||
std::vector<AnimPose> poses = _animSkeleton->getRelativeDefaultPoses();
|
||||
|
||||
|
@ -113,7 +113,7 @@ void ScriptableAvatar::update(float deltatime) {
|
|||
const QString& name = animationJointNames[i];
|
||||
// As long as we need the model preRotations anyway, let's get the jointIndex from the bind skeleton rather than
|
||||
// trusting the .fst (which is sometimes not updated to match changes to .fbx).
|
||||
int mapping = _bind->getGeometry().getJointIndex(name);
|
||||
int mapping = _bind->getHFMModel().getJointIndex(name);
|
||||
if (mapping != -1 && !_maskedJoints.contains(name)) {
|
||||
|
||||
AnimPose floorPose = composeAnimPose(modelJoints[mapping], floorFrame.rotations[i], floorFrame.translations[i] * UNIT_SCALE);
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="22" height="26" fill="none" version="1.1" viewBox="0 0 22 26" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 7L11 1L21 7M1 7L11 13M1 7V19L11 25M11 13L21 7M11 13V25M21 7V19L11 25" stroke="#000" stroke-linejoin="round" stroke-width="2"/>
|
||||
<circle class="st1" cx="19.407" cy="2.5881" r="2.5846" fill="#ef3b4e" stroke-width=".24043"/>
|
||||
</svg>
|
After Width: | Height: | Size: 356 B |
3
interface/resources/icons/tablet-icons/inventory-a.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="22" height="26" viewBox="0 0 22 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 7L11 1L21 7M1 7L11 13M1 7V19L11 25M11 13L21 7M11 13V25M21 7V19L11 25" stroke="black" stroke-width="2" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 243 B |
|
@ -0,0 +1,4 @@
|
|||
<svg width="22" height="26" fill="none" version="1.1" viewBox="0 0 22 26" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 7L11 1L21 7M1 7L11 13M1 7V19L11 25M11 13L21 7M11 13V25M21 7V19L11 25" stroke="#fff" stroke-linejoin="round" stroke-width="2"/>
|
||||
<circle class="st1" cx="19.41" cy="2.5828" r="2.5846" fill="#ef3b4e" stroke-width=".24043"/>
|
||||
</svg>
|
After Width: | Height: | Size: 355 B |
3
interface/resources/icons/tablet-icons/inventory-i.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="22" height="26" viewBox="0 0 22 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 7L11 1L21 7M1 7L11 13M1 7V19L11 25M11 13L21 7M11 13V25M21 7V19L11 25" stroke="white" stroke-width="2" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 243 B |
|
@ -1,6 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st1{fill:#EF3B4E;}
|
||||
</style>
|
||||
<circle class="st1" cx="84.6" cy="11.5" r="10.75"/>
|
||||
<g><path d="M2.4,70.5c0,6.1,4.9,11,11,11H76c6.1,0,11-4.9,11-11V59.6c3.7-0.7,6.6-3.9,6.6-7.9v-7.5c0-3.9-2.8-7.2-6.6-7.9V25.5 c0-6.1-4.9-11-11-11H13.4c-6.1,0-11,4.9-11,11V70.5z M87.6,51.8c0,1.1-0.9,2-2,2H72.2c-2.8,0-5-2.2-5-5v-1.5c0-2.8,2.2-5,5-5h13.3 c1.1,0,2,0.9,2,2V51.8z M8.4,25.5c0-2.8,2.2-5,5-5H76c2.8,0,5,2.2,5,5v10.7h-8.7c-6.1,0-11,4.9-11,11v1.5c0,6.1,4.9,11,11,11H81 v10.7c0,2.8-2.2,5-5,5H13.4c-2.8,0-5-2.2-5-5V25.5z"></path></g></svg>
|
Before Width: | Height: | Size: 755 B |
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve"><g><path d="M2.4,70.5c0,6.1,4.9,11,11,11H76c6.1,0,11-4.9,11-11V59.6c3.7-0.7,6.6-3.9,6.6-7.9v-7.5c0-3.9-2.8-7.2-6.6-7.9V25.5 c0-6.1-4.9-11-11-11H13.4c-6.1,0-11,4.9-11,11V70.5z M87.6,51.8c0,1.1-0.9,2-2,2H72.2c-2.8,0-5-2.2-5-5v-1.5c0-2.8,2.2-5,5-5h13.3 c1.1,0,2,0.9,2,2V51.8z M8.4,25.5c0-2.8,2.2-5,5-5H76c2.8,0,5,2.2,5,5v10.7h-8.7c-6.1,0-11,4.9-11,11v1.5c0,6.1,4.9,11,11,11H81 v10.7c0,2.8-2.2,5-5,5H13.4c-2.8,0-5-2.2-5-5V25.5z"></path></g></svg>
|
Before Width: | Height: | Size: 643 B |
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
.st1{fill:#EF3B4E;}
|
||||
</style>
|
||||
<circle class="st1" cx="84.6" cy="11.5" r="10.75"/>
|
||||
<g>
|
||||
<path class="st0" d="M2.4,70.5c0,6.1,4.9,11,11,11H76c6.1,0,11-4.9,11-11V59.6c3.7-0.7,6.6-3.9,6.6-7.9v-7.5c0-3.9-2.8-7.2-6.6-7.9
|
||||
V25.5c0-6.1-4.9-11-11-11H13.4c-6.1,0-11,4.9-11,11C2.4,25.5,2.4,70.5,2.4,70.5z M87.6,51.8c0,1.1-0.9,2-2,2H72.2c-2.8,0-5-2.2-5-5
|
||||
v-1.5c0-2.8,2.2-5,5-5h13.3c1.1,0,2,0.9,2,2L87.6,51.8L87.6,51.8z M8.4,25.5c0-2.8,2.2-5,5-5H76c2.8,0,5,2.2,5,5v10.7h-8.7
|
||||
c-6.1,0-11,4.9-11,11v1.5c0,6.1,4.9,11,11,11H81v10.7c0,2.8-2.2,5-5,5H13.4c-2.8,0-5-2.2-5-5V25.5z"/>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 984 B |
|
@ -1,14 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M2.4,70.5c0,6.1,4.9,11,11,11H76c6.1,0,11-4.9,11-11V59.6c3.7-0.7,6.6-3.9,6.6-7.9v-7.5c0-3.9-2.8-7.2-6.6-7.9
|
||||
V25.5c0-6.1-4.9-11-11-11H13.4c-6.1,0-11,4.9-11,11C2.4,25.5,2.4,70.5,2.4,70.5z M87.6,51.8c0,1.1-0.9,2-2,2H72.2c-2.8,0-5-2.2-5-5
|
||||
v-1.5c0-2.8,2.2-5,5-5h13.3c1.1,0,2,0.9,2,2L87.6,51.8L87.6,51.8z M8.4,25.5c0-2.8,2.2-5,5-5H76c2.8,0,5,2.2,5,5v10.7h-8.7
|
||||
c-6.1,0-11,4.9-11,11v1.5c0,6.1,4.9,11,11,11H81v10.7c0,2.8-2.2,5-5,5H13.4c-2.8,0-5-2.2-5-5V25.5z"/>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 909 B |
|
@ -96,7 +96,7 @@ Item {
|
|||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
|
||||
text: qsTr("Sign in to High Fidelity to make friends, get HFC, and buy interesting things on the Marketplace!")
|
||||
text: qsTr("Sign in to High Fidelity to make friends, get HFC, and get interesting things on the Marketplace!")
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
lineHeight: 1
|
||||
|
@ -136,7 +136,7 @@ Item {
|
|||
|
||||
TextField {
|
||||
id: usernameField
|
||||
text: Settings.getValue("wallet/savedUsername", "");
|
||||
text: Settings.getValue("keepMeLoggedIn/savedUsername", "");
|
||||
width: parent.width
|
||||
focus: true
|
||||
placeholderText: "Username or Email"
|
||||
|
@ -165,7 +165,7 @@ Item {
|
|||
root.text = "";
|
||||
}
|
||||
Component.onCompleted: {
|
||||
var savedUsername = Settings.getValue("wallet/savedUsername", "");
|
||||
var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", "");
|
||||
usernameField.text = savedUsername === "Unknown user" ? "" : savedUsername;
|
||||
}
|
||||
}
|
||||
|
@ -239,7 +239,10 @@ Item {
|
|||
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: linkAccountBody.login()
|
||||
Keys.onReturnPressed: {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
linkAccountBody.login();
|
||||
}
|
||||
}
|
||||
|
||||
InfoItem {
|
||||
|
@ -263,21 +266,21 @@ Item {
|
|||
|
||||
CheckBox {
|
||||
id: autoLogoutCheckbox
|
||||
checked: !Settings.getValue("wallet/autoLogout", true)
|
||||
text: "Keep me signed in"
|
||||
checked: Settings.getValue("keepMeLoggedIn", false)
|
||||
text: "Keep me logged in"
|
||||
boxSize: 20;
|
||||
labelFontSize: 15
|
||||
color: hifi.colors.black
|
||||
onCheckedChanged: {
|
||||
Settings.setValue("wallet/autoLogout", !checked);
|
||||
Settings.setValue("keepMeLoggedIn", checked);
|
||||
if (checked) {
|
||||
Settings.setValue("wallet/savedUsername", Account.username);
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
} else {
|
||||
Settings.setValue("wallet/savedUsername", "");
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", "");
|
||||
}
|
||||
}
|
||||
Component.onDestruction: {
|
||||
Settings.setValue("wallet/autoLogout", !checked);
|
||||
Settings.setValue("keepMeLoggedIn", checked);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,7 +292,10 @@ Item {
|
|||
text: qsTr(loginDialog.isSteamRunning() ? "Link Account" : "Log in")
|
||||
color: hifi.buttons.blue
|
||||
|
||||
onClicked: linkAccountBody.login()
|
||||
onClicked: {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
linkAccountBody.login();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -403,6 +409,7 @@ Item {
|
|||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
linkAccountBody.login()
|
||||
break
|
||||
}
|
||||
|
|
|
@ -260,38 +260,50 @@ Item {
|
|||
interactive: false;
|
||||
anchors.fill: parent;
|
||||
model: filterBarModel;
|
||||
delegate: Rectangle {
|
||||
id: dropDownButton;
|
||||
color: hifi.colors.white;
|
||||
delegate: Item {
|
||||
width: parent.width;
|
||||
height: 50;
|
||||
Rectangle {
|
||||
id: dropDownButton;
|
||||
color: hifi.colors.white;
|
||||
width: parent.width;
|
||||
height: 50;
|
||||
visible: true;
|
||||
|
||||
RalewaySemiBold {
|
||||
id: dropDownButtonText;
|
||||
text: model.displayName;
|
||||
anchors.fill: parent;
|
||||
anchors.leftMargin: 12;
|
||||
color: hifi.colors.baseGray;
|
||||
horizontalAlignment: Text.AlignLeft;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
size: 18;
|
||||
RalewaySemiBold {
|
||||
id: dropDownButtonText;
|
||||
text: model.displayName;
|
||||
anchors.fill: parent;
|
||||
anchors.topMargin: 2;
|
||||
anchors.leftMargin: 12;
|
||||
color: hifi.colors.baseGray;
|
||||
horizontalAlignment: Text.AlignLeft;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
size: 18;
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
hoverEnabled: true;
|
||||
propagateComposedEvents: false;
|
||||
onEntered: {
|
||||
dropDownButton.color = hifi.colors.blueHighlight;
|
||||
}
|
||||
onExited: {
|
||||
dropDownButton.color = hifi.colors.white;
|
||||
}
|
||||
onClicked: {
|
||||
textField.forceActiveFocus();
|
||||
root.primaryFilter_index = index;
|
||||
dropdownContainer.visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
hoverEnabled: true;
|
||||
propagateComposedEvents: false;
|
||||
onEntered: {
|
||||
dropDownButton.color = hifi.colors.blueHighlight;
|
||||
}
|
||||
onExited: {
|
||||
dropDownButton.color = hifi.colors.white;
|
||||
}
|
||||
onClicked: {
|
||||
textField.forceActiveFocus();
|
||||
root.primaryFilter_index = index;
|
||||
dropdownContainer.visible = false;
|
||||
}
|
||||
Rectangle {
|
||||
height: 2;
|
||||
width: parent.width;
|
||||
color: hifi.colors.lightGray;
|
||||
visible: model.separator
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,8 +63,8 @@ MessageBox {
|
|||
popup.dialogButtons.yesButton.fontCapitalization = Font.MixedCase;
|
||||
popup.button1text = 'CANCEL'
|
||||
popup.titleText = 'Get Wearables'
|
||||
popup.bodyText = 'Buy wearables from <b><a href="app://marketplace">Marketplace.</a></b>' + '<br/>' +
|
||||
'Wear wearable from <b><a href="app://purchases">My Purchases.</a></b>' + '<br/>' + '<br/>' +
|
||||
popup.bodyText = 'Get wearables from <b><a href="app://marketplace">Marketplace.</a></b>' + '<br/>' +
|
||||
'Wear wearable from <b><a href="app://purchases">Inventory.</a></b>' + '<br/>' + '<br/>' +
|
||||
'Visit “AvatarIsland” to get wearables'
|
||||
|
||||
popup.imageSource = getWearablesUrl;
|
||||
|
@ -89,7 +89,7 @@ MessageBox {
|
|||
|
||||
function showDeleteFavorite(favoriteName, callback) {
|
||||
popup.titleText = 'Delete Favorite: {AvatarName}'.replace('{AvatarName}', favoriteName)
|
||||
popup.bodyText = 'This will delete your favorite. You will retain access to the wearables and avatar that made up the favorite from My Purchases.'
|
||||
popup.bodyText = 'This will delete your favorite. You will retain access to the wearables and avatar that made up the favorite from Inventory.'
|
||||
popup.imageSource = null;
|
||||
popup.button1text = 'CANCEL'
|
||||
popup.button2text = 'DELETE'
|
||||
|
@ -128,8 +128,8 @@ MessageBox {
|
|||
popup.button1text = 'CANCEL'
|
||||
popup.titleText = 'Get Avatars'
|
||||
|
||||
popup.bodyText = 'Buy avatars from <b><a href="app://marketplace">Marketplace.</a></b>' + '<br/>' +
|
||||
'Wear avatars in <b><a href="app://purchases">My Purchases.</a></b>' + '<br/>' + '<br/>' +
|
||||
popup.bodyText = 'Get avatars from <b><a href="app://marketplace">Marketplace.</a></b>' + '<br/>' +
|
||||
'Wear avatars in <b><a href="app://purchases">Inventory.</a></b>' + '<br/>' + '<br/>' +
|
||||
'Visit “BodyMart” to get free avatars.'
|
||||
|
||||
popup.imageSource = getAvatarsUrl;
|
||||
|
|
|
@ -240,11 +240,6 @@ Rectangle {
|
|||
lightboxPopup.button1method = function() {
|
||||
lightboxPopup.visible = false;
|
||||
}
|
||||
lightboxPopup.button2text = "GO TO WALLET";
|
||||
lightboxPopup.button2method = function() {
|
||||
lightboxPopup.visible = false;
|
||||
sendToScript({method: 'checkout_openWallet'});
|
||||
};
|
||||
lightboxPopup.visible = true;
|
||||
} else {
|
||||
sendToScript(msg);
|
||||
|
@ -383,7 +378,7 @@ Rectangle {
|
|||
anchors.leftMargin: 16;
|
||||
width: paintedWidth;
|
||||
height: paintedHeight;
|
||||
text: "Review Purchase:";
|
||||
text: "Review:";
|
||||
color: hifi.colors.black;
|
||||
size: 28;
|
||||
}
|
||||
|
@ -448,7 +443,7 @@ Rectangle {
|
|||
// "HFC" balance label
|
||||
HiFiGlyphs {
|
||||
id: itemPriceTextLabel;
|
||||
visible: !(root.isUpdating && root.itemEdition > 0);
|
||||
visible: !(root.isUpdating && root.itemEdition > 0) && (root.itemPrice > 0);
|
||||
text: hifi.glyphs.hfc;
|
||||
// Size
|
||||
size: 30;
|
||||
|
@ -464,7 +459,7 @@ Rectangle {
|
|||
}
|
||||
FiraSansSemiBold {
|
||||
id: itemPriceText;
|
||||
text: (root.isUpdating && root.itemEdition > 0) ? "FREE\nUPDATE" : ((root.itemPrice === -1) ? "--" : root.itemPrice);
|
||||
text: (root.isUpdating && root.itemEdition > 0) ? "FREE\nUPDATE" : ((root.itemPrice === -1) ? "--" : ((root.itemPrice > 0) ? root.itemPrice : "FREE"));
|
||||
// Text size
|
||||
size: (root.isUpdating && root.itemEdition > 0) ? 20 : 26;
|
||||
// Anchors
|
||||
|
@ -559,7 +554,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
// "View in My Purchases" button
|
||||
// "View in Inventory" button
|
||||
HifiControlsUit.Button {
|
||||
id: viewInMyPurchasesButton;
|
||||
visible: false;
|
||||
|
@ -570,7 +565,7 @@ Rectangle {
|
|||
height: 50;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
text: root.isUpdating ? "UPDATE TO THIS ITEM FOR FREE" : "VIEW THIS ITEM IN MY PURCHASES";
|
||||
text: root.isUpdating ? "UPDATE TO THIS ITEM FOR FREE" : "VIEW THIS ITEM IN YOUR INVENTORY";
|
||||
onClicked: {
|
||||
if (root.isUpdating) {
|
||||
sendToScript({method: 'checkout_goToPurchases', filterText: root.baseItemName});
|
||||
|
@ -594,7 +589,7 @@ Rectangle {
|
|||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
text: (root.isUpdating && root.itemEdition > 0) ? "CONFIRM UPDATE" : (((root.isCertified) ? ((ownershipStatusReceived && balanceReceived && availableUpdatesReceived) ?
|
||||
((viewInMyPurchasesButton.visible && !root.isUpdating) ? "Buy It Again" : "Confirm Purchase") : "--") : "Get Item"));
|
||||
((viewInMyPurchasesButton.visible && !root.isUpdating) ? "Get It Again" : "Confirm") : "--") : "Get Item"));
|
||||
onClicked: {
|
||||
if (root.isUpdating && root.itemEdition > 0) {
|
||||
// If we're updating an app, the existing app needs to be uninstalled.
|
||||
|
@ -608,9 +603,9 @@ Rectangle {
|
|||
} else if (root.isCertified) {
|
||||
if (!root.shouldBuyWithControlledFailure) {
|
||||
if (root.itemType === "contentSet" && !Entities.canReplaceContent()) {
|
||||
lightboxPopup.titleText = "Purchase Content Set";
|
||||
lightboxPopup.titleText = "Get Content Set";
|
||||
lightboxPopup.bodyText = "You will not be able to replace this domain's content with <b>" + root.itemName +
|
||||
" </b>until the server owner gives you 'Replace Content' permissions.<br><br>Are you sure you want to purchase this content set?";
|
||||
" </b>until the server owner gives you 'Replace Content' permissions.<br><br>Are you sure you want to get this content set?";
|
||||
lightboxPopup.button1text = "CANCEL";
|
||||
lightboxPopup.button1method = function() {
|
||||
lightboxPopup.visible = false;
|
||||
|
@ -694,7 +689,7 @@ Rectangle {
|
|||
id: completeText2;
|
||||
text: "The " + (root.itemTypesText)[itemTypesArray.indexOf(root.itemType)] +
|
||||
' <font color="' + hifi.colors.blueAccent + '"><a href="#">' + root.itemName + '</a></font>' +
|
||||
" has been added to your Purchases and a receipt will appear in your Wallet's transaction history.";
|
||||
" has been added to your Inventory.";
|
||||
// Text size
|
||||
size: 18;
|
||||
// Anchors
|
||||
|
@ -833,7 +828,7 @@ Rectangle {
|
|||
}
|
||||
lightboxPopup.button2text = "OPEN GOTO";
|
||||
lightboxPopup.button2method = function() {
|
||||
sendToScript({method: 'purchases_openGoTo'});
|
||||
sendToScript({method: 'checkout_openGoTo'});
|
||||
lightboxPopup.visible = false;
|
||||
};
|
||||
lightboxPopup.visible = true;
|
||||
|
@ -864,7 +859,7 @@ Rectangle {
|
|||
|
||||
RalewaySemiBold {
|
||||
id: myPurchasesLink;
|
||||
text: '<font color="' + hifi.colors.primaryHighlight + '"><a href="#">View this item in My Purchases</a></font>';
|
||||
text: '<font color="' + hifi.colors.primaryHighlight + '"><a href="#">View this item in your Inventory</a></font>';
|
||||
// Text size
|
||||
size: 18;
|
||||
// Anchors
|
||||
|
@ -886,7 +881,8 @@ Rectangle {
|
|||
|
||||
RalewaySemiBold {
|
||||
id: walletLink;
|
||||
text: '<font color="' + hifi.colors.primaryHighlight + '"><a href="#">View receipt in Wallet</a></font>';
|
||||
visible: !WalletScriptingInterface.limitedCommerce;
|
||||
text: '<font color="' + hifi.colors.primaryHighlight + '"><a href="#">View receipt in Recent Activity</a></font>';
|
||||
// Text size
|
||||
size: 18;
|
||||
// Anchors
|
||||
|
@ -902,18 +898,18 @@ Rectangle {
|
|||
horizontalAlignment: Text.AlignLeft;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
onLinkActivated: {
|
||||
sendToScript({method: 'purchases_openWallet'});
|
||||
sendToScript({method: 'checkout_openRecentActivity'});
|
||||
}
|
||||
}
|
||||
|
||||
RalewayRegular {
|
||||
id: pendingText;
|
||||
text: 'Your item is marked "pending" while your purchase is being confirmed. ' +
|
||||
text: 'Your item is marked "pending" while the transfer is being confirmed. ' +
|
||||
'<b><font color="' + hifi.colors.primaryHighlight + '"><a href="#">Learn More</a></font></b>';
|
||||
// Text size
|
||||
size: 18;
|
||||
// Anchors
|
||||
anchors.top: walletLink.bottom;
|
||||
anchors.top: walletLink.visible ? walletLink.bottom : myPurchasesLink.bottom;
|
||||
anchors.topMargin: 32;
|
||||
height: paintedHeight;
|
||||
anchors.left: parent.left;
|
||||
|
@ -925,8 +921,8 @@ Rectangle {
|
|||
horizontalAlignment: Text.AlignLeft;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
onLinkActivated: {
|
||||
lightboxPopup.titleText = "Purchase Confirmations";
|
||||
lightboxPopup.bodyText = 'Your item is marked "pending" while your purchase is being confirmed.<br><br>' +
|
||||
lightboxPopup.titleText = "Confirmations";
|
||||
lightboxPopup.bodyText = 'Your item is marked "pending" while the transfer is being confirmed.<br><br>' +
|
||||
'Confirmations usually take about 90 seconds.';
|
||||
lightboxPopup.button1text = "CLOSE";
|
||||
lightboxPopup.button1method = function() {
|
||||
|
@ -936,9 +932,9 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
// "Continue Shopping" button
|
||||
// "Continue" button
|
||||
HifiControlsUit.Button {
|
||||
id: continueShoppingButton;
|
||||
id: continueButton;
|
||||
color: hifi.buttons.noneBorderlessGray;
|
||||
colorScheme: hifi.colorSchemes.light;
|
||||
anchors.bottom: parent.bottom;
|
||||
|
@ -946,9 +942,9 @@ Rectangle {
|
|||
anchors.right: parent.right;
|
||||
width: 193;
|
||||
height: 44;
|
||||
text: "Continue Shopping";
|
||||
text: "Continue";
|
||||
onClicked: {
|
||||
sendToScript({method: 'checkout_continueShopping', itemId: itemId});
|
||||
sendToScript({method: 'checkout_continue', itemId: itemId});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -971,7 +967,7 @@ Rectangle {
|
|||
|
||||
RalewayRegular {
|
||||
id: failureHeaderText;
|
||||
text: "<b>Purchase Failed.</b><br>Your Purchases and HFC balance haven't changed.";
|
||||
text: "<b>Purchase Failed.</b><br>Your Inventory and HFC balance haven't changed.";
|
||||
// Text size
|
||||
size: 24;
|
||||
// Anchors
|
||||
|
@ -1037,7 +1033,7 @@ Rectangle {
|
|||
width: parent.width/2 - anchors.leftMargin*2;
|
||||
text: "Back to Marketplace";
|
||||
onClicked: {
|
||||
sendToScript({method: 'checkout_continueShopping', itemId: itemId});
|
||||
sendToScript({method: 'checkout_continue', itemId: itemId});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1122,10 +1118,10 @@ Rectangle {
|
|||
if (root.balanceAfterPurchase < 0) {
|
||||
// If you already own the item...
|
||||
if (!root.alreadyOwned) {
|
||||
buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item.</b>";
|
||||
buyText.text = "<b>You do not have sufficient funds to purchase this item.</b>";
|
||||
// Else if you don't already own the item...
|
||||
} else if (canBuyAgain()) {
|
||||
buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item again.</b>";
|
||||
buyText.text = "<b>You do not have sufficient funds to purchase this item again.</b>";
|
||||
} else {
|
||||
buyText.text = "<b>While you do not have sufficient funds to buy this, you already have this item.</b>"
|
||||
}
|
||||
|
@ -1171,7 +1167,7 @@ Rectangle {
|
|||
buyText.text = "";
|
||||
}
|
||||
} else {
|
||||
buyText.text = '<i>This type of item cannot currently be certified, so it will not show up in "My Purchases". You can access it again for free from the Marketplace.</i>';
|
||||
buyText.text = '<i>This type of item cannot currently be certified, so it will not show up in "Inventory". You can access it again for free from the Marketplace.</i>';
|
||||
buyTextContainer.color = hifi.colors.white;
|
||||
buyTextContainer.border.color = hifi.colors.white;
|
||||
buyGlyph.text = "";
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
import Hifi 1.0 as Hifi
|
||||
import QtQuick 2.5
|
||||
import QtGraphicalEffects 1.0
|
||||
import "../../../styles-uit"
|
||||
import "../../../controls-uit" as HifiControlsUit
|
||||
import "../../../controls" as HifiControls
|
||||
import "qrc:////qml//styles-uit"
|
||||
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||
import "qrc:////qml//controls" as HifiControls
|
||||
|
||||
// references XXX from root context
|
||||
|
||||
|
@ -33,13 +33,15 @@ Rectangle {
|
|||
property string buttonLayout: "leftright";
|
||||
|
||||
readonly property string securityPicBodyText: "When you see your Security Pic, your actions and data are securely making use of your " +
|
||||
"Wallet's private keys.<br><br>You can change your Security Pic in your Wallet.";
|
||||
"private keys.<br><br>You can change your Security Pic via Settings > Security...";
|
||||
|
||||
id: root;
|
||||
visible: false;
|
||||
anchors.fill: parent;
|
||||
color: Qt.rgba(0, 0, 0, 0.5);
|
||||
z: 999;
|
||||
|
||||
HifiConstants { id: hifi; }
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
|
|
|
@ -27,7 +27,6 @@ Item {
|
|||
property string referrerURL: (Account.metaverseServerURL + "/marketplace?");
|
||||
readonly property int additionalDropdownHeight: usernameDropdown.height - myUsernameButton.anchors.bottomMargin;
|
||||
property alias usernameDropdownVisible: usernameDropdown.visible;
|
||||
property bool messagesWaiting: false;
|
||||
|
||||
height: mainContainer.height + additionalDropdownHeight;
|
||||
|
||||
|
@ -38,7 +37,6 @@ Item {
|
|||
if (walletStatus === 0) {
|
||||
sendToParent({method: "needsLogIn"});
|
||||
} else if (walletStatus === 5) {
|
||||
Commerce.getAvailableUpdates();
|
||||
Commerce.getSecurityImage();
|
||||
} else if (walletStatus > 5) {
|
||||
console.log("ERROR in EmulatedMarketplaceHeader.qml: Unknown wallet status: " + walletStatus);
|
||||
|
@ -59,14 +57,6 @@ Item {
|
|||
securityImage.source = "image://security/securityImage";
|
||||
}
|
||||
}
|
||||
|
||||
onAvailableUpdatesResult: {
|
||||
if (result.status !== 'success') {
|
||||
console.log("Failed to get Available Updates", result.data.message);
|
||||
} else {
|
||||
root.messagesWaiting = result.data.updates.length > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
|
@ -118,50 +108,6 @@ Item {
|
|||
anchors.right: securityImage.left;
|
||||
anchors.rightMargin: 6;
|
||||
|
||||
Rectangle {
|
||||
id: myPurchasesLink;
|
||||
anchors.right: myUsernameButton.left;
|
||||
anchors.rightMargin: 8;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
height: 40;
|
||||
width: myPurchasesText.paintedWidth + 10;
|
||||
|
||||
RalewaySemiBold {
|
||||
id: myPurchasesText;
|
||||
text: "My Purchases";
|
||||
// Text size
|
||||
size: 18;
|
||||
// Style
|
||||
color: hifi.colors.blueAccent;
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
// Anchors
|
||||
anchors.centerIn: parent;
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
hoverEnabled: enabled;
|
||||
onClicked: {
|
||||
sendToParent({ method: 'header_goToPurchases', hasUpdates: root.messagesWaiting });
|
||||
}
|
||||
onEntered: myPurchasesText.color = hifi.colors.blueHighlight;
|
||||
onExited: myPurchasesText.color = hifi.colors.blueAccent;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: messagesWaitingLight;
|
||||
visible: root.messagesWaiting;
|
||||
anchors.right: myPurchasesLink.left;
|
||||
anchors.rightMargin: -2;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
height: 10;
|
||||
width: height;
|
||||
radius: height/2;
|
||||
color: "red";
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: textMetrics;
|
||||
font.family: "Raleway"
|
||||
|
@ -267,7 +213,7 @@ Item {
|
|||
anchors.topMargin: -buttonAndUsernameContainer.anchors.bottomMargin;
|
||||
anchors.right: buttonAndUsernameContainer.right;
|
||||
height: childrenRect.height;
|
||||
width: 100;
|
||||
width: 150;
|
||||
|
||||
Rectangle {
|
||||
id: myItemsButton;
|
||||
|
@ -279,7 +225,7 @@ Item {
|
|||
|
||||
RalewaySemiBold {
|
||||
anchors.fill: parent;
|
||||
text: "My Items"
|
||||
text: "My Submissions"
|
||||
color: hifi.colors.baseGray;
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
|
|
|
@ -87,7 +87,7 @@ Rectangle {
|
|||
}
|
||||
RalewayRegular {
|
||||
id: introText2;
|
||||
text: "My Purchases";
|
||||
text: "Inventory";
|
||||
// Text size
|
||||
size: 22;
|
||||
// Anchors
|
||||
|
@ -116,7 +116,7 @@ Rectangle {
|
|||
|
||||
RalewayRegular {
|
||||
id: step1text;
|
||||
text: "The <b>'REZ IT'</b> button makes your purchase appear in front of you.";
|
||||
text: "The <b>'REZ IT'</b> button makes your item appear in front of you.";
|
||||
// Text size
|
||||
size: 20;
|
||||
// Anchors
|
||||
|
|
|
@ -73,6 +73,10 @@ Item {
|
|||
}
|
||||
|
||||
onTransferAssetToNodeResult: {
|
||||
if (!root.visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
root.isCurrentlySendingAsset = false;
|
||||
|
||||
if (result.status === 'success') {
|
||||
|
@ -92,6 +96,10 @@ Item {
|
|||
}
|
||||
|
||||
onTransferAssetToUsernameResult: {
|
||||
if (!root.visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
root.isCurrentlySendingAsset = false;
|
||||
|
||||
if (result.status === 'success') {
|
||||
|
@ -1309,13 +1317,13 @@ Item {
|
|||
|
||||
Rectangle {
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: root.assetName === "" ? 15 : 150;
|
||||
anchors.topMargin: root.assetName === "" ? 15 : 125;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: root.assetName === "" ? 15 : 50;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: root.assetName === "" ? 15 : 50;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.bottomMargin: root.assetName === "" ? 15 : 240;
|
||||
anchors.bottomMargin: root.assetName === "" ? 15 : 125;
|
||||
color: "#FFFFFF";
|
||||
|
||||
RalewaySemiBold {
|
||||
|
|
|
@ -28,7 +28,7 @@ Rectangle {
|
|||
property string itemName: "--";
|
||||
property string itemOwner: "--";
|
||||
property string itemEdition: "--";
|
||||
property string dateOfPurchase: "--";
|
||||
property string dateAcquired: "--";
|
||||
property string itemCost: "--";
|
||||
property string certTitleTextColor: hifi.colors.darkGray;
|
||||
property string certTextColor: hifi.colors.white;
|
||||
|
@ -64,7 +64,7 @@ Rectangle {
|
|||
root.itemName = "";
|
||||
root.itemEdition = "";
|
||||
root.itemOwner = "";
|
||||
root.dateOfPurchase = "";
|
||||
root.dateAcquired = "";
|
||||
root.itemCost = "";
|
||||
errorText.text = "Information about this certificate is currently unavailable. Please try again later.";
|
||||
}
|
||||
|
@ -77,8 +77,9 @@ Rectangle {
|
|||
// "\u2022" is the Unicode character 'BULLET' - it's what's used in password fields on the web, etc
|
||||
root.itemOwner = root.isMyCert ? Account.username :
|
||||
"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
|
||||
root.dateOfPurchase = root.isMyCert ? getFormattedDate(result.data.transfer_created_at * 1000) : "Undisclosed";
|
||||
root.itemCost = (root.isMyCert && result.data.cost !== undefined) ? result.data.cost : "Undisclosed";
|
||||
root.dateAcquired = root.isMyCert ? getFormattedDate(result.data.transfer_created_at * 1000) : "Undisclosed";
|
||||
root.itemCost = (root.isMyCert && result.data.cost !== undefined) ?
|
||||
(parseInt(result.data.cost) > 0 ? result.data.cost : "Free") : "Undisclosed";
|
||||
}
|
||||
if (root.certInfoReplaceMode > 4) {
|
||||
root.itemEdition = result.data.edition_number + "/" + (result.data.limited_run === -1 ? "\u221e" : result.data.limited_run);
|
||||
|
@ -86,7 +87,7 @@ Rectangle {
|
|||
|
||||
if (root.certificateStatus === 4) { // CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED
|
||||
if (root.isMyCert) {
|
||||
errorText.text = "This item is an uncertified copy of an item you purchased.";
|
||||
errorText.text = "This item is an uncertified copy of an item you acquired.";
|
||||
} else {
|
||||
errorText.text = "The person who placed this item doesn't own it.";
|
||||
}
|
||||
|
@ -102,8 +103,8 @@ Rectangle {
|
|||
showInMarketplaceButton.visible = false;
|
||||
// "Edition" text previously set above in this function
|
||||
// "Owner" text previously set above in this function
|
||||
// "Purchase Date" text previously set above in this function
|
||||
// "Purchase Price" text previously set above in this function
|
||||
// "Acquisition Date" text previously set above in this function
|
||||
// "Acquisition Price" text previously set above in this function
|
||||
if (result.data.invalid_reason) {
|
||||
errorText.text = result.data.invalid_reason;
|
||||
}
|
||||
|
@ -117,8 +118,8 @@ Rectangle {
|
|||
showInMarketplaceButton.visible = true;
|
||||
// "Edition" text previously set above in this function
|
||||
// "Owner" text previously set above in this function
|
||||
// "Purchase Date" text previously set above in this function
|
||||
// "Purchase Price" text previously set above in this function
|
||||
// "Acquisition Date" text previously set above in this function
|
||||
// "Acquisition Price" text previously set above in this function
|
||||
errorText.text = "The status of this item is still pending confirmation. If the purchase is not confirmed, " +
|
||||
"this entity will be cleaned up by the domain.";
|
||||
}
|
||||
|
@ -145,8 +146,8 @@ Rectangle {
|
|||
// "Item Name" text will be set in "onCertificateInfoResult()"
|
||||
// "Edition" text will be set in "onCertificateInfoResult()"
|
||||
// "Owner" text will be set in "onCertificateInfoResult()"
|
||||
// "Purchase Date" text will be set in "onCertificateInfoResult()"
|
||||
// "Purchase Price" text will be set in "onCertificateInfoResult()"
|
||||
// "Acquisition Date" text will be set in "onCertificateInfoResult()"
|
||||
// "Acquisition Price" text will be set in "onCertificateInfoResult()"
|
||||
errorText.text = "";
|
||||
} else if (root.certificateStatus === 2) { // CERTIFICATE_STATUS_VERIFICATION_TIMEOUT
|
||||
root.useGoldCert = false;
|
||||
|
@ -160,7 +161,7 @@ Rectangle {
|
|||
root.itemName = "";
|
||||
root.itemEdition = "";
|
||||
root.itemOwner = "";
|
||||
root.dateOfPurchase = "";
|
||||
root.dateAcquired = "";
|
||||
root.itemCost = "";
|
||||
errorText.text = "Your request to inspect this item timed out. Please try again later.";
|
||||
} else if (root.certificateStatus === 3) { // CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED
|
||||
|
@ -175,8 +176,8 @@ Rectangle {
|
|||
// "Item Name" text will be set in "onCertificateInfoResult()"
|
||||
// "Edition" text will be set in "onCertificateInfoResult()"
|
||||
// "Owner" text will be set in "onCertificateInfoResult()"
|
||||
// "Purchase Date" text will be set in "onCertificateInfoResult()"
|
||||
// "Purchase Price" text will be set in "onCertificateInfoResult()"
|
||||
// "Acquisition Date" text will be set in "onCertificateInfoResult()"
|
||||
// "Acquisition Price" text will be set in "onCertificateInfoResult()"
|
||||
errorText.text = "The information associated with this item has been modified and it no longer matches the original certified item.";
|
||||
} else if (root.certificateStatus === 4) { // CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED
|
||||
root.useGoldCert = false;
|
||||
|
@ -190,8 +191,8 @@ Rectangle {
|
|||
// "Item Name" text will be set in "onCertificateInfoResult()"
|
||||
root.itemEdition = "Uncertified Copy"
|
||||
// "Owner" text will be set in "onCertificateInfoResult()"
|
||||
// "Purchase Date" text will be set in "onCertificateInfoResult()"
|
||||
// "Purchase Price" text will be set in "onCertificateInfoResult()"
|
||||
// "Acquisition Date" text will be set in "onCertificateInfoResult()"
|
||||
// "Acquisition Price" text will be set in "onCertificateInfoResult()"
|
||||
// "Error Text" text will be set in "onCertificateInfoResult()"
|
||||
} else {
|
||||
console.log("Unknown certificate status received from ledger signal!");
|
||||
|
@ -485,8 +486,8 @@ Rectangle {
|
|||
}
|
||||
|
||||
RalewayRegular {
|
||||
id: dateOfPurchaseHeader;
|
||||
text: "PURCHASE DATE";
|
||||
id: dateAcquiredHeader;
|
||||
text: "ACQUISITION DATE";
|
||||
// Text size
|
||||
size: 16;
|
||||
// Anchors
|
||||
|
@ -500,15 +501,15 @@ Rectangle {
|
|||
color: hifi.colors.darkGray;
|
||||
}
|
||||
AnonymousProRegular {
|
||||
id: dateOfPurchase;
|
||||
text: root.dateOfPurchase;
|
||||
id: dateAcquired;
|
||||
text: root.dateAcquired;
|
||||
// Text size
|
||||
size: 18;
|
||||
// Anchors
|
||||
anchors.top: dateOfPurchaseHeader.bottom;
|
||||
anchors.top: dateAcquiredHeader.bottom;
|
||||
anchors.topMargin: 8;
|
||||
anchors.left: dateOfPurchaseHeader.left;
|
||||
anchors.right: dateOfPurchaseHeader.right;
|
||||
anchors.left: dateAcquiredHeader.left;
|
||||
anchors.right: dateAcquiredHeader.right;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: root.infoTextColor;
|
||||
|
@ -516,7 +517,7 @@ Rectangle {
|
|||
|
||||
RalewayRegular {
|
||||
id: priceHeader;
|
||||
text: "PURCHASE PRICE";
|
||||
text: "ACQUISITION PRICE";
|
||||
// Text size
|
||||
size: 16;
|
||||
// Anchors
|
||||
|
@ -530,7 +531,7 @@ Rectangle {
|
|||
}
|
||||
HiFiGlyphs {
|
||||
id: hfcGlyph;
|
||||
visible: priceText.text !== "Undisclosed" && priceText.text !== "";
|
||||
visible: priceText.text !== "Undisclosed" && priceText.text !== "" && priceText.text !== "Free";
|
||||
text: hifi.glyphs.hfc;
|
||||
// Size
|
||||
size: 24;
|
||||
|
@ -618,7 +619,7 @@ Rectangle {
|
|||
root.itemName = "--";
|
||||
root.itemOwner = "--";
|
||||
root.itemEdition = "--";
|
||||
root.dateOfPurchase = "--";
|
||||
root.dateAcquired = "--";
|
||||
root.marketplaceUrl = "";
|
||||
root.itemCost = "--";
|
||||
root.isMyCert = false;
|
||||
|
|
|
@ -47,8 +47,7 @@ Item {
|
|||
property string wornEntityID;
|
||||
property string upgradeUrl;
|
||||
property string upgradeTitle;
|
||||
property bool updateAvailable: root.upgradeUrl !== "" && !root.isShowingMyItems;
|
||||
property bool isShowingMyItems;
|
||||
property bool updateAvailable: root.upgradeUrl !== "";
|
||||
property bool valid;
|
||||
|
||||
property string originalStatusText;
|
||||
|
@ -231,7 +230,7 @@ Item {
|
|||
|
||||
Loader {
|
||||
id: giftButton;
|
||||
visible: !root.isShowingMyItems;
|
||||
visible: root.itemEdition > 0;
|
||||
sourceComponent: contextCardButton;
|
||||
anchors.right: parent.right;
|
||||
anchors.top: parent.top;
|
||||
|
@ -345,6 +344,7 @@ Item {
|
|||
|
||||
Rectangle {
|
||||
id: permissionExplanationCard;
|
||||
visible: false;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 30;
|
||||
anchors.top: parent.top;
|
||||
|
|
|
@ -19,7 +19,6 @@ import "../../../controls" as HifiControls
|
|||
import "qrc:////qml//hifi//models" as HifiModels // Absolute path so the same code works everywhere.
|
||||
import "../wallet" as HifiWallet
|
||||
import "../common" as HifiCommerceCommon
|
||||
import "../inspectionCertificate" as HifiInspectionCertificate
|
||||
import "../common/sendAsset" as HifiSendAsset
|
||||
import "../.." as HifiCommon
|
||||
|
||||
|
@ -34,7 +33,6 @@ Rectangle {
|
|||
property bool securityImageResultReceived: false;
|
||||
property bool purchasesReceived: false;
|
||||
property bool punctuationMode: false;
|
||||
property bool isShowingMyItems: false;
|
||||
property bool isDebuggingFirstUseTutorial: false;
|
||||
property string installedApps;
|
||||
property bool keyboardRaised: false;
|
||||
|
@ -92,7 +90,6 @@ Rectangle {
|
|||
if (result.status !== 'success') {
|
||||
console.log("Failed to get Available Updates", result.data.message);
|
||||
} else {
|
||||
sendToScript({method: 'purchases_availableUpdatesReceived', numUpdates: result.data.updates.length });
|
||||
root.numUpdatesAvailable = result.total_entries;
|
||||
}
|
||||
}
|
||||
|
@ -106,10 +103,6 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
onIsShowingMyItemsChanged: {
|
||||
getPurchases();
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: notSetUpTimer;
|
||||
interval: 200;
|
||||
|
@ -118,19 +111,6 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
HifiInspectionCertificate.InspectionCertificate {
|
||||
id: inspectionCertificate;
|
||||
z: 998;
|
||||
visible: false;
|
||||
anchors.fill: parent;
|
||||
|
||||
Connections {
|
||||
onSendToScript: {
|
||||
sendToScript(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiCommerceCommon.CommerceLightbox {
|
||||
id: lightboxPopup;
|
||||
z: 999;
|
||||
|
@ -180,7 +160,8 @@ Rectangle {
|
|||
HifiCommerceCommon.EmulatedMarketplaceHeader {
|
||||
id: titleBarContainer;
|
||||
z: 997;
|
||||
visible: !needsLogIn.visible;
|
||||
visible: false;
|
||||
height: 100;
|
||||
// Size
|
||||
width: parent.width;
|
||||
// Anchors
|
||||
|
@ -199,11 +180,6 @@ Rectangle {
|
|||
lightboxPopup.button1method = function() {
|
||||
lightboxPopup.visible = false;
|
||||
}
|
||||
lightboxPopup.button2text = "GO TO WALLET";
|
||||
lightboxPopup.button2method = function() {
|
||||
sendToScript({method: 'purchases_openWallet'});
|
||||
lightboxPopup.visible = false;
|
||||
};
|
||||
lightboxPopup.visible = true;
|
||||
} else {
|
||||
sendToScript(msg);
|
||||
|
@ -475,7 +451,7 @@ Rectangle {
|
|||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 16;
|
||||
width: paintedWidth;
|
||||
text: isShowingMyItems ? "My Items" : "My Purchases";
|
||||
text: "Items";
|
||||
color: hifi.colors.black;
|
||||
size: 22;
|
||||
}
|
||||
|
@ -517,8 +493,13 @@ Rectangle {
|
|||
"filterName": "wearable"
|
||||
},
|
||||
{
|
||||
"separator" : true,
|
||||
"displayName": "Updatable",
|
||||
"filterName": "updated"
|
||||
},
|
||||
{
|
||||
"displayName": "My Submissions",
|
||||
"filterName": "proofs"
|
||||
}
|
||||
]
|
||||
filterBar.primaryFilterChoices.clear();
|
||||
|
@ -533,6 +514,7 @@ Rectangle {
|
|||
onTextChanged: {
|
||||
purchasesModel.searchFilter = filterBar.text;
|
||||
filterBar.previousText = filterBar.text;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -556,10 +538,18 @@ Rectangle {
|
|||
listModelName: 'purchases';
|
||||
listView: purchasesContentsList;
|
||||
getPage: function () {
|
||||
console.debug('getPage', purchasesModel.listModelName, root.isShowingMyItems, filterBar.primaryFilter_filterName, purchasesModel.currentPageToRetrieve, purchasesModel.itemsPerPage);
|
||||
console.debug('getPage', purchasesModel.listModelName, filterBar.primaryFilter_filterName, purchasesModel.currentPageToRetrieve, purchasesModel.itemsPerPage);
|
||||
var editionFilter = "";
|
||||
var primaryFilter = "";
|
||||
|
||||
if (filterBar.primaryFilter_filterName === "proofs") {
|
||||
editionFilter = "proofs";
|
||||
} else {
|
||||
primaryFilter = filterBar.primaryFilter_filterName;
|
||||
}
|
||||
Commerce.inventory(
|
||||
root.isShowingMyItems ? "proofs" : "purchased",
|
||||
filterBar.primaryFilter_filterName,
|
||||
editionFilter,
|
||||
primaryFilter,
|
||||
filterBar.text,
|
||||
purchasesModel.currentPageToRetrieve,
|
||||
purchasesModel.itemsPerPage
|
||||
|
@ -609,7 +599,6 @@ Rectangle {
|
|||
upgradeUrl: model.upgrade_url;
|
||||
upgradeTitle: model.upgrade_title;
|
||||
itemType: model.item_type;
|
||||
isShowingMyItems: root.isShowingMyItems;
|
||||
valid: model.valid;
|
||||
anchors.topMargin: 10;
|
||||
anchors.bottomMargin: 10;
|
||||
|
@ -626,8 +615,6 @@ Rectangle {
|
|||
sendToScript({ method: 'purchases_updateWearables' });
|
||||
}
|
||||
} else if (msg.method === 'purchases_itemCertificateClicked') {
|
||||
inspectionCertificate.visible = true;
|
||||
inspectionCertificate.isLightbox = true;
|
||||
sendToScript(msg);
|
||||
} else if (msg.method === "showInvalidatedLightbox") {
|
||||
lightboxPopup.titleText = "Item Invalidated";
|
||||
|
@ -640,7 +627,7 @@ Rectangle {
|
|||
lightboxPopup.visible = true;
|
||||
} else if (msg.method === "showPendingLightbox") {
|
||||
lightboxPopup.titleText = "Item Pending";
|
||||
lightboxPopup.bodyText = 'Your item is marked "pending" while your purchase is being confirmed. ' +
|
||||
lightboxPopup.bodyText = 'Your item is marked "pending" while the transfer is being confirmed. ' +
|
||||
"Usually, purchases take about 90 seconds to confirm.";
|
||||
lightboxPopup.button1text = "CLOSE";
|
||||
lightboxPopup.button1method = function() {
|
||||
|
@ -822,7 +809,8 @@ Rectangle {
|
|||
|
||||
Rectangle {
|
||||
id: updatesAvailableBanner;
|
||||
visible: root.numUpdatesAvailable > 0 && !root.isShowingMyItems;
|
||||
visible: root.numUpdatesAvailable > 0 &&
|
||||
filterBar.primaryFilter_filterName !== "proofs";
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
|
@ -883,9 +871,8 @@ Rectangle {
|
|||
id: noItemsAlertContainer;
|
||||
visible: !purchasesContentsList.visible &&
|
||||
root.purchasesReceived &&
|
||||
root.isShowingMyItems &&
|
||||
filterBar.text === "" &&
|
||||
filterBar.primaryFilter_displayName === "";
|
||||
filterBar.primaryFilter_filterName === "proofs";
|
||||
anchors.top: filterBarContainer.bottom;
|
||||
anchors.topMargin: 12;
|
||||
anchors.left: parent.left;
|
||||
|
@ -895,7 +882,7 @@ Rectangle {
|
|||
// Explanitory text
|
||||
RalewayRegular {
|
||||
id: noItemsYet;
|
||||
text: "<b>You haven't submitted anything to the Marketplace yet!</b><br><br>Submit an item to the Marketplace to add it to My Items.";
|
||||
text: "<b>You haven't submitted anything to the Marketplace yet!</b><br><br>Submit an item to the Marketplace to add it to My Submissions.";
|
||||
// Text size
|
||||
size: 22;
|
||||
// Anchors
|
||||
|
@ -933,7 +920,6 @@ Rectangle {
|
|||
id: noPurchasesAlertContainer;
|
||||
visible: !purchasesContentsList.visible &&
|
||||
root.purchasesReceived &&
|
||||
!root.isShowingMyItems &&
|
||||
filterBar.text === "" &&
|
||||
filterBar.primaryFilter_displayName === "";
|
||||
anchors.top: filterBarContainer.bottom;
|
||||
|
@ -945,7 +931,7 @@ Rectangle {
|
|||
// Explanitory text
|
||||
RalewayRegular {
|
||||
id: haventPurchasedYet;
|
||||
text: "<b>You haven't purchased anything yet!</b><br><br>Get an item from <b>Marketplace</b> to add it to My Purchases.";
|
||||
text: "<b>You haven't gotten anything yet!</b><br><br>Get an item from <b>Marketplace</b> to add it to your Inventory.";
|
||||
// Text size
|
||||
size: 22;
|
||||
// Anchors
|
||||
|
@ -1065,11 +1051,10 @@ Rectangle {
|
|||
titleBarContainer.referrerURL = message.referrerURL || "";
|
||||
filterBar.text = message.filterText ? message.filterText : "";
|
||||
break;
|
||||
case 'inspectionCertificate_setCertificateId':
|
||||
inspectionCertificate.fromScript(message);
|
||||
break;
|
||||
case 'purchases_showMyItems':
|
||||
root.isShowingMyItems = true;
|
||||
filterBar.primaryFilter_filterName = "proofs";
|
||||
filterBar.primaryFilter_displayName = "Proofs";
|
||||
filterBar.primaryFilter_index = 6;
|
||||
break;
|
||||
case 'updateConnections':
|
||||
sendAsset.updateConnections(message.connections);
|
||||
|
|
|
@ -62,7 +62,7 @@ Item {
|
|||
isExpanded: false;
|
||||
question: "How can I get HFC?";
|
||||
answer: "High Fidelity commerce is in open beta right now. Want more HFC? \
|
||||
Get it by going to <br><br><b><font color='#0093C5'><a href='#bank'>BankOfHighFidelity.</a></font></b> and meeting with the banker!";
|
||||
Get it by going to <b><font color='#0093C5'><a href='#bank'>BankOfHighFidelity</a></font></b> and meeting with the banker!";
|
||||
}
|
||||
ListElement {
|
||||
isExpanded: false;
|
||||
|
@ -74,8 +74,7 @@ In your Wallet's Send Money tab, choose from your list of connections, or choose
|
|||
isExpanded: false;
|
||||
question: "What is a Security Pic?"
|
||||
answer: "Your Security Pic acts as an extra layer of Wallet security. \
|
||||
When you see your Security Pic, you know that your actions and data are securely making use of your account. \
|
||||
<br><br><b><font color='#0093C5'><a href='#securitypic'>Tap here to change your Security Pic.</a></font></b>";
|
||||
When you see your Security Pic, you know that your actions and data are securely making use of your account.";
|
||||
}
|
||||
ListElement {
|
||||
isExpanded: false;
|
||||
|
@ -137,7 +136,7 @@ At the moment, there is currently no way to convert HFC to other currencies. Sta
|
|||
anchors.left: parent.left;
|
||||
width: parent.width;
|
||||
height: questionText.paintedHeight + 50;
|
||||
|
||||
|
||||
RalewaySemiBold {
|
||||
id: plusMinusButton;
|
||||
text: model.isExpanded ? "-" : "+";
|
||||
|
@ -217,8 +216,6 @@ At the moment, there is currently no way to convert HFC to other currencies. Sta
|
|||
}
|
||||
} else if (link === "#support") {
|
||||
Qt.openUrlExternally("mailto:support@highfidelity.com");
|
||||
} else if (link === "#securitypic") {
|
||||
sendSignalToWallet({method: 'walletSecurity_changeSecurityImage'});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ Item {
|
|||
// Text below helper text
|
||||
RalewayRegular {
|
||||
id: loginDetailText;
|
||||
text: "To buy/sell items on the <b>Marketplace</b>, or to use your <b>Wallet</b>, you must first log in to High Fidelity.";
|
||||
text: "To get items on the <b>Marketplace</b>, or to use your <b>Assets</b>, you must first log in to High Fidelity.";
|
||||
// Text size
|
||||
size: 18;
|
||||
// Anchors
|
||||
|
|
|
@ -1,246 +0,0 @@
|
|||
//
|
||||
// Security.qml
|
||||
// qml/hifi/commerce/wallet
|
||||
//
|
||||
// Security
|
||||
//
|
||||
// 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 QtGraphicalEffects 1.0
|
||||
import "../../../styles-uit"
|
||||
import "../../../controls-uit" as HifiControlsUit
|
||||
import "../../../controls" as HifiControls
|
||||
|
||||
// references XXX from root context
|
||||
|
||||
Item {
|
||||
HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
property string keyFilePath;
|
||||
|
||||
Connections {
|
||||
target: Commerce;
|
||||
|
||||
onKeyFilePathIfExistsResult: {
|
||||
root.keyFilePath = path;
|
||||
}
|
||||
}
|
||||
|
||||
// Username Text
|
||||
RalewayRegular {
|
||||
id: usernameText;
|
||||
text: Account.username;
|
||||
// Text size
|
||||
size: 24;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
elide: Text.ElideRight;
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 20;
|
||||
width: parent.width/2;
|
||||
height: 80;
|
||||
}
|
||||
|
||||
Item {
|
||||
id: securityContainer;
|
||||
anchors.top: usernameText.bottom;
|
||||
anchors.topMargin: 20;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.bottom: parent.bottom;
|
||||
|
||||
RalewaySemiBold {
|
||||
id: securityText;
|
||||
text: "Security";
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 20;
|
||||
anchors.right: parent.right;
|
||||
height: 30;
|
||||
// Text size
|
||||
size: 18;
|
||||
// Style
|
||||
color: hifi.colors.blueHighlight;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: securityTextSeparator;
|
||||
// Size
|
||||
width: parent.width;
|
||||
height: 1;
|
||||
// Anchors
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.top: securityText.bottom;
|
||||
anchors.topMargin: 8;
|
||||
// Style
|
||||
color: hifi.colors.faintGray;
|
||||
}
|
||||
|
||||
Item {
|
||||
id: changeSecurityImageContainer;
|
||||
anchors.top: securityTextSeparator.bottom;
|
||||
anchors.topMargin: 8;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 40;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 55;
|
||||
height: 75;
|
||||
|
||||
HiFiGlyphs {
|
||||
id: changeSecurityImageImage;
|
||||
text: hifi.glyphs.securityImage;
|
||||
// Size
|
||||
size: 80;
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.left: parent.left;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
text: "Security Pic";
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.left: changeSecurityImageImage.right;
|
||||
anchors.leftMargin: 30;
|
||||
width: 50;
|
||||
// Text size
|
||||
size: 18;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
}
|
||||
|
||||
// "Change Security Pic" button
|
||||
HifiControlsUit.Button {
|
||||
id: changeSecurityImageButton;
|
||||
color: hifi.buttons.blue;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.right: parent.right;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
width: 140;
|
||||
height: 40;
|
||||
text: "Change";
|
||||
onClicked: {
|
||||
sendSignalToWallet({method: 'walletSecurity_changeSecurityImage'});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: autoLogoutContainer;
|
||||
anchors.top: changeSecurityImageContainer.bottom;
|
||||
anchors.topMargin: 8;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 40;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 55;
|
||||
height: 75;
|
||||
|
||||
HiFiGlyphs {
|
||||
id: autoLogoutImage;
|
||||
text: hifi.glyphs.walletKey;
|
||||
// Size
|
||||
size: 80;
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 20;
|
||||
anchors.left: parent.left;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
}
|
||||
|
||||
HifiControlsUit.CheckBox {
|
||||
id: autoLogoutCheckbox;
|
||||
checked: Settings.getValue("wallet/autoLogout", false);
|
||||
text: "Automatically Log Out when Exiting Interface"
|
||||
// Anchors
|
||||
anchors.verticalCenter: autoLogoutImage.verticalCenter;
|
||||
anchors.left: autoLogoutImage.right;
|
||||
anchors.leftMargin: 20;
|
||||
anchors.right: autoLogoutHelp.left;
|
||||
anchors.rightMargin: 12;
|
||||
boxSize: 28;
|
||||
labelFontSize: 18;
|
||||
color: hifi.colors.white;
|
||||
onCheckedChanged: {
|
||||
Settings.setValue("wallet/autoLogout", checked);
|
||||
if (checked) {
|
||||
Settings.setValue("wallet/savedUsername", Account.username);
|
||||
} else {
|
||||
Settings.setValue("wallet/savedUsername", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
id: autoLogoutHelp;
|
||||
text: '[?]';
|
||||
// Anchors
|
||||
anchors.verticalCenter: autoLogoutImage.verticalCenter;
|
||||
anchors.right: parent.right;
|
||||
width: 30;
|
||||
height: 30;
|
||||
// Text size
|
||||
size: 18;
|
||||
// Style
|
||||
color: hifi.colors.blueHighlight;
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
hoverEnabled: true;
|
||||
onEntered: {
|
||||
parent.color = hifi.colors.blueAccent;
|
||||
}
|
||||
onExited: {
|
||||
parent.color = hifi.colors.blueHighlight;
|
||||
}
|
||||
onClicked: {
|
||||
sendSignalToWallet({method: 'walletSecurity_autoLogoutHelp'});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// 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
|
||||
//
|
||||
}
|
|
@ -20,6 +20,8 @@ import "../../../controls" as HifiControls
|
|||
import "../common" as HifiCommerceCommon
|
||||
import "../common/sendAsset"
|
||||
import "../.." as HifiCommon
|
||||
import "../purchases" as HifiPurchases
|
||||
import "../inspectionCertificate" as HifiInspectionCertificate
|
||||
|
||||
Rectangle {
|
||||
HifiConstants { id: hifi; }
|
||||
|
@ -27,6 +29,7 @@ Rectangle {
|
|||
id: root;
|
||||
|
||||
property string activeView: "initialize";
|
||||
property string initialActiveViewAfterStatus5: "walletInventory";
|
||||
property bool keyboardRaised: false;
|
||||
property bool isPassword: false;
|
||||
|
||||
|
@ -64,7 +67,8 @@ Rectangle {
|
|||
}
|
||||
} else if (walletStatus === 5) {
|
||||
if (root.activeView !== "walletSetup") {
|
||||
root.activeView = "walletHome";
|
||||
root.activeView = root.initialActiveViewAfterStatus5;
|
||||
Commerce.getAvailableUpdates();
|
||||
Commerce.getSecurityImage();
|
||||
}
|
||||
} else {
|
||||
|
@ -86,6 +90,21 @@ Rectangle {
|
|||
titleBarSecurityImage.source = "image://security/securityImage";
|
||||
}
|
||||
}
|
||||
|
||||
onAvailableUpdatesResult: {
|
||||
if (result.status !== 'success') {
|
||||
console.log("Failed to get Available Updates", result.data.message);
|
||||
} else {
|
||||
exchangeMoneyButtonContainer.messagesWaiting = result.data.updates.length > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onActiveViewChanged: {
|
||||
if (activeView === "walletHome") {
|
||||
walletHomeButtonContainer.messagesWaiting = false;
|
||||
sendToScript({method: 'clearShouldShowDotHistory'});
|
||||
}
|
||||
}
|
||||
|
||||
HifiCommerceCommon.CommerceLightbox {
|
||||
|
@ -108,29 +127,32 @@ Rectangle {
|
|||
anchors.top: parent.top;
|
||||
|
||||
// Wallet icon
|
||||
HiFiGlyphs {
|
||||
Image {
|
||||
id: walletIcon;
|
||||
text: hifi.glyphs.wallet;
|
||||
// Size
|
||||
size: parent.height * 0.8;
|
||||
// Anchors
|
||||
source: "../../../../icons/tablet-icons/inventory-a.svg";
|
||||
height: parent.height * 0.5;
|
||||
width: walletIcon.height;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 8;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
// Style
|
||||
visible: false; // When we use a white .svg instead of a glyph with color property, we set to invisible and use the following ColorOverlay.
|
||||
}
|
||||
ColorOverlay {
|
||||
anchors.fill: walletIcon;
|
||||
source: walletIcon;
|
||||
color: hifi.colors.blueHighlight;
|
||||
}
|
||||
|
||||
// Title Bar text
|
||||
RalewaySemiBold {
|
||||
id: titleBarText;
|
||||
text: "WALLET";
|
||||
text: "INVENTORY";
|
||||
// Text size
|
||||
size: hifi.fontSizes.overlayTitle;
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.left: walletIcon.right;
|
||||
anchors.leftMargin: 4;
|
||||
anchors.leftMargin: 6;
|
||||
anchors.bottom: parent.bottom;
|
||||
width: paintedWidth;
|
||||
// Style
|
||||
|
@ -142,7 +164,7 @@ Rectangle {
|
|||
Image {
|
||||
id: titleBarSecurityImage;
|
||||
source: "";
|
||||
visible: titleBarSecurityImage.source !== "" && !securityImageChange.visible;
|
||||
visible: titleBarSecurityImage.source !== "";
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 6;
|
||||
anchors.top: parent.top;
|
||||
|
@ -232,10 +254,6 @@ Rectangle {
|
|||
root.isPassword = msg.isPasswordField;
|
||||
} else if (msg.method === 'walletSetup_lowerKeyboard') {
|
||||
root.keyboardRaised = false;
|
||||
} else if (msg.method === 'walletSecurity_changePassphraseCancelled') {
|
||||
root.activeView = "security";
|
||||
} else if (msg.method === 'walletSecurity_changePassphraseSuccess') {
|
||||
root.activeView = "security";
|
||||
} else {
|
||||
sendToScript(msg);
|
||||
}
|
||||
|
@ -245,27 +263,6 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
SecurityImageChange {
|
||||
id: securityImageChange;
|
||||
visible: root.activeView === "securityImageChange";
|
||||
z: 997;
|
||||
anchors.top: titleBarContainer.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.bottom: parent.bottom;
|
||||
|
||||
Connections {
|
||||
onSendSignalToWallet: {
|
||||
if (msg.method === 'walletSecurity_changeSecurityImageCancelled') {
|
||||
root.activeView = "security";
|
||||
} else if (msg.method === 'walletSecurity_changeSecurityImageSuccess') {
|
||||
root.activeView = "security";
|
||||
} else {
|
||||
sendToScript(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TAB CONTENTS START
|
||||
|
@ -344,6 +341,39 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
HifiInspectionCertificate.InspectionCertificate {
|
||||
id: inspectionCertificate;
|
||||
z: 998;
|
||||
visible: false;
|
||||
anchors.fill: parent;
|
||||
|
||||
Connections {
|
||||
onSendToScript: {
|
||||
sendToScript(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiPurchases.Purchases {
|
||||
id: walletInventory;
|
||||
visible: root.activeView === "walletInventory";
|
||||
anchors.top: titleBarContainer.bottom;
|
||||
anchors.bottom: !WalletScriptingInterface.limitedCommerce ? tabButtonsContainer.top : parent.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
Connections {
|
||||
onSendToScript: {
|
||||
if (message.method === 'purchases_itemCertificateClicked') {
|
||||
inspectionCertificate.visible = true;
|
||||
inspectionCertificate.isLightbox = true;
|
||||
sendToScript(message);
|
||||
} else {
|
||||
sendToScript(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiCommon.RootHttpRequest {
|
||||
id: http;
|
||||
}
|
||||
|
@ -366,39 +396,6 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
Security {
|
||||
id: security;
|
||||
visible: root.activeView === "security";
|
||||
anchors.top: titleBarContainer.bottom;
|
||||
anchors.bottom: tabButtonsContainer.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
|
||||
Connections {
|
||||
onSendSignalToWallet: {
|
||||
if (msg.method === 'walletSecurity_changePassphrase') {
|
||||
root.activeView = "passphraseChange";
|
||||
passphraseChange.clearPassphraseFields();
|
||||
passphraseChange.resetSubmitButton();
|
||||
} else if (msg.method === 'walletSecurity_changeSecurityImage') {
|
||||
securityImageChange.initModel();
|
||||
root.activeView = "securityImageChange";
|
||||
} else if (msg.method === 'walletSecurity_autoLogoutHelp') {
|
||||
lightboxPopup.titleText = "Automatically Log Out";
|
||||
lightboxPopup.bodyText = "By default, after you log in to High Fidelity, you will stay logged in to your High Fidelity " +
|
||||
"account even after you close and re-open Interface. This means anyone who opens Interface on your computer " +
|
||||
"could make purchases with your Wallet.\n\n" +
|
||||
"If you do not want to stay logged in across Interface sessions, check this box.";
|
||||
lightboxPopup.button1text = "CLOSE";
|
||||
lightboxPopup.button1method = function() {
|
||||
lightboxPopup.visible = false;
|
||||
}
|
||||
lightboxPopup.visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Help {
|
||||
id: help;
|
||||
visible: root.activeView === "help";
|
||||
|
@ -407,14 +404,6 @@ Rectangle {
|
|||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
|
||||
Connections {
|
||||
onSendSignalToWallet: {
|
||||
if (msg.method === 'walletSecurity_changeSecurityImage') {
|
||||
securityImageChange.initModel();
|
||||
root.activeView = "securityImageChange";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -427,8 +416,8 @@ Rectangle {
|
|||
//
|
||||
Item {
|
||||
id: tabButtonsContainer;
|
||||
visible: !needsLogIn.visible && root.activeView !== "passphraseChange" && root.activeView !== "securityImageChange" && sendMoney.currentActiveView !== "sendAssetStep";
|
||||
property int numTabs: 5;
|
||||
visible: !needsLogIn.visible && root.activeView !== "passphraseChange" && sendMoney.currentActiveView !== "sendAssetStep" && !WalletScriptingInterface.limitedCommerce;
|
||||
property int numTabs: 4;
|
||||
// Size
|
||||
width: root.width;
|
||||
height: 90;
|
||||
|
@ -446,16 +435,17 @@ Rectangle {
|
|||
// "WALLET HOME" tab button
|
||||
Rectangle {
|
||||
id: walletHomeButtonContainer;
|
||||
property bool messagesWaiting: false;
|
||||
visible: !walletSetup.visible;
|
||||
color: root.activeView === "walletHome" ? hifi.colors.blueAccent : hifi.colors.black;
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.left: exchangeMoneyButtonContainer.right;
|
||||
anchors.bottom: parent.bottom;
|
||||
width: parent.width / tabButtonsContainer.numTabs;
|
||||
|
||||
HiFiGlyphs {
|
||||
id: homeTabIcon;
|
||||
text: hifi.glyphs.home2;
|
||||
text: hifi.glyphs.leftRightArrows;
|
||||
// Size
|
||||
size: 50;
|
||||
// Anchors
|
||||
|
@ -463,11 +453,24 @@ Rectangle {
|
|||
anchors.top: parent.top;
|
||||
anchors.topMargin: -2;
|
||||
// Style
|
||||
color: root.activeView === "walletHome" || walletHomeTabMouseArea.containsMouse ? hifi.colors.white : hifi.colors.blueHighlight;
|
||||
color: WalletScriptingInterface.limitedCommerce ? hifi.colors.lightGray50 : ((root.activeView === "walletHome" || walletHomeTabMouseArea.containsMouse) ? hifi.colors.white : hifi.colors.blueHighlight);
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: recentActivityMessagesWaitingLight;
|
||||
visible: parent.messagesWaiting;
|
||||
anchors.right: homeTabIcon.left;
|
||||
anchors.rightMargin: -4;
|
||||
anchors.top: homeTabIcon.top;
|
||||
anchors.topMargin: 16;
|
||||
height: 10;
|
||||
width: height;
|
||||
radius: height/2;
|
||||
color: "red";
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
text: "WALLET HOME";
|
||||
text: "RECENT ACTIVITY";
|
||||
// Text size
|
||||
size: 16;
|
||||
// Anchors
|
||||
|
@ -478,7 +481,7 @@ Rectangle {
|
|||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 4;
|
||||
// Style
|
||||
color: root.activeView === "walletHome" || walletHomeTabMouseArea.containsMouse ? hifi.colors.white : hifi.colors.blueHighlight;
|
||||
color: WalletScriptingInterface.limitedCommerce ? hifi.colors.lightGray50 : ((root.activeView === "walletHome" || walletHomeTabMouseArea.containsMouse) ? hifi.colors.white : hifi.colors.blueHighlight);
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
|
@ -487,6 +490,7 @@ Rectangle {
|
|||
MouseArea {
|
||||
id: walletHomeTabMouseArea;
|
||||
anchors.fill: parent;
|
||||
enabled: !WalletScriptingInterface.limitedCommerce;
|
||||
hoverEnabled: enabled;
|
||||
onClicked: {
|
||||
root.activeView = "walletHome";
|
||||
|
@ -500,28 +504,46 @@ Rectangle {
|
|||
// "EXCHANGE MONEY" tab button
|
||||
Rectangle {
|
||||
id: exchangeMoneyButtonContainer;
|
||||
property bool messagesWaiting: false;
|
||||
|
||||
visible: !walletSetup.visible;
|
||||
color: hifi.colors.black;
|
||||
color: root.activeView === "walletInventory" ? hifi.colors.blueAccent : hifi.colors.black;
|
||||
anchors.top: parent.top;
|
||||
anchors.left: walletHomeButtonContainer.right;
|
||||
anchors.left: parent.left;
|
||||
anchors.bottom: parent.bottom;
|
||||
width: parent.width / tabButtonsContainer.numTabs;
|
||||
|
||||
HiFiGlyphs {
|
||||
Image {
|
||||
id: exchangeMoneyTabIcon;
|
||||
text: hifi.glyphs.leftRightArrows;
|
||||
// Size
|
||||
size: 50;
|
||||
// Anchors
|
||||
source: "images/items-tab-a.svg";
|
||||
height: 25;
|
||||
width: exchangeMoneyTabIcon.height;
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: -2;
|
||||
// Style
|
||||
color: hifi.colors.lightGray50;
|
||||
anchors.topMargin: 10;
|
||||
visible: false; // When we use a white .svg instead of a glyph with color property, we set to invisible and use the following ColorOverlay.
|
||||
}
|
||||
ColorOverlay {
|
||||
anchors.fill: exchangeMoneyTabIcon;
|
||||
source: exchangeMoneyTabIcon;
|
||||
color: root.activeView === "walletInventory" || inventoryTabMouseArea.containsMouse ? hifi.colors.white : hifi.colors.blueHighlight;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: exchangeMoneyMessagesWaitingLight;
|
||||
visible: parent.messagesWaiting;
|
||||
anchors.right: exchangeMoneyTabIcon.left;
|
||||
anchors.rightMargin: 9;
|
||||
anchors.top: exchangeMoneyTabIcon.top;
|
||||
anchors.topMargin: 4;
|
||||
height: 10;
|
||||
width: height;
|
||||
radius: height/2;
|
||||
color: "red";
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
text: "EXCHANGE MONEY";
|
||||
text: "ITEMS";
|
||||
// Text size
|
||||
size: 16;
|
||||
// Anchors
|
||||
|
@ -532,12 +554,24 @@ Rectangle {
|
|||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 4;
|
||||
// Style
|
||||
color: hifi.colors.lightGray50;
|
||||
color: root.activeView === "walletInventory" || inventoryTabMouseArea.containsMouse ? hifi.colors.white : hifi.colors.blueHighlight;
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignTop;
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: inventoryTabMouseArea;
|
||||
anchors.fill: parent;
|
||||
hoverEnabled: enabled;
|
||||
onClicked: {
|
||||
root.activeView = "walletInventory";
|
||||
tabButtonsContainer.resetTabButtonColors();
|
||||
}
|
||||
onEntered: parent.color = hifi.colors.blueHighlight;
|
||||
onExited: parent.color = root.activeView === "walletInventory" ? hifi.colors.blueAccent : hifi.colors.black;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -547,7 +581,7 @@ Rectangle {
|
|||
visible: !walletSetup.visible;
|
||||
color: root.activeView === "sendMoney" ? hifi.colors.blueAccent : hifi.colors.black;
|
||||
anchors.top: parent.top;
|
||||
anchors.left: exchangeMoneyButtonContainer.right;
|
||||
anchors.left: walletHomeButtonContainer.right;
|
||||
anchors.bottom: parent.bottom;
|
||||
width: parent.width / tabButtonsContainer.numTabs;
|
||||
|
||||
|
@ -561,7 +595,7 @@ Rectangle {
|
|||
anchors.top: parent.top;
|
||||
anchors.topMargin: -2;
|
||||
// Style
|
||||
color: root.activeView === "sendMoney" || sendMoneyTabMouseArea.containsMouse ? hifi.colors.white : hifi.colors.blueHighlight;
|
||||
color: WalletScriptingInterface.limitedCommerce ? hifi.colors.lightGray50 : ((root.activeView === "sendMoney" || sendMoneyTabMouseArea.containsMouse) ? hifi.colors.white : hifi.colors.blueHighlight);
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
|
@ -576,7 +610,7 @@ Rectangle {
|
|||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 4;
|
||||
// Style
|
||||
color: root.activeView === "sendMoney" || sendMoneyTabMouseArea.containsMouse ? hifi.colors.white : hifi.colors.blueHighlight;
|
||||
color: WalletScriptingInterface.limitedCommerce ? hifi.colors.lightGray50 : ((root.activeView === "sendMoney" || sendMoneyTabMouseArea.containsMouse) ? hifi.colors.white : hifi.colors.blueHighlight);
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
|
@ -586,6 +620,7 @@ Rectangle {
|
|||
MouseArea {
|
||||
id: sendMoneyTabMouseArea;
|
||||
anchors.fill: parent;
|
||||
enabled: !WalletScriptingInterface.limitedCommerce;
|
||||
hoverEnabled: enabled;
|
||||
onClicked: {
|
||||
root.activeView = "sendMoney";
|
||||
|
@ -596,67 +631,13 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
// "SECURITY" tab button
|
||||
Rectangle {
|
||||
id: securityButtonContainer;
|
||||
visible: !walletSetup.visible;
|
||||
color: root.activeView === "security" ? hifi.colors.blueAccent : hifi.colors.black;
|
||||
anchors.top: parent.top;
|
||||
anchors.left: sendMoneyButtonContainer.right;
|
||||
anchors.bottom: parent.bottom;
|
||||
width: parent.width / tabButtonsContainer.numTabs;
|
||||
|
||||
HiFiGlyphs {
|
||||
id: securityTabIcon;
|
||||
text: hifi.glyphs.lock;
|
||||
// Size
|
||||
size: 38;
|
||||
// Anchors
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 2;
|
||||
// Style
|
||||
color: root.activeView === "security" || securityTabMouseArea.containsMouse ? hifi.colors.white : hifi.colors.blueHighlight;
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
text: "SECURITY";
|
||||
// Text size
|
||||
size: 16;
|
||||
// Anchors
|
||||
anchors.bottom: parent.bottom;
|
||||
height: parent.height/2;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 4;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 4;
|
||||
// Style
|
||||
color: root.activeView === "security" || securityTabMouseArea.containsMouse ? hifi.colors.white : hifi.colors.blueHighlight;
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignTop;
|
||||
}
|
||||
MouseArea {
|
||||
id: securityTabMouseArea;
|
||||
anchors.fill: parent;
|
||||
hoverEnabled: enabled;
|
||||
onClicked: {
|
||||
root.activeView = "security";
|
||||
tabButtonsContainer.resetTabButtonColors();
|
||||
}
|
||||
onEntered: parent.color = hifi.colors.blueHighlight;
|
||||
onExited: parent.color = root.activeView === "security" ? hifi.colors.blueAccent : hifi.colors.black;
|
||||
}
|
||||
}
|
||||
|
||||
// "HELP" tab button
|
||||
Rectangle {
|
||||
id: helpButtonContainer;
|
||||
visible: !walletSetup.visible;
|
||||
color: root.activeView === "help" ? hifi.colors.blueAccent : hifi.colors.black;
|
||||
anchors.top: parent.top;
|
||||
anchors.left: securityButtonContainer.right;
|
||||
anchors.left: sendMoneyButtonContainer.right;
|
||||
anchors.bottom: parent.bottom;
|
||||
width: parent.width / tabButtonsContainer.numTabs;
|
||||
|
||||
|
@ -708,16 +689,16 @@ Rectangle {
|
|||
function resetTabButtonColors() {
|
||||
walletHomeButtonContainer.color = hifi.colors.black;
|
||||
sendMoneyButtonContainer.color = hifi.colors.black;
|
||||
securityButtonContainer.color = hifi.colors.black;
|
||||
helpButtonContainer.color = hifi.colors.black;
|
||||
exchangeMoneyButtonContainer.color = hifi.colors.black;
|
||||
if (root.activeView === "walletHome") {
|
||||
walletHomeButtonContainer.color = hifi.colors.blueAccent;
|
||||
} else if (root.activeView === "sendMoney") {
|
||||
sendMoneyButtonContainer.color = hifi.colors.blueAccent;
|
||||
} else if (root.activeView === "security") {
|
||||
securityButtonContainer.color = hifi.colors.blueAccent;
|
||||
} else if (root.activeView === "help") {
|
||||
helpButtonContainer.color = hifi.colors.blueAccent;
|
||||
} else if (root.activeView == "walletInventory") {
|
||||
exchangeMoneyButtonContainer.color = hifi.colors.blueAccent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -783,18 +764,40 @@ Rectangle {
|
|||
break;
|
||||
case 'updateConnections':
|
||||
sendMoney.updateConnections(message.connections);
|
||||
walletInventory.fromScript(message);
|
||||
break;
|
||||
case 'selectRecipient':
|
||||
case 'updateSelectedRecipientUsername':
|
||||
sendMoney.fromScript(message);
|
||||
walletInventory.fromScript(message);
|
||||
break;
|
||||
case 'http.response':
|
||||
http.handleHttpResponse(message);
|
||||
// Duplicate handler is required because we don't track referrer for `http`
|
||||
walletInventory.fromScript(message);
|
||||
break;
|
||||
case 'palIsStale':
|
||||
case 'avatarDisconnected':
|
||||
// Because we don't have "channels" for sending messages to a specific QML object, the messages are broadcast to all QML Items. If an Item of yours happens to be visible when some script sends a message with a method you don't expect, you'll get "Unrecognized message..." logs.
|
||||
break;
|
||||
case 'inspectionCertificate_setCertificateId':
|
||||
inspectionCertificate.fromScript(message);
|
||||
break;
|
||||
case 'updatePurchases':
|
||||
case 'purchases_showMyItems':
|
||||
case 'updateWearables':
|
||||
walletInventory.fromScript(message);
|
||||
break;
|
||||
case 'updateRecentActivityMessageLight':
|
||||
walletHomeButtonContainer.messagesWaiting = message.messagesWaiting;
|
||||
break;
|
||||
case 'checkout_openRecentActivity':
|
||||
if (root.activeView === "initialize") {
|
||||
root.initialActiveViewAfterStatus5 = "walletHome";
|
||||
} else {
|
||||
root.activeView = "walletHome";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log('Unrecognized message from wallet.js:', JSON.stringify(message));
|
||||
}
|
||||
|
@ -842,7 +845,8 @@ Rectangle {
|
|||
root.activeView = "initialize";
|
||||
Commerce.getWalletStatus();
|
||||
} else if (msg.referrer === 'purchases') {
|
||||
sendToScript({method: 'goToPurchases'});
|
||||
root.activeView = "walletInventory";
|
||||
tabButtonsContainer.resetTabButtonColors();
|
||||
} else if (msg.referrer === 'marketplace cta' || msg.referrer === 'mainPage') {
|
||||
sendToScript({method: 'goToMarketplaceMainPage', itemId: msg.referrer});
|
||||
} else {
|
||||
|
|
|
@ -179,28 +179,6 @@ Item {
|
|||
color: hifi.colors.baseGrayHighlight;
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
id: myPurchasesLink;
|
||||
text: '<font color="#0093C5"><a href="#myPurchases">My Purchases</a></font>';
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 26;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 20;
|
||||
width: paintedWidth;
|
||||
height: 30;
|
||||
y: 4;
|
||||
// Text size
|
||||
size: 18;
|
||||
// Style
|
||||
color: hifi.colors.baseGrayHighlight;
|
||||
horizontalAlignment: Text.AlignRight;
|
||||
|
||||
onLinkActivated: {
|
||||
sendSignalToWallet({method: 'goToPurchases_fromWalletHome'});
|
||||
}
|
||||
}
|
||||
|
||||
HifiModels.PSFListModel {
|
||||
id: transactionHistoryModel;
|
||||
property int lastPendingCount: 0;
|
||||
|
|
|
@ -243,7 +243,6 @@ Item {
|
|||
height: 50;
|
||||
text: "Set Up Wallet";
|
||||
onClicked: {
|
||||
securityImageSelection.initModel();
|
||||
root.activeView = "step_2";
|
||||
}
|
||||
}
|
||||
|
@ -267,124 +266,6 @@ Item {
|
|||
// FIRST PAGE END
|
||||
//
|
||||
|
||||
//
|
||||
// SECURITY IMAGE SELECTION START
|
||||
//
|
||||
Item {
|
||||
id: securityImageContainer;
|
||||
visible: root.activeView === "step_2";
|
||||
// Anchors
|
||||
anchors.top: titleBarContainer.bottom;
|
||||
anchors.topMargin: 30;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 16;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 16;
|
||||
|
||||
// Text below title bar
|
||||
RalewayRegular {
|
||||
id: securityImageTitleHelper;
|
||||
text: "Choose a Security Pic:";
|
||||
// Text size
|
||||
size: 24;
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
height: 50;
|
||||
width: paintedWidth;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHLeft;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
|
||||
SecurityImageSelection {
|
||||
id: securityImageSelection;
|
||||
// Anchors
|
||||
anchors.top: securityImageTitleHelper.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
height: 300;
|
||||
|
||||
Connections {
|
||||
onSendSignalToWallet: {
|
||||
sendSignalToWallet(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Text below security images
|
||||
RalewayRegular {
|
||||
text: "<b>Your security picture shows you that the service asking for your passphrase is authorized.</b> You can change your secure picture at any time.";
|
||||
// Text size
|
||||
size: 18;
|
||||
// Anchors
|
||||
anchors.top: securityImageSelection.bottom;
|
||||
anchors.topMargin: 40;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
wrapMode: Text.WordWrap;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHLeft;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
|
||||
// Navigation Bar
|
||||
Item {
|
||||
// Size
|
||||
width: parent.width;
|
||||
height: 50;
|
||||
// Anchors:
|
||||
anchors.left: parent.left;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.bottomMargin: 50;
|
||||
|
||||
// "Back" button
|
||||
HifiControlsUit.Button {
|
||||
color: hifi.buttons.noneBorderlessWhite;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 20;
|
||||
width: 200;
|
||||
text: "Back"
|
||||
onClicked: {
|
||||
securityImageSelection.resetSelection();
|
||||
root.activeView = "step_1";
|
||||
}
|
||||
}
|
||||
|
||||
// "Next" button
|
||||
HifiControlsUit.Button {
|
||||
enabled: securityImageSelection.currentIndex !== -1;
|
||||
color: hifi.buttons.blue;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 20;
|
||||
width: 200;
|
||||
text: "Next";
|
||||
onClicked: {
|
||||
root.lastPage = "step_2";
|
||||
var securityImagePath = securityImageSelection.getImagePathFromImageID(securityImageSelection.getSelectedImageIndex())
|
||||
Commerce.chooseSecurityImage(securityImagePath);
|
||||
root.activeView = "step_3";
|
||||
passphraseSelection.clearPassphraseFields();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// SECURITY IMAGE SELECTION END
|
||||
//
|
||||
|
||||
//
|
||||
// SECURE PASSPHRASE SELECTION START
|
||||
//
|
||||
|
@ -525,7 +406,6 @@ Item {
|
|||
width: 200;
|
||||
text: "Back"
|
||||
onClicked: {
|
||||
securityImageSelection.resetSelection();
|
||||
root.lastPage = "step_3";
|
||||
root.activeView = "step_2";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<svg width="26" height="24" viewBox="0 0 26 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<line x1="6" y1="2" x2="26" y2="2" stroke="white" stroke-width="4"/>
|
||||
<line x1="1.74846e-07" y1="2" x2="4" y2="2" stroke="white" stroke-width="4"/>
|
||||
<line x1="6" y1="12" x2="26" y2="12" stroke="white" stroke-width="4"/>
|
||||
<line x1="1.74846e-07" y1="12" x2="4" y2="12" stroke="white" stroke-width="4"/>
|
||||
<line x1="6" y1="22" x2="26" y2="22" stroke="white" stroke-width="4"/>
|
||||
<line x1="1.74846e-07" y1="22" x2="4" y2="22" stroke="white" stroke-width="4"/>
|
||||
</svg>
|
After Width: | Height: | Size: 552 B |
344
interface/resources/qml/hifi/dialogs/security/Security.qml
Normal file
|
@ -0,0 +1,344 @@
|
|||
//
|
||||
// Security.qml
|
||||
// qml\hifi\dialogs\security
|
||||
//
|
||||
// Security
|
||||
//
|
||||
// Created by Zach Fox on 2018-10-31
|
||||
// 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 "qrc:////qml//styles-uit" as HifiStylesUit
|
||||
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||
import "qrc:////qml//controls" as HifiControls
|
||||
import "qrc:////qml//hifi//commerce//common" as HifiCommerceCommon
|
||||
|
||||
Rectangle {
|
||||
HifiStylesUit.HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
color: hifi.colors.baseGray;
|
||||
|
||||
property string title: "Security Settings";
|
||||
property bool walletSetUp;
|
||||
|
||||
QtObject {
|
||||
id: margins
|
||||
property real paddings: root.width / 20.25
|
||||
|
||||
property real sizeCheckBox: root.width / 13.5
|
||||
property real sizeText: root.width / 2.5
|
||||
property real sizeLevel: root.width / 5.8
|
||||
property real sizeDesktop: root.width / 5.8
|
||||
property real sizeVR: root.width / 13.5
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Commerce;
|
||||
|
||||
onWalletStatusResult: {
|
||||
if (walletStatus === 5) {
|
||||
Commerce.getSecurityImage();
|
||||
root.walletSetUp = true;
|
||||
} else {
|
||||
root.walletSetUp = false;
|
||||
}
|
||||
}
|
||||
|
||||
onSecurityImageResult: {
|
||||
if (exists) {
|
||||
currentSecurityPicture.source = "";
|
||||
currentSecurityPicture.source = "image://security/securityImage";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
Commerce.getWalletStatus();
|
||||
}
|
||||
|
||||
HifiCommerceCommon.CommerceLightbox {
|
||||
z: 996;
|
||||
id: lightboxPopup;
|
||||
visible: false;
|
||||
anchors.fill: parent;
|
||||
}
|
||||
|
||||
SecurityImageChange {
|
||||
id: securityImageChange;
|
||||
visible: false;
|
||||
z: 997;
|
||||
anchors.top: usernameText.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.bottom: parent.bottom;
|
||||
|
||||
Connections {
|
||||
onSendSignalToParent: {
|
||||
securityImageChange.visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Username Text
|
||||
HifiStylesUit.RalewayRegular {
|
||||
id: usernameText;
|
||||
text: Account.username === "Unknown user" ? "Please Log In" : Account.username;
|
||||
// Text size
|
||||
size: 24;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
elide: Text.ElideRight;
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 20;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 20;
|
||||
height: 60;
|
||||
}
|
||||
|
||||
Item {
|
||||
id: pleaseLogInContainer;
|
||||
visible: Account.username === "Unknown user";
|
||||
anchors.top: usernameText.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.bottom: parent.bottom;
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
text: "Please log in for security settings."
|
||||
// Text size
|
||||
size: 24;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
// Anchors
|
||||
anchors.bottom: openLoginButton.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
height: 60;
|
||||
}
|
||||
|
||||
HifiControlsUit.Button {
|
||||
id: openLoginButton;
|
||||
color: hifi.buttons.white;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.centerIn: parent;
|
||||
width: 140;
|
||||
height: 40;
|
||||
text: "Log In";
|
||||
onClicked: {
|
||||
DialogsManager.showLoginDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: securitySettingsContainer;
|
||||
visible: !pleaseLogInContainer.visible;
|
||||
anchors.top: usernameText.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.bottom: parent.bottom;
|
||||
|
||||
Item {
|
||||
id: accountContainer;
|
||||
anchors.top: securitySettingsContainer.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
height: childrenRect.height;
|
||||
|
||||
Rectangle {
|
||||
id: accountHeaderContainer;
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
height: 55;
|
||||
color: hifi.colors.baseGrayHighlight;
|
||||
|
||||
HifiStylesUit.RalewaySemiBold {
|
||||
text: "Account";
|
||||
anchors.fill: parent;
|
||||
anchors.leftMargin: 20;
|
||||
color: hifi.colors.white;
|
||||
size: 18;
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: keepMeLoggedInContainer;
|
||||
anchors.top: accountHeaderContainer.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
height: 80;
|
||||
|
||||
HifiControlsUit.CheckBox {
|
||||
id: autoLogoutCheckbox;
|
||||
checked: Settings.getValue("keepMeLoggedIn", false);
|
||||
text: "Keep Me Logged In"
|
||||
// Anchors
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 20;
|
||||
boxSize: 24;
|
||||
labelFontSize: 18;
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
color: hifi.colors.white;
|
||||
width: 240;
|
||||
onCheckedChanged: {
|
||||
Settings.setValue("keepMeLoggedIn", checked);
|
||||
if (checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", Account.username);
|
||||
} else {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiStylesUit.RalewaySemiBold {
|
||||
id: autoLogoutHelp;
|
||||
text: '[?]';
|
||||
// Anchors
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
anchors.right: autoLogoutCheckbox.right;
|
||||
width: 30;
|
||||
height: 30;
|
||||
// Text size
|
||||
size: 18;
|
||||
// Style
|
||||
color: hifi.colors.blueHighlight;
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
hoverEnabled: true;
|
||||
onEntered: {
|
||||
parent.color = hifi.colors.blueAccent;
|
||||
}
|
||||
onExited: {
|
||||
parent.color = hifi.colors.blueHighlight;
|
||||
}
|
||||
onClicked: {
|
||||
lightboxPopup.titleText = "Keep Me Logged In";
|
||||
lightboxPopup.bodyText = "If you choose to stay logged in, ensure that this is a trusted device.\n\n" +
|
||||
"Also, remember that logging out may not disconnect you from a domain.";
|
||||
lightboxPopup.button1text = "OK";
|
||||
lightboxPopup.button1method = function() {
|
||||
lightboxPopup.visible = false;
|
||||
}
|
||||
lightboxPopup.visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: walletContainer;
|
||||
anchors.top: accountContainer.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
height: childrenRect.height;
|
||||
|
||||
Rectangle {
|
||||
id: walletHeaderContainer;
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
height: 55;
|
||||
color: hifi.colors.baseGrayHighlight;
|
||||
|
||||
HifiStylesUit.RalewaySemiBold {
|
||||
text: "Wallet";
|
||||
anchors.fill: parent;
|
||||
anchors.leftMargin: 20;
|
||||
color: hifi.colors.white;
|
||||
size: 18;
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: walletSecurityPictureContainer;
|
||||
visible: root.walletSetUp;
|
||||
anchors.top: walletHeaderContainer.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
height: 80;
|
||||
|
||||
Image {
|
||||
id: currentSecurityPicture;
|
||||
source: "";
|
||||
visible: true;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 20;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
height: 40;
|
||||
width: height;
|
||||
mipmap: true;
|
||||
cache: false;
|
||||
}
|
||||
|
||||
HifiStylesUit.RalewaySemiBold {
|
||||
id: securityPictureText;
|
||||
text: "Wallet Security Picture";
|
||||
// Anchors
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.left: currentSecurityPicture.right;
|
||||
anchors.leftMargin: 12;
|
||||
width: paintedWidth;
|
||||
// Text size
|
||||
size: 18;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
}
|
||||
|
||||
// "Change Security Pic" button
|
||||
HifiControlsUit.Button {
|
||||
id: changeSecurityImageButton;
|
||||
color: hifi.buttons.white;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.left: securityPictureText.right;
|
||||
anchors.leftMargin: 12;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
width: 140;
|
||||
height: 40;
|
||||
text: "Change";
|
||||
onClicked: {
|
||||
securityImageChange.visible = true;
|
||||
securityImageChange.initModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: walletNotSetUpContainer;
|
||||
visible: !root.walletSetUp;
|
||||
anchors.top: walletHeaderContainer.bottom;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
height: 60;
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
text: "Your wallet is not set up.\n" +
|
||||
"Open the ASSETS app to get started.";
|
||||
// Anchors
|
||||
anchors.fill: parent;
|
||||
// Text size
|
||||
size: 18;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
//
|
||||
// SecurityImageChange.qml
|
||||
// qml/hifi/commerce/wallet
|
||||
// qml\hifi\dialogs\security
|
||||
//
|
||||
// SecurityImageChange
|
||||
// Security
|
||||
//
|
||||
// Created by Zach Fox on 2017-08-18
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Created by Zach Fox on 2018-10-31
|
||||
// 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
|
||||
|
@ -13,16 +13,17 @@
|
|||
|
||||
import Hifi 1.0 as Hifi
|
||||
import QtQuick 2.5
|
||||
import "../../../styles-uit"
|
||||
import "../../../controls-uit" as HifiControlsUit
|
||||
import "../../../controls" as HifiControls
|
||||
import "qrc:////qml//styles-uit" as HifiStylesUit
|
||||
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||
import "qrc:////qml//controls" as HifiControls
|
||||
|
||||
// references XXX from root context
|
||||
|
||||
Item {
|
||||
HifiConstants { id: hifi; }
|
||||
Rectangle {
|
||||
HifiStylesUit.HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
color: hifi.colors.baseGray;
|
||||
property bool justSubmitted: false;
|
||||
|
||||
Connections {
|
||||
|
@ -33,7 +34,7 @@ Item {
|
|||
securityImageChangePageSecurityImage.source = "image://security/securityImage";
|
||||
if (exists) { // Success submitting new security image
|
||||
if (root.justSubmitted) {
|
||||
sendSignalToWallet({method: "walletSecurity_changeSecurityImageSuccess"});
|
||||
sendSignalToParent({method: "walletSecurity_changeSecurityImageSuccess"});
|
||||
root.justSubmitted = false;
|
||||
}
|
||||
} else if (root.justSubmitted) {
|
||||
|
@ -72,7 +73,7 @@ Item {
|
|||
anchors.bottom: parent.bottom;
|
||||
height: 22;
|
||||
// Lock icon
|
||||
HiFiGlyphs {
|
||||
HifiStylesUit.HiFiGlyphs {
|
||||
id: lockIcon;
|
||||
text: hifi.glyphs.lock;
|
||||
anchors.bottom: parent.bottom;
|
||||
|
@ -83,8 +84,8 @@ Item {
|
|||
verticalAlignment: Text.AlignBottom;
|
||||
color: hifi.colors.white;
|
||||
}
|
||||
// "Security image" text below pic
|
||||
RalewayRegular {
|
||||
// "Security image" text below image
|
||||
HifiStylesUit.RalewayRegular {
|
||||
id: securityImageText;
|
||||
text: "SECURITY PIC";
|
||||
// Text size
|
||||
|
@ -116,9 +117,9 @@ Item {
|
|||
anchors.bottom: parent.bottom;
|
||||
|
||||
// "Change Security Image" text
|
||||
RalewaySemiBold {
|
||||
HifiStylesUit.RalewaySemiBold {
|
||||
id: securityImageTitle;
|
||||
text: "Change Security Pic:";
|
||||
text: "Change Security Image:";
|
||||
// Text size
|
||||
size: 18;
|
||||
anchors.top: parent.top;
|
||||
|
@ -139,12 +140,6 @@ Item {
|
|||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 16;
|
||||
height: 300;
|
||||
|
||||
Connections {
|
||||
onSendSignalToWallet: {
|
||||
sendSignalToWallet(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Navigation Bar
|
||||
|
@ -169,7 +164,7 @@ Item {
|
|||
width: 150;
|
||||
text: "Cancel"
|
||||
onClicked: {
|
||||
sendSignalToWallet({method: "walletSecurity_changeSecurityImageCancelled"});
|
||||
sendSignalToParent({method: "walletSecurity_changeSecurityImageCancelled"});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,7 +192,7 @@ Item {
|
|||
// SECURITY IMAGE SELECTION END
|
||||
//
|
||||
|
||||
signal sendSignalToWallet(var msg);
|
||||
signal sendSignalToParent(var msg);
|
||||
|
||||
function initModel() {
|
||||
securityImageSelection.initModel();
|
|
@ -1,11 +1,11 @@
|
|||
//
|
||||
// SecurityImageModel.qml
|
||||
// qml/hifi/commerce
|
||||
// qml\hifi\dialogs\security
|
||||
//
|
||||
// SecurityImageModel
|
||||
// Security
|
||||
//
|
||||
// Created by Zach Fox on 2017-08-17
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Created by Zach Fox on 2018-10-31
|
||||
// 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
|
|
@ -1,11 +1,11 @@
|
|||
//
|
||||
// SecurityImageSelection.qml
|
||||
// qml/hifi/commerce/wallet
|
||||
// qml\hifi\dialogs\security
|
||||
//
|
||||
// SecurityImageSelection
|
||||
// Security
|
||||
//
|
||||
// Created by Zach Fox on 2017-08-17
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Created by Zach Fox on 2018-10-31
|
||||
// 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
|
||||
|
@ -13,14 +13,14 @@
|
|||
|
||||
import Hifi 1.0 as Hifi
|
||||
import QtQuick 2.5
|
||||
import "../../../styles-uit"
|
||||
import "../../../controls-uit" as HifiControlsUit
|
||||
import "../../../controls" as HifiControls
|
||||
import "qrc:////qml//styles-uit" as HifiStylesUit
|
||||
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||
import "qrc:////qml//controls" as HifiControls
|
||||
|
||||
// references XXX from root context
|
||||
|
||||
Item {
|
||||
HifiConstants { id: hifi; }
|
||||
HifiStylesUit.HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
property alias currentIndex: securityImageGrid.currentIndex;
|
||||
|
@ -64,17 +64,15 @@ Item {
|
|||
}
|
||||
}
|
||||
highlight: Rectangle {
|
||||
width: securityImageGrid.cellWidth;
|
||||
height: securityImageGrid.cellHeight;
|
||||
color: hifi.colors.blueHighlight;
|
||||
}
|
||||
width: securityImageGrid.cellWidth;
|
||||
height: securityImageGrid.cellHeight;
|
||||
color: hifi.colors.blueHighlight;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// FUNCTION DEFINITIONS START
|
||||
//
|
||||
signal sendSignalToWallet(var msg);
|
||||
|
||||
function getImagePathFromImageID(imageID) {
|
||||
return (imageID ? gridModel.getImagePathFromImageID(imageID) : "");
|
||||
}
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
@ -383,7 +383,7 @@ static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds
|
|||
static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop";
|
||||
static const QString ACTIVE_DISPLAY_PLUGIN_SETTING_NAME = "activeDisplayPlugin";
|
||||
static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
|
||||
static const QString AUTO_LOGOUT_SETTING_NAME = "wallet/autoLogout";
|
||||
static const QString KEEP_ME_LOGGED_IN_SETTING_NAME = "keepMeLoggedIn";
|
||||
|
||||
const std::vector<std::pair<QString, Application::AcceptURLMethod>> Application::_acceptedExtensions {
|
||||
{ SVO_EXTENSION, &Application::importSVOFromURL },
|
||||
|
@ -1150,7 +1150,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
// set the OCULUS_STORE property so the oculus plugin can know if we ran from the Oculus Store
|
||||
static const QString OCULUS_STORE_ARG = "--oculus-store";
|
||||
setProperty(hifi::properties::OCULUS_STORE, arguments().indexOf(OCULUS_STORE_ARG) != -1);
|
||||
bool isStore = arguments().indexOf(OCULUS_STORE_ARG) != -1;
|
||||
setProperty(hifi::properties::OCULUS_STORE, isStore);
|
||||
DependencyManager::get<WalletScriptingInterface>()->setLimitedCommerce(isStore); // Or we could make it a separate arg, or if either arg is set, etc. And should this instead by a hifi::properties?
|
||||
|
||||
updateHeartbeat();
|
||||
|
||||
|
@ -2569,8 +2571,8 @@ void Application::cleanupBeforeQuit() {
|
|||
}
|
||||
DependencyManager::destroy<ScriptEngines>();
|
||||
|
||||
bool autoLogout = Setting::Handle<bool>(AUTO_LOGOUT_SETTING_NAME, false).get();
|
||||
if (autoLogout) {
|
||||
bool keepMeLoggedIn = Setting::Handle<bool>(KEEP_ME_LOGGED_IN_SETTING_NAME, false).get();
|
||||
if (!keepMeLoggedIn) {
|
||||
DependencyManager::get<AccountManager>()->removeAccountFromFile();
|
||||
}
|
||||
|
||||
|
@ -2946,14 +2948,14 @@ void Application::initializeUi() {
|
|||
QUrl{ "hifi/commerce/wallet/PassphraseChange.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/PassphraseModal.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/PassphraseSelection.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/Security.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/SecurityImageChange.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/SecurityImageModel.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/SecurityImageSelection.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/Wallet.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/WalletHome.qml" },
|
||||
QUrl{ "hifi/commerce/wallet/WalletSetup.qml" },
|
||||
}, commerceCallback);
|
||||
QUrl{ "hifi/dialogs/security/Security.qml" },
|
||||
QUrl{ "hifi/dialogs/security/SecurityImageChange.qml" },
|
||||
QUrl{ "hifi/dialogs/security/SecurityImageModel.qml" },
|
||||
QUrl{ "hifi/dialogs/security/SecurityImageSelection.qml" },
|
||||
}, callback);
|
||||
QmlContextCallback ttsCallback = [](QQmlContext* context) {
|
||||
context->setContextProperty("TextToSpeech", DependencyManager::get<TTSScriptingInterface>().data());
|
||||
};
|
||||
|
@ -3160,7 +3162,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
|
|||
surfaceContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
|
||||
surfaceContext->setContextProperty("Selection", DependencyManager::get<SelectionScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
|
||||
surfaceContext->setContextProperty("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("WalletScriptingInterface", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance());
|
||||
surfaceContext->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
|
||||
|
@ -6882,7 +6884,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
|||
scriptEngine->registerGlobalObject("AvatarInputs", AvatarInputs::getInstance());
|
||||
scriptEngine->registerGlobalObject("Selection", DependencyManager::get<SelectionScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
|
||||
scriptEngine->registerGlobalObject("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("WalletScriptingInterface", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance());
|
||||
scriptEngine->registerGlobalObject("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
|
@ -7887,6 +7889,7 @@ 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();
|
||||
|
|
|
@ -265,6 +265,18 @@ Menu::Menu() {
|
|||
QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog");
|
||||
});
|
||||
|
||||
// Settings > Security...
|
||||
action = addActionToQMenuAndActionHash(settingsMenu, "Security...");
|
||||
connect(action, &QAction::triggered, [] {
|
||||
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
|
||||
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||
tablet->pushOntoStack("hifi/dialogs/security/Security.qml");
|
||||
|
||||
if (!hmd->getShouldShowTablet()) {
|
||||
hmd->toggleShouldShowTablet();
|
||||
}
|
||||
});
|
||||
|
||||
// Settings > Developer Menu
|
||||
addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus()));
|
||||
|
||||
|
|
|
@ -109,10 +109,10 @@ bool ModelPackager::loadModel() {
|
|||
qCDebug(interfaceapp) << "Reading FBX file : " << _fbxInfo.filePath();
|
||||
QByteArray fbxContents = fbx.readAll();
|
||||
|
||||
_geometry.reset(readFBX(fbxContents, QVariantHash(), _fbxInfo.filePath()));
|
||||
_hfmModel.reset(readFBX(fbxContents, QVariantHash(), _fbxInfo.filePath()));
|
||||
|
||||
// make sure we have some basic mappings
|
||||
populateBasicMapping(_mapping, _fbxInfo.filePath(), *_geometry);
|
||||
populateBasicMapping(_mapping, _fbxInfo.filePath(), *_hfmModel);
|
||||
} catch (const QString& error) {
|
||||
qCDebug(interfaceapp) << "Error reading " << _fbxInfo.filePath() << ": " << error;
|
||||
return false;
|
||||
|
@ -122,7 +122,7 @@ bool ModelPackager::loadModel() {
|
|||
|
||||
bool ModelPackager::editProperties() {
|
||||
// open the dialog to configure the rest
|
||||
ModelPropertiesDialog properties(_modelType, _mapping, _modelFile.path(), *_geometry);
|
||||
ModelPropertiesDialog properties(_modelType, _mapping, _modelFile.path(), *_hfmModel);
|
||||
if (properties.exec() == QDialog::Rejected) {
|
||||
return false;
|
||||
}
|
||||
|
@ -235,18 +235,18 @@ bool ModelPackager::zipModel() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename, const FBXGeometry& geometry) {
|
||||
void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename, const HFMModel& hfmModel) {
|
||||
|
||||
bool isBodyType = _modelType == FSTReader::BODY_ONLY_MODEL || _modelType == FSTReader::HEAD_AND_BODY_MODEL;
|
||||
|
||||
// mixamo files - in the event that a mixamo file was edited by some other tool, it's likely the applicationName will
|
||||
// be rewritten, so we detect the existence of several different blendshapes which indicate we're likely a mixamo file
|
||||
bool likelyMixamoFile = geometry.applicationName == "mixamo.com" ||
|
||||
(geometry.blendshapeChannelNames.contains("BrowsDown_Right") &&
|
||||
geometry.blendshapeChannelNames.contains("MouthOpen") &&
|
||||
geometry.blendshapeChannelNames.contains("Blink_Left") &&
|
||||
geometry.blendshapeChannelNames.contains("Blink_Right") &&
|
||||
geometry.blendshapeChannelNames.contains("Squint_Right"));
|
||||
bool likelyMixamoFile = hfmModel.applicationName == "mixamo.com" ||
|
||||
(hfmModel.blendshapeChannelNames.contains("BrowsDown_Right") &&
|
||||
hfmModel.blendshapeChannelNames.contains("MouthOpen") &&
|
||||
hfmModel.blendshapeChannelNames.contains("Blink_Left") &&
|
||||
hfmModel.blendshapeChannelNames.contains("Blink_Right") &&
|
||||
hfmModel.blendshapeChannelNames.contains("Squint_Right"));
|
||||
|
||||
if (!mapping.contains(NAME_FIELD)) {
|
||||
mapping.insert(NAME_FIELD, QFileInfo(filename).baseName());
|
||||
|
@ -268,15 +268,15 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename
|
|||
}
|
||||
QVariantHash joints = mapping.value(JOINT_FIELD).toHash();
|
||||
if (!joints.contains("jointEyeLeft")) {
|
||||
joints.insert("jointEyeLeft", geometry.jointIndices.contains("jointEyeLeft") ? "jointEyeLeft" :
|
||||
(geometry.jointIndices.contains("EyeLeft") ? "EyeLeft" : "LeftEye"));
|
||||
joints.insert("jointEyeLeft", hfmModel.jointIndices.contains("jointEyeLeft") ? "jointEyeLeft" :
|
||||
(hfmModel.jointIndices.contains("EyeLeft") ? "EyeLeft" : "LeftEye"));
|
||||
}
|
||||
if (!joints.contains("jointEyeRight")) {
|
||||
joints.insert("jointEyeRight", geometry.jointIndices.contains("jointEyeRight") ? "jointEyeRight" :
|
||||
geometry.jointIndices.contains("EyeRight") ? "EyeRight" : "RightEye");
|
||||
joints.insert("jointEyeRight", hfmModel.jointIndices.contains("jointEyeRight") ? "jointEyeRight" :
|
||||
hfmModel.jointIndices.contains("EyeRight") ? "EyeRight" : "RightEye");
|
||||
}
|
||||
if (!joints.contains("jointNeck")) {
|
||||
joints.insert("jointNeck", geometry.jointIndices.contains("jointNeck") ? "jointNeck" : "Neck");
|
||||
joints.insert("jointNeck", hfmModel.jointIndices.contains("jointNeck") ? "jointNeck" : "Neck");
|
||||
}
|
||||
|
||||
if (isBodyType) {
|
||||
|
@ -296,7 +296,7 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename
|
|||
|
||||
if (!joints.contains("jointHead")) {
|
||||
const char* topName = likelyMixamoFile ? "HeadTop_End" : "HeadEnd";
|
||||
joints.insert("jointHead", geometry.jointIndices.contains(topName) ? topName : "Head");
|
||||
joints.insert("jointHead", hfmModel.jointIndices.contains(topName) ? topName : "Head");
|
||||
}
|
||||
|
||||
mapping.insert(JOINT_FIELD, joints);
|
||||
|
@ -370,7 +370,7 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename
|
|||
|
||||
void ModelPackager::listTextures() {
|
||||
_textures.clear();
|
||||
foreach (const FBXMaterial mat, _geometry->materials) {
|
||||
foreach (const HFMMaterial mat, _hfmModel->materials) {
|
||||
if (!mat.albedoTexture.filename.isEmpty() && mat.albedoTexture.content.isEmpty() &&
|
||||
!_textures.contains(mat.albedoTexture.filename)) {
|
||||
_textures << mat.albedoTexture.filename;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "ui/ModelsBrowser.h"
|
||||
|
||||
class FBXGeometry;
|
||||
class HFMModel;
|
||||
|
||||
class ModelPackager : public QObject {
|
||||
public:
|
||||
|
@ -32,7 +32,7 @@ private:
|
|||
bool editProperties();
|
||||
bool zipModel();
|
||||
|
||||
void populateBasicMapping(QVariantHash& mapping, QString filename, const FBXGeometry& geometry);
|
||||
void populateBasicMapping(QVariantHash& mapping, QString filename, const HFMModel& hfmModel);
|
||||
|
||||
void listTextures();
|
||||
bool copyTextures(const QString& oldDir, const QDir& newDir);
|
||||
|
@ -44,7 +44,7 @@ private:
|
|||
QString _scriptDir;
|
||||
|
||||
QVariantHash _mapping;
|
||||
std::unique_ptr<FBXGeometry> _geometry;
|
||||
std::unique_ptr<HFMModel> _hfmModel;
|
||||
QStringList _textures;
|
||||
QStringList _scripts;
|
||||
};
|
||||
|
|
|
@ -27,11 +27,11 @@
|
|||
|
||||
|
||||
ModelPropertiesDialog::ModelPropertiesDialog(FSTReader::ModelType modelType, const QVariantHash& originalMapping,
|
||||
const QString& basePath, const FBXGeometry& geometry) :
|
||||
const QString& basePath, const HFMModel& hfmModel) :
|
||||
_modelType(modelType),
|
||||
_originalMapping(originalMapping),
|
||||
_basePath(basePath),
|
||||
_geometry(geometry)
|
||||
_hfmModel(hfmModel)
|
||||
{
|
||||
setWindowTitle("Set Model Properties");
|
||||
|
||||
|
@ -108,8 +108,8 @@ QVariantHash ModelPropertiesDialog::getMapping() const {
|
|||
|
||||
// update the joint indices
|
||||
QVariantHash jointIndices;
|
||||
for (int i = 0; i < _geometry.joints.size(); i++) {
|
||||
jointIndices.insert(_geometry.joints.at(i).name, QString::number(i));
|
||||
for (int i = 0; i < _hfmModel.joints.size(); i++) {
|
||||
jointIndices.insert(_hfmModel.joints.at(i).name, QString::number(i));
|
||||
}
|
||||
mapping.insert(JOINT_INDEX_FIELD, jointIndices);
|
||||
|
||||
|
@ -118,10 +118,10 @@ QVariantHash ModelPropertiesDialog::getMapping() const {
|
|||
if (_modelType == FSTReader::ATTACHMENT_MODEL) {
|
||||
glm::vec3 pivot;
|
||||
if (_pivotAboutCenter->isChecked()) {
|
||||
pivot = (_geometry.meshExtents.minimum + _geometry.meshExtents.maximum) * 0.5f;
|
||||
pivot = (_hfmModel.meshExtents.minimum + _hfmModel.meshExtents.maximum) * 0.5f;
|
||||
|
||||
} else if (_pivotJoint->currentIndex() != 0) {
|
||||
pivot = extractTranslation(_geometry.joints.at(_pivotJoint->currentIndex() - 1).transform);
|
||||
pivot = extractTranslation(_hfmModel.joints.at(_pivotJoint->currentIndex() - 1).transform);
|
||||
}
|
||||
mapping.insert(TRANSLATION_X_FIELD, -pivot.x * (float)_scale->value() + (float)_translationX->value());
|
||||
mapping.insert(TRANSLATION_Y_FIELD, -pivot.y * (float)_scale->value() + (float)_translationY->value());
|
||||
|
@ -191,7 +191,7 @@ void ModelPropertiesDialog::reset() {
|
|||
}
|
||||
foreach (const QVariant& joint, _originalMapping.values(FREE_JOINT_FIELD)) {
|
||||
QString jointName = joint.toString();
|
||||
if (_geometry.jointIndices.contains(jointName)) {
|
||||
if (_hfmModel.jointIndices.contains(jointName)) {
|
||||
createNewFreeJoint(jointName);
|
||||
}
|
||||
}
|
||||
|
@ -249,8 +249,8 @@ QComboBox* ModelPropertiesDialog::createJointBox(bool withNone) const {
|
|||
if (withNone) {
|
||||
box->addItem("(none)");
|
||||
}
|
||||
foreach (const FBXJoint& joint, _geometry.joints) {
|
||||
if (joint.isSkeletonJoint || !_geometry.hasSkeletonJoints) {
|
||||
foreach (const HFMJoint& joint, _hfmModel.joints) {
|
||||
if (joint.isSkeletonJoint || !_hfmModel.hasSkeletonJoints) {
|
||||
box->addItem(joint.name);
|
||||
}
|
||||
}
|
||||
|
@ -266,7 +266,7 @@ QDoubleSpinBox* ModelPropertiesDialog::createTranslationBox() const {
|
|||
}
|
||||
|
||||
void ModelPropertiesDialog::insertJointMapping(QVariantHash& joints, const QString& joint, const QString& name) const {
|
||||
if (_geometry.jointIndices.contains(name)) {
|
||||
if (_hfmModel.jointIndices.contains(name)) {
|
||||
joints.insert(joint, name);
|
||||
} else {
|
||||
joints.remove(joint);
|
||||
|
|
|
@ -30,7 +30,7 @@ class ModelPropertiesDialog : public QDialog {
|
|||
|
||||
public:
|
||||
ModelPropertiesDialog(FSTReader::ModelType modelType, const QVariantHash& originalMapping,
|
||||
const QString& basePath, const FBXGeometry& geometry);
|
||||
const QString& basePath, const HFMModel& hfmModel);
|
||||
|
||||
QVariantHash getMapping() const;
|
||||
|
||||
|
@ -50,7 +50,7 @@ private:
|
|||
FSTReader::ModelType _modelType;
|
||||
QVariantHash _originalMapping;
|
||||
QString _basePath;
|
||||
FBXGeometry _geometry;
|
||||
HFMModel _hfmModel;
|
||||
QLineEdit* _name = nullptr;
|
||||
QPushButton* _textureDirectory = nullptr;
|
||||
QPushButton* _scriptDirectory = nullptr;
|
||||
|
|
|
@ -155,8 +155,8 @@ MyAvatar::MyAvatar(QThread* thread) :
|
|||
});
|
||||
connect(_skeletonModel.get(), &Model::rigReady, this, [this]() {
|
||||
if (_shouldLoadScripts) {
|
||||
auto geometry = getSkeletonModel()->getFBXGeometry();
|
||||
qApp->loadAvatarScripts(geometry.scripts);
|
||||
auto hfmModel = getSkeletonModel()->getHFMModel();
|
||||
qApp->loadAvatarScripts(hfmModel.scripts);
|
||||
_shouldLoadScripts = false;
|
||||
}
|
||||
// Load and convert old attachments to avatar entities
|
||||
|
@ -2429,10 +2429,10 @@ void MyAvatar::attachmentDataToEntityProperties(const AttachmentData& data, Enti
|
|||
void MyAvatar::initHeadBones() {
|
||||
int neckJointIndex = -1;
|
||||
if (_skeletonModel->isLoaded()) {
|
||||
neckJointIndex = _skeletonModel->getFBXGeometry().neckJointIndex;
|
||||
neckJointIndex = _skeletonModel->getHFMModel().neckJointIndex;
|
||||
}
|
||||
if (neckJointIndex == -1) {
|
||||
neckJointIndex = (_skeletonModel->getFBXGeometry().headJointIndex - 1);
|
||||
neckJointIndex = (_skeletonModel->getHFMModel().headJointIndex - 1);
|
||||
if (neckJointIndex < 0) {
|
||||
// return if the head is not even there. can't cauterize!!
|
||||
return;
|
||||
|
@ -2443,7 +2443,7 @@ void MyAvatar::initHeadBones() {
|
|||
q.push(neckJointIndex);
|
||||
_headBoneSet.insert(neckJointIndex);
|
||||
|
||||
// fbxJoints only hold links to parents not children, so we have to do a bit of extra work here.
|
||||
// hfmJoints only hold links to parents not children, so we have to do a bit of extra work here.
|
||||
while (q.size() > 0) {
|
||||
int jointIndex = q.front();
|
||||
for (int i = 0; i < _skeletonModel->getJointStateCount(); i++) {
|
||||
|
@ -2592,11 +2592,11 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
|||
|
||||
if (_skeletonModel && _skeletonModel->isLoaded()) {
|
||||
const Rig& rig = _skeletonModel->getRig();
|
||||
const FBXGeometry& geometry = _skeletonModel->getFBXGeometry();
|
||||
const HFMModel& hfmModel = _skeletonModel->getHFMModel();
|
||||
for (int i = 0; i < rig.getJointStateCount(); i++) {
|
||||
AnimPose jointPose;
|
||||
rig.getAbsoluteJointPoseInRigFrame(i, jointPose);
|
||||
const FBXJointShapeInfo& shapeInfo = geometry.joints[i].shapeInfo;
|
||||
const HFMJointShapeInfo& shapeInfo = hfmModel.joints[i].shapeInfo;
|
||||
const AnimPose pose = rigToWorldPose * jointPose;
|
||||
for (size_t j = 0; j < shapeInfo.debugLines.size() / 2; j++) {
|
||||
glm::vec3 pointA = pose.xformPoint(shapeInfo.debugLines[2 * j]);
|
||||
|
@ -4012,7 +4012,7 @@ float MyAvatar::getSitStandStateChange() const {
|
|||
}
|
||||
|
||||
QVector<QString> MyAvatar::getScriptUrls() {
|
||||
QVector<QString> scripts = _skeletonModel->isLoaded() ? _skeletonModel->getFBXGeometry().scripts : QVector<QString>();
|
||||
QVector<QString> scripts = _skeletonModel->isLoaded() ? _skeletonModel->getHFMModel().scripts : QVector<QString>();
|
||||
return scripts;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) {
|
|||
|
||||
// Called within Model::simulate call, below.
|
||||
void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||
const FBXGeometry& geometry = getFBXGeometry();
|
||||
const HFMModel& hfmModel = getHFMModel();
|
||||
|
||||
Head* head = _owningAvatar->getHead();
|
||||
|
||||
|
@ -268,19 +268,19 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
// pass detailed torso k-dops to rig.
|
||||
int hipsJoint = _rig.indexOfJoint("Hips");
|
||||
if (hipsJoint >= 0) {
|
||||
params.hipsShapeInfo = geometry.joints[hipsJoint].shapeInfo;
|
||||
params.hipsShapeInfo = hfmModel.joints[hipsJoint].shapeInfo;
|
||||
}
|
||||
int spineJoint = _rig.indexOfJoint("Spine");
|
||||
if (spineJoint >= 0) {
|
||||
params.spineShapeInfo = geometry.joints[spineJoint].shapeInfo;
|
||||
params.spineShapeInfo = hfmModel.joints[spineJoint].shapeInfo;
|
||||
}
|
||||
int spine1Joint = _rig.indexOfJoint("Spine1");
|
||||
if (spine1Joint >= 0) {
|
||||
params.spine1ShapeInfo = geometry.joints[spine1Joint].shapeInfo;
|
||||
params.spine1ShapeInfo = hfmModel.joints[spine1Joint].shapeInfo;
|
||||
}
|
||||
int spine2Joint = _rig.indexOfJoint("Spine2");
|
||||
if (spine2Joint >= 0) {
|
||||
params.spine2ShapeInfo = geometry.joints[spine2Joint].shapeInfo;
|
||||
params.spine2ShapeInfo = hfmModel.joints[spine2Joint].shapeInfo;
|
||||
}
|
||||
|
||||
_rig.updateFromControllerParameters(params, deltaTime);
|
||||
|
@ -300,8 +300,8 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
eyeParams.eyeSaccade = head->getSaccade();
|
||||
eyeParams.modelRotation = getRotation();
|
||||
eyeParams.modelTranslation = getTranslation();
|
||||
eyeParams.leftEyeJointIndex = geometry.leftEyeJointIndex;
|
||||
eyeParams.rightEyeJointIndex = geometry.rightEyeJointIndex;
|
||||
eyeParams.leftEyeJointIndex = hfmModel.leftEyeJointIndex;
|
||||
eyeParams.rightEyeJointIndex = hfmModel.rightEyeJointIndex;
|
||||
|
||||
_rig.updateFromEyeParameters(eyeParams);
|
||||
|
||||
|
|
|
@ -219,7 +219,11 @@ QString transactionString(const QJsonObject& valueObject) {
|
|||
if (!message.isEmpty()) {
|
||||
result += QString("<br>with memo: <i>\"%1\"</i>").arg(message);
|
||||
}
|
||||
} else if (sentMoney <= 0 && receivedMoney <= 0 && (sentCerts > 0 || receivedCerts > 0) && !KNOWN_USERS.contains(valueObject["sender_name"].toString())) {
|
||||
} else if (sentMoney <= 0 && receivedMoney <= 0 &&
|
||||
(sentCerts > 0 || receivedCerts > 0) &&
|
||||
!KNOWN_USERS.contains(valueObject["sender_name"].toString()) &&
|
||||
!KNOWN_USERS.contains(valueObject["recipient_name"].toString())
|
||||
) {
|
||||
// this is a non-HFC asset transfer.
|
||||
if (sentCerts > 0) {
|
||||
QString recipient = userLink(valueObject["recipient_name"].toString(), valueObject["place_name"].toString());
|
||||
|
@ -240,7 +244,6 @@ QString transactionString(const QJsonObject& valueObject) {
|
|||
return result;
|
||||
}
|
||||
|
||||
static const QString MARKETPLACE_ITEMS_BASE_URL = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/marketplace/items/";
|
||||
void Ledger::historySuccess(QNetworkReply* reply) {
|
||||
// here we send a historyResult with some extra stuff in it
|
||||
// Namely, the styled text we'd like to show. The issue is the
|
||||
|
|
|
@ -687,7 +687,7 @@ void Wallet::chooseSecurityImage(const QString& filename) {
|
|||
delete _securityImage;
|
||||
}
|
||||
QString path = PathUtils::resourcesPath();
|
||||
path.append("/qml/hifi/commerce/wallet/");
|
||||
path.append("/qml/hifi/dialogs/security/");
|
||||
path.append(filename);
|
||||
|
||||
// now create a new security image pixmap
|
||||
|
|
|
@ -131,7 +131,7 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
|
|||
// should never fall in here when collision model not fully loaded
|
||||
// TODO: assert that all geometries exist and are loaded
|
||||
//assert(_model && _model->isLoaded() && _compoundShapeResource && _compoundShapeResource->isLoaded());
|
||||
const FBXGeometry& collisionGeometry = resource->getFBXGeometry();
|
||||
const HFMModel& collisionModel = resource->getHFMModel();
|
||||
|
||||
ShapeInfo::PointCollection& pointCollection = shapeInfo.getPointCollection();
|
||||
pointCollection.clear();
|
||||
|
@ -139,15 +139,15 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
|
|||
|
||||
// the way OBJ files get read, each section under a "g" line is its own meshPart. We only expect
|
||||
// to find one actual "mesh" (with one or more meshParts in it), but we loop over the meshes, just in case.
|
||||
foreach (const FBXMesh& mesh, collisionGeometry.meshes) {
|
||||
foreach (const HFMMesh& mesh, collisionModel.meshes) {
|
||||
// each meshPart is a convex hull
|
||||
foreach (const FBXMeshPart &meshPart, mesh.parts) {
|
||||
foreach (const HFMMeshPart &meshPart, mesh.parts) {
|
||||
pointCollection.push_back(QVector<glm::vec3>());
|
||||
ShapeInfo::PointList& pointsInPart = pointCollection[i];
|
||||
|
||||
// run through all the triangles and (uniquely) add each point to the hull
|
||||
uint32_t numIndices = (uint32_t)meshPart.triangleIndices.size();
|
||||
// TODO: assert rather than workaround after we start sanitizing FBXMesh higher up
|
||||
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
|
||||
//assert(numIndices % TRIANGLE_STRIDE == 0);
|
||||
numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader
|
||||
|
||||
|
@ -168,7 +168,7 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
|
|||
|
||||
// run through all the quads and (uniquely) add each point to the hull
|
||||
numIndices = (uint32_t)meshPart.quadIndices.size();
|
||||
// TODO: assert rather than workaround after we start sanitizing FBXMesh higher up
|
||||
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
|
||||
//assert(numIndices % QUAD_STRIDE == 0);
|
||||
numIndices -= numIndices % QUAD_STRIDE; // WORKAROUND lack of sanity checking in FBXReader
|
||||
|
||||
|
@ -206,7 +206,7 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
|
|||
// to the visual model and apply them to the collision model (without regard for the
|
||||
// collision model's extents).
|
||||
|
||||
glm::vec3 scaleToFit = dimensions / resource->getFBXGeometry().getUnscaledMeshExtents().size();
|
||||
glm::vec3 scaleToFit = dimensions / resource->getHFMModel().getUnscaledMeshExtents().size();
|
||||
// multiply each point by scale
|
||||
for (int32_t i = 0; i < pointCollection.size(); i++) {
|
||||
for (int32_t j = 0; j < pointCollection[i].size(); j++) {
|
||||
|
@ -216,11 +216,11 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
|
|||
}
|
||||
shapeInfo.setParams(type, dimensions, resource->getURL().toString());
|
||||
} else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) {
|
||||
const FBXGeometry& fbxGeometry = resource->getFBXGeometry();
|
||||
int numFbxMeshes = fbxGeometry.meshes.size();
|
||||
const HFMModel& hfmModel = resource->getHFMModel();
|
||||
int numHFMMeshes = hfmModel.meshes.size();
|
||||
int totalNumVertices = 0;
|
||||
for (int i = 0; i < numFbxMeshes; i++) {
|
||||
const FBXMesh& mesh = fbxGeometry.meshes.at(i);
|
||||
for (int i = 0; i < numHFMMeshes; i++) {
|
||||
const HFMMesh& mesh = hfmModel.meshes.at(i);
|
||||
totalNumVertices += mesh.vertices.size();
|
||||
}
|
||||
const int32_t MAX_VERTICES_PER_STATIC_MESH = 1e6;
|
||||
|
@ -230,7 +230,7 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
|
|||
return;
|
||||
}
|
||||
|
||||
auto& meshes = resource->getFBXGeometry().meshes;
|
||||
auto& meshes = resource->getHFMModel().meshes;
|
||||
int32_t numMeshes = (int32_t)(meshes.size());
|
||||
|
||||
const int MAX_ALLOWED_MESH_COUNT = 1000;
|
||||
|
@ -285,12 +285,12 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
|
|||
if (type == SHAPE_TYPE_STATIC_MESH) {
|
||||
// copy into triangleIndices
|
||||
size_t triangleIndicesCount = 0;
|
||||
for (const FBXMeshPart& meshPart : mesh.parts) {
|
||||
for (const HFMMeshPart& meshPart : mesh.parts) {
|
||||
triangleIndicesCount += meshPart.triangleIndices.count();
|
||||
}
|
||||
triangleIndices.reserve((int)triangleIndicesCount);
|
||||
|
||||
for (const FBXMeshPart& meshPart : mesh.parts) {
|
||||
for (const HFMMeshPart& meshPart : mesh.parts) {
|
||||
const int* indexItr = meshPart.triangleIndices.cbegin();
|
||||
while (indexItr != meshPart.triangleIndices.cend()) {
|
||||
triangleIndices.push_back(*indexItr);
|
||||
|
@ -299,11 +299,11 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
|
|||
}
|
||||
} else if (type == SHAPE_TYPE_SIMPLE_COMPOUND) {
|
||||
// for each mesh copy unique part indices, separated by special bogus (flag) index values
|
||||
for (const FBXMeshPart& meshPart : mesh.parts) {
|
||||
for (const HFMMeshPart& meshPart : mesh.parts) {
|
||||
// collect unique list of indices for this part
|
||||
std::set<int32_t> uniqueIndices;
|
||||
auto numIndices = meshPart.triangleIndices.count();
|
||||
// TODO: assert rather than workaround after we start sanitizing FBXMesh higher up
|
||||
// TODO: assert rather than workaround after we start sanitizing HFMMesh higher up
|
||||
//assert(numIndices% TRIANGLE_STRIDE == 0);
|
||||
numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader
|
||||
|
||||
|
|
|
@ -10,13 +10,15 @@
|
|||
//
|
||||
|
||||
#include "WalletScriptingInterface.h"
|
||||
#include <SettingHandle.h>
|
||||
|
||||
CheckoutProxy::CheckoutProxy(QObject* qmlObject, QObject* parent) : QmlWrapper(qmlObject, parent) {
|
||||
Q_ASSERT(QThread::currentThread() == qApp->thread());
|
||||
}
|
||||
|
||||
WalletScriptingInterface::WalletScriptingInterface() {
|
||||
|
||||
connect(DependencyManager::get<AccountManager>().data(),
|
||||
&AccountManager::limitedCommerceChanged, this, &WalletScriptingInterface::limitedCommerceChanged);
|
||||
}
|
||||
|
||||
void WalletScriptingInterface::refreshWalletStatus() {
|
||||
|
@ -42,4 +44,4 @@ void WalletScriptingInterface::proveAvatarEntityOwnershipVerification(const QUui
|
|||
} else {
|
||||
qCDebug(entities) << "Failed to prove ownership of:" << entityID << "is not an avatar entity";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,13 +15,13 @@
|
|||
#include <QtCore/QObject>
|
||||
#include <DependencyManager.h>
|
||||
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include <ui/TabletScriptingInterface.h>
|
||||
#include <ui/QmlWrapper.h>
|
||||
#include <OffscreenUi.h>
|
||||
#include "Application.h"
|
||||
#include "commerce/Wallet.h"
|
||||
#include "ui/overlays/ContextOverlayInterface.h"
|
||||
#include <AccountManager.h>
|
||||
|
||||
class CheckoutProxy : public QmlWrapper {
|
||||
Q_OBJECT
|
||||
|
@ -29,7 +29,6 @@ public:
|
|||
CheckoutProxy(QObject* qmlObject, QObject* parent = nullptr);
|
||||
};
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @namespace Wallet
|
||||
*
|
||||
|
@ -37,28 +36,31 @@ public:
|
|||
* @hifi-client-entity
|
||||
*
|
||||
* @property {number} walletStatus
|
||||
* @property {bool} limitedCommerce
|
||||
*/
|
||||
class WalletScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
||||
SINGLETON_DEPENDENCY
|
||||
Q_PROPERTY(uint walletStatus READ getWalletStatus WRITE setWalletStatus NOTIFY walletStatusChanged)
|
||||
Q_PROPERTY(bool limitedCommerce READ getLimitedCommerce WRITE setLimitedCommerce NOTIFY limitedCommerceChanged)
|
||||
|
||||
public:
|
||||
|
||||
WalletScriptingInterface();
|
||||
|
||||
/**jsdoc
|
||||
* @function Wallet.refreshWalletStatus
|
||||
* @function WalletScriptingInterface.refreshWalletStatus
|
||||
*/
|
||||
Q_INVOKABLE void refreshWalletStatus();
|
||||
|
||||
/**jsdoc
|
||||
* @function Wallet.getWalletStatus
|
||||
* @function WalletScriptingInterface.getWalletStatus
|
||||
* @returns {number}
|
||||
*/
|
||||
Q_INVOKABLE uint getWalletStatus() { return _walletStatus; }
|
||||
|
||||
/**jsdoc
|
||||
* @function Wallet.proveAvatarEntityOwnershipVerification
|
||||
* @function WalletScriptingInterface.proveAvatarEntityOwnershipVerification
|
||||
* @param {Uuid} entityID
|
||||
*/
|
||||
Q_INVOKABLE void proveAvatarEntityOwnershipVerification(const QUuid& entityID);
|
||||
|
@ -67,29 +69,38 @@ public:
|
|||
// scripts could cause the Wallet to incorrectly report its status.
|
||||
void setWalletStatus(const uint& status);
|
||||
|
||||
bool getLimitedCommerce() { return DependencyManager::get<AccountManager>()->getLimitedCommerce(); }
|
||||
void setLimitedCommerce(bool isLimited) { DependencyManager::get<AccountManager>()->setLimitedCommerce(isLimited); };
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* @function Wallet.walletStatusChanged
|
||||
* @function WalletScriptingInterface.walletStatusChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void walletStatusChanged();
|
||||
|
||||
/**jsdoc
|
||||
* @function Wallet.walletNotSetup
|
||||
* @function WalletScriptingInterface.limitedCommerceChanged
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void limitedCommerceChanged();
|
||||
|
||||
/**jsdoc
|
||||
* @function WalletScriptingInterface.walletNotSetup
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void walletNotSetup();
|
||||
|
||||
/**jsdoc
|
||||
* @function Wallet.ownershipVerificationSuccess
|
||||
* @function WalletScriptingInterface.ownershipVerificationSuccess
|
||||
* @param {Uuid} entityID
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void ownershipVerificationSuccess(const QUuid& entityID);
|
||||
|
||||
/**jsdoc
|
||||
* @function Wallet.ownershipVerificationFailed
|
||||
* @function WalletScriptingInterface.ownershipVerificationFailed
|
||||
* @param {Uuid} entityID
|
||||
* @returns {Signal}
|
||||
*/
|
||||
|
|
|
@ -223,12 +223,7 @@ bool ContextOverlayInterface::createOrDestroyContextOverlay(const EntityItemID&
|
|||
|
||||
bool ContextOverlayInterface::contextOverlayFilterPassed(const EntityItemID& entityItemID) {
|
||||
EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(entityItemID, _entityPropertyFlags);
|
||||
Setting::Handle<bool> _settingSwitch{ "commerce", true };
|
||||
if (_settingSwitch.get()) {
|
||||
return (entityProperties.getCertificateID().length() != 0);
|
||||
} else {
|
||||
return (entityProperties.getMarketplaceID().length() != 0);
|
||||
}
|
||||
return (entityProperties.getCertificateID().length() != 0);
|
||||
}
|
||||
|
||||
bool ContextOverlayInterface::destroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event) {
|
||||
|
|
|
@ -446,7 +446,7 @@ QVariant ModelOverlay::getProperty(const QString& property) {
|
|||
|
||||
if (property == "jointNames") {
|
||||
if (_model && _model->isActive()) {
|
||||
// note: going through Rig because Model::getJointNames() (which proxies to FBXGeometry) was always empty
|
||||
// note: going through Rig because Model::getJointNames() (which proxies to HFMModel) was always empty
|
||||
const Rig* rig = &(_model->getRig());
|
||||
return mapJoints<QStringList, QString>([rig](int jointIndex) -> QString {
|
||||
return rig->nameOfJoint(jointIndex);
|
||||
|
@ -574,7 +574,7 @@ void ModelOverlay::animate() {
|
|||
|
||||
QVector<JointData> jointsData;
|
||||
|
||||
const QVector<FBXAnimationFrame>& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
|
||||
const QVector<HFMAnimationFrame>& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
|
||||
int frameCount = frames.size();
|
||||
if (frameCount <= 0) {
|
||||
return;
|
||||
|
@ -605,11 +605,11 @@ void ModelOverlay::animate() {
|
|||
return;
|
||||
}
|
||||
|
||||
QStringList animationJointNames = _animation->getGeometry().getJointNames();
|
||||
auto& fbxJoints = _animation->getGeometry().joints;
|
||||
QStringList animationJointNames = _animation->getHFMModel().getJointNames();
|
||||
auto& hfmJoints = _animation->getHFMModel().joints;
|
||||
|
||||
auto& originalFbxJoints = _model->getFBXGeometry().joints;
|
||||
auto& originalFbxIndices = _model->getFBXGeometry().jointIndices;
|
||||
auto& originalHFMJoints = _model->getHFMModel().joints;
|
||||
auto& originalHFMIndices = _model->getHFMModel().jointIndices;
|
||||
|
||||
const QVector<glm::quat>& rotations = frames[_lastKnownCurrentFrame].rotations;
|
||||
const QVector<glm::vec3>& translations = frames[_lastKnownCurrentFrame].translations;
|
||||
|
@ -626,23 +626,23 @@ void ModelOverlay::animate() {
|
|||
translationMat = glm::translate(translations[index]);
|
||||
}
|
||||
} else if (index < animationJointNames.size()) {
|
||||
QString jointName = fbxJoints[index].name;
|
||||
QString jointName = hfmJoints[index].name;
|
||||
|
||||
if (originalFbxIndices.contains(jointName)) {
|
||||
if (originalHFMIndices.contains(jointName)) {
|
||||
// Making sure the joint names exist in the original model the animation is trying to apply onto. If they do, then remap and get its translation.
|
||||
int remappedIndex = originalFbxIndices[jointName] - 1; // JointIndeces seem to always start from 1 and the found index is always 1 higher than actual.
|
||||
translationMat = glm::translate(originalFbxJoints[remappedIndex].translation);
|
||||
int remappedIndex = originalHFMIndices[jointName] - 1; // JointIndeces seem to always start from 1 and the found index is always 1 higher than actual.
|
||||
translationMat = glm::translate(originalHFMJoints[remappedIndex].translation);
|
||||
}
|
||||
}
|
||||
glm::mat4 rotationMat;
|
||||
if (index < rotations.size()) {
|
||||
rotationMat = glm::mat4_cast(fbxJoints[index].preRotation * rotations[index] * fbxJoints[index].postRotation);
|
||||
rotationMat = glm::mat4_cast(hfmJoints[index].preRotation * rotations[index] * hfmJoints[index].postRotation);
|
||||
} else {
|
||||
rotationMat = glm::mat4_cast(fbxJoints[index].preRotation * fbxJoints[index].postRotation);
|
||||
rotationMat = glm::mat4_cast(hfmJoints[index].preRotation * hfmJoints[index].postRotation);
|
||||
}
|
||||
|
||||
glm::mat4 finalMat = (translationMat * fbxJoints[index].preTransform *
|
||||
rotationMat * fbxJoints[index].postTransform);
|
||||
glm::mat4 finalMat = (translationMat * hfmJoints[index].preTransform *
|
||||
rotationMat * hfmJoints[index].postTransform);
|
||||
auto& jointData = jointsData[j];
|
||||
jointData.translation = extractTranslation(finalMat);
|
||||
jointData.translationIsDefaultPose = false;
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "ui/AvatarInputs.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "scripting/AccountServicesScriptingInterface.h"
|
||||
#include "scripting/WalletScriptingInterface.h"
|
||||
#include <plugins/InputConfiguration.h>
|
||||
#include "ui/Snapshot.h"
|
||||
#include "SoundCacheScriptingInterface.h"
|
||||
|
@ -270,6 +271,7 @@ void Web3DOverlay::setupQmlSurface(bool isTablet) {
|
|||
_webSurface->getSurfaceContext()->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Reticle", qApp->getApplicationCompositor().getReticleInterface());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("HiFiAbout", AboutUtil::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("WalletScriptingInterface", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
|
||||
// Override min fps for tablet UI, for silky smooth scrolling
|
||||
|
|
|
@ -101,8 +101,8 @@ void AnimClip::copyFromNetworkAnim() {
|
|||
|
||||
// build a mapping from animation joint indices to skeleton joint indices.
|
||||
// by matching joints with the same name.
|
||||
const FBXGeometry& geom = _networkAnim->getGeometry();
|
||||
AnimSkeleton animSkeleton(geom);
|
||||
const HFMModel& hfmModel = _networkAnim->getHFMModel();
|
||||
AnimSkeleton animSkeleton(hfmModel);
|
||||
const auto animJointCount = animSkeleton.getNumJoints();
|
||||
const auto skeletonJointCount = _skeleton->getNumJoints();
|
||||
std::vector<int> jointMap;
|
||||
|
@ -115,12 +115,12 @@ void AnimClip::copyFromNetworkAnim() {
|
|||
jointMap.push_back(skeletonJoint);
|
||||
}
|
||||
|
||||
const int frameCount = geom.animationFrames.size();
|
||||
const int frameCount = hfmModel.animationFrames.size();
|
||||
_anim.resize(frameCount);
|
||||
|
||||
for (int frame = 0; frame < frameCount; frame++) {
|
||||
|
||||
const FBXAnimationFrame& fbxAnimFrame = geom.animationFrames[frame];
|
||||
const HFMAnimationFrame& hfmAnimFrame = hfmModel.animationFrames[frame];
|
||||
|
||||
// init all joints in animation to default pose
|
||||
// this will give us a resonable result for bones in the model skeleton but not in the animation.
|
||||
|
@ -132,8 +132,8 @@ void AnimClip::copyFromNetworkAnim() {
|
|||
for (int animJoint = 0; animJoint < animJointCount; animJoint++) {
|
||||
int skeletonJoint = jointMap[animJoint];
|
||||
|
||||
const glm::vec3& fbxAnimTrans = fbxAnimFrame.translations[animJoint];
|
||||
const glm::quat& fbxAnimRot = fbxAnimFrame.rotations[animJoint];
|
||||
const glm::vec3& hfmAnimTrans = hfmAnimFrame.translations[animJoint];
|
||||
const glm::quat& hfmAnimRot = hfmAnimFrame.rotations[animJoint];
|
||||
|
||||
// skip joints that are in the animation but not in the skeleton.
|
||||
if (skeletonJoint >= 0 && skeletonJoint < skeletonJointCount) {
|
||||
|
@ -146,19 +146,19 @@ void AnimClip::copyFromNetworkAnim() {
|
|||
preRot.scale() = glm::vec3(1.0f);
|
||||
postRot.scale() = glm::vec3(1.0f);
|
||||
|
||||
AnimPose rot(glm::vec3(1.0f), fbxAnimRot, glm::vec3());
|
||||
AnimPose rot(glm::vec3(1.0f), hfmAnimRot, glm::vec3());
|
||||
|
||||
// adjust translation offsets, so large translation animatons on the reference skeleton
|
||||
// will be adjusted when played on a skeleton with short limbs.
|
||||
const glm::vec3& fbxZeroTrans = geom.animationFrames[0].translations[animJoint];
|
||||
const glm::vec3& hfmZeroTrans = hfmModel.animationFrames[0].translations[animJoint];
|
||||
const AnimPose& relDefaultPose = _skeleton->getRelativeDefaultPose(skeletonJoint);
|
||||
float boneLengthScale = 1.0f;
|
||||
const float EPSILON = 0.0001f;
|
||||
if (fabsf(glm::length(fbxZeroTrans)) > EPSILON) {
|
||||
boneLengthScale = glm::length(relDefaultPose.trans()) / glm::length(fbxZeroTrans);
|
||||
if (fabsf(glm::length(hfmZeroTrans)) > EPSILON) {
|
||||
boneLengthScale = glm::length(relDefaultPose.trans()) / glm::length(hfmZeroTrans);
|
||||
}
|
||||
|
||||
AnimPose trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans() + boneLengthScale * (fbxAnimTrans - fbxZeroTrans));
|
||||
AnimPose trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans() + boneLengthScale * (hfmAnimTrans - hfmZeroTrans));
|
||||
|
||||
_anim[frame][skeletonJoint] = trans * preRot * rot * postRot;
|
||||
}
|
||||
|
|
|
@ -16,17 +16,17 @@
|
|||
|
||||
#include "AnimationLogging.h"
|
||||
|
||||
AnimSkeleton::AnimSkeleton(const FBXGeometry& fbxGeometry) {
|
||||
AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) {
|
||||
// convert to std::vector of joints
|
||||
std::vector<FBXJoint> joints;
|
||||
joints.reserve(fbxGeometry.joints.size());
|
||||
for (auto& joint : fbxGeometry.joints) {
|
||||
std::vector<HFMJoint> joints;
|
||||
joints.reserve(hfmModel.joints.size());
|
||||
for (auto& joint : hfmModel.joints) {
|
||||
joints.push_back(joint);
|
||||
}
|
||||
buildSkeletonFromJoints(joints);
|
||||
}
|
||||
|
||||
AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
|
||||
AnimSkeleton::AnimSkeleton(const std::vector<HFMJoint>& joints) {
|
||||
buildSkeletonFromJoints(joints);
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const {
|
|||
}
|
||||
}
|
||||
|
||||
void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints) {
|
||||
void AnimSkeleton::buildSkeletonFromJoints(const std::vector<HFMJoint>& joints) {
|
||||
_joints = joints;
|
||||
_jointsSize = (int)joints.size();
|
||||
// build a cache of bind poses
|
||||
|
@ -177,7 +177,7 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints)
|
|||
_relativePreRotationPoses.reserve(_jointsSize);
|
||||
_relativePostRotationPoses.reserve(_jointsSize);
|
||||
|
||||
// iterate over FBXJoints and extract the bind pose information.
|
||||
// iterate over HFMJoints and extract the bind pose information.
|
||||
for (int i = 0; i < _jointsSize; i++) {
|
||||
|
||||
// build pre and post transforms
|
||||
|
@ -240,7 +240,7 @@ void AnimSkeleton::dump(bool verbose) const {
|
|||
qCDebug(animation) << " absDefaultPose =" << getAbsoluteDefaultPose(i);
|
||||
qCDebug(animation) << " relDefaultPose =" << getRelativeDefaultPose(i);
|
||||
if (verbose) {
|
||||
qCDebug(animation) << " fbxJoint =";
|
||||
qCDebug(animation) << " hfmJoint =";
|
||||
qCDebug(animation) << " isFree =" << _joints[i].isFree;
|
||||
qCDebug(animation) << " freeLineage =" << _joints[i].freeLineage;
|
||||
qCDebug(animation) << " parentIndex =" << _joints[i].parentIndex;
|
||||
|
|
|
@ -23,8 +23,8 @@ public:
|
|||
using Pointer = std::shared_ptr<AnimSkeleton>;
|
||||
using ConstPointer = std::shared_ptr<const AnimSkeleton>;
|
||||
|
||||
explicit AnimSkeleton(const FBXGeometry& fbxGeometry);
|
||||
explicit AnimSkeleton(const std::vector<FBXJoint>& joints);
|
||||
explicit AnimSkeleton(const HFMModel& hfmModel);
|
||||
explicit AnimSkeleton(const std::vector<HFMJoint>& joints);
|
||||
int nameToJointIndex(const QString& jointName) const;
|
||||
const QString& getJointName(int jointIndex) const;
|
||||
int getNumJoints() const;
|
||||
|
@ -64,9 +64,9 @@ public:
|
|||
std::vector<int> lookUpJointIndices(const std::vector<QString>& jointNames) const;
|
||||
|
||||
protected:
|
||||
void buildSkeletonFromJoints(const std::vector<FBXJoint>& joints);
|
||||
void buildSkeletonFromJoints(const std::vector<HFMJoint>& joints);
|
||||
|
||||
std::vector<FBXJoint> _joints;
|
||||
std::vector<HFMJoint> _joints;
|
||||
int _jointsSize { 0 };
|
||||
AnimPoseVec _relativeDefaultPoses;
|
||||
AnimPoseVec _absoluteDefaultPoses;
|
||||
|
|
|
@ -69,14 +69,14 @@ void AnimationReader::run() {
|
|||
|
||||
if (urlValid) {
|
||||
// Parse the FBX directly from the QNetworkReply
|
||||
FBXGeometry::Pointer fbxgeo;
|
||||
HFMModel::Pointer hfmModel;
|
||||
if (_url.path().toLower().endsWith(".fbx")) {
|
||||
fbxgeo.reset(readFBX(_data, QVariantHash(), _url.path()));
|
||||
hfmModel.reset(readFBX(_data, QVariantHash(), _url.path()));
|
||||
} else {
|
||||
QString errorStr("usupported format");
|
||||
emit onError(299, errorStr);
|
||||
}
|
||||
emit onSuccess(fbxgeo);
|
||||
emit onSuccess(hfmModel);
|
||||
} else {
|
||||
throw QString("url is invalid");
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ void AnimationReader::run() {
|
|||
}
|
||||
|
||||
bool Animation::isLoaded() const {
|
||||
return _loaded && _geometry;
|
||||
return _loaded && _hfmModel;
|
||||
}
|
||||
|
||||
QStringList Animation::getJointNames() const {
|
||||
|
@ -99,45 +99,45 @@ QStringList Animation::getJointNames() const {
|
|||
return result;
|
||||
}
|
||||
QStringList names;
|
||||
if (_geometry) {
|
||||
foreach (const FBXJoint& joint, _geometry->joints) {
|
||||
if (_hfmModel) {
|
||||
foreach (const HFMJoint& joint, _hfmModel->joints) {
|
||||
names.append(joint.name);
|
||||
}
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
QVector<FBXAnimationFrame> Animation::getFrames() const {
|
||||
QVector<HFMAnimationFrame> Animation::getFrames() const {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVector<FBXAnimationFrame> result;
|
||||
QVector<HFMAnimationFrame> result;
|
||||
BLOCKING_INVOKE_METHOD(const_cast<Animation*>(this), "getFrames",
|
||||
Q_RETURN_ARG(QVector<FBXAnimationFrame>, result));
|
||||
Q_RETURN_ARG(QVector<HFMAnimationFrame>, result));
|
||||
return result;
|
||||
}
|
||||
if (_geometry) {
|
||||
return _geometry->animationFrames;
|
||||
if (_hfmModel) {
|
||||
return _hfmModel->animationFrames;
|
||||
} else {
|
||||
return QVector<FBXAnimationFrame>();
|
||||
return QVector<HFMAnimationFrame>();
|
||||
}
|
||||
}
|
||||
|
||||
const QVector<FBXAnimationFrame>& Animation::getFramesReference() const {
|
||||
return _geometry->animationFrames;
|
||||
const QVector<HFMAnimationFrame>& Animation::getFramesReference() const {
|
||||
return _hfmModel->animationFrames;
|
||||
}
|
||||
|
||||
void Animation::downloadFinished(const QByteArray& data) {
|
||||
// parse the animation/fbx file on a background thread.
|
||||
AnimationReader* animationReader = new AnimationReader(_url, data);
|
||||
connect(animationReader, SIGNAL(onSuccess(FBXGeometry::Pointer)), SLOT(animationParseSuccess(FBXGeometry::Pointer)));
|
||||
connect(animationReader, SIGNAL(onSuccess(HFMModel::Pointer)), SLOT(animationParseSuccess(HFMModel::Pointer)));
|
||||
connect(animationReader, SIGNAL(onError(int, QString)), SLOT(animationParseError(int, QString)));
|
||||
QThreadPool::globalInstance()->start(animationReader);
|
||||
}
|
||||
|
||||
void Animation::animationParseSuccess(FBXGeometry::Pointer geometry) {
|
||||
void Animation::animationParseSuccess(HFMModel::Pointer hfmModel) {
|
||||
|
||||
qCDebug(animation) << "Animation parse success" << _url.toDisplayString();
|
||||
|
||||
_geometry = geometry;
|
||||
_hfmModel = hfmModel;
|
||||
finishedLoading(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
|
||||
QString getType() const override { return "Animation"; }
|
||||
|
||||
const FBXGeometry& getGeometry() const { return *_geometry; }
|
||||
const HFMModel& getHFMModel() const { return *_hfmModel; }
|
||||
|
||||
virtual bool isLoaded() const override;
|
||||
|
||||
|
@ -80,20 +80,20 @@ public:
|
|||
* @function AnimationObject.getFrames
|
||||
* @returns {FBXAnimationFrame[]}
|
||||
*/
|
||||
Q_INVOKABLE QVector<FBXAnimationFrame> getFrames() const;
|
||||
Q_INVOKABLE QVector<HFMAnimationFrame> getFrames() const;
|
||||
|
||||
const QVector<FBXAnimationFrame>& getFramesReference() const;
|
||||
const QVector<HFMAnimationFrame>& getFramesReference() const;
|
||||
|
||||
protected:
|
||||
virtual void downloadFinished(const QByteArray& data) override;
|
||||
|
||||
protected slots:
|
||||
void animationParseSuccess(FBXGeometry::Pointer geometry);
|
||||
void animationParseSuccess(HFMModel::Pointer hfmModel);
|
||||
void animationParseError(int error, QString str);
|
||||
|
||||
private:
|
||||
|
||||
FBXGeometry::Pointer _geometry;
|
||||
HFMModel::Pointer _hfmModel;
|
||||
};
|
||||
|
||||
/// Reads geometry in a worker thread.
|
||||
|
@ -105,7 +105,7 @@ public:
|
|||
virtual void run() override;
|
||||
|
||||
signals:
|
||||
void onSuccess(FBXGeometry::Pointer geometry);
|
||||
void onSuccess(HFMModel::Pointer hfmModel);
|
||||
void onError(int error, QString str);
|
||||
|
||||
private:
|
||||
|
|
|
@ -19,17 +19,17 @@ QStringList AnimationObject::getJointNames() const {
|
|||
return qscriptvalue_cast<AnimationPointer>(thisObject())->getJointNames();
|
||||
}
|
||||
|
||||
QVector<FBXAnimationFrame> AnimationObject::getFrames() const {
|
||||
QVector<HFMAnimationFrame> AnimationObject::getFrames() const {
|
||||
return qscriptvalue_cast<AnimationPointer>(thisObject())->getFrames();
|
||||
}
|
||||
|
||||
QVector<glm::quat> AnimationFrameObject::getRotations() const {
|
||||
return qscriptvalue_cast<FBXAnimationFrame>(thisObject()).rotations;
|
||||
return qscriptvalue_cast<HFMAnimationFrame>(thisObject()).rotations;
|
||||
}
|
||||
|
||||
void registerAnimationTypes(QScriptEngine* engine) {
|
||||
qScriptRegisterSequenceMetaType<QVector<FBXAnimationFrame> >(engine);
|
||||
engine->setDefaultPrototype(qMetaTypeId<FBXAnimationFrame>(), engine->newQObject(
|
||||
qScriptRegisterSequenceMetaType<QVector<HFMAnimationFrame> >(engine);
|
||||
engine->setDefaultPrototype(qMetaTypeId<HFMAnimationFrame>(), engine->newQObject(
|
||||
new AnimationFrameObject(), QScriptEngine::ScriptOwnership));
|
||||
engine->setDefaultPrototype(qMetaTypeId<AnimationPointer>(), engine->newQObject(
|
||||
new AnimationObject(), QScriptEngine::ScriptOwnership));
|
||||
|
|
|
@ -23,13 +23,13 @@ class QScriptEngine;
|
|||
class AnimationObject : public QObject, protected QScriptable {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
||||
Q_PROPERTY(QVector<FBXAnimationFrame> frames READ getFrames)
|
||||
Q_PROPERTY(QVector<HFMAnimationFrame> frames READ getFrames)
|
||||
|
||||
public:
|
||||
|
||||
Q_INVOKABLE QStringList getJointNames() const;
|
||||
|
||||
Q_INVOKABLE QVector<FBXAnimationFrame> getFrames() const;
|
||||
Q_INVOKABLE QVector<HFMAnimationFrame> getFrames() const;
|
||||
};
|
||||
|
||||
/// Scriptable wrapper for animation frames.
|
||||
|
|
|
@ -260,14 +260,14 @@ void Rig::destroyAnimGraph() {
|
|||
_rightEyeJointChildren.clear();
|
||||
}
|
||||
|
||||
void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset) {
|
||||
_geometryOffset = AnimPose(geometry.offset);
|
||||
void Rig::initJointStates(const HFMModel& hfmModel, const glm::mat4& modelOffset) {
|
||||
_geometryOffset = AnimPose(hfmModel.offset);
|
||||
_invGeometryOffset = _geometryOffset.inverse();
|
||||
_geometryToRigTransform = modelOffset * geometry.offset;
|
||||
_geometryToRigTransform = modelOffset * hfmModel.offset;
|
||||
_rigToGeometryTransform = glm::inverse(_geometryToRigTransform);
|
||||
setModelOffset(modelOffset);
|
||||
|
||||
_animSkeleton = std::make_shared<AnimSkeleton>(geometry);
|
||||
_animSkeleton = std::make_shared<AnimSkeleton>(hfmModel);
|
||||
|
||||
_internalPoseSet._relativePoses.clear();
|
||||
_internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
|
||||
|
@ -293,24 +293,24 @@ void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOff
|
|||
|
||||
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
|
||||
|
||||
_rootJointIndex = geometry.rootJointIndex;
|
||||
_leftEyeJointIndex = geometry.leftEyeJointIndex;
|
||||
_rightEyeJointIndex = geometry.rightEyeJointIndex;
|
||||
_leftHandJointIndex = geometry.leftHandJointIndex;
|
||||
_leftElbowJointIndex = _leftHandJointIndex >= 0 ? geometry.joints.at(_leftHandJointIndex).parentIndex : -1;
|
||||
_leftShoulderJointIndex = _leftElbowJointIndex >= 0 ? geometry.joints.at(_leftElbowJointIndex).parentIndex : -1;
|
||||
_rightHandJointIndex = geometry.rightHandJointIndex;
|
||||
_rightElbowJointIndex = _rightHandJointIndex >= 0 ? geometry.joints.at(_rightHandJointIndex).parentIndex : -1;
|
||||
_rightShoulderJointIndex = _rightElbowJointIndex >= 0 ? geometry.joints.at(_rightElbowJointIndex).parentIndex : -1;
|
||||
_rootJointIndex = hfmModel.rootJointIndex;
|
||||
_leftEyeJointIndex = hfmModel.leftEyeJointIndex;
|
||||
_rightEyeJointIndex = hfmModel.rightEyeJointIndex;
|
||||
_leftHandJointIndex = hfmModel.leftHandJointIndex;
|
||||
_leftElbowJointIndex = _leftHandJointIndex >= 0 ? hfmModel.joints.at(_leftHandJointIndex).parentIndex : -1;
|
||||
_leftShoulderJointIndex = _leftElbowJointIndex >= 0 ? hfmModel.joints.at(_leftElbowJointIndex).parentIndex : -1;
|
||||
_rightHandJointIndex = hfmModel.rightHandJointIndex;
|
||||
_rightElbowJointIndex = _rightHandJointIndex >= 0 ? hfmModel.joints.at(_rightHandJointIndex).parentIndex : -1;
|
||||
_rightShoulderJointIndex = _rightElbowJointIndex >= 0 ? hfmModel.joints.at(_rightElbowJointIndex).parentIndex : -1;
|
||||
|
||||
_leftEyeJointChildren = _animSkeleton->getChildrenOfJoint(geometry.leftEyeJointIndex);
|
||||
_rightEyeJointChildren = _animSkeleton->getChildrenOfJoint(geometry.rightEyeJointIndex);
|
||||
_leftEyeJointChildren = _animSkeleton->getChildrenOfJoint(hfmModel.leftEyeJointIndex);
|
||||
_rightEyeJointChildren = _animSkeleton->getChildrenOfJoint(hfmModel.rightEyeJointIndex);
|
||||
}
|
||||
|
||||
void Rig::reset(const FBXGeometry& geometry) {
|
||||
_geometryOffset = AnimPose(geometry.offset);
|
||||
void Rig::reset(const HFMModel& hfmModel) {
|
||||
_geometryOffset = AnimPose(hfmModel.offset);
|
||||
_invGeometryOffset = _geometryOffset.inverse();
|
||||
_animSkeleton = std::make_shared<AnimSkeleton>(geometry);
|
||||
_animSkeleton = std::make_shared<AnimSkeleton>(hfmModel);
|
||||
|
||||
_internalPoseSet._relativePoses.clear();
|
||||
_internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
|
||||
|
@ -338,18 +338,18 @@ void Rig::reset(const FBXGeometry& geometry) {
|
|||
|
||||
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
|
||||
|
||||
_rootJointIndex = geometry.rootJointIndex;
|
||||
_leftEyeJointIndex = geometry.leftEyeJointIndex;
|
||||
_rightEyeJointIndex = geometry.rightEyeJointIndex;
|
||||
_leftHandJointIndex = geometry.leftHandJointIndex;
|
||||
_leftElbowJointIndex = _leftHandJointIndex >= 0 ? geometry.joints.at(_leftHandJointIndex).parentIndex : -1;
|
||||
_leftShoulderJointIndex = _leftElbowJointIndex >= 0 ? geometry.joints.at(_leftElbowJointIndex).parentIndex : -1;
|
||||
_rightHandJointIndex = geometry.rightHandJointIndex;
|
||||
_rightElbowJointIndex = _rightHandJointIndex >= 0 ? geometry.joints.at(_rightHandJointIndex).parentIndex : -1;
|
||||
_rightShoulderJointIndex = _rightElbowJointIndex >= 0 ? geometry.joints.at(_rightElbowJointIndex).parentIndex : -1;
|
||||
_rootJointIndex = hfmModel.rootJointIndex;
|
||||
_leftEyeJointIndex = hfmModel.leftEyeJointIndex;
|
||||
_rightEyeJointIndex = hfmModel.rightEyeJointIndex;
|
||||
_leftHandJointIndex = hfmModel.leftHandJointIndex;
|
||||
_leftElbowJointIndex = _leftHandJointIndex >= 0 ? hfmModel.joints.at(_leftHandJointIndex).parentIndex : -1;
|
||||
_leftShoulderJointIndex = _leftElbowJointIndex >= 0 ? hfmModel.joints.at(_leftElbowJointIndex).parentIndex : -1;
|
||||
_rightHandJointIndex = hfmModel.rightHandJointIndex;
|
||||
_rightElbowJointIndex = _rightHandJointIndex >= 0 ? hfmModel.joints.at(_rightHandJointIndex).parentIndex : -1;
|
||||
_rightShoulderJointIndex = _rightElbowJointIndex >= 0 ? hfmModel.joints.at(_rightElbowJointIndex).parentIndex : -1;
|
||||
|
||||
_leftEyeJointChildren = _animSkeleton->getChildrenOfJoint(geometry.leftEyeJointIndex);
|
||||
_rightEyeJointChildren = _animSkeleton->getChildrenOfJoint(geometry.rightEyeJointIndex);
|
||||
_leftEyeJointChildren = _animSkeleton->getChildrenOfJoint(hfmModel.leftEyeJointIndex);
|
||||
_rightEyeJointChildren = _animSkeleton->getChildrenOfJoint(hfmModel.rightEyeJointIndex);
|
||||
|
||||
if (!_animGraphURL.isEmpty()) {
|
||||
_animNode.reset();
|
||||
|
@ -1253,7 +1253,7 @@ const glm::vec3 DOP14_NORMALS[DOP14_COUNT] = {
|
|||
// returns true if the given point lies inside of the k-dop, specified by shapeInfo & shapePose.
|
||||
// if the given point does lie within the k-dop, it also returns the amount of displacement necessary to push that point outward
|
||||
// such that it lies on the surface of the kdop.
|
||||
static bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose, const FBXJointShapeInfo& shapeInfo, glm::vec3& displacementOut) {
|
||||
static bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose, const HFMJointShapeInfo& shapeInfo, glm::vec3& displacementOut) {
|
||||
|
||||
// transform point into local space of jointShape.
|
||||
glm::vec3 localPoint = shapePose.inverse().xformPoint(point);
|
||||
|
@ -1299,8 +1299,8 @@ static bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& sh
|
|||
}
|
||||
}
|
||||
|
||||
glm::vec3 Rig::deflectHandFromTorso(const glm::vec3& handPosition, const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo,
|
||||
const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo) const {
|
||||
glm::vec3 Rig::deflectHandFromTorso(const glm::vec3& handPosition, const HFMJointShapeInfo& hipsShapeInfo, const HFMJointShapeInfo& spineShapeInfo,
|
||||
const HFMJointShapeInfo& spine1ShapeInfo, const HFMJointShapeInfo& spine2ShapeInfo) const {
|
||||
glm::vec3 position = handPosition;
|
||||
glm::vec3 displacement;
|
||||
int hipsJoint = indexOfJoint("Hips");
|
||||
|
@ -1349,8 +1349,8 @@ glm::vec3 Rig::deflectHandFromTorso(const glm::vec3& handPosition, const FBXJoin
|
|||
void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated,
|
||||
bool leftArmEnabled, bool rightArmEnabled, bool headEnabled, float dt,
|
||||
const AnimPose& leftHandPose, const AnimPose& rightHandPose,
|
||||
const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo,
|
||||
const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo,
|
||||
const HFMJointShapeInfo& hipsShapeInfo, const HFMJointShapeInfo& spineShapeInfo,
|
||||
const HFMJointShapeInfo& spine1ShapeInfo, const HFMJointShapeInfo& spine2ShapeInfo,
|
||||
const glm::mat4& rigToSensorMatrix, const glm::mat4& sensorToRigMatrix) {
|
||||
|
||||
const bool ENABLE_POLE_VECTORS = true;
|
||||
|
@ -1938,7 +1938,7 @@ void Rig::copyJointsIntoJointData(QVector<JointData>& jointDataVec) const {
|
|||
data.rotationIsDefaultPose = isEqual(data.rotation, defaultAbsRot);
|
||||
|
||||
// translations are in relative frame but scaled so that they are in meters,
|
||||
// instead of geometry units.
|
||||
// instead of model units.
|
||||
glm::vec3 defaultRelTrans = _geometryOffset.scale() * _animSkeleton->getRelativeDefaultPose(i).trans();
|
||||
data.translation = _geometryOffset.scale() * (!_sendNetworkNode ? _internalPoseSet._relativePoses[i].trans() : _networkPoseSet._relativePoses[i].trans());
|
||||
data.translationIsDefaultPose = isEqual(data.translation, defaultRelTrans);
|
||||
|
@ -1963,7 +1963,7 @@ void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
|
|||
return;
|
||||
}
|
||||
|
||||
// make a vector of rotations in absolute-geometry-frame
|
||||
// make a vector of rotations in absolute-model-frame
|
||||
std::vector<glm::quat> rotations;
|
||||
rotations.reserve(numJoints);
|
||||
const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform));
|
||||
|
@ -1972,7 +1972,7 @@ void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
|
|||
if (data.rotationIsDefaultPose) {
|
||||
rotations.push_back(absoluteDefaultPoses[i].rot());
|
||||
} else {
|
||||
// JointData rotations are in absolute rig-frame so we rotate them to absolute geometry-frame
|
||||
// JointData rotations are in absolute rig-frame so we rotate them to absolute model-frame
|
||||
rotations.push_back(rigToGeometryRot * data.rotation);
|
||||
}
|
||||
}
|
||||
|
@ -2008,7 +2008,7 @@ void Rig::computeExternalPoses(const glm::mat4& modelOffsetMat) {
|
|||
}
|
||||
|
||||
void Rig::computeAvatarBoundingCapsule(
|
||||
const FBXGeometry& geometry,
|
||||
const HFMModel& hfmModel,
|
||||
float& radiusOut,
|
||||
float& heightOut,
|
||||
glm::vec3& localOffsetOut) const {
|
||||
|
@ -2041,7 +2041,7 @@ void Rig::computeAvatarBoundingCapsule(
|
|||
// from the head to the hips when computing the rest of the bounding capsule.
|
||||
int index = indexOfJoint("Head");
|
||||
while (index != -1) {
|
||||
const FBXJointShapeInfo& shapeInfo = geometry.joints.at(index).shapeInfo;
|
||||
const HFMJointShapeInfo& shapeInfo = hfmModel.joints.at(index).shapeInfo;
|
||||
AnimPose pose = _animSkeleton->getAbsoluteDefaultPose(index);
|
||||
if (shapeInfo.points.size() > 0) {
|
||||
for (auto& point : shapeInfo.points) {
|
||||
|
|
|
@ -86,10 +86,10 @@ public:
|
|||
AnimPose secondaryControllerPoses[NumSecondaryControllerTypes]; // rig space
|
||||
uint8_t secondaryControllerFlags[NumSecondaryControllerTypes];
|
||||
bool isTalking;
|
||||
FBXJointShapeInfo hipsShapeInfo;
|
||||
FBXJointShapeInfo spineShapeInfo;
|
||||
FBXJointShapeInfo spine1ShapeInfo;
|
||||
FBXJointShapeInfo spine2ShapeInfo;
|
||||
HFMJointShapeInfo hipsShapeInfo;
|
||||
HFMJointShapeInfo spineShapeInfo;
|
||||
HFMJointShapeInfo spine1ShapeInfo;
|
||||
HFMJointShapeInfo spine2ShapeInfo;
|
||||
};
|
||||
|
||||
struct EyeParameters {
|
||||
|
@ -122,8 +122,8 @@ public:
|
|||
void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
||||
void restoreRoleAnimation(const QString& role);
|
||||
|
||||
void initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset);
|
||||
void reset(const FBXGeometry& geometry);
|
||||
void initJointStates(const HFMModel& hfmModel, const glm::mat4& modelOffset);
|
||||
void reset(const HFMModel& hfmModel);
|
||||
bool jointStatesEmpty();
|
||||
int getJointStateCount() const;
|
||||
int indexOfJoint(const QString& jointName) const;
|
||||
|
@ -210,7 +210,7 @@ public:
|
|||
void copyJointsFromJointData(const QVector<JointData>& jointDataVec);
|
||||
void computeExternalPoses(const glm::mat4& modelOffsetMat);
|
||||
|
||||
void computeAvatarBoundingCapsule(const FBXGeometry& geometry, float& radiusOut, float& heightOut, glm::vec3& offsetOut) const;
|
||||
void computeAvatarBoundingCapsule(const HFMModel& hfmModel, float& radiusOut, float& heightOut, glm::vec3& offsetOut) const;
|
||||
|
||||
void setEnableInverseKinematics(bool enable);
|
||||
void setEnableAnimations(bool enable);
|
||||
|
@ -245,8 +245,8 @@ protected:
|
|||
void updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated,
|
||||
bool leftArmEnabled, bool rightArmEnabled, bool headEnabled, float dt,
|
||||
const AnimPose& leftHandPose, const AnimPose& rightHandPose,
|
||||
const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo,
|
||||
const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo,
|
||||
const HFMJointShapeInfo& hipsShapeInfo, const HFMJointShapeInfo& spineShapeInfo,
|
||||
const HFMJointShapeInfo& spine1ShapeInfo, const HFMJointShapeInfo& spine2ShapeInfo,
|
||||
const glm::mat4& rigToSensorMatrix, const glm::mat4& sensorToRigMatrix);
|
||||
void updateFeet(bool leftFootEnabled, bool rightFootEnabled, bool headEnabled,
|
||||
const AnimPose& leftFootPose, const AnimPose& rightFootPose,
|
||||
|
@ -257,8 +257,8 @@ protected:
|
|||
|
||||
bool calculateElbowPoleVector(int handIndex, int elbowIndex, int armIndex, int oppositeArmIndex, glm::vec3& poleVector) const;
|
||||
glm::vec3 calculateKneePoleVector(int footJointIndex, int kneeJoint, int upLegIndex, int hipsIndex, const AnimPose& targetFootPose) const;
|
||||
glm::vec3 deflectHandFromTorso(const glm::vec3& handPosition, const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo,
|
||||
const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo) const;
|
||||
glm::vec3 deflectHandFromTorso(const glm::vec3& handPosition, const HFMJointShapeInfo& hipsShapeInfo, const HFMJointShapeInfo& spineShapeInfo,
|
||||
const HFMJointShapeInfo& spine1ShapeInfo, const HFMJointShapeInfo& spine2ShapeInfo) const;
|
||||
|
||||
|
||||
AnimPose _modelOffset; // model to rig space
|
||||
|
|
|
@ -1311,7 +1311,7 @@ glm::quat Avatar::getAbsoluteJointRotationInObjectFrame(int index) const {
|
|||
case CAMERA_MATRIX_INDEX: {
|
||||
glm::quat rotation;
|
||||
if (_skeletonModel && _skeletonModel->isActive()) {
|
||||
int headJointIndex = _skeletonModel->getFBXGeometry().headJointIndex;
|
||||
int headJointIndex = _skeletonModel->getHFMModel().headJointIndex;
|
||||
if (headJointIndex >= 0) {
|
||||
_skeletonModel->getAbsoluteJointRotationInRigFrame(headJointIndex, rotation);
|
||||
}
|
||||
|
@ -1360,7 +1360,7 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const {
|
|||
case CAMERA_MATRIX_INDEX: {
|
||||
glm::vec3 translation;
|
||||
if (_skeletonModel && _skeletonModel->isActive()) {
|
||||
int headJointIndex = _skeletonModel->getFBXGeometry().headJointIndex;
|
||||
int headJointIndex = _skeletonModel->getHFMModel().headJointIndex;
|
||||
if (headJointIndex >= 0) {
|
||||
_skeletonModel->getAbsoluteJointTranslationInRigFrame(headJointIndex, translation);
|
||||
}
|
||||
|
@ -1416,7 +1416,7 @@ void Avatar::withValidJointIndicesCache(std::function<void()> const& worker) con
|
|||
if (!_modelJointsCached) {
|
||||
_modelJointIndicesCache.clear();
|
||||
if (_skeletonModel && _skeletonModel->isActive()) {
|
||||
_modelJointIndicesCache = _skeletonModel->getFBXGeometry().jointIndices;
|
||||
_modelJointIndicesCache = _skeletonModel->getHFMModel().jointIndices;
|
||||
_modelJointsCached = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,9 +54,9 @@ void SkeletonModel::setTextures(const QVariantMap& textures) {
|
|||
}
|
||||
|
||||
void SkeletonModel::initJointStates() {
|
||||
const FBXGeometry& geometry = getFBXGeometry();
|
||||
const HFMModel& hfmModel = getHFMModel();
|
||||
glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset);
|
||||
_rig.initJointStates(geometry, modelOffset);
|
||||
_rig.initJointStates(hfmModel, modelOffset);
|
||||
|
||||
{
|
||||
// initialize _jointData with proper values for default joints
|
||||
|
@ -66,7 +66,7 @@ void SkeletonModel::initJointStates() {
|
|||
}
|
||||
|
||||
// Determine the default eye position for avatar scale = 1.0
|
||||
int headJointIndex = geometry.headJointIndex;
|
||||
int headJointIndex = hfmModel.headJointIndex;
|
||||
if (0 > headJointIndex || headJointIndex >= _rig.getJointStateCount()) {
|
||||
qCWarning(avatars_renderer) << "Bad head joint! Got:" << headJointIndex << "jointCount:" << _rig.getJointStateCount();
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ void SkeletonModel::initJointStates() {
|
|||
getEyeModelPositions(leftEyePosition, rightEyePosition);
|
||||
glm::vec3 midEyePosition = (leftEyePosition + rightEyePosition) / 2.0f;
|
||||
|
||||
int rootJointIndex = geometry.rootJointIndex;
|
||||
int rootJointIndex = hfmModel.rootJointIndex;
|
||||
glm::vec3 rootModelPosition;
|
||||
getJointPosition(rootJointIndex, rootModelPosition);
|
||||
|
||||
|
@ -96,7 +96,7 @@ void SkeletonModel::initJointStates() {
|
|||
// Called within Model::simulate call, below.
|
||||
void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||
assert(!_owningAvatar->isMyAvatar());
|
||||
const FBXGeometry& geometry = getFBXGeometry();
|
||||
const HFMModel& hfmModel = getHFMModel();
|
||||
|
||||
Head* head = _owningAvatar->getHead();
|
||||
|
||||
|
@ -124,7 +124,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
|
||||
// If the head is not positioned, updateEyeJoints won't get the math right
|
||||
glm::quat headOrientation;
|
||||
_rig.getJointRotation(geometry.headJointIndex, headOrientation);
|
||||
_rig.getJointRotation(hfmModel.headJointIndex, headOrientation);
|
||||
glm::vec3 eulers = safeEulerAngles(headOrientation);
|
||||
head->setBasePitch(glm::degrees(-eulers.x));
|
||||
head->setBaseYaw(glm::degrees(eulers.y));
|
||||
|
@ -135,8 +135,8 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
eyeParams.eyeSaccade = glm::vec3(0.0f);
|
||||
eyeParams.modelRotation = getRotation();
|
||||
eyeParams.modelTranslation = getTranslation();
|
||||
eyeParams.leftEyeJointIndex = geometry.leftEyeJointIndex;
|
||||
eyeParams.rightEyeJointIndex = geometry.rightEyeJointIndex;
|
||||
eyeParams.leftEyeJointIndex = hfmModel.leftEyeJointIndex;
|
||||
eyeParams.rightEyeJointIndex = hfmModel.rightEyeJointIndex;
|
||||
|
||||
_rig.updateFromEyeParameters(eyeParams);
|
||||
}
|
||||
|
@ -259,45 +259,45 @@ bool SkeletonModel::getRightShoulderPosition(glm::vec3& position) const {
|
|||
}
|
||||
|
||||
bool SkeletonModel::getHeadPosition(glm::vec3& headPosition) const {
|
||||
return isActive() && getJointPositionInWorldFrame(getFBXGeometry().headJointIndex, headPosition);
|
||||
return isActive() && getJointPositionInWorldFrame(getHFMModel().headJointIndex, headPosition);
|
||||
}
|
||||
|
||||
bool SkeletonModel::getNeckPosition(glm::vec3& neckPosition) const {
|
||||
return isActive() && getJointPositionInWorldFrame(getFBXGeometry().neckJointIndex, neckPosition);
|
||||
return isActive() && getJointPositionInWorldFrame(getHFMModel().neckJointIndex, neckPosition);
|
||||
}
|
||||
|
||||
bool SkeletonModel::getLocalNeckPosition(glm::vec3& neckPosition) const {
|
||||
return isActive() && getJointPosition(getFBXGeometry().neckJointIndex, neckPosition);
|
||||
return isActive() && getJointPosition(getHFMModel().neckJointIndex, neckPosition);
|
||||
}
|
||||
|
||||
bool SkeletonModel::getEyeModelPositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const {
|
||||
if (!isActive()) {
|
||||
return false;
|
||||
}
|
||||
const FBXGeometry& geometry = getFBXGeometry();
|
||||
const HFMModel& hfmModel = getHFMModel();
|
||||
|
||||
if (getJointPosition(geometry.leftEyeJointIndex, firstEyePosition) &&
|
||||
getJointPosition(geometry.rightEyeJointIndex, secondEyePosition)) {
|
||||
if (getJointPosition(hfmModel.leftEyeJointIndex, firstEyePosition) &&
|
||||
getJointPosition(hfmModel.rightEyeJointIndex, secondEyePosition)) {
|
||||
return true;
|
||||
}
|
||||
// no eye joints; try to estimate based on head/neck joints
|
||||
glm::vec3 neckPosition, headPosition;
|
||||
if (getJointPosition(geometry.neckJointIndex, neckPosition) &&
|
||||
getJointPosition(geometry.headJointIndex, headPosition)) {
|
||||
if (getJointPosition(hfmModel.neckJointIndex, neckPosition) &&
|
||||
getJointPosition(hfmModel.headJointIndex, headPosition)) {
|
||||
const float EYE_PROPORTION = 0.6f;
|
||||
glm::vec3 baseEyePosition = glm::mix(neckPosition, headPosition, EYE_PROPORTION);
|
||||
glm::quat headRotation;
|
||||
getJointRotation(geometry.headJointIndex, headRotation);
|
||||
getJointRotation(hfmModel.headJointIndex, headRotation);
|
||||
const float EYES_FORWARD = 0.25f;
|
||||
const float EYE_SEPARATION = 0.1f;
|
||||
float headHeight = glm::distance(neckPosition, headPosition);
|
||||
firstEyePosition = baseEyePosition + headRotation * glm::vec3(EYE_SEPARATION, 0.0f, EYES_FORWARD) * headHeight;
|
||||
secondEyePosition = baseEyePosition + headRotation * glm::vec3(-EYE_SEPARATION, 0.0f, EYES_FORWARD) * headHeight;
|
||||
return true;
|
||||
} else if (getJointPosition(geometry.headJointIndex, headPosition)) {
|
||||
} else if (getJointPosition(hfmModel.headJointIndex, headPosition)) {
|
||||
glm::vec3 baseEyePosition = headPosition;
|
||||
glm::quat headRotation;
|
||||
getJointRotation(geometry.headJointIndex, headRotation);
|
||||
getJointRotation(hfmModel.headJointIndex, headRotation);
|
||||
const float EYES_FORWARD_HEAD_ONLY = 0.30f;
|
||||
const float EYE_SEPARATION = 0.1f;
|
||||
firstEyePosition = baseEyePosition + headRotation * glm::vec3(EYE_SEPARATION, 0.0f, EYES_FORWARD_HEAD_ONLY);
|
||||
|
@ -330,15 +330,15 @@ void SkeletonModel::computeBoundingShape() {
|
|||
return;
|
||||
}
|
||||
|
||||
const FBXGeometry& geometry = getFBXGeometry();
|
||||
if (geometry.joints.isEmpty() || geometry.rootJointIndex == -1) {
|
||||
const HFMModel& hfmModel = getHFMModel();
|
||||
if (hfmModel.joints.isEmpty() || hfmModel.rootJointIndex == -1) {
|
||||
// rootJointIndex == -1 if the avatar model has no skeleton
|
||||
return;
|
||||
}
|
||||
|
||||
float radius, height;
|
||||
glm::vec3 offset;
|
||||
_rig.computeAvatarBoundingCapsule(geometry, radius, height, offset);
|
||||
_rig.computeAvatarBoundingCapsule(hfmModel, radius, height, offset);
|
||||
float invScale = 1.0f / _owningAvatar->getModelScale();
|
||||
_boundingCapsuleRadius = invScale * radius;
|
||||
_boundingCapsuleHeight = invScale * height;
|
||||
|
@ -369,7 +369,7 @@ void SkeletonModel::renderBoundingCollisionShapes(RenderArgs* args, gpu::Batch&
|
|||
}
|
||||
|
||||
bool SkeletonModel::hasSkeleton() {
|
||||
return isActive() ? getFBXGeometry().rootJointIndex != -1 : false;
|
||||
return isActive() ? getHFMModel().rootJointIndex != -1 : false;
|
||||
}
|
||||
|
||||
void SkeletonModel::onInvalidate() {
|
||||
|
|
|
@ -41,10 +41,10 @@ public:
|
|||
void updateAttitude(const glm::quat& orientation);
|
||||
|
||||
/// Returns the index of the left hand joint, or -1 if not found.
|
||||
int getLeftHandJointIndex() const { return isActive() ? getFBXGeometry().leftHandJointIndex : -1; }
|
||||
int getLeftHandJointIndex() const { return isActive() ? getHFMModel().leftHandJointIndex : -1; }
|
||||
|
||||
/// Returns the index of the right hand joint, or -1 if not found.
|
||||
int getRightHandJointIndex() const { return isActive() ? getFBXGeometry().rightHandJointIndex : -1; }
|
||||
int getRightHandJointIndex() const { return isActive() ? getHFMModel().rightHandJointIndex : -1; }
|
||||
|
||||
bool getLeftGrabPosition(glm::vec3& position) const;
|
||||
bool getRightGrabPosition(glm::vec3& position) const;
|
||||
|
|
|
@ -206,7 +206,7 @@ void FBXBaker::importScene() {
|
|||
}
|
||||
#endif
|
||||
|
||||
_geometry = reader.extractFBXGeometry({}, _modelURL.toString());
|
||||
_hfmModel = reader.extractHFMModel({}, _modelURL.toString());
|
||||
_textureContentMap = reader._textureContent;
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,7 @@ void FBXBaker::rewriteAndBakeSceneModels() {
|
|||
for (FBXNode& objectChild : rootChild.children) {
|
||||
if (objectChild.name == "Geometry") {
|
||||
|
||||
// TODO Pull this out of _geometry instead so we don't have to reprocess it
|
||||
// TODO Pull this out of _hfmModel instead so we don't have to reprocess it
|
||||
auto extractedMesh = FBXReader::extractMesh(objectChild, meshIndex, false);
|
||||
|
||||
// Callback to get MaterialID
|
||||
|
@ -293,7 +293,7 @@ void FBXBaker::rewriteAndBakeSceneTextures() {
|
|||
QHash<QString, image::TextureUsage::Type> textureTypes;
|
||||
|
||||
// enumerate the materials in the extracted geometry so we can determine the texture type for each texture ID
|
||||
for (const auto& material : _geometry->materials) {
|
||||
for (const auto& material : _hfmModel->materials) {
|
||||
if (material.normalTexture.isBumpmap) {
|
||||
textureTypes[material.normalTexture.id] = BUMP_TEXTURE;
|
||||
} else {
|
||||
|
@ -329,7 +329,7 @@ void FBXBaker::rewriteAndBakeSceneTextures() {
|
|||
for (FBXNode& textureChild : object->children) {
|
||||
|
||||
if (textureChild.name == "RelativeFilename") {
|
||||
QString fbxTextureFileName { textureChild.properties.at(0).toString() };
|
||||
QString hfmTextureFileName { textureChild.properties.at(0).toString() };
|
||||
|
||||
// grab the ID for this texture so we can figure out the
|
||||
// texture type from the loaded materials
|
||||
|
@ -337,7 +337,7 @@ void FBXBaker::rewriteAndBakeSceneTextures() {
|
|||
auto textureType = textureTypes[textureID];
|
||||
|
||||
// Compress the texture information and return the new filename to be added into the FBX scene
|
||||
auto bakedTextureFile = compressTexture(fbxTextureFileName, textureType);
|
||||
auto bakedTextureFile = compressTexture(hfmTextureFileName, textureType);
|
||||
|
||||
// If no errors or warnings have occurred during texture compression add the filename to the FBX scene
|
||||
if (!bakedTextureFile.isNull()) {
|
||||
|
|
|
@ -53,7 +53,7 @@ private:
|
|||
void rewriteAndBakeSceneModels();
|
||||
void rewriteAndBakeSceneTextures();
|
||||
|
||||
FBXGeometry* _geometry;
|
||||
HFMModel* _hfmModel;
|
||||
QHash<QString, int> _textureNameMatchCount;
|
||||
QHash<QUrl, QString> _remappedTexturePaths;
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ void ModelBaker::abort() {
|
|||
}
|
||||
}
|
||||
|
||||
bool ModelBaker::compressMesh(FBXMesh& mesh, bool hasDeformers, FBXNode& dracoMeshNode, GetMaterialIDCallback materialIDCallback) {
|
||||
bool ModelBaker::compressMesh(HFMMesh& mesh, bool hasDeformers, FBXNode& dracoMeshNode, GetMaterialIDCallback materialIDCallback) {
|
||||
if (mesh.wasCompressed) {
|
||||
handleError("Cannot re-bake a file that contains compressed mesh");
|
||||
return false;
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
const QString& bakedOutputDirectory, const QString& originalOutputDirectory = "");
|
||||
virtual ~ModelBaker();
|
||||
|
||||
bool compressMesh(FBXMesh& mesh, bool hasDeformers, FBXNode& dracoMeshNode, GetMaterialIDCallback materialIDCallback = nullptr);
|
||||
bool compressMesh(HFMMesh& mesh, bool hasDeformers, FBXNode& dracoMeshNode, GetMaterialIDCallback materialIDCallback = nullptr);
|
||||
QString compressTexture(QString textureFileName, image::TextureUsage::Type = image::TextureUsage::Type::DEFAULT_TEXTURE);
|
||||
virtual void setWasAborted(bool wasAborted) override;
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ void OBJBaker::bakeOBJ() {
|
|||
checkIfTexturesFinished();
|
||||
}
|
||||
|
||||
void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
|
||||
void OBJBaker::createFBXNodeTree(FBXNode& rootNode, HFMModel& hfmModel) {
|
||||
// Generating FBX Header Node
|
||||
FBXNode headerNode;
|
||||
headerNode.name = FBX_HEADER_EXTENSION;
|
||||
|
@ -199,7 +199,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
|
|||
// Compress the mesh information and store in dracoNode
|
||||
bool hasDeformers = false; // No concept of deformers for an OBJ
|
||||
FBXNode dracoNode;
|
||||
compressMesh(geometry.meshes[0], hasDeformers, dracoNode);
|
||||
compressMesh(hfmModel.meshes[0], hasDeformers, dracoNode);
|
||||
geometryNode.children.append(dracoNode);
|
||||
|
||||
// Generating Object node's child - Model node
|
||||
|
@ -214,17 +214,17 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
|
|||
objectNode.children = { geometryNode, modelNode };
|
||||
|
||||
// Generating Objects node's child - Material node
|
||||
auto& meshParts = geometry.meshes[0].parts;
|
||||
auto& meshParts = hfmModel.meshes[0].parts;
|
||||
for (auto& meshPart : meshParts) {
|
||||
FBXNode materialNode;
|
||||
materialNode.name = MATERIAL_NODE_NAME;
|
||||
if (geometry.materials.size() == 1) {
|
||||
if (hfmModel.materials.size() == 1) {
|
||||
// case when no material information is provided, OBJReader considers it as a single default material
|
||||
for (auto& materialID : geometry.materials.keys()) {
|
||||
setMaterialNodeProperties(materialNode, materialID, geometry);
|
||||
for (auto& materialID : hfmModel.materials.keys()) {
|
||||
setMaterialNodeProperties(materialNode, materialID, hfmModel);
|
||||
}
|
||||
} else {
|
||||
setMaterialNodeProperties(materialNode, meshPart.materialID, geometry);
|
||||
setMaterialNodeProperties(materialNode, meshPart.materialID, hfmModel);
|
||||
}
|
||||
|
||||
objectNode.children.append(materialNode);
|
||||
|
@ -235,7 +235,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
|
|||
auto size = meshParts.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
QString material = meshParts[i].materialID;
|
||||
FBXMaterial currentMaterial = geometry.materials[material];
|
||||
HFMMaterial currentMaterial = hfmModel.materials[material];
|
||||
if (!currentMaterial.albedoTexture.filename.isEmpty() || !currentMaterial.specularTexture.filename.isEmpty()) {
|
||||
auto textureID = nextNodeID();
|
||||
_mapTextureMaterial.emplace_back(textureID, i);
|
||||
|
@ -325,12 +325,12 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry) {
|
|||
}
|
||||
|
||||
// Set properties for material nodes
|
||||
void OBJBaker::setMaterialNodeProperties(FBXNode& materialNode, QString material, FBXGeometry& geometry) {
|
||||
void OBJBaker::setMaterialNodeProperties(FBXNode& materialNode, QString material, HFMModel& hfmModel) {
|
||||
auto materialID = nextNodeID();
|
||||
_materialIDs.push_back(materialID);
|
||||
materialNode.properties = { materialID, material, MESH };
|
||||
|
||||
FBXMaterial currentMaterial = geometry.materials[material];
|
||||
HFMMaterial currentMaterial = hfmModel.materials[material];
|
||||
|
||||
// Setting the hierarchy: Material -> Properties70 -> P -> Properties
|
||||
FBXNode properties70Node;
|
||||
|
|
|
@ -39,8 +39,8 @@ private slots:
|
|||
|
||||
private:
|
||||
void loadOBJ();
|
||||
void createFBXNodeTree(FBXNode& rootNode, FBXGeometry& geometry);
|
||||
void setMaterialNodeProperties(FBXNode& materialNode, QString material, FBXGeometry& geometry);
|
||||
void createFBXNodeTree(FBXNode& rootNode, HFMModel& hfmModel);
|
||||
void setMaterialNodeProperties(FBXNode& materialNode, QString material, HFMModel& hfmModel);
|
||||
NodeID nextNodeID() { return _nodeID++; }
|
||||
|
||||
|
||||
|
|