3
0
Fork 0
mirror of https://github.com/JulianGro/overte.git synced 2025-04-30 09:02:57 +02:00

Merge branch 'master' into feature/handheld-marketplace

This commit is contained in:
Anthony J. Thibault 2016-08-24 16:07:04 -07:00
commit c2af948e25
78 changed files with 4971 additions and 1176 deletions
BUILD.mdCMakeLists.txt
cmake
interface
libraries
plugins/openvr/src
scripts

View file

@ -18,6 +18,7 @@
* [oglplus](http://oglplus.org/) ~> 0.63
* [OpenVR](https://github.com/ValveSoftware/openvr) ~> 0.91 (Win32 only)
* [Polyvox](http://www.volumesoffun.com/) ~> 0.2.1
* [QuaZip](http://sourceforge.net/projects/quazip/files/quazip/) ~> 0.7.1
* [SDL2](https://www.libsdl.org/download-2.0.php) ~> 2.0.3
* [soxr](http://soxr.sourceforge.net) ~> 0.1.1
* [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3

View file

@ -204,6 +204,7 @@ set_property(DIRECTORY PROPERTY EP_PREFIX ${EXTERNAL_PROJECT_PREFIX})
setup_externals_binary_dir()
option(USE_NSIGHT "Attempt to find the nSight libraries" 1)
option(GET_QUAZIP "Get QuaZip library automatically as external project" 1)
if (WIN32)

55
cmake/externals/quazip/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,55 @@
set(EXTERNAL_NAME quazip)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
cmake_policy(SET CMP0046 OLD)
include(ExternalProject)
if (WIN32)
# windows shell does not like backslashes expanded on the command line,
# so convert all backslashes in the QT path to forward slashes
string(REPLACE \\ / QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH})
elseif ($ENV{QT_CMAKE_PREFIX_PATH})
set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH})
endif ()
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://s3-us-west-1.amazonaws.com/hifi-production/dependencies/quazip-0.7.2.zip
URL_MD5 2955176048a31262c09259ca8d309d19
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=<INSTALL_DIR>/lib -DZLIB_ROOT=${ZLIB_ROOT} -DCMAKE_POSITION_INDEPENDENT_CODE=ON
LOG_DOWNLOAD 1
LOG_CONFIGURE 1
LOG_BUILD 1
)
add_dependencies(quazip zlib)
# Hide this external target (for ide users)
set_target_properties(${EXTERNAL_NAME} PROPERTIES
FOLDER "hidden/externals"
INSTALL_NAME_DIR ${INSTALL_DIR}/lib
BUILD_WITH_INSTALL_RPATH True)
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include CACHE PATH "List of QuaZip include directories")
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${${EXTERNAL_NAME_UPPER}_INCLUDE_DIR} CACHE PATH "List of QuaZip include directories")
set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/lib CACHE FILEPATH "Location of QuaZip DLL")
if (APPLE)
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5.1.0.0.dylib CACHE FILEPATH "Location of QuaZip release library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5d.1.0.0.dylib CACHE FILEPATH "Location of QuaZip release library")
elseif (WIN32)
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/quazip5.lib CACHE FILEPATH "Location of QuaZip release library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/quazip5d.lib CACHE FILEPATH "Location of QuaZip release library")
else ()
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5d.so CACHE FILEPATH "Location of QuaZip release library")
endif ()
include(SelectLibraryConfigurations)
select_library_configurations(${EXTERNAL_NAME_UPPER})
# Force selected libraries into the cache
set(${EXTERNAL_NAME_UPPER}_LIBRARY ${${EXTERNAL_NAME_UPPER}_LIBRARY} CACHE FILEPATH "Location of QuaZip libraries")
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Location of QuaZip libraries")

View file

@ -0,0 +1,16 @@
#
# Copyright 2015 High Fidelity, Inc.
# Created by Leonardo Murillo on 2015/11/20
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(TARGET_QUAZIP)
add_dependency_external_projects(quazip)
find_package(QuaZip REQUIRED)
target_include_directories(${TARGET_NAME} PUBLIC ${QUAZIP_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} ${QUAZIP_LIBRARIES})
if (WIN32)
add_paths_to_fixup_libs(${QUAZIP_DLL_PATH})
endif ()
endmacro()

View file

@ -0,0 +1,29 @@
#
# FindQuaZip.h
# StackManagerQt/cmake/modules
#
# Created by Mohammed Nafees.
# Copyright (c) 2014 High Fidelity. All rights reserved.
#
# QUAZIP_FOUND - QuaZip library was found
# QUAZIP_INCLUDE_DIR - Path to QuaZip include dir
# QUAZIP_INCLUDE_DIRS - Path to QuaZip and zlib include dir (combined from QUAZIP_INCLUDE_DIR + ZLIB_INCLUDE_DIR)
# QUAZIP_LIBRARIES - List of QuaZip libraries
# QUAZIP_ZLIB_INCLUDE_DIR - The include dir of zlib headers
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
hifi_library_search_hints("quazip")
if (WIN32)
find_path(QUAZIP_INCLUDE_DIRS quazip.h PATH_SUFFIXES include/quazip HINTS ${QUAZIP_SEARCH_DIRS})
elseif (APPLE)
find_path(QUAZIP_INCLUDE_DIRS quazip.h PATH_SUFFIXES include/quazip HINTS ${QUAZIP_SEARCH_DIRS})
else ()
find_path(QUAZIP_INCLUDE_DIRS quazip.h PATH_SUFFIXES quazip HINTS ${QUAZIP_SEARCH_DIRS})
endif ()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(QUAZIP DEFAULT_MSG QUAZIP_INCLUDE_DIRS)
mark_as_advanced(QUAZIP_INCLUDE_DIRS QUAZIP_SEARCH_DIRS)

View file

@ -0,0 +1,42 @@
<?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 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<g>
<path d="M25.9,20.6c0.29,0.15,0.47,0.38,0.48,0.72c0,0.7,0.1,2.92,0.08,3.62c1,0.3,3.61,1.19,4.56,1.45
c0.15,0.01,0.27,0.03,0.38,0.09c0.2,0.1,0.33,0.3,0.36,0.58c0.01,0.11,0.02,0.22,0.02,0.33c-0.03,1.5,0.01,1.08-0.05,2.58
c-0.06,1.55-0.78,2.72-2.21,3.34c-1.12,0.49-2.01,0.57-2.92,0.1c-0.25-0.13-0.5-0.3-0.76-0.51c-1.46-1.21-2.95-2.39-4.42-3.59
c-0.37-0.3-0.48-0.75-0.29-1.15c0.19-0.39,0.63-0.61,1.05-0.49c0.06,0.02,0.12,0.04,0.18,0.07c0.1,0.05,0.19,0.11,0.27,0.18
c0.64,0.51,1,1.02,1.63,1.53c0,0,0.01,0,0.01,0.01c0.01,0.01,0.04,0.01,0.09,0.04c0-0.12,0.01-0.23,0.01-0.33
c0.06-2.53,0.12-5.06,0.18-7.59c0.01-0.36,0.06-0.69,0.37-0.92c0.28-0.2,0.58-0.25,0.89-0.12C25.85,20.57,25.88,20.58,25.9,20.6
M26.64,19.16c-0.06-0.03-0.12-0.06-0.18-0.09c-0.83-0.36-1.74-0.25-2.48,0.3c-1,0.73-1.03,1.83-1.04,2.19
c-0.04,1.54-0.07,3.11-0.11,4.64c-0.07-0.02-0.13-0.05-0.2-0.07c-1.17-0.34-2.41,0.22-2.96,1.33c-0.26,0.53-0.32,1.14-0.18,1.71
c0.14,0.55,0.45,1.03,0.91,1.4c0.49,0.4,0.98,0.8,1.46,1.18c0.97,0.78,1.97,1.59,2.94,2.4c0.35,0.29,0.7,0.52,1.05,0.71
c1.72,0.88,3.28,0.39,4.3-0.06c1.96-0.86,3.09-2.55,3.18-4.76c0.03-0.89,0.04-1.13,0.04-1.47c0-0.23,0-0.51,0.01-1.13
c0-0.18,0-0.37-0.03-0.56c-0.1-0.82-0.54-1.49-1.23-1.84c-0.25-0.13-0.53-0.21-0.82-0.25c-0.56-0.16-1.57-0.49-2.48-0.79
c-0.27-0.09-0.53-0.17-0.78-0.25c-0.01-0.34-0.02-0.7-0.03-1.06C28.02,22.12,28,21.58,28,21.31
C27.99,20.39,27.49,19.59,26.64,19.16L26.64,19.16z"/>
</g>
<path d="M33.4,17.76l-2.87-2.64l-0.13,1.65c-1.42-0.61-3.13-0.95-4.95-0.95c-1.91,0-3.66,0.37-5.06,1.04l-0.23-1.76l-2.73,2.79
l3.35,2l-0.22-1.66c1.27-0.71,3.01-1.11,4.89-1.11c1.8,0,3.52,0.37,4.84,1.03l-0.14,1.79L33.4,17.76z"/>
<g>
<path class="st0" d="M25.64,19.86c0.29,0.15,0.47,0.38,0.48,0.72c0,0.7,0.1,2.92,0.08,3.62c1,0.3,3.61,1.19,4.56,1.45
c0.16,0.04,0.28,0.08,0.39,0.13c0.2,0.1,0.31,0.26,0.35,0.54c0.01,0.11,0.02,0.22,0.02,0.33c-0.03,1.5,0.01,1.08-0.05,2.58
c-0.06,1.55-0.78,2.72-2.21,3.34c-1.12,0.49-2.01,0.57-2.92,0.1c-0.25-0.13-0.5-0.3-0.76-0.51c-1.46-1.21-2.95-2.39-4.42-3.59
c-0.37-0.3-0.48-0.75-0.29-1.15c0.19-0.39,0.63-0.61,1.05-0.49c0.06,0.02,0.12,0.04,0.18,0.07c0.1,0.05,0.19,0.11,0.27,0.18
c0.64,0.51,1,1.02,1.63,1.53c0,0,0.01,0,0.01,0.01c0.01,0.01,0.04,0.01,0.09,0.04c0-0.12,0.01-0.23,0.01-0.33
c0.06-2.53,0.12-5.06,0.18-7.59c0.01-0.36,0.06-0.69,0.37-0.92c0.28-0.2,0.58-0.25,0.89-0.12C25.59,19.83,25.62,19.84,25.64,19.86
M26.38,18.42c-0.06-0.03-0.12-0.06-0.18-0.09c-0.83-0.36-1.74-0.25-2.48,0.3c-1,0.73-1.03,1.83-1.04,2.19
c-0.04,1.54-0.07,3.11-0.11,4.64c-0.07-0.02-0.13-0.05-0.2-0.07c-1.17-0.34-2.41,0.22-2.96,1.33c-0.26,0.53-0.32,1.14-0.18,1.71
c0.14,0.55,0.45,1.03,0.91,1.4c0.49,0.4,0.98,0.8,1.46,1.18c0.97,0.78,1.97,1.59,2.94,2.4c0.35,0.29,0.7,0.52,1.05,0.71
c1.72,0.88,3.28,0.39,4.3-0.06c1.96-0.86,3.09-2.55,3.18-4.76c0.03-0.89,0.04-1.13,0.04-1.47c0-0.23,0-0.51,0.01-1.13
c0-0.18,0-0.37-0.03-0.56c-0.1-0.82-0.45-1.41-1.13-1.76c-0.25-0.13-0.61-0.24-0.91-0.32c-0.56-0.16-1.57-0.49-2.48-0.79
c-0.27-0.09-0.53-0.17-0.78-0.25c-0.01-0.34-0.02-0.7-0.03-1.06c-0.02-0.57-0.03-1.11-0.04-1.38
C27.73,19.65,27.23,18.85,26.38,18.42L26.38,18.42z"/>
</g>
<path class="st0" d="M33.14,17.02l-2.87-2.64l-0.13,1.65c-1.42-0.61-3.13-0.95-4.95-0.95c-1.91,0-3.66,0.37-5.06,1.04l-0.23-1.76
l-2.73,2.79l3.35,2l-0.22-1.66c1.27-0.71,3.01-1.11,4.89-1.11c1.8,0,3.52,0.37,4.84,1.03l-0.14,1.79L33.14,17.02z"/>
</svg>

After

(image error) Size: 3.7 KiB

View file

