diff --git a/scripts/simplifiedUI/system/assets/images/icon-particles.svg b/scripts/simplifiedUI/system/assets/images/icon-particles.svg deleted file mode 100644 index 5e0105d7cd..0000000000 --- a/scripts/simplifiedUI/system/assets/images/icon-particles.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/icon-point-light.svg b/scripts/simplifiedUI/system/assets/images/icon-point-light.svg deleted file mode 100644 index 896c35b63b..0000000000 --- a/scripts/simplifiedUI/system/assets/images/icon-point-light.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/icon-spot-light.svg b/scripts/simplifiedUI/system/assets/images/icon-spot-light.svg deleted file mode 100644 index ac2f87bb27..0000000000 --- a/scripts/simplifiedUI/system/assets/images/icon-spot-light.svg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/simplifiedUI/system/assets/images/icon-zone.svg b/scripts/simplifiedUI/system/assets/images/icon-zone.svg deleted file mode 100644 index 41aeac4951..0000000000 --- a/scripts/simplifiedUI/system/assets/images/icon-zone.svg +++ /dev/null @@ -1,73 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/scripts/simplifiedUI/system/edit.js b/scripts/simplifiedUI/system/edit.js deleted file mode 100644 index cf99f3a618..0000000000 --- a/scripts/simplifiedUI/system/edit.js +++ /dev/null @@ -1,2858 +0,0 @@ -// 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/entitySelectionTool.js", - "libraries/ToolTip.js", - "libraries/entityCameraTool.js", - "libraries/gridTool.js", - "libraries/entityList.js", - "libraries/utils.js", - "libraries/entityIconOverlayManager.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("create/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("create/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("create/New" + entityType + "Dialog.qml")); - } else { - closeExistingDialogWindow(); - var qmlPath = Script.resolvePath("create/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("create/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/html/entityList.html b/scripts/simplifiedUI/system/html/entityList.html deleted file mode 100644 index 986e5c09b0..0000000000 --- a/scripts/simplifiedUI/system/html/entityList.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - Entity List - - - - - - - - - - - - - -
- -
- - -
- - - -
-
-
-
-
- -
-
-
- -
- - -
-
-
-
- Y -
- -
- - -
-
-
- - - - -
-
-
- -
-
-
- -
-
-
- There are no entities to display. Please check your filters or create an entity to begin. -
-
-
- - - diff --git a/scripts/simplifiedUI/system/html/entityProperties.html b/scripts/simplifiedUI/system/html/entityProperties.html deleted file mode 100644 index 67f03a33a2..0000000000 --- a/scripts/simplifiedUI/system/html/entityProperties.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - Properties - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/scripts/simplifiedUI/system/html/js/createAppTooltip.js b/scripts/simplifiedUI/system/html/js/createAppTooltip.js deleted file mode 100644 index 3eb206d8a3..0000000000 --- a/scripts/simplifiedUI/system/html/js/createAppTooltip.js +++ /dev/null @@ -1,116 +0,0 @@ -// 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/libraries/EditEntityList.qml b/scripts/simplifiedUI/system/libraries/EditEntityList.qml deleted file mode 100644 index 4fc5ff19ef..0000000000 --- a/scripts/simplifiedUI/system/libraries/EditEntityList.qml +++ /dev/null @@ -1,12 +0,0 @@ -import QtQuick 2.7 -import QtQuick.Controls 2.2 -import QtWebChannel 1.0 -import QtGraphicalEffects 1.0 -import "qrc:///qml/controls" as HifiControls - -HifiControls.WebView { - id: entityListToolWebView - url: Qt.resolvedUrl("../html/entityList.html") - enabled: true - blurOnCtrlShift: false -} diff --git a/scripts/simplifiedUI/system/libraries/entityList.js b/scripts/simplifiedUI/system/libraries/entityList.js deleted file mode 100644 index 585e4e06a5..0000000000 --- a/scripts/simplifiedUI/system/libraries/entityList.js +++ /dev/null @@ -1,330 +0,0 @@ -"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("../create/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/libraries/entitySelectionTool.js b/scripts/simplifiedUI/system/libraries/entitySelectionTool.js deleted file mode 100644 index 3fdc1d6652..0000000000 --- a/scripts/simplifiedUI/system/libraries/entitySelectionTool.js +++ /dev/null @@ -1,2925 +0,0 @@ -// -// 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([ - "./controllers.js", - "./controllerDispatcherUtils.js", - "./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/assets/images/hourglass.svg b/scripts/system/create/assets/images/hourglass.svg similarity index 100% rename from scripts/simplifiedUI/system/assets/images/hourglass.svg rename to scripts/system/create/assets/images/hourglass.svg diff --git a/scripts/system/create/edit.js b/scripts/system/create/edit.js index ae7cd43767..f50bc547e5 100644 --- a/scripts/system/create/edit.js +++ b/scripts/system/create/edit.js @@ -31,7 +31,7 @@ Script.include([ "../libraries/entityCameraTool.js", "../libraries/utils.js", "../libraries/entityIconOverlayManager.js", - "../libraries/gridTool/gridTool.js", + "../libraries/gridTool.js", "entityList/entityList.js", "entitySelectionTool/entitySelectionTool.js" ]); diff --git a/scripts/system/create/modules/entityShapeVisualizer.js b/scripts/system/create/modules/entityShapeVisualizer.js index da28369cdd..dbf09a1cb7 100644 --- a/scripts/system/create/modules/entityShapeVisualizer.js +++ b/scripts/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/system/create/qml/EditTabView.qml b/scripts/system/create/qml/EditTabView.qml index 4c780c3427..f90a962f7a 100644 --- a/scripts/system/create/qml/EditTabView.qml +++ b/scripts/system/create/qml/EditTabView.qml @@ -263,7 +263,7 @@ TabBar { property Component visualItem: Component { WebView { id: gridControlsWebView - url: Qt.resolvedURL("../../libraries/gridTool/html/gridControls.html") + url: Qt.resolvedURL("../../html/gridControls.html") enabled: true blurOnCtrlShift: false } diff --git a/scripts/system/create/qml/EditToolsTabView.qml b/scripts/system/create/qml/EditToolsTabView.qml index fdba4cdbc9..0ce8d8e8d4 100644 --- a/scripts/system/create/qml/EditToolsTabView.qml +++ b/scripts/system/create/qml/EditToolsTabView.qml @@ -253,7 +253,7 @@ TabBar { property Component visualItem: Component { WebView { id: gridControlsWebView - url: Qt.resolvedUrl("../../libraries/gridTool/html/gridControls.html") + url: Qt.resolvedUrl("../../html/gridControls.html") enabled: true blurOnCtrlShift: false } diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 5c7623066b..38287e3af3 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -17,7 +17,7 @@ var selectionDisplay = null; // for gridTool.js to ignore (function () { // BEGIN LOCAL_SCOPE var AppUi = Script.require('appUi'); -Script.include("/~/system/libraries/gridTool/gridTool.js"); +Script.include("/~/system/libraries/gridTool.js"); Script.include("/~/system/libraries/connectionUtils.js"); Script.include("/~/system/libraries/accountUtils.js");