From 714a3f6b086e7210059a1c5d028622d712ed3d02 Mon Sep 17 00:00:00 2001
From: RebeccaStankus <Rebecca@highfidelity.io>
Date: Tue, 9 Jul 2019 13:02:54 -0700
Subject: [PATCH] Fixed path to tabletAssetServer in HMD, simplifiedUI system
 folder

---
 interface/src/Application.cpp                 |    2 +-
 .../system/assets/images/hourglass.svg        |   18 +
 .../assets/data/createAppTooltips.json        |    0
 .../system/create/assets/images/hourglass.svg |   18 +
 .../images/icon-particles.svg}                |    0
 .../create/assets/images/icon-point-light.svg |   57 +
 .../create/assets/images/icon-spot-light.svg  |   37 +
 .../system/create/assets/images/icon-zone.svg |   73 +
 scripts/simplifiedUI/system/create/edit.js    | 2858 ++++++++++++++++
 .../system/create/entityList/entityList.js    |  330 ++
 .../create/entityList/html/entityList.html    |   93 +
 .../entityList}/html/js/entityList.js         |    0
 .../html/js/entityListContextMenu.js          |    0
 .../entityList}/html/js/listView.js           |    0
 .../{ => entityList/qml}/EditEntityList.qml   |    2 +-
 .../{ => entityList/qml}/EntityList.qml       |    2 +-
 .../html/entityProperties.html                |   52 +
 .../html/js/createAppTooltip.js               |  116 +
 .../html/js/draggableNumber.js                |    0
 .../html/js/entityProperties.js               |    0
 .../html/js/underscore-min.js                 |    0
 .../entitySelectionTool.js                    | 2925 +++++++++++++++++
 .../{ => create}/modules/createWindow.js      |    0
 .../modules/entityShapeVisualizer.js          |    4 +-
 .../system/create/{ => qml}/Edit.qml          |    2 +-
 .../system/create/{ => qml}/EditTabButton.qml |    0
 .../system/create/{ => qml}/EditTabView.qml   |   24 +-
 .../system/create/{ => qml}/EditTools.qml     |    0
 .../create/{ => qml}/EditToolsTabView.qml     |   22 +-
 .../create/{ => qml}/NewEntityButton.qml      |    0
 .../create/{ => qml}/NewMaterialDialog.qml    |    2 +-
 .../create/{ => qml}/NewMaterialWindow.qml    |    0
 .../create/{ => qml}/NewModelDialog.qml       |   11 +-
 .../create/{ => qml}/NewModelWindow.qml       |    0
 .../icons}/126-material-01.svg                |    0
 .../icons}/20-text-01.svg                     |    0
 .../icons}/21-cube-01.svg                     |    0
 .../icons}/22-sphere-01.svg                   |    0
 .../icons}/23-zone-01.svg                     |    0
 .../icons}/24-light-01.svg                    |    0
 .../icons}/25-web-1-01.svg                    |    0
 .../create/qml/icons/90-particles-01.svg      |   29 +
 .../icons}/94-model-01.svg                    |    0
 .../{create-icons => qml/icons}/image.svg     |    0
 .../keyboardShortcuts/keyboardShortcuts.js    |   29 +
 scripts/system/create/qml/Edit.qml            |    2 +-
 scripts/system/create/qml/NewModelDialog.qml  |    9 +-
 47 files changed, 6669 insertions(+), 48 deletions(-)
 create mode 100644 scripts/simplifiedUI/system/assets/images/hourglass.svg
 rename scripts/simplifiedUI/system/{ => create}/assets/data/createAppTooltips.json (100%)
 create mode 100644 scripts/simplifiedUI/system/create/assets/images/hourglass.svg
 rename scripts/simplifiedUI/system/create/{create-icons/90-particles-01.svg => assets/images/icon-particles.svg} (100%)
 create mode 100644 scripts/simplifiedUI/system/create/assets/images/icon-point-light.svg
 create mode 100644 scripts/simplifiedUI/system/create/assets/images/icon-spot-light.svg
 create mode 100644 scripts/simplifiedUI/system/create/assets/images/icon-zone.svg
 create mode 100644 scripts/simplifiedUI/system/create/edit.js
 create mode 100644 scripts/simplifiedUI/system/create/entityList/entityList.js
 create mode 100644 scripts/simplifiedUI/system/create/entityList/html/entityList.html
 rename scripts/simplifiedUI/system/{ => create/entityList}/html/js/entityList.js (100%)
 rename scripts/simplifiedUI/system/{ => create/entityList}/html/js/entityListContextMenu.js (100%)
 rename scripts/simplifiedUI/system/{ => create/entityList}/html/js/listView.js (100%)
 rename scripts/simplifiedUI/system/create/{ => entityList/qml}/EditEntityList.qml (82%)
 rename scripts/simplifiedUI/system/create/{ => entityList/qml}/EntityList.qml (58%)
 create mode 100644 scripts/simplifiedUI/system/create/entityProperties/html/entityProperties.html
 create mode 100644 scripts/simplifiedUI/system/create/entityProperties/html/js/createAppTooltip.js
 rename scripts/simplifiedUI/system/{ => create/entityProperties}/html/js/draggableNumber.js (100%)
 rename scripts/simplifiedUI/system/{ => create/entityProperties}/html/js/entityProperties.js (100%)
 rename scripts/simplifiedUI/system/{ => create/entityProperties}/html/js/underscore-min.js (100%)
 create mode 100644 scripts/simplifiedUI/system/create/entitySelectionTool/entitySelectionTool.js
 rename scripts/simplifiedUI/system/{ => create}/modules/createWindow.js (100%)
 rename scripts/simplifiedUI/system/{ => create}/modules/entityShapeVisualizer.js (98%)
 rename scripts/simplifiedUI/system/create/{ => qml}/Edit.qml (95%)
 rename scripts/simplifiedUI/system/create/{ => qml}/EditTabButton.qml (100%)
 rename scripts/simplifiedUI/system/create/{ => qml}/EditTabView.qml (93%)
 rename scripts/simplifiedUI/system/create/{ => qml}/EditTools.qml (100%)
 rename scripts/simplifiedUI/system/create/{ => qml}/EditToolsTabView.qml (93%)
 rename scripts/simplifiedUI/system/create/{ => qml}/NewEntityButton.qml (100%)
 rename scripts/simplifiedUI/system/create/{ => qml}/NewMaterialDialog.qml (99%)
 rename scripts/simplifiedUI/system/create/{ => qml}/NewMaterialWindow.qml (100%)
 rename scripts/simplifiedUI/system/create/{ => qml}/NewModelDialog.qml (95%)
 rename scripts/simplifiedUI/system/create/{ => qml}/NewModelWindow.qml (100%)
 rename scripts/simplifiedUI/system/create/{create-icons => qml/icons}/126-material-01.svg (100%)
 rename scripts/simplifiedUI/system/create/{create-icons => qml/icons}/20-text-01.svg (100%)
 rename scripts/simplifiedUI/system/create/{create-icons => qml/icons}/21-cube-01.svg (100%)
 rename scripts/simplifiedUI/system/create/{create-icons => qml/icons}/22-sphere-01.svg (100%)
 rename scripts/simplifiedUI/system/create/{create-icons => qml/icons}/23-zone-01.svg (100%)
 rename scripts/simplifiedUI/system/create/{create-icons => qml/icons}/24-light-01.svg (100%)
 rename scripts/simplifiedUI/system/create/{create-icons => qml/icons}/25-web-1-01.svg (100%)
 create mode 100644 scripts/simplifiedUI/system/create/qml/icons/90-particles-01.svg
 rename scripts/simplifiedUI/system/create/{create-icons => qml/icons}/94-model-01.svg (100%)
 rename scripts/simplifiedUI/system/create/{create-icons => qml/icons}/image.svg (100%)
 create mode 100644 scripts/simplifiedUI/system/keyboardShortcuts/keyboardShortcuts.js

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 3c37bb6a6f..b0da721823 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -7880,7 +7880,7 @@ void Application::showAssetServerWidget(QString filePath) {
         if (!hmd->getShouldShowTablet() && !isHMDMode()) {
             getOffscreenUI()->show(url, "AssetServer", startUpload);
         } else {
-            static const QUrl url("hifi/dialogs/TabletAssetServer.qml");
+            static const QUrl url("qrc:///qml/hifi/dialogs/TabletAssetServer.qml");
             if (!tablet->isPathLoaded(url)) {
                 tablet->pushOntoStack(url);
             }
diff --git a/scripts/simplifiedUI/system/assets/images/hourglass.svg b/scripts/simplifiedUI/system/assets/images/hourglass.svg
new file mode 100644
index 0000000000..5c5055b755
--- /dev/null
+++ b/scripts/simplifiedUI/system/assets/images/hourglass.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<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="-442.8 171 127.6 220" style="enable-background:new -442.8 171 127.6 220;" xml:space="preserve">
+<g id="Captions">
+</g>
+<g id="Your_Icon">
+	<path style="fill:#FFFFFF;" d="M-379.022,253.815c15.657-14.331,25.069-27.038,25.909-31.313l-51.775-0.055
+		C-403.917,226.88-394.503,239.642-379.022,253.815z"/>
+	<path style="fill:#FFFFFF;" d="M-326.2,222.762c0-25.881,0-38.562,0-38.562h11V171h-127.6v13.2h11c0,0,0,12.681,0,38.562
+		c0,19.413,29.121,46.105,43.677,58.238c-14.555,12.133-43.677,38.826-43.677,58.238c0,25.881,0,38.562,0,38.562h-11V391h127.6
+		v-13.2h-11c0,0,0-12.681,0-38.562c0-19.413-29.117-46.105-43.679-58.238C-355.317,268.867-326.2,242.174-326.2,222.762z
+		 M-339.4,339.238V364.6h-7.564c-1.192-4.4-12.848-21.281-32.017-38.821c-19.369,17.73-31.013,34.421-32.056,38.821h-7.564v-25.362
+		c0-11.051,21.382-33.051,39.609-48.211C-359.053,307.543-339.4,328.989-339.4,339.238z M-379.011,270.977
+		c-19.941-16.52-39.589-37.965-39.589-48.215V197.4h79.2v25.362C-339.4,233.814-360.777,255.819-379.011,270.977z"/>
+</g>
+</svg>
diff --git a/scripts/simplifiedUI/system/assets/data/createAppTooltips.json b/scripts/simplifiedUI/system/create/assets/data/createAppTooltips.json
similarity index 100%
rename from scripts/simplifiedUI/system/assets/data/createAppTooltips.json
rename to scripts/simplifiedUI/system/create/assets/data/createAppTooltips.json
diff --git a/scripts/simplifiedUI/system/create/assets/images/hourglass.svg b/scripts/simplifiedUI/system/create/assets/images/hourglass.svg
new file mode 100644
index 0000000000..5c5055b755
--- /dev/null
+++ b/scripts/simplifiedUI/system/create/assets/images/hourglass.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<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="-442.8 171 127.6 220" style="enable-background:new -442.8 171 127.6 220;" xml:space="preserve">
+<g id="Captions">
+</g>
+<g id="Your_Icon">
+	<path style="fill:#FFFFFF;" d="M-379.022,253.815c15.657-14.331,25.069-27.038,25.909-31.313l-51.775-0.055
+		C-403.917,226.88-394.503,239.642-379.022,253.815z"/>
+	<path style="fill:#FFFFFF;" d="M-326.2,222.762c0-25.881,0-38.562,0-38.562h11V171h-127.6v13.2h11c0,0,0,12.681,0,38.562
+		c0,19.413,29.121,46.105,43.677,58.238c-14.555,12.133-43.677,38.826-43.677,58.238c0,25.881,0,38.562,0,38.562h-11V391h127.6
+		v-13.2h-11c0,0,0-12.681,0-38.562c0-19.413-29.117-46.105-43.679-58.238C-355.317,268.867-326.2,242.174-326.2,222.762z
+		 M-339.4,339.238V364.6h-7.564c-1.192-4.4-12.848-21.281-32.017-38.821c-19.369,17.73-31.013,34.421-32.056,38.821h-7.564v-25.362
+		c0-11.051,21.382-33.051,39.609-48.211C-359.053,307.543-339.4,328.989-339.4,339.238z M-379.011,270.977
+		c-19.941-16.52-39.589-37.965-39.589-48.215V197.4h79.2v25.362C-339.4,233.814-360.777,255.819-379.011,270.977z"/>
+</g>
+</svg>
diff --git a/scripts/simplifiedUI/system/create/create-icons/90-particles-01.svg b/scripts/simplifiedUI/system/create/assets/images/icon-particles.svg
similarity index 100%
rename from scripts/simplifiedUI/system/create/create-icons/90-particles-01.svg
rename to scripts/simplifiedUI/system/create/assets/images/icon-particles.svg
diff --git a/scripts/simplifiedUI/system/create/assets/images/icon-point-light.svg b/scripts/simplifiedUI/system/create/assets/images/icon-point-light.svg
new file mode 100644
index 0000000000..896c35b63b
--- /dev/null
+++ b/scripts/simplifiedUI/system/create/assets/images/icon-point-light.svg
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<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 960 560" style="enable-background:new 0 0 960 560;" xml:space="preserve">
+<g>
+	<g>
+		<path style="fill:#333333;" d="M478.879,127.676c-83.872,0-152.325,68.454-152.325,152.325s68.454,152.325,152.325,152.325
+			s152.325-67.837,152.325-152.325C631.204,196.13,563.366,127.676,478.879,127.676z"/>
+		<path style="fill:#FFFFFF;" d="M478.881,437.281C392.156,437.281,321.6,366.725,321.6,280s70.557-157.281,157.281-157.281
+			S636.157,193.275,636.157,280S565.606,437.281,478.881,437.281z M478.881,132.627c-81.263,0-147.373,66.115-147.373,147.373
+			s66.11,147.373,147.373,147.373c81.258,0,147.368-66.115,147.368-147.373S560.138,132.627,478.881,132.627z"/>
+	</g>
+	<g>
+		<rect x="459.145" y="4.952" style="fill:#333333;" width="40.086" height="75.237"/>
+		<path style="fill:#FFFFFF;" d="M504.183,85.147h-49.99V0h49.99V85.147z M464.1,75.239h30.174V9.908H464.1V75.239z"/>
+	</g>
+	<g>
+		
+			<rect x="272.766" y="90.696" transform="matrix(-0.707 -0.7072 0.7072 -0.707 451.5123 408.5368)" style="fill:#333333;" width="75.236" height="40.085"/>
+		<path style="fill:#FFFFFF;" d="M322.809,158.519l-60.198-60.212l35.351-35.346l60.198,60.212L322.809,158.519z M276.621,98.307
+			l46.188,46.202l21.34-21.335l-46.188-46.202L276.621,98.307z"/>
+	</g>
+	<g>
+		<rect x="201.98" y="257.8" style="fill:#333333;" width="75.237" height="40.086"/>
+		<path style="fill:#FFFFFF;" d="M282.17,302.845h-85.142V252.85h85.142V302.845z M206.936,292.937h65.327v-30.179h-65.327V292.937z
+			"/>
+	</g>
+	<g>
+		
+			<rect x="287.46" y="408.97" transform="matrix(0.7072 0.707 -0.707 0.7072 405.7749 -86.6482)" style="fill:#333333;" width="40.085" height="75.236"/>
+		<path style="fill:#FFFFFF;" d="M295.083,494.359l-35.355-35.346l60.198-60.212l35.355,35.346L295.083,494.359z M273.738,459.013
+			l21.345,21.335l46.187-46.202l-21.345-21.335L273.738,459.013z"/>
+	</g>
+	<g>
+		<rect x="454.827" y="479.812" style="fill:#333333;" width="40.086" height="75.237"/>
+		<path style="fill:#FFFFFF;" d="M499.868,560h-49.995v-85.137h49.995V560z M459.781,550.091h30.179V484.77h-30.179V550.091z"/>
+	</g>
+	<g>
+		
+			<rect x="606.017" y="429.505" transform="matrix(0.707 0.7072 -0.7072 0.707 506.5034 -323.4691)" style="fill:#333333;" width="75.236" height="40.085"/>
+		<path style="fill:#FFFFFF;" d="M656.06,497.32l-60.198-60.212l35.351-35.346l60.198,60.212L656.06,497.32z M609.872,437.107
+			l46.187,46.202l21.34-21.335l-46.188-46.202L609.872,437.107z"/>
+	</g>
+	<g>
+		<rect x="676.839" y="262.117" style="fill:#333333;" width="75.237" height="40.086"/>
+		<path style="fill:#FFFFFF;" d="M757.032,307.16h-85.147v-49.995h85.147V307.16z M681.792,297.252h65.332v-30.179h-65.332V297.252z
+			"/>
+	</g>
+	<g>
+		
+			<rect x="626.205" y="75.756" transform="matrix(-0.7072 -0.707 0.707 -0.7072 1023.1211 650.4535)" style="fill:#333333;" width="40.085" height="75.236"/>
+		<path style="fill:#FFFFFF;" d="M633.825,161.161l-35.351-35.346l60.198-60.212l35.351,35.346L633.825,161.161z M612.485,125.815
+			l21.34,21.335l46.188-46.202l-21.34-21.335L612.485,125.815z"/>
+	</g>
+</g>
+</svg>
diff --git a/scripts/simplifiedUI/system/create/assets/images/icon-spot-light.svg b/scripts/simplifiedUI/system/create/assets/images/icon-spot-light.svg
new file mode 100644
index 0000000000..ac2f87bb27
--- /dev/null
+++ b/scripts/simplifiedUI/system/create/assets/images/icon-spot-light.svg
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="3.44 0 735.338 557.9" style="enable-background:new 3.44 0 735.338 557.9;" xml:space="preserve">
+<g>
+	<g>
+		<rect x="503.95" y="260.767" style="fill:#333333;" width="227.728" height="36.376"/>
+		<path style="fill:#FFFFFF;" d="M738.778,304.24H496.854v-50.566h241.924V304.24z M511.052,290.042H724.58v-22.17H511.052V290.042z
+			"/>
+	</g>
+	<g>
+		<g>
+			<g>
+				
+					<rect x="426.085" y="465.518" transform="matrix(-0.9213 -0.3888 0.3888 -0.9213 849.3369 1139.2869)" style="fill:#333333;" width="227.719" height="36.374"/>
+				<path style="fill:#FFFFFF;" d="M641.55,554.032l-222.88-94.06l19.668-46.6l222.88,94.06L641.55,554.032z M437.277,452.401
+					l196.717,83.024l8.617-20.423l-196.717-83.024L437.277,452.401z"/>
+			</g>
+			<g>
+				
+					<rect x="426.295" y="56.081" transform="matrix(0.9213 -0.3888 0.3888 0.9213 13.624 215.8596)" style="fill:#333333;" width="227.719" height="36.374"/>
+				<path style="fill:#FFFFFF;" d="M438.545,144.598l-19.668-46.6l222.887-94.06l19.667,46.6L438.545,144.598z M437.484,105.568
+					l8.617,20.423l196.724-83.024l-8.617-20.423L437.484,105.568z"/>
+			</g>
+		</g>
+		<g>
+			<path style="fill:#333333;" d="M430.774,280.311c0-50.839-32.955-93.895-78.642-109.198V13.262L124.404,165.081H10.54v227.728
+				h113.864l227.728,151.819V389.51C397.818,374.206,430.774,331.151,430.774,280.311z"/>
+			<path style="fill:#FFFFFF;" d="M359.23,557.9L122.257,399.908H3.44V157.978h118.816L359.23,0v166.117
+				c47.245,18.038,78.642,63.308,78.642,114.192s-31.397,96.154-78.642,114.192V557.9z M17.638,385.711h108.917l218.478,145.652
+				V384.407l4.846-1.622c44.139-14.794,73.796-55.973,73.796-102.476s-29.657-87.682-73.796-102.476l-4.846-1.622V26.538
+				L126.555,172.176H17.638V385.711z"/>
+		</g>
+	</g>
+</g>
+</svg>
diff --git a/scripts/simplifiedUI/system/create/assets/images/icon-zone.svg b/scripts/simplifiedUI/system/create/assets/images/icon-zone.svg
new file mode 100644
index 0000000000..41aeac4951
--- /dev/null
+++ b/scripts/simplifiedUI/system/create/assets/images/icon-zone.svg
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+
+<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"
+   id="Layer_1"
+   x="0px"
+   y="0px"
+   viewBox="0 0 512 512"
+   style="enable-background:new 0 0 512 512;"
+   xml:space="preserve"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="icon-zone.svg"><metadata
+     id="metadata4211"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+     id="defs4209" /><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="2560"
+     inkscape:window-height="1377"
+     id="namedview4207"
+     showgrid="false"
+     inkscape:zoom="2"
+     inkscape:cx="228.01796"
+     inkscape:cy="376.88605"
+     inkscape:window-x="-8"
+     inkscape:window-y="-8"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g4191" /><style
+     type="text/css"
+     id="style4189">
+	.st0{fill:none;stroke:#000000;stroke-width:18;stroke-miterlimit:10;}
+	.st1{fill:none;stroke:#000000;stroke-width:18;stroke-linecap:round;stroke-miterlimit:10;}
+	.st2{fill:none;stroke:#000000;stroke-width:19;stroke-linecap:round;stroke-miterlimit:10;}
+</style><g
+     id="g4191"><path
+       d="M 380.7,139.8 C 378,133.2 371.5,129 364.4,129 l -72.4,0 0,34 29.9,0 -162.9,163.1 0,-36.1 -36,0 0,79 0.006,0.024 c 0.1,2 0.5,4.1 1.3,5.9 C 127.00564,381.52397 134.7,386 141.8,386 l 83.2,0 0,-35 -40.8,0 161.8,-161.3 0,25.3 36.125,0.125 -0.19692,-62.65758 C 382.08839,148.14645 382.4,144 380.7,139.8 Z"
+       id="path4193"
+       style="fill:#333333;fill-opacity:1"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cscccccccccscccccccc" /><path
+       d="M338.4,437.6c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0   C348.1,459.3,338.4,449.6,338.4,437.6z M266.9,437.6c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0   c0,12-9.7,21.7-21.7,21.7l0,0C276.6,459.3,266.9,449.6,266.9,437.6z M195.4,437.6c0-12,9.7-21.7,21.7-21.7l0,0   c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0C205.1,459.3,195.4,449.6,195.4,437.6z M123.9,437.6   c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0C133.6,459.3,123.9,449.6,123.9,437.6z"
+       id="path4195"
+       style="fill:#333333;fill-opacity:1" /><path
+       d="M74.1,459.3c-5.7,0-11.3-2.3-15.4-6.4c-4-4-6.4-9.6-6.4-15.3c0-5.7,2.3-11.3,6.4-15.3c4-4,9.6-6.4,15.4-6.4   c5.7,0,11.3,2.3,15.3,6.4c4,4,6.4,9.6,6.4,15.3c0,5.7-2.3,11.3-6.4,15.3C85.4,457,79.8,459.3,74.1,459.3z"
+       id="path4197"
+       style="fill:#333333;fill-opacity:1" /><path
+       d="M52.4,366.1c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0   C62.1,387.8,52.4,378,52.4,366.1z M52.4,294.6c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7   l0,0C62.1,316.3,52.4,306.5,52.4,294.6z M52.4,223.1c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0   c0,12-9.7,21.7-21.7,21.7l0,0C62.1,244.8,52.4,235,52.4,223.1z M52.4,151.5c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7   l0,0c0,12-9.7,21.7-21.7,21.7l0,0C62.1,173.2,52.4,163.5,52.4,151.5z"
+       id="path4199"
+       style="fill:#333333;fill-opacity:1" /><path
+       d="M338.4,80c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0   C348.1,101.7,338.4,92,338.4,80z M266.9,80c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0   C276.6,101.7,266.9,92,266.9,80z M195.4,80c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0   C205.1,101.7,195.4,92,195.4,80z M123.9,80c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0   C133.6,101.7,123.9,92,123.9,80z"
+       id="path4201"
+       style="fill:#333333;fill-opacity:1" /><path
+       d="M431.6,101.7c-5.7,0-11.3-2.3-15.3-6.4c-4-4-6.4-9.6-6.4-15.3c0-5.7,2.3-11.3,6.4-15.3c4-4,9.6-6.4,15.3-6.4   s11.3,2.3,15.3,6.4c4,4,6.4,9.6,6.4,15.3c0,5.7-2.3,11.3-6.4,15.3C442.9,99.4,437.4,101.7,431.6,101.7z"
+       id="path4203"
+       style="fill:#333333;fill-opacity:1" /><path
+       d="M409.9,366.1c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0   C419.7,387.8,409.9,378.1,409.9,366.1z M409.9,294.6c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0   c0,12-9.7,21.7-21.7,21.7l0,0C419.7,316.3,409.9,306.5,409.9,294.6z M409.9,223.1c0-12,9.7-21.7,21.7-21.7l0,0   c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0C419.7,244.7,409.9,235,409.9,223.1z M409.9,151.5   c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0C419.7,173.2,409.9,163.5,409.9,151.5z"
+       id="path4205"
+       style="fill:#333333;fill-opacity:1" /></g></svg>
\ No newline at end of file
diff --git a/scripts/simplifiedUI/system/create/edit.js b/scripts/simplifiedUI/system/create/edit.js
new file mode 100644
index 0000000000..f50bc547e5
--- /dev/null
+++ b/scripts/simplifiedUI/system/create/edit.js
@@ -0,0 +1,2858 @@
+//  edit.js
+//
+//  Created by Brad Hefta-Gaub on 10/2/14.
+//  Persist toolbar by HRS 6/11/15.
+//  Copyright 2014 High Fidelity, Inc.
+//
+//  This script allows you to edit entities with a new UI/UX for mouse and trackpad based editing
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+/* global Script, SelectionDisplay, LightOverlayManager, CameraManager, Grid, GridTool, EntityListTool, Vec3, SelectionManager,
+   Overlays, OverlayWebWindow, UserActivityLogger, Settings, Entities, Tablet, Toolbars, Messages, Menu, Camera,
+   progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, OverlaySystemWindow,
+   keyUpEventFromUIWindow:true */
+
+(function() { // BEGIN LOCAL_SCOPE
+
+"use strict";
+
+var EDIT_TOGGLE_BUTTON = "com.highfidelity.interface.system.editButton";
+
+var CONTROLLER_MAPPING_NAME = "com.highfidelity.editMode";
+
+Script.include([
+    "../libraries/stringHelpers.js",
+    "../libraries/dataViewHelpers.js",
+    "../libraries/progressDialog.js",
+    "../libraries/ToolTip.js",
+    "../libraries/entityCameraTool.js",
+    "../libraries/utils.js",
+    "../libraries/entityIconOverlayManager.js",
+    "../libraries/gridTool.js",
+    "entityList/entityList.js",
+    "entitySelectionTool/entitySelectionTool.js"
+]);
+
+var CreateWindow = Script.require('./modules/createWindow.js');
+
+var TITLE_OFFSET = 60;
+var CREATE_TOOLS_WIDTH = 490;
+var MAX_DEFAULT_ENTITY_LIST_HEIGHT = 942;
+
+var DEFAULT_IMAGE = "https://hifi-content.s3.amazonaws.com/DomainContent/production/no-image.jpg";
+
+var createToolsWindow = new CreateWindow(
+    Script.resolvePath("qml/EditTools.qml"),
+    'Create Tools',
+    'com.highfidelity.create.createToolsWindow',
+    function () {
+        var windowHeight = Window.innerHeight - TITLE_OFFSET;
+        if (windowHeight > MAX_DEFAULT_ENTITY_LIST_HEIGHT) {
+            windowHeight = MAX_DEFAULT_ENTITY_LIST_HEIGHT;
+        }
+        return {
+            size: {
+                x: CREATE_TOOLS_WIDTH,
+                y: windowHeight
+            },
+            position: {
+                x: Window.x + Window.innerWidth - CREATE_TOOLS_WIDTH,
+                y: Window.y + TITLE_OFFSET
+            }
+        }
+    },
+    false
+);
+
+/**
+ * @description Returns true in case we should use the tablet version of the CreateApp
+ * @returns boolean
+ */
+var shouldUseEditTabletApp = function() {
+    return HMD.active || (!HMD.active && !Settings.getValue("desktopTabletBecomesToolbar", true));
+};
+
+
+var selectionDisplay = SelectionDisplay;
+var selectionManager = SelectionManager;
+
+var PARTICLE_SYSTEM_URL = Script.resolvePath("assets/images/icon-particles.svg");
+var POINT_LIGHT_URL = Script.resolvePath("assets/images/icon-point-light.svg");
+var SPOT_LIGHT_URL = Script.resolvePath("assets/images/icon-spot-light.svg");
+var ZONE_URL = Script.resolvePath("assets/images/icon-zone.svg");
+
+var entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect', 'Zone'], function(entityID) {
+    var properties = Entities.getEntityProperties(entityID, ['type', 'isSpotlight']);
+    if (properties.type === 'Light') {
+        return {
+            url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL,
+        };
+    } else if (properties.type === 'Zone') {
+        return {
+            url: ZONE_URL,
+        };
+    } else {
+        return {
+            url: PARTICLE_SYSTEM_URL,
+        };
+    }
+});
+
+var cameraManager = new CameraManager();
+
+var grid = new Grid();
+var gridTool = new GridTool({
+    horizontalGrid: grid,
+    createToolsWindow: createToolsWindow,
+    shouldUseEditTabletApp: shouldUseEditTabletApp
+});
+gridTool.setVisible(false);
+
+var EntityShapeVisualizer = Script.require('./modules/entityShapeVisualizer.js');
+var entityShapeVisualizer = new EntityShapeVisualizer(["Zone"]);
+
+var entityListTool = new EntityListTool(shouldUseEditTabletApp);
+
+selectionManager.addEventListener(function () {
+    selectionDisplay.updateHandles();
+    entityIconOverlayManager.updatePositions();
+    entityShapeVisualizer.setEntities(selectionManager.selections);
+});
+
+var DEGREES_TO_RADIANS = Math.PI / 180.0;
+var RADIANS_TO_DEGREES = 180.0 / Math.PI;
+
+var MIN_ANGULAR_SIZE = 2;
+var MAX_ANGULAR_SIZE = 45;
+var allowLargeModels = true;
+var allowSmallModels = true;
+
+var DEFAULT_DIMENSION = 0.20;
+
+var DEFAULT_DIMENSIONS = {
+    x: DEFAULT_DIMENSION,
+    y: DEFAULT_DIMENSION,
+    z: DEFAULT_DIMENSION
+};
+
+var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS);
+
+var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select";
+var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus";
+var MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "Show Lights and Particle Systems in Create Mode";
+var MENU_SHOW_ZONES_IN_EDIT_MODE = "Show Zones in Create Mode";
+
+var MENU_CREATE_ENTITIES_GRABBABLE = "Create Entities As Grabbable (except Zones, Particles, and Lights)";
+var MENU_ALLOW_SELECTION_LARGE = "Allow Selecting of Large Models";
+var MENU_ALLOW_SELECTION_SMALL = "Allow Selecting of Small Models";
+var MENU_ALLOW_SELECTION_LIGHTS = "Allow Selecting of Lights";
+
+var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect";
+var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus";
+var SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "showLightsAndParticlesInEditMode";
+var SETTING_SHOW_ZONES_IN_EDIT_MODE = "showZonesInEditMode";
+
+var SETTING_EDIT_PREFIX = "Edit/";
+
+
+var CREATE_ENABLED_ICON = "icons/tablet-icons/edit-i.svg";
+var CREATE_DISABLED_ICON = "icons/tablet-icons/edit-disabled.svg";
+
+// marketplace info, etc.  not quite ready yet.
+var SHOULD_SHOW_PROPERTY_MENU = false;
+var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain.";
+var INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG = "You do not have the necessary permissions to place items on this domain.";
+
+var isActive = false;
+var createButton = null;
+
+var IMPORTING_SVO_OVERLAY_WIDTH = 144;
+var IMPORTING_SVO_OVERLAY_HEIGHT = 30;
+var IMPORTING_SVO_OVERLAY_MARGIN = 5;
+var IMPORTING_SVO_OVERLAY_LEFT_MARGIN = 34;
+var importingSVOImageOverlay = Overlays.addOverlay("image", {
+    imageURL: Script.resolvePath("assets/images/hourglass.svg"),
+    width: 20,
+    height: 20,
+    alpha: 1.0,
+    x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH,
+    y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT,
+    visible: false
+});
+var importingSVOTextOverlay = Overlays.addOverlay("text", {
+    font: {
+        size: 14
+    },
+    text: "Importing SVO...",
+    leftMargin: IMPORTING_SVO_OVERLAY_LEFT_MARGIN,
+    x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH - IMPORTING_SVO_OVERLAY_MARGIN,
+    y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT - IMPORTING_SVO_OVERLAY_MARGIN,
+    width: IMPORTING_SVO_OVERLAY_WIDTH,
+    height: IMPORTING_SVO_OVERLAY_HEIGHT,
+    backgroundColor: {
+        red: 80,
+        green: 80,
+        blue: 80
+    },
+    backgroundAlpha: 0.7,
+    visible: false
+});
+
+var MARKETPLACE_URL = Account.metaverseServerURL + "/marketplace";
+var marketplaceWindow = new OverlayWebWindow({
+    title: 'Marketplace',
+    source: "about:blank",
+    width: 900,
+    height: 700,
+    visible: false
+});
+
+function showMarketplace(marketplaceID) {
+    var url = MARKETPLACE_URL;
+    if (marketplaceID) {
+        url = url + "/items/" + marketplaceID;
+    }
+    marketplaceWindow.setURL(url);
+    marketplaceWindow.setVisible(true);
+    marketplaceWindow.raise();
+
+    UserActivityLogger.logAction("opened_marketplace");
+}
+
+function hideMarketplace() {
+    marketplaceWindow.setVisible(false);
+    marketplaceWindow.setURL("about:blank");
+}
+
+// function toggleMarketplace() {
+//     if (marketplaceWindow.visible) {
+//         hideMarketplace();
+//     } else {
+//         showMarketplace();
+//     }
+// }
+
+function adjustPositionPerBoundingBox(position, direction, registration, dimensions, orientation) {
+    // Adjust the position such that the bounding box (registration, dimensions and orientation) lies behind the original
+    // position in the given direction.
+    var CORNERS = [
+        { x: 0, y: 0, z: 0 },
+        { x: 0, y: 0, z: 1 },
+        { x: 0, y: 1, z: 0 },
+        { x: 0, y: 1, z: 1 },
+        { x: 1, y: 0, z: 0 },
+        { x: 1, y: 0, z: 1 },
+        { x: 1, y: 1, z: 0 },
+        { x: 1, y: 1, z: 1 },
+    ];
+
+    // Go through all corners and find least (most negative) distance in front of position.
+    var distance = 0;
+    for (var i = 0, length = CORNERS.length; i < length; i++) {
+        var cornerVector =
+            Vec3.multiplyQbyV(orientation, Vec3.multiplyVbyV(Vec3.subtract(CORNERS[i], registration), dimensions));
+        var cornerDistance = Vec3.dot(cornerVector, direction);
+        distance = Math.min(cornerDistance, distance);
+    }
+    position = Vec3.sum(Vec3.multiply(distance, direction), position);
+    return position;
+}
+
+var GRABBABLE_ENTITIES_MENU_CATEGORY = "Edit";
+
+// Handles any edit mode updates required when domains have switched
+function checkEditPermissionsAndUpdate() {
+    if ((createButton === null) || (createButton === undefined)) {
+        //--EARLY EXIT--( nothing to safely update )
+        return;
+    }
+
+    var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified());
+    createButton.editProperties({
+        icon: (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON),
+        captionColor: (hasRezPermissions ? "#ffffff" : "#888888"),
+    });
+
+    if (!hasRezPermissions && isActive) {
+        that.setActive(false);
+        tablet.gotoHomeScreen();
+    }
+}
+
+// Copies the properties in `b` into `a`. `a` will be modified.
+function copyProperties(a, b) {
+    for (var key in b) {
+        a[key] = b[key];
+    }
+    return a;
+}
+
+const DEFAULT_DYNAMIC_PROPERTIES = {
+    dynamic: true,
+    damping: 0.39347,
+    angularDamping: 0.39347,
+    gravity: { x: 0, y: -9.8, z: 0 },
+};
+
+const DEFAULT_NON_DYNAMIC_PROPERTIES = {
+    dynamic: false,
+    damping: 0,
+    angularDamping: 0,
+    gravity: { x: 0, y: 0, z: 0 },
+};
+
+const DEFAULT_ENTITY_PROPERTIES = {
+    All: {
+        description: "",
+        rotation: { x: 0, y: 0, z: 0, w: 1 },
+        collidesWith: "static,dynamic,kinematic,otherAvatar,myAvatar",
+        collisionSoundURL: "",
+        cloneable: false,
+        ignoreIK: true,
+        canCastShadow: true,
+        href: "",
+        script: "",
+        serverScripts:"",
+        velocity: {
+            x: 0,
+            y: 0,
+            z: 0
+        },
+        angularVelocity: {
+            x: 0,
+            y: 0,
+            z: 0
+        },
+        restitution: 0.5,
+        friction: 0.5,
+        density: 1000,
+        dynamic: false,
+    },
+    Shape: {
+        shape: "Box",
+        dimensions: { x: 0.2, y: 0.2, z: 0.2 },
+        color: { red: 0, green: 180, blue: 239 },
+    },
+    Text: {
+        text: "Text",
+        dimensions: {
+            x: 0.65,
+            y: 0.3,
+            z: 0.01
+        },
+        textColor: { red: 255, green: 255, blue: 255 },
+        backgroundColor: { red: 0, green: 0, blue: 0 },
+        lineHeight: 0.06,
+        faceCamera: false,
+    },
+    Zone: {
+        dimensions: {
+            x: 10,
+            y: 10,
+            z: 10
+        },
+        flyingAllowed: true,
+        ghostingAllowed: true,
+        filter: "",
+        keyLightMode: "inherit",
+        keyLightColor: { red: 255, green: 255, blue: 255 },
+        keyLight: {
+            intensity: 1.0,
+            direction: {
+                x: 0.0,
+                y: -0.707106769084930, // 45 degrees
+                z: 0.7071067690849304
+            },
+            castShadows: true
+        },
+        ambientLightMode: "inherit",
+        ambientLight: {
+            ambientIntensity: 0.5,
+            ambientURL: ""
+        },
+        hazeMode: "inherit",
+        haze: {
+            hazeRange: 1000,
+            hazeAltitudeEffect: false,
+            hazeBaseRef: 0,
+            hazeColor: {
+                red: 128,
+                green: 154,
+                blue: 179
+            },
+            hazeBackgroundBlend: 0,
+            hazeEnableGlare: false,
+            hazeGlareColor: {
+                red: 255,
+                green: 229,
+                blue: 179
+            },
+        },
+        shapeType: "box",
+        bloomMode: "inherit",
+        avatarPriority: "inherit"
+    },
+    Model: {
+        collisionShape: "none",
+        compoundShapeURL: "",
+        animation: {
+            url: "",
+            running: false,
+            allowTranslation: false,
+            loop: true,
+            hold: false,
+            currentFrame: 0,
+            firstFrame: 0,
+            lastFrame: 100000,
+            fps: 30.0,
+        }
+    },
+    Image: {
+        dimensions: {
+            x: 0.5385,
+            y: 0.2819,
+            z: 0.0092
+        },
+        shapeType: "box",
+        collisionless: true,
+        keepAspectRatio: false,
+        imageURL: DEFAULT_IMAGE
+    },
+    Web: {
+        dimensions: {
+            x: 1.6,
+            y: 0.9,
+            z: 0.01
+        },
+        sourceUrl: "https://highfidelity.com/",
+        dpi: 30,
+    },
+    ParticleEffect: {
+        lifespan: 1.5,
+        maxParticles: 10,
+        textures: "https://content.highfidelity.com/DomainContent/production/Particles/wispy-smoke.png",
+        emitRate: 5.5,
+        emitSpeed: 0,
+        speedSpread: 0,
+        emitDimensions: { x: 0, y: 0, z: 0 },
+        emitOrientation: { x: 0, y: 0, z: 0, w: 1 },
+        emitterShouldTrail: true,
+        particleRadius: 0.25,
+        radiusStart: 0,
+        radiusSpread: 0,
+        particleColor: {
+            red: 255,
+            green: 255,
+            blue: 255
+        },
+        colorSpread: {
+            red: 0,
+            green: 0,
+            blue: 0
+        },
+        alpha: 0,
+        alphaStart: 1,
+        alphaSpread: 0,
+        emitAcceleration: {
+            x: 0,
+            y: 2.5,
+            z: 0
+        },
+        accelerationSpread: {
+            x: 0,
+            y: 0,
+            z: 0
+        },
+        particleSpin: 0,
+        spinSpread: 0,
+        rotateWithEntity: false,
+        polarStart: 0,
+        polarFinish: Math.PI,
+        azimuthStart: -Math.PI,
+        azimuthFinish: Math.PI
+    },
+    Light: {
+        color: { red: 255, green: 255, blue: 255 },
+        intensity: 5.0,
+        dimensions: DEFAULT_LIGHT_DIMENSIONS,
+        falloffRadius: 1.0,
+        isSpotlight: false,
+        exponent: 1.0,
+        cutoff: 75.0,
+    },
+};
+
+var toolBar = (function () {
+    var EDIT_SETTING = "io.highfidelity.isEditing"; // for communication with other scripts
+    var that = {},
+        toolBar,
+        activeButton = null,
+        systemToolbar = null,
+        dialogWindow = null,
+        tablet = null;
+
+    function createNewEntity(requestedProperties) {
+        var dimensions = requestedProperties.dimensions ? requestedProperties.dimensions : DEFAULT_DIMENSIONS;
+        var position = getPositionToCreateEntity();
+        var entityID = null;
+
+        var properties = {};
+
+        copyProperties(properties, DEFAULT_ENTITY_PROPERTIES.All);
+
+        var type = requestedProperties.type;
+        if (type === "Box" || type === "Sphere") {
+            copyProperties(properties, DEFAULT_ENTITY_PROPERTIES.Shape);
+        } else {
+            copyProperties(properties, DEFAULT_ENTITY_PROPERTIES[type]);
+        }
+
+        // We apply the requested properties first so that they take priority over any default properties.
+        copyProperties(properties, requestedProperties);
+
+        if (properties.dynamic) {
+            copyProperties(properties, DEFAULT_DYNAMIC_PROPERTIES);
+        } else {
+            copyProperties(properties, DEFAULT_NON_DYNAMIC_PROPERTIES);
+        }
+
+
+        if (position !== null && position !== undefined) {
+            var direction;
+            if (Camera.mode === "entity" || Camera.mode === "independent") {
+                direction = Camera.orientation;
+            } else {
+                direction = MyAvatar.orientation;
+            }
+            direction = Vec3.multiplyQbyV(direction, Vec3.UNIT_Z);
+
+            var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Image", "Web", "Material"];
+            if (PRE_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) {
+
+                // Adjust position of entity per bounding box prior to creating it.
+                var registration = properties.registration;
+                if (registration === undefined) {
+                    var DEFAULT_REGISTRATION = { x: 0.5, y: 0.5, z: 0.5 };
+                    registration = DEFAULT_REGISTRATION;
+                }
+
+                var orientation = properties.orientation;
+                if (orientation === undefined) {
+                    properties.orientation = MyAvatar.orientation;
+                    var DEFAULT_ORIENTATION = properties.orientation;
+                    orientation = DEFAULT_ORIENTATION;
+                } else {
+                    // If the orientation is already defined, we perform the corresponding rotation assuming that
+                    //  our start referential is the avatar referential.
+                    properties.orientation = Quat.multiply(MyAvatar.orientation, properties.orientation);
+                    var DEFAULT_ORIENTATION = properties.orientation;
+                    orientation = DEFAULT_ORIENTATION;
+                }
+
+                position = adjustPositionPerBoundingBox(position, direction, registration, dimensions, orientation);
+            }
+
+            position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions);
+            properties.position = position;
+
+            if (!properties.grab) {
+                properties.grab = {};
+                if (Menu.isOptionChecked(MENU_CREATE_ENTITIES_GRABBABLE) &&
+                    !(properties.type === "Zone" || properties.type === "Light" || properties.type === "ParticleEffect")) {
+                    properties.grab.grabbable = true;
+                } else {
+                    properties.grab.grabbable = false;
+                }
+            }
+
+            entityID = Entities.addEntity(properties);
+            SelectionManager.addEntity(entityID, false, this);
+            SelectionManager.saveProperties();
+            pushCommandForSelections([{
+                entityID: entityID,
+                properties: properties
+            }], [], true);
+
+            var POST_ADJUST_ENTITY_TYPES = ["Model"];
+            if (POST_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) {
+                // Adjust position of entity per bounding box after it has been created and auto-resized.
+                var initialDimensions = Entities.getEntityProperties(entityID, ["dimensions"]).dimensions;
+                var DIMENSIONS_CHECK_INTERVAL = 200;
+                var MAX_DIMENSIONS_CHECKS = 10;
+                var dimensionsCheckCount = 0;
+                var dimensionsCheckFunction = function () {
+                    dimensionsCheckCount++;
+                    var properties = Entities.getEntityProperties(entityID, ["dimensions", "registrationPoint", "rotation"]);
+                    if (!Vec3.equal(properties.dimensions, initialDimensions)) {
+                        position = adjustPositionPerBoundingBox(position, direction, properties.registrationPoint,
+                            properties.dimensions, properties.rotation);
+                        position = grid.snapToSurface(grid.snapToGrid(position, false, properties.dimensions),
+                            properties.dimensions);
+                        Entities.editEntity(entityID, {
+                            position: position
+                        });
+                        selectionManager._update(false, this);
+                    } else if (dimensionsCheckCount < MAX_DIMENSIONS_CHECKS) {
+                        Script.setTimeout(dimensionsCheckFunction, DIMENSIONS_CHECK_INTERVAL);
+                    }
+                };
+                Script.setTimeout(dimensionsCheckFunction, DIMENSIONS_CHECK_INTERVAL);
+            }
+        } else {
+            Window.notifyEditError("Can't create " + properties.type + ": " +
+                                   properties.type + " would be out of bounds.");
+        }
+
+        selectionManager.clearSelections(this);
+        entityListTool.sendUpdate();
+        selectionManager.setSelections([entityID], this);
+
+        Window.setFocus();
+
+        return entityID;
+    }
+
+    function closeExistingDialogWindow() {
+        if (dialogWindow) {
+            dialogWindow.close();
+            dialogWindow = null;
+        }
+    }
+
+    function cleanup() {
+        that.setActive(false);
+        if (tablet) {
+            tablet.removeButton(activeButton);
+        }
+        if (systemToolbar) {
+            systemToolbar.removeButton(EDIT_TOGGLE_BUTTON);
+        }
+    }
+
+    var buttonHandlers = {}; // only used to tablet mode
+
+    function addButton(name, handler) {
+        buttonHandlers[name] = handler;
+    }
+
+    var SHAPE_TYPE_NONE = 0;
+    var SHAPE_TYPE_SIMPLE_HULL = 1;
+    var SHAPE_TYPE_SIMPLE_COMPOUND = 2;
+    var SHAPE_TYPE_STATIC_MESH = 3;
+    var SHAPE_TYPE_BOX = 4;
+    var SHAPE_TYPE_SPHERE = 5;
+    var DYNAMIC_DEFAULT = false;
+
+    var MATERIAL_MODE_UV = 0;
+    var MATERIAL_MODE_PROJECTED = 1;
+
+    function handleNewModelDialogResult(result) {
+        if (result) {
+            var url = result.url;
+            var shapeType;
+            switch (result.collisionShapeIndex) {
+            case SHAPE_TYPE_SIMPLE_HULL:
+                shapeType = "simple-hull";
+                break;
+            case SHAPE_TYPE_SIMPLE_COMPOUND:
+                shapeType = "simple-compound";
+                break;
+            case SHAPE_TYPE_STATIC_MESH:
+                shapeType = "static-mesh";
+                break;
+            case SHAPE_TYPE_BOX:
+                shapeType = "box";
+                break;
+            case SHAPE_TYPE_SPHERE:
+                shapeType = "sphere";
+                break;
+            default:
+                shapeType = "none";
+            }
+
+            var dynamic = result.dynamic !== null ? result.dynamic : DYNAMIC_DEFAULT;
+            if (shapeType === "static-mesh" && dynamic) {
+                // The prompt should prevent this case
+                print("Error: model cannot be both static mesh and dynamic.  This should never happen.");
+            } else if (url) {
+                createNewEntity({
+                    type: "Model",
+                    modelURL: url,
+                    shapeType: shapeType,
+                    grab: {
+                        grabbable: result.grabbable
+                    },
+                    dynamic: dynamic,
+                });
+            }
+        }
+    }
+
+    function handleNewMaterialDialogResult(result) {
+        if (result) {
+            var materialURL = result.textInput;
+            //var materialMappingMode;
+            //switch (result.comboBox) {
+            //    case MATERIAL_MODE_PROJECTED:
+            //        materialMappingMode = "projected";
+            //        break;
+            //    default:
+            //        shapeType = "uv";
+            //}
+            var materialData = "";
+            if (materialURL.startsWith("materialData")) {
+                materialData = JSON.stringify({
+                    "materials": {}
+                });
+            }
+
+            var DEFAULT_LAYERED_MATERIAL_PRIORITY = 1;
+            if (materialURL) {
+                createNewEntity({
+                    type: "Material",
+                    materialURL: materialURL,
+                    //materialMappingMode: materialMappingMode,
+                    priority: DEFAULT_LAYERED_MATERIAL_PRIORITY,
+                    materialData: materialData
+                });
+            }
+        }
+    }
+
+    function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml.
+        var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
+        tablet.popFromStack();
+        switch (message.method) {
+            case "newModelDialogAdd":
+                handleNewModelDialogResult(message.params);
+                closeExistingDialogWindow();
+                break;
+            case "newModelDialogCancel":
+                closeExistingDialogWindow();
+                break;
+            case "newEntityButtonClicked":
+                buttonHandlers[message.params.buttonName]();
+                break;
+            case "newMaterialDialogAdd":
+                handleNewMaterialDialogResult(message.params);
+                closeExistingDialogWindow();
+                break;
+            case "newMaterialDialogCancel":
+                closeExistingDialogWindow();
+                break;
+        }
+    }
+
+    var entitiesToDelete = [];
+    var deletedEntityTimer = null;
+    var DELETE_ENTITY_TIMER_TIMEOUT = 100;
+
+    function checkDeletedEntityAndUpdate(entityID) {
+        // Allow for multiple entity deletes before updating the entities selected.
+        entitiesToDelete.push(entityID);
+        if (deletedEntityTimer !== null) {
+            Script.clearTimeout(deletedEntityTimer);
+        }
+        deletedEntityTimer = Script.setTimeout(function () {
+            if (entitiesToDelete.length > 0) {
+                selectionManager.removeEntities(entitiesToDelete, this);
+            }
+            entityListTool.removeEntities(entitiesToDelete, selectionManager.selections);
+            entitiesToDelete = [];
+            deletedEntityTimer = null;
+        }, DELETE_ENTITY_TIMER_TIMEOUT);
+    }
+
+    function initialize() {
+        Script.scriptEnding.connect(cleanup);
+        Window.domainChanged.connect(function () {
+            if (isActive) {
+                tablet.gotoHomeScreen();
+            }
+            that.setActive(false);
+            that.clearEntityList();
+            checkEditPermissionsAndUpdate();
+        });
+
+        HMD.displayModeChanged.connect(function() {
+            if (isActive) {
+                tablet.gotoHomeScreen();
+            }
+            that.setActive(false);
+        });
+
+        Entities.canAdjustLocksChanged.connect(function (canAdjustLocks) {
+            if (isActive && !canAdjustLocks) {
+                that.setActive(false);
+            }
+            checkEditPermissionsAndUpdate();
+        });
+
+        Entities.canRezChanged.connect(checkEditPermissionsAndUpdate);
+        Entities.canRezTmpChanged.connect(checkEditPermissionsAndUpdate);
+        Entities.canRezCertifiedChanged.connect(checkEditPermissionsAndUpdate);
+        Entities.canRezTmpCertifiedChanged.connect(checkEditPermissionsAndUpdate);
+        var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified());
+
+        Entities.deletingEntity.connect(checkDeletedEntityAndUpdate);
+
+        var createButtonIconRsrc = (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON);
+        tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
+        activeButton = tablet.addButton({
+            captionColor: hasRezPermissions ? "#ffffff" : "#888888",
+            icon: createButtonIconRsrc,
+            activeIcon: "icons/tablet-icons/edit-a.svg",
+            text: "CREATE",
+            sortOrder: 10
+        });
+        createButton = activeButton;
+        tablet.screenChanged.connect(function (type, url) {
+            var isGoingToHomescreenOnDesktop = (!shouldUseEditTabletApp() &&
+                (url === 'hifi/tablet/TabletHome.qml' || url === ''));
+            if (isActive && (type !== "QML" || url !== Script.resolvePath("qml/Edit.qml")) && !isGoingToHomescreenOnDesktop) {
+                that.setActive(false);
+            }
+        });
+        tablet.fromQml.connect(fromQml);
+        createToolsWindow.fromQml.addListener(fromQml);
+
+        createButton.clicked.connect(function() {
+            if ( ! (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()) ) {
+                Window.notifyEditError(INSUFFICIENT_PERMISSIONS_ERROR_MSG);
+                return;
+            }
+
+            that.toggle();
+        });
+
+        addButton("importEntitiesButton", function() {
+            Window.browseChanged.connect(onFileOpenChanged);
+            Window.browseAsync("Select Model to Import", "", "*.json");
+        });
+
+        addButton("openAssetBrowserButton", function() {
+            Window.showAssetServer();
+        });
+        function createNewEntityDialogButtonCallback(entityType) {
+            return function() {
+                if (shouldUseEditTabletApp()) {
+                    // tablet version of new-model dialog
+                    var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
+                    tablet.pushOntoStack(Script.resolvePath("qml/New" + entityType + "Dialog.qml"));
+                } else {
+                    closeExistingDialogWindow();
+                    var qmlPath = Script.resolvePath("qml/New" + entityType + "Window.qml");
+                    var DIALOG_WINDOW_SIZE = { x: 500, y: 300 };
+                    dialogWindow = Desktop.createWindow(qmlPath, {
+                        title: "New " + entityType + " Entity",
+                        flags: Desktop.ALWAYS_ON_TOP | Desktop.CLOSE_BUTTON_HIDES,
+                        presentationMode: Desktop.PresentationMode.NATIVE,
+                        size: DIALOG_WINDOW_SIZE,
+                        visible: true
+                    });
+                    dialogWindow.fromQml.connect(fromQml);
+                }
+            };
+        }
+
+        addButton("newModelButton", createNewEntityDialogButtonCallback("Model"));
+
+        addButton("newShapeButton", function () {
+            createNewEntity({
+                type: "Shape",
+                shape: "Cube",
+            });
+        });
+
+        addButton("newLightButton", function () {
+            createNewEntity({
+                type: "Light",
+            });
+        });
+
+        addButton("newTextButton", function () {
+            createNewEntity({
+                type: "Text",
+            });
+        });
+
+        addButton("newImageButton", function () {
+            createNewEntity({
+                type: "Image",
+            });
+        });
+
+        addButton("newWebButton", function () {
+            createNewEntity({
+                type: "Web",
+            });
+        });
+
+        addButton("newZoneButton", function () {
+            createNewEntity({
+                type: "Zone",
+            });
+        });
+
+        addButton("newParticleButton", function () {
+            createNewEntity({
+                type: "ParticleEffect",
+            });
+        });
+
+        addButton("newMaterialButton", createNewEntityDialogButtonCallback("Material"));
+
+        var deactivateCreateIfDesktopWindowsHidden = function() {
+            if (!shouldUseEditTabletApp() && !entityListTool.isVisible() && !createToolsWindow.isVisible()) {
+                that.setActive(false);
+            }
+        };
+        entityListTool.interactiveWindowHidden.addListener(this, deactivateCreateIfDesktopWindowsHidden);
+        createToolsWindow.interactiveWindowHidden.addListener(this, deactivateCreateIfDesktopWindowsHidden);
+
+        that.setActive(false);
+    }
+
+    that.clearEntityList = function () {
+        entityListTool.clearEntityList();
+    };
+
+    that.toggle = function () {
+        that.setActive(!isActive);
+        if (!isActive) {
+            tablet.gotoHomeScreen();
+        }
+    };
+
+    that.setActive = function (active) {
+        ContextOverlay.enabled = !active;
+        Settings.setValue(EDIT_SETTING, active);
+        if (active) {
+            Controller.captureEntityClickEvents();
+        } else {
+            Controller.releaseEntityClickEvents();
+
+            closeExistingDialogWindow();
+        }
+        if (active === isActive) {
+            return;
+        }
+        if (active && !Entities.canRez() && !Entities.canRezTmp() && !Entities.canRezCertified() && !Entities.canRezTmpCertified()) {
+            Window.notifyEditError(INSUFFICIENT_PERMISSIONS_ERROR_MSG);
+            return;
+        }
+        Messages.sendLocalMessage("edit-events", JSON.stringify({
+            enabled: active
+        }));
+        isActive = active;
+        activeButton.editProperties({isActive: isActive});
+        undoHistory.setEnabled(isActive);
+
+        var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
+
+        if (!isActive) {
+            entityListTool.setVisible(false);
+            gridTool.setVisible(false);
+            grid.setEnabled(false);
+            propertiesTool.setVisible(false);
+            selectionManager.clearSelections(this);
+            cameraManager.disable();
+            selectionDisplay.disableTriggerMapping();
+            tablet.landscape = false;
+            Controller.disableMapping(CONTROLLER_MAPPING_NAME);
+        } else {
+            if (shouldUseEditTabletApp()) {
+                tablet.loadQMLSource(Script.resolvePath("qml/Edit.qml"), true);
+            } else {
+                // make other apps inactive while in desktop mode
+                tablet.gotoHomeScreen();
+            }
+            UserActivityLogger.enabledEdit();
+            entityListTool.setVisible(true);
+            entityListTool.sendUpdate();
+            gridTool.setVisible(true);
+            grid.setEnabled(true);
+            propertiesTool.setVisible(true);
+            selectionDisplay.enableTriggerMapping();
+            print("starting tablet in landscape mode");
+            tablet.landscape = true;
+            Controller.enableMapping(CONTROLLER_MAPPING_NAME);
+            // Not sure what the following was meant to accomplish, but it currently causes
+            // everybody else to think that Interface has lost focus overall. fogbugzid:558
+            // Window.setFocus();
+        }
+        entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE));
+        Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
+    };
+
+    initialize();
+    return that;
+})();
+
+var selectedEntityID;
+var orientation;
+var intersection;
+
+
+function rayPlaneIntersection(pickRay, point, normal) { //
+    //
+    //  This version of the test returns the intersection of a line with a plane
+    //
+    var collides = Vec3.dot(pickRay.direction, normal);
+
+    var d = -Vec3.dot(point, normal);
+    var t = -(Vec3.dot(pickRay.origin, normal) + d) / collides;
+
+    return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t));
+}
+
+function rayPlaneIntersection2(pickRay, point, normal) {
+    //
+    //  This version of the test returns false if the ray is directed away from the plane
+    //
+    var collides = Vec3.dot(pickRay.direction, normal);
+    var d = -Vec3.dot(point, normal);
+    var t = -(Vec3.dot(pickRay.origin, normal) + d) / collides;
+    if (t < 0.0) {
+        return false;
+    } else {
+        return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t));
+    }
+}
+
+function findClickedEntity(event) {
+    var pickZones = event.isControl;
+
+    if (pickZones) {
+        Entities.setZonesArePickable(true);
+    }
+
+    var pickRay = Camera.computePickRay(event.x, event.y);
+    var tabletIDs = getMainTabletIDs();
+    if (tabletIDs.length > 0) {
+        var overlayResult = Overlays.findRayIntersection(pickRay, true, tabletIDs);
+        if (overlayResult.intersects) {
+            return null;
+        }
+    }
+
+    var entityResult = Entities.findRayIntersection(pickRay, true); // want precision picking
+    var iconResult = entityIconOverlayManager.findRayIntersection(pickRay);
+    iconResult.accurate = true;
+
+    if (pickZones) {
+        Entities.setZonesArePickable(false);
+    }
+
+    var result;
+
+    if (iconResult.intersects) {
+        result = iconResult;
+    } else if (entityResult.intersects) {
+        result = entityResult;
+    } else {
+        return null;
+    }
+
+    if (!result.accurate) {
+        return null;
+    }
+
+    var foundEntity = result.entityID;
+    return {
+        pickRay: pickRay,
+        entityID: foundEntity,
+        intersection: result.intersection
+    };
+}
+
+// Handles selections on overlays while in edit mode by querying entities from
+// entityIconOverlayManager.
+function handleOverlaySelectionToolUpdates(channel, message, sender) {
+    var wantDebug = false;
+    if (sender !== MyAvatar.sessionUUID || channel !== 'entityToolUpdates')
+        return;
+
+    var data = JSON.parse(message);
+
+    if (data.method === "selectOverlay") {
+        if (!selectionDisplay.triggered() || selectionDisplay.triggeredHand === data.hand) {
+            if (wantDebug) {
+                print("setting selection to overlay " + data.overlayID);
+            }
+            var entity = entityIconOverlayManager.findEntity(data.overlayID);
+
+            if (entity !== null) {
+                selectionManager.setSelections([entity], this);
+            }
+        }
+    }
+}
+
+function handleMessagesReceived(channel, message, sender) {
+    switch( channel ){
+        case 'entityToolUpdates': {
+            handleOverlaySelectionToolUpdates( channel, message, sender );
+            break;
+        }
+        default: {
+            return;
+        }
+    }
+}
+
+Messages.subscribe("entityToolUpdates");
+Messages.messageReceived.connect(handleMessagesReceived);
+
+var mouseHasMovedSincePress = false;
+var mousePressStartTime = 0;
+var mousePressStartPosition = {
+    x: 0,
+    y: 0
+};
+var mouseDown = false;
+
+function mousePressEvent(event) {
+    mouseDown = true;
+    mousePressStartPosition = {
+        x: event.x,
+        y: event.y
+    };
+    mousePressStartTime = Date.now();
+    mouseHasMovedSincePress = false;
+    mouseCapturedByTool = false;
+
+    if (propertyMenu.mousePressEvent(event) || progressDialog.mousePressEvent(event)) {
+        mouseCapturedByTool = true;
+        return;
+    }
+    if (isActive) {
+        if (cameraManager.mousePressEvent(event) || selectionDisplay.mousePressEvent(event)) {
+            // Event handled; do nothing.
+            return;
+        }
+    }
+}
+
+var mouseCapturedByTool = false;
+var lastMousePosition = null;
+var CLICK_TIME_THRESHOLD = 500 * 1000; // 500 ms
+var CLICK_MOVE_DISTANCE_THRESHOLD = 20;
+var IDLE_MOUSE_TIMEOUT = 200;
+
+var lastMouseMoveEvent = null;
+
+function mouseMoveEventBuffered(event) {
+    lastMouseMoveEvent = event;
+}
+
+function mouseMove(event) {
+    if (mouseDown && !mouseHasMovedSincePress) {
+        var timeSincePressMicro = Date.now() - mousePressStartTime;
+
+        var dX = mousePressStartPosition.x - event.x;
+        var dY = mousePressStartPosition.y - event.y;
+        var sqDist = (dX * dX) + (dY * dY);
+
+        // If less than CLICK_TIME_THRESHOLD has passed since the mouse click AND the mouse has moved
+        // less than CLICK_MOVE_DISTANCE_THRESHOLD distance, then don't register this as a mouse move
+        // yet. The goal is to provide mouse clicks that are more lenient to small movements.
+        if (timeSincePressMicro < CLICK_TIME_THRESHOLD && sqDist < CLICK_MOVE_DISTANCE_THRESHOLD) {
+            return;
+        }
+        mouseHasMovedSincePress = true;
+    }
+
+    if (!isActive) {
+        return;
+    }
+
+    // allow the selectionDisplay and cameraManager to handle the event first, if it doesn't handle it, then do our own thing
+    if (selectionDisplay.mouseMoveEvent(event) || propertyMenu.mouseMoveEvent(event) || cameraManager.mouseMoveEvent(event)) {
+        return;
+    }
+
+    lastMousePosition = {
+        x: event.x,
+        y: event.y
+    };
+}
+
+function mouseReleaseEvent(event) {
+    mouseDown = false;
+
+    if (lastMouseMoveEvent) {
+        mouseMove(lastMouseMoveEvent);
+        lastMouseMoveEvent = null;
+    }
+    if (propertyMenu.mouseReleaseEvent(event)) {
+        return true;
+    }
+    if (isActive && selectionManager.hasSelection()) {
+        tooltip.show(false);
+    }
+    if (mouseCapturedByTool) {
+
+        return;
+    }
+
+    cameraManager.mouseReleaseEvent(event);
+
+    if (!mouseHasMovedSincePress) {
+        mouseClickEvent(event);
+    }
+}
+
+function wasTabletOrEditHandleClicked(event) {
+    var rayPick = Camera.computePickRay(event.x, event.y);
+    var result = Overlays.findRayIntersection(rayPick, true);
+    if (result.intersects) {
+        var overlayID = result.overlayID;
+        var tabletIDs = getMainTabletIDs();
+        if (tabletIDs.indexOf(overlayID) >= 0) {
+            return true;
+        } else if (selectionDisplay.isEditHandle(overlayID)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+function mouseClickEvent(event) {
+    var wantDebug = false;
+    var result, properties, tabletClicked;
+    if (isActive && event.isLeftButton) {
+        result = findClickedEntity(event);
+        var tabletOrEditHandleClicked = wasTabletOrEditHandleClicked(event);
+        if (tabletOrEditHandleClicked) {
+            return;
+        }
+
+        if (result === null || result === undefined) {
+            if (!event.isShifted) {
+                selectionManager.clearSelections(this);
+            }
+            return;
+        }
+        toolBar.setActive(true);
+        var pickRay = result.pickRay;
+        var foundEntity = result.entityID;
+        if (HMD.tabletID && foundEntity === HMD.tabletID) {
+            return;
+        }
+        properties = Entities.getEntityProperties(foundEntity);
+        var halfDiagonal = Vec3.length(properties.dimensions) / 2.0;
+
+        if (wantDebug) {
+            print("Checking properties: " + properties.id + " " + " - Half Diagonal:" + halfDiagonal);
+        }
+        //                P         P - Model
+        //               /|         A - Palm
+        //              / | d       B - unit vector toward tip
+        //             /  |         X - base of the perpendicular line
+        //            A---X----->B  d - distance fom axis
+        //              x           x - distance from A
+        //
+        //            |X-A| = (P-A).B
+        //            X === A + ((P-A).B)B
+        //            d = |P-X|
+
+        var A = pickRay.origin;
+        var B = Vec3.normalize(pickRay.direction);
+        var P = properties.position;
+
+        var x = Vec3.dot(Vec3.subtract(P, A), B);
+
+        var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) *
+                          180 / Math.PI;
+
+        var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) &&
+                     (allowSmallModels || angularSize > MIN_ANGULAR_SIZE);
+
+        if (0 < x && sizeOK) {
+            selectedEntityID = foundEntity;
+            orientation = MyAvatar.orientation;
+            intersection = rayPlaneIntersection(pickRay, P, Quat.getForward(orientation));
+
+            if (!event.isShifted) {
+                selectionManager.setSelections([foundEntity], this);
+            } else {
+                selectionManager.addEntity(foundEntity, true, this);
+            }
+            selectionManager.saveProperties();
+
+            if (wantDebug) {
+                print("Model selected: " + foundEntity);
+            }
+            selectionDisplay.select(selectedEntityID, event);
+
+            if (Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)) {
+                cameraManager.enable();
+                cameraManager.focus(selectionManager.worldPosition,
+                    selectionManager.worldDimensions,
+                    Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
+            }
+        }
+    } else if (event.isRightButton) {
+        result = findClickedEntity(event);
+        if (result) {
+            if (SHOULD_SHOW_PROPERTY_MENU !== true) {
+                return;
+            }
+            properties = Entities.getEntityProperties(result.entityID);
+            if (properties.marketplaceID) {
+                propertyMenu.marketplaceID = properties.marketplaceID;
+                propertyMenu.updateMenuItemText(showMenuItem, "Show in Marketplace");
+            } else {
+                propertyMenu.marketplaceID = null;
+                propertyMenu.updateMenuItemText(showMenuItem, "No marketplace info");
+            }
+            propertyMenu.setPosition(event.x, event.y);
+            propertyMenu.show();
+        } else {
+            propertyMenu.hide();
+        }
+    }
+}
+
+Controller.mousePressEvent.connect(mousePressEvent);
+Controller.mouseMoveEvent.connect(mouseMoveEventBuffered);
+Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
+
+
+// In order for editVoxels and editModels to play nice together, they each check to see if a "delete" menu item already
+// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that
+// added it.
+var modelMenuAddedDelete = false;
+var originalLightsArePickable = Entities.getLightsArePickable();
+
+function setupModelMenus() {
+    // adj our menuitems
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: "Undo",
+        shortcutKey: 'Ctrl+Z',
+        position: 0,
+    });
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: "Redo",
+        shortcutKey: 'Ctrl+Y',
+        position: 1,
+    });
+
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: "Entities",
+        isSeparator: true
+    });
+    if (!Menu.menuItemExists("Edit", "Delete")) {
+        Menu.addMenuItem({
+            menuName: "Edit",
+            menuItemName: "Delete",
+            shortcutKeyEvent: {
+                text: "delete"
+            },
+            afterItem: "Entities",
+        });
+        modelMenuAddedDelete = true;
+    }
+
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: "Parent Entity to Last",
+        afterItem: "Entities"
+    });
+
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: "Unparent Entity",
+        afterItem: "Parent Entity to Last"
+    });
+
+    Menu.addMenuItem({
+        menuName: GRABBABLE_ENTITIES_MENU_CATEGORY,
+        menuItemName: MENU_CREATE_ENTITIES_GRABBABLE,
+        afterItem: "Unparent Entity",
+        isCheckable: true,
+        isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_CREATE_ENTITIES_GRABBABLE, true)
+    });
+
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: MENU_ALLOW_SELECTION_LARGE,
+        afterItem: MENU_CREATE_ENTITIES_GRABBABLE,
+        isCheckable: true,
+        isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, true)
+    });
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: MENU_ALLOW_SELECTION_SMALL,
+        afterItem: MENU_ALLOW_SELECTION_LARGE,
+        isCheckable: true,
+        isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, true)
+    });
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: MENU_ALLOW_SELECTION_LIGHTS,
+        afterItem: MENU_ALLOW_SELECTION_SMALL,
+        isCheckable: true,
+        isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, false)
+    });
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: "Select All Entities In Box",
+        afterItem: "Allow Selecting of Lights"
+    });
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: "Select All Entities Touching Box",
+        afterItem: "Select All Entities In Box"
+    });
+
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: "Export Entities",
+        afterItem: "Entities"
+    });
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: "Import Entities",
+        afterItem: "Export Entities"
+    });
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: "Import Entities from URL",
+        afterItem: "Import Entities"
+    });
+
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: MENU_AUTO_FOCUS_ON_SELECT,
+        isCheckable: true,
+        isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) === "true"
+    });
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: MENU_EASE_ON_FOCUS,
+        afterItem: MENU_AUTO_FOCUS_ON_SELECT,
+        isCheckable: true,
+        isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) === "true"
+    });
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE,
+        afterItem: MENU_EASE_ON_FOCUS,
+        isCheckable: true,
+        isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) !== "false"
+    });
+    Menu.addMenuItem({
+        menuName: "Edit",
+        menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE,
+        afterItem: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE,
+        isCheckable: true,
+        isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) !== "false"
+    });
+
+    Entities.setLightsArePickable(false);
+}
+
+setupModelMenus(); // do this when first running our script.
+
+function cleanupModelMenus() {
+    Menu.removeMenuItem("Edit", "Undo");
+    Menu.removeMenuItem("Edit", "Redo");
+
+    Menu.removeSeparator("Edit", "Entities");
+    if (modelMenuAddedDelete) {
+        // delete our menuitems
+        Menu.removeMenuItem("Edit", "Delete");
+    }
+
+    Menu.removeMenuItem("Edit", "Parent Entity to Last");
+    Menu.removeMenuItem("Edit", "Unparent Entity");
+    Menu.removeMenuItem("Edit", "Allow Selecting of Large Models");
+    Menu.removeMenuItem("Edit", "Allow Selecting of Small Models");
+    Menu.removeMenuItem("Edit", "Allow Selecting of Lights");
+    Menu.removeMenuItem("Edit", "Select All Entities In Box");
+    Menu.removeMenuItem("Edit", "Select All Entities Touching Box");
+
+    Menu.removeMenuItem("Edit", "Export Entities");
+    Menu.removeMenuItem("Edit", "Import Entities");
+    Menu.removeMenuItem("Edit", "Import Entities from URL");
+
+    Menu.removeMenuItem("Edit", MENU_AUTO_FOCUS_ON_SELECT);
+    Menu.removeMenuItem("Edit", MENU_EASE_ON_FOCUS);
+    Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE);
+    Menu.removeMenuItem("Edit", MENU_SHOW_ZONES_IN_EDIT_MODE);
+    Menu.removeMenuItem("Edit", MENU_CREATE_ENTITIES_GRABBABLE);
+}
+
+Script.scriptEnding.connect(function () {
+    toolBar.setActive(false);
+    Settings.setValue(SETTING_AUTO_FOCUS_ON_SELECT, Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT));
+    Settings.setValue(SETTING_EASE_ON_FOCUS, Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
+    Settings.setValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE));
+    Settings.setValue(SETTING_SHOW_ZONES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
+
+    Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LARGE));
+    Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, Menu.isOptionChecked(MENU_ALLOW_SELECTION_SMALL));
+    Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LIGHTS));
+
+
+    progressDialog.cleanup();
+    cleanupModelMenus();
+    tooltip.cleanup();
+    selectionDisplay.cleanup();
+    entityShapeVisualizer.cleanup();
+    Entities.setLightsArePickable(originalLightsArePickable);
+
+    Overlays.deleteOverlay(importingSVOImageOverlay);
+    Overlays.deleteOverlay(importingSVOTextOverlay);
+
+    Controller.keyReleaseEvent.disconnect(keyReleaseEvent);
+    Controller.keyPressEvent.disconnect(keyPressEvent);
+
+    Controller.mousePressEvent.disconnect(mousePressEvent);
+    Controller.mouseMoveEvent.disconnect(mouseMoveEventBuffered);
+    Controller.mouseReleaseEvent.disconnect(mouseReleaseEvent);
+
+    Messages.messageReceived.disconnect(handleMessagesReceived);
+    Messages.unsubscribe("entityToolUpdates");
+    createButton = null;
+});
+
+var lastOrientation = null;
+var lastPosition = null;
+
+// Do some stuff regularly, like check for placement of various overlays
+Script.update.connect(function (deltaTime) {
+    progressDialog.move();
+    selectionDisplay.checkControllerMove();
+    var dOrientation = Math.abs(Quat.dot(Camera.orientation, lastOrientation) - 1);
+    var dPosition = Vec3.distance(Camera.position, lastPosition);
+    if (dOrientation > 0.001 || dPosition > 0.001) {
+        propertyMenu.hide();
+        lastOrientation = Camera.orientation;
+        lastPosition = Camera.position;
+    }
+    if (lastMouseMoveEvent) {
+        mouseMove(lastMouseMoveEvent);
+        lastMouseMoveEvent = null;
+    }
+});
+
+function insideBox(center, dimensions, point) {
+    return (Math.abs(point.x - center.x) <= (dimensions.x / 2.0)) &&
+           (Math.abs(point.y - center.y) <= (dimensions.y / 2.0)) &&
+           (Math.abs(point.z - center.z) <= (dimensions.z / 2.0));
+}
+
+function selectAllEntitiesInCurrentSelectionBox(keepIfTouching) {
+    if (selectionManager.hasSelection()) {
+        // Get all entities touching the bounding box of the current selection
+        var boundingBoxCorner = Vec3.subtract(selectionManager.worldPosition,
+            Vec3.multiply(selectionManager.worldDimensions, 0.5));
+        var entities = Entities.findEntitiesInBox(boundingBoxCorner, selectionManager.worldDimensions);
+
+        if (!keepIfTouching) {
+            var isValid;
+            if (selectionManager.localPosition === null || selectionManager.localPosition === undefined) {
+                isValid = function (position) {
+                    return insideBox(selectionManager.worldPosition, selectionManager.worldDimensions, position);
+                };
+            } else {
+                isValid = function (position) {
+                    var localPosition = Vec3.multiplyQbyV(Quat.inverse(selectionManager.localRotation),
+                        Vec3.subtract(position,
+                            selectionManager.localPosition));
+                    return insideBox(Vec3.ZERO, selectionManager.localDimensions, localPosition);
+                };
+            }
+            for (var i = 0; i < entities.length; ++i) {
+                var properties = Entities.getEntityProperties(entities[i]);
+                if (!isValid(properties.position)) {
+                    entities.splice(i, 1);
+                    --i;
+                }
+            }
+        }
+        selectionManager.setSelections(entities, this);
+    }
+}
+
+function sortSelectedEntities(selected) {
+    var sortedEntities = selected.slice();
+    var begin = 0;
+    while (begin < sortedEntities.length) {
+        var elementRemoved = false;
+        var next = begin + 1;
+        while (next < sortedEntities.length) {
+            var beginID = sortedEntities[begin];
+            var nextID = sortedEntities[next];
+
+            if (Entities.isChildOfParent(beginID, nextID)) {
+                sortedEntities[begin] = nextID;
+                sortedEntities[next] = beginID;
+                sortedEntities.splice(next, 1);
+                elementRemoved = true;
+                break;
+            } else if (Entities.isChildOfParent(nextID, beginID)) {
+                sortedEntities.splice(next, 1);
+                elementRemoved = true;
+                break;
+            }
+            next++;
+        }
+        if (!elementRemoved) {
+            begin++;
+        }
+    }
+    return sortedEntities;
+}
+
+function recursiveDelete(entities, childrenList, deletedIDs, entityHostType) {
+    var wantDebug = false;
+    var entitiesLength = entities.length;
+    var initialPropertySets = Entities.getMultipleEntityProperties(entities);
+    var entityHostTypes = Entities.getMultipleEntityProperties(entities, 'entityHostType');
+    for (var i = 0; i < entitiesLength; ++i) {
+        var entityID = entities[i];
+
+        if (entityHostTypes[i].entityHostType !== entityHostType) {
+            if (wantDebug) {
+                console.log("Skipping deletion of entity " + entityID + " with conflicting entityHostType: " +
+                    entityHostTypes[i].entityHostType + ", expected: " + entityHostType);
+            }
+            continue;
+        }
+
+        var children = Entities.getChildrenIDs(entityID);
+        var grandchildrenList = [];
+        recursiveDelete(children, grandchildrenList, deletedIDs, entityHostType);
+        childrenList.push({
+            entityID: entityID,
+            properties: initialPropertySets[i],
+            children: grandchildrenList
+        });
+        deletedIDs.push(entityID);
+        Entities.deleteEntity(entityID);
+    }
+}
+
+function unparentSelectedEntities() {
+    if (SelectionManager.hasSelection()) {
+        var selectedEntities = selectionManager.selections;
+        var parentCheck = false;
+
+        if (selectedEntities.length < 1) {
+            Window.notifyEditError("You must have an entity selected in order to unparent it.");
+            return;
+        }
+        selectedEntities.forEach(function (id, index) {
+            var parentId = Entities.getEntityProperties(id, ["parentID"]).parentID;
+            if (parentId !== null && parentId.length > 0 && parentId !== Uuid.NULL) {
+                parentCheck = true;
+            }
+            Entities.editEntity(id, {parentID: null});
+            return true;
+        });
+        if (parentCheck) {
+            if (selectedEntities.length > 1) {
+                Window.notify("Entities unparented");
+            } else {
+                Window.notify("Entity unparented");
+            }
+        } else {
+            if (selectedEntities.length > 1) {
+                Window.notify("Selected Entities have no parents");
+            } else {
+                Window.notify("Selected Entity does not have a parent");
+            }
+        }
+    } else {
+        Window.notifyEditError("You have nothing selected to unparent");
+    }
+}
+function parentSelectedEntities() {
+    if (SelectionManager.hasSelection()) {
+        var selectedEntities = selectionManager.selections;
+        if (selectedEntities.length <= 1) {
+            Window.notifyEditError("You must have multiple entities selected in order to parent them");
+            return;
+        }
+        var parentCheck = false;
+        var lastEntityId = selectedEntities[selectedEntities.length - 1];
+        selectedEntities.forEach(function (id, index) {
+            if (lastEntityId !== id) {
+                var parentId = Entities.getEntityProperties(id, ["parentID"]).parentID;
+                if (parentId !== lastEntityId) {
+                    parentCheck = true;
+                }
+                Entities.editEntity(id, {parentID: lastEntityId});
+            }
+        });
+
+        if (parentCheck) {
+            Window.notify("Entities parented");
+        } else {
+            Window.notify("Entities are already parented to last");
+        }
+    } else {
+        Window.notifyEditError("You have nothing selected to parent");
+    }
+}
+function deleteSelectedEntities() {
+    if (SelectionManager.hasSelection()) {
+        var deletedIDs = [];
+
+        SelectionManager.saveProperties();
+        var savedProperties = [];
+        var newSortedSelection = sortSelectedEntities(selectionManager.selections);
+        var entityHostTypes = Entities.getMultipleEntityProperties(newSortedSelection, 'entityHostType');
+        for (var i = 0; i < newSortedSelection.length; ++i) {
+            var entityID = newSortedSelection[i];
+            var initialProperties = SelectionManager.savedProperties[entityID];
+            if (initialProperties.locked ||
+                (initialProperties.avatarEntity && initialProperties.owningAvatarID !== MyAvatar.sessionUUID)) {
+                continue;
+            }
+            var children = Entities.getChildrenIDs(entityID);
+            var childList = [];
+            recursiveDelete(children, childList, deletedIDs, entityHostTypes[i].entityHostType);
+            savedProperties.push({
+                entityID: entityID,
+                properties: initialProperties,
+                children: childList
+            });
+            deletedIDs.push(entityID);
+            Entities.deleteEntity(entityID);
+        }
+
+        if (savedProperties.length > 0) {
+            SelectionManager.clearSelections(this);
+            pushCommandForSelections([], savedProperties);
+            entityListTool.deleteEntities(deletedIDs);
+        }
+    }
+}
+
+function toggleSelectedEntitiesLocked() {
+    if (SelectionManager.hasSelection()) {
+        var locked = !Entities.getEntityProperties(SelectionManager.selections[0], ["locked"]).locked;
+        for (var i = 0; i < selectionManager.selections.length; i++) {
+            var entityID = SelectionManager.selections[i];
+            Entities.editEntity(entityID, {
+                locked: locked
+            });
+        }
+        entityListTool.sendUpdate();
+        selectionManager._update(false, this);
+    }
+}
+
+function toggleSelectedEntitiesVisible() {
+    if (SelectionManager.hasSelection()) {
+        var visible = !Entities.getEntityProperties(SelectionManager.selections[0], ["visible"]).visible;
+        for (var i = 0; i < selectionManager.selections.length; i++) {
+            var entityID = SelectionManager.selections[i];
+            Entities.editEntity(entityID, {
+                visible: visible
+            });
+        }
+        entityListTool.sendUpdate();
+        selectionManager._update(false, this);
+    }
+}
+
+function onFileSaveChanged(filename) {
+    Window.saveFileChanged.disconnect(onFileSaveChanged);
+    if (filename !== "") {
+        var success = Clipboard.exportEntities(filename, selectionManager.selections);
+        if (!success) {
+            Window.notifyEditError("Export failed.");
+        }
+    }
+}
+
+function onFileOpenChanged(filename) {
+    // disconnect the event, otherwise the requests will stack up
+    try {
+        // Not all calls to onFileOpenChanged() connect an event.
+        Window.browseChanged.disconnect(onFileOpenChanged);
+    } catch (e) {
+        // Ignore.
+    }
+
+    var importURL = null;
+    if (filename !== "") {
+        importURL = filename;
+        if (!/^(http|https):\/\//.test(filename)) {
+            importURL = "file:///" + importURL;
+        }
+    }
+    if (importURL) {
+        if (!isActive && (Entities.canRez() && Entities.canRezTmp() && Entities.canRezCertified() && Entities.canRezTmpCertified())) {
+            toolBar.toggle();
+        }
+        importSVO(importURL);
+    }
+}
+
+function onPromptTextChanged(prompt) {
+    Window.promptTextChanged.disconnect(onPromptTextChanged);
+    if (prompt !== "") {
+        if (!isActive && (Entities.canRez() && Entities.canRezTmp() && Entities.canRezCertified() && Entities.canRezTmpCertified())) {
+            toolBar.toggle();
+        }
+        importSVO(prompt);
+    }
+}
+
+function handleMenuEvent(menuItem) {
+    if (menuItem === "Allow Selecting of Small Models") {
+        allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models");
+    } else if (menuItem === "Allow Selecting of Large Models") {
+        allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models");
+    } else if (menuItem === "Allow Selecting of Lights") {
+        Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights"));
+    } else if (menuItem === "Delete") {
+        deleteSelectedEntities();
+    } else if (menuItem === "Undo") {
+        undoHistory.undo();
+    } else if (menuItem === "Redo") {
+        undoHistory.redo();
+    } else if (menuItem === "Parent Entity to Last") {
+        parentSelectedEntities();
+    } else if (menuItem === "Unparent Entity") {
+        unparentSelectedEntities();
+    } else if (menuItem === "Export Entities") {
+        if (!selectionManager.hasSelection()) {
+            Window.notifyEditError("No entities have been selected.");
+        } else {
+            Window.saveFileChanged.connect(onFileSaveChanged);
+            Window.saveAsync("Select Where to Save", "", "*.json");
+        }
+    } else if (menuItem === "Import Entities" || menuItem === "Import Entities from URL") {
+        if (menuItem === "Import Entities") {
+            Window.browseChanged.connect(onFileOpenChanged);
+            Window.browseAsync("Select Model to Import", "", "*.json");
+        } else {
+            Window.promptTextChanged.connect(onPromptTextChanged);
+            Window.promptAsync("URL of SVO to import", "");
+        }
+    } else if (menuItem === "Select All Entities In Box") {
+        selectAllEntitiesInCurrentSelectionBox(false);
+    } else if (menuItem === "Select All Entities Touching Box") {
+        selectAllEntitiesInCurrentSelectionBox(true);
+    } else if (menuItem === MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) {
+        entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE));
+    } else if (menuItem === MENU_SHOW_ZONES_IN_EDIT_MODE) {
+        Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
+    } else if (menuItem === MENU_CREATE_ENTITIES_GRABBABLE) {
+        Settings.setValue(SETTING_EDIT_PREFIX + menuItem, Menu.isOptionChecked(menuItem));
+    }
+    tooltip.show(false);
+}
+
+var HALF_TREE_SCALE = 16384;
+
+function getPositionToCreateEntity(extra) {
+    var CREATE_DISTANCE = 2;
+    var position;
+    var delta = extra !== undefined ? extra : 0;
+    if (Camera.mode === "entity" || Camera.mode === "independent") {
+        position = Vec3.sum(Camera.position, Vec3.multiply(Quat.getForward(Camera.orientation), CREATE_DISTANCE + delta));
+    } else {
+        position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getForward(MyAvatar.orientation), CREATE_DISTANCE + delta));
+    }
+
+    if (position.x > HALF_TREE_SCALE || position.y > HALF_TREE_SCALE || position.z > HALF_TREE_SCALE) {
+        return null;
+    }
+    return position;
+}
+
+function importSVO(importURL) {
+    if (!Entities.canRez() && !Entities.canRezTmp() &&
+        !Entities.canRezCertified() && !Entities.canRezTmpCertified()) {
+        Window.notifyEditError(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG);
+        return;
+    }
+
+    Overlays.editOverlay(importingSVOTextOverlay, {
+        visible: true
+    });
+    Overlays.editOverlay(importingSVOImageOverlay, {
+        visible: true
+    });
+
+    var success = Clipboard.importEntities(importURL);
+
+    if (success) {
+        var VERY_LARGE = 10000;
+        var isLargeImport = Clipboard.getClipboardContentsLargestDimension() >= VERY_LARGE;
+        var position = Vec3.ZERO;
+        if (!isLargeImport) {
+            position = getPositionToCreateEntity(Clipboard.getClipboardContentsLargestDimension() / 2);
+        }
+        if (position !== null && position !== undefined) {
+            var pastedEntityIDs = Clipboard.pasteEntities(position);
+            if (!isLargeImport) {
+                // The first entity in Clipboard gets the specified position with the rest being relative to it. Therefore, move
+                // entities after they're imported so that they're all the correct distance in front of and with geometric mean
+                // centered on the avatar/camera direction.
+                var deltaPosition = Vec3.ZERO;
+                var entityPositions = [];
+                var entityParentIDs = [];
+
+                var propType = Entities.getEntityProperties(pastedEntityIDs[0], ["type"]).type;
+                var NO_ADJUST_ENTITY_TYPES = ["Zone", "Light", "ParticleEffect"];
+                if (NO_ADJUST_ENTITY_TYPES.indexOf(propType) === -1) {
+                    var targetDirection;
+                    if (Camera.mode === "entity" || Camera.mode === "independent") {
+                        targetDirection = Camera.orientation;
+                    } else {
+                        targetDirection = MyAvatar.orientation;
+                    }
+                    targetDirection = Vec3.multiplyQbyV(targetDirection, Vec3.UNIT_Z);
+
+                    var targetPosition = getPositionToCreateEntity();
+                    var deltaParallel = HALF_TREE_SCALE;  // Distance to move entities parallel to targetDirection.
+                    var deltaPerpendicular = Vec3.ZERO;  // Distance to move entities perpendicular to targetDirection.
+                    for (var i = 0, length = pastedEntityIDs.length; i < length; i++) {
+                        var curLoopEntityProps = Entities.getEntityProperties(pastedEntityIDs[i], ["position", "dimensions",
+                            "registrationPoint", "rotation", "parentID"]);
+                        var adjustedPosition = adjustPositionPerBoundingBox(targetPosition, targetDirection,
+                            curLoopEntityProps.registrationPoint, curLoopEntityProps.dimensions, curLoopEntityProps.rotation);
+                        var delta = Vec3.subtract(adjustedPosition, curLoopEntityProps.position);
+                        var distance = Vec3.dot(delta, targetDirection);
+                        deltaParallel = Math.min(distance, deltaParallel);
+                        deltaPerpendicular = Vec3.sum(Vec3.subtract(delta, Vec3.multiply(distance, targetDirection)),
+                            deltaPerpendicular);
+                        entityPositions[i] = curLoopEntityProps.position;
+                        entityParentIDs[i] = curLoopEntityProps.parentID;
+                    }
+                    deltaPerpendicular = Vec3.multiply(1 / pastedEntityIDs.length, deltaPerpendicular);
+                    deltaPosition = Vec3.sum(Vec3.multiply(deltaParallel, targetDirection), deltaPerpendicular);
+                }
+
+                if (grid.getSnapToGrid()) {
+                    var firstEntityProps = Entities.getEntityProperties(pastedEntityIDs[0], ["position", "dimensions",
+                        "registrationPoint"]);
+                    var positionPreSnap = Vec3.sum(deltaPosition, firstEntityProps.position);
+                    position = grid.snapToSurface(grid.snapToGrid(positionPreSnap, false, firstEntityProps.dimensions,
+                            firstEntityProps.registrationPoint), firstEntityProps.dimensions, firstEntityProps.registrationPoint);
+                    deltaPosition = Vec3.subtract(position, firstEntityProps.position);
+                }
+
+                if (!Vec3.equal(deltaPosition, Vec3.ZERO)) {
+                    for (var editEntityIndex = 0, numEntities = pastedEntityIDs.length; editEntityIndex < numEntities; editEntityIndex++) {
+                        if (Uuid.isNull(entityParentIDs[editEntityIndex])) {
+                            Entities.editEntity(pastedEntityIDs[editEntityIndex], {
+                                position: Vec3.sum(deltaPosition, entityPositions[editEntityIndex])
+                            });
+                        }
+                    }
+                }
+            }
+
+            if (isActive) {
+                selectionManager.setSelections(pastedEntityIDs, this);
+            }
+        } else {
+            Window.notifyEditError("Can't import entities: entities would be out of bounds.");
+        }
+    } else {
+        Window.notifyEditError("There was an error importing the entity file.");
+    }
+
+    Overlays.editOverlay(importingSVOTextOverlay, {
+        visible: false
+    });
+    Overlays.editOverlay(importingSVOImageOverlay, {
+        visible: false
+    });
+}
+Window.svoImportRequested.connect(importSVO);
+
+Menu.menuItemEvent.connect(handleMenuEvent);
+
+var keyPressEvent = function (event) {
+    if (isActive) {
+        cameraManager.keyPressEvent(event);
+    }
+};
+var keyReleaseEvent = function (event) {
+    if (isActive) {
+        cameraManager.keyReleaseEvent(event);
+    }
+};
+Controller.keyReleaseEvent.connect(keyReleaseEvent);
+Controller.keyPressEvent.connect(keyPressEvent);
+
+function deleteKey(value) {
+    if (value === 0) { // on release
+        deleteSelectedEntities();
+    }
+}
+function deselectKey(value) {
+    if (value === 0) { // on release
+        selectionManager.clearSelections(this);
+    }
+}
+function toggleKey(value) {
+    if (value === 0) { // on release
+        selectionDisplay.toggleSpaceMode();
+    }
+}
+function focusKey(value) {
+    if (value === 0) { // on release
+        cameraManager.enable();
+        if (selectionManager.hasSelection()) {
+            cameraManager.focus(selectionManager.worldPosition, selectionManager.worldDimensions,
+                                Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
+        }
+    }
+}
+function gridKey(value) {
+    if (value === 0) { // on release
+        if (selectionManager.hasSelection()) {
+            grid.moveToSelection();
+        }
+    }
+}
+function recursiveAdd(newParentID, parentData) {
+    if (parentData.children !== undefined) {
+        var children = parentData.children;
+        for (var i = 0; i < children.length; i++) {
+            var childProperties = children[i].properties;
+            childProperties.parentID = newParentID;
+            var newChildID = Entities.addEntity(childProperties);
+            recursiveAdd(newChildID, children[i]);
+        }
+    }
+}
+
+var UndoHistory = function(onUpdate) {
+    this.history = [];
+    // The current position is the index of the last executed action in the history array.
+    //
+    //     -1 0 1 2 3    <- position
+    //        A B C D    <- actions in history
+    //
+    // If our lastExecutedIndex is 1, the last executed action is B.
+    // If we undo, we undo B (index 1). If we redo, we redo C (index 2).
+    this.lastExecutedIndex = -1;
+    this.enabled = true;
+    this.onUpdate = onUpdate;
+};
+
+UndoHistory.prototype.pushCommand = function(undoFn, undoArgs, redoFn, redoArgs) {
+    if (!this.enabled) {
+        return;
+    }
+    // Delete any history following the last executed action.
+    this.history.splice(this.lastExecutedIndex + 1);
+    this.history.push({
+        undoFn: undoFn,
+        undoArgs: undoArgs,
+        redoFn: redoFn,
+        redoArgs: redoArgs
+    });
+    this.lastExecutedIndex++;
+
+    if (this.onUpdate) {
+        this.onUpdate();
+    }
+};
+UndoHistory.prototype.setEnabled = function(enabled) {
+    this.enabled = enabled;
+    if (this.onUpdate) {
+        this.onUpdate();
+    }
+};
+UndoHistory.prototype.canUndo = function() {
+    return this.enabled && this.lastExecutedIndex >= 0;
+};
+UndoHistory.prototype.canRedo = function() {
+    return this.enabled && this.lastExecutedIndex < this.history.length - 1;
+};
+UndoHistory.prototype.undo = function() {
+    if (!this.canUndo()) {
+        console.warn("Cannot undo action");
+        return;
+    }
+
+    var command = this.history[this.lastExecutedIndex];
+    command.undoFn(command.undoArgs);
+    this.lastExecutedIndex--;
+
+    if (this.onUpdate) {
+        this.onUpdate();
+    }
+};
+UndoHistory.prototype.redo = function() {
+    if (!this.canRedo()) {
+        console.warn("Cannot redo action");
+        return;
+    }
+
+    var command = this.history[this.lastExecutedIndex + 1];
+    command.redoFn(command.redoArgs);
+    this.lastExecutedIndex++;
+
+    if (this.onUpdate) {
+        this.onUpdate();
+    }
+};
+
+function updateUndoRedoMenuItems() {
+    Menu.setMenuEnabled("Edit > Undo", undoHistory.canUndo());
+    Menu.setMenuEnabled("Edit > Redo", undoHistory.canRedo());
+}
+var undoHistory = new UndoHistory(updateUndoRedoMenuItems);
+updateUndoRedoMenuItems();
+
+// When an entity has been deleted we need a way to "undo" this deletion.  Because it's not currently
+// possible to create an entity with a specific id, earlier undo commands to the deleted entity
+// will fail if there isn't a way to find the new entity id.
+var DELETED_ENTITY_MAP = {};
+
+function applyEntityProperties(data) {
+    var editEntities = data.editEntities;
+    var createEntities = data.createEntities;
+    var deleteEntities = data.deleteEntities;
+    var selectedEntityIDs = [];
+    var selectEdits = createEntities.length === 0 || !data.selectCreated;
+    var i, entityID, entityProperties;
+    for (i = 0; i < createEntities.length; i++) {
+        entityID = createEntities[i].entityID;
+        entityProperties = createEntities[i].properties;
+        var newEntityID = Entities.addEntity(entityProperties);
+        recursiveAdd(newEntityID, createEntities[i]);
+        DELETED_ENTITY_MAP[entityID] = newEntityID;
+        if (data.selectCreated) {
+            selectedEntityIDs.push(newEntityID);
+        }
+    }
+    for (i = 0; i < deleteEntities.length; i++) {
+        entityID = deleteEntities[i].entityID;
+        if (DELETED_ENTITY_MAP[entityID] !== undefined) {
+            entityID = DELETED_ENTITY_MAP[entityID];
+        }
+        Entities.deleteEntity(entityID);
+        var index = selectedEntityIDs.indexOf(entityID);
+        if (index >= 0) {
+            selectedEntityIDs.splice(index, 1);
+        }
+    }
+    for (i = 0; i < editEntities.length; i++) {
+        entityID = editEntities[i].entityID;
+        if (DELETED_ENTITY_MAP[entityID] !== undefined) {
+            entityID = DELETED_ENTITY_MAP[entityID];
+        }
+        entityProperties = editEntities[i].properties;
+        if (entityProperties !== null) {
+            Entities.editEntity(entityID, entityProperties);
+        }
+        if (selectEdits) {
+            selectedEntityIDs.push(entityID);
+        }
+    }
+
+    // We might be getting an undo while edit.js is disabled. If that is the case, don't set
+    // our selections, causing the edit widgets to display.
+    if (isActive) {
+        selectionManager.setSelections(selectedEntityIDs, this);
+        selectionManager.saveProperties();
+    }
+}
+
+// For currently selected entities, push a command to the UndoStack that uses the current entity properties for the
+// redo command, and the saved properties for the undo command.  Also, include create and delete entity data.
+function pushCommandForSelections(createdEntityData, deletedEntityData, doNotSaveEditProperties) {
+    doNotSaveEditProperties = false;
+    var undoData = {
+        editEntities: [],
+        createEntities: deletedEntityData || [],
+        deleteEntities: createdEntityData || [],
+        selectCreated: true
+    };
+    var redoData = {
+        editEntities: [],
+        createEntities: createdEntityData || [],
+        deleteEntities: deletedEntityData || [],
+        selectCreated: true
+    };
+    for (var i = 0; i < SelectionManager.selections.length; i++) {
+        var entityID = SelectionManager.selections[i];
+        var initialProperties = SelectionManager.savedProperties[entityID];
+        var currentProperties = null;
+        if (!initialProperties) {
+            continue;
+        }
+
+        if (doNotSaveEditProperties) {
+            initialProperties = null;
+        } else {
+            currentProperties = Entities.getEntityProperties(entityID);
+        }
+
+        undoData.editEntities.push({
+            entityID: entityID,
+            properties: initialProperties
+        });
+        redoData.editEntities.push({
+            entityID: entityID,
+            properties: currentProperties
+        });
+    }
+    undoHistory.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData);
+}
+
+var ServerScriptStatusMonitor = function(entityID, statusCallback) {
+    var self = this;
+
+    self.entityID = entityID;
+    self.active = true;
+    self.sendRequestTimerID = null;
+
+    var onStatusReceived = function(success, isRunning, status, errorInfo) {
+        if (self.active) {
+            statusCallback({
+                statusRetrieved: success,
+                isRunning: isRunning,
+                status: status,
+                errorInfo: errorInfo
+            });
+            self.sendRequestTimerID = Script.setTimeout(function() {
+                if (self.active) {
+                    Entities.getServerScriptStatus(entityID, onStatusReceived);
+                }
+            }, 1000);
+        }
+    };
+    self.stop = function() {
+        self.active = false;
+    };
+
+    Entities.getServerScriptStatus(entityID, onStatusReceived);
+};
+
+var PropertiesTool = function (opts) {
+    var that = {};
+
+    var webView = null;
+    webView = Tablet.getTablet("com.highfidelity.interface.tablet.system");
+    webView.setVisible = function(value) {};
+
+    var visible = false;
+
+    // This keeps track of the last entity ID that was selected. If multiple entities
+    // are selected or if no entity is selected this will be `null`.
+    var currentSelectedEntityID = null;
+    var statusMonitor = null;
+    var blockPropertyUpdates = false;
+
+    that.setVisible = function (newVisible) {
+        visible = newVisible;
+        webView.setVisible(shouldUseEditTabletApp() && visible);
+        createToolsWindow.setVisible(!shouldUseEditTabletApp() && visible);
+    };
+
+    that.setVisible(false);
+
+    function emitScriptEvent(data) {
+        var dataString = JSON.stringify(data);
+        webView.emitScriptEvent(dataString);
+        createToolsWindow.emitScriptEvent(dataString);
+    }
+
+    function updateScriptStatus(info) {
+        info.type = "server_script_status";
+        emitScriptEvent(info);
+    }
+
+    function resetScriptStatus() {
+        updateScriptStatus({
+            statusRetrieved: undefined,
+            isRunning: undefined,
+            status: "",
+            errorInfo: ""
+        });
+    }
+
+    that.setSpaceMode = function(spaceMode) {
+        emitScriptEvent({
+            type: 'setSpaceMode',
+            spaceMode: spaceMode
+        })
+    };
+
+    function updateSelections(selectionUpdated, caller) {
+        if (blockPropertyUpdates) {
+            return;
+        }
+
+        var data = {
+            type: 'update',
+            spaceMode: selectionDisplay.getSpaceMode(),
+            isPropertiesToolUpdate: caller === this,
+        };
+
+        if (selectionUpdated) {
+            resetScriptStatus();
+
+            if (selectionManager.selections.length !== 1) {
+                if (statusMonitor !== null) {
+                    statusMonitor.stop();
+                    statusMonitor = null;
+                }
+                currentSelectedEntityID = null;
+            } else if (currentSelectedEntityID !== selectionManager.selections[0]) {
+                if (statusMonitor !== null) {
+                    statusMonitor.stop();
+                }
+                var entityID = selectionManager.selections[0];
+                currentSelectedEntityID = entityID;
+                statusMonitor = new ServerScriptStatusMonitor(entityID, updateScriptStatus);
+            }
+        }
+
+        var selections = [];
+        for (var i = 0; i < selectionManager.selections.length; i++) {
+            var entity = {};
+            entity.id = selectionManager.selections[i];
+            entity.properties = Entities.getEntityProperties(selectionManager.selections[i]);
+            if (entity.properties.rotation !== undefined) {
+                entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation);
+            }
+            if (entity.properties.localRotation !== undefined) {
+                entity.properties.localRotation = Quat.safeEulerAngles(entity.properties.localRotation);
+            }
+            if (entity.properties.emitOrientation !== undefined) {
+                entity.properties.emitOrientation = Quat.safeEulerAngles(entity.properties.emitOrientation);
+            }
+            if (entity.properties.keyLight !== undefined && entity.properties.keyLight.direction !== undefined) {
+                entity.properties.keyLight.direction = Vec3.toPolar(entity.properties.keyLight.direction);
+                entity.properties.keyLight.direction.z = 0.0;
+            }
+            selections.push(entity);
+        }
+        data.selections = selections;
+
+        emitScriptEvent(data);
+    }
+    selectionManager.addEventListener(updateSelections, this);
+
+
+    var onWebEventReceived = function(data) {
+        try {
+            data = JSON.parse(data);
+        } catch(e) {
+            return;
+        }
+        var i, properties, dY, diff, newPosition;
+        if (data.type === "update") {
+
+            if (data.properties || data.propertiesMap) {
+                var propertiesMap = data.propertiesMap;
+                if (propertiesMap === undefined) {
+                    propertiesMap = [{
+                        entityIDs: data.ids,
+                        properties: data.properties,
+                    }];
+                }
+
+                var sendListUpdate = false;
+                propertiesMap.forEach(function(propertiesObject) {
+                    var properties = propertiesObject.properties;
+                    var updateEntityIDs = propertiesObject.entityIDs;
+                    if (properties.dynamic === false) {
+                        // this object is leaving dynamic, so we zero its velocities
+                        properties.localVelocity = Vec3.ZERO;
+                        properties.localAngularVelocity = Vec3.ZERO;
+                    }
+                    if (properties.rotation !== undefined) {
+                        properties.rotation = Quat.fromVec3Degrees(properties.rotation);
+                    }
+                    if (properties.localRotation !== undefined) {
+                        properties.localRotation = Quat.fromVec3Degrees(properties.localRotation);
+                    }
+                    if (properties.emitOrientation !== undefined) {
+                        properties.emitOrientation = Quat.fromVec3Degrees(properties.emitOrientation);
+                    }
+                    if (properties.keyLight !== undefined && properties.keyLight.direction !== undefined) {
+                        var currentKeyLightDirection = Vec3.toPolar(Entities.getEntityProperties(selectionManager.selections[0], ['keyLight.direction']).keyLight.direction);
+                        if (properties.keyLight.direction.x === undefined) {
+                            properties.keyLight.direction.x = currentKeyLightDirection.x;
+                        }
+                        if (properties.keyLight.direction.y === undefined) {
+                            properties.keyLight.direction.y = currentKeyLightDirection.y;
+                        }
+                        properties.keyLight.direction = Vec3.fromPolar(properties.keyLight.direction.x, properties.keyLight.direction.y);
+                    }
+
+                    updateEntityIDs.forEach(function (entityID) {
+                        Entities.editEntity(entityID, properties);
+                    });
+
+                    if (properties.name !== undefined || properties.modelURL !== undefined || properties.materialURL !== undefined ||
+                        properties.visible !== undefined || properties.locked !== undefined) {
+
+                        sendListUpdate = true;
+                    }
+
+                });
+                if (sendListUpdate) {
+                    entityListTool.sendUpdate();
+                }
+            }
+
+
+            if (data.onlyUpdateEntities) {
+                blockPropertyUpdates = true;
+            } else {
+                pushCommandForSelections();
+                SelectionManager.saveProperties();
+            }
+            selectionManager._update(false, this);
+            blockPropertyUpdates = false;
+        } else if (data.type === 'saveUserData' || data.type === 'saveMaterialData') {
+            data.ids.forEach(function(entityID) {
+                Entities.editEntity(entityID, data.properties);
+            });
+        } else if (data.type === "showMarketplace") {
+            showMarketplace();
+        } else if (data.type === "action") {
+            if (data.action === "moveSelectionToGrid") {
+                if (selectionManager.hasSelection()) {
+                    selectionManager.saveProperties();
+                    dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2);
+                    diff = {
+                        x: 0,
+                        y: dY,
+                        z: 0
+                    };
+                    for (i = 0; i < selectionManager.selections.length; i++) {
+                        properties = selectionManager.savedProperties[selectionManager.selections[i]];
+                        newPosition = Vec3.sum(properties.position, diff);
+                        Entities.editEntity(selectionManager.selections[i], {
+                            position: newPosition
+                        });
+                    }
+                    pushCommandForSelections();
+                    selectionManager._update(false, this);
+                }
+            } else if (data.action === "moveAllToGrid") {
+                if (selectionManager.hasSelection()) {
+                    selectionManager.saveProperties();
+                    for (i = 0; i < selectionManager.selections.length; i++) {
+                        properties = selectionManager.savedProperties[selectionManager.selections[i]];
+                        var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2;
+                        dY = grid.getOrigin().y - bottomY;
+                        diff = {
+                            x: 0,
+                            y: dY,
+                            z: 0
+                        };
+                        newPosition = Vec3.sum(properties.position, diff);
+                        Entities.editEntity(selectionManager.selections[i], {
+                            position: newPosition
+                        });
+                    }
+                    pushCommandForSelections();
+                    selectionManager._update(false, this);
+                }
+            } else if (data.action === "resetToNaturalDimensions") {
+                if (selectionManager.hasSelection()) {
+                    selectionManager.saveProperties();
+                    for (i = 0; i < selectionManager.selections.length; i++) {
+                        properties = selectionManager.savedProperties[selectionManager.selections[i]];
+                        var naturalDimensions = properties.naturalDimensions;
+
+                        // If any of the natural dimensions are not 0, resize
+                        if (properties.type === "Model" && naturalDimensions.x === 0 && naturalDimensions.y === 0 &&
+                            naturalDimensions.z === 0) {
+                            Window.notifyEditError("Cannot reset entity to its natural dimensions: Model URL" +
+                                " is invalid or the model has not yet been loaded.");
+                        } else {
+                            Entities.editEntity(selectionManager.selections[i], {
+                                dimensions: properties.naturalDimensions
+                            });
+                        }
+                    }
+                    pushCommandForSelections();
+                    selectionManager._update(false, this);
+                }
+            } else if (data.action === "previewCamera") {
+                if (selectionManager.hasSelection()) {
+                    Camera.mode = "entity";
+                    Camera.cameraEntity = selectionManager.selections[0];
+                }
+            } else if (data.action === "rescaleDimensions") {
+                var multiplier = data.percentage / 100.0;
+                if (selectionManager.hasSelection()) {
+                    selectionManager.saveProperties();
+                    for (i = 0; i < selectionManager.selections.length; i++) {
+                        properties = selectionManager.savedProperties[selectionManager.selections[i]];
+                        Entities.editEntity(selectionManager.selections[i], {
+                            dimensions: Vec3.multiply(multiplier, properties.dimensions)
+                        });
+                    }
+                    pushCommandForSelections();
+                    selectionManager._update(false, this);
+                }
+            } else if (data.action === "reloadClientScripts") {
+                if (selectionManager.hasSelection()) {
+                    var timestamp = Date.now();
+                    for (i = 0; i < selectionManager.selections.length; i++) {
+                        Entities.editEntity(selectionManager.selections[i], {
+                            scriptTimestamp: timestamp
+                        });
+                    }
+                }
+            } else if (data.action === "reloadServerScripts") {
+                if (selectionManager.hasSelection()) {
+                    for (i = 0; i < selectionManager.selections.length; i++) {
+                        Entities.reloadServerScripts(selectionManager.selections[i]);
+                    }
+                }
+            }
+        } else if (data.type === "propertiesPageReady") {
+            updateSelections(true);
+        } else if (data.type === "tooltipsRequest") {
+            emitScriptEvent({
+                type: 'tooltipsReply',
+                tooltips: Script.require('./assets/data/createAppTooltips.json'),
+                hmdActive: HMD.active,
+            });
+        } else if (data.type === "propertyRangeRequest") {
+            var propertyRanges = {};
+            data.properties.forEach(function (property) {
+                propertyRanges[property] = Entities.getPropertyInfo(property);
+            });
+            emitScriptEvent({
+                type: 'propertyRangeReply',
+                propertyRanges: propertyRanges,
+            });
+        } else if (data.type === "materialTargetRequest") {
+            var parentModelData;
+            var properties = Entities.getEntityProperties(data.entityID, ["type", "parentID"]);
+            if (properties.type === "Material" && properties.parentID !== Uuid.NULL) {
+                var parentType = Entities.getEntityProperties(properties.parentID, ["type"]).type;
+                if (parentType === "Model" || Entities.getNestableType(properties.parentID) === "avatar") {
+                    parentModelData = Graphics.getModel(properties.parentID);
+                } else if (parentType === "Shape" || parentType === "Box" || parentType === "Sphere") {
+                    parentModelData = {};
+                    parentModelData.numMeshes = 1;
+                    parentModelData.materialNames = [];
+                }
+            }
+            emitScriptEvent({
+                type: 'materialTargetReply',
+                entityID: data.entityID,
+                materialTargetData: parentModelData,
+            });
+        }
+    };
+
+    HMD.displayModeChanged.connect(function() {
+        emitScriptEvent({
+            type: 'hmdActiveChanged',
+            hmdActive: HMD.active,
+        });
+    });
+
+    createToolsWindow.webEventReceived.addListener(this, onWebEventReceived);
+
+    webView.webEventReceived.connect(this, onWebEventReceived);
+
+    return that;
+};
+
+
+var PopupMenu = function () {
+    var self = this;
+
+    var MENU_ITEM_HEIGHT = 21;
+    var MENU_ITEM_SPACING = 1;
+    var TEXT_MARGIN = 7;
+
+    var overlays = [];
+    var overlayInfo = {};
+
+    var visible = false;
+
+    var upColor = {
+        red: 0,
+        green: 0,
+        blue: 0
+    };
+    var downColor = {
+        red: 192,
+        green: 192,
+        blue: 192
+    };
+    var overColor = {
+        red: 128,
+        green: 128,
+        blue: 128
+    };
+
+    self.onSelectMenuItem = function () {};
+
+    self.addMenuItem = function (name) {
+        var id = Overlays.addOverlay("text", {
+            text: name,
+            backgroundAlpha: 1.0,
+            backgroundColor: upColor,
+            topMargin: TEXT_MARGIN,
+            leftMargin: TEXT_MARGIN,
+            width: 210,
+            height: MENU_ITEM_HEIGHT,
+            font: {
+                size: 12
+            },
+            visible: false
+        });
+        overlays.push(id);
+        overlayInfo[id] = {
+            name: name
+        };
+        return id;
+    };
+
+    self.updateMenuItemText = function (id, newText) {
+        Overlays.editOverlay(id, {
+            text: newText
+        });
+    };
+
+    self.setPosition = function (x, y) {
+        for (var key in overlayInfo) {
+            Overlays.editOverlay(key, {
+                x: x,
+                y: y
+            });
+            y += MENU_ITEM_HEIGHT + MENU_ITEM_SPACING;
+        }
+    };
+
+    self.onSelected = function () {};
+
+    var pressingOverlay = null;
+    var hoveringOverlay = null;
+
+    self.mousePressEvent = function (event) {
+        if (event.isLeftButton) {
+            var overlay = Overlays.getOverlayAtPoint({
+                x: event.x,
+                y: event.y
+            });
+            if (overlay in overlayInfo) {
+                pressingOverlay = overlay;
+                Overlays.editOverlay(pressingOverlay, {
+                    backgroundColor: downColor
+                });
+            } else {
+                self.hide();
+            }
+            return false;
+        }
+    };
+    self.mouseMoveEvent = function (event) {
+        if (visible) {
+            var overlay = Overlays.getOverlayAtPoint({
+                x: event.x,
+                y: event.y
+            });
+            if (!pressingOverlay) {
+                if (hoveringOverlay !== null && overlay !== hoveringOverlay) {
+                    Overlays.editOverlay(hoveringOverlay, {
+                        backgroundColor: upColor
+                    });
+                    hoveringOverlay = null;
+                }
+                if (overlay !== hoveringOverlay && overlay in overlayInfo) {
+                    Overlays.editOverlay(overlay, {
+                        backgroundColor: overColor
+                    });
+                    hoveringOverlay = overlay;
+                }
+            }
+        }
+        return false;
+    };
+    self.mouseReleaseEvent = function (event) {
+        var overlay = Overlays.getOverlayAtPoint({
+            x: event.x,
+            y: event.y
+        });
+        if (pressingOverlay !== null && pressingOverlay !== undefined) {
+            if (overlay === pressingOverlay) {
+                self.onSelectMenuItem(overlayInfo[overlay].name);
+            }
+            Overlays.editOverlay(pressingOverlay, {
+                backgroundColor: upColor
+            });
+            pressingOverlay = null;
+            self.hide();
+        }
+    };
+
+    self.setVisible = function (newVisible) {
+        if (newVisible !== visible) {
+            visible = newVisible;
+            for (var key in overlayInfo) {
+                Overlays.editOverlay(key, {
+                    visible: newVisible
+                });
+            }
+        }
+    };
+    self.show = function () {
+        self.setVisible(true);
+    };
+    self.hide = function () {
+        self.setVisible(false);
+    };
+
+    function cleanup() {
+        ContextOverlay.enabled = true;
+        for (var i = 0; i < overlays.length; i++) {
+            Overlays.deleteOverlay(overlays[i]);
+        }
+        Controller.mousePressEvent.disconnect(self.mousePressEvent);
+        Controller.mouseMoveEvent.disconnect(self.mouseMoveEvent);
+        Controller.mouseReleaseEvent.disconnect(self.mouseReleaseEvent);
+
+        Entities.canRezChanged.disconnect(checkEditPermissionsAndUpdate);
+        Entities.canRezTmpChanged.disconnect(checkEditPermissionsAndUpdate);
+        Entities.canRezCertifiedChanged.disconnect(checkEditPermissionsAndUpdate);
+        Entities.canRezTmpCertifiedChanged.disconnect(checkEditPermissionsAndUpdate);
+    }
+
+    Controller.mousePressEvent.connect(self.mousePressEvent);
+    Controller.mouseMoveEvent.connect(self.mouseMoveEvent);
+    Controller.mouseReleaseEvent.connect(self.mouseReleaseEvent);
+    Script.scriptEnding.connect(cleanup);
+
+    return this;
+};
+
+function whenPressed(fn) {
+    return function(value) {
+        if (value > 0) {
+            fn();
+        }
+    };
+}
+
+function whenReleased(fn) {
+    return function(value) {
+        if (value === 0) {
+            fn();
+        }
+    };
+}
+
+var isOnMacPlatform = Controller.getValue(Controller.Hardware.Application.PlatformMac);
+
+var mapping = Controller.newMapping(CONTROLLER_MAPPING_NAME);
+if (isOnMacPlatform) {
+    mapping.from([Controller.Hardware.Keyboard.Backspace]).to(deleteKey);
+} else {
+    mapping.from([Controller.Hardware.Keyboard.Delete]).to(deleteKey);
+}
+mapping.from([Controller.Hardware.Keyboard.T]).to(toggleKey);
+mapping.from([Controller.Hardware.Keyboard.F]).to(focusKey);
+mapping.from([Controller.Hardware.Keyboard.G]).to(gridKey);
+mapping.from([Controller.Hardware.Keyboard.X])
+    .when([Controller.Hardware.Keyboard.Control])
+    .to(whenReleased(function() { selectionManager.cutSelectedEntities() }));
+mapping.from([Controller.Hardware.Keyboard.C])
+    .when([Controller.Hardware.Keyboard.Control])
+    .to(whenReleased(function() { selectionManager.copySelectedEntities() }));
+mapping.from([Controller.Hardware.Keyboard.V])
+    .when([Controller.Hardware.Keyboard.Control])
+    .to(whenReleased(function() { selectionManager.pasteEntities() }));
+mapping.from([Controller.Hardware.Keyboard.D])
+    .when([Controller.Hardware.Keyboard.Control])
+    .to(whenReleased(function() { selectionManager.duplicateSelection() }));
+
+// Bind undo to ctrl-shift-z to maintain backwards-compatibility
+mapping.from([Controller.Hardware.Keyboard.Z])
+    .when([Controller.Hardware.Keyboard.Control, Controller.Hardware.Keyboard.Shift])
+    .to(whenPressed(function() { undoHistory.redo() }));
+
+
+mapping.from([Controller.Hardware.Keyboard.P])
+    .when([Controller.Hardware.Keyboard.Control, Controller.Hardware.Keyboard.Shift])
+    .to(whenReleased(function() { unparentSelectedEntities(); }));
+
+mapping.from([Controller.Hardware.Keyboard.P])
+    .when([Controller.Hardware.Keyboard.Control, !Controller.Hardware.Keyboard.Shift])
+    .to(whenReleased(function() { parentSelectedEntities(); }));
+
+keyUpEventFromUIWindow = function(keyUpEvent) {
+    var WANT_DEBUG_MISSING_SHORTCUTS = false;
+
+    var pressedValue = 0.0;
+
+    if ((!isOnMacPlatform && keyUpEvent.keyCodeString === "Delete")
+        || (isOnMacPlatform && keyUpEvent.keyCodeString === "Backspace")) {
+
+        deleteKey(pressedValue);
+    } else if (keyUpEvent.keyCodeString === "T") {
+        toggleKey(pressedValue);
+    } else if (keyUpEvent.keyCodeString === "F") {
+        focusKey(pressedValue);
+    } else if (keyUpEvent.keyCodeString === "G") {
+        gridKey(pressedValue);
+    } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "X") {
+        selectionManager.cutSelectedEntities();
+    } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "C") {
+        selectionManager.copySelectedEntities();
+    } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "V") {
+        selectionManager.pasteEntities();
+    } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "D") {
+        selectionManager.duplicateSelection();
+    } else if (!isOnMacPlatform && keyUpEvent.controlKey && !keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "Z") {
+        undoHistory.undo(); // undo is only handled via handleMenuItem on Mac
+    } else if (keyUpEvent.controlKey && !keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "P") {
+        parentSelectedEntities();
+    } else if (keyUpEvent.controlKey && keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "P") {
+        unparentSelectedEntities();
+    } else if (!isOnMacPlatform &&
+              ((keyUpEvent.controlKey && keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "Z") ||
+               (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "Y"))) {
+        undoHistory.redo(); // redo is only handled via handleMenuItem on Mac
+    } else if (WANT_DEBUG_MISSING_SHORTCUTS) {
+        console.warn("unhandled key event: " + JSON.stringify(keyUpEvent))
+    }
+};
+
+var propertyMenu = new PopupMenu();
+
+propertyMenu.onSelectMenuItem = function (name) {
+
+    if (propertyMenu.marketplaceID) {
+        showMarketplace(propertyMenu.marketplaceID);
+    }
+};
+
+var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace");
+
+var propertiesTool = new PropertiesTool();
+
+selectionDisplay.onSpaceModeChange = function(spaceMode) {
+    entityListTool.setSpaceMode(spaceMode);
+    propertiesTool.setSpaceMode(spaceMode);
+};
+
+}()); // END LOCAL_SCOPE
diff --git a/scripts/simplifiedUI/system/create/entityList/entityList.js b/scripts/simplifiedUI/system/create/entityList/entityList.js
new file mode 100644
index 0000000000..06e100f457
--- /dev/null
+++ b/scripts/simplifiedUI/system/create/entityList/entityList.js
@@ -0,0 +1,330 @@
+"use strict";
+
+//  entityList.js
+//
+//  Copyright 2014 High Fidelity, Inc.
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+/* global EntityListTool, Tablet, selectionManager, Entities, Camera, MyAvatar, Vec3, Menu, Messages,
+   cameraManager, MENU_EASE_ON_FOCUS, deleteSelectedEntities, toggleSelectedEntitiesLocked, toggleSelectedEntitiesVisible,
+   keyUpEventFromUIWindow, Script, SelectionDisplay, SelectionManager, Clipboard */
+
+var PROFILING_ENABLED = false;
+var profileIndent = '';
+const PROFILE_NOOP = function(_name, fn, args) {
+    fn.apply(this, args);
+};
+const PROFILE = !PROFILING_ENABLED ? PROFILE_NOOP : function(name, fn, args) {
+    console.log("PROFILE-Script " + profileIndent + "(" + name + ") Begin");
+    var previousIndent = profileIndent;
+    profileIndent += '  ';
+    var before = Date.now();
+    fn.apply(this, args);
+    var delta = Date.now() - before;
+    profileIndent = previousIndent;
+    console.log("PROFILE-Script " + profileIndent + "(" + name + ") End " + delta + "ms");
+};
+
+EntityListTool = function(shouldUseEditTabletApp) {
+    var that = {};
+
+    var CreateWindow = Script.require('../modules/createWindow.js');
+
+    var TITLE_OFFSET = 60;
+    var ENTITY_LIST_WIDTH = 495;
+    var MAX_DEFAULT_CREATE_TOOLS_HEIGHT = 778;
+    var entityListWindow = new CreateWindow(
+        Script.resolvePath("./qml/EditEntityList.qml"),
+        'Entity List',
+        'com.highfidelity.create.entityListWindow',
+        function () {
+            var windowHeight = Window.innerHeight - TITLE_OFFSET;
+            if (windowHeight > MAX_DEFAULT_CREATE_TOOLS_HEIGHT) {
+                windowHeight = MAX_DEFAULT_CREATE_TOOLS_HEIGHT;
+            }
+            return {
+                size: {
+                    x: ENTITY_LIST_WIDTH,
+                    y: windowHeight
+                },
+                position: {
+                    x: Window.x,
+                    y: Window.y + TITLE_OFFSET
+                }
+            };
+        },
+        false
+    );
+
+    var webView = null;
+    webView = Tablet.getTablet("com.highfidelity.interface.tablet.system");
+    webView.setVisible = function(value){ };
+
+    var filterInView = false;
+    var searchRadius = 100;
+
+    var visible = false;
+
+    that.webView = webView;
+
+    that.setVisible = function(newVisible) {
+        visible = newVisible;
+        webView.setVisible(shouldUseEditTabletApp() && visible);
+        entityListWindow.setVisible(!shouldUseEditTabletApp() && visible);
+    };
+
+    that.isVisible = function() {
+        return entityListWindow.isVisible();
+    };
+
+    that.setVisible(false);
+
+    function emitJSONScriptEvent(data) {
+        var dataString;
+        PROFILE("Script-JSON.stringify", function() {
+            dataString = JSON.stringify(data);
+        });
+        PROFILE("Script-emitScriptEvent", function() {
+            webView.emitScriptEvent(dataString);
+            if (entityListWindow.window) {
+                entityListWindow.window.emitScriptEvent(dataString);
+            }
+        });
+    }
+
+    that.toggleVisible = function() {
+        that.setVisible(!visible);
+    };
+
+    selectionManager.addEventListener(function(isSelectionUpdate, caller) {
+        if (caller === that) {
+            // ignore events that we emitted from the entity list itself
+            return;
+        }
+        var selectedIDs = [];
+
+        for (var i = 0; i < selectionManager.selections.length; i++) {
+            selectedIDs.push(selectionManager.selections[i]);
+        }
+
+        emitJSONScriptEvent({
+            type: 'selectionUpdate',
+            selectedIDs: selectedIDs
+        });
+    });
+
+    that.setSpaceMode = function(spaceMode) {
+        emitJSONScriptEvent({
+            type: 'setSpaceMode',
+            spaceMode: spaceMode
+        });
+    };
+
+    that.clearEntityList = function() {
+        emitJSONScriptEvent({
+            type: 'clearEntityList'
+        });
+    };
+
+    that.removeEntities = function (deletedIDs, selectedIDs) {
+        emitJSONScriptEvent({
+            type: 'removeEntities',
+            deletedIDs: deletedIDs,
+            selectedIDs: selectedIDs
+        });
+    };
+
+    that.deleteEntities = function (deletedIDs) {
+        emitJSONScriptEvent({
+            type: "deleted",
+            ids: deletedIDs
+        });
+    };
+
+    function valueIfDefined(value) {
+        return value !== undefined ? value : "";
+    }
+
+    function entityIsBaked(properties) {
+        if (properties.type === "Model") {
+            var lowerModelURL = properties.modelURL.toLowerCase();
+            return lowerModelURL.endsWith(".baked.fbx") || lowerModelURL.endsWith(".baked.fst");
+        } else if (properties.type === "Zone") {
+            var lowerSkyboxURL = properties.skybox ? properties.skybox.url.toLowerCase() : "";
+            var lowerAmbientURL = properties.ambientLight ? properties.ambientLight.ambientURL.toLowerCase() : "";
+            return (lowerSkyboxURL === "" || lowerSkyboxURL.endsWith(".texmeta.json")) &&
+                (lowerAmbientURL === "" || lowerAmbientURL.endsWith(".texmeta.json"));
+        } else {
+            return false;
+        }
+    }
+
+    that.sendUpdate = function() {
+        PROFILE('Script-sendUpdate', function() {
+            var entities = [];
+
+            var ids;
+            PROFILE("findEntities", function() {
+                if (filterInView) {
+                    ids = Entities.findEntitiesInFrustum(Camera.frustum);
+                } else {
+                    ids = Entities.findEntities(MyAvatar.position, searchRadius);
+                }
+            });
+
+            var cameraPosition = Camera.position;
+            PROFILE("getMultipleProperties", function () {
+                var multipleProperties = Entities.getMultipleEntityProperties(ids, ['name', 'type', 'locked',
+                    'visible', 'renderInfo', 'modelURL', 'materialURL', 'imageURL', 'script', 'certificateID',
+                    'skybox.url', 'ambientLight.url']);
+                for (var i = 0; i < multipleProperties.length; i++) {
+                    var properties = multipleProperties[i];
+
+                    if (!filterInView || Vec3.distance(properties.position, cameraPosition) <= searchRadius) {
+                        var url = "";
+                        if (properties.type === "Model") {
+                            url = properties.modelURL;
+                        } else if (properties.type === "Material") {
+                            url = properties.materialURL;
+                        } else if (properties.type === "Image") {
+                            url = properties.imageURL;
+                        }
+                        entities.push({
+                            id: ids[i],
+                            name: properties.name,
+                            type: properties.type,
+                            url: url,
+                            locked: properties.locked,
+                            visible: properties.visible,
+                            certificateID: properties.certificateID,
+                            verticesCount: (properties.renderInfo !== undefined ?
+                                valueIfDefined(properties.renderInfo.verticesCount) : ""),
+                            texturesCount: (properties.renderInfo !== undefined ?
+                                valueIfDefined(properties.renderInfo.texturesCount) : ""),
+                            texturesSize: (properties.renderInfo !== undefined ?
+                                valueIfDefined(properties.renderInfo.texturesSize) : ""),
+                            hasTransparent: (properties.renderInfo !== undefined ?
+                                valueIfDefined(properties.renderInfo.hasTransparent) : ""),
+                            isBaked: entityIsBaked(properties),
+                            drawCalls: (properties.renderInfo !== undefined ?
+                                valueIfDefined(properties.renderInfo.drawCalls) : ""),
+                            hasScript: properties.script !== ""
+                        });
+                    }
+                }
+            });
+
+            var selectedIDs = [];
+            for (var j = 0; j < selectionManager.selections.length; j++) {
+                selectedIDs.push(selectionManager.selections[j]);
+            }
+
+            emitJSONScriptEvent({
+                type: "update",
+                entities: entities,
+                selectedIDs: selectedIDs,
+                spaceMode: SelectionDisplay.getSpaceMode(),
+            });
+        });
+    };
+
+    function onFileSaveChanged(filename) {
+        Window.saveFileChanged.disconnect(onFileSaveChanged);
+        if (filename !== "") {
+            var success = Clipboard.exportEntities(filename, selectionManager.selections);
+            if (!success) {
+                Window.notifyEditError("Export failed.");
+            }
+        }
+    }
+
+    var onWebEventReceived = function(data) {
+        try {
+            data = JSON.parse(data);
+        } catch(e) {
+            print("entityList.js: Error parsing JSON");
+            return;
+        }
+
+        if (data.type === "selectionUpdate") {
+            var ids = data.entityIds;
+            var entityIDs = [];
+            for (var i = 0; i < ids.length; i++) {
+                entityIDs.push(ids[i]);
+            }
+            selectionManager.setSelections(entityIDs, that);
+            if (data.focus) {
+                cameraManager.enable();
+                cameraManager.focus(selectionManager.worldPosition,
+                                    selectionManager.worldDimensions,
+                                    Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
+            }
+        } else if (data.type === "refresh") {
+            that.sendUpdate();
+        } else if (data.type === "teleport") {
+            if (selectionManager.hasSelection()) {
+                MyAvatar.position = selectionManager.worldPosition;
+            }
+        } else if (data.type === "export") {
+            if (!selectionManager.hasSelection()) {
+                Window.notifyEditError("No entities have been selected.");
+            } else {
+                Window.saveFileChanged.connect(onFileSaveChanged);
+                Window.saveAsync("Select Where to Save", "", "*.json");
+            }
+        } else if (data.type === "pal") {
+            var sessionIds = {}; // Collect the sessionsIds of all selected entities, w/o duplicates.
+            selectionManager.selections.forEach(function (id) {
+                var lastEditedBy = Entities.getEntityProperties(id, 'lastEditedBy').lastEditedBy;
+                if (lastEditedBy) {
+                    sessionIds[lastEditedBy] = true;
+                }
+            });
+            var dedupped = Object.keys(sessionIds);
+            if (!selectionManager.selections.length) {
+                Window.alert('No objects selected.');
+            } else if (!dedupped.length) {
+                Window.alert('There were no recent users of the ' + selectionManager.selections.length + ' selected objects.');
+            } else {
+                // No need to subscribe if we're just sending.
+                Messages.sendMessage('com.highfidelity.pal', JSON.stringify({method: 'select', params: [dedupped, true, false]}), 'local');
+            }
+        } else if (data.type === "delete") {
+            deleteSelectedEntities();
+        } else if (data.type === "toggleLocked") {
+            toggleSelectedEntitiesLocked();
+        } else if (data.type === "toggleVisible") {
+            toggleSelectedEntitiesVisible();
+        } else if (data.type === "filterInView") {
+            filterInView = data.filterInView === true;
+        } else if (data.type === "radius") {
+            searchRadius = data.radius;
+        } else if (data.type === "cut") {
+            SelectionManager.cutSelectedEntities();
+        } else if (data.type === "copy") {
+            SelectionManager.copySelectedEntities();
+        } else if (data.type === "paste") {
+            SelectionManager.pasteEntities();
+        } else if (data.type === "duplicate") {
+            SelectionManager.duplicateSelection();
+            that.sendUpdate();
+        } else if (data.type === "rename") {
+            Entities.editEntity(data.entityID, {name: data.name});
+            // make sure that the name also gets updated in the properties window
+            SelectionManager._update();
+        } else if (data.type === "toggleSpaceMode") {
+            SelectionDisplay.toggleSpaceMode();
+        } else if (data.type === 'keyUpEvent') {
+            keyUpEventFromUIWindow(data.keyUpEvent);
+        }
+    };
+
+    webView.webEventReceived.connect(onWebEventReceived);
+    entityListWindow.webEventReceived.addListener(onWebEventReceived);
+    that.interactiveWindowHidden = entityListWindow.interactiveWindowHidden;
+
+    return that;
+};
diff --git a/scripts/simplifiedUI/system/create/entityList/html/entityList.html b/scripts/simplifiedUI/system/create/entityList/html/entityList.html
new file mode 100644
index 0000000000..3e17a66df5
--- /dev/null
+++ b/scripts/simplifiedUI/system/create/entityList/html/entityList.html
@@ -0,0 +1,93 @@
+<!--
+//  entityList.html
+//
+//  Created by Ryan Huffman on 19 Nov 2014
+//  Copyright 2014 High Fidelity, Inc.
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+-->
+<html>
+    <head>
+        <title>Entity List</title>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+        <link rel="stylesheet" type="text/css" href="../../../html/css/edit-style.css">
+        <script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
+        <script type="text/javascript" src="../../../html/js/jquery-2.1.4.min.js"></script>
+        <script type="text/javascript" src="../../../html/js/eventBridgeLoader.js"></script>
+        <script type="text/javascript" src="../../../html/js/spinButtons.js"></script>
+        <script type="text/javascript" src="../../../html/js/utils.js"></script>
+        <script type="text/javascript" src="../../../html/js/includes.js"></script>
+        <script type="text/javascript" src="js/listView.js"></script>
+        <script type="text/javascript" src="js/entityListContextMenu.js"></script>
+        <script type="text/javascript" src="js/entityList.js"></script>
+    </head>
+    <body onload='loaded();' id="entity-list-body">
+        <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="pal" class="glyph" value="&#xe00c;" />
+            <button id="toggle-space-mode" class="hifi-edit-button space-mode-local">Local</button>
+            <input type="button" class="red glyph" id="delete" value="{" />
+        </div>
+        <div id="entity-list">
+            <div id="filter-area">
+                <div id="filter-type-multiselect" class="multiselect">
+                    <div id="filter-type-multiselect-box" class="multiselect-box">
+                        <select>
+                            <option id="filter-type-text">All Types</option>
+                        </select>
+                        <div class="over-select"></div>
+                    </div>
+                    <div id="filter-type-options" class="multiselect-options">
+                        <!-- type options with checkbox, icon, and label are added at runtime in entityList -->
+                        <div id="filter-type-options-buttons">
+                            <input type="button" id="filter-type-select-all" value="Select All"/>
+                            <input type="button" id="filter-type-clear-all" value="Clear All"/>
+                        </div>
+                    </div>
+                </div>
+                <div id="filter-search-and-icon">
+                    <span class="icon-input"><input type="search" class="search" id="filter-search" placeholder="Search" /><span>Y</span></span>
+                </div>
+                <input type="button" id="filter-in-view" class="glyph" value="&#xe007;" />
+                <div id="filter-radius-and-unit" class="number">
+                    <label for="radius">Search radius <span class="unit">m</span></label>
+                    <input type="text" id="filter-radius" maxlength="9" value="100" />
+                </div>
+            </div>
+            <div id="entity-table-scroll">
+                <table id="entity-table">
+                    <!-- rows and columns are added at runtime in entityList / listView -->
+                    <thead id="entity-table-header"/>
+                    <tbody class="list" id="entity-table-body"/>
+                </table>
+                <div id="entity-table-columns-multiselect" class="multiselect">
+                    <div id="entity-table-columns-multiselect-box" class="multiselect-box">
+                        <select>
+                            <option id="entity-table-columns-toggle"></option>
+                        </select>
+                        <div class="over-select"></div>
+                    </div>
+                    <div id="entity-table-columns-options" class="multiselect-options">
+                        <!-- column options are added at runtime in entityList -->
+                    </div>
+                </div>
+                <div id="no-entities">
+                    There are no entities to display. Please check your filters or create an entity to begin.
+                </div>
+            </div>
+        </div>
+        <div id="entity-list-footer">
+            <div>
+                <input type="button" id="export" value="Export Selection" />
+                <div id="footer-text">
+                    <b><span id="selected-entities-count">0</span> of <span id="visible-entities-count">0</span></b> selected
+                </div>
+            </div>
+        </div>
+    </body>
+</html>
diff --git a/scripts/simplifiedUI/system/html/js/entityList.js b/scripts/simplifiedUI/system/create/entityList/html/js/entityList.js
similarity index 100%
rename from scripts/simplifiedUI/system/html/js/entityList.js
rename to scripts/simplifiedUI/system/create/entityList/html/js/entityList.js
diff --git a/scripts/simplifiedUI/system/html/js/entityListContextMenu.js b/scripts/simplifiedUI/system/create/entityList/html/js/entityListContextMenu.js
similarity index 100%
rename from scripts/simplifiedUI/system/html/js/entityListContextMenu.js
rename to scripts/simplifiedUI/system/create/entityList/html/js/entityListContextMenu.js
diff --git a/scripts/simplifiedUI/system/html/js/listView.js b/scripts/simplifiedUI/system/create/entityList/html/js/listView.js
similarity index 100%
rename from scripts/simplifiedUI/system/html/js/listView.js
rename to scripts/simplifiedUI/system/create/entityList/html/js/listView.js
diff --git a/scripts/simplifiedUI/system/create/EditEntityList.qml b/scripts/simplifiedUI/system/create/entityList/qml/EditEntityList.qml
similarity index 82%
rename from scripts/simplifiedUI/system/create/EditEntityList.qml
rename to scripts/simplifiedUI/system/create/entityList/qml/EditEntityList.qml
index 94935c7bb5..1d5beb9914 100644
--- a/scripts/simplifiedUI/system/create/EditEntityList.qml
+++ b/scripts/simplifiedUI/system/create/entityList/qml/EditEntityList.qml
@@ -10,7 +10,7 @@ import stylesUit 1.0
 
 WebView {
     id: entityListToolWebView
-    url: Paths.defaultScripts + "/system/html/entityList.html"
+    url: Qt.resolvedUrl("../html/entityList.html")
     enabled: true
     blurOnCtrlShift: false
 }
diff --git a/scripts/simplifiedUI/system/create/EntityList.qml b/scripts/simplifiedUI/system/create/entityList/qml/EntityList.qml
similarity index 58%
rename from scripts/simplifiedUI/system/create/EntityList.qml
rename to scripts/simplifiedUI/system/create/entityList/qml/EntityList.qml
index 2f8a8863be..8f92ffe6ce 100644
--- a/scripts/simplifiedUI/system/create/EntityList.qml
+++ b/scripts/simplifiedUI/system/create/entityList/qml/EntityList.qml
@@ -1,6 +1,6 @@
 WebView {
     id: entityListToolWebView
-    url: Paths.defaultScripts + "/system/html/entityList.html"
+    url:  Qt.resolvedUrl("../html/entityList.html")
     enabled: true
     blurOnCtrlShift: false
 }
diff --git a/scripts/simplifiedUI/system/create/entityProperties/html/entityProperties.html b/scripts/simplifiedUI/system/create/entityProperties/html/entityProperties.html
new file mode 100644
index 0000000000..876e75ec35
--- /dev/null
+++ b/scripts/simplifiedUI/system/create/entityProperties/html/entityProperties.html
@@ -0,0 +1,52 @@
+<!--
+//  entityProperties.html
+//
+//  Created by Ryan Huffman on 13 Nov 2014
+//  Copyright 2014 High Fidelity, Inc.
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+-->
+<html>
+
+<head>
+    <title>Properties</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+    <link rel="stylesheet" type="text/css" href="../../../html/css/edit-style.css">
+    <link rel="stylesheet" type="text/css" href="../../../html/css/colpick.css">
+    <link rel="stylesheet" type="text/css" href="../../../html/css/jsoneditor.css">
+    <script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
+    <script src="../../../html/js/jquery-2.1.4.min.js"></script>
+    <script type="text/javascript" src="../../../html/js/colpick.js"></script>
+    <script type="text/javascript" src="../../../html/js/jsoneditor.min.js"></script>
+    <script type="text/javascript" src="../../../html/js/eventBridgeLoader.js"></script>
+    <script type="text/javascript" src="../../../html/js/spinButtons.js"></script>
+    <script type="text/javascript" src="../../../html/js/utils.js"></script>
+    <script type="text/javascript" src="../../../html/js/includes.js"></script>
+    <script type="text/javascript" src="js/underscore-min.js"></script>
+    <script type="text/javascript" src="js/createAppTooltip.js"></script>
+    <script type="text/javascript" src="js/draggableNumber.js"></script>
+    <script type="text/javascript" src="js/entityProperties.js"></script>
+    
+</head>
+
+<body onload='loaded();'>
+    <div id="properties-list">
+        <div class='property container'>
+            <label id='placeholder-property-type'></label>
+            <div class='value'>
+                <div class='row flex-center' style='padding-bottom: 8px;'>
+                    <div id="placeholder-property-name" class="stretch"></div>
+                    <div id="placeholder-property-locked" class="shrink"></div>
+                    <div id="placeholder-property-visible" class="shrink"></div>
+                </div>
+                <div class='row'>
+                    <div id="placeholder-property-id" class="stretch"></div>
+                </div>
+            </div>
+        </div>
+        <!-- each property is added at runtime in entityProperties -->
+    </div>
+</body>
+
+</html>
diff --git a/scripts/simplifiedUI/system/create/entityProperties/html/js/createAppTooltip.js b/scripts/simplifiedUI/system/create/entityProperties/html/js/createAppTooltip.js
new file mode 100644
index 0000000000..3eb206d8a3
--- /dev/null
+++ b/scripts/simplifiedUI/system/create/entityProperties/html/js/createAppTooltip.js
@@ -0,0 +1,116 @@
+//  createAppTooltip.js
+//
+//  Created by Thijs Wenker on 17 Oct 2018
+//  Copyright 2018 High Fidelity, Inc.
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+
+const CREATE_APP_TOOLTIP_OFFSET = 20;
+const TOOLTIP_DELAY = 500; // ms
+const TOOLTIP_DEBUG = false;
+
+function CreateAppTooltip() {
+    this._tooltipData = null;
+    this._tooltipDiv = null;
+    this._delayTimeout = null;
+    this._isEnabled = false;
+}
+
+CreateAppTooltip.prototype = {
+    _tooltipData: null,
+    _tooltipDiv: null,
+    _delayTimeout: null,
+    _isEnabled: null,
+
+    _removeTooltipIfExists: function() {
+        if (this._delayTimeout !== null) {
+            window.clearTimeout(this._delayTimeout);
+            this._delayTimeout = null;
+        }
+
+        if (this._tooltipDiv !== null) {
+            this._tooltipDiv.remove();
+            this._tooltipDiv = null;
+        }
+    },
+
+    setIsEnabled: function(isEnabled) {
+        this._isEnabled = isEnabled;
+    },
+
+    setTooltipData: function(tooltipData) {
+        this._tooltipData = tooltipData;
+    },
+
+    registerTooltipElement: function(element, tooltipID, jsPropertyName) {
+        element.addEventListener("mouseover", function() {
+            if (!this._isEnabled) {
+                return;
+            }
+
+            this._removeTooltipIfExists();
+
+            this._delayTimeout = window.setTimeout(function() {
+                let tooltipData = this._tooltipData[tooltipID];
+
+                if (!tooltipData || tooltipData.tooltip === "") {
+                    if (!TOOLTIP_DEBUG) {
+                        return;
+                    }
+                    tooltipData = { tooltip: 'PLEASE SET THIS TOOLTIP' };
+                }
+
+                let elementRect = element.getBoundingClientRect();
+                let elTip = document.createElement("div");
+                elTip.className = "create-app-tooltip";
+
+                let elTipDescription = document.createElement("div");
+                elTipDescription.className = "create-app-tooltip-description";
+                elTipDescription.innerText = tooltipData.tooltip;
+                elTip.appendChild(elTipDescription);
+
+                let jsAttribute = jsPropertyName;
+                if (tooltipData.jsPropertyName) {
+                    jsAttribute = tooltipData.jsPropertyName;
+                }
+
+                if (!tooltipData.skipJSProperty) {
+                    let elTipJSAttribute = document.createElement("div");
+                    elTipJSAttribute.className = "create-app-tooltip-js-attribute";
+                    elTipJSAttribute.innerText = `JS Attribute: ${jsAttribute}`;
+                    elTip.appendChild(elTipJSAttribute);
+                }
+
+                document.body.appendChild(elTip);
+
+                let elementTop = window.pageYOffset + elementRect.top;
+
+                let desiredTooltipTop = elementTop + element.clientHeight + CREATE_APP_TOOLTIP_OFFSET;
+                let desiredTooltipLeft = window.pageXOffset + elementRect.left;
+
+                if ((window.innerHeight + window.pageYOffset) < (desiredTooltipTop + elTip.clientHeight)) {
+                    // show above when otherwise out of bounds
+                    elTip.style.top = elementTop - CREATE_APP_TOOLTIP_OFFSET - elTip.clientHeight;
+                } else {
+                    // show tooltip below by default
+                    elTip.style.top = desiredTooltipTop;
+                }
+                if ((window.innerWidth + window.pageXOffset) < (desiredTooltipLeft + elTip.clientWidth)) {
+                    elTip.style.left = document.body.clientWidth + window.pageXOffset - elTip.offsetWidth;
+                } else {
+                    elTip.style.left = desiredTooltipLeft;
+                }
+
+                this._tooltipDiv = elTip;
+            }.bind(this), TOOLTIP_DELAY);
+        }.bind(this), false);
+        element.addEventListener("mouseout", function() {
+            if (!this._isEnabled) {
+                return;
+            }
+
+            this._removeTooltipIfExists();
+        }.bind(this), false);
+    }
+};
diff --git a/scripts/simplifiedUI/system/html/js/draggableNumber.js b/scripts/simplifiedUI/system/create/entityProperties/html/js/draggableNumber.js
similarity index 100%
rename from scripts/simplifiedUI/system/html/js/draggableNumber.js
rename to scripts/simplifiedUI/system/create/entityProperties/html/js/draggableNumber.js
diff --git a/scripts/simplifiedUI/system/html/js/entityProperties.js b/scripts/simplifiedUI/system/create/entityProperties/html/js/entityProperties.js
similarity index 100%
rename from scripts/simplifiedUI/system/html/js/entityProperties.js
rename to scripts/simplifiedUI/system/create/entityProperties/html/js/entityProperties.js
diff --git a/scripts/simplifiedUI/system/html/js/underscore-min.js b/scripts/simplifiedUI/system/create/entityProperties/html/js/underscore-min.js
similarity index 100%
rename from scripts/simplifiedUI/system/html/js/underscore-min.js
rename to scripts/simplifiedUI/system/create/entityProperties/html/js/underscore-min.js
diff --git a/scripts/simplifiedUI/system/create/entitySelectionTool/entitySelectionTool.js b/scripts/simplifiedUI/system/create/entitySelectionTool/entitySelectionTool.js
new file mode 100644
index 0000000000..9c993d6d73
--- /dev/null
+++ b/scripts/simplifiedUI/system/create/entitySelectionTool/entitySelectionTool.js
@@ -0,0 +1,2925 @@
+//
+//  entitySelectionTool.js
+//  examples
+//
+//  Created by Brad hefta-Gaub on 10/1/14.
+//    Modified by Daniela Fontes * @DanielaFifo and Tiago Andrade @TagoWill on 4/7/2017
+//    Modified by David Back on 1/9/2018
+//  Copyright 2014 High Fidelity, Inc.
+//
+//  This script implements a class useful for building tools for editing entities.
+//
+//  Distributed under the Apache License, Version 2.0.
+//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+/* global SelectionManager, SelectionDisplay, grid, rayPlaneIntersection, rayPlaneIntersection2, pushCommandForSelections,
+   getMainTabletIDs, getControllerWorldLocation, TRIGGER_ON_VALUE */
+
+const SPACE_LOCAL = "local";
+const SPACE_WORLD = "world";
+const HIGHLIGHT_LIST_NAME = "editHandleHighlightList";
+
+Script.include([
+    "../../libraries/controllers.js",
+    "../../libraries/controllerDispatcherUtils.js",
+    "../../libraries/utils.js"
+]);
+
+
+function deepCopy(v) {
+    return JSON.parse(JSON.stringify(v));
+}
+
+SelectionManager = (function() {
+    var that = {};
+
+    // FUNCTION: SUBSCRIBE TO UPDATE MESSAGES
+    function subscribeToUpdateMessages() {
+        Messages.subscribe("entityToolUpdates");
+        Messages.messageReceived.connect(handleEntitySelectionToolUpdates);
+    }
+
+    // FUNCTION: HANDLE ENTITY SELECTION TOOL UPDATES
+    function handleEntitySelectionToolUpdates(channel, message, sender) {
+        if (channel !== 'entityToolUpdates') {
+            return;
+        }
+        if (sender !== MyAvatar.sessionUUID) {
+            return;
+        }
+
+        var wantDebug = false;
+        var messageParsed;
+        try {
+            messageParsed = JSON.parse(message);
+        } catch (err) {
+            print("ERROR: entitySelectionTool.handleEntitySelectionToolUpdates - got malformed message");
+            return;
+        }
+
+        if (messageParsed.method === "selectEntity") {
+            if (!SelectionDisplay.triggered() || SelectionDisplay.triggeredHand === messageParsed.hand) {
+                if (wantDebug) {
+                    print("setting selection to " + messageParsed.entityID);
+                }
+                that.setSelections([messageParsed.entityID], that);
+            }
+        } else if (messageParsed.method === "clearSelection") {
+            if (!SelectionDisplay.triggered() || SelectionDisplay.triggeredHand === messageParsed.hand) {
+                that.clearSelections();
+            }
+        } else if (messageParsed.method === "pointingAt") {
+            if (messageParsed.hand === Controller.Standard.RightHand) {
+                that.pointingAtDesktopWindowRight = messageParsed.desktopWindow;
+                that.pointingAtTabletRight = messageParsed.tablet;
+            } else {
+                that.pointingAtDesktopWindowLeft = messageParsed.desktopWindow;
+                that.pointingAtTabletLeft = messageParsed.tablet;
+            }
+        }
+    }
+
+    subscribeToUpdateMessages();
+
+    // disabling this for now as it is causing rendering issues with the other handle overlays
+    /*
+    var COLOR_ORANGE_HIGHLIGHT = { red: 255, green: 99, blue: 9 };
+    var editHandleOutlineStyle = {
+        outlineUnoccludedColor: COLOR_ORANGE_HIGHLIGHT,
+        outlineOccludedColor: COLOR_ORANGE_HIGHLIGHT,
+        fillUnoccludedColor: COLOR_ORANGE_HIGHLIGHT,
+        fillOccludedColor: COLOR_ORANGE_HIGHLIGHT,
+        outlineUnoccludedAlpha: 1,
+        outlineOccludedAlpha: 0,
+        fillUnoccludedAlpha: 0,
+        fillOccludedAlpha: 0,
+        outlineWidth: 3,
+        isOutlineSmooth: true
+    };
+    Selection.enableListHighlight(HIGHLIGHT_LIST_NAME, editHandleOutlineStyle);
+    */
+
+    that.savedProperties = {};
+    that.selections = [];
+    var listeners = [];
+
+    that.localRotation = Quat.IDENTITY;
+    that.localPosition = Vec3.ZERO;
+    that.localDimensions = Vec3.ZERO;
+    that.localRegistrationPoint = Vec3.HALF;
+
+    that.worldRotation = Quat.IDENTITY;
+    that.worldPosition = Vec3.ZERO;
+    that.worldDimensions = Vec3.ZERO;
+    that.worldRegistrationPoint = Vec3.HALF;
+    that.centerPosition = Vec3.ZERO;
+    
+    that.pointingAtDesktopWindowLeft = false;
+    that.pointingAtDesktopWindowRight = false;
+    that.pointingAtTabletLeft = false;
+    that.pointingAtTabletRight = false;
+
+    that.saveProperties = function() {
+        that.savedProperties = {};
+        for (var i = 0; i < that.selections.length; i++) {
+            var entityID = that.selections[i];
+            that.savedProperties[entityID] = Entities.getEntityProperties(entityID);
+        }
+    };
+
+    that.addEventListener = function(func, thisContext) {
+        listeners.push({
+            callback: func,
+            thisContext: thisContext
+        });
+    };
+
+    that.hasSelection = function() {
+        return that.selections.length > 0;
+    };
+
+    that.setSelections = function(entityIDs, caller) {
+        that.selections = [];
+        for (var i = 0; i < entityIDs.length; i++) {
+            var entityID = entityIDs[i];
+            that.selections.push(entityID);
+            Selection.addToSelectedItemsList(HIGHLIGHT_LIST_NAME, "entity", entityID);
+        }
+
+        that._update(true, caller);
+    };
+
+    that.addEntity = function(entityID, toggleSelection, caller) {
+        if (entityID) {
+            var idx = -1;
+            for (var i = 0; i < that.selections.length; i++) {
+                if (entityID === that.selections[i]) {
+                    idx = i;
+                    break;
+                }
+            }
+            if (idx === -1) {
+                that.selections.push(entityID);
+                Selection.addToSelectedItemsList(HIGHLIGHT_LIST_NAME, "entity", entityID);
+            } else if (toggleSelection) {
+                that.selections.splice(idx, 1);
+                Selection.removeFromSelectedItemsList(HIGHLIGHT_LIST_NAME, "entity", entityID);
+            }
+        }
+
+        that._update(true, caller);
+    };
+
+    function removeEntityByID(entityID) {
+        var idx = that.selections.indexOf(entityID);
+        if (idx >= 0) {
+            that.selections.splice(idx, 1);
+            Selection.removeFromSelectedItemsList(HIGHLIGHT_LIST_NAME, "entity", entityID);
+        }
+    }
+
+    that.removeEntity = function (entityID, caller) {
+        removeEntityByID(entityID);
+        that._update(true, caller);
+    };
+
+    that.removeEntities = function(entityIDs, caller) {
+        for (var i = 0, length = entityIDs.length; i < length; i++) {
+            removeEntityByID(entityIDs[i]);
+        }
+        that._update(true, caller);
+    };
+
+    that.clearSelections = function(caller) {
+        that.selections = [];
+        that._update(true, caller);
+    };
+    
+    that.addChildrenEntities = function(parentEntityID, entityList, entityHostType) {
+        var wantDebug = false;
+        var children = Entities.getChildrenIDs(parentEntityID);
+        var entityHostTypes = Entities.getMultipleEntityProperties(children, 'entityHostType');
+        for (var i = 0; i < children.length; i++) {
+            var childID = children[i];
+
+            if (entityHostTypes[i].entityHostType !== entityHostType) {
+                if (wantDebug) {
+                    console.log("Skipping addition of entity " + childID + " with conflicting entityHostType: " +
+                        entityHostTypes[i].entityHostType + ", expected: " + entityHostType);
+                }
+                continue;
+            }
+
+            if (entityList.indexOf(childID) < 0) {
+                entityList.push(childID);
+            }
+            that.addChildrenEntities(childID, entityList, entityHostType);
+        }
+    };
+
+    // Determine if an entity is being grabbed.
+    // This is mostly a heuristic - there is no perfect way to know if an entity is being
+    // grabbed.
+    //
+    // @return {boolean} true if the given entity with `properties` is being grabbed by an avatar
+    function nonDynamicEntityIsBeingGrabbedByAvatar(properties) {
+        if (properties.dynamic || Uuid.isNull(properties.parentID)) {
+            return false;
+        }
+
+        var avatar = AvatarList.getAvatar(properties.parentID);
+        if (Uuid.isNull(avatar.sessionUUID)) {
+            return false;
+        }
+
+        var grabJointNames = [
+            'RightHand', 'LeftHand',
+            '_CONTROLLER_RIGHTHAND', '_CONTROLLER_LEFTHAND',
+            '_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND', '_CAMERA_RELATIVE_CONTROLLER_LEFTHAND',
+            '_FARGRAB_RIGHTHAND', '_FARGRAB_LEFTHAND', '_FARGRAB_MOUSE'
+        ];
+
+        for (var i = 0; i < grabJointNames.length; ++i) {
+            if (avatar.getJointIndex(grabJointNames[i]) === properties.parentJointIndex) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    var entityClipboard = {
+        entities: {}, // Map of id -> properties for copied entities
+        position: { x: 0, y: 0, z: 0 },
+        dimensions: { x: 0, y: 0, z: 0 },
+    };
+
+    that.duplicateSelection = function() {
+        var entitiesToDuplicate = [];
+        var duplicatedEntityIDs = [];
+        var duplicatedChildrenWithOldParents = [];
+        var originalEntityToNewEntityID = [];
+
+        SelectionManager.saveProperties();
+        
+        // build list of entities to duplicate by including any unselected children of selected parent entities
+        var originalEntityIDs = Object.keys(that.savedProperties);
+        var entityHostTypes = Entities.getMultipleEntityProperties(originalEntityIDs, 'entityHostType');
+        for (var i = 0; i < originalEntityIDs.length; i++) {
+            var originalEntityID = originalEntityIDs[i];
+            if (entitiesToDuplicate.indexOf(originalEntityID) === -1) {
+                entitiesToDuplicate.push(originalEntityID);
+            }
+            that.addChildrenEntities(originalEntityID, entitiesToDuplicate, entityHostTypes[i].entityHostType);
+        }
+        
+        // duplicate entities from above and store their original to new entity mappings and children needing re-parenting
+        for (var i = 0; i < entitiesToDuplicate.length; i++) {
+            var originalEntityID = entitiesToDuplicate[i];
+            var properties = that.savedProperties[originalEntityID];
+            if (properties === undefined) {
+                properties = Entities.getEntityProperties(originalEntityID);
+            }
+            if (!properties.locked && (!properties.avatarEntity || properties.owningAvatarID === MyAvatar.sessionUUID)) {
+                if (nonDynamicEntityIsBeingGrabbedByAvatar(properties)) {
+                    properties.parentID = null;
+                    properties.parentJointIndex = null;
+                    properties.localPosition = properties.position;
+                    properties.localRotation = properties.rotation;
+                }
+
+                properties.localVelocity = Vec3.ZERO;
+                properties.localAngularVelocity = Vec3.ZERO;
+
+                delete properties.actionData;
+                var newEntityID = Entities.addEntity(properties);
+
+                // Re-apply actions from the original entity
+                var actionIDs = Entities.getActionIDs(properties.id);
+                for (var j = 0; j < actionIDs.length; ++j) {
+                    var actionID = actionIDs[j];
+                    var actionArguments = Entities.getActionArguments(properties.id, actionID);
+                    if (actionArguments) {
+                        var type = actionArguments.type;
+                        if (type === 'hold' || type === 'far-grab') {
+                            continue;
+                        }
+                        delete actionArguments.ttl;
+                        Entities.addAction(type, newEntityID, actionArguments);
+                    }
+                }
+
+                duplicatedEntityIDs.push({
+                    entityID: newEntityID,
+                    properties: properties
+                });
+                if (properties.parentID !== Uuid.NULL) {
+                    duplicatedChildrenWithOldParents[newEntityID] = properties.parentID;
+                }
+                originalEntityToNewEntityID[originalEntityID] = newEntityID;
+            }
+        }
+        
+        // re-parent duplicated children to the duplicate entities of their original parents (if they were duplicated)
+        Object.keys(duplicatedChildrenWithOldParents).forEach(function(childIDNeedingNewParent) {
+            var originalParentID = duplicatedChildrenWithOldParents[childIDNeedingNewParent];
+            var newParentID = originalEntityToNewEntityID[originalParentID];
+            if (newParentID) {
+                Entities.editEntity(childIDNeedingNewParent, { parentID: newParentID });
+                for (var i = 0; i < duplicatedEntityIDs.length; i++) {
+                    var duplicatedEntity = duplicatedEntityIDs[i];
+                    if (duplicatedEntity.entityID === childIDNeedingNewParent) {
+                        duplicatedEntity.properties.parentID = newParentID;
+                    }
+                }
+            }
+        });
+        
+        return duplicatedEntityIDs;
+    };
+
+    // Create the entities in entityProperties, maintaining parent-child relationships.
+    // @param entityProperties {array} - Array of entity property objects
+    that.createEntities = function(entityProperties) {
+        var entitiesToCreate = [];
+        var createdEntityIDs = [];
+        var createdChildrenWithOldParents = [];
+        var originalEntityToNewEntityID = [];
+
+        that.saveProperties();
+
+        for (var i = 0; i < entityProperties.length; ++i) {
+            var properties = entityProperties[i];
+            if (properties.parentID in originalEntityToNewEntityID) {
+                properties.parentID = originalEntityToNewEntityID[properties.parentID];
+            } else {
+                delete properties.parentID;
+            }
+
+            delete properties.actionData;
+            var newEntityID = Entities.addEntity(properties);
+
+            if (newEntityID) {
+                createdEntityIDs.push({
+                    entityID: newEntityID,
+                    properties: properties
+                });
+                if (properties.parentID !== Uuid.NULL) {
+                    createdChildrenWithOldParents[newEntityID] = properties.parentID;
+                }
+                originalEntityToNewEntityID[properties.id] = newEntityID;
+                properties.id = newEntityID;
+            }
+        }
+
+        return createdEntityIDs;
+    };
+
+    that.cutSelectedEntities = function() {
+        that.copySelectedEntities();
+        deleteSelectedEntities();
+    };
+
+    that.copySelectedEntities = function() {
+        var entityProperties = Entities.getMultipleEntityProperties(that.selections);
+        var entityHostTypes = Entities.getMultipleEntityProperties(that.selections, 'entityHostType');
+        var entities = {};
+        entityProperties.forEach(function(props) {
+            entities[props.id] = props;
+        });
+
+        function appendChildren(entityID, entities, entityHostType) {
+            var wantDebug = false;
+            var childrenIDs = Entities.getChildrenIDs(entityID);
+            var entityHostTypes = Entities.getMultipleEntityProperties(childrenIDs, 'entityHostType');
+            for (var i = 0; i < childrenIDs.length; ++i) {
+                var id = childrenIDs[i];
+
+                if (entityHostTypes[i].entityHostType !== entityHostType) {
+                    if (wantDebug) {
+                        console.warn("Skipping addition of entity " + id + " with conflicting entityHostType: " +
+                            entityHostTypes[i].entityHostType + ", expected: " + entityHostType);
+                    }
+                    continue;
+                }
+
+                if (!(id in entities)) {
+                    entities[id] = Entities.getEntityProperties(id); 
+                    appendChildren(id, entities, entityHostType);
+                }
+            }
+        }
+
+        var len = entityProperties.length;
+        for (var i = 0; i < len; ++i) {
+            appendChildren(entityProperties[i].id, entities, entityHostTypes[i].entityHostType);
+        }
+
+        for (var id in entities) {
+            var parentID = entities[id].parentID;
+            entities[id].root = !(parentID in entities);
+        }
+
+        entityClipboard.entities = [];
+
+        var ids = Object.keys(entities);
+        while (ids.length > 0) {
+            // Go through all remaining entities.
+            // If an entity does not have a parent left, move it into the list
+            for (var i = 0; i < ids.length; ++i) {
+                var id = ids[i];
+                var parentID = entities[id].parentID;
+                if (parentID in entities) {
+                    continue;
+                }
+                entityClipboard.entities.push(entities[id]);
+                delete entities[id];
+            }
+            ids = Object.keys(entities);
+        }
+
+        // Calculate size
+        if (entityClipboard.entities.length === 0) {
+            entityClipboard.dimensions = { x: 0, y: 0, z: 0 };
+            entityClipboard.position = { x: 0, y: 0, z: 0 };
+        } else {
+            var properties = entityClipboard.entities;
+            var brn = properties[0].boundingBox.brn;
+            var tfl = properties[0].boundingBox.tfl;
+            for (var i = 1; i < properties.length; i++) {
+                var bb = properties[i].boundingBox;
+                brn.x = Math.min(bb.brn.x, brn.x);
+                brn.y = Math.min(bb.brn.y, brn.y);
+                brn.z = Math.min(bb.brn.z, brn.z);
+                tfl.x = Math.max(bb.tfl.x, tfl.x);
+                tfl.y = Math.max(bb.tfl.y, tfl.y);
+                tfl.z = Math.max(bb.tfl.z, tfl.z);
+            }
+            entityClipboard.dimensions = {
+                x: tfl.x - brn.x,
+                y: tfl.y - brn.y,
+                z: tfl.z - brn.z
+            };
+            entityClipboard.position = {
+                x: brn.x + entityClipboard.dimensions.x / 2,
+                y: brn.y + entityClipboard.dimensions.y / 2,
+                z: brn.z + entityClipboard.dimensions.z / 2
+            };
+        }
+    };
+
+    that.pasteEntities = function() {
+        var dimensions = entityClipboard.dimensions;
+        var maxDimension = Math.max(dimensions.x, dimensions.y, dimensions.z);
+        var pastePosition = getPositionToCreateEntity(maxDimension);
+        var deltaPosition = Vec3.subtract(pastePosition, entityClipboard.position);
+
+        var copiedProperties = [];
+        var ids = [];
+        entityClipboard.entities.forEach(function(originalProperties) {
+            var properties = deepCopy(originalProperties);
+            if (properties.root) {
+                properties.position = Vec3.sum(properties.position, deltaPosition);
+                delete properties.localPosition;
+            } else {
+                delete properties.position;
+            }
+            copiedProperties.push(properties);
+        });
+
+        var currentSelections = deepCopy(SelectionManager.selections);
+
+        function redo(copiedProperties) {
+            var created = that.createEntities(copiedProperties);
+            var ids = [];
+            for (var i = 0; i < created.length; ++i) {
+                ids.push(created[i].entityID);
+            }
+            SelectionManager.setSelections(ids);
+        }
+
+        function undo(copiedProperties) {
+            for (var i = 0; i < copiedProperties.length; ++i) {
+                Entities.deleteEntity(copiedProperties[i].id);
+            }
+            SelectionManager.setSelections(currentSelections);
+        }
+
+        redo(copiedProperties);
+        undoHistory.pushCommand(undo, copiedProperties, redo, copiedProperties);
+    };
+
+    that._update = function(selectionUpdated, caller) {
+        var properties = null;
+        if (that.selections.length === 0) {
+            that.localDimensions = null;
+            that.localPosition = null;
+            that.worldDimensions = null;
+            that.worldPosition = null;
+            that.worldRotation = null;
+        } else if (that.selections.length === 1) {
+            properties = Entities.getEntityProperties(that.selections[0],
+                ['dimensions', 'position', 'rotation', 'registrationPoint', 'boundingBox', 'type']);
+            that.localDimensions = properties.dimensions;
+            that.localPosition = properties.position;
+            that.localRotation = properties.rotation;
+            that.localRegistrationPoint = properties.registrationPoint;
+
+            that.worldDimensions = properties.boundingBox.dimensions;
+            that.worldPosition = properties.boundingBox.center;
+            that.worldRotation = Quat.IDENTITY;
+
+            that.entityType = properties.type;
+            
+            if (selectionUpdated) {
+                SelectionDisplay.useDesiredSpaceMode();
+            }
+        } else {
+            properties = Entities.getEntityProperties(that.selections[0], ['type', 'boundingBox']);
+
+            that.entityType = properties.type;
+
+            var brn = properties.boundingBox.brn;
+            var tfl = properties.boundingBox.tfl;
+
+            for (var i = 1; i < that.selections.length; i++) {
+                properties = Entities.getEntityProperties(that.selections[i], 'boundingBox');
+                var bb = properties.boundingBox;
+                brn.x = Math.min(bb.brn.x, brn.x);
+                brn.y = Math.min(bb.brn.y, brn.y);
+                brn.z = Math.min(bb.brn.z, brn.z);
+                tfl.x = Math.max(bb.tfl.x, tfl.x);
+                tfl.y = Math.max(bb.tfl.y, tfl.y);
+                tfl.z = Math.max(bb.tfl.z, tfl.z);
+            }
+
+            that.localRotation = null;
+            that.localDimensions = null;
+            that.localPosition = null;
+            that.worldDimensions = {
+                x: tfl.x - brn.x,
+                y: tfl.y - brn.y,
+                z: tfl.z - brn.z
+            };
+            that.worldRotation = Quat.IDENTITY;
+            that.worldPosition = {
+                x: brn.x + (that.worldDimensions.x / 2),
+                y: brn.y + (that.worldDimensions.y / 2),
+                z: brn.z + (that.worldDimensions.z / 2)
+            };
+
+            // For 1+ selections we can only modify selections in world space
+            SelectionDisplay.setSpaceMode(SPACE_WORLD, false);
+        }
+
+        for (var j = 0; j < listeners.length; j++) {
+            try {
+                listeners[j].callback.call(listeners[j].thisContext, selectionUpdated === true, caller);
+            } catch (e) {
+                print("ERROR: entitySelectionTool.update got exception: " + JSON.stringify(e));
+            }
+        }
+    };
+
+    return that;
+})();
+
+// Normalize degrees to be in the range (-180, 180)
+function normalizeDegrees(degrees) {
+    var maxDegrees = 360;
+    var halfMaxDegrees = maxDegrees / 2;
+    degrees = ((degrees + halfMaxDegrees) % maxDegrees) - halfMaxDegrees;
+    if (degrees <= -halfMaxDegrees) {
+        degrees += maxDegrees;
+    }
+    return degrees;
+}
+
+// SELECTION DISPLAY DEFINITION
+SelectionDisplay = (function() {
+    var that = {};
+
+    const COLOR_GREEN = { red: 31, green: 198, blue: 166 };
+    const COLOR_BLUE = { red: 0, green: 147, blue: 197 };
+    const COLOR_RED = { red: 226, green: 51, blue: 77 };
+    const COLOR_HOVER = { red: 227, green: 227, blue: 227 };
+    const COLOR_ROTATE_CURRENT_RING = { red: 255, green: 99, blue: 9 };
+    const COLOR_BOUNDING_EDGE = { red: 87, green: 87, blue: 87 };
+    const COLOR_SCALE_CUBE = { red: 106, green: 106, blue: 106 };
+    const COLOR_SCALE_CUBE_SELECTED = { red: 18, green: 18, blue: 18 };
+    const COLOR_DEBUG_PICK_PLANE = { red: 255, green: 255, blue: 255 };
+    const COLOR_DEBUG_PICK_PLANE_HIT = { red: 255, green: 165, blue: 0 };
+
+    const TRANSLATE_ARROW_CYLINDER_OFFSET = 0.1;
+    const TRANSLATE_ARROW_CYLINDER_CAMERA_DISTANCE_MULTIPLE = 0.005;
+    const TRANSLATE_ARROW_CYLINDER_Y_MULTIPLE = 7.5;
+    const TRANSLATE_ARROW_CONE_CAMERA_DISTANCE_MULTIPLE = 0.025;
+    const TRANSLATE_ARROW_CONE_OFFSET_CYLINDER_DIMENSION_MULTIPLE = 0.83;
+
+    const ROTATE_RING_CAMERA_DISTANCE_MULTIPLE = 0.15;
+    const ROTATE_CTRL_SNAP_ANGLE = 22.5;
+    const ROTATE_DEFAULT_SNAP_ANGLE = 1;
+    const ROTATE_DEFAULT_TICK_MARKS_ANGLE = 5;
+    const ROTATE_RING_IDLE_INNER_RADIUS = 0.92;
+    const ROTATE_RING_SELECTED_INNER_RADIUS = 0.9;
+
+    // These are multipliers for sizing the rotation degrees display while rotating an entity
+    const ROTATE_DISPLAY_DISTANCE_MULTIPLIER = 2;
+    const ROTATE_DISPLAY_SIZE_X_MULTIPLIER = 0.2;
+    const ROTATE_DISPLAY_SIZE_Y_MULTIPLIER = 0.09;
+    const ROTATE_DISPLAY_LINE_HEIGHT_MULTIPLIER = 0.07;
+
+    const STRETCH_CUBE_OFFSET = 0.06;
+    const STRETCH_CUBE_CAMERA_DISTANCE_MULTIPLE = 0.02;
+    const STRETCH_PANEL_WIDTH = 0.01;
+
+    const SCALE_OVERLAY_CAMERA_DISTANCE_MULTIPLE = 0.02;
+    const SCALE_DIMENSIONS_CAMERA_DISTANCE_MULTIPLE = 0.5;
+    
+    const BOUNDING_EDGE_OFFSET = 0.5;
+
+    const DUPLICATOR_OFFSET = { x: 0.9, y: -0.9, z: 0.9 };    
+    
+    const CTRL_KEY_CODE = 16777249;
+
+    const RAIL_AXIS_LENGTH = 10000;
+    
+    const NEGATE_VECTOR = -1;
+    const NO_HAND = -1;
+    
+    const DEBUG_PICK_PLANE_HIT_LIMIT = 200;
+    const DEBUG_PICK_PLANE_HIT_CAMERA_DISTANCE_MULTIPLE = 0.01;
+
+    const TRANSLATE_DIRECTION = {
+        X: 0,
+        Y: 1,
+        Z: 2
+    };
+
+    const STRETCH_DIRECTION = {
+        X: 0,
+        Y: 1,
+        Z: 2,
+        ALL: 3
+    };
+
+    const ROTATE_DIRECTION = {
+        PITCH: 0,
+        YAW: 1,
+        ROLL: 2
+    };
+
+    const INEDIT_STATUS_CHANNEL = "Hifi-InEdit-Status";
+
+    /**
+     * The current space mode, this could have been a forced space mode since we do not support multi selection while in
+     * local space mode.
+     * @type {string} - should only be set to SPACE_LOCAL or SPACE_WORLD
+     */
+    var spaceMode = SPACE_LOCAL;
+
+    /**
+     * The desired space mode, this is the user set space mode, which should be respected whenever it is possible. In the case
+     * of multi entity selection this space mode may differ from the actual spaceMode.
+     * @type {string} - should only be set to SPACE_LOCAL or SPACE_WORLD
+     */
+    var desiredSpaceMode = SPACE_LOCAL;
+
+    var overlayNames = [];
+    var lastControllerPoses = [
+        getControllerWorldLocation(Controller.Standard.LeftHand, true),
+        getControllerWorldLocation(Controller.Standard.RightHand, true)
+    ];
+
+    var worldRotationX;
+    var worldRotationY;
+    var worldRotationZ;
+    
+    var activeStretchCubePanelOffset = null;
+
+    var previousHandle = null;
+    var previousHandleHelper = null;
+    var previousHandleColor;
+
+    var ctrlPressed = false;
+
+    that.replaceCollisionsAfterStretch = false;
+
+    var handlePropertiesTranslateArrowCones = {
+        alpha: 1,
+        shape: "Cone",
+        solid: true,
+        visible: false,
+        ignorePickIntersection: true,
+        drawInFront: true
+    };
+    var handlePropertiesTranslateArrowCylinders = {
+        alpha: 1,
+        shape: "Cylinder",
+        solid: true,
+        visible: false,
+        ignorePickIntersection: true,
+        drawInFront: true
+    };
+    var handleTranslateXCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones);
+    var handleTranslateXCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders);
+    Overlays.editOverlay(handleTranslateXCone, { color: COLOR_RED });
+    Overlays.editOverlay(handleTranslateXCylinder, { color: COLOR_RED });
+    var handleTranslateYCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones);
+    var handleTranslateYCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders);
+    Overlays.editOverlay(handleTranslateYCone, { color: COLOR_GREEN });
+    Overlays.editOverlay(handleTranslateYCylinder, { color: COLOR_GREEN });
+    var handleTranslateZCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones);
+    var handleTranslateZCylinder = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCylinders);
+    Overlays.editOverlay(handleTranslateZCone, { color: COLOR_BLUE });
+    Overlays.editOverlay(handleTranslateZCylinder, { color: COLOR_BLUE });
+
+    var handlePropertiesRotateRings = {
+        alpha: 1,
+        solid: true,
+        startAt: 0,
+        endAt: 360,
+        innerRadius: ROTATE_RING_IDLE_INNER_RADIUS,
+        majorTickMarksAngle: ROTATE_DEFAULT_TICK_MARKS_ANGLE,
+        majorTickMarksLength: 0.1,
+        visible: false,
+        ignorePickIntersection: true,
+        drawInFront: true
+    };
+    var handleRotatePitchRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings);
+    Overlays.editOverlay(handleRotatePitchRing, { 
+        color: COLOR_RED,
+        majorTickMarksColor: COLOR_RED
+    });
+    var handleRotateYawRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings);
+    Overlays.editOverlay(handleRotateYawRing, { 
+        color: COLOR_GREEN,
+        majorTickMarksColor: COLOR_GREEN
+    });
+    var handleRotateRollRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings);
+    Overlays.editOverlay(handleRotateRollRing, { 
+        color: COLOR_BLUE,
+        majorTickMarksColor: COLOR_BLUE
+    });
+
+    var handleRotateCurrentRing = Overlays.addOverlay("circle3d", {
+        alpha: 1,
+        color: COLOR_ROTATE_CURRENT_RING,
+        solid: true,
+        innerRadius: 0.9,
+        visible: false,
+        ignorePickIntersection: true,
+        drawInFront: true
+    });
+
+    var rotationDegreesDisplay = Overlays.addOverlay("text3d", {
+        text: "",
+        color: { red: 0, green: 0, blue: 0 },
+        backgroundColor: { red: 255, green: 255, blue: 255 },
+        alpha: 0.7,
+        backgroundAlpha: 0.7,
+        visible: false,
+        isFacingAvatar: true,
+        drawInFront: true,
+        ignorePickIntersection: true,
+        dimensions: { x: 0, y: 0 },
+        lineHeight: 0.0,
+        topMargin: 0,
+        rightMargin: 0,
+        bottomMargin: 0,
+        leftMargin: 0
+    });
+
+    var handlePropertiesStretchCubes = {
+        solid: true,
+        visible: false,
+        ignorePickIntersection: true,
+        drawInFront: true
+    };
+    var handleStretchXCube = Overlays.addOverlay("cube", handlePropertiesStretchCubes);
+    Overlays.editOverlay(handleStretchXCube, { color: COLOR_RED });
+    var handleStretchYCube = Overlays.addOverlay("cube", handlePropertiesStretchCubes);
+    Overlays.editOverlay(handleStretchYCube, { color: COLOR_GREEN });
+    var handleStretchZCube = Overlays.addOverlay("cube", handlePropertiesStretchCubes);
+    Overlays.editOverlay(handleStretchZCube, { color: COLOR_BLUE });
+
+    var handlePropertiesStretchPanel = {
+        alpha: 0.5,
+        solid: true,
+        visible: false,
+        ignorePickIntersection: true,
+        drawInFront: true
+    };
+    var handleStretchXPanel = Overlays.addOverlay("cube", handlePropertiesStretchPanel);
+    Overlays.editOverlay(handleStretchXPanel, { color: COLOR_RED });
+    var handleStretchYPanel = Overlays.addOverlay("cube", handlePropertiesStretchPanel);
+    Overlays.editOverlay(handleStretchYPanel, { color: COLOR_GREEN });
+    var handleStretchZPanel = Overlays.addOverlay("cube", handlePropertiesStretchPanel);
+    Overlays.editOverlay(handleStretchZPanel, { color: COLOR_BLUE });
+
+    var handleScaleCube = Overlays.addOverlay("cube", {
+        size: 0.025,
+        color: COLOR_SCALE_CUBE,
+        solid: true,
+        visible: false,
+        ignorePickIntersection: true,
+        drawInFront: true,
+        borderSize: 1.4
+    });
+
+    var handleBoundingBox = Overlays.addOverlay("cube", {
+        alpha: 1,
+        color: COLOR_BOUNDING_EDGE,
+        visible: false,
+        ignorePickIntersection: true,
+        drawInFront: true,
+        isSolid: false
+    });
+
+    var handleDuplicator = Overlays.addOverlay("cube", {
+        alpha: 1,
+        size: 0.05,
+        color: COLOR_GREEN,
+        solid: true,
+        visible: false,
+        ignorePickIntersection: true,
+        drawInFront: true,
+        borderSize: 1.4
+    });
+
+    // setting to 0 alpha for now to keep this hidden vs using visible false 
+    // because its used as the translate xz tool handle overlay
+    var selectionBox = Overlays.addOverlay("cube", {
+        size: 1,
+        color: COLOR_RED,
+        alpha: 0,
+        solid: false,
+        visible: false,
+        ignorePickIntersection: true,
+        dashed: false
+    });
+
+    // Handle for x-z translation of particle effect and light entities while inside the bounding box.
+    // Limitation: If multiple entities are selected, only the first entity's icon translates the selection.
+    var iconSelectionBox = Overlays.addOverlay("cube", {
+        size: 0.3, // Match entity icon size.
+        color: COLOR_RED,
+        alpha: 0,
+        solid: false,
+        visible: false,
+        ignorePickIntersection: true,
+        dashed: false
+    });
+
+    var xRailOverlay = Overlays.addOverlay("line3d", {
+        visible: false,
+        start: Vec3.ZERO,
+        end: Vec3.ZERO,
+        color: {
+            red: 255,
+            green: 0,
+            blue: 0
+        },
+        ignorePickIntersection: true // always ignore this
+    });
+    var yRailOverlay = Overlays.addOverlay("line3d", {
+        visible: false,
+        start: Vec3.ZERO,
+        end: Vec3.ZERO,
+        color: {
+            red: 0,
+            green: 255,
+            blue: 0
+        },
+        ignorePickIntersection: true // always ignore this
+    });
+    var zRailOverlay = Overlays.addOverlay("line3d", {
+        visible: false,
+        start: Vec3.ZERO,
+        end: Vec3.ZERO,
+        color: {
+            red: 0,
+            green: 0,
+            blue: 255
+        },
+        ignorePickIntersection: true // always ignore this
+    });
+
+    var allOverlays = [
+        handleTranslateXCone,
+        handleTranslateXCylinder,
+        handleTranslateYCone,
+        handleTranslateYCylinder,
+        handleTranslateZCone,
+        handleTranslateZCylinder,
+        handleRotatePitchRing,
+        handleRotateYawRing,
+        handleRotateRollRing,
+        handleRotateCurrentRing,
+        rotationDegreesDisplay,
+        handleStretchXCube,
+        handleStretchYCube,
+        handleStretchZCube,
+        handleStretchXPanel,
+        handleStretchYPanel,
+        handleStretchZPanel,
+        handleScaleCube,
+        handleBoundingBox,
+        handleDuplicator,
+        selectionBox,
+        iconSelectionBox,
+        xRailOverlay,
+        yRailOverlay,
+        zRailOverlay
+    ];
+
+    const nonLayeredOverlays = [selectionBox, iconSelectionBox];
+
+    var maximumHandleInAllOverlays = handleDuplicator;
+
+    overlayNames[handleTranslateXCone] = "handleTranslateXCone";
+    overlayNames[handleTranslateXCylinder] = "handleTranslateXCylinder";
+    overlayNames[handleTranslateYCone] = "handleTranslateYCone";
+    overlayNames[handleTranslateYCylinder] = "handleTranslateYCylinder";
+    overlayNames[handleTranslateZCone] = "handleTranslateZCone";
+    overlayNames[handleTranslateZCylinder] = "handleTranslateZCylinder";
+
+    overlayNames[handleRotatePitchRing] = "handleRotatePitchRing";
+    overlayNames[handleRotateYawRing] = "handleRotateYawRing";
+    overlayNames[handleRotateRollRing] = "handleRotateRollRing";
+    overlayNames[handleRotateCurrentRing] = "handleRotateCurrentRing";
+    overlayNames[rotationDegreesDisplay] = "rotationDegreesDisplay";
+
+    overlayNames[handleStretchXCube] = "handleStretchXCube";
+    overlayNames[handleStretchYCube] = "handleStretchYCube";
+    overlayNames[handleStretchZCube] = "handleStretchZCube";
+    overlayNames[handleStretchXPanel] = "handleStretchXPanel";
+    overlayNames[handleStretchYPanel] = "handleStretchYPanel";
+    overlayNames[handleStretchZPanel] = "handleStretchZPanel";
+
+    overlayNames[handleScaleCube] = "handleScaleCube";
+
+    overlayNames[handleBoundingBox] = "handleBoundingBox";
+
+    overlayNames[handleDuplicator] = "handleDuplicator";
+    overlayNames[selectionBox] = "selectionBox";
+    overlayNames[iconSelectionBox] = "iconSelectionBox";
+
+    var activeTool = null;
+    var handleTools = {};
+    
+    var debugPickPlaneEnabled = false;
+    var debugPickPlane = Overlays.addOverlay("shape", {
+        shape: "Quad",
+        alpha: 0.25,
+        color: COLOR_DEBUG_PICK_PLANE,
+        solid: true,
+        visible: false,
+        ignorePickIntersection: true,
+        drawInFront: false
+    });
+    var debugPickPlaneHits = [];
+
+    // We get mouseMoveEvents from the handControllers, via handControllerPointer.
+    // But we dont' get mousePressEvents.
+    that.triggerClickMapping = Controller.newMapping(Script.resolvePath('') + '-click');
+    that.triggerPressMapping = Controller.newMapping(Script.resolvePath('') + '-press');
+    that.triggeredHand = NO_HAND;
+    that.pressedHand = NO_HAND;
+    that.editingHand = NO_HAND;
+    that.triggered = function() {
+        return that.triggeredHand !== NO_HAND;
+    };
+    function pointingAtDesktopWindowOrTablet(hand) {
+        var pointingAtDesktopWindow = (hand === Controller.Standard.RightHand && 
+                                       SelectionManager.pointingAtDesktopWindowRight) ||
+                                      (hand === Controller.Standard.LeftHand && 
+                                       SelectionManager.pointingAtDesktopWindowLeft);
+        var pointingAtTablet = (hand === Controller.Standard.RightHand && SelectionManager.pointingAtTabletRight) ||
+                               (hand === Controller.Standard.LeftHand && SelectionManager.pointingAtTabletLeft);
+        return pointingAtDesktopWindow || pointingAtTablet;
+    }
+    function makeClickHandler(hand) {
+        return function (clicked) {
+            // Don't allow both hands to trigger at the same time
+            if (that.triggered() && hand !== that.triggeredHand) {
+                return;
+            }
+            if (!that.triggered() && clicked && !pointingAtDesktopWindowOrTablet(hand)) {
+                that.triggeredHand = hand;
+                that.mousePressEvent({});
+            } else if (that.triggered() && !clicked) {
+                that.triggeredHand = NO_HAND;
+                that.mouseReleaseEvent({});
+            }
+        };
+    }
+    function makePressHandler(hand) {
+        return function (value) {
+            if (value >= TRIGGER_ON_VALUE && !that.triggered() && !pointingAtDesktopWindowOrTablet(hand)) {
+                that.pressedHand = hand;
+                that.updateHighlight({});
+            } else {
+                that.pressedHand = NO_HAND;
+                that.resetPreviousHandleColor();
+            }
+        }
+    }
+    that.triggerClickMapping.from(Controller.Standard.RTClick).peek().to(makeClickHandler(Controller.Standard.RightHand));
+    that.triggerClickMapping.from(Controller.Standard.LTClick).peek().to(makeClickHandler(Controller.Standard.LeftHand));
+    that.triggerPressMapping.from(Controller.Standard.RT).peek().to(makePressHandler(Controller.Standard.RightHand));
+    that.triggerPressMapping.from(Controller.Standard.LT).peek().to(makePressHandler(Controller.Standard.LeftHand));
+    that.enableTriggerMapping = function() {
+        that.triggerClickMapping.enable();
+        that.triggerPressMapping.enable();
+    };
+    that.disableTriggerMapping = function() {
+        that.triggerClickMapping.disable();
+        that.triggerPressMapping.disable();
+    };
+    Script.scriptEnding.connect(that.disableTriggerMapping);
+
+    // FUNCTION DEF(s): Intersection Check Helpers
+    function testRayIntersect(queryRay, overlayIncludes, overlayExcludes) {
+        var wantDebug = false;
+        if ((queryRay === undefined) || (queryRay === null)) {
+            if (wantDebug) {
+                print("testRayIntersect - EARLY EXIT -> queryRay is undefined OR null!");
+            }
+            return null;
+        }
+
+        // We want to first check the drawInFront overlays (i.e. the handles, but really everything except the selectionBoxes)
+        // so that you can click on them even when they're behind things
+        var overlayIncludesLayered = [];
+        var overlayIncludesNonLayered = [];
+        for (var i = 0; i < overlayIncludes.length; i++) {
+            var value = overlayIncludes[i];
+            var contains = false;
+            for (var j = 0; j < nonLayeredOverlays.length; j++) {
+                if (nonLayeredOverlays[j] === value) {
+                    contains = true;
+                    break;
+                }
+            }
+            if (contains) {
+                overlayIncludesNonLayered.push(value);
+            } else {
+                overlayIncludesLayered.push(value);
+            }
+        }
+
+        var intersectObj = Overlays.findRayIntersection(queryRay, true, overlayIncludesLayered, overlayExcludes);
+
+        if (!intersectObj.intersects && overlayIncludesNonLayered.length > 0) {
+            intersectObj = Overlays.findRayIntersection(queryRay, true, overlayIncludesNonLayered, overlayExcludes);
+        }
+
+        if (wantDebug) {
+            if (!overlayIncludes) {
+                print("testRayIntersect - no overlayIncludes provided.");
+            }
+            if (!overlayExcludes) {
+                print("testRayIntersect - no overlayExcludes provided.");
+            }
+            print("testRayIntersect - Hit: " + intersectObj.intersects);
+            print("    intersectObj.overlayID:" + intersectObj.overlayID + "[" + overlayNames[intersectObj.overlayID] + "]");
+            print("        OverlayName: " + overlayNames[intersectObj.overlayID]);
+            print("    intersectObj.distance:" + intersectObj.distance);
+            print("    intersectObj.face:" + intersectObj.face);
+            Vec3.print("    intersectObj.intersection:", intersectObj.intersection);
+        }
+
+        return intersectObj;
+    }
+
+    function isPointInsideBox(point, box) {
+        var position = Vec3.subtract(point, box.position);
+        position = Vec3.multiplyQbyV(Quat.inverse(box.rotation), position);
+        return Math.abs(position.x) <= box.dimensions.x / 2 && Math.abs(position.y) <= box.dimensions.y / 2
+            && Math.abs(position.z) <= box.dimensions.z / 2;
+    }
+    
+    that.isEditHandle = function(overlayID) {
+        var overlayIndex = allOverlays.indexOf(overlayID);
+        var maxHandleIndex = allOverlays.indexOf(maximumHandleInAllOverlays);
+        return overlayIndex >= 0 && overlayIndex <= maxHandleIndex;
+    };
+
+    // FUNCTION: MOUSE PRESS EVENT
+    that.mousePressEvent = function (event) {
+        var wantDebug = false;
+        if (wantDebug) {
+            print("=============== eST::MousePressEvent BEG =======================");
+        }
+        if (!event.isLeftButton && !that.triggered()) {
+            // EARLY EXIT-(if another mouse button than left is pressed ignore it)
+            return false;
+        }
+
+        var pickRay = generalComputePickRay(event.x, event.y);
+        // TODO_Case6491:  Move this out to setup just to make it once
+        var interactiveOverlays = getMainTabletIDs();
+        for (var key in handleTools) {
+            if (handleTools.hasOwnProperty(key)) {
+                interactiveOverlays.push(key);
+            }
+        }
+
+        // Start with unknown mode, in case no tool can handle this.
+        activeTool = null;
+
+        var results = testRayIntersect(pickRay, interactiveOverlays);
+        if (results.intersects) {
+            var hitOverlayID = results.overlayID;
+            if ((HMD.tabletID && hitOverlayID === HMD.tabletID) || (HMD.tabletScreenID && hitOverlayID === HMD.tabletScreenID)
+                || (HMD.homeButtonID && hitOverlayID === HMD.homeButtonID)) {
+                // EARLY EXIT-(mouse clicks on the tablet should override the edit affordances)
+                return false;
+            }
+
+            var hitTool = handleTools[ hitOverlayID ];
+            if (hitTool) {
+                activeTool = hitTool;
+                that.clearDebugPickPlane();
+                if (activeTool.onBegin) {
+                    that.editingHand = that.triggeredHand;
+                    Messages.sendLocalMessage(INEDIT_STATUS_CHANNEL, JSON.stringify({
+                        method: "editing",
+                        hand: that.editingHand === Controller.Standard.LeftHand ? LEFT_HAND : RIGHT_HAND,
+                        editing: true
+                    }));
+                    activeTool.onBegin(event, pickRay, results);
+                } else {
+                    print("ERROR: entitySelectionTool.mousePressEvent - ActiveTool(" + activeTool.mode + ") missing onBegin");
+                }
+            } else {
+                print("ERROR: entitySelectionTool.mousePressEvent - Hit unexpected object, check interactiveOverlays");
+            }// End_if (hitTool)
+        }// End_If(results.intersects)
+
+        if (wantDebug) {
+            print("    DisplayMode: " + getMode());
+            print("=============== eST::MousePressEvent END =======================");
+        }
+
+        // If mode is known then we successfully handled this;
+        // otherwise, we're missing a tool.
+        return activeTool;
+    };
+
+    that.resetPreviousHandleColor = function() {
+        if (previousHandle !== null) {
+            Overlays.editOverlay(previousHandle, { color: previousHandleColor });
+            previousHandle = null;
+        }
+        if (previousHandleHelper !== null) {
+            Overlays.editOverlay(previousHandleHelper, { color: previousHandleColor });
+            previousHandleHelper = null;
+        }
+    };
+
+    that.getHandleHelper = function(overlay) {
+        if (overlay === handleTranslateXCone) {
+            return handleTranslateXCylinder;
+        } else if (overlay === handleTranslateXCylinder) {
+            return handleTranslateXCone;
+        } else if (overlay === handleTranslateYCone) {
+            return handleTranslateYCylinder;
+        } else if (overlay === handleTranslateYCylinder) {
+            return handleTranslateYCone;
+        } else if (overlay === handleTranslateZCone) {
+            return handleTranslateZCylinder;
+        } else if (overlay === handleTranslateZCylinder) {
+            return handleTranslateZCone;
+        }
+        return Uuid.NULL;
+    };
+    
+    that.updateHighlight = function(event) {
+        // if no tool is active, then just look for handles to highlight...
+        var pickRay = generalComputePickRay(event.x, event.y);        
+        var result = testRayIntersect(pickRay, allOverlays);
+        var pickedColor;
+        var highlightNeeded = false;
+
+        if (result.intersects) {
+            switch (result.overlayID) {
+                case handleTranslateXCone:
+                case handleTranslateXCylinder:
+                case handleRotatePitchRing:
+                case handleStretchXCube:
+                    pickedColor = COLOR_RED;
+                    highlightNeeded = true;
+                    break;
+                case handleTranslateYCone:
+                case handleTranslateYCylinder:
+                case handleRotateYawRing:
+                case handleStretchYCube:
+                    pickedColor = COLOR_GREEN;
+                    highlightNeeded = true;
+                    break;
+                case handleTranslateZCone:
+                case handleTranslateZCylinder:
+                case handleRotateRollRing:
+                case handleStretchZCube:
+                    pickedColor = COLOR_BLUE;
+                    highlightNeeded = true;
+                    break;
+                case handleScaleCube:
+                    pickedColor = COLOR_SCALE_CUBE;
+                    highlightNeeded = true;
+                    break;
+                default:
+                    that.resetPreviousHandleColor();
+                    break;
+            }
+
+            if (highlightNeeded) {
+                that.resetPreviousHandleColor();
+                Overlays.editOverlay(result.overlayID, { color: COLOR_HOVER });
+                previousHandle = result.overlayID;
+                previousHandleHelper = that.getHandleHelper(result.overlayID);
+                if (previousHandleHelper !== null) {
+                    Overlays.editOverlay(previousHandleHelper, { color: COLOR_HOVER });
+                }
+                previousHandleColor = pickedColor;
+            }
+
+        } else {
+            that.resetPreviousHandleColor();
+        }
+    };
+
+    // FUNCTION: MOUSE MOVE EVENT
+    var lastMouseEvent = null;
+    that.mouseMoveEvent = function(event) {
+        var wantDebug = false;
+        if (wantDebug) {
+            print("=============== eST::MouseMoveEvent BEG =======================");
+        }
+        lastMouseEvent = event;
+        if (activeTool) {
+            if (wantDebug) {
+                print("    Trigger ActiveTool(" + activeTool.mode + ")'s onMove");
+            }
+            activeTool.onMove(event);
+
+            if (wantDebug) {
+                print("    Trigger SelectionManager::update");
+            }
+            SelectionManager._update(false, that);
+
+            if (wantDebug) {
+                print("=============== eST::MouseMoveEvent END =======================");
+            }
+            // EARLY EXIT--(Move handled via active tool)
+            return true;
+        }
+
+        that.updateHighlight(event);
+        
+        if (wantDebug) {
+            print("=============== eST::MouseMoveEvent END =======================");
+        }
+        return false;
+    };
+
+    // FUNCTION: MOUSE RELEASE EVENT
+    that.mouseReleaseEvent = function(event) {
+        var wantDebug = false;
+        if (wantDebug) {
+            print("=============== eST::MouseReleaseEvent BEG =======================");
+        }
+        var showHandles = false;
+        if (activeTool) {
+            if (activeTool.onEnd) {
+                if (wantDebug) {
+                    print("    Triggering ActiveTool(" + activeTool.mode + ")'s onEnd");
+                }
+                Messages.sendLocalMessage(INEDIT_STATUS_CHANNEL, JSON.stringify({
+                    method: "editing",
+                    hand: that.editingHand === Controller.Standard.LeftHand ? LEFT_HAND : RIGHT_HAND,
+                    editing: false
+                }));
+                that.editingHand = NO_HAND;
+                activeTool.onEnd(event);
+            } else if (wantDebug) {
+                print("    ActiveTool(" + activeTool.mode + ")'s missing onEnd");
+            }
+        }
+
+        showHandles = activeTool; // base on prior tool value
+        activeTool = null;
+
+        // if something is selected, then reset the "original" properties for any potential next click+move operation
+        if (SelectionManager.hasSelection()) {
+            if (showHandles) {
+                if (wantDebug) {
+                    print("    Triggering that.select");
+                }
+                that.select(SelectionManager.selections[0], event);
+            }
+        }
+
+        if (wantDebug) {
+            print("=============== eST::MouseReleaseEvent END =======================");
+        }
+    };
+
+    // Control key remains active only while key is held down
+    that.keyReleaseEvent = function(event) {
+        if (event.key === CTRL_KEY_CODE) {
+            ctrlPressed = false;
+            that.updateActiveRotateRing();
+        }
+        that.updateLastMouseEvent(event);
+    };
+
+    // Triggers notification on specific key driven events
+    that.keyPressEvent = function(event) {
+        if (event.key === CTRL_KEY_CODE) {
+            ctrlPressed = true;
+            that.updateActiveRotateRing();
+        }
+        that.updateLastMouseEvent(event);
+    };
+    
+    that.updateLastMouseEvent = function(event) {
+        if (activeTool && lastMouseEvent !== null) { 
+            var change = lastMouseEvent.isShifted !== event.isShifted || lastMouseEvent.isMeta !== event.isMeta ||
+                         lastMouseEvent.isControl !== event.isControl || lastMouseEvent.isAlt !== event.isAlt;
+            lastMouseEvent.isShifted = event.isShifted; 
+            lastMouseEvent.isMeta = event.isMeta;   
+            lastMouseEvent.isControl = event.isControl; 
+            lastMouseEvent.isAlt = event.isAlt;
+            if (change) {
+                activeTool.onMove(lastMouseEvent);
+            }           
+        }
+    };
+
+    // NOTE: mousePressEvent and mouseMoveEvent from the main script should call us., so we don't hook these:
+    //       Controller.mousePressEvent.connect(that.mousePressEvent);
+    //       Controller.mouseMoveEvent.connect(that.mouseMoveEvent);
+    Controller.mouseReleaseEvent.connect(that.mouseReleaseEvent);
+    Controller.keyPressEvent.connect(that.keyPressEvent);
+    Controller.keyReleaseEvent.connect(that.keyReleaseEvent);
+
+    that.checkControllerMove = function() {
+        if (SelectionManager.hasSelection()) {
+            var controllerPose = getControllerWorldLocation(that.triggeredHand, true);
+            var hand = (that.triggeredHand === Controller.Standard.LeftHand) ? 0 : 1;
+            if (controllerPose.valid && lastControllerPoses[hand].valid && that.triggered()) {
+                if (!Vec3.equal(controllerPose.position, lastControllerPoses[hand].position) ||
+                    !Vec3.equal(controllerPose.rotation, lastControllerPoses[hand].rotation)) {
+                    that.mouseMoveEvent({});
+                }
+            }
+            lastControllerPoses[hand] = controllerPose;
+        }
+    };
+
+    function controllerComputePickRay() {
+        var hand = that.triggered() ? that.triggeredHand : that.pressedHand;
+        var controllerPose = getControllerWorldLocation(hand, true);
+        if (controllerPose.valid) {
+            var controllerPosition = controllerPose.translation;
+            // This gets point direction right, but if you want general quaternion it would be more complicated:
+            var controllerDirection = Quat.getUp(controllerPose.rotation);
+            return {origin: controllerPosition, direction: controllerDirection};
+        }
+    }
+
+    function generalComputePickRay(x, y) {
+        return controllerComputePickRay() || Camera.computePickRay(x, y);
+    }
+    
+    function getControllerAvatarFramePositionFromPickRay(pickRay) {
+        var controllerPosition = Vec3.subtract(pickRay.origin, MyAvatar.position);
+        controllerPosition = Vec3.multiplyQbyV(Quat.inverse(MyAvatar.orientation), controllerPosition);
+        return controllerPosition;
+    }
+
+    function getDistanceToCamera(position) {
+        var cameraPosition = Camera.getPosition();
+        var toCameraDistance = Vec3.length(Vec3.subtract(cameraPosition, position));
+        return toCameraDistance;
+    }
+    
+    function usePreviousPickRay(pickRayDirection, previousPickRayDirection, normal) {
+        return (Vec3.dot(pickRayDirection, normal) > 0 && Vec3.dot(previousPickRayDirection, normal) < 0) ||
+               (Vec3.dot(pickRayDirection, normal) < 0 && Vec3.dot(previousPickRayDirection, normal) > 0);
+    }
+
+    // @return string - The mode of the currently active tool;
+    //                  otherwise, "UNKNOWN" if there's no active tool.
+    function getMode() {
+        return (activeTool ? activeTool.mode : "UNKNOWN");
+    }
+
+    that.cleanup = function() {
+        for (var i = 0; i < allOverlays.length; i++) {
+            Overlays.deleteOverlay(allOverlays[i]);
+        }
+        that.clearDebugPickPlane();
+    };
+
+    that.select = function(entityID, event) {
+        var properties = Entities.getEntityProperties(SelectionManager.selections[0]);
+
+        if (event !== false) {
+            var wantDebug = false;
+            if (wantDebug) {
+                print("select() with EVENT...... ");
+                print("                event.y:" + event.y);
+                Vec3.print("       current position:", properties.position);
+            }
+        }
+
+        that.updateHandles();
+    };
+
+
+    /**
+     * This callback is used for spaceMode changes.
+     * @callback spaceModeChangedCallback
+     * @param {string} spaceMode
+     */
+
+    /**
+     * set this property with a callback to keep track of spaceMode changes.
+     * @type {spaceModeChangedCallback}
+     */
+    that.onSpaceModeChange = null;
+
+    // FUNCTION: SET SPACE MODE
+    that.setSpaceMode = function(newSpaceMode, isDesiredChange) {
+        var wantDebug = false;
+        if (wantDebug) {
+            print("======> SetSpaceMode called. ========");
+        }
+
+        if (spaceMode !== newSpaceMode) {
+            if (wantDebug) {
+                print("    Updating SpaceMode From: " + spaceMode + " To: " + newSpaceMode);
+            }
+            if (isDesiredChange) {
+                desiredSpaceMode = newSpaceMode;
+            }
+            spaceMode = newSpaceMode;
+
+            if (that.onSpaceModeChange !== null) {
+                that.onSpaceModeChange(newSpaceMode);
+            }
+
+            that.updateHandles();
+        } else if (wantDebug) {
+            print("WARNING: entitySelectionTool.setSpaceMode - Can't update SpaceMode. CurrentMode: " + 
+                  spaceMode + " DesiredMode: " + newSpaceMode);
+        }
+        if (wantDebug) {
+            print("====== SetSpaceMode called. <========");
+        }
+    };
+
+    // FUNCTION: TOGGLE SPACE MODE
+    that.toggleSpaceMode = function() {
+        var wantDebug = false;
+        if (wantDebug) {
+            print("========> ToggleSpaceMode called. =========");
+        }
+        if ((spaceMode === SPACE_WORLD) && (SelectionManager.selections.length > 1)) {
+            if (wantDebug) {
+                print("Local space editing is not available with multiple selections");
+            }
+            return;
+        }
+        if (wantDebug) {
+            print("PreToggle: " + spaceMode);
+        }
+        that.setSpaceMode((spaceMode === SPACE_LOCAL) ? SPACE_WORLD : SPACE_LOCAL, true);
+        if (wantDebug) {
+            print("PostToggle: " + spaceMode);        
+            print("======== ToggleSpaceMode called. <=========");
+        }
+    };
+
+    /**
+     * Switches the display mode back to the set desired display mode
+     */
+    that.useDesiredSpaceMode = function() {
+        var wantDebug = false;
+        if (wantDebug) {
+            print("========> UseDesiredSpaceMode called. =========");
+        }
+        that.setSpaceMode(desiredSpaceMode, false);
+        if (wantDebug) {
+            print("PostToggle: " + spaceMode);
+            print("======== UseDesiredSpaceMode called. <=========");
+        }
+    };
+
+    /**
+     * Get the currently set SpaceMode
+     * @returns {string} spaceMode
+     */
+    that.getSpaceMode = function() {
+        return spaceMode;
+    };
+
+    function addHandleTool(overlay, tool) {
+        handleTools[overlay] = tool;
+        return tool;
+    }
+
+    // @param: toolHandle:  The overlayID associated with the tool
+    //         that correlates to the tool you wish to query.
+    // @note: If toolHandle is null or undefined then activeTool
+    //        will be checked against those values as opposed to
+    //        the tool registered under toolHandle.  Null & Undefined 
+    //        are treated as separate values.
+    // @return: bool - Indicates if the activeTool is that queried.
+    function isActiveTool(toolHandle) {
+        if (!toolHandle) {
+            // Allow isActiveTool(null) and similar to return true if there's
+            // no active tool
+            return (activeTool === toolHandle);
+        }
+
+        if (!handleTools.hasOwnProperty(toolHandle)) {
+            print("WARNING: entitySelectionTool.isActiveTool - Encountered unknown grabberToolHandle: " + 
+                  toolHandle + ". Tools should be registered via addHandleTool.");
+            // EARLY EXIT
+            return false;
+        }
+
+        return (activeTool === handleTools[ toolHandle ]);
+    }
+
+    // FUNCTION: UPDATE HANDLES
+    that.updateHandles = function() {
+        var wantDebug = false;
+        if (wantDebug) {
+            print("======> Update Handles =======");
+            print("    Selections Count: " + SelectionManager.selections.length);
+            print("    SpaceMode: " + spaceMode);
+            print("    DisplayMode: " + getMode());
+        }
+        
+        if (SelectionManager.selections.length === 0) {
+            that.setOverlaysVisible(false);
+            that.clearDebugPickPlane();
+            return;
+        }
+
+        if (SelectionManager.hasSelection()) {
+            var position = SelectionManager.worldPosition;
+            var rotation = spaceMode === SPACE_LOCAL ? SelectionManager.localRotation : SelectionManager.worldRotation;
+            var dimensions = spaceMode === SPACE_LOCAL ? SelectionManager.localDimensions : SelectionManager.worldDimensions;
+            var rotationInverse = Quat.inverse(rotation);
+            var toCameraDistance = getDistanceToCamera(position);
+
+            var rotationDegrees = 90;
+            var localRotationX = Quat.fromPitchYawRollDegrees(0, 0, -rotationDegrees);
+            var rotationX = Quat.multiply(rotation, localRotationX);
+            worldRotationX = rotationX;
+            var localRotationY = Quat.fromPitchYawRollDegrees(0, rotationDegrees, 0);
+            var rotationY = Quat.multiply(rotation, localRotationY);
+            worldRotationY = rotationY;
+            var localRotationZ = Quat.fromPitchYawRollDegrees(rotationDegrees, 0, 0);
+            var rotationZ = Quat.multiply(rotation, localRotationZ);
+            worldRotationZ = rotationZ;
+            
+            var selectionBoxGeometry = {
+                position: position,
+                rotation: rotation,
+                dimensions: dimensions
+            };
+            var isCameraInsideBox = isPointInsideBox(Camera.position, selectionBoxGeometry);
+            
+            // in HMD if outside the bounding box clamp the overlays to the bounding box for now so lasers can hit them
+            var maxHandleDimension = 0;
+            if (HMD.active && !isCameraInsideBox) {
+                maxHandleDimension = Math.max(dimensions.x, dimensions.y, dimensions.z);
+            }
+
+            // UPDATE ROTATION RINGS
+            // rotateDimension is used as the base dimension for all overlays
+            var rotateDimension = Math.max(maxHandleDimension, toCameraDistance * ROTATE_RING_CAMERA_DISTANCE_MULTIPLE);
+            var rotateDimensions = { x: rotateDimension, y: rotateDimension, z: rotateDimension };
+            if (!isActiveTool(handleRotatePitchRing)) {
+                Overlays.editOverlay(handleRotatePitchRing, { 
+                    position: position, 
+                    rotation: rotationY,
+                    dimensions: rotateDimensions,
+                    majorTickMarksAngle: ROTATE_DEFAULT_TICK_MARKS_ANGLE
+                });
+            }
+            if (!isActiveTool(handleRotateYawRing)) {
+                Overlays.editOverlay(handleRotateYawRing, { 
+                    position: position, 
+                    rotation: rotationZ,
+                    dimensions: rotateDimensions,
+                    majorTickMarksAngle: ROTATE_DEFAULT_TICK_MARKS_ANGLE
+                });
+            }
+            if (!isActiveTool(handleRotateRollRing)) {
+                Overlays.editOverlay(handleRotateRollRing, { 
+                    position: position, 
+                    rotation: rotationX,
+                    dimensions: rotateDimensions,
+                    majorTickMarksAngle: ROTATE_DEFAULT_TICK_MARKS_ANGLE
+                });
+            }
+            Overlays.editOverlay(handleRotateCurrentRing, { dimensions: rotateDimensions });
+            that.updateActiveRotateRing();
+
+            // UPDATE TRANSLATION ARROWS
+            var arrowCylinderDimension = rotateDimension * TRANSLATE_ARROW_CYLINDER_CAMERA_DISTANCE_MULTIPLE / 
+                                                           ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
+            var arrowCylinderDimensions = { 
+                x: arrowCylinderDimension, 
+                y: arrowCylinderDimension * TRANSLATE_ARROW_CYLINDER_Y_MULTIPLE, 
+                z: arrowCylinderDimension 
+            };
+            var arrowConeDimension = rotateDimension * TRANSLATE_ARROW_CONE_CAMERA_DISTANCE_MULTIPLE / 
+                                                       ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
+            var arrowConeDimensions = { x: arrowConeDimension, y: arrowConeDimension, z: arrowConeDimension };
+            var arrowCylinderOffset = rotateDimension * TRANSLATE_ARROW_CYLINDER_OFFSET / ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
+            var arrowConeOffset = arrowCylinderDimensions.y * TRANSLATE_ARROW_CONE_OFFSET_CYLINDER_DIMENSION_MULTIPLE;
+            var cylinderXPosition = { x: arrowCylinderOffset, y: 0, z: 0 };
+            cylinderXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderXPosition));
+            Overlays.editOverlay(handleTranslateXCylinder, { 
+                position: cylinderXPosition, 
+                rotation: rotationX,
+                dimensions: arrowCylinderDimensions
+            });
+            var cylinderXOffset = Vec3.subtract(cylinderXPosition, position);
+            var coneXPosition = Vec3.sum(cylinderXPosition, Vec3.multiply(Vec3.normalize(cylinderXOffset), arrowConeOffset));
+            Overlays.editOverlay(handleTranslateXCone, { 
+                position: coneXPosition, 
+                rotation: rotationX,
+                dimensions: arrowConeDimensions
+            });
+            var cylinderYPosition = { x: 0, y: arrowCylinderOffset, z: 0 };
+            cylinderYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderYPosition));
+            Overlays.editOverlay(handleTranslateYCylinder, { 
+                position: cylinderYPosition, 
+                rotation: rotationY,
+                dimensions: arrowCylinderDimensions
+            });
+            var cylinderYOffset = Vec3.subtract(cylinderYPosition, position);
+            var coneYPosition = Vec3.sum(cylinderYPosition, Vec3.multiply(Vec3.normalize(cylinderYOffset), arrowConeOffset));
+            Overlays.editOverlay(handleTranslateYCone, { 
+                position: coneYPosition, 
+                rotation: rotationY,
+                dimensions: arrowConeDimensions
+            });
+            var cylinderZPosition = { x: 0, y: 0, z: arrowCylinderOffset };
+            cylinderZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, cylinderZPosition));
+            Overlays.editOverlay(handleTranslateZCylinder, { 
+                position: cylinderZPosition, 
+                rotation: rotationZ,
+                dimensions: arrowCylinderDimensions
+            });
+            var cylinderZOffset = Vec3.subtract(cylinderZPosition, position);
+            var coneZPosition = Vec3.sum(cylinderZPosition, Vec3.multiply(Vec3.normalize(cylinderZOffset), arrowConeOffset));
+            Overlays.editOverlay(handleTranslateZCone, { 
+                position: coneZPosition, 
+                rotation: rotationZ,
+                dimensions: arrowConeDimensions
+            });
+
+            // UPDATE SCALE CUBE
+            var scaleCubeRotation = spaceMode === SPACE_LOCAL ? rotation : Quat.IDENTITY;            
+            var scaleCubeDimension = rotateDimension * SCALE_OVERLAY_CAMERA_DISTANCE_MULTIPLE / 
+                                                       ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
+            var scaleCubeDimensions = { x: scaleCubeDimension, y: scaleCubeDimension, z: scaleCubeDimension };
+            Overlays.editOverlay(handleScaleCube, { 
+                position: position, 
+                rotation: scaleCubeRotation,
+                dimensions: scaleCubeDimensions
+            });
+
+            // UPDATE BOUNDING BOX
+            Overlays.editOverlay(handleBoundingBox, {
+                position: position,
+                rotation: rotation,
+                dimensions: dimensions
+            });
+
+            // UPDATE STRETCH HIGHLIGHT PANELS
+            var edgeOffsetX = BOUNDING_EDGE_OFFSET * dimensions.x;
+            var edgeOffsetY = BOUNDING_EDGE_OFFSET * dimensions.y;
+            var edgeOffsetZ = BOUNDING_EDGE_OFFSET * dimensions.z;
+            var RBFPosition = { x: edgeOffsetX, y: -edgeOffsetY, z: edgeOffsetZ };
+            RBFPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RBFPosition));
+            var RTFPosition = { x: edgeOffsetX, y: edgeOffsetY, z: edgeOffsetZ };
+            RTFPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RTFPosition));
+            var LTNPosition = { x: -edgeOffsetX, y: edgeOffsetY, z: -edgeOffsetZ };
+            LTNPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, LTNPosition));
+            var RTNPosition = { x: edgeOffsetX, y: edgeOffsetY, z: -edgeOffsetZ };
+            RTNPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RTNPosition));
+
+            var RBFPositionRotated = Vec3.multiplyQbyV(rotationInverse, RBFPosition);
+            var RTFPositionRotated = Vec3.multiplyQbyV(rotationInverse, RTFPosition);
+            var LTNPositionRotated = Vec3.multiplyQbyV(rotationInverse, LTNPosition);
+            var RTNPositionRotated = Vec3.multiplyQbyV(rotationInverse, RTNPosition);
+            var stretchPanelXDimensions = Vec3.subtract(RTNPositionRotated, RBFPositionRotated);
+            var tempY = Math.abs(stretchPanelXDimensions.y);
+            stretchPanelXDimensions.x = STRETCH_PANEL_WIDTH;
+            stretchPanelXDimensions.y = Math.abs(stretchPanelXDimensions.z);
+            stretchPanelXDimensions.z = tempY;
+            var stretchPanelXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x: dimensions.x / 2, y: 0, z: 0 }));
+            Overlays.editOverlay(handleStretchXPanel, { 
+                position: stretchPanelXPosition, 
+                rotation: rotationZ,
+                dimensions: stretchPanelXDimensions
+            });
+            var stretchPanelYDimensions = Vec3.subtract(LTNPositionRotated, RTFPositionRotated);
+            var tempX = Math.abs(stretchPanelYDimensions.x);
+            stretchPanelYDimensions.x = Math.abs(stretchPanelYDimensions.z);
+            stretchPanelYDimensions.y = STRETCH_PANEL_WIDTH;
+            stretchPanelYDimensions.z = tempX;
+            var stretchPanelYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x: 0, y: dimensions.y / 2, z: 0 }));
+            Overlays.editOverlay(handleStretchYPanel, { 
+                position: stretchPanelYPosition, 
+                rotation: rotationY,
+                dimensions: stretchPanelYDimensions
+            });
+            var stretchPanelZDimensions = Vec3.subtract(LTNPositionRotated, RBFPositionRotated);
+            tempX = Math.abs(stretchPanelZDimensions.x);
+            stretchPanelZDimensions.x = Math.abs(stretchPanelZDimensions.y);
+            stretchPanelZDimensions.y = tempX;
+            stretchPanelZDimensions.z = STRETCH_PANEL_WIDTH;
+            var stretchPanelZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, { x: 0, y: 0, z: dimensions.z / 2 }));
+            Overlays.editOverlay(handleStretchZPanel, { 
+                position: stretchPanelZPosition, 
+                rotation: rotationX,
+                dimensions: stretchPanelZDimensions
+            });
+
+            // UPDATE STRETCH CUBES
+            var stretchCubeDimension = rotateDimension * STRETCH_CUBE_CAMERA_DISTANCE_MULTIPLE / 
+                                                           ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
+            var stretchCubeDimensions = { x: stretchCubeDimension, y: stretchCubeDimension, z: stretchCubeDimension };
+            var stretchCubeOffset = rotateDimension * STRETCH_CUBE_OFFSET / ROTATE_RING_CAMERA_DISTANCE_MULTIPLE;
+            var stretchXPosition, stretchYPosition, stretchZPosition;
+            if (isActiveTool(handleStretchXCube)) {
+                stretchXPosition = Vec3.subtract(stretchPanelXPosition, activeStretchCubePanelOffset);
+            } else {
+                stretchXPosition = { x: stretchCubeOffset, y: 0, z: 0 };
+                stretchXPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchXPosition));
+            }
+            if (isActiveTool(handleStretchYCube)) {
+                stretchYPosition = Vec3.subtract(stretchPanelYPosition, activeStretchCubePanelOffset);
+            } else {
+                stretchYPosition = { x: 0, y: stretchCubeOffset, z: 0 };
+                stretchYPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchYPosition));
+            }
+            if (isActiveTool(handleStretchZCube)) {
+                stretchZPosition = Vec3.subtract(stretchPanelZPosition, activeStretchCubePanelOffset);
+            } else {
+                stretchZPosition = { x: 0, y: 0, z: stretchCubeOffset };
+                stretchZPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, stretchZPosition));
+            }
+            Overlays.editOverlay(handleStretchXCube, { 
+                position: stretchXPosition, 
+                rotation: rotationX,
+                dimensions: stretchCubeDimensions 
+            });
+            Overlays.editOverlay(handleStretchYCube, { 
+                position: stretchYPosition, 
+                rotation: rotationY,
+                dimensions: stretchCubeDimensions 
+            });
+            Overlays.editOverlay(handleStretchZCube, { 
+                position: stretchZPosition,
+                rotation: rotationZ,
+                dimensions: stretchCubeDimensions 
+            });
+
+            // UPDATE SELECTION BOX (CURRENTLY INVISIBLE WITH 0 ALPHA FOR TRANSLATE XZ TOOL)
+            var inModeRotate = isActiveTool(handleRotatePitchRing) || 
+                               isActiveTool(handleRotateYawRing) || 
+                               isActiveTool(handleRotateRollRing);
+            selectionBoxGeometry.visible = !inModeRotate && !isCameraInsideBox;
+            selectionBoxGeometry.ignorePickIntersection = !selectionBoxGeometry.visible;
+            Overlays.editOverlay(selectionBox, selectionBoxGeometry);
+
+            // UPDATE ICON TRANSLATE HANDLE
+            if (SelectionManager.entityType === "ParticleEffect" || SelectionManager.entityType === "Light") {
+                var iconSelectionBoxGeometry = {
+                    position: position,
+                    rotation: rotation
+                };
+                iconSelectionBoxGeometry.visible = !inModeRotate && isCameraInsideBox;
+                iconSelectionBoxGeometry.ignorePickIntersection = !iconSelectionBoxGeometry.visible;
+                Overlays.editOverlay(iconSelectionBox, iconSelectionBoxGeometry);
+            } else {
+                Overlays.editOverlay(iconSelectionBox, {
+                    visible: false,
+                    ignorePickIntersection: true
+                });
+            }
+
+            // UPDATE DUPLICATOR (CURRENTLY HIDDEN FOR NOW)
+            var handleDuplicatorOffset = { 
+                x: DUPLICATOR_OFFSET.x * dimensions.x, 
+                y: DUPLICATOR_OFFSET.y * dimensions.y, 
+                z: DUPLICATOR_OFFSET.z * dimensions.z 
+            };
+            var handleDuplicatorPos = Vec3.sum(position, Vec3.multiplyQbyV(rotation, handleDuplicatorOffset));
+            Overlays.editOverlay(handleDuplicator, {
+                position: handleDuplicatorPos,
+                rotation: rotation,
+                dimensions: scaleCubeDimensions
+            });
+        }
+
+        that.setHandleTranslateXVisible(!activeTool || isActiveTool(handleTranslateXCone) || 
+                                                       isActiveTool(handleTranslateXCylinder));
+        that.setHandleTranslateYVisible(!activeTool || isActiveTool(handleTranslateYCone) || 
+                                                       isActiveTool(handleTranslateYCylinder));
+        that.setHandleTranslateZVisible(!activeTool || isActiveTool(handleTranslateZCone) || 
+                                                       isActiveTool(handleTranslateZCylinder));
+        that.setHandleRotatePitchVisible(!activeTool || isActiveTool(handleRotatePitchRing));
+        that.setHandleRotateYawVisible(!activeTool || isActiveTool(handleRotateYawRing));
+        that.setHandleRotateRollVisible(!activeTool || isActiveTool(handleRotateRollRing));
+
+        var showScaleStretch = !activeTool && SelectionManager.selections.length === 1 && spaceMode === SPACE_LOCAL;
+        that.setHandleStretchXVisible(showScaleStretch || isActiveTool(handleStretchXCube));
+        that.setHandleStretchYVisible(showScaleStretch || isActiveTool(handleStretchYCube));
+        that.setHandleStretchZVisible(showScaleStretch || isActiveTool(handleStretchZCube));
+        that.setHandleScaleVisible(showScaleStretch || isActiveTool(handleScaleCube));
+
+        var showOutlineForZone = (SelectionManager.selections.length === 1 && 
+                                    typeof SelectionManager.savedProperties[SelectionManager.selections[0]] !== "undefined" &&
+                                    SelectionManager.savedProperties[SelectionManager.selections[0]].type === "Zone");
+        that.setHandleBoundingBoxVisible(showOutlineForZone || (!isActiveTool(handleRotatePitchRing) &&
+                                                              !isActiveTool(handleRotateYawRing) &&
+                                                              !isActiveTool(handleRotateRollRing)));
+
+        // keep duplicator always hidden for now since you can hold Alt to duplicate while
+        // translating an entity - we may bring duplicator back for HMD only later
+        // that.setHandleDuplicatorVisible(!activeTool || isActiveTool(handleDuplicator));
+
+        if (wantDebug) {
+            print("====== Update Handles <=======");
+        }
+    };
+    Script.update.connect(that.updateHandles);
+
+    // FUNCTION: UPDATE ACTIVE ROTATE RING
+    that.updateActiveRotateRing = function() {
+        var activeRotateRing = null;
+        if (isActiveTool(handleRotatePitchRing)) {
+            activeRotateRing = handleRotatePitchRing;
+        } else if (isActiveTool(handleRotateYawRing)) {
+            activeRotateRing = handleRotateYawRing;
+        } else if (isActiveTool(handleRotateRollRing)) {
+            activeRotateRing = handleRotateRollRing;
+        }
+        if (activeRotateRing !== null) {
+            var tickMarksAngle = ctrlPressed ? ROTATE_CTRL_SNAP_ANGLE : ROTATE_DEFAULT_TICK_MARKS_ANGLE;
+            Overlays.editOverlay(activeRotateRing, { majorTickMarksAngle: tickMarksAngle });
+        }
+    };
+
+    // FUNCTION: SET OVERLAYS VISIBLE
+    that.setOverlaysVisible = function(isVisible) {
+        for (var i = 0, length = allOverlays.length; i < length; i++) {
+            Overlays.editOverlay(allOverlays[i], { visible: isVisible, ignorePickIntersection: !isVisible });
+        }
+    };
+
+    // FUNCTION: SET HANDLE TRANSLATE VISIBLE
+    that.setHandleTranslateVisible = function(isVisible) {
+        that.setHandleTranslateXVisible(isVisible);
+        that.setHandleTranslateYVisible(isVisible);
+        that.setHandleTranslateZVisible(isVisible);
+    };
+
+    that.setHandleTranslateXVisible = function(isVisible) {
+        Overlays.editOverlay(handleTranslateXCone, { visible: isVisible, ignorePickIntersection: !isVisible });
+        Overlays.editOverlay(handleTranslateXCylinder, { visible: isVisible, ignorePickIntersection: !isVisible });
+    };
+
+    that.setHandleTranslateYVisible = function(isVisible) {
+        Overlays.editOverlay(handleTranslateYCone, { visible: isVisible, ignorePickIntersection: !isVisible });
+        Overlays.editOverlay(handleTranslateYCylinder, { visible: isVisible, ignorePickIntersection: !isVisible });
+    };
+
+    that.setHandleTranslateZVisible = function(isVisible) {
+        Overlays.editOverlay(handleTranslateZCone, { visible: isVisible, ignorePickIntersection: !isVisible });
+        Overlays.editOverlay(handleTranslateZCylinder, { visible: isVisible, ignorePickIntersection: !isVisible });
+    };
+
+    // FUNCTION: SET HANDLE ROTATE VISIBLE
+    that.setHandleRotateVisible = function(isVisible) {
+        that.setHandleRotatePitchVisible(isVisible);
+        that.setHandleRotateYawVisible(isVisible);
+        that.setHandleRotateRollVisible(isVisible);
+    };
+
+    that.setHandleRotatePitchVisible = function(isVisible) {
+        Overlays.editOverlay(handleRotatePitchRing, { visible: isVisible, ignorePickIntersection: !isVisible });
+    };
+
+    that.setHandleRotateYawVisible = function(isVisible) {
+        Overlays.editOverlay(handleRotateYawRing, { visible: isVisible, ignorePickIntersection: !isVisible });
+    };
+
+    that.setHandleRotateRollVisible = function(isVisible) {
+        Overlays.editOverlay(handleRotateRollRing, { visible: isVisible, ignorePickIntersection: !isVisible });
+    };
+
+    // FUNCTION: SET HANDLE STRETCH VISIBLE
+    that.setHandleStretchVisible = function(isVisible) {
+        that.setHandleStretchXVisible(isVisible);
+        that.setHandleStretchYVisible(isVisible);
+        that.setHandleStretchZVisible(isVisible);
+    };
+
+    that.setHandleStretchXVisible = function(isVisible) {
+        Overlays.editOverlay(handleStretchXCube, { visible: isVisible, ignorePickIntersection: !isVisible });
+    };
+
+    that.setHandleStretchYVisible = function(isVisible) {
+        Overlays.editOverlay(handleStretchYCube, { visible: isVisible, ignorePickIntersection: !isVisible });
+    };
+
+    that.setHandleStretchZVisible = function(isVisible) {
+        Overlays.editOverlay(handleStretchZCube, { visible: isVisible, ignorePickIntersection: !isVisible });
+    };
+    
+    // FUNCTION: SET HANDLE SCALE VISIBLE
+    that.setHandleScaleVisible = function(isVisible) {
+        that.setHandleScaleVisible(isVisible);
+        that.setHandleBoundingBoxVisible(isVisible);
+    };
+
+    that.setHandleScaleVisible = function(isVisible) {
+        Overlays.editOverlay(handleScaleCube, { visible: isVisible, ignorePickIntersection: !isVisible });
+    };
+
+    that.setHandleBoundingBoxVisible = function(isVisible) {
+        Overlays.editOverlay(handleBoundingBox, { visible: isVisible, ignorePickIntersection: true });
+    };
+
+    // FUNCTION: SET HANDLE DUPLICATOR VISIBLE
+    that.setHandleDuplicatorVisible = function(isVisible) {
+        Overlays.editOverlay(handleDuplicator, { visible: isVisible, ignorePickIntersection: !isVisible });
+    };
+
+    // FUNCTION: DEBUG PICK PLANE
+    that.showDebugPickPlane = function(pickPlanePosition, pickPlaneNormal) {
+        var planePlusNormal = Vec3.sum(pickPlanePosition, pickPlaneNormal);
+        var rotation = Quat.lookAtSimple(planePlusNormal, pickPlanePosition);
+        var dimensionXZ = getDistanceToCamera(pickPlanePosition) * 1.25;   
+        var dimensions = { x:dimensionXZ, y:dimensionXZ, z:STRETCH_PANEL_WIDTH };
+        Overlays.editOverlay(debugPickPlane, {
+            position: pickPlanePosition,
+            rotation: rotation,
+            dimensions: dimensions,
+            visible: true
+        });
+    };
+    
+    that.showDebugPickPlaneHit = function(pickHitPosition) {
+        var dimension = getDistanceToCamera(pickHitPosition) * DEBUG_PICK_PLANE_HIT_CAMERA_DISTANCE_MULTIPLE;
+        var pickPlaneHit = Overlays.addOverlay("shape", {
+            alpha: 0.5,
+            shape: "Sphere",
+            solid: true,
+            visible: true,
+            ignorePickIntersection: true,
+            drawInFront: false,
+            color: COLOR_DEBUG_PICK_PLANE_HIT,
+            position: pickHitPosition,
+            dimensions: { x: dimension, y: dimension, z: dimension }
+        });
+        debugPickPlaneHits.push(pickPlaneHit);
+        if (debugPickPlaneHits.length > DEBUG_PICK_PLANE_HIT_LIMIT) {
+            var removedPickPlaneHit = debugPickPlaneHits.shift();
+            Overlays.deleteOverlay(removedPickPlaneHit);
+        }
+    };
+    
+    that.clearDebugPickPlane = function() {
+        Overlays.editOverlay(debugPickPlane, { visible: false });
+        for (var i = 0; i < debugPickPlaneHits.length; i++) {
+            Overlays.deleteOverlay(debugPickPlaneHits[i]);
+        }
+        debugPickPlaneHits = [];
+    };
+    
+    // TOOL DEFINITION: HANDLE TRANSLATE XZ TOOL
+    function addHandleTranslateXZTool(overlay, mode, doDuplicate) {
+        var initialPick = null;
+        var isConstrained = false;
+        var constrainMajorOnly = false;
+        var startPosition = null;
+        var duplicatedEntityIDs = null;
+        var pickPlanePosition = null;
+        var pickPlaneNormal = { x: 0, y: 1, z: 0 };
+        var greatestDimension = 0.0;
+        var startingDistance = 0.0;
+        var startingElevation = 0.0;
+        addHandleTool(overlay, {
+            mode: mode,
+            onBegin: function(event, pickRay, pickResult) {
+                var wantDebug = false;
+                if (wantDebug) {
+                    print("================== TRANSLATE_XZ(Beg) -> =======================");
+                    Vec3.print("    pickRay", pickRay);
+                    Vec3.print("    pickRay.origin", pickRay.origin);
+                    Vec3.print("    pickResult.intersection", pickResult.intersection);
+                }
+
+                // Duplicate entities if alt is pressed.  This will make a
+                // copy of the selected entities and move the _original_ entities, not
+                // the new ones.
+                if (event.isAlt || doDuplicate) {
+                    duplicatedEntityIDs = SelectionManager.duplicateSelection();
+                    var ids = [];
+                    for (var i = 0; i < duplicatedEntityIDs.length; ++i) {
+                        ids.push(duplicatedEntityIDs[i].entityID);
+                    }
+                    SelectionManager.setSelections(ids);
+                } else {
+                    duplicatedEntityIDs = null;
+                }
+
+                SelectionManager.saveProperties();
+                that.resetPreviousHandleColor();
+
+                that.setHandleTranslateVisible(false);
+                that.setHandleRotateVisible(false);
+                that.setHandleScaleVisible(false);
+                that.setHandleStretchVisible(false);
+                that.setHandleDuplicatorVisible(false);
+
+                startPosition = SelectionManager.worldPosition;
+                pickPlanePosition = pickResult.intersection;
+                greatestDimension = Math.max(Math.max(SelectionManager.worldDimensions.x, 
+                                                      SelectionManager.worldDimensions.y),
+                                                      SelectionManager.worldDimensions.z);
+                startingDistance = Vec3.distance(pickRay.origin, SelectionManager.position);
+                startingElevation = this.elevation(pickRay.origin, pickPlanePosition);
+                if (wantDebug) {
+                    print("    longest dimension: " + greatestDimension);
+                    print("    starting distance: " + startingDistance);
+                    print("    starting elevation: " + startingElevation);
+                }
+
+                initialPick = rayPlaneIntersection(pickRay, pickPlanePosition, pickPlaneNormal);
+                
+                if (debugPickPlaneEnabled) {
+                    that.showDebugPickPlane(pickPlanePosition, pickPlaneNormal);
+                    that.showDebugPickPlaneHit(initialPick);
+                }
+
+                isConstrained = false;
+                if (wantDebug) {
+                    print("================== TRANSLATE_XZ(End) <- =======================");
+                }
+            },
+            onEnd: function(event, reason) {
+                pushCommandForSelections(duplicatedEntityIDs);
+                if (isConstrained) {
+                    Overlays.editOverlay(xRailOverlay, {
+                        visible: false,
+                        ignorePickIntersection: true
+                    });
+                    Overlays.editOverlay(zRailOverlay, {
+                        visible: false,
+                        ignorePickIntersection: true
+                    });
+                }
+            },
+            elevation: function(origin, intersection) {
+                return (origin.y - intersection.y) / Vec3.distance(origin, intersection);
+            },
+            onMove: function(event) {
+                var wantDebug = false;
+                var pickRay = generalComputePickRay(event.x, event.y);
+
+                var newPick = rayPlaneIntersection2(pickRay, pickPlanePosition, pickPlaneNormal);
+
+                // If the pick ray doesn't hit the pick plane in this direction, do nothing.
+                // this will happen when someone drags across the horizon from the side they started on.
+                if (!newPick) {
+                    if (wantDebug) {
+                        print("    "+ mode + "Pick ray does not intersect XZ plane.");
+                    }
+                    
+                    // EARLY EXIT--(Invalid ray detected.)
+                    return;
+                }
+                
+                if (debugPickPlaneEnabled) {
+                    that.showDebugPickPlaneHit(newPick);
+                }
+
+                var vector = Vec3.subtract(newPick, initialPick);
+
+                // If the mouse is too close to the horizon of the pick plane, stop moving
+                var MIN_ELEVATION = 0.02; //  largest dimension of object divided by distance to it
+                var elevation = this.elevation(pickRay.origin, newPick);
+                if (wantDebug) {
+                    print("Start Elevation: " + startingElevation + ", elevation: " + elevation);
+                }
+                if ((startingElevation > 0.0 && elevation < MIN_ELEVATION) ||
+                    (startingElevation < 0.0 && elevation > -MIN_ELEVATION)) {
+                    if (wantDebug) {
+                        print("    "+ mode + " - too close to horizon!");
+                    }
+
+                    // EARLY EXIT--(Don't proceed past the reached limit.)
+                    return;
+                }
+
+                //  If the angular size of the object is too small, stop moving
+                var MIN_ANGULAR_SIZE = 0.01; //  Radians
+                if (greatestDimension > 0) {
+                    var angularSize = Math.atan(greatestDimension / Vec3.distance(pickRay.origin, newPick));
+                    if (wantDebug) {
+                        print("Angular size = " + angularSize);
+                    }
+                    if (angularSize < MIN_ANGULAR_SIZE) {
+                        return;
+                    }
+                }
+
+                // If shifted, constrain to one axis
+                if (event.isShifted) {
+                    if (Math.abs(vector.x) > Math.abs(vector.z)) {
+                        vector.z = 0;
+                    } else {
+                        vector.x = 0;
+                    }
+                    if (!isConstrained) {
+                        var xStart = Vec3.sum(startPosition, {
+                            x: -RAIL_AXIS_LENGTH,
+                            y: 0,
+                            z: 0
+                        });
+                        var xEnd = Vec3.sum(startPosition, {
+                            x: RAIL_AXIS_LENGTH,
+                            y: 0,
+                            z: 0
+                        });
+                        var zStart = Vec3.sum(startPosition, {
+                            x: 0,
+                            y: 0,
+                            z: -RAIL_AXIS_LENGTH
+                        });
+                        var zEnd = Vec3.sum(startPosition, {
+                            x: 0,
+                            y: 0,
+                            z: RAIL_AXIS_LENGTH
+                        });
+                        Overlays.editOverlay(xRailOverlay, {
+                            start: xStart,
+                            end: xEnd,
+                            visible: true,
+                            ignorePickIntersection: true
+                        });
+                        Overlays.editOverlay(zRailOverlay, {
+                            start: zStart,
+                            end: zEnd,
+                            visible: true,
+                            ignorePickIntersection: true
+                        });
+                        isConstrained = true;
+                    }
+                } else {
+                    if (isConstrained) {
+                        Overlays.editOverlay(xRailOverlay, {
+                            visible: false,
+                            ignorePickIntersection: true
+                        });
+                        Overlays.editOverlay(zRailOverlay, {
+                            visible: false,
+                            ignorePickIntersection: true
+                        });
+                        isConstrained = false;
+                    }
+                }
+
+                constrainMajorOnly = event.isControl;
+                var negateAndHalve = -0.5;
+                var cornerPosition = Vec3.sum(startPosition, Vec3.multiply(negateAndHalve, SelectionManager.worldDimensions));
+                vector = Vec3.subtract(
+                    grid.snapToGrid(Vec3.sum(cornerPosition, vector), constrainMajorOnly),
+                    cornerPosition);
+
+                // editing a parent will cause all the children to automatically follow along, so don't
+                // edit any entity who has an ancestor in SelectionManager.selections
+                var toMove = SelectionManager.selections.filter(function (selection) {
+                    if (SelectionManager.selections.indexOf(SelectionManager.savedProperties[selection].parentID) >= 0) {
+                        return false; // a parent is also being moved, so don't issue an edit for this entity
+                    } else {
+                        return true;
+                    }
+                });
+
+                for (var i = 0; i < toMove.length; i++) {
+                    var properties = SelectionManager.savedProperties[toMove[i]];
+                    if (!properties) {
+                        continue;
+                    }
+                    var newPosition = Vec3.sum(properties.position, {
+                        x: vector.x,
+                        y: 0,
+                        z: vector.z
+                    });
+                    Entities.editEntity(toMove[i], {
+                        position: newPosition
+                    });
+
+                    if (wantDebug) {
+                        print("translateXZ... ");
+                        Vec3.print("                 vector:", vector);
+                        Vec3.print("            newPosition:", properties.position);
+                        Vec3.print("            newPosition:", newPosition);
+                    }
+                }
+
+                SelectionManager._update(false, this);
+            }
+        });
+    }
+
+    // TOOL DEFINITION: HANDLE TRANSLATE TOOL    
+    function addHandleTranslateTool(overlay, mode, direction) {
+        var pickPlanePosition = null;
+        var pickPlaneNormal = null;
+        var initialPick = null;
+        var projectionVector = null;
+        var previousPickRay = null;
+        var rotation = null;
+        addHandleTool(overlay, {
+            mode: mode,
+            onBegin: function(event, pickRay, pickResult) {
+                // Duplicate entities if alt is pressed.  This will make a
+                // copy of the selected entities and move the _original_ entities, not
+                // the new ones.
+                if (event.isAlt) {
+                    duplicatedEntityIDs = SelectionManager.duplicateSelection();
+                    var ids = [];
+                    for (var i = 0; i < duplicatedEntityIDs.length; ++i) {
+                        ids.push(duplicatedEntityIDs[i].entityID);
+                    }
+                    SelectionManager.setSelections(ids);
+                } else {
+                    duplicatedEntityIDs = null;
+                }
+
+                var axisVector;
+                if (direction === TRANSLATE_DIRECTION.X) {
+                    axisVector = { x: 1, y: 0, z: 0 };
+                } else if (direction === TRANSLATE_DIRECTION.Y) {
+                    axisVector = { x: 0, y: 1, z: 0 };
+                } else if (direction === TRANSLATE_DIRECTION.Z) {
+                    axisVector = { x: 0, y: 0, z: 1 };
+                }
+                
+                rotation = spaceMode === SPACE_LOCAL ? SelectionManager.localRotation : SelectionManager.worldRotation;
+                axisVector = Vec3.multiplyQbyV(rotation, axisVector);
+                pickPlaneNormal = Vec3.cross(Vec3.cross(pickRay.direction, axisVector), axisVector);
+                pickPlanePosition = SelectionManager.worldPosition;
+                initialPick = rayPlaneIntersection(pickRay, pickPlanePosition, pickPlaneNormal);
+    
+                SelectionManager.saveProperties();
+                that.resetPreviousHandleColor();
+
+                that.setHandleTranslateXVisible(direction === TRANSLATE_DIRECTION.X);
+                that.setHandleTranslateYVisible(direction === TRANSLATE_DIRECTION.Y);
+                that.setHandleTranslateZVisible(direction === TRANSLATE_DIRECTION.Z);
+                that.setHandleRotateVisible(false);
+                that.setHandleStretchVisible(false);
+                that.setHandleScaleVisible(false);
+                that.setHandleDuplicatorVisible(false);
+                
+                previousPickRay = pickRay;
+                
+                if (debugPickPlaneEnabled) {
+                    that.showDebugPickPlane(pickPlanePosition, pickPlaneNormal);
+                    that.showDebugPickPlaneHit(initialPick);
+                }
+            },
+            onEnd: function(event, reason) {
+                pushCommandForSelections(duplicatedEntityIDs);
+            },
+            onMove: function(event) {
+                var pickRay = generalComputePickRay(event.x, event.y);
+                
+                // Use previousPickRay if new pickRay will cause resulting rayPlaneIntersection values to wrap around
+                if (usePreviousPickRay(pickRay.direction, previousPickRay.direction, pickPlaneNormal)) {
+                    pickRay = previousPickRay;
+                }
+    
+                var newPick = rayPlaneIntersection(pickRay, pickPlanePosition, pickPlaneNormal);
+                if (debugPickPlaneEnabled) {
+                    that.showDebugPickPlaneHit(newPick);
+                }
+                
+                var vector = Vec3.subtract(newPick, initialPick);
+                
+                if (direction === TRANSLATE_DIRECTION.X) {
+                    projectionVector = { x: 1, y: 0, z: 0 };
+                } else if (direction === TRANSLATE_DIRECTION.Y) {
+                    projectionVector = { x: 0, y: 1, z: 0 };
+                } else if (direction === TRANSLATE_DIRECTION.Z) {
+                    projectionVector = { x: 0, y: 0, z: 1 };
+                }
+                projectionVector = Vec3.multiplyQbyV(rotation, projectionVector);
+
+                var dotVector = Vec3.dot(vector, projectionVector);
+                vector = Vec3.multiply(dotVector, projectionVector);
+                var gridOrigin = grid.getOrigin();
+                vector = Vec3.subtract(grid.snapToGrid(Vec3.sum(vector, gridOrigin)), gridOrigin);
+                
+                var wantDebug = false;
+                if (wantDebug) {
+                    print("translateUpDown... ");
+                    print("                event.y:" + event.y);
+                    Vec3.print("        newIntersection:", newIntersection);
+                    Vec3.print("                 vector:", vector);
+                }
+
+                // editing a parent will cause all the children to automatically follow along, so don't
+                // edit any entity who has an ancestor in SelectionManager.selections
+                var toMove = SelectionManager.selections.filter(function (selection) {
+                    if (SelectionManager.selections.indexOf(SelectionManager.savedProperties[selection].parentID) >= 0) {
+                        return false; // a parent is also being moved, so don't issue an edit for this entity
+                    } else {
+                        return true;
+                    }
+                });
+
+                for (var i = 0; i < toMove.length; i++) {
+                    var id = toMove[i];
+                    var properties = SelectionManager.savedProperties[id];
+                    var newPosition = Vec3.sum(properties.position, vector);
+                    Entities.editEntity(id, { position: newPosition });
+                }
+                
+                previousPickRay = pickRay;
+    
+                SelectionManager._update(false, this);
+            }
+        });
+    }
+
+    // TOOL DEFINITION: HANDLE STRETCH TOOL   
+    function addHandleStretchTool(overlay, mode, directionEnum) {
+        var initialPick = null;
+        var initialPosition = null;
+        var initialDimensions = null;
+        var rotation = null;
+        var registrationPoint = null;
+        var pickPlanePosition = null;
+        var pickPlaneNormal = null;
+        var previousPickRay = null;
+        var directionVector = null;
+        var axisVector = null;
+        var signs = null;
+        var mask = null;
+        var stretchPanel = null;
+        var handleStretchCube = null;
+        var deltaPivot = null;
+        addHandleTool(overlay, {
+            mode: mode,
+            onBegin: function(event, pickRay, pickResult) {             
+                if (directionEnum === STRETCH_DIRECTION.X) {
+                    stretchPanel = handleStretchXPanel;
+                    handleStretchCube = handleStretchXCube;
+                    directionVector = { x: -1, y: 0, z: 0 };
+                } else if (directionEnum === STRETCH_DIRECTION.Y) {
+                    stretchPanel = handleStretchYPanel;
+                    handleStretchCube = handleStretchYCube;
+                    directionVector = { x: 0, y: -1, z: 0 };
+                } else if (directionEnum === STRETCH_DIRECTION.Z) {
+                    stretchPanel = handleStretchZPanel;
+                    handleStretchCube = handleStretchZCube;
+                    directionVector = { x: 0, y: 0, z: -1 };
+                }
+                
+                rotation = SelectionManager.localRotation;
+                initialPosition = SelectionManager.localPosition;
+                initialDimensions = SelectionManager.localDimensions;
+                registrationPoint = SelectionManager.localRegistrationPoint;
+                
+                axisVector = Vec3.multiply(NEGATE_VECTOR, directionVector);
+                axisVector = Vec3.multiplyQbyV(rotation, axisVector);
+                
+                signs = {
+                    x: directionVector.x < 0 ? -1 : (directionVector.x > 0 ? 1 : 0),
+                    y: directionVector.y < 0 ? -1 : (directionVector.y > 0 ? 1 : 0),
+                    z: directionVector.z < 0 ? -1 : (directionVector.z > 0 ? 1 : 0)
+                };
+                mask = {
+                    x: Math.abs(directionVector.x) > 0 ? 1 : 0,
+                    y: Math.abs(directionVector.y) > 0 ? 1 : 0,
+                    z: Math.abs(directionVector.z) > 0 ? 1 : 0
+                };
+                
+                var pivot = directionVector;
+                var offset = Vec3.multiply(directionVector, NEGATE_VECTOR);
+                
+                // Modify range of registrationPoint to be [-0.5, 0.5]
+                var centeredRP = Vec3.subtract(registrationPoint, {
+                    x: 0.5,
+                    y: 0.5,
+                    z: 0.5
+                });
+
+                // Scale pivot to be in the same range as registrationPoint
+                var scaledPivot = Vec3.multiply(0.5, pivot);
+                deltaPivot = Vec3.subtract(centeredRP, scaledPivot);
+
+                var scaledOffset = Vec3.multiply(0.5, offset);
+
+                // Offset from the registration point
+                var offsetRP = Vec3.subtract(scaledOffset, centeredRP);
+
+                // Scaled offset in world coordinates
+                var scaledOffsetWorld = Vec3.multiplyVbyV(initialDimensions, offsetRP);
+                
+                pickPlaneNormal = Vec3.cross(Vec3.cross(pickRay.direction, axisVector), axisVector);
+                pickPlanePosition = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffsetWorld));
+                initialPick = rayPlaneIntersection(pickRay, pickPlanePosition, pickPlaneNormal);
+
+                that.setHandleTranslateVisible(false);
+                that.setHandleRotateVisible(false);
+                that.setHandleScaleVisible(true);
+                that.setHandleStretchXVisible(directionEnum === STRETCH_DIRECTION.X);
+                that.setHandleStretchYVisible(directionEnum === STRETCH_DIRECTION.Y);
+                that.setHandleStretchZVisible(directionEnum === STRETCH_DIRECTION.Z);
+                that.setHandleDuplicatorVisible(false);
+            
+                SelectionManager.saveProperties();
+                that.resetPreviousHandleColor();
+
+                var collisionToRemove = "myAvatar";
+                var properties = Entities.getEntityProperties(SelectionManager.selections[0]);
+                if (properties.collidesWith.indexOf(collisionToRemove) > -1) {
+                    var newCollidesWith = properties.collidesWith.replace(collisionToRemove, "");
+                    Entities.editEntity(SelectionManager.selections[0], {collidesWith: newCollidesWith});
+                    that.replaceCollisionsAfterStretch = true;
+                }
+
+                if (stretchPanel !== null) {
+                    Overlays.editOverlay(stretchPanel, { visible: true, ignorePickIntersection: false });
+                }
+                var stretchCubePosition = Overlays.getProperty(handleStretchCube, "position");
+                var stretchPanelPosition = Overlays.getProperty(stretchPanel, "position");
+                activeStretchCubePanelOffset = Vec3.subtract(stretchPanelPosition, stretchCubePosition);
+                
+                previousPickRay = pickRay;
+
+                if (debugPickPlaneEnabled) {
+                    that.showDebugPickPlane(pickPlanePosition, pickPlaneNormal);
+                    that.showDebugPickPlaneHit(initialPick);
+                }
+            },
+            onEnd: function(event, reason) {                
+                if (that.replaceCollisionsAfterStretch) {
+                    var newCollidesWith = SelectionManager.savedProperties[SelectionManager.selections[0]].collidesWith;
+                    Entities.editEntity(SelectionManager.selections[0], {collidesWith: newCollidesWith});
+                    that.replaceCollisionsAfterStretch = false;
+                }
+                
+                if (stretchPanel !== null) {
+                    Overlays.editOverlay(stretchPanel, { visible: false, ignorePickIntersection: true });
+                }
+                activeStretchCubePanelOffset = null;
+                
+                pushCommandForSelections();
+            },
+            onMove: function(event) {            
+                var pickRay = generalComputePickRay(event.x, event.y);
+                
+                // Use previousPickRay if new pickRay will cause resulting rayPlaneIntersection values to wrap around
+                if (usePreviousPickRay(pickRay.direction, previousPickRay.direction, pickPlaneNormal)) {
+                    pickRay = previousPickRay;
+                }
+                
+                var newPick = rayPlaneIntersection(pickRay, pickPlanePosition, pickPlaneNormal);
+                if (debugPickPlaneEnabled) {
+                    that.showDebugPickPlaneHit(newPick);
+                }
+                
+                var changeInDimensions = Vec3.subtract(newPick, initialPick);
+                var dotVector = Vec3.dot(changeInDimensions, axisVector);
+                changeInDimensions = Vec3.multiply(dotVector, axisVector);
+                changeInDimensions = Vec3.multiplyQbyV(Quat.inverse(rotation), changeInDimensions);
+                changeInDimensions = Vec3.multiplyVbyV(mask, changeInDimensions);
+                changeInDimensions = grid.snapToSpacing(changeInDimensions);
+                changeInDimensions = Vec3.multiply(NEGATE_VECTOR, Vec3.multiplyVbyV(signs, changeInDimensions));    
+
+                var newDimensions = Vec3.sum(initialDimensions, changeInDimensions);
+
+                var minimumDimension = Entities.getPropertyInfo("dimensions").minimum; 
+                if (newDimensions.x < minimumDimension) {
+                    newDimensions.x = minimumDimension;
+                    changeInDimensions.x = minimumDimension - initialDimensions.x;
+                }
+                if (newDimensions.y < minimumDimension) {
+                    newDimensions.y = minimumDimension;
+                    changeInDimensions.y = minimumDimension - initialDimensions.y;
+                }
+                if (newDimensions.z < minimumDimension) {
+                    newDimensions.z = minimumDimension;
+                    changeInDimensions.z = minimumDimension - initialDimensions.z;
+                }
+
+                var changeInPosition = Vec3.multiplyQbyV(rotation, Vec3.multiplyVbyV(deltaPivot, changeInDimensions));
+                var newPosition = Vec3.sum(initialPosition, changeInPosition);
+        
+                Entities.editEntity(SelectionManager.selections[0], {
+                    position: newPosition,
+                    dimensions: newDimensions
+                });
+                    
+                var wantDebug = false;
+                if (wantDebug) {
+                    print(mode);
+                    Vec3.print("            changeInDimensions:", changeInDimensions);
+                    Vec3.print("                 newDimensions:", newDimensions);
+                    Vec3.print("              changeInPosition:", changeInPosition);
+                    Vec3.print("                   newPosition:", newPosition);
+                }
+                
+                previousPickRay = pickRay;
+        
+                SelectionManager._update(false, this);
+            }
+        });
+    }
+
+    // TOOL DEFINITION: HANDLE SCALE TOOL   
+    function addHandleScaleTool(overlay, mode) {
+        var initialPick = null;
+        var initialPosition = null;
+        var initialDimensions = null;
+        var pickPlanePosition = null;
+        var pickPlaneNormal = null;
+        var previousPickRay = null;     
+        addHandleTool(overlay, {
+            mode: mode,
+            onBegin: function(event, pickRay, pickResult) {
+                initialPosition = SelectionManager.localPosition;
+                initialDimensions = SelectionManager.localDimensions;               
+                
+                pickPlanePosition = initialPosition;                
+                pickPlaneNormal = Vec3.subtract(pickRay.origin, pickPlanePosition);
+                initialPick = rayPlaneIntersection(pickRay, pickPlanePosition, pickPlaneNormal);
+
+                that.setHandleTranslateVisible(false);
+                that.setHandleRotateVisible(false);
+                that.setHandleScaleVisible(true);
+                that.setHandleStretchVisible(false);
+                that.setHandleDuplicatorVisible(false);
+            
+                SelectionManager.saveProperties();
+                that.resetPreviousHandleColor();
+
+                var collisionToRemove = "myAvatar";
+                var properties = Entities.getEntityProperties(SelectionManager.selections[0]);
+                if (properties.collidesWith.indexOf(collisionToRemove) > -1) {
+                    var newCollidesWith = properties.collidesWith.replace(collisionToRemove, "");
+                    Entities.editEntity(SelectionManager.selections[0], {collidesWith: newCollidesWith});
+                    that.replaceCollisionsAfterStretch = true;
+                }
+
+                previousPickRay = pickRay;
+                
+                if (debugPickPlaneEnabled) {
+                    that.showDebugPickPlane(pickPlanePosition, pickPlaneNormal);
+                    that.showDebugPickPlaneHit(initialPick);
+                }
+            },
+            onEnd: function(event, reason) {                
+                if (that.replaceCollisionsAfterStretch) {
+                    var newCollidesWith = SelectionManager.savedProperties[SelectionManager.selections[0]].collidesWith;
+                    Entities.editEntity(SelectionManager.selections[0], {collidesWith: newCollidesWith});
+                    that.replaceCollisionsAfterStretch = false;
+                }
+                
+                pushCommandForSelections();
+            },
+            onMove: function(event) {            
+                var pickRay = generalComputePickRay(event.x, event.y);
+                
+                // Use previousPickRay if new pickRay will cause resulting rayPlaneIntersection values to wrap around
+                if (usePreviousPickRay(pickRay.direction, previousPickRay.direction, pickPlaneNormal)) {
+                    pickRay = previousPickRay;
+                }
+                
+                var newPick = rayPlaneIntersection(pickRay, pickPlanePosition, pickPlaneNormal);
+                if (debugPickPlaneEnabled) {
+                    that.showDebugPickPlaneHit(newPick);
+                }
+                
+                var toCameraDistance = getDistanceToCamera(initialPosition);  
+                var dimensionsMultiple = toCameraDistance * SCALE_DIMENSIONS_CAMERA_DISTANCE_MULTIPLE;
+                var changeInDimensions = Vec3.subtract(newPick, initialPick);                   
+                changeInDimensions = Vec3.multiplyQbyV(Quat.inverse(Camera.orientation), changeInDimensions);
+                changeInDimensions = grid.snapToSpacing(changeInDimensions);
+                changeInDimensions = Vec3.multiply(changeInDimensions, dimensionsMultiple);
+                
+                var averageDimensionChange = (changeInDimensions.x + changeInDimensions.y + changeInDimensions.z) / 3;
+                var averageInitialDimension = (initialDimensions.x + initialDimensions.y + initialDimensions.z) / 3;
+                percentChange = averageDimensionChange / averageInitialDimension;
+                percentChange += 1.0;
+                
+                var newDimensions = Vec3.multiply(percentChange, initialDimensions);
+                newDimensions.x = Math.abs(newDimensions.x);
+                newDimensions.y = Math.abs(newDimensions.y);
+                newDimensions.z = Math.abs(newDimensions.z);
+
+                var minimumDimension = Entities.getPropertyInfo("dimensions").minimum; 
+                if (newDimensions.x < minimumDimension) {
+                    newDimensions.x = minimumDimension;
+                    changeInDimensions.x = minimumDimension - initialDimensions.x;
+                }
+                if (newDimensions.y < minimumDimension) {
+                    newDimensions.y = minimumDimension;
+                    changeInDimensions.y = minimumDimension - initialDimensions.y;
+                }
+                if (newDimensions.z < minimumDimension) {
+                    newDimensions.z = minimumDimension;
+                    changeInDimensions.z = minimumDimension - initialDimensions.z;
+                }
+                
+                Entities.editEntity(SelectionManager.selections[0], { dimensions: newDimensions });
+                    
+                var wantDebug = false;
+                if (wantDebug) {
+                    print(mode);
+                    Vec3.print("            changeInDimensions:", changeInDimensions);
+                    Vec3.print("                 newDimensions:", newDimensions);
+                }
+                
+                previousPickRay = pickRay;
+        
+                SelectionManager._update(false, this);
+            }
+        });
+    }
+
+    // FUNCTION: UPDATE ROTATION DEGREES OVERLAY
+    function updateRotationDegreesOverlay(angleFromZero, position) {
+        var toCameraDistance = getDistanceToCamera(position);
+        var overlayProps = {
+            position: position,
+            dimensions: {
+                x: toCameraDistance * ROTATE_DISPLAY_SIZE_X_MULTIPLIER,
+                y: toCameraDistance * ROTATE_DISPLAY_SIZE_Y_MULTIPLIER
+            },
+            lineHeight: toCameraDistance * ROTATE_DISPLAY_LINE_HEIGHT_MULTIPLIER,
+            text: normalizeDegrees(-angleFromZero) + "°"
+        };
+        Overlays.editOverlay(rotationDegreesDisplay, overlayProps);
+    }
+
+    // FUNCTION DEF: updateSelectionsRotation
+    //    Helper func used by rotation handle tools 
+    function updateSelectionsRotation(rotationChange, initialPosition) {
+        if (!rotationChange) {
+            print("ERROR: entitySelectionTool.updateSelectionsRotation - Invalid arg specified!!");
+
+            // EARLY EXIT
+            return;
+        }
+
+        // Entities should only reposition if we are rotating multiple selections around
+        // the selections center point.  Otherwise, the rotation will be around the entities
+        // registration point which does not need repositioning.
+        var reposition = (SelectionManager.selections.length > 1);
+
+        // editing a parent will cause all the children to automatically follow along, so don't
+        // edit any entity who has an ancestor in SelectionManager.selections
+        var toRotate = SelectionManager.selections.filter(function (selection) {
+            if (SelectionManager.selections.indexOf(SelectionManager.savedProperties[selection].parentID) >= 0) {
+                return false; // a parent is also being moved, so don't issue an edit for this entity
+            } else {
+                return true;
+            }
+        });
+
+        for (var i = 0; i < toRotate.length; i++) {
+            var entityID = toRotate[i];
+            var initialProperties = SelectionManager.savedProperties[entityID];
+
+            var newProperties = {
+                rotation: Quat.multiply(rotationChange, initialProperties.rotation)
+            };
+
+            if (reposition) {
+                var dPos = Vec3.subtract(initialProperties.position, initialPosition);
+                dPos = Vec3.multiplyQbyV(rotationChange, dPos);
+                newProperties.position = Vec3.sum(initialPosition, dPos);
+            }
+
+            Entities.editEntity(entityID, newProperties);
+        }
+    }
+
+    // TOOL DEFINITION: HANDLE ROTATION TOOL   
+    function addHandleRotateTool(overlay, mode, direction) {
+        var selectedHandle = null;
+        var worldRotation = null;
+        var initialRotation = null;
+        var rotationCenter = null;
+        var rotationNormal = null;
+        var rotationZero = null;
+        var rotationDegreesPosition = null;
+        addHandleTool(overlay, {
+            mode: mode,
+            onBegin: function(event, pickRay, pickResult) {
+                var wantDebug = false;
+                if (wantDebug) {
+                    print("================== " + getMode() + "(addHandleRotateTool onBegin) -> =======================");
+                }
+                
+                if (direction === ROTATE_DIRECTION.PITCH) {
+                    rotationNormal = { x: 1, y: 0, z: 0 };
+                    worldRotation = worldRotationY;
+                    selectedHandle = handleRotatePitchRing;
+                } else if (direction === ROTATE_DIRECTION.YAW) {
+                    rotationNormal = { x: 0, y: 1, z: 0 };
+                    worldRotation = worldRotationZ;
+                    selectedHandle = handleRotateYawRing;
+                } else if (direction === ROTATE_DIRECTION.ROLL) {
+                    rotationNormal = { x: 0, y: 0, z: 1 };
+                    worldRotation = worldRotationX;
+                    selectedHandle = handleRotateRollRing;
+                }
+                
+                initialRotation = spaceMode === SPACE_LOCAL ? SelectionManager.localRotation : SelectionManager.worldRotation;
+                rotationNormal = Vec3.multiplyQbyV(initialRotation, rotationNormal);
+                rotationCenter = SelectionManager.worldPosition;
+
+                SelectionManager.saveProperties();
+                that.resetPreviousHandleColor();
+    
+                that.setHandleTranslateVisible(false);
+                that.setHandleRotatePitchVisible(direction === ROTATE_DIRECTION.PITCH);
+                that.setHandleRotateYawVisible(direction === ROTATE_DIRECTION.YAW);
+                that.setHandleRotateRollVisible(direction === ROTATE_DIRECTION.ROLL);
+                that.setHandleStretchVisible(false);
+                that.setHandleScaleVisible(false);
+                that.setHandleDuplicatorVisible(false);
+
+                Overlays.editOverlay(selectedHandle, { 
+                    hasTickMarks: true,
+                    solid: false,
+                    innerRadius: ROTATE_RING_SELECTED_INNER_RADIUS
+                });
+
+                Overlays.editOverlay(rotationDegreesDisplay, { visible: true });
+                Overlays.editOverlay(handleRotateCurrentRing, {
+                    position: rotationCenter,
+                    rotation: worldRotation,
+                    startAt: 0,
+                    endAt: 0,
+                    visible: true,
+                    ignorePickIntersection: false
+                });
+
+                // editOverlays may not have committed rotation changes.
+                // Compute zero position based on where the overlay will be eventually.
+                var initialPick = rayPlaneIntersection(pickRay, rotationCenter, rotationNormal);
+                // In case of a parallel ray, this will be null, which will cause early-out
+                // in the onMove helper.
+                rotationZero = initialPick;
+
+                var rotationCenterToZero = Vec3.subtract(rotationZero, rotationCenter);
+                var rotationCenterToZeroLength = Vec3.length(rotationCenterToZero);
+                rotationDegreesPosition = Vec3.sum(rotationCenter, Vec3.multiply(Vec3.normalize(rotationCenterToZero), 
+                                                   rotationCenterToZeroLength * ROTATE_DISPLAY_DISTANCE_MULTIPLIER));
+                updateRotationDegreesOverlay(0, rotationDegreesPosition);
+                
+                if (debugPickPlaneEnabled) {
+                    that.showDebugPickPlane(rotationCenter, rotationNormal);
+                    that.showDebugPickPlaneHit(initialPick);
+                }
+
+                if (wantDebug) {
+                    print("================== " + getMode() + "(addHandleRotateTool onBegin) <- =======================");
+                }
+            },
+            onEnd: function(event, reason) {
+                var wantDebug = false;
+                if (wantDebug) {
+                    print("================== " + getMode() + "(addHandleRotateTool onEnd) -> =======================");
+                }
+                Overlays.editOverlay(rotationDegreesDisplay, { visible: false, ignorePickIntersection: true });
+                Overlays.editOverlay(selectedHandle, { 
+                    hasTickMarks: false,
+                    solid: true,
+                    innerRadius: ROTATE_RING_IDLE_INNER_RADIUS
+                });
+                Overlays.editOverlay(handleRotateCurrentRing, { visible: false, ignorePickIntersection: true });
+                pushCommandForSelections();
+                if (wantDebug) {
+                    print("================== " + getMode() + "(addHandleRotateTool onEnd) <- =======================");
+                }
+            },
+            onMove: function(event) {
+                if (!rotationZero) {
+                    print("ERROR: entitySelectionTool.addHandleRotateTool.onMove - " +
+                          "Invalid RotationZero Specified (missed rotation target plane?)");
+
+                    // EARLY EXIT
+                    return;
+                }
+                
+                var wantDebug = false;
+                if (wantDebug) {
+                    print("================== "+ getMode() + "(addHandleRotateTool onMove) -> =======================");
+                    Vec3.print("    rotationZero: ", rotationZero);
+                }
+
+                var pickRay = generalComputePickRay(event.x, event.y);
+                var result = rayPlaneIntersection(pickRay, rotationCenter, rotationNormal);
+                if (result) {
+                    var centerToZero = Vec3.subtract(rotationZero, rotationCenter);
+                    var centerToIntersect = Vec3.subtract(result, rotationCenter);
+
+                    if (wantDebug) {
+                        Vec3.print("    RotationNormal:    ", rotationNormal);
+                        Vec3.print("    rotationZero:           ", rotationZero);
+                        Vec3.print("    rotationCenter:         ", rotationCenter);
+                        Vec3.print("    intersect:         ", result);
+                        Vec3.print("    centerToZero:      ", centerToZero);
+                        Vec3.print("    centerToIntersect: ", centerToIntersect);
+                    }
+
+                    // Note: orientedAngle which wants normalized centerToZero and centerToIntersect
+                    //             handles that internally, so it's to pass unnormalized vectors here.
+                    var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal);        
+                    var snapAngle = ctrlPressed ? ROTATE_CTRL_SNAP_ANGLE : ROTATE_DEFAULT_SNAP_ANGLE;
+                    angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle;
+                    var rotationChange = Quat.angleAxis(angleFromZero, rotationNormal);
+                    updateSelectionsRotation(rotationChange, rotationCenter);
+                    updateRotationDegreesOverlay(-angleFromZero, rotationDegreesPosition);
+
+                    if (direction === ROTATE_DIRECTION.YAW) {
+                        angleFromZero *= -1;
+                    }
+
+                    var startAtCurrent = 0;
+                    var endAtCurrent = angleFromZero;
+                    var maxDegrees = 360;
+                    if (angleFromZero < 0) {
+                        startAtCurrent = maxDegrees + angleFromZero;
+                        endAtCurrent = maxDegrees;
+                    }
+                    Overlays.editOverlay(handleRotateCurrentRing, {
+                        startAt: startAtCurrent,
+                        endAt: endAtCurrent
+                    });
+                    
+                    if (debugPickPlaneEnabled) {
+                        that.showDebugPickPlaneHit(result);
+                    }
+                }
+
+                if (wantDebug) {
+                    print("================== "+ getMode() + "(addHandleRotateTool onMove) <- =======================");
+                }
+            }
+        });
+    }    
+
+    addHandleTranslateXZTool(selectionBox, "TRANSLATE_XZ", false);
+    addHandleTranslateXZTool(iconSelectionBox, "TRANSLATE_XZ", false);
+    addHandleTranslateXZTool(handleDuplicator, "DUPLICATE", true);
+
+    addHandleTranslateTool(handleTranslateXCone, "TRANSLATE_X", TRANSLATE_DIRECTION.X);
+    addHandleTranslateTool(handleTranslateXCylinder, "TRANSLATE_X", TRANSLATE_DIRECTION.X);
+    addHandleTranslateTool(handleTranslateYCone, "TRANSLATE_Y", TRANSLATE_DIRECTION.Y);
+    addHandleTranslateTool(handleTranslateYCylinder, "TRANSLATE_Y", TRANSLATE_DIRECTION.Y);
+    addHandleTranslateTool(handleTranslateZCone, "TRANSLATE_Z", TRANSLATE_DIRECTION.Z);
+    addHandleTranslateTool(handleTranslateZCylinder, "TRANSLATE_Z", TRANSLATE_DIRECTION.Z);
+
+    addHandleRotateTool(handleRotatePitchRing, "ROTATE_PITCH", ROTATE_DIRECTION.PITCH);
+    addHandleRotateTool(handleRotateYawRing, "ROTATE_YAW", ROTATE_DIRECTION.YAW);
+    addHandleRotateTool(handleRotateRollRing, "ROTATE_ROLL", ROTATE_DIRECTION.ROLL);
+
+    addHandleStretchTool(handleStretchXCube, "STRETCH_X", STRETCH_DIRECTION.X);
+    addHandleStretchTool(handleStretchYCube, "STRETCH_Y", STRETCH_DIRECTION.Y);
+    addHandleStretchTool(handleStretchZCube, "STRETCH_Z", STRETCH_DIRECTION.Z);
+
+    addHandleScaleTool(handleScaleCube, "SCALE");
+    
+    return that;
+}());
diff --git a/scripts/simplifiedUI/system/modules/createWindow.js b/scripts/simplifiedUI/system/create/modules/createWindow.js
similarity index 100%
rename from scripts/simplifiedUI/system/modules/createWindow.js
rename to scripts/simplifiedUI/system/create/modules/createWindow.js
diff --git a/scripts/simplifiedUI/system/modules/entityShapeVisualizer.js b/scripts/simplifiedUI/system/create/modules/entityShapeVisualizer.js
similarity index 98%
rename from scripts/simplifiedUI/system/modules/entityShapeVisualizer.js
rename to scripts/simplifiedUI/system/create/modules/entityShapeVisualizer.js
index da28369cdd..dbf09a1cb7 100644
--- a/scripts/simplifiedUI/system/modules/entityShapeVisualizer.js
+++ b/scripts/simplifiedUI/system/create/modules/entityShapeVisualizer.js
@@ -146,8 +146,8 @@ EntityShape.prototype = {
             parentID: this.entity,
             priority: 1,
             materialMappingMode: PROJECTED_MATERIALS ? "projected" : "uv",
-            materialURL: Script.resolvePath("../assets/images/materials/GridPattern.json"),
-            ignorePickIntersection: true,
+            materialURL: Script.resolvePath("../../assets/images/materials/GridPattern.json"),
+            ignorePickIntersection: true
         }, "local");
     },
     update: function() {
diff --git a/scripts/simplifiedUI/system/create/Edit.qml b/scripts/simplifiedUI/system/create/qml/Edit.qml
similarity index 95%
rename from scripts/simplifiedUI/system/create/Edit.qml
rename to scripts/simplifiedUI/system/create/qml/Edit.qml
index ca18388def..13e7874ca8 100644
--- a/scripts/simplifiedUI/system/create/Edit.qml
+++ b/scripts/simplifiedUI/system/create/qml/Edit.qml
@@ -34,7 +34,7 @@ StackView {
     }
 
     function pushSource(path) {
-        var item = Qt.createComponent(Qt.resolvedUrl("../../" + path));
+        var item = Qt.createComponent(path);
         editRoot.push(item, itemProperties,
                       StackView.Immediate);
         editRoot.currentItem.sendToScript.connect(editRoot.sendToScript);
diff --git a/scripts/simplifiedUI/system/create/EditTabButton.qml b/scripts/simplifiedUI/system/create/qml/EditTabButton.qml
similarity index 100%
rename from scripts/simplifiedUI/system/create/EditTabButton.qml
rename to scripts/simplifiedUI/system/create/qml/EditTabButton.qml
diff --git a/scripts/simplifiedUI/system/create/EditTabView.qml b/scripts/simplifiedUI/system/create/qml/EditTabView.qml
similarity index 93%
rename from scripts/simplifiedUI/system/create/EditTabView.qml
rename to scripts/simplifiedUI/system/create/qml/EditTabView.qml
index 7e8789487c..a0cff70d50 100644
--- a/scripts/simplifiedUI/system/create/EditTabView.qml
+++ b/scripts/simplifiedUI/system/create/qml/EditTabView.qml
@@ -72,7 +72,7 @@ TabBar {
 
 
                         NewEntityButton {
-                            icon: "create-icons/94-model-01.svg"
+                            icon: "icons/94-model-01.svg"
                             text: "MODEL"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -84,7 +84,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/21-cube-01.svg"
+                            icon: "icons/21-cube-01.svg"
                             text: "SHAPE"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -96,7 +96,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/24-light-01.svg"
+                            icon: "icons/24-light-01.svg"
                             text: "LIGHT"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -108,7 +108,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/20-text-01.svg"
+                            icon: "icons/20-text-01.svg"
                             text: "TEXT"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -120,7 +120,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/image.svg"
+                            icon: "icons/image.svg"
                             text: "IMAGE"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -132,7 +132,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/25-web-1-01.svg"
+                            icon: "icons/25-web-1-01.svg"
                             text: "WEB"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -144,7 +144,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/23-zone-01.svg"
+                            icon: "icons/23-zone-01.svg"
                             text: "ZONE"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -156,7 +156,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/90-particles-01.svg"
+                            icon: "icons/90-particles-01.svg"
                             text: "PARTICLE"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -168,7 +168,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/126-material-01.svg"
+                            icon: "icons/126-material-01.svg"
                             text: "MATERIAL"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -231,7 +231,7 @@ TabBar {
         property Component visualItem: Component {
             WebView {
                 id: entityListToolWebView
-                url: Paths.defaultScripts + "/system/html/entityList.html"
+                url: Qt.resolvedUrl("../entityList/html/entityList.html")
                 enabled: true
                 blurOnCtrlShift: false
             }
@@ -247,7 +247,7 @@ TabBar {
         property Component visualItem: Component {
             WebView {
                 id: entityPropertiesWebView
-                url: Paths.defaultScripts + "/system/html/entityProperties.html"
+                url: Qt.resolvedUrl("../entityProperties/html/entityProperties.html")
                 enabled: true
                 blurOnCtrlShift: false
             }
@@ -263,7 +263,7 @@ TabBar {
         property Component visualItem: Component {
             WebView {
                 id: gridControlsWebView
-                url: Paths.defaultScripts + "/system/html/gridControls.html"
+                url: Qt.resolvedUrl("../../html/gridControls.html")
                 enabled: true
                 blurOnCtrlShift: false
             }
diff --git a/scripts/simplifiedUI/system/create/EditTools.qml b/scripts/simplifiedUI/system/create/qml/EditTools.qml
similarity index 100%
rename from scripts/simplifiedUI/system/create/EditTools.qml
rename to scripts/simplifiedUI/system/create/qml/EditTools.qml
diff --git a/scripts/simplifiedUI/system/create/EditToolsTabView.qml b/scripts/simplifiedUI/system/create/qml/EditToolsTabView.qml
similarity index 93%
rename from scripts/simplifiedUI/system/create/EditToolsTabView.qml
rename to scripts/simplifiedUI/system/create/qml/EditToolsTabView.qml
index a333acc586..0ce8d8e8d4 100644
--- a/scripts/simplifiedUI/system/create/EditToolsTabView.qml
+++ b/scripts/simplifiedUI/system/create/qml/EditToolsTabView.qml
@@ -78,7 +78,7 @@ TabBar {
 
 
                         NewEntityButton {
-                            icon: "create-icons/94-model-01.svg"
+                            icon: "icons/94-model-01.svg"
                             text: "MODEL"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -90,7 +90,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/21-cube-01.svg"
+                            icon: "icons/21-cube-01.svg"
                             text: "SHAPE"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -102,7 +102,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/24-light-01.svg"
+                            icon: "icons/24-light-01.svg"
                             text: "LIGHT"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -114,7 +114,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/20-text-01.svg"
+                            icon: "icons/20-text-01.svg"
                             text: "TEXT"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -126,7 +126,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/image.svg"
+                            icon: "icons/image.svg"
                             text: "IMAGE"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -138,7 +138,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/25-web-1-01.svg"
+                            icon: "icons/25-web-1-01.svg"
                             text: "WEB"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -150,7 +150,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/23-zone-01.svg"
+                            icon: "icons/23-zone-01.svg"
                             text: "ZONE"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -162,7 +162,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/90-particles-01.svg"
+                            icon: "icons/90-particles-01.svg"
                             text: "PARTICLE"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -174,7 +174,7 @@ TabBar {
                         }
 
                         NewEntityButton {
-                            icon: "create-icons/126-material-01.svg"
+                            icon: "icons/126-material-01.svg"
                             text: "MATERIAL"
                             onClicked: {
                                 editRoot.sendToScript({
@@ -237,7 +237,7 @@ TabBar {
         property Component visualItem: Component {
             WebView {
                 id: entityPropertiesWebView
-                url: Paths.defaultScripts + "/system/html/entityProperties.html"
+                url: Qt.resolvedUrl("../entityProperties/html/entityProperties.html")
                 enabled: true
                 blurOnCtrlShift: false
             }
@@ -253,7 +253,7 @@ TabBar {
         property Component visualItem: Component {
             WebView {
                 id: gridControlsWebView
-                url: Paths.defaultScripts + "/system/html/gridControls.html"
+                url: Qt.resolvedUrl("../../html/gridControls.html")
                 enabled: true
                 blurOnCtrlShift: false
             }
diff --git a/scripts/simplifiedUI/system/create/NewEntityButton.qml b/scripts/simplifiedUI/system/create/qml/NewEntityButton.qml
similarity index 100%
rename from scripts/simplifiedUI/system/create/NewEntityButton.qml
rename to scripts/simplifiedUI/system/create/qml/NewEntityButton.qml
diff --git a/scripts/simplifiedUI/system/create/NewMaterialDialog.qml b/scripts/simplifiedUI/system/create/qml/NewMaterialDialog.qml
similarity index 99%
rename from scripts/simplifiedUI/system/create/NewMaterialDialog.qml
rename to scripts/simplifiedUI/system/create/qml/NewMaterialDialog.qml
index 75570327e0..1631632fb4 100644
--- a/scripts/simplifiedUI/system/create/NewMaterialDialog.qml
+++ b/scripts/simplifiedUI/system/create/qml/NewMaterialDialog.qml
@@ -15,7 +15,7 @@ import QtQuick.Dialogs 1.2 as OriginalDialogs
 
 import stylesUit 1.0
 import controlsUit 1.0
-import dialogs 1.0
+import hifi.dialogs 1.0
 
 Rectangle {
     id: newMaterialDialog
diff --git a/scripts/simplifiedUI/system/create/NewMaterialWindow.qml b/scripts/simplifiedUI/system/create/qml/NewMaterialWindow.qml
similarity index 100%
rename from scripts/simplifiedUI/system/create/NewMaterialWindow.qml
rename to scripts/simplifiedUI/system/create/qml/NewMaterialWindow.qml
diff --git a/scripts/simplifiedUI/system/create/NewModelDialog.qml b/scripts/simplifiedUI/system/create/qml/NewModelDialog.qml
similarity index 95%
rename from scripts/simplifiedUI/system/create/NewModelDialog.qml
rename to scripts/simplifiedUI/system/create/qml/NewModelDialog.qml
index 1ded00d701..741902fa7f 100644
--- a/scripts/simplifiedUI/system/create/NewModelDialog.qml
+++ b/scripts/simplifiedUI/system/create/qml/NewModelDialog.qml
@@ -14,7 +14,7 @@ import QtQuick.Dialogs 1.2 as OriginalDialogs
 
 import stylesUit 1.0
 import controlsUit 1.0
-import dialogs 1.0
+import hifi.dialogs 1.0
 
 Rectangle {
     id: newModelDialog
@@ -135,19 +135,12 @@ Rectangle {
                     height: 400
                     spacing: 20
 
-                    Image {
-                        id: image1
-                        width: 30
-                        height: 30
-                        source: "qrc:/qtquickplugin/images/template_image.png"
-                    }
-
                     Text {
                         id: text2
                         width: 160
                         x: dynamic.width / 2
                         color: "#ffffff"
-                        text: qsTr("Models with automatic collisions set to 'Exact' cannot be dynamic, and should not be used as floors")
+                        text: qsTr("Models with automatic collisions set to 'Exact' cannot be dynamic.")
                         wrapMode: Text.WordWrap
                         font.pixelSize: 12
                     }
diff --git a/scripts/simplifiedUI/system/create/NewModelWindow.qml b/scripts/simplifiedUI/system/create/qml/NewModelWindow.qml
similarity index 100%
rename from scripts/simplifiedUI/system/create/NewModelWindow.qml
rename to scripts/simplifiedUI/system/create/qml/NewModelWindow.qml
diff --git a/scripts/simplifiedUI/system/create/create-icons/126-material-01.svg b/scripts/simplifiedUI/system/create/qml/icons/126-material-01.svg
similarity index 100%
rename from scripts/simplifiedUI/system/create/create-icons/126-material-01.svg
rename to scripts/simplifiedUI/system/create/qml/icons/126-material-01.svg
diff --git a/scripts/simplifiedUI/system/create/create-icons/20-text-01.svg b/scripts/simplifiedUI/system/create/qml/icons/20-text-01.svg
similarity index 100%
rename from scripts/simplifiedUI/system/create/create-icons/20-text-01.svg
rename to scripts/simplifiedUI/system/create/qml/icons/20-text-01.svg
diff --git a/scripts/simplifiedUI/system/create/create-icons/21-cube-01.svg b/scripts/simplifiedUI/system/create/qml/icons/21-cube-01.svg
similarity index 100%
rename from scripts/simplifiedUI/system/create/create-icons/21-cube-01.svg
rename to scripts/simplifiedUI/system/create/qml/icons/21-cube-01.svg
diff --git a/scripts/simplifiedUI/system/create/create-icons/22-sphere-01.svg b/scripts/simplifiedUI/system/create/qml/icons/22-sphere-01.svg
similarity index 100%
rename from scripts/simplifiedUI/system/create/create-icons/22-sphere-01.svg
rename to scripts/simplifiedUI/system/create/qml/icons/22-sphere-01.svg
diff --git a/scripts/simplifiedUI/system/create/create-icons/23-zone-01.svg b/scripts/simplifiedUI/system/create/qml/icons/23-zone-01.svg
similarity index 100%
rename from scripts/simplifiedUI/system/create/create-icons/23-zone-01.svg
rename to scripts/simplifiedUI/system/create/qml/icons/23-zone-01.svg
diff --git a/scripts/simplifiedUI/system/create/create-icons/24-light-01.svg b/scripts/simplifiedUI/system/create/qml/icons/24-light-01.svg
similarity index 100%
rename from scripts/simplifiedUI/system/create/create-icons/24-light-01.svg
rename to scripts/simplifiedUI/system/create/qml/icons/24-light-01.svg
diff --git a/scripts/simplifiedUI/system/create/create-icons/25-web-1-01.svg b/scripts/simplifiedUI/system/create/qml/icons/25-web-1-01.svg
similarity index 100%
rename from scripts/simplifiedUI/system/create/create-icons/25-web-1-01.svg
rename to scripts/simplifiedUI/system/create/qml/icons/25-web-1-01.svg
diff --git a/scripts/simplifiedUI/system/create/qml/icons/90-particles-01.svg b/scripts/simplifiedUI/system/create/qml/icons/90-particles-01.svg
new file mode 100644
index 0000000000..5e0105d7cd
--- /dev/null
+++ b/scripts/simplifiedUI/system/create/qml/icons/90-particles-01.svg
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<path d="M331.8,283.4c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
+	C342.1,306.6,331.8,296.2,331.8,283.4z"/>
+<path d="M277.8,350.9c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
+	C288.1,374.2,277.8,363.8,277.8,350.9z"/>
+<path d="M216.3,368.8c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
+	C226.7,392,216.3,381.6,216.3,368.8z"/>
+<path d="M169.9,308.9c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
+	C180.3,332.1,169.9,321.7,169.9,308.9z"/>
+<path d="M251.2,447.4c-4.9-3.6-8.3-9.1-9.2-15.3c-0.9-6,0.6-12.3,4.2-17.2c3.6-4.9,9.1-8.3,15.2-9.1c6-0.9,12.3,0.6,17.3,4.3
+	c4.9,3.6,8.3,9.1,9.1,15.2c0.9,6-0.6,12.3-4.2,17.2s-9.1,8.3-15.2,9.1C262.4,452.6,256.1,451,251.2,447.4z"/>
+<path d="M67.6,246.1c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
+	C78,269.3,67.6,258.8,67.6,246.1z"/>
+<path d="M178.8,199.5c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
+	C189.1,222.7,178.8,212.2,178.8,199.5z"/>
+<path d="M250.3,293.9c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
+	C260.7,317.1,250.3,306.6,250.3,293.9z"/>
+<path d="M413,242.1c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
+	C423.5,265.3,413,255,413,242.1z"/>
+<path d="M302.1,203.7c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
+	C312.6,226.9,302.1,216.5,302.1,203.7z"/>
+<path d="M132.3,113.5c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
+	C142.8,136.6,132.3,126.2,132.3,113.5z"/>
+<path d="M366.6,136.7c0-12.8,10.4-23.2,23.2-23.2l0,0c12.8,0,23.2,10.4,23.2,23.2l0,0c0,12.8-10.4,23.2-23.2,23.2l0,0
+	C377.1,159.9,366.6,149.5,366.6,136.7z"/>
+</svg>
diff --git a/scripts/simplifiedUI/system/create/create-icons/94-model-01.svg b/scripts/simplifiedUI/system/create/qml/icons/94-model-01.svg
similarity index 100%
rename from scripts/simplifiedUI/system/create/create-icons/94-model-01.svg
rename to scripts/simplifiedUI/system/create/qml/icons/94-model-01.svg
diff --git a/scripts/simplifiedUI/system/create/create-icons/image.svg b/scripts/simplifiedUI/system/create/qml/icons/image.svg
similarity index 100%
rename from scripts/simplifiedUI/system/create/create-icons/image.svg
rename to scripts/simplifiedUI/system/create/qml/icons/image.svg
diff --git a/scripts/simplifiedUI/system/keyboardShortcuts/keyboardShortcuts.js b/scripts/simplifiedUI/system/keyboardShortcuts/keyboardShortcuts.js
new file mode 100644
index 0000000000..cf3927ac2d
--- /dev/null
+++ b/scripts/simplifiedUI/system/keyboardShortcuts/keyboardShortcuts.js
@@ -0,0 +1,29 @@
+"use strict";
+
+//
+//  keyboardShortcuts.js
+//  scripts/system/keyboardShortcuts
+//
+//  Created by Preston Bezos on 06/28/2019
+//  Copyright 2019 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
+//
+
+(function () { // BEGIN LOCAL_SCOPE
+    function keyPressEvent(event) {
+        if (event.text.toUpperCase() === "B" && event.isControl) {
+            Window.openWebBrowser();
+        } else if (event.text.toUpperCase() === "N" && event.isControl) {
+            Users.toggleIgnoreRadius();
+        }
+    }
+
+    function scriptEnding() {
+        Controller.keyPressEvent.disconnect(keyPressEvent);
+    }
+
+    Controller.keyPressEvent.connect(keyPressEvent);
+    Script.scriptEnding.connect(scriptEnding);
+}()); // END LOCAL_SCOPE
diff --git a/scripts/system/create/qml/Edit.qml b/scripts/system/create/qml/Edit.qml
index ca18388def..13e7874ca8 100644
--- a/scripts/system/create/qml/Edit.qml
+++ b/scripts/system/create/qml/Edit.qml
@@ -34,7 +34,7 @@ StackView {
     }
 
     function pushSource(path) {
-        var item = Qt.createComponent(Qt.resolvedUrl("../../" + path));
+        var item = Qt.createComponent(path);
         editRoot.push(item, itemProperties,
                       StackView.Immediate);
         editRoot.currentItem.sendToScript.connect(editRoot.sendToScript);
diff --git a/scripts/system/create/qml/NewModelDialog.qml b/scripts/system/create/qml/NewModelDialog.qml
index 92a08df10d..741902fa7f 100644
--- a/scripts/system/create/qml/NewModelDialog.qml
+++ b/scripts/system/create/qml/NewModelDialog.qml
@@ -135,19 +135,12 @@ Rectangle {
                     height: 400
                     spacing: 20
 
-                    Image {
-                        id: image1
-                        width: 30
-                        height: 30
-                        source: "qrc:/qtquickplugin/images/template_image.png"
-                    }
-
                     Text {
                         id: text2
                         width: 160
                         x: dynamic.width / 2
                         color: "#ffffff"
-                        text: qsTr("Models with automatic collisions set to 'Exact' cannot be dynamic, and should not be used as floors")
+                        text: qsTr("Models with automatic collisions set to 'Exact' cannot be dynamic.")
                         wrapMode: Text.WordWrap
                         font.pixelSize: 12
                     }