@ -1,81 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1440"
height="200"
data-icon="map-marker"
data-container-transform="translate(24)"
viewBox="0 0 1440 200"
id="svg4136"
inkscape:version="0.91 r13725"
sodipodi:docname="address-bar.svg">
<metadata
id="metadata4144">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4142" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1536"
inkscape:window-height="687"
id="namedview4140"
showgrid="false"
inkscape:zoom="0.61319416"
inkscape:cx="670.06567"
inkscape:cy="52.468468"
inkscape:window-x="105"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg4136" />
<rect
style="fill:#ededed;fill-opacity:1;stroke:none;stroke-linejoin:round;stroke-opacity:1"
id="rect4141"
width="1280"
height="140"
x="160"
y="30"
rx="16.025024"
ry="17.019567" />
<rect
style="fill:#dadada;fill-opacity:1;stroke:#cbcbcb;stroke-width:0.35830048;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
id="rect4135"
width="328.72031"
height="139.64169"
x="150.33546"
y="30.179144"
rx="18.876532"
ry="20.609974" />
<circle
style="fill:#b8b8b8;fill-opacity:1;stroke:none;stroke-opacity:1"
id="path4146"
cx="100"
cy="100"
r="100" />
<path
d="m 100,36.000005 c -22.1,0 -40,17.9 -40,39.999995 0,30 40,88 40,88 0,0 40,-58 40,-88 0,-22.099995 -17.9,-39.999995 -40,-39.999995 z m 0,22 c 9.9,0 18,8.099995 18,17.999995 0,9.9 -8.1,18 -18,18 -9.9,0 -18,-8.1 -18,-18 0,-9.9 8.1,-17.999995 18,-17.999995 z"
id="path4138"
inkscape:connector-curvature="0" />
<?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="svg4136" inkscape:version="0.91 r13725" sodipodi:docname="address-bar.svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1440 200"
style="enable-background:new 0 0 1440 200;" xml:space="preserve">
<style type="text/css">
.st0{fill:#1E1E1E;}
.st1{fill:#E6E7E8;}
.st2{fill:#FFFFFF;}
</style>
<path class="st0" d="M1428.61,172H11.46c-6.27,0-11.39-5.13-11.39-11.39V49.58c0-6.27,5.13-11.39,11.39-11.39h1417.15
c6.27,0,11.39,5.13,11.39,11.39v111.03C1440,166.87,1434.87,172,1428.61,172z"/>
<path class="st1" d="M1428.61,165.81H11.46c-6.27,0-11.39-5.13-11.39-11.39V43.39c0-6.27,5.13-11.39,11.39-11.39h1417.15
c6.27,0,11.39,5.13,11.39,11.39v111.03C1440,160.68,1434.87,165.81,1428.61,165.81z"/>
<path class="st2" d="M1133.24,165.81H417.95c-4.47,0-8.12-3.65-8.12-8.12V40.11c0-4.47,3.65-8.12,8.12-8.12h715.28
c4.47,0,8.12,3.65,8.12,8.12v117.57C1141.36,162.15,1137.7,165.81,1133.24,165.81z"/>
</svg>

Before

(image error) Size: 2.5 KiB

After

(image error) Size: 1.4 KiB

View file

@ -0,0 +1,28 @@
<?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" 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{fill:#414042;}
.st1{fill:#CCCCCC;}
.st2{fill:#1398BB;}
.st3{fill:#31D8FF;}
</style>
<g id="Layer_1">
<path class="st0" d="M33.72,85.08l-9.15-9.15l-0.74-0.74l0.74-0.74l9.35-9.35c0.59-0.59,0.59-1.56,0-2.15
c-0.29-0.29-0.67-0.45-1.08-0.45c-0.41,0-0.79,0.16-1.08,0.45L19.52,75.19l12.04,12.04c0.29,0.29,0.67,0.45,1.08,0.45
c0.41,0,0.79-0.16,1.08-0.45C34.31,86.64,34.31,85.67,33.72,85.08z"/>
<path class="st1" d="M33.72,33.45l-9.15-9.15l-0.74-0.74l0.74-0.74l9.35-9.35c0.59-0.59,0.59-1.56,0-2.15
c-0.29-0.29-0.67-0.45-1.08-0.45c-0.41,0-0.79,0.16-1.08,0.45L19.52,23.56L31.56,35.6c0.29,0.29,0.67,0.45,1.08,0.45
c0.41,0,0.79-0.16,1.08-0.45C34.31,35.01,34.31,34.04,33.72,33.45z"/>
<path class="st2" d="M17.99,124.82l12.78,12.78c1,1,2.63,1,3.63,0c1-1,1-2.63,0-3.63l-9.15-9.15l9.35-9.35c1-1,1-2.63,0-3.63
c-1-1-2.63-1-3.63,0L17.99,124.82z"/>
<path class="st3" d="M32.79,112.13c0.41,0,0.79,0.16,1.08,0.45c0.59,0.59,0.59,1.56,0,2.15l-9.35,9.35l-0.74,0.74l0.74,0.74
l9.15,9.15c0.59,0.59,0.59,1.56,0,2.15c-0.29,0.29-0.67,0.45-1.08,0.45c-0.41,0-0.79-0.16-1.08-0.45l-12.04-12.04l12.24-12.24
C32,112.29,32.38,112.13,32.79,112.13 M32.79,111.08c-0.66,0-1.31,0.25-1.82,0.75l-12.98,12.98l12.78,12.78
c0.5,0.5,1.16,0.75,1.82,0.75c0.66,0,1.31-0.25,1.82-0.75c1-1,1-2.63,0-3.63l-9.15-9.15l9.35-9.35c1-1,1-2.63,0-3.63
C34.1,111.34,33.44,111.08,32.79,111.08L32.79,111.08z"/>
</g>
<g id="Layer_2">
</g>
</svg>

After

(image error) Size: 1.7 KiB

View file

@ -0,0 +1,28 @@
<?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" 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{fill:#414042;}
.st1{fill:#CCCCCC;}
.st2{fill:#1398BB;}
.st3{fill:#31D8FF;}
</style>
<g id="Layer_1">
<path class="st0" d="M21.12,62.95c-0.29-0.29-0.67-0.45-1.08-0.45c-0.41,0-0.79,0.16-1.08,0.45c-0.59,0.59-0.59,1.56,0,2.15
l9.35,9.35l0.74,0.74l-0.74,0.74l-9.15,9.15c-0.59,0.59-0.59,1.56,0,2.15c0.29,0.29,0.67,0.45,1.08,0.45
c0.41,0,0.79-0.16,1.08-0.45l12.04-12.04L21.12,62.95z"/>
<path class="st1" d="M21.12,11.32c-0.29-0.29-0.67-0.45-1.08-0.45c-0.41,0-0.79,0.16-1.08,0.45c-0.59,0.59-0.59,1.56,0,2.15
l9.35,9.35l0.74,0.74l-0.74,0.74l-9.15,9.15c-0.59,0.59-0.59,1.56,0,2.15c0.29,0.29,0.67,0.45,1.08,0.45
c0.41,0,0.79-0.16,1.08-0.45l12.04-12.04L21.12,11.32z"/>
<path class="st2" d="M34.9,124.82L22.11,137.6c-1,1-2.63,1-3.63,0c-1-1-1-2.63,0-3.63l9.15-9.15l-9.35-9.35c-1-1-1-2.63,0-3.63
c1-1,2.63-1,3.63,0L34.9,124.82z"/>
<path class="st3" d="M20.1,112.13c0.41,0,0.79,0.16,1.08,0.45l12.24,12.24l-12.04,12.04c-0.29,0.29-0.67,0.45-1.08,0.45
c-0.41,0-0.79-0.16-1.08-0.45c-0.59-0.59-0.59-1.56,0-2.15l9.15-9.15l0.74-0.74l-0.74-0.74l-9.35-9.35c-0.59-0.59-0.59-1.56,0-2.15
C19.31,112.29,19.69,112.13,20.1,112.13 M20.1,111.08c-0.66,0-1.31,0.25-1.82,0.75c-1,1-1,2.63,0,3.63l9.35,9.35l-9.15,9.15
c-1,1-1,2.63,0,3.63c0.5,0.5,1.16,0.75,1.82,0.75s1.31-0.25,1.82-0.75l12.78-12.78l-12.98-12.98
C21.41,111.34,20.76,111.08,20.1,111.08L20.1,111.08z"/>
</g>
<g id="Layer_2">
</g>
</svg>

After

(image error) Size: 1.7 KiB

View file

@ -0,0 +1,50 @@
<?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" 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{fill:#414042;}
.st1{fill:#CCCCCC;}
.st2{fill:#1398BB;}
.st3{fill:#31D8FF;}
</style>
<g id="Layer_1">
<g>
<path class="st0" d="M36.75,71.26c-0.05-0.31-0.22-0.57-0.47-0.76l-10.72-7.73l-8.21,5.71l0,0l0,0l-2.98,1.99
c-0.26,0.17-0.43,0.43-0.5,0.74c-0.06,0.3,0,0.61,0.17,0.87c0.22,0.32,0.58,0.52,0.97,0.52c0.23,0,0.45-0.07,0.64-0.19l2.99-1.99
l6.62-4.61l0.28-0.2l0.28,0.2l9.11,6.57c0.2,0.14,0.43,0.22,0.68,0.22c0.37,0,0.73-0.18,0.94-0.48
C36.73,71.88,36.8,71.57,36.75,71.26z"/>
<path class="st0" d="M23.59,79.62c0-1.13,0.97-2.03,2.1-2.03c1.13,0,2.1,0.93,2.1,2.06v6.06h7.58v-8.97l-3.28-2.41l-6.46-4.68
l-6.88,4.64l-3.23,2.1v9.32h8.07V79.62z"/>
</g>
<g>
<path class="st1" d="M36.75,19.64c-0.05-0.31-0.22-0.57-0.47-0.76l-10.72-7.73l-8.21,5.71l0,0l0,0l-2.98,1.99
c-0.26,0.17-0.43,0.43-0.5,0.74c-0.06,0.3,0,0.61,0.17,0.87c0.22,0.32,0.58,0.52,0.97,0.52c0.23,0,0.45-0.07,0.64-0.19l2.99-1.99
l6.62-4.61l0.28-0.2l0.28,0.2l9.11,6.57c0.2,0.14,0.43,0.22,0.68,0.22c0.37,0,0.73-0.18,0.94-0.48
C36.73,20.25,36.8,19.94,36.75,19.64z"/>
<path class="st1" d="M23.59,27.99c0-1.13,0.97-2.03,2.1-2.03c1.13,0,2.1,0.93,2.1,2.06v6.06h7.58v-8.97l-3.28-2.41l-6.46-4.68
l-6.88,4.64l-3.23,2.1v9.32h8.07V27.99z"/>
</g>
<g>
<path class="st2" d="M15,122.61c-0.53,0-1.05-0.26-1.37-0.73c-0.5-0.76-0.3-1.78,0.46-2.28l2.98-1.99l8.5-5.91l11,7.93
c0.74,0.53,0.9,1.56,0.37,2.3c-0.53,0.74-1.56,0.9-2.3,0.37l-9.11-6.57l-6.63,4.61l-3,1.99C15.63,122.52,15.31,122.61,15,122.61z"
/>
<path class="st2" d="M35.6,122.69c-0.36,0-0.71-0.11-1.01-0.33l-9.07-6.53l-6.58,4.58l-3,2c-0.28,0.19-0.61,0.29-0.95,0.29
c-0.58,0-1.12-0.29-1.44-0.77c-0.53-0.79-0.31-1.87,0.48-2.39l2.98-1.99l8.54-5.94l11.05,7.96c0.37,0.27,0.62,0.67,0.69,1.12
c0.07,0.46-0.03,0.91-0.3,1.29c-0.27,0.37-0.67,0.62-1.12,0.69C35.79,122.68,35.7,122.69,35.6,122.69z M25.53,115.63l9.16,6.6
c0.34,0.24,0.75,0.34,1.17,0.28s0.77-0.29,1.02-0.63c0.24-0.34,0.34-0.75,0.28-1.17c-0.07-0.41-0.29-0.77-0.63-1.02l-10.96-7.9
l-8.45,5.88l-2.98,1.99c-0.72,0.48-0.91,1.45-0.44,2.17c0.29,0.44,0.78,0.7,1.3,0.7c0.31,0,0.61-0.09,0.87-0.26l3-1.99
L25.53,115.63z"/>
</g>
<path class="st3" d="M36.62,119.56l-11.05-7.96l-8.54,5.94l-2.98,1.99c-0.79,0.53-1.01,1.6-0.48,2.39
c0.32,0.48,0.86,0.77,1.44,0.77c0.34,0,0.67-0.1,0.95-0.29l3-2l6.58-4.58l9.07,6.53c0.3,0.21,0.64,0.33,1.01,0.33
c0.55,0,1.08-0.27,1.4-0.72C37.56,121.2,37.39,120.12,36.62,119.56z M17.39,118.07l8.17-5.68l10.68,7.7
c0.23,0.17,0.39,0.42,0.43,0.7c0.05,0.28-0.02,0.57-0.19,0.8c-0.2,0.28-0.53,0.45-0.88,0.45c-0.23,0-0.45-0.07-0.63-0.2l-9.44-6.8
l-6.95,4.83l-2.99,1.99c-0.18,0.12-0.38,0.18-0.6,0.18c-0.36,0-0.7-0.18-0.9-0.48c-0.16-0.24-0.22-0.53-0.16-0.81
c0.06-0.28,0.22-0.53,0.46-0.69L17.39,118.07z"/>
<path class="st2" d="M23.59,129.14c0-1.13,0.97-2.03,2.1-2.03c1.13,0,2.1,0.93,2.1,2.06v6.06h7.58v-8.97l-3.28-2.41l-6.46-4.68
l-6.88,4.64l-3.23,2.1v9.32h8.07V129.14z"/>
</g>
<g id="Layer_2">
</g>
</svg>

After

(image error) Size: 3.2 KiB

View file

@ -0,0 +1,33 @@
<?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" 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{fill:#414042;}
.st1{fill:#CCCCCC;}
.st2{fill:#1398BB;}
.st3{fill:#31D8FF;}
</style>
<g id="Layer_1">
<path class="st0" d="M25.71,59.91c-4.83,0-8.75,3.92-8.75,8.75c0,4.83,8.75,16.5,8.75,16.5s8.75-11.67,8.75-16.5
C34.46,63.83,30.54,59.91,25.71,59.91z M25.71,72.53c-2.48,0-4.5-2.01-4.5-4.5c0-2.48,2.01-4.5,4.5-4.5s4.5,2.01,4.5,4.5
C30.2,70.52,28.19,72.53,25.71,72.53z"/>
<path class="st0" d="M36.43,86.1H14.28c-0.49,0-0.9,0.39-0.9,0.89c0,0.49,0.4,0.89,0.9,0.89h22.15c0.49,0,0.9-0.39,0.9-0.89
C37.32,86.49,36.92,86.1,36.43,86.1z"/>
<path class="st1" d="M25.71,8.28c-4.83,0-8.75,3.92-8.75,8.75c0,4.83,8.75,16.5,8.75,16.5s8.75-11.67,8.75-16.5
C34.46,12.2,30.54,8.28,25.71,8.28z M25.71,20.91c-2.48,0-4.5-2.01-4.5-4.5c0-2.48,2.01-4.5,4.5-4.5s4.5,2.01,4.5,4.5
C30.2,18.89,28.19,20.91,25.71,20.91z"/>
<path class="st1" d="M36.43,34.47H14.28c-0.49,0-0.9,0.39-0.9,0.89s0.4,0.89,0.9,0.89h22.15c0.49,0,0.9-0.39,0.9-0.89
S36.92,34.47,36.43,34.47z"/>
<path class="st2" d="M25.71,109.66c-4.83,0-8.75,3.92-8.75,8.75c0,4.83,8.75,16.5,8.75,16.5s8.75-11.67,8.75-16.5
C34.46,113.57,30.54,109.66,25.71,109.66z M25.71,122.28c-2.48,0-4.5-2.01-4.5-4.5c0-2.48,2.01-4.5,4.5-4.5s4.5,2.01,4.5,4.5
C30.2,120.27,28.19,122.28,25.71,122.28z"/>
<path class="st2" d="M36.43,138.33H14.28c-0.85,0-1.54-0.69-1.54-1.54s0.69-1.54,1.54-1.54h22.15c0.85,0,1.54,0.69,1.54,1.54
S37.28,138.33,36.43,138.33z"/>
<path class="st3" d="M36.43,135.89c0.49,0,0.9,0.4,0.9,0.9c0,0.49-0.4,0.9-0.9,0.9H14.28c-0.49,0-0.9-0.4-0.9-0.9
c0-0.49,0.4-0.9,0.9-0.9H36.43 M36.43,135.25H14.28c-0.85,0-1.54,0.69-1.54,1.54c0,0.85,0.69,1.54,1.54,1.54h22.15
c0.85,0,1.54-0.69,1.54-1.54C37.97,135.94,37.28,135.25,36.43,135.25L36.43,135.25z"/>
</g>
<g id="Layer_2">
</g>
</svg>

After

(image error) Size: 2 KiB

View file

@ -0,0 +1,41 @@
<?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" 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{fill:#414042;}
.st1{fill:#CCCCCC;}
.st2{fill:#1398BB;}
.st3{fill:#31D8FF;}
</style>
<g id="Layer_1">
<circle class="st0" cx="26.54" cy="69.8" r="4.44"/>
<path class="st0" d="M34.87,82.89c0.01-0.01,0.02-0.02,0.03-0.03v-1.86c0-2.68-2.33-4.77-5-4.77h-6.42c-2.68,0-4.85,2.09-4.85,4.77
v1.88H34.87z"/>
<path class="st0" d="M44.17,67.05c0-3.97-3.22-7.19-7.19-7.19H16.67c-3.97,0-7.19,3.22-7.19,7.19v14.18c0,3.97,3.22,7.19,7.19,7.19
h20.31c3.97,0,7.19-3.22,7.19-7.19V67.05z M42.39,81.32c0,3.03-2.46,5.49-5.49,5.49H16.58c-3.03,0-5.49-2.46-5.49-5.49v-14.2
c0-3.03,2.46-5.49,5.49-5.49h20.33c3.03,0,5.49,2.46,5.49,5.49V81.32z"/>
<circle class="st1" cx="26.54" cy="18.17" r="4.44"/>
<path class="st1" d="M34.87,31.26c0.01-0.01,0.02-0.02,0.03-0.03v-1.86c0-2.68-2.33-4.77-5-4.77h-6.42c-2.68,0-4.85,2.09-4.85,4.77
v1.88H34.87z"/>
<path class="st1" d="M44.17,15.42c0-3.97-3.22-7.19-7.19-7.19H16.67c-3.97,0-7.19,3.22-7.19,7.19V29.6c0,3.97,3.22,7.19,7.19,7.19
h20.31c3.97,0,7.19-3.22,7.19-7.19V15.42z M42.39,29.69c0,3.03-2.46,5.49-5.49,5.49H16.58c-3.03,0-5.49-2.46-5.49-5.49V15.5
c0-3.03,2.46-5.49,5.49-5.49h20.33c3.03,0,5.49,2.46,5.49,5.49V29.69z"/>
<circle class="st2" cx="26.52" cy="119.45" r="4.44"/>
<path class="st2" d="M34.85,132.54c0.01-0.01,0.02-0.02,0.03-0.03v-1.86c0-2.68-2.33-4.77-5-4.77h-6.42
c-2.68,0-4.85,2.09-4.85,4.77v1.88H34.85z"/>
<g>
<path class="st2" d="M36.9,138.76H16.6c-4.32,0-7.83-3.51-7.83-7.83v-14.16c0-4.32,3.51-7.83,7.83-7.83h20.3
c4.32,0,7.83,3.51,7.83,7.83v14.16C44.73,135.25,41.22,138.76,36.9,138.76z M16.6,111.93c-2.67,0-4.84,2.17-4.84,4.84v14.16
c0,2.67,2.17,4.84,4.84,4.84h20.3c2.67,0,4.84-2.17,4.84-4.84v-14.16c0-2.67-2.17-4.84-4.84-4.84H16.6z"/>
<path class="st3" d="M36.9,109.58c3.96,0,7.19,3.22,7.19,7.19v14.16c0,3.96-3.22,7.19-7.19,7.19H16.6c-3.96,0-7.19-3.22-7.19-7.19
v-14.16c0-3.96,3.22-7.19,7.19-7.19H36.9 M16.6,136.42h20.3c3.02,0,5.49-2.46,5.49-5.49v-14.16c0-3.02-2.46-5.49-5.49-5.49H16.6
c-3.02,0-5.49,2.46-5.49,5.49v14.16C11.11,133.95,13.57,136.42,16.6,136.42 M36.9,108.93H16.6c-4.32,0-7.83,3.51-7.83,7.83v14.16
c0,4.32,3.51,7.83,7.83,7.83h20.3c4.32,0,7.83-3.51,7.83-7.83v-14.16C44.73,112.45,41.22,108.93,36.9,108.93L36.9,108.93z
M16.6,135.77c-2.67,0-4.84-2.17-4.84-4.84v-14.16c0-2.67,2.17-4.84,4.84-4.84h20.3c2.67,0,4.84,2.17,4.84,4.84v14.16
c0,2.67-2.17,4.84-4.84,4.84H16.6L16.6,135.77z"/>
</g>
</g>
<g id="Layer_2">
</g>
</svg>

After

(image error) Size: 2.7 KiB

View file

@ -14,6 +14,8 @@ import "controls"
import "styles"
import "windows"
import "hifi"
import "hifi/toolbars"
import "controls-uit" as HifiControls
Window {
id: root
@ -45,50 +47,80 @@ Window {
anchors.centerIn = parent;
}
function resetAfterTeleport() {
storyCardFrame.shown = root.shown = false;
}
function goCard(card) {
addressLine.text = card.userStory.name;
if (addressBarDialog.useFeed) {
storyCardHTML.url = addressBarDialog.metaverseServerUrl + "/user_stories/" + card.storyId;
storyCardFrame.shown = true;
return;
}
addressLine.text = card.hifiUrl;
toggleOrGo(true);
}
property var allDomains: [];
property var suggestionChoices: [];
property var domainsBaseUrl: null;
property var allPlaces: [];
property var allStories: [];
property int cardWidth: 200;
property int cardHeight: 152;
property string metaverseBase: addressBarDialog.metaverseServerUrl + "/api/v1/";
AddressBarDialog {
id: addressBarDialog
implicitWidth: backgroundImage.width
implicitHeight: backgroundImage.height
// The buttons have their button state changed on hover, so we have to manually fix them up here
onBackEnabledChanged: backArrow.buttonState = addressBarDialog.backEnabled ? 1 : 0;
onForwardEnabledChanged: forwardArrow.buttonState = addressBarDialog.forwardEnabled ? 1 : 0;
onUseFeedChanged: updateFeedState();
onReceivedHifiSchemeURL: resetAfterTeleport();
Row {
ListModel { id: suggestions }
ListView {
id: scroll
width: backgroundImage.width;
height: cardHeight;
spacing: hifi.layout.spacing;
clip: true;
anchors {
bottom: backgroundImage.top;
bottomMargin: 2 * hifi.layout.spacing;
right: backgroundImage.right;
rightMargin: -104; // FIXME
horizontalCenter: backgroundImage.horizontalCenter
}
spacing: hifi.layout.spacing;
Card {
id: s0;
model: suggestions;
orientation: ListView.Horizontal;
delegate: Card {
width: cardWidth;
height: cardHeight;
goFunction: goCard
goFunction: goCard;
userName: model.username;
placeName: model.place_name;
hifiUrl: model.place_name + model.path;
imageUrl: model.image_url;
thumbnail: model.thumbnail_url;
action: model.action;
timestamp: model.created_at;
onlineUsers: model.online_users;
storyId: model.metaverseId;
hoverThunk: function () { ListView.view.currentIndex = index; }
unhoverThunk: function () { ListView.view.currentIndex = -1; }
}
Card {
id: s1;
width: cardWidth;
height: cardHeight;
goFunction: goCard
}
Card {
id: s2;
width: cardWidth;
height: cardHeight;
goFunction: goCard
highlightMoveDuration: -1;
highlightMoveVelocity: -1;
highlight: Rectangle { color: "transparent"; border.width: 4; border.color: "#1DB5ED"; z: 1; }
leftMargin: 50; // Start the first item over by about the same amount as the last item peeks through on the other side.
rightMargin: 50;
}
Image { // Just a visual indicator that the user can swipe the cards over to see more.
source: "../images/Swipe-Icon-single.svg"
width: 50;
visible: suggestions.count > 3;
anchors {
right: scroll.right;
verticalCenter: scroll.verticalCenter;
}
}
Image {
id: backgroundImage
source: "../images/address-bar.svg"
@ -97,64 +129,43 @@ Window {
property int inputAreaHeight: 56.0 * root.scale // Height of the background's input area
property int inputAreaStep: (height - inputAreaHeight) / 2
Image {
ToolbarButton {
id: homeButton
source: "../images/home-button.svg"
width: 29
height: 26
imageURL: "../images/home.svg"
buttonState: 1
defaultState: 1
hoverState: 2
onClicked: addressBarDialog.loadHome();
anchors {
left: parent.left
leftMargin: parent.height + 2 * hifi.layout.spacing
leftMargin: homeButton.width / 2
verticalCenter: parent.verticalCenter
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onClicked: {
addressBarDialog.loadHome()
}
}
}
Image {
id: backArrow
source: addressBarDialog.backEnabled ? "../images/left-arrow.svg" : "../images/left-arrow-disabled.svg"
width: 22
height: 26
ToolbarButton {
id: backArrow;
imageURL: "../images/backward.svg";
hoverState: addressBarDialog.backEnabled ? 2 : 0;
defaultState: addressBarDialog.backEnabled ? 1 : 0;
buttonState: addressBarDialog.backEnabled ? 1 : 0;
onClicked: addressBarDialog.loadBack();
anchors {
left: homeButton.right
leftMargin: 2 * hifi.layout.spacing
verticalCenter: parent.verticalCenter
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onClicked: {
addressBarDialog.loadBack()
}
}
}
Image {
id: forwardArrow
source: addressBarDialog.forwardEnabled ? "../images/right-arrow.svg" : "../images/right-arrow-disabled.svg"
width: 22
height: 26
ToolbarButton {
id: forwardArrow;
imageURL: "../images/forward.svg";
hoverState: addressBarDialog.forwardEnabled ? 2 : 0;
defaultState: addressBarDialog.forwardEnabled ? 1 : 0;
buttonState: addressBarDialog.forwardEnabled ? 1 : 0;
onClicked: addressBarDialog.loadForward();
anchors {
left: backArrow.right
leftMargin: 2 * hifi.layout.spacing
verticalCenter: parent.verticalCenter
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onClicked: {
addressBarDialog.loadForward()
}
}
}
// FIXME replace with TextField
@ -162,20 +173,80 @@ Window {
id: addressLine
focus: true
anchors {
fill: parent
leftMargin: parent.height + parent.height + hifi.layout.spacing * 7
rightMargin: hifi.layout.spacing * 2
top: parent.top
bottom: parent.bottom
left: forwardArrow.right
right: placesButton.left
leftMargin: forwardArrow.width
rightMargin: placesButton.width
topMargin: parent.inputAreaStep + hifi.layout.spacing
bottomMargin: parent.inputAreaStep + hifi.layout.spacing
}
font.pixelSize: hifi.fonts.pixelSize * root.scale * 0.75
helperText: "Go to: place, @user, /path, network address"
helperPixelSize: font.pixelSize * 0.75
helperItalic: true
onTextChanged: filterChoicesByText()
}
// These two are radio buttons.
ToolbarButton {
id: placesButton
imageURL: "../images/places.svg"
buttonState: 1
defaultState: addressBarDialog.useFeed ? 0 : 1;
hoverState: addressBarDialog.useFeed ? 2 : -1;
onClicked: addressBarDialog.useFeed ? toggleFeed() : identity()
anchors {
right: feedButton.left;
bottom: addressLine.bottom;
}
}
ToolbarButton {
id: feedButton;
imageURL: "../images/snap-feed.svg";
buttonState: 0
defaultState: addressBarDialog.useFeed ? 1 : 0;
hoverState: addressBarDialog.useFeed ? -1 : 2;
onClicked: addressBarDialog.useFeed ? identity() : toggleFeed();
anchors {
right: parent.right;
bottom: addressLine.bottom;
rightMargin: feedButton.width / 2
}
}
}
Window {
width: 938;
height: 625;
scale: 0.8 // Reset scale of Window to 1.0 (counteract address bar's scale value of 1.25)
HifiControls.WebView {
anchors.fill: parent;
id: storyCardHTML;
}
id: storyCardFrame;
shown: false;
destroyOnCloseButton: false;
pinnable: false;
anchors {
verticalCenter: backgroundImage.verticalCenter;
horizontalCenter: scroll.horizontalCenter;
}
}
}
function toggleFeed() {
addressBarDialog.useFeed = !addressBarDialog.useFeed;
updateFeedState();
}
function updateFeedState() {
placesButton.buttonState = addressBarDialog.useFeed ? 0 : 1;
feedButton.buttonState = addressBarDialog.useFeed ? 1 : 0;
filterChoicesByText();
}
function getRequest(url, cb) { // cb(error, responseOfCorrectContentType) of url. General for 'get' text/html/json, but without redirects.
// TODO: make available to other .qml.
var request = new XMLHttpRequest();
@ -200,133 +271,217 @@ Window {
request.open("GET", url, true);
request.send();
}
// call iterator(element, icb) once for each element of array, and then cb(error) when icb(error) has been called by each iterator.
// short-circuits if error. Note that iterator MUST be an asynchronous function. (Use setTimeout if necessary.)
function asyncEach(array, iterator, cb) {
var count = array.length;
function icb(error) {
if (!--count || error) {
count = -1; // don't cb multiple times (e.g., if error)
cb(error);
}
}
function asyncMap(array, iterator, cb) {
// call iterator(element, icb) once for each element of array, and then cb(error, mappedResult)
// when icb(error, mappedElement) has been called by each iterator.
// Calls to iterator are overlapped and may call icb in any order, but the mappedResults are collected in the same
// order as the elements of the array.
// Short-circuits if error. Note that iterator MUST be an asynchronous function. (Use setTimeout if necessary.)
var count = array.length, results = [];
if (!count) {
return cb();
return cb(null, results);
}
array.forEach(function (element) {
iterator(element, icb);
array.forEach(function (element, index) {
if (count < 0) { // don't keep iterating after we short-circuit
return;
}
iterator(element, function (error, mapped) {
results[index] = mapped;
if (error || !--count) {
count = 0; // don't cb multiple times if error
cb(error, results);
}
});
});
}
// Example:
/*asyncMap([0, 1, 2, 3, 4, 5, 6], function (elt, icb) {
console.log('called', elt);
setTimeout(function () {
console.log('answering', elt);
icb(null, elt);
}, Math.random() * 1000);
}, console.log); */
function identity(x) {
return x;
}
function addPictureToDomain(domainInfo, cb) { // asynchronously add thumbnail and lobby to domainInfo, if available, and cb(error)
// This requests data for all the names at once, and just uses the first one to come back.
// We might change this to check one at a time, which would be less requests and more latency.
asyncEach([domainInfo.name].concat(domainInfo.names || null).filter(identity), function (name, icb) {
var url = "https://metaverse.highfidelity.com/api/v1/places/" + name;
getRequest(url, function (error, json) {
var previews = !error && json.data.place.previews;
if (previews) {
if (!domainInfo.thumbnail) { // just grab the first one
domainInfo.thumbnail = previews.thumbnail;
}
if (!domainInfo.lobby) {
domainInfo.lobby = previews.lobby;
}
}
icb(error);
});
}, cb);
function handleError(url, error, data, cb) { // cb(error) and answer truthy if needed, else falsey
if (!error && (data.status === 'success')) {
return;
}
if (!error) { // Create a message from the data
error = data.status + ': ' + data.error;
}
if (typeof(error) === 'string') { // Make a proper Error object
error = new Error(error);
}
error.message += ' in ' + url; // Include the url.
cb(error);
return true;
}
function getDomains(options, cb) { // cb(error, arrayOfData)
if (!options.page) {
options.page = 1;
}
if (!domainsBaseUrl) {
var domainsOptions = [
'open', // published hours handle now
'active', // has at least one person connected. FIXME: really want any place that is verified accessible.
// FIXME: really want places I'm allowed in, not just open ones.
'restriction=open', // Not by whitelist, etc. FIXME: If logged in, add hifi to the restriction options, in order to include places that require login.
// FIXME add maturity
'protocol=' + encodeURIComponent(AddressManager.protocolVersion()),
'sort_by=users',
'sort_order=desc',
];
domainsBaseUrl = "https://metaverse.highfidelity.com/api/v1/domains/all?" + domainsOptions.join('&');
}
var url = domainsBaseUrl + "&page=" + options.page + "&users=" + options.minUsers + "-" + options.maxUsers;
getRequest(url, function (error, json) {
if (!error && (json.status !== 'success')) {
error = new Error("Bad response: " + JSON.stringify(json));
}
if (error) {
error.message += ' for ' + url;
return cb(error);
}
var domains = json.data.domains;
if (json.current_page < json.total_pages) {
options.page++;
return getDomains(options, function (error, others) {
cb(error, domains.concat(others));
});
}
cb(null, domains);
});
}
function filterChoicesByText() {
function fill1(target, data) {
if (!data) {
target.visible = false;
function getPlace(placeData, cb) { // cb(error, side-effected-placeData), after adding path, thumbnails, and description
var url = metaverseBase + 'places/' + placeData.place_name;
getRequest(url, function (error, data) {
if (handleError(url, error, data, cb)) {
return;
}
console.log('suggestion:', JSON.stringify(data));
target.userStory = data;
target.image.source = data.lobby || target.defaultPicture;
target.placeText = data.name;
target.usersText = data.online_users + ((data.online_users === 1) ? ' user' : ' users');
target.visible = true;
}
var words = addressLine.text.toUpperCase().split(/\s+/).filter(identity);
var filtered = !words.length ? suggestionChoices : allDomains.filter(function (domain) {
var text = domain.names.concat(domain.tags).join(' ');
if (domain.description) {
text += domain.description;
var place = data.data.place, previews = place.previews;
placeData.path = place.path;
if (previews && previews.thumbnail) {
placeData.thumbnail_url = previews.thumbnail;
}
text = text.toUpperCase();
return words.every(function (word) {
return text.indexOf(word) >= 0;
if (place.description) {
placeData.description = place.description;
placeData.searchText += ' ' + place.description.toUpperCase();
}
cb(error, placeData);
});
}
function makeModelData(data, optionalPlaceName) { // create a new obj from data
// ListModel elements will only ever have those properties that are defined by the first obj that is added.
// So here we make sure that we have all the properties we need, regardless of whether it is a place data or user story.
var name = optionalPlaceName || data.place_name,
tags = data.tags || [data.action, data.username],
description = data.description || "",
thumbnail_url = data.thumbnail_url || "",
image_url = thumbnail_url;
if (data.details) {
try {
image_url = JSON.parse(data.details).image_url || thumbnail_url;
} catch (e) {
console.log(name, "has bad details", data.details);
}
}
return {
place_name: name,
username: data.username || "",
path: data.path || "",
created_at: data.created_at || "",
action: data.action || "",
thumbnail_url: thumbnail_url,
image_url: image_url,
metaverseId: (data.id || "").toString(), // Some are strings from server while others are numbers. Model objects require uniformity.
tags: tags,
description: description,
online_users: data.online_users || 0,
searchText: [name].concat(tags, description || []).join(' ').toUpperCase()
}
}
function mapDomainPlaces(domain, cb) { // cb(error, arrayOfDomainPlaceData)
function addPlace(name, icb) {
getPlace(makeModelData(domain, name), icb);
}
// IWBNI we could get these results in order with most-recent-entered first.
// In any case, we don't really need to preserve the domain.names order in the results.
asyncMap(domain.names || [], addPlace, cb);
}
function suggestable(place) {
if (addressBarDialog.useFeed) {
return true;
}
return (place.place_name !== AddressManager.hostname) // Not our entry, but do show other entry points to current domain.
&& place.thumbnail_url
&& place.online_users // at least one present means it's actually online
&& place.online_users <= 20;
}
function getDomainPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model
// Each page of results is processed completely before we start on the next page.
// For each page of domains, we process each domain in parallel, and for each domain, process each place name in parallel.
// This gives us minimum latency within the page, but we do preserve the order within the page by using asyncMap and
// only appending the collected results.
var params = [
'open', // published hours handle now
// TBD: should determine if place is actually running?
'restriction=open', // Not by whitelist, etc. TBD: If logged in, add hifi to the restriction options, in order to include places that require login?
// TBD: add maturity?
'protocol=' + encodeURIComponent(AddressManager.protocolVersion()),
'sort_by=users',
'sort_order=desc',
'page=' + pageNumber
];
var url = metaverseBase + 'domains/all?' + params.join('&');
getRequest(url, function (error, data) {
if (handleError(url, error, data, cb)) {
return;
}
asyncMap(data.data.domains, mapDomainPlaces, function (error, pageResults) {
if (error) {
return cb(error);
}
// pageResults is now [ [ placeDataOneForDomainOne, placeDataTwoForDomainOne, ...], [ placeDataTwoForDomainTwo...] ]
pageResults.forEach(function (domainResults) {
allPlaces = allPlaces.concat(domainResults);
if (!addressLine.text && !addressBarDialog.useFeed) { // Don't add if the user is already filtering
domainResults.forEach(function (place) {
if (suggestable(place)) {
suggestions.append(place);
}
});
}
});
if (data.current_page < data.total_pages) {
return getDomainPage(pageNumber + 1, cb);
}
cb();
});
});
fill1(s0, filtered[0]);
fill1(s1, filtered[1]);
fill1(s2, filtered[2]);
}
function getUserStoryPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model
var url = metaverseBase + 'user_stories?page=' + pageNumber;
getRequest(url, function (error, data) {
if (handleError(url, error, data, cb)) {
return;
}
var stories = data.user_stories.map(function (story) { // explicit single-argument function
return makeModelData(story);
});
allStories = allStories.concat(stories);
if (!addressLine.text && addressBarDialog.useFeed) { // Don't add if the user is already filtering
stories.forEach(function (story) {
suggestions.append(story);
});
}
if ((data.current_page < data.total_pages) && (data.current_page <= 10)) { // just 10 pages = 100 stories for now
return getUserStoryPage(pageNumber + 1, cb);
}
cb();
});
}
function filterChoicesByText() {
suggestions.clear();
var words = addressLine.text.toUpperCase().split(/\s+/).filter(identity),
data = addressBarDialog.useFeed ? allStories : allPlaces;
function matches(place) {
if (!words.length) {
return suggestable(place);
}
return words.every(function (word) {
return place.searchText.indexOf(word) >= 0;
});
}
data.forEach(function (place) {
if (matches(place)) {
suggestions.append(place);
}
});
}
function fillDestinations() {
allDomains = suggestionChoices = [];
getDomains({minUsers: 0, maxUsers: 20}, function (error, domains) {
if (error) {
console.log('domain query failed:', error);
return filterChoicesByText();
}
var here = AddressManager.hostname; // don't show where we are now.
allDomains = domains.filter(function (domain) { return domain.name !== here; });
// Whittle down suggestions to those that have at least one user, and try to get pictures.
suggestionChoices = allDomains.filter(function (domain) { return domain.online_users; });
asyncEach(domains, addPictureToDomain, function (error) {
if (error) {
console.log('place picture query failed:', error);
}
// Whittle down more by requiring a picture.
suggestionChoices = suggestionChoices.filter(function (domain) { return domain.lobby; });
filterChoicesByText();
});
allPlaces = [];
allStories = [];
suggestions.clear();
getDomainPage(1, function (error) {
console.log('domain query', error || 'ok', allPlaces.length);
});
getUserStoryPage(1, function (error) {
console.log('user stories query', error || 'ok', allStories.length);
});
}

View file

@ -218,16 +218,22 @@ ScrollingWindow {
onIconChanged: {
console.log("New icon: " + icon)
}
onNewViewRequested:{
onNewViewRequested: {
var component = Qt.createComponent("Browser.qml");
var newWindow = component.createObject(desktop);
request.openIn(newWindow.webView)
}
}
Component.onCompleted: {
desktop.initWebviewProfileHandlers(webview.profile)
}
//profile: desktop.browserProfile
}
} // item
Keys.onPressed: {
switch(event.key) {
case Qt.Key_L:

View file

@ -0,0 +1,103 @@
//
// MarketplaceComboBox.qml
//
// Created by Elisa Lupin-Jimenez on 3 Aug 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 QtWebChannel 1.0
import QtWebEngine 1.1
import QtWebSockets 1.0
import "qrc:///qtwebchannel/qwebchannel.js" as WebChannel
import "controls"
import "controls-uit" as Controls
import "styles"
import "styles-uit"
Rectangle {
HifiConstants { id: hifi }
id: marketplaceComboBox
anchors.fill: parent
color: hifi.colors.baseGrayShadow
property var currentUrl: "https://metaverse.highfidelity.com/marketplace"
Controls.WebView {
id: webview
url: currentUrl
anchors.top: switchMarketView.bottom
width: parent.width
height: parent.height - 40
focus: true
Timer {
id: zipTimer
running: false
repeat: false
interval: 1500
property var handler;
onTriggered: handler();
}
property var autoCancel: 'var element = $("a.btn.cancel");
element.click();'
onNewViewRequested: {
var component = Qt.createComponent("Browser.qml");
var newWindow = component.createObject(desktop);
request.openIn(newWindow.webView);
if (File.isZippedFbx(desktop.currentUrl)) {
zipTimer.handler = function() {
newWindow.destroy();
runJavaScript(autoCancel);
}
zipTimer.start();
}
}
property var simpleDownload: 'var element = $("a.download-file");
element.removeClass("download-file");
element.removeAttr("download");'
onLinkHovered: {
desktop.currentUrl = hoveredUrl;
// add an error message for non-fbx files
if (File.isZippedFbx(desktop.currentUrl)) {
runJavaScript(simpleDownload, function(){console.log("ran the JS");});
}
}
}
Controls.ComboBox {
id: switchMarketView
anchors.top: parent.top
anchors.right: parent.right
colorScheme: hifi.colorSchemes.dark
width: 200
height: 40
visible: true
model: ["Marketplace", "Clara.io"]
onCurrentIndexChanged: {
if (currentIndex === 0) { webview.url = "https://metaverse.highfidelity.com/marketplace"; }
if (currentIndex === 1) { webview.url = "https://clara.io/library"; }
}
}
Controls.Label {
id: switchMarketLabel
anchors.verticalCenter: switchMarketView.verticalCenter
anchors.right: switchMarketView.left
color: hifi.colors.white
text: "Explore interesting content from: "
}
}

View file

@ -1,13 +1,16 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls 1.4
import QtWebChannel 1.0
import QtWebEngine 1.1
import QtWebSockets 1.0
import "qrc:///qtwebchannel/qwebchannel.js" as WebChannel
import "windows" as Windows
import "controls"
import "controls-uit" as Controls
import "styles"
import "styles-uit"
Windows.Window {
id: root
@ -23,6 +26,8 @@ Windows.Window {
property var eventBridge;
property var component;
property var dynamicContent;
onSourceChanged: {
if (dynamicContent) {
dynamicContent.destroy();

View file

@ -21,6 +21,8 @@ Original.Button {
width: 120
height: hifi.dimensions.controlLineHeight
HifiConstants { id: hifi }
style: ButtonStyle {
background: Rectangle {

View file

@ -18,6 +18,7 @@ import "." as VrControls
FocusScope {
id: root
HifiConstants { id: hifi }
property alias model: comboBox.model;
property alias comboBox: comboBox

View file

@ -13,6 +13,7 @@ import QtQuick 2.5
import "../styles-uit"
RalewaySemiBold {
HifiConstants { id: hifi }
property int colorScheme: hifi.colorSchemes.light
size: hifi.fontSizes.inputLabel

View file

@ -25,6 +25,8 @@ WebEngineView {
});
}
// FIXME hack to get the URL with the auth token included. Remove when we move to Qt 5.6
Timer {
id: urlReplacementTimer
@ -59,11 +61,6 @@ WebEngineView {
}
}
onNewViewRequested:{
var component = Qt.createComponent("../Browser.qml");
var newWindow = component.createObject(desktop);
request.openIn(newWindow.webView)
}
// This breaks the webchannel used for passing messages. Fixed in Qt 5.6
// See https://bugreports.qt.io/browse/QTBUG-49521

View file

@ -12,6 +12,8 @@ Original.TextInput {
verticalAlignment: Original.TextInput.AlignVCenter
font.family: hifi.fonts.fontFamily
font.pixelSize: hifi.fonts.pixelSize
property int helperPixelSize: font.pixelSize
property bool helperItalic: false
/*
Original.Rectangle {
@ -23,7 +25,8 @@ Original.TextInput {
*/
Text {
anchors.fill: parent
font.pixelSize: parent.font.pixelSize
font.pixelSize: helperPixelSize
font.italic: helperItalic
font.family: parent.font.family
verticalAlignment: parent.verticalAlignment
horizontalAlignment: parent.horizontalAlignment

View file

@ -17,28 +17,69 @@ import QtGraphicalEffects 1.0
import "../styles-uit"
Rectangle {
property string userName: "";
property string placeName: "";
property string action: "";
property string timestamp: "";
property string hifiUrl: "";
property string thumbnail: defaultThumbnail;
property string imageUrl: "";
property var goFunction: null;
property var userStory: null;
property alias image: lobby;
property alias placeText: place.text;
property alias usersText: users.text;
property string storyId: "";
property string timePhrase: pastTime(timestamp);
property string actionPhrase: makeActionPhrase(action);
property int onlineUsers: 0;
property bool isUserStory: userName && !onlineUsers;
property int textPadding: 20;
property int textSize: 24;
property string defaultPicture: "../../images/default-domain.gif";
property int textSizeSmall: 18;
property string defaultThumbnail: Qt.resolvedUrl("../../images/default-domain.gif");
HifiConstants { id: hifi }
function pastTime(timestamp) { // Answer a descriptive string
timestamp = new Date(timestamp);
var then = timestamp.getTime(),
now = Date.now(),
since = now - then,
ONE_MINUTE = 1000 * 60,
ONE_HOUR = ONE_MINUTE * 60,
hours = since / ONE_HOUR,
minutes = (hours % 1) * 60;
if (hours > 24) {
return timestamp.toDateString();
}
if (hours > 1) {
return Math.floor(hours).toString() + ' hr ' + Math.floor(minutes) + ' min ago';
}
if (minutes >= 2) {
return Math.floor(minutes).toString() + ' min ago';
}
return 'about a minute ago';
}
function makeActionPhrase(actionLabel) {
switch (actionLabel) {
case "snapshot":
return "took a snapshot";
default:
return "unknown"
}
}
Image {
id: lobby;
width: parent.width;
height: parent.height;
source: defaultPicture;
source: thumbnail || defaultThumbnail;
fillMode: Image.PreserveAspectCrop;
// source gets filled in later
anchors.verticalCenter: parent.verticalCenter;
anchors.left: parent.left;
onStatusChanged: {
if (status == Image.Error) {
console.log("source: " + source + ": failed to load " + JSON.stringify(userStory));
source = defaultPicture;
console.log("source: " + source + ": failed to load " + hifiUrl);
source = defaultThumbnail;
}
}
}
@ -69,6 +110,7 @@ Rectangle {
}
RalewaySemiBold {
id: place;
text: isUserStory ? "" : placeName;
color: hifi.colors.white;
size: textSize;
anchors {
@ -79,7 +121,8 @@ Rectangle {
}
RalewayRegular {
id: users;
size: textSize;
text: isUserStory ? timePhrase : (onlineUsers + ((onlineUsers === 1) ? ' person' : ' people'));
size: textSizeSmall;
color: hifi.colors.white;
anchors {
bottom: parent.bottom;
@ -87,10 +130,18 @@ Rectangle {
margins: textPadding;
}
}
// These two can be supplied to provide hover behavior.
// For example, AddressBarDialog provides functions that set the current list view item
// to that which is being hovered over.
property var hoverThunk: function () { };
property var unhoverThunk: function () { };
MouseArea {
id: zmouseArea;
anchors.fill: parent;
acceptedButtons: Qt.LeftButton;
onClicked: goFunction(parent);
hoverEnabled: true;
onEntered: hoverThunk();
onExited: unhoverThunk();
}
}

View file

@ -20,6 +20,8 @@ OriginalDesktop.Desktop {
onEntered: ApplicationCompositor.reticleOverDesktop = true
onExited: ApplicationCompositor.reticleOverDesktop = false
acceptedButtons: Qt.NoButton
}
// The tool window, one instance
@ -71,6 +73,39 @@ OriginalDesktop.Desktop {
});
}
// Accept a download through the webview
property bool webViewProfileSetup: false
property string currentUrl: ""
property string adaptedPath: ""
property string tempDir: ""
function initWebviewProfileHandlers(profile) {
console.log("The webview url in desktop is: " + currentUrl);
if (webViewProfileSetup) return;
webViewProfileSetup = true;
profile.downloadRequested.connect(function(download){
console.log("Download start: " + download.state);
adaptedPath = File.convertUrlToPath(currentUrl);
tempDir = File.getTempDir();
console.log("Temp dir created: " + tempDir);
download.path = tempDir + "/" + adaptedPath;
console.log("Path where object should download: " + download.path);
download.accept();
if (download.state === WebEngineDownloadItem.DownloadInterrupted) {
console.log("download failed to complete");
}
})
profile.downloadFinished.connect(function(download){
if (download.state === WebEngineDownloadItem.DownloadCompleted) {
File.runUnzip(download.path, currentUrl);
} else {
console.log("The download was corrupted, state: " + download.state);
}
})
}
// Create or fetch a toolbar with the given name
function getToolbar(name) {
var result = toolbars[name];

View file

@ -57,6 +57,7 @@
#include <display-plugins/DisplayPlugin.h>
#include <EntityScriptingInterface.h>
#include <ErrorDialog.h>
#include <FileScriptingInterface.h>
#include <Finally.h>
#include <FramebufferCache.h>
#include <gpu/Batch.h>
@ -1578,6 +1579,9 @@ void Application::initializeUi() {
rootContext->setContextProperty("Audio", &AudioScriptingInterface::getInstance());
rootContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());
rootContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
FileScriptingInterface* fileDownload = new FileScriptingInterface(engine);
rootContext->setContextProperty("File", fileDownload);
connect(fileDownload, &FileScriptingInterface::unzipSuccess, this, &Application::showAssetServerWidget);
rootContext->setContextProperty("MyAvatar", getMyAvatar());
rootContext->setContextProperty("Messages", DependencyManager::get<MessagesClient>().data());
rootContext->setContextProperty("Recording", DependencyManager::get<RecordingScriptingInterface>().data());
@ -2024,7 +2028,6 @@ bool Application::importJSONFromURL(const QString& urlString) {
}
bool Application::importSVOFromURL(const QString& urlString) {
emit svoImportRequested(urlString);
return true;
}
@ -2149,13 +2152,15 @@ bool Application::event(QEvent* event) {
// handle custom URL
if (event->type() == QEvent::FileOpen) {
QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event);
QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event);
QUrl url = fileEvent->url();
if (!url.isEmpty()) {
QString urlString = url.toString();
if (canAcceptURL(urlString)) {
return acceptURL(urlString);
}
}
@ -2296,7 +2301,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
} else if (isOption && !isShifted && !isMeta) {
Menu::getInstance()->triggerOption(MenuOption::ScriptEditor);
} else if (!isOption && !isShifted && isMeta) {
takeSnapshot();
takeSnapshot(true);
}
break;
@ -4326,7 +4331,7 @@ namespace render {
}
case model::SunSkyStage::SKY_BOX: {
auto skybox = skyStage->getSkybox();
if (skybox) {
if (!skybox->empty()) {
PerformanceTimer perfTimer("skybox");
skybox->render(batch, args->getViewFrustum());
break;
@ -4913,6 +4918,7 @@ bool Application::canAcceptURL(const QString& urlString) const {
bool Application::acceptURL(const QString& urlString, bool defaultUpload) {
if (urlString.startsWith(HIFI_URL_SCHEME)) {
// this is a hifi URL - have the AddressManager handle it
emit receivedHifiSchemeURL(urlString);
QMetaObject::invokeMethod(DependencyManager::get<AddressManager>().data(), "handleLookupString",
Qt::AutoConnection, Q_ARG(const QString&, urlString));
return true;
@ -5020,7 +5026,6 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
}
bool Application::askToWearAvatarAttachmentUrl(const QString& url) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest = QNetworkRequest(url);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
@ -5118,11 +5123,11 @@ void Application::toggleRunningScriptsWidget() const {
//}
}
void Application::showAssetServerWidget(QString filePath) {
if (!DependencyManager::get<NodeList>()->getThisNodeCanWriteAssets()) {
return;
}
static const QUrl url { "AssetServer.qml" };
auto startUpload = [=](QQmlContext* context, QObject* newObject){
@ -5189,15 +5194,24 @@ void Application::toggleLogDialog() {
}
}
void Application::takeSnapshot() {
QMediaPlayer* player = new QMediaPlayer();
QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav");
player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath()));
player->play();
void Application::takeSnapshot(bool notify, float aspectRatio) {
postLambdaEvent([notify, aspectRatio, this] {
QMediaPlayer* player = new QMediaPlayer();
QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav");
player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath()));
player->play();
QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot());
QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio));
emit DependencyManager::get<WindowScriptingInterface>()->snapshotTaken(path);
emit DependencyManager::get<WindowScriptingInterface>()->snapshotTaken(path, notify);
});
}
void Application::shareSnapshot(const QString& path) {
postLambdaEvent([path] {
// not much to do here, everything is done in snapshot code...
Snapshot::uploadSnapshot(path);
});
}
float Application::getRenderResolutionScale() const {

View file

@ -250,6 +250,9 @@ public:
float getAvatarSimrate() const { return _avatarSimCounter.rate(); }
float getAverageSimsPerSecond() const { return _simCounter.rate(); }
void takeSnapshot(bool notify, float aspectRatio = 0.0f);
void shareSnapshot(const QString& filename);
model::SkyboxPointer getDefaultSkybox() const { return _defaultSkybox; }
gpu::TexturePointer getDefaultSkyboxTexture() const { return _defaultSkyboxTexture; }
@ -276,6 +279,7 @@ signals:
void activeDisplayPluginChanged();
void uploadRequest(QString path);
void receivedHifiSchemeURL(const QString& url);
public slots:
QVector<EntityItemID> pasteEntities(float x, float y, float z);
@ -396,8 +400,6 @@ private:
int sendNackPackets();
void takeSnapshot();
MyAvatar* getMyAvatar() const;
void checkSkeleton() const;

View file

@ -27,10 +27,6 @@ void ConnectionMonitor::init() {
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &ConnectionMonitor::disconnectedFromDomain);
connect(&domainHandler, &DomainHandler::connectedToDomain, this, &ConnectionMonitor::connectedToDomain);
// Connect to AddressManager::hostChanged
auto addressManager = DependencyManager::get<AddressManager>();
connect(addressManager.data(), &AddressManager::hostChanged, this, &ConnectionMonitor::hostChanged);
_timer.setSingleShot(true);
_timer.setInterval(DISPLAY_AFTER_DISCONNECTED_FOR_X_MS);
_timer.start();
@ -46,7 +42,3 @@ void ConnectionMonitor::disconnectedFromDomain() {
void ConnectionMonitor::connectedToDomain(const QString& name) {
_timer.stop();
}
void ConnectionMonitor::hostChanged(const QString& name) {
_timer.start();
}

View file

@ -25,7 +25,6 @@ public:
private slots:
void disconnectedFromDomain();
void connectedToDomain(const QString& name);
void hostChanged(const QString& name);
private:
QTimer _timer;

View file

@ -26,6 +26,11 @@ bool AccountScriptingInterface::isLoggedIn() {
return accountManager->isLoggedIn();
}
bool AccountScriptingInterface::checkAndSignalForAccessToken() {
auto accountManager = DependencyManager::get<AccountManager>();
return accountManager->checkAndSignalForAccessToken();
}
QString AccountScriptingInterface::getUsername() {
auto accountManager = DependencyManager::get<AccountManager>();
if (accountManager->isLoggedIn()) {

View file

@ -26,6 +26,7 @@ public slots:
static AccountScriptingInterface* getInstance();
QString getUsername();
bool isLoggedIn();
bool checkAndSignalForAccessToken();
};
#endif // hifi_AccountScriptingInterface_h

View file

@ -17,6 +17,8 @@
#include "Application.h"
#include "MainWindow.h"
#include <display-plugins/CompositorHelper.h>
#include <DependencyManager.h>
#include <OffscreenUi.h>
int DesktopScriptingInterface::getWidth() {
QSize size = qApp->getWindow()->windowHandle()->screen()->virtualSize();
@ -31,3 +33,11 @@ void DesktopScriptingInterface::setOverlayAlpha(float alpha) {
qApp->getApplicationCompositor().setAlpha(alpha);
}
void DesktopScriptingInterface::show(const QString& path, const QString& title) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "show", Qt::QueuedConnection, Q_ARG(QString, path), Q_ARG(QString, title));
return;
}
DependencyManager::get<OffscreenUi>()->show(path, title);
}

View file

@ -23,6 +23,7 @@ class DesktopScriptingInterface : public QObject, public Dependency {
public:
Q_INVOKABLE void setOverlayAlpha(float alpha);
Q_INVOKABLE void show(const QString& path, const QString& title);
int getWidth();
int getHeight();

View file

@ -26,3 +26,8 @@ void DialogsManagerScriptingInterface::toggleAddressBar() {
QMetaObject::invokeMethod(DependencyManager::get<DialogsManager>().data(),
"toggleAddressBar", Qt::QueuedConnection);
}
void DialogsManagerScriptingInterface::showFeed() {
QMetaObject::invokeMethod(DependencyManager::get<DialogsManager>().data(),
"showFeed", Qt::QueuedConnection);
}

View file

@ -18,6 +18,7 @@ class DialogsManagerScriptingInterface : public QObject {
Q_OBJECT
public:
DialogsManagerScriptingInterface();
Q_INVOKABLE void showFeed();
public slots:
void toggleAddressBar();

View file

@ -96,7 +96,7 @@ void WindowScriptingInterface::alert(const QString& message) {
/// \param const QString& message message to display
/// \return QScriptValue `true` if 'Yes' was clicked, `false` otherwise
QScriptValue WindowScriptingInterface::confirm(const QString& message) {
return QScriptValue((QMessageBox::Yes == OffscreenUi::question("", message)));
return QScriptValue((QMessageBox::Yes == OffscreenUi::question("", message, QMessageBox::Yes | QMessageBox::No)));
}
/// Display a prompt with a text box
@ -203,3 +203,11 @@ void WindowScriptingInterface::copyToClipboard(const QString& text) {
qDebug() << "Copying";
QApplication::clipboard()->setText(text);
}
void WindowScriptingInterface::takeSnapshot(bool notify, float aspectRatio) {
qApp->takeSnapshot(notify, aspectRatio);
}
void WindowScriptingInterface::shareSnapshot(const QString& path) {
qApp->shareSnapshot(path);
}

View file

@ -55,12 +55,15 @@ public slots:
QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
void showAssetServer(const QString& upload = "");
void copyToClipboard(const QString& text);
void takeSnapshot(bool notify = true, float aspectRatio = 0.0f);
void shareSnapshot(const QString& path);
signals:
void domainChanged(const QString& domainHostname);
void svoImportRequested(const QString& url);
void domainConnectionRefused(const QString& reasonMessage, int reasonCode);
void snapshotTaken(const QString& path);
void snapshotTaken(const QString& path, bool notify);
void snapshotShared(const QString& error);
private slots:
WebWindowClass* doCreateWebWindow(const QString& title, const QString& url, int width, int height);

View file

@ -38,6 +38,8 @@ AddressBarDialog::AddressBarDialog(QQuickItem* parent) : OffscreenQmlDialog(pare
});
_backEnabled = !(DependencyManager::get<AddressManager>()->getBackStack().isEmpty());
_forwardEnabled = !(DependencyManager::get<AddressManager>()->getForwardStack().isEmpty());
connect(DependencyManager::get<DialogsManager>().data(), &DialogsManager::setUseFeed, this, &AddressBarDialog::setUseFeed);
connect(qApp, &Application::receivedHifiSchemeURL, this, &AddressBarDialog::receivedHifiSchemeURL);
}
void AddressBarDialog::loadAddress(const QString& address, bool fromSuggestions) {

View file

@ -14,21 +14,29 @@
#define hifi_AddressBarDialog_h
#include <OffscreenQmlDialog.h>
#include <NetworkingConstants.h>
class AddressBarDialog : public OffscreenQmlDialog {
Q_OBJECT
HIFI_QML_DECL
Q_PROPERTY(bool backEnabled READ backEnabled NOTIFY backEnabledChanged)
Q_PROPERTY(bool forwardEnabled READ forwardEnabled NOTIFY forwardEnabledChanged)
Q_PROPERTY(bool useFeed READ useFeed WRITE setUseFeed NOTIFY useFeedChanged)
Q_PROPERTY(QString metaverseServerUrl READ metaverseServerUrl)
public:
AddressBarDialog(QQuickItem* parent = nullptr);
bool backEnabled() { return _backEnabled; }
bool forwardEnabled() { return _forwardEnabled; }
bool useFeed() { return _useFeed; }
void setUseFeed(bool useFeed) { if (_useFeed != useFeed) { _useFeed = useFeed; emit useFeedChanged(); } }
QString metaverseServerUrl() { return NetworkingConstants::METAVERSE_SERVER_URL.toString(); }
signals:
void backEnabledChanged();
void forwardEnabledChanged();
void useFeedChanged();
void receivedHifiSchemeURL(const QString& url);
protected:
void displayAddressOfflineMessage();
@ -42,6 +50,7 @@ protected:
bool _backEnabled;
bool _forwardEnabled;
bool _useFeed { false };
};
#endif

View file

@ -54,6 +54,11 @@ void DialogsManager::showAddressBar() {
AddressBarDialog::show();
}
void DialogsManager::showFeed() {
AddressBarDialog::show();
emit setUseFeed(true);
}
void DialogsManager::toggleDiskCacheEditor() {
maybeCreateDialog(_diskCacheEditor);
_diskCacheEditor->toggle();

View file

@ -45,6 +45,7 @@ public:
public slots:
void toggleAddressBar();
void showAddressBar();
void showFeed();
void toggleDiskCacheEditor();
void toggleLoginDialog();
void showLoginDialog();
@ -63,6 +64,7 @@ public slots:
signals:
void addressBarToggled();
void addressBarShown(bool visible);
void setUseFeed(bool useFeed);
private slots:
void hmdToolsClosed();

View file

@ -32,6 +32,7 @@
#include "Application.h"
#include "Snapshot.h"
#include "SnapshotUploader.h"
// filename format: hifi-snap-by-%username%-on-%date%_%time%_@-%location%.jpg
// %1 <= username, %2 <= date and time, %3 <= current location
@ -141,3 +142,34 @@ QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary) {
return imageTempFile;
}
}
void Snapshot::uploadSnapshot(const QString& filename) {
const QString SNAPSHOT_UPLOAD_URL = "/api/v1/snapshots";
static SnapshotUploader uploader;
QFile* file = new QFile(filename);
Q_ASSERT(file->exists());
file->open(QIODevice::ReadOnly);
QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader,
QVariant("form-data; name=\"image\"; filename=\"" + file->fileName() + "\""));
imagePart.setBodyDevice(file);
QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart
multiPart->append(imagePart);
auto accountManager = DependencyManager::get<AccountManager>();
JSONCallbackParameters callbackParams(&uploader, "uploadSuccess", &uploader, "uploadFailure");
accountManager->sendRequest(SNAPSHOT_UPLOAD_URL,
AccountManagerAuth::Required,
QNetworkAccessManager::PostOperation,
callbackParams,
nullptr,
multiPart);
}

View file

@ -40,6 +40,7 @@ public:
static Setting::Handle<QString> snapshotsLocation;
static Setting::Handle<bool> hasSetSnapshotsLocation;
static void uploadSnapshot(const QString& filename);
private:
static QFile* savedFileForSnapshot(QImage & image, bool isTemporary);
};

View file

@ -0,0 +1,75 @@
//
// SnapshotUploader.cpp
// interface/src/ui
//
// Created by Howard Stearns on 8/22/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
//
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonArray>
#include <AddressManager.h>
#include "scripting/WindowScriptingInterface.h"
#include "SnapshotUploader.h"
void SnapshotUploader::uploadSuccess(QNetworkReply& reply) {
const QString STORY_UPLOAD_URL = "/api/v1/user_stories";
static SnapshotUploader uploader;
// parse the reply for the thumbnail_url
QByteArray contents = reply.readAll();
QJsonParseError jsonError;
auto doc = QJsonDocument::fromJson(contents, &jsonError);
if (jsonError.error == QJsonParseError::NoError) {
auto dataObject = doc.object().value("data").toObject();
QString thumbnailUrl = dataObject.value("thumbnail_url").toString();
QString imageUrl = dataObject.value("image_url").toString();
auto addressManager = DependencyManager::get<AddressManager>();
QString placeName = addressManager->getPlaceName();
if (placeName.isEmpty()) {
placeName = addressManager->getHost();
}
QString currentPath = addressManager->currentPath(true);
// create json post data
QJsonObject rootObject;
QJsonObject userStoryObject;
QJsonObject detailsObject;
detailsObject.insert("image_url", imageUrl);
QString pickledDetails = QJsonDocument(detailsObject).toJson();
userStoryObject.insert("details", pickledDetails);
userStoryObject.insert("thumbnail_url", thumbnailUrl);
userStoryObject.insert("place_name", placeName);
userStoryObject.insert("path", currentPath);
userStoryObject.insert("action", "snapshot");
rootObject.insert("user_story", userStoryObject);
auto accountManager = DependencyManager::get<AccountManager>();
JSONCallbackParameters callbackParams(&uploader, "createStorySuccess", &uploader, "createStoryFailure");
accountManager->sendRequest(STORY_UPLOAD_URL,
AccountManagerAuth::Required,
QNetworkAccessManager::PostOperation,
callbackParams,
QJsonDocument(rootObject).toJson());
}
else {
emit DependencyManager::get<WindowScriptingInterface>()->snapshotShared(contents);
}
}
void SnapshotUploader::uploadFailure(QNetworkReply& reply) {
emit DependencyManager::get<WindowScriptingInterface>()->snapshotShared(reply.readAll());
}
void SnapshotUploader::createStorySuccess(QNetworkReply& reply) {
emit DependencyManager::get<WindowScriptingInterface>()->snapshotShared(QString());
}
void SnapshotUploader::createStoryFailure(QNetworkReply& reply) {
emit DependencyManager::get<WindowScriptingInterface>()->snapshotShared(reply.readAll());
}

View file

@ -0,0 +1,26 @@
//
// SnapshotUploader.h
// interface/src/ui
//
// Created by Howard Stearns on 8/22/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
//
#ifndef hifi_SnapshotUploader_h
#define hifi_SnapshotUploader_h
#include <QObject>
#include <QtNetwork/QNetworkReply>
class SnapshotUploader : public QObject {
Q_OBJECT
public slots:
void uploadSuccess(QNetworkReply& reply);
void uploadFailure(QNetworkReply& reply);
void createStorySuccess(QNetworkReply& reply);
void createStoryFailure(QNetworkReply& reply);
};
#endif // hifi_SnapshotUploader_h

View file

@ -31,6 +31,6 @@ void NullDisplayPlugin::submitFrame(const gpu::FramePointer& frame) {
}
}
QImage NullDisplayPlugin::getScreenshot() const {
QImage NullDisplayPlugin::getScreenshot(float aspectRatio) const {
return QImage();
}

View file

@ -18,7 +18,7 @@ public:
glm::uvec2 getRecommendedRenderSize() const override;
bool hasFocus() const override;
void submitFrame(const gpu::FramePointer& newFrame) override;
QImage getScreenshot() const override;
QImage getScreenshot(float aspectRatio = 0.0f) const override;
private:
static const QString NAME;
};

View file

@ -659,12 +659,26 @@ void OpenGLDisplayPlugin::withMainThreadContext(std::function<void()> f) const {
_container->makeRenderingContextCurrent();
}
QImage OpenGLDisplayPlugin::getScreenshot() const {
QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) const {
auto size = _compositeFramebuffer->getSize();
if (isHmd()) {
size.x /= 2;
}
auto bestSize = size;
uvec2 corner(0);
if (aspectRatio != 0.0f) { // Pick out the largest piece of the center that produces the requested width/height aspectRatio
if (ceil(size.y * aspectRatio) < size.x) {
bestSize.x = round(size.y * aspectRatio);
} else {
bestSize.y = round(size.x / aspectRatio);
}
corner.x = round((size.x - bestSize.x) / 2.0f);
corner.y = round((size.y - bestSize.y) / 2.0f);
}
auto glBackend = const_cast<OpenGLDisplayPlugin&>(*this).getGLBackend();
QImage screenshot(size.x, size.y, QImage::Format_ARGB32);
QImage screenshot(bestSize.x, bestSize.y, QImage::Format_ARGB32);
withMainThreadContext([&] {
glBackend->downloadFramebuffer(_compositeFramebuffer, ivec4(uvec2(0), size), screenshot);
glBackend->downloadFramebuffer(_compositeFramebuffer, ivec4(corner, bestSize), screenshot);
});
return screenshot.mirrored(false, true);
}

View file

@ -54,7 +54,7 @@ public:
return getSurfaceSize();
}
QImage getScreenshot() const override;
QImage getScreenshot(float aspectRatio = 0.0f) const override;
float presentRate() const override;

View file

@ -676,6 +676,10 @@ void sphericalHarmonicsEvaluateDirection(float * result, int order, const glm::
}
bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<glm::vec3> & output, const uint order) {
int width = cubeTexture.getWidth();
if(width != cubeTexture.getHeight()) {
return false;
}
const uint sqOrder = order*order;
// allocate memory for calculations
@ -684,8 +688,6 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
std::vector<float> resultG(sqOrder);
std::vector<float> resultB(sqOrder);
int width, height;
// initialize values
float fWt = 0.0f;
for(uint i=0; i < sqOrder; i++) {
@ -696,11 +698,16 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
}
std::vector<float> shBuff(sqOrder);
std::vector<float> shBuffB(sqOrder);
// get width and height
width = height = cubeTexture.getWidth();
if(width != height) {
return false;
// We trade accuracy for speed by breaking the image into 32x32 parts
// and approximating the distance for all the pixels in each part to be
// the distance to the part's center.
int numDivisionsPerSide = 32;
if (width < numDivisionsPerSide) {
numDivisionsPerSide = width;
}
int stride = width / numDivisionsPerSide;
int halfStride = stride / 2;
// for each face of cube texture
for(int face=0; face < gpu::Texture::NUM_CUBE_FACES; face++) {
@ -718,11 +725,11 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
// step between two texels for range [-1, 1]
float invWidthBy2 = 2.0f / float(width);
for(int y=0; y < width; y++) {
for(int y=halfStride; y < width-halfStride; y += stride) {
// texture coordinate V in range [-1 to 1]
const float fV = negativeBound + float(y) * invWidthBy2;
for(int x=0; x < width; x++) {
for(int x=halfStride; x < width - halfStride; x += stride) {
// texture coordinate U in range [-1 to 1]
const float fU = negativeBound + float(x) * invWidthBy2;
@ -785,32 +792,37 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
sphericalHarmonicsEvaluateDirection(shBuff.data(), order, dir);
// index of texel in texture
uint pixOffsetIndex = (x + y * width) * numComponents;
// get color from texture and map to range [0, 1]
glm::vec3 clr(ColorUtils::sRGB8ToLinearFloat(data[pixOffsetIndex]),
ColorUtils::sRGB8ToLinearFloat(data[pixOffsetIndex + 1]),
ColorUtils::sRGB8ToLinearFloat(data[pixOffsetIndex + 2]));
float red { 0.0f };
float green { 0.0f };
float blue { 0.0f };
for (int i = 0; i < stride; ++i) {
for (int j = 0; j < stride; ++j) {
int k = (int)(x + i - halfStride + (y + j - halfStride) * width) * numComponents;
red += ColorUtils::sRGB8ToLinearFloat(data[k]);
green += ColorUtils::sRGB8ToLinearFloat(data[k + 1]);
blue += ColorUtils::sRGB8ToLinearFloat(data[k + 2]);
}
}
glm::vec3 clr(red, green, blue);
// scale color and add to previously accumulated coefficients
sphericalHarmonicsScale(shBuffB.data(), order,
shBuff.data(), clr.r * fDiffSolid);
sphericalHarmonicsAdd(resultR.data(), order,
resultR.data(), shBuffB.data());
sphericalHarmonicsScale(shBuffB.data(), order,
shBuff.data(), clr.g * fDiffSolid);
sphericalHarmonicsAdd(resultG.data(), order,
resultG.data(), shBuffB.data());
sphericalHarmonicsScale(shBuffB.data(), order,
shBuff.data(), clr.b * fDiffSolid);
sphericalHarmonicsAdd(resultB.data(), order,
resultB.data(), shBuffB.data());
// red
sphericalHarmonicsScale(shBuffB.data(), order, shBuff.data(), clr.r * fDiffSolid);
sphericalHarmonicsAdd(resultR.data(), order, resultR.data(), shBuffB.data());
// green
sphericalHarmonicsScale(shBuffB.data(), order, shBuff.data(), clr.g * fDiffSolid);
sphericalHarmonicsAdd(resultG.data(), order, resultG.data(), shBuffB.data());
// blue
sphericalHarmonicsScale(shBuffB.data(), order, shBuff.data(), clr.b * fDiffSolid);
sphericalHarmonicsAdd(resultB.data(), order, resultB.data(), shBuffB.data());
}
}
}
// final scale for coefficients
const float fNormProj = (4.0f * glm::pi<float>()) / fWt;
const float fNormProj = (4.0f * glm::pi<float>()) / (fWt * (float)(stride * stride));
sphericalHarmonicsScale(resultR.data(), order, resultR.data(), fNormProj);
sphericalHarmonicsScale(resultG.data(), order, resultG.data(), fNormProj);
sphericalHarmonicsScale(resultB.data(), order, resultB.data(), fNormProj);

View file

@ -35,6 +35,7 @@ public:
void setCubemap(const gpu::TexturePointer& cubemap);
const gpu::TexturePointer& getCubemap() const { return _cubemap; }
virtual bool empty() { return _schemaBuffer.get<Schema>().color == vec3(0) && !_cubemap; }
virtual void clear() { setCubemap(nullptr); }
void prepare(gpu::Batch& batch, int textureSlot = SKYBOX_SKYMAP_SLOT, int bufferSlot = SKYBOX_CONSTANTS_SLOT) const;

View file

@ -38,6 +38,7 @@ class AddressManager : public QObject, public Dependency {
Q_PROPERTY(QString protocol READ getProtocol)
Q_PROPERTY(QString hostname READ getHost)
Q_PROPERTY(QString pathname READ currentPath)
Q_PROPERTY(QString placename READ getPlaceName)
public:
Q_INVOKABLE QString protocolVersion();
using PositionGetter = std::function<glm::vec3()>;

View file

@ -172,7 +172,7 @@ public:
}
// Fetch the most recently displayed image as a QImage
virtual QImage getScreenshot() const = 0;
virtual QImage getScreenshot(float aspectRatio = 0.0f) const = 0;
// will query the underlying hmd api to compute the most recent head pose
virtual bool beginFrameRender(uint32_t frameIndex) { return true; }

View file

@ -38,6 +38,7 @@ public:
void parse(const QString& userDataJson);
bool ready();
bool enabled() { return _enabled; }
void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation);
const gpu::ShaderPointer& getShader() const { return _shader; }

View file

@ -26,6 +26,10 @@ ProceduralSkybox::ProceduralSkybox() : model::Skybox() {
_procedural._opaqueState->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
}
bool ProceduralSkybox::empty() {
return !_procedural.enabled() && Skybox::empty();
}
void ProceduralSkybox::clear() {
// Parse and prepare a procedural with no shaders to release textures
parse(QString());

View file

@ -20,13 +20,14 @@
class ProceduralSkybox: public model::Skybox {
public:
ProceduralSkybox();
virtual ~ProceduralSkybox() {};
~ProceduralSkybox() override {};
void parse(const QString& userData) { _procedural.parse(userData); }
virtual void clear() override;
bool empty() override;
void clear() override;
virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const override;
void render(gpu::Batch& batch, const ViewFrustum& frustum) const override;
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox);
protected:

View file

@ -1,3 +1,15 @@
set(TARGET_NAME script-engine)
setup_hifi_library(Gui Network Script ScriptTools WebSockets Widgets)
target_zlib()
add_dependency_external_projects(quazip)
find_package(QuaZip REQUIRED)
target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${QUAZIP_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} ${QUAZIP_LIBRARIES})
if (WIN32)
add_paths_to_fixup_libs(${QUAZIP_DLL_PATH})
endif ()
link_hifi_libraries(shared networking octree gpu ui procedural model model-networking recording avatars fbx entities controllers animation audio physics)

View file

@ -0,0 +1,145 @@
//
// FileScriptingInterface.cpp
// libraries/script-engine/src
//
// Created by Elisa Lupin-Jimenez on 6/28/16.
// 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
//
#include <QTemporaryDir>
#include <QDir>
#include <QFile>
#include <QDebug>
#include <QBuffer>
#include <QTextCodec>
#include <QIODevice>
#include <QUrl>
#include <QByteArray>
#include <QString>
#include <QFileInfo>
#include <quazip5/quazip.h>
#include <quazip5/JlCompress.h>
#include "ResourceManager.h"
#include "FileScriptingInterface.h"
FileScriptingInterface::FileScriptingInterface(QObject* parent) : QObject(parent) {
// nothing for now
}
void FileScriptingInterface::runUnzip(QString path, QUrl url) {
qDebug() << "Url that was downloaded: " + url.toString();
qDebug() << "Path where download is saved: " + path;
QString fileName = "/" + path.section("/", -1);
QString tempDir = path;
tempDir.remove(fileName);
qDebug() << "Temporary directory at: " + tempDir;
if (!isTempDir(tempDir)) {
qDebug() << "Temporary directory mismatch; risk of losing files";
return;
}
QString file = unzipFile(path, tempDir);
if (file != "") {
qDebug() << "Object file to upload: " + file;
QUrl url = QUrl::fromLocalFile(file);
emit unzipSuccess(url.toString());
} else {
qDebug() << "unzip failed";
}
qDebug() << "Removing temporary directory at: " + tempDir;
QDir(tempDir).removeRecursively();
}
// fix to check that we are only referring to a temporary directory
bool FileScriptingInterface::isTempDir(QString tempDir) {
QString folderName = "/" + tempDir.section("/", -1);
QString tempContainer = tempDir;
tempContainer.remove(folderName);
QTemporaryDir test;
QString testDir = test.path();
folderName = "/" + testDir.section("/", -1);
QString testContainer = testDir;
testContainer.remove(folderName);
if (testContainer == tempContainer) return true;
return false;
}
bool FileScriptingInterface::isZippedFbx(QUrl url) {
if (url.toString().contains(".zip") && url.toString().contains("fbx")) return true;
return false;
}
// this function is not in use
QString FileScriptingInterface::getTempDir() {
QTemporaryDir dir;
dir.setAutoRemove(false);
return dir.path();
// do something to delete this temp dir later
}
QString FileScriptingInterface::convertUrlToPath(QUrl url) {
QString newUrl;
QString oldUrl = url.toString();
newUrl = oldUrl.section("filename=", 1, 1);
qDebug() << "Filename should be: " + newUrl;
return newUrl;
}
// this function is not in use
void FileScriptingInterface::downloadZip(QString path, const QString link) {
QUrl url = QUrl(link);
auto request = ResourceManager::createResourceRequest(nullptr, url);
connect(request, &ResourceRequest::finished, this, [this, path]{
unzipFile(path, ""); // so intellisense isn't mad
});
request->send();
}
QString FileScriptingInterface::unzipFile(QString path, QString tempDir) {
QDir dir(path);
QString dirName = dir.path();
QString target = tempDir + "/model_repo";
QStringList list = JlCompress::extractDir(dirName, target);
qDebug() << list;
if (!list.isEmpty()) {
return list.front();
} else {
qDebug() << "Extraction failed";
return "";
}
}
// this function is not in use
void FileScriptingInterface::recursiveFileScan(QFileInfo file, QString* dirName) {
/*if (!file.isDir()) {
qDebug() << "Regular file logged: " + file.fileName();
return;
}*/
QFileInfoList files;
if (file.fileName().contains(".zip")) {
qDebug() << "Extracting archive: " + file.fileName();
JlCompress::extractDir(file.fileName());
}
files = file.dir().entryInfoList();
/*if (files.empty()) {
files = JlCompress::getFileList(file.fileName());
}*/
foreach (QFileInfo file, files) {
qDebug() << "Looking into file: " + file.fileName();
recursiveFileScan(file, dirName);
}
return;
}

View file

@ -0,0 +1,43 @@
//
// FileScriptingInterface.h
// libraries/script-engine/src
//
// Created by Elisa Lupin-Jimenez on 6/28/16.
// 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
//
#ifndef hifi_FileScriptingInterface_h
#define hifi_FileScriptingInterface_h
#include <QtCore/QObject>
#include <QFileInfo>
#include <QString>
class FileScriptingInterface : public QObject {
Q_OBJECT
public:
FileScriptingInterface(QObject* parent);
public slots:
bool isZippedFbx(QUrl url);
QString convertUrlToPath(QUrl url);
void runUnzip(QString path, QUrl url);
QString getTempDir();
signals:
void unzipSuccess(QString url);
private:
bool isTempDir(QString tempDir);
QString unzipFile(QString path, QString tempDir);
void recursiveFileScan(QFileInfo file, QString* dirName);
void downloadZip(QString path, const QString link);
};
#endif // hifi_FileScriptingInterface_h

View file

@ -49,6 +49,7 @@
#include "BatchLoader.h"
#include "DataViewClass.h"
#include "EventTypes.h"
#include "FileScriptingInterface.h" // unzip project
#include "MenuItemProperties.h"
#include "ScriptAudioInjector.h"
#include "ScriptCache.h"
@ -501,6 +502,9 @@ void ScriptEngine::init() {
registerGlobalObject("Mat4", &_mat4Library);
registerGlobalObject("Uuid", &_uuidLibrary);
registerGlobalObject("Messages", DependencyManager::get<MessagesClient>().data());
registerGlobalObject("File", new FileScriptingInterface(this));
qScriptRegisterMetaType(this, animVarMapToScriptValue, animVarMapFromScriptValue);
qScriptRegisterMetaType(this, resultHandlerToScriptValue, resultHandlerFromScriptValue);

View file

@ -176,8 +176,7 @@ void showOpenVrKeyboard(bool show = true) {
}
}
void finishOpenVrKeyboardInput() {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
void updateFromOpenVrKeyboardInput() {
auto chars = _overlay->GetKeyboardText(textArray, 8192);
auto newText = QString(QByteArray(textArray, chars));
_keyboardFocusObject->setProperty("text", newText);
@ -187,6 +186,11 @@ void finishOpenVrKeyboardInput() {
//QInputMethodEvent event(_existingText, QList<QInputMethodEvent::Attribute>());
//event.setCommitString(newText, 0, _existingText.size());
//qApp->sendEvent(_keyboardFocusObject, &event);
}
void finishOpenVrKeyboardInput() {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
updateFromOpenVrKeyboardInput();
// Simulate an enter press on the top level window to trigger the action
if (0 == (_currentHints & Qt::ImhMultiLine)) {
qApp->sendEvent(offscreenUi->getWindow(), &QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::KeyboardModifiers(), QString("\n")));
@ -267,6 +271,11 @@ void handleOpenVrEvents() {
activeHmd->AcknowledgeQuit_Exiting();
break;
case vr::VREvent_KeyboardCharInput:
// Make the focused field match the keyboard results, inclusive of combining characters and such.
updateFromOpenVrKeyboardInput();
break;
case vr::VREvent_KeyboardDone:
finishOpenVrKeyboardInput();

View file

@ -15,7 +15,7 @@ Script.load("system/users.js");
Script.load("system/mute.js");
Script.load("system/goto.js");
Script.load("system/hmd.js");
Script.load("system/marketplace.js");
Script.load("system/marketplaces/marketplace.js");
Script.load("system/edit.js");
Script.load("system/mod.js");
Script.load("system/selectAudioDevice.js");
@ -27,4 +27,6 @@ Script.load("system/controllers/grab.js");
Script.load("system/controllers/teleport.js");
Script.load("system/controllers/toggleAdvancedMovementForHandControllers.js")
Script.load("system/dialTone.js");
Script.load("system/firstPersonHMD.js");
Script.load("system/firstPersonHMD.js");
Script.load("system/snapshot.js");

View file

@ -0,0 +1,109 @@
<?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 200.1" style="enable-background:new 0 0 50 200.1;" xml:space="preserve">
<style type="text/css">
.st0{fill:#414042;}
.st1{fill:#FFFFFF;}
.st2{fill:#1E1E1E;}
.st3{fill:#333333;}
</style>
<g id="Layer_2">
<g>
<g>
<path class="st0" d="M50.1,146.1c0,2.2-1.8,4-4,4h-42c-2.2,0-4-1.8-4-4v-42c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V146.1z"/>
</g>
</g>
<g>
<g>
<path class="st0" d="M50,196.1c0,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,4V196.1z"/>
</g>
</g>
<g>
<g>
<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>
<path class="st2" d="M50,96.1c0,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,4V96.1z"/>
</g>
</g>
<path class="st1" d="M33.2,114.1H32v-0.9c0-1.6-2-2.1-3.6-2.1h-7c-1.6,0-2.4,0.5-2.4,2.1v0.9h-3c-1.6,0-3,0.8-3,2.4v10.7
c0,1.6,1.3,2.9,3,2.9h17.2c1.6,0,3.8-1.7,3.8-3.3v-10.3C37,114.9,34.8,114.1,33.2,114.1z M24.7,128.1c-3.8,0-6.8-3.1-6.8-6.8
c0-3.8,3.1-6.8,6.8-6.8c3.8,0,6.8,3.1,6.8,6.8C31.5,125,28.5,128.1,24.7,128.1z"/>
<g>
<path class="st1" d="M17.3,137.8c0,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.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.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.9s-0.3,0.4-0.5,0.6c-0.2,0.1-0.5,0.3-0.8,0.3s-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.2s-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.3c-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.5L17.3,137.8z"/>
<path class="st1" d="M20.5,138.4v4.1h-1.2v-6.4h1l3.3,4.2v-4.2h1.2v6.4h-1L20.5,138.4z"/>
<path class="st1" d="M25.7,142.5l2.5-6.4h1l2.5,6.4h-1.3l-0.6-1.6h-2.2l-0.6,1.6H25.7z M28.8,137.5l-0.9,2.6h1.8L28.8,137.5z"/>
<path class="st1" d="M32.7,142.5v-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.1H32.7z M33.9,139.3h1.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.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-0.2-0.1-0.3-0.1h-1.4V139.3z"/>
</g>
<path class="st1" d="M33.2,64.1H32v-1c0-1.6-2-2-3.6-2h-7c-1.6,0-2.4,0.4-2.4,2v1h-3c-1.6,0-3,0.7-3,2.3v10.7c0,1.6,1.3,3,3,3h17.2
c1.6,0,3.8-1.8,3.8-3.4V66.4C37,64.8,34.8,64.1,33.2,64.1z M24.7,78c-3.8,0-6.8-3.1-6.8-6.8c0-3.8,3.1-6.8,6.8-6.8
c3.8,0,6.8,3.1,6.8,6.8C31.5,74.9,28.5,78,24.7,78z"/>
<g>
<path class="st1" d="M17.3,87.7c0,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.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.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.9s-0.3,0.4-0.5,0.6c-0.2,0.1-0.5,0.3-0.8,0.3s-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.3C16.2,90,16,90,15.8,89.9s-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.3c-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.4C15,86,15.3,86,15.7,86c0.5,0,0.9,0.1,1.2,0.2c0.4,0.1,0.7,0.3,1,0.5L17.3,87.7z"/>
<path class="st1" d="M20.5,88.3v4.1h-1.2V86h1l3.3,4.2V86h1.2v6.4h-1L20.5,88.3z"/>
<path class="st1" d="M25.7,92.4l2.5-6.4h1l2.5,6.4h-1.3l-0.6-1.6h-2.2l-0.6,1.6H25.7z M28.8,87.4L27.8,90h1.8L28.8,87.4z"/>
<path class="st1" d="M32.7,92.4V86h2.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.1H32.7z M33.9,89.2h1.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.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-0.2-0.1-0.3-0.1h-1.4V89.2z"/>
</g>
<path class="st1" d="M33.2,164.1H32v-0.8c0-1.6-2-2.2-3.6-2.2h-7c-1.6,0-2.4,0.6-2.4,2.2v0.8h-3c-1.6,0-3,0.9-3,2.5v10.7
c0,1.6,1.3,2.8,3,2.8h17.2c1.6,0,3.8-1.6,3.8-3.2v-10.3C37,165,34.8,164.1,33.2,164.1z M24.7,178.2c-3.8,0-6.8-3.1-6.8-6.8
s3.1-6.8,6.8-6.8c3.8,0,6.8,3.1,6.8,6.8S28.5,178.2,24.7,178.2z"/>
<g>
<path class="st1" d="M17.3,187.9c0,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.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.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.9s-0.3,0.4-0.5,0.6c-0.2,0.1-0.5,0.3-0.8,0.3s-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.2s-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.3c-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.5L17.3,187.9z"/>
<path class="st1" d="M20.5,188.5v4.1h-1.2v-6.4h1l3.3,4.2v-4.2h1.2v6.4h-1L20.5,188.5z"/>
<path class="st1" d="M25.7,192.6l2.5-6.4h1l2.5,6.4h-1.3l-0.6-1.6h-2.2l-0.6,1.6H25.7z M28.8,187.6l-0.9,2.6h1.8L28.8,187.6z"/>
<path class="st1" d="M32.7,192.6v-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.1H32.7z M33.9,189.4h1.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.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-0.2-0.1-0.3-0.1h-1.4V189.4z"/>
</g>
<path class="st3" d="M33.2,14.1H32v-0.7c0-1.6-2-2.3-3.6-2.3h-7c-1.6,0-2.4,0.6-2.4,2.3v0.7h-3c-1.6,0-3,0.9-3,2.5v10.7
c0,1.6,1.3,2.7,3,2.7h17.2c1.6,0,3.8-1.6,3.8-3.2V16.6C37,15,34.8,14.1,33.2,14.1z M24.7,28.2c-3.8,0-6.8-3.1-6.8-6.8
c0-3.8,3.1-6.8,6.8-6.8c3.8,0,6.8,3.1,6.8,6.8C31.5,25.2,28.5,28.2,24.7,28.2z"/>
<g>
<path class="st3" d="M17.3,38c0,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.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.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.9s-0.3,0.4-0.5,0.6c-0.2,0.1-0.5,0.3-0.8,0.3s-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.2S15.4,40,15.1,40
c-0.3-0.1-0.6-0.2-0.8-0.3c-0.2-0.1-0.4-0.2-0.6-0.3c-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.5L17.3,38z"/>
<path class="st3" d="M20.5,38.6v4.1h-1.2v-6.4h1l3.3,4.2v-4.2h1.2v6.4h-1L20.5,38.6z"/>
<path class="st3" d="M25.7,42.7l2.5-6.4h1l2.5,6.4h-1.3l-0.6-1.6h-2.2l-0.6,1.6H25.7z M28.8,37.6l-0.9,2.6h1.8L28.8,37.6z"/>
<path class="st3" d="M32.7,42.7v-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.1H32.7z M33.9,39.5h1.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.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-0.2-0.1-0.3-0.1h-1.4V39.5z"/>
</g>
<circle class="st1" cx="24.7" cy="121.2" r="4"/>
<circle class="st1" cx="24.7" cy="171.3" r="4"/>
</svg>

After

(image error) Size: 8.5 KiB

View file

@ -553,6 +553,7 @@ function Teleporter() {
_this.smoothArrivalInterval = Script.setInterval(function() {
if (_this.arrivalPoints.length === 0) {
Script.clearInterval(_this.smoothArrivalInterval);
HMD.centerUI();
return;
}
var landingPoint = _this.arrivalPoints.shift();
@ -564,6 +565,8 @@ function Teleporter() {
}
}, SMOOTH_ARRIVAL_SPACING);
}
}

View file

@ -143,7 +143,6 @@ function showMarketplace(marketplaceID) {
if (marketplaceID) {
url = url + "/items/" + marketplaceID;
}
print("setting marketplace URL to " + url);
marketplaceWindow.setURL(url);
marketplaceWindow.setVisible(true);
marketplaceWindow.raise();
@ -216,7 +215,6 @@ var toolBar = (function () {
}
function initialize() {
print("QQQ creating edit toolbar");
Script.scriptEnding.connect(cleanup);
Window.domainChanged.connect(function () {
@ -794,7 +792,6 @@ var modelMenuAddedDelete = false;
var originalLightsArePickable = Entities.getLightsArePickable();
function setupModelMenus() {
print("setupModelMenus()");
// adj our menuitems
Menu.addMenuItem({
menuName: "Edit",
@ -803,7 +800,6 @@ function setupModelMenus() {
grouping: "Advanced"
});
if (!Menu.menuItemExists("Edit", "Delete")) {
print("no delete... adding ours");
Menu.addMenuItem({
menuName: "Edit",
menuItemName: "Delete",
@ -814,8 +810,6 @@ function setupModelMenus() {
grouping: "Advanced"
});
modelMenuAddedDelete = true;
} else {
print("delete exists... don't add ours");
}
Menu.addMenuItem({
@ -1046,8 +1040,6 @@ function deleteSelectedEntities() {
}
SelectionManager.clearSelections();
pushCommandForSelections([], savedProperties);
} else {
print(" Delete Entity.... not holding...");
}
}
@ -1163,7 +1155,6 @@ function getPositionToImportEntity() {
return position;
}
function importSVO(importURL) {
print("Import URL requested: " + importURL);
if (!Entities.canAdjustLocks()) {
Window.alert(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG);
return;
@ -1427,6 +1418,8 @@ var PropertiesTool = function (opts) {
}
pushCommandForSelections();
selectionManager._update();
} else if(data.type === 'saveUserData'){
Entities.editEntity(data.id, data.properties)
} else if (data.type === "showMarketplace") {
showMarketplace();
} else if (data.type === "action") {

View file

@ -0,0 +1,48 @@
<html>
<head>
<title>Share</title>
<link rel="stylesheet" type="text/css" href="css/edit-style.css">
<link rel="stylesheet" type="text/css" href="css/SnapshotReview.css">
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script type="text/javascript" src="js/eventBridgeLoader.js"></script>
<script type="text/javascript" src="js/SnapshotReview.js"></script>
</head>
<body>
<div class="snapshot-container">
<div class="snapshot-column-left">
<div class="snapsection">
<label class="title">Snapshot successfully saved!</label>
</div>
<hr />
<div class="snapsection">
<div id="sharing">
<div class="prompt">Would you like to share your pic in the Snapshots feed?</div>
<div class="button">
<span class="compound-button">
<input type="button" class="blue" id="share" value="Share in Feed" onclick="shareSelected()"/>
<span class="glyph"></span>
</span>
</div>
</div>
<div class="button">
<input type="button" class="black" id="close" value="Don't Share" onclick="doNotShare()"/>
</div>
</div>
<hr />
<div class="snapsection">
<span class="setting">
<input type="button" class="glyph naked" id="snapshotSettings" value="@" onclick="snapshotSettings()" />
<label for="snapshotSettings">Snapshot settings</label>
</span>
<span class="setting checkbox">
<input id="openFeed" type="checkbox" checked/>
<label for="openFeed">Open feed after</label>
</span>
</div>
</div>
<div id="snapshot-images" class="snapshot-column-right"/>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,131 @@
/*
// SnapshotReview.css
//
// Created by Howard Stearns for David Rowe 8/22/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
*/
.snapshot-container {
width: 100%;
padding-top: 3px;
}
.snapshot-column-left {
width: 320px;
position: absolute;
padding-top: 8px;
}
.snapshot-column-right {
margin-left: 342px;
}
.snapshot-column-right > div > img {
width: 100%;
}
@media (max-width: 768px) {
.snapshot-column-left {
position: initial;
width: 100%;
}
.snapshot-column-right {
margin-left: 0;
width: 100%;
}
.snapshot-column-right > div > img {
margin-top: 18px !important;
}
}
.snapshot-column-right > div {
position: relative;
padding: 2px;
}
.snapshot-column-right > div > img {
border: 2px solid #575757;
margin: -2px;
}
hr {
padding-left: 0;
padding-right: 0;
margin: 21px 0;
}
.snapsection {
text-align: center;
}
.title {
text-transform: uppercase;
font-size: 12px;
}
.prompt {
font-family: Raleway-SemiBold;
font-size: 14px;
}
div.button {
padding-top: 21px;
}
.compound-button {
position: relative;
height: auto;
}
.compound-button input {
padding-left: 40px;
}
.compound-button .glyph {
display: inline-block;
position: absolute;
left: 12px;
top: 16px;
width: 23px;
height: 23px;
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgaGVpZ2h0PSI0MCIKICAgd2lkdGg9IjQwIgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIKICAgdmlld0JveD0iMCAwIDQwIDQwIgogICB5PSIwcHgiCiAgIHg9IjBweCIKICAgdmVyc2lvbj0iMS4xIj48bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGEzNCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48ZGM6dGl0bGU+PC9kYzp0aXRsZT48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczMyIiAvPjxzdHlsZQogICAgIGlkPSJzdHlsZTQiCiAgICAgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsOiM0MTQwNDI7fQoJLnN0MXtmaWxsOiNDQ0NDQ0M7fQoJLnN0MntmaWxsOiMxMzk4QkI7fQoJLnN0M3tmaWxsOiMzMUQ4RkY7fQo8L3N0eWxlPjxnCiAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtMTEwKSIKICAgICBpZD0iTGF5ZXJfMSI+PGNpcmNsZQogICAgICAgc3R5bGU9ImZpbGw6I2ZmZmZmZjtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJjaXJjbGUxMyIKICAgICAgIHI9IjQuNDQwMDAwMSIKICAgICAgIGN5PSIxMjYuMTciCiAgICAgICBjeD0iMjAuNTQwMDAxIgogICAgICAgY2xhc3M9InN0MSIgLz48cGF0aAogICAgICAgc3R5bGU9ImZpbGw6I2ZmZmZmZjtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJwYXRoMTUiCiAgICAgICBkPSJtIDI4Ljg3LDEzOS4yNiBjIDAuMDEsLTAuMDEgMC4wMiwtMC4wMiAwLjAzLC0wLjAzIGwgMCwtMS44NiBjIDAsLTIuNjggLTIuMzMsLTQuNzcgLTUsLTQuNzcgbCAtNi40MiwwIGMgLTIuNjgsMCAtNC44NSwyLjA5IC00Ljg1LDQuNzcgbCAwLDEuODggMTYuMjQsMCB6IgogICAgICAgY2xhc3M9InN0MSIgLz48cGF0aAogICAgICAgc3R5bGU9ImZpbGw6I2ZmZmZmZjtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJwYXRoMTciCiAgICAgICBkPSJtIDM4LjE3LDEyMy40MiBjIDAsLTMuOTcgLTMuMjIsLTcuMTkgLTcuMTksLTcuMTkgbCAtMjAuMzEsMCBjIC0zLjk3LDAgLTcuMTksMy4yMiAtNy4xOSw3LjE5IGwgMCwxNC4xOCBjIDAsMy45NyAzLjIyLDcuMTkgNy4xOSw3LjE5IGwgMjAuMzEsMCBjIDMuOTcsMCA3LjE5LC0zLjIyIDcuMTksLTcuMTkgbCAwLC0xNC4xOCB6IG0gLTEuNzgsMTQuMjcgYyAwLDMuMDMgLTIuNDYsNS40OSAtNS40OSw1LjQ5IGwgLTIwLjMyLDAgYyAtMy4wMywwIC01LjQ5LC0yLjQ2IC01LjQ5LC01LjQ5IGwgMCwtMTQuMTkgYyAwLC0zLjAzIDIuNDYsLTUuNDkgNS40OSwtNS40OSBsIDIwLjMzLDAgYyAzLjAzLDAgNS40OSwyLjQ2IDUuNDksNS40OSBsIDAsMTQuMTkgeiIKICAgICAgIGNsYXNzPSJzdDEiIC8+PC9nPjxnCiAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwtMTEwKSIKICAgICBpZD0iTGF5ZXJfMiIgLz48L3N2Zz4=);
background-repeat: no-repeat;
background-size: 23px 23px;
}
.setting {
display: inline-table;
height: 28px;
}
.setting label {
display: table-cell;
vertical-align: middle;
font-family: Raleway-SemiBold;
font-size: 14px;
}
.setting + .setting {
margin-left: 18px;
}
input[type=button].naked {
font-size: 40px;
line-height: 40px;
width: 30px;
padding: 0;
margin: 0 0 -6px 0;
position: relative;
top: -6px;
left: -8px;
background: none;
}
input[type=button].naked:hover {
color: #00b4ef;
background: none;
}

View file

@ -798,7 +798,7 @@ tuple, .blue:focus, .tuple .z:focus, .tuple .roll:focus {
}
::-webkit-scrollbar {
width: 10px;
width: 20px;
height: 10px;
}
::-webkit-scrollbar-track {
@ -1081,3 +1081,25 @@ input#reset-to-natural-dimensions {
#animation-fps {
margin-top: 48px;
}
#userdata-clear{
margin-bottom: 10px;
}
#static-userdata{
display: none;
z-index: 99;
position: absolute;
width: 96%;
padding-left:1%;
margin-top:5px;
margin-bottom:10px;
background-color: #2e2e2e;
}
#userdata-saved{
margin-top:5px;
font-size:16px;
display:none;
}

View file

@ -0,0 +1,893 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="216"
height="144"
id="svg4136"
version="1.1"
inkscape:version="0.91 r"
sodipodi:docname="jsoneditor-icons.svg">
<title
id="title6512">JSON Editor Icons</title>
<metadata
id="metadata4148">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>JSON Editor Icons</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4146" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1028"
id="namedview4144"
showgrid="true"
inkscape:zoom="4"
inkscape:cx="97.217248"
inkscape:cy="59.950227"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4136"
showguides="false"
borderlayer="false"
inkscape:showpageshadow="true"
showborder="true">
<inkscape:grid
type="xygrid"
id="grid4640"
empspacing="24" />
</sodipodi:namedview>
<!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
<g
id="g4394">
<rect
x="4"
y="4"
width="16"
height="16"
id="svg_1"
style="fill:#1aae1c;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
style="fill:#ec3f29;fill-opacity:0.94117647;stroke:none;stroke-width:0"
x="28.000006"
y="3.999995"
width="16"
height="16"
id="svg_1-7" />
<rect
id="rect4165"
height="16"
width="16"
y="3.999995"
x="52.000004"
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
x="172.00002"
y="3.9999852"
width="16"
height="16"
id="rect4175" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
x="196"
y="3.999995"
width="16"
height="16"
id="rect4175-3" />
<g
style="stroke:none"
id="g4299">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1-1"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<g
style="stroke:none"
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,19.029435,12.000001)"
id="g4299-3">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1-0"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1-1-9"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="55.000004"
y="7.0000048"
width="6.9999909"
height="6.9999905"
id="svg_1-7-5" />
<rect
id="rect4354"
height="6.9999905"
width="6.9999909"
y="10.00001"
x="58"
style="fill:#ffffff;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#3c80df;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
x="58.000004"
y="10.000005"
width="6.9999909"
height="6.9999905"
id="svg_1-7-5-7" />
<g
id="g4378">
<rect
id="svg_1-7-5-3"
height="1.9999965"
width="7.9999909"
y="10.999999"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="7.0000005"
width="11.999995"
height="1.9999946"
id="rect4374" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="14.999996"
width="3.9999928"
height="1.9999995"
id="rect4376" />
</g>
<g
id="g4383"
transform="matrix(1,0,0,-1,-23.999995,23.999995)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="10.999999"
width="7.9999909"
height="1.9999965"
id="rect4385" />
<rect
id="rect4387"
height="1.9999946"
width="11.999995"
y="7.0000005"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
id="rect4389"
height="1.9999995"
width="3.9999928"
y="14.999996"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
</g>
<rect
y="3.9999199"
x="76"
height="16"
width="16"
id="rect3754-4"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="cccccccc"
inkscape:connector-curvature="0"
id="path4351"
d="m 85.10447,6.0157384 -0.0156,1.4063 c 3.02669,-0.2402 0.33008,3.6507996 2.48438,4.5780996 -2.18694,1.0938 0.49191,4.9069 -2.45313,4.5781 l -0.0156,1.4219 c 5.70828,0.559 1.03264,-5.1005 4.70313,-5.2656 l 0,-1.4063 c -3.61303,-0.027 1.11893,-5.7069996 -4.70313,-5.3124996 z"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="cccccccc"
inkscape:connector-curvature="0"
id="path4351-9"
d="m 82.78125,5.9984384 0.0156,1.4063 c -3.02668,-0.2402 -0.33007,3.6506996 -2.48437,4.5780996 2.18694,1.0938 -0.49192,4.9069 2.45312,4.5781 l 0.0156,1.4219 c -5.70827,0.559 -1.03263,-5.1004 -4.70312,-5.2656 l 0,-1.4063 c 3.61303,-0.027 -1.11894,-5.7070996 4.70312,-5.3124996 z"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
y="3.9999199"
x="100"
height="16"
width="16"
id="rect3754-25"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path2987"
d="m 103.719,5.6719384 0,12.7187996 3.03125,0 0,-1.5313 -1.34375,0 0,-9.6249996 1.375,0 0,-1.5625 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path2987-1"
d="m 112.2185,5.6721984 0,12.7187996 -3.03125,0 0,-1.5313 1.34375,0 0,-9.6249996 -1.375,0 0,-1.5625 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<rect
y="3.9999199"
x="124"
height="16"
width="16"
id="rect3754-73"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0"
id="path3780"
d="m 126.2824,17.602938 1.78957,0 1.14143,-2.8641 5.65364,0 1.14856,2.8641 1.76565,0 -4.78687,-11.1610996 -1.91903,0 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path3782"
d="m 129.72704,13.478838 4.60852,0.01 -2.30426,-5.5497996 z"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<rect
y="3.9999199"
x="148"
height="16"
width="16"
id="rect3754-35"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="path5008-2"
d="m 156.47655,5.8917384 0,2.1797 0.46093,2.3983996 1.82813,0 0.39844,-2.3983996 0,-2.1797 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="path5008-2-8"
d="m 152.51561,5.8906384 0,2.1797 0.46094,2.3983996 1.82812,0 0.39844,-2.3983996 0,-2.1797 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
</g>
<rect
x="4"
y="27.999994"
width="16"
height="16"
id="rect4432"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0"
x="28.000006"
y="27.99999"
width="16"
height="16"
id="rect4434" />
<rect
id="rect4436"
height="16"
width="16"
y="27.99999"
x="52.000004"
style="fill:#d3d3d3;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#d3d3d3;stroke:#000000;stroke-width:0"
x="172.00002"
y="27.999981"
width="16"
height="16"
id="rect4446" />
<rect
style="fill:#d3d3d3;stroke:#000000;stroke-width:0"
x="196"
y="27.99999"
width="16"
height="16"
id="rect4448" />
<g
id="g4466"
style="stroke:none"
transform="translate(0,23.999995)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4468"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4470"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<g
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,19.029435,35.999996)"
id="g4472"
style="stroke:none">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4474"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4476"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="55.000004"
y="31"
width="6.9999909"
height="6.9999905"
id="rect4478" />
<rect
id="rect4480"
height="6.9999905"
width="6.9999909"
y="34.000008"
x="58"
style="fill:#ffffff;fill-opacity:1;stroke:#d3d3d3;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#d3d3d3;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
x="58.000004"
y="34.000004"
width="6.9999909"
height="6.9999905"
id="rect4482" />
<g
id="g4484"
transform="translate(0,23.999995)">
<rect
id="rect4486"
height="1.9999965"
width="7.9999909"
y="10.999999"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="7.0000005"
width="11.999995"
height="1.9999946"
id="rect4488" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="14.999996"
width="3.9999928"
height="1.9999995"
id="rect4490" />
</g>
<g
id="g4492"
transform="matrix(1,0,0,-1,-23.999995,47.99999)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="10.999999"
width="7.9999909"
height="1.9999965"
id="rect4494" />
<rect
id="rect4496"
height="1.9999946"
width="11.999995"
y="7.0000005"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
id="rect4498"
height="1.9999995"
width="3.9999928"
y="14.999996"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
</g>
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-8"
width="16"
height="16"
x="76"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 85.10448,30.015537 -0.0156,1.4063 c 3.02668,-0.2402 0.33007,3.6508 2.48438,4.5781 -2.18695,1.0938 0.49191,4.90688 -2.45313,4.57808 l -0.0156,1.4219 c 5.70827,0.559 1.03263,-5.10048 4.70313,-5.26558 l 0,-1.4063 c -3.61304,-0.027 1.11893,-5.707 -4.70313,-5.3125 z"
id="path4351-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 82.78126,29.998237 0.0156,1.4063 c -3.02668,-0.2402 -0.33008,3.6507 -2.48438,4.5781 2.18694,1.0938 -0.49191,4.90688 2.45313,4.57808 l 0.0156,1.4219 c -5.70828,0.559 -1.03264,-5.10038 -4.70313,-5.26558 l 0,-1.4063 c 3.61303,-0.027 -1.11893,-5.7071 4.70313,-5.3125 z"
id="path4351-9-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-65"
width="16"
height="16"
x="100"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 103.719,29.671937 0,12.71878 3.03125,0 0,-1.5313 -1.34375,0 0,-9.62498 1.375,0 0,-1.5625 z"
id="path2987-8"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 112.2185,29.671937 0,12.71878 -3.03125,0 0,-1.5313 1.34375,0 0,-9.62498 -1.375,0 0,-1.5625 z"
id="path2987-1-9"
inkscape:connector-curvature="0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-92"
width="16"
height="16"
x="124"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 126.2824,41.602917 1.78957,0 1.14143,-2.86408 5.65364,0 1.14856,2.86408 1.76565,0 -4.78687,-11.16108 -1.91902,0 z"
id="path3780-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
<path
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
d="m 129.72704,37.478837 4.60852,0.01 -2.30426,-5.5498 z"
id="path3782-2"
inkscape:connector-curvature="0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-47"
width="16"
height="16"
x="148"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 156.47656,29.891737 0,2.1797 0.46093,2.3984 1.82813,0 0.39844,-2.3984 0,-2.1797 z"
id="path5008-2-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 152.51562,29.890637 0,2.1797 0.46094,2.3984 1.82812,0 0.39844,-2.3984 0,-2.1797 z"
id="path5008-2-8-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<rect
id="svg_1-7-2"
height="1.9999961"
width="11.999996"
y="64"
x="54"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
id="svg_1-7-2-2"
height="2.9999905"
width="2.9999907"
y="52"
x="80.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="85.000008"
y="52"
width="2.9999907"
height="2.9999905"
id="rect4561" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="80.000008"
y="58"
width="2.9999907"
height="2.9999905"
id="rect4563" />
<rect
id="rect4565"
height="2.9999905"
width="2.9999907"
y="58"
x="85.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
id="rect4567"
height="2.9999905"
width="2.9999907"
y="64"
x="80.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="85.000008"
y="64"
width="2.9999907"
height="2.9999905"
id="rect4569" />
<circle
style="opacity:1;fill:none;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4571"
cx="110.06081"
cy="57.939209"
r="4.7438836" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="116.64566"
y="-31.79752"
width="4.229713"
height="6.4053884"
id="rect4563-2"
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" />
<path
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 125,56 138.77027,56.095 132,64 Z"
id="path4613"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4615"
d="M 149,64 162.77027,63.905 156,56 Z"
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="54"
y="53"
width="11.999996"
height="1.9999961"
id="rect4638" />
<rect
id="svg_1-7-2-24"
height="1.9999957"
width="12.99999"
y="-56"
x="53"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
transform="matrix(0,1,-1,0,0,0)" />
<rect
transform="matrix(0,1,-1,0,0,0)"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="53"
y="-66"
width="12.99999"
height="1.9999957"
id="rect4657" />
<rect
id="rect4659"
height="0.99999291"
width="11.999999"
y="57"
x="54"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="54"
y="88.000122"
width="11.999996"
height="1.9999961"
id="rect4661" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="80.000008"
y="76.000122"
width="2.9999907"
height="2.9999905"
id="rect4663" />
<rect
id="rect4665"
height="2.9999905"
width="2.9999907"
y="76.000122"
x="85.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
id="rect4667"
height="2.9999905"
width="2.9999907"
y="82.000122"
x="80.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="85.000008"
y="82.000122"
width="2.9999907"
height="2.9999905"
id="rect4669" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="80.000008"
y="88.000122"
width="2.9999907"
height="2.9999905"
id="rect4671" />
<rect
id="rect4673"
height="2.9999905"
width="2.9999907"
y="88.000122"
x="85.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<circle
r="4.7438836"
cy="81.939331"
cx="110.06081"
id="circle4675"
style="opacity:1;fill:none;fill-opacity:1;stroke:#d3d3d3;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)"
id="rect4677"
height="6.4053884"
width="4.229713"
y="-14.826816"
x="133.6163"
style="fill:#d3d3d3;fill-opacity:1;stroke:#d3d3d3;stroke-width:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4679"
d="m 125,80.000005 13.77027,0.09499 L 132,87.999992 Z"
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 149,88.0002 162.77027,87.9052 156,80.0002 Z"
id="path4681"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<rect
id="rect4683"
height="1.9999961"
width="11.999996"
y="77.000122"
x="54"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
transform="matrix(0,1,-1,0,0,0)"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="77.000122"
y="-56"
width="12.99999"
height="1.9999957"
id="rect4685" />
<rect
id="rect4687"
height="1.9999957"
width="12.99999"
y="-66"
x="77.000122"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
transform="matrix(0,1,-1,0,0,0)" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="54"
y="81.000122"
width="11.999999"
height="0.99999291"
id="rect4689" />
<rect
id="rect4761-1"
height="1.9999945"
width="15.99999"
y="101"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-0"
height="1.9999945"
width="15.99999"
y="105"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-7"
height="1.9999945"
width="9"
y="109"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1"
height="1.9999945"
width="12"
y="125"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4"
height="1.9999945"
width="10"
y="137"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4-4"
height="1.9999945"
width="10"
y="129"
x="82"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4-4-3"
height="1.9999945"
width="9"
y="133"
x="82"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 36.398438,100.0254 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,100.5991 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1452 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533865,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550756,0 6.710442,-2.4113 7.650391,-5.9414 0.939949,-3.5301 -0.618463,-7.2736 -3.710938,-9.0703 -1.159678,-0.6738 -2.431087,-1.0231 -3.701171,-1.0625 z"
id="path4138" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 59.722656,99.9629 c -1.270084,0.039 -2.541493,0.3887 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5402 -3.710937,9.0703 0.939949,3.5301 4.09768,5.9414 7.648437,5.9414 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4056 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
id="path4138-1" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
d="m 10.5,100 0,2 -2.4999996,0 L 12,107 l 4,-5 -2.5,0 0,-2 -3,0 z"
id="path3055-0-77" />
<path
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.966;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.9850574,108.015 14.0298856,-0.03"
id="path5244-5-0-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.966;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.9849874,132.015 14.0298866,-0.03"
id="path5244-5-0-5-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 36.398438,123.9629 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,124.5366 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1453 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533864,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550757,0 6.710442,-2.4093 7.650391,-5.9394 0.939949,-3.5301 -0.618463,-7.2756 -3.710938,-9.0723 -1.159678,-0.6737 -2.431087,-1.0231 -3.701171,-1.0625 z"
id="path4138-12" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 59.722656,123.9629 c -1.270084,0.039 -2.541493,0.3888 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5422 -3.710937,9.0723 0.939949,3.5301 4.09768,5.9394 7.648437,5.9394 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4055 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
id="path4138-1-3" />
<path
id="path6191"
d="m 10.5,116 0,-2 -2.4999996,0 L 12,109 l 4,5 -2.5,0 0,2 -3,0 z"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
d="m 10.5,129 0,-2 -2.4999996,0 L 12,122 l 4,5 -2.5,0 0,2 -3,0 z"
id="path6193" />
<path
id="path6195"
d="m 10.5,135 0,2 -2.4999996,0 L 12,142 l 4,-5 -2.5,0 0,-2 -3,0 z"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
sodipodi:type="star"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4500"
sodipodi:sides="3"
sodipodi:cx="11.55581"
sodipodi:cy="60.073242"
sodipodi:r1="5.1116104"
sodipodi:r2="2.5558052"
sodipodi:arg1="0"
sodipodi:arg2="1.0471976"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 16.66742,60.073242 -3.833708,2.213392 -3.8337072,2.213393 0,-4.426785 0,-4.426784 3.8337082,2.213392 z"
inkscape:transform-center-x="-1.2779026" />
<path
inkscape:transform-center-x="1.277902"
d="m -31.500004,60.073242 -3.833708,2.213392 -3.833707,2.213393 0,-4.426785 0,-4.426784 3.833707,2.213392 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="false"
sodipodi:arg2="1.0471976"
sodipodi:arg1="0"
sodipodi:r2="2.5558052"
sodipodi:r1="5.1116104"
sodipodi:cy="60.073242"
sodipodi:cx="-36.611614"
sodipodi:sides="3"
id="path4502"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:type="star"
transform="scale(-1,1)" />
<path
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="false"
sodipodi:arg2="1.0471976"
sodipodi:arg1="0"
sodipodi:r2="2.5558052"
sodipodi:r1="5.1116104"
sodipodi:cy="60.073212"
sodipodi:cx="11.55581"
sodipodi:sides="3"
id="path4504"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:type="star"
transform="matrix(0,1,-1,0,72.0074,71.7877)"
inkscape:transform-center-y="1.2779029" />
<path
inkscape:transform-center-y="-1.2779026"
transform="matrix(0,-1,-1,0,96,96)"
sodipodi:type="star"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4506"
sodipodi:sides="3"
sodipodi:cx="11.55581"
sodipodi:cy="60.073212"
sodipodi:r1="5.1116104"
sodipodi:r2="2.5558052"
sodipodi:arg1="0"
sodipodi:arg2="1.0471976"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4615-5"
d="m 171.82574,65.174193 16.34854,0 -8.17427,-13.348454 z"
style="fill:#fbb917;fill-opacity:1;fill-rule:evenodd;stroke:#fbb917;stroke-width:1.65161395;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 179,55 0,6 2,0 0,-6"
id="path4300"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 179,62 0,2 2,0 0,-2"
id="path4300-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</svg>

After

(image error) Size: 35 KiB

View file

@ -0,0 +1,934 @@
/* reset styling (prevent conflicts with bootstrap, materialize.css, etc.) */
div.jsoneditor input {
height: auto;
border: inherit;
}
div.jsoneditor input:focus {
border: none !important;
box-shadow: none !important;
}
div.jsoneditor table {
border-collapse: collapse;
width: auto;
}
div.jsoneditor td,
div.jsoneditor th {
padding: 0;
display: table-cell;
text-align: left;
vertical-align: inherit;
border-radius: inherit;
}
div.jsoneditor-field,
div.jsoneditor-value,
div.jsoneditor-readonly {
border: 1px solid transparent;
min-height: 16px;
min-width: 32px;
padding: 2px;
margin: 1px;
word-wrap: break-word;
float: left;
}
/* adjust margin of p elements inside editable divs, needed for Opera, IE */
div.jsoneditor-field p,
div.jsoneditor-value p {
margin: 0;
}
div.jsoneditor-value {
word-break: break-word;
}
div.jsoneditor-readonly {
min-width: 16px;
color: red;
}
div.jsoneditor-empty {
border-color: lightgray;
border-style: dashed;
border-radius: 2px;
}
div.jsoneditor-field.jsoneditor-empty::after,
div.jsoneditor-value.jsoneditor-empty::after {
pointer-events: none;
color: lightgray;
font-size: 8pt;
}
div.jsoneditor-field.jsoneditor-empty::after {
content: "field";
}
div.jsoneditor-value.jsoneditor-empty::after {
content: "value";
}
div.jsoneditor-value.jsoneditor-url,
a.jsoneditor-value.jsoneditor-url {
color: green;
text-decoration: underline;
}
a.jsoneditor-value.jsoneditor-url {
display: inline-block;
padding: 2px;
margin: 2px;
}
a.jsoneditor-value.jsoneditor-url:hover,
a.jsoneditor-value.jsoneditor-url:focus {
color: #ee422e;
}
div.jsoneditor td.jsoneditor-separator {
padding: 3px 0;
vertical-align: top;
color: gray;
}
div.jsoneditor-field[contenteditable=true]:focus,
div.jsoneditor-field[contenteditable=true]:hover,
div.jsoneditor-value[contenteditable=true]:focus,
div.jsoneditor-value[contenteditable=true]:hover,
div.jsoneditor-field.jsoneditor-highlight,
div.jsoneditor-value.jsoneditor-highlight {
background-color: #FFFFAB;
border: 1px solid yellow;
border-radius: 2px;
}
div.jsoneditor-field.jsoneditor-highlight-active,
div.jsoneditor-field.jsoneditor-highlight-active:focus,
div.jsoneditor-field.jsoneditor-highlight-active:hover,
div.jsoneditor-value.jsoneditor-highlight-active,
div.jsoneditor-value.jsoneditor-highlight-active:focus,
div.jsoneditor-value.jsoneditor-highlight-active:hover {
background-color: #ffee00;
border: 1px solid #ffc700;
border-radius: 2px;
}
div.jsoneditor-value.jsoneditor-string {
color: #008000;
}
div.jsoneditor-value.jsoneditor-object,
div.jsoneditor-value.jsoneditor-array {
min-width: 16px;
color: #808080;
}
div.jsoneditor-value.jsoneditor-number {
color: #ee422e;
}
div.jsoneditor-value.jsoneditor-boolean {
color: #ff8c00;
}
div.jsoneditor-value.jsoneditor-null {
color: #004ED0;
}
div.jsoneditor-value.jsoneditor-invalid {
color: #000000;
}
div.jsoneditor-tree button {
width: 24px;
height: 24px;
padding: 0;
margin: 0;
border: none;
cursor: pointer;
background: transparent url("img/jsoneditor-icons.svg");
}
div.jsoneditor-mode-view tr.jsoneditor-expandable td.jsoneditor-tree,
div.jsoneditor-mode-form tr.jsoneditor-expandable td.jsoneditor-tree {
cursor: pointer;
}
div.jsoneditor-tree button.jsoneditor-collapsed {
background-position: 0 -48px;
}
div.jsoneditor-tree button.jsoneditor-expanded {
background-position: 0 -72px;
}
div.jsoneditor-tree button.jsoneditor-contextmenu {
background-position: -48px -72px;
}
div.jsoneditor-tree button.jsoneditor-contextmenu:hover,
div.jsoneditor-tree button.jsoneditor-contextmenu:focus,
div.jsoneditor-tree button.jsoneditor-contextmenu.jsoneditor-selected,
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu {
background-position: -48px -48px;
}
div.jsoneditor-tree *:focus {
outline: none;
}
div.jsoneditor-tree button:focus {
/* TODO: nice outline for buttons with focus
outline: #97B0F8 solid 2px;
box-shadow: 0 0 8px #97B0F8;
*/
background-color: #f5f5f5;
outline: #e5e5e5 solid 1px;
}
div.jsoneditor-tree button.jsoneditor-invisible {
visibility: hidden;
background: none;
}
#userdata-editor{
height:100%;
}
div.jsoneditor {
color: #1A1A1A;
border: 1px solid #2e2e2e;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
overflow: hidden;
position: relative;
padding: 0;
line-height: 100%;
}
div.jsoneditor-tree table.jsoneditor-tree {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
margin: 0;
}
div.jsoneditor-outer {
width: 100%;
height: 100%;
min-height: 150px;
margin: -35px 0 0 0;
padding: 0 0 0 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
overflow-y: auto;
}
textarea.jsoneditor-text,
.ace-jsoneditor {
min-height: 150px;
}
div.jsoneditor-tree {
width: 100%;
height: 100%;
position: relative;
}
textarea.jsoneditor-text {
width: 100%;
height: 100%;
margin: 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
outline-width: 0;
border: none;
background-color: white;
resize: none;
}
tr.jsoneditor-highlight,
tr.jsoneditor-selected {
background-color: #e6e6e6;
}
tr.jsoneditor-selected button.jsoneditor-dragarea,
tr.jsoneditor-selected button.jsoneditor-contextmenu {
visibility: hidden;
}
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea,
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu {
visibility: visible;
}
div.jsoneditor-tree button.jsoneditor-dragarea {
background: url("img/jsoneditor-icons.svg") -72px -72px;
cursor: move;
}
div.jsoneditor-tree button.jsoneditor-dragarea:hover,
div.jsoneditor-tree button.jsoneditor-dragarea:focus,
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea {
background-position: -72px -48px;
}
div.jsoneditor tr,
div.jsoneditor th,
div.jsoneditor td {
padding: 0;
margin: 0;
overflow: visible;
}
div.jsoneditor td {
vertical-align: top;
}
div.jsoneditor td.jsoneditor-tree {
vertical-align: top;
}
div.jsoneditor-field,
div.jsoneditor-value,
div.jsoneditor td,
div.jsoneditor th,
div.jsoneditor textarea,
.jsoneditor-schema-error {
font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif;
font-size: 10pt;
color: grey;
}
/* popover */
.jsoneditor-schema-error {
cursor: default;
display: inline-block;
/*font-family: arial, sans-serif;*/
height: 24px;
line-height: 24px;
position: relative;
text-align: center;
width: 24px;
}
div.jsoneditor-tree .jsoneditor-schema-error {
width: 24px;
height: 24px;
padding: 0;
margin: 0 4px 0 0;
background: url("img/jsoneditor-icons.svg") -168px -48px;
}
.jsoneditor-schema-error .jsoneditor-popover {
background-color: #4c4c4c;
border-radius: 3px;
box-shadow: 0 0 5px rgba(0,0,0,0.4);
color: #fff;
display: none;
padding: 7px 10px;
position: absolute;
width: 200px;
z-index: 4;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above {
bottom: 32px;
left: -98px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below {
top: 32px;
left: -98px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left {
top: -7px;
right: 32px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right {
top: -7px;
left: 32px;
}
.jsoneditor-schema-error .jsoneditor-popover:before {
border-right: 7px solid transparent;
border-left: 7px solid transparent;
content: '';
display: block;
left: 50%;
margin-left: -7px;
position: absolute;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above:before {
border-top: 7px solid #4c4c4c;
bottom: -7px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below:before {
border-bottom: 7px solid #4c4c4c;
top: -7px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left:before {
border-left: 7px solid #4c4c4c;
border-top: 7px solid transparent;
border-bottom: 7px solid transparent;
content: '';
top: 19px;
right: -14px;
left: inherit;
margin-left: inherit;
margin-top: -7px;
position: absolute;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right:before {
border-right: 7px solid #4c4c4c;
border-top: 7px solid transparent;
border-bottom: 7px solid transparent;
content: '';
top: 19px;
left: -14px;
margin-left: inherit;
margin-top: -7px;
position: absolute;
}
.jsoneditor-schema-error:hover .jsoneditor-popover,
.jsoneditor-schema-error:focus .jsoneditor-popover {
display: block;
-webkit-animation: fade-in .3s linear 1, move-up .3s linear 1;
-moz-animation: fade-in .3s linear 1, move-up .3s linear 1;
-ms-animation: fade-in .3s linear 1, move-up .3s linear 1;
}
@-webkit-keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@-moz-keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@-ms-keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/*@-webkit-keyframes move-up {*/
/*from { bottom: 24px; }*/
/*to { bottom: 32px; }*/
/*}*/
/*@-moz-keyframes move-up {*/
/*from { bottom: 24px; }*/
/*to { bottom: 32px; }*/
/*}*/
/*@-ms-keyframes move-up {*/
/*from { bottom: 24px; }*/
/*to { bottom: 32px; }*/
/*}*/
/* JSON schema errors displayed at the bottom of the editor in mode text and code */
.jsoneditor .jsoneditor-text-errors {
width: 100%;
border-collapse: collapse;
background-color: #ffef8b;
border-top: 1px solid #ffd700;
}
.jsoneditor .jsoneditor-text-errors td {
padding: 3px 6px;
vertical-align: middle;
}
.jsoneditor-text-errors .jsoneditor-schema-error {
border: none;
width: 24px;
height: 24px;
padding: 0;
margin: 0 4px 0 0;
background: url("img/jsoneditor-icons.svg") -168px -48px;
}
/* ContextMenu - main menu */
div.jsoneditor-contextmenu-root {
position: relative;
width: 0;
height: 0;
}
div.jsoneditor-contextmenu {
position: absolute;
box-sizing: content-box;
z-index: 99999;
}
div.jsoneditor-contextmenu ul,
div.jsoneditor-contextmenu li {
box-sizing: content-box;
}
div.jsoneditor-contextmenu ul {
position: relative;
left: 0;
top: 0;
width: 124px;
background: white;
border: 1px solid #d3d3d3;
box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3);
list-style: none;
margin: 0;
padding: 0;
}
div.jsoneditor-contextmenu ul li button {
padding: 0;
margin: 0;
width: 124px;
height: 24px;
border: none;
cursor: pointer;
color: #4d4d4d;
background: transparent;
font-size: 10pt;
font-family: arial, sans-serif;
box-sizing: border-box;
line-height: 26px;
text-align: left;
}
/* Fix button padding in firefox */
div.jsoneditor-contextmenu ul li button::-moz-focus-inner {
padding: 0;
border: 0;
}
div.jsoneditor-contextmenu ul li button:hover,
div.jsoneditor-contextmenu ul li button:focus {
color: #1a1a1a;
background-color: #f5f5f5;
outline: none;
}
div.jsoneditor-contextmenu ul li button.jsoneditor-default {
width: 92px;
}
div.jsoneditor-contextmenu ul li button.jsoneditor-expand {
float: right;
width: 32px;
height: 24px;
border-left: 1px solid #e5e5e5;
}
div.jsoneditor-contextmenu div.jsoneditor-icon {
float: left;
width: 24px;
height: 24px;
border: none;
padding: 0;
margin: 0;
background-image: url("img/jsoneditor-icons.svg");
}
div.jsoneditor-contextmenu ul li button div.jsoneditor-expand {
float: right;
width: 24px;
height: 24px;
padding: 0;
margin: 0 4px 0 0;
background: url("img/jsoneditor-icons.svg") 0 -72px;
opacity: 0.4;
}
div.jsoneditor-contextmenu ul li button:hover div.jsoneditor-expand,
div.jsoneditor-contextmenu ul li button:focus div.jsoneditor-expand,
div.jsoneditor-contextmenu ul li.jsoneditor-selected div.jsoneditor-expand,
div.jsoneditor-contextmenu ul li button.jsoneditor-expand:hover div.jsoneditor-expand,
div.jsoneditor-contextmenu ul li button.jsoneditor-expand:focus div.jsoneditor-expand {
opacity: 1;
}
div.jsoneditor-contextmenu div.jsoneditor-separator {
height: 0;
border-top: 1px solid #e5e5e5;
padding-top: 5px;
margin-top: 5px;
}
div.jsoneditor-contextmenu button.jsoneditor-remove > div.jsoneditor-icon {
background-position: -24px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-remove:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-remove:focus > div.jsoneditor-icon {
background-position: -24px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-append > div.jsoneditor-icon {
background-position: 0 -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-append:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-append:focus > div.jsoneditor-icon {
background-position: 0 0;
}
div.jsoneditor-contextmenu button.jsoneditor-insert > div.jsoneditor-icon {
background-position: 0 -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-insert:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-insert:focus > div.jsoneditor-icon {
background-position: 0 0;
}
div.jsoneditor-contextmenu button.jsoneditor-duplicate > div.jsoneditor-icon {
background-position: -48px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-duplicate:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-duplicate:focus > div.jsoneditor-icon {
background-position: -48px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-sort-asc > div.jsoneditor-icon {
background-position: -168px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-sort-asc:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-sort-asc:focus > div.jsoneditor-icon {
background-position: -168px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-sort-desc > div.jsoneditor-icon {
background-position: -192px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-sort-desc:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-sort-desc:focus > div.jsoneditor-icon {
background-position: -192px 0;
}
/* ContextMenu - sub menu */
div.jsoneditor-contextmenu ul li button.jsoneditor-selected,
div.jsoneditor-contextmenu ul li button.jsoneditor-selected:hover,
div.jsoneditor-contextmenu ul li button.jsoneditor-selected:focus {
color: white;
background-color: #ee422e;
}
div.jsoneditor-contextmenu ul li {
overflow: hidden;
}
div.jsoneditor-contextmenu ul li ul {
display: none;
position: relative;
left: -10px;
top: 0;
border: none;
box-shadow: inset 0 0 10px rgba(128, 128, 128, 0.5);
padding: 0 10px;
/* TODO: transition is not supported on IE8-9 */
-webkit-transition: all 0.3s ease-out;
-moz-transition: all 0.3s ease-out;
-o-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
}
div.jsoneditor-contextmenu ul li ul li button {
padding-left: 24px;
animation: all ease-in-out 1s;
}
div.jsoneditor-contextmenu ul li ul li button:hover,
div.jsoneditor-contextmenu ul li ul li button:focus {
background-color: #f5f5f5;
}
div.jsoneditor-contextmenu button.jsoneditor-type-string > div.jsoneditor-icon {
background-position: -144px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-type-string:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-string:focus > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-string.jsoneditor-selected > div.jsoneditor-icon {
background-position: -144px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-type-auto > div.jsoneditor-icon {
background-position: -120px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-type-auto:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-auto:focus > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-auto.jsoneditor-selected > div.jsoneditor-icon {
background-position: -120px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-type-object > div.jsoneditor-icon {
background-position: -72px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-type-object:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-object:focus > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-object.jsoneditor-selected > div.jsoneditor-icon {
background-position: -72px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-type-array > div.jsoneditor-icon {
background-position: -96px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-type-array:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-array:focus > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-array.jsoneditor-selected > div.jsoneditor-icon {
background-position: -96px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon {
background-image: none;
width: 6px;
}
div.jsoneditor-menu {
width: 100%;
height: 35px;
padding: 2px;
margin: 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: white;
background-color: #2e2e2e;
border-bottom: 1px solid #2e2e2e;
}
div.jsoneditor-menu > button,
div.jsoneditor-menu > div.jsoneditor-modes > button {
width: 26px;
height: 26px;
margin: 2px;
padding: 0;
border-radius: 2px;
border: 1px solid transparent;
background: transparent url("img/jsoneditor-icons.svg");
color: white;
opacity: 0.8;
font-family: arial, sans-serif;
font-size: 10pt;
float: left;
}
div.jsoneditor-menu > button:hover,
div.jsoneditor-menu > div.jsoneditor-modes > button:hover {
background-color: rgba(255,255,255,0.2);
border: 1px solid rgba(255,255,255,0.4);
}
div.jsoneditor-menu > button:focus,
div.jsoneditor-menu > button:active,
div.jsoneditor-menu > div.jsoneditor-modes > button:focus,
div.jsoneditor-menu > div.jsoneditor-modes > button:active {
background-color: rgba(255,255,255,0.3);
}
div.jsoneditor-menu > button:disabled,
div.jsoneditor-menu > div.jsoneditor-modes > button:disabled {
opacity: 0.5;
}
div.jsoneditor-menu > button.jsoneditor-collapse-all {
background-position: 0 -96px;
}
div.jsoneditor-menu > button.jsoneditor-expand-all {
background-position: 0 -120px;
}
div.jsoneditor-menu > button.jsoneditor-undo {
background-position: -24px -96px;
}
div.jsoneditor-menu > button.jsoneditor-undo:disabled {
background-position: -24px -120px;
}
div.jsoneditor-menu > button.jsoneditor-redo {
background-position: -48px -96px;
}
div.jsoneditor-menu > button.jsoneditor-redo:disabled {
background-position: -48px -120px;
}
div.jsoneditor-menu > button.jsoneditor-compact {
background-position: -72px -96px;
}
div.jsoneditor-menu > button.jsoneditor-format {
background-position: -72px -120px;
}
div.jsoneditor-menu > div.jsoneditor-modes {
display: inline-block;
float: left;
}
div.jsoneditor-menu > div.jsoneditor-modes > button {
background-image: none;
width: auto;
padding-left: 6px;
padding-right: 6px;
}
div.jsoneditor-menu > button.jsoneditor-separator,
div.jsoneditor-menu > div.jsoneditor-modes > button.jsoneditor-separator {
margin-left: 10px;
}
div.jsoneditor-menu a {
font-family: arial, sans-serif;
font-size: 10pt;
color: white;
opacity: 0.8;
vertical-align: middle;
}
div.jsoneditor-menu a:hover {
opacity: 1;
}
div.jsoneditor-menu a.jsoneditor-poweredBy {
font-size: 8pt;
position: absolute;
right: 0;
top: 0;
padding: 10px;
}
table.jsoneditor-search input,
table.jsoneditor-search div.jsoneditor-results {
font-family: arial, sans-serif;
font-size: 10pt;
color: #1A1A1A;
background: transparent;
/* For Firefox */
}
table.jsoneditor-search div.jsoneditor-results {
color: white;
padding-right: 5px;
line-height: 24px;
}
table.jsoneditor-search {
position: absolute;
right: 4px;
top: 4px;
border-collapse: collapse;
border-spacing: 0;
}
table.jsoneditor-search div.jsoneditor-frame {
border: 1px solid transparent;
background-color: white;
padding: 0 2px;
margin: 0;
}
table.jsoneditor-search div.jsoneditor-frame table {
border-collapse: collapse;
}
table.jsoneditor-search input {
width: 120px;
border: none;
outline: none;
margin: 1px;
line-height: 20px;
}
table.jsoneditor-search button {
width: 16px;
height: 24px;
padding: 0;
margin: 0;
border: none;
background: url("img/jsoneditor-icons.svg");
vertical-align: top;
}
table.jsoneditor-search button:hover {
background-color: transparent;
}
table.jsoneditor-search button.jsoneditor-refresh {
width: 18px;
background-position: -99px -73px;
}
table.jsoneditor-search button.jsoneditor-next {
cursor: pointer;
background-position: -124px -73px;
}
table.jsoneditor-search button.jsoneditor-next:hover {
background-position: -124px -49px;
}
table.jsoneditor-search button.jsoneditor-previous {
cursor: pointer;
background-position: -148px -73px;
margin-right: 2px;
}
table.jsoneditor-search button.jsoneditor-previous:hover {
background-position: -148px -49px;
}

View file

@ -7,73 +7,71 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-->
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/edit-style.css">
<script src="js/list.min.js"></script>
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script type="text/javascript" src="js/eventBridgeLoader.js"></script>
<script type="text/javascript" src="js/spinButtons.js"></script>
<script type="text/javascript" src="js/entityList.js"></script>
</head>
<body onload='loaded();'>
<div id="entity-list-header">
<input type="button" class="glyph" id="refresh" value="F" />
<div>
<input type="button" id="locked" class="glyph" value="&#xe006;" />
<input type="button" id="visible" class="glyph" value="&#xe007;" />
</div>
<input type="button" id="teleport" value="Jump To Selection" />
<input type="button" class="red" id="delete" value="Delete" />
</div>
<div id="entity-list">
<div id="search-area">
<span class="icon-input"><input type="text" class="search" id="filter" placeholder="Filter" /><span>Y</span></span>
<div id="radius-and-unit" class="number">
<label for="radius">Search radius <span class="unit">m</span></label>
<input type="number" id="radius" value="100" />
<head>
<link rel="stylesheet" type="text/css" href="css/edit-style.css">
<script src="js/list.min.js"></script>
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script type="text/javascript" src="js/eventBridgeLoader.js"></script>
<script type="text/javascript" src="js/spinButtons.js"></script>
<script type="text/javascript" src="js/entityList.js"></script>
</head>
<body onload='loaded();'>
<div id="entity-list-header">
<input type="button" class="glyph" id="refresh" value="F" />
<div>
<input type="button" id="locked" class="glyph" value="&#xe006;" />
<input type="button" id="visible" class="glyph" value="&#xe007;" />
</div>
<input type="button" id="teleport" value="Jump To Selection" />
<input type="button" class="red" id="delete" value="Delete" />
</div>
<div id="entity-table-scroll">
<table id="entity-table">
<colgroup>
<div id="entity-list">
<div id="search-area">
<span class="icon-input"><input type="text" class="search" id="filter" placeholder="Filter" /><span>Y</span></span>
<div id="radius-and-unit" class="number">
<label for="radius">Search radius <span class="unit">m</span></label>
<input type="number" id="radius" value="100" />
</div>
</div>
<div id="entity-table-scroll">
<table id="entity-table">
<colgroup>
<col span="1" id="col-type" />
<col span="1" id="col-name" />
<col span="1" id="col-url" />
<col span="1" id="col-locked" />
<col span="1" id="col-visible" />
</colgroup>
<thead>
<tr>
<th id="entity-type" data-sort="type">Type<span class="sort-order"></span></th>
<th id="entity-name" data-sort="type">Name<span class="sort-order"></span></th>
<th id="entity-url" data-sort="url">File<span class="sort-order"></span></th>
<th id="entity-locked" data-sort="locked"><span class="glyph">&#xe006;</span><span class="sort-order"></span></th>
<th colspan="2" id="entity-visible" data-sort="visible"><span class="glyph">&#xe007;</span><span class="sort-order"></span></th>
</tr>
</thead>
<tbody class="list" id="entity-table-body">
<tr>
<td class="type">Type</td>
<td class="name">Name</td>
<td class="url"><div class='outer'><div class='inner'>URL</div></div></td>
<td class="locked glyph">?</td>
<td class="visible glyph">?</td>
<td class="id" style="display: none">ID</td>
</tr>
</tbody>
<tfoot>
</colgroup>
<thead>
<tr>
<th id="entity-type" data-sort="type">Type<span class="sort-order"></span></th>
<th id="entity-name" data-sort="type">Name<span class="sort-order"></span></th>
<th id="entity-url" data-sort="url">File<span class="sort-order"></span></th>
<th id="entity-locked" data-sort="locked"><span class="glyph">&#xe006;</span><span class="sort-order"></span></th>
<th colspan="2" id="entity-visible" data-sort="visible"><span class="glyph">&#xe007;</span><span class="sort-order"></span></th>
</tr>
</thead>
<tbody class="list" id="entity-table-body">
<tr>
<td class="type">Type</td>
<td class="name">Name</td>
<td class="url"><div class='outer'><div class='inner'>URL</div></div></td>
<td class="locked glyph">?</td>
<td class="visible glyph">?</td>
<td class="id" style="display: none">ID</td>
</tr>
</tbody>
<tfoot>
<tr>
<td id="footer-text" colspan="5"> </td>
</tr>
</tfoot>
</table>
<div id="no-entities">
No entities found within a <span id="no-entities-radius">100</span> meter radius. Try moving to a different location and refreshing.
</tfoot>
</table>
<div id="no-entities">
No entities found within a <span id="no-entities-radius">100</span> meter radius. Try moving to a different location and refreshing.
</div>
</div>
</div>
</div>
</body>
</html>
</body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -7,67 +7,59 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-->
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/edit-style.css">
<link rel="stylesheet" type="text/css" href="css/colpick.css">
<script src="js/jquery-2.1.4.min.js"></script>
<script src="js/colpick.js"></script>
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script type="text/javascript" src="js/eventBridgeLoader.js"></script>
<script type="text/javascript" src="js/spinButtons.js"></script>
<script type="text/javascript" src="js/gridControls.js"></script>
</head>
<body onload='loaded();'>
<div id="grid-section">
<div class="section-header">
<label>Editing Grid</label>
</div>
<div class="property checkbox">
<input type='checkbox' id="horiz-grid-visible">
<label for="horiz-grid-visible">Visible</label>
</div>
<div class="property checkbox">
<input type="checkbox" id="snap-to-grid">
<label for="snap-to-grid">Snap entities to grid</label>
</div>
<div class="property">
<div class="number">
<label for="major-spacing">Major grid size <span class="unit">m</span></label>
<input type="number" id="major-spacing" min="1" step="1" />
<head>
<link rel="stylesheet" type="text/css" href="css/edit-style.css">
<link rel="stylesheet" type="text/css" href="css/colpick.css">
<script src="js/jquery-2.1.4.min.js"></script>
<script src="js/colpick.js"></script>
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script type="text/javascript" src="js/eventBridgeLoader.js"></script>
<script type="text/javascript" src="js/spinButtons.js"></script>
<script type="text/javascript" src="js/gridControls.js"></script>
</head>
<body onload='loaded();'>
<div id="grid-section">
<div class="section-header">
<label>Editing Grid</label>
</div>
<div class="number">
<label for="minor-spacing">Minor grid size <span class="unit">m</span></label>
<input type="number" id="minor-spacing" min="0.2" step="0.2" />
<div class="property checkbox">
<input type='checkbox' id="horiz-grid-visible">
<label for="horiz-grid-visible">Visible</label>
</div>
<div class="property checkbox">
<input type="checkbox" id="snap-to-grid">
<label for="snap-to-grid">Snap entities to grid</label>
</div>
<div class="property">
<div class="number">
<label for="major-spacing">Major grid size <span class="unit">m</span></label>
<input type="number" id="major-spacing" min="1" step="1" />
</div>
<div class="number">
<label for="minor-spacing">Minor grid size <span class="unit">m</span></label>
<input type="number" id="minor-spacing" min="0.2" step="0.2" />
</div>
</div>
<div class="property number">
<label for="horiz-y">Position (Y axis) <span class="unit">m</span></label>
<input type="number" id="horiz-y" step="0.1" />
</div>
<div class="property rgb">
<div id="grid-color" class="color-picker"></div>
<label>Grid line color</label>
<div class="tuple">
<div><input type="number" class="red" id="grid-color-red"><label for="grid-color-red">Red:</label></div>
<div><input type="number" class="green" id="grid-color-green"><label for="grid-color-green">Green:</label></div>
<div><input type="number" class="blue" id="grid-color-blue"><label for="grid-color-blue">Blue:</label></div>
</div>
</div>
<div class="property">
<span>
<input type="button" id="move-to-selection" value="Align To Selection">
<input type="button" id="move-to-avatar" value="Align To Avatar">
</span>
</div>
</div>
<div class="property number">
<label for="horiz-y">Position (Y axis) <span class="unit">m</span></label>
<input type="number" id="horiz-y" step="0.1" />
</div>
<div class="property rgb">
<div id="grid-color" class="color-picker"></div>
<label>Grid line color</label>
<div class="tuple">
<div><input type="number" class="red" id="grid-color-red"><label for="grid-color-red">Red:</label></div>
<div><input type="number" class="green" id="grid-color-green"><label for="grid-color-green">Green:</label></div>
<div><input type="number" class="blue" id="grid-color-blue"><label for="grid-color-blue">Blue:</label></div>
</div>
</div>
<div class="property">
<span>
<input type="button" id="move-to-selection" value="Align To Selection">
<input type="button" id="move-to-avatar" value="Align To Avatar">
</span>
</div>
</div>
</body>
</html>
</body>
</html>

View file

@ -0,0 +1,77 @@
"use strict";
//
// SnapshotReview.js
// scripts/system/html/js/
//
// Created by Howard Stearns 8/22/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
//
var paths = [], idCounter = 0, useCheckboxes;
function addImage(data) {
var div = document.createElement("DIV"),
input = document.createElement("INPUT"),
label = document.createElement("LABEL"),
img = document.createElement("IMG"),
id = "p" + idCounter++;
function toggle() { data.share = input.checked; }
img.src = data.localPath;
div.appendChild(img);
data.share = true;
if (useCheckboxes) { // I'd rather use css, but the included stylesheet is quite particular.
// Our stylesheet(?) requires input.id to match label.for. Otherwise input doesn't display the check state.
label.setAttribute('for', id); // cannot do label.for =
input.id = id;
input.type = "checkbox";
input.checked = true;
input.addEventListener('change', toggle);
div.class = "property checkbox";
div.appendChild(input);
div.appendChild(label);
}
document.getElementById("snapshot-images").appendChild(div);
paths.push(data);
}
function handleShareButtons(shareMsg) {
var openFeed = document.getElementById('openFeed');
openFeed.checked = shareMsg.openFeedAfterShare;
openFeed.onchange = function () { EventBridge.emitWebEvent(openFeed.checked ? 'setOpenFeedTrue' : 'setOpenFeedFalse'); };
if (!shareMsg.canShare) {
// this means you may or may not be logged in, but can't share
// because you are not in a public place.
document.getElementById("sharing").innerHTML = "<p class='prompt'>Snapshots can be shared when they're taken in shareable places.";
}
}
window.onload = function () {
// Something like the following will allow testing in a browser.
//addImage({localPath: 'c:/Users/howar/OneDrive/Pictures/hifi-snap-by--on-2016-07-27_12-58-43.jpg'});
//addImage({localPath: 'http://lorempixel.com/1512/1680'});
openEventBridge(function () {
// Set up a handler for receiving the data, and tell the .js we are ready to receive it.
EventBridge.scriptEventReceived.connect(function (message) {
// last element of list contains a bool for whether or not we can share stuff
var shareMsg = message.pop();
handleShareButtons(shareMsg);
// rest are image paths which we add
useCheckboxes = message.length > 1;
message.forEach(addImage);
});
EventBridge.emitWebEvent('ready');
});
};
// beware of bug: Cannot send objects at top level. (Nested in arrays is fine.)
function shareSelected() {
EventBridge.emitWebEvent(paths);
};
function doNotShare() {
EventBridge.emitWebEvent([]);
};
function snapshotSettings() {
EventBridge.emitWebEvent("openSettings");
};

View file

@ -23,12 +23,14 @@ var ICON_FOR_TYPE = {
Multiple: "&#xe000;"
}
var colorPickers = [];
var EDITOR_TIMEOUT_DURATION = 1500;
var colorPickers = [];
var lastEntityID = null;
debugPrint = function(message) {
EventBridge.emitWebEvent(
JSON.stringify({
type:"print",
type: "print",
message: message
})
);
@ -40,6 +42,7 @@ function enableChildren(el, selector) {
els[i].removeAttribute('disabled');
}
}
function disableChildren(el, selector) {
els = el.querySelectorAll(selector);
for (var i = 0; i < els.length; i++) {
@ -50,14 +53,26 @@ function disableChildren(el, selector) {
function enableProperties() {
enableChildren(document.getElementById("properties-list"), "input, textarea, checkbox, .dropdown dl, .color-picker");
enableChildren(document, ".colpick");
var elLocked = document.getElementById("property-locked");
if (elLocked.checked === false) {
removeStaticUserData();
}
}
function disableProperties() {
disableChildren(document.getElementById("properties-list"), "input, textarea, checkbox, .dropdown dl, .color-picker");
disableChildren(document, ".colpick");
for (var i = 0; i < colorPickers.length; i++) {
colorPickers[i].colpickHide();
}
var elLocked = document.getElementById("property-locked");
if ($('#userdata-editor').css('display') === "block" && elLocked.checked === true) {
showStaticUserData();
}
}
function showElements(els, show) {
@ -69,7 +84,7 @@ function showElements(els, show) {
function createEmitCheckedPropertyUpdateFunction(propertyName) {
return function() {
EventBridge.emitWebEvent(
'{ "type":"update", "properties":{"' + propertyName + '":' + this.checked + '}}'
'{"id":' + lastEntityID + ', "type":"update", "properties":{"' + propertyName + '":' + this.checked + '}}'
);
};
}
@ -85,12 +100,13 @@ function createEmitCheckedToStringPropertyUpdateFunction(checkboxElement, name,
}
function createEmitGroupCheckedPropertyUpdateFunction(group, propertyName) {
return function () {
return function() {
var properties = {};
properties[group] = {};
properties[group][propertyName] = this.checked;
EventBridge.emitWebEvent(
JSON.stringify({
id: lastEntityID,
type: "update",
properties: properties
})
@ -104,10 +120,11 @@ function createEmitNumberPropertyUpdateFunction(propertyName, decimals) {
var value = parseFloat(this.value).toFixed(decimals);
EventBridge.emitWebEvent(
'{ "type":"update", "properties":{"' + propertyName + '":' + value + '}}'
'{"id":' + lastEntityID + ', "type":"update", "properties":{"' + propertyName + '":' + value + '}}'
);
};
}
function createEmitGroupNumberPropertyUpdateFunction(group, propertyName) {
return function() {
var properties = {};
@ -115,6 +132,7 @@ function createEmitGroupNumberPropertyUpdateFunction(group, propertyName) {
properties[group][propertyName] = this.value;
EventBridge.emitWebEvent(
JSON.stringify({
id: lastEntityID,
type: "update",
properties: properties,
})
@ -129,6 +147,7 @@ function createEmitTextPropertyUpdateFunction(propertyName) {
properties[propertyName] = this.value;
EventBridge.emitWebEvent(
JSON.stringify({
id: lastEntityID,
type: "update",
properties: properties,
})
@ -136,13 +155,14 @@ function createEmitTextPropertyUpdateFunction(propertyName) {
};
}
function createEmitGroupTextPropertyUpdateFunction(group,propertyName) {
function createEmitGroupTextPropertyUpdateFunction(group, propertyName) {
return function() {
var properties = {};
properties[group] = {};
properties[group][propertyName] = this.value;
EventBridge.emitWebEvent(
JSON.stringify({
id: lastEntityID,
type: "update",
properties: properties,
})
@ -153,14 +173,14 @@ function createEmitGroupTextPropertyUpdateFunction(group,propertyName) {
function createEmitVec3PropertyUpdateFunction(property, elX, elY, elZ) {
return function() {
var data = {
type: "update",
properties: {
}
id: lastEntityID,
type: "update",
properties: {}
};
data.properties[property] = {
x: elX.value,
y: elY.value,
z: elZ.value,
x: elX.value,
y: elY.value,
z: elZ.value,
};
EventBridge.emitWebEvent(JSON.stringify(data));
}
@ -169,15 +189,15 @@ function createEmitVec3PropertyUpdateFunction(property, elX, elY, elZ) {
function createEmitGroupVec3PropertyUpdateFunction(group, property, elX, elY, elZ) {
return function() {
var data = {
type: "update",
properties: {
}
id: lastEntityID,
type: "update",
properties: {}
};
data.properties[group] = { };
data.properties[group] = {};
data.properties[group][property] = {
x: elX.value,
y: elY.value,
z: elZ ? elZ.value : 0,
x: elX.value,
y: elY.value,
z: elZ ? elZ.value : 0,
};
EventBridge.emitWebEvent(JSON.stringify(data));
}
@ -186,14 +206,14 @@ function createEmitGroupVec3PropertyUpdateFunction(group, property, elX, elY, el
function createEmitVec3PropertyUpdateFunctionWithMultiplier(property, elX, elY, elZ, multiplier) {
return function() {
var data = {
type: "update",
properties: {
}
id: lastEntityID,
type: "update",
properties: {}
};
data.properties[property] = {
x: elX.value * multiplier,
y: elY.value * multiplier,
z: elZ.value * multiplier,
x: elX.value * multiplier,
y: elY.value * multiplier,
z: elZ.value * multiplier,
};
EventBridge.emitWebEvent(JSON.stringify(data));
}
@ -206,42 +226,42 @@ function createEmitColorPropertyUpdateFunction(property, elRed, elGreen, elBlue)
};
function emitColorPropertyUpdate(property, red, green, blue, group) {
var data = {
type: "update",
properties: {
}
var data = {
id: lastEntityID,
type: "update",
properties: {}
};
if (group) {
data.properties[group] = {};
data.properties[group][property] = {
red: red,
green: green,
blue: blue,
};
if (group) {
data.properties[group] = { };
data.properties[group][property] = {
red: red,
green: green,
blue: blue,
};
} else {
data.properties[property] = {
red: red,
green: green,
blue: blue,
};
}
EventBridge.emitWebEvent(JSON.stringify(data));
} else {
data.properties[property] = {
red: red,
green: green,
blue: blue,
};
}
EventBridge.emitWebEvent(JSON.stringify(data));
};
function createEmitGroupColorPropertyUpdateFunction(group, property, elRed, elGreen, elBlue) {
return function() {
var data = {
type: "update",
properties: {
}
id: lastEntityID,
type: "update",
properties: {}
};
data.properties[group] = { };
data.properties[group] = {};
data.properties[group][property] = {
red: elRed.value,
green: elGreen.value,
blue: elBlue.value,
red: elRed.value,
green: elGreen.value,
blue: elBlue.value,
};
EventBridge.emitWebEvent(JSON.stringify(data));
}
@ -251,30 +271,70 @@ function updateCheckedSubProperty(propertyName, propertyValue, subPropertyElemen
if (subPropertyElement.checked) {
if (propertyValue.indexOf(subPropertyString)) {
propertyValue += subPropertyString + ',';
}
}
} else {
// We've unchecked, so remove
propertyValue = propertyValue.replace(subPropertyString + ",", "");
}
var _properties ={}
var _properties = {}
_properties[propertyName] = propertyValue;
EventBridge.emitWebEvent(
JSON.stringify({
type: "update",
properties: _properties
})
JSON.stringify({
id: lastEntityID,
type: "update",
properties: _properties
})
);
}
function setUserDataFromEditor(noUpdate) {
var json = null;
try {
json = editor.get();
} catch (e) {
alert('Invalid JSON code - look for red X in your code ', +e)
}
if (json === null) {
return;
} else {
var text = editor.getText()
if (noUpdate === true) {
EventBridge.emitWebEvent(
JSON.stringify({
id: lastEntityID,
type: "saveUserData",
properties: {
userData: text
},
})
);
return;
} else {
EventBridge.emitWebEvent(
JSON.stringify({
id: lastEntityID,
type: "update",
properties: {
userData: text
},
})
);
}
}
}
function userDataChanger(groupName, keyName, checkBoxElement, userDataElement, defaultValue) {
var properties = {};
var parsedData = {};
try {
parsedData = JSON.parse(userDataElement.value);
} catch(e) {}
} catch (e) {}
if (!(groupName in parsedData)) {
parsedData[groupName] = {}
@ -297,6 +357,7 @@ function userDataChanger(groupName, keyName, checkBoxElement, userDataElement, d
EventBridge.emitWebEvent(
JSON.stringify({
id: lastEntityID,
type: "update",
properties: properties,
})
@ -306,9 +367,148 @@ function userDataChanger(groupName, keyName, checkBoxElement, userDataElement, d
function setTextareaScrolling(element) {
var isScrolling = element.scrollHeight > element.offsetHeight;
element.setAttribute("scrolling", isScrolling ? "true" : "false");
};
var editor = null;
var editorTimeout = null;
var lastJSONString = null;
function createJSONEditor() {
var container = document.getElementById("userdata-editor");
var options = {
search: false,
mode: 'tree',
modes: ['code', 'tree'],
name: 'userData',
onModeChange: function() {
$('.jsoneditor-poweredBy').remove();
},
onError: function(e) {
alert('JSON editor:' + e)
},
onChange: function() {
var currentJSONString = editor.getText();
if (currentJSONString === '{"":""}') {
return;
}
$('#userdata-save').attr('disabled', false)
}
};
editor = new JSONEditor(container, options);
};
function hideNewJSONEditorButton() {
$('#userdata-new-editor').hide();
};
function hideClearUserDataButton() {
$('#userdata-clear').hide();
};
function showSaveUserDataButton() {
$('#userdata-save').show();
}
function loaded() {
function hideSaveUserDataButton() {
$('#userdata-save').hide();
}
function showNewJSONEditorButton() {
$('#userdata-new-editor').show();
};
function showClearUserDataButton() {
$('#userdata-clear').show();
};
function showUserDataTextArea() {
$('#property-user-data').show();
};
function hideUserDataTextArea() {
$('#property-user-data').hide();
};
function showStaticUserData() {
$('#static-userdata').show();
$('#static-userdata').css('height', $('#userdata-editor').height())
$('#static-userdata').text(editor.getText());
};
function removeStaticUserData() {
$('#static-userdata').hide();
};
function setEditorJSON(json) {
editor.set(json)
editor.expandAll();
};
function getEditorJSON() {
return editor.get();
};
function deleteJSONEditor() {
if (editor !== null) {
editor.destroy();
editor = null;
}
};
var savedJSONTimer = null;
function saveJSONUserData(noUpdate) {
setUserDataFromEditor(noUpdate);
$('#userdata-saved').show();
$('#userdata-save').attr('disabled', true)
if (savedJSONTimer !== null) {
clearTimeout(savedJSONTimer);
}
savedJSONTimer = setTimeout(function() {
$('#userdata-saved').hide();
}, 1500)
}
function bindAllNonJSONEditorElements() {
var inputs = $('input');
var i;
for (i = 0; i < inputs.length; i++) {
var input = inputs[i];
var field = $(input);
field.on('focus', function(e) {
if (e.target.id === "userdata-new-editor" || e.target.id === "userdata-clear") {
return;
} else {
if ($('#userdata-editor').css('height') !== "0px") {
saveJSONUserData(true);
}
}
})
}
}
function unbindAllInputs() {
var inputs = $('input');
var i;
for (i = 0; i < inputs.length; i++) {
var input = inputs[i];
var field = $(input);
field.unbind();
}
}
function loaded() {
openEventBridge(function() {
var allSections = [];
var elID = document.getElementById("property-id");
@ -364,7 +564,7 @@ function loaded() {
var elDensity = document.getElementById("property-density");
var elCollisionless = document.getElementById("property-collisionless");
var elDynamic = document.getElementById("property-dynamic" );
var elDynamic = document.getElementById("property-dynamic");
var elCollideStatic = document.getElementById("property-collide-static");
var elCollideDynamic = document.getElementById("property-collide-dynamic");
var elCollideKinematic = document.getElementById("property-collide-kinematic");
@ -384,7 +584,10 @@ function loaded() {
*/
var elReloadScriptButton = document.getElementById("reload-script-button");
var elUserData = document.getElementById("property-user-data");
var elClearUserData = document.getElementById("userdata-clear");
var elSaveUserData = document.getElementById("userdata-save");
var elJSONEditor = document.getElementById("userdata-editor");
var elNewJSONEditor = document.getElementById('userdata-new-editor');
var elColorSections = document.querySelectorAll(".color-section");
var elColor = document.getElementById("property-color");
var elColorRed = document.getElementById("property-color-red");
@ -394,7 +597,7 @@ function loaded() {
var elShapeSections = document.querySelectorAll(".shape-section");
allSections.push(elShapeSections);
var elShape = document.getElementById("property-shape");
var elLightSections = document.querySelectorAll(".light-section");
allSections.push(elLightSections);
var elLightSpotLight = document.getElementById("property-light-spot-light");
@ -432,9 +635,9 @@ function loaded() {
var elDescription = document.getElementById("property-description");
var elHyperlinkHref = document.getElementById("property-hyperlink-href");
var elHyperlinkSections = document.querySelectorAll(".hyperlink-section");
var elTextSections = document.querySelectorAll(".text-section");
allSections.push(elTextSections);
@ -498,12 +701,18 @@ function loaded() {
EventBridge.scriptEventReceived.connect(function(data) {
data = JSON.parse(data);
if (data.type == "update") {
if (data.selections.length == 0) {
if (editor !== null && lastEntityID !== null) {
saveJSONUserData(true);
deleteJSONEditor();
}
elTypeIcon.style.display = "none";
elType.innerHTML = "<i>No selection</i>";
elID.innerHTML = "";
disableProperties();
} else if (data.selections.length > 1) {
deleteJSONEditor();
var selections = data.selections;
var ids = [];
@ -534,10 +743,13 @@ function loaded() {
disableProperties();
} else {
properties = data.selections[0].properties;
if (lastEntityID !== properties.id && lastEntityID !== null && editor !== null) {
saveJSONUserData(true);
}
lastEntityID = properties.id;
elID.innerHTML = properties.id;
elType.innerHTML = properties.type;
@ -546,12 +758,6 @@ function loaded() {
elLocked.checked = properties.locked;
if (properties.locked) {
disableProperties();
elLocked.removeAttribute('disabled');
} else {
enableProperties();
}
elName.value = properties.name;
@ -613,7 +819,7 @@ function loaded() {
var parsedUserData = {}
try {
parsedUserData = JSON.parse(properties.userData);
if ("grabbableKey" in parsedUserData) {
if ("grabbable" in parsedUserData["grabbableKey"]) {
elGrabbable.checked = parsedUserData["grabbableKey"].grabbable;
@ -625,7 +831,7 @@ function loaded() {
elIgnoreIK.checked = parsedUserData["grabbableKey"].ignoreIK;
}
}
} catch(e) {}
} catch (e) {}
elCollisionSoundURL.value = properties.collisionSoundURL;
elLifetime.value = properties.lifetime;
@ -634,8 +840,27 @@ function loaded() {
FIXME: See FIXME for property-script-url.
elScriptTimestamp.value = properties.scriptTimestamp;
*/
elUserData.value = properties.userData;
setTextareaScrolling(elUserData);
hideUserDataTextArea();
var json = null;
try {
json = JSON.parse(properties.userData);
if (editor === null) {
createJSONEditor();
}
setEditorJSON(json);
showSaveUserDataButton();
hideNewJSONEditorButton();
} catch (e) {
//normal text
elUserData.value = properties.userData;
showUserDataTextArea();
showNewJSONEditorButton();
hideSaveUserDataButton();
}
elHyperlinkHref.value = properties.href;
elDescription.value = properties.description;
@ -644,7 +869,7 @@ function loaded() {
for (var j = 0; j < allSections[i].length; j++) {
allSections[i][j].style.display = 'none';
}
}
}
for (var i = 0; i < elHyperlinkSections.length; i++) {
elHyperlinkSections[i].style.display = 'table';
@ -662,7 +887,7 @@ function loaded() {
elShapeSections[i].style.display = 'none';
}
}
if (properties.type == "Shape" || properties.type == "Box" || properties.type == "Sphere" || properties.type == "ParticleEffect") {
for (var i = 0; i < elColorSections.length; i++) {
elColorSections[i].style.display = 'table';
@ -670,7 +895,7 @@ function loaded() {
elColorRed.value = properties.color.red;
elColorGreen.value = properties.color.green;
elColorBlue.value = properties.color.blue;
elColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")";
elColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")";
} else {
for (var i = 0; i < elColorSections.length; i++) {
elColorSections[i].style.display = 'none';
@ -716,7 +941,7 @@ function loaded() {
elTextText.value = properties.text;
elTextLineHeight.value = properties.lineHeight.toFixed(4);
elTextFaceCamera = properties.faceCamera;
elTextTextColor.style.backgroundColor = "rgb(" + properties.textColor.red + "," + properties.textColor.green + "," + properties.textColor.blue + ")";
elTextTextColor.style.backgroundColor = "rgb(" + properties.textColor.red + "," + properties.textColor.green + "," + properties.textColor.blue + ")";
elTextTextColorRed.value = properties.textColor.red;
elTextTextColorGreen.value = properties.textColor.green;
elTextTextColorBlue.value = properties.textColor.blue;
@ -730,7 +955,7 @@ function loaded() {
elLightSpotLight.checked = properties.isSpotlight;
elLightColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")";
elLightColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")";
elLightColorRed.value = properties.color.red;
elLightColorGreen.value = properties.color.green;
elLightColorBlue.value = properties.color.blue;
@ -745,7 +970,7 @@ function loaded() {
}
elZoneStageSunModelEnabled.checked = properties.stage.sunModelEnabled;
elZoneKeyLightColor.style.backgroundColor = "rgb(" + properties.keyLight.color.red + "," + properties.keyLight.color.green + "," + properties.keyLight.color.blue + ")";
elZoneKeyLightColor.style.backgroundColor = "rgb(" + properties.keyLight.color.red + "," + properties.keyLight.color.green + "," + properties.keyLight.color.blue + ")";
elZoneKeyLightColorRed.value = properties.keyLight.color.red;
elZoneKeyLightColorGreen.value = properties.keyLight.color.green;
elZoneKeyLightColorBlue.value = properties.keyLight.color.blue;
@ -768,7 +993,7 @@ function loaded() {
elZoneBackgroundMode.value = properties.backgroundMode;
setDropdownText(elZoneBackgroundMode);
elZoneSkyboxColor.style.backgroundColor = "rgb(" + properties.skybox.color.red + "," + properties.skybox.color.green + "," + properties.skybox.color.blue + ")";
elZoneSkyboxColor.style.backgroundColor = "rgb(" + properties.skybox.color.red + "," + properties.skybox.color.green + "," + properties.skybox.color.blue + ")";
elZoneSkyboxColorRed.value = properties.skybox.color.red;
elZoneSkyboxColorGreen.value = properties.skybox.color.green;
elZoneSkyboxColorBlue.value = properties.skybox.color.blue;
@ -792,10 +1017,18 @@ function loaded() {
elYTextureURL.value = properties.yTextureURL;
elZTextureURL.value = properties.zTextureURL;
}
if (properties.locked) {
disableProperties();
elLocked.removeAttribute('disabled');
} else {
enableProperties();
elSaveUserData.disabled = true;
}
var activeElement = document.activeElement;
if(typeof activeElement.select!=="undefined"){
if (typeof activeElement.select !== "undefined") {
activeElement.select();
}
}
@ -905,8 +1138,44 @@ function loaded() {
FIXME: See FIXME for property-script-url.
elScriptTimestamp.addEventListener('change', createEmitNumberPropertyUpdateFunction('scriptTimestamp'));
*/
elClearUserData.addEventListener("click", function() {
deleteJSONEditor();
elUserData.value = "";
showUserDataTextArea();
showNewJSONEditorButton();
hideSaveUserDataButton();
var properties = {};
properties['userData'] = elUserData.value;
EventBridge.emitWebEvent(
JSON.stringify({
id: lastEntityID,
type: "update",
properties: properties,
})
);
});
elSaveUserData.addEventListener("click", function() {
saveJSONUserData(true);
});
elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData'));
elNewJSONEditor.addEventListener('click', function() {
deleteJSONEditor();
createJSONEditor();
var data = {};
setEditorJSON(data);
hideUserDataTextArea();
hideNewJSONEditorButton();
showSaveUserDataButton();
});
var colorChangeFunction = createEmitColorPropertyUpdateFunction(
'color', elColorRed, elColorGreen, elColorBlue);
elColorRed.addEventListener('change', colorChangeFunction);
@ -916,13 +1185,13 @@ function loaded() {
colorScheme: 'dark',
layout: 'hex',
color: '000000',
onShow: function (colpick) {
onShow: function(colpick) {
$('#property-color').attr('active', 'true');
},
onHide: function (colpick) {
onHide: function(colpick) {
$('#property-color').attr('active', 'false');
},
onSubmit: function (hsb, hex, rgb, el) {
onSubmit: function(hsb, hex, rgb, el) {
$(el).css('background-color', '#' + hex);
$(el).colpickHide();
emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b);
@ -940,13 +1209,13 @@ function loaded() {
colorScheme: 'dark',
layout: 'hex',
color: '000000',
onShow: function (colpick) {
onShow: function(colpick) {
$('#property-light-color').attr('active', 'true');
},
onHide: function (colpick) {
onHide: function(colpick) {
$('#property-light-color').attr('active', 'false');
},
onSubmit: function (hsb, hex, rgb, el) {
onSubmit: function(hsb, hex, rgb, el) {
$(el).css('background-color', '#' + hex);
$(el).colpickHide();
emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b);
@ -968,8 +1237,8 @@ function loaded() {
elCompoundShapeURL.addEventListener('change', createEmitTextPropertyUpdateFunction('compoundShapeURL'));
elModelAnimationURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('animation', 'url'));
elModelAnimationPlaying.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation','running'));
elModelAnimationFPS.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation','fps'));
elModelAnimationPlaying.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'running'));
elModelAnimationFPS.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'fps'));
elModelAnimationFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'currentFrame'));
elModelAnimationFirstFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'firstFrame'));
elModelAnimationLastFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'lastFrame'));
@ -987,17 +1256,17 @@ function loaded() {
elTextTextColorGreen.addEventListener('change', textTextColorChangeFunction);
elTextTextColorBlue.addEventListener('change', textTextColorChangeFunction);
colorPickers.push($('#property-text-text-color').colpick({
colorScheme:'dark',
layout:'hex',
colorScheme: 'dark',
layout: 'hex',
color: '000000',
onShow: function (colpick) {
onShow: function(colpick) {
$('#property-text-text-color').attr('active', 'true');
},
onHide: function (colpick) {
onHide: function(colpick) {
$('#property-text-text-color').attr('active', 'false');
},
onSubmit: function (hsb, hex, rgb, el) {
$(el).css('background-color', '#'+hex);
onSubmit: function(hsb, hex, rgb, el) {
$(el).css('background-color', '#' + hex);
$(el).colpickHide();
$(el).attr('active', 'false');
emitColorPropertyUpdate('textColor', rgb.r, rgb.g, rgb.b);
@ -1010,82 +1279,82 @@ function loaded() {
elTextBackgroundColorGreen.addEventListener('change', textBackgroundColorChangeFunction);
elTextBackgroundColorBlue.addEventListener('change', textBackgroundColorChangeFunction);
colorPickers.push($('#property-text-background-color').colpick({
colorScheme:'dark',
layout:'hex',
color:'000000',
onShow: function (colpick) {
colorScheme: 'dark',
layout: 'hex',
color: '000000',
onShow: function(colpick) {
$('#property-text-background-color').attr('active', 'true');
},
onHide: function (colpick) {
onHide: function(colpick) {
$('#property-text-background-color').attr('active', 'false');
},
onSubmit: function (hsb, hex, rgb, el) {
$(el).css('background-color', '#'+hex);
onSubmit: function(hsb, hex, rgb, el) {
$(el).css('background-color', '#' + hex);
$(el).colpickHide();
emitColorPropertyUpdate('backgroundColor', rgb.r, rgb.g, rgb.b);
}
}));
elZoneStageSunModelEnabled.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage','sunModelEnabled'));
elZoneStageSunModelEnabled.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage', 'sunModelEnabled'));
colorPickers.push($('#property-zone-key-light-color').colpick({
colorScheme:'dark',
layout:'hex',
color:'000000',
onShow: function (colpick) {
colorScheme: 'dark',
layout: 'hex',
color: '000000',
onShow: function(colpick) {
$('#property-zone-key-light-color').attr('active', 'true');
},
onHide: function (colpick) {
onHide: function(colpick) {
$('#property-zone-key-light-color').attr('active', 'false');
},
onSubmit: function (hsb, hex, rgb, el) {
$(el).css('background-color', '#'+hex);
onSubmit: function(hsb, hex, rgb, el) {
$(el).css('background-color', '#' + hex);
$(el).colpickHide();
emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'keyLight');
}
}));
var zoneKeyLightColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('keyLight','color', elZoneKeyLightColorRed, elZoneKeyLightColorGreen, elZoneKeyLightColorBlue);
var zoneKeyLightColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('keyLight', 'color', elZoneKeyLightColorRed, elZoneKeyLightColorGreen, elZoneKeyLightColorBlue);
elZoneKeyLightColorRed.addEventListener('change', zoneKeyLightColorChangeFunction);
elZoneKeyLightColorGreen.addEventListener('change', zoneKeyLightColorChangeFunction);
elZoneKeyLightColorBlue.addEventListener('change', zoneKeyLightColorChangeFunction);
elZoneKeyLightIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight','intensity'));
elZoneKeyLightAmbientIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight','ambientIntensity'));
elZoneKeyLightAmbientURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('keyLight','ambientURL'));
var zoneKeyLightDirectionChangeFunction = createEmitGroupVec3PropertyUpdateFunction('keyLight','direction', elZoneKeyLightDirectionX, elZoneKeyLightDirectionY);
elZoneKeyLightIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight', 'intensity'));
elZoneKeyLightAmbientIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('keyLight', 'ambientIntensity'));
elZoneKeyLightAmbientURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('keyLight', 'ambientURL'));
var zoneKeyLightDirectionChangeFunction = createEmitGroupVec3PropertyUpdateFunction('keyLight', 'direction', elZoneKeyLightDirectionX, elZoneKeyLightDirectionY);
elZoneKeyLightDirectionX.addEventListener('change', zoneKeyLightDirectionChangeFunction);
elZoneKeyLightDirectionY.addEventListener('change', zoneKeyLightDirectionChangeFunction);
elZoneStageLatitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','latitude'));
elZoneStageLongitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','longitude'));
elZoneStageAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','altitude'));
elZoneStageAutomaticHourDay.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage','automaticHourDay'));
elZoneStageDay.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','day'));
elZoneStageHour.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage','hour'));
elZoneStageLatitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage', 'latitude'));
elZoneStageLongitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage', 'longitude'));
elZoneStageAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage', 'altitude'));
elZoneStageAutomaticHourDay.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage', 'automaticHourDay'));
elZoneStageDay.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage', 'day'));
elZoneStageHour.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage', 'hour'));
elZoneBackgroundMode.addEventListener('change', createEmitTextPropertyUpdateFunction('backgroundMode'));
var zoneSkyboxColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('skybox','color',
var zoneSkyboxColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('skybox', 'color',
elZoneSkyboxColorRed, elZoneSkyboxColorGreen, elZoneSkyboxColorBlue);
elZoneSkyboxColorRed.addEventListener('change', zoneSkyboxColorChangeFunction);
elZoneSkyboxColorGreen.addEventListener('change', zoneSkyboxColorChangeFunction);
elZoneSkyboxColorBlue.addEventListener('change', zoneSkyboxColorChangeFunction);
colorPickers.push($('#property-zone-skybox-color').colpick({
colorScheme:'dark',
layout:'hex',
color:'000000',
onShow: function (colpick) {
colorScheme: 'dark',
layout: 'hex',
color: '000000',
onShow: function(colpick) {
$('#property-zone-skybox-color').attr('active', 'true');
},
onHide: function (colpick) {
onHide: function(colpick) {
$('#property-zone-skybox-color').attr('active', 'false');
},
onSubmit: function (hsb, hex, rgb, el) {
$(el).css('background-color', '#'+hex);
onSubmit: function(hsb, hex, rgb, el) {
$(el).css('background-color', '#' + hex);
$(el).colpickHide();
emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'skybox');
}
}));
elZoneSkyboxURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('skybox','url'));
elZoneSkyboxURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('skybox', 'url'));
elZoneFlyingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('flyingAllowed'));
elZoneGhostingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('ghostingAllowed'));
@ -1167,12 +1436,13 @@ function loaded() {
clicked = true;
};
}
bindAllNonJSONEditorElements();
});
// Collapsible sections
var elCollapsible = document.getElementsByClassName("section-header");
var toggleCollapsedEvent = function (event) {
var toggleCollapsedEvent = function(event) {
var element = event.target;
if (element.nodeName !== "DIV") {
element = element.parentNode;
@ -1191,7 +1461,7 @@ function loaded() {
// Textarea scrollbars
var elTextareas = document.getElementsByTagName("TEXTAREA");
var textareaOnChangeEvent = function (event) {
var textareaOnChangeEvent = function(event) {
setTextareaScrolling(event.target);
}
@ -1277,7 +1547,7 @@ function loaded() {
dt.appendChild(span);
var span = document.createElement("span");
span.textContent = "5"; // caratDn
span.textContent = "5"; // caratDn
dt.appendChild(span);
var dd = document.createElement("dd");
@ -1305,8 +1575,7 @@ function loaded() {
augmentSpinButtons();
// Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked
document.addEventListener("contextmenu", function (event) {
document.addEventListener("contextmenu", function(event) {
event.preventDefault();
}, false);
}
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,79 @@
//
// clara.js
//
// Created by Eric Levin on 8 Jan 2016
// Edited by Elisa Lupin-Jimenez on 23 Aug 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
//
var toolIconUrl = Script.resolvePath("../assets/images/tools/");
var qml = Script.resolvePath("../../../resources/qml/MarketplaceComboBox.qml")
var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace";
var marketplaceWindow = new OverlayWindow({
title: "Marketplace",
source: qml,
width: 900,
height: 700,
toolWindow: false,
visible: false,
});
var toolHeight = 50;
var toolWidth = 50;
var TOOLBAR_MARGIN_Y = 0;
function showMarketplace(marketplaceID) {
var url = MARKETPLACE_URL;
if (marketplaceID) {
url = url + "/items/" + marketplaceID;
}
marketplaceWindow.setVisible(true);
UserActivityLogger.openedMarketplace();
}
function hideMarketplace() {
marketplaceWindow.setVisible(false);
}
function toggleMarketplace() {
if (marketplaceWindow.visible) {
hideMarketplace();
} else {
showMarketplace();
}
}
var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system");
var browseExamplesButton = toolBar.addButton({
imageURL: toolIconUrl + "market.svg",
objectName: "marketplace",
buttonState: 1,
defaultState: 1,
hoverState: 3,
alpha: 0.9
});
function onExamplesWindowVisibilityChanged() {
browseExamplesButton.writeProperty('buttonState', marketplaceWindow.visible ? 0 : 1);
browseExamplesButton.writeProperty('defaultState', marketplaceWindow.visible ? 0 : 1);
browseExamplesButton.writeProperty('hoverState', marketplaceWindow.visible ? 2 : 3);
}
function onClick() {
toggleMarketplace();
}
browseExamplesButton.clicked.connect(onClick);
marketplaceWindow.visibleChanged.connect(onExamplesWindowVisibilityChanged);
Script.scriptEnding.connect(function () {
toolBar.removeButton("marketplace");
browseExamplesButton.clicked.disconnect(onClick);
marketplaceWindow.visibleChanged.disconnect(onExamplesWindowVisibilityChanged);
});

View file

@ -11,7 +11,7 @@
/* global WebTablet */
Script.include("./libraries/WebTablet.js");
var toolIconUrl = Script.resolvePath("assets/images/tools/");
var toolIconUrl = Script.resolvePath("../assets/images/tools/");
var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace";
var marketplaceWindow = new OverlayWebWindow({

View file

@ -527,12 +527,14 @@ function onDomainConnectionRefused(reason) {
createNotification("Connection refused: " + reason, NotificationType.CONNECTION_REFUSED);
}
function onSnapshotTaken(path) {
var imageProperties = {
path: Script.resolvePath("file:///" + path),
aspectRatio: Window.innerWidth / Window.innerHeight
function onSnapshotTaken(path, notify) {
if (notify) {
var imageProperties = {
path: Script.resolvePath("file:///" + path),
aspectRatio: Window.innerWidth / Window.innerHeight
}
createNotification(wordWrap("Snapshot saved to " + path), NotificationType.SNAPSHOT, imageProperties);
}
createNotification(wordWrap("Snapshot saved to " + path), NotificationType.SNAPSHOT, imageProperties);
}
// handles mouse clicks on buttons

154
scripts/system/snapshot.js Normal file
View file

@ -0,0 +1,154 @@
//
// snapshot.js
//
// Created by David Kelly on 1 August 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
//
var SNAPSHOT_DELAY = 500; // 500ms
var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system");
var resetOverlays;
var reticleVisible;
var button = toolBar.addButton({
objectName: "snapshot",
imageURL: Script.resolvePath("assets/images/tools/snap.svg"),
visible: true,
buttonState: 1,
defaultState: 1,
hoverState: 2,
alpha: 0.9,
});
function shouldOpenFeedAfterShare() {
var persisted = Settings.getValue('openFeedAfterShare', true); // might answer true, false, "true", or "false"
return persisted && (persisted !== 'false');
}
function showFeedWindow() {
DialogsManager.showFeed();
}
var outstanding;
function confirmShare(data) {
var dialog = new OverlayWebWindow('Snapshot Review', Script.resolvePath("html/SnapshotReview.html"), 800, 320);
function onMessage(message) {
// Receives message from the html dialog via the qwebchannel EventBridge. This is complicated by the following:
// 1. Although we can send POJOs, we cannot receive a toplevel object. (Arrays of POJOs are fine, though.)
// 2. Although we currently use a single image, we would like to take snapshot, a selfie, a 360 etc. all at the
// same time, show the user all of them, and have the user deselect any that they do not want to share.
// So we'll ultimately be receiving a set of objects, perhaps with different post processing for each.
var isLoggedIn;
var needsLogin = false;
switch (message) {
case 'ready':
dialog.emitScriptEvent(data); // Send it.
outstanding = 0;
break;
case 'openSettings':
Desktop.show("hifi/dialogs/GeneralPreferencesDialog.qml", "GeneralPreferencesDialog");
break;
case 'setOpenFeedFalse':
Settings.setValue('openFeedAfterShare', false)
break;
case 'setOpenFeedTrue':
Settings.setValue('openFeedAfterShare', true)
break;
default:
dialog.webEventReceived.disconnect(onMessage);
dialog.close();
isLoggedIn = Account.isLoggedIn();
message.forEach(function (submessage) {
if (submessage.share && !isLoggedIn) {
needsLogin = true;
submessage.share = false;
}
if (submessage.share) {
print('sharing', submessage.localPath);
outstanding++;
Window.shareSnapshot(submessage.localPath);
} else {
print('not sharing', submessage.localPath);
}
});
if (!outstanding && shouldOpenFeedAfterShare()) {
showFeedWindow();
}
if (needsLogin) { // after the possible feed, so that the login is on top
Account.checkAndSignalForAccessToken();
}
}
}
dialog.webEventReceived.connect(onMessage);
dialog.raise();
}
function snapshotShared(errorMessage) {
if (!errorMessage) {
print('snapshot uploaded and shared');
} else {
print(errorMessage);
}
if ((--outstanding <= 0) && shouldOpenFeedAfterShare()) {
showFeedWindow();
}
}
function onClicked() {
// update button states
resetOverlays = Menu.isOptionChecked("Overlays");
reticleVisible = Reticle.visible;
Reticle.visible = false;
Window.snapshotTaken.connect(resetButtons);
button.writeProperty("buttonState", 0);
button.writeProperty("defaultState", 0);
button.writeProperty("hoverState", 2);
// hide overlays if they are on
if (resetOverlays) {
Menu.setIsOptionChecked("Overlays", false);
}
// hide hud
toolBar.writeProperty("visible", false);
// take snapshot (with no notification)
Script.setTimeout(function () {
Window.takeSnapshot(false, 1.91);
}, SNAPSHOT_DELAY);
}
function resetButtons(path, notify) {
// show overlays if they were on
if (resetOverlays) {
Menu.setIsOptionChecked("Overlays", true);
}
// show hud
toolBar.writeProperty("visible", true);
Reticle.visible = reticleVisible;
// update button states
button.writeProperty("buttonState", 1);
button.writeProperty("defaultState", 1);
button.writeProperty("hoverState", 3);
Window.snapshotTaken.disconnect(resetButtons);
// last element in data array tells dialog whether we can share or not
confirmShare([
{ localPath: path },
{
canShare: !!location.placename,
openFeedAfterShare: shouldOpenFeedAfterShare()
}
]);
}
button.clicked.connect(onClicked);
Window.snapshotShared.connect(snapshotShared);
Script.scriptEnding.connect(function () {
toolBar.removeButton("snapshot");
button.clicked.disconnect(onClicked);
Window.snapshotShared.disconnect(snapshotShared);
});