Merge branch 'tablet-ui' into feature/can-touch-this
|
@ -241,6 +241,7 @@ void AudioMixer::sendStatsPacket() {
|
|||
|
||||
statsObject["avg_streams_per_frame"] = (float)_stats.sumStreams / (float)_numStatFrames;
|
||||
statsObject["avg_listeners_per_frame"] = (float)_stats.sumListeners / (float)_numStatFrames;
|
||||
statsObject["avg_listeners_(silent)_per_frame"] = (float)_stats.sumListenersSilent / (float)_numStatFrames;
|
||||
|
||||
statsObject["silent_packets_per_frame"] = (float)_numSilentPackets / (float)_numStatFrames;
|
||||
|
||||
|
|
|
@ -106,6 +106,7 @@ void AudioMixerSlave::mix(const SharedNodePointer& node) {
|
|||
|
||||
sendMixPacket(node, *data, encodedBuffer);
|
||||
} else {
|
||||
++stats.sumListenersSilent;
|
||||
sendSilentPacket(node, *data);
|
||||
}
|
||||
|
||||
|
@ -221,17 +222,19 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) {
|
|||
stats.mixTime += mixTime.count();
|
||||
#endif
|
||||
|
||||
// use the per listener AudioLimiter to render the mixed data...
|
||||
listenerData->audioLimiter.render(_mixSamples, _bufferSamples, AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
|
||||
|
||||
// check for silent audio after the peak limiter has converted the samples
|
||||
// check for silent audio before limiting
|
||||
// limiting uses a dither and can only guarantee abs(sample) <= 1
|
||||
bool hasAudio = false;
|
||||
for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; ++i) {
|
||||
if (_bufferSamples[i] != 0) {
|
||||
if (_mixSamples[i] != 0.0f) {
|
||||
hasAudio = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// use the per listener AudioLimiter to render the mixed data
|
||||
listenerData->audioLimiter.render(_mixSamples, _bufferSamples, AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
|
||||
|
||||
return hasAudio;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
void AudioMixerStats::reset() {
|
||||
sumStreams = 0;
|
||||
sumListeners = 0;
|
||||
sumListenersSilent = 0;
|
||||
totalMixes = 0;
|
||||
hrtfRenders = 0;
|
||||
hrtfSilentRenders = 0;
|
||||
|
@ -28,6 +29,7 @@ void AudioMixerStats::reset() {
|
|||
void AudioMixerStats::accumulate(const AudioMixerStats& otherStats) {
|
||||
sumStreams += otherStats.sumStreams;
|
||||
sumListeners += otherStats.sumListeners;
|
||||
sumListenersSilent += otherStats.sumListenersSilent;
|
||||
totalMixes += otherStats.totalMixes;
|
||||
hrtfRenders += otherStats.hrtfRenders;
|
||||
hrtfSilentRenders += otherStats.hrtfSilentRenders;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
struct AudioMixerStats {
|
||||
int sumStreams { 0 };
|
||||
int sumListeners { 0 };
|
||||
int sumListenersSilent { 0 };
|
||||
|
||||
int totalMixes { 0 };
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ macro(LINK_HIFI_LIBRARIES)
|
|||
include_directories("${HIFI_LIBRARY_DIR}/${HIFI_LIBRARY}/src")
|
||||
include_directories("${CMAKE_BINARY_DIR}/libraries/${HIFI_LIBRARY}/shaders")
|
||||
|
||||
add_dependencies(${TARGET_NAME} ${HIFI_LIBRARY})
|
||||
#add_dependencies(${TARGET_NAME} ${HIFI_LIBRARY})
|
||||
|
||||
# link the actual library - it is static so don't bubble it up
|
||||
target_link_libraries(${TARGET_NAME} ${HIFI_LIBRARY})
|
||||
|
|
26
interface/resources/icons/create-icons/20-text-01.svg
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:#000000;stroke-width:18;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:#000000;stroke-width:18;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:#000000;stroke-width:19;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M220.3,378.4l-81.1-232c-1-2.8-3.6-4.3-6.6-4.3h-9.2c-3,0-5.6,1.5-6.6,4.3L34,378.5c-0.8,2.1-0.4,5.1,0.9,7
|
||||
c1.3,1.9,3.4,3.5,5.7,3.5h15.9c3,0,5.6-2.6,6.6-5.4L90.2,305h73.7l27,78.6c1,2.8,3.6,5.4,6.6,5.4h16.2c2.3,0,4.4-1.8,5.7-3.6
|
||||
C220.7,383.5,221.1,380.5,220.3,378.4z M100.3,276l25.6-73.1c0.6-1.7,1.3-3.3,1.9-5.1c0.6,1.8,1.2,3,1.7,4.5l24.9,73.7H100.3z"/>
|
||||
<path d="M351.6,215.5c-9.7-11.4-24.3-17.2-43.2-17.2c-17.5,0-35.5,4.7-53.2,14.1c-3.1,1.7-4.6,5.4-3.3,8.7l5.2,13.6
|
||||
c0.7,1.9,2.3,3.4,4.2,4.1c1.9,0.7,4.1,0.5,5.8-0.6c14.1-8.2,27.7-12.3,40.6-12.3c10.9,0,18.8,3.2,23.3,9.6c5.2,7.3,8,18.4,8,33
|
||||
v4.6l-22.7,0.7c-25,0.6-44.7,6-58.2,16.1c-14.3,10.7-21.6,25.7-21.6,44.7c0,17.1,4.9,30.9,14.5,40.8c9.7,10,23.2,15.1,40.1,15.1
|
||||
c12,0,22.8-2.7,32.2-8c5.6-3.1,11.1-7.7,16.4-13.6l1.6,13.3c0.4,3.5,3.4,6.8,6.9,6.8h10.2c3.9,0,7.6-4.4,7.6-8.3V265.9
|
||||
C366,243.2,361.1,226.7,351.6,215.5z M265.1,335.2c0-11.2,3.5-19.1,10.7-24.1c8-5.6,22.1-9,42-10.1l19.1-0.9v9.6
|
||||
c0,17.2-3.8,29.9-12,39.1c-8.1,9-19,13.4-33.3,13.4c-8.8,0-15.3-2.2-19.8-6.9C267.3,350.8,265.1,344.2,265.1,335.2z"/>
|
||||
<path d="M451.3,439.9c-10,0-15.3-8.1-15.3-18c-0.1-22.2-0.2-298.2-0.4-320.4c-0.1-10,5.2-18.2,15.2-18.3c0.1,0,0.1,0,0.2,0
|
||||
c9.9,0,15.2,8,15.3,18c0.2,22.2,0.3,298.3,0.4,320.5C466.7,431.7,461.4,439.9,451.3,439.9C451.4,439.9,451.3,439.9,451.3,439.9z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2 KiB |
17
interface/resources/icons/create-icons/21-cube-01.svg
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:#000000;stroke-width:18;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:#000000;stroke-width:18;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:#000000;stroke-width:19;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<g>
|
||||
<path d="M451.6,90.8L189.4,64.9c-3.2-0.3-6.2,0.5-8.8,2.4l0.1,0L54.9,155.4l0,0c-0.5,0.3-0.5,0.7-0.9,1c-2.8,2.5-4,6.1-4,9.9v262.5
|
||||
c0,6.8,4.8,12.6,11.6,13.2l262.3,25.9c0.4,0,0.8,0.1,1.2,0.1c2.7,0,5.3-0.9,7.6-2.4l0,0l125.8-88.2l0,0c0.5-0.3,0.3-0.7,0.7-1
|
||||
c2.8-2.5,3.8-6.1,3.8-9.9V104.1C463,97.2,458.4,91.5,451.6,90.8z M430.1,364.7l-1.8,1.4c-0.2,0.1-0.3,0.3-0.6,0.4c0,0,0.4,0,0.4,0
|
||||
L339,429.2v-230l98-69.5v222.2C436,358,435,361.1,430.1,364.7z M203.3,93l210.6,20.8l-92.4,64.7L99.6,156.6l86.7-60.8
|
||||
c0.2,0,0.3,0,0.5,0c0,0,0,0,0.1,0c3.4-2.1,7.4-3.4,11.4-3.4C200,92.4,201.7,92.6,203.3,93z M313,440L76,416.7V181l237,23.3V440z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
21
interface/resources/icons/create-icons/22-sphere-01.svg
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:#000000;stroke-width:18;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:#000000;stroke-width:18;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:#000000;stroke-width:19;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<g>
|
||||
<path d="M417.6,96.6c-90.2-90.2-236.9-90.2-327.1,0c-43.7,43.7-67.8,101.8-67.8,163.6c0,61.8,24.1,119.9,67.8,163.6
|
||||
c45.1,45.1,104.3,67.6,163.6,67.6c59.2,0,118.5-22.5,163.6-67.6c43.7-43.7,67.8-101.8,67.8-163.6
|
||||
C485.4,198.4,461.3,140.3,417.6,96.6z M112.7,118.8c30-30,67.2-48.4,106.1-55.3c-7.4,11.3-14,26-19.8,44
|
||||
c-13.2,41.4-20.5,96.3-20.5,154.5c0,2.8,0,7,0.1,9.8c6.4,1.6,12.8,1.7,19.3,2.8c1.9,0.3,3.9,0.6,5.9,0.8c-0.1-4.4-0.1-8.8-0.1-13.3
|
||||
c0-116.9,30-193.4,52.3-200c0.5-0.5,1-1,1.4-1.6c50.1,0.8,99.9,20.3,138,58.4c36.6,36.6,57.3,85,58.5,136.6
|
||||
c-4.8,22.4-81.7,53.2-200.2,53.2c-115.3,0-191.3-29.1-199.6-51.4C54.9,204.9,75.6,155.9,112.7,118.8z M395.5,401.6
|
||||
C356,441.1,304,460.5,252.1,460c-14.1-8.9-30.3-43.3-39.9-96.6l-25.6-1.4c3.2,19.2,7.4,38.5,12.5,54.3c5.1,16,10.9,29.4,17.3,40.1
|
||||
c-38-7.2-74.3-25.5-103.7-54.9C83.2,372.1,64,334.9,57.1,294.6c11,6.9,25.2,13.2,42.3,18.7c41.4,13.2,96.3,20.5,154.5,20.5
|
||||
c58.2,0,113-7.3,154.5-20.5c17.4-5.6,31.7-11.9,42.9-19C444.2,334.7,425.1,372,395.5,401.6z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
38
interface/resources/icons/create-icons/23-zone-01.svg
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:#000000;stroke-width:18;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:#000000;stroke-width:18;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:#000000;stroke-width:19;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<g>
|
||||
<path d="M380.7,139.8c-2.7-6.6-9.2-10.8-16.3-10.8H292v34h29.9L159,326.1V290h-36v79h1.3c0.1,2,0.5,4.1,1.3,5.9
|
||||
c2.7,6.6,9.1,11.1,16.2,11.1H225v-35h-40.8L346,189.7V215h35v-62.4C382,148.5,382.4,144,380.7,139.8z"/>
|
||||
<path d="M338.4,437.6c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0
|
||||
C348.1,459.3,338.4,449.6,338.4,437.6z M266.9,437.6c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0
|
||||
c0,12-9.7,21.7-21.7,21.7l0,0C276.6,459.3,266.9,449.6,266.9,437.6z M195.4,437.6c0-12,9.7-21.7,21.7-21.7l0,0
|
||||
c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0C205.1,459.3,195.4,449.6,195.4,437.6z M123.9,437.6
|
||||
c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0C133.6,459.3,123.9,449.6,123.9,437.6z"/>
|
||||
<path d="M74.1,459.3c-5.7,0-11.3-2.3-15.4-6.4c-4-4-6.4-9.6-6.4-15.3c0-5.7,2.3-11.3,6.4-15.3c4-4,9.6-6.4,15.4-6.4
|
||||
c5.7,0,11.3,2.3,15.3,6.4c4,4,6.4,9.6,6.4,15.3c0,5.7-2.3,11.3-6.4,15.3C85.4,457,79.8,459.3,74.1,459.3z"/>
|
||||
<path d="M52.4,366.1c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0
|
||||
C62.1,387.8,52.4,378,52.4,366.1z M52.4,294.6c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7
|
||||
l0,0C62.1,316.3,52.4,306.5,52.4,294.6z M52.4,223.1c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0
|
||||
c0,12-9.7,21.7-21.7,21.7l0,0C62.1,244.8,52.4,235,52.4,223.1z M52.4,151.5c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7
|
||||
l0,0c0,12-9.7,21.7-21.7,21.7l0,0C62.1,173.2,52.4,163.5,52.4,151.5z"/>
|
||||
<path d="M338.4,80c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0
|
||||
C348.1,101.7,338.4,92,338.4,80z M266.9,80c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0
|
||||
C276.6,101.7,266.9,92,266.9,80z M195.4,80c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0
|
||||
C205.1,101.7,195.4,92,195.4,80z M123.9,80c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0
|
||||
C133.6,101.7,123.9,92,123.9,80z"/>
|
||||
<path d="M431.6,101.7c-5.7,0-11.3-2.3-15.3-6.4c-4-4-6.4-9.6-6.4-15.3c0-5.7,2.3-11.3,6.4-15.3c4-4,9.6-6.4,15.3-6.4
|
||||
s11.3,2.3,15.3,6.4c4,4,6.4,9.6,6.4,15.3c0,5.7-2.3,11.3-6.4,15.3C442.9,99.4,437.4,101.7,431.6,101.7z"/>
|
||||
<path d="M409.9,366.1c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0
|
||||
C419.7,387.8,409.9,378.1,409.9,366.1z M409.9,294.6c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0
|
||||
c0,12-9.7,21.7-21.7,21.7l0,0C419.7,316.3,409.9,306.5,409.9,294.6z M409.9,223.1c0-12,9.7-21.7,21.7-21.7l0,0
|
||||
c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0C419.7,244.7,409.9,235,409.9,223.1z M409.9,151.5
|
||||
c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0C419.7,173.2,409.9,163.5,409.9,151.5z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
34
interface/resources/icons/create-icons/24-light-01.svg
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:#000000;stroke-width:18;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:#000000;stroke-width:18;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:#000000;stroke-width:19;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<g>
|
||||
<circle cx="259.2" cy="252.5" r="38.3"/>
|
||||
<path d="M259.2,361.8c-60.3,0-109.3-49-109.3-109.3s49-109.3,109.3-109.3s109.3,49,109.3,109.3S319.4,361.8,259.2,361.8z
|
||||
M259.2,171.8c-44.5,0-80.7,36.2-80.7,80.7s36.2,80.7,80.7,80.7s80.7-36.2,80.7-80.7S303.7,171.8,259.2,171.8z"/>
|
||||
<path d="M414.1,268.5c-7.9,0-14.2-6.4-14.3-14.2c0-7.9,6.3-14.3,14.2-14.3c17.1-0.1,34.5-0.2,51.6-0.3c0,0,0.1,0,0.1,0
|
||||
c7.8,0,14.2,6.3,14.3,14.2c0.1,7.9-6.3,14.3-14.2,14.4C448.8,268.3,431.4,268.4,414.1,268.5C414.2,268.5,414.1,268.5,414.1,268.5z"
|
||||
/>
|
||||
<path d="M105.8,268.5C105.8,268.5,105.8,268.5,105.8,268.5c-17.3-0.1-34.6-0.2-51.7-0.4c-7.9-0.1-14.2-6.5-14.1-14.4
|
||||
c0.1-7.8,6.5-14.1,14.3-14.1c0.1,0,0.1,0,0.2,0c17,0.2,34.3,0.3,51.5,0.4c7.9,0,14.3,6.5,14.2,14.3
|
||||
C120.1,262.2,113.7,268.5,105.8,268.5z"/>
|
||||
<path d="M369.1,159.5c-3.6,0-7.3-1.4-10-4.1c-5.6-5.6-5.6-14.6-0.1-20.2c12-12.1,24.2-24.5,36.3-36.7c5.5-5.6,14.6-5.7,20.2-0.2
|
||||
c5.6,5.5,5.7,14.6,0.2,20.2c-12.1,12.3-24.3,24.7-36.4,36.8C376.4,158.1,372.8,159.5,369.1,159.5z"/>
|
||||
<path d="M114.4,413.7c-3.7,0-7.4-1.4-10.2-4.3c-5.5-5.6-5.4-14.7,0.2-20.2c12.2-11.9,24.5-24.1,36.7-36.1
|
||||
c5.6-5.6,14.6-5.5,20.2,0.1c5.6,5.6,5.5,14.6-0.1,20.2c-12.2,12.1-24.6,24.3-36.8,36.2C121.6,412.3,118,413.7,114.4,413.7z"/>
|
||||
<path d="M260.2,114.2c-7.9,0-14.2-6.4-14.3-14.2c-0.1-17-0.2-34.4-0.3-51.6c-0.1-7.9,6.3-14.3,14.2-14.4c0,0,0.1,0,0.1,0
|
||||
c7.8,0,14.2,6.3,14.3,14.2c0.1,17.3,0.3,34.7,0.3,51.7C274.5,107.8,268.1,114.2,260.2,114.2C260.2,114.2,260.2,114.2,260.2,114.2z"
|
||||
/>
|
||||
<path d="M259.9,474.1c-0.1,0-0.1,0-0.2,0c-7.9-0.1-14.2-6.5-14.1-14.4c0.2-16.9,0.3-34.3,0.4-51.5c0-7.9,6.4-14.2,14.3-14.2
|
||||
c0,0,0,0,0.1,0c7.9,0,14.3,6.5,14.2,14.3c-0.1,17.3-0.2,34.6-0.4,51.7C274,467.8,267.7,474.1,259.9,474.1z"/>
|
||||
<path d="M151.2,159.3c-3.6,0-7.3-1.4-10-4.1c-12.2-12.1-24.6-24.3-36.7-36.3c-5.6-5.5-5.7-14.6-0.2-20.2c5.5-5.6,14.6-5.7,20.2-0.2
|
||||
c12.2,12,24.6,24.2,36.8,36.4c5.6,5.6,5.6,14.6,0.1,20.2C158.5,157.9,154.9,159.3,151.2,159.3z"/>
|
||||
<path d="M405.4,414c-3.7,0-7.4-1.4-10.2-4.3c-11.9-12.2-24-24.5-36.1-36.7c-5.6-5.6-5.5-14.6,0.1-20.2c5.6-5.6,14.6-5.5,20.2,0.1
|
||||
c12.1,12.2,24.3,24.6,36.2,36.8c5.5,5.6,5.4,14.7-0.2,20.2C412.6,412.6,409,414,405.4,414z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
30
interface/resources/icons/create-icons/25-web-1-01.svg
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:#000000;stroke-width:18;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:#000000;stroke-width:18;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:#000000;stroke-width:19;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st3{stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<g>
|
||||
<path d="M438,121.5c0-8-6.5-14.5-14.5-14.5h-333c-8,0-14.5,6.5-14.5,14.5v298c0,8,6.5,14.5,14.5,14.5h333c8,0,14.5-6.5,14.5-14.5
|
||||
V121.5z M219.4,130H391c8.3,0,15,7.2,15,16s-6.7,16-15,16H219.4c-8.3,0-15-7.2-15-16S211.1,130,219.4,130z M171.5,128.6
|
||||
c9.2,0,16.7,7.5,16.7,16.7c0,9.2-7.5,16.7-16.7,16.7c-9.2,0-16.7-7.5-16.7-16.7C154.8,136,162.3,128.6,171.5,128.6z M121,128.6
|
||||
c9.2,0,16.7,7.5,16.7,16.7c0,9.2-7.5,16.7-16.7,16.7c-9.2,0-16.7-7.5-16.7-16.7C104.4,136,111.8,128.6,121,128.6z M412,405H104V186
|
||||
h308V405z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st3" d="M161.6,320.5h-14.3l-20.5-59.3h12.9l14.7,44.8l14.7-44.8h12.9l14.7,44.8l14.7-44.8h12.9L204,320.5h-14.3
|
||||
l-14-40.6L161.6,320.5z"/>
|
||||
<path class="st3" d="M299.4,296.3h-46.5c0.3,4.3,2.3,7.8,5.9,10.4c3.6,2.6,7.8,4,12.5,4c7.4,0,13.1-2.3,16.9-7l7.1,7.8
|
||||
c-6.4,6.6-14.7,9.9-25,9.9c-8.3,0-15.4-2.8-21.2-8.3c-5.8-5.5-8.7-13-8.7-22.3c0-9.3,3-16.7,8.9-22.2c5.9-5.5,12.9-8.2,21-8.2
|
||||
c8.1,0,14.9,2.4,20.6,7.3c5.6,4.9,8.5,11.6,8.5,20.1V296.3z M252.9,286.5h34c0-5-1.6-8.8-4.7-11.5s-7-4-11.5-4
|
||||
c-4.6,0-8.7,1.4-12.3,4.2C254.7,278,252.9,281.8,252.9,286.5z"/>
|
||||
<path class="st3" d="M353.6,260.3c7.9,0,14.7,2.8,20.4,8.2c5.6,5.5,8.5,12.8,8.5,22c0,9.1-2.8,16.6-8.4,22.3
|
||||
c-5.6,5.7-12.1,8.6-19.6,8.6s-14.2-3.3-20.1-9.8v8.9h-12.5v-82.7h12.5v33.8C339.2,264.1,345.6,260.3,353.6,260.3z M334.1,291
|
||||
c0,5.6,1.7,10.3,5.1,13.9c3.4,3.6,7.6,5.4,12.5,5.4c4.9,0,9.2-1.8,12.8-5.3c3.6-3.6,5.5-8.2,5.5-13.9c0-5.7-1.8-10.4-5.3-14.2
|
||||
c-3.6-3.8-7.8-5.6-12.8-5.6c-5,0-9.2,1.9-12.6,5.6C335.8,280.6,334.1,285.3,334.1,291z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
29
interface/resources/icons/create-icons/90-particles-01.svg
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<path d="M331.8,283.4c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
|
||||
C342.1,306.6,331.8,296.2,331.8,283.4z"/>
|
||||
<path d="M277.8,350.9c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
|
||||
C288.1,374.2,277.8,363.8,277.8,350.9z"/>
|
||||
<path d="M216.3,368.8c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
|
||||
C226.7,392,216.3,381.6,216.3,368.8z"/>
|
||||
<path d="M169.9,308.9c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
|
||||
C180.3,332.1,169.9,321.7,169.9,308.9z"/>
|
||||
<path d="M251.2,447.4c-4.9-3.6-8.3-9.1-9.2-15.3c-0.9-6,0.6-12.3,4.2-17.2c3.6-4.9,9.1-8.3,15.2-9.1c6-0.9,12.3,0.6,17.3,4.3
|
||||
c4.9,3.6,8.3,9.1,9.1,15.2c0.9,6-0.6,12.3-4.2,17.2s-9.1,8.3-15.2,9.1C262.4,452.6,256.1,451,251.2,447.4z"/>
|
||||
<path d="M67.6,246.1c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
|
||||
C78,269.3,67.6,258.8,67.6,246.1z"/>
|
||||
<path d="M178.8,199.5c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
|
||||
C189.1,222.7,178.8,212.2,178.8,199.5z"/>
|
||||
<path d="M250.3,293.9c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
|
||||
C260.7,317.1,250.3,306.6,250.3,293.9z"/>
|
||||
<path d="M413,242.1c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
|
||||
C423.5,265.3,413,255,413,242.1z"/>
|
||||
<path d="M302.1,203.7c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
|
||||
C312.6,226.9,302.1,216.5,302.1,203.7z"/>
|
||||
<path d="M132.3,113.5c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
|
||||
C142.8,136.6,132.3,126.2,132.3,113.5z"/>
|
||||
<path d="M366.6,136.7c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
|
||||
C377.1,159.9,366.6,149.5,366.6,136.7z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
20
interface/resources/icons/create-icons/94-model-01.svg
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<path d="M494.2,117.2c-2.2-5.3-7.8-8.4-13.5-7.3l-89.9,16.4l44.9-72.6c2.8-4.6,2.3-10.5-1.2-14.5s-9.3-5.3-14.2-3l-213.1,98
|
||||
c-15.3-4.9-72.2-27.3-111.4-43.2c-0.3-0.1-0.6-0.2-0.8-0.3c0,0-0.1,0-0.1,0c-0.4-0.1-0.9-0.2-1.3-0.3c-0.1,0-0.2-0.1-0.3-0.1
|
||||
c-0.5-0.1-0.9-0.2-1.4-0.2c0,0,0,0-0.1,0c-0.5,0-0.9,0.1-1.4,0.1c-0.1,0-0.1,0-0.2,0c0,0-0.1,0-0.1,0c-0.5,0-0.9,0.1-1.3,0.2
|
||||
c-0.1,0-0.2,0-0.3,0.1c-0.4,0.1-0.8,0.2-1.2,0.3c-0.1,0-0.1,0-0.2,0.1c-0.4,0.1-0.8,0.3-1.2,0.5c-0.1,0-0.2,0.1-0.3,0.1
|
||||
c-0.8,0.4-1.6,0.9-2.3,1.5c-0.1,0.1-0.2,0.1-0.2,0.2c-0.3,0.3-0.7,0.6-1,0.9c0,0-0.1,0.1-0.1,0.1c-0.2,0.2-0.4,0.4-0.5,0.6
|
||||
c-0.1,0.1-0.2,0.2-0.3,0.4c-0.1,0.1-0.1,0.2-0.2,0.3c-0.3,0.4-0.5,0.8-0.7,1.2c0,0,0,0,0,0l-27.3,52.1l-32.7,40.1
|
||||
c-3.4,4.2-3.7,10.2-0.6,14.7c2.3,3.3,6.1,5.2,10,5.2c1.3,0,2.6-0.2,3.9-0.7l50.1-17l40.6-1.9l-26.7,50.3c-2.4,4.5-1.7,9.9,1.6,13.7
|
||||
c0.3,0.3,25.6,29.3,51.7,57.7c15.4,16.8,28,30.1,37.6,39.6c6.6,6.5,11.6,11.2,15.6,14.4l-16,61l-45.7,18.2
|
||||
c-6.3,2.5-9.3,9.6-6.8,15.8c1.9,4.8,6.5,7.7,11.3,7.7c1.5,0,3-0.3,4.5-0.9l44.5-17.7l17.2,15.4c2.3,2.1,5.2,3.1,8.1,3.1
|
||||
c3.4,0,6.7-1.4,9.1-4.1c4.5-5,4-12.7-1-17.2L212.1,431l16-60.7l75.7,89.3c2.4,2.8,5.8,4.3,9.3,4.3c1.1,0,2.1-0.1,3.2-0.4l84.6-22.8
|
||||
c4.8-1.3,8.4-5.4,8.9-10.4c0.6-5-2-9.8-6.4-12.1l-136.2-71.8l44.4-91.2L489.9,132C494.6,128.7,496.4,122.6,494.2,117.2z
|
||||
M294.4,234.2l-122.6-55.4l41.5-20.6c0,0,0,0,0,0l180.4-82.9L294.4,234.2z M146.4,160.8l-24.8-33.2c16.7,6.6,39.3,15.5,54,21
|
||||
L146.4,160.8z M87.3,166.6l-9.6-12.3l15.1-28.9l27.4,37.3l1.7,2.3L87.3,166.6z M123.2,243.6l22.8-43.3c18.3,44.8,35.2,91,47,121
|
||||
C173.7,301.1,147.7,271.5,123.2,243.6z M317.4,438l-57.5-67.8l104.6,55.1L317.4,438z M223.3,336.7c-5.5-14.1-42.6-104.1-30.8-76.4
|
||||
c0.6,1.4-20.5-49.2-27.9-66.3l120.9,58.9l-47.1,95L223.3,336.7z M330.5,216.7l43-62.3l70.9-16.2L330.5,216.7z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
108
interface/resources/images/sphere-01.svg
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 150" style="enable-background:new 0 0 50 150;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{opacity:0.9;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
.st2{fill:#1E1E1E;}
|
||||
.st3{fill:#EAEAEA;}
|
||||
.st4{opacity:0.47;}
|
||||
.st5{opacity:0.47;fill:#EAEAEA;}
|
||||
</style>
|
||||
<g>
|
||||
<g class="st0">
|
||||
<path class="st1" d="M50,46c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4V4c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V46z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g class="st0">
|
||||
<path class="st2" d="M50,96c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4V54c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V96z"/>
|
||||
</g>
|
||||
<path d="M32.7,9.4c-4.3-4.3-11.2-4.3-15.5,0c-2.1,2.1-3.2,4.8-3.2,7.7c0,2.9,1.1,5.7,3.2,7.7C19.4,27,22.2,28,25,28
|
||||
c2.8,0,5.6-1.1,7.7-3.2c2.1-2.1,3.2-4.8,3.2-7.7C35.9,14.2,34.8,11.4,32.7,9.4z M18.3,10.4c1.4-1.4,3.2-2.3,5-2.6
|
||||
C23,8.3,22.7,9,22.4,9.9c-0.6,2-1,4.6-1,7.3c0,0.1,0,0.3,0,0.5c0.3,0.1,0.6,0.1,0.9,0.1c0.1,0,0.2,0,0.3,0c0-0.2,0-0.4,0-0.6
|
||||
c0-5.5,1.4-9.2,2.5-9.5c0,0,0,0,0.1-0.1c2.4,0,4.7,1,6.5,2.8c1.7,1.7,2.7,4,2.8,6.5c-0.2,1.1-3.9,2.5-9.5,2.5
|
||||
c-5.5,0-9.1-1.4-9.4-2.4C15.6,14.5,16.6,12.2,18.3,10.4z M31.7,23.8c-1.9,1.9-4.3,2.8-6.8,2.8c-0.7-0.4-1.4-2.1-1.9-4.6l-1.2-0.1
|
||||
c0.2,0.9,0.4,1.8,0.6,2.6c0.2,0.8,0.5,1.4,0.8,1.9c-1.8-0.3-3.5-1.2-4.9-2.6c-1.4-1.4-2.3-3.2-2.6-5.1c0.5,0.3,1.2,0.6,2,0.9
|
||||
c2,0.6,4.6,1,7.3,1s5.3-0.3,7.3-1c0.8-0.3,1.5-0.6,2-0.9C34,20.6,33.1,22.4,31.7,23.8z"/>
|
||||
<g>
|
||||
<path d="M11.1,37.5c0,0-0.1-0.1-0.2-0.2c-0.1-0.1-0.2-0.1-0.4-0.2c-0.2-0.1-0.3-0.1-0.5-0.2c-0.2,0-0.4-0.1-0.6-0.1
|
||||
c-0.3,0-0.6,0.1-0.8,0.2c-0.2,0.1-0.3,0.3-0.3,0.5c0,0.1,0,0.2,0.1,0.3c0.1,0.1,0.2,0.2,0.3,0.2s0.3,0.1,0.5,0.2
|
||||
c0.2,0.1,0.4,0.1,0.6,0.2c0.3,0.1,0.6,0.2,0.9,0.3c0.3,0.1,0.5,0.2,0.6,0.4c0.2,0.1,0.3,0.3,0.4,0.5c0.1,0.2,0.1,0.4,0.1,0.7
|
||||
c0,0.3-0.1,0.6-0.2,0.9c-0.1,0.2-0.3,0.4-0.5,0.6s-0.5,0.3-0.8,0.3c-0.3,0.1-0.6,0.1-0.9,0.1c-0.5,0-1-0.1-1.4-0.2
|
||||
s-0.9-0.3-1.3-0.6l0.5-1.1c0.1,0.1,0.2,0.1,0.3,0.2c0.1,0.1,0.3,0.2,0.5,0.3s0.4,0.2,0.6,0.2c0.2,0.1,0.5,0.1,0.7,0.1
|
||||
c0.7,0,1-0.2,1-0.7c0-0.1,0-0.3-0.1-0.4c-0.1-0.1-0.2-0.2-0.3-0.3c-0.1-0.1-0.3-0.1-0.5-0.2c-0.2-0.1-0.4-0.1-0.7-0.2
|
||||
c-0.3-0.1-0.6-0.2-0.8-0.3S7.7,39,7.6,38.9c-0.2-0.1-0.3-0.3-0.3-0.5c-0.1-0.2-0.1-0.4-0.1-0.6c0-0.3,0.1-0.6,0.2-0.9
|
||||
c0.1-0.3,0.3-0.5,0.5-0.6s0.5-0.3,0.7-0.4c0.3-0.1,0.6-0.1,0.9-0.1c0.5,0,0.9,0.1,1.2,0.2c0.4,0.1,0.7,0.3,1,0.5L11.1,37.5z"/>
|
||||
<path d="M13.1,42.2v-6.4h2.7c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
|
||||
c0,0.3,0,0.5-0.1,0.8c-0.1,0.3-0.2,0.5-0.4,0.7c-0.2,0.2-0.4,0.4-0.6,0.5c-0.2,0.1-0.5,0.2-0.8,0.2h-1.5v2.1H13.1z M14.3,39h1.4
|
||||
c0.2,0,0.4-0.1,0.6-0.3c0.2-0.2,0.2-0.4,0.2-0.8c0-0.2,0-0.3-0.1-0.4c0-0.1-0.1-0.2-0.2-0.3C16.2,37.1,16.1,37,16,37
|
||||
c-0.1,0-0.2-0.1-0.3-0.1h-1.4V39z"/>
|
||||
<path d="M24.3,35.8v6.4H23v-2.7h-2.9v2.7h-1.2v-6.4h1.2v2.6H23v-2.6H24.3z"/>
|
||||
<path d="M30.3,41.1v1.1h-4.4v-6.4h4.4v1.1h-3.1v1.5h2.7v1h-2.7v1.7H30.3z"/>
|
||||
<path d="M31.5,42.2v-6.4h2.8c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
|
||||
c0,0.4-0.1,0.8-0.3,1.1c-0.2,0.3-0.5,0.6-0.8,0.7l1.5,2.4h-1.4L34,40.1h-1.2v2.1H31.5z M32.7,39h1.6c0.1,0,0.2,0,0.3-0.1
|
||||
c0.1-0.1,0.2-0.1,0.3-0.2c0.1-0.1,0.1-0.2,0.2-0.3s0.1-0.3,0.1-0.4c0-0.1,0-0.3-0.1-0.4s-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.2-0.3-0.2
|
||||
c-0.1-0.1-0.2-0.1-0.3-0.1h-1.5V39z"/>
|
||||
<path d="M42.2,41.1v1.1h-4.4v-6.4h4.4v1.1H39v1.5h2.7v1H39v1.7H42.2z"/>
|
||||
</g>
|
||||
<path class="st3" d="M33.1,59.4c-4.3-4.3-11.2-4.3-15.5,0c-2.1,2.1-3.2,4.8-3.2,7.7c0,2.9,1.1,5.7,3.2,7.7c2.1,2.1,4.9,3.2,7.7,3.2
|
||||
c2.8,0,5.6-1.1,7.7-3.2c2.1-2.1,3.2-4.8,3.2-7.7C36.3,64.2,35.1,61.5,33.1,59.4z M18.6,60.4c1.4-1.4,3.2-2.3,5-2.6
|
||||
c-0.3,0.5-0.7,1.2-0.9,2.1c-0.6,2-1,4.6-1,7.3c0,0.1,0,0.3,0,0.5c0.3,0.1,0.6,0.1,0.9,0.1c0.1,0,0.2,0,0.3,0c0-0.2,0-0.4,0-0.6
|
||||
c0-5.5,1.4-9.2,2.5-9.5c0,0,0,0,0.1-0.1c2.4,0,4.7,1,6.5,2.8c1.7,1.7,2.7,4,2.8,6.5c-0.2,1.1-3.9,2.5-9.5,2.5
|
||||
c-5.5,0-9.1-1.4-9.4-2.4C15.9,64.5,16.9,62.2,18.6,60.4z M32,73.8c-1.9,1.9-4.3,2.8-6.8,2.8c-0.7-0.4-1.4-2.1-1.9-4.6l-1.2-0.1
|
||||
c0.2,0.9,0.4,1.8,0.6,2.6c0.2,0.8,0.5,1.4,0.8,1.9c-1.8-0.3-3.5-1.2-4.9-2.6c-1.4-1.4-2.3-3.2-2.6-5.1c0.5,0.3,1.2,0.6,2,0.9
|
||||
c2,0.6,4.6,1,7.3,1s5.3-0.3,7.3-1c0.8-0.3,1.5-0.6,2-0.9C34.3,70.7,33.4,72.4,32,73.8z"/>
|
||||
<g>
|
||||
<path class="st3" d="M11.5,87.5c0,0-0.1-0.1-0.2-0.2c-0.1-0.1-0.2-0.1-0.4-0.2S10.5,87,10.3,87c-0.2,0-0.4-0.1-0.6-0.1
|
||||
c-0.3,0-0.6,0.1-0.8,0.2s-0.3,0.3-0.3,0.5c0,0.1,0,0.2,0.1,0.3C8.9,88,9,88.1,9.1,88.2c0.1,0.1,0.3,0.1,0.5,0.2
|
||||
c0.2,0.1,0.4,0.1,0.6,0.2c0.3,0.1,0.6,0.2,0.9,0.3s0.5,0.2,0.6,0.4c0.2,0.1,0.3,0.3,0.4,0.5c0.1,0.2,0.1,0.4,0.1,0.7
|
||||
c0,0.3-0.1,0.6-0.2,0.9c-0.1,0.2-0.3,0.4-0.5,0.6c-0.2,0.2-0.5,0.3-0.8,0.3c-0.3,0.1-0.6,0.1-0.9,0.1c-0.5,0-1-0.1-1.4-0.2
|
||||
C8,92,7.6,91.8,7.2,91.5l0.5-1.1c0.1,0.1,0.2,0.1,0.3,0.2c0.1,0.1,0.3,0.2,0.5,0.3s0.4,0.2,0.6,0.2c0.2,0.1,0.5,0.1,0.7,0.1
|
||||
c0.7,0,1-0.2,1-0.7c0-0.1,0-0.3-0.1-0.4c-0.1-0.1-0.2-0.2-0.3-0.3c-0.1-0.1-0.3-0.1-0.5-0.2c-0.2-0.1-0.4-0.1-0.7-0.2
|
||||
c-0.3-0.1-0.6-0.2-0.8-0.3c-0.2-0.1-0.4-0.2-0.6-0.3s-0.3-0.3-0.3-0.5c-0.1-0.2-0.1-0.4-0.1-0.6c0-0.3,0.1-0.6,0.2-0.9
|
||||
c0.1-0.3,0.3-0.5,0.5-0.6s0.5-0.3,0.7-0.4s0.6-0.1,0.9-0.1c0.5,0,0.9,0.1,1.2,0.2s0.7,0.3,1,0.5L11.5,87.5z"/>
|
||||
<path class="st3" d="M13.4,92.2v-6.4h2.7c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5s0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
|
||||
c0,0.3,0,0.5-0.1,0.8c-0.1,0.3-0.2,0.5-0.4,0.7c-0.2,0.2-0.4,0.4-0.6,0.5c-0.2,0.1-0.5,0.2-0.8,0.2h-1.5v2.1H13.4z M14.7,89h1.4
|
||||
c0.2,0,0.4-0.1,0.6-0.3c0.2-0.2,0.2-0.4,0.2-0.8c0-0.2,0-0.3-0.1-0.4c0-0.1-0.1-0.2-0.2-0.3s-0.2-0.2-0.3-0.2
|
||||
c-0.1,0-0.2-0.1-0.3-0.1h-1.4V89z"/>
|
||||
<path class="st3" d="M24.6,85.9v6.4h-1.2v-2.7h-2.9v2.7h-1.2v-6.4h1.2v2.6h2.9v-2.6H24.6z"/>
|
||||
<path class="st3" d="M30.6,91.2v1.1h-4.4v-6.4h4.4v1.1h-3.1v1.5h2.7v1h-2.7v1.7H30.6z"/>
|
||||
<path class="st3" d="M31.8,92.2v-6.4h2.8c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
|
||||
c0,0.4-0.1,0.8-0.3,1.1s-0.5,0.6-0.8,0.7l1.5,2.4h-1.4l-1.3-2.1h-1.2v2.1H31.8z M33.1,89h1.6c0.1,0,0.2,0,0.3-0.1
|
||||
c0.1-0.1,0.2-0.1,0.3-0.2c0.1-0.1,0.1-0.2,0.2-0.3s0.1-0.3,0.1-0.4c0-0.1,0-0.3-0.1-0.4s-0.1-0.2-0.2-0.3S35,87.1,34.9,87
|
||||
c-0.1-0.1-0.2-0.1-0.3-0.1h-1.5V89z"/>
|
||||
<path class="st3" d="M42.5,91.2v1.1h-4.4v-6.4h4.4v1.1h-3.1v1.5H42v1h-2.7v1.7H42.5z"/>
|
||||
</g>
|
||||
<g class="st4">
|
||||
<path class="st2" d="M50,146c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4v-42c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V146z"/>
|
||||
</g>
|
||||
<path class="st5" d="M33.1,109.4c-4.3-4.3-11.2-4.3-15.5,0c-2.1,2.1-3.2,4.8-3.2,7.7c0,2.9,1.1,5.7,3.2,7.7c2.1,2.1,4.9,3.2,7.7,3.2
|
||||
c2.8,0,5.6-1.1,7.7-3.2c2.1-2.1,3.2-4.8,3.2-7.7C36.3,114.2,35.1,111.5,33.1,109.4z M18.6,110.4c1.4-1.4,3.2-2.3,5-2.6
|
||||
c-0.3,0.5-0.7,1.2-0.9,2.1c-0.6,2-1,4.6-1,7.3c0,0.1,0,0.3,0,0.5c0.3,0.1,0.6,0.1,0.9,0.1c0.1,0,0.2,0,0.3,0c0-0.2,0-0.4,0-0.6
|
||||
c0-5.5,1.4-9.2,2.5-9.5c0,0,0,0,0.1-0.1c2.4,0,4.7,1,6.5,2.8c1.7,1.7,2.7,4,2.8,6.5c-0.2,1.1-3.9,2.5-9.5,2.5
|
||||
c-5.5,0-9.1-1.4-9.4-2.4C15.9,114.5,16.9,112.2,18.6,110.4z M32,123.8c-1.9,1.9-4.3,2.8-6.8,2.8c-0.7-0.4-1.4-2.1-1.9-4.6l-1.2-0.1
|
||||
c0.2,0.9,0.4,1.8,0.6,2.6c0.2,0.8,0.5,1.4,0.8,1.9c-1.8-0.3-3.5-1.2-4.9-2.6c-1.4-1.4-2.3-3.2-2.6-5.1c0.5,0.3,1.2,0.6,2,0.9
|
||||
c2,0.6,4.6,1,7.3,1s5.3-0.3,7.3-1c0.8-0.3,1.5-0.6,2-0.9C34.3,120.7,33.4,122.4,32,123.8z"/>
|
||||
<g class="st4">
|
||||
<path class="st3" d="M11.5,137.5c0,0-0.1-0.1-0.2-0.2c-0.1-0.1-0.2-0.1-0.4-0.2s-0.3-0.1-0.5-0.2c-0.2,0-0.4-0.1-0.6-0.1
|
||||
c-0.3,0-0.6,0.1-0.8,0.2s-0.3,0.3-0.3,0.5c0,0.1,0,0.2,0.1,0.3c0.1,0.1,0.2,0.2,0.3,0.2c0.1,0.1,0.3,0.1,0.5,0.2
|
||||
c0.2,0.1,0.4,0.1,0.6,0.2c0.3,0.1,0.6,0.2,0.9,0.3s0.5,0.2,0.6,0.4c0.2,0.1,0.3,0.3,0.4,0.5c0.1,0.2,0.1,0.4,0.1,0.7
|
||||
c0,0.3-0.1,0.6-0.2,0.9c-0.1,0.2-0.3,0.4-0.5,0.6c-0.2,0.2-0.5,0.3-0.8,0.3c-0.3,0.1-0.6,0.1-0.9,0.1c-0.5,0-1-0.1-1.4-0.2
|
||||
c-0.5-0.1-0.9-0.3-1.3-0.6l0.5-1.1c0.1,0.1,0.2,0.1,0.3,0.2c0.1,0.1,0.3,0.2,0.5,0.3s0.4,0.2,0.6,0.2c0.2,0.1,0.5,0.1,0.7,0.1
|
||||
c0.7,0,1-0.2,1-0.7c0-0.1,0-0.3-0.1-0.4c-0.1-0.1-0.2-0.2-0.3-0.3c-0.1-0.1-0.3-0.1-0.5-0.2c-0.2-0.1-0.4-0.1-0.7-0.2
|
||||
c-0.3-0.1-0.6-0.2-0.8-0.3c-0.2-0.1-0.4-0.2-0.6-0.3s-0.3-0.3-0.3-0.5c-0.1-0.2-0.1-0.4-0.1-0.6c0-0.3,0.1-0.6,0.2-0.9
|
||||
c0.1-0.3,0.3-0.5,0.5-0.6s0.5-0.3,0.7-0.4s0.6-0.1,0.9-0.1c0.5,0,0.9,0.1,1.2,0.2s0.7,0.3,1,0.5L11.5,137.5z"/>
|
||||
<path class="st3" d="M13.4,142.2v-6.4h2.7c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5s0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
|
||||
c0,0.3,0,0.5-0.1,0.8c-0.1,0.3-0.2,0.5-0.4,0.7c-0.2,0.2-0.4,0.4-0.6,0.5c-0.2,0.1-0.5,0.2-0.8,0.2h-1.5v2.1H13.4z M14.7,139h1.4
|
||||
c0.2,0,0.4-0.1,0.6-0.3c0.2-0.2,0.2-0.4,0.2-0.8c0-0.2,0-0.3-0.1-0.4c0-0.1-0.1-0.2-0.2-0.3s-0.2-0.2-0.3-0.2
|
||||
c-0.1,0-0.2-0.1-0.3-0.1h-1.4V139z"/>
|
||||
<path class="st3" d="M24.6,135.9v6.4h-1.2v-2.7h-2.9v2.7h-1.2v-6.4h1.2v2.6h2.9v-2.6H24.6z"/>
|
||||
<path class="st3" d="M30.6,141.2v1.1h-4.4v-6.4h4.4v1.1h-3.1v1.5h2.7v1h-2.7v1.7H30.6z"/>
|
||||
<path class="st3" d="M31.8,142.2v-6.4h2.8c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
|
||||
c0,0.4-0.1,0.8-0.3,1.1s-0.5,0.6-0.8,0.7l1.5,2.4h-1.4l-1.3-2.1h-1.2v2.1H31.8z M33.1,139h1.6c0.1,0,0.2,0,0.3-0.1
|
||||
c0.1-0.1,0.2-0.1,0.3-0.2c0.1-0.1,0.1-0.2,0.2-0.3s0.1-0.3,0.1-0.4c0-0.1,0-0.3-0.1-0.4s-0.1-0.2-0.2-0.3s-0.2-0.2-0.3-0.2
|
||||
c-0.1-0.1-0.2-0.1-0.3-0.1h-1.5V139z"/>
|
||||
<path class="st3" d="M42.5,141.2v1.1h-4.4v-6.4h4.4v1.1h-3.1v1.5H42v1h-2.7v1.7H42.5z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 9.1 KiB |
|
@ -15,7 +15,7 @@ import HFWebEngineProfile 1.0
|
|||
WebEngineView {
|
||||
id: root
|
||||
|
||||
profile: desktop.browserProfile
|
||||
// profile: desktop.browserProfile
|
||||
|
||||
Component.onCompleted: {
|
||||
console.log("Connecting JS messaging to Hifi Logging")
|
||||
|
|
|
@ -14,7 +14,6 @@ import QtQuick.Controls.Styles 1.4
|
|||
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
import "." as VrControls
|
||||
|
||||
FocusScope {
|
||||
id: root
|
||||
|
@ -119,14 +118,14 @@ FocusScope {
|
|||
}
|
||||
|
||||
function showList() {
|
||||
var r = 20//desktop.mapFromItem(root, 0, 0, root.width, root.height);
|
||||
var y = 200;
|
||||
var bottom = 0 + scrollView.height;
|
||||
var r = mapFromItem(root, 0, 0, root.width, root.height);
|
||||
var y = r.y + r.height;
|
||||
var bottom = y + scrollView.height;
|
||||
if (bottom > 720) {
|
||||
y -= bottom - 720 + 8;
|
||||
y -= bottom - tabletRoot.height + 8;
|
||||
}
|
||||
scrollView.x = 0;
|
||||
scrollView.y = 0;
|
||||
scrollView.x = r.x;
|
||||
scrollView.y = y;
|
||||
popup.visible = true;
|
||||
popup.forceActiveFocus();
|
||||
listView.currentIndex = root.currentIndex;
|
||||
|
@ -141,6 +140,7 @@ FocusScope {
|
|||
|
||||
FocusScope {
|
||||
id: popup
|
||||
z: 12
|
||||
parent: parent
|
||||
anchors.fill: parent
|
||||
visible: false
|
||||
|
|
339
interface/resources/qml/dialogs/TabletCustomQueryDialog.qml
Normal file
|
@ -0,0 +1,339 @@
|
|||
//
|
||||
// TabletCustomQueryDialog.qml
|
||||
//
|
||||
// Created by Vlad Stelmahovsky on 3/27/17
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Dialogs 1.2 as OriginalDialogs
|
||||
|
||||
import "../controls-uit" as ControlsUIT
|
||||
import "../styles-uit"
|
||||
import "../windows"
|
||||
|
||||
TabletModalWindow {
|
||||
id: root;
|
||||
HifiConstants { id: hifi; }
|
||||
|
||||
y: hifi.dimensions.tabletMenuHeader
|
||||
|
||||
title: ""
|
||||
visible: true;
|
||||
property bool keyboardOverride: true
|
||||
|
||||
signal selected(var result);
|
||||
signal canceled();
|
||||
|
||||
property int icon: hifi.icons.none;
|
||||
property string iconText: "";
|
||||
property int iconSize: 35;
|
||||
onIconChanged: updateIcon();
|
||||
|
||||
property var textInput;
|
||||
property var comboBox;
|
||||
property var checkBox;
|
||||
onTextInputChanged: {
|
||||
if (textInput && textInput.text !== undefined) {
|
||||
textField.text = textInput.text;
|
||||
}
|
||||
}
|
||||
onComboBoxChanged: {
|
||||
if (comboBox && comboBox.index !== undefined) {
|
||||
comboBoxField.currentIndex = comboBox.index;
|
||||
}
|
||||
}
|
||||
onCheckBoxChanged: {
|
||||
if (checkBox && checkBox.checked !== undefined) {
|
||||
checkBoxField.checked = checkBox.checked;
|
||||
}
|
||||
}
|
||||
|
||||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
onKeyboardRaisedChanged: d.resize();
|
||||
|
||||
property var warning: "";
|
||||
property var result;
|
||||
|
||||
property var implicitCheckState: null;
|
||||
|
||||
property int titleWidth: 0;
|
||||
onTitleWidthChanged: d.resize();
|
||||
|
||||
MouseArea {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
}
|
||||
|
||||
function updateIcon() {
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
iconText = hifi.glyphForIcon(root.icon);
|
||||
}
|
||||
|
||||
function updateCheckbox() {
|
||||
if (checkBox.disableForItems) {
|
||||
var currentItemInDisableList = false;
|
||||
for (var i in checkBox.disableForItems) {
|
||||
if (comboBoxField.currentIndex === checkBox.disableForItems[i]) {
|
||||
currentItemInDisableList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentItemInDisableList) {
|
||||
checkBoxField.enabled = false;
|
||||
if (checkBox.checkStateOnDisable !== null && checkBox.checkStateOnDisable !== undefined) {
|
||||
root.implicitCheckState = checkBoxField.checked;
|
||||
checkBoxField.checked = checkBox.checkStateOnDisable;
|
||||
}
|
||||
root.warning = checkBox.warningOnDisable;
|
||||
} else {
|
||||
checkBoxField.enabled = true;
|
||||
if (root.implicitCheckState !== null) {
|
||||
checkBoxField.checked = root.implicitCheckState;
|
||||
root.implicitCheckState = null;
|
||||
}
|
||||
root.warning = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TabletModalFrame {
|
||||
id: modalWindowItem
|
||||
width: parent.width - 12
|
||||
height: 240
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d;
|
||||
readonly property int minWidth: 470
|
||||
readonly property int maxWidth: 470
|
||||
readonly property int minHeight: 240
|
||||
readonly property int maxHeight: 720
|
||||
|
||||
function resize() {
|
||||
var targetWidth = Math.max(titleWidth, 470);
|
||||
var targetHeight = (textField.visible ? textField.controlHeight + hifi.dimensions.contentSpacing.y : 0) +
|
||||
(extraInputs.visible ? extraInputs.height + hifi.dimensions.contentSpacing.y : 0) +
|
||||
(buttons.height + 3 * hifi.dimensions.contentSpacing.y) +
|
||||
((keyboardEnabled && keyboardRaised) ? (keyboard.raisedHeight + hifi.dimensions.contentSpacing.y) : 0);
|
||||
|
||||
root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth);
|
||||
root.height = (targetHeight < d.minHeight) ? d.minHeight : ((targetHeight > d.maxHeight) ?
|
||||
d.maxHeight : targetHeight);
|
||||
if (checkBoxField.visible && comboBoxField.visible) {
|
||||
checkBoxField.width = extraInputs.width / 2;
|
||||
comboBoxField.width = extraInputs.width / 2;
|
||||
} else if (!checkBoxField.visible && comboBoxField.visible) {
|
||||
comboBoxField.width = extraInputs.width;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Item {
|
||||
// anchors {
|
||||
// // top: parent.top;
|
||||
// // bottom: extraInputs.visible ? extraInputs.top : buttons.top;
|
||||
// left: parent.left;
|
||||
// right: parent.right;
|
||||
// topMargin: 20
|
||||
// }
|
||||
|
||||
// FIXME make a text field type that can be bound to a history for autocompletion
|
||||
ControlsUIT.TextField {
|
||||
id: textField;
|
||||
label: root.textInput.label;
|
||||
focus: root.textInput ? true : false;
|
||||
visible: root.textInput ? true : false;
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
leftMargin: 5; rightMargin: 5;
|
||||
topMargin: textField.controlHeight - textField.height + 5
|
||||
}
|
||||
}
|
||||
|
||||
ControlsUIT.Keyboard {
|
||||
id: keyboard
|
||||
raised: keyboardEnabled && keyboardRaised
|
||||
numeric: punctuationMode
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
leftMargin: 5; rightMargin: 5;
|
||||
top: textField.bottom
|
||||
topMargin: raised ? hifi.dimensions.contentSpacing.y : 0
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
Row {
|
||||
id: extraInputs;
|
||||
visible: Boolean(root.checkBox || root.comboBox);
|
||||
anchors {
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
leftMargin: 5; rightMargin: 5;
|
||||
top: keyboard.bottom;
|
||||
topMargin: hifi.dimensions.contentSpacing.y + 20;
|
||||
}
|
||||
height: comboBoxField.controlHeight;
|
||||
onHeightChanged: d.resize();
|
||||
onWidthChanged: d.resize();
|
||||
|
||||
ControlsUIT.CheckBox {
|
||||
id: checkBoxField;
|
||||
text: root.checkBox.label;
|
||||
focus: Boolean(root.checkBox);
|
||||
visible: Boolean(root.checkBox);
|
||||
// anchors {
|
||||
// left: parent.left;
|
||||
// bottom: parent.bottom;
|
||||
// leftMargin: 6; // Magic number to align with warning icon
|
||||
// bottomMargin: 6;
|
||||
// }
|
||||
}
|
||||
|
||||
ControlsUIT.TabletComboBox {
|
||||
id: comboBoxField;
|
||||
label: root.comboBox.label;
|
||||
focus: Boolean(root.comboBox);
|
||||
visible: Boolean(root.comboBox);
|
||||
// anchors {
|
||||
// right: parent.right;
|
||||
// bottom: parent.bottom;
|
||||
// }
|
||||
model: root.comboBox ? root.comboBox.items : [];
|
||||
onAccepted: {
|
||||
updateCheckbox();
|
||||
focus = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: buttons;
|
||||
focus: true;
|
||||
spacing: hifi.dimensions.contentSpacing.x;
|
||||
layoutDirection: Qt.RightToLeft;
|
||||
onHeightChanged: d.resize();
|
||||
onWidthChanged: {
|
||||
d.resize();
|
||||
resizeWarningText();
|
||||
}
|
||||
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y;
|
||||
leftMargin: 5; rightMargin: 5;
|
||||
}
|
||||
|
||||
function resizeWarningText() {
|
||||
var rowWidth = buttons.width;
|
||||
var buttonsWidth = acceptButton.width + cancelButton.width + hifi.dimensions.contentSpacing.x * 2;
|
||||
var warningIconWidth = warningIcon.width + hifi.dimensions.contentSpacing.x;
|
||||
warningText.width = rowWidth - buttonsWidth - warningIconWidth;
|
||||
}
|
||||
|
||||
ControlsUIT.Button {
|
||||
id: cancelButton;
|
||||
action: cancelAction;
|
||||
}
|
||||
|
||||
ControlsUIT.Button {
|
||||
id: acceptButton;
|
||||
action: acceptAction;
|
||||
}
|
||||
|
||||
Text {
|
||||
id: warningText;
|
||||
visible: Boolean(root.warning);
|
||||
text: root.warning;
|
||||
wrapMode: Text.WordWrap;
|
||||
font.italic: true;
|
||||
maximumLineCount: 2;
|
||||
}
|
||||
|
||||
HiFiGlyphs {
|
||||
id: warningIcon;
|
||||
visible: Boolean(root.warning);
|
||||
text: hifi.glyphs.alert;
|
||||
size: hifi.dimensions.controlLineHeight;
|
||||
}
|
||||
}
|
||||
// }//column
|
||||
Action {
|
||||
id: cancelAction;
|
||||
text: qsTr("Cancel");
|
||||
shortcut: Qt.Key_Escape;
|
||||
onTriggered: {
|
||||
root.result = null;
|
||||
root.canceled();
|
||||
root.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
Action {
|
||||
id: acceptAction;
|
||||
text: qsTr("Add");
|
||||
shortcut: Qt.Key_Return;
|
||||
onTriggered: {
|
||||
var result = {};
|
||||
if (textInput) {
|
||||
result.textInput = textField.text;
|
||||
}
|
||||
if (comboBox) {
|
||||
result.comboBox = comboBoxField.currentIndex;
|
||||
result.comboBoxText = comboBoxField.currentText;
|
||||
}
|
||||
if (checkBox) {
|
||||
result.checkBox = checkBoxField.enabled ? checkBoxField.checked : null;
|
||||
}
|
||||
root.result = JSON.stringify(result);
|
||||
root.selected(root.result);
|
||||
root.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (!visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.key) {
|
||||
case Qt.Key_Escape:
|
||||
case Qt.Key_Back:
|
||||
cancelAction.trigger();
|
||||
event.accepted = true;
|
||||
break;
|
||||
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
acceptAction.trigger();
|
||||
event.accepted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
keyboardEnabled = HMD.active;
|
||||
updateIcon();
|
||||
updateCheckbox();
|
||||
d.resize();
|
||||
textField.forceActiveFocus();
|
||||
}
|
||||
}
|
782
interface/resources/qml/dialogs/TabletFileDialog.qml
Normal file
|
@ -0,0 +1,782 @@
|
|||
//
|
||||
// FileDialog.qml
|
||||
//
|
||||
// Created by Dante Ruiz on 23 Feb 2017
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import Qt.labs.folderlistmodel 2.1
|
||||
import Qt.labs.settings 1.0
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick.Dialogs 1.2 as OriginalDialogs
|
||||
|
||||
import ".."
|
||||
import "../controls-uit"
|
||||
import "../styles-uit"
|
||||
import "../windows"
|
||||
|
||||
import "fileDialog"
|
||||
|
||||
//FIXME implement shortcuts for favorite location
|
||||
TabletModalWindow {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
Settings {
|
||||
category: "FileDialog"
|
||||
property alias width: root.width
|
||||
property alias height: root.height
|
||||
property alias x: root.x
|
||||
property alias y: root.y
|
||||
}
|
||||
|
||||
|
||||
// Set from OffscreenUi::getOpenFile()
|
||||
property alias caption: root.title;
|
||||
// Set from OffscreenUi::getOpenFile()
|
||||
property alias dir: fileTableModel.folder;
|
||||
// Set from OffscreenUi::getOpenFile()
|
||||
property alias filter: selectionType.filtersString;
|
||||
// Set from OffscreenUi::getOpenFile()
|
||||
property int options; // <-- FIXME unused
|
||||
|
||||
property string iconText: root.title !== "" ? hifi.glyphs.scriptUpload : ""
|
||||
property int iconSize: 40
|
||||
|
||||
property bool selectDirectory: false;
|
||||
property bool showHidden: false;
|
||||
// FIXME implement
|
||||
property bool multiSelect: false;
|
||||
property bool saveDialog: false;
|
||||
property var helper: fileDialogHelper
|
||||
property alias model: fileTableView.model
|
||||
property var drives: helper.drives()
|
||||
|
||||
property int titleWidth: 0
|
||||
|
||||
signal selectedFile(var file);
|
||||
signal canceled();
|
||||
|
||||
Component.onCompleted: {
|
||||
fileDialogItem.keyboardEnabled = HMD.active;
|
||||
|
||||
// HACK: The following lines force the model to initialize properly such that the go-up button
|
||||
// works properly from the initial screen.
|
||||
var initialFolder = folderListModel.folder;
|
||||
fileTableModel.folder = helper.pathToUrl(drives[0]);
|
||||
fileTableModel.folder = initialFolder;
|
||||
|
||||
iconText = root.title !== "" ? hifi.glyphs.scriptUpload : "";
|
||||
|
||||
// Clear selection when click on external frame.
|
||||
//frameClicked.connect(function() { d.clearSelection(); });
|
||||
|
||||
if (selectDirectory) {
|
||||
currentSelection.text = d.capitalizeDrive(helper.urlToPath(initialFolder));
|
||||
d.currentSelectionIsFolder = true;
|
||||
d.currentSelectionUrl = initialFolder;
|
||||
}
|
||||
|
||||
helper.contentsChanged.connect(function() {
|
||||
if (folderListModel) {
|
||||
// Make folderListModel refresh.
|
||||
var save = folderListModel.folder;
|
||||
folderListModel.folder = "";
|
||||
folderListModel.folder = save;
|
||||
}
|
||||
});
|
||||
|
||||
fileTableView.forceActiveFocus();
|
||||
}
|
||||
|
||||
TabletModalFrame {
|
||||
id: fileDialogItem
|
||||
width: parent.width - 6
|
||||
height: parent.height - 6
|
||||
|
||||
anchors {
|
||||
horizontalCenter: root.horizontalCenter
|
||||
verticalCenter: root.verticalCenter
|
||||
}
|
||||
|
||||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
|
||||
MouseArea {
|
||||
// Clear selection when click on internal unused area.
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
d.clearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: navControls
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: (fileDialogItem.hasTitle ? (fileDialogItem.frameMarginTop + hifi.dimensions.modalDialogMargin.y) : hifi.dimension.modalDialogMargin.y)
|
||||
left: parent.left
|
||||
leftMargin: hifi.dimensions.contentSpacing.x
|
||||
}
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
|
||||
GlyphButton {
|
||||
id: upButton
|
||||
glyph: hifi.glyphs.levelUp
|
||||
width: height
|
||||
size: 30
|
||||
enabled: fileTableModel.parentFolder && fileTableModel.parentFolder !== ""
|
||||
onClicked: d.navigateUp();
|
||||
}
|
||||
|
||||
GlyphButton {
|
||||
id: homeButton
|
||||
property var destination: helper.home();
|
||||
glyph: hifi.glyphs.home
|
||||
size: 28
|
||||
width: height
|
||||
enabled: d.homeDestination ? true : false
|
||||
onClicked: d.navigateHome();
|
||||
}
|
||||
}
|
||||
|
||||
TabletComboBox {
|
||||
id: pathSelector
|
||||
z: 10
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: (fileDialogItem.hasTitle ? (fileDialogItem.frameMarginTop + hifi.dimensions.modalDialogMargin.y) : hifi.dimension.modalDialogMargin.y)
|
||||
left: navControls.right
|
||||
leftMargin: hifi.dimensions.contentSpacing.x
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
property var lastValidFolder: helper.urlToPath(fileTableModel.folder)
|
||||
|
||||
function calculatePathChoices(folder) {
|
||||
var folders = folder.split("/"),
|
||||
choices = [],
|
||||
i, length;
|
||||
|
||||
if (folders[folders.length - 1] === "") {
|
||||
folders.pop();
|
||||
}
|
||||
|
||||
choices.push(folders[0]);
|
||||
|
||||
for (i = 1, length = folders.length; i < length; i++) {
|
||||
choices.push(choices[i - 1] + "/" + folders[i]);
|
||||
}
|
||||
|
||||
if (folders[0] === "") {
|
||||
// Special handling for OSX root dir.
|
||||
choices[0] = "/";
|
||||
}
|
||||
|
||||
choices.reverse();
|
||||
|
||||
if (drives && drives.length > 1) {
|
||||
choices.push("This PC");
|
||||
}
|
||||
|
||||
if (choices.length > 0) {
|
||||
pathSelector.model = choices;
|
||||
}
|
||||
}
|
||||
|
||||
onLastValidFolderChanged: {
|
||||
var folder = d.capitalizeDrive(lastValidFolder);
|
||||
calculatePathChoices(folder);
|
||||
}
|
||||
|
||||
onCurrentTextChanged: {
|
||||
var folder = currentText;
|
||||
|
||||
if (/^[a-zA-z]:$/.test(folder)) {
|
||||
folder = "file:///" + folder + "/";
|
||||
} else if (folder === "This PC") {
|
||||
folder = "file:///";
|
||||
} else {
|
||||
folder = helper.pathToUrl(folder);
|
||||
}
|
||||
|
||||
if (helper.urlToPath(folder).toLowerCase() !== helper.urlToPath(fileTableModel.folder).toLowerCase()) {
|
||||
if (root.selectDirectory) {
|
||||
currentSelection.text = currentText !== "This PC" ? currentText : "";
|
||||
d.currentSelectionUrl = helper.pathToUrl(currentText);
|
||||
}
|
||||
fileTableModel.folder = folder;
|
||||
fileTableView.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property var currentSelectionUrl;
|
||||
readonly property string currentSelectionPath: helper.urlToPath(currentSelectionUrl);
|
||||
property bool currentSelectionIsFolder;
|
||||
property var backStack: []
|
||||
property var tableViewConnection: Connections { target: fileTableView; onCurrentRowChanged: d.update(); }
|
||||
property var modelConnection: Connections { target: fileTableModel; onFolderChanged: d.update(); }
|
||||
property var homeDestination: helper.home();
|
||||
|
||||
function capitalizeDrive(path) {
|
||||
// Consistently capitalize drive letter for Windows.
|
||||
if (/[a-zA-Z]:/.test(path)) {
|
||||
return path.charAt(0).toUpperCase() + path.slice(1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
function update() {
|
||||
var row = fileTableView.currentRow;
|
||||
|
||||
if (row === -1) {
|
||||
if (!root.selectDirectory) {
|
||||
currentSelection.text = "";
|
||||
currentSelectionIsFolder = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
currentSelectionUrl = helper.pathToUrl(fileTableView.model.get(row).filePath);
|
||||
currentSelectionIsFolder = fileTableView.model.isFolder(row);
|
||||
if (root.selectDirectory || !currentSelectionIsFolder) {
|
||||
currentSelection.text = capitalizeDrive(helper.urlToPath(currentSelectionUrl));
|
||||
} else {
|
||||
currentSelection.text = "";
|
||||
}
|
||||
}
|
||||
|
||||
function navigateUp() {
|
||||
if (fileTableModel.parentFolder && fileTableModel.parentFolder !== "") {
|
||||
fileTableModel.folder = fileTableModel.parentFolder;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function navigateHome() {
|
||||
fileTableModel.folder = homeDestination;
|
||||
return true;
|
||||
}
|
||||
|
||||
function clearSelection() {
|
||||
fileTableView.selection.clear();
|
||||
fileTableView.currentRow = -1;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
FolderListModel {
|
||||
id: folderListModel
|
||||
nameFilters: selectionType.currentFilter
|
||||
showDirsFirst: true
|
||||
showDotAndDotDot: false
|
||||
showFiles: !root.selectDirectory
|
||||
Component.onCompleted: {
|
||||
showFiles = !root.selectDirectory
|
||||
}
|
||||
|
||||
onFolderChanged: {
|
||||
fileTableModel.update(); // Update once the data from the folder change is available.
|
||||
}
|
||||
|
||||
function getItem(index, field) {
|
||||
return get(index, field);
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
// Emulates FolderListModel but contains drive data.
|
||||
id: driveListModel
|
||||
|
||||
property int count: 1
|
||||
|
||||
Component.onCompleted: initialize();
|
||||
|
||||
function initialize() {
|
||||
var drive,
|
||||
i;
|
||||
|
||||
count = drives.length;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
drive = drives[i].slice(0, -1); // Remove trailing "/".
|
||||
append({
|
||||
fileName: drive,
|
||||
fileModified: new Date(0),
|
||||
fileSize: 0,
|
||||
filePath: drive + "/",
|
||||
fileIsDir: true,
|
||||
fileNameSort: drive.toLowerCase()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getItem(index, field) {
|
||||
return get(index)[field];
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: fileTableModel
|
||||
|
||||
// FolderListModel has a couple of problems:
|
||||
// 1) Files and directories sort case-sensitively: https://bugreports.qt.io/browse/QTBUG-48757
|
||||
// 2) Cannot browse up to the "computer" level to view Windows drives: https://bugreports.qt.io/browse/QTBUG-42901
|
||||
//
|
||||
// To solve these problems an intermediary ListModel is used that implements proper sorting and can be populated with
|
||||
// drive information when viewing at the computer level.
|
||||
|
||||
property var folder
|
||||
property int sortOrder: Qt.AscendingOrder
|
||||
property int sortColumn: 0
|
||||
property var model: folderListModel
|
||||
property string parentFolder: calculateParentFolder();
|
||||
|
||||
readonly property string rootFolder: "file:///"
|
||||
|
||||
function calculateParentFolder() {
|
||||
if (model === folderListModel) {
|
||||
if (folderListModel.parentFolder.toString() === "" && driveListModel.count > 1) {
|
||||
return rootFolder;
|
||||
} else {
|
||||
return folderListModel.parentFolder;
|
||||
}
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
onFolderChanged: {
|
||||
if (folder === rootFolder) {
|
||||
model = driveListModel;
|
||||
helper.monitorDirectory("");
|
||||
update();
|
||||
} else {
|
||||
var needsUpdate = model === driveListModel && folder === folderListModel.folder;
|
||||
|
||||
model = folderListModel;
|
||||
folderListModel.folder = folder;
|
||||
helper.monitorDirectory(helper.urlToPath(folder));
|
||||
|
||||
if (needsUpdate) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isFolder(row) {
|
||||
if (row === -1) {
|
||||
return false;
|
||||
}
|
||||
return get(row).fileIsDir;
|
||||
}
|
||||
|
||||
function update() {
|
||||
var dataFields = ["fileName", "fileModified", "fileSize"],
|
||||
sortFields = ["fileNameSort", "fileModified", "fileSize"],
|
||||
dataField = dataFields[sortColumn],
|
||||
sortField = sortFields[sortColumn],
|
||||
sortValue,
|
||||
fileName,
|
||||
fileIsDir,
|
||||
comparisonFunction,
|
||||
lower,
|
||||
middle,
|
||||
upper,
|
||||
rows = 0,
|
||||
i;
|
||||
|
||||
clear();
|
||||
|
||||
comparisonFunction = sortOrder === Qt.AscendingOrder
|
||||
? function(a, b) { return a < b; }
|
||||
: function(a, b) { return a > b; }
|
||||
|
||||
for (i = 0; i < model.count; i++) {
|
||||
fileName = model.getItem(i, "fileName");
|
||||
fileIsDir = model.getItem(i, "fileIsDir");
|
||||
|
||||
sortValue = model.getItem(i, dataField);
|
||||
if (dataField === "fileName") {
|
||||
// Directories first by prefixing a "*".
|
||||
// Case-insensitive.
|
||||
sortValue = (fileIsDir ? "*" : "") + sortValue.toLowerCase();
|
||||
}
|
||||
|
||||
lower = 0;
|
||||
upper = rows;
|
||||
while (lower < upper) {
|
||||
middle = Math.floor((lower + upper) / 2);
|
||||
var lessThan;
|
||||
if (comparisonFunction(sortValue, get(middle)[sortField])) {
|
||||
lessThan = true;
|
||||
upper = middle;
|
||||
} else {
|
||||
lessThan = false;
|
||||
lower = middle + 1;
|
||||
}
|
||||
}
|
||||
|
||||
insert(lower, {
|
||||
fileName: fileName,
|
||||
fileModified: (fileIsDir ? new Date(0) : model.getItem(i, "fileModified")),
|
||||
fileSize: model.getItem(i, "fileSize"),
|
||||
filePath: model.getItem(i, "filePath"),
|
||||
fileIsDir: fileIsDir,
|
||||
fileNameSort: (fileIsDir ? "*" : "") + fileName.toLowerCase()
|
||||
});
|
||||
|
||||
rows++;
|
||||
}
|
||||
|
||||
d.clearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
Table {
|
||||
id: fileTableView
|
||||
colorScheme: hifi.colorSchemes.light
|
||||
anchors {
|
||||
top: navControls.bottom
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: currentSelection.top
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y + currentSelection.controlHeight - currentSelection.height
|
||||
}
|
||||
headerVisible: !selectDirectory
|
||||
onClicked: navigateToRow(row);
|
||||
onDoubleClicked: navigateToRow(row);
|
||||
focus: true
|
||||
Keys.onReturnPressed: navigateToCurrentRow();
|
||||
Keys.onEnterPressed: navigateToCurrentRow();
|
||||
|
||||
sortIndicatorColumn: 0
|
||||
sortIndicatorOrder: Qt.AscendingOrder
|
||||
sortIndicatorVisible: true
|
||||
|
||||
model: fileTableModel
|
||||
|
||||
function updateSort() {
|
||||
model.sortOrder = sortIndicatorOrder;
|
||||
model.sortColumn = sortIndicatorColumn;
|
||||
model.update();
|
||||
}
|
||||
|
||||
onSortIndicatorColumnChanged: { updateSort(); }
|
||||
|
||||
onSortIndicatorOrderChanged: { updateSort(); }
|
||||
|
||||
itemDelegate: Item {
|
||||
clip: true
|
||||
|
||||
//FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; }
|
||||
//FontLoader { id: firaSansRegular; source: "../../fonts/FiraSans-Regular.ttf"; }
|
||||
|
||||
FiraSansSemiBold {
|
||||
text: getText();
|
||||
elide: styleData.elideMode
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: hifi.dimensions.tablePadding
|
||||
right: parent.right
|
||||
rightMargin: hifi.dimensions.tablePadding
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
size: hifi.fontSizes.tableText
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
//font.family: (styleData.row !== -1 && fileTableView.model.get(styleData.row).fileIsDir)
|
||||
//? firaSansSemiBold.name : firaSansRegular.name
|
||||
|
||||
function getText() {
|
||||
if (styleData.row === -1) {
|
||||
return styleData.value;
|
||||
}
|
||||
|
||||
switch (styleData.column) {
|
||||
case 1: return fileTableView.model.get(styleData.row).fileIsDir ? "" : styleData.value;
|
||||
case 2: return fileTableView.model.get(styleData.row).fileIsDir ? "" : formatSize(styleData.value);
|
||||
default: return styleData.value;
|
||||
}
|
||||
}
|
||||
function formatSize(size) {
|
||||
var suffixes = [ "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" ];
|
||||
var suffixIndex = 0
|
||||
while ((size / 1024.0) > 1.1) {
|
||||
size /= 1024.0;
|
||||
++suffixIndex;
|
||||
}
|
||||
|
||||
size = Math.round(size*1000)/1000;
|
||||
size = size.toLocaleString()
|
||||
|
||||
return size + " " + suffixes[suffixIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TableViewColumn {
|
||||
id: fileNameColumn
|
||||
role: "fileName"
|
||||
title: "Name"
|
||||
width: (selectDirectory ? 1.0 : 0.5) * fileTableView.width
|
||||
movable: false
|
||||
resizable: true
|
||||
}
|
||||
TableViewColumn {
|
||||
id: fileMofifiedColumn
|
||||
role: "fileModified"
|
||||
title: "Date"
|
||||
width: 0.3 * fileTableView.width
|
||||
movable: false
|
||||
resizable: true
|
||||
visible: !selectDirectory
|
||||
}
|
||||
TableViewColumn {
|
||||
role: "fileSize"
|
||||
title: "Size"
|
||||
width: fileTableView.width - fileNameColumn.width - fileMofifiedColumn.width
|
||||
movable: false
|
||||
resizable: true
|
||||
visible: !selectDirectory
|
||||
}
|
||||
|
||||
function navigateToRow(row) {
|
||||
currentRow = row;
|
||||
navigateToCurrentRow();
|
||||
}
|
||||
|
||||
function navigateToCurrentRow() {
|
||||
var row = fileTableView.currentRow
|
||||
var isFolder = model.isFolder(row);
|
||||
var file = model.get(row).filePath;
|
||||
if (isFolder) {
|
||||
fileTableView.model.folder = helper.pathToUrl(file);
|
||||
} else {
|
||||
okAction.trigger();
|
||||
}
|
||||
}
|
||||
|
||||
property string prefix: ""
|
||||
|
||||
function addToPrefix(event) {
|
||||
if (!event.text || event.text === "") {
|
||||
return false;
|
||||
}
|
||||
var newPrefix = prefix + event.text.toLowerCase();
|
||||
var matchedIndex = -1;
|
||||
for (var i = 0; i < model.count; ++i) {
|
||||
var name = model.get(i).fileName.toLowerCase();
|
||||
if (0 === name.indexOf(newPrefix)) {
|
||||
matchedIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (matchedIndex !== -1) {
|
||||
fileTableView.selection.clear();
|
||||
fileTableView.selection.select(matchedIndex);
|
||||
fileTableView.currentRow = matchedIndex;
|
||||
fileTableView.prefix = newPrefix;
|
||||
}
|
||||
prefixClearTimer.restart();
|
||||
return true;
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: prefixClearTimer
|
||||
interval: 1000
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: fileTableView.prefix = "";
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Backspace:
|
||||
case Qt.Key_Tab:
|
||||
case Qt.Key_Backtab:
|
||||
event.accepted = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (addToPrefix(event)) {
|
||||
event.accepted = true
|
||||
} else {
|
||||
event.accepted = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: currentSelection
|
||||
label: selectDirectory ? "Directory:" : "File name:"
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: selectionType.visible ? selectionType.left: parent.right
|
||||
rightMargin: hifi.dimensions.contentSpacing.x
|
||||
leftMargin: hifi.dimensions.contentSpacing.x
|
||||
bottom: keyboard.top
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
readOnly: !root.saveDialog
|
||||
activeFocusOnTab: !readOnly
|
||||
onActiveFocusChanged: if (activeFocus) { selectAll(); }
|
||||
onAccepted: okAction.trigger();
|
||||
}
|
||||
|
||||
FileTypeSelection {
|
||||
id: selectionType
|
||||
anchors {
|
||||
top: currentSelection.top
|
||||
left: buttonRow.left
|
||||
right: parent.right
|
||||
}
|
||||
visible: !selectDirectory && filtersCount > 1
|
||||
KeyNavigation.left: fileTableView
|
||||
KeyNavigation.right: openButton
|
||||
}
|
||||
|
||||
Keyboard {
|
||||
id: keyboard
|
||||
raised: parent.keyboardEnabled && parent.keyboardRaised
|
||||
numeric: parent.punctuationMode
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: buttonRow.top
|
||||
bottomMargin: visible ? hifi.dimensions.contentSpacing.y : 0
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: buttonRow
|
||||
anchors {
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
spacing: hifi.dimensions.contentSpacing.y
|
||||
|
||||
Button {
|
||||
id: openButton
|
||||
color: hifi.buttons.blue
|
||||
action: okAction
|
||||
Keys.onReturnPressed: okAction.trigger()
|
||||
KeyNavigation.up: selectionType
|
||||
KeyNavigation.left: selectionType
|
||||
KeyNavigation.right: cancelButton
|
||||
}
|
||||
|
||||
Button {
|
||||
id: cancelButton
|
||||
action: cancelAction
|
||||
KeyNavigation.up: selectionType
|
||||
KeyNavigation.left: openButton
|
||||
KeyNavigation.right: fileTableView.contentItem
|
||||
Keys.onReturnPressed: { canceled(); root.enabled = false }
|
||||
}
|
||||
}
|
||||
|
||||
Action {
|
||||
id: okAction
|
||||
text: currentSelection.text ? (root.selectDirectory && fileTableView.currentRow === -1 ? "Choose" : (root.saveDialog ? "Save" : "Open")) : "Open"
|
||||
enabled: currentSelection.text || !root.selectDirectory && d.currentSelectionIsFolder ? true : false
|
||||
onTriggered: {
|
||||
if (!root.selectDirectory && !d.currentSelectionIsFolder
|
||||
|| root.selectDirectory && fileTableView.currentRow === -1) {
|
||||
okActionTimer.start();
|
||||
} else {
|
||||
fileTableView.navigateToCurrentRow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: okActionTimer
|
||||
interval: 50
|
||||
running: false
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
if (!root.saveDialog) {
|
||||
selectedFile(d.currentSelectionUrl);
|
||||
root.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle the ambiguity between different cases
|
||||
// * typed name (with or without extension)
|
||||
// * full path vs relative vs filename only
|
||||
var selection = helper.saveHelper(currentSelection.text, root.dir, selectionType.currentFilter);
|
||||
|
||||
if (!selection) {
|
||||
desktop.messageBox({ icon: OriginalDialogs.StandardIcon.Warning, text: "Unable to parse selection" })
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper.urlIsDir(selection)) {
|
||||
root.dir = selection;
|
||||
currentSelection.text = "";
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the file is a valid target
|
||||
if (!helper.urlIsWritable(selection)) {
|
||||
desktop.messageBox({
|
||||
icon: OriginalDialogs.StandardIcon.Warning,
|
||||
text: "Unable to write to location " + selection
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
if (helper.urlExists(selection)) {
|
||||
var messageBox = desktop.messageBox({
|
||||
icon: OriginalDialogs.StandardIcon.Question,
|
||||
buttons: OriginalDialogs.StandardButton.Yes | OriginalDialogs.StandardButton.No,
|
||||
text: "Do you wish to overwrite " + selection + "?",
|
||||
});
|
||||
var result = messageBox.exec();
|
||||
if (OriginalDialogs.StandardButton.Yes !== result) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Selecting " + selection)
|
||||
selectedFile(selection);
|
||||
root.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
Action {
|
||||
id: cancelAction
|
||||
text: "Cancel"
|
||||
onTriggered: { canceled();root.destroy(); }
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Backspace:
|
||||
event.accepted = d.navigateUp();
|
||||
break;
|
||||
|
||||
case Qt.Key_Home:
|
||||
event.accepted = d.navigateHome();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
249
interface/resources/qml/dialogs/TabletMessageBox.qml
Normal file
|
@ -0,0 +1,249 @@
|
|||
//
|
||||
// MessageDialog.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 15 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Dialogs 1.2 as OriginalDialogs
|
||||
|
||||
import "../controls-uit"
|
||||
import "../styles-uit"
|
||||
import "../windows"
|
||||
|
||||
import "messageDialog"
|
||||
|
||||
TabletModalWindow {
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
visible: true
|
||||
|
||||
signal selected(int button);
|
||||
|
||||
MouseArea {
|
||||
id: mouse;
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
function click(button) {
|
||||
clickedButton = button;
|
||||
selected(button);
|
||||
destroy();
|
||||
}
|
||||
|
||||
function exec() {
|
||||
return OffscreenUi.waitForMessageBoxResult(root);
|
||||
}
|
||||
|
||||
property alias detailedText: detailedText.text
|
||||
property alias text: mainTextContainer.text
|
||||
property alias informativeText: informativeTextContainer.text
|
||||
property int buttons: OriginalDialogs.StandardButton.Ok
|
||||
property int icon: OriginalDialogs.StandardIcon.NoIcon
|
||||
property string iconText: ""
|
||||
property int iconSize: 50
|
||||
onIconChanged: updateIcon();
|
||||
property int defaultButton: OriginalDialogs.StandardButton.NoButton;
|
||||
property int clickedButton: OriginalDialogs.StandardButton.NoButton;
|
||||
focus: defaultButton === OriginalDialogs.StandardButton.NoButton
|
||||
|
||||
property int titleWidth: 0
|
||||
onTitleWidthChanged: d.resize();
|
||||
|
||||
function updateIcon() {
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
iconText = hifi.glyphForIcon(root.icon);
|
||||
}
|
||||
|
||||
TabletModalFrame {
|
||||
id: messageBox
|
||||
clip: true
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: parent.width - 6
|
||||
height: 300
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property int minWidth: 200
|
||||
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
|
||||
+ (informativeTextContainer.text != "" ? informativeTextContainer.contentHeight + 3 * hifi.dimensions.contentSpacing.y : 0)
|
||||
+ buttons.height
|
||||
+ (details.implicitHeight + hifi.dimensions.contentSpacing.y) + messageBox.frameMarginTop
|
||||
messageBox.height = (targetHeight < d.minHeight) ? d.minHeight: ((targetHeight > d.maxHeight) ? d.maxHeight : targetHeight)
|
||||
}
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
id: mainTextContainer
|
||||
onTextChanged: d.resize();
|
||||
wrapMode: Text.WordWrap
|
||||
size: hifi.fontSizes.sectionName
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
width: parent.width - 6
|
||||
anchors {
|
||||
top: parent.top
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
margins: 0
|
||||
topMargin: hifi.dimensions.contentSpacing.y + messageBox.frameMarginTop
|
||||
}
|
||||
maximumLineCount: 30
|
||||
elide: Text.ElideLeft
|
||||
lineHeight: 2
|
||||
lineHeightMode: Text.ProportionalHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
id: informativeTextContainer
|
||||
onTextChanged: d.resize();
|
||||
wrapMode: Text.WordWrap
|
||||
size: hifi.fontSizes.sectionName
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
anchors {
|
||||
top: mainTextContainer.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
margins: 0
|
||||
topMargin: text != "" ? hifi.dimensions.contentSpacing.y : 0
|
||||
}
|
||||
}
|
||||
|
||||
Flow {
|
||||
id: buttons
|
||||
focus: true
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
layoutDirection: Qt.RightToLeft
|
||||
anchors {
|
||||
top: informativeTextContainer.text == "" ? mainTextContainer.bottom : informativeTextContainer.bottom
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
margins: 0
|
||||
topMargin: 2 * hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
MessageDialogButton { dialog: root; text: qsTr("Close"); button: OriginalDialogs.StandardButton.Close; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Abort"); button: OriginalDialogs.StandardButton.Abort; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Cancel"); button: OriginalDialogs.StandardButton.Cancel; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Restore Defaults"); button: OriginalDialogs.StandardButton.RestoreDefaults; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Reset"); button: OriginalDialogs.StandardButton.Reset; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Discard"); button: OriginalDialogs.StandardButton.Discard; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("No to All"); button: OriginalDialogs.StandardButton.NoToAll; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("No"); button: OriginalDialogs.StandardButton.No; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Yes to All"); button: OriginalDialogs.StandardButton.YesToAll; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Yes"); button: OriginalDialogs.StandardButton.Yes; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Apply"); button: OriginalDialogs.StandardButton.Apply; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Ignore"); button: OriginalDialogs.StandardButton.Ignore; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Retry"); button: OriginalDialogs.StandardButton.Retry; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Save All"); button: OriginalDialogs.StandardButton.SaveAll; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Save"); button: OriginalDialogs.StandardButton.Save; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("Open"); button: OriginalDialogs.StandardButton.Open; }
|
||||
MessageDialogButton { dialog: root; text: qsTr("OK"); button: OriginalDialogs.StandardButton.Ok; }
|
||||
|
||||
Button {
|
||||
id: moreButton
|
||||
text: qsTr("Show Details...")
|
||||
width: 160
|
||||
onClicked: { content.state = (content.state === "" ? "expanded" : "") }
|
||||
visible: detailedText && detailedText.length > 0
|
||||
}
|
||||
MessageDialogButton { dialog: root; text: qsTr("Help"); button: OriginalDialogs.StandardButton.Help; }
|
||||
}
|
||||
|
||||
Item {
|
||||
id: details
|
||||
width: parent.width
|
||||
implicitHeight: detailedText.implicitHeight
|
||||
height: 0
|
||||
clip: true
|
||||
anchors {
|
||||
top: buttons.bottom
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
margins: 0
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
Flickable {
|
||||
id: flickable
|
||||
contentHeight: detailedText.height
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: hifi.dimensions.contentSpacing.x
|
||||
anchors.bottomMargin: hifi.dimensions.contentSpacing.y
|
||||
TextEdit {
|
||||
id: detailedText
|
||||
size: hifi.fontSizes.menuItem
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
width: details.width
|
||||
wrapMode: Text.WordWrap
|
||||
readOnly: true
|
||||
selectByMouse: true
|
||||
anchors.margins: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "expanded"
|
||||
PropertyChanges { target: root; anchors.fill: undefined }
|
||||
PropertyChanges { target: details; height: 120 }
|
||||
PropertyChanges { target: moreButton; text: qsTr("Hide Details") }
|
||||
}
|
||||
]
|
||||
|
||||
Component.onCompleted: {
|
||||
updateIcon();
|
||||
d.resize();
|
||||
}
|
||||
onStateChanged: d.resize()
|
||||
}
|
||||
|
||||
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
|
||||
root.click(OriginalDialogs.StandardButton.Cancel)
|
||||
break
|
||||
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true
|
||||
root.click(root.defaultButton)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
206
interface/resources/qml/dialogs/TabletQueryDialog.qml
Normal file
|
@ -0,0 +1,206 @@
|
|||
//
|
||||
// QueryDialog.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 22 Jan 2016
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Dialogs 1.2 as OriginalDialogs
|
||||
|
||||
import "../controls-uit"
|
||||
import "../styles-uit"
|
||||
import "../windows"
|
||||
|
||||
TabletModalWindow {
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
signal selected(var result);
|
||||
signal canceled();
|
||||
layer.enabled: true
|
||||
property int icon: hifi.icons.none
|
||||
property string iconText: ""
|
||||
property int iconSize: 35
|
||||
|
||||
MouseArea {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
}
|
||||
|
||||
property bool keyboardOverride: true
|
||||
onIconChanged: updateIcon();
|
||||
|
||||
property var items;
|
||||
property string label: ""
|
||||
property var result;
|
||||
property alias current: textResult.text
|
||||
|
||||
// For text boxes
|
||||
property alias placeholderText: textResult.placeholderText
|
||||
|
||||
// For combo boxes
|
||||
property bool editable: true;
|
||||
|
||||
property int titleWidth: 0
|
||||
onTitleWidthChanged: d.resize();
|
||||
|
||||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
|
||||
onKeyboardRaisedChanged: d.resize();
|
||||
|
||||
function updateIcon() {
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
iconText = hifi.glyphForIcon(root.icon);
|
||||
}
|
||||
|
||||
TabletModalFrame {
|
||||
id: modalWindowItem
|
||||
width: parent.width - 12
|
||||
height: 240
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property int minWidth: 470
|
||||
readonly property int maxWidth: 470
|
||||
readonly property int minHeight: 120
|
||||
readonly property int maxHeight: 720
|
||||
|
||||
function resize() {
|
||||
var targetWidth = Math.max(titleWidth, 470)
|
||||
var targetHeight = (items ? comboBox.controlHeight : textResult.controlHeight) + 5 * hifi.dimensions.contentSpacing.y + buttons.height
|
||||
modalWindowItem.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth);
|
||||
modalWindowItem.height = ((targetHeight < d.minHeight) ? d.minHeight : ((targetHeight > d.maxHeight) ? d.maxHeight : targetHeight)) + ((keyboardEnabled && keyboardRaised) ? (keyboard.raisedHeight + 2 * hifi.dimensions.contentSpacing.y) : 0) + modalWindowItem.frameMarginTop
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: keyboard.top;
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
margins: 0
|
||||
bottomMargin: 2 * hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
|
||||
// FIXME make a text field type that can be bound to a history for autocompletion
|
||||
TextField {
|
||||
id: textResult
|
||||
label: root.label
|
||||
focus: items ? false : true
|
||||
visible: items ? false : true
|
||||
anchors {
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
bottom: parent.bottom
|
||||
leftMargin: 5
|
||||
}
|
||||
}
|
||||
|
||||
TabletComboBox {
|
||||
id: comboBox
|
||||
label: root.label
|
||||
focus: true
|
||||
visible: items ? true : false
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
rightMargin: 5
|
||||
}
|
||||
model: items ? items : []
|
||||
}
|
||||
}
|
||||
|
||||
property alias keyboardOverride: root.keyboardOverride
|
||||
property alias keyboardRaised: root.keyboardRaised
|
||||
property alias punctuationMode: root.punctuationMode
|
||||
|
||||
Keyboard {
|
||||
id: keyboard
|
||||
raised: keyboardEnabled && keyboardRaised
|
||||
numeric: punctuationMode
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: buttons.top
|
||||
bottomMargin: raised ? 2 * hifi.dimensions.contentSpacing.y : 0
|
||||
}
|
||||
}
|
||||
|
||||
Flow {
|
||||
id: buttons
|
||||
focus: true
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||
layoutDirection: Qt.RightToLeft
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
margins: 0
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
Button { action: cancelAction }
|
||||
Button { action: acceptAction }
|
||||
}
|
||||
|
||||
Action {
|
||||
id: cancelAction
|
||||
text: qsTr("Cancel")
|
||||
shortcut: Qt.Key_Escape
|
||||
onTriggered: {
|
||||
root.canceled();
|
||||
root.destroy();
|
||||
}
|
||||
}
|
||||
Action {
|
||||
id: acceptAction
|
||||
text: qsTr("OK")
|
||||
shortcut: Qt.Key_Return
|
||||
onTriggered: {
|
||||
root.result = items ? comboBox.currentText : textResult.text
|
||||
root.selected(root.result);
|
||||
root.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (!visible) {
|
||||
return
|
||||
}
|
||||
|
||||
switch (event.key) {
|
||||
case Qt.Key_Escape:
|
||||
case Qt.Key_Back:
|
||||
cancelAction.trigger()
|
||||
event.accepted = true;
|
||||
break;
|
||||
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
acceptAction.trigger()
|
||||
event.accepted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
keyboardEnabled = HMD.active;
|
||||
updateIcon();
|
||||
d.resize();
|
||||
textResult.forceActiveFocus();
|
||||
}
|
||||
}
|
|
@ -23,7 +23,10 @@ Preference {
|
|||
|
||||
Component.onCompleted: {
|
||||
dataTextField.text = preference.value;
|
||||
console.log("MyAvatar modelName " + MyAvatar.getFullAvatarModelName())
|
||||
// FIXME: MyAvatar object isn't available in HMD mode for some reason.
|
||||
if (typeof MyAvatar !== "undefined") {
|
||||
console.log("MyAvatar modelName " + MyAvatar.getFullAvatarModelName())
|
||||
}
|
||||
console.log("Application : " + ApplicationInterface)
|
||||
ApplicationInterface.fullAvatarURLChanged.connect(processNewAvatar);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// PreferencesDialog.qml
|
||||
// GeneralPreferencesDialog.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 24 Jan 2016
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
|
|
614
interface/resources/qml/hifi/dialogs/TabletAssetServer.qml
Normal file
|
@ -0,0 +1,614 @@
|
|||
//
|
||||
// TabletAssetServer.qml
|
||||
//
|
||||
// Created by Vlad Stelmahovsky on 3/3/17
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Dialogs 1.2 as OriginalDialogs
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
import "../../styles-uit"
|
||||
import "../../controls-uit" as HifiControls
|
||||
import "../../windows"
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
objectName: "AssetServer"
|
||||
|
||||
property var eventBridge;
|
||||
signal sendToScript(var message);
|
||||
property bool isHMD: false
|
||||
|
||||
color: hifi.colors.baseGray
|
||||
|
||||
property int colorScheme: hifi.colorSchemes.dark
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
property var scripts: ScriptDiscoveryService;
|
||||
property var assetProxyModel: Assets.proxyModel;
|
||||
property var assetMappingsModel: Assets.mappingModel;
|
||||
property var currentDirectory;
|
||||
|
||||
Settings {
|
||||
category: "Overlay.AssetServer"
|
||||
property alias directory: root.currentDirectory
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
isHMD = HMD.active;
|
||||
ApplicationInterface.uploadRequest.connect(uploadClicked);
|
||||
assetMappingsModel.errorGettingMappings.connect(handleGetMappingsError);
|
||||
reload();
|
||||
}
|
||||
|
||||
function doDeleteFile(path) {
|
||||
console.log("Deleting " + path);
|
||||
|
||||
Assets.deleteMappings(path, function(err) {
|
||||
if (err) {
|
||||
console.log("Asset browser - error deleting path: ", path, err);
|
||||
|
||||
box = errorMessageBox("There was an error deleting:\n" + path + "\n" + err);
|
||||
box.selected.connect(reload);
|
||||
} else {
|
||||
console.log("Asset browser - finished deleting path: ", path);
|
||||
reload();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function doRenameFile(oldPath, newPath) {
|
||||
|
||||
if (newPath[0] !== "/") {
|
||||
newPath = "/" + newPath;
|
||||
}
|
||||
|
||||
if (oldPath[oldPath.length - 1] === '/' && newPath[newPath.length - 1] != '/') {
|
||||
// this is a folder rename but the user neglected to add a trailing slash when providing a new path
|
||||
newPath = newPath + "/";
|
||||
}
|
||||
|
||||
if (Assets.isKnownFolder(newPath)) {
|
||||
box = errorMessageBox("Cannot overwrite existing directory.");
|
||||
box.selected.connect(reload);
|
||||
}
|
||||
|
||||
console.log("Asset browser - renaming " + oldPath + " to " + newPath);
|
||||
|
||||
Assets.renameMapping(oldPath, newPath, function(err) {
|
||||
if (err) {
|
||||
console.log("Asset browser - error renaming: ", oldPath, "=>", newPath, " - error ", err);
|
||||
box = errorMessageBox("There was an error renaming:\n" + oldPath + " to " + newPath + "\n" + err);
|
||||
box.selected.connect(reload);
|
||||
} else {
|
||||
console.log("Asset browser - finished rename: ", oldPath, "=>", newPath);
|
||||
}
|
||||
|
||||
reload();
|
||||
});
|
||||
}
|
||||
|
||||
function fileExists(path) {
|
||||
return Assets.isKnownMapping(path);
|
||||
}
|
||||
|
||||
function askForOverwrite(path, callback) {
|
||||
var object = tabletRoot.messageBox({
|
||||
icon: hifi.icons.question,
|
||||
buttons: OriginalDialogs.StandardButton.Yes | OriginalDialogs.StandardButton.No,
|
||||
defaultButton: OriginalDialogs.StandardButton.No,
|
||||
title: "Overwrite File",
|
||||
text: path + "\n" + "This file already exists. Do you want to overwrite it?"
|
||||
});
|
||||
object.selected.connect(function(button) {
|
||||
if (button === OriginalDialogs.StandardButton.Yes) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function canAddToWorld(path) {
|
||||
var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i];
|
||||
|
||||
return supportedExtensions.reduce(function(total, current) {
|
||||
return total | new RegExp(current).test(path);
|
||||
}, false);
|
||||
}
|
||||
|
||||
function clear() {
|
||||
Assets.mappingModel.clear();
|
||||
}
|
||||
|
||||
function reload() {
|
||||
Assets.mappingModel.refresh();
|
||||
treeView.selection.clear();
|
||||
}
|
||||
|
||||
function handleGetMappingsError(errorString) {
|
||||
errorMessageBox(
|
||||
"There was a problem retreiving the list of assets from your Asset Server.\n"
|
||||
+ errorString
|
||||
);
|
||||
}
|
||||
|
||||
function addToWorld() {
|
||||
var defaultURL = assetProxyModel.data(treeView.selection.currentIndex, 0x103);
|
||||
|
||||
if (!defaultURL || !canAddToWorld(defaultURL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var SHAPE_TYPE_NONE = 0;
|
||||
var SHAPE_TYPE_SIMPLE_HULL = 1;
|
||||
var SHAPE_TYPE_SIMPLE_COMPOUND = 2;
|
||||
var SHAPE_TYPE_STATIC_MESH = 3;
|
||||
|
||||
var SHAPE_TYPES = [];
|
||||
SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision";
|
||||
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model";
|
||||
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_COMPOUND] = "Good - Sub-meshes";
|
||||
SHAPE_TYPES[SHAPE_TYPE_STATIC_MESH] = "Exact - All polygons";
|
||||
|
||||
var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_STATIC_MESH;
|
||||
var DYNAMIC_DEFAULT = false;
|
||||
var prompt = tabletRoot.customInputDialog({
|
||||
textInput: {
|
||||
label: "Model URL",
|
||||
text: defaultURL
|
||||
},
|
||||
comboBox: {
|
||||
label: "Automatic Collisions",
|
||||
index: SHAPE_TYPE_DEFAULT,
|
||||
items: SHAPE_TYPES
|
||||
},
|
||||
checkBox: {
|
||||
label: "Dynamic",
|
||||
checked: DYNAMIC_DEFAULT,
|
||||
disableForItems: [
|
||||
SHAPE_TYPE_STATIC_MESH
|
||||
],
|
||||
checkStateOnDisable: false,
|
||||
warningOnDisable: "Models with automatic collisions set to 'Exact' cannot be dynamic"
|
||||
}
|
||||
});
|
||||
|
||||
prompt.selected.connect(function (jsonResult) {
|
||||
if (jsonResult) {
|
||||
var result = JSON.parse(jsonResult);
|
||||
var url = result.textInput.trim();
|
||||
var shapeType;
|
||||
switch (result.comboBox) {
|
||||
case SHAPE_TYPE_SIMPLE_HULL:
|
||||
shapeType = "simple-hull";
|
||||
break;
|
||||
case SHAPE_TYPE_SIMPLE_COMPOUND:
|
||||
shapeType = "simple-compound";
|
||||
break;
|
||||
case SHAPE_TYPE_STATIC_MESH:
|
||||
shapeType = "static-mesh";
|
||||
break;
|
||||
default:
|
||||
shapeType = "none";
|
||||
}
|
||||
|
||||
var dynamic = result.checkBox !== null ? result.checkBox : DYNAMIC_DEFAULT;
|
||||
if (shapeType === "static-mesh" && dynamic) {
|
||||
// The prompt should prevent this case
|
||||
print("Error: model cannot be both static mesh and dynamic. This should never happen.");
|
||||
} else if (url) {
|
||||
var name = assetProxyModel.data(treeView.selection.currentIndex);
|
||||
var addPosition = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getFront(MyAvatar.orientation)));
|
||||
var gravity;
|
||||
if (dynamic) {
|
||||
// Create a vector <0, -10, 0>. { x: 0, y: -10, z: 0 } won't work because Qt is dumb and this is a
|
||||
// different scripting engine from QTScript.
|
||||
gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 10);
|
||||
} else {
|
||||
gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 0);
|
||||
}
|
||||
|
||||
print("Asset browser - adding asset " + url + " (" + name + ") to world.");
|
||||
|
||||
// Entities.addEntity doesn't work from QML, so we use this.
|
||||
Entities.addModelEntity(name, url, shapeType, dynamic, addPosition, gravity);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function copyURLToClipboard(index) {
|
||||
if (!index) {
|
||||
index = treeView.selection.currentIndex;
|
||||
}
|
||||
|
||||
var url = assetProxyModel.data(treeView.selection.currentIndex, 0x103);
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
Window.copyToClipboard(url);
|
||||
}
|
||||
|
||||
function renameEl(index, data) {
|
||||
if (!index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var path = assetProxyModel.data(index, 0x100);
|
||||
if (!path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var destinationPath = path.split('/');
|
||||
destinationPath[destinationPath.length - (path[path.length - 1] === '/' ? 2 : 1)] = data;
|
||||
destinationPath = destinationPath.join('/').trim();
|
||||
|
||||
if (path === destinationPath) {
|
||||
return;
|
||||
}
|
||||
if (!fileExists(destinationPath)) {
|
||||
doRenameFile(path, destinationPath);
|
||||
}
|
||||
}
|
||||
function renameFile(index) {
|
||||
if (!index) {
|
||||
index = treeView.selection.currentIndex;
|
||||
}
|
||||
|
||||
var path = assetProxyModel.data(index, 0x100);
|
||||
if (!path) {
|
||||
return;
|
||||
}
|
||||
|
||||
var object = tabletRoot.inputDialog({
|
||||
label: "Enter new path:",
|
||||
current: path,
|
||||
placeholderText: "Enter path here"
|
||||
});
|
||||
object.selected.connect(function(destinationPath) {
|
||||
destinationPath = destinationPath.trim();
|
||||
|
||||
if (path === destinationPath) {
|
||||
return;
|
||||
}
|
||||
if (fileExists(destinationPath)) {
|
||||
askForOverwrite(destinationPath, function() {
|
||||
doRenameFile(path, destinationPath);
|
||||
});
|
||||
} else {
|
||||
doRenameFile(path, destinationPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
function deleteFile(index) {
|
||||
if (!index) {
|
||||
index = treeView.selection.currentIndex;
|
||||
}
|
||||
var path = assetProxyModel.data(index, 0x100);
|
||||
if (!path) {
|
||||
return;
|
||||
}
|
||||
|
||||
var isFolder = assetProxyModel.data(treeView.selection.currentIndex, 0x101);
|
||||
var typeString = isFolder ? 'folder' : 'file';
|
||||
|
||||
var object = tabletRoot.messageBox({
|
||||
icon: hifi.icons.question,
|
||||
buttons: OriginalDialogs.StandardButton.Yes + OriginalDialogs.StandardButton.No,
|
||||
defaultButton: OriginalDialogs.StandardButton.Yes,
|
||||
title: "Delete",
|
||||
text: "You are about to delete the following " + typeString + ":\n" + path + "\nDo you want to continue?"
|
||||
});
|
||||
object.selected.connect(function(button) {
|
||||
if (button === OriginalDialogs.StandardButton.Yes) {
|
||||
doDeleteFile(path);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: doUploadTimer
|
||||
property var url
|
||||
property bool isConnected: false
|
||||
interval: 5
|
||||
repeat: false
|
||||
running: false
|
||||
}
|
||||
|
||||
property bool uploadOpen: false;
|
||||
Timer {
|
||||
id: timer
|
||||
}
|
||||
function uploadClicked(fileUrl) {
|
||||
if (uploadOpen) {
|
||||
return;
|
||||
}
|
||||
uploadOpen = true;
|
||||
|
||||
function doUpload(url, dropping) {
|
||||
var fileUrl = fileDialogHelper.urlToPath(url);
|
||||
|
||||
var path = assetProxyModel.data(treeView.selection.currentIndex, 0x100);
|
||||
var directory = path ? path.slice(0, path.lastIndexOf('/') + 1) : "/";
|
||||
var filename = fileUrl.slice(fileUrl.lastIndexOf('/') + 1);
|
||||
|
||||
Assets.uploadFile(fileUrl, directory + filename,
|
||||
function() {
|
||||
// Upload started
|
||||
uploadSpinner.visible = true;
|
||||
uploadButton.enabled = false;
|
||||
uploadProgressLabel.text = "In progress...";
|
||||
},
|
||||
function(err, path) {
|
||||
print(err, path);
|
||||
if (err === "") {
|
||||
uploadProgressLabel.text = "Upload Complete";
|
||||
timer.interval = 1000;
|
||||
timer.repeat = false;
|
||||
timer.triggered.connect(function() {
|
||||
uploadSpinner.visible = false;
|
||||
uploadButton.enabled = true;
|
||||
uploadOpen = false;
|
||||
});
|
||||
timer.start();
|
||||
console.log("Asset Browser - finished uploading: ", fileUrl);
|
||||
reload();
|
||||
} else {
|
||||
uploadSpinner.visible = false;
|
||||
uploadButton.enabled = true;
|
||||
uploadOpen = false;
|
||||
|
||||
if (err !== -1) {
|
||||
console.log("Asset Browser - error uploading: ", fileUrl, " - error ", err);
|
||||
var box = errorMessageBox("There was an error uploading:\n" + fileUrl + "\n" + err);
|
||||
box.selected.connect(reload);
|
||||
}
|
||||
}
|
||||
}, dropping);
|
||||
}
|
||||
|
||||
function initiateUpload(url) {
|
||||
doUpload(doUploadTimer.url, false);
|
||||
}
|
||||
|
||||
if (fileUrl) {
|
||||
doUpload(fileUrl, true);
|
||||
} else {
|
||||
var browser = tabletRoot.fileDialog({
|
||||
selectDirectory: false,
|
||||
dir: currentDirectory
|
||||
});
|
||||
|
||||
browser.canceled.connect(function() {
|
||||
uploadOpen = false;
|
||||
});
|
||||
|
||||
browser.selectedFile.connect(function(url) {
|
||||
currentDirectory = browser.dir;
|
||||
|
||||
// Initiate upload from a timer so that file browser dialog can close beforehand.
|
||||
doUploadTimer.url = url;
|
||||
if (!doUploadTimer.isConnected) {
|
||||
doUploadTimer.triggered.connect(function() { initiateUpload(); });
|
||||
doUploadTimer.isConnected = true;
|
||||
}
|
||||
doUploadTimer.start();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function errorMessageBox(message) {
|
||||
return tabletRoot.messageBox({
|
||||
icon: hifi.icons.warning,
|
||||
defaultButton: OriginalDialogs.StandardButton.Ok,
|
||||
title: "Error",
|
||||
text: message
|
||||
});
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
y: hifi.dimensions.tabletMenuHeader //-bgNavBar
|
||||
spacing: 10
|
||||
|
||||
HifiControls.TabletContentSection {
|
||||
id: assetDirectory
|
||||
name: "Asset Directory"
|
||||
isFirst: true
|
||||
|
||||
HifiControls.VerticalSpacer {}
|
||||
|
||||
Row {
|
||||
id: buttonRow
|
||||
width: parent.width
|
||||
height: 30
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
|
||||
HifiControls.GlyphButton {
|
||||
glyph: hifi.glyphs.reload
|
||||
color: hifi.buttons.black
|
||||
colorScheme: root.colorScheme
|
||||
width: hifi.dimensions.controlLineHeight
|
||||
|
||||
onClicked: root.reload()
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
text: "Add To World"
|
||||
color: hifi.buttons.black
|
||||
colorScheme: root.colorScheme
|
||||
width: 120
|
||||
|
||||
enabled: canAddToWorld(assetProxyModel.data(treeView.selection.currentIndex, 0x100))
|
||||
|
||||
onClicked: root.addToWorld()
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
text: "Rename"
|
||||
color: hifi.buttons.black
|
||||
colorScheme: root.colorScheme
|
||||
width: 80
|
||||
|
||||
onClicked: root.renameFile()
|
||||
enabled: treeView.selection.hasSelection
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
id: deleteButton
|
||||
|
||||
text: "Delete"
|
||||
color: hifi.buttons.red
|
||||
colorScheme: root.colorScheme
|
||||
width: 80
|
||||
|
||||
onClicked: root.deleteFile()
|
||||
enabled: treeView.selection.hasSelection
|
||||
}
|
||||
}
|
||||
|
||||
Menu {
|
||||
id: contextMenu
|
||||
title: "Edit"
|
||||
property var url: ""
|
||||
property var currentIndex: null
|
||||
|
||||
MenuItem {
|
||||
text: "Copy URL"
|
||||
onTriggered: {
|
||||
copyURLToClipboard(contextMenu.currentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: "Rename"
|
||||
onTriggered: {
|
||||
renameFile(contextMenu.currentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: "Delete"
|
||||
onTriggered: {
|
||||
deleteFile(contextMenu.currentIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
HifiControls.Tree {
|
||||
id: treeView
|
||||
height: 430
|
||||
anchors.leftMargin: hifi.dimensions.contentMargin.x + 2 // Extra for border
|
||||
anchors.rightMargin: hifi.dimensions.contentMargin.x + 2 // Extra for border
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
treeModel: assetProxyModel
|
||||
canEdit: true
|
||||
colorScheme: root.colorScheme
|
||||
|
||||
modifyEl: renameEl
|
||||
|
||||
MouseArea {
|
||||
propagateComposedEvents: true
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton
|
||||
onClicked: {
|
||||
if (!HMD.active) { // Popup only displays properly on desktop
|
||||
var index = treeView.indexAt(mouse.x, mouse.y);
|
||||
treeView.selection.setCurrentIndex(index, 0x0002);
|
||||
contextMenu.currentIndex = index;
|
||||
contextMenu.popup();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HifiControls.TabletContentSection {
|
||||
id: uploadSection
|
||||
name: "Upload A File"
|
||||
spacing: hifi.dimensions.contentSpacing.y
|
||||
//anchors.bottom: parent.bottom
|
||||
height: 65
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Item {
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
HifiControls.Button {
|
||||
id: uploadButton
|
||||
anchors.right: parent.right
|
||||
|
||||
text: "Choose File"
|
||||
color: hifi.buttons.blue
|
||||
colorScheme: root.colorScheme
|
||||
height: 30
|
||||
width: 155
|
||||
|
||||
onClicked: uploadClickedTimer.running = true
|
||||
|
||||
// For some reason trigginer an API that enters
|
||||
// an internal event loop directly from the button clicked
|
||||
// trigger below causes the appliction to behave oddly.
|
||||
// Most likely because the button onClicked handling is never
|
||||
// completed until the function returns.
|
||||
// FIXME find a better way of handling the input dialogs that
|
||||
// doesn't trigger this.
|
||||
Timer {
|
||||
id: uploadClickedTimer
|
||||
interval: 5
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: uploadClicked();
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: uploadSpinner
|
||||
visible: false
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
width: 40
|
||||
height: 32
|
||||
|
||||
Image {
|
||||
id: image
|
||||
width: 24
|
||||
height: 24
|
||||
source: "../../../images/Loading-Outer-Ring.png"
|
||||
RotationAnimation on rotation {
|
||||
loops: Animation.Infinite
|
||||
from: 0
|
||||
to: 360
|
||||
duration: 2000
|
||||
}
|
||||
}
|
||||
Image {
|
||||
width: 24
|
||||
height: 24
|
||||
source: "../../../images/Loading-Inner-H.png"
|
||||
}
|
||||
HifiControls.Label {
|
||||
id: uploadProgressLabel
|
||||
anchors.left: image.right
|
||||
anchors.leftMargin: 10
|
||||
anchors.verticalCenter: image.verticalCenter
|
||||
text: "In progress..."
|
||||
colorScheme: root.colorScheme
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
344
interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml
Normal file
|
@ -0,0 +1,344 @@
|
|||
//
|
||||
// RunningScripts.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 12 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Dialogs 1.2 as OriginalDialogs
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
import "../../styles-uit"
|
||||
import "../../controls-uit" as HifiControls
|
||||
import "../../windows"
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
objectName: "RunningScripts"
|
||||
HifiConstants { id: hifi }
|
||||
signal sendToScript(var message);
|
||||
property var eventBridge;
|
||||
property var scripts: ScriptDiscoveryService;
|
||||
property var scriptsModel: scripts.scriptsModelFilter
|
||||
property var runningScriptsModel: ListModel { }
|
||||
property bool isHMD: false
|
||||
|
||||
color: hifi.colors.baseGray
|
||||
|
||||
Connections {
|
||||
target: ScriptDiscoveryService
|
||||
onScriptCountChanged: updateRunningScripts();
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
isHMD = HMD.active;
|
||||
updateRunningScripts();
|
||||
}
|
||||
|
||||
function updateRunningScripts() {
|
||||
var runningScripts = ScriptDiscoveryService.getRunning();
|
||||
runningScriptsModel.clear()
|
||||
for (var i = 0; i < runningScripts.length; ++i) {
|
||||
runningScriptsModel.append(runningScripts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function loadScript(script) {
|
||||
console.log("Load script " + script);
|
||||
scripts.loadOneScript(script);
|
||||
}
|
||||
|
||||
function reloadScript(script) {
|
||||
console.log("Reload script " + script);
|
||||
scripts.stopScript(script, true);
|
||||
}
|
||||
|
||||
function stopScript(script) {
|
||||
console.log("Stop script " + script);
|
||||
scripts.stopScript(script);
|
||||
}
|
||||
|
||||
function reloadAll() {
|
||||
console.log("Reload all scripts");
|
||||
scripts.reloadAllScripts();
|
||||
}
|
||||
|
||||
function loadDefaults() {
|
||||
console.log("Load default scripts");
|
||||
scripts.loadOneScript(scripts.defaultScriptsPath + "/defaultScripts.js");
|
||||
}
|
||||
|
||||
function stopAll() {
|
||||
console.log("Stop all scripts");
|
||||
scripts.stopAllScripts();
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
HifiControls.TabletContentSection {
|
||||
name: "Currently Running"
|
||||
isFirst: true
|
||||
|
||||
HifiControls.VerticalSpacer {}
|
||||
|
||||
Row {
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
|
||||
HifiControls.Button {
|
||||
text: "Reload All"
|
||||
color: hifi.buttons.black
|
||||
onClicked: reloadAll()
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
text: "Remove All"
|
||||
color: hifi.buttons.red
|
||||
onClicked: stopAll()
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {
|
||||
height: hifi.dimensions.controlInterlineHeight + 2 // Add space for border
|
||||
}
|
||||
|
||||
HifiControls.Table {
|
||||
model: runningScriptsModel
|
||||
id: table
|
||||
height: 185
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
expandSelectedRow: true
|
||||
|
||||
itemDelegate: Item {
|
||||
anchors {
|
||||
left: parent ? parent.left : undefined
|
||||
leftMargin: hifi.dimensions.tablePadding
|
||||
right: parent ? parent.right : undefined
|
||||
rightMargin: hifi.dimensions.tablePadding
|
||||
}
|
||||
|
||||
FiraSansSemiBold {
|
||||
id: textItem
|
||||
text: styleData.value
|
||||
size: hifi.fontSizes.tableText
|
||||
color: table.colorScheme == hifi.colorSchemes.light
|
||||
? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight)
|
||||
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
topMargin: 3
|
||||
}
|
||||
|
||||
HiFiGlyphs {
|
||||
id: reloadButton
|
||||
text: hifi.glyphs.reloadSmall
|
||||
color: reloadButtonArea.pressed ? hifi.colors.white : parent.color
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: stopButton.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
MouseArea {
|
||||
id: reloadButtonArea
|
||||
anchors { fill: parent; margins: -2 }
|
||||
onClicked: reloadScript(model.url)
|
||||
}
|
||||
}
|
||||
|
||||
HiFiGlyphs {
|
||||
id: stopButton
|
||||
text: hifi.glyphs.closeSmall
|
||||
color: stopButtonArea.pressed ? hifi.colors.white : parent.color
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
MouseArea {
|
||||
id: stopButtonArea
|
||||
anchors { fill: parent; margins: -2 }
|
||||
onClicked: stopScript(model.url)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FiraSansSemiBold {
|
||||
text: runningScriptsModel.get(styleData.row) ? runningScriptsModel.get(styleData.row).url : ""
|
||||
elide: Text.ElideMiddle
|
||||
size: hifi.fontSizes.tableText
|
||||
color: table.colorScheme == hifi.colorSchemes.light
|
||||
? (styleData.selected ? hifi.colors.black : hifi.colors.lightGray)
|
||||
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
|
||||
anchors {
|
||||
top: textItem.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
visible: styleData.selected
|
||||
}
|
||||
}
|
||||
|
||||
TableViewColumn {
|
||||
role: "name"
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {
|
||||
height: hifi.dimensions.controlInterlineHeight + 2 // Add space for border
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.TabletContentSection {
|
||||
name: "Load Scripts"
|
||||
|
||||
HifiControls.VerticalSpacer {}
|
||||
|
||||
Row {
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
|
||||
HifiControls.Button {
|
||||
text: "from URL"
|
||||
color: hifi.buttons.black
|
||||
height: 26
|
||||
onClicked: fromUrlTimer.running = true
|
||||
|
||||
// For some reason trigginer an API that enters
|
||||
// an internal event loop directly from the button clicked
|
||||
// trigger below causes the appliction to behave oddly.
|
||||
// Most likely because the button onClicked handling is never
|
||||
// completed until the function returns.
|
||||
// FIXME find a better way of handling the input dialogs that
|
||||
// doesn't trigger this.
|
||||
Timer {
|
||||
id: fromUrlTimer
|
||||
interval: 5
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: ApplicationInterface.loadScriptURLDialog();
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
text: "from Disk"
|
||||
color: hifi.buttons.black
|
||||
height: 26
|
||||
onClicked: fromDiskTimer.running = true
|
||||
|
||||
Timer {
|
||||
id: fromDiskTimer
|
||||
interval: 5
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: ApplicationInterface.loadDialog();
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
text: "Load Defaults"
|
||||
color: hifi.buttons.black
|
||||
height: 26
|
||||
onClicked: loadDefaults()
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {}
|
||||
|
||||
HifiControls.TextField {
|
||||
id: filterEdit
|
||||
isSearchField: true
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
placeholderText: "Filter"
|
||||
onTextChanged: scriptsModel.filterRegExp = new RegExp("^.*" + text + ".*$", "i")
|
||||
Component.onCompleted: scriptsModel.filterRegExp = new RegExp("^.*$", "i")
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {
|
||||
height: hifi.dimensions.controlInterlineHeight + 2 // Add space for border
|
||||
}
|
||||
|
||||
HifiControls.Tree {
|
||||
id: treeView
|
||||
height: 155
|
||||
treeModel: scriptsModel
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {
|
||||
height: hifi.dimensions.controlInterlineHeight + 2 // Add space for border
|
||||
}
|
||||
|
||||
HifiControls.TextField {
|
||||
id: selectedScript
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: loadButton.width + hifi.dimensions.contentSpacing.x
|
||||
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
readOnly: true
|
||||
|
||||
Connections {
|
||||
target: treeView
|
||||
onCurrentIndexChanged: {
|
||||
var path = scriptsModel.data(treeView.currentIndex, 0x100)
|
||||
if (path) {
|
||||
selectedScript.text = path
|
||||
} else {
|
||||
selectedScript.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
// Take the loadButton out of the column flow.
|
||||
id: loadButtonContainer
|
||||
anchors.top: selectedScript.top
|
||||
anchors.right: parent.right
|
||||
|
||||
HifiControls.Button {
|
||||
id: loadButton
|
||||
anchors.right: parent.right
|
||||
|
||||
text: "Load"
|
||||
color: hifi.buttons.blue
|
||||
enabled: selectedScript.text != ""
|
||||
onClicked: root.loadScript(selectedScript.text)
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {
|
||||
height: hifi.dimensions.controlInterlineHeight - (!isHMD ? 3 : 0)
|
||||
}
|
||||
|
||||
HifiControls.TextAction {
|
||||
id: directoryButton
|
||||
icon: hifi.glyphs.script
|
||||
iconSize: 24
|
||||
text: "Reveal Scripts Folder"
|
||||
onClicked: fileDialogHelper.openDirectory(scripts.defaultScriptsPath)
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
anchors.left: parent.left
|
||||
visible: !isHMD
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {
|
||||
height: hifi.dimensions.controlInterlineHeight - 3
|
||||
visible: !isHMD
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
354
interface/resources/qml/hifi/tablet/Edit.qml
Normal file
|
@ -0,0 +1,354 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtWebEngine 1.1
|
||||
import QtWebChannel 1.0
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import "../../controls"
|
||||
import "../toolbars"
|
||||
import HFWebEngineProfile 1.0
|
||||
import QtGraphicalEffects 1.0
|
||||
import "../../styles-uit"
|
||||
|
||||
StackView {
|
||||
id: editRoot
|
||||
objectName: "stack"
|
||||
initialItem: editBasePage
|
||||
|
||||
property var eventBridge;
|
||||
signal sendToScript(var message);
|
||||
|
||||
function pushSource(path) {
|
||||
editRoot.push(Qt.resolvedUrl(path));
|
||||
editRoot.currentItem.eventBridge = editRoot.eventBridge;
|
||||
editRoot.currentItem.sendToScript.connect(editRoot.sendToScript);
|
||||
}
|
||||
|
||||
function popSource() {
|
||||
editRoot.pop();
|
||||
}
|
||||
|
||||
|
||||
Component {
|
||||
id: editBasePage
|
||||
TabView {
|
||||
id: editTabView
|
||||
// anchors.fill: parent
|
||||
height: 60
|
||||
|
||||
Tab {
|
||||
title: "CREATE"
|
||||
active: true
|
||||
enabled: true
|
||||
property string originalUrl: ""
|
||||
|
||||
Rectangle {
|
||||
color: "#404040"
|
||||
|
||||
Text {
|
||||
color: "#ffffff"
|
||||
text: "Choose an Entity Type to Create:"
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 28
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 28
|
||||
}
|
||||
|
||||
Flow {
|
||||
id: createEntitiesFlow
|
||||
spacing: 35
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 55
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 55
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 70
|
||||
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/94-model-01.svg"
|
||||
text: "MODEL"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newModelButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/21-cube-01.svg"
|
||||
text: "CUBE"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newCubeButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/22-sphere-01.svg"
|
||||
text: "SPHERE"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newSphereButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/24-light-01.svg"
|
||||
text: "LIGHT"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newLightButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/20-text-01.svg"
|
||||
text: "TEXT"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newTextButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/25-web-1-01.svg"
|
||||
text: "WEB"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newWebButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/23-zone-01.svg"
|
||||
text: "ZONE"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newZoneButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
|
||||
NewEntityButton {
|
||||
icon: "icons/create-icons/90-particles-01.svg"
|
||||
text: "PARTICLE"
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "newParticleButton" }
|
||||
});
|
||||
editTabView.currentIndex = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: assetServerButton
|
||||
width: 370
|
||||
height: 38
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: createEntitiesFlow.bottom
|
||||
anchors.topMargin: 35
|
||||
|
||||
Rectangle {
|
||||
id: assetServerButtonBg
|
||||
color: "black"
|
||||
opacity: 1
|
||||
radius: 6
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 0
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: assetServerButtonGradient
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "#383838"
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
opacity: 1
|
||||
radius: 6
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 0
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
|
||||
Text {
|
||||
color: "#ffffff"
|
||||
text: "OPEN THIS DOMAIN'S ASSET SERVER"
|
||||
font.bold: true
|
||||
font.pixelSize: 14
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
enabled: true
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
method: "newEntityButtonClicked", params: { buttonName: "openAssetBrowserButton" }
|
||||
});
|
||||
}
|
||||
onEntered: {
|
||||
assetServerButton.state = "hover state";
|
||||
}
|
||||
onExited: {
|
||||
assetServerButton.state = "base state";
|
||||
}
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "hover state"
|
||||
|
||||
PropertyChanges {
|
||||
target: assetServerButtonGradient
|
||||
opacity: 0
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "base state"
|
||||
|
||||
PropertyChanges {
|
||||
target: assetServerButtonGradient
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Tab {
|
||||
title: "LIST"
|
||||
active: true
|
||||
enabled: true
|
||||
property string originalUrl: ""
|
||||
|
||||
WebView {
|
||||
id: entityListToolWebView
|
||||
url: "../../../../../scripts/system/html/entityList.html"
|
||||
eventBridge: editRoot.eventBridge
|
||||
anchors.fill: parent
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
|
||||
Tab {
|
||||
title: "PROPERTIES"
|
||||
active: true
|
||||
enabled: true
|
||||
property string originalUrl: ""
|
||||
|
||||
WebView {
|
||||
id: entityPropertiesWebView
|
||||
url: "../../../../../scripts/system/html/entityProperties.html"
|
||||
eventBridge: editRoot.eventBridge
|
||||
anchors.fill: parent
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
|
||||
Tab {
|
||||
title: "GRID"
|
||||
active: true
|
||||
enabled: true
|
||||
property string originalUrl: ""
|
||||
|
||||
WebView {
|
||||
id: gridControlsWebView
|
||||
url: "../../../../../scripts/system/html/gridControls.html"
|
||||
eventBridge: editRoot.eventBridge
|
||||
anchors.fill: parent
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
|
||||
Tab {
|
||||
title: "P"
|
||||
active: true
|
||||
enabled: true
|
||||
property string originalUrl: ""
|
||||
|
||||
WebView {
|
||||
id: particleExplorerWebView
|
||||
url: "../../../../../scripts/system/particle_explorer/particleExplorer.html"
|
||||
eventBridge: editRoot.eventBridge
|
||||
anchors.fill: parent
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
style: TabViewStyle {
|
||||
frameOverlap: 1
|
||||
tab: Rectangle {
|
||||
color: styleData.selected ? "#404040" :"black"
|
||||
implicitWidth: text.width + 42
|
||||
implicitHeight: 40
|
||||
Text {
|
||||
id: text
|
||||
anchors.centerIn: parent
|
||||
text: styleData.title
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
color: styleData.selected ? "white" : "white"
|
||||
property string glyphtext: ""
|
||||
HiFiGlyphs {
|
||||
anchors.centerIn: parent
|
||||
size: 30
|
||||
color: "#ffffff"
|
||||
text: text.glyphtext
|
||||
}
|
||||
Component.onCompleted: if (styleData.title == "P") {
|
||||
text.text = " ";
|
||||
text.glyphtext = "\ue004";
|
||||
}
|
||||
}
|
||||
}
|
||||
tabBar: Rectangle {
|
||||
color: "black"
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 0
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
160
interface/resources/qml/hifi/tablet/NewEntityButton.qml
Normal file
|
@ -0,0 +1,160 @@
|
|||
import QtQuick 2.0
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
Item {
|
||||
id: newEntityButton
|
||||
property var uuid;
|
||||
property string text: "ENTITY"
|
||||
property string icon: "icons/edit-icon.svg"
|
||||
property string activeText: newEntityButton.text
|
||||
property string activeIcon: newEntityButton.icon
|
||||
property bool isActive: false
|
||||
property bool inDebugMode: false
|
||||
property bool isEntered: false
|
||||
property double sortOrder: 100
|
||||
property int stableOrder: 0
|
||||
property var tabletRoot;
|
||||
width: 100
|
||||
height: 100
|
||||
|
||||
signal clicked()
|
||||
|
||||
function changeProperty(key, value) {
|
||||
tabletButton[key] = value;
|
||||
}
|
||||
|
||||
onIsActiveChanged: {
|
||||
if (tabletButton.isEntered) {
|
||||
tabletButton.state = (tabletButton.isActive) ? "hover active state" : "hover sate";
|
||||
} else {
|
||||
tabletButton.state = (tabletButton.isActive) ? "active state" : "base sate";
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: buttonBg
|
||||
color: "#1c1c1c"
|
||||
opacity: 1
|
||||
radius: 8
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 0
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
|
||||
function urlHelper(src) {
|
||||
if (src.match(/\bhttp/)) {
|
||||
return src;
|
||||
} else {
|
||||
return "../../../" + src;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: buttonOutline
|
||||
color: "#00000000"
|
||||
opacity: 0
|
||||
radius: 8
|
||||
z: 1
|
||||
border.width: 2
|
||||
border.color: "#ffffff"
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 0
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
|
||||
DropShadow {
|
||||
id: glow
|
||||
visible: false
|
||||
anchors.fill: parent
|
||||
horizontalOffset: 0
|
||||
verticalOffset: 0
|
||||
color: "#ffffff"
|
||||
radius: 20
|
||||
z: -1
|
||||
samples: 41
|
||||
source: buttonOutline
|
||||
}
|
||||
|
||||
|
||||
Image {
|
||||
id: icon
|
||||
width: 50
|
||||
height: 50
|
||||
visible: false
|
||||
anchors.bottom: text.top
|
||||
anchors.bottomMargin: 5
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
fillMode: Image.Stretch
|
||||
source: newEntityButton.urlHelper(newEntityButton.icon)
|
||||
}
|
||||
|
||||
ColorOverlay {
|
||||
id: iconColorOverlay
|
||||
anchors.fill: icon
|
||||
source: icon
|
||||
color: "#ffffff"
|
||||
}
|
||||
|
||||
Text {
|
||||
id: text
|
||||
color: "#ffffff"
|
||||
text: newEntityButton.text
|
||||
font.bold: true
|
||||
font.pixelSize: 16
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 12
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
enabled: true
|
||||
onClicked: {
|
||||
newEntityButton.clicked();
|
||||
}
|
||||
onEntered: {
|
||||
newEntityButton.state = "hover state";
|
||||
}
|
||||
onExited: {
|
||||
newEntityButton.state = "base state";
|
||||
}
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "hover state"
|
||||
|
||||
PropertyChanges {
|
||||
target: buttonOutline
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: glow
|
||||
visible: true
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "base state"
|
||||
|
||||
PropertyChanges {
|
||||
target: glow
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
158
interface/resources/qml/hifi/tablet/NewModelDialog.qml
Normal file
|
@ -0,0 +1,158 @@
|
|||
//
|
||||
// NewModelDialog.qml
|
||||
// qml/hifi
|
||||
//
|
||||
// Created by Seth Alves on 2017-2-10
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import "../../styles-uit"
|
||||
import "../../controls-uit"
|
||||
|
||||
Rectangle {
|
||||
id: newModelDialog
|
||||
// width: parent.width
|
||||
// height: parent.height
|
||||
HifiConstants { id: hifi }
|
||||
color: hifi.colors.baseGray;
|
||||
property var eventBridge;
|
||||
signal sendToScript(var message);
|
||||
|
||||
Column {
|
||||
id: column1
|
||||
anchors.rightMargin: 10
|
||||
anchors.leftMargin: 10
|
||||
anchors.bottomMargin: 10
|
||||
anchors.topMargin: 10
|
||||
anchors.fill: parent
|
||||
spacing: 5
|
||||
|
||||
Text {
|
||||
id: text1
|
||||
text: qsTr("Model URL")
|
||||
color: "#ffffff"
|
||||
font.pixelSize: 12
|
||||
}
|
||||
|
||||
TextInput {
|
||||
id: modelURL
|
||||
height: 20
|
||||
text: qsTr("")
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
font.pixelSize: 12
|
||||
}
|
||||
|
||||
Row {
|
||||
id: row1
|
||||
height: 400
|
||||
spacing: 30
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
|
||||
Column {
|
||||
id: column2
|
||||
width: 200
|
||||
height: 400
|
||||
spacing: 10
|
||||
|
||||
CheckBox {
|
||||
id: dynamic
|
||||
text: qsTr("Dynamic")
|
||||
|
||||
}
|
||||
|
||||
Row {
|
||||
id: row2
|
||||
width: 200
|
||||
height: 400
|
||||
spacing: 20
|
||||
|
||||
Image {
|
||||
id: image1
|
||||
width: 30
|
||||
height: 30
|
||||
source: "qrc:/qtquickplugin/images/template_image.png"
|
||||
}
|
||||
|
||||
Text {
|
||||
id: text2
|
||||
width: 160
|
||||
color: "#ffffff"
|
||||
text: qsTr("Models with automatic collisions set to 'Exact' cannot be dynamic")
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: 12
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: column3
|
||||
height: 400
|
||||
spacing: 10
|
||||
|
||||
Text {
|
||||
id: text3
|
||||
text: qsTr("Automatic Collisions")
|
||||
color: "#ffffff"
|
||||
font.pixelSize: 12
|
||||
}
|
||||
|
||||
TabletComboBox {
|
||||
id: collisionType
|
||||
width: 200
|
||||
z: 100
|
||||
transformOrigin: Item.Center
|
||||
model: ["No Collision",
|
||||
"Basic - Whole model",
|
||||
"Good - Sub-meshes",
|
||||
"Exact - All polygons"]
|
||||
}
|
||||
|
||||
Row {
|
||||
id: row3
|
||||
width: 200
|
||||
height: 400
|
||||
spacing: 5
|
||||
|
||||
anchors {
|
||||
rightMargin: 15
|
||||
}
|
||||
Button {
|
||||
id: button1
|
||||
text: qsTr("Add")
|
||||
z: -1
|
||||
onClicked: {
|
||||
newModelDialog.sendToScript({
|
||||
method: "newModelDialogAdd",
|
||||
params: {
|
||||
textInput: modelURL.text,
|
||||
checkBox: dynamic.checked,
|
||||
comboBox: collisionType.currentIndex
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: button2
|
||||
z: -1
|
||||
text: qsTr("Cancel")
|
||||
onClicked: {
|
||||
newModelDialog.sendToScript({method: "newModelDialogCancel"})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// TabletAudioPreferences.qml
|
||||
//
|
||||
// Created by Davd Rowe on 7 Mar 2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import "tabletWindows"
|
||||
import "../../dialogs"
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
StackView {
|
||||
id: profileRoot
|
||||
initialItem: root
|
||||
objectName: "stack"
|
||||
|
||||
property var eventBridge;
|
||||
signal sendToScript(var message);
|
||||
|
||||
function pushSource(path) {
|
||||
editRoot.push(Qt.reslovedUrl(path));
|
||||
}
|
||||
|
||||
function popSource() {
|
||||
|
||||
}
|
||||
|
||||
TabletPreferencesDialog {
|
||||
id: root
|
||||
property string title: "Audio Settings"
|
||||
objectName: "TabletAudioPreferences"
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
showCategories: ["Audio"]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// TabletAvatarPreferences.qml
|
||||
//
|
||||
// Created by Davd Rowe on 2 Mar 2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import "tabletWindows"
|
||||
import "../../dialogs"
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
StackView {
|
||||
id: profileRoot
|
||||
initialItem: root
|
||||
objectName: "stack"
|
||||
|
||||
property var eventBridge;
|
||||
signal sendToScript(var message);
|
||||
|
||||
function pushSource(path) {
|
||||
editRoot.push(Qt.reslovedUrl(path));
|
||||
}
|
||||
|
||||
function popSource() {
|
||||
|
||||
}
|
||||
|
||||
TabletPreferencesDialog {
|
||||
id: root
|
||||
property string title: "Avatar Preferences"
|
||||
objectName: "TabletAvatarPreferences"
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
showCategories: ["Avatar Basics", "Avatar Tuning", "Avatar Camera"]
|
||||
}
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
//
|
||||
// TabletGeneralSettings.qml
|
||||
// scripts/system/
|
||||
// TabletGeneralPreferences.qml
|
||||
//
|
||||
// Created by Dante Ruiz on 9 Feb 2017
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -34,11 +33,10 @@ StackView {
|
|||
|
||||
TabletPreferencesDialog {
|
||||
id: root
|
||||
objectName: "GeneralPreferencesDialog"
|
||||
property string title: "General Preferences"
|
||||
objectName: "TabletGeneralPreferences"
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers", "Perception Neuron", "Kinect"]
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -2,8 +2,14 @@ import QtQuick 2.5
|
|||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQml 2.2
|
||||
import QtWebChannel 1.0
|
||||
import QtWebEngine 1.1
|
||||
import HFWebEngineProfile 1.0
|
||||
|
||||
|
||||
import "."
|
||||
import "../../styles-uit"
|
||||
import "../../controls"
|
||||
|
||||
FocusScope {
|
||||
id: tabletMenu
|
||||
|
@ -13,10 +19,11 @@ FocusScope {
|
|||
height: 720
|
||||
|
||||
property var rootMenu: Menu { objectName:"rootMenu" }
|
||||
property var point: Qt.point(50, 50)
|
||||
property var point: Qt.point(50, 50);
|
||||
TabletMenuStack { id: menuPopperUpper }
|
||||
property string subMenu: ""
|
||||
|
||||
TabletMouseHandler { id: menuPopperUpper }
|
||||
property var eventBridge;
|
||||
signal sendToScript(var message);
|
||||
|
||||
Rectangle {
|
||||
id: bgNavBar
|
||||
|
@ -57,6 +64,7 @@ FocusScope {
|
|||
// navigate back to root level menu
|
||||
onClicked: {
|
||||
buildMenu();
|
||||
breadcrumbText.text = "Menu";
|
||||
tabletRoot.playButtonClickSound();
|
||||
}
|
||||
}
|
||||
|
@ -97,6 +105,7 @@ FocusScope {
|
|||
menuPopperUpper.closeLastMenu();
|
||||
}
|
||||
|
||||
|
||||
function setRootMenu(rootMenu, subMenu) {
|
||||
tabletMenu.subMenu = subMenu;
|
||||
tabletMenu.rootMenu = rootMenu;
|
||||
|
@ -116,12 +125,12 @@ FocusScope {
|
|||
}
|
||||
subMenu = ""; // Continue with full menu after initially displaying submenu.
|
||||
if (found) {
|
||||
menuPopperUpper.popup(tabletMenu, rootMenu.items[index].items);
|
||||
menuPopperUpper.popup(rootMenu.items[index].items);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise build whole menu.
|
||||
menuPopperUpper.popup(tabletMenu, rootMenu.items);
|
||||
menuPopperUpper.popup(rootMenu.items);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// MessageDialog.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 18 Jan 2016
|
||||
// Created by Dante Ruiz on 13 Feb 2017
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
|
@ -17,19 +17,13 @@ Item {
|
|||
id: root
|
||||
anchors.fill: parent
|
||||
objectName: "tabletMenuHandlerItem"
|
||||
|
||||
MouseArea {
|
||||
id: menuRoot;
|
||||
objectName: "tabletMenuHandlerMouseArea"
|
||||
|
||||
StackView {
|
||||
anchors.fill: parent
|
||||
enabled: d.topMenu !== null
|
||||
onClicked: {
|
||||
d.clearMenus();
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
objectName: "stack"
|
||||
initialItem: topMenu
|
||||
|
||||
property var menuStack: []
|
||||
property var topMenu: null;
|
||||
property var modelMaker: Component { ListModel { } }
|
||||
|
@ -53,6 +47,18 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
function pushSource(path) {
|
||||
d.push(Qt.resolvedUrl(path));
|
||||
d.currentItem.eventBridge = tabletMenu.eventBridge
|
||||
d.currentItem.sendToScript.connect(tabletMenu.sendToScript);
|
||||
breadcrumbText.text = d.currentItem.objectName;
|
||||
}
|
||||
|
||||
function popSource() {
|
||||
console.log("trying to pop page");
|
||||
d.pop();
|
||||
}
|
||||
|
||||
function toModel(items) {
|
||||
var result = modelMaker.createObject(tabletMenu);
|
||||
for (var i = 0; i < items.length; ++i) {
|
||||
|
@ -76,22 +82,18 @@ Item {
|
|||
}
|
||||
|
||||
function popMenu() {
|
||||
if (menuStack.length) {
|
||||
menuStack.pop().destroy();
|
||||
if (d.depth) {
|
||||
d.pop();
|
||||
}
|
||||
if (menuStack.length) {
|
||||
topMenu = menuStack[menuStack.length - 1];
|
||||
if (d.depth) {
|
||||
topMenu = d.currentItem;
|
||||
topMenu.focus = true;
|
||||
topMenu.forceActiveFocus();
|
||||
// show current menu level on nav bar
|
||||
if (topMenu.objectName === "") {
|
||||
if (topMenu.objectName === "" || d.depth === 1) {
|
||||
breadcrumbText.text = "Menu";
|
||||
} else {
|
||||
if (menuStack.length === 1) {
|
||||
breadcrumbText.text = "Menu";
|
||||
} else {
|
||||
breadcrumbText.text = topMenu.objectName;
|
||||
}
|
||||
breadcrumbText.text = topMenu.objectName;
|
||||
}
|
||||
} else {
|
||||
breadcrumbText.text = "Menu";
|
||||
|
@ -100,16 +102,14 @@ Item {
|
|||
}
|
||||
|
||||
function pushMenu(newMenu) {
|
||||
menuStack.push(newMenu);
|
||||
d.push({ item:newMenu, destroyOnPop: true});
|
||||
topMenu = newMenu;
|
||||
topMenu.focus = true;
|
||||
topMenu.forceActiveFocus();
|
||||
}
|
||||
|
||||
function clearMenus() {
|
||||
while (menuStack.length) {
|
||||
popMenu()
|
||||
}
|
||||
d.clear()
|
||||
}
|
||||
|
||||
function clampMenuPosition(menu) {
|
||||
|
@ -127,7 +127,7 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
function buildMenu(items, targetPosition) {
|
||||
function buildMenu(items) {
|
||||
var model = toModel(items);
|
||||
// Menus must be childed to desktop for Z-ordering
|
||||
var newMenu = menuViewMaker.createObject(tabletMenu, { model: model, isSubMenu: topMenu !== null });
|
||||
|
@ -158,13 +158,13 @@ Item {
|
|||
|
||||
}
|
||||
|
||||
function popup(parent, items) {
|
||||
function popup(items) {
|
||||
d.clearMenus();
|
||||
d.buildMenu(items, point);
|
||||
d.buildMenu(items);
|
||||
}
|
||||
|
||||
function closeLastMenu() {
|
||||
if (d.menuStack.length > 1) {
|
||||
if (d.depth > 1) {
|
||||
d.popMenu();
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// TabletNetworkingPreferences.qml
|
||||
//
|
||||
// Created by Davd Rowe on 7 Mar 2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import "tabletWindows"
|
||||
import "../../dialogs"
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
StackView {
|
||||
id: profileRoot
|
||||
initialItem: root
|
||||
objectName: "stack"
|
||||
|
||||
property var eventBridge;
|
||||
signal sendToScript(var message);
|
||||
|
||||
function pushSource(path) {
|
||||
editRoot.push(Qt.reslovedUrl(path));
|
||||
}
|
||||
|
||||
function popSource() {
|
||||
|
||||
}
|
||||
|
||||
TabletPreferencesDialog {
|
||||
id: root
|
||||
property string title: "Networking Settings"
|
||||
objectName: "NetworkingPreferences"
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
showCategories: ["Networking"]
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
import QtQuick 2.0
|
||||
import Hifi 1.0
|
||||
import QtQuick.Controls 1.4
|
||||
import "../../dialogs"
|
||||
|
||||
Item {
|
||||
id: tabletRoot
|
||||
|
@ -8,19 +10,50 @@ Item {
|
|||
property var eventBridge;
|
||||
|
||||
property var rootMenu;
|
||||
property var openModal: null;
|
||||
property var openMessage: null;
|
||||
property string subMenu: ""
|
||||
|
||||
signal showDesktop();
|
||||
|
||||
function setOption(value) {
|
||||
option = value;
|
||||
}
|
||||
|
||||
Component { id: inputDialogBuilder; TabletQueryDialog { } }
|
||||
function inputDialog(properties) {
|
||||
openModal = inputDialogBuilder.createObject(tabletRoot, properties);
|
||||
return openModal;
|
||||
}
|
||||
Component { id: messageBoxBuilder; TabletMessageBox { } }
|
||||
function messageBox(properties) {
|
||||
openMessage = messageBoxBuilder.createObject(tabletRoot, properties);
|
||||
return openMessage;
|
||||
}
|
||||
|
||||
Component { id: customInputDialogBuilder; TabletCustomQueryDialog { } }
|
||||
function customInputDialog(properties) {
|
||||
return customInputDialogBuilder.createObject(tabletRoot, properties);
|
||||
}
|
||||
|
||||
Component { id: fileDialogBuilder; TabletFileDialog { } }
|
||||
function fileDialog(properties) {
|
||||
openModal = fileDialogBuilder.createObject(tabletRoot, properties);
|
||||
return openModal;
|
||||
}
|
||||
|
||||
function setMenuProperties(rootMenu, subMenu) {
|
||||
tabletRoot.rootMenu = rootMenu;
|
||||
tabletRoot.subMenu = subMenu;
|
||||
}
|
||||
|
||||
function isDialogOpen() {
|
||||
if (openMessage !== null || openModal !== null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function loadSource(url) {
|
||||
loader.source = ""; // make sure we load the qml fresh each time.
|
||||
loader.source = url;
|
||||
|
@ -68,6 +101,7 @@ Item {
|
|||
objectName: "loader"
|
||||
asynchronous: false
|
||||
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
|
@ -89,6 +123,12 @@ Item {
|
|||
loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu);
|
||||
}
|
||||
loader.item.forceActiveFocus();
|
||||
|
||||
if (openModal) {
|
||||
openModal.canceled();
|
||||
openModal.destroy();
|
||||
openModal = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,12 +27,22 @@ Item {
|
|||
HifiConstants { id: hifi }
|
||||
property var sections: []
|
||||
property var showCategories: []
|
||||
|
||||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
|
||||
property var tablet;
|
||||
|
||||
function saveAll() {
|
||||
dialog.forceActiveFocus(); // Accept any text box edits in progress.
|
||||
|
||||
for (var i = 0; i < sections.length; ++i) {
|
||||
var section = sections[i];
|
||||
section.saveAll();
|
||||
}
|
||||
|
||||
closeDialog();
|
||||
}
|
||||
|
||||
function restoreAll() {
|
||||
|
@ -40,22 +50,59 @@ Item {
|
|||
var section = sections[i];
|
||||
section.restoreAll();
|
||||
}
|
||||
|
||||
closeDialog();
|
||||
}
|
||||
|
||||
|
||||
function closeDialog() {
|
||||
Tablet.getTablet("com.highfidelity.interface.tablet.system").gotoHomeScreen();
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: main
|
||||
height: parent.height - 40
|
||||
id: header
|
||||
height: 90
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: footer.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
z: 100
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "#2b2b2b"
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "#1e1e1e"
|
||||
}
|
||||
}
|
||||
|
||||
RalewayBold {
|
||||
text: title
|
||||
size: 26
|
||||
color: "#34a2c7"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: hifi.dimensions.contentMargin.x
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: main
|
||||
anchors {
|
||||
top: header.bottom
|
||||
bottom: footer.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "#2b2b2b"
|
||||
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
|
@ -110,9 +157,7 @@ Item {
|
|||
}
|
||||
|
||||
scrollView.contentHeight = scrollView.getSectionsHeight();
|
||||
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
id: prefControls
|
||||
|
@ -131,13 +176,30 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
// Defocuses the current control so that the HMD keyboard gets hidden.
|
||||
// Created under the footer so that the non-button part of the footer can defocus a control.
|
||||
id: mouseArea
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: keyboard.top
|
||||
}
|
||||
propagateComposedEvents: true
|
||||
acceptedButtons: Qt.AllButtons
|
||||
onPressed: {
|
||||
parent.forceActiveFocus();
|
||||
mouse.accepted = false;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: footer
|
||||
height: 40
|
||||
|
||||
anchors {
|
||||
top: main.bottom
|
||||
bottom: parent.bottom
|
||||
bottom: keyboard.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
|
@ -145,7 +207,6 @@ Item {
|
|||
GradientStop {
|
||||
position: 0
|
||||
color: "#2b2b2b"
|
||||
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
|
@ -156,7 +217,7 @@ Item {
|
|||
|
||||
Row {
|
||||
anchors {
|
||||
top: parent,top
|
||||
verticalCenter: parent.verticalCenter
|
||||
right: parent.right
|
||||
rightMargin: hifi.dimensions.contentMargin.x
|
||||
}
|
||||
|
@ -165,15 +226,39 @@ Item {
|
|||
HifiControls.Button {
|
||||
text: "Save changes"
|
||||
color: hifi.buttons.blue
|
||||
onClicked: root.saveAll()
|
||||
onClicked: dialog.saveAll()
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
text: "Cancel"
|
||||
color: hifi.buttons.white
|
||||
onClicked: root.restoreAll()
|
||||
onClicked: dialog.restoreAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Keyboard {
|
||||
id: keyboard
|
||||
raised: parent.keyboardEnabled && parent.keyboardRaised
|
||||
numeric: parent.punctuationMode
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
keyboardEnabled = HMD.active;
|
||||
}
|
||||
|
||||
onKeyboardRaisedChanged: {
|
||||
if (keyboardEnabled && keyboardRaised) {
|
||||
var delta = mouseArea.mouseY - (dialog.height - footer.height - keyboard.raisedHeight -hifi.dimensions.controlLineHeight);
|
||||
if (delta > 0) {
|
||||
scrollView.contentY += delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import QtQuick.Controls.Styles 1.4
|
|||
|
||||
Text {
|
||||
id: root
|
||||
FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; }
|
||||
FontLoader { id: firaSansSemiBold; source: pathToFonts + "fonts/FiraSans-SemiBold.ttf"; }
|
||||
property real size: 32
|
||||
font.pixelSize: size
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
|
|
@ -14,7 +14,7 @@ import QtQuick.Controls.Styles 1.4
|
|||
|
||||
Text {
|
||||
id: root
|
||||
FontLoader { id: hiFiGlyphs; source: "../../fonts/hifi-glyphs.ttf"; }
|
||||
FontLoader { id: hiFiGlyphs; source: pathToFonts + "fonts/hifi-glyphs.ttf"; }
|
||||
property int size: 32
|
||||
font.pixelSize: size
|
||||
width: size
|
||||
|
|
|
@ -159,6 +159,7 @@ Item {
|
|||
readonly property vector2d menuPadding: Qt.vector2d(14, 102)
|
||||
readonly property real scrollbarBackgroundWidth: 18
|
||||
readonly property real scrollbarHandleWidth: scrollbarBackgroundWidth - 2
|
||||
readonly property real tabletMenuHeader: 90
|
||||
}
|
||||
|
||||
Item {
|
||||
|
|
|
@ -14,7 +14,7 @@ import QtQuick.Controls.Styles 1.4
|
|||
|
||||
Text {
|
||||
id: root
|
||||
FontLoader { id: ralewayBold; source: "../../fonts/Raleway-Bold.ttf"; }
|
||||
FontLoader { id: ralewayBold; source: pathToFonts + "fonts/Raleway-Bold.ttf"; }
|
||||
property real size: 32
|
||||
font.pixelSize: size
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
|
|
@ -14,7 +14,7 @@ import QtQuick.Controls.Styles 1.4
|
|||
|
||||
Text {
|
||||
id: root
|
||||
FontLoader { id: ralewayRegular; source: "../../fonts/Raleway-Regular.ttf"; }
|
||||
FontLoader { id: ralewayRegular; source: pathToFonts + "fonts/Raleway-Regular.ttf"; }
|
||||
property real size: 32
|
||||
font.pixelSize: size
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
|
|
@ -14,7 +14,7 @@ import QtQuick.Controls.Styles 1.4
|
|||
|
||||
Text {
|
||||
id: root
|
||||
FontLoader { id: ralewaySemiBold; source: "../../fonts/Raleway-SemiBold.ttf"; }
|
||||
FontLoader { id: ralewaySemiBold; source: pathToFonts + "fonts/Raleway-SemiBold.ttf"; }
|
||||
property real size: 32
|
||||
font.pixelSize: size
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
|
89
interface/resources/qml/windows/TabletModalFrame.qml
Normal file
|
@ -0,0 +1,89 @@
|
|||
//
|
||||
// ModalFrame.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 15 Jan 2016
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
|
||||
import "."
|
||||
import "../controls-uit"
|
||||
import "../styles-uit"
|
||||
|
||||
|
||||
Rectangle {
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
id: frameContent
|
||||
|
||||
readonly property bool hasTitle: root.title != ""
|
||||
|
||||
readonly property int frameMarginLeft: hifi.dimensions.modalDialogMargin.x
|
||||
readonly property int frameMarginRight: hifi.dimensions.modalDialogMargin.x
|
||||
readonly property int frameMarginTop: hifi.dimensions.modalDialogMargin.y + (frameContent.hasTitle ? hifi.dimensions.modalDialogTitleHeight + 10 : 0)
|
||||
readonly property int frameMarginBottom: hifi.dimensions.modalDialogMargin.y
|
||||
|
||||
border {
|
||||
width: hifi.dimensions.borderWidth
|
||||
color: hifi.colors.lightGrayText80
|
||||
}
|
||||
|
||||
radius: hifi.dimensions.borderRadius
|
||||
color: hifi.colors.faintGray
|
||||
Item {
|
||||
id: frameTitle
|
||||
visible: frameContent.hasTitle
|
||||
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
verticalCenter: parent.verticalCenter
|
||||
fill: parent
|
||||
topMargin: frameMarginTop
|
||||
leftMargin: frameMarginLeft
|
||||
rightMargin: frameMarginRight
|
||||
//bottomMargin: frameMarginBottom
|
||||
}
|
||||
|
||||
Item {
|
||||
width: title.width + (icon.text !== "" ? icon.width + hifi.dimensions.contentSpacing.x : 20)
|
||||
|
||||
onWidthChanged: root.titleWidth = width
|
||||
|
||||
HiFiGlyphs {
|
||||
id: icon
|
||||
text: root.iconText ? root.iconText : ""
|
||||
size: root.iconSize ? root.iconSize : 30
|
||||
color: hifi.colors.lightGray
|
||||
visible: true
|
||||
anchors.verticalCenter: title.verticalCenter
|
||||
anchors.leftMargin: 50
|
||||
anchors.left: parent.left
|
||||
}
|
||||
|
||||
RalewayRegular {
|
||||
id: title
|
||||
text: root.title
|
||||
elide: Text.ElideRight
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
size: hifi.fontSizes.overlayTitle
|
||||
y: -hifi.dimensions.modalDialogTitleHeight
|
||||
anchors.rightMargin: -50
|
||||
anchors.right: parent.right
|
||||
//anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 1
|
||||
color: hifi.colors.lightGray
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
22
interface/resources/qml/windows/TabletModalWindow.qml
Normal file
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
// ModalWindow.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 22 Jan 2016
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Dialogs 1.2 as OriginalDialogs
|
||||
import "."
|
||||
|
||||
Rectangle {
|
||||
id: modalWindow
|
||||
layer.enabled: true
|
||||
property var title: "Modal"
|
||||
width: tabletRoot.width
|
||||
height: tabletRoot.height
|
||||
color: "#80000000"
|
||||
}
|
|
@ -313,6 +313,6 @@ Fadable {
|
|||
}
|
||||
}
|
||||
|
||||
onMouseEntered: console.log("Mouse entered " + window)
|
||||
onMouseExited: console.log("Mouse exited " + window)
|
||||
// onMouseEntered: console.log("Mouse entered " + window)
|
||||
// onMouseExited: console.log("Mouse exited " + window)
|
||||
}
|
||||
|
|
|
@ -499,6 +499,7 @@ bool setupEssentials(int& argc, char** argv) {
|
|||
DependencyManager::set<TabletScriptingInterface>();
|
||||
DependencyManager::set<ToolbarScriptingInterface>();
|
||||
DependencyManager::set<UserActivityLoggerScriptingInterface>();
|
||||
DependencyManager::set<AssetMappingsScriptingInterface>();
|
||||
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
DependencyManager::set<SpeechRecognizer>();
|
||||
|
@ -847,6 +848,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress);
|
||||
|
||||
connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateThreadPoolCount);
|
||||
connect(this, &Application::activeDisplayPluginChanged, this, [](){
|
||||
qApp->setProperty(hifi::properties::HMD, qApp->isHMDMode());
|
||||
});
|
||||
connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateSystemTabletMode);
|
||||
|
||||
// Save avatar location immediately after a teleport.
|
||||
|
@ -1619,17 +1623,14 @@ QString Application::getUserAgent() {
|
|||
return userAgent;
|
||||
}
|
||||
|
||||
uint64_t lastTabletUIToggle { 0 };
|
||||
const uint64_t toggleTabletUILockout { 500000 };
|
||||
void Application::toggleTabletUI() const {
|
||||
uint64_t now = usecTimestampNow();
|
||||
if (now - lastTabletUIToggle < toggleTabletUILockout) {
|
||||
return;
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
TabletProxy* tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
||||
bool messageOpen = tablet->isMessageDialogOpen();
|
||||
if (!messageOpen) {
|
||||
auto HMD = DependencyManager::get<HMDScriptingInterface>();
|
||||
HMD->toggleShouldShowTablet();
|
||||
}
|
||||
lastTabletUIToggle = now;
|
||||
|
||||
auto HMD = DependencyManager::get<HMDScriptingInterface>();
|
||||
HMD->toggleShouldShowTablet();
|
||||
}
|
||||
|
||||
void Application::checkChangeCursor() {
|
||||
|
@ -1961,12 +1962,13 @@ void Application::initializeUi() {
|
|||
rootContext->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
rootContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface);
|
||||
rootContext->setContextProperty("Rates", new RatesScriptingInterface(this));
|
||||
rootContext->setContextProperty("pathToFonts", "../../");
|
||||
|
||||
rootContext->setContextProperty("TREE_SCALE", TREE_SCALE);
|
||||
rootContext->setContextProperty("Quat", new Quat());
|
||||
rootContext->setContextProperty("Vec3", new Vec3());
|
||||
rootContext->setContextProperty("Uuid", new ScriptUUID());
|
||||
rootContext->setContextProperty("Assets", new AssetMappingsScriptingInterface());
|
||||
rootContext->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
|
||||
|
||||
rootContext->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
|
||||
rootContext->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
|
||||
|
@ -5790,8 +5792,23 @@ bool Application::displayAvatarAttachmentConfirmationDialog(const QString& name)
|
|||
}
|
||||
|
||||
void Application::toggleRunningScriptsWidget() const {
|
||||
static const QUrl url("hifi/dialogs/RunningScripts.qml");
|
||||
DependencyManager::get<OffscreenUi>()->show(url, "RunningScripts");
|
||||
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
||||
if (tablet->getToolbarMode()) {
|
||||
static const QUrl url("hifi/dialogs/RunningScripts.qml");
|
||||
DependencyManager::get<OffscreenUi>()->show(url, "RunningScripts");
|
||||
} else {
|
||||
QQuickItem* tabletRoot = tablet->getTabletRoot();
|
||||
if (!tabletRoot && !isHMDMode()) {
|
||||
static const QUrl url("hifi/dialogs/RunningScripts.qml");
|
||||
DependencyManager::get<OffscreenUi>()->show(url, "RunningScripts");
|
||||
} else {
|
||||
static const QUrl url("../../hifi/dialogs/TabletRunningScripts.qml");
|
||||
tablet->pushOntoStack(url);
|
||||
}
|
||||
}
|
||||
//DependencyManager::get<OffscreenUi>()->show(url, "RunningScripts");
|
||||
//if (_runningScriptsWidget->isVisible()) {
|
||||
// if (_runningScriptsWidget->hasFocus()) {
|
||||
// _runningScriptsWidget->hide();
|
||||
|
@ -5818,7 +5835,21 @@ void Application::showAssetServerWidget(QString filePath) {
|
|||
emit uploadRequest(filePath);
|
||||
}
|
||||
};
|
||||
DependencyManager::get<OffscreenUi>()->show(url, "AssetServer", startUpload);
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
||||
|
||||
if (tablet->getToolbarMode()) {
|
||||
DependencyManager::get<OffscreenUi>()->show(url, "AssetServer", startUpload);
|
||||
} else {
|
||||
QQuickItem* tabletRoot = tablet->getTabletRoot();
|
||||
if (!tabletRoot && !isHMDMode()) {
|
||||
DependencyManager::get<OffscreenUi>()->show(url, "AssetServer", startUpload);
|
||||
} else {
|
||||
static const QUrl url("../../hifi/dialogs/TabletAssetServer.qml");
|
||||
tablet->pushOntoStack(url);
|
||||
}
|
||||
}
|
||||
|
||||
startUpload(nullptr, nullptr);
|
||||
}
|
||||
|
||||
|
@ -5841,6 +5872,16 @@ void Application::addAssetToWorldFromURL(QString url) {
|
|||
request->send();
|
||||
}
|
||||
|
||||
void Application::showDialog(const QString& desktopURL, const QString& tabletURL, const QString& name) const {
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
||||
if (tablet->getToolbarMode() || (!tablet->getTabletRoot() && !isHMDMode())) {
|
||||
DependencyManager::get<OffscreenUi>()->show(desktopURL, name);
|
||||
} else {
|
||||
tablet->loadQMLSource(tabletURL);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::addAssetToWorldFromURLRequestFinished() {
|
||||
auto request = qobject_cast<ResourceRequest*>(sender());
|
||||
auto url = request->getUrl().toString();
|
||||
|
@ -6908,6 +6949,7 @@ void Application::updateThreadPoolCount() const {
|
|||
}
|
||||
|
||||
void Application::updateSystemTabletMode() {
|
||||
qApp->setProperty(hifi::properties::HMD, isHMDMode());
|
||||
if (isHMDMode()) {
|
||||
DependencyManager::get<TabletScriptingInterface>()->setToolbarMode(getHmdTabletBecomesToolbarSetting());
|
||||
} else {
|
||||
|
|
|
@ -333,6 +333,8 @@ public slots:
|
|||
void toggleRunningScriptsWidget() const;
|
||||
Q_INVOKABLE void showAssetServerWidget(QString filePath = "");
|
||||
|
||||
void showDialog(const QString& desktopURL, const QString& tabletURL, const QString& name) const;
|
||||
|
||||
// FIXME: Move addAssetToWorld* methods to own class?
|
||||
void addAssetToWorldFromURL(QString url);
|
||||
void addAssetToWorldFromURLRequestFinished();
|
||||
|
|
|
@ -294,13 +294,15 @@ Menu::Menu() {
|
|||
// Settings > General...
|
||||
action = addActionToQMenuAndActionHash(settingsMenu, MenuOption::Preferences, Qt::CTRL | Qt::Key_Comma, nullptr, nullptr, QAction::PreferencesRole);
|
||||
connect(action, &QAction::triggered, [] {
|
||||
DependencyManager::get<OffscreenUi>()->toggle(QString("hifi/dialogs/GeneralPreferencesDialog.qml"), "GeneralPreferencesDialog");
|
||||
qApp->showDialog(QString("hifi/dialogs/GeneralPreferencesDialog.qml"),
|
||||
QString("../../hifi/tablet/TabletGeneralPreferences.qml"), "GeneralPreferencesDialog");
|
||||
});
|
||||
|
||||
// Settings > Avatar...
|
||||
action = addActionToQMenuAndActionHash(settingsMenu, "Avatar...");
|
||||
connect(action, &QAction::triggered, [] {
|
||||
DependencyManager::get<OffscreenUi>()->toggle(QString("hifi/dialogs/AvatarPreferencesDialog.qml"), "AvatarPreferencesDialog");
|
||||
qApp->showDialog(QString("hifi/dialogs/AvatarPreferencesDialog.qml"),
|
||||
QString("../../hifi/tablet/TabletAvatarPreferences.qml"), "AvatarPreferencesDialog");
|
||||
});
|
||||
|
||||
// Settings > LOD...
|
||||
|
@ -550,8 +552,8 @@ Menu::Menu() {
|
|||
MenuWrapper* networkMenu = developerMenu->addMenu("Network");
|
||||
action = addActionToQMenuAndActionHash(networkMenu, MenuOption::Networking);
|
||||
connect(action, &QAction::triggered, [] {
|
||||
DependencyManager::get<OffscreenUi>()->toggle(QUrl("hifi/dialogs/NetworkingPreferencesDialog.qml"),
|
||||
"NetworkingPreferencesDialog");
|
||||
qApp->showDialog(QString("hifi/dialogs/NetworkingPreferencesDialog.qml"),
|
||||
QString("../../hifi/tablet/TabletNetworkingPreferences.qml"), "NetworkingPreferencesDialog");
|
||||
});
|
||||
addActionToQMenuAndActionHash(networkMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches()));
|
||||
addCheckableActionToQMenuAndActionHash(networkMenu,
|
||||
|
@ -612,7 +614,8 @@ Menu::Menu() {
|
|||
|
||||
action = addActionToQMenuAndActionHash(audioDebugMenu, "Buffers...");
|
||||
connect(action, &QAction::triggered, [] {
|
||||
DependencyManager::get<OffscreenUi>()->toggle(QString("hifi/dialogs/AudioPreferencesDialog.qml"), "AudioPreferencesDialog");
|
||||
qApp->showDialog(QString("hifi/dialogs/AudioPreferencesDialog.qml"),
|
||||
QString("../../hifi/tablet/TabletAudioPreferences.qml"), "AudioPreferencesDialog");
|
||||
});
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioNoiseReduction, 0, true,
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include <AssetClient.h>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
#include "DependencyManager.h"
|
||||
|
||||
|
||||
class AssetMappingModel : public QStandardItemModel {
|
||||
Q_OBJECT
|
||||
|
@ -39,10 +41,12 @@ private:
|
|||
QHash<QString, QStandardItem*> _pathToItemMap;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(AssetMappingModel*);
|
||||
Q_DECLARE_METATYPE(AssetMappingModel*)
|
||||
|
||||
class AssetMappingsScriptingInterface : public QObject {
|
||||
class AssetMappingsScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
Q_PROPERTY(AssetMappingModel* mappingModel READ getAssetMappingModel CONSTANT)
|
||||
Q_PROPERTY(QAbstractProxyModel* proxyModel READ getProxyModel CONSTANT)
|
||||
public:
|
||||
|
|
|
@ -81,6 +81,10 @@ void HMDScriptingInterface::closeTablet() {
|
|||
_showTablet = false;
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::openTablet() {
|
||||
_showTablet = true;
|
||||
}
|
||||
|
||||
QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine) {
|
||||
glm::vec3 hudIntersection;
|
||||
auto instance = DependencyManager::get<HMDScriptingInterface>();
|
||||
|
@ -131,7 +135,7 @@ glm::quat HMDScriptingInterface::getOrientation() const {
|
|||
return glm::quat();
|
||||
}
|
||||
|
||||
bool HMDScriptingInterface::isMounted() const{
|
||||
bool HMDScriptingInterface::isMounted() const {
|
||||
auto displayPlugin = qApp->getActiveDisplayPlugin();
|
||||
return (displayPlugin->isHmd() && displayPlugin->isDisplayVisible());
|
||||
}
|
||||
|
|
|
@ -76,6 +76,8 @@ public:
|
|||
|
||||
Q_INVOKABLE void closeTablet();
|
||||
|
||||
Q_INVOKABLE void openTablet();
|
||||
|
||||
signals:
|
||||
bool shouldShowHandControllersChanged();
|
||||
|
||||
|
|
|
@ -100,6 +100,9 @@ void Overlay::setProperties(const QVariantMap& properties) {
|
|||
}
|
||||
|
||||
QVariant Overlay::getProperty(const QString& property) {
|
||||
if (property == "type") {
|
||||
return QVariant(getType());
|
||||
}
|
||||
if (property == "color") {
|
||||
return xColorToVariant(_color);
|
||||
}
|
||||
|
|
|
@ -711,10 +711,9 @@ PointerEvent Overlays::calculatePointerEvent(Overlay::Pointer overlay, PickRay r
|
|||
auto dimensions = thisOverlay->getSize();
|
||||
|
||||
glm::vec2 pos2D = projectOntoOverlayXYPlane(position, rotation, dimensions, ray, rayPickResult);
|
||||
PointerEvent pointerEvent(eventType, MOUSE_POINTER_ID,
|
||||
pos2D, rayPickResult.intersection,
|
||||
rayPickResult.surfaceNormal, ray.direction,
|
||||
toPointerButton(*event), toPointerButtons(*event));
|
||||
|
||||
PointerEvent pointerEvent(eventType, MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal,
|
||||
ray.direction, toPointerButton(*event), toPointerButtons(*event), event->modifiers());
|
||||
|
||||
return pointerEvent;
|
||||
}
|
||||
|
|
|
@ -37,8 +37,12 @@
|
|||
#include <AddressManager.h>
|
||||
#include "scripting/AccountScriptingInterface.h"
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include "scripting/AssetMappingsScriptingInterface.h"
|
||||
#include <Preferences.h>
|
||||
#include <ScriptEngines.h>
|
||||
#include "FileDialogHelper.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "AudioClient.h"
|
||||
|
||||
static const float DPI = 30.47f;
|
||||
static const float INCHES_TO_METERS = 1.0f / 39.3701f;
|
||||
|
@ -161,6 +165,10 @@ void Web3DOverlay::loadSourceURL() {
|
|||
_webSurface->getRootContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("Vec3", new Vec3());
|
||||
_webSurface->getRootContext()->setContextProperty("Quat", new Quat());
|
||||
_webSurface->getRootContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
|
||||
_webSurface->getRootContext()->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
|
||||
|
||||
if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") {
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
|
@ -168,17 +176,30 @@ void Web3DOverlay::loadSourceURL() {
|
|||
_webSurface->getRootContext()->setContextProperty("offscreenFlags", flags);
|
||||
_webSurface->getRootContext()->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("Account", AccountScriptingInterface::getInstance());
|
||||
_webSurface->getRootContext()->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
|
||||
_webSurface->getRootContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("fileDialogHelper", new FileDialogHelper());
|
||||
_webSurface->getRootContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
|
||||
_webSurface->getRootContext()->setContextProperty("pathToFonts", "../../");
|
||||
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface->getRootItem(), _webSurface.data());
|
||||
|
||||
// Override min fps for tablet UI, for silky smooth scrolling
|
||||
_webSurface->setMaxFps(90);
|
||||
setMaxFPS(90);
|
||||
}
|
||||
}
|
||||
_webSurface->getRootContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
|
||||
}
|
||||
|
||||
void Web3DOverlay::setMaxFPS(uint8_t maxFPS) {
|
||||
_desiredMaxFPS = maxFPS;
|
||||
if (_webSurface) {
|
||||
_webSurface->setMaxFps(_desiredMaxFPS);
|
||||
_currentMaxFPS = _desiredMaxFPS;
|
||||
}
|
||||
}
|
||||
|
||||
void Web3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible || !getParentVisible()) {
|
||||
return;
|
||||
|
@ -188,9 +209,11 @@ void Web3DOverlay::render(RenderArgs* args) {
|
|||
QSurface * currentSurface = currentContext->surface();
|
||||
if (!_webSurface) {
|
||||
_webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(pickURL());
|
||||
_webSurface->setMaxFps(10);
|
||||
// FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces
|
||||
// and the current rendering load)
|
||||
if (_currentMaxFPS != _desiredMaxFPS) {
|
||||
setMaxFPS(_desiredMaxFPS);
|
||||
}
|
||||
loadSourceURL();
|
||||
_webSurface->resume();
|
||||
_webSurface->resize(QSize(_resolution.x, _resolution.y));
|
||||
|
@ -240,6 +263,10 @@ void Web3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
_emitScriptEventConnection = connect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent);
|
||||
_webEventReceivedConnection = connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived);
|
||||
} else {
|
||||
if (_currentMaxFPS != _desiredMaxFPS) {
|
||||
setMaxFPS(_desiredMaxFPS);
|
||||
}
|
||||
}
|
||||
|
||||
vec2 halfSize = getSize() / 2.0f;
|
||||
|
@ -353,9 +380,8 @@ void Web3DOverlay::handlePointerEvent(const PointerEvent& event) {
|
|||
QList<QTouchEvent::TouchPoint> touchPoints;
|
||||
touchPoints.push_back(point);
|
||||
|
||||
QTouchEvent* touchEvent = new QTouchEvent(type);
|
||||
QTouchEvent* touchEvent = new QTouchEvent(type, &_touchDevice, event.getKeyboardModifiers());
|
||||
touchEvent->setWindow(_webSurface->getWindow());
|
||||
touchEvent->setDevice(&_touchDevice);
|
||||
touchEvent->setTarget(_webSurface->getRootItem());
|
||||
touchEvent->setTouchPoints(touchPoints);
|
||||
touchEvent->setTouchPointStates(touchPointState);
|
||||
|
@ -396,6 +422,11 @@ void Web3DOverlay::setProperties(const QVariantMap& properties) {
|
|||
_dpi = dpi.toFloat();
|
||||
}
|
||||
|
||||
auto maxFPS = properties["maxFPS"];
|
||||
if (maxFPS.isValid()) {
|
||||
_desiredMaxFPS = maxFPS.toInt();
|
||||
}
|
||||
|
||||
auto showKeyboardFocusHighlight = properties["showKeyboardFocusHighlight"];
|
||||
if (showKeyboardFocusHighlight.isValid()) {
|
||||
_showKeyboardFocusHighlight = showKeyboardFocusHighlight.toBool();
|
||||
|
@ -415,6 +446,9 @@ QVariant Web3DOverlay::getProperty(const QString& property) {
|
|||
if (property == "dpi") {
|
||||
return _dpi;
|
||||
}
|
||||
if (property == "maxFPS") {
|
||||
return _desiredMaxFPS;
|
||||
}
|
||||
if (property == "showKeyboardFocusHighlight") {
|
||||
return _showKeyboardFocusHighlight;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ public:
|
|||
|
||||
QString pickURL();
|
||||
void loadSourceURL();
|
||||
void setMaxFPS(uint8_t maxFPS);
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
|
||||
|
@ -75,6 +76,9 @@ private:
|
|||
bool _pressed{ false };
|
||||
QTouchDevice _touchDevice;
|
||||
|
||||
uint8_t _desiredMaxFPS { 10 };
|
||||
uint8_t _currentMaxFPS { 0 };
|
||||
|
||||
QMetaObject::Connection _mousePressConnection;
|
||||
QMetaObject::Connection _mouseReleaseConnection;
|
||||
QMetaObject::Connection _mouseMoveConnection;
|
||||
|
|
|
@ -713,7 +713,8 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) {
|
|||
PointerEvent pointerEvent(PointerEvent::Press, MOUSE_POINTER_ID,
|
||||
pos2D, rayPickResult.intersection,
|
||||
rayPickResult.surfaceNormal, ray.direction,
|
||||
toPointerButton(*event), toPointerButtons(*event));
|
||||
toPointerButton(*event), toPointerButtons(*event),
|
||||
Qt::NoModifier); // TODO -- check for modifier keys?
|
||||
|
||||
emit mousePressOnEntity(rayPickResult.entityID, pointerEvent);
|
||||
|
||||
|
@ -753,7 +754,8 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) {
|
|||
PointerEvent pointerEvent(PointerEvent::Release, MOUSE_POINTER_ID,
|
||||
pos2D, rayPickResult.intersection,
|
||||
rayPickResult.surfaceNormal, ray.direction,
|
||||
toPointerButton(*event), toPointerButtons(*event));
|
||||
toPointerButton(*event), toPointerButtons(*event),
|
||||
Qt::NoModifier); // TODO -- check for modifier keys?
|
||||
|
||||
emit mouseReleaseOnEntity(rayPickResult.entityID, pointerEvent);
|
||||
if (_entitiesScriptEngine) {
|
||||
|
@ -773,7 +775,8 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) {
|
|||
PointerEvent pointerEvent(PointerEvent::Release, MOUSE_POINTER_ID,
|
||||
pos2D, rayPickResult.intersection,
|
||||
rayPickResult.surfaceNormal, ray.direction,
|
||||
toPointerButton(*event), toPointerButtons(*event));
|
||||
toPointerButton(*event), toPointerButtons(*event),
|
||||
Qt::NoModifier); // TODO -- check for modifier keys?
|
||||
|
||||
emit clickReleaseOnEntity(_currentClickingOnEntityID, pointerEvent);
|
||||
if (_entitiesScriptEngine) {
|
||||
|
@ -803,7 +806,8 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
|
|||
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
|
||||
pos2D, rayPickResult.intersection,
|
||||
rayPickResult.surfaceNormal, ray.direction,
|
||||
toPointerButton(*event), toPointerButtons(*event));
|
||||
toPointerButton(*event), toPointerButtons(*event),
|
||||
Qt::NoModifier); // TODO -- check for modifier keys?
|
||||
|
||||
emit mouseMoveOnEntity(rayPickResult.entityID, pointerEvent);
|
||||
|
||||
|
@ -823,7 +827,8 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
|
|||
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
|
||||
pos2D, rayPickResult.intersection,
|
||||
rayPickResult.surfaceNormal, ray.direction,
|
||||
toPointerButton(*event), toPointerButtons(*event));
|
||||
toPointerButton(*event), toPointerButtons(*event),
|
||||
Qt::NoModifier); // TODO -- check for modifier keys?
|
||||
|
||||
emit hoverLeaveEntity(_currentHoverOverEntityID, pointerEvent);
|
||||
if (_entitiesScriptEngine) {
|
||||
|
@ -864,7 +869,8 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
|
|||
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
|
||||
pos2D, rayPickResult.intersection,
|
||||
rayPickResult.surfaceNormal, ray.direction,
|
||||
toPointerButton(*event), toPointerButtons(*event));
|
||||
toPointerButton(*event), toPointerButtons(*event),
|
||||
Qt::NoModifier); // TODO -- check for modifier keys?
|
||||
|
||||
emit hoverLeaveEntity(_currentHoverOverEntityID, pointerEvent);
|
||||
if (_entitiesScriptEngine) {
|
||||
|
@ -883,7 +889,8 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) {
|
|||
PointerEvent pointerEvent(PointerEvent::Move, MOUSE_POINTER_ID,
|
||||
pos2D, rayPickResult.intersection,
|
||||
rayPickResult.surfaceNormal, ray.direction,
|
||||
toPointerButton(*event), toPointerButtons(*event));
|
||||
toPointerButton(*event), toPointerButtons(*event),
|
||||
Qt::NoModifier); // TODO -- check for modifier keys?
|
||||
|
||||
emit holdingClickOnEntity(_currentClickingOnEntityID, pointerEvent);
|
||||
if (_entitiesScriptEngine) {
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <AccountManager.h>
|
||||
#include <NetworkAccessManager.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <shared/GlobalAppProperties.h>
|
||||
|
||||
#include "OffscreenGLCanvas.h"
|
||||
#include "GLHelpers.h"
|
||||
|
@ -433,6 +434,7 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
|
|||
auto rootContext = getRootContext();
|
||||
rootContext->setContextProperty("urlHandler", new UrlHandler());
|
||||
rootContext->setContextProperty("resourceDirectoryUrl", QUrl::fromLocalFile(PathUtils::resourcesPath()));
|
||||
rootContext->setContextProperty("pathToFonts", "../../");
|
||||
}
|
||||
|
||||
static uvec2 clampSize(const uvec2& size, uint32_t maxDimension) {
|
||||
|
@ -911,20 +913,23 @@ void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool n
|
|||
return;
|
||||
}
|
||||
|
||||
QQuickItem* item = dynamic_cast<QQuickItem*>(object);
|
||||
while (item) {
|
||||
// Numeric value may be set in parameter from HTML UI; for QML UI, detect numeric fields here.
|
||||
numeric = numeric || QString(item->metaObject()->className()).left(7) == "SpinBox";
|
||||
// if HMD is being worn, allow keyboard to open. allow it to close, HMD or not.
|
||||
if (!raised || qApp->property(hifi::properties::HMD).toBool()) {
|
||||
QQuickItem* item = dynamic_cast<QQuickItem*>(object);
|
||||
while (item) {
|
||||
// Numeric value may be set in parameter from HTML UI; for QML UI, detect numeric fields here.
|
||||
numeric = numeric || QString(item->metaObject()->className()).left(7) == "SpinBox";
|
||||
|
||||
if (item->property("keyboardRaised").isValid()) {
|
||||
// FIXME - HMD only: Possibly set value of "keyboardEnabled" per isHMDMode() for use in WebView.qml.
|
||||
if (item->property("punctuationMode").isValid()) {
|
||||
item->setProperty("punctuationMode", QVariant(numeric));
|
||||
if (item->property("keyboardRaised").isValid()) {
|
||||
// FIXME - HMD only: Possibly set value of "keyboardEnabled" per isHMDMode() for use in WebView.qml.
|
||||
if (item->property("punctuationMode").isValid()) {
|
||||
item->setProperty("punctuationMode", QVariant(numeric));
|
||||
}
|
||||
item->setProperty("keyboardRaised", QVariant(raised));
|
||||
return;
|
||||
}
|
||||
item->setProperty("keyboardRaised", QVariant(raised));
|
||||
return;
|
||||
item = dynamic_cast<QQuickItem*>(item->parentItem());
|
||||
}
|
||||
item = dynamic_cast<QQuickItem*>(item->parentItem());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -250,6 +250,18 @@ static QString getUsername() {
|
|||
}
|
||||
}
|
||||
|
||||
bool TabletProxy::isMessageDialogOpen() {
|
||||
if (_qmlTabletRoot) {
|
||||
QVariant result;
|
||||
QMetaObject::invokeMethod(_qmlTabletRoot, "isDialogOpen",Qt::DirectConnection,
|
||||
Q_RETURN_ARG(QVariant, result));
|
||||
|
||||
return result.toBool();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface) {
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
_qmlOffscreenSurface = qmlOffscreenSurface;
|
||||
|
@ -275,7 +287,8 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr
|
|||
QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_SOURCE_URL)));
|
||||
}
|
||||
|
||||
gotoHomeScreen();
|
||||
// force to the tablet to go to the homescreen
|
||||
loadHomeScreen(true);
|
||||
|
||||
QMetaObject::invokeMethod(_qmlTabletRoot, "setUsername", Q_ARG(const QVariant&, QVariant(getUsername())));
|
||||
|
||||
|
@ -293,6 +306,9 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr
|
|||
}
|
||||
}
|
||||
|
||||
void TabletProxy::gotoHomeScreen() {
|
||||
loadHomeScreen(false);
|
||||
}
|
||||
void TabletProxy::gotoMenuScreen(const QString& submenu) {
|
||||
|
||||
QObject* root = nullptr;
|
||||
|
@ -331,11 +347,53 @@ void TabletProxy::loadQMLSource(const QVariant& path) {
|
|||
emit screenChanged(QVariant("QML"), path);
|
||||
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
|
||||
}
|
||||
} else {
|
||||
qCDebug(scriptengine) << "tablet cannot load QML because _qmlTabletRoot is null";
|
||||
}
|
||||
}
|
||||
|
||||
void TabletProxy::gotoHomeScreen() {
|
||||
if (_state != State::Home) {
|
||||
void TabletProxy::pushOntoStack(const QVariant& path) {
|
||||
if (_qmlTabletRoot) {
|
||||
auto stack = _qmlTabletRoot->findChild<QQuickItem*>("stack");
|
||||
if (stack) {
|
||||
QMetaObject::invokeMethod(stack, "pushSource", Q_ARG(const QVariant&, path));
|
||||
} else {
|
||||
qCDebug(scriptengine) << "tablet cannot push QML because _qmlTabletRoot doesn't have child stack";
|
||||
}
|
||||
} else if (_desktopWindow) {
|
||||
auto stack = _desktopWindow->asQuickItem()->findChild<QQuickItem*>("stack");
|
||||
if (stack) {
|
||||
QMetaObject::invokeMethod(stack, "pushSource", Q_ARG(const QVariant&, path));
|
||||
} else {
|
||||
qCDebug(scriptengine) << "tablet cannot push QML because _desktopWindow doesn't have child stack";
|
||||
}
|
||||
} else {
|
||||
qCDebug(scriptengine) << "tablet cannot push QML because _qmlTabletRoot or _desktopWindow is null";
|
||||
}
|
||||
}
|
||||
|
||||
void TabletProxy::popFromStack() {
|
||||
if (_qmlTabletRoot) {
|
||||
auto stack = _qmlTabletRoot->findChild<QQuickItem*>("stack");
|
||||
if (stack) {
|
||||
QMetaObject::invokeMethod(stack, "popSource");
|
||||
} else {
|
||||
qCDebug(scriptengine) << "tablet cannot push QML because _qmlTabletRoot doesn't have child stack";
|
||||
}
|
||||
} else if (_desktopWindow) {
|
||||
auto stack = _desktopWindow->asQuickItem()->findChild<QQuickItem*>("stack");
|
||||
if (stack) {
|
||||
QMetaObject::invokeMethod(stack, "popSource");
|
||||
} else {
|
||||
qCDebug(scriptengine) << "tablet cannot pop QML because _desktopWindow doesn't have child stack";
|
||||
}
|
||||
} else {
|
||||
qCDebug(scriptengine) << "tablet cannot pop QML because _qmlTabletRoot or _desktopWindow is null";
|
||||
}
|
||||
}
|
||||
|
||||
void TabletProxy::loadHomeScreen(bool forceOntoHomeScreen) {
|
||||
if ((_state != State::Home && _state != State::Uninitialized) || forceOntoHomeScreen) {
|
||||
if (!_toolbarMode && _qmlTabletRoot) {
|
||||
auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader");
|
||||
QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen()), Qt::DirectConnection);
|
||||
|
@ -560,7 +618,7 @@ QQuickItem* TabletProxy::getQmlTablet() const {
|
|||
}
|
||||
|
||||
QQuickItem* TabletProxy::getQmlMenu() const {
|
||||
if (!_qmlTabletRoot) {
|
||||
if (!_qmlTabletRoot) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -106,6 +106,14 @@ public:
|
|||
Q_INVOKABLE void gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl);
|
||||
|
||||
Q_INVOKABLE void loadQMLSource(const QVariant& path);
|
||||
Q_INVOKABLE void pushOntoStack(const QVariant& path);
|
||||
Q_INVOKABLE void popFromStack();
|
||||
|
||||
/** jsdoc
|
||||
* Check if the tablet has a message dialog open
|
||||
* @function TabletProxy#isMessageDialogOpen
|
||||
*/
|
||||
Q_INVOKABLE bool isMessageDialogOpen();
|
||||
|
||||
/**jsdoc
|
||||
* Creates a new button, adds it to this and returns it.
|
||||
|
@ -150,8 +158,14 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE void sendToQml(QVariant msg);
|
||||
|
||||
/**jsdoc
|
||||
* Check if the tablet is on the homescreen
|
||||
* @function TabletProxy#onHomeScreen()
|
||||
*/
|
||||
Q_INVOKABLE bool onHomeScreen();
|
||||
|
||||
QQuickItem* getTabletRoot() const { return _qmlTabletRoot; }
|
||||
|
||||
QObject* getTabletSurface();
|
||||
|
||||
QQuickItem* getQmlTablet() const;
|
||||
|
@ -188,6 +202,7 @@ protected slots:
|
|||
void desktopWindowClosed();
|
||||
protected:
|
||||
void removeButtonsFromHomeScreen();
|
||||
void loadHomeScreen(bool forceOntoHomeScreen);
|
||||
void addButtonsToToolbar();
|
||||
void removeButtonsFromToolbar();
|
||||
|
||||
|
|
|
@ -25,9 +25,9 @@ PointerEvent::PointerEvent() {
|
|||
}
|
||||
|
||||
PointerEvent::PointerEvent(EventType type, uint32_t id,
|
||||
const glm::vec2& pos2D, const glm::vec3& pos3D,
|
||||
const glm::vec3& normal, const glm::vec3& direction,
|
||||
Button button, uint32_t buttons) :
|
||||
const glm::vec2& pos2D, const glm::vec3& pos3D,
|
||||
const glm::vec3& normal, const glm::vec3& direction,
|
||||
Button button, uint32_t buttons, Qt::KeyboardModifiers keyboardModifiers) :
|
||||
_type(type),
|
||||
_id(id),
|
||||
_pos2D(pos2D),
|
||||
|
@ -35,7 +35,8 @@ PointerEvent::PointerEvent(EventType type, uint32_t id,
|
|||
_normal(normal),
|
||||
_direction(direction),
|
||||
_button(button),
|
||||
_buttons(buttons)
|
||||
_buttons(buttons),
|
||||
_keyboardModifiers(keyboardModifiers)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
@ -119,6 +120,8 @@ QScriptValue PointerEvent::toScriptValue(QScriptEngine* engine, const PointerEve
|
|||
obj.setProperty("isSecondaryHeld", areFlagsSet(event._buttons, SecondaryButton));
|
||||
obj.setProperty("isTertiaryHeld", areFlagsSet(event._buttons, TertiaryButton));
|
||||
|
||||
obj.setProperty("keyboardModifiers", QScriptValue(event.getKeyboardModifiers()));
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -174,5 +177,7 @@ void PointerEvent::fromScriptValue(const QScriptValue& object, PointerEvent& eve
|
|||
if (tertiary) {
|
||||
event._buttons |= TertiaryButton;
|
||||
}
|
||||
|
||||
event._keyboardModifiers = (Qt::KeyboardModifiers)(object.property("keyboardModifiers").toUInt32());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#ifndef hifi_PointerEvent_h
|
||||
#define hifi_PointerEvent_h
|
||||
|
||||
#include <Qt>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <QScriptValue>
|
||||
|
@ -35,7 +37,7 @@ public:
|
|||
PointerEvent(EventType type, uint32_t id,
|
||||
const glm::vec2& pos2D, const glm::vec3& pos3D,
|
||||
const glm::vec3& normal, const glm::vec3& direction,
|
||||
Button button, uint32_t buttons);
|
||||
Button button, uint32_t buttons, Qt::KeyboardModifiers keyboardModifiers);
|
||||
|
||||
static QScriptValue toScriptValue(QScriptEngine* engine, const PointerEvent& event);
|
||||
static void fromScriptValue(const QScriptValue& object, PointerEvent& event);
|
||||
|
@ -50,6 +52,7 @@ public:
|
|||
const glm::vec3& getDirection() const { return _direction; }
|
||||
Button getButton() const { return _button; }
|
||||
uint32_t getButtons() const { return _buttons; }
|
||||
Qt::KeyboardModifiers getKeyboardModifiers() const { return _keyboardModifiers; }
|
||||
|
||||
private:
|
||||
EventType _type;
|
||||
|
@ -61,6 +64,7 @@ private:
|
|||
|
||||
Button _button { NoButtons }; // button assosiated with this event, (if type is Press, this will be the button that is pressed)
|
||||
uint32_t _buttons { NoButtons }; // the current state of all the buttons.
|
||||
Qt::KeyboardModifiers _keyboardModifiers; // set of keys held when event was generated
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(PointerEvent)
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace hifi { namespace properties {
|
|||
const char* OCULUS_STORE = "com.highfidelity.oculusStore";
|
||||
const char* TEST = "com.highfidelity.test";
|
||||
const char* TRACING = "com.highfidelity.tracing";
|
||||
const char* HMD = "com.highfidelity.hmd";
|
||||
|
||||
namespace gl {
|
||||
const char* BACKEND = "com.highfidelity.gl.backend";
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace hifi { namespace properties {
|
|||
extern const char* OCULUS_STORE;
|
||||
extern const char* TEST;
|
||||
extern const char* TRACING;
|
||||
extern const char* HMD;
|
||||
|
||||
namespace gl {
|
||||
extern const char* BACKEND;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
set(TARGET_NAME ui)
|
||||
setup_hifi_library(OpenGL Network Qml Quick Script WebChannel WebSockets XmlPatterns)
|
||||
link_hifi_libraries(shared networking gl)
|
||||
link_hifi_libraries(shared networking gl script-engine)
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
|
||||
#include <AbstractUriHandler.h>
|
||||
#include <AccountManager.h>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <TabletScriptingInterface.h>
|
||||
#include "FileDialogHelper.h"
|
||||
#include "VrMenu.h"
|
||||
|
||||
|
@ -210,9 +211,19 @@ QQuickItem* OffscreenUi::createMessageBox(Icon icon, const QString& title, const
|
|||
map.insert("buttons", buttons.operator int());
|
||||
map.insert("defaultButton", defaultButton);
|
||||
QVariant result;
|
||||
bool invokeResult = QMetaObject::invokeMethod(_desktop, "messageBox",
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(QVariant, QVariant::fromValue(map)));
|
||||
bool invokeResult;
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
TabletProxy* tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
||||
if (tablet->getToolbarMode()) {
|
||||
invokeResult = QMetaObject::invokeMethod(_desktop, "messageBox",
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(QVariant, QVariant::fromValue(map)));
|
||||
} else {
|
||||
QQuickItem* tabletRoot = tablet->getTabletRoot();
|
||||
invokeResult = QMetaObject::invokeMethod(tabletRoot, "messageBox",
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(QVariant, QVariant::fromValue(map)));
|
||||
}
|
||||
|
||||
if (!invokeResult) {
|
||||
qWarning() << "Failed to create message box";
|
||||
|
@ -405,10 +416,21 @@ QQuickItem* OffscreenUi::createInputDialog(const Icon icon, const QString& title
|
|||
map.insert("label", label);
|
||||
map.insert("current", current);
|
||||
QVariant result;
|
||||
bool invokeResult = QMetaObject::invokeMethod(_desktop, "inputDialog",
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(QVariant, QVariant::fromValue(map)));
|
||||
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
TabletProxy* tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
||||
|
||||
bool invokeResult;
|
||||
if (tablet->getToolbarMode()) {
|
||||
invokeResult = QMetaObject::invokeMethod(_desktop, "inputDialog",
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(QVariant, QVariant::fromValue(map)));
|
||||
} else {
|
||||
QQuickItem* tabletRoot = tablet->getTabletRoot();
|
||||
invokeResult = QMetaObject::invokeMethod(tabletRoot, "inputDialog",
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(QVariant, QVariant::fromValue(map)));
|
||||
}
|
||||
if (!invokeResult) {
|
||||
qWarning() << "Failed to create message box";
|
||||
return nullptr;
|
||||
|
@ -422,10 +444,21 @@ QQuickItem* OffscreenUi::createCustomInputDialog(const Icon icon, const QString&
|
|||
map.insert("title", title);
|
||||
map.insert("icon", icon);
|
||||
QVariant result;
|
||||
bool invokeResult = QMetaObject::invokeMethod(_desktop, "customInputDialog",
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(QVariant, QVariant::fromValue(map)));
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
TabletProxy* tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
||||
|
||||
bool invokeResult;
|
||||
if (tablet->getToolbarMode()) {
|
||||
invokeResult = QMetaObject::invokeMethod(_desktop, "inputDialog",
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(QVariant, QVariant::fromValue(map)));
|
||||
} else {
|
||||
QQuickItem* tabletRoot = tablet->getTabletRoot();
|
||||
invokeResult = QMetaObject::invokeMethod(tabletRoot, "inputDialog",
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(QVariant, QVariant::fromValue(map)));
|
||||
}
|
||||
|
||||
if (!invokeResult) {
|
||||
qWarning() << "Failed to create custom message box";
|
||||
return nullptr;
|
||||
|
@ -569,9 +602,19 @@ private slots:
|
|||
|
||||
QString OffscreenUi::fileDialog(const QVariantMap& properties) {
|
||||
QVariant buildDialogResult;
|
||||
bool invokeResult = QMetaObject::invokeMethod(_desktop, "fileDialog",
|
||||
Q_RETURN_ARG(QVariant, buildDialogResult),
|
||||
Q_ARG(QVariant, QVariant::fromValue(properties)));
|
||||
bool invokeResult;
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
TabletProxy* tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
||||
if (tablet->getToolbarMode()) {
|
||||
invokeResult = QMetaObject::invokeMethod(_desktop, "fileDialog",
|
||||
Q_RETURN_ARG(QVariant, buildDialogResult),
|
||||
Q_ARG(QVariant, QVariant::fromValue(properties)));
|
||||
} else {
|
||||
QQuickItem* tabletRoot = tablet->getTabletRoot();
|
||||
invokeResult = QMetaObject::invokeMethod(tabletRoot, "fileDialog",
|
||||
Q_RETURN_ARG(QVariant, buildDialogResult),
|
||||
Q_ARG(QVariant, QVariant::fromValue(properties)));
|
||||
}
|
||||
|
||||
if (!invokeResult) {
|
||||
qWarning() << "Failed to create file open dialog";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// stats.qml
|
||||
// Stats.qml
|
||||
// scripts/developer/utilities/audio
|
||||
//
|
||||
// Created by Zach Pomerantz on 9/22/2016
|
||||
|
@ -12,22 +12,21 @@ import QtQuick 2.5
|
|||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "../../../../resources/qml/controls-uit" as HifiControls
|
||||
|
||||
Column {
|
||||
id: stats
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
property bool showGraphs: toggleGraphs.checked
|
||||
|
||||
RowLayout {
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 30
|
||||
|
||||
Button {
|
||||
HifiControls.Button {
|
||||
id: toggleGraphs
|
||||
property bool checked: false
|
||||
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: checked ? "Hide graphs" : "Show graphs"
|
||||
onClicked: function() { checked = !checked; }
|
||||
}
|
||||
|
@ -35,11 +34,9 @@ Column {
|
|||
|
||||
Grid {
|
||||
width: parent.width
|
||||
height: parent.height - 30
|
||||
|
||||
Column {
|
||||
width: parent.width / 2
|
||||
height: parent.height
|
||||
|
||||
Section {
|
||||
label: "Latency"
|
||||
|
@ -76,7 +73,6 @@ Column {
|
|||
|
||||
Column {
|
||||
width: parent.width / 2
|
||||
height: parent.height
|
||||
|
||||
Section {
|
||||
label: "Mixer (upstream)"
|
||||
|
@ -92,4 +88,3 @@ Column {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
89
scripts/developer/utilities/audio/TabletStats.qml
Normal file
|
@ -0,0 +1,89 @@
|
|||
//
|
||||
// TabletStats.qml
|
||||
// scripts/developer/utilities/audio
|
||||
//
|
||||
// Created by David Rowe on 3 Mar 2017.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "../../../../resources/qml/styles-uit"
|
||||
|
||||
Item {
|
||||
id: dialog
|
||||
width: 480
|
||||
height: 720
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
Rectangle {
|
||||
id: header
|
||||
height: 90
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
z: 100
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "#2b2b2b"
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "#1e1e1e"
|
||||
}
|
||||
}
|
||||
|
||||
RalewayBold {
|
||||
text: "Audio Interface Statistics"
|
||||
size: 26
|
||||
color: "#34a2c7"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: hifi.dimensions.contentMargin.x // ####### hifi is not defined
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: main
|
||||
anchors {
|
||||
top: header.bottom
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0
|
||||
color: "#2b2b2b"
|
||||
}
|
||||
|
||||
GradientStop {
|
||||
position: 1
|
||||
color: "#0f212e"
|
||||
}
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: scrollView
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
contentWidth: parent.width
|
||||
contentHeight: stats.height
|
||||
|
||||
Stats {
|
||||
id: stats
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,17 +9,23 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var INITIAL_WIDTH = 400;
|
||||
var INITIAL_OFFSET = 50;
|
||||
if (HMD.active && !Settings.getValue("HUDUIEnabled")) {
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
var qml = Script.resolvePath("TabletStats.qml");
|
||||
tablet.loadQMLSource(qml);
|
||||
Script.stop();
|
||||
|
||||
// Set up the qml ui
|
||||
var qml = Script.resolvePath('stats.qml');
|
||||
var window = new OverlayWindow({
|
||||
title: 'Audio Interface Statistics',
|
||||
source: qml,
|
||||
width: 500, height: 520 // stats.qml may be too large for some screens
|
||||
});
|
||||
window.setPosition(INITIAL_OFFSET, INITIAL_OFFSET);
|
||||
} else {
|
||||
var INITIAL_WIDTH = 400;
|
||||
var INITIAL_OFFSET = 50;
|
||||
|
||||
window.closed.connect(function() { Script.stop(); });
|
||||
var qml = Script.resolvePath("Stats.qml");
|
||||
var window = new OverlayWindow({
|
||||
title: "Audio Interface Statistics",
|
||||
source: qml,
|
||||
width: 500, height: 520 // stats.qml may be too large for some screens
|
||||
});
|
||||
window.setPosition(INITIAL_OFFSET, INITIAL_OFFSET);
|
||||
|
||||
window.closed.connect(function () { Script.stop(); });
|
||||
}
|
||||
|
|
|
@ -72,6 +72,9 @@ tablet.screenChanged.connect(onScreenChanged);
|
|||
AudioDevice.muteToggled.connect(onMuteToggled);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
if (onAudioScreen) {
|
||||
tablet.gotoHomeScreen();
|
||||
}
|
||||
button.clicked.disconnect(onClicked);
|
||||
tablet.screenChanged.disconnect(onScreenChanged);
|
||||
AudioDevice.muteToggled.disconnect(onMuteToggled);
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
/* global getEntityCustomData, flatten, Xform, Script, Quat, Vec3, MyAvatar, Entities, Overlays, Settings,
|
||||
Reticle, Controller, Camera, Messages, Mat4, getControllerWorldLocation, getGrabPointSphereOffset, setGrabCommunications,
|
||||
Menu, HMD, isInEditMode */
|
||||
Reticle, Controller, Camera, Messages, Mat4, getControllerWorldLocation, getGrabPointSphereOffset,
|
||||
setGrabCommunications, Menu, HMD, isInEditMode */
|
||||
/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */
|
||||
|
||||
(function() { // BEGIN LOCAL_SCOPE
|
||||
|
@ -28,7 +28,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
//
|
||||
|
||||
var WANT_DEBUG = false;
|
||||
var WANT_DEBUG_STATE = false;
|
||||
var WANT_DEBUG_STATE = true;
|
||||
var WANT_DEBUG_SEARCH_NAME = null;
|
||||
|
||||
var FORCE_IGNORE_IK = false;
|
||||
|
@ -1027,6 +1027,7 @@ function MyController(hand) {
|
|||
this.grabPointIntersectsEntity = false;
|
||||
this.stylus = null;
|
||||
this.homeButtonTouched = false;
|
||||
this.editTriggered = false;
|
||||
|
||||
this.controllerJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ?
|
||||
"_CONTROLLER_RIGHTHAND" :
|
||||
|
@ -1389,7 +1390,7 @@ function MyController(hand) {
|
|||
}
|
||||
|
||||
var searchSphereLocation = Vec3.sum(distantPickRay.origin,
|
||||
Vec3.multiply(distantPickRay.direction, this.searchSphereDistance));
|
||||
Vec3.multiply(distantPickRay.direction, this.searchSphereDistance));
|
||||
this.searchSphereOn(searchSphereLocation, SEARCH_SPHERE_SIZE * this.searchSphereDistance,
|
||||
(this.triggerSmoothedGrab() || this.secondarySqueezed()) ?
|
||||
COLORS_GRAB_SEARCHING_FULL_SQUEEZE :
|
||||
|
@ -1709,6 +1710,10 @@ function MyController(hand) {
|
|||
|
||||
this.checkForUnexpectedChildren();
|
||||
|
||||
if (this.editTriggered) {
|
||||
this.editTriggered = false;
|
||||
}
|
||||
|
||||
if (this.triggerSmoothedReleased() && this.secondaryReleased()) {
|
||||
this.waitForTriggerRelease = false;
|
||||
}
|
||||
|
@ -2177,23 +2182,21 @@ function MyController(hand) {
|
|||
return aDistance - bDistance;
|
||||
});
|
||||
entity = grabbableEntities[0];
|
||||
name = entityPropertiesCache.getProps(entity).name;
|
||||
this.grabbedThingID = entity;
|
||||
this.grabbedIsOverlay = false;
|
||||
if (this.entityWantsTrigger(entity)) {
|
||||
if (this.triggerSmoothedGrab()) {
|
||||
this.setState(STATE_NEAR_TRIGGER, "near trigger '" + name + "'");
|
||||
return;
|
||||
if (!isInEditMode() || entity == HMD.tabletID) { // tablet is grabbable, even when editing
|
||||
name = entityPropertiesCache.getProps(entity).name;
|
||||
this.grabbedThingID = entity;
|
||||
this.grabbedIsOverlay = false;
|
||||
if (this.entityWantsTrigger(entity)) {
|
||||
if (this.triggerSmoothedGrab()) {
|
||||
this.setState(STATE_NEAR_TRIGGER, "near trigger '" + name + "'");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// potentialNearTriggerEntity = entity;
|
||||
}
|
||||
} else {
|
||||
// If near something grabbable, grab it!
|
||||
if ((this.triggerSmoothedGrab() || this.secondarySqueezed()) && nearGrabEnabled) {
|
||||
this.setState(STATE_NEAR_GRABBING, "near grab entity '" + name + "'");
|
||||
return;
|
||||
} else {
|
||||
// potentialNearGrabEntity = entity;
|
||||
// If near something grabbable, grab it!
|
||||
if ((this.triggerSmoothedGrab() || this.secondarySqueezed()) && nearGrabEnabled) {
|
||||
this.setState(STATE_NEAR_GRABBING, "near grab entity '" + name + "'");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2208,6 +2211,21 @@ function MyController(hand) {
|
|||
}
|
||||
}
|
||||
|
||||
if (isInEditMode()) {
|
||||
this.searchIndicatorOn(rayPickInfo.searchRay);
|
||||
if (this.triggerSmoothedGrab()) {
|
||||
if (!this.editTriggered && rayPickInfo.entityID) {
|
||||
Messages.sendLocalMessage("entityToolUpdates", JSON.stringify({
|
||||
method: "selectEntity",
|
||||
entityID: rayPickInfo.entityID
|
||||
}));
|
||||
}
|
||||
this.editTriggered = true;
|
||||
}
|
||||
Reticle.setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rayPickInfo.entityID) {
|
||||
entity = rayPickInfo.entityID;
|
||||
name = entityPropertiesCache.getProps(entity).name;
|
||||
|
@ -2277,12 +2295,12 @@ function MyController(hand) {
|
|||
return false;
|
||||
};
|
||||
|
||||
this.handleLaserOnWebEntity = function(rayPickInfo) {
|
||||
this.handleLaserOnWebEntity = function (rayPickInfo) {
|
||||
var pointerEvent;
|
||||
|
||||
if (rayPickInfo.entityID && Entities.wantsHandControllerPointerEvents(rayPickInfo.entityID)) {
|
||||
var entity = rayPickInfo.entityID;
|
||||
var props = entityPropertiesCache.getProps(entity);
|
||||
var name = props.name;
|
||||
var name = entityPropertiesCache.getProps(entity).name;
|
||||
|
||||
if (Entities.keyboardFocusEntity != entity) {
|
||||
Overlays.keyboardFocusOverlay = 0;
|
||||
|
@ -2293,7 +2311,7 @@ function MyController(hand) {
|
|||
id: this.hand + 1, // 0 is reserved for hardware mouse
|
||||
pos2D: projectOntoEntityXYPlane(entity, rayPickInfo.intersection),
|
||||
pos3D: rayPickInfo.intersection,
|
||||
normal: rayPickInfo.normal,
|
||||
normal: rayPickInfo.normal,
|
||||
direction: rayPickInfo.searchRay.direction,
|
||||
button: "None"
|
||||
};
|
||||
|
@ -2325,12 +2343,13 @@ function MyController(hand) {
|
|||
Entities.sendHoverOverEntity(entity, pointerEvent);
|
||||
}
|
||||
|
||||
if (this.triggerSmoothedGrab() && (!isEditing() || this.isTablet(entity))) {
|
||||
if (this.triggerSmoothedGrab()) {
|
||||
this.grabbedThingID = entity;
|
||||
this.grabbedIsOverlay = false;
|
||||
this.setState(STATE_ENTITY_LASER_TOUCHING, "begin touching entity '" + name + "'");
|
||||
return true;
|
||||
}
|
||||
|
||||
} else if (this.hoverEntity) {
|
||||
pointerEvent = {
|
||||
type: "Move",
|
||||
|
@ -2343,13 +2362,13 @@ function MyController(hand) {
|
|||
return false;
|
||||
};
|
||||
|
||||
this.handleLaserOnWebOverlay = function(rayPickInfo) {
|
||||
this.handleLaserOnWebOverlay = function (rayPickInfo) {
|
||||
var pointerEvent;
|
||||
var overlay;
|
||||
|
||||
if (rayPickInfo.overlayID) {
|
||||
overlay = rayPickInfo.overlayID;
|
||||
|
||||
var overlay = rayPickInfo.overlayID;
|
||||
if (Overlays.getProperty(overlay, "type") != "web3d") {
|
||||
return false;
|
||||
}
|
||||
if (Overlays.keyboardFocusOverlay != overlay) {
|
||||
Entities.keyboardFocusEntity = null;
|
||||
Overlays.keyboardFocusOverlay = overlay;
|
||||
|
@ -3366,7 +3385,7 @@ function MyController(hand) {
|
|||
|
||||
entityPropertiesCache.addEntity(this.grabbedThingID);
|
||||
|
||||
if (this.state == STATE_ENTITY_LASER_TOUCHING && !this.triggerSmoothedGrab()) {
|
||||
if (this.state == STATE_ENTITY_LASER_TOUCHING && !this.triggerSmoothedGrab()) { // AJT:
|
||||
this.setState(STATE_OFF, "released trigger");
|
||||
return;
|
||||
}
|
||||
|
@ -3663,6 +3682,8 @@ function MyController(hand) {
|
|||
this.cleanup = function() {
|
||||
this.release();
|
||||
this.grabPointSphereOff();
|
||||
this.hideStylus();
|
||||
this.overlayLineOff();
|
||||
};
|
||||
|
||||
this.thisHandIsParent = function(props) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
// newEditEntities.js
|
||||
// examples
|
||||
// edit.js
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 10/2/14.
|
||||
// Persist toolbar by HRS 6/11/15.
|
||||
|
@ -13,6 +12,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* global Script, SelectionDisplay, LightOverlayManager, CameraManager, Grid, GridTool, EntityListTool, Vec3, SelectionManager, Overlays, OverlayWebWindow, UserActivityLogger, Settings, Entities, Tablet, Toolbars, Messages, Menu, Camera, progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, ParticleExplorerTool */
|
||||
|
||||
(function() { // BEGIN LOCAL_SCOPE
|
||||
|
||||
var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
|
@ -59,18 +60,13 @@ selectionManager.addEventListener(function () {
|
|||
const KEY_P = 80; //Key code for letter p used for Parenting hotkey.
|
||||
var DEGREES_TO_RADIANS = Math.PI / 180.0;
|
||||
var RADIANS_TO_DEGREES = 180.0 / Math.PI;
|
||||
var epsilon = 0.001;
|
||||
|
||||
var MIN_ANGULAR_SIZE = 2;
|
||||
var MAX_ANGULAR_SIZE = 45;
|
||||
var allowLargeModels = true;
|
||||
var allowSmallModels = true;
|
||||
|
||||
var SPAWN_DISTANCE = 1;
|
||||
var DEFAULT_DIMENSION = 0.20;
|
||||
var DEFAULT_TEXT_DIMENSION_X = 1.0;
|
||||
var DEFAULT_TEXT_DIMENSION_Y = 1.0;
|
||||
var DEFAULT_TEXT_DIMENSION_Z = 0.01;
|
||||
|
||||
var DEFAULT_DIMENSIONS = {
|
||||
x: DEFAULT_DIMENSION,
|
||||
|
@ -85,7 +81,6 @@ var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus";
|
|||
var MENU_SHOW_LIGHTS_IN_EDIT_MODE = "Show Lights in Edit Mode";
|
||||
var MENU_SHOW_ZONES_IN_EDIT_MODE = "Show Zones in Edit Mode";
|
||||
|
||||
var SETTING_INSPECT_TOOL_ENABLED = "inspectToolEnabled";
|
||||
var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect";
|
||||
var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus";
|
||||
var SETTING_SHOW_LIGHTS_IN_EDIT_MODE = "showLightsInEditMode";
|
||||
|
@ -157,13 +152,13 @@ function hideMarketplace() {
|
|||
marketplaceWindow.setURL("about:blank");
|
||||
}
|
||||
|
||||
function toggleMarketplace() {
|
||||
if (marketplaceWindow.visible) {
|
||||
hideMarketplace();
|
||||
} else {
|
||||
showMarketplace();
|
||||
}
|
||||
}
|
||||
// function toggleMarketplace() {
|
||||
// if (marketplaceWindow.visible) {
|
||||
// hideMarketplace();
|
||||
// } else {
|
||||
// showMarketplace();
|
||||
// }
|
||||
// }
|
||||
|
||||
var TOOLS_PATH = Script.resolvePath("assets/images/tools/");
|
||||
|
||||
|
@ -176,8 +171,6 @@ var toolBar = (function () {
|
|||
tablet = null;
|
||||
|
||||
function createNewEntity(properties) {
|
||||
Settings.setValue(EDIT_SETTING, false);
|
||||
|
||||
var dimensions = properties.dimensions ? properties.dimensions : DEFAULT_DIMENSIONS;
|
||||
var position = getPositionToCreateEntity();
|
||||
var entityID = null;
|
||||
|
@ -185,8 +178,12 @@ var toolBar = (function () {
|
|||
position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions),
|
||||
properties.position = position;
|
||||
entityID = Entities.addEntity(properties);
|
||||
if (properties.type == "ParticleEffect") {
|
||||
selectParticleEntity(entityID);
|
||||
}
|
||||
} else {
|
||||
Window.notifyEditError("Can't create " + properties.type + ": " + properties.type + " would be out of bounds.");
|
||||
Window.notifyEditError("Can't create " + properties.type + ": " +
|
||||
properties.type + " would be out of bounds.");
|
||||
}
|
||||
|
||||
selectionManager.clearSelections();
|
||||
|
@ -206,24 +203,63 @@ var toolBar = (function () {
|
|||
}
|
||||
}
|
||||
|
||||
var buttonHandlers = {}; // only used to tablet mode
|
||||
|
||||
function addButton(name, image, handler) {
|
||||
var imageUrl = TOOLS_PATH + image;
|
||||
var button = toolBar.addButton({
|
||||
objectName: name,
|
||||
imageURL: imageUrl,
|
||||
imageOffOut: 1,
|
||||
imageOffIn: 2,
|
||||
imageOnOut: 0,
|
||||
imageOnIn: 2,
|
||||
alpha: 0.9,
|
||||
visible: true
|
||||
});
|
||||
if (handler) {
|
||||
button.clicked.connect(function () {
|
||||
Script.setTimeout(handler, 100);
|
||||
});
|
||||
buttonHandlers[name] = handler;
|
||||
}
|
||||
|
||||
var SHAPE_TYPE_NONE = 0;
|
||||
var SHAPE_TYPE_SIMPLE_HULL = 1;
|
||||
var SHAPE_TYPE_SIMPLE_COMPOUND = 2;
|
||||
var SHAPE_TYPE_STATIC_MESH = 3;
|
||||
var DYNAMIC_DEFAULT = false;
|
||||
|
||||
function handleNewModelDialogResult(result) {
|
||||
if (result) {
|
||||
var url = result.textInput;
|
||||
var shapeType;
|
||||
switch (result.comboBox) {
|
||||
case SHAPE_TYPE_SIMPLE_HULL:
|
||||
shapeType = "simple-hull";
|
||||
break;
|
||||
case SHAPE_TYPE_SIMPLE_COMPOUND:
|
||||
shapeType = "simple-compound";
|
||||
break;
|
||||
case SHAPE_TYPE_STATIC_MESH:
|
||||
shapeType = "static-mesh";
|
||||
break;
|
||||
default:
|
||||
shapeType = "none";
|
||||
}
|
||||
|
||||
var dynamic = result.checkBox !== null ? result.checkBox : DYNAMIC_DEFAULT;
|
||||
if (shapeType === "static-mesh" && dynamic) {
|
||||
// The prompt should prevent this case
|
||||
print("Error: model cannot be both static mesh and dynamic. This should never happen.");
|
||||
} else if (url) {
|
||||
createNewEntity({
|
||||
type: "Model",
|
||||
modelURL: url,
|
||||
shapeType: shapeType,
|
||||
dynamic: dynamic,
|
||||
gravity: dynamic ? { x: 0, y: -10, z: 0 } : { x: 0, y: 0, z: 0 }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml.
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.popFromStack();
|
||||
switch (message.method) {
|
||||
case "newModelDialogAdd":
|
||||
handleNewModelDialogResult(message.params);
|
||||
break;
|
||||
case "newEntityButtonClicked":
|
||||
buttonHandlers[message.params.buttonName]();
|
||||
break;
|
||||
}
|
||||
return button;
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
|
@ -240,101 +276,40 @@ var toolBar = (function () {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
if (Settings.getValue("HUDUIEnabled")) {
|
||||
systemToolbar = Toolbars.getToolbar(SYSTEM_TOOLBAR);
|
||||
activeButton = systemToolbar.addButton({
|
||||
objectName: EDIT_TOGGLE_BUTTON,
|
||||
imageURL: TOOLS_PATH + "edit.svg",
|
||||
visible: true,
|
||||
alpha: 0.9,
|
||||
defaultState: 1
|
||||
});
|
||||
} else {
|
||||
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
activeButton = tablet.addButton({
|
||||
icon: "icons/tablet-icons/edit-i.svg",
|
||||
activeIcon: "icons/tablet-icons/edit-a.svg",
|
||||
text: "EDIT",
|
||||
sortOrder: 10
|
||||
});
|
||||
}
|
||||
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
activeButton = tablet.addButton({
|
||||
icon: "icons/tablet-icons/edit-i.svg",
|
||||
activeIcon: "icons/tablet-icons/edit-a.svg",
|
||||
text: "EDIT",
|
||||
sortOrder: 10
|
||||
});
|
||||
tablet.screenChanged.connect(function (type, url) {
|
||||
if (isActive && (type !== "QML" || url !== "Edit.qml")) {
|
||||
that.toggle();
|
||||
}
|
||||
});
|
||||
tablet.fromQml.connect(fromQml);
|
||||
|
||||
activeButton.clicked.connect(function() {
|
||||
that.toggle();
|
||||
});
|
||||
|
||||
toolBar = Toolbars.getToolbar(EDIT_TOOLBAR);
|
||||
toolBar.writeProperty("shown", false);
|
||||
addButton("openAssetBrowserButton","assets-01.svg",function(){
|
||||
addButton("openAssetBrowserButton", "assets-01.svg", function(){
|
||||
Window.showAssetServer();
|
||||
})
|
||||
});
|
||||
|
||||
addButton("newModelButton", "model-01.svg", function () {
|
||||
var SHAPE_TYPE_NONE = 0;
|
||||
var SHAPE_TYPE_SIMPLE_HULL = 1;
|
||||
var SHAPE_TYPE_SIMPLE_COMPOUND = 2;
|
||||
var SHAPE_TYPE_STATIC_MESH = 3;
|
||||
|
||||
var SHAPE_TYPES = [];
|
||||
SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision";
|
||||
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model";
|
||||
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_COMPOUND] = "Good - Sub-meshes";
|
||||
SHAPE_TYPES[SHAPE_TYPE_STATIC_MESH] = "Exact - All polygons";
|
||||
|
||||
var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_STATIC_MESH;
|
||||
var DYNAMIC_DEFAULT = false;
|
||||
var result = Window.customPrompt({
|
||||
textInput: {
|
||||
label: "Model URL"
|
||||
},
|
||||
comboBox: {
|
||||
label: "Automatic Collisions",
|
||||
index: SHAPE_TYPE_DEFAULT,
|
||||
items: SHAPE_TYPES
|
||||
},
|
||||
checkBox: {
|
||||
label: "Dynamic",
|
||||
checked: DYNAMIC_DEFAULT,
|
||||
disableForItems: [
|
||||
SHAPE_TYPE_STATIC_MESH
|
||||
],
|
||||
checkStateOnDisable: false,
|
||||
warningOnDisable: "Models with automatic collisions set to 'Exact' cannot be dynamic"
|
||||
}
|
||||
});
|
||||
|
||||
if (result) {
|
||||
var url = result.textInput;
|
||||
var shapeType;
|
||||
switch (result.comboBox) {
|
||||
case SHAPE_TYPE_SIMPLE_HULL:
|
||||
shapeType = "simple-hull";
|
||||
break;
|
||||
case SHAPE_TYPE_SIMPLE_COMPOUND:
|
||||
shapeType = "simple-compound";
|
||||
break;
|
||||
case SHAPE_TYPE_STATIC_MESH:
|
||||
shapeType = "static-mesh";
|
||||
break;
|
||||
default:
|
||||
shapeType = "none";
|
||||
}
|
||||
|
||||
var dynamic = result.checkBox !== null ? result.checkBox : DYNAMIC_DEFAULT;
|
||||
if (shapeType === "static-mesh" && dynamic) {
|
||||
// The prompt should prevent this case
|
||||
print("Error: model cannot be both static mesh and dynamic. This should never happen.");
|
||||
} else if (url) {
|
||||
createNewEntity({
|
||||
type: "Model",
|
||||
modelURL: url,
|
||||
shapeType: shapeType,
|
||||
dynamic: dynamic,
|
||||
gravity: dynamic ? { x: 0, y: -10, z: 0 } : { x: 0, y: 0, z: 0 }
|
||||
});
|
||||
}
|
||||
}
|
||||
// tablet version of new-model dialog
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.pushOntoStack("NewModelDialog.qml");
|
||||
});
|
||||
|
||||
addButton("newCubeButton", "cube-01.svg", function () {
|
||||
|
@ -456,10 +431,12 @@ var toolBar = (function () {
|
|||
entityListTool.clearEntityList();
|
||||
};
|
||||
|
||||
|
||||
that.toggle = function () {
|
||||
that.setActive(!isActive);
|
||||
activeButton.editProperties({isActive: isActive});
|
||||
if (!isActive) {
|
||||
tablet.gotoHomeScreen();
|
||||
}
|
||||
};
|
||||
|
||||
that.setActive = function (active) {
|
||||
|
@ -489,6 +466,8 @@ var toolBar = (function () {
|
|||
cameraManager.disable();
|
||||
selectionDisplay.triggerMapping.disable();
|
||||
} else {
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
tablet.loadQMLSource("Edit.qml");
|
||||
UserActivityLogger.enabledEdit();
|
||||
entityListTool.setVisible(true);
|
||||
gridTool.setVisible(true);
|
||||
|
@ -499,13 +478,6 @@ var toolBar = (function () {
|
|||
// everybody else to think that Interface has lost focus overall. fogbugzid:558
|
||||
// Window.setFocus();
|
||||
}
|
||||
// Sets visibility of tool buttons, excluding the power button
|
||||
toolBar.writeProperty("shown", active);
|
||||
var visible = toolBar.readProperty("visible");
|
||||
if (active && !visible) {
|
||||
toolBar.writeProperty("shown", false);
|
||||
toolBar.writeProperty("shown", true);
|
||||
}
|
||||
lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE));
|
||||
Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
|
||||
};
|
||||
|
@ -642,7 +614,6 @@ var idleMouseTimerId = null;
|
|||
var CLICK_TIME_THRESHOLD = 500 * 1000; // 500 ms
|
||||
var CLICK_MOVE_DISTANCE_THRESHOLD = 20;
|
||||
var IDLE_MOUSE_TIMEOUT = 200;
|
||||
var DEFAULT_ENTITY_DRAG_DROP_DISTANCE = 2.0;
|
||||
|
||||
var lastMouseMoveEvent = null;
|
||||
|
||||
|
@ -772,6 +743,12 @@ function mouseClickEvent(event) {
|
|||
orientation = MyAvatar.orientation;
|
||||
intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation));
|
||||
|
||||
if (event.isShifted) {
|
||||
particleExplorerTool.destroyWebView();
|
||||
}
|
||||
if (properties.type !== "ParticleEffect") {
|
||||
particleExplorerTool.destroyWebView();
|
||||
}
|
||||
|
||||
if (!event.isShifted) {
|
||||
selectionManager.setSelections([foundEntity]);
|
||||
|
@ -1297,11 +1274,11 @@ function getPositionToCreateEntity() {
|
|||
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(direction, distance));
|
||||
|
||||
if (Camera.mode === "entity" || Camera.mode === "independent") {
|
||||
position = Vec3.sum(Camera.position, Vec3.multiply(Quat.getFront(Camera.orientation), distance))
|
||||
position = Vec3.sum(Camera.position, Vec3.multiply(Quat.getFront(Camera.orientation), distance));
|
||||
}
|
||||
position.y += 0.5;
|
||||
if (position.x > HALF_TREE_SCALE || position.y > HALF_TREE_SCALE || position.z > HALF_TREE_SCALE) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
@ -1315,11 +1292,11 @@ function getPositionToImportEntity() {
|
|||
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(direction, longest));
|
||||
|
||||
if (Camera.mode === "entity" || Camera.mode === "independent") {
|
||||
position = Vec3.sum(Camera.position, Vec3.multiply(Quat.getFront(Camera.orientation), longest))
|
||||
position = Vec3.sum(Camera.position, Vec3.multiply(Quat.getFront(Camera.orientation), longest));
|
||||
}
|
||||
|
||||
if (position.x > HALF_TREE_SCALE || position.y > HALF_TREE_SCALE || position.z > HALF_TREE_SCALE) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
|
||||
return position;
|
||||
|
@ -1527,11 +1504,11 @@ var ServerScriptStatusMonitor = function(entityID, statusCallback) {
|
|||
Entities.getServerScriptStatus(entityID, onStatusReceived);
|
||||
}
|
||||
}, 1000);
|
||||
};
|
||||
}
|
||||
};
|
||||
self.stop = function() {
|
||||
self.active = false;
|
||||
}
|
||||
};
|
||||
|
||||
Entities.getServerScriptStatus(entityID, onStatusReceived);
|
||||
};
|
||||
|
@ -1539,11 +1516,9 @@ var ServerScriptStatusMonitor = function(entityID, statusCallback) {
|
|||
var PropertiesTool = function (opts) {
|
||||
var that = {};
|
||||
|
||||
var webView = new OverlayWebWindow({
|
||||
title: 'Entity Properties',
|
||||
source: ENTITY_PROPERTIES_URL,
|
||||
toolWindow: true
|
||||
});
|
||||
var webView = null;
|
||||
webView = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
webView.setVisible = function(value) {};
|
||||
|
||||
var visible = false;
|
||||
|
||||
|
@ -1562,7 +1537,7 @@ var PropertiesTool = function (opts) {
|
|||
function updateScriptStatus(info) {
|
||||
info.type = "server_script_status";
|
||||
webView.emitScriptEvent(JSON.stringify(info));
|
||||
};
|
||||
}
|
||||
|
||||
function resetScriptStatus() {
|
||||
updateScriptStatus({
|
||||
|
@ -1621,7 +1596,7 @@ var PropertiesTool = function (opts) {
|
|||
data = JSON.parse(data);
|
||||
}
|
||||
catch(e) {
|
||||
print('Edit.js received web event that was not valid json.')
|
||||
print('Edit.js received web event that was not valid json.');
|
||||
return;
|
||||
}
|
||||
var i, properties, dY, diff, newPosition;
|
||||
|
@ -1639,15 +1614,15 @@ var PropertiesTool = function (opts) {
|
|||
for (i = 0; i < selectionManager.selections.length; i++) {
|
||||
Entities.editEntity(selectionManager.selections[i], properties);
|
||||
}
|
||||
} else {
|
||||
} else if (data.properties) {
|
||||
if (data.properties.dynamic === false) {
|
||||
// this object is leaving dynamic, so we zero its velocities
|
||||
data.properties["velocity"] = {
|
||||
data.properties.velocity = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
};
|
||||
data.properties["angularVelocity"] = {
|
||||
data.properties.angularVelocity = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
|
@ -1960,6 +1935,21 @@ var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace");
|
|||
var propertiesTool = new PropertiesTool();
|
||||
var particleExplorerTool = new ParticleExplorerTool();
|
||||
var selectedParticleEntity = 0;
|
||||
|
||||
function selectParticleEntity(entityID) {
|
||||
var properties = Entities.getEntityProperties(entityID);
|
||||
var particleData = {
|
||||
messageType: "particle_settings",
|
||||
currentProperties: properties
|
||||
};
|
||||
particleExplorerTool.destroyWebView();
|
||||
particleExplorerTool.createWebView();
|
||||
|
||||
selectedParticleEntity = entityID;
|
||||
particleExplorerTool.setActiveParticleEntity(entityID);
|
||||
particleExplorerTool.webView.emitScriptEvent(JSON.stringify(particleData));
|
||||
}
|
||||
|
||||
entityListTool.webView.webEventReceived.connect(function (data) {
|
||||
data = JSON.parse(data);
|
||||
if(data.type === 'parent') {
|
||||
|
@ -1975,22 +1965,7 @@ entityListTool.webView.webEventReceived.connect(function (data) {
|
|||
return;
|
||||
}
|
||||
// Destroy the old particles web view first
|
||||
particleExplorerTool.destroyWebView();
|
||||
particleExplorerTool.createWebView();
|
||||
var properties = Entities.getEntityProperties(ids[0]);
|
||||
var particleData = {
|
||||
messageType: "particle_settings",
|
||||
currentProperties: properties
|
||||
};
|
||||
selectedParticleEntity = ids[0];
|
||||
particleExplorerTool.setActiveParticleEntity(ids[0]);
|
||||
|
||||
particleExplorerTool.webView.webEventReceived.connect(function (data) {
|
||||
data = JSON.parse(data);
|
||||
if (data.messageType === "page_loaded") {
|
||||
particleExplorerTool.webView.emitScriptEvent(JSON.stringify(particleData));
|
||||
}
|
||||
});
|
||||
selectParticleEntity(ids[0]);
|
||||
} else {
|
||||
selectedParticleEntity = 0;
|
||||
particleExplorerTool.destroyWebView();
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
var buttonName = "Settings";
|
||||
var toolBar = null;
|
||||
var tablet = null;
|
||||
var settings = "TabletGeneralSettings.qml"
|
||||
var settings = "TabletGeneralPreferences.qml"
|
||||
function onClicked(){
|
||||
if (tablet) {
|
||||
tablet.loadQMLSource(settings);
|
||||
|
|
|
@ -18,13 +18,14 @@ var button;
|
|||
var buttonName = "GOTO";
|
||||
var toolBar = null;
|
||||
var tablet = null;
|
||||
|
||||
var onGotoScreen = false;
|
||||
function onAddressBarShown(visible) {
|
||||
button.editProperties({isActive: visible});
|
||||
}
|
||||
|
||||
function onClicked(){
|
||||
DialogsManager.toggleAddressBar();
|
||||
onGotoScreen = !onGotoScreen;
|
||||
}
|
||||
|
||||
if (Settings.getValue("HUDUIEnabled")) {
|
||||
|
@ -49,6 +50,9 @@ button.clicked.connect(onClicked);
|
|||
DialogsManager.addressBarShown.connect(onAddressBarShown);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
if (onGotoScreen) {
|
||||
DialogsManager.toggleAddressBar();
|
||||
}
|
||||
button.clicked.disconnect(onClicked);
|
||||
if (tablet) {
|
||||
tablet.removeButton(button);
|
||||
|
|
|
@ -48,6 +48,9 @@
|
|||
}, POLL_RATE);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
if (enabled) {
|
||||
Menu.closeInfoView('InfoView_html/help.html');
|
||||
}
|
||||
button.clicked.disconnect(onClicked);
|
||||
Script.clearInterval(interval);
|
||||
if (tablet) {
|
||||
|
|
|
@ -871,6 +871,7 @@ textarea:enabled[scrolling="true"]::-webkit-resizer {
|
|||
float: right;
|
||||
margin-right: 0;
|
||||
background-color: #ff0000;
|
||||
min-width: 90px;
|
||||
}
|
||||
|
||||
#entity-list {
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
</div>
|
||||
<div id="id" class="property value">
|
||||
<label>ID:</label>
|
||||
<span id="property-id" class="selectable"></span>
|
||||
<input type="text" id="property-id" readonly>
|
||||
</div>
|
||||
<div class="section-header hyperlink-group hyperlink-section">
|
||||
<label>Hyperlink</label><span>M</span>
|
||||
|
|
|
@ -338,10 +338,10 @@ function loaded() {
|
|||
}
|
||||
} else if (data.type == "update") {
|
||||
var newEntities = data.entities;
|
||||
if (newEntities.length == 0) {
|
||||
if (newEntities && newEntities.length == 0) {
|
||||
elNoEntitiesMessage.style.display = "block";
|
||||
elFooter.firstChild.nodeValue = "0 entities found";
|
||||
} else {
|
||||
} else if (newEntities) {
|
||||
elNoEntitiesMessage.style.display = "none";
|
||||
for (var i = 0; i < newEntities.length; i++) {
|
||||
var id = newEntities[i].id;
|
||||
|
|
|
@ -758,16 +758,16 @@ function loaded() {
|
|||
}
|
||||
} else if (data.type == "update") {
|
||||
|
||||
if (data.selections.length == 0) {
|
||||
if (!data.selections || data.selections.length == 0) {
|
||||
if (editor !== null && lastEntityID !== null) {
|
||||
saveJSONUserData(true);
|
||||
deleteJSONEditor();
|
||||
}
|
||||
elTypeIcon.style.display = "none";
|
||||
elType.innerHTML = "<i>No selection</i>";
|
||||
elID.innerHTML = "";
|
||||
elID.value = "";
|
||||
disableProperties();
|
||||
} else if (data.selections.length > 1) {
|
||||
} else if (data.selections && data.selections.length > 1) {
|
||||
deleteJSONEditor();
|
||||
var selections = data.selections;
|
||||
|
||||
|
@ -795,7 +795,7 @@ function loaded() {
|
|||
elTypeIcon.innerHTML = ICON_FOR_TYPE[type];
|
||||
elTypeIcon.style.display = "inline-block";
|
||||
|
||||
elID.innerHTML = ids.join("<br>");
|
||||
elID.value = "";
|
||||
|
||||
disableProperties();
|
||||
} else {
|
||||
|
@ -808,7 +808,7 @@ function loaded() {
|
|||
//the event bridge and json parsing handle our avatar id string differently.
|
||||
|
||||
lastEntityID = '"' + properties.id + '"';
|
||||
elID.innerHTML = properties.id;
|
||||
elID.value = properties.id;
|
||||
|
||||
elType.innerHTML = properties.type;
|
||||
elTypeIcon.innerHTML = ICON_FOR_TYPE[properties.type];
|
||||
|
|
|
@ -45,6 +45,10 @@ function calcSpawnInfo(hand, height) {
|
|||
var headPos = (HMD.active && Camera.mode === "first person") ? HMD.position : Camera.position;
|
||||
var headRot = (HMD.active && Camera.mode === "first person") ? HMD.orientation : Camera.orientation;
|
||||
|
||||
if (!hand) {
|
||||
hand = NO_HANDS;
|
||||
}
|
||||
|
||||
if (HMD.active && hand !== NO_HANDS) {
|
||||
var handController = getControllerWorldLocation(hand, true);
|
||||
var controllerPosition = handController.position;
|
||||
|
@ -96,7 +100,7 @@ function calcSpawnInfo(hand, height) {
|
|||
* @param hand [number] -1 indicates no hand, Controller.Standard.RightHand or Controller.Standard.LeftHand
|
||||
* @param clientOnly [bool] true indicates tablet model is only visible to client.
|
||||
*/
|
||||
WebTablet = function (url, width, dpi, hand, clientOnly) {
|
||||
WebTablet = function (url, width, dpi, hand, clientOnly, location) {
|
||||
|
||||
var _this = this;
|
||||
|
||||
|
@ -134,6 +138,10 @@ WebTablet = function (url, width, dpi, hand, clientOnly) {
|
|||
|
||||
// compute position, rotation & parentJointIndex of the tablet
|
||||
this.calculateTabletAttachmentProperties(hand, true, tabletProperties);
|
||||
if (location) {
|
||||
tabletProperties.localPosition = location.localPosition;
|
||||
tabletProperties.localRotation = location.localRotation;
|
||||
}
|
||||
|
||||
this.cleanUpOldTablets();
|
||||
|
||||
|
@ -185,10 +193,16 @@ WebTablet = function (url, width, dpi, hand, clientOnly) {
|
|||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
var onHomeScreen = tablet.onHomeScreen();
|
||||
if (onHomeScreen) {
|
||||
HMD.closeTablet();
|
||||
var isMessageOpen = tablet.isMessageDialogOpen();
|
||||
if (isMessageOpen === false) {
|
||||
HMD.closeTablet();
|
||||
}
|
||||
} else {
|
||||
tablet.gotoHomeScreen();
|
||||
_this.setHomeButtonTexture();
|
||||
var isMessageOpen = tablet.isMessageDialogOpen();
|
||||
if (isMessageOpen === false) {
|
||||
tablet.gotoHomeScreen();
|
||||
_this.setHomeButtonTexture();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -467,11 +481,16 @@ WebTablet.prototype.mousePressEvent = function (event) {
|
|||
if (overlayPickResults.intersects && overlayPickResults.overlayID === this.homeButtonID) {
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
var onHomeScreen = tablet.onHomeScreen();
|
||||
var isMessageOpen = tablet.isMessageDialogOpen();
|
||||
if (onHomeScreen) {
|
||||
HMD.closeTablet();
|
||||
if (isMessageOpen === false) {
|
||||
HMD.closeTablet();
|
||||
}
|
||||
} else {
|
||||
tablet.gotoHomeScreen();
|
||||
this.setHomeButtonTexture();
|
||||
if (isMessageOpen === false) {
|
||||
tablet.gotoHomeScreen();
|
||||
this.setHomeButtonTexture();
|
||||
}
|
||||
}
|
||||
} else if (!HMD.active && (!overlayPickResults.intersects || overlayPickResults.overlayID !== this.webOverlayID)) {
|
||||
this.dragging = true;
|
||||
|
|
|
@ -1,13 +1,22 @@
|
|||
var ENTITY_LIST_HTML_URL = Script.resolvePath('../html/entityList.html');
|
||||
"use strict";
|
||||
|
||||
// entityList.js
|
||||
//
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* global EntityListTool, Tablet, selectionManager, Entities, Camera, MyAvatar, Vec3, Menu, Messages,
|
||||
cameraManager, MENU_EASE_ON_FOCUS, deleteSelectedEntities, toggleSelectedEntitiesLocked, toggleSelectedEntitiesVisible */
|
||||
|
||||
EntityListTool = function(opts) {
|
||||
var that = {};
|
||||
|
||||
var url = ENTITY_LIST_HTML_URL;
|
||||
var webView = new OverlayWebWindow({
|
||||
title: 'Entity List', source: url, toolWindow: true
|
||||
});
|
||||
|
||||
var webView = null;
|
||||
webView = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
webView.setVisible = function(value) {};
|
||||
|
||||
var filterInView = false;
|
||||
var searchRadius = 100;
|
||||
|
@ -25,7 +34,7 @@ EntityListTool = function(opts) {
|
|||
|
||||
that.toggleVisible = function() {
|
||||
that.setVisible(!visible);
|
||||
}
|
||||
};
|
||||
|
||||
selectionManager.addEventListener(function() {
|
||||
var selectedIDs = [];
|
||||
|
@ -44,7 +53,7 @@ EntityListTool = function(opts) {
|
|||
that.clearEntityList = function () {
|
||||
var data = {
|
||||
type: 'clearEntityList'
|
||||
}
|
||||
};
|
||||
webView.emitScriptEvent(JSON.stringify(data));
|
||||
};
|
||||
|
||||
|
@ -86,8 +95,8 @@ EntityListTool = function(opts) {
|
|||
}
|
||||
|
||||
var selectedIDs = [];
|
||||
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||
selectedIDs.push(selectionManager.selections[i].id);
|
||||
for (var j = 0; j < selectionManager.selections.length; j++) {
|
||||
selectedIDs.push(selectionManager.selections[j].id);
|
||||
}
|
||||
|
||||
var data = {
|
||||
|
@ -96,7 +105,7 @@ EntityListTool = function(opts) {
|
|||
selectedIDs: selectedIDs,
|
||||
};
|
||||
webView.emitScriptEvent(JSON.stringify(data));
|
||||
}
|
||||
};
|
||||
|
||||
webView.webEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
|
@ -149,11 +158,11 @@ EntityListTool = function(opts) {
|
|||
}
|
||||
});
|
||||
|
||||
webView.visibleChanged.connect(function () {
|
||||
if (webView.visible) {
|
||||
that.sendUpdate();
|
||||
}
|
||||
});
|
||||
// webView.visibleChanged.connect(function () {
|
||||
// if (webView.visible) {
|
||||
// that.sendUpdate();
|
||||
// }
|
||||
// });
|
||||
|
||||
return that;
|
||||
};
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* global HIFI_PUBLIC_BUCKET, SPACE_LOCAL, Script, SelectionManager */
|
||||
|
||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
|
||||
SPACE_LOCAL = "local";
|
||||
|
@ -28,7 +30,7 @@ SelectionManager = (function() {
|
|||
var that = {};
|
||||
|
||||
function subscribeToUpdateMessages() {
|
||||
Messages.subscribe('entityToolUpdates');
|
||||
Messages.subscribe("entityToolUpdates");
|
||||
Messages.messageReceived.connect(handleEntitySelectionToolUpdates);
|
||||
}
|
||||
|
||||
|
@ -40,8 +42,20 @@ SelectionManager = (function() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (message === 'callUpdate') {
|
||||
that._update();
|
||||
var messageParsed;
|
||||
try {
|
||||
messageParsed = JSON.parse(message);
|
||||
} catch (err) {
|
||||
print("error -- entitySelectionTool got malformed message: " + message);
|
||||
}
|
||||
|
||||
// if (message === 'callUpdate') {
|
||||
// that._update();
|
||||
// }
|
||||
|
||||
if (messageParsed.method === "selectEntity") {
|
||||
print("setting selection to " + messageParsed.entityID);
|
||||
that.setSelections([messageParsed.entityID]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,13 +163,14 @@ SelectionManager = (function() {
|
|||
};
|
||||
|
||||
that._update = function(selectionUpdated) {
|
||||
if (that.selections.length == 0) {
|
||||
var properties = null;
|
||||
if (that.selections.length === 0) {
|
||||
that.localDimensions = null;
|
||||
that.localPosition = null;
|
||||
that.worldDimensions = null;
|
||||
that.worldPosition = null;
|
||||
} else if (that.selections.length == 1) {
|
||||
var properties = Entities.getEntityProperties(that.selections[0]);
|
||||
properties = Entities.getEntityProperties(that.selections[0]);
|
||||
that.localDimensions = properties.dimensions;
|
||||
that.localPosition = properties.position;
|
||||
that.localRotation = properties.rotation;
|
||||
|
@ -170,7 +185,7 @@ SelectionManager = (function() {
|
|||
that.localDimensions = null;
|
||||
that.localPosition = null;
|
||||
|
||||
var properties = Entities.getEntityProperties(that.selections[0]);
|
||||
properties = Entities.getEntityProperties(that.selections[0]);
|
||||
|
||||
var brn = properties.boundingBox.brn;
|
||||
var tfl = properties.boundingBox.tfl;
|
||||
|
@ -203,9 +218,9 @@ SelectionManager = (function() {
|
|||
SelectionDisplay.setSpaceMode(SPACE_WORLD);
|
||||
}
|
||||
|
||||
for (var i = 0; i < listeners.length; i++) {
|
||||
for (var j = 0; j < listeners.length; j++) {
|
||||
try {
|
||||
listeners[i](selectionUpdated === true);
|
||||
listeners[j](selectionUpdated === true);
|
||||
} catch (e) {
|
||||
print("EntitySelectionTool got exception: " + JSON.stringify(e));
|
||||
}
|
||||
|
@ -229,8 +244,8 @@ function getRelativeCenterPosition(dimensions, registrationPoint) {
|
|||
return {
|
||||
x: -dimensions.x * (registrationPoint.x - 0.5),
|
||||
y: -dimensions.y * (registrationPoint.y - 0.5),
|
||||
z: -dimensions.z * (registrationPoint.z - 0.5),
|
||||
}
|
||||
z: -dimensions.z * (registrationPoint.z - 0.5)
|
||||
};
|
||||
}
|
||||
|
||||
SelectionDisplay = (function() {
|
||||
|
@ -253,7 +268,7 @@ SelectionDisplay = (function() {
|
|||
|
||||
var spaceMode = SPACE_LOCAL;
|
||||
var mode = "UNKNOWN";
|
||||
var overlayNames = new Array();
|
||||
var overlayNames = [];
|
||||
var lastCameraPosition = Camera.getPosition();
|
||||
var lastCameraOrientation = Camera.getOrientation();
|
||||
|
||||
|
@ -679,8 +694,7 @@ SelectionDisplay = (function() {
|
|||
green: 0,
|
||||
blue: 0
|
||||
},
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
visible: false,
|
||||
ignoreRayIntersection: true // always ignore this
|
||||
});
|
||||
var yRailOverlay = Overlays.addOverlay("line3d", {
|
||||
visible: false,
|
||||
|
@ -700,8 +714,7 @@ SelectionDisplay = (function() {
|
|||
green: 255,
|
||||
blue: 0
|
||||
},
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
visible: false,
|
||||
ignoreRayIntersection: true // always ignore this
|
||||
});
|
||||
var zRailOverlay = Overlays.addOverlay("line3d", {
|
||||
visible: false,
|
||||
|
@ -721,8 +734,7 @@ SelectionDisplay = (function() {
|
|||
green: 0,
|
||||
blue: 255
|
||||
},
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
visible: false,
|
||||
ignoreRayIntersection: true // always ignore this
|
||||
});
|
||||
|
||||
var rotateZeroOverlay = Overlays.addOverlay("line3d", {
|
||||
|
@ -1022,30 +1034,13 @@ SelectionDisplay = (function() {
|
|||
that.triggered = true;
|
||||
if (activeHand !== hand) {
|
||||
// No switching while the other is already triggered, so no need to release.
|
||||
activeHand = (activeHand === Controller.Standard.RightHand) ? Controller.Standard.LeftHand : Controller.Standard.RightHand;
|
||||
activeHand = (activeHand === Controller.Standard.RightHand) ?
|
||||
Controller.Standard.LeftHand : Controller.Standard.RightHand;
|
||||
}
|
||||
if (Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(Reticle.position)) {
|
||||
return;
|
||||
}
|
||||
var eventResult = that.mousePressEvent({});
|
||||
if (!eventResult || (eventResult === 'selectionBox')) {
|
||||
var pickRay = controllerComputePickRay();
|
||||
if (pickRay) {
|
||||
var entityIntersection = Entities.findRayIntersection(pickRay, true);
|
||||
|
||||
|
||||
var overlayIntersection = Overlays.findRayIntersection(pickRay);
|
||||
if (entityIntersection.intersects &&
|
||||
(!overlayIntersection.intersects || (entityIntersection.distance < overlayIntersection.distance))) {
|
||||
|
||||
if (HMD.tabletID === entityIntersection.entityID) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectionManager.setSelections([entityIntersection.entityID]);
|
||||
}
|
||||
}
|
||||
}
|
||||
that.mousePressEvent({});
|
||||
} else if (that.triggered && (value < that.TRIGGER_OFF_VALUE)) {
|
||||
that.triggered = false;
|
||||
that.mouseReleaseEvent({});
|
||||
|
@ -1054,6 +1049,8 @@ SelectionDisplay = (function() {
|
|||
}
|
||||
that.triggerMapping.from(Controller.Standard.RT).peek().to(makeTriggerHandler(Controller.Standard.RightHand));
|
||||
that.triggerMapping.from(Controller.Standard.LT).peek().to(makeTriggerHandler(Controller.Standard.LeftHand));
|
||||
|
||||
|
||||
function controllerComputePickRay() {
|
||||
var controllerPose = getControllerWorldLocation(activeHand, true);
|
||||
if (controllerPose.valid && that.triggered) {
|
||||
|
@ -1072,7 +1069,7 @@ SelectionDisplay = (function() {
|
|||
onBegin: tool.onBegin,
|
||||
onMove: tool.onMove,
|
||||
onEnd: tool.onEnd,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
@ -1080,8 +1077,8 @@ SelectionDisplay = (function() {
|
|||
for (var i = 0; i < allOverlays.length; i++) {
|
||||
Overlays.deleteOverlay(allOverlays[i]);
|
||||
}
|
||||
for (var i = 0; i < selectionBoxes.length; i++) {
|
||||
Overlays.deleteOverlay(selectionBoxes[i]);
|
||||
for (var j = 0; j < selectionBoxes.length; j++) {
|
||||
Overlays.deleteOverlay(selectionBoxes[j]);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1125,7 +1122,7 @@ SelectionDisplay = (function() {
|
|||
});
|
||||
|
||||
that.updateHandles();
|
||||
}
|
||||
};
|
||||
|
||||
that.updateRotationHandles = function() {
|
||||
var diagonal = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1;
|
||||
|
@ -1572,7 +1569,7 @@ SelectionDisplay = (function() {
|
|||
that.unselectAll = function() {};
|
||||
|
||||
that.updateHandles = function() {
|
||||
if (SelectionManager.selections.length == 0) {
|
||||
if (SelectionManager.selections.length === 0) {
|
||||
that.setOverlaysVisible(false);
|
||||
return;
|
||||
}
|
||||
|
@ -1608,7 +1605,8 @@ SelectionDisplay = (function() {
|
|||
var bottom = -registrationPointDimensions.y;
|
||||
var top = dimensions.y - registrationPointDimensions.y;
|
||||
var near = -registrationPointDimensions.z;
|
||||
var front = far = dimensions.z - registrationPointDimensions.z;
|
||||
var far = dimensions.z - registrationPointDimensions.z;
|
||||
var front = far;
|
||||
|
||||
var worldTop = SelectionManager.worldDimensions.y / 2;
|
||||
|
||||
|
@ -1808,9 +1806,9 @@ SelectionDisplay = (function() {
|
|||
|
||||
if (selectionManager.selections.length == 1) {
|
||||
var properties = Entities.getEntityProperties(selectionManager.selections[0]);
|
||||
if (properties.type == "Light" && properties.isSpotlight == true) {
|
||||
var stretchHandlesVisible = false;
|
||||
var extendedStretchHandlesVisible = false;
|
||||
if (properties.type == "Light" && properties.isSpotlight) {
|
||||
stretchHandlesVisible = false;
|
||||
extendedStretchHandlesVisible = false;
|
||||
|
||||
Overlays.editOverlay(grabberSpotLightCenter, {
|
||||
position: position,
|
||||
|
@ -1903,9 +1901,9 @@ SelectionDisplay = (function() {
|
|||
Overlays.editOverlay(grabberPointLightN, {
|
||||
visible: false
|
||||
});
|
||||
} else if (properties.type == "Light" && properties.isSpotlight == false) {
|
||||
var stretchHandlesVisible = false;
|
||||
var extendedStretchHandlesVisible = false;
|
||||
} else if (properties.type == "Light" && !properties.isSpotlight) {
|
||||
stretchHandlesVisible = false;
|
||||
extendedStretchHandlesVisible = false;
|
||||
Overlays.editOverlay(grabberPointLightT, {
|
||||
position: TOP,
|
||||
rotation: rotation,
|
||||
|
@ -2171,23 +2169,23 @@ SelectionDisplay = (function() {
|
|||
}));
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
i = 0;
|
||||
// Only show individual selections boxes if there is more than 1 selection
|
||||
if (selectionManager.selections.length > 1) {
|
||||
for (; i < selectionManager.selections.length; i++) {
|
||||
var properties = Entities.getEntityProperties(selectionManager.selections[i]);
|
||||
var props = Entities.getEntityProperties(selectionManager.selections[i]);
|
||||
|
||||
// Adjust overlay position to take registrationPoint into account
|
||||
// centeredRP = registrationPoint with range [-0.5, 0.5]
|
||||
var centeredRP = Vec3.subtract(properties.registrationPoint, {
|
||||
var centeredRP = Vec3.subtract(props.registrationPoint, {
|
||||
x: 0.5,
|
||||
y: 0.5,
|
||||
z: 0.5
|
||||
});
|
||||
var offset = vec3Mult(properties.dimensions, centeredRP);
|
||||
var offset = vec3Mult(props.dimensions, centeredRP);
|
||||
offset = Vec3.multiply(-1, offset);
|
||||
offset = Vec3.multiplyQbyV(properties.rotation, offset);
|
||||
var boxPosition = Vec3.sum(properties.position, offset);
|
||||
offset = Vec3.multiplyQbyV(props.rotation, offset);
|
||||
var boxPosition = Vec3.sum(props.position, offset);
|
||||
|
||||
var color = {red: 255, green: 128, blue: 0};
|
||||
if (i >= selectionManager.selections.length - 1) color = {red: 255, green: 255, blue: 64};
|
||||
|
@ -2195,8 +2193,8 @@ SelectionDisplay = (function() {
|
|||
Overlays.editOverlay(selectionBoxes[i], {
|
||||
position: boxPosition,
|
||||
color: color,
|
||||
rotation: properties.rotation,
|
||||
dimensions: properties.dimensions,
|
||||
rotation: props.rotation,
|
||||
dimensions: props.dimensions,
|
||||
visible: true,
|
||||
});
|
||||
}
|
||||
|
@ -2588,11 +2586,11 @@ SelectionDisplay = (function() {
|
|||
y: v1.y * v2.y,
|
||||
z: v1.z * v2.z
|
||||
};
|
||||
}
|
||||
// stretchMode - name of mode
|
||||
// direction - direction to stretch in
|
||||
// pivot - point to use as a pivot
|
||||
// offset - the position of the overlay tool relative to the selections center position
|
||||
};
|
||||
// stretchMode - name of mode
|
||||
// direction - direction to stretch in
|
||||
// pivot - point to use as a pivot
|
||||
// offset - the position of the overlay tool relative to the selections center position
|
||||
var makeStretchTool = function(stretchMode, direction, pivot, offset, customOnMove) {
|
||||
var signs = {
|
||||
x: direction.x < 0 ? -1 : (direction.x > 0 ? 1 : 0),
|
||||
|
@ -2644,7 +2642,7 @@ SelectionDisplay = (function() {
|
|||
});
|
||||
|
||||
// Scale pivot to be in the same range as registrationPoint
|
||||
var scaledPivot = Vec3.multiply(0.5, pivot)
|
||||
var scaledPivot = Vec3.multiply(0.5, pivot);
|
||||
deltaPivot = Vec3.subtract(centeredRP, scaledPivot);
|
||||
|
||||
var scaledOffset = Vec3.multiply(0.5, offset);
|
||||
|
@ -2656,14 +2654,16 @@ SelectionDisplay = (function() {
|
|||
var scaledOffsetWorld = vec3Mult(initialDimensions, offsetRP);
|
||||
pickRayPosition = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffsetWorld));
|
||||
|
||||
var start = null;
|
||||
var end = null;
|
||||
if (numDimensions == 1 && mask.x) {
|
||||
var start = Vec3.multiplyQbyV(rotation, {
|
||||
start = Vec3.multiplyQbyV(rotation, {
|
||||
x: -10000,
|
||||
y: 0,
|
||||
z: 0
|
||||
});
|
||||
start = Vec3.sum(start, properties.position);
|
||||
var end = Vec3.multiplyQbyV(rotation, {
|
||||
end = Vec3.multiplyQbyV(rotation, {
|
||||
x: 10000,
|
||||
y: 0,
|
||||
z: 0
|
||||
|
@ -2676,13 +2676,13 @@ SelectionDisplay = (function() {
|
|||
});
|
||||
}
|
||||
if (numDimensions == 1 && mask.y) {
|
||||
var start = Vec3.multiplyQbyV(rotation, {
|
||||
start = Vec3.multiplyQbyV(rotation, {
|
||||
x: 0,
|
||||
y: -10000,
|
||||
z: 0
|
||||
});
|
||||
start = Vec3.sum(start, properties.position);
|
||||
var end = Vec3.multiplyQbyV(rotation, {
|
||||
end = Vec3.multiplyQbyV(rotation, {
|
||||
x: 0,
|
||||
y: 10000,
|
||||
z: 0
|
||||
|
@ -2695,13 +2695,13 @@ SelectionDisplay = (function() {
|
|||
});
|
||||
}
|
||||
if (numDimensions == 1 && mask.z) {
|
||||
var start = Vec3.multiplyQbyV(rotation, {
|
||||
start = Vec3.multiplyQbyV(rotation, {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: -10000
|
||||
});
|
||||
start = Vec3.sum(start, properties.position);
|
||||
var end = Vec3.multiplyQbyV(rotation, {
|
||||
end = Vec3.multiplyQbyV(rotation, {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 10000
|
||||
|
@ -2734,13 +2734,13 @@ SelectionDisplay = (function() {
|
|||
};
|
||||
}
|
||||
} else if (numDimensions == 2) {
|
||||
if (mask.x == 0) {
|
||||
if (mask.x === 0) {
|
||||
planeNormal = {
|
||||
x: 1,
|
||||
y: 0,
|
||||
z: 0
|
||||
};
|
||||
} else if (mask.y == 0) {
|
||||
} else if (mask.y === 0) {
|
||||
planeNormal = {
|
||||
x: 0,
|
||||
y: 1,
|
||||
|
@ -2898,7 +2898,7 @@ SelectionDisplay = (function() {
|
|||
});
|
||||
|
||||
SelectionManager._update();
|
||||
};
|
||||
}
|
||||
|
||||
function radiusStretchFunc(vector, change) {
|
||||
var props = selectionManager.savedProperties[selectionManager.selections[0]];
|
||||
|
@ -3889,11 +3889,9 @@ SelectionDisplay = (function() {
|
|||
Overlays.editOverlay(rollHandle, {
|
||||
ignoreRayIntersection: true
|
||||
});
|
||||
var result = Overlays.findRayIntersection(pickRay);
|
||||
|
||||
result = Overlays.findRayIntersection(pickRay);
|
||||
if (result.intersects) {
|
||||
|
||||
|
||||
if (wantDebug) {
|
||||
print("something intersects... ");
|
||||
print(" result.overlayID:" + result.overlayID + "[" + overlayNames[result.overlayID] + "]");
|
||||
|
@ -4423,7 +4421,7 @@ SelectionDisplay = (function() {
|
|||
scale: handleSize / 1.25,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
Script.update.connect(that.updateHandleSizes);
|
||||
|
||||
that.mouseReleaseEvent = function(event) {
|
||||
|
|
|
@ -228,10 +228,9 @@ GridTool = function(opts) {
|
|||
var verticalGrid = opts.verticalGrid;
|
||||
var listeners = [];
|
||||
|
||||
var url = GRID_CONTROLS_HTML_URL;
|
||||
var webView = new OverlayWebWindow({
|
||||
title: 'Grid', source: url, toolWindow: true
|
||||
});
|
||||
var webView = null;
|
||||
webView = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
webView.setVisible = function(value) {};
|
||||
|
||||
horizontalGrid.addListener(function(data) {
|
||||
webView.emitScriptEvent(JSON.stringify(data));
|
||||
|
|
|
@ -121,6 +121,7 @@ function onClick() {
|
|||
if (onMarketplaceScreen) {
|
||||
// for toolbar-mode: go back to home screen, this will close the window.
|
||||
tablet.gotoHomeScreen();
|
||||
onMarketplaceScreen = false;
|
||||
} else {
|
||||
var entity = HMD.tabletID;
|
||||
Entities.editEntity(entity, {textures: JSON.stringify({"tex.close": HOME_BUTTON_TEXTURE})});
|
||||
|
@ -140,6 +141,9 @@ tablet.screenChanged.connect(onScreenChanged);
|
|||
Entities.canWriteAssetsChanged.connect(onCanWriteAssetsChanged);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
if (onMarketplaceScreen) {
|
||||
tablet.gotoHomeScreen();
|
||||
}
|
||||
tablet.removeButton(marketplaceButton);
|
||||
tablet.screenChanged.disconnect(onScreenChanged);
|
||||
Entities.canWriteAssetsChanged.disconnect(onCanWriteAssetsChanged);
|
||||
|
|
|
@ -48,6 +48,9 @@ var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-
|
|||
tablet.screenChanged.connect(onScreenChanged);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
if (onMenuScreen) {
|
||||
tablet.gotoHomeScreen();
|
||||
}
|
||||
button.clicked.disconnect(onClicked);
|
||||
tablet.removeButton(button);
|
||||
tablet.screenChanged.disconnect(onScreenChanged);
|
||||
|
|
|
@ -696,6 +696,9 @@ function clearLocalQMLDataAndClosePAL() {
|
|||
}
|
||||
|
||||
function shutdown() {
|
||||
if (onPalScreen) {
|
||||
tablet.gotoHomeScreen();
|
||||
}
|
||||
button.clicked.disconnect(onTabletButtonClicked);
|
||||
tablet.removeButton(button);
|
||||
tablet.screenChanged.disconnect(onTabletScreenChanged);
|
||||
|
|
|
@ -76,4 +76,4 @@ body{
|
|||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -32,6 +32,8 @@ var gui = null;
|
|||
var settings = new Settings();
|
||||
var updateInterval;
|
||||
|
||||
var active = false;
|
||||
|
||||
var currentInputField;
|
||||
var storedController;
|
||||
//CHANGE TO WHITELIST
|
||||
|
@ -358,9 +360,25 @@ function listenForSettingsUpdates() {
|
|||
settings[key] = value;
|
||||
});
|
||||
|
||||
loadGUI();
|
||||
}
|
||||
if (gui) {
|
||||
manuallyUpdateDisplay();
|
||||
} else {
|
||||
loadGUI();
|
||||
}
|
||||
if (!active) {
|
||||
// gui.toggleHide();
|
||||
gui.closed = false;
|
||||
}
|
||||
active = true;
|
||||
|
||||
} else if (data.messageType === "particle_close") {
|
||||
// none of this seems to work.
|
||||
// if (active) {
|
||||
// gui.toggleHide();
|
||||
// }
|
||||
active = false;
|
||||
gui.closed = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -505,4 +523,4 @@ function registerDOMElementsForListenerBlocking() {
|
|||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,26 +18,21 @@ ParticleExplorerTool = function() {
|
|||
var that = {};
|
||||
|
||||
that.createWebView = function() {
|
||||
var url = PARTICLE_EXPLORER_HTML_URL;
|
||||
that.webView = new OverlayWebWindow({
|
||||
title: 'Particle Explorer',
|
||||
source: url,
|
||||
toolWindow: true
|
||||
});
|
||||
|
||||
that.webView.setVisible(true);
|
||||
that.webView = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
that.webView.setVisible = function(value) {};
|
||||
that.webView.webEventReceived.connect(that.webEventReceived);
|
||||
}
|
||||
|
||||
|
||||
that.destroyWebView = function() {
|
||||
if (!that.webView) {
|
||||
return;
|
||||
}
|
||||
|
||||
that.webView.close();
|
||||
that.webView = null;
|
||||
that.activeParticleEntity = 0;
|
||||
|
||||
var messageData = {
|
||||
messageType: "particle_close"
|
||||
};
|
||||
that.webView.emitScriptEvent(JSON.stringify(messageData));
|
||||
}
|
||||
|
||||
that.webEventReceived = function(data) {
|
||||
|
@ -51,8 +46,5 @@ ParticleExplorerTool = function() {
|
|||
that.activeParticleEntity = id;
|
||||
}
|
||||
|
||||
|
||||
return that;
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
|
|
|
@ -191,12 +191,12 @@ function resetButtons(pathStillSnapshot, pathAnimatedSnapshot, notify) {
|
|||
if (clearOverlayWhenMoving) {
|
||||
MyAvatar.setClearOverlayWhenMoving(true); // not until after the share dialog
|
||||
}
|
||||
HMD.openTablet();
|
||||
}
|
||||
|
||||
function processingGif() {
|
||||
// show hud
|
||||
Reticle.visible = reticleVisible;
|
||||
|
||||
button.clicked.disconnect(onClicked);
|
||||
buttonConnected = false;
|
||||
// show overlays if they were on
|
||||
|
@ -211,8 +211,10 @@ Window.snapshotShared.connect(snapshotShared);
|
|||
Window.processingGif.connect(processingGif);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
button.clicked.disconnect(onClicked);
|
||||
buttonConnected = false;
|
||||
if (buttonConnected) {
|
||||
button.clicked.disconnect(onClicked);
|
||||
buttonConnected = false;
|
||||
}
|
||||
if (tablet) {
|
||||
tablet.removeButton(button);
|
||||
}
|
||||
|
|
|
@ -12,21 +12,47 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* global Script, HMD, WebTablet, UIWebTablet, UserActivityLogger, Settings, Entities, Messages, Tablet, Overlays, MyAvatar */
|
||||
/* global Script, HMD, WebTablet, UIWebTablet, UserActivityLogger, Settings, Entities, Messages, Tablet, Overlays,
|
||||
MyAvatar, Menu */
|
||||
|
||||
(function() { // BEGIN LOCAL_SCOPE
|
||||
var tabletShown = false;
|
||||
var tabletLocation = null;
|
||||
var tabletRezzed = false;
|
||||
var activeHand = null;
|
||||
var DEFAULT_WIDTH = 0.4375;
|
||||
var DEFAULT_TABLET_SCALE = 100;
|
||||
var preMakeTime = Date.now();
|
||||
var validCheckTime = Date.now();
|
||||
var debugTablet = false;
|
||||
UIWebTablet = null;
|
||||
|
||||
Script.include("../libraries/WebTablet.js");
|
||||
|
||||
function showTabletUI() {
|
||||
tabletShown = true;
|
||||
print("show tablet-ui");
|
||||
function tabletIsValid() {
|
||||
if (!UIWebTablet) {
|
||||
return false;
|
||||
}
|
||||
if (UIWebTablet.tabletIsOverlay && Overlays.getProperty(HMD.tabletID, "type") != "model") {
|
||||
if (debugTablet) {
|
||||
print("TABLET is invalid due to frame: " + JSON.stringify(Overlays.getProperty(HMD.tabletID, "type")));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (Overlays.getProperty(HMD.homeButtonID, "type") != "sphere" ||
|
||||
Overlays.getProperty(HMD.tabletScreenID, "type") != "web3d") {
|
||||
if (debugTablet) {
|
||||
print("TABLET is invalid due to other");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var DEFAULT_WIDTH = 0.4375;
|
||||
var DEFAULT_TABLET_SCALE = 100;
|
||||
|
||||
function rezTablet() {
|
||||
if (debugTablet) {
|
||||
print("TABLET rezzing");
|
||||
}
|
||||
var toolbarMode = Tablet.getTablet("com.highfidelity.interface.tablet.system").toolbarMode;
|
||||
var TABLET_SCALE = DEFAULT_TABLET_SCALE;
|
||||
if (toolbarMode) {
|
||||
|
@ -34,37 +60,98 @@
|
|||
} else {
|
||||
TABLET_SCALE = Settings.getValue("hmdTabletScale") || DEFAULT_TABLET_SCALE;
|
||||
}
|
||||
UIWebTablet = new WebTablet("qml/hifi/tablet/TabletRoot.qml", DEFAULT_WIDTH * (TABLET_SCALE / 100), null, activeHand, true);
|
||||
|
||||
UIWebTablet = new WebTablet("qml/hifi/tablet/TabletRoot.qml",
|
||||
DEFAULT_WIDTH * (TABLET_SCALE / 100),
|
||||
null, activeHand, true);
|
||||
UIWebTablet.register();
|
||||
HMD.tabletID = UIWebTablet.tabletEntityID;
|
||||
HMD.homeButtonID = UIWebTablet.homeButtonID;
|
||||
HMD.tabletScreenID = UIWebTablet.webOverlayID;
|
||||
|
||||
tabletRezzed = true;
|
||||
}
|
||||
|
||||
function showTabletUI() {
|
||||
tabletShown = true;
|
||||
|
||||
if (!tabletRezzed) {
|
||||
rezTablet(false);
|
||||
}
|
||||
|
||||
if (UIWebTablet && tabletRezzed) {
|
||||
if (debugTablet) {
|
||||
print("TABLET in showTabletUI, already rezzed");
|
||||
}
|
||||
var tabletProperties = {};
|
||||
UIWebTablet.calculateTabletAttachmentProperties(activeHand, true, tabletProperties);
|
||||
tabletProperties.visible = true;
|
||||
if (UIWebTablet.tabletIsOverlay) {
|
||||
Overlays.editOverlay(HMD.tabletID, tabletProperties);
|
||||
}
|
||||
Overlays.editOverlay(HMD.homeButtonID, { visible: true });
|
||||
Overlays.editOverlay(HMD.tabletScreenID, { visible: true });
|
||||
Overlays.editOverlay(HMD.tabletScreenID, { maxFPS: 90 });
|
||||
}
|
||||
}
|
||||
|
||||
function hideTabletUI() {
|
||||
tabletShown = false;
|
||||
print("hide tablet-ui");
|
||||
if (!UIWebTablet) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (UIWebTablet.tabletIsOverlay) {
|
||||
if (debugTablet) {
|
||||
print("TABLET hide");
|
||||
}
|
||||
if (Settings.getValue("tabletVisibleToOthers")) {
|
||||
closeTabletUI();
|
||||
} else {
|
||||
// Overlays.editOverlay(HMD.tabletID, { localPosition: { x: -1000, y: 0, z:0 } });
|
||||
Overlays.editOverlay(HMD.tabletID, { visible: false });
|
||||
Overlays.editOverlay(HMD.homeButtonID, { visible: false });
|
||||
Overlays.editOverlay(HMD.tabletScreenID, { visible: false });
|
||||
Overlays.editOverlay(HMD.tabletScreenID, { maxFPS: 1 });
|
||||
}
|
||||
} else {
|
||||
closeTabletUI();
|
||||
}
|
||||
}
|
||||
|
||||
function closeTabletUI() {
|
||||
tabletShown = false;
|
||||
if (UIWebTablet) {
|
||||
if (UIWebTablet.onClose) {
|
||||
UIWebTablet.onClose();
|
||||
}
|
||||
|
||||
tabletLocation = UIWebTablet.getLocation();
|
||||
if (debugTablet) {
|
||||
print("TABLET close");
|
||||
}
|
||||
UIWebTablet.unregister();
|
||||
UIWebTablet.destroy();
|
||||
UIWebTablet = null;
|
||||
HMD.tabletID = null;
|
||||
HMD.homeButtonID = null;
|
||||
HMD.tabletScreenID = null;
|
||||
} else if (debugTablet) {
|
||||
print("TABLET closeTabletUI, UIWebTablet is null");
|
||||
}
|
||||
tabletRezzed = false;
|
||||
}
|
||||
|
||||
|
||||
function updateShowTablet() {
|
||||
var MSECS_PER_SEC = 1000.0;
|
||||
var now = Date.now();
|
||||
|
||||
// close the WebTablet if it we go into toolbar mode.
|
||||
var toolbarMode = Tablet.getTablet("com.highfidelity.interface.tablet.system").toolbarMode;
|
||||
var visibleToOthers = Settings.getValue("tabletVisibleToOthers");
|
||||
|
||||
if (tabletShown && toolbarMode) {
|
||||
hideTabletUI();
|
||||
closeTabletUI();
|
||||
HMD.closeTablet();
|
||||
return;
|
||||
}
|
||||
|
@ -78,19 +165,48 @@
|
|||
tablet.updateAudioBar(currentMicLevel);
|
||||
}
|
||||
|
||||
if (tabletShown && UIWebTablet && Overlays.getOverlayType(UIWebTablet.webOverlayID) != "web3d") {
|
||||
// when we switch domains, the tablet entity gets destroyed and recreated. this causes
|
||||
// the overlay to be deleted, but not recreated. If the overlay is deleted for this or any
|
||||
// other reason, close the tablet.
|
||||
hideTabletUI();
|
||||
HMD.closeTablet();
|
||||
} else if (HMD.showTablet && !tabletShown && !toolbarMode) {
|
||||
UserActivityLogger.openedTablet(Settings.getValue("tabletVisibleToOthers"));
|
||||
if (validCheckTime - now > MSECS_PER_SEC) {
|
||||
validCheckTime = now;
|
||||
if (tabletRezzed && UIWebTablet && !tabletIsValid()) {
|
||||
// when we switch domains, the tablet entity gets destroyed and recreated. this causes
|
||||
// the overlay to be deleted, but not recreated. If the overlay is deleted for this or any
|
||||
// other reason, close the tablet.
|
||||
closeTabletUI();
|
||||
HMD.closeTablet();
|
||||
if (debugTablet) {
|
||||
print("TABLET autodestroying");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (HMD.showTablet && !tabletShown && !toolbarMode) {
|
||||
UserActivityLogger.openedTablet(visibleToOthers);
|
||||
showTabletUI();
|
||||
} else if (!HMD.showTablet && tabletShown) {
|
||||
UserActivityLogger.closedTablet();
|
||||
hideTabletUI();
|
||||
if (visibleToOthers) {
|
||||
closeTabletUI();
|
||||
} else {
|
||||
hideTabletUI();
|
||||
}
|
||||
}
|
||||
|
||||
// if the tablet is an overlay, attempt to pre-create it and then hide it so that when it's
|
||||
// summoned, it will appear quickly.
|
||||
if (!toolbarMode && !visibleToOthers) {
|
||||
if (now - preMakeTime > MSECS_PER_SEC) {
|
||||
preMakeTime = now;
|
||||
if (!tabletIsValid()) {
|
||||
closeTabletUI();
|
||||
rezTablet(false);
|
||||
tabletShown = false;
|
||||
} else if (!tabletShown) {
|
||||
hideTabletUI();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function toggleHand(channel, hand, senderUUID, localOnly) {
|
||||
|
|
|
@ -67,7 +67,6 @@
|
|||
}
|
||||
|
||||
function onWebEventReceived(event) {
|
||||
print("Script received a web event, its type is " + typeof event);
|
||||
if (typeof event === "string") {
|
||||
event = JSON.parse(event);
|
||||
}
|
||||
|
@ -115,6 +114,9 @@
|
|||
tablet.screenChanged.connect(onScreenChanged);
|
||||
|
||||
function cleanup() {
|
||||
if (onUsersScreen) {
|
||||
tablet.gotoHomeScreen();
|
||||
}
|
||||
button.clicked.disconnect(onClicked);
|
||||
tablet.removeButton(button);
|
||||
}
|
||||
|
|