Merge branch 'master' of https://github.com/highfidelity/hifi into pop_dynamicTests

This commit is contained in:
Zach Fox 2017-10-10 12:38:14 -07:00
commit 0ae69b6ad9
42 changed files with 2337 additions and 1625 deletions

9
.gitignore vendored
View file

@ -17,6 +17,15 @@ Makefile
local.properties
android/libraries
# VSCode
# List taken from Github Global Ignores master@435c4d92
# https://github.com/github/gitignore/commits/master/Global/VisualStudioCode.gitignore
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
# Xcode
*.xcodeproj
*.xcworkspace

View file

@ -0,0 +1,609 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body
{
margin: 0;
padding: 0;
color: #333;
background-color: #eee;
font: 300 16px/22px "Lato", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
background: rgba(74,219,255,1);
background: -moz-linear-gradient(-45deg, rgba(74,219,255,1) 0%, rgba(61,171,255,1) 41%, rgba(54,124,209,1) 100%);
background: -webkit-gradient(left top, right bottom, color-stop(0%, rgba(74,219,255,1)), color-stop(41%, rgba(61,171,255,1)), color-stop(100%, rgba(54,124,209,1)));
background: -webkit-linear-gradient(-45deg, rgba(74,219,255,1) 0%, rgba(61,171,255,1) 41%, rgba(54,124,209,1) 100%);
background: -o-linear-gradient(-45deg, rgba(74,219,255,1) 0%, rgba(61,171,255,1) 41%, rgba(54,124,209,1) 100%);
background: -ms-linear-gradient(-45deg, rgba(74,219,255,1) 0%, rgba(61,171,255,1) 41%, rgba(54,124,209,1) 100%);
background: linear-gradient(135deg, rgba(74,219,255,1) 0%, rgba(61,171,255,1) 41%, rgba(54,124,209,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4adbff', endColorstr='#367cd1', GradientType=1 );
}
h1,h2,h3,h4,h5,h6
{
margin: 0 0 .5em;
font-weight: 500;
line-height: 1.1;
}
h1 { font-size: 2.25em; } /* 36px */
h2 { font-size: 1.75em; } /* 28px */
h3 { font-size: 1.375em; } /* 22px */
h4 { font-size: 1.125em; } /* 18px */
h5 { font-size: 1em; } /* 16px */
h6 { font-size: .875em; } /* 14px */
p
{
margin: 0 0 1.5em;
line-height: 1.5;
}
blockquote
{
padding: 1em 2em;
margin: 0 0 2em;
border-left: 5px solid #eee;
}
hr
{
height: 0;
margin-top: 1em;
margin-bottom: 2em;
border: 0;
border-top: 1px solid #ddd;
}
table
{
background-color: transparent;
border-spacing: 0;
border-collapse: collapse;
border-top: 1px solid #ddd;
}
th, td
{
padding: .5em 1em;
vertical-align: top;
text-align: left;
border-bottom: 1px solid #ddd;
}
a:link { color: #0093C5; }
a:visited { color: #0093C5; }
a:focus { color: black; }
a:hover { color: #00B4EF; }
a:active { color: #00B4EF; }
/* -----------------------
Layout styles
------------------------*/
.container
{
max-width: 50em;
margin: 0 auto;
background-color: #fff;
}
.header
{
color: #fff;
background: #333;
padding: 1em 1.25em;
}
.header-heading { margin: 0; }
.nav-bar
{
background: #000;
padding: 0;
}
.content { padding: 1em 1.25em; }
.footer
{
color: #fff;
background: #000;
}
.alert
{
padding: 1em 1.25em;
border-radius: 2px;
border-width: thin;
border-color: #ccc;
background: #eee;
}
/* -----------------------
Nav
------------------------*/
.nav
{
margin: 0;
padding: 0;
list-style: none;
}
.nav li
{
display: inline;
margin: 0;
}
.nav a
{
display: block;
padding: .7em 1.25em;
color: #fff;
text-decoration: none;
border-bottom: 1px solid gray;
}
.nav a:link { color: white; }
.nav a:visited { color: white; }
.nav a:focus
{
color: black;
background-color: white;
}
.nav a:hover
{
color: white;
background-color: green;
}
.nav a:active
{
color: white;
background-color: red;
}
/* -----------------------
Single styles
------------------------*/
.img-responsive { max-width: 100%; }
.btn
{
color: #fff !important;
background-color: royalblue;
border-color: #222;
display: inline-block;
padding: .5em 1em;
margin-bottom: 0;
font-weight: 400;
line-height: 1.2;
text-align: center;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
border: 1px solid transparent;
border-radius: .2em;
text-decoration: none;
}
.btn:hover
{
color: #fff !important;
background-color: #0093C5;
}
.btn:focus
{
color: #fff !important;
background-color: black;
}
.btn:active
{
color: #fff !important;
background-color: black;
}
.table
{
width: 100%;
max-width: 100%;
margin-bottom: 20px;
}
.list-unstyled
{
padding-left: 0;
list-style: none;
}
.list-inline
{
padding-left: 0;
margin-left: -5px;
list-style: none;
}
.list-inline > li
{
display: inline-block;
padding-right: 5px;
padding-left: 5px;
}
/* -----------------------
Wide styles
------------------------*/
@media (min-width: 42em)
{
.header { padding: 1.5em 3em; }
.nav-bar { padding: 1em 3em; }
.content { padding: 2em 3em; }
.footer { padding: 2em 3em; }
.nav li
{
display: inline;
margin: 0 1em 0 0;
}
.nav a
{
display: inline;
padding: 0;
border-bottom: 0;
}
}
</style>
<title>Backing Up Your Private Keys | High Fidelity</title>
</head>
<body>
<div class="container">
<div class="header">
<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 1200 95" style="enable-background:new 0 0 1200 95;" xml:space="preserve">
<style type="text/css">
.st15{fill:#10bcff;}
.st16{fill:#939598;}
</style>
<g id="Layer_1_1_">
<path class="st15" d="M144,35.8v29.2h-6.3V52.3h-10.3v12.8h-6.3V35.8h6.3v11.3h10.3V35.8H144z"/>
<path class="st15" d="M155.1,65.1h-6.3V35.8h6.3V65.1z"/>
<path class="st15" d="M173.2,40.5c-1.5,0-2.7,0.1-3.8,0.4c-1,0.3-1.8,0.8-2.5,1.4c-0.6,0.6-1.1,1.6-1.4,2.7s-0.4,2.5-0.4,4.2v2.7
c0,1.8,0.1,3.2,0.4,4.3c0.2,1.1,0.6,2,1.2,2.6c0.5,0.6,1.3,1.1,2.2,1.3c0.9,0.2,2,0.4,3.3,0.4c0.4,0,0.8,0,1.2-0.1
c0.4,0,0.8-0.1,1.3-0.1v-7.9h-3.7l0.6-4.8h9v16.7c-1.1,0.4-2.5,0.7-4.3,0.9c-1.7,0.2-3.4,0.4-5.2,0.4c-2.2,0-4.1-0.3-5.7-0.8
c-1.6-0.5-2.8-1.4-3.8-2.5c-1-1.1-1.7-2.5-2.2-4.2c-0.5-1.7-0.6-3.7-0.6-5.9v-3c0-2.1,0.2-3.9,0.6-5.6c0.5-1.7,1.2-3.1,2.3-4.3
c1.1-1.2,2.5-2.1,4.2-2.8c1.7-0.6,3.9-1,6.5-1c1.4,0,2.8,0.1,4.2,0.4c1.4,0.2,2.5,0.5,3.4,0.8l-1,4.7c-0.8-0.2-1.7-0.4-2.6-0.6
C175.5,40.5,174.5,40.5,173.2,40.5z"/>
<path class="st15" d="M208.8,35.8v29.2h-6.3V52.3h-10.3v12.8H186V35.8h6.3v11.3h10.3V35.8H208.8z"/>
<path class="st15" d="M242.2,35.8l-0.7,5.1h-10.9V47h10.1l-0.7,5.1h-9.4v13h-6.3V35.8H242.2z"/>
<path class="st15" d="M252.3,65.1h-6.3V35.8h6.3V65.1z"/>
<path class="st15" d="M257.4,35.8h9.6c2.5,0,4.5,0.4,6.2,1s3,1.6,4,2.7c1,1.2,1.7,2.5,2.1,4.2c0.4,1.7,0.6,3.4,0.6,5.3v2.8
c0,1.9-0.2,3.7-0.6,5.4c-0.4,1.7-1.1,3-2.1,4.2c-1,1.2-2.3,2.1-4,2.7c-1.7,0.6-3.7,1-6.2,1h-9.5L257.4,35.8L257.4,35.8z M263.6,60
h2.7c1.2,0,2.2-0.1,3.1-0.4c0.9-0.3,1.7-0.8,2.2-1.4s1-1.5,1.3-2.6c0.3-1.1,0.4-2.4,0.4-4.1v-2.2c0-1.7-0.1-3-0.4-4.1
c-0.3-1.1-0.7-1.9-1.3-2.6s-1.3-1.1-2.2-1.4c-0.9-0.2-1.9-0.4-3.1-0.4h-2.7V60z"/>
<path class="st15" d="M302,35.8l-0.6,4.9h-11.3v6.4h10.6l-0.6,4.9h-10v8.2h11.9l-0.6,4.9h-17.6V35.8H302z"/>
<path class="st15" d="M312.4,35.8V60h11.9l-0.7,5.1h-17.4V35.8H312.4z"/>
<path class="st15" d="M334.6,65.1h-6.3V35.8h6.3V65.1z"/>
<path class="st15" d="M361.6,35.8l-0.7,5.1H353v24.2h-6.3V40.9h-8.6l0.7-5.1C338.8,35.8,361.6,35.8,361.6,35.8z"/>
<path class="st15" d="M376.5,47.2l6.1-11.4h6.4l-9.6,16.5v12.8h-6.3V52.3l-9.5-16.5h6.9L376.5,47.2z"/>
<g>
<path class="st15" d="M58.8,92c-5.9,0-11.7-1.2-17.1-3.4c-5.3-2.2-9.9-5.4-13.9-9.4c-4-4-7.2-8.7-9.4-13.9C16,59.7,14.8,54,14.8,48
c0-5.9,1.2-11.7,3.4-17.1c2.2-5.3,5.4-9.9,9.4-13.9s8.7-7.2,13.9-9.4C47,5.3,52.7,4.2,58.7,4.2s11.7,1.2,17.1,3.4
C81,9.8,85.7,13,89.7,17s7.2,8.7,9.4,13.9c2.3,5.4,3.4,11.2,3.4,17.1s-1.2,11.7-3.4,17.1c-2.2,5.3-5.4,9.9-9.4,13.9
c-4,4-8.7,7.2-13.9,9.4C70.5,90.8,64.7,92,58.8,92z M58.8,8.7C37.1,8.7,19.4,26.4,19.4,48s17.7,39.4,39.4,39.4S98.1,69.7,98.1,48
S80.5,8.7,58.8,8.7z"/>
<path class="st15" d="M72.2,66.7V35.9c1.9-0.6,3.3-2.5,3.3-4.6c0-2.7-2.2-4.8-4.8-4.8c-2.7,0-4.8,2.2-4.8,4.8
c0,2.1,1.2,3.8,3.1,4.5v14.4l-20.1-9.3V29.5c1.9-0.6,3.3-2.5,3.3-4.6c0-2.7-2.2-4.8-4.8-4.8c-2.7,0-4.8,2.2-4.8,4.8
c0,2.1,1.2,3.8,3.1,4.5v31c-1.8,0.7-3.1,2.5-3.1,4.5c0,2.7,2.2,4.8,4.8,4.8c2.7,0,4.8-2.2,4.8-4.8c0-2.1-1.4-4-3.3-4.6V44.7
l20.1,9.3v12.7c-1.8,0.7-3.1,2.5-3.1,4.5c0,2.7,2.2,4.8,4.8,4.8c2.7,0,4.8-2.2,4.8-4.8C75.5,69.1,74.1,67.4,72.2,66.7z"/>
</g>
</g>
<path class="st16" d="M418.8,34h2.6v38.6h-2.6V34z"/>
<path class="st16" d="M471.1,35.3v29.9h-2.7V50.8h-15.6v14.4h-2.7V35.3h2.7v13h15.6v-13H471.1z"/>
<path class="st16" d="M480.1,55.4c0,1.5,0.2,2.7,0.4,3.8c0.3,1,0.7,1.9,1.3,2.5c0.6,0.7,1.5,1.1,2.5,1.4s2.4,0.4,4,0.4
c0.9,0,1.8-0.1,2.8-0.2c1-0.1,1.8-0.3,2.5-0.4l-0.3,2.1c-0.6,0.2-1.5,0.4-2.5,0.5c-1,0.1-2,0.2-3,0.2c-1.9,0-3.5-0.2-4.8-0.7
c-1.3-0.4-2.4-1.1-3.2-1.9c-0.8-0.9-1.4-1.9-1.7-3.2c-0.4-1.3-0.5-2.8-0.5-4.5v-1.6c0-1.6,0.2-3,0.5-4.3c0.3-1.3,0.9-2.4,1.6-3.3
c0.7-0.9,1.7-1.6,2.8-2.1c1.1-0.5,2.5-0.7,4.2-0.7c1.4,0,2.7,0.2,3.7,0.7c1,0.4,1.9,1,2.6,1.8c0.7,0.8,1.2,1.7,1.5,2.7
c0.3,1,0.5,2.2,0.5,3.5v1.2c0,0.8-0.1,1.4-0.4,1.8c-0.2,0.3-0.8,0.5-1.6,0.5H480.1z M486.5,45.4c-1.1,0-2,0.1-2.8,0.4
c-0.8,0.3-1.5,0.7-2,1.4s-0.9,1.4-1.2,2.5c-0.3,1-0.4,2.3-0.4,3.7h12.3v-1.5c0-2.2-0.5-3.8-1.4-4.9C490.1,46,488.6,45.4,486.5,45.4z
"/>
<path class="st16" d="M500.8,34h2.6v31.2h-2.6V34z"/>
<path class="st16" d="M528.3,55.5c0,1.8-0.2,3.3-0.7,4.6c-0.4,1.3-1.1,2.3-1.9,3.2c-0.8,0.8-1.8,1.4-2.9,1.8
c-1.1,0.4-2.4,0.6-3.7,0.6c-0.7,0-1.3,0-1.8-0.1c-0.5-0.1-1.1-0.1-1.6-0.3c-0.5-0.1-1-0.3-1.5-0.5c-0.5-0.2-1-0.4-1.6-0.7V75h-2.6
V43.7h2.2l0.3,2.9c1.5-2.3,4-3.4,7.4-3.4c1.2,0,2.4,0.2,3.4,0.5c1,0.4,1.9,1,2.6,1.8c0.7,0.8,1.3,1.9,1.7,3.2
c0.4,1.3,0.6,2.9,0.6,4.8V55.5z M525.7,54.1c0-1.3-0.1-2.5-0.3-3.6c-0.2-1.1-0.5-2-1-2.7c-0.5-0.7-1.1-1.3-2-1.7
c-0.8-0.4-1.8-0.6-3.1-0.6c-1.3,0-2.3,0.2-3.2,0.5c-0.9,0.3-1.5,0.8-2.1,1.4c-0.5,0.6-0.9,1.4-1.1,2.3c-0.2,0.9-0.3,2-0.3,3.2v9
c1,0.5,1.9,0.9,2.8,1.2c0.9,0.2,2,0.4,3.2,0.4c1.3,0,2.4-0.2,3.3-0.5c0.9-0.3,1.6-0.9,2.1-1.6c0.5-0.7,0.9-1.6,1.2-2.6
c0.2-1.1,0.4-2.3,0.4-3.6V54.1z"/>
</svg>
</div>
<div class="content">
<div class="main">
<h1>Backing Up Your Private Keys</h1>
<hr>
<!-- Paragraphs -->
<h3>What are private keys?</h3>
<p>A private key is a secret piece of text that is used to prove ownership, unlock confidential information and sign transactions.</p>
<p>In High Fidelity, your private keys are used to securely access the contents of your Wallet and Purchases.</p>
<hr>
<h3>Where are my private keys stored?"</h3>
<p>By default, your private keys are only stored on your hard drive in High Fidelity Interface's <code>AppData</code> directory.</p>
<p>Here is the file path of your hifikey - you can browse to it using your file explorer.</p>
<div class="alert"> <code>HIFIKEY_PATH_REPLACEME</code> </div>
<hr>
<h3>How should I make a backup of my private keys?</h3>
<p>You should backup your <code>.hifikey</code> file above by copying it to a USB flash drive, or to a service like Dropbox or Google Drive. Restore your backup by replacing the file in Interface's AppData directory with your backed-up copy.</p>
<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 497.3 186.1" style="enable-background:new 0 0 497.3 186.1;" xml:space="preserve">
<style type="text/css">
.st0{fill:#CECECE;}
.st1{fill:#FFFFFF;}
.st2{fill:#FEFEFE;}
.st3{fill:#0DA860;}
.st4{fill:#F9C942;}
.st5{fill:#367CF3;}
.st6{fill:#2D6FDC;}
.st7{fill:#E4B83D;}
.st8{fill:#08137C;}
.st9{fill:#EF3B4E;}
.st10{fill:#B8355B;}
.st11{fill:#A7C5D1;}
.st12{fill:#7C909B;}
.st13{fill:#CBF2FD;}
.st14{fill:#000222;}
</style>
<circle class="st0" cx="255" cy="69.5" r="61.1"/>
<circle class="st0" cx="88" cy="69.5" r="61.1"/>
<circle class="st1" cx="88" cy="65.5" r="61.1"/>
<path class="st2" d="M133.4,78c0-0.1-0.1-0.2-0.1-0.3c-5-8.7-10-17.4-15-26c-4.7-8.2-9.4-16.3-14.1-24.5c-0.2-0.3-0.4-0.4-0.7-0.4
c-10.2,0-20.4,0-30.6,0c-0.2,0-0.3,0-0.5,0c-0.1,0.1-0.2,0.2-0.2,0.3c-9.7,16.8-19.4,33.6-29.1,50.5c-0.2,0.3-0.2,0.5,0,0.8
c4.2,7.2,8.4,14.5,12.6,21.7c1,1.7,2,3.5,3,5.2c0.1,0.1,0.3,0.1,0.5,0.1c19.4,0,38.8,0,58.2,0c0.4,0,0.6-0.1,0.8-0.4
c4.3-7.4,8.6-14.9,12.9-22.3C131.6,81.1,132.5,79.6,133.4,78z"/>
<path class="st3" d="M58.5,105.3c-1-1.7-2-3.4-3-5.2c-4.2-7.2-8.4-14.5-12.6-21.7c-0.2-0.3-0.2-0.5,0-0.8
C52.6,60.8,62.3,43.9,72,27.1c0.1-0.1,0.1-0.2,0.2-0.3c0.1,0.1,0.2,0.2,0.2,0.4c5.1,8.9,10.3,17.8,15.4,26.6
c0.1,0.1,0.2,0.2,0.2,0.4c-0.1,0.1-0.2,0.2-0.2,0.3c-3.2,5.5-6.4,11-9.6,16.5c-1.3,2.3-2.6,4.6-4,6.9c-0.1,0.1-0.2,0.2-0.2,0.3
c-1.9,3.3-3.8,6.6-5.7,9.9c-2.7,4.7-5.5,9.4-8.2,14.2c-0.5,0.9-1.1,1.8-1.5,2.7c0,0,0,0,0,0c0,0.1-0.1,0.1-0.1,0.2
C58.6,105.2,58.5,105.3,58.5,105.3z"/>
<path class="st4" d="M88.1,54.2c0-0.2-0.1-0.3-0.2-0.4C82.8,44.9,77.6,36,72.5,27.2c-0.1-0.1-0.2-0.2-0.2-0.4c0.2-0.1,0.3,0,0.5,0
c10.2,0,20.4,0,30.6,0c0.3,0,0.5,0.1,0.7,0.4c4.7,8.2,9.4,16.3,14.1,24.5c5,8.7,10,17.4,15,26c0.1,0.1,0.1,0.2,0.1,0.3
c-0.1,0-0.1,0-0.2,0c0-0.1-0.1-0.1-0.2-0.1c-3.6-1.1-7.2-2.2-10.7-3.3c-2.5-0.8-4.9-1.5-7.4-2.3c-4.2-1.3-8.4-2.6-12.6-3.9
c-2.3-0.7-4.6-1.4-6.8-2.1c-0.1,0-0.3-0.1-0.4,0c0,0-0.1-0.1-0.1-0.1c-1.6-2.7-3.1-5.4-4.7-8.1C89.6,56.8,88.8,55.5,88.1,54.2z"/>
<path class="st5" d="M133.2,78c0.1,0,0.1,0,0.2,0c-0.9,1.5-1.8,3.1-2.6,4.6c-4.3,7.4-8.6,14.8-12.9,22.3c-0.2,0.3-0.4,0.4-0.8,0.4
c-19.4,0-38.8,0-58.2,0c-0.2,0-0.3,0.1-0.5-0.1c0,0,0.1-0.1,0.1-0.1c0.1,0,0.1-0.1,0.1-0.2c0,0,0,0,0,0c0.3-0.1,0.5-0.3,0.8-0.5
c1.1-1,2.3-2.1,3.4-3.2c1.6-1.5,3.2-3,4.8-4.5c1.1-1.1,2.3-2.1,3.4-3.2c1.6-1.5,3.3-3,4.9-4.5c1.2-1.1,2.3-2.1,3.5-3.2
c1.8-1.7,3.6-3.4,5.4-5c0.8-0.8,1.7-1.5,2.5-2.4c0.2-0.2,0.5-0.2,0.5-0.5c1.5,0,3,0,4.5,0c3.1,0,6.2,0,9.3,0
c0.2,0.1,0.3,0.1,0.5,0.1c10.1,0,20.3,0,30.4,0C132.9,78,133.1,78,133.2,78z"/>
<path class="st2" d="M101.8,78c-3.1,0-6.2,0-9.3,0c-1.5,0-3,0-4.5,0c-0.2,0-0.4,0-0.5,0c-3.9,0-7.8,0-11.7,0c-0.5,0-0.9,0-1.4,0
c1.3-2.3,2.6-4.6,4-6.9c3.2-5.5,6.4-11,9.6-16.5c0.1-0.1,0.1-0.2,0.2-0.3c0.8,1.3,1.5,2.6,2.3,3.9c1.6,2.7,3.1,5.4,4.7,8.1
c0,0,0.1,0.1,0.1,0.1c1.2,2,2.3,4,3.5,6C99.6,74.2,100.7,76.1,101.8,78z"/>
<path class="st6" d="M74.3,78c0.5,0,0.9,0,1.4,0c3.9,0,7.8,0,11.7,0c0.2,0,0.4,0,0.5,0c-0.1,0.3-0.3,0.4-0.5,0.5
c-0.8,0.8-1.7,1.6-2.5,2.4c-1.8,1.7-3.6,3.4-5.4,5c-1.2,1.1-2.3,2.1-3.5,3.2c-1.6,1.5-3.2,3-4.9,4.5c-1.2,1.1-2.3,2.1-3.4,3.2
c-1.6,1.5-3.2,3-4.8,4.5c-1.1,1.1-2.3,2.1-3.4,3.2c-0.2,0.2-0.4,0.4-0.8,0.5c0.4-0.9,1-1.8,1.5-2.7c2.7-4.7,5.4-9.4,8.2-14.2
c1.9-3.3,3.8-6.6,5.7-9.9C74.2,78.1,74.2,78.1,74.3,78z"/>
<path class="st6" d="M58.7,105c0,0.1,0,0.2-0.1,0.2C58.6,105.1,58.7,105.1,58.7,105z"/>
<path class="st7" d="M101.8,78c-1.1-1.9-2.2-3.8-3.3-5.7c-1.1-2-2.3-4-3.5-6c0.1-0.2,0.3-0.1,0.4,0c2.3,0.7,4.6,1.4,6.8,2.1
c4.2,1.3,8.4,2.6,12.6,3.9c2.5,0.8,4.9,1.5,7.4,2.3c3.6,1.1,7.2,2.2,10.7,3.3c0.1,0,0.2,0,0.2,0.1c-0.2,0-0.3,0-0.5,0
c-10.1,0-20.3,0-30.4,0C102.1,78,101.9,78.1,101.8,78z"/>
<g>
<path class="st1" d="M315.5,65.6c0.1-33.6-27.3-60.9-61-61c-33.6-0.1-61,27.2-61,60.9c-0.1,33.6,27.2,61,61,61.1
C288.1,126.6,315.5,99.3,315.5,65.6z"/>
<path class="st1" d="M315.5,65.6c-0.1,33.7-27.4,61.1-61,61c-33.7-0.1-61-27.4-61-61.1c0.1-33.7,27.4-61,61-60.9
C288.3,4.6,315.6,31.9,315.5,65.6z M297.6,45.8c-0.1-0.1-0.2-0.1-0.3-0.2c-7-4.4-14-8.9-20.9-13.4c-0.3-0.2-0.4-0.1-0.7,0
c-6.9,4.4-13.9,8.8-20.8,13.3c-0.4,0.3-0.4,0.3,0,0.5c6.9,4.4,13.8,8.8,20.7,13.2c0.1,0.1,0.3,0.2,0.4,0.3
c-7.2,4.6-14.3,9.1-21.5,13.7c0.2,0.1,0.3,0.2,0.5,0.3c6.9,4.4,13.8,8.8,20.7,13.2c0.3,0.2,0.5,0.2,0.8,0c6.7-4.3,13.3-8.5,20-12.7
c0.4-0.2,0.8-0.5,1.2-0.8c-7.2-4.6-14.4-9.1-21.6-13.7C283.2,55,290.4,50.4,297.6,45.8z M254.5,73.3c-7.2-4.6-14.4-9.2-21.6-13.7
c0.2-0.1,0.4-0.2,0.5-0.3c6.9-4.4,13.7-8.7,20.6-13.1c0.4-0.3,0.4-0.3,0-0.6c-6.9-4.4-13.8-8.8-20.7-13.2c-0.3-0.2-0.5-0.2-0.8,0
c-6.9,4.4-13.8,8.8-20.7,13.2c-0.4,0.3-0.4,0.3,0,0.6c5.3,3.4,10.6,6.8,15.9,10.1c1.7,1.1,3.4,2.2,5.2,3.3
c-7.2,4.6-14.4,9.1-21.6,13.7c0.2,0.1,0.3,0.2,0.5,0.3c6.9,4.4,13.8,8.8,20.7,13.2c0.3,0.2,0.5,0.2,0.8,0
c5.1-3.3,10.2-6.5,15.4-9.8C250.6,75.8,252.5,74.5,254.5,73.3z M275.9,91.6c-0.1-0.1-0.2-0.2-0.3-0.2c-6.9-4.4-13.9-8.8-20.8-13.3
c-0.2-0.2-0.4-0.2-0.7,0c-6.9,4.4-13.9,8.9-20.8,13.3c-0.1,0.1-0.2,0.2-0.4,0.3c0.2,0.1,0.3,0.2,0.4,0.3
c6.9,4.4,13.9,8.8,20.8,13.3c0.3,0.2,0.5,0.1,0.7,0c6.9-4.4,13.8-8.8,20.7-13.2C275.7,91.8,275.8,91.7,275.9,91.6z"/>
<path class="st8" d="M297.6,45.8c-7.2,4.6-14.4,9.1-21.6,13.7c7.2,4.6,14.4,9.1,21.6,13.7c-0.4,0.3-0.8,0.5-1.2,0.8
c-6.7,4.2-13.3,8.5-20,12.7c-0.3,0.2-0.5,0.2-0.8,0c-6.9-4.4-13.8-8.8-20.7-13.2c-0.1-0.1-0.3-0.2-0.5-0.3
c7.2-4.6,14.3-9.1,21.5-13.7c-0.2-0.1-0.3-0.2-0.4-0.3c-6.9-4.4-13.8-8.8-20.7-13.2c-0.4-0.3-0.4-0.3,0-0.5
c6.9-4.4,13.9-8.8,20.8-13.3c0.2-0.2,0.4-0.2,0.7,0c7,4.5,14,8.9,20.9,13.4C297.4,45.7,297.4,45.7,297.6,45.8z"/>
<path class="st8" d="M254.5,73.3c-2,1.3-3.9,2.5-5.8,3.7c-5.1,3.3-10.3,6.5-15.4,9.8c-0.3,0.2-0.5,0.2-0.8,0
c-6.9-4.4-13.8-8.8-20.7-13.2c-0.1-0.1-0.3-0.2-0.5-0.3c7.2-4.6,14.3-9.1,21.6-13.7c-1.8-1.1-3.5-2.2-5.2-3.3
c-5.3-3.4-10.6-6.8-15.9-10.1c-0.4-0.3-0.4-0.3,0-0.6c6.9-4.4,13.8-8.8,20.7-13.2c0.3-0.2,0.5-0.2,0.8,0
c6.9,4.4,13.8,8.8,20.7,13.2c0.4,0.3,0.4,0.3,0,0.6c-6.9,4.4-13.7,8.7-20.6,13.1c-0.2,0.1-0.3,0.2-0.5,0.3
C240.1,64.1,247.2,68.7,254.5,73.3z"/>
<path class="st8" d="M275.9,91.6c-0.1,0.2-0.3,0.2-0.4,0.3c-6.9,4.4-13.8,8.8-20.7,13.2c-0.2,0.2-0.4,0.2-0.7,0
c-6.9-4.4-13.9-8.9-20.8-13.3c-0.1-0.1-0.2-0.1-0.4-0.3c0.1-0.1,0.3-0.2,0.4-0.3c6.9-4.4,13.9-8.8,20.8-13.3c0.3-0.2,0.4-0.1,0.7,0
c6.9,4.4,13.9,8.9,20.8,13.3C275.7,91.4,275.8,91.5,275.9,91.6z"/>
</g>
<path class="st9" d="M389.9,117c-6.8-6.8-13.7-13.6-20.5-20.5c-1.9-2-1.8-5.6,0.1-7.7c0.2-0.3,0.5-0.5,0.8-0.8
c15.9-15.9,31.8-31.7,47.6-47.6c2.6-2.6,5.9-1.9,7.8-0.1c0.3,0.3,0.6,0.6,0.9,0.9c6.2,6.2,12.5,12.5,18.7,18.7
c0.3,0.3,0.6,0.6,0.9,1c0.1,0.3,0.3,0.6,0.4,0.8c0.8,1.7,0.4,4-0.9,5.2c-16.4,16.3-32.7,32.7-49.1,49c-0.2,0.2-0.4,0.4-0.7,0.6
C394,117.8,392,117.9,389.9,117z M423.3,62.2c-2,0.5-3.9,1-5.8,1.6c-1.6,0.4-1.6,0.4-0.4,1.6c0.4,0.4,0.5,0.7,0,1.1
c-5,5-9.9,9.9-14.9,14.9c-0.1,0.1-0.3,0.4-0.5,0.2c-0.1-0.1-0.1-0.3-0.1-0.5c0-1.5-0.1-2.9-0.1-4.4c0-0.6,0.2-1.1,0.7-1.6
c1.2-1.2,2.4-2.4,3.6-3.6c0.3-0.3,0.6-0.5,1.2-0.4c1.7,0.2,3.2-1.2,3.2-2.9c0-1.9-1.4-3.2-3.2-3.1c-1.8,0.1-3.1,1.6-2.8,3.4
c0.1,0.4-0.1,0.7-0.4,1c-1.2,1.1-2.3,2.3-3.5,3.4c-1.2,1.1-1.7,2.4-1.6,4c0.1,2.2,0.1,4.5,0.1,6.7c0,1.3-1,2-1.7,2.7
c-0.5,0.5-1,0-1.5-0.1c-2.2-0.5-4.4,0.7-5.3,2.7c-0.9,2.2-0.1,4.5,1.8,5.7c1.8,1.1,3.8,0.9,5.6-0.5c1.2-1,1.8-3.1,1.2-4.9
c-0.2-0.6-0.1-1,0.3-1.4c1.7-1.6,3.3-3.3,4.9-4.9c0.5-0.5,1-0.7,1.6-0.7c2.1,0,4.2,0,6.3,0.2c1.7,0.1,3.3-0.3,4.5-1.6
c0.4-0.5,0.9-0.9,1.4-1.4c0.5-0.6,0.9-0.6,1.3,0c0.3,0.4,0.6,0.5,1,0c1.1-1.1,2.2-2.2,3.3-3.3c0.4-0.4,0.4-0.6,0-1
c-1.1-1.1-2.2-2.2-3.3-3.3c-0.4-0.4-0.7-0.3-1,0.1c-1,1-2,2.1-3.1,3.1c-0.5,0.5-0.7,0.8,0,1.3c0.3,0.2,0.6,0.5,0.2,0.9
c-0.6,0.6-1.3,1.3-1.9,1.9c-0.4,0.3-0.9,0.6-1.5,0.5c-1.5-0.2-2.9-0.1-4.4-0.1c-0.2,0-0.5,0.1-0.6-0.1c0-0.1,0-0.1,0-0.2
c3.7-3.7,7.4-7.4,11.1-11.1c0.4-0.4,0.6-0.2,0.9,0.1c1.3,1.2,1.3,1.1,1.7-0.5C422.3,66,422.8,64.1,423.3,62.2z"/>
<path class="st10" d="M389.9,117c2.1,0.9,4.1,0.9,6-0.4c0.3-0.2,0.5-0.4,0.7-0.6c16.4-16.3,32.7-32.7,49.1-49
c1.3-1.3,1.7-3.5,0.9-5.2c-0.1-0.3-0.2-0.6-0.4-0.8c1.4,1.4,2.7,2.7,4.1,4.1c0.6,0.6,1.3,1.2,1.8,1.9c1.7,2.2,1.5,4.8-0.5,6.8
c-7.8,7.8-15.7,15.7-23.5,23.5c-8.3,8.3-16.5,16.5-24.8,24.8c-1,1-2.1,1.6-3.4,1.9c-1.8,0.3-3.4-0.1-4.7-1.4
C393.5,120.5,391.7,118.8,389.9,117z"/>
<path class="st11" d="M445.3,59.9c-6.2-6.2-12.5-12.5-18.7-18.7c5-5,10.1-10,15.1-15.1c0.6-0.6,0.8-0.6,1.4,0c6,6,12,12,18,18
C455.9,49.4,450.6,54.7,445.3,59.9z M439.3,37.5c-0.5-0.5-0.9-1-1.4-1.4c-0.5-0.5-1.1-0.5-1.6,0c-0.4,0.4-0.8,0.8-1.2,1.2
c-0.5,0.6-0.5,1.1,0,1.7c0.5,0.6,1.1,1.1,1.7,1.7c2,2.2,2,1.7,3.9-0.1c0,0,0,0,0.1-0.1c0.5-0.5,0.5-1.1,0-1.6
C440.3,38.4,439.8,38,439.3,37.5z M449,47.2c-0.5-0.5-1-1-1.5-1.5c-0.7-0.6-1.1-0.5-2.5,1c-0.8,0.8-0.9,1.3-0.3,1.9
c0.9,1,1.9,1.9,2.9,2.9c0.7,0.6,1.1,0.5,2.5-1c0.8-0.8,0.9-1.3,0.3-1.9C449.9,48.1,449.5,47.6,449,47.2z"/>
<path class="st12" d="M445.3,59.9c5.3-5.3,10.5-10.5,15.8-15.8c1.5,1.5,3,3,4.5,4.4c0.5,0.5,0.4,0.7,0,1.1
c-4.9,4.8-9.7,9.7-14.6,14.5c-0.2,0.2-0.5,0.5-0.7,0.7c-1.4-1.4-2.7-2.7-4.1-4.1C445.9,60.6,445.6,60.2,445.3,59.9z"/>
<path class="st1" d="M423.3,62.2c-0.5,2-1,3.8-1.5,5.6c-0.5,1.7-0.5,1.7-1.7,0.5c-0.3-0.3-0.6-0.4-0.9-0.1
c-3.7,3.7-7.4,7.4-11.1,11.1c0,0,0,0.1,0,0.2c0.2,0.2,0.4,0.1,0.6,0.1c1.5,0.1,2.9-0.1,4.4,0.1c0.6,0.1,1.1-0.2,1.5-0.5
c0.7-0.6,1.3-1.2,1.9-1.9c0.4-0.4,0.1-0.7-0.2-0.9c-0.6-0.5-0.5-0.8,0-1.3c1.1-1,2.1-2,3.1-3.1c0.4-0.4,0.6-0.5,1-0.1
c1.1,1.1,2.2,2.2,3.3,3.3c0.4,0.4,0.4,0.6,0,1c-1.1,1.1-2.2,2.2-3.3,3.3c-0.4,0.4-0.7,0.4-1,0c-0.5-0.6-0.9-0.6-1.3,0
c-0.4,0.5-0.9,0.9-1.4,1.4c-1.2,1.4-2.7,1.7-4.5,1.6c-2.1-0.1-4.2-0.1-6.3-0.2c-0.6,0-1.2,0.3-1.6,0.7c-1.6,1.7-3.3,3.3-4.9,4.9
c-0.4,0.4-0.6,0.8-0.3,1.4c0.6,1.7,0,3.9-1.2,4.9c-1.8,1.4-3.8,1.6-5.6,0.5c-2-1.2-2.7-3.6-1.8-5.7c0.8-2.1,3.1-3.2,5.3-2.7
c0.5,0.1,1,0.6,1.5,0.1c0.8-0.8,1.8-1.4,1.7-2.7c-0.1-2.2-0.1-4.5-0.1-6.7c0-1.6,0.5-2.9,1.6-4c1.2-1.1,2.3-2.3,3.5-3.4
c0.3-0.3,0.4-0.6,0.4-1c-0.2-1.8,1.1-3.3,2.8-3.4c1.8-0.1,3.2,1.3,3.2,3.1c0,1.7-1.5,3.1-3.2,2.9c-0.5-0.1-0.8,0.1-1.2,0.4
c-1.2,1.2-2.4,2.4-3.6,3.6c-0.5,0.4-0.7,0.9-0.7,1.6c0,1.5,0.1,2.9,0.1,4.4c0,0.2,0,0.4,0.1,0.5c0.2,0.1,0.3-0.1,0.5-0.2
c5-5,9.9-9.9,14.9-14.9c0.4-0.4,0.4-0.7,0-1.1c-1.1-1.2-1.1-1.2,0.4-1.6C419.4,63.2,421.3,62.7,423.3,62.2z"/>
<path class="st13" d="M439.3,37.5c0.5,0.5,0.9,0.9,1.4,1.4c0.5,0.5,0.5,1,0,1.6c0,0,0,0-0.1,0.1c-1.9,1.9-1.9,2.3-3.9,0.1
c-0.5-0.6-1.1-1.1-1.7-1.7c-0.6-0.6-0.6-1.1,0-1.7c0.4-0.4,0.8-0.8,1.2-1.2c0.5-0.5,1.1-0.5,1.6,0C438.4,36.6,438.9,37.1,439.3,37.5
z"/>
<path class="st13" d="M449,47.2c0.5,0.5,0.9,0.9,1.4,1.4c0.6,0.6,0.5,1.1-0.3,1.9c-1.4,1.5-1.8,1.6-2.5,1c-1-0.9-1.9-1.9-2.9-2.9
c-0.6-0.6-0.5-1.1,0.3-1.9c1.4-1.5,1.8-1.6,2.5-1C448,46.2,448.5,46.7,449,47.2z"/>
<g>
<path class="st14" d="M32.1,158.8l0.2-1.2h4.2v7.7c-0.2,0.1-0.5,0.2-0.8,0.3c-0.3,0.1-0.7,0.2-1,0.2c-0.4,0.1-0.7,0.1-1.1,0.1
s-0.7,0-1,0c-1.4,0-2.6-0.2-3.5-0.5c-0.9-0.4-1.5-0.8-2-1.5c-0.5-0.6-0.8-1.4-0.9-2.3c-0.1-0.9-0.2-1.9-0.2-2.9v-1.6
c0-1.2,0.1-2.2,0.3-3.1c0.2-0.9,0.6-1.7,1.1-2.3s1.2-1.1,2.1-1.4c0.9-0.3,2-0.5,3.3-0.5c0.6,0,1.2,0.1,1.8,0.2
c0.6,0.1,1.1,0.2,1.6,0.4l-0.3,1.1c-0.4-0.1-0.9-0.2-1.4-0.3c-0.5-0.1-1.1-0.1-1.7-0.1c-1,0-1.8,0.1-2.4,0.3s-1.2,0.5-1.6,1
c-0.4,0.5-0.7,1.1-0.9,1.9s-0.3,1.8-0.3,3v1.5c0,1.2,0.1,2.1,0.3,2.9c0.2,0.8,0.5,1.4,0.9,1.8c0.4,0.5,0.9,0.8,1.6,1
c0.7,0.2,1.5,0.3,2.4,0.3c0.5,0,0.9,0,1.4-0.1c0.4,0,0.8-0.1,1.2-0.2v-5.6H32.1z"/>
<path class="st14" d="M44.5,154.2c1,0,1.7,0.1,2.4,0.4c0.6,0.2,1.1,0.6,1.5,1.1c0.4,0.5,0.6,1,0.8,1.7c0.2,0.7,0.2,1.4,0.2,2.2v1.2
c0,0.8-0.1,1.5-0.3,2.2c-0.2,0.7-0.5,1.2-0.8,1.7c-0.4,0.5-0.9,0.8-1.5,1.1c-0.6,0.2-1.4,0.4-2.3,0.4c-1,0-1.7-0.1-2.4-0.4
c-0.6-0.2-1.1-0.6-1.5-1.1s-0.6-1-0.8-1.7c-0.2-0.7-0.2-1.4-0.2-2.2v-1.2c0-0.8,0.1-1.5,0.3-2.2c0.2-0.7,0.5-1.2,0.9-1.7
s0.9-0.8,1.5-1.1C42.8,154.3,43.6,154.2,44.5,154.2z M44.5,164.8c0.7,0,1.2-0.1,1.7-0.2s0.8-0.4,1.1-0.7c0.3-0.3,0.5-0.8,0.6-1.3
c0.1-0.5,0.2-1.2,0.2-1.9v-1c0-0.8-0.1-1.4-0.2-2s-0.3-1-0.6-1.3c-0.3-0.3-0.6-0.6-1.1-0.7s-1-0.2-1.6-0.2c-0.7,0-1.2,0.1-1.7,0.2
c-0.5,0.2-0.8,0.4-1.1,0.7c-0.3,0.3-0.5,0.8-0.6,1.3c-0.1,0.5-0.2,1.2-0.2,1.9v1c0,0.8,0.1,1.4,0.2,1.9c0.1,0.5,0.3,1,0.6,1.3
c0.3,0.3,0.6,0.6,1.1,0.7C43.2,164.7,43.8,164.8,44.5,164.8z"/>
<path class="st14" d="M57.1,154.2c1,0,1.7,0.1,2.4,0.4c0.6,0.2,1.1,0.6,1.5,1.1c0.4,0.5,0.6,1,0.8,1.7c0.2,0.7,0.2,1.4,0.2,2.2v1.2
c0,0.8-0.1,1.5-0.3,2.2c-0.2,0.7-0.5,1.2-0.8,1.7c-0.4,0.5-0.9,0.8-1.5,1.1c-0.6,0.2-1.4,0.4-2.3,0.4c-1,0-1.7-0.1-2.4-0.4
c-0.6-0.2-1.1-0.6-1.5-1.1s-0.6-1-0.8-1.7c-0.2-0.7-0.2-1.4-0.2-2.2v-1.2c0-0.8,0.1-1.5,0.3-2.2c0.2-0.7,0.5-1.2,0.9-1.7
s0.9-0.8,1.5-1.1C55.4,154.3,56.2,154.2,57.1,154.2z M57.1,164.8c0.7,0,1.2-0.1,1.7-0.2s0.8-0.4,1.1-0.7c0.3-0.3,0.5-0.8,0.6-1.3
c0.1-0.5,0.2-1.2,0.2-1.9v-1c0-0.8-0.1-1.4-0.2-2s-0.3-1-0.6-1.3c-0.3-0.3-0.6-0.6-1.1-0.7s-1-0.2-1.6-0.2c-0.7,0-1.2,0.1-1.7,0.2
c-0.5,0.2-0.8,0.4-1.1,0.7c-0.3,0.3-0.5,0.8-0.6,1.3c-0.1,0.5-0.2,1.2-0.2,1.9v1c0,0.8,0.1,1.4,0.2,1.9c0.1,0.5,0.3,1,0.6,1.3
c0.3,0.3,0.6,0.6,1.1,0.7C55.9,164.7,56.4,164.8,57.1,164.8z"/>
<path class="st14" d="M74.3,165.5c0,0.8-0.1,1.6-0.3,2.3c-0.2,0.7-0.5,1.2-0.9,1.7c-0.4,0.5-0.9,0.8-1.6,1.1
c-0.6,0.2-1.4,0.4-2.3,0.4c-1.3,0-2.7-0.2-4-0.6l0.3-1.1c0.6,0.2,1.2,0.3,1.8,0.4c0.6,0.1,1.2,0.1,1.9,0.1s1.3-0.1,1.8-0.3
c0.5-0.2,0.8-0.5,1.1-0.9c0.3-0.4,0.5-0.9,0.6-1.4c0.1-0.6,0.2-1.2,0.2-1.9v-1.3c-0.1,0.2-0.3,0.5-0.5,0.7
c-0.2,0.2-0.5,0.4-0.8,0.6c-0.3,0.2-0.7,0.3-1.1,0.4c-0.4,0.1-0.9,0.1-1.5,0.1c-0.6,0-1.2-0.1-1.8-0.3c-0.5-0.2-1-0.5-1.4-0.9
c-0.4-0.4-0.7-1-0.9-1.6c-0.2-0.7-0.3-1.5-0.3-2.5v-0.7c0-0.9,0.1-1.7,0.4-2.4s0.6-1.2,1.1-1.7c0.5-0.5,1-0.8,1.6-1
c0.6-0.2,1.3-0.3,2.1-0.3c0.8,0,1.6,0.1,2.3,0.3c0.7,0.2,1.4,0.4,2,0.8V165.5z M66.1,160.1c0,0.7,0.1,1.3,0.2,1.9s0.3,1,0.5,1.4
c0.3,0.4,0.6,0.7,1,0.8s0.9,0.3,1.6,0.3c1.2,0,2.1-0.3,2.7-0.9c0.6-0.6,0.9-1.6,0.9-3V156c-0.4-0.2-0.8-0.4-1.3-0.5
c-0.4-0.1-1-0.2-1.6-0.2c-1.3,0-2.3,0.3-3,1s-1,1.8-1,3.4V160.1z"/>
<path class="st14" d="M77.8,149.3h1.3v16.3h-1.3V149.3z"/>
<path class="st14" d="M83.6,160.5c0,0.8,0.1,1.4,0.2,2c0.1,0.5,0.4,1,0.7,1.3c0.3,0.3,0.8,0.6,1.3,0.7c0.5,0.2,1.2,0.2,2.1,0.2
c0.5,0,0.9,0,1.5-0.1c0.5-0.1,1-0.1,1.3-0.2l-0.2,1.1c-0.3,0.1-0.8,0.2-1.3,0.3c-0.5,0.1-1.1,0.1-1.6,0.1c-1,0-1.8-0.1-2.5-0.3
c-0.7-0.2-1.2-0.6-1.7-1s-0.7-1-0.9-1.7c-0.2-0.7-0.3-1.5-0.3-2.4v-0.9c0-0.8,0.1-1.6,0.3-2.3c0.2-0.7,0.5-1.3,0.8-1.7
c0.4-0.5,0.9-0.9,1.5-1.1c0.6-0.3,1.3-0.4,2.2-0.4c0.7,0,1.4,0.1,1.9,0.3c0.5,0.2,1,0.5,1.3,0.9s0.6,0.9,0.8,1.4
c0.2,0.5,0.2,1.2,0.2,1.8v0.6c0,0.4-0.1,0.7-0.2,0.9c-0.1,0.2-0.4,0.3-0.8,0.3H83.6z M86.9,155.3c-0.6,0-1,0.1-1.5,0.2
s-0.8,0.4-1,0.7c-0.3,0.3-0.5,0.8-0.6,1.3c-0.1,0.5-0.2,1.2-0.2,2h6.5v-0.8c0-1.1-0.2-2-0.7-2.6S88,155.3,86.9,155.3z"/>
<path class="st14" d="M100.2,150h4.9c1.3,0,2.3,0.2,3.1,0.5c0.8,0.3,1.5,0.8,2,1.4c0.5,0.6,0.8,1.3,1,2.2c0.2,0.8,0.3,1.7,0.3,2.7
v2c0,1-0.1,1.9-0.3,2.8c-0.2,0.8-0.6,1.6-1.1,2.2c-0.5,0.6-1.1,1.1-2,1.4s-1.8,0.5-3.1,0.5h-4.8V150z M101.6,164.5h3.3
c0.8,0,1.5-0.1,2.2-0.3c0.6-0.2,1.2-0.5,1.6-0.9c0.4-0.4,0.8-1,1-1.8c0.2-0.7,0.3-1.6,0.3-2.8V157c0-1.1-0.1-2-0.3-2.7
c-0.2-0.7-0.5-1.3-0.9-1.8c-0.4-0.4-0.9-0.8-1.6-1c-0.6-0.2-1.4-0.3-2.2-0.3h-3.4V164.5z"/>
<path class="st14" d="M120.7,155.6c-0.2,0-0.4-0.1-0.7-0.1c-0.2,0-0.4,0-0.6,0c-1.1,0-1.9,0.3-2.4,1c-0.5,0.7-0.8,1.7-0.8,3.2v6.1
h-1.4v-11.2h1.1l0.2,1.8c0.7-1.3,1.9-1.9,3.5-1.9c0.2,0,0.5,0,0.7,0.1c0.2,0,0.4,0.1,0.6,0.1L120.7,155.6z"/>
<path class="st14" d="M123.8,150.1c0.7,0,1,0.3,1,1c0,0.6-0.3,1-1,1c-0.6,0-1-0.3-1-1C122.9,150.4,123.2,150.1,123.8,150.1z
M123.2,154.4h1.4v11.2h-1.4V154.4z"/>
<path class="st14" d="M127.1,154.4h1.5l3.8,9.9l3.8-9.9h1.5l-4.5,11.2h-1.5L127.1,154.4z"/>
<path class="st14" d="M140.6,160.5c0,0.8,0.1,1.4,0.2,2c0.1,0.5,0.4,1,0.7,1.3c0.3,0.3,0.8,0.6,1.3,0.7c0.5,0.2,1.2,0.2,2.1,0.2
c0.5,0,0.9,0,1.5-0.1c0.5-0.1,1-0.1,1.3-0.2l-0.2,1.1c-0.3,0.1-0.8,0.2-1.3,0.3c-0.5,0.1-1.1,0.1-1.6,0.1c-1,0-1.8-0.1-2.5-0.3
c-0.7-0.2-1.2-0.6-1.7-1s-0.7-1-0.9-1.7c-0.2-0.7-0.3-1.5-0.3-2.4v-0.9c0-0.8,0.1-1.6,0.3-2.3c0.2-0.7,0.5-1.3,0.8-1.7
c0.4-0.5,0.9-0.9,1.5-1.1c0.6-0.3,1.3-0.4,2.2-0.4c0.7,0,1.4,0.1,1.9,0.3c0.5,0.2,1,0.5,1.3,0.9s0.6,0.9,0.8,1.4
c0.2,0.5,0.2,1.2,0.2,1.8v0.6c0,0.4-0.1,0.7-0.2,0.9c-0.1,0.2-0.4,0.3-0.8,0.3H140.6z M143.9,155.3c-0.6,0-1,0.1-1.5,0.2
s-0.8,0.4-1,0.7c-0.3,0.3-0.5,0.8-0.6,1.3c-0.1,0.5-0.2,1.2-0.2,2h6.5v-0.8c0-1.1-0.2-2-0.7-2.6S145,155.3,143.9,155.3z"/>
</g>
<g>
<path class="st14" d="M217.3,150h4.9c1.3,0,2.3,0.2,3.1,0.5c0.8,0.3,1.5,0.8,2,1.4c0.5,0.6,0.8,1.3,1,2.2c0.2,0.8,0.3,1.7,0.3,2.7
v2c0,1-0.1,1.9-0.3,2.8c-0.2,0.8-0.6,1.6-1.1,2.2c-0.5,0.6-1.1,1.1-2,1.4s-1.8,0.5-3.1,0.5h-4.8V150z M218.8,164.5h3.3
c0.8,0,1.5-0.1,2.2-0.3c0.6-0.2,1.2-0.5,1.6-0.9c0.4-0.4,0.8-1,1-1.8c0.2-0.7,0.3-1.6,0.3-2.8V157c0-1.1-0.1-2-0.3-2.7
c-0.2-0.7-0.5-1.3-0.9-1.8c-0.4-0.4-0.9-0.8-1.6-1c-0.6-0.2-1.4-0.3-2.2-0.3h-3.4V164.5z"/>
<path class="st14" d="M237.9,155.6c-0.2,0-0.4-0.1-0.7-0.1c-0.2,0-0.4,0-0.6,0c-1.1,0-1.9,0.3-2.4,1c-0.5,0.7-0.8,1.7-0.8,3.2v6.1
H232v-11.2h1.1l0.2,1.8c0.7-1.3,1.9-1.9,3.5-1.9c0.2,0,0.5,0,0.7,0.1c0.2,0,0.4,0.1,0.6,0.1L237.9,155.6z"/>
<path class="st14" d="M244.3,154.2c1,0,1.7,0.1,2.4,0.4c0.6,0.2,1.1,0.6,1.5,1.1c0.4,0.5,0.6,1,0.8,1.7c0.2,0.7,0.2,1.4,0.2,2.2
v1.2c0,0.8-0.1,1.5-0.3,2.2c-0.2,0.7-0.5,1.2-0.8,1.7c-0.4,0.5-0.9,0.8-1.5,1.1c-0.6,0.2-1.4,0.4-2.3,0.4c-1,0-1.7-0.1-2.4-0.4
c-0.6-0.2-1.1-0.6-1.5-1.1s-0.6-1-0.8-1.7c-0.2-0.7-0.2-1.4-0.2-2.2v-1.2c0-0.8,0.1-1.5,0.3-2.2c0.2-0.7,0.5-1.2,0.9-1.7
s0.9-0.8,1.5-1.1C242.7,154.3,243.4,154.2,244.3,154.2z M244.3,164.8c0.7,0,1.2-0.1,1.7-0.2s0.8-0.4,1.1-0.7
c0.3-0.3,0.5-0.8,0.6-1.3c0.1-0.5,0.2-1.2,0.2-1.9v-1c0-0.8-0.1-1.4-0.2-2s-0.3-1-0.6-1.3c-0.3-0.3-0.6-0.6-1.1-0.7s-1-0.2-1.6-0.2
c-0.7,0-1.2,0.1-1.7,0.2c-0.5,0.2-0.8,0.4-1.1,0.7c-0.3,0.3-0.5,0.8-0.6,1.3c-0.1,0.5-0.2,1.2-0.2,1.9v1c0,0.8,0.1,1.4,0.2,1.9
c0.1,0.5,0.3,1,0.6,1.3c0.3,0.3,0.6,0.6,1.1,0.7C243.1,164.7,243.7,164.8,244.3,164.8z"/>
<path class="st14" d="M261.9,160.6c0,0.9-0.1,1.7-0.4,2.4c-0.2,0.7-0.6,1.2-1,1.7s-0.9,0.8-1.5,1s-1.2,0.3-1.9,0.3
c-0.4,0-0.7,0-1,0c-0.3,0-0.6-0.1-0.8-0.1c-0.3-0.1-0.5-0.2-0.8-0.3c-0.3-0.1-0.5-0.2-0.8-0.4v5.7h-1.3v-16.3h1.1l0.2,1.5
c0.8-1.2,2.1-1.8,3.9-1.8c0.6,0,1.2,0.1,1.8,0.3c0.5,0.2,1,0.5,1.4,0.9c0.4,0.4,0.7,1,0.9,1.7c0.2,0.7,0.3,1.5,0.3,2.5V160.6z
M260.5,159.9c0-0.7,0-1.3-0.1-1.9s-0.3-1-0.5-1.4c-0.3-0.4-0.6-0.7-1-0.9c-0.4-0.2-1-0.3-1.6-0.3c-0.7,0-1.2,0.1-1.7,0.3
c-0.4,0.2-0.8,0.4-1.1,0.7s-0.5,0.7-0.6,1.2c-0.1,0.5-0.2,1-0.2,1.7v4.7c0.5,0.3,1,0.5,1.5,0.6c0.5,0.1,1,0.2,1.7,0.2
c0.7,0,1.3-0.1,1.7-0.3s0.8-0.5,1.1-0.8c0.3-0.4,0.5-0.8,0.6-1.4s0.2-1.2,0.2-1.9V159.9z"/>
<path class="st14" d="M269.4,165.9c-0.7,0-1.5-0.1-2.2-0.3c-0.7-0.2-1.4-0.5-2.1-0.8v-15.5h1.3v6.6c0.4-0.6,0.9-1.1,1.5-1.3
c0.6-0.3,1.3-0.4,2.2-0.4c0.7,0,1.3,0.1,1.8,0.3c0.6,0.2,1,0.5,1.4,0.9s0.7,1,0.9,1.6c0.2,0.7,0.3,1.5,0.3,2.5v1
c0,1.8-0.4,3.2-1.3,4.1C272.4,165.5,271.1,165.9,269.4,165.9z M269.3,164.8c0.7,0,1.3-0.1,1.8-0.3c0.5-0.2,0.9-0.4,1.2-0.8
c0.3-0.4,0.5-0.8,0.7-1.4c0.1-0.6,0.2-1.2,0.2-2v-0.5c0-0.7-0.1-1.3-0.2-1.9c-0.1-0.6-0.3-1-0.5-1.4s-0.6-0.7-1-0.9
c-0.4-0.2-1-0.3-1.6-0.3c-0.5,0-1,0.1-1.4,0.2s-0.8,0.4-1.1,0.7c-0.3,0.3-0.5,0.7-0.7,1.2c-0.2,0.5-0.3,1.1-0.3,1.8v4.9
c0.4,0.2,0.9,0.4,1.3,0.5C268.2,164.7,268.7,164.8,269.3,164.8z"/>
<path class="st14" d="M282.3,154.2c1,0,1.7,0.1,2.4,0.4c0.6,0.2,1.1,0.6,1.5,1.1c0.4,0.5,0.6,1,0.8,1.7c0.2,0.7,0.2,1.4,0.2,2.2
v1.2c0,0.8-0.1,1.5-0.3,2.2c-0.2,0.7-0.5,1.2-0.8,1.7c-0.4,0.5-0.9,0.8-1.5,1.1c-0.6,0.2-1.4,0.4-2.3,0.4c-1,0-1.7-0.1-2.4-0.4
c-0.6-0.2-1.1-0.6-1.5-1.1s-0.6-1-0.8-1.7c-0.2-0.7-0.2-1.4-0.2-2.2v-1.2c0-0.8,0.1-1.5,0.3-2.2c0.2-0.7,0.5-1.2,0.9-1.7
s0.9-0.8,1.5-1.1C280.6,154.3,281.4,154.2,282.3,154.2z M282.3,164.8c0.7,0,1.2-0.1,1.7-0.2s0.8-0.4,1.1-0.7
c0.3-0.3,0.5-0.8,0.6-1.3c0.1-0.5,0.2-1.2,0.2-1.9v-1c0-0.8-0.1-1.4-0.2-2s-0.3-1-0.6-1.3c-0.3-0.3-0.6-0.6-1.1-0.7s-1-0.2-1.6-0.2
c-0.7,0-1.2,0.1-1.7,0.2c-0.5,0.2-0.8,0.4-1.1,0.7c-0.3,0.3-0.5,0.8-0.6,1.3c-0.1,0.5-0.2,1.2-0.2,1.9v1c0,0.8,0.1,1.4,0.2,1.9
c0.1,0.5,0.3,1,0.6,1.3c0.3,0.3,0.6,0.6,1.1,0.7C281.1,164.7,281.6,164.8,282.3,164.8z"/>
<path class="st14" d="M288.8,154.4h1.5l3.1,4.4l3.1-4.4h1.5l-3.9,5.4l4.2,5.8h-1.6l-3.4-4.9l-3.4,4.9h-1.5l4.2-5.9L288.8,154.4z"/>
</g>
<g>
<path class="st14" d="M379.5,166c-1.1,0-2-0.1-2.8-0.4s-1.3-0.7-1.7-1.2c-0.4-0.6-0.7-1.2-0.9-2c-0.2-0.8-0.2-1.8-0.2-2.8V150h1.4
v9.5c0,1,0.1,1.9,0.2,2.5c0.2,0.7,0.4,1.2,0.7,1.6c0.3,0.4,0.8,0.7,1.3,0.9c0.5,0.2,1.2,0.3,2,0.3c0.8,0,1.5-0.1,2-0.3
c0.5-0.2,1-0.5,1.3-0.9c0.3-0.4,0.6-1,0.7-1.6s0.2-1.5,0.2-2.5V150h1.4v9.5c0,1.1-0.1,2-0.3,2.8s-0.5,1.5-0.9,2
c-0.4,0.5-1,0.9-1.7,1.2S380.6,166,379.5,166z"/>
<path class="st14" d="M394.4,157.1c0.7,0.1,1.3,0.3,1.8,0.5c0.5,0.2,0.9,0.5,1.2,0.9s0.5,0.8,0.6,1.2c0.1,0.5,0.2,0.9,0.2,1.5v0.3
c0,0.6-0.1,1.2-0.3,1.8c-0.2,0.5-0.6,1-1,1.4c-0.5,0.4-1,0.7-1.8,0.9c-0.7,0.2-1.5,0.3-2.5,0.3c-0.8,0-1.6-0.1-2.4-0.2
c-0.8-0.1-1.4-0.3-2-0.5l0.3-1.2c0.6,0.2,1.2,0.3,1.9,0.4c0.7,0.1,1.4,0.2,2.2,0.2c1.5,0,2.6-0.3,3.2-0.8c0.6-0.5,1-1.4,1-2.5
c0-0.4,0-0.7-0.1-1c-0.1-0.3-0.2-0.6-0.4-0.9c-0.2-0.3-0.5-0.5-0.9-0.6c-0.4-0.2-0.9-0.3-1.4-0.4l-2-0.3c-1.3-0.2-2.3-0.6-2.8-1.3
c-0.6-0.7-0.8-1.6-0.8-2.7V154c0-0.7,0.1-1.3,0.4-1.8c0.3-0.5,0.6-1,1.1-1.3c0.5-0.4,1.1-0.6,1.8-0.8c0.7-0.2,1.5-0.3,2.3-0.3
c0.7,0,1.5,0.1,2.1,0.2c0.7,0.1,1.2,0.3,1.7,0.5l-0.3,1.1c-0.5-0.2-1.1-0.3-1.7-0.4s-1.3-0.2-2-0.2c-1.5,0-2.5,0.3-3.2,0.8
c-0.6,0.5-1,1.3-1,2.3c0,0.8,0.2,1.4,0.6,1.8c0.4,0.4,1.1,0.7,2.2,0.8L394.4,157.1z"/>
<path class="st14" d="M401.4,165.7V150h5.5c0.8,0,1.5,0.1,2,0.3c0.5,0.2,1,0.5,1.3,0.8c0.3,0.3,0.6,0.7,0.7,1.2
c0.1,0.4,0.2,0.9,0.2,1.4v0.5c0,0.8-0.2,1.5-0.6,2c-0.4,0.5-0.9,0.9-1.6,1.2c0.5,0.1,0.8,0.3,1.2,0.5c0.3,0.2,0.6,0.5,0.8,0.9
c0.2,0.3,0.4,0.7,0.5,1.1c0.1,0.4,0.2,0.8,0.2,1.3v0.5c0,0.6-0.1,1.1-0.3,1.6c-0.2,0.5-0.5,0.9-0.9,1.3c-0.4,0.4-0.9,0.6-1.5,0.8
s-1.3,0.3-2.1,0.3H401.4z M402.8,156.9h4.2c0.9,0,1.7-0.2,2.2-0.7c0.5-0.4,0.7-1.1,0.7-1.8v-0.5c0-1.8-1-2.8-3.1-2.8h-3.9V156.9z
M402.8,164.5h4.2c1.1,0,1.9-0.2,2.4-0.7c0.5-0.4,0.8-1.2,0.8-2.2v-0.5c0-2-1.1-3.1-3.3-3.1h-4.2V164.5z"/>
<path class="st14" d="M421.6,150v7.1l7-7.1h1.6l-7.5,7.5l8,8.1h-1.8l-7.3-7.5v7.5h-1.3V150H421.6z"/>
<path class="st14" d="M433.1,160.5c0,0.8,0.1,1.4,0.2,2c0.1,0.5,0.4,1,0.7,1.3c0.3,0.3,0.8,0.6,1.3,0.7c0.5,0.2,1.2,0.2,2.1,0.2
c0.5,0,0.9,0,1.5-0.1c0.5-0.1,1-0.1,1.3-0.2l-0.2,1.1c-0.3,0.1-0.8,0.2-1.3,0.3c-0.5,0.1-1.1,0.1-1.6,0.1c-1,0-1.8-0.1-2.5-0.3
c-0.7-0.2-1.2-0.6-1.7-1s-0.7-1-0.9-1.7c-0.2-0.7-0.3-1.5-0.3-2.4v-0.9c0-0.8,0.1-1.6,0.3-2.3c0.2-0.7,0.5-1.3,0.8-1.7
c0.4-0.5,0.9-0.9,1.5-1.1c0.6-0.3,1.3-0.4,2.2-0.4c0.7,0,1.4,0.1,1.9,0.3c0.5,0.2,1,0.5,1.3,0.9s0.6,0.9,0.8,1.4
c0.2,0.5,0.2,1.2,0.2,1.8v0.6c0,0.4-0.1,0.7-0.2,0.9c-0.1,0.2-0.4,0.3-0.8,0.3H433.1z M436.4,155.3c-0.6,0-1,0.1-1.5,0.2
s-0.8,0.4-1,0.7s-0.5,0.8-0.6,1.3c-0.1,0.5-0.2,1.2-0.2,2h6.5v-0.8c0-1.1-0.2-2-0.7-2.6S437.5,155.3,436.4,155.3z"/>
<path class="st14" d="M451.7,154.4h1.5l-4.9,12.6c-0.3,0.8-0.6,1.4-0.9,1.9c-0.3,0.5-0.6,0.9-0.9,1.2c-0.3,0.3-0.6,0.5-1,0.6
c-0.4,0.1-0.7,0.2-1.2,0.2c-0.3,0-0.6,0-0.9-0.1c-0.3-0.1-0.5-0.1-0.8-0.2l0.2-1c0.2,0,0.4,0.1,0.6,0.1c0.2,0,0.5,0,0.7,0
c0.3,0,0.6,0,0.9-0.1c0.3-0.1,0.5-0.2,0.7-0.4c0.2-0.2,0.4-0.5,0.6-0.8c0.2-0.4,0.4-0.9,0.6-1.5l0.4-1.2l-4.8-11.4h1.5l3.9,9.7
L451.7,154.4z"/>
</g>
</svg>
<hr>
<h3>What happens if I lose my passphrase?</h3>
<p>Your passphrase is used to encrypt your private keys. If you lose your passphrase, you will no longer be able to decrypt your private key file nor have access to the contents of your Wallet or My Purchases.</p>
<p>In order to guarantee your privacy, nobody can help you recover your passphrase, including High Fidelity.
<p><b>Please write it down and store it securely.</b></p>
<p>&nbsp;</p>
<hr>
<h2>Want to learn more?</h2>
<p>You can find out much more about the blockchain and about commerce in High Fidelity by visiting our Docs site:</p>
<p><a href="http://docs.highfidelity.com" class="btn">Visit High Fidelity's Docs</a></p>
<hr>
</div>
</div>
<div class="footer">
High Fidelity | <a href="http://highfidelity.com" target="_blank">highfidelity.com</a>
</div>
</div>
</body>
</html>

View file

@ -29,12 +29,22 @@ RowLayout {
function playSound() {
// FIXME: MyAvatar is not properly exposed to QML; MyAvatar.qmlPosition is a stopgap
// FIXME: Audio.playSystemSound should not require position
sample = Audio.playSystemSound(sound, MyAvatar.qmlPosition);
isPlaying = true;
sample.finished.connect(function() { isPlaying = false; sample = null; });
if (sample === null && !isPlaying) {
sample = Audio.playSystemSound(sound, MyAvatar.qmlPosition);
isPlaying = true;
sample.finished.connect(reset);
}
}
function stopSound() {
sample && sample.stop();
if (sample && isPlaying) {
sample.stop();
}
}
function reset() {
sample.finished.disconnect(reset);
isPlaying = false;
sample = null;
}
Component.onCompleted: createSampleSound();

View file

@ -79,6 +79,7 @@ Rectangle {
failureErrorText.text = result.message;
root.activeView = "checkoutFailure";
} else {
root.itemHref = result.data.download_url;
root.activeView = "checkoutSuccess";
}
}
@ -114,7 +115,7 @@ Rectangle {
}
onItemHrefChanged: {
itemIsJson = root.itemHref.indexOf('.json') !== -1;
itemIsJson = root.itemHref.endsWith('.json');
}
onItemPriceChanged: {
@ -574,8 +575,8 @@ Rectangle {
anchors.right: parent.right;
text: "Rez It"
onClicked: {
if (urlHandler.canHandleUrl(itemHref)) {
urlHandler.handleUrl(itemHref);
if (urlHandler.canHandleUrl(root.itemHref)) {
urlHandler.handleUrl(root.itemHref);
}
rezzedNotifContainer.visible = true;
rezzedNotifContainerTimer.start();

View file

@ -426,7 +426,7 @@ Rectangle {
itemName: title;
itemId: id;
itemPreviewImageUrl: preview;
itemHref: root_file_url;
itemHref: download_url;
purchaseStatus: status;
purchaseStatusChanged: statusChanged;
itemEdition: model.edition_number;

View file

@ -30,12 +30,14 @@ Item {
id: commerce;
onKeyFilePathIfExistsResult: {
keyFilePath = path;
root.keyFilePath = path;
}
}
Component.onCompleted: {
commerce.getKeyFilePathIfExists();
onVisibleChanged: {
if (visible) {
commerce.getKeyFilePathIfExists();
}
}
RalewaySemiBold {
@ -103,7 +105,7 @@ Item {
ListElement {
isExpanded: false;
question: "What is a 'Security Pic'?"
answer: qsTr("Your Security Pic is an encrypted image that you selected during Wallet Setup. <b>It acts as an extra layer of Wallet security.</b><br><br>When you see your Security Pic, you know that your actions and data are securely making use of your private keys.<br><br><b>If you don't see your Security Pic on a page that is asking you for your Wallet passphrase, someone untrustworthy may be trying to gain access to your Wallet.</b><br><br>The Pic is stored on your hard drive inside the same file as your private keys.");
answer: qsTr("Your Security Pic is an encrypted image that you selected during Wallet Setup. <b>It acts as an extra layer of Wallet security.</b><br><br>When you see your Security Pic, you know that your actions and data are securely making use of your private keys.<br><br><b>If you don't see your Security Pic on a page that is asking you for your Wallet passphrase, someone untrustworthy may be trying to gain access to your Wallet.</b><br><br>The encrypted Pic is stored on your hard drive inside the same file as your private keys.");
}
ListElement {
isExpanded: false;

View file

@ -25,13 +25,13 @@ Item {
HifiConstants { id: hifi; }
id: root;
property string keyFilePath: "";
property string keyFilePath;
Hifi.QmlCommerce {
id: commerce;
onKeyFilePathIfExistsResult: {
keyFilePath = path;
root.keyFilePath = path;
}
}
@ -232,6 +232,12 @@ Item {
anchors.rightMargin: 55;
anchors.bottom: parent.bottom;
onVisibleChanged: {
if (visible) {
commerce.getKeyFilePathIfExists();
}
}
HiFiGlyphs {
id: yourPrivateKeysImage;
text: hifi.glyphs.walletKey;
@ -320,8 +326,9 @@ Item {
height: 40;
onClicked: {
Qt.openUrlExternally("https://www.highfidelity.com/");
Qt.openUrlExternally("file:///" + root.keyFilePath.substring(0, root.keyFilePath.lastIndexOf('/')));
var keyPath = "file:///" + root.keyFilePath.substring(0, root.keyFilePath.lastIndexOf('/'));
Qt.openUrlExternally(keyPath + "/backup_instructions.html");
Qt.openUrlExternally(keyPath);
removeHmdContainer.visible = true;
removeHmdContainerTimer.start();
}

View file

@ -30,6 +30,7 @@ Item {
property string lastPage;
property bool hasShownSecurityImageTip: false;
property string referrer;
property string keyFilePath;
Image {
anchors.fill: parent;
@ -58,7 +59,7 @@ Item {
}
onKeyFilePathIfExistsResult: {
keyFilePath.text = path;
root.keyFilePath = path;
}
}
@ -608,7 +609,7 @@ Item {
anchors.fill: parent;
RalewaySemiBold {
id: keyFilePathText;
id: keyFilePathHelperText;
text: "Private Key File Location:";
size: 18;
anchors.top: parent.top;
@ -627,7 +628,7 @@ Item {
colorScheme: hifi.colorSchemes.dark;
anchors.left: parent.left;
anchors.leftMargin: 30;
anchors.top: keyFilePathText.bottom;
anchors.top: keyFilePathHelperText.bottom;
anchors.topMargin: 8;
height: 24;
width: height;
@ -643,11 +644,12 @@ Item {
}
onClicked: {
Qt.openUrlExternally("file:///" + keyFilePath.text.substring(0, keyFilePath.text.lastIndexOf('/')));
Qt.openUrlExternally("file:///" + keyFilePath.substring(0, keyFilePath.lastIndexOf('/')));
}
}
RalewayRegular {
id: keyFilePath;
id: keyFilePathText;
text: root.keyFilePath;
size: 18;
anchors.top: clipboardButton.top;
anchors.left: clipboardButton.right;
@ -670,7 +672,7 @@ Item {
id: openInstructionsButton;
color: hifi.buttons.blue;
colorScheme: hifi.colorSchemes.dark;
anchors.top: keyFilePath.bottom;
anchors.top: keyFilePathText.bottom;
anchors.topMargin: 30;
anchors.left: parent.left;
anchors.leftMargin: 30;
@ -682,8 +684,9 @@ Item {
instructions01Container.visible = false;
instructions02Container.visible = true;
keysReadyPageFinishButton.visible = true;
Qt.openUrlExternally("https://www.highfidelity.com/");
Qt.openUrlExternally("file:///" + root.keyFilePath.substring(0, root.keyFilePath.lastIndexOf('/')));
var keyPath = "file:///" + root.keyFilePath.substring(0, root.keyFilePath.lastIndexOf('/'));
Qt.openUrlExternally(keyPath + "/backup_instructions.html");
Qt.openUrlExternally(keyPath);
}
}
}

View file

@ -15,7 +15,7 @@ import "."
Rectangle {
id: modalWindow
layer.enabled: true
property var title: "Modal"
property var title: "Open"
width: tabletRoot.width
height: tabletRoot.height
color: "#80000000"

View file

@ -1639,12 +1639,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false;
QJsonObject bytesDownloaded;
bytesDownloaded["atp"] = statTracker->getStat(STAT_ATP_RESOURCE_TOTAL_BYTES).toInt();
bytesDownloaded["http"] = statTracker->getStat(STAT_HTTP_RESOURCE_TOTAL_BYTES).toInt();
bytesDownloaded["file"] = statTracker->getStat(STAT_FILE_RESOURCE_TOTAL_BYTES).toInt();
bytesDownloaded["total"] = bytesDownloaded["atp"].toInt() + bytesDownloaded["http"].toInt()
+ bytesDownloaded["file"].toInt();
properties["bytesDownloaded"] = bytesDownloaded;
auto atpBytes = statTracker->getStat(STAT_ATP_RESOURCE_TOTAL_BYTES).toLongLong();
auto httpBytes = statTracker->getStat(STAT_HTTP_RESOURCE_TOTAL_BYTES).toLongLong();
auto fileBytes = statTracker->getStat(STAT_FILE_RESOURCE_TOTAL_BYTES).toLongLong();
bytesDownloaded["atp"] = atpBytes;
bytesDownloaded["http"] = httpBytes;
bytesDownloaded["file"] = fileBytes;
bytesDownloaded["total"] = atpBytes + httpBytes + fileBytes;
properties["bytes_downloaded"] = bytesDownloaded;
auto myAvatar = getMyAvatar();
glm::vec3 avatarPosition = myAvatar->getPosition();
@ -2690,15 +2692,10 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
bool Application::importJSONFromURL(const QString& urlString) {
// we only load files that terminate in just .json (not .svo.json and not .ava.json)
// if they come from the High Fidelity Marketplace Assets CDN
QUrl jsonURL { urlString };
if (jsonURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) {
emit svoImportRequested(urlString);
return true;
} else {
return false;
}
emit svoImportRequested(urlString);
return true;
}
bool Application::importSVOFromURL(const QString& urlString) {
@ -5640,14 +5637,37 @@ bool Application::nearbyEntitiesAreReadyForPhysics() {
return false;
}
// We don't want to use EntityTree::findEntities(AABox, ...) method because that scan will snarf parented entities
// whose bounding boxes cannot be computed (it is too loose for our purposes here). Instead we manufacture
// custom filters and use the general-purpose EntityTree::findEntities(filter, ...)
QVector<EntityItemPointer> entities;
AABox avatarBox(getMyAvatar()->getPosition() - glm::vec3(PHYSICS_READY_RANGE), glm::vec3(2 * PHYSICS_READY_RANGE));
// create two functions that use avatarBox (entityScan and elementScan), the second calls the first
std::function<bool (EntityItemPointer&)> entityScan = [=](EntityItemPointer& entity) {
if (entity->shouldBePhysical()) {
bool success = false;
AABox entityBox = entity->getAABox(success);
// important: bail for entities that cannot supply a valid AABox
return success && avatarBox.touches(entityBox);
}
return false;
};
std::function<bool(const OctreeElementPointer&, void*)> elementScan = [&](const OctreeElementPointer& element, void* unused) {
if (element->getAACube().touches(avatarBox)) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
entityTreeElement->getEntities(entityScan, entities);
return true;
}
return false;
};
entityTree->withReadLock([&] {
AABox box(getMyAvatar()->getPosition() - glm::vec3(PHYSICS_READY_RANGE), glm::vec3(2 * PHYSICS_READY_RANGE));
entityTree->findEntities(box, entities);
// Pass the second function to the general-purpose EntityTree::findEntities()
// which will traverse the tree, apply the two filter functions (to element, then to entities)
// as it traverses. The end result will be a list of entities that match.
entityTree->findEntities(elementScan, entities);
});
// For reasons I haven't found, we don't necessarily have the full scene when we receive a stats packet. Apply
// a heuristic to try to decide when we actually know about all of the nearby entities.
uint32_t nearbyCount = entities.size();
if (nearbyCount == _nearbyEntitiesCountAtLastPhysicsCheck) {
_nearbyEntitiesStabilityCount++;

View file

@ -78,7 +78,7 @@ void ATPAssetMigrator::loadEntityServerFile() {
request->send();
} else {
++_errorCount;
qWarning() << "Count not create request for asset at" << migrationURL.toString();
qWarning() << "Could not create request for asset at" << migrationURL.toString();
}
};

View file

@ -41,6 +41,7 @@
#endif
static const char* KEY_FILE = "hifikey";
static const char* INSTRUCTIONS_FILE = "backup_instructions.html";
static const char* IMAGE_HEADER = "-----BEGIN SECURITY IMAGE-----\n";
static const char* IMAGE_FOOTER = "-----END SECURITY IMAGE-----\n";
@ -104,6 +105,38 @@ RSA* readKeys(const char* filename) {
return key;
}
bool writeBackupInstructions() {
QString inputFilename(PathUtils::resourcesPath() + "html/commerce/backup_instructions.html");
QString filename = PathUtils::getAppDataFilePath(INSTRUCTIONS_FILE);
QFile outputFile(filename);
bool retval = false;
if (QFile::exists(filename))
{
QFile::remove(filename);
}
QFile::copy(inputFilename, filename);
if (QFile::exists(filename) && outputFile.open(QIODevice::ReadWrite)) {
QByteArray fileData = outputFile.readAll();
QString text(fileData);
text.replace(QString("HIFIKEY_PATH_REPLACEME"), keyFilePath());
outputFile.seek(0); // go to the beginning of the file
outputFile.write(text.toUtf8()); // write the new text back to the file
outputFile.close(); // close the file handle.
retval = true;
qCDebug(commerce) << "wrote html file successfully";
} else {
qCDebug(commerce) << "failed to open output html file" << filename;
}
return retval;
}
bool writeKeys(const char* filename, RSA* keys) {
FILE* fp;
bool retval = false;
@ -121,6 +154,8 @@ bool writeKeys(const char* filename, RSA* keys) {
QFile(QString(filename)).remove();
return retval;
}
writeBackupInstructions();
retval = true;
qCDebug(commerce) << "wrote keys successfully";
@ -303,6 +338,11 @@ Wallet::Wallet() {
walletScriptingInterface->setWalletStatus(status);
emit walletStatusResult(status);
});
auto accountManager = DependencyManager::get<AccountManager>();
connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() {
getWalletStatus();
});
}
Wallet::~Wallet() {
@ -488,7 +528,6 @@ bool Wallet::generateKeyPair() {
// TODO: redo this soon -- need error checking and so on
writeSecurityImage(_securityImage, keyFilePath());
emit keyFilePathIfExistsResult(getKeyFilePath());
QString oldKey = _publicKeys.count() == 0 ? "" : _publicKeys.last();
QString key = keyPair.first->toBase64();
_publicKeys.push_back(key);
@ -646,6 +685,7 @@ bool Wallet::writeWallet(const QString& newPassphrase) {
QFile(QString(keyFilePath())).remove();
QFile(tempFileName).rename(QString(keyFilePath()));
qCDebug(commerce) << "wallet written successfully";
emit keyFilePathIfExistsResult(getKeyFilePath());
return true;
} else {
qCDebug(commerce) << "couldn't write security image to temp wallet";

View file

@ -21,6 +21,7 @@
#include <NetworkLogging.h>
#include <NodeList.h>
#include <OffscreenUi.h>
#include <UserActivityLogger.h>
static const int AUTO_REFRESH_INTERVAL = 1000;
@ -104,6 +105,21 @@ void AssetMappingsScriptingInterface::uploadFile(QString path, QString mapping,
startedCallback.call();
QFileInfo fileInfo { path };
int64_t size { fileInfo.size() };
QString extension = "";
auto idx = path.lastIndexOf(".");
if (idx >= 0) {
extension = path.mid(idx + 1);
}
UserActivityLogger::getInstance().logAction("uploading_asset", {
{ "size", (qint64)size },
{ "mapping", mapping },
{ "extension", extension}
});
auto upload = DependencyManager::get<AssetClient>()->createUpload(path);
QObject::connect(upload, &AssetUpload::finished, this, [=](AssetUpload* upload, const QString& hash) mutable {
if (upload->getError() != AssetUpload::NoError) {

View file

@ -1240,6 +1240,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
mapJoints(entity, model->getJointNames());
}
animate(entity);
emit requestRenderUpdate();
}
}

View file

@ -895,6 +895,12 @@ void EntityTree::findEntities(const ViewFrustum& frustum, QVector<EntityItemPoin
foundEntities.swap(args.entities);
}
// NOTE: assumes caller has handled locking
void EntityTree::findEntities(RecurseOctreeOperation& elementFilter,
QVector<EntityItemPointer>& foundEntities) {
recurseTreeWithOperation(elementFilter, nullptr);
}
EntityItemPointer EntityTree::findEntityByID(const QUuid& id) {
EntityItemID entityID(id);
return findEntityByEntityItemID(entityID);

View file

@ -171,6 +171,11 @@ public:
/// \param foundEntities[out] vector of EntityItemPointer
void findEntities(const ViewFrustum& frustum, QVector<EntityItemPointer>& foundEntities);
/// finds all entities that match scanOperator
/// \parameter scanOperator function that scans entities that match criteria
/// \parameter foundEntities[out] vector of EntityItemPointer
void findEntities(RecurseOctreeOperation& scanOperator, QVector<EntityItemPointer>& foundEntities);
void addNewlyCreatedHook(NewlyCreatedEntityHook* hook);
void removeNewlyCreatedHook(NewlyCreatedEntityHook* hook);

View file

@ -869,6 +869,14 @@ void EntityTreeElement::getEntities(const ViewFrustum& frustum, QVector<EntityIt
});
}
void EntityTreeElement::getEntities(EntityItemFilter& filter, QVector<EntityItemPointer>& foundEntities) {
forEachEntity([&](EntityItemPointer entity) {
if (filter(entity)) {
foundEntities.push_back(entity);
}
});
}
EntityItemPointer EntityTreeElement::getEntityWithEntityItemID(const EntityItemID& id) const {
EntityItemPointer foundEntity = NULL;
withReadLock([&] {

View file

@ -27,6 +27,7 @@ class EntityTreeElement;
using EntityItems = QVector<EntityItemPointer>;
using EntityTreeElementWeakPointer = std::weak_ptr<EntityTreeElement>;
using EntityTreeElementPointer = std::shared_ptr<EntityTreeElement>;
using EntityItemFilter = std::function<bool(EntityItemPointer&)>;
class EntityTreeUpdateArgs {
public:
@ -199,6 +200,11 @@ public:
/// \param entities[out] vector of non-const EntityItemPointer
void getEntities(const ViewFrustum& frustum, QVector<EntityItemPointer>& foundEntities);
/// finds all entities that match filter
/// \param filter function that adds matching entities to foundEntities
/// \param entities[out] vector of non-const EntityItemPointer
void getEntities(EntityItemFilter& filter, QVector<EntityItemPointer>& foundEntities);
EntityItemPointer getEntityWithID(uint32_t id) const;
EntityItemPointer getEntityWithEntityItemID(const EntityItemID& id) const;
void getEntitiesInside(const AACube& box, QVector<EntityItemPointer>& foundEntities);

View file

@ -19,6 +19,7 @@ bool GLTexelFormat::isCompressed() const {
case GL_COMPRESSED_RED_RGTC1:
case GL_COMPRESSED_RG_RGTC2:
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
return true;
default:
return false;
@ -94,6 +95,11 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) {
result = GL_R11F_G11F_B10F;
break;
case gpu::RGB9E5:
// the type should be float
result = GL_RGB9_E5;
break;
case gpu::DEPTH:
result = GL_DEPTH_COMPONENT32;
switch (dstFormat.getType()) {
@ -244,6 +250,9 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) {
case gpu::COMPRESSED_BC5_XY:
result = GL_COMPRESSED_RG_RGTC2;
break;
case gpu::COMPRESSED_BC6_RGB:
result = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
break;
case gpu::COMPRESSED_BC7_SRGBA:
result = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
break;
@ -396,6 +405,9 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E
case gpu::COMPRESSED_BC5_XY:
texel.internalFormat = GL_COMPRESSED_RG_RGTC2;
break;
case gpu::COMPRESSED_BC6_RGB:
texel.internalFormat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
break;
case gpu::COMPRESSED_BC7_SRGBA:
texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
break;
@ -495,10 +507,16 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E
case gpu::R11G11B10:
texel.format = GL_RGB;
// the type should be float
texel.type = GL_UNSIGNED_INT_10F_11F_11F_REV;
texel.internalFormat = GL_R11F_G11F_B10F;
break;
case gpu::RGB9E5:
texel.format = GL_RGB;
texel.type = GL_UNSIGNED_INT_5_9_9_9_REV;
texel.internalFormat = GL_RGB9_E5;
break;
case gpu::DEPTH:
texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it
texel.internalFormat = GL_DEPTH_COMPONENT32;
@ -694,6 +712,9 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E
case gpu::COMPRESSED_BC5_XY:
texel.internalFormat = GL_COMPRESSED_RG_RGTC2;
break;
case gpu::COMPRESSED_BC6_RGB:
texel.internalFormat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
break;
case gpu::COMPRESSED_BC7_SRGBA:
texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
break;

View file

@ -114,6 +114,7 @@ Size GL41Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const
case GL_COMPRESSED_RED_RGTC1:
case GL_COMPRESSED_RG_RGTC2:
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
glCompressedTexSubImage2D(_target, mip, 0, yOffset, size.x, size.y, internalFormat,
static_cast<GLsizei>(sourceSize), sourcePointer);
break;
@ -131,6 +132,7 @@ Size GL41Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const
case GL_COMPRESSED_RED_RGTC1:
case GL_COMPRESSED_RG_RGTC2:
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
glCompressedTexSubImage2D(target, mip, 0, yOffset, size.x, size.y, internalFormat,
static_cast<GLsizei>(sourceSize), sourcePointer);
break;

View file

@ -143,6 +143,7 @@ Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const
case GL_COMPRESSED_RED_RGTC1:
case GL_COMPRESSED_RG_RGTC2:
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat,
static_cast<GLsizei>(sourceSize), sourcePointer);
break;
@ -158,6 +159,7 @@ Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const
case GL_COMPRESSED_RED_RGTC1:
case GL_COMPRESSED_RG_RGTC2:
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
if (glCompressedTextureSubImage2DEXT) {
auto target = GLTexture::CUBE_FACE_LAYOUT[face];
glCompressedTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, internalFormat,

View file

@ -24,11 +24,13 @@ const Element Element::COLOR_COMPRESSED_SRGB { TILE4x4, COMPRESSED, COMPRESSED_B
const Element Element::COLOR_COMPRESSED_SRGBA_MASK { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGBA };
const Element Element::COLOR_COMPRESSED_SRGBA { TILE4x4, COMPRESSED, COMPRESSED_BC3_SRGBA };
const Element Element::COLOR_COMPRESSED_XY { TILE4x4, COMPRESSED, COMPRESSED_BC5_XY };
const Element Element::COLOR_COMPRESSED_SRGBA_HIGH { TILE4x4, COMPRESSED, COMPRESSED_BC7_SRGBA };
const Element Element::COLOR_COMPRESSED_SRGBA_HIGH{ TILE4x4, COMPRESSED, COMPRESSED_BC7_SRGBA };
const Element Element::COLOR_COMPRESSED_HDR_RGB{ TILE4x4, COMPRESSED, COMPRESSED_BC6_RGB };
const Element Element::VEC2NU8_XY{ VEC2, NUINT8, XY };
const Element Element::COLOR_R11G11B10{ SCALAR, FLOAT, R11G11B10 };
const Element Element::COLOR_RGB9E5{ SCALAR, FLOAT, RGB9E5 };
const Element Element::VEC4F_COLOR_RGBA{ VEC4, FLOAT, RGBA };
const Element Element::VEC2F_UV{ VEC2, FLOAT, UV };
const Element Element::VEC2F_XY{ VEC2, FLOAT, XY };

View file

@ -187,11 +187,13 @@ enum Semantic : uint8_t {
COMPRESSED_BC3_SRGBA,
COMPRESSED_BC4_RED,
COMPRESSED_BC5_XY,
COMPRESSED_BC6_RGB,
COMPRESSED_BC7_SRGBA,
_LAST_COMPRESSED,
R11G11B10,
RGB9E5,
UNIFORM,
UNIFORM_BUFFER,
@ -240,11 +242,13 @@ static const int SEMANTIC_SIZE_FACTOR[NUM_SEMANTICS] = {
16, //COMPRESSED_BC3_SRGBA, 1 byte/pixel * 4x4 pixels = 16 bytes
8, //COMPRESSED_BC4_RED, 1/2 byte/pixel * 4x4 pixels = 8 bytes
16, //COMPRESSED_BC5_XY, 1 byte/pixel * 4x4 pixels = 16 bytes
16, //COMPRESSED_BC6_RGB, 1 byte/pixel * 4x4 pixels = 16 bytes
16, //COMPRESSED_BC7_SRGBA, 1 byte/pixel * 4x4 pixels = 16 bytes
1, //_LAST_COMPRESSED,
1, //R11G11B10,
1, //RGB9E5
1, //UNIFORM,
1, //UNIFORM_BUFFER,
@ -306,12 +310,14 @@ public:
static const Element COLOR_BGRA_32;
static const Element COLOR_SBGRA_32;
static const Element COLOR_R11G11B10;
static const Element COLOR_RGB9E5;
static const Element COLOR_COMPRESSED_RED;
static const Element COLOR_COMPRESSED_SRGB;
static const Element COLOR_COMPRESSED_SRGBA_MASK;
static const Element COLOR_COMPRESSED_SRGBA;
static const Element COLOR_COMPRESSED_XY;
static const Element COLOR_COMPRESSED_SRGBA_HIGH;
static const Element COLOR_COMPRESSED_HDR_RGB;
static const Element VEC2NU8_XY;
static const Element VEC4F_COLOR_RGBA;
static const Element VEC2F_UV;

View file

@ -14,6 +14,7 @@
#include <glm/gtc/constants.hpp>
#include <glm/gtx/component_wise.hpp>
#include <glm/gtc/packing.hpp>
#include <QtCore/QDebug>
#include <QtCore/QThread>
@ -683,6 +684,21 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
PROFILE_RANGE(render_gpu, "sphericalHarmonicsFromTexture");
auto mipFormat = cubeTexture.getStoredMipFormat();
std::function<glm::vec3(uint32)> unpackFunc;
switch (mipFormat.getSemantic()) {
case gpu::R11G11B10:
unpackFunc = glm::unpackF2x11_1x10;
break;
case gpu::RGB9E5:
unpackFunc = glm::unpackF3x9_E1x5;
break;
default:
assert(false);
break;
}
const uint sqOrder = order*order;
// allocate memory for calculations
@ -716,17 +732,7 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
for(int face=0; face < gpu::Texture::NUM_CUBE_FACES; face++) {
PROFILE_RANGE(render_gpu, "ProcessFace");
auto mipFormat = cubeTexture.getStoredMipFormat();
auto numComponents = mipFormat.getScalarCount();
int roffset { 0 };
int goffset { 1 };
int boffset { 2 };
if ((mipFormat.getSemantic() == gpu::BGRA) || (mipFormat.getSemantic() == gpu::SBGRA)) {
roffset = 2;
boffset = 0;
}
auto data = cubeTexture.accessStoredMipFace(0, face)->readData();
auto data = reinterpret_cast<const uint32*>( cubeTexture.accessStoredMipFace(0, face)->readData() );
if (data == nullptr) {
continue;
}
@ -806,29 +812,24 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
// index of texel in texture
// get color from texture and map to range [0, 1]
float red { 0.0f };
float green { 0.0f };
float blue { 0.0f };
// get color from texture
glm::vec3 color{ 0.0f, 0.0f, 0.0f };
for (int i = 0; i < stride; ++i) {
for (int j = 0; j < stride; ++j) {
int k = (int)(x + i - halfStride + (y + j - halfStride) * width) * numComponents;
red += ColorUtils::sRGB8ToLinearFloat(data[k + roffset]);
green += ColorUtils::sRGB8ToLinearFloat(data[k + goffset]);
blue += ColorUtils::sRGB8ToLinearFloat(data[k + boffset]);
int k = (int)(x + i - halfStride + (y + j - halfStride) * width);
color += unpackFunc(data[k]);
}
}
glm::vec3 clr(red, green, blue);
// scale color and add to previously accumulated coefficients
// red
sphericalHarmonicsScale(shBuffB.data(), order, shBuff.data(), clr.r * fDiffSolid);
sphericalHarmonicsScale(shBuffB.data(), order, shBuff.data(), color.r * fDiffSolid);
sphericalHarmonicsAdd(resultR.data(), order, resultR.data(), shBuffB.data());
// green
sphericalHarmonicsScale(shBuffB.data(), order, shBuff.data(), clr.g * fDiffSolid);
sphericalHarmonicsScale(shBuffB.data(), order, shBuff.data(), color.g * fDiffSolid);
sphericalHarmonicsAdd(resultG.data(), order, resultG.data(), shBuffB.data());
// blue
sphericalHarmonicsScale(shBuffB.data(), order, shBuff.data(), clr.b * fDiffSolid);
sphericalHarmonicsScale(shBuffB.data(), order, shBuff.data(), color.b * fDiffSolid);
sphericalHarmonicsAdd(resultB.data(), order, resultB.data(), shBuffB.data());
}
}

View file

@ -515,8 +515,6 @@ TexturePointer Texture::build(const ktx::KTXDescriptor& descriptor) {
return texture;
}
TexturePointer Texture::unserialize(const cache::FilePointer& cacheEntry) {
std::unique_ptr<ktx::KTX> ktxPointer = ktx::KTX::create(std::make_shared<storage::FileStorage>(cacheEntry->getFilepath().c_str()));
if (!ktxPointer) {
@ -536,7 +534,7 @@ TexturePointer Texture::unserialize(const std::string& ktxfile) {
if (!ktxPointer) {
return nullptr;
}
auto texture = build(ktxPointer->toDescriptor());
if (texture) {
texture->setKtxBacking(ktxfile);
@ -570,6 +568,12 @@ bool Texture::evalKTXFormat(const Element& mipFormat, const Element& texelFormat
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RG_RGTC2, ktx::GLBaseInternalFormat::RG);
} else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA_HIGH && mipFormat == Format::COLOR_COMPRESSED_SRGBA_HIGH) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_HDR_RGB && mipFormat == Format::COLOR_COMPRESSED_HDR_RGB) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, ktx::GLBaseInternalFormat::RGB);
} else if (texelFormat == Format::COLOR_RGB9E5 && mipFormat == Format::COLOR_RGB9E5) {
header.setUncompressed(ktx::GLType::UNSIGNED_INT_5_9_9_9_REV, 1, ktx::GLFormat::RGB, ktx::GLInternalFormat::RGB9_E5, ktx::GLBaseInternalFormat::RGB);
} else if (texelFormat == Format::COLOR_R11G11B10 && mipFormat == Format::COLOR_R11G11B10) {
header.setUncompressed(ktx::GLType::UNSIGNED_INT_10F_11F_11F_REV, 1, ktx::GLFormat::RGB, ktx::GLInternalFormat::R11F_G11F_B10F, ktx::GLBaseInternalFormat::RGB);
} else {
return false;
}
@ -612,6 +616,12 @@ bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, E
} else {
return false;
}
} else if (header.getGLFormat() == ktx::GLFormat::RGB && header.getGLType() == ktx::GLType::UNSIGNED_INT_10F_11F_11F_REV) {
mipFormat = Format::COLOR_R11G11B10;
texelFormat = Format::COLOR_R11G11B10;
} else if (header.getGLFormat() == ktx::GLFormat::RGB && header.getGLType() == ktx::GLType::UNSIGNED_INT_5_9_9_9_REV) {
mipFormat = Format::COLOR_RGB9E5;
texelFormat = Format::COLOR_RGB9E5;
} else if (header.isCompressed()) {
if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT) {
mipFormat = Format::COLOR_COMPRESSED_SRGB;
@ -631,6 +641,9 @@ bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, E
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM) {
mipFormat = Format::COLOR_COMPRESSED_SRGBA_HIGH;
texelFormat = Format::COLOR_COMPRESSED_SRGBA_HIGH;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT) {
mipFormat = Format::COLOR_COMPRESSED_HDR_RGB;
texelFormat = Format::COLOR_COMPRESSED_HDR_RGB;
} else {
return false;
}

View file

@ -11,9 +11,10 @@
#include "Image.h"
#include <nvtt/nvtt.h>
#include <glm/gtc/packing.hpp>
#include <QtCore/QtGlobal>
#include <QUrl>
#include <QImage>
#include <QBuffer>
@ -42,6 +43,8 @@ bool DEV_DECIMATE_TEXTURES = false;
std::atomic<size_t> DECIMATED_TEXTURE_COUNT{ 0 };
std::atomic<size_t> RECTIFIED_TEXTURE_COUNT{ 0 };
static const auto HDR_FORMAT = gpu::Element::COLOR_R11G11B10;
static std::atomic<bool> compressColorTextures { false };
static std::atomic<bool> compressNormalTextures { false };
static std::atomic<bool> compressGrayscaleTextures { false };
@ -71,6 +74,10 @@ glm::uvec2 rectifyToSparseSize(const glm::uvec2& size) {
namespace image {
enum {
QIMAGE_HDR_FORMAT = QImage::Format_RGB30
};
TextureUsage::TextureLoader TextureUsage::getTextureLoaderForType(Type type, const QVariantMap& options) {
switch (type) {
case ALBEDO_TEXTURE:
@ -213,6 +220,25 @@ void setCubeTexturesCompressionEnabled(bool enabled) {
compressCubeTextures.store(enabled);
}
static float denormalize(float value, const float minValue) {
return value < minValue ? 0.0f : value;
}
uint32 packR11G11B10F(const glm::vec3& color) {
// Denormalize else unpacking gives high and incorrect values
// See https://www.khronos.org/opengl/wiki/Small_Float_Formats for this min value
static const auto minValue = 6.10e-5f;
static const auto maxValue = 6.50e4f;
glm::vec3 ucolor;
ucolor.r = denormalize(color.r, minValue);
ucolor.g = denormalize(color.g, minValue);
ucolor.b = denormalize(color.b, minValue);
ucolor.r = std::min(ucolor.r, maxValue);
ucolor.g = std::min(ucolor.g, maxValue);
ucolor.b = std::min(ucolor.b, maxValue);
return glm::packF2x11_1x10(ucolor);
}
gpu::TexturePointer processImage(const QByteArray& content, const std::string& filename,
int maxNumPixels, TextureUsage::Type textureType,
const std::atomic<bool>& abortProcessing) {
@ -270,8 +296,6 @@ gpu::TexturePointer processImage(const QByteArray& content, const std::string& f
return texture;
}
QImage processSourceImage(const QImage& srcImage, bool cubemap) {
PROFILE_RANGE(resource_parse, "processSourceImage");
const glm::uvec2 srcImageSize = toGlm(srcImage.size());
@ -303,8 +327,8 @@ QImage processSourceImage(const QImage& srcImage, bool cubemap) {
}
#if defined(NVTT_API)
struct MyOutputHandler : public nvtt::OutputHandler {
MyOutputHandler(gpu::Texture* texture, int face) : _texture(texture), _face(face) {}
struct OutputHandler : public nvtt::OutputHandler {
OutputHandler(gpu::Texture* texture, int face) : _texture(texture), _face(face) {}
virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel) override {
_size = size;
@ -313,12 +337,14 @@ struct MyOutputHandler : public nvtt::OutputHandler {
_data = static_cast<gpu::Byte*>(malloc(size));
_current = _data;
}
virtual bool writeData(const void* data, int size) override {
assert(_current + size <= _data + _size);
memcpy(_current, data, size);
_current += size;
return true;
}
virtual void endImage() override {
if (_face >= 0) {
_texture->assignStoredMipFace(_miplevel, _face, _size, static_cast<const gpu::Byte*>(_data));
@ -336,6 +362,51 @@ struct MyOutputHandler : public nvtt::OutputHandler {
int _size = 0;
int _face = -1;
};
struct PackedFloatOutputHandler : public OutputHandler {
PackedFloatOutputHandler(gpu::Texture* texture, int face, gpu::Element format) : OutputHandler(texture, face) {
if (format == gpu::Element::COLOR_RGB9E5) {
_packFunc = glm::packF3x9_E1x5;
} else if (format == gpu::Element::COLOR_R11G11B10) {
_packFunc = packR11G11B10F;
} else {
qCWarning(imagelogging) << "Unknown handler format";
Q_UNREACHABLE();
}
}
virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel) override {
// Divide by 3 because we will compress from 3*floats to 1 uint32
OutputHandler::beginImage(size / 3, width, height, depth, face, miplevel);
}
virtual bool writeData(const void* data, int size) override {
// Expecting to write multiple of floats
if (_packFunc) {
assert((size % sizeof(float)) == 0);
auto floatCount = size / sizeof(float);
const float* floatBegin = (const float*)data;
const float* floatEnd = floatBegin + floatCount;
while (floatBegin < floatEnd) {
_pixel[_coordIndex] = *floatBegin;
floatBegin++;
_coordIndex++;
if (_coordIndex == 3) {
uint32 packedRGB = _packFunc(_pixel);
_coordIndex = 0;
OutputHandler::writeData(&packedRGB, sizeof(packedRGB));
}
}
return true;
}
return false;
}
std::function<uint32(const glm::vec3&)> _packFunc;
glm::vec3 _pixel;
int _coordIndex{ 0 };
};
struct MyErrorHandler : public nvtt::ErrorHandler {
virtual void error(nvtt::Error e) override {
qCWarning(imagelogging) << "Texture compression error:" << nvtt::errorString(e);
@ -343,10 +414,115 @@ struct MyErrorHandler : public nvtt::ErrorHandler {
};
#endif
void generateMips(gpu::Texture* texture, QImage& image, const std::atomic<bool>& abortProcessing = false, int face = -1) {
#if CPU_MIPMAPS
PROFILE_RANGE(resource_parse, "generateMips");
class SequentialTaskDispatcher : public nvtt::TaskDispatcher {
public:
SequentialTaskDispatcher(const std::atomic<bool>& abortProcessing) : _abortProcessing(abortProcessing) {};
const std::atomic<bool>& _abortProcessing;
virtual void dispatch(nvtt::Task* task, void* context, int count) override {
for (int i = 0; i < count; i++) {
if (!_abortProcessing.load()) {
task(context, i);
} else {
break;
}
}
}
};
void generateHDRMips(gpu::Texture* texture, const QImage& image, const std::atomic<bool>& abortProcessing, int face) {
assert(image.format() == QIMAGE_HDR_FORMAT);
const int width = image.width(), height = image.height();
std::vector<glm::vec4> data;
std::vector<glm::vec4>::iterator dataIt;
auto mipFormat = texture->getStoredMipFormat();
std::function<glm::vec3(uint32)> unpackFunc;
nvtt::TextureType textureType = nvtt::TextureType_2D;
nvtt::InputFormat inputFormat = nvtt::InputFormat_RGBA_32F;
nvtt::WrapMode wrapMode = nvtt::WrapMode_Mirror;
nvtt::RoundMode roundMode = nvtt::RoundMode_None;
nvtt::AlphaMode alphaMode = nvtt::AlphaMode_None;
nvtt::CompressionOptions compressionOptions;
compressionOptions.setQuality(nvtt::Quality_Production);
if (mipFormat == gpu::Element::COLOR_COMPRESSED_HDR_RGB) {
compressionOptions.setFormat(nvtt::Format_BC6);
} else if (mipFormat == gpu::Element::COLOR_RGB9E5) {
compressionOptions.setFormat(nvtt::Format_RGB);
compressionOptions.setPixelType(nvtt::PixelType_Float);
compressionOptions.setPixelFormat(32, 32, 32, 0);
} else if (mipFormat == gpu::Element::COLOR_R11G11B10) {
compressionOptions.setFormat(nvtt::Format_RGB);
compressionOptions.setPixelType(nvtt::PixelType_Float);
compressionOptions.setPixelFormat(32, 32, 32, 0);
} else {
qCWarning(imagelogging) << "Unknown mip format";
Q_UNREACHABLE();
return;
}
if (HDR_FORMAT == gpu::Element::COLOR_RGB9E5) {
unpackFunc = glm::unpackF3x9_E1x5;
} else if (HDR_FORMAT == gpu::Element::COLOR_R11G11B10) {
unpackFunc = glm::unpackF2x11_1x10;
} else {
qCWarning(imagelogging) << "Unknown HDR encoding format in QImage";
Q_UNREACHABLE();
return;
}
data.resize(width*height);
dataIt = data.begin();
for (auto lineNb = 0; lineNb < height; lineNb++) {
const uint32* srcPixelIt = reinterpret_cast<const uint32*>( image.constScanLine(lineNb) );
const uint32* srcPixelEnd = srcPixelIt + width;
while (srcPixelIt < srcPixelEnd) {
*dataIt = glm::vec4(unpackFunc(*srcPixelIt), 1.0f);
++srcPixelIt;
++dataIt;
}
}
assert(dataIt == data.end());
nvtt::OutputOptions outputOptions;
outputOptions.setOutputHeader(false);
std::unique_ptr<nvtt::OutputHandler> outputHandler;
MyErrorHandler errorHandler;
outputOptions.setErrorHandler(&errorHandler);
nvtt::Context context;
int mipLevel = 0;
if (mipFormat == gpu::Element::COLOR_RGB9E5 || mipFormat == gpu::Element::COLOR_R11G11B10) {
// Don't use NVTT (at least version 2.1) as it outputs wrong RGB9E5 and R11G11B10F values from floats
outputHandler.reset(new PackedFloatOutputHandler(texture, face, mipFormat));
} else {
outputHandler.reset( new OutputHandler(texture, face) );
}
outputOptions.setOutputHandler(outputHandler.get());
nvtt::Surface surface;
surface.setImage(inputFormat, width, height, 1, &(*data.begin()));
surface.setAlphaMode(alphaMode);
surface.setWrapMode(wrapMode);
SequentialTaskDispatcher dispatcher(abortProcessing);
nvtt::Compressor compressor;
context.setTaskDispatcher(&dispatcher);
context.compress(surface, face, mipLevel++, compressionOptions, outputOptions);
while (surface.canMakeNextMipmap() && !abortProcessing.load()) {
surface.buildNextMipmap(nvtt::MipmapFilter_Box);
context.compress(surface, face, mipLevel++, compressionOptions, outputOptions);
}
}
void generateLDRMips(gpu::Texture* texture, QImage& image, const std::atomic<bool>& abortProcessing, int face) {
if (image.format() != QImage::Format_ARGB32) {
image = image.convertToFormat(QImage::Format_ARGB32);
}
@ -400,10 +576,10 @@ void generateMips(gpu::Texture* texture, QImage& image, const std::atomic<bool>&
compressionOptions.setPixelType(nvtt::PixelType_UnsignedNorm);
compressionOptions.setPitchAlignment(4);
compressionOptions.setPixelFormat(32,
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000);
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000);
inputGamma = 1.0f;
outputGamma = 1.0f;
} else if (mipFormat == gpu::Element::COLOR_BGRA_32) {
@ -411,10 +587,10 @@ void generateMips(gpu::Texture* texture, QImage& image, const std::atomic<bool>&
compressionOptions.setPixelType(nvtt::PixelType_UnsignedNorm);
compressionOptions.setPitchAlignment(4);
compressionOptions.setPixelFormat(32,
0x00FF0000,
0x0000FF00,
0x000000FF,
0xFF000000);
0x00FF0000,
0x0000FF00,
0x000000FF,
0xFF000000);
inputGamma = 1.0f;
outputGamma = 1.0f;
} else if (mipFormat == gpu::Element::COLOR_SRGBA_32) {
@ -422,19 +598,19 @@ void generateMips(gpu::Texture* texture, QImage& image, const std::atomic<bool>&
compressionOptions.setPixelType(nvtt::PixelType_UnsignedNorm);
compressionOptions.setPitchAlignment(4);
compressionOptions.setPixelFormat(32,
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000);
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000);
} else if (mipFormat == gpu::Element::COLOR_SBGRA_32) {
compressionOptions.setFormat(nvtt::Format_RGBA);
compressionOptions.setPixelType(nvtt::PixelType_UnsignedNorm);
compressionOptions.setPitchAlignment(4);
compressionOptions.setPixelFormat(32,
0x00FF0000,
0x0000FF00,
0x000000FF,
0xFF000000);
0x00FF0000,
0x0000FF00,
0x000000FF,
0xFF000000);
} else if (mipFormat == gpu::Element::COLOR_R_8) {
compressionOptions.setFormat(nvtt::Format_RGB);
compressionOptions.setPixelType(nvtt::PixelType_UnsignedNorm);
@ -454,32 +630,26 @@ void generateMips(gpu::Texture* texture, QImage& image, const std::atomic<bool>&
nvtt::OutputOptions outputOptions;
outputOptions.setOutputHeader(false);
MyOutputHandler outputHandler(texture, face);
OutputHandler outputHandler(texture, face);
outputOptions.setOutputHandler(&outputHandler);
MyErrorHandler errorHandler;
outputOptions.setErrorHandler(&errorHandler);
class SequentialTaskDispatcher : public nvtt::TaskDispatcher {
public:
SequentialTaskDispatcher(const std::atomic<bool>& abortProcessing) : _abortProcessing(abortProcessing) {};
const std::atomic<bool>& _abortProcessing;
virtual void dispatch(nvtt::Task* task, void* context, int count) override {
for (int i = 0; i < count; i++) {
if (!_abortProcessing.load()) {
task(context, i);
} else {
break;
}
}
}
};
SequentialTaskDispatcher dispatcher(abortProcessing);
nvtt::Compressor compressor;
compressor.setTaskDispatcher(&dispatcher);
compressor.process(inputOptions, compressionOptions, outputOptions);
}
void generateMips(gpu::Texture* texture, QImage& image, const std::atomic<bool>& abortProcessing = false, int face = -1) {
#if CPU_MIPMAPS
PROFILE_RANGE(resource_parse, "generateMips");
if (image.format() == QIMAGE_HDR_FORMAT) {
generateHDRMips(texture, image, abortProcessing, face);
} else {
generateLDRMips(texture, image, abortProcessing, face);
}
#else
texture->setAutoGenerateMips(true);
#endif
@ -961,6 +1131,62 @@ const CubeLayout CubeLayout::CUBEMAP_LAYOUTS[] = {
};
const int CubeLayout::NUM_CUBEMAP_LAYOUTS = sizeof(CubeLayout::CUBEMAP_LAYOUTS) / sizeof(CubeLayout);
//#define DEBUG_COLOR_PACKING
QImage convertToHDRFormat(QImage srcImage, gpu::Element format) {
QImage hdrImage(srcImage.width(), srcImage.height(), (QImage::Format)QIMAGE_HDR_FORMAT);
std::function<uint32(const glm::vec3&)> packFunc;
#ifdef DEBUG_COLOR_PACKING
std::function<glm::vec3(uint32)> unpackFunc;
#endif
switch (format.getSemantic()) {
case gpu::R11G11B10:
packFunc = packR11G11B10F;
#ifdef DEBUG_COLOR_PACKING
unpackFunc = glm::unpackF2x11_1x10;
#endif
break;
case gpu::RGB9E5:
packFunc = glm::packF3x9_E1x5;
#ifdef DEBUG_COLOR_PACKING
unpackFunc = glm::unpackF3x9_E1x5;
#endif
break;
default:
qCWarning(imagelogging) << "Unsupported HDR format";
Q_UNREACHABLE();
return srcImage;
}
srcImage = srcImage.convertToFormat(QImage::Format_ARGB32);
for (auto y = 0; y < srcImage.height(); y++) {
const QRgb* srcLineIt = reinterpret_cast<const QRgb*>( srcImage.constScanLine(y) );
const QRgb* srcLineEnd = srcLineIt + srcImage.width();
uint32* hdrLineIt = reinterpret_cast<uint32*>( hdrImage.scanLine(y) );
glm::vec3 color;
while (srcLineIt < srcLineEnd) {
color.r = qRed(*srcLineIt);
color.g = qGreen(*srcLineIt);
color.b = qBlue(*srcLineIt);
// Normalize and apply gamma
color /= 255.0f;
color.r = powf(color.r, 2.2f);
color.g = powf(color.g, 2.2f);
color.b = powf(color.b, 2.2f);
*hdrLineIt = packFunc(color);
#ifdef DEBUG_COLOR_PACKING
glm::vec3 ucolor = unpackFunc(*hdrLineIt);
assert(glm::distance(color, ucolor) <= 5e-2);
#endif
++srcLineIt;
++hdrLineIt;
}
}
return hdrImage;
}
gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName,
bool generateIrradiance,
const std::atomic<bool>& abortProcessing) {
@ -969,18 +1195,19 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage&
gpu::TexturePointer theTexture = nullptr;
if ((srcImage.width() > 0) && (srcImage.height() > 0)) {
QImage image = processSourceImage(srcImage, true);
if (image.format() != QImage::Format_ARGB32) {
image = image.convertToFormat(QImage::Format_ARGB32);
}
gpu::Element formatMip;
gpu::Element formatGPU;
if (isCubeTexturesCompressionEnabled()) {
formatMip = gpu::Element::COLOR_COMPRESSED_SRGBA_HIGH;
formatGPU = gpu::Element::COLOR_COMPRESSED_SRGBA_HIGH;
formatMip = gpu::Element::COLOR_COMPRESSED_HDR_RGB;
formatGPU = gpu::Element::COLOR_COMPRESSED_HDR_RGB;
} else {
formatMip = gpu::Element::COLOR_SRGBA_32;
formatGPU = gpu::Element::COLOR_SRGBA_32;
formatMip = HDR_FORMAT;
formatGPU = HDR_FORMAT;
}
if (image.format() != QIMAGE_HDR_FORMAT) {
image = convertToHDRFormat(image, HDR_FORMAT);
}
// Find the layout of the cubemap in the 2D image
@ -1028,9 +1255,9 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(const QImage&
// Generate irradiance while we are at it
if (generateIrradiance) {
PROFILE_RANGE(resource_parse, "generateIrradiance");
auto irradianceTexture = gpu::Texture::createCube(gpu::Element::COLOR_SRGBA_32, faces[0].width(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP));
auto irradianceTexture = gpu::Texture::createCube(HDR_FORMAT, faces[0].width(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP));
irradianceTexture->setSource(srcImageName);
irradianceTexture->setStoredMipFormat(gpu::Element::COLOR_SBGRA_32);
irradianceTexture->setStoredMipFormat(HDR_FORMAT);
for (uint8 face = 0; face < faces.size(); ++face) {
irradianceTexture->assignStoredMipFace(0, face, faces[face].byteCount(), faces[face].constBits());
}

View file

@ -209,6 +209,137 @@ namespace khronos {
COMPRESSED_SIGNED_RG11_EAC = 0x9273,
};
inline uint8_t evalUncompressedBlockBitSize(InternalFormat format) {
switch (format) {
case InternalFormat::R8:
case InternalFormat::R8_SNORM:
return 8;
case InternalFormat::R16:
case InternalFormat::R16_SNORM:
case InternalFormat::RG8:
case InternalFormat::RG8_SNORM:
return 16;
case InternalFormat::RG16:
case InternalFormat::RG16_SNORM:
return 16;
case InternalFormat::R3_G3_B2:
return 8;
case InternalFormat::RGB4:
return 12;
case InternalFormat::RGB5:
case InternalFormat::RGB565:
return 16;
case InternalFormat::RGB8:
case InternalFormat::RGB8_SNORM:
return 24;
case InternalFormat::RGB10:
// TODO: check if this is really the case
return 32;
case InternalFormat::RGB12:
// TODO: check if this is really the case
return 48;
case InternalFormat::RGB16:
case InternalFormat::RGB16_SNORM:
return 48;
case InternalFormat::RGBA2:
return 8;
case InternalFormat::RGBA4:
case InternalFormat::RGB5_A1:
return 16;
case InternalFormat::RGBA8:
case InternalFormat::RGBA8_SNORM:
case InternalFormat::RGB10_A2:
case InternalFormat::RGB10_A2UI:
return 32;
case InternalFormat::RGBA12:
return 48;
case InternalFormat::RGBA16:
case InternalFormat::RGBA16_SNORM:
return 64;
case InternalFormat::SRGB8:
return 24;
case InternalFormat::SRGB8_ALPHA8:
return 32;
case InternalFormat::R16F:
return 16;
case InternalFormat::RG16F:
return 32;
case InternalFormat::RGB16F:
return 48;
case InternalFormat::RGBA16F:
return 64;
case InternalFormat::R32F:
return 32;
case InternalFormat::RG32F:
return 64;
case InternalFormat::RGB32F:
return 96;
case InternalFormat::RGBA32F:
return 128;
case InternalFormat::R11F_G11F_B10F:
case InternalFormat::RGB9_E5:
return 32;
case InternalFormat::R8I:
case InternalFormat::R8UI:
return 8;
case InternalFormat::R16I:
case InternalFormat::R16UI:
return 16;
case InternalFormat::R32I:
case InternalFormat::R32UI:
return 32;
case InternalFormat::RG8I:
case InternalFormat::RG8UI:
return 16;
case InternalFormat::RG16I:
case InternalFormat::RG16UI:
return 32;
case InternalFormat::RG32I:
case InternalFormat::RG32UI:
return 64;
case InternalFormat::RGB8I:
case InternalFormat::RGB8UI:
return 24;
case InternalFormat::RGB16I:
case InternalFormat::RGB16UI:
return 48;
case InternalFormat::RGB32I:
case InternalFormat::RGB32UI:
return 96;
case InternalFormat::RGBA8I:
case InternalFormat::RGBA8UI:
return 32;
case InternalFormat::RGBA16I:
case InternalFormat::RGBA16UI:
return 64;
case InternalFormat::RGBA32I:
case InternalFormat::RGBA32UI:
return 128;
case InternalFormat::DEPTH_COMPONENT16:
return 16;
case InternalFormat::DEPTH_COMPONENT24:
return 24;
case InternalFormat::DEPTH_COMPONENT32:
case InternalFormat::DEPTH_COMPONENT32F:
case InternalFormat::DEPTH24_STENCIL8:
return 32;
case InternalFormat::DEPTH32F_STENCIL8:
// TODO : check if this true
return 40;
case InternalFormat::STENCIL_INDEX1:
return 1;
case InternalFormat::STENCIL_INDEX4:
return 4;
case InternalFormat::STENCIL_INDEX8:
return 8;
case InternalFormat::STENCIL_INDEX16:
return 16;
default:
return 0;
}
}
template <uint32_t ALIGNMENT>
inline uint32_t evalAlignedCompressedBlockCount(uint32_t value) {
enum { val = ALIGNMENT && !(ALIGNMENT & (ALIGNMENT - 1)) };
@ -225,6 +356,7 @@ namespace khronos {
case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: // BC3
case InternalFormat::COMPRESSED_RED_RGTC1: // BC4
case InternalFormat::COMPRESSED_RG_RGTC2: // BC5
case InternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: // BC6
case InternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM: // BC7
return evalAlignedCompressedBlockCount<4>(value);
@ -241,6 +373,7 @@ namespace khronos {
return 8;
case InternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
case InternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
case InternalFormat::COMPRESSED_RG_RGTC2:
return 16;
@ -250,6 +383,10 @@ namespace khronos {
}
}
inline uint8_t evalCompressedBlockBitSize(InternalFormat format) {
return evalCompressedBlockSize(format) * 8;
}
enum class BaseInternalFormat : uint32_t {
// GL 4.4 Table 8.11
DEPTH_COMPONENT = 0x1902,

View file

@ -54,15 +54,13 @@ uint32_t Header::evalPixelOrBlockDepth(uint32_t level) const {
return evalMipDimension(level, getPixelDepth());
}
size_t Header::evalPixelOrBlockSize() const {
size_t Header::evalPixelOrBlockBitSize() const {
size_t result = 0;
auto format = getGLInternaFormat();
if (isCompressed()) {
auto format = getGLInternaFormat();
result = khronos::gl::texture::evalCompressedBlockSize(format);
result = khronos::gl::texture::evalCompressedBlockBitSize(format);
} else {
// FIXME should really be using the internal format, not the base internal format
auto baseFormat = getGLBaseInternalFormat();
result = khronos::gl::texture::evalComponentCount(baseFormat);
result = khronos::gl::texture::evalUncompressedBlockBitSize(format);
}
if (0 == result) {
@ -73,11 +71,14 @@ size_t Header::evalPixelOrBlockSize() const {
size_t Header::evalRowSize(uint32_t level) const {
auto pixWidth = evalPixelOrBlockWidth(level);
auto pixSize = evalPixelOrBlockSize();
auto pixSize = evalPixelOrBlockBitSize();
if (pixSize == 0) {
return 0;
}
return evalPaddedSize(pixWidth * pixSize);
auto totalByteSize = pixWidth * pixSize;
// Round to the nearest upper byte size
totalByteSize = (totalByteSize / 8) + (((totalByteSize % 8) != 0) & 1);
return evalPaddedSize(totalByteSize);
}
size_t Header::evalFaceSize(uint32_t level) const {

View file

@ -170,7 +170,7 @@ namespace ktx {
uint32_t evalPixelOrBlockHeight(uint32_t level) const;
uint32_t evalPixelOrBlockDepth(uint32_t level) const;
size_t evalPixelOrBlockSize() const;
size_t evalPixelOrBlockBitSize() const;
size_t evalRowSize(uint32_t level) const;
size_t evalFaceSize(uint32_t level) const;
size_t evalImageSize(uint32_t level) const;

View file

@ -155,6 +155,7 @@ void AssetResourceRequest::requestHash(const AssetHash& hash) {
case AssetRequest::Error::NoError:
_data = req->getData();
_result = Success;
recordBytesDownloadedInStats(STAT_ATP_RESOURCE_TOTAL_BYTES, _data.size());
break;
case AssetRequest::InvalidHash:
_result = InvalidURL;
@ -202,9 +203,8 @@ void AssetResourceRequest::onDownloadProgress(qint64 bytesReceived, qint64 bytes
emit progress(bytesReceived, bytesTotal);
auto now = p_high_resolution_clock::now();
// Recording ATP bytes downloaded in stats
DependencyManager::get<StatTracker>()->updateStat(STAT_ATP_RESOURCE_TOTAL_BYTES, bytesReceived);
recordBytesDownloadedInStats(STAT_ATP_RESOURCE_TOTAL_BYTES, bytesReceived);
// if we haven't received the full asset check if it is time to output progress to log
// we do so every X seconds to assist with ATP download tracking

View file

@ -41,6 +41,8 @@ private:
AssetRequest* _assetRequest { nullptr };
p_high_resolution_clock::time_point _lastProgressDebug;
int64_t _lastRecordedBytesDownloaded { 0 };
};
#endif

View file

@ -69,8 +69,7 @@ void FileResourceRequest::doSend() {
if (_result == ResourceRequest::Success) {
statTracker->incrementStat(STAT_FILE_REQUEST_SUCCESS);
// Recording FILE bytes downloaded in stats
statTracker->updateStat(STAT_FILE_RESOURCE_TOTAL_BYTES,fileSize);
statTracker->updateStat(STAT_FILE_RESOURCE_TOTAL_BYTES, fileSize);
} else {
statTracker->incrementStat(STAT_FILE_REQUEST_FAILED);
}

View file

@ -141,6 +141,8 @@ void HTTPResourceRequest::onRequestFinished() {
}
}
recordBytesDownloadedInStats(STAT_HTTP_RESOURCE_TOTAL_BYTES, _data.size());
break;
case QNetworkReply::TimeoutError:
@ -201,11 +203,8 @@ void HTTPResourceRequest::onDownloadProgress(qint64 bytesReceived, qint64 bytesT
_sendTimer->start();
emit progress(bytesReceived, bytesTotal);
// Recording HTTP bytes downloaded in stats
DependencyManager::get<StatTracker>()->updateStat(STAT_HTTP_RESOURCE_TOTAL_BYTES, bytesReceived);
recordBytesDownloadedInStats(STAT_HTTP_RESOURCE_TOTAL_BYTES, bytesReceived);
}
void HTTPResourceRequest::onTimeout() {

View file

@ -11,6 +11,9 @@
#include "ResourceRequest.h"
#include <DependencyManager.h>
#include <StatTracker.h>
#include <QtCore/QThread>
ResourceRequest::ResourceRequest(const QUrl& url) : _url(url) { }
@ -40,3 +43,11 @@ QString ResourceRequest::getResultString() const {
default: return "Unspecified Error";
}
}
void ResourceRequest::recordBytesDownloadedInStats(const QString& statName, int64_t bytesReceived) {
auto dBytes = bytesReceived - _lastRecordedBytesDownloaded;
if (dBytes > 0) {
_lastRecordedBytesDownloaded = bytesReceived;
DependencyManager::get<StatTracker>()->updateStat(statName, dBytes);
}
}

View file

@ -85,6 +85,7 @@ signals:
protected:
virtual void doSend() = 0;
void recordBytesDownloadedInStats(const QString& statName, int64_t bytesReceived);
QUrl _url;
QUrl _relativePathURL;
@ -97,6 +98,7 @@ protected:
ByteRange _byteRange;
bool _rangeRequestSuccessful { false };
uint64_t _totalSizeOfResource { 0 };
int64_t _lastRecordedBytesDownloaded { 0 };
};
#endif

View file

@ -14,15 +14,15 @@ StatTracker::StatTracker() {
QVariant StatTracker::getStat(const QString& name) {
std::lock_guard<std::mutex> lock(_statsLock);
return _stats[name];
return QVariant::fromValue<int64_t>(_stats[name]);
}
void StatTracker::setStat(const QString& name, int value) {
void StatTracker::setStat(const QString& name, int64_t value) {
Lock lock(_statsLock);
_stats[name] = value;
}
void StatTracker::updateStat(const QString& name, int value) {
void StatTracker::updateStat(const QString& name, int64_t value) {
Lock lock(_statsLock);
auto itr = _stats.find(name);
if (_stats.end() == itr) {

View file

@ -24,15 +24,15 @@ class StatTracker : public Dependency {
public:
StatTracker();
QVariant getStat(const QString& name);
void setStat(const QString& name, int value);
void updateStat(const QString& name, int mod);
void setStat(const QString& name, int64_t value);
void updateStat(const QString& name, int64_t mod);
void incrementStat(const QString& name);
void decrementStat(const QString& name);
private:
using Mutex = std::mutex;
using Lock = std::lock_guard<Mutex>;
Mutex _statsLock;
QHash<QString, int> _stats;
QHash<QString, int64_t> _stats;
};
class CounterStat {

View file

@ -119,6 +119,7 @@ Script.include("/~/system/libraries/controllers.js");
this.reticleMaxX;
this.reticleMinY = MARGIN;
this.reticleMaxY;
this.madeDynamic = false;
var ACTION_TTL = 15; // seconds
@ -344,6 +345,13 @@ Script.include("/~/system/libraries/controllers.js");
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
Entities.callEntityMethod(this.grabbedThingID, "releaseGrab", args);
if (this.madeDynamic) {
var props = {};
props.dynamic = false;
props.localVelocity = {x: 0, y: 0, z: 0};
Entities.editEntity(this.grabbedThingID, props);
this.madeDynamic = false;
}
this.actionID = null;
this.grabbedThingID = null;
};
@ -503,7 +511,13 @@ Script.include("/~/system/libraries/controllers.js");
this.destroyContextOverlay();
}
if (entityIsDistanceGrabbable(targetProps)) {
if (entityIsGrabbable(targetProps)) {
if (!entityIsDistanceGrabbable(targetProps)) {
targetProps.dynamic = true;
Entities.editEntity(entityID, targetProps);
this.madeDynamic = true;
}
if (!this.distanceRotating) {
this.grabbedThingID = entityID;
this.grabbedDistance = rayPickInfo.distance;

View file

@ -15,12 +15,13 @@
//
/* global MyAvatar, Entities, Script, Camera, Vec3, Reticle, Overlays, getEntityCustomData, Messages, Quat, Controller,
isInEditMode, HMD */
isInEditMode, HMD entityIsGrabbable*/
(function() { // BEGIN LOCAL_SCOPE
Script.include("/~/system/libraries/utils.js");
Script.include("/~/system/libraries/utils.js");
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
var MAX_SOLID_ANGLE = 0.01; // objects that appear smaller than this can't be grabbed
var DELAY_FOR_30HZ = 33; // milliseconds
@ -330,9 +331,11 @@ Grabber.prototype.pressEvent = function(event) {
return;
}
var isDynamic = Entities.getEntityProperties(pickResults.objectID, "dynamic").dynamic;
if (!isDynamic) {
// only grab dynamic objects
var props = Entities.getEntityProperties(pickResults.objectID, ["dynamic", "userData", "locked", "type"]);
var isDynamic = props.dynamic;
var isGrabbable = props.grabbable;
if (!entityIsGrabbable(props)) {
// only grab grabbable objects
return;
}
@ -350,6 +353,7 @@ Grabber.prototype.pressEvent = function(event) {
var entityProperties = Entities.getEntityProperties(clickedEntity);
this.startPosition = entityProperties.position;
this.lastRotation = entityProperties.rotation;
this.madeDynamic = false;
var cameraPosition = Camera.getPosition();
var objectBoundingDiameter = Vec3.length(entityProperties.dimensions);
@ -361,6 +365,11 @@ Grabber.prototype.pressEvent = function(event) {
return;
}
if (entityIsGrabbable(props) && !isDynamic) {
entityProperties.dynamic = true;
Entities.editEntity(clickedEntity, entityProperties);
this.madeDynamic = true;
}
// this.activateEntity(clickedEntity, entityProperties);
this.isGrabbing = true;
@ -416,6 +425,14 @@ Grabber.prototype.releaseEvent = function(event) {
if (this.actionID) {
Entities.deleteAction(this.entityID, this.actionID);
}
if (this.madeDynamic) {
var entityProps = {};
entityProps.dynamic = false;
entityProps.localVelocity = {x: 0, y: 0, z: 0};
Entities.editEntity(this.entityID, entityProps);
}
this.actionID = null;
LaserPointers.setRenderState(this.mouseRayEntities, "");

View file

@ -26,7 +26,7 @@
var xmlHttpRequest = null;
var isPreparing = false; // Explicitly track download request status.
var confirmAllPurchases = false; // Set this to "true" to cause Checkout.qml to popup for all items, even if free
var commerceMode = false;
var userIsLoggedIn = false;
var walletNeedsSetup = false;
@ -99,7 +99,9 @@
}
function maybeAddSetupWalletButton() {
if (userIsLoggedIn && walletNeedsSetup) {
if (!$('body').hasClass("walletsetup-injected") && userIsLoggedIn && walletNeedsSetup) {
$('body').addClass("walletsetup-injected");
var resultsElement = document.getElementById('results');
var setupWalletElement = document.createElement('div');
setupWalletElement.classList.add("row");
@ -135,7 +137,8 @@
}
function maybeAddLogInButton() {
if (!userIsLoggedIn) {
if (!$('body').hasClass("login-injected") && !userIsLoggedIn) {
$('body').addClass("login-injected");
var resultsElement = document.getElementById('results');
var logInElement = document.createElement('div');
logInElement.classList.add("row");
@ -300,68 +303,72 @@
}
function injectHiFiCode() {
if (!$('body').hasClass("code-injected") && confirmAllPurchases) {
$('body').addClass("code-injected");
if (commerceMode) {
maybeAddLogInButton();
maybeAddSetupWalletButton();
changeDropdownMenu();
var target = document.getElementById('templated-items');
// MutationObserver is necessary because the DOM is populated after the page is loaded.
// We're searching for changes to the element whose ID is '#templated-items' - this is
// the element that gets filled in by the AJAX.
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
injectBuyButtonOnMainPage();
if (!$('body').hasClass("code-injected")) {
$('body').addClass("code-injected");
changeDropdownMenu();
var target = document.getElementById('templated-items');
// MutationObserver is necessary because the DOM is populated after the page is loaded.
// We're searching for changes to the element whose ID is '#templated-items' - this is
// the element that gets filled in by the AJAX.
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
injectBuyButtonOnMainPage();
});
//observer.disconnect();
});
//observer.disconnect();
});
var config = { attributes: true, childList: true, characterData: true };
observer.observe(target, config);
var config = { attributes: true, childList: true, characterData: true };
observer.observe(target, config);
// Try this here in case it works (it will if the user just pressed the "back" button,
// since that doesn't trigger another AJAX request.
injectBuyButtonOnMainPage();
maybeAddPurchasesButton();
// Try this here in case it works (it will if the user just pressed the "back" button,
// since that doesn't trigger another AJAX request.
injectBuyButtonOnMainPage();
maybeAddPurchasesButton();
}
}
}
function injectHiFiItemPageCode() {
if (!$('body').hasClass("code-injected") && confirmAllPurchases) {
$('body').addClass("code-injected");
if (commerceMode) {
maybeAddLogInButton();
changeDropdownMenu();
var purchaseButton = $('#side-info').find('.btn').first();
if (!$('body').hasClass("code-injected")) {
var href = purchaseButton.attr('href');
purchaseButton.attr('href', '#');
purchaseButton.css({
"background": "linear-gradient(#00b4ef, #0093C5)",
"color": "#FFF",
"font-weight": "600",
"padding-bottom": "10px"
});
$('body').addClass("code-injected");
changeDropdownMenu();
var cost = $('.item-cost').text();
var purchaseButton = $('#side-info').find('.btn').first();
if (parseInt(cost) > 0 && $('#side-info').find('#buyItemButton').size() === 0) {
purchaseButton.html('PURCHASE <span class="hifi-glyph hifi-glyph-hfc" style="filter:invert(1);background-size:20px;' +
'width:20px;height:20px;position:relative;top:5px;"></span> ' + cost);
var href = purchaseButton.attr('href');
purchaseButton.attr('href', '#');
purchaseButton.css({
"background": "linear-gradient(#00b4ef, #0093C5)",
"color": "#FFF",
"font-weight": "600",
"padding-bottom": "10px"
});
var cost = $('.item-cost').text();
if (parseInt(cost) > 0 && $('#side-info').find('#buyItemButton').size() === 0) {
purchaseButton.html('PURCHASE <span class="hifi-glyph hifi-glyph-hfc" style="filter:invert(1);background-size:20px;' +
'width:20px;height:20px;position:relative;top:5px;"></span> ' + cost);
}
purchaseButton.on('click', function () {
buyButtonClicked(window.location.pathname.split("/")[3],
$('#top-center').find('h1').text(),
$('#creator').find('.value').text(),
cost,
href);
});
maybeAddPurchasesButton();
}
purchaseButton.on('click', function () {
buyButtonClicked(window.location.pathname.split("/")[3],
$('#top-center').find('h1').text(),
$('#creator').find('.value').text(),
cost,
href);
});
maybeAddPurchasesButton();
}
}
@ -622,7 +629,7 @@
if (parsedJsonMessage.type === "marketplaces") {
if (parsedJsonMessage.action === "commerceSetting") {
confirmAllPurchases = !!parsedJsonMessage.data.commerceMode;
commerceMode = !!parsedJsonMessage.data.commerceMode;
userIsLoggedIn = !!parsedJsonMessage.data.userIsLoggedIn;
walletNeedsSetup = !!parsedJsonMessage.data.walletNeedsSetup;
injectCode();

File diff suppressed because it is too large Load diff

View file

@ -98,6 +98,7 @@
// for toolbar-mode: go back to home screen, this will close the window.
tablet.gotoHomeScreen();
} else {
Wallet.refreshWalletStatus();
var entity = HMD.tabletID;
Entities.editEntity(entity, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) });
showMarketplace();
@ -157,11 +158,24 @@
}
}
function sendCommerceSettings() {
tablet.emitScriptEvent(JSON.stringify({
type: "marketplaces",
action: "commerceSetting",
data: {
commerceMode: Settings.getValue("commerce", false),
userIsLoggedIn: Account.loggedIn,
walletNeedsSetup: Wallet.walletStatus === 1
}
}));
}
marketplaceButton.clicked.connect(onClick);
tablet.screenChanged.connect(onScreenChanged);
Entities.canWriteAssetsChanged.connect(onCanWriteAssetsChanged);
ContextOverlay.contextOverlayClicked.connect(setCertificateInfo);
GlobalServices.myUsernameChanged.connect(onUsernameChanged);
Wallet.walletStatusChanged.connect(sendCommerceSettings);
Wallet.refreshWalletStatus();
function onMessage(message) {
@ -203,15 +217,7 @@
canRezCertifiedItems: Entities.canRezCertified || Entities.canRezTmpCertified
});
} else if (parsedJsonMessage.type === "REQUEST_SETTING") {
tablet.emitScriptEvent(JSON.stringify({
type: "marketplaces",
action: "commerceSetting",
data: {
commerceMode: Settings.getValue("commerce", false),
userIsLoggedIn: Account.loggedIn,
walletNeedsSetup: Wallet.walletStatus === 1
}
}));
sendCommerceSettings();
} else if (parsedJsonMessage.type === "PURCHASES") {
referrerURL = parsedJsonMessage.referrerURL;
filterText = "";
@ -244,6 +250,7 @@
tablet.webEventReceived.disconnect(onMessage);
Entities.canWriteAssetsChanged.disconnect(onCanWriteAssetsChanged);
GlobalServices.myUsernameChanged.disconnect(onUsernameChanged);
Wallet.walletStatusChanged.disconnect(sendCommerceSettings);
});