Merge branch 'master' of https://github.com/highfidelity/hifi into punk
|
@ -395,8 +395,14 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
|||
}
|
||||
|
||||
// If Avatar A's PAL WAS open but is no longer open, AND
|
||||
// Avatar A should be ignoring Avatar B...
|
||||
if (PALWasOpen && !PALIsOpen && shouldIgnore) {
|
||||
// Avatar A is ignoring Avatar B OR Avatar B is ignoring Avatar A...
|
||||
//
|
||||
// This is a bit heavy-handed still - there are cases where a kill packet
|
||||
// will be sent when it doesn't need to be (but where it _should_ be OK to send).
|
||||
// However, it's less heavy-handed than using `shouldIgnore`.
|
||||
if (PALWasOpen && !PALIsOpen &&
|
||||
(destinationNode->isIgnoringNodeWithID(avatarNode->getUUID()) ||
|
||||
avatarNode->isIgnoringNodeWithID(destinationNode->getUUID()))) {
|
||||
// ...send a Kill Packet to Node A, instructing Node A to kill Avatar B,
|
||||
// then have Node A cleanup the killed Node B.
|
||||
auto packet = NLPacket::create(PacketType::KillAvatar, NUM_BYTES_RFC4122_UUID + sizeof(KillAvatarReason), true);
|
||||
|
|
78
interface/resources/controllers/standard_nomovement.json
Normal file
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
"name": "Standard to Action (No Movement)",
|
||||
"channels": [
|
||||
{ "from": "Standard.LT", "to": "Actions.LeftHandClick" },
|
||||
{ "from": "Standard.RT", "to": "Actions.RightHandClick" },
|
||||
|
||||
{ "from": "Standard.LeftHand", "to": "Actions.LeftHand" },
|
||||
{ "from": "Standard.LeftHandThumb1", "to": "Actions.LeftHandThumb1"},
|
||||
{ "from": "Standard.LeftHandThumb2", "to": "Actions.LeftHandThumb2"},
|
||||
{ "from": "Standard.LeftHandThumb3", "to": "Actions.LeftHandThumb3"},
|
||||
{ "from": "Standard.LeftHandThumb4", "to": "Actions.LeftHandThumb4"},
|
||||
{ "from": "Standard.LeftHandIndex1", "to": "Actions.LeftHandIndex1"},
|
||||
{ "from": "Standard.LeftHandIndex2", "to": "Actions.LeftHandIndex2"},
|
||||
{ "from": "Standard.LeftHandIndex3", "to": "Actions.LeftHandIndex3"},
|
||||
{ "from": "Standard.LeftHandIndex4", "to": "Actions.LeftHandIndex4"},
|
||||
{ "from": "Standard.LeftHandMiddle1", "to": "Actions.LeftHandMiddle1"},
|
||||
{ "from": "Standard.LeftHandMiddle2", "to": "Actions.LeftHandMiddle2"},
|
||||
{ "from": "Standard.LeftHandMiddle3", "to": "Actions.LeftHandMiddle3"},
|
||||
{ "from": "Standard.LeftHandMiddle4", "to": "Actions.LeftHandMiddle4"},
|
||||
{ "from": "Standard.LeftHandRing1", "to": "Actions.LeftHandRing1"},
|
||||
{ "from": "Standard.LeftHandRing2", "to": "Actions.LeftHandRing2"},
|
||||
{ "from": "Standard.LeftHandRing3", "to": "Actions.LeftHandRing3"},
|
||||
{ "from": "Standard.LeftHandRing4", "to": "Actions.LeftHandRing4"},
|
||||
{ "from": "Standard.LeftHandPinky1", "to": "Actions.LeftHandPinky1"},
|
||||
{ "from": "Standard.LeftHandPinky2", "to": "Actions.LeftHandPinky2"},
|
||||
{ "from": "Standard.LeftHandPinky3", "to": "Actions.LeftHandPinky3"},
|
||||
{ "from": "Standard.LeftHandPinky4", "to": "Actions.LeftHandPinky4"},
|
||||
|
||||
{ "from": "Standard.RightHand", "to": "Actions.RightHand" },
|
||||
{ "from": "Standard.RightHandThumb1", "to": "Actions.RightHandThumb1"},
|
||||
{ "from": "Standard.RightHandThumb2", "to": "Actions.RightHandThumb2"},
|
||||
{ "from": "Standard.RightHandThumb3", "to": "Actions.RightHandThumb3"},
|
||||
{ "from": "Standard.RightHandThumb4", "to": "Actions.RightHandThumb4"},
|
||||
{ "from": "Standard.RightHandIndex1", "to": "Actions.RightHandIndex1"},
|
||||
{ "from": "Standard.RightHandIndex2", "to": "Actions.RightHandIndex2"},
|
||||
{ "from": "Standard.RightHandIndex3", "to": "Actions.RightHandIndex3"},
|
||||
{ "from": "Standard.RightHandIndex4", "to": "Actions.RightHandIndex4"},
|
||||
{ "from": "Standard.RightHandMiddle1", "to": "Actions.RightHandMiddle1"},
|
||||
{ "from": "Standard.RightHandMiddle2", "to": "Actions.RightHandMiddle2"},
|
||||
{ "from": "Standard.RightHandMiddle3", "to": "Actions.RightHandMiddle3"},
|
||||
{ "from": "Standard.RightHandMiddle4", "to": "Actions.RightHandMiddle4"},
|
||||
{ "from": "Standard.RightHandRing1", "to": "Actions.RightHandRing1"},
|
||||
{ "from": "Standard.RightHandRing2", "to": "Actions.RightHandRing2"},
|
||||
{ "from": "Standard.RightHandRing3", "to": "Actions.RightHandRing3"},
|
||||
{ "from": "Standard.RightHandRing4", "to": "Actions.RightHandRing4"},
|
||||
{ "from": "Standard.RightHandPinky1", "to": "Actions.RightHandPinky1"},
|
||||
{ "from": "Standard.RightHandPinky2", "to": "Actions.RightHandPinky2"},
|
||||
{ "from": "Standard.RightHandPinky3", "to": "Actions.RightHandPinky3"},
|
||||
{ "from": "Standard.RightHandPinky4", "to": "Actions.RightHandPinky4"},
|
||||
|
||||
{ "from": "Standard.LeftFoot", "to": "Actions.LeftFoot" },
|
||||
{ "from": "Standard.RightFoot", "to": "Actions.RightFoot" },
|
||||
|
||||
{ "from": "Standard.Hips", "to": "Actions.Hips" },
|
||||
{ "from": "Standard.Spine2", "to": "Actions.Spine2" },
|
||||
|
||||
{ "from": "Standard.Head", "to": "Actions.Head" },
|
||||
{ "from": "Standard.LeftArm", "to": "Actions.LeftArm" },
|
||||
{ "from": "Standard.RightArm", "to": "Actions.RightArm" },
|
||||
|
||||
{ "from": "Standard.TrackedObject00", "to" : "Actions.TrackedObject00" },
|
||||
{ "from": "Standard.TrackedObject01", "to" : "Actions.TrackedObject01" },
|
||||
{ "from": "Standard.TrackedObject02", "to" : "Actions.TrackedObject02" },
|
||||
{ "from": "Standard.TrackedObject03", "to" : "Actions.TrackedObject03" },
|
||||
{ "from": "Standard.TrackedObject04", "to" : "Actions.TrackedObject04" },
|
||||
{ "from": "Standard.TrackedObject05", "to" : "Actions.TrackedObject05" },
|
||||
{ "from": "Standard.TrackedObject06", "to" : "Actions.TrackedObject06" },
|
||||
{ "from": "Standard.TrackedObject07", "to" : "Actions.TrackedObject07" },
|
||||
{ "from": "Standard.TrackedObject08", "to" : "Actions.TrackedObject08" },
|
||||
{ "from": "Standard.TrackedObject09", "to" : "Actions.TrackedObject09" },
|
||||
{ "from": "Standard.TrackedObject10", "to" : "Actions.TrackedObject10" },
|
||||
{ "from": "Standard.TrackedObject11", "to" : "Actions.TrackedObject11" },
|
||||
{ "from": "Standard.TrackedObject12", "to" : "Actions.TrackedObject12" },
|
||||
{ "from": "Standard.TrackedObject13", "to" : "Actions.TrackedObject13" },
|
||||
{ "from": "Standard.TrackedObject14", "to" : "Actions.TrackedObject14" },
|
||||
{ "from": "Standard.TrackedObject15", "to" : "Actions.TrackedObject15" }
|
||||
]
|
||||
}
|
|
@ -154,4 +154,6 @@
|
|||
<glyph glyph-name="40-reload" unicode="F" d="M365 261c-9 1-17-5-18-15-4-45-43-80-89-80-49 0-89 40-89 89 0 19 4 45 25 65 16 15 39 23 68 25l-15-16c-6-6-6-17 0-24 4-3 8-4 12-4 4 0 9 1 12 5l43 44c2 2 3 4 4 6 2 6 1 13-4 18l-44 44c-6 6-17 6-23 0-7-7-7-17 0-24l15-15c-38-2-69-14-91-35-23-21-36-53-36-88 0-68 55-123 123-123 64 0 116 47 122 110 1 9-5 18-15 18"/>
|
||||
<glyph glyph-name="forward" unicode="D" d="M330 278l-95 70c-5 4-12 5-18 2-5-3-9-9-9-16l0-150c0-7 4-13 10-16 2-1 5-2 7-2 4 0 8 2 11 5l95 79c4 4 6 9 6 14-1 5-3 10-7 14"/>
|
||||
<glyph glyph-name="avatar-1" unicode="T" d="M396 344l-2 2c-4 4-9 5-15 5-1 0-88-13-124-14-1 0-2 0-3 0-37 0-126 15-127 15-7 1-14-2-18-8l-2-4c-3-4-3-9-2-14 2-5 5-9 10-11 16-7 69-22 85-29 3-1 10-4 10-14 1-11-4-67-10-93-7-26-18-60-19-60-3-9 2-19 11-22l11-4c4-2 9-1 13 1 5 2 8 6 9 10l31 94 28-96c2-5 5-9 9-11 3-1 5-2 8-2 2 0 4 0 7 1l10 4c8 3 12 12 10 20 0 1-8 36-16 65-4 17-6 43-7 64-1 13-1 21-3 30 0 1 2 11 10 14 10 4 81 29 80 28 6 2 10 7 11 13 1 6-1 12-5 16z m-98 54c0-24-19-43-43-43-24 0-43 19-43 43 0 23 19 42 43 42 24 0 43-19 43-42z"/>
|
||||
<glyph glyph-name="steam-square" unicode="" d="M391 327c0 15-5 28-16 39-11 11-24 16-39 16-15 0-28-5-39-16-11-11-16-24-16-39 0-15 5-28 16-39 11-11 24-16 39-16 15 0 28 5 39 16 11 11 16 24 16 39z m-174-168c0-16-5-29-16-40-11-11-25-16-40-16-11 0-21 2-30 8-9 5-16 13-20 22 9-4 19-8 28-12 11-4 22-4 34 1 11 5 19 13 24 25 5 11 5 22 0 34-5 11-13 19-25 24l-23 9c4 1 8 2 12 2 15 0 29-6 40-17 11-11 16-24 16-40z m258 234l0-274c0-23-8-42-24-58-16-16-35-24-58-24l-274 0c-23 0-42 8-58 24-16 16-24 35-24 58l0 44 49-20c4-18 12-32 26-44 14-11 30-17 49-17 19 0 37 7 51 20 15 14 23 30 25 50l99 72c28 0 53 10 73 30 20 20 30 44 30 73 0 28-10 52-30 73-20 20-45 30-73 30-28 0-53-10-73-30-20-20-30-44-30-72l-64-92c-2 0-5 0-8 0-15 0-28-4-40-11l-84 34 0 134c0 23 8 42 24 58 16 16 35 24 58 24l274 0c23 0 42-8 58-24 16-16 24-35 24-58z m-70-66c0-19-7-36-20-49-14-14-30-20-49-20-19 0-36 6-49 20-13 13-20 30-20 49 0 19 7 35 20 48 13 14 30 21 49 21 19 0 35-7 49-20 13-14 20-30 20-49z"/>
|
||||
<glyph glyph-name="oculus" unicode="" d="M431 363c-16 13-34 22-54 26-11 3-23 4-34 5-9 0-18 0-26 0-41 0-82 0-123 0-9 0-18 0-26 0-12-1-24-2-35-5-20-4-38-13-54-26-32-26-51-65-51-106 0-41 19-80 51-106 16-13 34-22 54-27 12-2 23-3 35-4 8 0 17 0 26 0 41 0 82 0 123 0 8 0 17 0 26 0 11 0 23 2 34 4 20 5 38 14 54 27 32 26 51 65 51 106 0 41-19 80-51 106z m-60-143c-6-4-13-7-20-8-7-1-14-1-22-1-49 0-99 0-148 0-8 0-15 0-22 1-7 1-14 4-20 8-12 8-19 22-19 37 0 15 7 29 19 37 6 4 13 7 20 8 7 1 14 1 22 1 49 0 99 0 148 0 8 0 15 0 22-1 7-1 14-4 20-8 12-8 19-22 19-37 0-15-7-29-19-37z"/>
|
||||
</font></defs></svg>
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 84 KiB |
|
@ -603,6 +603,14 @@
|
|||
<div class="icon icon-avatar-1"></div>
|
||||
<input type="text" readonly="readonly" value="avatar-1">
|
||||
</li>
|
||||
<li>
|
||||
<div class="icon icon-steam-square"></div>
|
||||
<input type="text" readonly="readonly" value="steam-square">
|
||||
</li>
|
||||
<li>
|
||||
<div class="icon icon-oculus"></div>
|
||||
<input type="text" readonly="readonly" value="oculus">
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Character mapping</h2>
|
||||
<ul class="glyphs character-mapping">
|
||||
|
@ -1194,6 +1202,14 @@
|
|||
<div data-icon="T" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="T">
|
||||
</li>
|
||||
<li>
|
||||
<div data-icon="" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="&#xe035;">
|
||||
</li>
|
||||
<li>
|
||||
<div data-icon="" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="&#xe036;">
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<script>(function() {
|
|
@ -479,3 +479,9 @@
|
|||
.icon-avatar-1:before {
|
||||
content: "\54";
|
||||
}
|
||||
.icon-steam-square:before {
|
||||
content: "\e035";
|
||||
}
|
||||
.icon-oculus:before {
|
||||
content: "\e036";
|
||||
}
|
4
interface/resources/icons/steam.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.4866 0C4.92045 0 0.367395 4.32104 0 9.78734L5.45262 11.9841C5.93184 11.651 6.51333 11.4545 7.14145 11.4545C7.27641 11.4545 7.4083 11.4666 7.53829 11.4841L10.1047 7.72495C10.1083 5.56672 11.861 3.81818 14.0229 3.81818C16.1872 3.81818 17.9416 5.57035 17.9416 7.73182C17.9416 9.89329 16.1872 11.6455 14.0229 11.6455C14.021 11.6455 14.0189 11.6453 14.017 11.6453L10.0936 14.2008C10.0986 14.2712 10.1043 14.3419 10.1043 14.4136C10.1043 16.048 8.77791 17.3727 7.14145 17.3727C5.69539 17.3727 4.49304 16.3376 4.2325 14.969L0.378099 13.3841C1.6334 17.7801 5.6822 21 10.4866 21C16.2931 21 21 16.2991 21 10.5C21 4.70114 16.2931 0 10.4866 0ZM7.14145 16.0364C6.96655 16.0364 6.79833 16.0081 6.64044 15.9569L6.63968 15.9589L6.59151 15.939C6.54506 15.9224 6.49975 15.9037 6.45541 15.8831L5.15462 15.3483C5.50614 16.0927 6.26253 16.6091 7.14145 16.6091C8.35546 16.6091 9.33971 15.6263 9.33971 14.4136C9.33971 13.201 8.35546 12.2182 7.14145 12.2182C6.87269 12.2182 6.61636 12.2688 6.37818 12.357L7.75448 12.9114C7.76404 12.9154 7.77359 12.9188 7.78296 12.923L7.89001 12.9662L7.88714 12.9732C8.40898 13.243 8.76625 13.7861 8.76625 14.4136C8.76625 15.3098 8.03872 16.0364 7.14145 16.0364ZM16.7946 7.73182C16.7946 6.20302 15.5537 4.96364 14.0229 4.96364C12.4922 4.96364 11.2512 6.20302 11.2512 7.73182C11.2512 9.26062 12.4922 10.5 14.0229 10.5C15.5537 10.5 16.7946 9.26062 16.7946 7.73182ZM12.0158 7.73182C12.0158 6.62474 12.9144 5.72727 14.0229 5.72727C15.1314 5.72727 16.03 6.62474 16.03 7.73182C16.03 8.8389 15.1314 9.73636 14.0229 9.73636C12.9144 9.73636 12.0158 8.8389 12.0158 7.73182Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
17
interface/resources/images/high-fidelity-banner.svg
Normal file
|
@ -0,0 +1,17 @@
|
|||
<svg width="360" height="85" viewBox="0 0 360 85" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M124 30V59H117.974V46.3455H108.026V59H102V30H108.026V41.1899H117.974V30H124Z" fill="#00B4F0"/>
|
||||
<path d="M135 59H129V30H135V59Z" fill="#00B4F0"/>
|
||||
<path d="M151.829 34.9471C150.406 34.9471 149.211 35.0608 148.187 35.3451C147.22 35.6294 146.423 36.0843 145.797 36.7098C145.171 37.3353 144.772 38.2451 144.488 39.3255C144.203 40.4059 144.089 41.7706 144.089 43.3627V45.9216C144.089 47.6275 144.203 48.9922 144.431 50.0726C144.659 51.1529 145.057 52.0059 145.626 52.5745C146.138 53.2 146.878 53.598 147.732 53.8255C148.585 54.0529 149.667 54.1667 150.919 54.1667C151.26 54.1667 151.659 54.1667 152.057 54.1098C152.455 54.1098 152.854 54.0529 153.309 53.9961V46.3765H149.78L150.35 41.7137H159V57.749C157.919 58.1471 156.553 58.4314 154.902 58.6588C153.309 58.8863 151.602 59 149.894 59C147.732 59 145.911 58.7157 144.431 58.2039C142.894 57.6922 141.699 56.8961 140.732 55.8157C139.764 54.7353 139.081 53.4275 138.626 51.7784C138.171 50.1863 138 48.2529 138 46.0922V43.1922C138 41.202 138.228 39.4392 138.626 37.7902C139.081 36.1412 139.821 34.7765 140.846 33.6392C141.87 32.502 143.236 31.5922 144.886 30.9667C146.537 30.3412 148.642 30 151.146 30C152.512 30 153.878 30.1137 155.187 30.3412C156.496 30.5686 157.577 30.8529 158.431 31.1373L157.463 35.6863C156.724 35.4588 155.87 35.2882 154.959 35.1176C154.049 35.0039 153.024 34.9471 151.829 34.9471Z" fill="#00B4F0"/>
|
||||
<path d="M187 30V59H180.959V46.3455H171.041V59H165V30H171.041V41.1899H181.016V30H187Z" fill="#00B4F0"/>
|
||||
<path d="M218 30L217.366 35.0384H207.597V41.0727H216.627L215.993 46.1111H207.597V59H202V30H218Z" fill="#00B4F0"/>
|
||||
<path d="M229 59H223V30H229V59Z" fill="#00B4F0"/>
|
||||
<path d="M233 30H242.404C244.842 30 246.873 30.3508 248.499 30.994C250.124 31.6371 251.401 32.5726 252.388 33.6835C253.375 34.8528 254.013 36.1976 254.42 37.8347C254.826 39.4718 255 41.2258 255 43.0968V45.8448C255 47.7742 254.826 49.5282 254.42 51.1653C254.013 52.8024 253.317 54.1472 252.388 55.3165C251.401 56.4859 250.124 57.3629 248.499 58.006C246.873 58.6492 244.842 59 242.404 59H233.058V30H233ZM239.095 53.9133H241.765C242.926 53.9133 243.913 53.7964 244.842 53.504C245.712 53.2117 246.467 52.744 247.047 52.1008C247.628 51.4577 248.034 50.5806 248.325 49.5282C248.615 48.4758 248.731 47.1311 248.731 45.494V43.3306C248.731 41.6935 248.615 40.3488 248.325 39.2964C248.034 38.2439 247.628 37.3669 247.047 36.7238C246.467 36.0806 245.77 35.6129 244.842 35.379C243.971 35.1452 242.926 34.9698 241.765 34.9698H239.095V53.9133Z" fill="#00B4F0"/>
|
||||
<path d="M275.945 30L275.34 34.8528H264.832V41.1673H274.735L274.184 46.0202H264.887V54.1472H276L275.395 59H259V30H275.945Z" fill="#00B4F0"/>
|
||||
<path d="M286.215 30V53.9616H298L297.296 59H280V30H286.215Z" fill="#00B4F0"/>
|
||||
<path d="M307 59H302V30H307V59Z" fill="#00B4F0"/>
|
||||
<path d="M334 30L333.307 35.0384H325.563V59H319.437V35.0384H311L311.693 30H334Z" fill="#00B4F0"/>
|
||||
<path d="M347.617 41.3071L353.633 30H360L350.537 46.3455V59H344.346V46.3455L335 30H341.776L347.617 41.3071Z" fill="#00B4F0"/>
|
||||
<path d="M42.1132 85C36.4528 85 30.9057 83.856 25.7547 81.6824C20.717 79.5659 16.2453 76.4771 12.3962 72.5875C8.54717 68.6978 5.49057 64.1218 3.39623 59.0882C1.13208 53.7685 -1.07963e-07 48.22 -1.07963e-07 42.4428C-1.07963e-07 36.7227 1.13208 31.1171 3.28302 25.9118C5.37736 20.821 8.43396 16.3022 12.283 12.4125C16.1321 8.52288 20.6604 5.43405 25.6415 3.31763C30.8491 1.08681 36.3396 1.09101e-07 42 1.09101e-07C47.6604 1.09101e-07 53.2076 1.14401 58.3585 3.31763C63.3962 5.43405 67.8679 8.52288 71.717 12.4125C75.566 16.3022 78.6227 20.8782 80.717 25.9118C82.9245 31.1743 84 36.7227 84 42.4428C84 48.1628 82.8679 53.7685 80.717 58.9737C78.6227 64.0646 75.566 68.5834 71.717 72.4731C67.8679 76.3627 63.3396 79.4515 58.3585 81.568C53.3208 83.856 47.7736 85 42.1132 85ZM42.1132 4.34724C21.3396 4.34724 4.41509 21.4502 4.41509 42.4428C4.41509 63.4354 21.3396 80.5384 42.1132 80.5384C62.8868 80.5384 79.8113 63.4354 79.8113 42.4428C79.8113 21.4502 62.8868 4.34724 42.1132 4.34724Z" fill="#00B4F0"/>
|
||||
<path d="M54.8 60.7368V30.5158C56.6857 29.8789 58 28.0842 58 26C58 23.3947 55.8857 21.2526 53.3143 21.2526C50.7429 21.2526 48.6286 23.3947 48.6286 26C48.6286 28.0263 49.8286 29.7053 51.6 30.4579V44.5263L32.1714 35.379V24.2632C34.0571 23.6263 35.3714 21.8316 35.3714 19.7474C35.3714 17.1421 33.2571 15 30.6857 15C28.1143 15 26 17.1421 26 19.7474C26 21.7737 27.2 23.4526 28.9714 24.2053V54.6C27.2571 55.2947 26 57.0316 26 59.0579C26 61.6632 28.1143 63.8053 30.6857 63.8053C33.2571 63.8053 35.3714 61.6632 35.3714 59.0579C35.3714 56.9737 34.0571 55.1789 32.1714 54.5421V39.2L51.6 48.3474V60.7947C49.8857 61.4895 48.6286 63.2263 48.6286 65.2526C48.6286 67.8579 50.7429 70 53.3143 70C55.8857 70 58 67.8579 58 65.2526C58 63.1105 56.6857 61.3737 54.8 60.7368Z" fill="#00B4F0"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
|
@ -54,7 +54,7 @@ Windows.Window {
|
|||
onSourceChanged: {
|
||||
if (dynamicContent) {
|
||||
dynamicContent.destroy();
|
||||
dynamicContent = null;
|
||||
dynamicContent = null;
|
||||
}
|
||||
QmlSurface.load(source, contentHolder, function(newObject) {
|
||||
dynamicContent = newObject;
|
||||
|
@ -117,7 +117,7 @@ Windows.Window {
|
|||
console.error("presentationMode should be set.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
// Fix for parent loss on OSX:
|
||||
parent.heightChanged.connect(updateContentParent);
|
||||
|
@ -215,7 +215,7 @@ Windows.Window {
|
|||
nativeWindow.raise();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Handle message traffic from our loaded QML to the script that launched us
|
||||
signal sendToScript(var message);
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
//
|
||||
// Created by David Rowe on 3 Jun 2015
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
@ -11,32 +10,34 @@
|
|||
import Hifi 1.0
|
||||
import QtQuick 2.4
|
||||
|
||||
import controlsUit 1.0
|
||||
import stylesUit 1.0
|
||||
import "windows"
|
||||
import controlsUit 1.0 as HifiControlsUit
|
||||
import stylesUit 1.0 as HifiStylesUit
|
||||
|
||||
import "LoginDialog"
|
||||
|
||||
ModalWindow {
|
||||
FocusScope {
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
HifiStylesUit.HifiConstants { id: hifi }
|
||||
objectName: "LoginDialog"
|
||||
implicitWidth: 520
|
||||
implicitHeight: 320
|
||||
closeButtonVisible: true
|
||||
destroyOnCloseButton: true
|
||||
destroyOnHidden: true
|
||||
visible: true
|
||||
property bool shown: true
|
||||
visible: shown
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
readonly property bool isTablet: false
|
||||
readonly property bool isOverlay: false
|
||||
|
||||
property string iconText: ""
|
||||
property int iconSize: 50
|
||||
|
||||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
property bool isPassword: false
|
||||
property string title: ""
|
||||
property string text: ""
|
||||
property int titleWidth: 0
|
||||
|
||||
keyboardOverride: true // Disable ModalWindow's keyboard.
|
||||
property alias bannerWidth: banner.width
|
||||
property alias bannerHeight: banner.height
|
||||
|
||||
function tryDestroy() {
|
||||
root.destroy()
|
||||
|
@ -47,7 +48,39 @@ ModalWindow {
|
|||
|
||||
Loader {
|
||||
id: bodyLoader
|
||||
source: loginDialog.isSteamRunning() ? "LoginDialog/SignInBody.qml" : "LoginDialog/LinkAccountBody.qml"
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
z: -10
|
||||
id: loginDialogBackground
|
||||
source: "LoginDialog/images/background.jpg"
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
z: -6
|
||||
id: opaqueRect
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
opacity: 0.65
|
||||
color: "black"
|
||||
}
|
||||
|
||||
Item {
|
||||
z: -5
|
||||
id: bannerContainer
|
||||
width: parent.width
|
||||
height: banner.height
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: 0.18 * parent.height
|
||||
}
|
||||
Image {
|
||||
id: banner
|
||||
anchors.centerIn: parent
|
||||
source: "../images/high-fidelity-banner.svg"
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +109,6 @@ ModalWindow {
|
|||
case Qt.Key_Escape:
|
||||
case Qt.Key_Back:
|
||||
event.accepted = true
|
||||
destroy()
|
||||
break
|
||||
|
||||
case Qt.Key_Enter:
|
||||
|
@ -85,4 +117,8 @@ ModalWindow {
|
|||
break
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
bodyLoader.setSource("LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,109 +12,240 @@ import Hifi 1.0
|
|||
import QtQuick 2.4
|
||||
import QtQuick.Controls.Styles 1.4 as OriginalStyles
|
||||
|
||||
import controlsUit 1.0
|
||||
import stylesUit 1.0
|
||||
import controlsUit 1.0 as HifiControlsUit
|
||||
import stylesUit 1.0 as HifiStylesUit
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Item {
|
||||
id: completeProfileBody
|
||||
clip: true
|
||||
width: root.pane.width
|
||||
height: root.pane.height
|
||||
width: root.width
|
||||
height: root.height
|
||||
readonly property string termsContainerText: qsTr("By creating this user profile, you agree to High Fidelity's Terms of Service")
|
||||
readonly property string fontFamily: "Raleway"
|
||||
readonly property int fontSize: 15
|
||||
readonly property bool fontBold: true
|
||||
|
||||
readonly property bool withSteam: withSteam
|
||||
property string errorString: errorString
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property int minWidth: 480
|
||||
readonly property int maxWidth: 1280
|
||||
readonly property int minWidthButton: !root.isTablet ? 256 : 174
|
||||
property int maxWidth: root.width
|
||||
readonly property int minHeight: 120
|
||||
readonly property int maxHeight: 720
|
||||
readonly property int minHeightButton: 36
|
||||
property int maxHeight: root.height
|
||||
|
||||
function resize() {
|
||||
maxWidth = root.width;
|
||||
maxHeight = root.height;
|
||||
if (root.isTablet === false) {
|
||||
var targetWidth = Math.max(titleWidth, Math.max(additionalTextContainer.contentWidth,
|
||||
termsContainer.contentWidth))
|
||||
var targetWidth = Math.max(Math.max(titleWidth, Math.max(additionalTextContainer.width,
|
||||
termsContainer.width)), mainContainer.width)
|
||||
parent.width = root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth))
|
||||
}
|
||||
var targetHeight = 5 * hifi.dimensions.contentSpacing.y + buttons.height + additionalTextContainer.height + termsContainer.height
|
||||
var targetHeight = Math.max(5 * hifi.dimensions.contentSpacing.y + d.minHeightButton + additionalTextContainer.height + termsContainer.height, d.maxHeight)
|
||||
parent.height = root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight))
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: buttons
|
||||
anchors {
|
||||
top: parent.top
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
margins: 0
|
||||
topMargin: 2 * hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
Item {
|
||||
id: mainContainer
|
||||
width: root.width
|
||||
height: root.height
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
Button {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 200
|
||||
Item {
|
||||
id: contentItem
|
||||
anchors.fill: parent
|
||||
|
||||
text: qsTr("Create your profile")
|
||||
color: hifi.buttons.blue
|
||||
Item {
|
||||
id: errorContainer
|
||||
width: parent.width
|
||||
height: loginErrorMessageTextMetrics.height
|
||||
anchors {
|
||||
bottom: buttons.top;
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y;
|
||||
left: buttons.left;
|
||||
}
|
||||
TextMetrics {
|
||||
id: loginErrorMessageTextMetrics
|
||||
font: loginErrorMessage.font
|
||||
text: loginErrorMessage.text
|
||||
}
|
||||
Text {
|
||||
id: loginErrorMessage;
|
||||
width: root.bannerWidth
|
||||
color: "red";
|
||||
font.family: completeProfileBody.fontFamily
|
||||
font.pixelSize: 18
|
||||
font.bold: completeProfileBody.fontBold
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: completeProfileBody.errorString
|
||||
visible: true
|
||||
}
|
||||
Component.onCompleted: {
|
||||
if (loginErrorMessageTextMetrics.width > root.bannerWidth && root.isTablet) {
|
||||
loginErrorMessage.wrapMode = Text.WordWrap;
|
||||
loginErrorMessage.verticalAlignment = Text.AlignLeft;
|
||||
loginErrorMessage.horizontalAlignment = Text.AlignLeft;
|
||||
errorContainer.height = 3 * loginErrorMessageTextMetrics.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: loginDialog.createAccountFromStream()
|
||||
Item {
|
||||
id: buttons
|
||||
width: root.bannerWidth
|
||||
height: d.minHeightButton
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: (parent.height - additionalTextContainer.height) / 2 - hifi.dimensions.contentSpacing.y
|
||||
left: parent.left
|
||||
leftMargin: (parent.width - root.bannerWidth) / 2
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
id: cancelButton
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
}
|
||||
width: (parent.width - hifi.dimensions.contentSpacing.x) / 2
|
||||
height: d.minHeightButton
|
||||
|
||||
text: qsTr("CANCEL")
|
||||
color: hifi.buttons.noneBorderlessWhite
|
||||
|
||||
fontFamily: completeProfileBody.fontFamily
|
||||
fontSize: completeProfileBody.fontSize
|
||||
fontBold: completeProfileBody.fontBold
|
||||
onClicked: {
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader });
|
||||
}
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
id: profileButton
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
}
|
||||
width: (parent.width - hifi.dimensions.contentSpacing.x) / 2
|
||||
height: d.minHeightButton
|
||||
|
||||
text: qsTr("Create your profile")
|
||||
color: hifi.buttons.blue
|
||||
|
||||
fontFamily: completeProfileBody.fontFamily
|
||||
fontSize: completeProfileBody.fontSize
|
||||
fontBold: completeProfileBody.fontBold
|
||||
onClicked: {
|
||||
loginErrorMessage.visible = false;
|
||||
loginDialog.createAccountFromSteam();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: additionalTextContainer
|
||||
width: parent.width
|
||||
height: additionalTextMetrics.height
|
||||
anchors {
|
||||
top: buttons.bottom
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
left: parent.left
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: additionalTextMetrics
|
||||
font: additionalText.font
|
||||
text: "Already have a High Fidelity profile? Link to an existing profile here."
|
||||
}
|
||||
|
||||
HifiStylesUit.ShortcutText {
|
||||
id: additionalText
|
||||
text: "<a href='https://fake.link'>Already have a High Fidelity profile? Link to an existing profile here.</a>"
|
||||
|
||||
font.family: completeProfileBody.fontFamily
|
||||
font.pixelSize: completeProfileBody.fontSize
|
||||
font.bold: completeProfileBody.fontBold
|
||||
wrapMode: Text.NoWrap
|
||||
lineHeight: 1
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
linkColor: hifi.colors.blueAccent
|
||||
|
||||
onLinkActivated: {
|
||||
loginDialog.isLogIn = true;
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": "", "withSteam": true, "linkSteam": true });
|
||||
}
|
||||
Component.onCompleted: {
|
||||
if (additionalTextMetrics.width > root.bannerWidth && root.isTablet) {
|
||||
additionalText.width = root.bannerWidth;
|
||||
additionalText.wrapMode = Text.WordWrap;
|
||||
additionalText.verticalAlignment = Text.AlignLeft;
|
||||
additionalText.horizontalAlignment = Text.AlignLeft;
|
||||
additionalTextContainer.height = (additionalTextMetrics.width / root.bannerWidth) * additionalTextMetrics.height;
|
||||
additionalTextContainer.anchors.left = buttons.left;
|
||||
} else {
|
||||
additionalText.anchors.centerIn = additionalTextContainer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: termsContainer
|
||||
width: parent.width
|
||||
height: termsTextMetrics.height
|
||||
anchors {
|
||||
top: additionalTextContainer.bottom
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
topMargin: 2 * hifi.dimensions.contentSpacing.y
|
||||
left: parent.left
|
||||
}
|
||||
TextMetrics {
|
||||
id: termsTextMetrics
|
||||
font: termsText.font
|
||||
text: completeProfileBody.termsContainerText
|
||||
Component.onCompleted: {
|
||||
// with the link.
|
||||
termsText.text = qsTr("By creating this user profile, you agree to <a href='https://highfidelity.com/terms'>High Fidelity's Terms of Service</a>")
|
||||
}
|
||||
}
|
||||
|
||||
HifiStylesUit.InfoItem {
|
||||
id: termsText
|
||||
text: completeProfileBody.termsContainerText
|
||||
font.family: completeProfileBody.fontFamily
|
||||
font.pixelSize: completeProfileBody.fontSize
|
||||
font.bold: completeProfileBody.fontBold
|
||||
wrapMode: Text.WordWrap
|
||||
color: hifi.colors.lightGray
|
||||
linkColor: hifi.colors.blueAccent
|
||||
lineHeight: 1
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
|
||||
onLinkActivated: loginDialog.openUrl(link);
|
||||
|
||||
Component.onCompleted: {
|
||||
if (termsTextMetrics.width > root.bannerWidth && root.isTablet) {
|
||||
termsText.width = root.bannerWidth;
|
||||
termsText.wrapMode = Text.WordWrap;
|
||||
additionalText.verticalAlignment = Text.AlignLeft;
|
||||
additionalText.horizontalAlignment = Text.AlignLeft;
|
||||
termsContainer.height = (termsTextMetrics.width / root.bannerWidth) * termsTextMetrics.height;
|
||||
termsContainer.anchors.left = buttons.left;
|
||||
} else {
|
||||
termsText.anchors.centerIn = termsContainer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: qsTr("Cancel")
|
||||
onClicked: root.tryDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
ShortcutText {
|
||||
id: additionalTextContainer
|
||||
anchors {
|
||||
top: buttons.bottom
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
margins: 0
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
|
||||
text: "<a href='https://fake.link'>Already have a High Fidelity profile? Link to an existing profile here.</a>"
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
lineHeight: 2
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
onLinkActivated: {
|
||||
bodyLoader.source = "LinkAccountBody.qml"
|
||||
bodyLoader.item.width = root.pane.width
|
||||
bodyLoader.item.height = root.pane.height
|
||||
}
|
||||
}
|
||||
|
||||
InfoItem {
|
||||
id: termsContainer
|
||||
anchors {
|
||||
top: additionalTextContainer.bottom
|
||||
margins: 0
|
||||
topMargin: 2 * hifi.dimensions.contentSpacing.y
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
width: parent.width
|
||||
|
||||
text: qsTr("By creating this user profile, you agree to <a href='https://highfidelity.com/terms'>High Fidelity's Terms of Service</a>")
|
||||
wrapMode: Text.WordWrap
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
lineHeight: 1
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
fontSizeMode: Text.HorizontalFit
|
||||
horizontalAlignment: Text.AlignVCenter
|
||||
|
||||
onLinkActivated: loginDialog.openUrl(link)
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
root.title = qsTr("Complete Your Profile")
|
||||
root.iconText = "<"
|
||||
d.resize();
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
@ -122,26 +253,23 @@ Item {
|
|||
onHandleCreateCompleted: {
|
||||
console.log("Create Succeeded")
|
||||
|
||||
loginDialog.loginThroughSteam()
|
||||
loginDialog.loginThroughSteam();
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": true, "linkSteam": false });
|
||||
}
|
||||
onHandleCreateFailed: {
|
||||
console.log("Create Failed: " + error)
|
||||
console.log("Create Failed: " + error);
|
||||
|
||||
bodyLoader.source = "UsernameCollisionBody.qml"
|
||||
if (!root.isTablet) {
|
||||
bodyLoader.item.width = root.pane.width
|
||||
bodyLoader.item.height = root.pane.height
|
||||
}
|
||||
}
|
||||
onHandleLoginCompleted: {
|
||||
console.log("Login Succeeded")
|
||||
|
||||
bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : false })
|
||||
bodyLoader.item.width = root.pane.width
|
||||
bodyLoader.item.height = root.pane.height
|
||||
}
|
||||
onHandleLoginFailed: {
|
||||
console.log("Login Failed")
|
||||
bodyLoader.setSource("UsernameCollisionBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader });
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
//but rise Tablet's one instead for Tablet interface
|
||||
if (root.isTablet || root.isOverlay) {
|
||||
root.keyboardEnabled = HMD.active;
|
||||
root.keyboardRaised = Qt.binding( function() { return keyboardRaised; })
|
||||
}
|
||||
d.resize();
|
||||
root.text = "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,408 +13,544 @@ import QtQuick 2.7
|
|||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4 as OriginalStyles
|
||||
|
||||
import controlsUit 1.0
|
||||
import stylesUit 1.0
|
||||
import "." as LoginDialog
|
||||
|
||||
import controlsUit 1.0 as HifiControlsUit
|
||||
import stylesUit 1.0 as HifiStylesUit
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Item {
|
||||
z: -2
|
||||
id: linkAccountBody
|
||||
clip: true
|
||||
height: root.pane.height
|
||||
width: root.pane.width
|
||||
property bool failAfterSignUp: false
|
||||
|
||||
onWidthChanged: d.resize();
|
||||
|
||||
function login() {
|
||||
flavorText.visible = false
|
||||
mainTextContainer.visible = false
|
||||
toggleLoading(true)
|
||||
loginDialog.login(usernameField.text, passwordField.text)
|
||||
}
|
||||
height: root.height
|
||||
width: root.width
|
||||
property int textFieldHeight: 31
|
||||
property string fontFamily: "Raleway"
|
||||
property int fontSize: 15
|
||||
property int textFieldFontSize: 18
|
||||
property bool fontBold: true
|
||||
readonly property var passwordImageRatio: 16 / 23
|
||||
|
||||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
|
||||
onKeyboardRaisedChanged: d.resize();
|
||||
property bool withSteam: false
|
||||
property bool linkSteam: linkSteam
|
||||
property bool withOculus: false
|
||||
property string errorString: errorString
|
||||
property bool lostFocus: false
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property int minWidth: 480
|
||||
readonly property int maxWidth: 1280
|
||||
readonly property int minWidthButton: !root.isTablet ? 256 : 174
|
||||
property int maxWidth: root.width
|
||||
readonly property int minHeight: 120
|
||||
readonly property int maxHeight: 720
|
||||
readonly property int minHeightButton: 36
|
||||
property int maxHeight: root.height
|
||||
|
||||
function resize() {
|
||||
var targetWidth = Math.max(titleWidth, form.contentWidth);
|
||||
var targetHeight = hifi.dimensions.contentSpacing.y + flavorText.height + mainTextContainer.height +
|
||||
4 * hifi.dimensions.contentSpacing.y + form.height;
|
||||
|
||||
if (additionalInformation.visible) {
|
||||
targetWidth = Math.max(targetWidth, additionalInformation.width);
|
||||
targetHeight += hifi.dimensions.contentSpacing.y + additionalInformation.height
|
||||
}
|
||||
maxWidth = root.width;
|
||||
maxHeight = root.height;
|
||||
var targetWidth = Math.max(titleWidth, mainContainer.width);
|
||||
var targetHeight = hifi.dimensions.contentSpacing.y + mainContainer.height + 4 * hifi.dimensions.contentSpacing.y;
|
||||
|
||||
var newWidth = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth));
|
||||
if(!isNaN(newWidth)) {
|
||||
if (!isNaN(newWidth)) {
|
||||
parent.width = root.width = newWidth;
|
||||
}
|
||||
|
||||
parent.height = root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight))
|
||||
+ (keyboardEnabled && keyboardRaised ? (200 + 2 * hifi.dimensions.contentSpacing.y) : hifi.dimensions.contentSpacing.y);
|
||||
parent.height = root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) + hifi.dimensions.contentSpacing.y;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleLoading(isLoading) {
|
||||
linkAccountSpinner.visible = isLoading
|
||||
form.visible = !isLoading
|
||||
|
||||
if (loginDialog.isSteamRunning()) {
|
||||
additionalInformation.visible = !isLoading
|
||||
}
|
||||
function login() {
|
||||
loginDialog.login(emailField.text, passwordField.text);
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": linkAccountBody.withSteam, "withOculus": linkAccountBody.withOculus, "linkSteam": linkAccountBody.linkSteam });
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: linkAccountSpinner
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
function init() {
|
||||
// going to/from sign in/up dialog.
|
||||
loginDialog.isLogIn = true;
|
||||
loginErrorMessage.text = linkAccountBody.errorString;
|
||||
loginErrorMessage.visible = (linkAccountBody.errorString !== "");
|
||||
loginButton.text = !linkAccountBody.linkSteam ? "Log In" : "Link Account";
|
||||
loginButton.color = hifi.buttons.blue;
|
||||
emailField.placeholderText = "Username or Email";
|
||||
var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", "");
|
||||
emailField.text = keepMeLoggedInCheckbox.checked ? savedUsername === "Unknown user" ? "" : savedUsername : "";
|
||||
if (linkAccountBody.linkSteam) {
|
||||
steamInfoText.anchors.top = passwordField.bottom;
|
||||
keepMeLoggedInCheckbox.anchors.top = steamInfoText.bottom;
|
||||
loginButton.width = (passwordField.width - hifi.dimensions.contentSpacing.x) / 2;
|
||||
loginButton.anchors.right = emailField.right;
|
||||
} else {
|
||||
loginButton.anchors.left = emailField.left;
|
||||
}
|
||||
|
||||
visible: false
|
||||
running: true
|
||||
|
||||
width: 48
|
||||
height: 48
|
||||
loginContainer.visible = true;
|
||||
}
|
||||
|
||||
ShortcutText {
|
||||
id: flavorText
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
margins: 0
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
Item {
|
||||
z: 10
|
||||
id: mainContainer
|
||||
width: root.width
|
||||
height: root.height
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
LoginDialog.LoginDialogLightbox {
|
||||
id: lightboxPopup;
|
||||
visible: false;
|
||||
anchors.fill: parent;
|
||||
}
|
||||
|
||||
text: qsTr("Sign in to High Fidelity to make friends, get HFC, and get interesting things on the Marketplace!")
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
lineHeight: 1
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
Item {
|
||||
id: loginContainer
|
||||
width: emailField.width
|
||||
height: errorContainer.height + emailField.height + passwordField.height + 5.5 * hifi.dimensions.contentSpacing.y +
|
||||
keepMeLoggedInCheckbox.height + loginButton.height + cantAccessTextMetrics.height + continueButton.height + steamInfoTextMetrics.height
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: root.bannerHeight + 0.25 * parent.height
|
||||
left: parent.left
|
||||
leftMargin: (parent.width - emailField.width) / 2
|
||||
}
|
||||
|
||||
ShortcutText {
|
||||
id: mainTextContainer
|
||||
anchors {
|
||||
top: flavorText.bottom
|
||||
left: parent.left
|
||||
margins: 0
|
||||
topMargin: 1.5 * hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
|
||||
visible: false
|
||||
text: qsTr("Username or password incorrect.")
|
||||
height: flavorText.height - 20
|
||||
wrapMode: Text.WordWrap
|
||||
color: hifi.colors.redAccent
|
||||
lineHeight: 1
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
Column {
|
||||
id: form
|
||||
width: parent.width
|
||||
onHeightChanged: d.resize();
|
||||
|
||||
anchors {
|
||||
top: mainTextContainer.bottom
|
||||
topMargin: 1.5 * hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
spacing: 2 * hifi.dimensions.contentSpacing.y
|
||||
|
||||
TextField {
|
||||
id: usernameField
|
||||
text: Settings.getValue("keepMeLoggedIn/savedUsername", "");
|
||||
width: parent.width
|
||||
focus: true
|
||||
placeholderText: "Username or Email"
|
||||
activeFocusOnPress: true
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
ShortcutText {
|
||||
z: 10
|
||||
y: usernameField.height
|
||||
Item {
|
||||
id: errorContainer
|
||||
width: loginErrorMessageTextMetrics.width
|
||||
height: loginErrorMessageTextMetrics.height
|
||||
anchors {
|
||||
right: usernameField.right
|
||||
top: usernameField.bottom
|
||||
topMargin: 4
|
||||
bottom: emailField.top;
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y;
|
||||
left: emailField.left;
|
||||
}
|
||||
TextMetrics {
|
||||
id: loginErrorMessageTextMetrics
|
||||
font: loginErrorMessage.font
|
||||
text: loginErrorMessage.text
|
||||
}
|
||||
Text {
|
||||
id: loginErrorMessage;
|
||||
color: "red";
|
||||
font.family: linkAccountBody.fontFamily
|
||||
font.pixelSize: linkAccountBody.textFieldFontSize
|
||||
font.bold: linkAccountBody.fontBold
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: ""
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.TextField {
|
||||
id: emailField
|
||||
width: root.bannerWidth
|
||||
height: linkAccountBody.textFieldHeight
|
||||
font.pixelSize: linkAccountBody.textFieldFontSize
|
||||
styleRenderType: Text.QtRendering
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: errorContainer.height
|
||||
}
|
||||
placeholderText: "Username or Email"
|
||||
activeFocusOnPress: true
|
||||
Keys.onPressed: {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Tab:
|
||||
event.accepted = true;
|
||||
passwordField.focus = true;
|
||||
break;
|
||||
case Qt.Key_Backtab:
|
||||
event.accepted = true;
|
||||
passwordField.focus = true;
|
||||
break;
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true;
|
||||
if (keepMeLoggedInCheckbox.checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", emailField.text);
|
||||
}
|
||||
linkAccountBody.login();
|
||||
break;
|
||||
}
|
||||
}
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
if (focus) {
|
||||
root.isPassword = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
HifiControlsUit.TextField {
|
||||
id: passwordField
|
||||
width: root.bannerWidth
|
||||
height: linkAccountBody.textFieldHeight
|
||||
font.pixelSize: linkAccountBody.textFieldFontSize
|
||||
styleRenderType: Text.QtRendering
|
||||
placeholderText: "Password"
|
||||
activeFocusOnPress: true
|
||||
echoMode: passwordFieldMouseArea.showPassword ? TextInput.Normal : TextInput.Password
|
||||
anchors {
|
||||
top: emailField.bottom
|
||||
topMargin: 1.5 * hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
|
||||
text: "<a href='https://highfidelity.com/users/password/new'>Forgot Username?</a>"
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
linkColor: hifi.colors.blueAccent
|
||||
|
||||
onLinkActivated: loginDialog.openUrl(link)
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
}
|
||||
Component.onCompleted: {
|
||||
var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", "");
|
||||
usernameField.text = savedUsername === "Unknown user" ? "" : savedUsername;
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: passwordField
|
||||
width: parent.width
|
||||
placeholderText: "Password"
|
||||
activeFocusOnPress: true
|
||||
echoMode: passwordFieldMouseArea.showPassword ? TextInput.Normal : TextInput.Password
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
ShortcutText {
|
||||
id: forgotPasswordShortcut
|
||||
y: passwordField.height
|
||||
z: 10
|
||||
anchors {
|
||||
right: passwordField.right
|
||||
top: passwordField.bottom
|
||||
topMargin: 4
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
root.isPassword = focus;
|
||||
}
|
||||
|
||||
text: "<a href='https://highfidelity.com/users/password/new'>Forgot Password?</a>"
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
linkColor: hifi.colors.blueAccent
|
||||
|
||||
onLinkActivated: loginDialog.openUrl(link)
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
root.isPassword = true;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: showPasswordHitbox
|
||||
z: 10
|
||||
x: passwordField.width - ((passwordField.height) * 31 / 23)
|
||||
width: parent.width - (parent.width - (parent.height * 31/16))
|
||||
height: parent.height
|
||||
anchors {
|
||||
right: parent.right
|
||||
}
|
||||
color: "transparent"
|
||||
|
||||
Image {
|
||||
id: showPasswordImage
|
||||
width: passwordField.height * 16 / 23
|
||||
height: passwordField.height * 16 / 23
|
||||
Item {
|
||||
id: showPasswordContainer
|
||||
z: 10
|
||||
// width + image's rightMargin
|
||||
width: showPasswordImage.width + 8
|
||||
height: parent.height
|
||||
anchors {
|
||||
right: parent.right
|
||||
rightMargin: 8
|
||||
top: parent.top
|
||||
topMargin: passwordFieldMouseArea.showPassword ? 6 : 8
|
||||
bottom: parent.bottom
|
||||
bottomMargin: passwordFieldMouseArea.showPassword ? 5 : 8
|
||||
}
|
||||
source: passwordFieldMouseArea.showPassword ? "../../images/eyeClosed.svg" : "../../images/eyeOpen.svg"
|
||||
MouseArea {
|
||||
id: passwordFieldMouseArea
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton
|
||||
property bool showPassword: false
|
||||
onClicked: {
|
||||
showPassword = !showPassword;
|
||||
|
||||
Image {
|
||||
id: showPasswordImage
|
||||
width: passwordField.height * passwordImageRatio
|
||||
height: passwordField.height * passwordImageRatio
|
||||
anchors {
|
||||
right: parent.right
|
||||
rightMargin: 8
|
||||
top: parent.top
|
||||
topMargin: passwordFieldMouseArea.showPassword ? 6 : 8
|
||||
bottom: parent.bottom
|
||||
bottomMargin: passwordFieldMouseArea.showPassword ? 5 : 8
|
||||
}
|
||||
source: passwordFieldMouseArea.showPassword ? "../../images/eyeClosed.svg" : "../../images/eyeOpen.svg"
|
||||
MouseArea {
|
||||
id: passwordFieldMouseArea
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton
|
||||
property bool showPassword: false
|
||||
onClicked: {
|
||||
showPassword = !showPassword;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Tab:
|
||||
case Qt.Key_Backtab:
|
||||
event.accepted = true;
|
||||
emailField.focus = true;
|
||||
break;
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true;
|
||||
if (keepMeLoggedInCheckbox.checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", emailField.text);
|
||||
}
|
||||
linkAccountBody.login();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
linkAccountBody.login();
|
||||
}
|
||||
}
|
||||
|
||||
InfoItem {
|
||||
id: additionalInformation
|
||||
|
||||
visible: loginDialog.isSteamRunning()
|
||||
|
||||
text: qsTr("Your steam account informations will not be exposed to other users.")
|
||||
wrapMode: Text.WordWrap
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
lineHeight: 1
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
Row {
|
||||
id: buttons
|
||||
spacing: hifi.dimensions.contentSpacing.y*2
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
CheckBox {
|
||||
id: autoLogoutCheckbox
|
||||
checked: Settings.getValue("keepMeLoggedIn", false)
|
||||
text: "Keep me logged in"
|
||||
boxSize: 20;
|
||||
labelFontSize: 15
|
||||
color: hifi.colors.black
|
||||
HifiControlsUit.CheckBox {
|
||||
id: keepMeLoggedInCheckbox
|
||||
checked: Settings.getValue("keepMeLoggedIn", false);
|
||||
text: qsTr("Keep Me Logged In");
|
||||
boxSize: 18;
|
||||
labelFontFamily: linkAccountBody.fontFamily
|
||||
labelFontSize: 18;
|
||||
color: hifi.colors.white;
|
||||
anchors {
|
||||
top: passwordField.bottom;
|
||||
topMargin: hifi.dimensions.contentSpacing.y;
|
||||
left: passwordField.left;
|
||||
}
|
||||
onCheckedChanged: {
|
||||
Settings.setValue("keepMeLoggedIn", checked);
|
||||
if (checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
if (keepMeLoggedInCheckbox.checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", emailField.text);
|
||||
} else {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", "");
|
||||
}
|
||||
}
|
||||
Component.onDestruction: {
|
||||
Settings.setValue("keepMeLoggedIn", checked);
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
id: cancelButton
|
||||
width: (passwordField.width - hifi.dimensions.contentSpacing.x) / 2;
|
||||
height: d.minHeightButton
|
||||
text: qsTr("Cancel")
|
||||
fontFamily: linkAccountBody.fontFamily
|
||||
fontSize: linkAccountBody.fontSize
|
||||
fontBold: linkAccountBody.fontBold
|
||||
color: hifi.buttons.noneBorderlessWhite;
|
||||
visible: linkAccountBody.linkSteam
|
||||
anchors {
|
||||
top: keepMeLoggedInCheckbox.bottom
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
onClicked: {
|
||||
bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": linkAccountBody.withSteam, "errorString": "" });
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: linkAccountButton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 200
|
||||
|
||||
text: qsTr(loginDialog.isSteamRunning() ? "Link Account" : "Log in")
|
||||
color: hifi.buttons.blue
|
||||
|
||||
HifiControlsUit.Button {
|
||||
id: loginButton
|
||||
width: passwordField.width
|
||||
height: d.minHeightButton
|
||||
text: qsTr("Log In")
|
||||
fontFamily: linkAccountBody.fontFamily
|
||||
fontSize: linkAccountBody.fontSize
|
||||
fontBold: linkAccountBody.fontBold
|
||||
anchors {
|
||||
top: keepMeLoggedInCheckbox.bottom
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
onClicked: {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
linkAccountBody.login();
|
||||
linkAccountBody.login()
|
||||
}
|
||||
}
|
||||
TextMetrics {
|
||||
id: steamInfoTextMetrics
|
||||
font: steamInfoText.font
|
||||
text: steamInfoText.text
|
||||
}
|
||||
Text {
|
||||
id: steamInfoText
|
||||
width: root.bannerWidth
|
||||
visible: linkAccountBody.linkSteam
|
||||
anchors {
|
||||
top: loginButton.bottom
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
left: emailField.left
|
||||
}
|
||||
|
||||
font.family: linkAccountBody.fontFamily
|
||||
font.pixelSize: linkAccountBody.textFieldFontSize
|
||||
color: "white"
|
||||
text: qsTr("Your Steam account information will not be exposed to others.");
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Component.onCompleted: {
|
||||
if (steamInfoTextMetrics.width > root.bannerWidth) {
|
||||
steamInfoText.wrapMode = Text.WordWrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
TextMetrics {
|
||||
id: cantAccessTextMetrics
|
||||
font: cantAccessText.font
|
||||
text: "Can't access your account?"
|
||||
}
|
||||
HifiStylesUit.ShortcutText {
|
||||
id: cantAccessText
|
||||
z: 10
|
||||
visible: !linkAccountBody.linkSteam
|
||||
anchors {
|
||||
top: loginButton.bottom
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
left: emailField.left
|
||||
}
|
||||
font.family: linkAccountBody.fontFamily
|
||||
font.pixelSize: linkAccountBody.textFieldFontSize
|
||||
font.bold: linkAccountBody.fontBold
|
||||
|
||||
text: "<a href='https://highfidelity.com/users/password/new'> Can't access your account?</a>"
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
linkColor: hifi.colors.blueAccent
|
||||
onLinkActivated: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
loginDialog.openUrl(link);
|
||||
lightboxPopup.titleText = "Can't Access Account";
|
||||
lightboxPopup.bodyText = lightboxPopup.cantAccessBodyText;
|
||||
lightboxPopup.button2text = "CLOSE";
|
||||
lightboxPopup.button2method = function() {
|
||||
lightboxPopup.visible = false;
|
||||
}
|
||||
lightboxPopup.visible = true;
|
||||
// bodyLoader.setSource("CantAccessBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader });
|
||||
}
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
id: continueButton;
|
||||
width: emailField.width;
|
||||
height: d.minHeightButton
|
||||
color: hifi.buttons.none;
|
||||
anchors {
|
||||
top: cantAccessText.bottom
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
left: emailField.left
|
||||
}
|
||||
text: qsTr("CONTINUE WITH STEAM")
|
||||
fontFamily: linkAccountBody.fontFamily
|
||||
fontSize: linkAccountBody.fontSize
|
||||
fontBold: linkAccountBody.fontBold
|
||||
buttonGlyph: hifi.glyphs.steamSquare
|
||||
buttonGlyphSize: 24
|
||||
buttonGlyphRightMargin: 10
|
||||
onClicked: {
|
||||
// if (loginDialog.isOculusStoreRunning()) {
|
||||
// linkAccountBody.withOculus = true;
|
||||
// loginDialog.loginThroughSteam();
|
||||
// } else
|
||||
if (loginDialog.isSteamRunning()) {
|
||||
linkAccountBody.withSteam = true;
|
||||
loginDialog.loginThroughSteam();
|
||||
}
|
||||
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader,
|
||||
"withSteam": linkAccountBody.withSteam, "withOculus": linkAccountBody.withOculus, "linkSteam": linkAccountBody.linkSteam });
|
||||
}
|
||||
Component.onCompleted: {
|
||||
if (linkAccountBody.linkSteam) {
|
||||
continueButton.visible = false;
|
||||
return;
|
||||
}
|
||||
// if (loginDialog.isOculusStoreRunning()) {
|
||||
// continueButton.text = qsTr("CONTINUE WITH OCULUS");
|
||||
// continueButton.buttonGlyph = hifi.glyphs.oculus;
|
||||
// } else
|
||||
if (loginDialog.isSteamRunning()) {
|
||||
continueButton.text = qsTr("CONTINUE WITH STEAM");
|
||||
continueButton.buttonGlyph = hifi.glyphs.steamSquare;
|
||||
} else {
|
||||
continueButton.visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: leftButton
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: hifi.dimensions.contentSpacing.y*2
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
RalewaySemiBold {
|
||||
size: hifi.fontSizes.inputLabel
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: qsTr("New to High Fidelity?")
|
||||
Item {
|
||||
id: signUpContainer
|
||||
width: loginContainer.width
|
||||
height: signUpTextMetrics.height
|
||||
visible: !linkAccountBody.linkSteam
|
||||
anchors {
|
||||
left: loginContainer.left
|
||||
top: loginContainer.bottom
|
||||
topMargin: 0.15 * parent.height
|
||||
}
|
||||
TextMetrics {
|
||||
id: signUpTextMetrics
|
||||
font: signUpText.font
|
||||
text: signUpText.text
|
||||
}
|
||||
Text {
|
||||
id: signUpText
|
||||
text: qsTr("Don't have an account?")
|
||||
anchors {
|
||||
left: parent.left
|
||||
}
|
||||
lineHeight: 1
|
||||
color: "white"
|
||||
font.family: linkAccountBody.fontFamily
|
||||
font.pixelSize: linkAccountBody.textFieldFontSize
|
||||
font.bold: linkAccountBody.fontBold
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
Button {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
text: qsTr("Sign Up")
|
||||
visible: !loginDialog.isSteamRunning()
|
||||
|
||||
onClicked: {
|
||||
bodyLoader.setSource("SignUpBody.qml")
|
||||
if (!root.isTablet) {
|
||||
bodyLoader.item.width = root.pane.width
|
||||
bodyLoader.item.height = root.pane.height
|
||||
}
|
||||
HifiStylesUit.ShortcutText {
|
||||
id: signUpShortcutText
|
||||
z: 10
|
||||
font.family: linkAccountBody.fontFamily
|
||||
font.pixelSize: linkAccountBody.textFieldFontSize
|
||||
font.bold: linkAccountBody.fontBold
|
||||
anchors {
|
||||
left: signUpText.right
|
||||
leftMargin: hifi.dimensions.contentSpacing.x
|
||||
}
|
||||
|
||||
text: "<a href='https://highfidelity.com'>Sign Up</a>"
|
||||
|
||||
linkColor: hifi.colors.blueAccent
|
||||
onLinkActivated: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
bodyLoader.setSource("SignUpBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader,
|
||||
"errorString": "", "linkSteam": linkAccountBody.linkSteam });
|
||||
}
|
||||
}
|
||||
}
|
||||
TextMetrics {
|
||||
id: dismissButtonTextMetrics
|
||||
font: loginErrorMessage.font
|
||||
text: dismissButton.text
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
id: dismissButton
|
||||
width: dismissButtonTextMetrics.width
|
||||
height: d.minHeightButton
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
margins: 3 * hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
color: hifi.buttons.noneBorderlessWhite
|
||||
text: qsTr("No thanks, take me in-world! >")
|
||||
fontCapitalization: Font.MixedCase
|
||||
fontFamily: linkAccountBody.fontFamily
|
||||
fontSize: linkAccountBody.fontSize
|
||||
fontBold: linkAccountBody.fontBold
|
||||
visible: loginDialog.getLoginDialogPoppedUp() && !linkAccountBody.linkSteam;
|
||||
onClicked: {
|
||||
if (loginDialog.getLoginDialogPoppedUp()) {
|
||||
console.log("[ENCOURAGELOGINDIALOG]: user dismissed login screen")
|
||||
var data = {
|
||||
"action": "user dismissed login screen"
|
||||
};
|
||||
UserActivityLogger.logAction("encourageLoginDialog", data);
|
||||
loginDialog.dismissLoginDialog();
|
||||
}
|
||||
root.tryDestroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: loginDialog
|
||||
onFocusEnabled: {
|
||||
if (!linkAccountBody.lostFocus) {
|
||||
Qt.callLater(function() {
|
||||
emailField.forceActiveFocus();
|
||||
});
|
||||
}
|
||||
}
|
||||
onFocusDisabled: {
|
||||
linkAccountBody.lostFocus = !root.isTablet && !root.isOverlay;
|
||||
if (linkAccountBody.lostFocus) {
|
||||
Qt.callLater(function() {
|
||||
emailField.focus = false;
|
||||
passwordField.focus = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
root.title = qsTr("Sign Into High Fidelity")
|
||||
root.iconText = "<"
|
||||
|
||||
//dont rise local keyboard
|
||||
keyboardEnabled = !root.isTablet && HMD.active;
|
||||
//but rise Tablet's one instead for Tablet interface
|
||||
if (root.isTablet) {
|
||||
root.keyboardEnabled = HMD.active;
|
||||
root.keyboardRaised = Qt.binding( function() { return keyboardRaised; })
|
||||
}
|
||||
root.keyboardEnabled = HMD.active;
|
||||
root.keyboardRaised = Qt.binding( function() { return keyboardRaised; })
|
||||
root.text = "";
|
||||
d.resize();
|
||||
|
||||
if (failAfterSignUp) {
|
||||
mainTextContainer.text = "Account created successfully."
|
||||
flavorText.visible = true
|
||||
mainTextContainer.visible = true
|
||||
}
|
||||
|
||||
usernameField.forceActiveFocus();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: loginDialog
|
||||
onHandleLoginCompleted: {
|
||||
console.log("Login Succeeded, linking steam account")
|
||||
var poppedUp = Settings.getValue("loginDialogPoppedUp", false);
|
||||
if (poppedUp) {
|
||||
console.log("[ENCOURAGELOGINDIALOG]: logging in")
|
||||
var data = {
|
||||
"action": "user logged in"
|
||||
};
|
||||
UserActivityLogger.logAction("encourageLoginDialog", data);
|
||||
Settings.setValue("loginDialogPoppedUp", false);
|
||||
}
|
||||
if (loginDialog.isSteamRunning()) {
|
||||
loginDialog.linkSteam()
|
||||
} else {
|
||||
bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : true })
|
||||
bodyLoader.item.width = root.pane.width
|
||||
bodyLoader.item.height = root.pane.height
|
||||
}
|
||||
}
|
||||
onHandleLoginFailed: {
|
||||
console.log("Login Failed")
|
||||
var poppedUp = Settings.getValue("loginDialogPoppedUp", false);
|
||||
if (poppedUp) {
|
||||
console.log("[ENCOURAGELOGINDIALOG]: failed logging in")
|
||||
var data = {
|
||||
"action": "user failed logging in"
|
||||
};
|
||||
UserActivityLogger.logAction("encourageLoginDialog", data);
|
||||
Settings.setValue("loginDialogPoppedUp", false);
|
||||
}
|
||||
flavorText.visible = true
|
||||
mainTextContainer.visible = true
|
||||
toggleLoading(false)
|
||||
}
|
||||
onHandleLinkCompleted: {
|
||||
console.log("Link Succeeded")
|
||||
|
||||
bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : true })
|
||||
bodyLoader.item.width = root.pane.width
|
||||
bodyLoader.item.height = root.pane.height
|
||||
}
|
||||
onHandleLinkFailed: {
|
||||
console.log("Link Failed")
|
||||
toggleLoading(false)
|
||||
}
|
||||
init();
|
||||
Qt.callLater(function() {
|
||||
emailField.forceActiveFocus();
|
||||
});
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (!visible) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.key) {
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
linkAccountBody.login()
|
||||
break
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true;
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", emailField.text);
|
||||
linkAccountBody.login();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
272
interface/resources/qml/LoginDialog/LoggingInBody.qml
Normal file
|
@ -0,0 +1,272 @@
|
|||
//
|
||||
// LoggingInBody.qml
|
||||
//
|
||||
// Created by Wayne Chen on 10/18/18
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import Hifi 1.0
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4 as OriginalStyles
|
||||
|
||||
import controlsUit 1.0 as HifiControlsUit
|
||||
import stylesUit 1.0 as HifiStylesUit
|
||||
|
||||
Item {
|
||||
id: loggingInBody
|
||||
clip: true
|
||||
height: root.height
|
||||
width: root.width
|
||||
property int textFieldHeight: 31
|
||||
property int loggingInGlyphRightMargin: 10
|
||||
property string fontFamily: "Raleway"
|
||||
property int fontSize: 15
|
||||
property bool fontBold: true
|
||||
property bool withSteam: withSteam
|
||||
property bool withOculus: withOculus
|
||||
property bool linkSteam: linkSteam
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property int minWidth: 480
|
||||
readonly property int minWidthButton: !root.isTablet ? 256 : 174
|
||||
property int maxWidth: root.width
|
||||
readonly property int minHeight: 120
|
||||
readonly property int minHeightButton: 36
|
||||
property int maxHeight: root.height
|
||||
|
||||
function resize() {
|
||||
maxWidth = root.width;
|
||||
maxHeight = root.height;
|
||||
var targetWidth = Math.max(titleWidth, mainContainer.width);
|
||||
var targetHeight = hifi.dimensions.contentSpacing.y + mainContainer.height +
|
||||
4 * hifi.dimensions.contentSpacing.y;
|
||||
|
||||
var newWidth = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth));
|
||||
if (!isNaN(newWidth)) {
|
||||
parent.width = root.width = newWidth;
|
||||
}
|
||||
|
||||
parent.height = root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) + hifi.dimensions.contentSpacing.y;
|
||||
}
|
||||
}
|
||||
|
||||
// timer to kill the dialog upon login success
|
||||
Timer {
|
||||
id: successTimer
|
||||
interval: 1000;
|
||||
running: false;
|
||||
repeat: false;
|
||||
onTriggered: {
|
||||
if (loginDialog.getLoginDialogPoppedUp()) {
|
||||
loginDialog.dismissLoginDialog();
|
||||
}
|
||||
root.tryDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
// For the process of logging in.
|
||||
loggingInText.wrapMode = Text.NoWrap;
|
||||
|
||||
if (loggingInBody.linkSteam) {
|
||||
loggingInGlyph.visible = true;
|
||||
loggingInText.text = "Linking to Steam";
|
||||
loggingInText.x = loggingInHeader.width/2 - loggingInTextMetrics.width/2 + loggingInGlyphTextMetrics.width/2;
|
||||
loginDialog.linkSteam();
|
||||
} else if (loggingInBody.withSteam) {
|
||||
loggingInGlyph.visible = true;
|
||||
loggingInText.text = "Logging in to Steam";
|
||||
loggingInText.x = loggingInHeader.width/2 - loggingInTextMetrics.width/2 + loggingInGlyphTextMetrics.width/2;
|
||||
} else if (loggingInBody.withOculus) {
|
||||
loggingInGlyph.text = hifi.glyphs.oculus;
|
||||
loggingInGlyph.visible = true;
|
||||
loggingInText.text = "Logging in to Oculus";
|
||||
loggingInText.x = loggingInHeader.width/2 - loggingInTextMetrics.width/2 + loggingInGlyphTextMetrics.width/2;
|
||||
} else {
|
||||
loggingInText.text = "Logging in";
|
||||
loggingInText.anchors.centerIn = loggingInHeader;
|
||||
}
|
||||
loggingInSpinner.visible = true;
|
||||
}
|
||||
function loadingSuccess() {
|
||||
loggingInSpinner.visible = false;
|
||||
if (loggingInBody.linkSteam) {
|
||||
loggingInText.text = "Linking to Steam";
|
||||
loginDialog.linkSteam();
|
||||
return;
|
||||
}
|
||||
if (loggingInBody.withSteam) {
|
||||
// reset the flag.
|
||||
loggingInGlyph.visible = false;
|
||||
loggingInText.text = "You are now logged into Steam!";
|
||||
loggingInText.x = 0;
|
||||
loggingInText.anchors.centerIn = loggingInHeader;
|
||||
loggedInGlyph.visible = true;
|
||||
} else if (loggingInBody.withOculus) {
|
||||
// reset the flag.
|
||||
loggingInGlyph.visible = false;
|
||||
loggingInText.text = "You are now logged into Oculus!";
|
||||
loggingInText.x = 0;
|
||||
loggingInText.anchors.centerIn = loggingInHeader;
|
||||
loggedInGlyph.text = hifi.glyphs.oculus;
|
||||
loggedInGlyph.visible = true;
|
||||
} else {
|
||||
loggingInText.text = "You are now logged in!";
|
||||
}
|
||||
successTimer.start();
|
||||
}
|
||||
|
||||
Item {
|
||||
id: mainContainer
|
||||
anchors.fill: parent
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
Item {
|
||||
id: loggingInContainer
|
||||
anchors.fill: parent
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
Item {
|
||||
id: loggingInHeader
|
||||
width: parent.width
|
||||
height: loggingInGlyph.height
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: 0.4 * parent.height
|
||||
left: parent.left
|
||||
}
|
||||
TextMetrics {
|
||||
id: loggingInGlyphTextMetrics;
|
||||
font: loggingInGlyph.font;
|
||||
text: loggingInGlyph.text;
|
||||
}
|
||||
HifiStylesUit.HiFiGlyphs {
|
||||
id: loggingInGlyph;
|
||||
text: hifi.glyphs.steamSquare;
|
||||
// Color
|
||||
color: "white";
|
||||
// Size
|
||||
size: 36;
|
||||
// Anchors
|
||||
anchors.right: loggingInText.left;
|
||||
anchors.rightMargin: loggingInBody.loggingInGlyphRightMargin
|
||||
anchors.bottom: parent.bottom;
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
visible: loggingInBody.withSteam || loggingInBody.withOculus;
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: loggingInTextMetrics;
|
||||
font: loggingInText.font;
|
||||
text: loggingInText.text;
|
||||
}
|
||||
Text {
|
||||
id: loggingInText;
|
||||
width: loggingInTextMetrics.width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: "white";
|
||||
font.family: loggingInBody.fontFamily
|
||||
font.pixelSize: 24
|
||||
font.bold: loggingInBody.fontBold
|
||||
wrapMode: Text.NoWrap
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: "Logging in"
|
||||
}
|
||||
}
|
||||
Item {
|
||||
id: loggingInFooter
|
||||
width: parent.width
|
||||
height: 0.5 * parent.height
|
||||
anchors {
|
||||
top: loggingInHeader.bottom
|
||||
topMargin: 2 * hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
AnimatedImage {
|
||||
id: loggingInSpinner
|
||||
source: "images/loader-snake-256.gif"
|
||||
width: 64
|
||||
height: width
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: (parent.width - width) / 2;
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
TextMetrics {
|
||||
id: loggedInGlyphTextMetrics;
|
||||
font: loggedInGlyph.font;
|
||||
text: loggedInGlyph.text;
|
||||
}
|
||||
HifiStylesUit.HiFiGlyphs {
|
||||
id: loggedInGlyph;
|
||||
text: hifi.glyphs.steamSquare;
|
||||
// color
|
||||
color: "white"
|
||||
// Size
|
||||
size: 78;
|
||||
// Anchors
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: (parent.width - loggedInGlyph.size) / 2;
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: hifi.dimensions.contentSpacing.y
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
visible: false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
d.resize();
|
||||
loggingInBody.init();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: loginDialog
|
||||
onHandleLinkCompleted: {
|
||||
console.log("Link Succeeded");
|
||||
loggingInBody.linkSteam = false;
|
||||
loggingInBody.loadingSuccess();
|
||||
}
|
||||
onHandleLinkFailed: {
|
||||
console.log("Link Failed: " + error);
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": true, "errorString": error });
|
||||
}
|
||||
|
||||
onHandleLoginCompleted: {
|
||||
console.log("Login Succeeded");
|
||||
loggingInBody.loadingSuccess();
|
||||
}
|
||||
|
||||
onHandleLoginFailed: {
|
||||
console.log("Login Failed")
|
||||
loggingInSpinner.visible = false;
|
||||
var errorString = "";
|
||||
if (loggingInBody.linkSteam && loggingInBody.withSteam) {
|
||||
errorString = "Username or password is incorrect.";
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": loggingInBody.withSteam, "linkSteam": loggingInBody.linkSteam, "errorString": errorString });
|
||||
} else if (loggingInBody.withSteam) {
|
||||
loggingInGlyph.visible = false;
|
||||
errorString = "Your Steam authentication has failed. Please make sure you are logged into Steam and try again.";
|
||||
bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": loggingInBody.withSteam, "errorString": errorString });
|
||||
} else if (loggingInBody.withOculus) {
|
||||
loggingInGlyph.visible = false;
|
||||
errorString = "Your Oculus authentication has failed. Please make sure you are logged into Oculus and try again."
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": errorString });
|
||||
}
|
||||
else {
|
||||
errorString = "Username or password is incorrect.";
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": errorString });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
170
interface/resources/qml/LoginDialog/LoginDialogLightbox.qml
Normal file
|
@ -0,0 +1,170 @@
|
|||
//
|
||||
// LoginDialogLightbox.qml
|
||||
// qml/LoginDialog
|
||||
//
|
||||
// LoginDialogLightbox
|
||||
//
|
||||
// Created by Wayne Chen on 2018-12-07
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import Hifi 1.0 as Hifi
|
||||
import QtQuick 2.5
|
||||
import QtGraphicalEffects 1.0
|
||||
import stylesUit 1.0
|
||||
import controlsUit 1.0 as HifiControlsUit
|
||||
import "qrc:////qml//controls" as HifiControls
|
||||
|
||||
// references XXX from root context
|
||||
|
||||
Rectangle {
|
||||
property string titleText;
|
||||
property string bodyImageSource;
|
||||
property string bodyText;
|
||||
property string button1color: hifi.buttons.noneBorderlessGray;
|
||||
property string button1text;
|
||||
property var button1method;
|
||||
property string button2color: hifi.buttons.blue;
|
||||
property string button2text;
|
||||
property var button2method;
|
||||
property string buttonLayout: "leftright";
|
||||
|
||||
readonly property string cantAccessBodyText: "Please navigate to your default browser to recover your account." +
|
||||
"<br><br>If you are in a VR headset, please take it off.";
|
||||
|
||||
id: root;
|
||||
visible: false;
|
||||
anchors.fill: parent;
|
||||
color: Qt.rgba(0, 0, 0, 0.5);
|
||||
z: 999;
|
||||
|
||||
HifiConstants { id: hifi; }
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
resetLightbox();
|
||||
}
|
||||
}
|
||||
|
||||
// This object is always used in a popup.
|
||||
// This MouseArea is used to prevent a user from being
|
||||
// able to click on a button/mouseArea underneath the popup.
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
propagateComposedEvents: false;
|
||||
hoverEnabled: true;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.centerIn: parent;
|
||||
width: 376;
|
||||
height: childrenRect.height + 30;
|
||||
color: "white";
|
||||
|
||||
RalewaySemiBold {
|
||||
id: titleText;
|
||||
text: root.titleText;
|
||||
anchors.top: parent.top;
|
||||
anchors.topMargin: 30;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 30;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 30;
|
||||
height: paintedHeight;
|
||||
color: hifi.colors.black;
|
||||
size: 24;
|
||||
verticalAlignment: Text.AlignTop;
|
||||
wrapMode: Text.WordWrap;
|
||||
}
|
||||
|
||||
RalewayRegular {
|
||||
id: bodyText;
|
||||
text: root.bodyText;
|
||||
anchors.top: root.bodyImageSource ? bodyImage.bottom : (root.titleText ? titleText.bottom : parent.top);
|
||||
anchors.topMargin: root.bodyImageSource ? 20 : (root.titleText ? 20 : 30);
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 30;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 30;
|
||||
height: paintedHeight;
|
||||
color: hifi.colors.black;
|
||||
size: 20;
|
||||
verticalAlignment: Text.AlignTop;
|
||||
wrapMode: Text.WordWrap;
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
id: buttons;
|
||||
anchors.top: bodyText.bottom;
|
||||
anchors.topMargin: 30;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
height: root.buttonLayout === "leftright" ? 70 : 150;
|
||||
|
||||
// Button 1
|
||||
HifiControlsUit.Button {
|
||||
id: button1;
|
||||
color: root.button1color;
|
||||
colorScheme: hifi.colorSchemes.light;
|
||||
anchors.top: root.buttonLayout === "leftright" ? parent.top : parent.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: root.buttonLayout === "leftright" ? 30 : 10;
|
||||
anchors.right: root.buttonLayout === "leftright" ? undefined : parent.right;
|
||||
anchors.rightMargin: root.buttonLayout === "leftright" ? undefined : 10;
|
||||
width: root.buttonLayout === "leftright" ? (root.button2text ? parent.width/2 - anchors.leftMargin*2 : parent.width - anchors.leftMargin * 2) :
|
||||
(undefined);
|
||||
height: 40;
|
||||
text: root.button1text;
|
||||
onClicked: {
|
||||
button1method();
|
||||
}
|
||||
visible: (root.button1text !== "");
|
||||
}
|
||||
|
||||
// Button 2
|
||||
HifiControlsUit.Button {
|
||||
id: button2;
|
||||
visible: root.button2text;
|
||||
color: root.button2color;
|
||||
colorScheme: hifi.colorSchemes.light;
|
||||
anchors.top: root.buttonLayout === "leftright" ? parent.top : button1.bottom;
|
||||
anchors.topMargin: root.buttonLayout === "leftright" ? undefined : 20;
|
||||
anchors.left: root.buttonLayout === "leftright" ? undefined : parent.left;
|
||||
anchors.leftMargin: root.buttonLayout === "leftright" ? undefined : 10;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: root.buttonLayout === "leftright" ? 30 : 10;
|
||||
width: root.buttonLayout === "leftright" ? parent.width/2 - anchors.rightMargin*2 : undefined;
|
||||
height: 40;
|
||||
text: root.button2text;
|
||||
onClicked: {
|
||||
button2method();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// FUNCTION DEFINITIONS START
|
||||
//
|
||||
signal sendToParent(var msg);
|
||||
|
||||
function resetLightbox() {
|
||||
root.titleText = "";
|
||||
root.bodyImageSource = "";
|
||||
root.bodyText = "";
|
||||
root.button1color = hifi.buttons.noneBorderlessGray;
|
||||
root.button1text = "";
|
||||
root.button1method = function() {};
|
||||
root.button2color = hifi.buttons.blue;
|
||||
root.button2text = "";
|
||||
root.button2method = function() {};
|
||||
root.buttonLayout = "leftright";
|
||||
}
|
||||
//
|
||||
// FUNCTION DEFINITIONS END
|
||||
//
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
//
|
||||
// SignInBody.qml
|
||||
//
|
||||
// Created by Clement on 7/18/16
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import Hifi 1.0
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls.Styles 1.4 as OriginalStyles
|
||||
|
||||
import controlsUit 1.0
|
||||
import stylesUit 1.0
|
||||
|
||||
Item {
|
||||
id: signInBody
|
||||
clip: true
|
||||
height: root.pane.height
|
||||
width: root.pane.width
|
||||
|
||||
property bool required: false
|
||||
|
||||
function login() {
|
||||
console.log("Trying to log in")
|
||||
loginDialog.loginThroughSteam()
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
root.tryDestroy()
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property int minWidth: 480
|
||||
readonly property int maxWidth: 1280
|
||||
readonly property int minHeight: 120
|
||||
readonly property int maxHeight: 720
|
||||
|
||||
function resize() {
|
||||
var targetWidth = Math.max(titleWidth, mainTextContainer.contentWidth)
|
||||
var targetHeight = mainTextContainer.height + 3 * hifi.dimensions.contentSpacing.y + buttons.height
|
||||
|
||||
parent.width = root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth))
|
||||
parent.height = root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight))
|
||||
}
|
||||
}
|
||||
|
||||
InfoItem {
|
||||
id: mainTextContainer
|
||||
anchors {
|
||||
top: parent.top
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
margins: 0
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
|
||||
text: required ? qsTr("This domain's owner requires that you sign in:")
|
||||
: qsTr("Sign in to access your user account:")
|
||||
wrapMode: Text.WordWrap
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
lineHeight: 2
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
Row {
|
||||
id: buttons
|
||||
anchors {
|
||||
top: mainTextContainer.bottom
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
margins: 0
|
||||
topMargin: 2 * hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
Button {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
width: undefined // invalidate so that the image's size sets the width
|
||||
height: undefined // invalidate so that the image's size sets the height
|
||||
focus: true
|
||||
|
||||
background: Image {
|
||||
id: buttonImage
|
||||
source: "../../images/steam-sign-in.png"
|
||||
}
|
||||
onClicked: signInBody.login()
|
||||
}
|
||||
Button {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
text: qsTr("Cancel");
|
||||
|
||||
onClicked: signInBody.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
root.title = required ? qsTr("Sign In Required")
|
||||
: qsTr("Sign In")
|
||||
root.iconText = ""
|
||||
d.resize();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: loginDialog
|
||||
onHandleLoginCompleted: {
|
||||
console.log("Login Succeeded")
|
||||
|
||||
bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : true })
|
||||
bodyLoader.item.width = root.pane.width
|
||||
bodyLoader.item.height = root.pane.height
|
||||
}
|
||||
onHandleLoginFailed: {
|
||||
console.log("Login Failed")
|
||||
|
||||
bodyLoader.source = "CompleteProfileBody.qml"
|
||||
if (!root.isTablet) {
|
||||
bodyLoader.item.width = root.pane.width
|
||||
bodyLoader.item.height = root.pane.height
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,21 +11,24 @@
|
|||
import Hifi 1.0
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4 as OriginalStyles
|
||||
|
||||
import controlsUit 1.0
|
||||
import stylesUit 1.0
|
||||
import controlsUit 1.0 as HifiControlsUit
|
||||
import stylesUit 1.0 as HifiStylesUit
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Item {
|
||||
id: signupBody
|
||||
z: -2
|
||||
id: signUpBody
|
||||
clip: true
|
||||
height: root.pane.height
|
||||
width: root.pane.width
|
||||
|
||||
function signup() {
|
||||
mainTextContainer.visible = false
|
||||
toggleLoading(true)
|
||||
loginDialog.signup(emailField.text, usernameField.text, passwordField.text)
|
||||
}
|
||||
height: root.height
|
||||
width: root.width
|
||||
property int textFieldHeight: 31
|
||||
property string fontFamily: "Raleway"
|
||||
property int fontSize: 15
|
||||
property int textFieldFontSize: 18
|
||||
property bool fontBold: true
|
||||
readonly property var passwordImageRatio: 16 / 23
|
||||
|
||||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
|
@ -33,248 +36,413 @@ Item {
|
|||
|
||||
onKeyboardRaisedChanged: d.resize();
|
||||
|
||||
property string errorString: errorString
|
||||
property bool linkSteam: linkSteam
|
||||
property bool lostFocus: false
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property int minWidth: 480
|
||||
readonly property int maxWidth: 1280
|
||||
readonly property int minWidthButton: !root.isTablet ? 256 : 174
|
||||
property int maxWidth: root.width
|
||||
readonly property int minHeight: 120
|
||||
readonly property int maxHeight: 720
|
||||
readonly property int minHeightButton: 36
|
||||
property int maxHeight: root.height
|
||||
|
||||
function resize() {
|
||||
var targetWidth = Math.max(titleWidth, form.contentWidth);
|
||||
var targetHeight = hifi.dimensions.contentSpacing.y + mainTextContainer.height +
|
||||
4 * hifi.dimensions.contentSpacing.y + form.height;
|
||||
maxWidth = root.width;
|
||||
maxHeight = root.height;
|
||||
var targetWidth = Math.max(titleWidth, mainContainer.width);
|
||||
var targetHeight = hifi.dimensions.contentSpacing.y + mainContainer.height +
|
||||
4 * hifi.dimensions.contentSpacing.y;
|
||||
|
||||
parent.width = root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth));
|
||||
parent.height = root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight))
|
||||
+ (keyboardEnabled && keyboardRaised ? (200 + 2 * hifi.dimensions.contentSpacing.y) : 0);
|
||||
var newWidth = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth));
|
||||
if (!isNaN(newWidth)) {
|
||||
parent.width = root.width = newWidth;
|
||||
}
|
||||
|
||||
parent.height = root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)) + hifi.dimensions.contentSpacing.y;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleLoading(isLoading) {
|
||||
linkAccountSpinner.visible = isLoading
|
||||
form.visible = !isLoading
|
||||
|
||||
leftButton.visible = !isLoading
|
||||
buttons.visible = !isLoading
|
||||
function signup() {
|
||||
loginDialog.signup(emailField.text, usernameField.text, passwordField.text);
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: linkAccountSpinner
|
||||
|
||||
anchors {
|
||||
top: parent.top
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
|
||||
visible: false
|
||||
running: true
|
||||
|
||||
width: 48
|
||||
height: 48
|
||||
function init() {
|
||||
// going to/from sign in/up dialog.
|
||||
loginDialog.isLogIn = false;
|
||||
emailField.placeholderText = "Email";
|
||||
emailField.text = "";
|
||||
emailField.anchors.top = usernameField.bottom;
|
||||
emailField.anchors.topMargin = 1.5 * hifi.dimensions.contentSpacing.y;
|
||||
passwordField.text = "";
|
||||
usernameField.forceActiveFocus();
|
||||
root.text = "";
|
||||
root.isPassword = false;
|
||||
loginContainer.visible = true;
|
||||
}
|
||||
|
||||
ShortcutText {
|
||||
id: mainTextContainer
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
margins: 0
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
|
||||
visible: false
|
||||
|
||||
text: qsTr("There was an unknown error while creating your account.")
|
||||
wrapMode: Text.WordWrap
|
||||
color: hifi.colors.redAccent
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
}
|
||||
|
||||
Column {
|
||||
id: form
|
||||
width: parent.width
|
||||
Item {
|
||||
id: mainContainer
|
||||
width: root.width
|
||||
height: root.height
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
anchors {
|
||||
top: mainTextContainer.bottom
|
||||
topMargin: 2 * hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
spacing: 2 * hifi.dimensions.contentSpacing.y
|
||||
|
||||
TextField {
|
||||
id: emailField
|
||||
width: parent.width
|
||||
label: "Email"
|
||||
activeFocusOnPress: true
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
Item {
|
||||
id: loginContainer
|
||||
width: usernameField.width
|
||||
height: parent.height
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: root.bannerHeight + 0.25 * parent.height
|
||||
left: parent.left
|
||||
leftMargin: (parent.width - usernameField.width) / 2
|
||||
}
|
||||
}
|
||||
visible: true
|
||||
|
||||
TextField {
|
||||
id: usernameField
|
||||
width: parent.width
|
||||
label: "Username"
|
||||
activeFocusOnPress: true
|
||||
|
||||
ShortcutText {
|
||||
Item {
|
||||
id: errorContainer
|
||||
width: parent.width
|
||||
height: loginErrorMessageTextMetrics.height
|
||||
anchors {
|
||||
verticalCenter: parent.textFieldLabel.verticalCenter
|
||||
left: parent.textFieldLabel.right
|
||||
leftMargin: 10
|
||||
bottom: usernameField.top;
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y;
|
||||
left: usernameField.left;
|
||||
}
|
||||
TextMetrics {
|
||||
id: loginErrorMessageTextMetrics
|
||||
font: loginErrorMessage.font
|
||||
text: loginErrorMessage.text
|
||||
}
|
||||
Text {
|
||||
id: loginErrorMessage;
|
||||
width: root.bannerWidth
|
||||
color: "red";
|
||||
font.family: signUpBody.fontFamily
|
||||
font.pixelSize: 18
|
||||
font.bold: signUpBody.fontBold
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: ""
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
|
||||
text: qsTr("No spaces / special chars.")
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
color: hifi.colors.blueAccent
|
||||
HifiControlsUit.TextField {
|
||||
id: usernameField
|
||||
width: root.bannerWidth
|
||||
height: signUpBody.textFieldHeight
|
||||
placeholderText: "Username"
|
||||
font.pixelSize: signUpBody.textFieldFontSize
|
||||
styleRenderType: Text.QtRendering
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: loginErrorMessage.height
|
||||
}
|
||||
Keys.onPressed: {
|
||||
if (!usernameField.visible) {
|
||||
return;
|
||||
}
|
||||
switch (event.key) {
|
||||
case Qt.Key_Tab:
|
||||
event.accepted = true;
|
||||
if (event.modifiers === Qt.ShiftModifier) {
|
||||
passwordField.focus = true;
|
||||
} else {
|
||||
emailField.focus = true;
|
||||
}
|
||||
break;
|
||||
case Qt.Key_Backtab:
|
||||
event.accepted = true;
|
||||
passwordField.focus = true;
|
||||
break;
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true;
|
||||
if (keepMeLoggedInCheckbox.checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
}
|
||||
signUpBody.signup();
|
||||
break;
|
||||
}
|
||||
}
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: passwordField
|
||||
width: parent.width
|
||||
label: "Password"
|
||||
echoMode: TextInput.Password
|
||||
activeFocusOnPress: true
|
||||
|
||||
ShortcutText {
|
||||
anchors {
|
||||
verticalCenter: parent.textFieldLabel.verticalCenter
|
||||
left: parent.textFieldLabel.right
|
||||
leftMargin: 10
|
||||
}
|
||||
|
||||
text: qsTr("At least 6 characters")
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
color: hifi.colors.blueAccent
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
root.isPassword = focus
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: signupBody.signup()
|
||||
}
|
||||
|
||||
Row {
|
||||
id: leftButton
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
Button {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
text: qsTr("Existing User")
|
||||
|
||||
onClicked: {
|
||||
bodyLoader.setSource("LinkAccountBody.qml")
|
||||
if (!root.isTablet) {
|
||||
bodyLoader.item.width = root.pane.width
|
||||
bodyLoader.item.height = root.pane.height
|
||||
if (focus) {
|
||||
root.isPassword = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: buttons
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
HifiControlsUit.TextField {
|
||||
id: emailField
|
||||
width: root.bannerWidth
|
||||
height: signUpBody.textFieldHeight
|
||||
anchors {
|
||||
top: parent.top
|
||||
}
|
||||
placeholderText: "Username or Email"
|
||||
font.pixelSize: signUpBody.textFieldFontSize
|
||||
styleRenderType: Text.QtRendering
|
||||
activeFocusOnPress: true
|
||||
Keys.onPressed: {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Tab:
|
||||
event.accepted = true;
|
||||
if (event.modifiers === Qt.ShiftModifier) {
|
||||
if (usernameField.visible) {
|
||||
usernameField.focus = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
passwordField.focus = true;
|
||||
break;
|
||||
case Qt.Key_Backtab:
|
||||
event.accepted = true;
|
||||
usernameField.focus = true;
|
||||
break;
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true;
|
||||
if (keepMeLoggedInCheckbox.checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
}
|
||||
signUpBody.signup();
|
||||
break;
|
||||
}
|
||||
}
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
if (focus) {
|
||||
root.isPassword = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
HifiControlsUit.TextField {
|
||||
id: passwordField
|
||||
width: root.bannerWidth
|
||||
height: signUpBody.textFieldHeight
|
||||
placeholderText: "Password (min. 6 characters)"
|
||||
font.pixelSize: signUpBody.textFieldFontSize
|
||||
styleRenderType: Text.QtRendering
|
||||
activeFocusOnPress: true
|
||||
echoMode: passwordFieldMouseArea.showPassword ? TextInput.Normal : TextInput.Password
|
||||
anchors {
|
||||
top: emailField.bottom
|
||||
topMargin: 1.5 * hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
|
||||
Button {
|
||||
id: linkAccountButton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 200
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
root.isPassword = focus;
|
||||
}
|
||||
|
||||
text: qsTr("Sign Up")
|
||||
color: hifi.buttons.blue
|
||||
Item {
|
||||
id: showPasswordContainer
|
||||
z: 10
|
||||
// width + image's rightMargin
|
||||
width: showPasswordImage.width + 8
|
||||
height: parent.height
|
||||
anchors {
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
onClicked: signupBody.signup()
|
||||
Image {
|
||||
id: showPasswordImage
|
||||
width: passwordField.height * passwordImageRatio
|
||||
height: passwordField.height * passwordImageRatio
|
||||
anchors {
|
||||
right: parent.right
|
||||
rightMargin: 8
|
||||
top: parent.top
|
||||
topMargin: passwordFieldMouseArea.showPassword ? 6 : 8
|
||||
bottom: parent.bottom
|
||||
bottomMargin: passwordFieldMouseArea.showPassword ? 5 : 8
|
||||
}
|
||||
source: passwordFieldMouseArea.showPassword ? "../../images/eyeClosed.svg" : "../../images/eyeOpen.svg"
|
||||
MouseArea {
|
||||
id: passwordFieldMouseArea
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton
|
||||
property bool showPassword: false
|
||||
onClicked: {
|
||||
showPassword = !showPassword;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Keys.onPressed: {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Tab:
|
||||
event.accepted = true;
|
||||
if (event.modifiers === Qt.ShiftModifier) {
|
||||
emailField.focus = true;
|
||||
} else if (usernameField.visible) {
|
||||
usernameField.focus = true;
|
||||
} else {
|
||||
emailField.focus = true;
|
||||
}
|
||||
break;
|
||||
case Qt.Key_Backtab:
|
||||
event.accepted = true;
|
||||
emailField.focus = true;
|
||||
break;
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true;
|
||||
if (keepMeLoggedInCheckbox.checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
}
|
||||
signUpBody.signup();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
HifiControlsUit.CheckBox {
|
||||
id: keepMeLoggedInCheckbox
|
||||
checked: Settings.getValue("keepMeLoggedIn", false);
|
||||
text: qsTr("Keep Me Logged In");
|
||||
boxSize: 18;
|
||||
labelFontFamily: signUpBody.fontFamily
|
||||
labelFontSize: 18;
|
||||
color: hifi.colors.white;
|
||||
anchors {
|
||||
top: passwordField.bottom;
|
||||
topMargin: hifi.dimensions.contentSpacing.y;
|
||||
left: passwordField.left;
|
||||
}
|
||||
onCheckedChanged: {
|
||||
Settings.setValue("keepMeLoggedIn", checked);
|
||||
if (keepMeLoggedInCheckbox.checked) {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", emailField.text);
|
||||
} else {
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
TextMetrics {
|
||||
id: cancelButtonTextMetrics
|
||||
font: loginErrorMessage.font
|
||||
text: cancelButton.text
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
id: cancelButton
|
||||
width: (emailField.width - hifi.dimensions.contentSpacing.x) / 2
|
||||
height: d.minHeightButton
|
||||
anchors {
|
||||
top: keepMeLoggedInCheckbox.bottom
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
left: parent.left
|
||||
}
|
||||
color: hifi.buttons.noneBorderlessWhite
|
||||
text: qsTr("CANCEL")
|
||||
fontFamily: signUpBody.fontFamily
|
||||
fontSize: signUpBody.fontSize
|
||||
fontBold: signUpBody.fontBold
|
||||
onClicked: {
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": signUpBody.linkSteam });
|
||||
}
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
id: signUpButton
|
||||
width: (emailField.width - hifi.dimensions.contentSpacing.x) / 2
|
||||
height: d.minHeightButton
|
||||
color: hifi.buttons.blue
|
||||
text: qsTr("Sign Up")
|
||||
fontFamily: signUpBody.fontFamily
|
||||
fontSize: signUpBody.fontSize
|
||||
fontBold: signUpBody.fontBold
|
||||
anchors {
|
||||
top: cancelButton.top
|
||||
right: passwordField.right
|
||||
}
|
||||
|
||||
text: qsTr("Cancel")
|
||||
onClicked: {
|
||||
signUpBody.signup();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: root.tryDestroy()
|
||||
MouseArea {
|
||||
z: -2
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onClicked: {
|
||||
if (!usernameField.focus && !emailField.focus && !passwordField.focus) {
|
||||
usernameField.focus = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
root.title = qsTr("Create an Account")
|
||||
root.iconText = "<"
|
||||
//dont rise local keyboard
|
||||
keyboardEnabled = !root.isTablet && HMD.active;
|
||||
//but rise Tablet's one instead for Tablet interface
|
||||
if (root.isTablet) {
|
||||
root.keyboardEnabled = HMD.active;
|
||||
root.keyboardRaised = Qt.binding( function() { return keyboardRaised; })
|
||||
}
|
||||
root.keyboardEnabled = HMD.active;
|
||||
root.keyboardRaised = Qt.binding( function() { return keyboardRaised; })
|
||||
root.text = "";
|
||||
d.resize();
|
||||
|
||||
emailField.forceActiveFocus();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: loginDialog
|
||||
onHandleSignupCompleted: {
|
||||
console.log("Sign Up Succeeded");
|
||||
|
||||
// now that we have an account, login with that username and password
|
||||
loginDialog.login(usernameField.text, passwordField.text)
|
||||
}
|
||||
onHandleSignupFailed: {
|
||||
console.log("Sign Up Failed")
|
||||
toggleLoading(false)
|
||||
|
||||
mainTextContainer.text = errorString
|
||||
mainTextContainer.visible = true
|
||||
|
||||
d.resize();
|
||||
}
|
||||
onHandleLoginCompleted: {
|
||||
bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack": false })
|
||||
bodyLoader.item.width = root.pane.width
|
||||
bodyLoader.item.height = root.pane.height
|
||||
}
|
||||
onHandleLoginFailed: {
|
||||
// we failed to login, show the LoginDialog so the user will try again
|
||||
bodyLoader.setSource("LinkAccountBody.qml", { "failAfterSignUp": true })
|
||||
if (!root.isTablet) {
|
||||
bodyLoader.item.width = root.pane.width
|
||||
bodyLoader.item.height = root.pane.height
|
||||
}
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (!visible) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.key) {
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true
|
||||
signupBody.signup()
|
||||
break
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true;
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||
signUpBody.login();
|
||||
break;
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: loginDialog
|
||||
onHandleSignupCompleted: {
|
||||
console.log("Sign Up Completed");
|
||||
|
||||
loginDialog.login(usernameField.text, passwordField.text);
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "linkSteam": false });
|
||||
}
|
||||
onHandleSignupFailed: {
|
||||
console.log("Sign Up Failed")
|
||||
|
||||
if (errorString !== "") {
|
||||
loginErrorMessage.visible = true;
|
||||
var errorStringEdited = errorString.replace(/[\n\r]+/g, "\n");
|
||||
loginErrorMessage.text = errorStringEdited;
|
||||
loginErrorMessageTextMetrics.text = errorString;
|
||||
if (loginErrorMessageTextMetrics.width > usernameField.width) {
|
||||
loginErrorMessage.wrapMode = Text.WordWrap;
|
||||
loginErrorMessage.verticalAlignment = Text.AlignLeft;
|
||||
loginErrorMessage.horizontalAlignment = Text.AlignLeft;
|
||||
errorContainer.height = (loginErrorMessageTextMetrics.width / usernameField.width) * loginErrorMessageTextMetrics.height;
|
||||
}
|
||||
errorContainer.anchors.bottom = usernameField.top;
|
||||
errorContainer.anchors.bottomMargin = hifi.dimensions.contentSpacing.y;
|
||||
errorContainer.anchors.left = usernameField.left;
|
||||
}
|
||||
}
|
||||
onFocusEnabled: {
|
||||
if (!signUpBody.lostFocus) {
|
||||
Qt.callLater(function() {
|
||||
emailField.forceActiveFocus();
|
||||
});
|
||||
}
|
||||
}
|
||||
onFocusDisabled: {
|
||||
signUpBody.lostFocus = !root.isTablet && !root.isOverlay;
|
||||
if (signUpBody.lostFocus) {
|
||||
Qt.callLater(function() {
|
||||
usernameField.focus = false;
|
||||
emailField.focus = false;
|
||||
passwordField.focus = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,169 +12,228 @@ import Hifi 1.0
|
|||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
import controlsUit 1.0
|
||||
import stylesUit 1.0
|
||||
import controlsUit 1.0 as HifiControlsUit
|
||||
import stylesUit 1.0 as HifiStylesUit
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
Item {
|
||||
id: usernameCollisionBody
|
||||
clip: true
|
||||
width: root.pane.width
|
||||
height: root.pane.height
|
||||
width: root.width
|
||||
height: root.height
|
||||
readonly property string fontFamily: "Raleway"
|
||||
readonly property int fontSize: 15
|
||||
readonly property int textFieldFontSize: 18
|
||||
readonly property bool fontBold: true
|
||||
|
||||
function create() {
|
||||
mainTextContainer.visible = false
|
||||
loginDialog.createAccountFromStream(textField.text)
|
||||
loginDialog.createAccountFromSteam(textField.text);
|
||||
}
|
||||
|
||||
|
||||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
|
||||
onKeyboardRaisedChanged: d.resize();
|
||||
|
||||
property bool lostFocus: false
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property int minWidth: 480
|
||||
readonly property int maxWidth: 1280
|
||||
readonly property int minWidthButton: !root.isTablet ? 256 : 174
|
||||
property int maxWidth: root.width
|
||||
readonly property int minHeight: 120
|
||||
readonly property int maxHeight: 720
|
||||
readonly property int minHeightButton: 36
|
||||
property int maxHeight: root.height
|
||||
|
||||
function resize() {
|
||||
var targetWidth = Math.max(titleWidth, mainTextContainer.contentWidth)
|
||||
maxWidth = root.width;
|
||||
maxHeight = root.height;
|
||||
var targetWidth = Math.max(titleWidth, mainContainer.width);
|
||||
var targetHeight = mainTextContainer.height +
|
||||
hifi.dimensions.contentSpacing.y + textField.height +
|
||||
hifi.dimensions.contentSpacing.y + buttons.height
|
||||
hifi.dimensions.contentSpacing.y + buttons.height;
|
||||
|
||||
parent.width = root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth))
|
||||
parent.height = root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight))
|
||||
+ (keyboardEnabled && keyboardRaised ? (200 + 2 * hifi.dimensions.contentSpacing.y) : hifi.dimensions.contentSpacing.y)
|
||||
parent.height = root.height = Math.max(Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight)), mainContainer.height + hifi.dimensions.contentSpacing.y);
|
||||
}
|
||||
}
|
||||
|
||||
ShortcutText {
|
||||
id: mainTextContainer
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
margins: 0
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
|
||||
text: qsTr("Your Steam username is not available.")
|
||||
wrapMode: Text.WordWrap
|
||||
color: hifi.colors.redAccent
|
||||
lineHeight: 1
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
|
||||
TextField {
|
||||
id: textField
|
||||
anchors {
|
||||
top: mainTextContainer.bottom
|
||||
left: parent.left
|
||||
margins: 0
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
width: parent.width
|
||||
|
||||
placeholderText: "Choose your own"
|
||||
}
|
||||
|
||||
// Override ScrollingWindow's keyboard that would be at very bottom of dialog.
|
||||
Keyboard {
|
||||
raised: keyboardEnabled && keyboardRaised
|
||||
numeric: punctuationMode
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: buttons.top
|
||||
bottomMargin: keyboardRaised ? 2 * hifi.dimensions.contentSpacing.y : 0
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: buttons
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
margins: 0
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
Item {
|
||||
id: mainContainer
|
||||
width: root.width
|
||||
height: root.height
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
anchors.fill: parent
|
||||
|
||||
Button {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 200
|
||||
|
||||
text: qsTr("Create your profile")
|
||||
color: hifi.buttons.blue
|
||||
|
||||
onClicked: usernameCollisionBody.create()
|
||||
TextMetrics {
|
||||
id: mainTextContainerTextMetrics
|
||||
font: mainTextContainer.font
|
||||
text: mainTextContainer.text
|
||||
}
|
||||
|
||||
Button {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Text {
|
||||
id: mainTextContainer
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
leftMargin: (parent.width - mainTextContainer.width) / 2
|
||||
topMargin: parent.height/2 - buttons.anchors.topMargin - textField.height - mainTextContainerTextMetrics.height
|
||||
}
|
||||
|
||||
text: qsTr("Cancel")
|
||||
font.family: usernameCollisionBody.fontFamily
|
||||
font.pixelSize: usernameCollisionBody.fontSize
|
||||
font.bold: usernameCollisionBody.fontBold
|
||||
text: qsTr("Your Steam username is not available.");
|
||||
wrapMode: Text.WordWrap
|
||||
color: hifi.colors.redAccent
|
||||
lineHeight: 1
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
onClicked: root.tryDestroy()
|
||||
|
||||
HifiControlsUit.TextField {
|
||||
id: textField
|
||||
anchors {
|
||||
top: mainTextContainer.bottom
|
||||
left: parent.left
|
||||
leftMargin: (parent.width - width) / 2
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
focus: true
|
||||
font.family: "Fira Sans"
|
||||
font.pixelSize: usernameCollisionBody.textFieldFontSize
|
||||
styleRenderType: Text.QtRendering
|
||||
width: root.bannerWidth
|
||||
|
||||
placeholderText: "Choose your own"
|
||||
|
||||
onFocusChanged: {
|
||||
root.text = "";
|
||||
if (focus) {
|
||||
root.isPassword = false;
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (!visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.key) {
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true;
|
||||
usernameCollisionBody.create();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: buttons
|
||||
width: root.bannerWidth
|
||||
height: d.minHeightButton
|
||||
anchors {
|
||||
top: textField.bottom
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
left: parent.left
|
||||
leftMargin: (parent.width - root.bannerWidth) / 2
|
||||
}
|
||||
|
||||
HifiControlsUit.Button {
|
||||
id: cancelButton
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
}
|
||||
width: (parent.width - hifi.dimensions.contentSpacing.x) / 2
|
||||
height: d.minHeightButton
|
||||
|
||||
text: qsTr("CANCEL")
|
||||
color: hifi.buttons.noneBorderlessWhite
|
||||
|
||||
fontFamily: usernameCollisionBody.fontFamily
|
||||
fontSize: usernameCollisionBody.fontSize
|
||||
fontBold: usernameCollisionBody.fontBold
|
||||
onClicked: {
|
||||
bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": "" });
|
||||
}
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
id: profileButton
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
}
|
||||
width: (parent.width - hifi.dimensions.contentSpacing.x) / 2
|
||||
height: d.minHeightButton
|
||||
|
||||
text: qsTr("Create your profile")
|
||||
color: hifi.buttons.blue
|
||||
|
||||
fontFamily: usernameCollisionBody.fontFamily
|
||||
fontSize: usernameCollisionBody.fontSize
|
||||
fontBold: usernameCollisionBody.fontBold
|
||||
onClicked: {
|
||||
usernameCollisionBody.create();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
root.title = qsTr("Complete Your Profile")
|
||||
root.iconText = "<"
|
||||
//dont rise local keyboard
|
||||
keyboardEnabled = !root.isTablet && HMD.active;
|
||||
//but rise Tablet's one instead for Tablet interface
|
||||
if (root.isTablet) {
|
||||
root.keyboardEnabled = HMD.active;
|
||||
root.keyboardRaised = Qt.binding( function() { return keyboardRaised; })
|
||||
}
|
||||
|
||||
root.keyboardEnabled = HMD.active;
|
||||
root.keyboardRaised = Qt.binding( function() { return keyboardRaised; })
|
||||
root.text = "";
|
||||
d.resize();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: loginDialog
|
||||
onHandleCreateCompleted: {
|
||||
console.log("Create Succeeded")
|
||||
|
||||
loginDialog.loginThroughSteam()
|
||||
console.log("Create Succeeded");
|
||||
loginDialog.loginThroughSteam();
|
||||
bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": true, "linkSteam": false })
|
||||
}
|
||||
onHandleCreateFailed: {
|
||||
console.log("Create Failed: " + error)
|
||||
|
||||
mainTextContainer.visible = true
|
||||
mainTextContainer.text = "\"" + textField.text + qsTr("\" is invalid or already taken.")
|
||||
mainTextContainer.text = "\"" + textField.text + qsTr("\" is invalid or already taken.");
|
||||
}
|
||||
onHandleLoginCompleted: {
|
||||
console.log("Login Succeeded")
|
||||
|
||||
bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : false })
|
||||
bodyLoader.item.width = root.pane.width
|
||||
bodyLoader.item.height = root.pane.height
|
||||
console.log("Login Succeeded");
|
||||
if (loginDialog.getLoginDialogPoppedUp()) {
|
||||
loginDialog.dismissLoginDialog();
|
||||
}
|
||||
root.tryDestroy();
|
||||
}
|
||||
|
||||
onHandleLoginFailed: {
|
||||
console.log("Login Failed")
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (!visible) {
|
||||
return
|
||||
mainTextContainer.text = "Login Failed";
|
||||
}
|
||||
|
||||
switch (event.key) {
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true
|
||||
usernameCollisionBody.create()
|
||||
break
|
||||
|
||||
onFocusEnabled: {
|
||||
if (!usernameCollisionBody.lostFocus) {
|
||||
Qt.callLater(function() {
|
||||
textField.forceActiveFocus();
|
||||
});
|
||||
}
|
||||
}
|
||||
onFocusDisabled: {
|
||||
usernameCollisionBody.lostFocus = !root.isTablet && !root.isOverlay;
|
||||
if (nusernameCollisionBody.lostFocus) {
|
||||
Qt.callLater(function() {
|
||||
textField.focus = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
//
|
||||
// WelcomeBody.qml
|
||||
//
|
||||
// Created by Clement on 7/18/16
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import Hifi 1.0
|
||||
import QtQuick 2.4
|
||||
|
||||
import controlsUit 1.0
|
||||
import stylesUit 1.0
|
||||
|
||||
Item {
|
||||
id: welcomeBody
|
||||
clip: true
|
||||
width: root.pane.width
|
||||
height: root.pane.height
|
||||
|
||||
property bool welcomeBack: false
|
||||
|
||||
function setTitle() {
|
||||
root.title = (welcomeBack ? qsTr("Welcome back <b>") : qsTr("Welcome <b>")) + Account.username + qsTr("</b>!")
|
||||
root.iconText = ""
|
||||
d.resize();
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property int minWidth: 480
|
||||
readonly property int maxWidth: 1280
|
||||
readonly property int minHeight: 120
|
||||
readonly property int maxHeight: 720
|
||||
|
||||
function resize() {
|
||||
var targetWidth = Math.max(titleWidth, mainTextContainer.contentWidth)
|
||||
var targetHeight = mainTextContainer.height + 3 * hifi.dimensions.contentSpacing.y + buttons.height
|
||||
|
||||
parent.width = root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth))
|
||||
parent.height = root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight))
|
||||
}
|
||||
}
|
||||
|
||||
InfoItem {
|
||||
id: mainTextContainer
|
||||
anchors {
|
||||
top: parent.top
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
margins: 0
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
|
||||
text: qsTr("You are now signed into High Fidelity")
|
||||
wrapMode: Text.WordWrap
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
lineHeight: 2
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
Row {
|
||||
id: buttons
|
||||
anchors {
|
||||
top: mainTextContainer.bottom
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
margins: 0
|
||||
topMargin: 2 * hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
|
||||
Button {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
text: qsTr("Close");
|
||||
|
||||
onClicked: root.tryDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: welcomeBody.setTitle()
|
||||
|
||||
Connections {
|
||||
target: Account
|
||||
onUsernameChanged: welcomeBody.setTitle()
|
||||
}
|
||||
}
|
BIN
interface/resources/qml/LoginDialog/images/background.jpg
Normal file
After Width: | Height: | Size: 960 KiB |
BIN
interface/resources/qml/LoginDialog/images/background_tablet.jpg
Normal file
After Width: | Height: | Size: 272 KiB |
BIN
interface/resources/qml/LoginDialog/images/loader-snake-256.gif
Normal file
After Width: | Height: | Size: 26 KiB |
154
interface/resources/qml/OverlayLoginDialog.qml
Normal file
|
@ -0,0 +1,154 @@
|
|||
//
|
||||
// LoginDialog.qml
|
||||
//
|
||||
// Created by Wayne Chen
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import Hifi 1.0
|
||||
import QtQuick 2.4
|
||||
|
||||
import controlsUit 1.0 as HifiControlsUit
|
||||
import stylesUit 1.0 as HifiStylesUit
|
||||
|
||||
import "LoginDialog"
|
||||
|
||||
FocusScope {
|
||||
id: root
|
||||
HifiStylesUit.HifiConstants { id: hifi }
|
||||
objectName: "LoginDialog"
|
||||
visible: true
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
readonly property bool isTablet: false
|
||||
readonly property bool isOverlay: true
|
||||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
property bool isPassword: false
|
||||
property string iconText: ""
|
||||
property int iconSize: 50
|
||||
|
||||
property string title: ""
|
||||
property int titleWidth: 0
|
||||
property alias text: loginKeyboard.mirroredText
|
||||
property alias bannerWidth: banner.width
|
||||
property alias bannerHeight: banner.height
|
||||
|
||||
function tryDestroy() {
|
||||
root.destroy()
|
||||
}
|
||||
|
||||
LoginDialog {
|
||||
id: loginDialog
|
||||
anchors.fill: parent
|
||||
Loader {
|
||||
id: bodyLoader
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
z: -10
|
||||
id: loginDialogBackground
|
||||
source: "LoginDialog/images/background.jpg"
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
z: -6
|
||||
id: opaqueRect
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
opacity: 0.65
|
||||
color: "black"
|
||||
}
|
||||
|
||||
Item {
|
||||
z: -5
|
||||
id: bannerContainer
|
||||
width: parent.width
|
||||
height: banner.height
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: 0.18 * parent.height
|
||||
}
|
||||
Image {
|
||||
id: banner
|
||||
anchors.centerIn: parent
|
||||
source: "../images/high-fidelity-banner.svg"
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: keyboardTimer
|
||||
repeat: false
|
||||
interval: 200
|
||||
|
||||
onTriggered: {
|
||||
if (MenuInterface.isOptionChecked("Use 3D Keyboard")) {
|
||||
KeyboardScriptingInterface.raised = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.Keyboard {
|
||||
id: loginKeyboard
|
||||
raised: root.keyboardEnabled && root.keyboardRaised
|
||||
numeric: root.punctuationMode
|
||||
password: root.isPassword
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (!visible) {
|
||||
return
|
||||
}
|
||||
|
||||
if (event.modifiers === Qt.ControlModifier)
|
||||
switch (event.key) {
|
||||
case Qt.Key_A:
|
||||
event.accepted = true
|
||||
detailedText.selectAll()
|
||||
break
|
||||
case Qt.Key_C:
|
||||
event.accepted = true
|
||||
detailedText.copy()
|
||||
break
|
||||
case Qt.Key_Period:
|
||||
if (Qt.platform.os === "osx") {
|
||||
event.accepted = true
|
||||
content.reject()
|
||||
}
|
||||
break
|
||||
} else switch (event.key) {
|
||||
case Qt.Key_Escape:
|
||||
case Qt.Key_Back:
|
||||
event.accepted = true
|
||||
break
|
||||
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
loginKeyboard.raised = false;
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
keyboardTimer.start();
|
||||
bodyLoader.setSource("LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false });
|
||||
}
|
||||
}
|
|
@ -19,10 +19,14 @@ Original.Button {
|
|||
|
||||
property int color: 0
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
property string fontFamily: "Raleway"
|
||||
property int fontSize: hifi.fontSizes.buttonLabel
|
||||
property bool fontBold: true
|
||||
property int radius: hifi.buttons.radius
|
||||
property alias implicitTextWidth: buttonText.implicitWidth
|
||||
property string buttonGlyph: "";
|
||||
property int buttonGlyphSize: 34;
|
||||
property int buttonGlyphRightMargin: 0;
|
||||
property int fontCapitalization: Font.AllUppercase
|
||||
|
||||
width: hifi.dimensions.buttonWidth
|
||||
|
@ -35,13 +39,13 @@ Original.Button {
|
|||
Tablet.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onFocusChanged: {
|
||||
if (focus) {
|
||||
Tablet.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
@ -89,14 +93,21 @@ Original.Button {
|
|||
}
|
||||
|
||||
contentItem: Item {
|
||||
id: buttonContentItem
|
||||
TextMetrics {
|
||||
id: buttonGlyphTextMetrics;
|
||||
font: buttonGlyph.font;
|
||||
text: buttonGlyph.text;
|
||||
}
|
||||
HiFiGlyphs {
|
||||
id: buttonGlyph;
|
||||
visible: control.buttonGlyph !== "";
|
||||
text: control.buttonGlyph === "" ? hifi.glyphs.question : control.buttonGlyph;
|
||||
// Size
|
||||
size: 34;
|
||||
size: control.buttonGlyphSize;
|
||||
// Anchors
|
||||
anchors.right: buttonText.left;
|
||||
anchors.rightMargin: control.buttonGlyphRightMargin
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
// Style
|
||||
|
@ -106,17 +117,32 @@ Original.Button {
|
|||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
RalewayBold {
|
||||
|
||||
TextMetrics {
|
||||
id: buttonTextMetrics;
|
||||
font: buttonText.font;
|
||||
text: buttonText.text;
|
||||
}
|
||||
Text {
|
||||
id: buttonText;
|
||||
anchors.centerIn: parent;
|
||||
width: buttonTextMetrics.width
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
font.capitalization: control.fontCapitalization
|
||||
color: enabled ? hifi.buttons.textColor[control.color]
|
||||
: hifi.buttons.disabledTextColor[control.colorScheme]
|
||||
size: control.fontSize
|
||||
font.family: control.fontFamily
|
||||
font.pixelSize: control.fontSize
|
||||
font.bold: control.fontBold
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: control.text
|
||||
Component.onCompleted: {
|
||||
if (control.buttonGlyph !== "") {
|
||||
buttonText.x = buttonContentItem.width/2 - buttonTextMetrics.width/2 + (buttonGlyphTextMetrics.width + control.buttonGlyphRightMargin)/2;
|
||||
} else {
|
||||
buttonText.anchors.centerIn = parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ TextField {
|
|||
property bool hasClearButton: false;
|
||||
property string leftPermanentGlyph: "";
|
||||
property string centerPlaceholderGlyph: "";
|
||||
property int styleRenderType: Text.NativeRendering
|
||||
|
||||
placeholderText: textField.placeholderText
|
||||
|
||||
|
@ -44,8 +45,8 @@ TextField {
|
|||
// workaround for https://bugreports.qt.io/browse/QTBUG-49297
|
||||
Keys.onPressed: {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
event.accepted = true;
|
||||
|
||||
// emit accepted signal manually
|
||||
|
@ -156,6 +157,7 @@ TextField {
|
|||
selectionColor: hifi.colors.primaryHighlight
|
||||
padding.left: hasRoundedBorder ? textField.height / 2 : ((isSearchField || textField.leftPermanentGlyph !== "") ? textField.height - 2 : 0) + hifi.dimensions.textPadding
|
||||
padding.right: (hasClearButton ? textField.height - 2 : 0) + hifi.dimensions.textPadding
|
||||
renderType: textField.styleRenderType
|
||||
}
|
||||
|
||||
HifiControls.Label {
|
||||
|
|
|
@ -11,59 +11,52 @@
|
|||
import Hifi 1.0
|
||||
import QtQuick 2.5
|
||||
|
||||
import controlsUit 1.0
|
||||
import stylesUit 1.0
|
||||
import "../windows"
|
||||
import controlsUit 1.0 as HifiControlsUit
|
||||
import stylesUit 1.0 as HifiStylesUit
|
||||
|
||||
import "../LoginDialog"
|
||||
|
||||
TabletModalWindow {
|
||||
id: realRoot
|
||||
FocusScope {
|
||||
id: root
|
||||
objectName: "LoginDialog"
|
||||
visible: true
|
||||
|
||||
anchors.fill: parent
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
signal sendToScript(var message);
|
||||
signal canceled();
|
||||
|
||||
property bool isHMD: false
|
||||
property bool gotoPreviousApp: false;
|
||||
color: hifi.colors.baseGray
|
||||
title: qsTr("Sign in to High Fidelity")
|
||||
property alias titleWidth: root.titleWidth
|
||||
property alias punctuationMode: root.punctuationMode
|
||||
|
||||
//fake root for shared components expecting root here
|
||||
property var root: QtObject {
|
||||
id: root
|
||||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
property bool isPassword: false
|
||||
|
||||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
property bool isPassword: false
|
||||
property alias text: loginKeyboard.mirroredText
|
||||
readonly property bool isTablet: true
|
||||
readonly property bool isOverlay: false
|
||||
property alias text: loginKeyboard.mirroredText
|
||||
|
||||
readonly property bool isTablet: true
|
||||
property int titleWidth: 0
|
||||
property alias bannerWidth: banner.width
|
||||
property alias bannerHeight: banner.height
|
||||
property string iconText: hifi.glyphs.avatar
|
||||
property int iconSize: 35
|
||||
|
||||
property alias title: realRoot.title
|
||||
property real width: realRoot.width
|
||||
property real height: realRoot.height
|
||||
|
||||
property int titleWidth: 0
|
||||
property string iconText: hifi.glyphs.avatar
|
||||
property int iconSize: 35
|
||||
|
||||
property var pane: QtObject {
|
||||
property real width: root.width
|
||||
property real height: root.height
|
||||
}
|
||||
|
||||
function tryDestroy() {
|
||||
canceled()
|
||||
}
|
||||
property var pane: QtObject {
|
||||
property real width: root.width
|
||||
property real height: root.height
|
||||
}
|
||||
|
||||
//property int colorScheme: hifi.colorSchemes.dark
|
||||
function tryDestroy() {
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
width: realRoot.width
|
||||
height: realRoot.height
|
||||
width: root.width
|
||||
height: root.height
|
||||
}
|
||||
|
||||
property bool keyboardOverride: true
|
||||
|
@ -71,29 +64,11 @@ TabletModalWindow {
|
|||
property var items;
|
||||
property string label: ""
|
||||
|
||||
//onTitleWidthChanged: d.resize();
|
||||
|
||||
//onKeyboardRaisedChanged: d.resize();
|
||||
|
||||
signal canceled();
|
||||
|
||||
property alias bodyLoader: bodyLoader
|
||||
property alias loginDialog: loginDialog
|
||||
property alias hifi: hifi
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
onCanceled: {
|
||||
if (bodyLoader.active === true) {
|
||||
//bodyLoader.active = false
|
||||
}
|
||||
if (gotoPreviousApp) {
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.returnToPreviousApp();
|
||||
} else {
|
||||
Tablet.getTablet("com.highfidelity.interface.tablet.system").gotoHomeScreen();
|
||||
}
|
||||
}
|
||||
HifiStylesUit.HifiConstants { id: hifi }
|
||||
|
||||
Timer {
|
||||
id: keyboardTimer
|
||||
|
@ -107,48 +82,50 @@ TabletModalWindow {
|
|||
}
|
||||
}
|
||||
|
||||
TabletModalFrame {
|
||||
id: mfRoot
|
||||
LoginDialog {
|
||||
id: loginDialog
|
||||
|
||||
width: root.width
|
||||
height: root.height + frameMarginTop + hifi.dimensions.contentMargin.x
|
||||
anchors.fill: parent
|
||||
Loader {
|
||||
id: bodyLoader
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
z: -10
|
||||
id: loginDialogBackground
|
||||
source: "../LoginDialog/images/background_tablet.jpg"
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Item {
|
||||
z: -5
|
||||
id: bannerContainer
|
||||
width: parent.width
|
||||
height: banner.height
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
verticalCenter: parent.verticalCenter
|
||||
verticalCenterOffset: -loginKeyboard.height / 2
|
||||
top: parent.top
|
||||
topMargin: 0.18 * parent.height
|
||||
}
|
||||
|
||||
LoginDialog {
|
||||
id: loginDialog
|
||||
|
||||
anchors {
|
||||
fill: parent
|
||||
topMargin: parent.frameMarginTop
|
||||
leftMargin: hifi.dimensions.contentMargin.x
|
||||
rightMargin: hifi.dimensions.contentMargin.x
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: bodyLoader
|
||||
anchors.fill: parent
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
source: loginDialog.isSteamRunning() ? "../LoginDialog/SignInBody.qml" : "../LoginDialog/LinkAccountBody.qml"
|
||||
}
|
||||
Image {
|
||||
id: banner
|
||||
anchors.centerIn: parent
|
||||
source: "../../images/high-fidelity-banner.svg"
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
loginKeyboard.raised = false;
|
||||
KeyboardScriptingInterface.raised = false;
|
||||
Rectangle {
|
||||
z: -6
|
||||
id: opaqueRect
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
opacity: 0.65
|
||||
color: "black"
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
keyboardTimer.start();
|
||||
}
|
||||
|
||||
Keyboard {
|
||||
HifiControlsUit.Keyboard {
|
||||
id: loginKeyboard
|
||||
raised: root.keyboardEnabled && root.keyboardRaised
|
||||
numeric: root.punctuationMode
|
||||
|
@ -182,16 +159,20 @@ TabletModalWindow {
|
|||
}
|
||||
break
|
||||
} else switch (event.key) {
|
||||
case Qt.Key_Escape:
|
||||
case Qt.Key_Back:
|
||||
event.accepted = true
|
||||
destroy()
|
||||
break
|
||||
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
loginKeyboard.raised = false;
|
||||
KeyboardScriptingInterface.raised = false;
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
keyboardTimer.start();
|
||||
bodyLoader.setSource("../LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import QtQuick 2.7
|
||||
import QtWebEngine 1.5;
|
||||
import Qt.labs.settings 1.0
|
||||
import Qt.labs.settings 1.0 as QtSettings
|
||||
|
||||
import QtQuick.Controls 2.3
|
||||
|
||||
|
@ -74,7 +74,7 @@ OriginalDesktop.Desktop {
|
|||
shown: tablet ? tablet.toolbarMode : false;
|
||||
}
|
||||
|
||||
Settings {
|
||||
QtSettings.Settings {
|
||||
id: settings;
|
||||
category: "toolbar";
|
||||
property bool constrainToolbarToCenterX: true;
|
||||
|
|
|
@ -61,7 +61,7 @@ Rectangle {
|
|||
'username';
|
||||
}
|
||||
sortAscending: connectionsTable.sortIndicatorOrder === Qt.AscendingOrder;
|
||||
itemsPerPage: 10;
|
||||
itemsPerPage: 1000;
|
||||
listView: connectionsTable;
|
||||
processPage: function (data) {
|
||||
return data.users.map(function (user) {
|
||||
|
|
|
@ -15,10 +15,10 @@ import Qt.labs.settings 1.0
|
|||
|
||||
import stylesUit 1.0
|
||||
import controlsUit 1.0 as HifiControls
|
||||
import "../../windows"
|
||||
import "../../windows" as Windows
|
||||
import "../"
|
||||
|
||||
ScrollingWindow {
|
||||
Windows.ScrollingWindow {
|
||||
id: root
|
||||
objectName: "RunningScripts"
|
||||
title: "Running Scripts"
|
||||
|
@ -30,7 +30,7 @@ ScrollingWindow {
|
|||
minSize: Qt.vector2d(424, 300)
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
|
||||
property var scripts: ScriptDiscoveryService;
|
||||
property var scriptsModel: scripts.scriptsModelFilter
|
||||
property var runningScriptsModel: ListModel { }
|
||||
|
@ -45,7 +45,7 @@ ScrollingWindow {
|
|||
|
||||
Component {
|
||||
id: letterBoxMessage
|
||||
Window {
|
||||
Windows.Window {
|
||||
implicitWidth: 400
|
||||
implicitHeight: 300
|
||||
minSize: Qt.vector2d(424, 300)
|
||||
|
@ -63,8 +63,8 @@ ScrollingWindow {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Timer {
|
||||
id: refreshTimer
|
||||
interval: 100
|
||||
|
@ -81,7 +81,7 @@ ScrollingWindow {
|
|||
running: false
|
||||
onTriggered: developerMenuEnabled = MenuInterface.isOptionChecked("Developer Menu");
|
||||
}
|
||||
|
||||
|
||||
Component {
|
||||
id: listModelBuilder
|
||||
ListModel { }
|
||||
|
@ -92,7 +92,7 @@ ScrollingWindow {
|
|||
onScriptCountChanged: {
|
||||
runningScriptsModel = listModelBuilder.createObject(root);
|
||||
refreshTimer.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
|
@ -120,7 +120,7 @@ ScrollingWindow {
|
|||
// Calling `runningScriptsModel.clear()` here instead of creating a new object
|
||||
// triggers some kind of weird heap corruption deep inside Qt. So instead of
|
||||
// modifying the model in place, possibly triggering behaviors in the table
|
||||
// instead we create a new `ListModel`, populate it and update the
|
||||
// instead we create a new `ListModel`, populate it and update the
|
||||
// existing model atomically.
|
||||
var newRunningScriptsModel = listModelBuilder.createObject(root);
|
||||
for (var i = 0; i < runningScripts.length; ++i) {
|
||||
|
@ -177,7 +177,7 @@ ScrollingWindow {
|
|||
if ((script === "controllerScripts.js") || (script === "defaultScripts.js")) {
|
||||
return developerMenuEnabled;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -369,7 +369,7 @@ ScrollingWindow {
|
|||
colorScheme: hifi.colorSchemes.dark
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
|
||||
TableViewColumn {
|
||||
role: "display";
|
||||
}
|
||||
|
@ -447,4 +447,3 @@ ScrollingWindow {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -349,5 +349,7 @@ QtObject {
|
|||
readonly property string update: "\ue032"
|
||||
readonly property string uninstall: "\ue033"
|
||||
readonly property string verticalEllipsis: "\ue034"
|
||||
readonly property string steamSquare: "\ue035"
|
||||
readonly property string oculus: "\ue036"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,22 +97,22 @@ Frame {
|
|||
|
||||
|
||||
GlyphButton {
|
||||
id: closeButton
|
||||
visible: window.closeButtonVisible
|
||||
width: 30
|
||||
y: -hifi.dimensions.modalDialogTitleHeight
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
topMargin: 10
|
||||
rightMargin: 10
|
||||
}
|
||||
glyph: hifi.glyphs.close
|
||||
size: 23
|
||||
onClicked: {
|
||||
window.clickedCloseButton = true;
|
||||
window.destroy();
|
||||
}
|
||||
}
|
||||
id: closeButton
|
||||
visible: window.closeButtonVisible
|
||||
width: 30
|
||||
y: -hifi.dimensions.modalDialogTitleHeight
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
topMargin: 10
|
||||
rightMargin: 10
|
||||
}
|
||||
glyph: hifi.glyphs.close
|
||||
size: 23
|
||||
onClicked: {
|
||||
window.clickedCloseButton = true;
|
||||
window.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@ import QtQuick 2.5
|
|||
import QtQuick.Controls 2.2
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import "."
|
||||
import "." as Windows
|
||||
import stylesUit 1.0
|
||||
import controlsUit 1.0 as HiFiControls
|
||||
import controlsUit 1.0 as HifiControlsUit
|
||||
|
||||
// FIXME how do I set the initial position of a window without
|
||||
// overriding places where the a individual client of the window
|
||||
|
@ -25,7 +25,7 @@ import controlsUit 1.0 as HiFiControls
|
|||
// of the desktop? How do I ensure when the desktop resizes all the windows
|
||||
// are still at least partially visible?
|
||||
|
||||
Window {
|
||||
Windows.Window {
|
||||
id: window
|
||||
HifiConstants { id: hifi }
|
||||
children: [ swallower, frame, defocuser, pane, activator ]
|
||||
|
@ -178,7 +178,7 @@ Window {
|
|||
children: [ footer ]
|
||||
}
|
||||
|
||||
HiFiControls.Keyboard {
|
||||
HifiControlsUit.Keyboard {
|
||||
id: keyboard
|
||||
enabled: !keyboardOverride
|
||||
raised: keyboardEnabled && keyboardRaised
|
||||
|
|
|
@ -328,7 +328,13 @@ static const float INITIAL_QUERY_RADIUS = 10.0f; // priority radius for entitie
|
|||
|
||||
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||
|
||||
Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS);
|
||||
Setting::Handle<int> maxOctreePacketsPerSecond{"maxOctreePPS", DEFAULT_MAX_OCTREE_PPS};
|
||||
|
||||
Setting::Handle<bool> loginDialogPoppedUp{"loginDialogPoppedUp", false};
|
||||
|
||||
static const QString STANDARD_TO_ACTION_MAPPING_NAME = "Standard to Action";
|
||||
static const QString NO_MOVEMENT_MAPPING_NAME = "Standard to Action (No Movement)";
|
||||
static const QString NO_MOVEMENT_MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/standard_nomovement.json";
|
||||
|
||||
static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com";
|
||||
static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds
|
||||
|
@ -971,6 +977,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
_fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES),
|
||||
_hmdTabletScale("hmdTabletScale", DEFAULT_HMD_TABLET_SCALE_PERCENT),
|
||||
_desktopTabletScale("desktopTabletScale", DEFAULT_DESKTOP_TABLET_SCALE_PERCENT),
|
||||
_firstRun(Settings::firstRun, true),
|
||||
_desktopTabletBecomesToolbarSetting("desktopTabletBecomesToolbar", DEFAULT_DESKTOP_TABLET_BECOMES_TOOLBAR),
|
||||
_hmdTabletBecomesToolbarSetting("hmdTabletBecomesToolbar", DEFAULT_HMD_TABLET_BECOMES_TOOLBAR),
|
||||
_preferStylusOverLaserSetting("preferStylusOverLaser", DEFAULT_PREFER_STYLUS_OVER_LASER),
|
||||
|
@ -989,12 +996,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
_lastFaceTrackerUpdate(0),
|
||||
_snapshotSound(nullptr),
|
||||
_sampleSound(nullptr)
|
||||
|
||||
{
|
||||
|
||||
auto steamClient = PluginManager::getInstance()->getSteamClientPlugin();
|
||||
setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning()));
|
||||
setProperty(hifi::properties::CRASHED, _previousSessionCrashed);
|
||||
|
||||
{
|
||||
const QStringList args = arguments();
|
||||
|
||||
|
@ -1268,6 +1275,27 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
setCrashAnnotation("hmd", displayPlugin->isHmd() ? "1" : "0");
|
||||
});
|
||||
connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateSystemTabletMode);
|
||||
connect(this, &Application::activeDisplayPluginChanged, this, [&](){
|
||||
if (getLoginDialogPoppedUp()) {
|
||||
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
||||
auto keyboard = DependencyManager::get<Keyboard>();
|
||||
if (_firstRun.get()) {
|
||||
// display mode changed. Don't allow auto-switch to work after this session.
|
||||
_firstRun.set(false);
|
||||
}
|
||||
if (isHMDMode()) {
|
||||
emit loginDialogFocusDisabled();
|
||||
dialogsManager->hideLoginDialog();
|
||||
createLoginDialogOverlay();
|
||||
} else {
|
||||
getOverlays().deleteOverlay(_loginDialogOverlayID);
|
||||
_loginDialogOverlayID = OverlayID();
|
||||
_loginStateManager.tearDown();
|
||||
dialogsManager->showLoginDialog();
|
||||
emit loginDialogFocusEnabled();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Save avatar location immediately after a teleport.
|
||||
connect(myAvatar.get(), &MyAvatar::positionGoneTo,
|
||||
|
@ -1472,9 +1500,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
qDebug() << "Detected installer type:" << installerType;
|
||||
qDebug() << "Detected installer campaign:" << installerCampaign;
|
||||
|
||||
// add firstRun flag from settings to launch event
|
||||
Setting::Handle<bool> firstRun { Settings::firstRun, true };
|
||||
|
||||
auto& userActivityLogger = UserActivityLogger::getInstance();
|
||||
if (userActivityLogger.isEnabled()) {
|
||||
// sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value.
|
||||
|
@ -1523,7 +1548,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3;
|
||||
}
|
||||
|
||||
properties["first_run"] = firstRun.get();
|
||||
properties["first_run"] = _firstRun.get();
|
||||
|
||||
// add the user's machine ID to the launch event
|
||||
QString machineFingerPrint = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint());
|
||||
|
@ -1736,27 +1761,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
userInputMapper->registerDevice(_touchscreenVirtualPadDevice->getInputDevice());
|
||||
}
|
||||
|
||||
{
|
||||
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
|
||||
// this will force the model the look at the correct directory (weird order of operations issue)
|
||||
scriptEngines->reloadLocalFiles();
|
||||
|
||||
// do this as late as possible so that all required subsystems are initialized
|
||||
// If we've overridden the default scripts location, just load default scripts
|
||||
// otherwise, load 'em all
|
||||
|
||||
// we just want to see if --scripts was set, we've already parsed it and done
|
||||
// the change in PathUtils. Rather than pass that in the constructor, lets just
|
||||
// look (this could be debated)
|
||||
QString scriptsSwitch = QString("--").append(SCRIPTS_SWITCH);
|
||||
QDir defaultScriptsLocation(getCmdOption(argc, constArgv, scriptsSwitch.toStdString().c_str()));
|
||||
if (!defaultScriptsLocation.exists()) {
|
||||
scriptEngines->loadDefaultScripts();
|
||||
scriptEngines->defaultScriptsLocationOverridden(true);
|
||||
} else {
|
||||
scriptEngines->loadScripts();
|
||||
}
|
||||
}
|
||||
QString scriptsSwitch = QString("--").append(SCRIPTS_SWITCH);
|
||||
_defaultScriptsLocation = getCmdOption(argc, constArgv, scriptsSwitch.toStdString().c_str());
|
||||
|
||||
// Make sure we don't time out during slow operations at startup
|
||||
updateHeartbeat();
|
||||
|
@ -1777,11 +1783,27 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
}
|
||||
});
|
||||
|
||||
connect(offscreenUi.data(), &OffscreenUi::keyboardFocusActive, [this]() {
|
||||
#if !defined(Q_OS_ANDROID) && !defined(DISABLE_QML)
|
||||
// Do not show login dialog if requested not to on the command line
|
||||
QString hifiNoLoginCommandLineKey = QString("--").append(HIFI_NO_LOGIN_COMMAND_LINE_KEY);
|
||||
int index = arguments().indexOf(hifiNoLoginCommandLineKey);
|
||||
if (index != -1) {
|
||||
resumeAfterLoginDialogActionTaken();
|
||||
return;
|
||||
}
|
||||
|
||||
showLoginScreen();
|
||||
#else
|
||||
resumeAfterLoginDialogActionTaken();
|
||||
#endif
|
||||
});
|
||||
|
||||
// Make sure we don't time out during slow operations at startup
|
||||
updateHeartbeat();
|
||||
QTimer* settingsTimer = new QTimer();
|
||||
moveToNewNamedThread(settingsTimer, "Settings Thread", [this, settingsTimer]{
|
||||
// This needs to run on the settings thread, so we need to pass the `settingsTimer` as the
|
||||
// This needs to run on the settings thread, so we need to pass the `settingsTimer` as the
|
||||
// receiver object, otherwise it will run on the application thread and trigger a warning
|
||||
// about trying to kill the timer on the main thread.
|
||||
connect(qApp, &Application::beforeAboutToQuit, settingsTimer, [this, settingsTimer]{
|
||||
|
@ -2234,29 +2256,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
_snapshotSound = DependencyManager::get<SoundCache>()->getSound(PathUtils::resourcesUrl("sounds/snapshot/snap.wav"));
|
||||
|
||||
QVariant testProperty = property(hifi::properties::TEST);
|
||||
qDebug() << testProperty;
|
||||
if (testProperty.isValid()) {
|
||||
const auto testScript = property(hifi::properties::TEST).toUrl();
|
||||
|
||||
// Set last parameter to exit interface when the test script finishes, if so requested
|
||||
DependencyManager::get<ScriptEngines>()->loadScript(testScript, false, false, false, false, quitWhenFinished);
|
||||
|
||||
// This is done so we don't get a "connection time-out" message when we haven't passed in a URL.
|
||||
if (arguments().contains("--url")) {
|
||||
auto reply = SandboxUtils::getStatus();
|
||||
connect(reply, &QNetworkReply::finished, this, [this, reply] {
|
||||
handleSandboxStatus(reply);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
PROFILE_RANGE(render, "GetSandboxStatus");
|
||||
auto reply = SandboxUtils::getStatus();
|
||||
connect(reply, &QNetworkReply::finished, this, [this, reply] {
|
||||
handleSandboxStatus(reply);
|
||||
});
|
||||
}
|
||||
|
||||
// Monitor model assets (e.g., from Clara.io) added to the world that may need resizing.
|
||||
static const int ADD_ASSET_TO_WORLD_TIMER_INTERVAL_MS = 1000;
|
||||
_addAssetToWorldResizeTimer.setInterval(ADD_ASSET_TO_WORLD_TIMER_INTERVAL_MS); // 1s, Qt::CoarseTimer acceptable
|
||||
|
@ -2330,33 +2329,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
connect(&AndroidHelper::instance(), &AndroidHelper::enterBackground, this, &Application::enterBackground);
|
||||
connect(&AndroidHelper::instance(), &AndroidHelper::enterForeground, this, &Application::enterForeground);
|
||||
AndroidHelper::instance().notifyLoadComplete();
|
||||
#else
|
||||
#if !defined(DISABLE_QML)
|
||||
// Do not show login dialog if requested not to on the command line
|
||||
const QString HIFI_NO_LOGIN_COMMAND_LINE_KEY = "--no-login-suggestion";
|
||||
int index = arguments().indexOf(HIFI_NO_LOGIN_COMMAND_LINE_KEY);
|
||||
if (index == -1) {
|
||||
// request not found
|
||||
static int CHECK_LOGIN_TIMER = 3000;
|
||||
QTimer* checkLoginTimer = new QTimer(this);
|
||||
checkLoginTimer->setInterval(CHECK_LOGIN_TIMER);
|
||||
checkLoginTimer->setSingleShot(true);
|
||||
connect(checkLoginTimer, &QTimer::timeout, this, []() {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
||||
if (!accountManager->isLoggedIn()) {
|
||||
Setting::Handle<bool>{ "loginDialogPoppedUp", false }.set(true);
|
||||
dialogsManager->showLoginDialog();
|
||||
QJsonObject loginData = {};
|
||||
loginData["action"] = "login dialog shown";
|
||||
UserActivityLogger::getInstance().logAction("encourageLoginDialog", loginData);
|
||||
}
|
||||
});
|
||||
Setting::Handle<bool>{ "loginDialogPoppedUp", false }.set(false);
|
||||
checkLoginTimer->start();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
pauseUntilLoginDetermined();
|
||||
}
|
||||
|
||||
void Application::updateVerboseLogging() {
|
||||
|
@ -2496,7 +2470,7 @@ void Application::onAboutToQuit() {
|
|||
// so its persisted explicitly here
|
||||
Setting::Handle<QString>{ ACTIVE_DISPLAY_PLUGIN_SETTING_NAME }.set(getActiveDisplayPlugin()->getName());
|
||||
|
||||
Setting::Handle<bool>{"loginDialogPoppedUp", false}.set(false);
|
||||
loginDialogPoppedUp.set(false);
|
||||
|
||||
getActiveDisplayPlugin()->deactivate();
|
||||
if (_autoSwitchDisplayModeSupportedHMDPlugin
|
||||
|
@ -2664,7 +2638,7 @@ Application::~Application() {
|
|||
|
||||
// shutdown graphics engine
|
||||
_graphicsEngine.shutdown();
|
||||
|
||||
|
||||
_gameWorkload.shutdown();
|
||||
|
||||
DependencyManager::destroy<Preferences>();
|
||||
|
@ -2871,6 +2845,32 @@ extern void setupPreferences();
|
|||
static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, int index, bool active = false);
|
||||
#endif
|
||||
|
||||
void Application::showLoginScreen() {
|
||||
#if !defined(DISABLE_QML)
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
||||
if (!accountManager->isLoggedIn()) {
|
||||
if (!isHMDMode()) {
|
||||
auto toolbar = DependencyManager::get<ToolbarScriptingInterface>()->getToolbar("com.highfidelity.interface.toolbar.system");
|
||||
toolbar->writeProperty("visible", false);
|
||||
}
|
||||
_loginDialogPoppedUp = true;
|
||||
dialogsManager->showLoginDialog();
|
||||
emit loginDialogFocusEnabled();
|
||||
QJsonObject loginData = {};
|
||||
loginData["action"] = "login dialog shown";
|
||||
UserActivityLogger::getInstance().logAction("encourageLoginDialog", loginData);
|
||||
_window->setWindowTitle("High Fidelity Interface");
|
||||
} else {
|
||||
resumeAfterLoginDialogActionTaken();
|
||||
}
|
||||
_loginDialogPoppedUp = !accountManager->isLoggedIn();
|
||||
loginDialogPoppedUp.set(_loginDialogPoppedUp);
|
||||
#else
|
||||
resumeAfterLoginDialogActionTaken();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Application::initializeUi() {
|
||||
AddressBarDialog::registerType();
|
||||
ErrorDialog::registerType();
|
||||
|
@ -3017,8 +3017,7 @@ void Application::initializeUi() {
|
|||
auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins();
|
||||
// first sort the plugins into groupings: standard, advanced, developer
|
||||
std::stable_sort(displayPlugins.begin(), displayPlugins.end(),
|
||||
[](const DisplayPluginPointer& a, const DisplayPluginPointer& b)->bool { return a->getGrouping() < b->getGrouping(); });
|
||||
|
||||
[](const DisplayPluginPointer& a, const DisplayPluginPointer& b) -> bool { return a->getGrouping() < b->getGrouping(); });
|
||||
int dpIndex = 1;
|
||||
// concatenate the groupings into a single list in the order: standard, advanced, developer
|
||||
for(const auto& displayPlugin : displayPlugins) {
|
||||
|
@ -3032,6 +3031,7 @@ void Application::initializeUi() {
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
// The display plugins are created before the menu now, so we need to do this here to hide the menu bar
|
||||
// now that it exists
|
||||
if (_window && _window->isFullScreen()) {
|
||||
|
@ -3458,8 +3458,6 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
|
|||
bool isUsingHMD = _displayPlugin->isHmd();
|
||||
bool isUsingHMDAndHandControllers = hasHMD && hasHandControllers && isUsingHMD;
|
||||
|
||||
Setting::Handle<bool> firstRun{ Settings::firstRun, true };
|
||||
|
||||
qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMDAndHandControllers;
|
||||
|
||||
// when --url in command line, teleport to location
|
||||
|
@ -3481,12 +3479,12 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
|
|||
QString sentTo;
|
||||
|
||||
// If this is a first run we short-circuit the address passed in
|
||||
if (firstRun.get()) {
|
||||
if (_firstRun.get()) {
|
||||
#if !defined(Q_OS_ANDROID)
|
||||
DependencyManager::get<AddressManager>()->goToEntry();
|
||||
sentTo = SENT_TO_ENTRY;
|
||||
#endif
|
||||
firstRun.set(false);
|
||||
_firstRun.set(false);
|
||||
|
||||
} else {
|
||||
#if !defined(Q_OS_ANDROID)
|
||||
|
@ -3572,16 +3570,7 @@ void Application::setIsServerlessMode(bool serverlessDomain) {
|
|||
}
|
||||
}
|
||||
|
||||
void Application::loadServerlessDomain(QUrl domainURL, bool errorDomain) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "loadServerlessDomain", Q_ARG(QUrl, domainURL), Q_ARG(bool, errorDomain));
|
||||
return;
|
||||
}
|
||||
|
||||
if (domainURL.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<QString, QString> Application::prepareServerlessDomainContents(QUrl domainURL) {
|
||||
QUuid serverlessSessionID = QUuid::createUuid();
|
||||
getMyAvatar()->setSessionUUID(serverlessSessionID);
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
@ -3605,13 +3594,43 @@ void Application::loadServerlessDomain(QUrl domainURL, bool errorDomain) {
|
|||
tmpTree->sendEntities(&_entityEditSender, getEntities()->getTree(), 0, 0, 0);
|
||||
}
|
||||
|
||||
std::map<QString, QString> namedPaths = tmpTree->getNamedPaths();
|
||||
if (errorDomain) {
|
||||
nodeList->getDomainHandler().loadedErrorDomain(namedPaths);
|
||||
} else {
|
||||
nodeList->getDomainHandler().connectedToServerless(namedPaths);
|
||||
return tmpTree->getNamedPaths();
|
||||
|
||||
}
|
||||
|
||||
void Application::loadServerlessDomain(QUrl domainURL) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "loadServerlessDomain", Q_ARG(QUrl, domainURL));
|
||||
return;
|
||||
}
|
||||
|
||||
if (domainURL.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto namedPaths = prepareServerlessDomainContents(domainURL);
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
nodeList->getDomainHandler().connectedToServerless(namedPaths);
|
||||
|
||||
_fullSceneReceivedCounter++;
|
||||
}
|
||||
|
||||
void Application::loadErrorDomain(QUrl domainURL) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "loadErrorDomain", Q_ARG(QUrl, domainURL));
|
||||
return;
|
||||
}
|
||||
|
||||
if (domainURL.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto namedPaths = prepareServerlessDomainContents(domainURL);
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
nodeList->getDomainHandler().loadedErrorDomain(namedPaths);
|
||||
|
||||
_fullSceneReceivedCounter++;
|
||||
}
|
||||
|
||||
|
@ -3851,7 +3870,34 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (hasFocus()) {
|
||||
if (hasFocus() && getLoginDialogPoppedUp()) {
|
||||
if (_keyboardMouseDevice->isActive()) {
|
||||
_keyboardMouseDevice->keyReleaseEvent(event);
|
||||
}
|
||||
|
||||
bool isMeta = event->modifiers().testFlag(Qt::ControlModifier);
|
||||
bool isOption = event->modifiers().testFlag(Qt::AltModifier);
|
||||
switch (event->key()) {
|
||||
case Qt::Key_4:
|
||||
case Qt::Key_5:
|
||||
case Qt::Key_6:
|
||||
case Qt::Key_7:
|
||||
if (isMeta || isOption) {
|
||||
unsigned int index = static_cast<unsigned int>(event->key() - Qt::Key_1);
|
||||
auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins();
|
||||
if (index < displayPlugins.size()) {
|
||||
auto targetPlugin = displayPlugins.at(index);
|
||||
QString targetName = targetPlugin->getName();
|
||||
auto menu = Menu::getInstance();
|
||||
QAction* action = menu->getActionForOption(targetName);
|
||||
if (action && !action->isChecked()) {
|
||||
action->trigger();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (hasFocus()) {
|
||||
if (_keyboardMouseDevice->isActive()) {
|
||||
_keyboardMouseDevice->keyPressEvent(event);
|
||||
}
|
||||
|
@ -4378,7 +4424,7 @@ void Application::wheelEvent(QWheelEvent* event) const {
|
|||
_controllerScriptingInterface->emitWheelEvent(event); // send events to any registered scripts
|
||||
|
||||
// if one of our scripts have asked to capture this event, then stop processing it
|
||||
if (_controllerScriptingInterface->isWheelCaptured()) {
|
||||
if (_controllerScriptingInterface->isWheelCaptured() || getLoginDialogPoppedUp()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4973,9 +5019,8 @@ void Application::loadSettings() {
|
|||
}
|
||||
}
|
||||
|
||||
Setting::Handle<bool> firstRun { Settings::firstRun, true };
|
||||
bool isFirstPerson = false;
|
||||
if (firstRun.get()) {
|
||||
if (_firstRun.get()) {
|
||||
// If this is our first run, and no preferred devices were set, default to
|
||||
// an HMD device if available.
|
||||
auto displayPlugins = pluginManager->getDisplayPlugins();
|
||||
|
@ -5125,6 +5170,124 @@ void Application::init() {
|
|||
_entitySimulation->setWorkloadSpace(getEntities()->getWorkloadSpace());
|
||||
}
|
||||
|
||||
void Application::pauseUntilLoginDetermined() {
|
||||
if (QThread::currentThread() != qApp->thread()) {
|
||||
QMetaObject::invokeMethod(this, "pauseUntilLoginDetermined");
|
||||
return;
|
||||
}
|
||||
|
||||
getMyAvatar()->setEnableMeshVisible(false);
|
||||
_controllerScriptingInterface->disableMapping(STANDARD_TO_ACTION_MAPPING_NAME);
|
||||
|
||||
{
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
if (userInputMapper->loadMapping(NO_MOVEMENT_MAPPING_JSON)) {
|
||||
_controllerScriptingInterface->enableMapping(NO_MOVEMENT_MAPPING_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
const auto& nodeList = DependencyManager::get<NodeList>();
|
||||
// save interstitial mode setting until resuming.
|
||||
_interstitialModeEnabled = nodeList->getDomainHandler().getInterstitialModeEnabled();
|
||||
nodeList->getDomainHandler().setInterstitialModeEnabled(false);
|
||||
|
||||
auto menu = Menu::getInstance();
|
||||
menu->getMenu("Edit")->setVisible(false);
|
||||
menu->getMenu("View")->setVisible(false);
|
||||
menu->getMenu("Navigate")->setVisible(false);
|
||||
menu->getMenu("Settings")->setVisible(false);
|
||||
_developerMenuVisible = menu->getMenu("Developer")->isVisible();
|
||||
menu->setIsOptionChecked(MenuOption::Stats, false);
|
||||
if (_developerMenuVisible) {
|
||||
menu->getMenu("Developer")->setVisible(false);
|
||||
}
|
||||
_previousCameraMode = _myCamera.getMode();
|
||||
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
|
||||
cameraModeChanged();
|
||||
|
||||
// disconnect domain handler.
|
||||
nodeList->getDomainHandler().disconnect();
|
||||
|
||||
}
|
||||
|
||||
void Application::resumeAfterLoginDialogActionTaken() {
|
||||
if (QThread::currentThread() != qApp->thread()) {
|
||||
QMetaObject::invokeMethod(this, "resumeAfterLoginDialogActionTaken");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isHMDMode() && getDesktopTabletBecomesToolbarSetting()) {
|
||||
auto toolbar = DependencyManager::get<ToolbarScriptingInterface>()->getToolbar("com.highfidelity.interface.toolbar.system");
|
||||
toolbar->writeProperty("visible", true);
|
||||
} else {
|
||||
getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(true);
|
||||
getApplicationCompositor().getReticleInterface()->setVisible(true);
|
||||
}
|
||||
|
||||
updateSystemTabletMode();
|
||||
|
||||
{
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
userInputMapper->unloadMapping(NO_MOVEMENT_MAPPING_JSON);
|
||||
_controllerScriptingInterface->disableMapping(NO_MOVEMENT_MAPPING_NAME);
|
||||
}
|
||||
getMyAvatar()->setEnableMeshVisible(true);
|
||||
_controllerScriptingInterface->enableMapping(STANDARD_TO_ACTION_MAPPING_NAME);
|
||||
|
||||
const auto& nodeList = DependencyManager::get<NodeList>();
|
||||
nodeList->getDomainHandler().setInterstitialModeEnabled(_interstitialModeEnabled);
|
||||
{
|
||||
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
|
||||
// this will force the model the look at the correct directory (weird order of operations issue)
|
||||
scriptEngines->reloadLocalFiles();
|
||||
|
||||
if (!_defaultScriptsLocation.exists()) {
|
||||
scriptEngines->loadDefaultScripts();
|
||||
scriptEngines->defaultScriptsLocationOverridden(true);
|
||||
} else {
|
||||
scriptEngines->loadScripts();
|
||||
}
|
||||
}
|
||||
|
||||
if (_firstRun.get()) {
|
||||
// not first run anymore since action was taken.
|
||||
_firstRun.set(false);
|
||||
}
|
||||
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
auto addressManager = DependencyManager::get<AddressManager>();
|
||||
|
||||
// restart domain handler.
|
||||
nodeList->getDomainHandler().resetting();
|
||||
|
||||
if (!accountManager->isLoggedIn()) {
|
||||
addressManager->goToEntry();
|
||||
} else {
|
||||
QVariant testProperty = property(hifi::properties::TEST);
|
||||
if (testProperty.isValid()) {
|
||||
const auto testScript = property(hifi::properties::TEST).toUrl();
|
||||
// Set last parameter to exit interface when the test script finishes, if so requested
|
||||
DependencyManager::get<ScriptEngines>()->loadScript(testScript, false, false, false, false, quitWhenFinished);
|
||||
// This is done so we don't get a "connection time-out" message when we haven't passed in a URL.
|
||||
if (arguments().contains("--url")) {
|
||||
auto reply = SandboxUtils::getStatus();
|
||||
connect(reply, &QNetworkReply::finished, this, [this, reply] { handleSandboxStatus(reply); });
|
||||
}
|
||||
} else {
|
||||
addressManager->loadSettings();
|
||||
}
|
||||
}
|
||||
|
||||
auto menu = Menu::getInstance();
|
||||
menu->getMenu("Edit")->setVisible(true);
|
||||
menu->getMenu("View")->setVisible(true);
|
||||
menu->getMenu("Navigate")->setVisible(true);
|
||||
menu->getMenu("Settings")->setVisible(true);
|
||||
menu->getMenu("Developer")->setVisible(_developerMenuVisible);
|
||||
_myCamera.setMode(_previousCameraMode);
|
||||
cameraModeChanged();
|
||||
}
|
||||
|
||||
void Application::loadAvatarScripts(const QVector<QString>& urls) {
|
||||
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||
auto runningScripts = scriptEngines->getRunningScripts();
|
||||
|
@ -5439,6 +5602,9 @@ void Application::rotationModeChanged() const {
|
|||
|
||||
void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions) {
|
||||
// Create focus
|
||||
if (qApp->getLoginDialogPoppedUp()) {
|
||||
return;
|
||||
}
|
||||
if (_keyboardFocusHighlightID == UNKNOWN_OVERLAY_ID || !getOverlays().isAddedOverlay(_keyboardFocusHighlightID)) {
|
||||
_keyboardFocusHighlight = std::make_shared<Cube3DOverlay>();
|
||||
_keyboardFocusHighlight->setAlpha(1.0f);
|
||||
|
@ -5466,6 +5632,9 @@ QUuid Application::getKeyboardFocusEntity() const {
|
|||
static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f;
|
||||
|
||||
void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) {
|
||||
if (qApp->getLoginDialogPoppedUp()) {
|
||||
return;
|
||||
}
|
||||
if (_keyboardFocusedEntity.get() != entityItemID) {
|
||||
_keyboardFocusedEntity.set(entityItemID);
|
||||
|
||||
|
@ -5506,6 +5675,15 @@ OverlayID Application::getKeyboardFocusOverlay() {
|
|||
|
||||
void Application::setKeyboardFocusOverlay(const OverlayID& overlayID) {
|
||||
if (overlayID != _keyboardFocusedOverlay.get()) {
|
||||
if (qApp->getLoginDialogPoppedUp() && !_loginDialogOverlayID.isNull()) {
|
||||
if (overlayID == _loginDialogOverlayID) {
|
||||
emit loginDialogFocusEnabled();
|
||||
} else {
|
||||
// that's the only overlay we want in focus;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_keyboardFocusedOverlay.set(overlayID);
|
||||
|
||||
if (_keyboardFocusHighlight && _keyboardFocusedEntity.get() == UNKNOWN_ENTITY_ID) {
|
||||
|
@ -5769,7 +5947,6 @@ void Application::update(float deltaTime) {
|
|||
if (keyboardMousePlugin && keyboardMousePlugin->isActive()) {
|
||||
keyboardMousePlugin->pluginUpdate(deltaTime, calibrationData);
|
||||
}
|
||||
|
||||
// Transfer the user inputs to the driveKeys
|
||||
// FIXME can we drop drive keys and just have the avatar read the action states directly?
|
||||
myAvatar->clearDriveKeys();
|
||||
|
@ -6044,6 +6221,11 @@ void Application::update(float deltaTime) {
|
|||
|
||||
updateLOD(deltaTime);
|
||||
|
||||
if (!_loginDialogOverlayID.isNull()) {
|
||||
_loginStateManager.update(getMyAvatar()->getDominantHand(), _loginDialogOverlayID);
|
||||
updateLoginDialogOverlayPosition();
|
||||
}
|
||||
|
||||
// TODO: break these out into distinct perfTimers when they prove interesting
|
||||
{
|
||||
PROFILE_RANGE(app, "PickManager");
|
||||
|
@ -6609,12 +6791,11 @@ void Application::goToErrorDomainURL(QUrl errorDomainURL) {
|
|||
resetPhysicsReadyInformation();
|
||||
setIsServerlessMode(errorDomainURL.scheme() != URL_SCHEME_HIFI);
|
||||
if (isServerlessMode()) {
|
||||
loadServerlessDomain(errorDomainURL, true);
|
||||
loadErrorDomain(errorDomainURL);
|
||||
}
|
||||
updateWindowTitle();
|
||||
}
|
||||
|
||||
|
||||
void Application::resettingDomain() {
|
||||
_notifiedPacketVersionMismatchThisDomain = false;
|
||||
|
||||
|
@ -7268,7 +7449,7 @@ void Application::showScriptLogs() {
|
|||
}
|
||||
|
||||
void Application::showAssetServerWidget(QString filePath) {
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanWriteAssets()) {
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanWriteAssets() || getLoginDialogPoppedUp()) {
|
||||
return;
|
||||
}
|
||||
static const QUrl url { "hifi/AssetServer.qml" };
|
||||
|
@ -7904,6 +8085,9 @@ void Application::loadDomainConnectionDialog() {
|
|||
}
|
||||
|
||||
void Application::toggleLogDialog() {
|
||||
if (getLoginDialogPoppedUp()) {
|
||||
return;
|
||||
}
|
||||
if (! _logDialog) {
|
||||
_logDialog = new LogDialog(nullptr, getLogger());
|
||||
}
|
||||
|
@ -8436,6 +8620,102 @@ void Application::setShowBulletConstraintLimits(bool value) {
|
|||
_physicsEngine->setShowBulletConstraintLimits(value);
|
||||
}
|
||||
|
||||
void Application::createLoginDialogOverlay() {
|
||||
const glm::vec2 LOGIN_OVERLAY_DIMENSIONS{ 0.89f, 0.5f };
|
||||
const auto OVERLAY_OFFSET = glm::vec2(0.7f, -0.1f);
|
||||
auto cameraPosition = _myCamera.getPosition();
|
||||
auto cameraOrientation = _myCamera.getOrientation();
|
||||
auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y;
|
||||
auto headLookVec = (cameraOrientation * Vectors::FRONT);
|
||||
// DEFAULT_DPI / tablet scale percentage
|
||||
const float OVERLAY_DPI = 31.0f / (75.0f / 100.0f);
|
||||
auto offset = headLookVec * OVERLAY_OFFSET.x;
|
||||
auto overlayPosition = (cameraPosition + offset) + (upVec * OVERLAY_OFFSET.y);
|
||||
QVariantMap overlayProperties = {
|
||||
{ "name", "LoginDialogOverlay" },
|
||||
{ "url", OVERLAY_LOGIN_DIALOG },
|
||||
{ "position", vec3toVariant(overlayPosition) },
|
||||
{ "orientation", quatToVariant(cameraOrientation) },
|
||||
{ "isSolid", true },
|
||||
{ "grabbable", false },
|
||||
{ "ignorePickIntersection", false },
|
||||
{ "alpha", 1.0 },
|
||||
{ "dimensions", vec2ToVariant(LOGIN_OVERLAY_DIMENSIONS)},
|
||||
{ "dpi", OVERLAY_DPI },
|
||||
{ "visible", true }
|
||||
};
|
||||
auto& overlays = getOverlays();
|
||||
_loginDialogOverlayID = overlays.addOverlay("web3d", overlayProperties);
|
||||
auto loginOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlays.getOverlay(_loginDialogOverlayID));
|
||||
auto keyboard = DependencyManager::get<Keyboard>().data();
|
||||
if (!keyboard->getAnchorID().isNull() && !_loginDialogOverlayID.isNull()) {
|
||||
const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f);
|
||||
auto keyboardLocalOffset = glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f);
|
||||
QVariantMap properties {
|
||||
{ "position", vec3toVariant(loginOverlay->getWorldPosition() + keyboardLocalOffset) },
|
||||
{ "orientation", quatToVariant(loginOverlay->getWorldOrientation() * KEYBOARD_LOCAL_ORIENTATION) },
|
||||
};
|
||||
overlays.editOverlay(keyboard->getAnchorID(), properties);
|
||||
keyboard->setResetKeyboardPositionOnRaise(false);
|
||||
}
|
||||
setKeyboardFocusOverlay(_loginDialogOverlayID);
|
||||
emit loginDialogFocusEnabled();
|
||||
getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(false);
|
||||
getApplicationCompositor().getReticleInterface()->setVisible(false);
|
||||
if (!_loginStateManager.isSetUp()) {
|
||||
_loginStateManager.setUp();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::updateLoginDialogOverlayPosition() {
|
||||
const float LOOK_AWAY_THRESHOLD_ANGLE = 40.0f;
|
||||
const auto OVERLAY_OFFSET = glm::vec2(0.7f, -0.1f);
|
||||
auto& overlays = getOverlays();
|
||||
auto loginOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlays.getOverlay(_loginDialogOverlayID));
|
||||
auto overlayPositionVec = loginOverlay->getWorldPosition();
|
||||
auto cameraPositionVec = _myCamera.getPosition();
|
||||
auto cameraOrientation = cancelOutRollAndPitch(_myCamera.getOrientation());
|
||||
auto headLookVec = (cameraOrientation * Vectors::FRONT);
|
||||
auto overlayToHeadVec = overlayPositionVec - cameraPositionVec;
|
||||
auto pointAngle = (glm::acos(glm::dot(glm::normalize(overlayToHeadVec), glm::normalize(headLookVec))) * 180.0f / PI);
|
||||
auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y;
|
||||
auto offset = headLookVec * OVERLAY_OFFSET.x;
|
||||
auto newOverlayPositionVec = (cameraPositionVec + offset) + (upVec * OVERLAY_OFFSET.y);
|
||||
auto newOverlayOrientation = glm::inverse(glm::quat_cast(glm::lookAt(newOverlayPositionVec, cameraPositionVec, upVec))) * Quaternions::Y_180;
|
||||
|
||||
bool overlayOutOfBounds = glm::distance(overlayPositionVec, cameraPositionVec) > 1.0f;
|
||||
|
||||
if (pointAngle > LOOK_AWAY_THRESHOLD_ANGLE || overlayOutOfBounds) {
|
||||
QVariantMap properties {
|
||||
{"position", vec3toVariant(newOverlayPositionVec)},
|
||||
{"orientation", quatToVariant(newOverlayOrientation)}
|
||||
};
|
||||
overlays.editOverlay(_loginDialogOverlayID, properties);
|
||||
const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f);
|
||||
auto keyboardLocalOffset = glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f);
|
||||
QVariantMap keyboardProperties {
|
||||
{ "position", vec3toVariant(loginOverlay->getWorldPosition() + keyboardLocalOffset) },
|
||||
{ "orientation", quatToVariant(loginOverlay->getWorldOrientation() * KEYBOARD_LOCAL_ORIENTATION) },
|
||||
};
|
||||
auto keyboard = DependencyManager::get<Keyboard>().data();
|
||||
overlays.editOverlay(keyboard->getAnchorID(), keyboardProperties);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::onDismissedLoginDialog() {
|
||||
_loginDialogPoppedUp = false;
|
||||
loginDialogPoppedUp.set(false);
|
||||
auto keyboard = DependencyManager::get<Keyboard>().data();
|
||||
keyboard->setResetKeyboardPositionOnRaise(true);
|
||||
if (!_loginDialogOverlayID.isNull()) {
|
||||
// deleting overlay.
|
||||
getOverlays().deleteOverlay(_loginDialogOverlayID);
|
||||
_loginDialogOverlayID = OverlayID();
|
||||
_loginStateManager.tearDown();
|
||||
}
|
||||
resumeAfterLoginDialogActionTaken();
|
||||
}
|
||||
|
||||
void Application::setShowTrackedObjects(bool value) {
|
||||
_showTrackedObjects = value;
|
||||
}
|
||||
|
@ -8586,7 +8866,7 @@ void Application::updateThreadPoolCount() const {
|
|||
}
|
||||
|
||||
void Application::updateSystemTabletMode() {
|
||||
if (_settingsLoaded) {
|
||||
if (_settingsLoaded && !getLoginDialogPoppedUp()) {
|
||||
qApp->setProperty(hifi::properties::HMD, isHMDMode());
|
||||
if (isHMDMode()) {
|
||||
DependencyManager::get<TabletScriptingInterface>()->setToolbarMode(getHmdTabletBecomesToolbarSetting());
|
||||
|
@ -8612,7 +8892,7 @@ QUuid Application::getTabletFrameID() const {
|
|||
}
|
||||
|
||||
QVector<QUuid> Application::getTabletIDs() const {
|
||||
// Most important overlays first.
|
||||
// Most important overlays first.
|
||||
QVector<QUuid> result;
|
||||
auto HMD = DependencyManager::get<HMDScriptingInterface>();
|
||||
result << HMD->getCurrentTabletScreenID();
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "ConnectionMonitor.h"
|
||||
#include "CursorManager.h"
|
||||
#include "gpu/Context.h"
|
||||
#include "LoginStateManager.h"
|
||||
#include "Menu.h"
|
||||
#include "octree/OctreePacketProcessor.h"
|
||||
#include "render/Engine.h"
|
||||
|
@ -97,6 +98,7 @@ static const UINT UWM_SHOW_APPLICATION =
|
|||
|
||||
static const QString RUNNING_MARKER_FILENAME = "Interface.running";
|
||||
static const QString SCRIPTS_SWITCH = "scripts";
|
||||
static const QString HIFI_NO_LOGIN_COMMAND_LINE_KEY = "no-login-suggestion";
|
||||
|
||||
class Application;
|
||||
#if defined(qApp)
|
||||
|
@ -232,7 +234,7 @@ public:
|
|||
float getSettingConstrainToolbarPosition() { return _constrainToolbarPosition.get(); }
|
||||
void setSettingConstrainToolbarPosition(bool setting);
|
||||
|
||||
Q_INVOKABLE void setMinimumGPUTextureMemStabilityCount(int stabilityCount) { _minimumGPUTextureMemSizeStabilityCount = stabilityCount; }
|
||||
Q_INVOKABLE void setMinimumGPUTextureMemStabilityCount(int stabilityCount) { _minimumGPUTextureMemSizeStabilityCount = stabilityCount; }
|
||||
|
||||
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
|
||||
|
||||
|
@ -320,6 +322,10 @@ public:
|
|||
int getOtherAvatarsReplicaCount() { return DependencyManager::get<AvatarHashMap>()->getReplicaCount(); }
|
||||
void setOtherAvatarsReplicaCount(int count) { DependencyManager::get<AvatarHashMap>()->setReplicaCount(count); }
|
||||
|
||||
bool getLoginDialogPoppedUp() const { return _loginDialogPoppedUp; }
|
||||
void createLoginDialogOverlay();
|
||||
void updateLoginDialogOverlayPosition();
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
void beforeEnterBackground();
|
||||
void enterBackground();
|
||||
|
@ -338,7 +344,8 @@ signals:
|
|||
|
||||
void interstitialModeChanged(bool isInInterstitialMode);
|
||||
|
||||
void loginDialogPoppedUp();
|
||||
void loginDialogFocusEnabled();
|
||||
void loginDialogFocusDisabled();
|
||||
|
||||
void miniTabletEnabledChanged(bool enabled);
|
||||
|
||||
|
@ -362,6 +369,8 @@ public slots:
|
|||
|
||||
void showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const QString& name) const;
|
||||
|
||||
void showLoginScreen();
|
||||
|
||||
// FIXME: Move addAssetToWorld* methods to own class?
|
||||
void addAssetToWorldFromURL(QString url);
|
||||
void addAssetToWorldFromURLRequestFinished();
|
||||
|
@ -440,7 +449,10 @@ public slots:
|
|||
void setPreferredCursor(const QString& cursor);
|
||||
|
||||
void setIsServerlessMode(bool serverlessDomain);
|
||||
void loadServerlessDomain(QUrl domainURL, bool errorDomain = false);
|
||||
std::map<QString, QString> prepareServerlessDomainContents(QUrl domainURL);
|
||||
|
||||
void loadServerlessDomain(QUrl domainURL);
|
||||
void loadErrorDomain(QUrl domainURL);
|
||||
void setIsInterstitialMode(bool interstitialMode);
|
||||
|
||||
void updateVerboseLogging();
|
||||
|
@ -505,10 +517,14 @@ private slots:
|
|||
void setShowBulletConstraints(bool value);
|
||||
void setShowBulletConstraintLimits(bool value);
|
||||
|
||||
void onDismissedLoginDialog();
|
||||
|
||||
void setShowTrackedObjects(bool value);
|
||||
|
||||
private:
|
||||
void init();
|
||||
void pauseUntilLoginDetermined();
|
||||
void resumeAfterLoginDialogActionTaken();
|
||||
bool handleKeyEventForFocusedEntityOrOverlay(QEvent* event);
|
||||
bool handleFileOpenEvent(QFileOpenEvent* event);
|
||||
void cleanupBeforeQuit();
|
||||
|
@ -622,6 +638,7 @@ private:
|
|||
Setting::Handle<float> _fieldOfView;
|
||||
Setting::Handle<float> _hmdTabletScale;
|
||||
Setting::Handle<float> _desktopTabletScale;
|
||||
Setting::Handle<bool> _firstRun;
|
||||
Setting::Handle<bool> _desktopTabletBecomesToolbarSetting;
|
||||
Setting::Handle<bool> _hmdTabletBecomesToolbarSetting;
|
||||
Setting::Handle<bool> _preferStylusOverLaserSetting;
|
||||
|
@ -649,6 +666,7 @@ private:
|
|||
ControllerScriptingInterface* _controllerScriptingInterface{ nullptr };
|
||||
QPointer<LogDialog> _logDialog;
|
||||
QPointer<EntityScriptServerLogDialog> _entityScriptServerLogDialog;
|
||||
QDir _defaultScriptsLocation;
|
||||
|
||||
FileLogger* _logger;
|
||||
|
||||
|
@ -669,6 +687,13 @@ private:
|
|||
glm::uvec2 _renderResolution;
|
||||
|
||||
int _maxOctreePPS = DEFAULT_MAX_OCTREE_PPS;
|
||||
bool _interstitialModeEnabled{ false };
|
||||
|
||||
bool _loginDialogPoppedUp = false;
|
||||
bool _developerMenuVisible{ false };
|
||||
CameraMode _previousCameraMode;
|
||||
OverlayID _loginDialogOverlayID;
|
||||
LoginStateManager _loginStateManager;
|
||||
|
||||
quint64 _lastFaceTrackerUpdate;
|
||||
|
||||
|
|
241
interface/src/LoginStateManager.cpp
Normal file
|
@ -0,0 +1,241 @@
|
|||
//
|
||||
// LoginStateManager.cpp
|
||||
// interface/src
|
||||
//
|
||||
// Created by Wayne Chen on 11/5/18.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "LoginStateManager.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVariantMap>
|
||||
|
||||
#include <plugins/PluginUtils.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "controllers/StateController.h"
|
||||
#include "controllers/UserInputMapper.h"
|
||||
#include "raypick/PointerScriptingInterface.h"
|
||||
#include "raypick/RayPickScriptingInterface.h"
|
||||
#include "raypick/PickScriptingInterface.h"
|
||||
#include "scripting/ControllerScriptingInterface.h"
|
||||
|
||||
static const float SEARCH_SPHERE_SIZE = 0.0132f;
|
||||
static const QVariantMap SEARCH_SPHERE = {{"x", SEARCH_SPHERE_SIZE},
|
||||
{"y", SEARCH_SPHERE_SIZE},
|
||||
{"z", SEARCH_SPHERE_SIZE}};
|
||||
|
||||
static const int DEFAULT_SEARCH_SPHERE_DISTANCE = 1000; // how far from camera to search intersection?
|
||||
|
||||
static const QVariantMap COLORS_GRAB_SEARCHING_HALF_SQUEEZE = {{"red", 10},
|
||||
{"green", 10},
|
||||
{"blue", 255}};
|
||||
|
||||
static const QVariantMap COLORS_GRAB_SEARCHING_FULL_SQUEEZE = {{"red", 250},
|
||||
{"green", 10},
|
||||
{"blue", 10}};
|
||||
|
||||
static const QVariantMap COLORS_GRAB_DISTANCE_HOLD = {{"red", 238},
|
||||
{"green", 75},
|
||||
{"blue", 214}};
|
||||
|
||||
|
||||
|
||||
void LoginStateManager::tearDown() {
|
||||
auto pointers = DependencyManager::get<PointerManager>().data();
|
||||
if (pointers) {
|
||||
if (_leftLoginPointerID > PointerEvent::INVALID_POINTER_ID) {
|
||||
pointers->removePointer(_leftLoginPointerID);
|
||||
_leftLoginPointerID = PointerEvent::INVALID_POINTER_ID;
|
||||
}
|
||||
if (_rightLoginPointerID > PointerEvent::INVALID_POINTER_ID) {
|
||||
pointers->removePointer(_rightLoginPointerID);
|
||||
_rightLoginPointerID = PointerEvent::INVALID_POINTER_ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoginStateManager::setUp() {
|
||||
QVariantMap fullPathRenderState {
|
||||
{"type", "line3d"},
|
||||
{"color", COLORS_GRAB_SEARCHING_FULL_SQUEEZE},
|
||||
{"visible", true},
|
||||
{"alpha", 1.0f},
|
||||
{"solid", true},
|
||||
{"glow", 1.0f},
|
||||
{"ignoreRayIntersection", true}, // always ignore this
|
||||
{"drawInFront", true}, // Even when burried inside of something, show it.
|
||||
{"drawHUDLayer", false}
|
||||
};
|
||||
QVariantMap fullEndRenderState {
|
||||
{"type", "sphere"},
|
||||
{"dimensions", SEARCH_SPHERE},
|
||||
{"solid", true},
|
||||
{"color", COLORS_GRAB_SEARCHING_FULL_SQUEEZE},
|
||||
{"alpha", 0.9f},
|
||||
{"ignoreRayIntersection", true},
|
||||
{"drawInFront", true}, // Even when burried inside of something, show it.
|
||||
{"drawHUDLayer", false},
|
||||
{"visible", true}
|
||||
};
|
||||
QVariantMap halfPathRenderState {
|
||||
{"type", "line3d"},
|
||||
{"color", COLORS_GRAB_SEARCHING_HALF_SQUEEZE},
|
||||
{"visible", true},
|
||||
{"alpha", 1.0f},
|
||||
{"solid", true},
|
||||
{"glow", 1.0f},
|
||||
{"ignoreRayIntersection", true}, // always ignore this
|
||||
{"drawInFront", true}, // Even when burried inside of something, show it.
|
||||
{"drawHUDLayer", false}
|
||||
};
|
||||
QVariantMap halfEndRenderState {
|
||||
{"type", "sphere"},
|
||||
{"dimensions", SEARCH_SPHERE},
|
||||
{"solid", true},
|
||||
{"color", COLORS_GRAB_SEARCHING_HALF_SQUEEZE},
|
||||
{"alpha", 0.9f},
|
||||
{"ignoreRayIntersection", true},
|
||||
{"drawInFront", true}, // Even when burried inside of something, show it.
|
||||
{"drawHUDLayer", false},
|
||||
{"visible", true}
|
||||
};
|
||||
QVariantMap holdPathRenderState {
|
||||
{"type", "line3d"},
|
||||
{"color", COLORS_GRAB_DISTANCE_HOLD},
|
||||
{"visible", true},
|
||||
{"alpha", 1.0f},
|
||||
{"solid", true},
|
||||
{"glow", 1.0f},
|
||||
{"ignoreRayIntersection", true}, // always ignore this
|
||||
{"drawInFront", true}, // Even when burried inside of something, show it.
|
||||
{"drawHUDLayer", false},
|
||||
};
|
||||
QVariantMap halfRenderStateIdentifier {
|
||||
{"name", "half"},
|
||||
{"path", halfPathRenderState},
|
||||
{"end", halfEndRenderState}
|
||||
};
|
||||
QVariantMap fullRenderStateIdentifier {
|
||||
{"name", "full"},
|
||||
{"path", fullPathRenderState},
|
||||
{"end", fullEndRenderState}
|
||||
};
|
||||
QVariantMap holdRenderStateIdentifier {
|
||||
{"name", "hold"},
|
||||
{"path", holdPathRenderState},
|
||||
};
|
||||
|
||||
QVariantMap halfDefaultRenderStateIdentifier {
|
||||
{"name", "half"},
|
||||
{"distance", DEFAULT_SEARCH_SPHERE_DISTANCE},
|
||||
{"path", halfPathRenderState}
|
||||
};
|
||||
QVariantMap fullDefaultRenderStateIdentifier {
|
||||
{"name", "full"},
|
||||
{"distance", DEFAULT_SEARCH_SPHERE_DISTANCE},
|
||||
{"path", fullPathRenderState}
|
||||
};
|
||||
QVariantMap holdDefaultRenderStateIdentifier {
|
||||
{"name", "hold"},
|
||||
{"distance", DEFAULT_SEARCH_SPHERE_DISTANCE},
|
||||
{"path", holdPathRenderState}
|
||||
};
|
||||
|
||||
_renderStates = QList<QVariant>({halfRenderStateIdentifier, fullRenderStateIdentifier, holdRenderStateIdentifier});
|
||||
_defaultRenderStates = QList<QVariant>({halfDefaultRenderStateIdentifier, fullDefaultRenderStateIdentifier, holdDefaultRenderStateIdentifier});
|
||||
|
||||
auto pointers = DependencyManager::get<PointerScriptingInterface>();
|
||||
auto controller = DependencyManager::get<controller::ScriptingInterface>();
|
||||
|
||||
const glm::vec3 grabPointSphereOffsetLeft { -0.04f, 0.13f, 0.039f }; // x = upward, y = forward, z = lateral
|
||||
const glm::vec3 grabPointSphereOffsetRight { 0.04f, 0.13f, 0.039f }; // x = upward, y = forward, z = lateral
|
||||
const glm::vec3 malletOffset {glm::vec3(0.0f, 0.18f - 0.050f, 0.0f)};
|
||||
|
||||
QList<QVariant> leftPointerTriggerProperties;
|
||||
QVariantMap ltClick1 {
|
||||
{ "action", controller->getStandard()["LTClick"] },
|
||||
{ "button", "Focus" }
|
||||
};
|
||||
QVariantMap ltClick2 {
|
||||
{ "action", controller->getStandard()["LTClick"] },
|
||||
{ "button", "Primary" }
|
||||
};
|
||||
|
||||
leftPointerTriggerProperties = QList<QVariant>({ltClick1, ltClick2});
|
||||
const unsigned int leftHand = 0;
|
||||
QVariantMap leftPointerProperties {
|
||||
{ "joint", "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND" },
|
||||
{ "filter", PickScriptingInterface::PICK_OVERLAYS() },
|
||||
{ "triggers", leftPointerTriggerProperties },
|
||||
{ "posOffset", vec3toVariant(grabPointSphereOffsetLeft + malletOffset) },
|
||||
{ "hover", true },
|
||||
{ "scaleWithParent", true },
|
||||
{ "distanceScaleEnd", true },
|
||||
{ "hand", leftHand }
|
||||
};
|
||||
leftPointerProperties["renderStates"] = _renderStates;
|
||||
leftPointerProperties["defaultRenderStates"] = _defaultRenderStates;
|
||||
_leftLoginPointerID = pointers->createPointer(PickQuery::PickType::Ray, leftPointerProperties);
|
||||
pointers->setRenderState(_leftLoginPointerID, "");
|
||||
pointers->enablePointer(_leftLoginPointerID);
|
||||
const unsigned int rightHand = 1;
|
||||
QList<QVariant> rightPointerTriggerProperties;
|
||||
|
||||
QVariantMap rtClick1 {
|
||||
{ "action", controller->getStandard()["RTClick"] },
|
||||
{ "button", "Focus" }
|
||||
};
|
||||
QVariantMap rtClick2 {
|
||||
{ "action", controller->getStandard()["RTClick"] },
|
||||
{ "button", "Primary" }
|
||||
};
|
||||
rightPointerTriggerProperties = QList<QVariant>({rtClick1, rtClick2});
|
||||
QVariantMap rightPointerProperties{
|
||||
{ "joint", "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" },
|
||||
{ "filter", PickScriptingInterface::PICK_OVERLAYS() },
|
||||
{ "triggers", rightPointerTriggerProperties },
|
||||
{ "posOffset", vec3toVariant(grabPointSphereOffsetRight + malletOffset) },
|
||||
{ "hover", true },
|
||||
{ "scaleWithParent", true },
|
||||
{ "distanceScaleEnd", true },
|
||||
{ "hand", rightHand }
|
||||
};
|
||||
rightPointerProperties["renderStates"] = _renderStates;
|
||||
rightPointerProperties["defaultRenderStates"] = _defaultRenderStates;
|
||||
_rightLoginPointerID = pointers->createPointer(PickQuery::PickType::Ray, rightPointerProperties);
|
||||
pointers->setRenderState(_rightLoginPointerID, "");
|
||||
pointers->enablePointer(_rightLoginPointerID);
|
||||
}
|
||||
|
||||
void LoginStateManager::update(const QString dominantHand, const QUuid loginOverlayID) {
|
||||
if (!isSetUp()) {
|
||||
return;
|
||||
}
|
||||
if (_dominantHand != dominantHand) {
|
||||
_dominantHand = dominantHand;
|
||||
}
|
||||
auto pointers = DependencyManager::get<PointerScriptingInterface>();
|
||||
auto raypicks = DependencyManager::get<RayPickScriptingInterface>();
|
||||
if (pointers && raypicks) {
|
||||
const auto rightObjectID = raypicks->getPrevRayPickResult(_rightLoginPointerID)["objectID"].toUuid();
|
||||
const auto leftObjectID = raypicks->getPrevRayPickResult(_leftLoginPointerID)["objectID"].toUuid();
|
||||
const QString leftMode = (leftObjectID.isNull() || leftObjectID != loginOverlayID) ? "" : "full";
|
||||
const QString rightMode = (rightObjectID.isNull() || rightObjectID != loginOverlayID) ? "" : "full";
|
||||
pointers->setRenderState(_leftLoginPointerID, leftMode);
|
||||
pointers->setRenderState(_rightLoginPointerID, rightMode);
|
||||
if (_dominantHand == "left" && !leftObjectID.isNull()) {
|
||||
// dominant is left.
|
||||
pointers->setRenderState(_rightLoginPointerID, "");
|
||||
pointers->setRenderState(_leftLoginPointerID, leftMode);
|
||||
} else if (_dominantHand == "right" && !rightObjectID.isNull()) {
|
||||
// dominant is right.
|
||||
pointers->setRenderState(_leftLoginPointerID, "");
|
||||
pointers->setRenderState(_rightLoginPointerID, rightMode);
|
||||
}
|
||||
}
|
||||
}
|
41
interface/src/LoginStateManager.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// LoginStateManager.h
|
||||
// interface/src
|
||||
//
|
||||
// Created by Wayne Chen on 11/5/18.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_LoginStateManager_h
|
||||
#define hifi_LoginStateManager_h
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
#include <PointerEvent.h>
|
||||
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
class LoginStateManager : protected ReadWriteLockable {
|
||||
public:
|
||||
LoginStateManager() = default;
|
||||
~LoginStateManager() = default;
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
void update(const QString dominantHand, const QUuid loginOverlayID);
|
||||
|
||||
bool isSetUp() const { return (_leftLoginPointerID > PointerEvent::INVALID_POINTER_ID) && (_rightLoginPointerID > PointerEvent::INVALID_POINTER_ID); }
|
||||
|
||||
private:
|
||||
QString _dominantHand;
|
||||
QList<QVariant> _renderStates {};
|
||||
QList<QVariant> _defaultRenderStates {};
|
||||
unsigned int _leftLoginPointerID { PointerEvent::INVALID_POINTER_ID };
|
||||
unsigned int _rightLoginPointerID { PointerEvent::INVALID_POINTER_ID };
|
||||
};
|
||||
|
||||
#endif // hifi_LoginStateManager_h
|
|
@ -123,10 +123,12 @@ Menu::Menu() {
|
|||
// Edit > Running Scripts
|
||||
auto action = addActionToQMenuAndActionHash(editMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J);
|
||||
connect(action, &QAction::triggered, [] {
|
||||
static const QUrl widgetUrl("hifi/dialogs/RunningScripts.qml");
|
||||
static const QUrl tabletUrl("hifi/dialogs/TabletRunningScripts.qml");
|
||||
static const QString name("RunningScripts");
|
||||
qApp->showDialog(widgetUrl, tabletUrl, name);
|
||||
if (!qApp->getLoginDialogPoppedUp()) {
|
||||
static const QUrl widgetUrl("hifi/dialogs/RunningScripts.qml");
|
||||
static const QUrl tabletUrl("hifi/dialogs/TabletRunningScripts.qml");
|
||||
static const QString name("RunningScripts");
|
||||
qApp->showDialog(widgetUrl, tabletUrl, name);
|
||||
}
|
||||
});
|
||||
|
||||
editMenu->addSeparator();
|
||||
|
@ -241,8 +243,10 @@ Menu::Menu() {
|
|||
// Settings > General...
|
||||
action = addActionToQMenuAndActionHash(settingsMenu, MenuOption::Preferences, Qt::CTRL | Qt::Key_G, nullptr, nullptr);
|
||||
connect(action, &QAction::triggered, [] {
|
||||
qApp->showDialog(QString("hifi/dialogs/GeneralPreferencesDialog.qml"),
|
||||
QString("hifi/tablet/TabletGeneralPreferences.qml"), "GeneralPreferencesDialog");
|
||||
if (!qApp->getLoginDialogPoppedUp()) {
|
||||
qApp->showDialog(QString("hifi/dialogs/GeneralPreferencesDialog.qml"),
|
||||
QString("hifi/tablet/TabletGeneralPreferences.qml"), "GeneralPreferencesDialog");
|
||||
}
|
||||
});
|
||||
|
||||
// Settings > Controls...
|
||||
|
|
|
@ -413,6 +413,8 @@ public:
|
|||
QVariant getPlayAreaRect();
|
||||
QVector<glm::vec3> getSensorPositions();
|
||||
|
||||
glm::vec3 getPosition() const;
|
||||
|
||||
private:
|
||||
bool _showTablet { false };
|
||||
bool _tabletContextualMode { false };
|
||||
|
@ -426,9 +428,6 @@ private:
|
|||
int _miniTabletHand { -1 };
|
||||
bool _miniTabletEnabled { true };
|
||||
|
||||
// Get the position of the HMD
|
||||
glm::vec3 getPosition() const;
|
||||
|
||||
// Get the orientation of the HMD
|
||||
glm::quat getOrientation() const;
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define hifi_KeyboardScriptingInterface_h
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QUuid>
|
||||
|
||||
#include "DependencyManager.h"
|
||||
#include "ui/overlays/Overlay.h"
|
||||
|
|
|
@ -39,7 +39,7 @@ void DialogsManager::maybeCreateDialog(QPointer<T>& member) {
|
|||
Q_CHECK_PTR(parent);
|
||||
member = new T(parent);
|
||||
Q_CHECK_PTR(member);
|
||||
|
||||
|
||||
if (_hmdToolsDialog && member->windowHandle()) {
|
||||
_hmdToolsDialog->watchWindow(member->windowHandle());
|
||||
}
|
||||
|
@ -117,6 +117,10 @@ void DialogsManager::showLoginDialog() {
|
|||
LoginDialog::showWithSelection();
|
||||
}
|
||||
|
||||
void DialogsManager::hideLoginDialog() {
|
||||
LoginDialog::hide();
|
||||
}
|
||||
|
||||
void DialogsManager::showUpdateDialog() {
|
||||
UpdateDialog::show();
|
||||
}
|
||||
|
@ -203,4 +207,4 @@ void DialogsManager::showDomainConnectionDialog() {
|
|||
|
||||
_domainConnectionDialog->show();
|
||||
_domainConnectionDialog->raise();
|
||||
}
|
||||
}
|
|
@ -48,6 +48,7 @@ public slots:
|
|||
void setDomainConnectionFailureVisibility(bool visible);
|
||||
void toggleLoginDialog();
|
||||
void showLoginDialog();
|
||||
void hideLoginDialog();
|
||||
void octreeStatsDetails();
|
||||
void lodTools();
|
||||
void hmdTools(bool showTools);
|
||||
|
|
|
@ -340,8 +340,10 @@ void Keyboard::raiseKeyboardAnchor(bool raise) const {
|
|||
auto anchorOverlay = std::dynamic_pointer_cast<Cube3DOverlay>(overlays.getOverlay(anchorOverlayID));
|
||||
if (anchorOverlay) {
|
||||
std::pair<glm::vec3, glm::quat> keyboardLocation = calculateKeyboardPositionAndOrientation();
|
||||
anchorOverlay->setWorldPosition(keyboardLocation.first);
|
||||
anchorOverlay->setWorldOrientation(keyboardLocation.second);
|
||||
if (_resetKeyboardPositionOnRaise) {
|
||||
anchorOverlay->setWorldPosition(keyboardLocation.first);
|
||||
anchorOverlay->setWorldOrientation(keyboardLocation.second);
|
||||
}
|
||||
anchorOverlay->setVisible(raise);
|
||||
|
||||
QVariantMap textDisplayProperties {
|
||||
|
@ -442,6 +444,14 @@ void Keyboard::setPassword(bool password) {
|
|||
updateTextDisplay();
|
||||
}
|
||||
|
||||
void Keyboard::setResetKeyboardPositionOnRaise(bool reset) {
|
||||
if (_resetKeyboardPositionOnRaise != reset) {
|
||||
withWriteLock([&] {
|
||||
_resetKeyboardPositionOnRaise = reset;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Keyboard::setPreferMalletsOverLasers(bool preferMalletsOverLasers) {
|
||||
_preferMalletsOverLasersSettingLock.withWriteLock([&] {
|
||||
_preferMalletsOverLasers.set(preferMalletsOverLasers);
|
||||
|
@ -911,6 +921,13 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) {
|
|||
request->send();
|
||||
}
|
||||
|
||||
|
||||
OverlayID Keyboard::getAnchorID() {
|
||||
return _ignoreItemsLock.resultWithReadLock<OverlayID>([&] {
|
||||
return _anchor.overlayID;
|
||||
});
|
||||
}
|
||||
|
||||
bool Keyboard::shouldProcessOverlay(const OverlayID& overlayID) const {
|
||||
return (!_keyboardLayers.empty() && isLayerSwitchTimerFinished() && overlayID != _backPlate.overlayID);
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ public:
|
|||
void registerKeyboardHighlighting();
|
||||
bool isRaised() const;
|
||||
void setRaised(bool raised);
|
||||
|
||||
void setResetKeyboardPositionOnRaise(bool reset);
|
||||
bool isPassword() const;
|
||||
void setPassword(bool password);
|
||||
void enableRightMallet();
|
||||
|
@ -115,6 +115,7 @@ public:
|
|||
|
||||
void loadKeyboardFile(const QString& keyboardFile);
|
||||
QVector<OverlayID> getKeysID();
|
||||
OverlayID getAnchorID();
|
||||
|
||||
public slots:
|
||||
void handleTriggerBegin(const OverlayID& overlayID, const PointerEvent& event);
|
||||
|
@ -160,6 +161,7 @@ private:
|
|||
bool isLayerSwitchTimerFinished() const;
|
||||
|
||||
bool _raised { false };
|
||||
bool _resetKeyboardPositionOnRaise { true };
|
||||
bool _password { false };
|
||||
bool _capsEnabled { false };
|
||||
int _layerIndex { 0 };
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <plugins/PluginManager.h>
|
||||
#include <plugins/SteamClientPlugin.h>
|
||||
#include <shared/GlobalAppProperties.h>
|
||||
#include <ui/TabletScriptingInterface.h>
|
||||
#include <UserActivityLogger.h>
|
||||
|
||||
|
@ -31,24 +32,24 @@
|
|||
|
||||
HIFI_QML_DEF(LoginDialog)
|
||||
|
||||
static const QUrl TABLET_LOGIN_DIALOG_URL("dialogs/TabletLoginDialog.qml");
|
||||
const QUrl OVERLAY_LOGIN_DIALOG = PathUtils::qmlUrl("OverlayLoginDialog.qml");
|
||||
|
||||
LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent) {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
// the login hasn't been dismissed yet if the user isn't logged in and is encouraged to login.
|
||||
#if !defined(Q_OS_ANDROID)
|
||||
connect(accountManager.data(), &AccountManager::loginComplete,
|
||||
this, &LoginDialog::handleLoginCompleted);
|
||||
connect(accountManager.data(), &AccountManager::loginFailed,
|
||||
this, &LoginDialog::handleLoginFailed);
|
||||
connect(qApp, &Application::loginDialogFocusEnabled, this, &LoginDialog::focusEnabled);
|
||||
connect(qApp, &Application::loginDialogFocusDisabled, this, &LoginDialog::focusDisabled);
|
||||
connect(this, SIGNAL(dismissedLoginDialog()), qApp, SLOT(onDismissedLoginDialog()));
|
||||
#endif
|
||||
}
|
||||
|
||||
LoginDialog::~LoginDialog() {
|
||||
Setting::Handle<bool> loginDialogPoppedUp{ "loginDialogPoppedUp", false };
|
||||
if (loginDialogPoppedUp.get()) {
|
||||
QJsonObject data;
|
||||
data["action"] = "user opted out";
|
||||
UserActivityLogger::getInstance().logAction("encourageLoginDialog", data);
|
||||
}
|
||||
loginDialogPoppedUp.set(false);
|
||||
}
|
||||
|
||||
void LoginDialog::showWithSelection() {
|
||||
|
@ -56,14 +57,25 @@ void LoginDialog::showWithSelection() {
|
|||
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
||||
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||
|
||||
if (tablet->getToolbarMode()) {
|
||||
LoginDialog::show();
|
||||
} else {
|
||||
static const QUrl url("dialogs/TabletLoginDialog.qml");
|
||||
tablet->initialScreen(url);
|
||||
if (!hmd->getShouldShowTablet()) {
|
||||
hmd->openTablet();
|
||||
if (!qApp->isHMDMode()) {
|
||||
if (qApp->getLoginDialogPoppedUp()) {
|
||||
LoginDialog::show();
|
||||
return;
|
||||
} else {
|
||||
if (!tablet->isPathLoaded(TABLET_LOGIN_DIALOG_URL)) {
|
||||
tablet->loadQMLSource(TABLET_LOGIN_DIALOG_URL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!qApp->getLoginDialogPoppedUp()) {
|
||||
tablet->initialScreen(TABLET_LOGIN_DIALOG_URL);
|
||||
} else {
|
||||
qApp->createLoginDialogOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
if (!hmd->getShouldShowTablet()) {
|
||||
hmd->openTablet();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +94,7 @@ void LoginDialog::toggleAction() {
|
|||
connection = connect(loginAction, &QAction::triggered, accountManager.data(), &AccountManager::logout);
|
||||
} else {
|
||||
// change the menu item to login
|
||||
loginAction->setText("Login / Sign Up");
|
||||
loginAction->setText("Log In / Sign Up");
|
||||
connection = connect(loginAction, &QAction::triggered, [] { LoginDialog::showWithSelection(); });
|
||||
}
|
||||
}
|
||||
|
@ -92,6 +104,18 @@ bool LoginDialog::isSteamRunning() const {
|
|||
return steamClient && steamClient->isRunning();
|
||||
}
|
||||
|
||||
bool LoginDialog::isOculusStoreRunning() const {
|
||||
return qApp->property(hifi::properties::OCULUS_STORE).toBool();
|
||||
}
|
||||
|
||||
void LoginDialog::dismissLoginDialog() {
|
||||
QAction* loginAction = Menu::getInstance()->getActionForOption(MenuOption::Login);
|
||||
Q_CHECK_PTR(loginAction);
|
||||
loginAction->setEnabled(true);
|
||||
|
||||
emit dismissedLoginDialog();
|
||||
}
|
||||
|
||||
void LoginDialog::login(const QString& username, const QString& password) const {
|
||||
qDebug() << "Attempting to login " << username;
|
||||
DependencyManager::get<AccountManager>()->requestAccessToken(username, password);
|
||||
|
@ -138,7 +162,7 @@ void LoginDialog::linkSteam() {
|
|||
}
|
||||
}
|
||||
|
||||
void LoginDialog::createAccountFromStream(QString username) {
|
||||
void LoginDialog::createAccountFromSteam(QString username) {
|
||||
qDebug() << "Attempting to create account from Steam info";
|
||||
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
||||
steamClient->requestTicket([this, username](Ticket ticket) {
|
||||
|
@ -169,25 +193,7 @@ void LoginDialog::createAccountFromStream(QString username) {
|
|||
}
|
||||
|
||||
void LoginDialog::openUrl(const QString& url) const {
|
||||
auto tablet = dynamic_cast<TabletProxy*>(DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system"));
|
||||
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
|
||||
if (tablet->getToolbarMode()) {
|
||||
offscreenUi->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) {
|
||||
newObject->setProperty("url", url);
|
||||
});
|
||||
LoginDialog::hide();
|
||||
} else {
|
||||
if (!hmd->getShouldShowTablet() && !qApp->isHMDMode()) {
|
||||
offscreenUi->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) {
|
||||
newObject->setProperty("url", url);
|
||||
});
|
||||
LoginDialog::hide();
|
||||
} else {
|
||||
tablet->gotoWebScreen(url);
|
||||
}
|
||||
}
|
||||
QDesktopServices::openUrl(QUrl(url));
|
||||
}
|
||||
|
||||
void LoginDialog::linkCompleted(QNetworkReply* reply) {
|
||||
|
@ -233,6 +239,10 @@ void LoginDialog::signupCompleted(QNetworkReply* reply) {
|
|||
emit handleSignupCompleted();
|
||||
}
|
||||
|
||||
bool LoginDialog::getLoginDialogPoppedUp() const {
|
||||
return qApp->getLoginDialogPoppedUp();
|
||||
}
|
||||
|
||||
QString errorStringFromAPIObject(const QJsonValue& apiObject) {
|
||||
if (apiObject.isArray()) {
|
||||
return apiObject.toArray()[0].toString();
|
||||
|
|
|
@ -18,8 +18,11 @@
|
|||
|
||||
class QNetworkReply;
|
||||
|
||||
extern const QUrl OVERLAY_LOGIN_DIALOG;
|
||||
|
||||
class LoginDialog : public OffscreenQmlDialog {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool isLogIn READ getIsLogIn WRITE setIsLogIn)
|
||||
HIFI_QML_DECL
|
||||
|
||||
public:
|
||||
|
@ -40,31 +43,48 @@ signals:
|
|||
|
||||
void handleCreateCompleted();
|
||||
void handleCreateFailed(QString error);
|
||||
|
||||
|
||||
void handleSignupCompleted();
|
||||
void handleSignupFailed(QString errorString);
|
||||
|
||||
// occurs upon dismissing the encouraging log in.
|
||||
void dismissedLoginDialog();
|
||||
|
||||
void focusEnabled();
|
||||
void focusDisabled();
|
||||
|
||||
public slots:
|
||||
void linkCompleted(QNetworkReply* reply);
|
||||
void linkFailed(QNetworkReply* reply);
|
||||
|
||||
void createCompleted(QNetworkReply* reply);
|
||||
void createFailed(QNetworkReply* reply);
|
||||
|
||||
|
||||
void signupCompleted(QNetworkReply* reply);
|
||||
void signupFailed(QNetworkReply* reply);
|
||||
|
||||
protected slots:
|
||||
Q_INVOKABLE void dismissLoginDialog();
|
||||
|
||||
Q_INVOKABLE bool isSteamRunning() const;
|
||||
Q_INVOKABLE bool isOculusStoreRunning() const;
|
||||
|
||||
Q_INVOKABLE void login(const QString& username, const QString& password) const;
|
||||
Q_INVOKABLE void loginThroughSteam();
|
||||
Q_INVOKABLE void linkSteam();
|
||||
Q_INVOKABLE void createAccountFromStream(QString username = QString());
|
||||
|
||||
Q_INVOKABLE void createAccountFromSteam(QString username = QString());
|
||||
|
||||
Q_INVOKABLE void signup(const QString& email, const QString& username, const QString& password);
|
||||
|
||||
Q_INVOKABLE void openUrl(const QString& url) const;
|
||||
|
||||
Q_INVOKABLE bool getLoginDialogPoppedUp() const;
|
||||
|
||||
private:
|
||||
bool getIsLogIn() const { return _isLogIn; }
|
||||
void setIsLogIn(const bool isLogIn) { _isLogIn = isLogIn; }
|
||||
|
||||
bool _isLogIn{ false };
|
||||
};
|
||||
|
||||
#endif // hifi_LoginDialog_h
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
void StandAloneJSConsole::toggleConsole() {
|
||||
QMainWindow* mainWindow = qApp->getWindow();
|
||||
if (!_jsConsole) {
|
||||
if (!_jsConsole && !qApp->getLoginDialogPoppedUp()) {
|
||||
QDialog* dialog = new QDialog(mainWindow, Qt::WindowStaysOnTopHint);
|
||||
QVBoxLayout* layout = new QVBoxLayout(dialog);
|
||||
dialog->setLayout(layout);
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "avatar/AvatarManager.h"
|
||||
#include "AudioClient.h"
|
||||
#include "LODManager.h"
|
||||
#include "ui/LoginDialog.h"
|
||||
#include "ui/OctreeStatsProvider.h"
|
||||
#include "ui/DomainConnectionModel.h"
|
||||
#include "ui/AvatarInputs.h"
|
||||
|
@ -190,7 +191,7 @@ void Web3DOverlay::buildWebSurface() {
|
|||
} else {
|
||||
_webSurface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface(), qmlSurfaceDeleter);
|
||||
connect(_webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, [this](QQmlContext* surfaceContext) {
|
||||
setupQmlSurface(_url == TabletScriptingInterface::QML);
|
||||
setupQmlSurface(_url == TabletScriptingInterface::QML, _url == OVERLAY_LOGIN_DIALOG.toString());
|
||||
});
|
||||
_webSurface->load(_url);
|
||||
_cachedWebSurface = false;
|
||||
|
@ -221,7 +222,7 @@ bool Web3DOverlay::isWebContent() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
void Web3DOverlay::setupQmlSurface(bool isTablet) {
|
||||
void Web3DOverlay::setupQmlSurface(bool isTablet, bool isLoginDialog) {
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
|
||||
|
@ -232,6 +233,12 @@ void Web3DOverlay::setupQmlSurface(bool isTablet) {
|
|||
_webSurface->getSurfaceContext()->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
|
||||
|
||||
if (isTablet || isLoginDialog) {
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("KeyboardScriptingInterface", DependencyManager::get<KeyboardScriptingInterface>().data());
|
||||
}
|
||||
if (isTablet) {
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
auto flags = tabletScriptingInterface->getFlags();
|
||||
|
@ -239,7 +246,6 @@ void Web3DOverlay::setupQmlSurface(bool isTablet) {
|
|||
_webSurface->getSurfaceContext()->setContextProperty("offscreenFlags", flags);
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||
_webSurface->getSurfaceContext()->setContextProperty("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AccountServices", AccountServicesScriptingInterface::getInstance());
|
||||
|
||||
|
@ -261,8 +267,6 @@ void Web3DOverlay::setupQmlSurface(bool isTablet) {
|
|||
_webSurface->getSurfaceContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("InputConfiguration", DependencyManager::get<InputConfiguration>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("SoundCache", DependencyManager::get<SoundCacheScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Render", AbstractViewStateInterface::instance()->getRenderEngine()->getConfiguration().get());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Workload", qApp->getGameWorkload()._engine->getConfiguration().get());
|
||||
|
@ -274,7 +278,6 @@ void Web3DOverlay::setupQmlSurface(bool isTablet) {
|
|||
_webSurface->getSurfaceContext()->setContextProperty("HiFiAbout", AboutUtil::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("WalletScriptingInterface", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("KeyboardScriptingInterface", DependencyManager::get<KeyboardScriptingInterface>().data());
|
||||
|
||||
// Override min fps for tablet UI, for silky smooth scrolling
|
||||
setMaxFPS(90);
|
||||
|
@ -542,7 +545,7 @@ void Web3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
|
@ -567,7 +570,7 @@ void Web3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
* @property {string} url - The URL of the Web page to display.
|
||||
* @property {string} scriptURL="" - The URL of a JavaScript file to inject into the Web page.
|
||||
* @property {number} dpi=30 - The dots per inch to display the Web page at, on the overlay.
|
||||
* @property {Vec2} dimensions=1,1 - The size of the overlay to display the Web page on, in meters. Synonyms:
|
||||
* @property {Vec2} dimensions=1,1 - The size of the overlay to display the Web page on, in meters. Synonyms:
|
||||
* <code>scale</code>, <code>size</code>.
|
||||
* @property {number} maxFPS=10 - The maximum update rate for the Web overlay content, in frames/second.
|
||||
* @property {boolean} showKeyboardFocusHighlight=true - If <code>true</code>, the Web overlay is highlighted when it has
|
||||
|
|
|
@ -79,7 +79,7 @@ protected:
|
|||
Transform evalRenderTransform() override;
|
||||
|
||||
private:
|
||||
void setupQmlSurface(bool isTablet);
|
||||
void setupQmlSurface(bool isTablet, bool isLoginDialog);
|
||||
void rebuildWebSurface();
|
||||
bool isWebContent() const;
|
||||
|
||||
|
|
|
@ -321,6 +321,7 @@ void ScriptEngines::loadScripts() {
|
|||
|
||||
// loads all saved scripts
|
||||
auto runningScripts = runningScriptsHandle.get();
|
||||
|
||||
for (auto script : runningScripts) {
|
||||
auto string = script.toString();
|
||||
if (!string.isEmpty()) {
|
||||
|
|
|
@ -639,24 +639,28 @@ public:
|
|||
KeyboardFocusHack() {
|
||||
Q_ASSERT(_mainWindow);
|
||||
QTimer::singleShot(200, [=] {
|
||||
_hackWindow = new QWindow();
|
||||
_hackWindow->setFlags(Qt::FramelessWindowHint);
|
||||
_hackWindow->setGeometry(_mainWindow->x(), _mainWindow->y(), 10, 10);
|
||||
_hackWindow->show();
|
||||
_hackWindow->requestActivate();
|
||||
_window = new QWindow();
|
||||
_window->setFlags(Qt::FramelessWindowHint);
|
||||
_window->setGeometry(_mainWindow->x(), _mainWindow->y(), 10, 10);
|
||||
_window->show();
|
||||
_window->requestActivate();
|
||||
QTimer::singleShot(200, [=] {
|
||||
_hackWindow->hide();
|
||||
_hackWindow->deleteLater();
|
||||
_hackWindow = nullptr;
|
||||
_window->hide();
|
||||
_window->deleteLater();
|
||||
_window = nullptr;
|
||||
_mainWindow->requestActivate();
|
||||
emit keyboardFocusActive();
|
||||
this->deleteLater();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
signals:
|
||||
void keyboardFocusActive();
|
||||
|
||||
private:
|
||||
QWindow* const _mainWindow { MainWindow::findMainWindow() };
|
||||
QWindow* _hackWindow { nullptr };
|
||||
QWindow* _window { nullptr };
|
||||
};
|
||||
|
||||
void OffscreenUi::createDesktop(const QUrl& url) {
|
||||
|
@ -675,9 +679,10 @@ void OffscreenUi::createDesktop(const QUrl& url) {
|
|||
menuInitializer(_vrMenu);
|
||||
}
|
||||
|
||||
new KeyboardFocusHack();
|
||||
auto keyboardFocus = new KeyboardFocusHack();
|
||||
connect(_desktop, SIGNAL(showDesktop()), this, SIGNAL(showDesktop()));
|
||||
emit desktopReady();
|
||||
connect(keyboardFocus, SIGNAL(keyboardFocusActive()), this, SIGNAL(keyboardFocusActive()));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -244,6 +244,7 @@ signals:
|
|||
// void assetDialogResponse(QString response);
|
||||
// void inputDialogResponse(QVariant response);
|
||||
void desktopReady();
|
||||
void keyboardFocusActive();
|
||||
|
||||
public slots:
|
||||
void removeModalDialog(QObject* modal);
|
||||
|
|
|
@ -554,6 +554,14 @@ void MenuWrapper::setEnabled(bool enabled) {
|
|||
_realMenu->setEnabled(enabled);
|
||||
}
|
||||
|
||||
bool MenuWrapper::isVisible() {
|
||||
return _realMenu->menuAction()->isVisible();
|
||||
}
|
||||
|
||||
void MenuWrapper::setVisible(bool visible) {
|
||||
_realMenu->menuAction()->setVisible(visible);
|
||||
}
|
||||
|
||||
QAction* MenuWrapper::addSeparator() {
|
||||
QAction* action = _realMenu->addSeparator();
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
|
|
|
@ -29,6 +29,9 @@ public:
|
|||
QList<QAction*> actions();
|
||||
MenuWrapper* addMenu(const QString& menuName);
|
||||
void setEnabled(bool enabled = true);
|
||||
|
||||
bool isVisible();
|
||||
void setVisible(bool visible = true);
|
||||
QAction* addSeparator();
|
||||
void addAction(QAction* action);
|
||||
|
||||
|
|
|
@ -377,12 +377,8 @@ function deleteSendMoneyParticleEffect() {
|
|||
}
|
||||
|
||||
function onUsernameChanged() {
|
||||
if (Account.username !== Settings.getValue("keepMeLoggedIn/savedUsername")) {
|
||||
Settings.setValue("keepMeLoggedIn", false);
|
||||
Settings.setValue("keepMeLoggedIn/savedUsername", "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var MARKETPLACES_INJECT_SCRIPT_URL = Script.resolvePath("../html/js/marketplacesInject.js");
|
||||
var METAVERSE_SERVER_URL = Account.metaverseServerURL;
|
||||
var MARKETPLACE_URL_INITIAL = MARKETPLACE_URL + "?"; // Append "?" to signal injected script that it's the initial page.
|
||||
|
|
|
@ -1989,7 +1989,7 @@ function focusKey(value) {
|
|||
if (value === 0) { // on release
|
||||
cameraManager.enable();
|
||||
if (selectionManager.hasSelection()) {
|
||||
cameraManager.focus(selectionManager.worldPosition, selectionManager.worldDimensions,
|
||||
cameraManager.focus(selectionManager.worldPosition, selectionManager.worldDimensions,
|
||||
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
|
||||
}
|
||||
}
|
||||
|
@ -2239,7 +2239,7 @@ var PropertiesTool = function (opts) {
|
|||
};
|
||||
|
||||
that.setVisible(false);
|
||||
|
||||
|
||||
function emitScriptEvent(data) {
|
||||
var dataString = JSON.stringify(data);
|
||||
webView.emitScriptEvent(dataString);
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
var TEXTURE_EPSILON = 0.01;
|
||||
var isVisible = false;
|
||||
var VOLUME = 0.4;
|
||||
var tune = SoundCache.getSound(Script.resolvePath("/~/system/assets/sounds/crystals_and_voices.mp3"));
|
||||
var tune = SoundCache.getSound(Script.resourcesPath() + "sounds/crystals_and_voices.mp3");
|
||||
var sample = null;
|
||||
var MAX_LEFT_MARGIN = 1.9;
|
||||
var INNER_CIRCLE_WIDTH = 4.7;
|
||||
|
|