From 5428192b2ef05902b079cac7c695ac8825922bda Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Tue, 12 Jul 2016 17:25:16 -0700 Subject: [PATCH 01/23] Add a few missing globals to .eslintrc file --- .eslintrc.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index a7f4291257..cb2d94360b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -28,6 +28,7 @@ module.exports = { "ModelCache": false, "MyAvatar": false, "Overlays": false, + "OverlayWebWindow": false, "Paths": false, "Quat": false, "Rates": false, @@ -42,6 +43,7 @@ module.exports = { "TextureCache": false, "Uuid": false, "UndoStack": false, + "UserActivityLogger": false, "Vec3": false, "WebSocket": false, "WebWindow": false, From ded82294f9775dad21271c8aacebfce5712f2042 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Tue, 12 Jul 2016 17:27:46 -0700 Subject: [PATCH 02/23] Bring edit.js up to the coding standard There were some serious bad practices going on there, I fixed them. There are still a few, but they are minimized. --- scripts/system/edit.js | 367 ++++++++++++++++++++++++----------------- 1 file changed, 217 insertions(+), 150 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 05d554393f..3bc54b898e 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -11,11 +11,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; +var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; var EDIT_TOGGLE_BUTTON = "com.highfidelity.interface.system.editButton"; -var SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system"; +var SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system"; var EDIT_TOOLBAR = "com.highfidelity.interface.toolbar.edit"; - + +/* globals SelectionDisplay, SelectionManager, LightOverlayManager, CameraManager, Grid, GridTool, EntityListTool, Toolbars, + progressDialog, tooltip, ParticleExplorerTool */ Script.include([ "libraries/stringHelpers.js", "libraries/dataViewHelpers.js", @@ -29,7 +31,7 @@ Script.include([ "libraries/gridTool.js", "libraries/entityList.js", "particle_explorer/particleExplorerTool.js", - "libraries/lightOverlayManager.js", + "libraries/lightOverlayManager.js" ]); var selectionDisplay = SelectionDisplay; @@ -39,15 +41,15 @@ var lightOverlayManager = new LightOverlayManager(); var cameraManager = new CameraManager(); -var grid = Grid(); -gridTool = GridTool({ +var grid = new Grid(); +var gridTool = new GridTool({ horizontalGrid: grid }); gridTool.setVisible(false); -var entityListTool = EntityListTool(); +var entityListTool = new EntityListTool(); -selectionManager.addEventListener(function() { +selectionManager.addEventListener(function () { selectionDisplay.updateHandles(); lightOverlayManager.updatePositions(); }); @@ -89,17 +91,16 @@ var SETTING_SHOW_ZONES_IN_EDIT_MODE = "showZonesInEditMode"; // 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 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 mode = 0; var isActive = false; -IMPORTING_SVO_OVERLAY_WIDTH = 144; -IMPORTING_SVO_OVERLAY_HEIGHT = 30; -IMPORTING_SVO_OVERLAY_MARGIN = 5; -IMPORTING_SVO_OVERLAY_LEFT_MARGIN = 34; - +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, @@ -107,7 +108,7 @@ var importingSVOImageOverlay = Overlays.addOverlay("image", { alpha: 1.0, x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH, y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT, - visible: false, + visible: false }); var importingSVOTextOverlay = Overlays.addOverlay("text", { font: { @@ -125,7 +126,7 @@ var importingSVOTextOverlay = Overlays.addOverlay("text", { blue: 80 }, backgroundAlpha: 0.7, - visible: false, + visible: false }); var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; @@ -163,14 +164,14 @@ function toggleMarketplace() { } } -var toolBar = (function() { +var toolBar = (function () { var EDIT_SETTING = "io.highfidelity.isEditting"; // for communication with other scripts var TOOL_ICON_URL = Script.resolvePath("assets/images/tools/"); var that = {}, toolBar, systemToolbar, activeButton; - + function createNewEntity(properties) { Settings.setValue(EDIT_SETTING, false); @@ -196,18 +197,18 @@ var toolBar = (function() { that.setActive(false); systemToolbar.removeButton(EDIT_TOGGLE_BUTTON); } - + function addButton(name, image, handler) { var imageUrl = TOOL_ICON_URL + image; var button = toolBar.addButton({ objectName: name, - imageURL: imageUrl, + imageURL: imageUrl, buttonState: 1, alpha: 0.9, - visible: true, + visible: true }); if (handler) { - button.clicked.connect(function() { + button.clicked.connect(function () { Script.setTimeout(handler, 100); }); } @@ -217,13 +218,13 @@ var toolBar = (function() { function initialize() { print("QQQ creating edit toolbar"); Script.scriptEnding.connect(cleanup); - - Window.domainChanged.connect(function() { + + Window.domainChanged.connect(function () { that.setActive(false); that.clearEntityList(); }); - Entities.canAdjustLocksChanged.connect(function(canAdjustLocks) { + Entities.canAdjustLocksChanged.connect(function (canAdjustLocks) { if (isActive && !canAdjustLocks) { that.setActive(false); } @@ -234,9 +235,9 @@ var toolBar = (function() { objectName: EDIT_TOGGLE_BUTTON, imageURL: TOOL_ICON_URL + "edit.svg", visible: true, - buttonState: 1, + buttonState: 1 }); - activeButton.clicked.connect(function() { + activeButton.clicked.connect(function () { that.setActive(!isActive); activeButton.writeProperty("buttonState", isActive ? 0 : 1); }); @@ -244,17 +245,73 @@ var toolBar = (function() { toolBar = Toolbars.getToolbar(EDIT_TOOLBAR); toolBar.writeProperty("shown", false); - addButton("newModelButton", "model-01.svg", function() { - var url = Window.prompt("Model URL"); - if (url !== null && url !== "") { - createNewEntity({ - type: "Model", - modelURL: url - }); + addButton("newModelButton", "model-01.svg", function () { + print("CREATE MODEL 1"); + var SHAPE_TYPE_NONE_TEXT = "No Collision"; + var SHAPE_TYPE_SIMPLE_HULL_TEXT = "Basic - Whole model"; + var SHAPE_TYPE_SIMPLE_COMPOUND_TEXT = "Good - Sub-meshes"; + var SHAPE_TYPE_STATIC_MESH_TEXT = "Exact - All polygons"; + var DYNAMIC_DEFAULT = false; + print("CREATE MODEL 2"); + var result = Window.customPrompt({ + textInput: { + label: "Model URL" + }, + comboBox: { + label: "Automatic Collisions", + items: [ + SHAPE_TYPE_NONE_TEXT, + SHAPE_TYPE_SIMPLE_HULL_TEXT, + SHAPE_TYPE_SIMPLE_COMPOUND_TEXT, + SHAPE_TYPE_STATIC_MESH_TEXT + ] + }, + checkBox: { + label: "Dynamic", + checked: DYNAMIC_DEFAULT, + disableForItems: [ + SHAPE_TYPE_STATIC_MESH_TEXT + ], + checkStateOnDisable: false, + warningOnDisable: "Models with automatic collisions set to 'Exact' cannot be dynamic" + } + }); + print("CREATE MODEL 3"); + print("RESULT = " + result); + + if (result) { + var url = result.textInput; + var shapeType; + switch (result.comboBox) { + case SHAPE_TYPE_SIMPLE_HULL_TEXT: + shapeType = "simple-hull"; + break; + case SHAPE_TYPE_SIMPLE_COMPOUND_TEXT: + shapeType = "simple-compound"; + break; + case SHAPE_TYPE_STATIC_MESH_TEXT: + shapeType = "static-mesh"; + break; + default: + shapeType = "none"; + } + + var dynamic = result.checkBox !== null ? result.checkBox : DYNAMIC_DEFAULT; + if (shapeType === "static-mesh" && dynamic) { + // The prompt should prevent this case + print("Error: model cannot be both static mesh and dynamic. This should never happen."); + } else if (url) { + createNewEntity({ + type: "Model", + modelURL: url, + shapeType: shapeType, + dynamic: dynamic + }); + } } }); - addButton("newCubeButton", "cube-01.svg", function() { + addButton("newCubeButton", "cube-01.svg", function () { createNewEntity({ type: "Box", dimensions: DEFAULT_DIMENSIONS, @@ -266,7 +323,7 @@ var toolBar = (function() { }); }); - addButton("newSphereButton", "sphere-01.svg", function() { + addButton("newSphereButton", "sphere-01.svg", function () { createNewEntity({ type: "Sphere", dimensions: DEFAULT_DIMENSIONS, @@ -278,7 +335,7 @@ var toolBar = (function() { }); }); - addButton("newLightButton", "light-01.svg", function() { + addButton("newLightButton", "light-01.svg", function () { createNewEntity({ type: "Light", dimensions: DEFAULT_LIGHT_DIMENSIONS, @@ -293,11 +350,11 @@ var toolBar = (function() { linearAttenuation: 0, quadraticAttenuation: 0, exponent: 0, - cutoff: 180, // in degrees + cutoff: 180 // in degrees }); }); - addButton("newTextButton", "text-01.svg", function() { + addButton("newTextButton", "text-01.svg", function () { createNewEntity({ type: "Text", dimensions: { @@ -320,7 +377,7 @@ var toolBar = (function() { }); }); - addButton("newWebButton", "web-01.svg", function() { + addButton("newWebButton", "web-01.svg", function () { createNewEntity({ type: "Web", dimensions: { @@ -328,26 +385,25 @@ var toolBar = (function() { y: 0.9, z: 0.01 }, - sourceUrl: "https://highfidelity.com/", + sourceUrl: "https://highfidelity.com/" }); }); - addButton("newZoneButton", "zone-01.svg", function() { + addButton("newZoneButton", "zone-01.svg", function () { createNewEntity({ type: "Zone", dimensions: { x: 10, y: 10, z: 10 - }, + } }); }); - addButton("newParticleButton", "particle-01.svg", function() { + addButton("newParticleButton", "particle-01.svg", function () { createNewEntity({ type: "ParticleEffect", isEmitting: true, - particleRadius: 0.1, emitAcceleration: { x: 0, y: -1, @@ -363,18 +419,18 @@ var toolBar = (function() { particleRadius: 0.025, alphaFinish: 0, emitRate: 100, - textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", + textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png" }); }); that.setActive(false); } - - that.clearEntityList = function() { + + that.clearEntityList = function () { entityListTool.clearEntityList(); }; - that.setActive = function(active) { + that.setActive = function (active) { if (active == isActive) { return; } @@ -397,7 +453,6 @@ var toolBar = (function() { selectionDisplay.triggerMapping.disable(); } else { UserActivityLogger.enabledEdit(); - hasShownPropertiesTool = false; entityListTool.setVisible(true); gridTool.setVisible(true); grid.setEnabled(true); @@ -410,11 +465,11 @@ var toolBar = (function() { // Sets visibility of tool buttons, excluding the power button toolBar.writeProperty("shown", active); var visible = toolBar.readProperty("visible"); - if (active && !visible) { + if (active && !visible) { toolBar.writeProperty("shown", false); toolBar.writeProperty("shown", true); } - //toolBar.selectTool(activeButton, isActive); + // toolBar.selectTool(activeButton, isActive); lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); }; @@ -624,8 +679,9 @@ function mouseReleaseEvent(event) { function mouseClickEvent(event) { var wantDebug = false; + var result, properties; if (isActive && event.isLeftButton) { - var result = findClickedEntity(event); + result = findClickedEntity(event); if (result === null) { if (!event.isShifted) { selectionManager.clearSelections(); @@ -636,7 +692,7 @@ function mouseClickEvent(event) { var pickRay = result.pickRay; var foundEntity = result.entityID; - var properties = Entities.getEntityProperties(foundEntity); + properties = Entities.getEntityProperties(foundEntity); if (isLocked(properties)) { if (wantDebug) { print("Model locked " + properties.id); @@ -663,16 +719,14 @@ function mouseClickEvent(event) { var P = properties.position; var x = Vec3.dot(Vec3.subtract(P, A), B); - var X = Vec3.sum(A, Vec3.multiply(B, x)); - var d = Vec3.length(Vec3.subtract(P, X)); - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; + var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * + 180 / 3.14; - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); + var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && + (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); if (0 < x && sizeOK) { - entitySelected = true; selectedEntityID = foundEntity; orientation = MyAvatar.orientation; intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation)); @@ -697,12 +751,12 @@ function mouseClickEvent(event) { } } } else if (event.isRightButton) { - var result = findClickedEntity(event); + result = findClickedEntity(event); if (result) { if (SHOULD_SHOW_PROPERTY_MENU !== true) { return; } - var properties = Entities.getEntityProperties(result.entityID); + properties = Entities.getEntityProperties(result.entityID); if (properties.marketplaceID) { propertyMenu.marketplaceID = properties.marketplaceID; propertyMenu.updateMenuItemText(showMenuItem, "Show in Marketplace"); @@ -885,7 +939,7 @@ function cleanupModelMenus() { Menu.removeMenuItem("Edit", MENU_SHOW_ZONES_IN_EDIT_MODE); } -Script.scriptEnding.connect(function() { +Script.scriptEnding.connect(function () { 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_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); @@ -905,7 +959,7 @@ var lastOrientation = null; var lastPosition = null; // Do some stuff regularly, like check for placement of various overlays -Script.update.connect(function(deltaTime) { +Script.update.connect(function (deltaTime) { progressDialog.move(); selectionDisplay.checkMove(); var dOrientation = Math.abs(Quat.dot(Camera.orientation, lastOrientation) - 1); @@ -922,7 +976,9 @@ Script.update.connect(function(deltaTime) { }); 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)); + 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 selectAllEtitiesInCurrentSelectionBox(keepIfTouching) { @@ -935,11 +991,11 @@ function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) { if (!keepIfTouching) { var isValid; if (selectionManager.localPosition === null) { - isValid = function(position) { + isValid = function (position) { return insideBox(selectionManager.worldPosition, selectionManager.worldDimensions, position); - } + }; } else { - isValid = function(position) { + isValid = function (position) { var localPosition = Vec3.multiplyQbyV(Quat.inverse(selectionManager.localRotation), Vec3.subtract(position, selectionManager.localPosition)); @@ -948,7 +1004,7 @@ function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) { y: 0, z: 0 }, selectionManager.localDimensions, localPosition); - } + }; } for (var i = 0; i < entities.length; ++i) { var properties = Entities.getEntityProperties(entities[i]); @@ -1026,7 +1082,7 @@ function handeMenuEvent(menuItem) { if (!selectionManager.hasSelection()) { Window.alert("No entities have been selected."); } else { - var filename = Window.save("Select Where to Save", "", "*.json") + var filename = Window.save("Select Where to Save", "", "*.json"); if (filename) { var success = Clipboard.exportEntities(filename, selectionManager.selections); if (!success) { @@ -1076,8 +1132,11 @@ function getPositionToCreateEntity() { var HALF_TREE_SCALE = 16384; - var cameraOutOfBounds = Math.abs(cameraPosition.x) > HALF_TREE_SCALE || Math.abs(cameraPosition.y) > HALF_TREE_SCALE || Math.abs(cameraPosition.z) > HALF_TREE_SCALE; - var placementOutOfBounds = Math.abs(placementPosition.x) > HALF_TREE_SCALE || Math.abs(placementPosition.y) > HALF_TREE_SCALE || Math.abs(placementPosition.z) > HALF_TREE_SCALE; + var cameraOutOfBounds = Math.abs(cameraPosition.x) > HALF_TREE_SCALE || Math.abs(cameraPosition.y) > HALF_TREE_SCALE || + Math.abs(cameraPosition.z) > HALF_TREE_SCALE; + var placementOutOfBounds = Math.abs(placementPosition.x) > HALF_TREE_SCALE || + Math.abs(placementPosition.y) > HALF_TREE_SCALE || + Math.abs(placementPosition.z) > HALF_TREE_SCALE; if (cameraOutOfBounds && placementOutOfBounds) { return null; @@ -1091,7 +1150,7 @@ function getPositionToCreateEntity() { } function importSVO(importURL) { - print("Import URL requested: " + importURL) + print("Import URL requested: " + importURL); if (!Entities.canAdjustLocks()) { Window.alert(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); return; @@ -1142,13 +1201,13 @@ Window.svoImportRequested.connect(importSVO); Menu.menuItemEvent.connect(handeMenuEvent); -Controller.keyPressEvent.connect(function(event) { +Controller.keyPressEvent.connect(function (event) { if (isActive) { cameraManager.keyPressEvent(event); } }); -Controller.keyReleaseEvent.connect(function(event) { +Controller.keyReleaseEvent.connect(function (event) { if (isActive) { cameraManager.keyReleaseEvent(event); } @@ -1188,30 +1247,31 @@ Controller.keyReleaseEvent.connect(function(event) { // 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. -DELETED_ENTITY_MAP = {} +var DELETED_ENTITY_MAP = {}; function applyEntityProperties(data) { var properties = data.setProperties; var selectedEntityIDs = []; - for (var i = 0; i < properties.length; i++) { - var entityID = properties[i].entityID; + var i, entityID; + for (i = 0; i < properties.length; i++) { + entityID = properties[i].entityID; if (DELETED_ENTITY_MAP[entityID] !== undefined) { entityID = DELETED_ENTITY_MAP[entityID]; } Entities.editEntity(entityID, properties[i].properties); selectedEntityIDs.push(entityID); } - for (var i = 0; i < data.createEntities.length; i++) { - var entityID = data.createEntities[i].entityID; - var properties = data.createEntities[i].properties; - var newEntityID = Entities.addEntity(properties); + for (i = 0; i < data.createEntities.length; i++) { + entityID = data.createEntities[i].entityID; + var entityProperties = data.createEntities[i].properties; + var newEntityID = Entities.addEntity(entityProperties); DELETED_ENTITY_MAP[entityID] = newEntityID; if (data.selectCreated) { selectedEntityIDs.push(newEntityID); } } - for (var i = 0; i < data.deleteEntities.length; i++) { - var entityID = data.deleteEntities[i].entityID; + for (i = 0; i < data.deleteEntities.length; i++) { + entityID = data.deleteEntities[i].entityID; if (DELETED_ENTITY_MAP[entityID] !== undefined) { entityID = DELETED_ENTITY_MAP[entityID]; } @@ -1219,7 +1279,7 @@ function applyEntityProperties(data) { } selectionManager.setSelections(selectedEntityIDs); -}; +} // 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. @@ -1228,13 +1288,13 @@ function pushCommandForSelections(createdEntityData, deletedEntityData) { setProperties: [], createEntities: deletedEntityData || [], deleteEntities: createdEntityData || [], - selectCreated: true, + selectCreated: true }; var redoData = { setProperties: [], createEntities: createdEntityData || [], deleteEntities: deletedEntityData || [], - selectCreated: false, + selectCreated: false }; for (var i = 0; i < SelectionManager.selections.length; i++) { var entityID = SelectionManager.selections[i]; @@ -1248,22 +1308,22 @@ function pushCommandForSelections(createdEntityData, deletedEntityData) { properties: { position: initialProperties.position, rotation: initialProperties.rotation, - dimensions: initialProperties.dimensions, - }, + dimensions: initialProperties.dimensions + } }); redoData.setProperties.push({ entityID: entityID, properties: { position: currentProperties.position, rotation: currentProperties.rotation, - dimensions: currentProperties.dimensions, - }, + dimensions: currentProperties.dimensions + } }); } UndoStack.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData); } -PropertiesTool = function(opts) { +var PropertiesTool = function (opts) { var that = {}; var url = Script.resolvePath('html/entityProperties.html'); @@ -1277,14 +1337,14 @@ PropertiesTool = function(opts) { webView.setVisible(visible); - that.setVisible = function(newVisible) { + that.setVisible = function (newVisible) { visible = newVisible; webView.setVisible(visible); }; - selectionManager.addEventListener(function() { - data = { - type: 'update', + selectionManager.addEventListener(function () { + var data = { + type: 'update' }; var selections = []; for (var i = 0; i < selectionManager.selections.length; i++) { @@ -1295,7 +1355,8 @@ PropertiesTool = function(opts) { entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation); } if (entity.properties.keyLight !== undefined && entity.properties.keyLight.direction !== undefined) { - entity.properties.keyLight.direction = Vec3.multiply(RADIANS_TO_DEGREES, Vec3.toPolar(entity.properties.keyLight.direction)); + entity.properties.keyLight.direction = Vec3.multiply(RADIANS_TO_DEGREES, + Vec3.toPolar(entity.properties.keyLight.direction)); entity.properties.keyLight.direction.z = 0.0; } selections.push(entity); @@ -1304,8 +1365,9 @@ PropertiesTool = function(opts) { webView.emitScriptEvent(JSON.stringify(data)); }); - webView.webEventReceived.connect(function(data) { + webView.webEventReceived.connect(function (data) { data = JSON.parse(data); + var i, properties, dY, diff, newPosition; if (data.type == "print") { if (data.message) { print(data.message); @@ -1315,9 +1377,9 @@ PropertiesTool = function(opts) { if (selectionManager.selections.length > 1) { properties = { locked: data.properties.locked, - visible: data.properties.visible, + visible: data.properties.visible }; - for (var i = 0; i < selectionManager.selections.length; i++) { + for (i = 0; i < selectionManager.selections.length; i++) { Entities.editEntity(selectionManager.selections[i], properties); } } else { @@ -1340,10 +1402,13 @@ PropertiesTool = function(opts) { } if (data.properties.keyLight !== undefined && data.properties.keyLight.direction !== undefined) { data.properties.keyLight.direction = Vec3.fromPolar( - data.properties.keyLight.direction.x * DEGREES_TO_RADIANS, data.properties.keyLight.direction.y * DEGREES_TO_RADIANS); + data.properties.keyLight.direction.x * DEGREES_TO_RADIANS, + data.properties.keyLight.direction.y * DEGREES_TO_RADIANS + ); } Entities.editEntity(selectionManager.selections[0], data.properties); - if (data.properties.name !== undefined || data.properties.modelURL !== undefined || data.properties.visible !== undefined || data.properties.locked !== undefined) { + if (data.properties.name !== undefined || data.properties.modelURL !== undefined || + data.properties.visible !== undefined || data.properties.locked !== undefined) { entityListTool.sendUpdate(); } } @@ -1355,17 +1420,17 @@ PropertiesTool = function(opts) { if (data.action == "moveSelectionToGrid") { if (selectionManager.hasSelection()) { selectionManager.saveProperties(); - var dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2); - var diff = { + dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2); + diff = { x: 0, y: dY, z: 0 }; - for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i]]; - var newPosition = Vec3.sum(properties.position, diff); + 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, + position: newPosition }); } pushCommandForSelections(); @@ -1374,18 +1439,18 @@ PropertiesTool = function(opts) { } else if (data.action == "moveAllToGrid") { if (selectionManager.hasSelection()) { selectionManager.saveProperties(); - for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i]]; + 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; - var dY = grid.getOrigin().y - bottomY; - var diff = { + dY = grid.getOrigin().y - bottomY; + diff = { x: 0, y: dY, z: 0 }; - var newPosition = Vec3.sum(properties.position, diff); + newPosition = Vec3.sum(properties.position, diff); Entities.editEntity(selectionManager.selections[i], { - position: newPosition, + position: newPosition }); } pushCommandForSelections(); @@ -1394,16 +1459,18 @@ PropertiesTool = function(opts) { } else if (data.action == "resetToNaturalDimensions") { if (selectionManager.hasSelection()) { selectionManager.saveProperties(); - for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i]]; + 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.alert("Cannot reset entity to its natural dimensions: Model URL" + " is invalid or the model has not yet been loaded."); + if (properties.type == "Model" && naturalDimensions.x == 0 && naturalDimensions.y == 0 && + naturalDimensions.z == 0) { + Window.alert("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, + dimensions: properties.naturalDimensions }); } } @@ -1419,10 +1486,10 @@ PropertiesTool = function(opts) { var multiplier = data.percentage / 100; if (selectionManager.hasSelection()) { selectionManager.saveProperties(); - for (var i = 0; i < selectionManager.selections.length; i++) { - var properties = selectionManager.savedProperties[selectionManager.selections[i]]; + 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), + dimensions: Vec3.multiply(multiplier, properties.dimensions) }); } pushCommandForSelections(); @@ -1431,9 +1498,9 @@ PropertiesTool = function(opts) { } else if (data.action == "reloadScript") { if (selectionManager.hasSelection()) { var timestamp = Date.now(); - for (var i = 0; i < selectionManager.selections.length; i++) { + for (i = 0; i < selectionManager.selections.length; i++) { Entities.editEntity(selectionManager.selections[i], { - scriptTimestamp: timestamp, + scriptTimestamp: timestamp }); } } @@ -1444,7 +1511,7 @@ PropertiesTool = function(opts) { return that; }; -PopupMenu = function() { +var PopupMenu = function () { var self = this; var MENU_ITEM_HEIGHT = 21; @@ -1470,9 +1537,9 @@ PopupMenu = function() { blue: 128 }; - self.onSelectMenuItem = function() {}; + self.onSelectMenuItem = function () {}; - self.addMenuItem = function(name) { + self.addMenuItem = function (name) { var id = Overlays.addOverlay("text", { text: name, backgroundAlpha: 1.0, @@ -1484,7 +1551,7 @@ PopupMenu = function() { font: { size: 12 }, - visible: false, + visible: false }); overlays.push(id); overlayInfo[id] = { @@ -1493,28 +1560,28 @@ PopupMenu = function() { return id; }; - self.updateMenuItemText = function(id, newText) { + self.updateMenuItemText = function (id, newText) { Overlays.editOverlay(id, { text: newText }); }; - self.setPosition = function(x, y) { + self.setPosition = function (x, y) { for (var key in overlayInfo) { Overlays.editOverlay(key, { x: x, - y: y, + y: y }); y += MENU_ITEM_HEIGHT + MENU_ITEM_SPACING; } }; - self.onSelected = function() {}; + self.onSelected = function () {}; var pressingOverlay = null; var hoveringOverlay = null; - self.mousePressEvent = function(event) { + self.mousePressEvent = function (event) { if (event.isLeftButton) { var overlay = Overlays.getOverlayAtPoint({ x: event.x, @@ -1531,7 +1598,7 @@ PopupMenu = function() { return false; } }; - self.mouseMoveEvent = function(event) { + self.mouseMoveEvent = function (event) { if (visible) { var overlay = Overlays.getOverlayAtPoint({ x: event.x, @@ -1554,7 +1621,7 @@ PopupMenu = function() { } return false; }; - self.mouseReleaseEvent = function(event) { + self.mouseReleaseEvent = function (event) { var overlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y @@ -1573,7 +1640,7 @@ PopupMenu = function() { var visible = false; - self.setVisible = function(newVisible) { + self.setVisible = function (newVisible) { if (newVisible != visible) { visible = newVisible; for (var key in overlayInfo) { @@ -1582,13 +1649,13 @@ PopupMenu = function() { }); } } - } - self.show = function() { + }; + self.show = function () { self.setVisible(true); - } - self.hide = function() { + }; + self.hide = function () { self.setVisible(false); - } + }; function cleanup() { for (var i = 0; i < overlays.length; i++) { @@ -1605,9 +1672,9 @@ PopupMenu = function() { }; -var propertyMenu = PopupMenu(); +var propertyMenu = new PopupMenu(); -propertyMenu.onSelectMenuItem = function(name) { +propertyMenu.onSelectMenuItem = function (name) { if (propertyMenu.marketplaceID) { showMarketplace(propertyMenu.marketplaceID); @@ -1616,11 +1683,11 @@ propertyMenu.onSelectMenuItem = function(name) { var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace"); -propertiesTool = PropertiesTool(); -var particleExplorerTool = ParticleExplorerTool(); +var propertiesTool = new PropertiesTool(); +var particleExplorerTool = new ParticleExplorerTool(); var selectedParticleEntity = 0; -entityListTool.webView.webEventReceived.connect(function(data) { - var data = JSON.parse(data); +entityListTool.webView.webEventReceived.connect(function (data) { + data = JSON.parse(data); if (data.type == "selectionUpdate") { var ids = data.entityIds; if (ids.length === 1) { @@ -1640,8 +1707,8 @@ entityListTool.webView.webEventReceived.connect(function(data) { selectedParticleEntity = ids[0]; particleExplorerTool.setActiveParticleEntity(ids[0]); - particleExplorerTool.webView.webEventReceived.connect(function(data) { - var data = JSON.parse(data); + particleExplorerTool.webView.webEventReceived.connect(function (data) { + data = JSON.parse(data); if (data.messageType === "page_loaded") { particleExplorerTool.webView.emitScriptEvent(JSON.stringify(particleData)); } From 6417bb18593b1aff391ed1f6faa5fe043fca6622 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Wed, 13 Jul 2016 16:03:44 -0700 Subject: [PATCH 03/23] Require tripple equals over double, fix in edit.js --- .eslintrc.js | 1 + scripts/system/edit.js | 96 +++++++++++++++++++++--------------------- 2 files changed, 49 insertions(+), 48 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index cb2d94360b..a62d72299b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -57,6 +57,7 @@ module.exports = { "comma-dangle": ["error", "never"], "camelcase": ["error"], "curly": ["error", "all"], + "eqeqeq": ["error", "always"], "indent": ["error", 4, { "SwitchCase": 1 }], "keyword-spacing": ["error", { "before": true, "after": true }], "max-len": ["error", 128, 4], diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 3bc54b898e..a32bba765e 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -178,7 +178,7 @@ var toolBar = (function () { var dimensions = properties.dimensions ? properties.dimensions : DEFAULT_DIMENSIONS; var position = getPositionToCreateEntity(); var entityID = null; - if (position != null) { + if (position !== null && position !== undefined) { position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions), properties.position = position; entityID = Entities.addEntity(properties); @@ -431,7 +431,7 @@ var toolBar = (function () { }; that.setActive = function (active) { - if (active == isActive) { + if (active === isActive) { return; } if (active && !Entities.canRez() && !Entities.canRezTmp()) { @@ -481,8 +481,8 @@ var toolBar = (function () { function isLocked(properties) { // special case to lock the ground plane model in hq. - if (location.hostname == "hq.highfidelity.io" && - properties.modelURL == HIFI_PUBLIC_BUCKET + "ozan/Terrain_Reduce_forAlpha.fbx") { + if (location.hostname === "hq.highfidelity.io" && + properties.modelURL === HIFI_PUBLIC_BUCKET + "ozan/Terrain_Reduce_forAlpha.fbx") { return true; } return false; @@ -682,7 +682,7 @@ function mouseClickEvent(event) { var result, properties; if (isActive && event.isLeftButton) { result = findClickedEntity(event); - if (result === null) { + if (result === null || result === undefined) { if (!event.isShifted) { selectionManager.clearSelections(); } @@ -711,7 +711,7 @@ function mouseClickEvent(event) { // x x - distance from A // // |X-A| = (P-A).B - // X == A + ((P-A).B)B + // X === A + ((P-A).B)B // d = |P-X| var A = pickRay.origin; @@ -882,7 +882,7 @@ function setupModelMenus() { menuName: "Edit", menuItemName: MENU_AUTO_FOCUS_ON_SELECT, isCheckable: true, - isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true", + isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) === "true", grouping: "Advanced" }); Menu.addMenuItem({ @@ -890,7 +890,7 @@ function setupModelMenus() { menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_AUTO_FOCUS_ON_SELECT, isCheckable: true, - isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true", + isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) === "true", grouping: "Advanced" }); Menu.addMenuItem({ @@ -898,7 +898,7 @@ function setupModelMenus() { menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE, afterItem: MENU_EASE_ON_FOCUS, isCheckable: true, - isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) == "true", + isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) === "true", grouping: "Advanced" }); Menu.addMenuItem({ @@ -906,7 +906,7 @@ function setupModelMenus() { menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE, afterItem: MENU_SHOW_LIGHTS_IN_EDIT_MODE, isCheckable: true, - isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) == "true", + isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) === "true", grouping: "Advanced" }); @@ -990,7 +990,7 @@ function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) { if (!keepIfTouching) { var isValid; - if (selectionManager.localPosition === null) { + if (selectionManager.localPosition === null || selectionManager.localPosition === undefined) { isValid = function (position) { return insideBox(selectionManager.worldPosition, selectionManager.worldDimensions, position); }; @@ -1070,15 +1070,15 @@ function toggleSelectedEntitiesVisible() { } function handeMenuEvent(menuItem) { - if (menuItem == "Allow Selecting of Small Models") { + if (menuItem === "Allow Selecting of Small Models") { allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models"); - } else if (menuItem == "Allow Selecting of Large Models") { + } else if (menuItem === "Allow Selecting of Large Models") { allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models"); - } else if (menuItem == "Allow Selecting of Lights") { + } else if (menuItem === "Allow Selecting of Lights") { Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); - } else if (menuItem == "Delete") { + } else if (menuItem === "Delete") { deleteSelectedEntities(); - } else if (menuItem == "Export Entities") { + } else if (menuItem === "Export Entities") { if (!selectionManager.hasSelection()) { Window.alert("No entities have been selected."); } else { @@ -1090,10 +1090,10 @@ function handeMenuEvent(menuItem) { } } } - } else if (menuItem == "Import Entities" || menuItem == "Import Entities from URL") { + } else if (menuItem === "Import Entities" || menuItem === "Import Entities from URL") { var importURL = null; - if (menuItem == "Import Entities") { + if (menuItem === "Import Entities") { var fullPath = Window.browse("Select Model to Import", "", "*.json"); if (fullPath) { importURL = "file:///" + fullPath; @@ -1105,15 +1105,15 @@ function handeMenuEvent(menuItem) { if (importURL) { importSVO(importURL); } - } else if (menuItem == "Entity List...") { + } else if (menuItem === "Entity List...") { entityListTool.toggleVisible(); - } else if (menuItem == "Select All Entities In Box") { + } else if (menuItem === "Select All Entities In Box") { selectAllEtitiesInCurrentSelectionBox(false); - } else if (menuItem == "Select All Entities Touching Box") { + } else if (menuItem === "Select All Entities Touching Box") { selectAllEtitiesInCurrentSelectionBox(true); - } else if (menuItem == MENU_SHOW_LIGHTS_IN_EDIT_MODE) { + } else if (menuItem === MENU_SHOW_LIGHTS_IN_EDIT_MODE) { lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE)); - } else if (menuItem == MENU_SHOW_ZONES_IN_EDIT_MODE) { + } else if (menuItem === MENU_SHOW_ZONES_IN_EDIT_MODE) { Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); } tooltip.show(false); @@ -1175,7 +1175,7 @@ function importSVO(importURL) { if (Clipboard.getClipboardContentsLargestDimension() < VERY_LARGE) { position = getPositionToCreateEntity(); } - if (position != null) { + if (position !== null && position !== undefined) { var pastedEntityIDs = Clipboard.pasteEntities(position); if (isActive) { @@ -1212,13 +1212,13 @@ Controller.keyReleaseEvent.connect(function (event) { cameraManager.keyReleaseEvent(event); } // since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items - if (event.text == "BACKSPACE" || event.text == "DELETE") { + if (event.text === "BACKSPACE" || event.text === "DELETE") { deleteSelectedEntities(); - } else if (event.text == "ESC") { + } else if (event.text === "ESC") { selectionManager.clearSelections(); - } else if (event.text == "TAB") { + } else if (event.text === "TAB") { selectionDisplay.toggleSpaceMode(); - } else if (event.text == "f") { + } else if (event.text === "f") { if (isActive) { if (selectionManager.hasSelection()) { cameraManager.enable(); @@ -1227,11 +1227,11 @@ Controller.keyReleaseEvent.connect(function (event) { Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); } } - } else if (event.text == '[') { + } else if (event.text === '[') { if (isActive) { cameraManager.enable(); } - } else if (event.text == 'g') { + } else if (event.text === 'g') { if (isActive && selectionManager.hasSelection()) { var newPosition = selectionManager.worldPosition; newPosition = Vec3.subtract(newPosition, { @@ -1368,11 +1368,11 @@ var PropertiesTool = function (opts) { webView.webEventReceived.connect(function (data) { data = JSON.parse(data); var i, properties, dY, diff, newPosition; - if (data.type == "print") { + if (data.type === "print") { if (data.message) { print(data.message); } - } else if (data.type == "update") { + } else if (data.type === "update") { selectionManager.saveProperties(); if (selectionManager.selections.length > 1) { properties = { @@ -1414,10 +1414,10 @@ var PropertiesTool = function (opts) { } pushCommandForSelections(); selectionManager._update(); - } else if (data.type == "showMarketplace") { + } else if (data.type === "showMarketplace") { showMarketplace(); - } else if (data.type == "action") { - if (data.action == "moveSelectionToGrid") { + } 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); @@ -1436,7 +1436,7 @@ var PropertiesTool = function (opts) { pushCommandForSelections(); selectionManager._update(); } - } else if (data.action == "moveAllToGrid") { + } else if (data.action === "moveAllToGrid") { if (selectionManager.hasSelection()) { selectionManager.saveProperties(); for (i = 0; i < selectionManager.selections.length; i++) { @@ -1456,7 +1456,7 @@ var PropertiesTool = function (opts) { pushCommandForSelections(); selectionManager._update(); } - } else if (data.action == "resetToNaturalDimensions") { + } else if (data.action === "resetToNaturalDimensions") { if (selectionManager.hasSelection()) { selectionManager.saveProperties(); for (i = 0; i < selectionManager.selections.length; i++) { @@ -1464,8 +1464,8 @@ var PropertiesTool = function (opts) { 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) { + if (properties.type === "Model" && naturalDimensions.x === 0 && naturalDimensions.y === 0 && + naturalDimensions.z === 0) { Window.alert("Cannot reset entity to its natural dimensions: Model URL" + " is invalid or the model has not yet been loaded."); } else { @@ -1477,12 +1477,12 @@ var PropertiesTool = function (opts) { pushCommandForSelections(); selectionManager._update(); } - } else if (data.action == "previewCamera") { + } else if (data.action === "previewCamera") { if (selectionManager.hasSelection()) { Camera.mode = "entity"; Camera.cameraEntity = selectionManager.selections[0]; } - } else if (data.action == "rescaleDimensions") { + } else if (data.action === "rescaleDimensions") { var multiplier = data.percentage / 100; if (selectionManager.hasSelection()) { selectionManager.saveProperties(); @@ -1495,7 +1495,7 @@ var PropertiesTool = function (opts) { pushCommandForSelections(); selectionManager._update(); } - } else if (data.action == "reloadScript") { + } else if (data.action === "reloadScript") { if (selectionManager.hasSelection()) { var timestamp = Date.now(); for (i = 0; i < selectionManager.selections.length; i++) { @@ -1605,13 +1605,13 @@ var PopupMenu = function () { y: event.y }); if (!pressingOverlay) { - if (hoveringOverlay != null && overlay != hoveringOverlay) { + if (hoveringOverlay !== null && hoveringOverlay !== null && overlay !== hoveringOverlay) { Overlays.editOverlay(hoveringOverlay, { backgroundColor: upColor }); hoveringOverlay = null; } - if (overlay != hoveringOverlay && overlay in overlayInfo) { + if (overlay !== hoveringOverlay && overlay in overlayInfo) { Overlays.editOverlay(overlay, { backgroundColor: overColor }); @@ -1626,8 +1626,8 @@ var PopupMenu = function () { x: event.x, y: event.y }); - if (pressingOverlay != null) { - if (overlay == pressingOverlay) { + if (pressingOverlay !== null && pressingOverlay !== undefined) { + if (overlay === pressingOverlay) { self.onSelectMenuItem(overlayInfo[overlay].name); } Overlays.editOverlay(pressingOverlay, { @@ -1641,7 +1641,7 @@ var PopupMenu = function () { var visible = false; self.setVisible = function (newVisible) { - if (newVisible != visible) { + if (newVisible !== visible) { visible = newVisible; for (var key in overlayInfo) { Overlays.editOverlay(key, { @@ -1688,7 +1688,7 @@ var particleExplorerTool = new ParticleExplorerTool(); var selectedParticleEntity = 0; entityListTool.webView.webEventReceived.connect(function (data) { data = JSON.parse(data); - if (data.type == "selectionUpdate") { + if (data.type === "selectionUpdate") { var ids = data.entityIds; if (ids.length === 1) { if (Entities.getEntityProperties(ids[0], "type").type === "ParticleEffect") { From 71f62c02fc326b8aa0fe8c2ccda0ea69bf8fd56a Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Fri, 15 Jul 2016 11:20:26 -0700 Subject: [PATCH 04/23] Add basic implementation of customPrompt Still missing the warning and diabling of dynamic checkbox when the static mesh is selected. --- interface/resources/qml/desktop/Desktop.qml | 19 +- .../qml/dialogs/CustomQueryDialog.qml | 237 ++++++++++++++++++ interface/src/Application.cpp | 1 + .../scripting/WindowScriptingInterface.cpp | 22 ++ .../src/scripting/WindowScriptingInterface.h | 13 + libraries/ui/src/OffscreenUi.cpp | 48 ++++ libraries/ui/src/OffscreenUi.h | 3 + 7 files changed, 336 insertions(+), 7 deletions(-) create mode 100644 interface/resources/qml/dialogs/CustomQueryDialog.qml diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index e5ff849df8..ea2f048c1f 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -35,7 +35,7 @@ FocusScope { } onHeightChanged: d.handleSizeChanged(); - + onWidthChanged: d.handleSizeChanged(); // Controls and windows can trigger this signal to ensure the desktop becomes visible @@ -70,8 +70,8 @@ FocusScope { } var oldRecommendedRect = recommendedRect; var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect(); - var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y, - newRecommendedRectJS.width, + var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y, + newRecommendedRectJS.width, newRecommendedRectJS.height); var oldChildren = expectedChildren; @@ -366,8 +366,8 @@ FocusScope { } var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect(); - var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y, - newRecommendedRectJS.width, + var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y, + newRecommendedRectJS.width, newRecommendedRectJS.height); var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height }; var newX = newRecommendedRect.x + ((newRecommendedRect.width - targetWindow.width) / 2); @@ -402,7 +402,7 @@ FocusScope { repositionWindow(targetWindow, false, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions); } - function repositionWindow(targetWindow, forceReposition, + function repositionWindow(targetWindow, forceReposition, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions) { if (desktop.width === 0 || desktop.height === 0) { @@ -456,6 +456,11 @@ FocusScope { return inputDialogBuilder.createObject(desktop, properties); } + Component { id: customInputDialogBuilder; CustomQueryDialog { } } + function customInputDialog(properties) { + return customInputDialogBuilder.createObject(desktop, properties); + } + Component { id: fileDialogBuilder; FileDialog { } } function fileDialog(properties) { return fileDialogBuilder.createObject(desktop, properties); @@ -487,7 +492,7 @@ FocusScope { } function unfocusWindows() { - // First find the active focus item, and unfocus it, all the way + // First find the active focus item, and unfocus it, all the way // up the parent chain to the window var currentFocus = offscreenWindow.activeFocusItem; var targetWindow = d.getDesktopWindow(currentFocus); diff --git a/interface/resources/qml/dialogs/CustomQueryDialog.qml b/interface/resources/qml/dialogs/CustomQueryDialog.qml new file mode 100644 index 0000000000..3f2bab010f --- /dev/null +++ b/interface/resources/qml/dialogs/CustomQueryDialog.qml @@ -0,0 +1,237 @@ +// +// CustomQueryDialog.qml +// +// Created by Zander Otavka on 7/14/16 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5; +import QtQuick.Controls 1.4; +import QtQuick.Dialogs 1.2 as OriginalDialogs; + +import "../controls-uit"; +import "../styles-uit"; +import "../windows"; + +ModalWindow { + id: root; + HifiConstants { id: hifi; } + implicitWidth: 640; + implicitHeight: 320; + visible: true; + + signal selected(var result); + signal canceled(); + + property int icon: hifi.icons.none; + property string iconText: ""; + property int iconSize: 35; + onIconChanged: updateIcon(); + + property var textInput; + property var comboBox; + property var checkBox; + + property var result; + property alias current: textField.text; + + // For text boxes + property alias placeholderText: textField.placeholderText; + + // For combo boxes + property bool editable: true; + + property int titleWidth: 0; + onTitleWidthChanged: d.resize(); + + function updateIcon() { + if (!root) { + return; + } + iconText = hifi.glyphForIcon(root.icon); + } + + Item { + clip: true; + width: pane.width; + height: pane.height; + anchors.margins: 0; + + QtObject { + id: d; + readonly property int minWidth: 480; + readonly property int maxWdith: 1280; + readonly property int minHeight: 120; + readonly property int maxHeight: 720; + + function resize() { + var targetWidth = Math.max(titleWidth, pane.width); + var targetHeight = (textInput ? textField.controlHeight : 0) + extraInputs.height + + (6 * hifi.dimensions.contentSpacing.y) + buttons.height; + // var targetHeight = 720; + print("CQD extraInputs.height = " + extraInputs.height); + print("CQD textField.controlHeight = " + textField.controlHeight); + print("CQD buttons.height = " + buttons.height); + print("CQD targetHeight = " + targetHeight); + root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth); + root.height = (targetHeight < d.minHeight) ? d.minHeight: ((targetHeight > d.maxHeight) ? + d.maxHeight : targetHeight); + print("CQD comboBoxField.visible = " + comboBoxField.visible); + if (comboBoxField.visible) { + print("CQD parent = " + parent); + comboBoxField.width = extraInputs.width / 2; + } + } + } + + Item { + anchors { + top: parent.top; + bottom: extraInputs.top; + left: parent.left; + right: parent.right; + margins: 0; + bottomMargin: 2 * hifi.dimensions.contentSpacing.y; + } + + // FIXME make a text field type that can be bound to a history for autocompletion + TextField { + id: textField; + label: root.textInput.label; + focus: root.textInput ? true : false; + visible: root.textInput ? true : false; + anchors { + left: parent.left; + right: parent.right; + bottom: parent.bottom; + } + } + } + + Row { + id: extraInputs; + spacing: hifi.dimensions.contentSpacing.x; + anchors { + left: parent.left; + right: parent.right; + bottom: buttons.top; + bottomMargin: hifi.dimensions.contentSpacing.y; + } + height: comboBoxField.controlHeight; + onHeightChanged: d.resize(); + onWidthChanged: d.resize(); + + CheckBox { + id: checkBoxField; + text: root.checkBox.label; + focus: root.checkBox ? true : false; + visible: root.checkBox ? true : false; + anchors { + left: parent.left; + bottom: parent.bottom; + } + } + + ComboBox { + id: comboBoxField; + label: root.comboBox.label; + focus: root.comboBox ? true : false; + visible: root.comboBox ? true : false; + anchors { + right: parent.right; + bottom: parent.bottom; + } + model: root.comboBox ? root.comboBox.items : []; + } + } + + Row { + id: buttons; + focus: true; + spacing: hifi.dimensions.contentSpacing.x; + onHeightChanged: d.resize(); + onWidthChanged: d.resize(); + anchors { + bottom: parent.bottom; + left: parent.left; + right: parent.right; + bottomMargin: hifi.dimensions.contentSpacing.y; + } + + Button { + id: acceptButton; + action: acceptAction; + // anchors { + // bottom: parent.bottom; + // right: cancelButton.left; + // leftMargin: hifi.dimensions.contentSpacing.x; + // } + } + + Button { + id: cancelButton; + action: cancelAction; + // anchors { + // bottom: parent.bottom; + // right: parent.right; + // leftMargin: hifi.dimensions.contentSpacing.x; + // } + } + } + + Action { + id: cancelAction; + text: qsTr("Cancel"); + shortcut: Qt.Key_Escape; + onTriggered: { + root.result = null; + root.canceled(); + root.destroy(); + } + } + + Action { + id: acceptAction; + text: qsTr("Add"); + shortcut: Qt.Key_Return; + onTriggered: { + root.result = { + textInput: textField.text, + comboBox: comboBoxField.currentText, + checkBox: checkBoxField.checked + }; + root.selected(root.result); + root.destroy(); + } + } + } + + Keys.onPressed: { + if (!visible) { + return; + } + + switch (event.key) { + case Qt.Key_Escape: + case Qt.Key_Back: + cancelAction.trigger(); + event.accepted = true; + break; + + case Qt.Key_Return: + case Qt.Key_Enter: + acceptAction.trigger(); + event.accepted = true; + break; + } + } + + Component.onCompleted: { + updateIcon(); + d.resize(); + textField.forceActiveFocus(); + } +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fb48472b14..49b9d875cb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4710,6 +4710,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Toolbars", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Window", DependencyManager::get().data()); + qScriptRegisterMetaType(scriptEngine, CustomPromptResultToScriptValue, CustomPromptResultFromScriptValue); scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, LocationScriptingInterface::locationSetter, "Window"); // register `location` on the global object. diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index f0ae221566..b165cda135 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -29,6 +29,20 @@ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStanda static const QString LAST_BROWSE_LOCATION_SETTING = "LastBrowseLocation"; +QScriptValue CustomPromptResultToScriptValue(QScriptEngine* engine, const CustomPromptResult& result) { + if (!result.value.isValid()) { + return QScriptValue::UndefinedValue; + } + + Q_ASSERT(result.value.userType() == qMetaTypeId()); + return engine->toScriptValue(result.value.toMap()); +} + +void CustomPromptResultFromScriptValue(const QScriptValue& object, CustomPromptResult& result) { + result.value = object.toVariant(); +} + + WindowScriptingInterface::WindowScriptingInterface() { const DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler(); connect(&domainHandler, &DomainHandler::connectedToDomain, this, &WindowScriptingInterface::domainChanged); @@ -95,6 +109,14 @@ QScriptValue WindowScriptingInterface::prompt(const QString& message, const QStr return ok ? QScriptValue(result) : QScriptValue::NullValue; } +CustomPromptResult WindowScriptingInterface::customPrompt(const QVariant& config) { + CustomPromptResult result; + bool ok = false; + auto configMap = config.toMap(); + result.value = OffscreenUi::getCustomInfo(OffscreenUi::ICON_NONE, "", configMap, &ok); + return ok ? result : CustomPromptResult(); +} + QString fixupPathForMac(const QString& directory) { // On OS X `directory` does not work as expected unless a file is included in the path, so we append a bogus // filename if the directory is valid. diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 4f26ccd057..9d73111333 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -18,6 +18,18 @@ class WebWindowClass; + +class CustomPromptResult { +public: + QVariant value; +}; + +Q_DECLARE_METATYPE(CustomPromptResult); + +QScriptValue CustomPromptResultToScriptValue(QScriptEngine* engine, const CustomPromptResult& result); +void CustomPromptResultFromScriptValue(const QScriptValue& object, CustomPromptResult& result); + + class WindowScriptingInterface : public QObject, public Dependency { Q_OBJECT Q_PROPERTY(int innerWidth READ getInnerWidth) @@ -38,6 +50,7 @@ public slots: void alert(const QString& message = ""); QScriptValue confirm(const QString& message = ""); QScriptValue prompt(const QString& message = "", const QString& defaultText = ""); + CustomPromptResult customPrompt(const QVariant& config); QScriptValue browse(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); void copyToClipboard(const QString& text); diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 28aba4a365..47ca210d01 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -343,6 +343,23 @@ QString OffscreenUi::getItem(const Icon icon, const QString& title, const QStrin return result.toString(); } +QVariant OffscreenUi::getCustomInfo(const Icon icon, const QString& title, const QVariantMap& config, bool* ok) { + if (ok) { + *ok = false; + } + + QVariant result = DependencyManager::get()->customInputDialog(icon, title, config); + if (ok && result.isValid()) { + *ok = true; + } + + // Casts from QJSValue to QVariantMap (not sure how, just copied from http://lists.qt-project.org/pipermail/development/2014-September/018513.html) + Q_ASSERT(result.userType() == qMetaTypeId()); + result = qvariant_cast(result).toVariant(); + + return result; +} + QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current) { if (QThread::currentThread() != thread()) { QVariant result; @@ -358,6 +375,20 @@ QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const Q return waitForInputDialogResult(createInputDialog(icon, title, label, current)); } +QVariant OffscreenUi::customInputDialog(const Icon icon, const QString& title, const QVariantMap& config) { + if (QThread::currentThread() != thread()) { + QVariant result; + QMetaObject::invokeMethod(this, "customInputDialog", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QVariant, result), + Q_ARG(Icon, icon), + Q_ARG(QString, title), + Q_ARG(QVariantMap, config)); + return result; + } + + return waitForInputDialogResult(createCustomInputDialog(icon, title, config)); +} + void OffscreenUi::togglePinned() { bool invokeResult = QMetaObject::invokeMethod(_desktop, "togglePinned"); if (!invokeResult) { @@ -401,6 +432,23 @@ QQuickItem* OffscreenUi::createInputDialog(const Icon icon, const QString& title return qvariant_cast(result); } +QQuickItem* OffscreenUi::createCustomInputDialog(const Icon icon, const QString& title, const QVariantMap& config) { + QVariantMap map = config; + map.insert("title", title); + map.insert("icon", icon); + QVariant result; + bool invokeResult = QMetaObject::invokeMethod(_desktop, "customInputDialog", + Q_RETURN_ARG(QVariant, result), + Q_ARG(QVariant, QVariant::fromValue(map))); + + if (!invokeResult) { + qWarning() << "Failed to create custom message box"; + return nullptr; + } + + return qvariant_cast(result); +} + QVariant OffscreenUi::waitForInputDialogResult(QQuickItem* inputDialog) { if (!inputDialog) { return QVariant(); diff --git a/libraries/ui/src/OffscreenUi.h b/libraries/ui/src/OffscreenUi.h index 2bd00bf612..36297d76c7 100644 --- a/libraries/ui/src/OffscreenUi.h +++ b/libraries/ui/src/OffscreenUi.h @@ -122,7 +122,9 @@ public: static QString getSaveFileName(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0); Q_INVOKABLE QVariant inputDialog(const Icon icon, const QString& title, const QString& label = QString(), const QVariant& current = QVariant()); + Q_INVOKABLE QVariant customInputDialog(const Icon icon, const QString& title, const QVariantMap& config); QQuickItem* createInputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current); + QQuickItem* createCustomInputDialog(const Icon icon, const QString& title, const QVariantMap& config); QVariant waitForInputDialogResult(QQuickItem* inputDialog); // Compatibility with QInputDialog::getText @@ -140,6 +142,7 @@ public: static QString getText(const Icon icon, const QString & title, const QString & label, const QString & text = QString(), bool * ok = 0); static QString getItem(const Icon icon, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0); + static QVariant getCustomInfo(const Icon icon, const QString& title, const QVariantMap& config, bool* ok = 0); unsigned int getMenuUserDataId() const; From c27e1d6fdb9c92f2998306f428c67f5fca1b394b Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Fri, 15 Jul 2016 16:39:35 -0700 Subject: [PATCH 05/23] Polish dialog behavior and spacing --- .../resources/qml/controls-uit/CheckBox.qml | 1 + .../resources/qml/controls-uit/Label.qml | 3 +- .../qml/dialogs/CustomQueryDialog.qml | 112 +++++++++++++----- libraries/ui/src/OffscreenUi.cpp | 6 +- 4 files changed, 90 insertions(+), 32 deletions(-) diff --git a/interface/resources/qml/controls-uit/CheckBox.qml b/interface/resources/qml/controls-uit/CheckBox.qml index bd16a33776..544609b478 100644 --- a/interface/resources/qml/controls-uit/CheckBox.qml +++ b/interface/resources/qml/controls-uit/CheckBox.qml @@ -65,6 +65,7 @@ Original.CheckBox { colorScheme: checkBox.colorScheme x: checkBox.boxSize / 2 wrapMode: Text.Wrap + enabled: checkBox.enabled } } } diff --git a/interface/resources/qml/controls-uit/Label.qml b/interface/resources/qml/controls-uit/Label.qml index d9d33c1bfa..3b4d757154 100644 --- a/interface/resources/qml/controls-uit/Label.qml +++ b/interface/resources/qml/controls-uit/Label.qml @@ -16,5 +16,6 @@ RalewaySemiBold { property int colorScheme: hifi.colorSchemes.light size: hifi.fontSizes.inputLabel - color: colorScheme == hifi.colorSchemes.light ? hifi.colors.lightGray : hifi.colors.lightGrayText + color: enabled ? (colorScheme == hifi.colorSchemes.light ? hifi.colors.lightGray : hifi.colors.lightGrayText) + : (colorScheme == hifi.colorSchemes.light ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight); } diff --git a/interface/resources/qml/dialogs/CustomQueryDialog.qml b/interface/resources/qml/dialogs/CustomQueryDialog.qml index 3f2bab010f..e1e2a65cf4 100644 --- a/interface/resources/qml/dialogs/CustomQueryDialog.qml +++ b/interface/resources/qml/dialogs/CustomQueryDialog.qml @@ -35,14 +35,10 @@ ModalWindow { property var comboBox; property var checkBox; + property var warning: ""; property var result; - property alias current: textField.text; - // For text boxes - property alias placeholderText: textField.placeholderText; - - // For combo boxes - property bool editable: true; + property var implicitCheckState: null; property int titleWidth: 0; onTitleWidthChanged: d.resize(); @@ -54,6 +50,34 @@ ModalWindow { iconText = hifi.glyphForIcon(root.icon); } + function updateCheckbox() { + if (checkBox.disableForItems) { + var currentTextInDisableList = false; + for (var i in checkBox.disableForItems) { + if (comboBoxField.currentText === checkBox.disableForItems[i]) { + currentTextInDisableList = true; + break; + } + } + + if (currentTextInDisableList) { + checkBoxField.enabled = false; + if (checkBox.checkStateOnDisable !== null && checkBox.checkStateOnDisable !== undefined) { + root.implicitCheckState = checkBoxField.checked; + checkBoxField.checked = checkBox.checkStateOnDisable; + } + root.warning = checkBox.warningOnDisable; + } else { + checkBoxField.enabled = true; + if (root.implicitCheckState !== null) { + checkBoxField.checked = root.implicitCheckState; + root.implicitCheckState = null; + } + root.warning = ""; + } + } + } + Item { clip: true; width: pane.width; @@ -70,18 +94,11 @@ ModalWindow { function resize() { var targetWidth = Math.max(titleWidth, pane.width); var targetHeight = (textInput ? textField.controlHeight : 0) + extraInputs.height + - (6 * hifi.dimensions.contentSpacing.y) + buttons.height; - // var targetHeight = 720; - print("CQD extraInputs.height = " + extraInputs.height); - print("CQD textField.controlHeight = " + textField.controlHeight); - print("CQD buttons.height = " + buttons.height); - print("CQD targetHeight = " + targetHeight); + (5 * hifi.dimensions.contentSpacing.y) + buttons.height; root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth); root.height = (targetHeight < d.minHeight) ? d.minHeight: ((targetHeight > d.maxHeight) ? d.maxHeight : targetHeight); - print("CQD comboBoxField.visible = " + comboBoxField.visible); if (comboBoxField.visible) { - print("CQD parent = " + parent); comboBoxField.width = extraInputs.width / 2; } } @@ -94,7 +111,7 @@ ModalWindow { left: parent.left; right: parent.right; margins: 0; - bottomMargin: 2 * hifi.dimensions.contentSpacing.y; + bottomMargin: hifi.dimensions.contentSpacing.y; } // FIXME make a text field type that can be bound to a history for autocompletion @@ -132,6 +149,7 @@ ModalWindow { anchors { left: parent.left; bottom: parent.bottom; + leftMargin: 6; // Magic number to align with warning icon } } @@ -145,6 +163,7 @@ ModalWindow { bottom: parent.bottom; } model: root.comboBox ? root.comboBox.items : []; + onCurrentTextChanged: updateCheckbox(); } } @@ -152,8 +171,13 @@ ModalWindow { id: buttons; focus: true; spacing: hifi.dimensions.contentSpacing.x; + layoutDirection: Qt.RightToLeft; onHeightChanged: d.resize(); - onWidthChanged: d.resize(); + onWidthChanged: { + d.resize(); + resizeWarningText(); + } + anchors { bottom: parent.bottom; left: parent.left; @@ -161,6 +185,23 @@ ModalWindow { bottomMargin: hifi.dimensions.contentSpacing.y; } + function resizeWarningText() { + var rowWidth = buttons.width; + var buttonsWidth = acceptButton.width + cancelButton.width + hifi.dimensions.contentSpacing.x * 2; + var warningIconWidth = warningIcon.width + hifi.dimensions.contentSpacing.x; + warningText.width = rowWidth - buttonsWidth - warningIconWidth; + } + + Button { + id: cancelButton; + action: cancelAction; + // anchors { + // bottom: parent.bottom; + // right: parent.right; + // leftMargin: hifi.dimensions.contentSpacing.x; + // } + } + Button { id: acceptButton; action: acceptAction; @@ -171,14 +212,20 @@ ModalWindow { // } } - Button { - id: cancelButton; - action: cancelAction; - // anchors { - // bottom: parent.bottom; - // right: parent.right; - // leftMargin: hifi.dimensions.contentSpacing.x; - // } + Text { + id: warningText; + visible: Boolean(root.warning); + text: root.warning; + wrapMode: Text.WordWrap; + font.italic: true; + maximumLineCount: 2; + } + + HiFiGlyphs { + id: warningIcon; + visible: Boolean(root.warning); + text: hifi.glyphs.alert; + size: hifi.dimensions.controlLineHeight; } } @@ -198,11 +245,18 @@ ModalWindow { text: qsTr("Add"); shortcut: Qt.Key_Return; onTriggered: { - root.result = { - textInput: textField.text, - comboBox: comboBoxField.currentText, - checkBox: checkBoxField.checked - }; + var result = {}; + if (textInput) { + result.textInput = textField.text; + } + if (comboBox) { + result.comboBox = comboBoxField.currentText; + result.comboBoxIndex = comboBoxField.currentIndex; + } + if (checkBox) { + result.checkBox = checkBoxField.enabled ? checkBoxField.checked : null; + } + root.result = result; root.selected(root.result); root.destroy(); } diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 47ca210d01..c8909b2756 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -354,8 +354,10 @@ QVariant OffscreenUi::getCustomInfo(const Icon icon, const QString& title, const } // Casts from QJSValue to QVariantMap (not sure how, just copied from http://lists.qt-project.org/pipermail/development/2014-September/018513.html) - Q_ASSERT(result.userType() == qMetaTypeId()); - result = qvariant_cast(result).toVariant(); + Q_ASSERT(!result.isValid() || result.userType() == qMetaTypeId()); + if (result.userType() == qMetaTypeId()) { + result = qvariant_cast(result).toVariant(); + } return result; } From 6c47db016fe298804a7d8ba835400febb529efd9 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Fri, 15 Jul 2016 17:43:37 -0700 Subject: [PATCH 06/23] Remove some debug logging --- scripts/system/edit.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index a32bba765e..86aaa7adc1 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -246,13 +246,11 @@ var toolBar = (function () { toolBar.writeProperty("shown", false); addButton("newModelButton", "model-01.svg", function () { - print("CREATE MODEL 1"); var SHAPE_TYPE_NONE_TEXT = "No Collision"; var SHAPE_TYPE_SIMPLE_HULL_TEXT = "Basic - Whole model"; var SHAPE_TYPE_SIMPLE_COMPOUND_TEXT = "Good - Sub-meshes"; var SHAPE_TYPE_STATIC_MESH_TEXT = "Exact - All polygons"; var DYNAMIC_DEFAULT = false; - print("CREATE MODEL 2"); var result = Window.customPrompt({ textInput: { label: "Model URL" @@ -276,8 +274,6 @@ var toolBar = (function () { warningOnDisable: "Models with automatic collisions set to 'Exact' cannot be dynamic" } }); - print("CREATE MODEL 3"); - print("RESULT = " + result); if (result) { var url = result.textInput; From 6bd7034c1a13c3fb442883e1fce761bad8b821f0 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Mon, 18 Jul 2016 11:14:45 -0700 Subject: [PATCH 07/23] Improve scaling of components in dialog CustomQueryDialog now better handles the absence of one or more input fields and scales appropriately. --- .../qml/dialogs/CustomQueryDialog.qml | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/interface/resources/qml/dialogs/CustomQueryDialog.qml b/interface/resources/qml/dialogs/CustomQueryDialog.qml index e1e2a65cf4..5351671837 100644 --- a/interface/resources/qml/dialogs/CustomQueryDialog.qml +++ b/interface/resources/qml/dialogs/CustomQueryDialog.qml @@ -93,13 +93,17 @@ ModalWindow { function resize() { var targetWidth = Math.max(titleWidth, pane.width); - var targetHeight = (textInput ? textField.controlHeight : 0) + extraInputs.height + - (5 * hifi.dimensions.contentSpacing.y) + buttons.height; + var targetHeight = (textField.visible ? textField.controlHeight + hifi.dimensions.contentSpacing.y : 0) + + (extraInputs.visible ? extraInputs.height + hifi.dimensions.contentSpacing.y : 0) + + (buttons.height + 3 * hifi.dimensions.contentSpacing.y); root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth); - root.height = (targetHeight < d.minHeight) ? d.minHeight: ((targetHeight > d.maxHeight) ? - d.maxHeight : targetHeight); - if (comboBoxField.visible) { + root.height = (targetHeight < d.minHeight) ? d.minHeight : ((targetHeight > d.maxHeight) ? + d.maxHeight : targetHeight); + if (checkBoxField.visible && comboBoxField.visible) { + checkBoxField.width = extraInputs.width / 2; comboBoxField.width = extraInputs.width / 2; + } else if (!checkBoxField.visible && comboBoxField.visible) { + comboBoxField.width = extraInputs.width; } } } @@ -107,7 +111,7 @@ ModalWindow { Item { anchors { top: parent.top; - bottom: extraInputs.top; + bottom: extraInputs.visible ? extraInputs.top : buttons.top; left: parent.left; right: parent.right; margins: 0; @@ -130,6 +134,7 @@ ModalWindow { Row { id: extraInputs; + visible: Boolean(root.checkBox || root.comboBox); spacing: hifi.dimensions.contentSpacing.x; anchors { left: parent.left; @@ -144,8 +149,8 @@ ModalWindow { CheckBox { id: checkBoxField; text: root.checkBox.label; - focus: root.checkBox ? true : false; - visible: root.checkBox ? true : false; + focus: Boolean(root.checkBox); + visible: Boolean(root.checkBox); anchors { left: parent.left; bottom: parent.bottom; @@ -156,8 +161,8 @@ ModalWindow { ComboBox { id: comboBoxField; label: root.comboBox.label; - focus: root.comboBox ? true : false; - visible: root.comboBox ? true : false; + focus: Boolean(root.comboBox); + visible: Boolean(root.comboBox); anchors { right: parent.right; bottom: parent.bottom; @@ -195,21 +200,11 @@ ModalWindow { Button { id: cancelButton; action: cancelAction; - // anchors { - // bottom: parent.bottom; - // right: parent.right; - // leftMargin: hifi.dimensions.contentSpacing.x; - // } } Button { id: acceptButton; action: acceptAction; - // anchors { - // bottom: parent.bottom; - // right: cancelButton.left; - // leftMargin: hifi.dimensions.contentSpacing.x; - // } } Text { From 06985f927832a1e3d5840ea073be2355af1fd63d Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Mon, 18 Jul 2016 12:06:11 -0700 Subject: [PATCH 08/23] Make combo box go by index, add default values --- .../qml/dialogs/CustomQueryDialog.qml | 27 ++++++++++++---- scripts/system/edit.js | 32 +++++++++++-------- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/interface/resources/qml/dialogs/CustomQueryDialog.qml b/interface/resources/qml/dialogs/CustomQueryDialog.qml index 5351671837..a721dfe4e3 100644 --- a/interface/resources/qml/dialogs/CustomQueryDialog.qml +++ b/interface/resources/qml/dialogs/CustomQueryDialog.qml @@ -34,6 +34,21 @@ ModalWindow { property var textInput; property var comboBox; property var checkBox; + onTextInputChanged: { + if (textInput) { + textField.text = textInput.text; + } + } + onComboBoxChanged: { + if (comboBox) { + comboBoxField.currentIndex = comboBox.index; + } + } + onCheckBoxChanged: { + if (checkBox) { + checkBoxField.checked = checkBox.checked; + } + } property var warning: ""; property var result; @@ -52,15 +67,15 @@ ModalWindow { function updateCheckbox() { if (checkBox.disableForItems) { - var currentTextInDisableList = false; + var currentItemInDisableList = false; for (var i in checkBox.disableForItems) { - if (comboBoxField.currentText === checkBox.disableForItems[i]) { - currentTextInDisableList = true; + if (comboBoxField.currentIndex === checkBox.disableForItems[i]) { + currentItemInDisableList = true; break; } } - if (currentTextInDisableList) { + if (currentItemInDisableList) { checkBoxField.enabled = false; if (checkBox.checkStateOnDisable !== null && checkBox.checkStateOnDisable !== undefined) { root.implicitCheckState = checkBoxField.checked; @@ -245,8 +260,8 @@ ModalWindow { result.textInput = textField.text; } if (comboBox) { - result.comboBox = comboBoxField.currentText; - result.comboBoxIndex = comboBoxField.currentIndex; + result.comboBox = comboBoxField.currentIndex; + result.comboBoxText = comboBoxField.currentText; } if (checkBox) { result.checkBox = checkBoxField.enabled ? checkBoxField.checked : null; diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 86aaa7adc1..1735244438 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -246,10 +246,18 @@ var toolBar = (function () { toolBar.writeProperty("shown", false); addButton("newModelButton", "model-01.svg", function () { - var SHAPE_TYPE_NONE_TEXT = "No Collision"; - var SHAPE_TYPE_SIMPLE_HULL_TEXT = "Basic - Whole model"; - var SHAPE_TYPE_SIMPLE_COMPOUND_TEXT = "Good - Sub-meshes"; - var SHAPE_TYPE_STATIC_MESH_TEXT = "Exact - All polygons"; + var SHAPE_TYPE_NONE = 0; + var SHAPE_TYPE_SIMPLE_HULL = 1; + var SHAPE_TYPE_SIMPLE_COMPOUND = 2; + var SHAPE_TYPE_STATIC_MESH = 3; + + var SHAPE_TYPES = []; + SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision"; + SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model"; + SHAPE_TYPES[SHAPE_TYPE_SIMPLE_COMPOUND] = "Good - Sub-meshes"; + SHAPE_TYPES[SHAPE_TYPE_STATIC_MESH] = "Exact - All polygons"; + + var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_STATIC_MESH; var DYNAMIC_DEFAULT = false; var result = Window.customPrompt({ textInput: { @@ -257,18 +265,14 @@ var toolBar = (function () { }, comboBox: { label: "Automatic Collisions", - items: [ - SHAPE_TYPE_NONE_TEXT, - SHAPE_TYPE_SIMPLE_HULL_TEXT, - SHAPE_TYPE_SIMPLE_COMPOUND_TEXT, - SHAPE_TYPE_STATIC_MESH_TEXT - ] + index: SHAPE_TYPE_DEFAULT, + items: SHAPE_TYPES }, checkBox: { label: "Dynamic", checked: DYNAMIC_DEFAULT, disableForItems: [ - SHAPE_TYPE_STATIC_MESH_TEXT + SHAPE_TYPE_STATIC_MESH ], checkStateOnDisable: false, warningOnDisable: "Models with automatic collisions set to 'Exact' cannot be dynamic" @@ -279,13 +283,13 @@ var toolBar = (function () { var url = result.textInput; var shapeType; switch (result.comboBox) { - case SHAPE_TYPE_SIMPLE_HULL_TEXT: + case SHAPE_TYPE_SIMPLE_HULL: shapeType = "simple-hull"; break; - case SHAPE_TYPE_SIMPLE_COMPOUND_TEXT: + case SHAPE_TYPE_SIMPLE_COMPOUND: shapeType = "simple-compound"; break; - case SHAPE_TYPE_STATIC_MESH_TEXT: + case SHAPE_TYPE_STATIC_MESH: shapeType = "static-mesh"; break; default: From 492f7e0c294b25233d4a02558b2912acff1966af Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Mon, 18 Jul 2016 12:43:14 -0700 Subject: [PATCH 09/23] Add gravity to dynamic model entities --- scripts/system/edit.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 1735244438..2d42e0ba64 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -305,7 +305,8 @@ var toolBar = (function () { type: "Model", modelURL: url, shapeType: shapeType, - dynamic: dynamic + dynamic: dynamic, + gravity: dynamic ? { x: 0, y: -10, z: 0 } : { x: 0, y: 0, z: 0 } }); } } From b8398944ac6b5bdeed06944c975b895451b914a0 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Mon, 18 Jul 2016 13:09:32 -0700 Subject: [PATCH 10/23] Fix QML warnings --- interface/resources/qml/dialogs/CustomQueryDialog.qml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/dialogs/CustomQueryDialog.qml b/interface/resources/qml/dialogs/CustomQueryDialog.qml index a721dfe4e3..7908abb685 100644 --- a/interface/resources/qml/dialogs/CustomQueryDialog.qml +++ b/interface/resources/qml/dialogs/CustomQueryDialog.qml @@ -35,17 +35,17 @@ ModalWindow { property var comboBox; property var checkBox; onTextInputChanged: { - if (textInput) { + if (textInput && textInput.text !== undefined) { textField.text = textInput.text; } } onComboBoxChanged: { - if (comboBox) { + if (comboBox && comboBox.index !== undefined) { comboBoxField.currentIndex = comboBox.index; } } onCheckBoxChanged: { - if (checkBox) { + if (checkBox && checkBox.checked !== undefined) { checkBoxField.checked = checkBox.checked; } } @@ -147,10 +147,9 @@ ModalWindow { } } - Row { + Item { id: extraInputs; visible: Boolean(root.checkBox || root.comboBox); - spacing: hifi.dimensions.contentSpacing.x; anchors { left: parent.left; right: parent.right; From 5f6e6082071998a6f5bbfe036fc6bd93f386bdd2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 19 Jul 2016 11:23:21 -0700 Subject: [PATCH 11/23] don't overwrite physical properties with those from the entity during editEntity -- only set those that the script didn't. --- libraries/entities/src/EntityItem.cpp | 20 +++++++++++++++----- libraries/entities/src/EntityTree.cpp | 11 ++++------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index f0a4d40860..f774d52274 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1211,11 +1211,21 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) const { // a TerseUpdate includes the transform and its derivatives - properties._position = getLocalPosition(); - properties._velocity = getLocalVelocity(); - properties._rotation = getLocalOrientation(); - properties._angularVelocity = getLocalAngularVelocity(); - properties._acceleration = _acceleration; + if (!properties._positionChanged) { + properties._position = getLocalPosition(); + } + if (!properties._velocityChanged) { + properties._velocity = getLocalVelocity(); + } + if (!properties._rotationChanged) { + properties._rotation = getLocalOrientation(); + } + if (!properties._angularVelocityChanged) { + properties._angularVelocity = getLocalAngularVelocity(); + } + if (!properties._accelerationChanged) { + properties._acceleration = _acceleration; + } properties._positionChanged = true; properties._velocityChanged = true; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index ef0401ceaf..848d473321 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -723,13 +723,10 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList= 0) { glm::vec3 value = properties.getVelocity(); - QString changeHint = "0"; - if (value.x + value.y + value.z > 0) { - changeHint = "+"; - } else if (value.x + value.y + value.z < 0) { - changeHint = "-"; - } - changedProperties[index] = QString("velocity:") + changeHint; + changedProperties[index] = QString("velocity:") + + QString::number((int)value.x) + "," + + QString::number((int)value.y) + "," + + QString::number((int)value.z); } } From be001a652ffdf6aea2ba3ce468618b6893d3c91c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 19 Jul 2016 11:50:53 -0700 Subject: [PATCH 12/23] when doing a parenting grab, zero velocity --- scripts/system/controllers/handControllerGrab.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index cf8146fba9..e5fb48abcd 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1922,7 +1922,9 @@ function MyController(hand) { var handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"); var reparentProps = { parentID: MyAvatar.sessionUUID, - parentJointIndex: handJointIndex + parentJointIndex: handJointIndex, + velocity: {x: 0, y: 0, z: 0}, + angularVelocity: {x: 0, y: 0, z: 0} }; if (hasPresetPosition) { reparentProps["localPosition"] = this.offsetPosition; From acf4539f4f3d515128898deebb83d442b40dac73 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Tue, 19 Jul 2016 13:21:08 -0700 Subject: [PATCH 13/23] Return a JSON string from QML instead of JS object Idk why QML can't return a JS object, but it can't. Strings work, so I use a string. --- .../resources/qml/dialogs/CustomQueryDialog.qml | 2 +- libraries/ui/src/OffscreenUi.cpp | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/interface/resources/qml/dialogs/CustomQueryDialog.qml b/interface/resources/qml/dialogs/CustomQueryDialog.qml index 7908abb685..d1fb885e0b 100644 --- a/interface/resources/qml/dialogs/CustomQueryDialog.qml +++ b/interface/resources/qml/dialogs/CustomQueryDialog.qml @@ -265,7 +265,7 @@ ModalWindow { if (checkBox) { result.checkBox = checkBoxField.enabled ? checkBoxField.checked : null; } - root.result = result; + root.result = JSON.stringify(result); root.selected(root.result); root.destroy(); } diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index c8909b2756..9e5f6c4e62 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -349,14 +349,12 @@ QVariant OffscreenUi::getCustomInfo(const Icon icon, const QString& title, const } QVariant result = DependencyManager::get()->customInputDialog(icon, title, config); - if (ok && result.isValid()) { - *ok = true; - } - - // Casts from QJSValue to QVariantMap (not sure how, just copied from http://lists.qt-project.org/pipermail/development/2014-September/018513.html) - Q_ASSERT(!result.isValid() || result.userType() == qMetaTypeId()); - if (result.userType() == qMetaTypeId()) { - result = qvariant_cast(result).toVariant(); + if (result.isValid()) { + // We get a JSON encoded result, so we unpack it into a QVariant wrapping a QVariantMap + result = QVariant(QJsonDocument::fromJson(result.toString().toUtf8()).object().toVariantMap()); + if (ok) { + *ok = true; + } } return result; From 56726183f6674980d58eb996e8ab3977460bda0d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 19 Jul 2016 16:45:57 -0700 Subject: [PATCH 14/23] clear internal bullet flag before switching entity to kinematic --- libraries/physics/src/PhysicsEngine.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index d3247ec62c..aa6c1b4e40 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -88,6 +88,7 @@ void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) { motionState->updateBodyVelocities(); motionState->updateLastKinematicStep(); body->setSleepingThresholds(KINEMATIC_LINEAR_SPEED_THRESHOLD, KINEMATIC_ANGULAR_SPEED_THRESHOLD); + motionState->clearInternalKinematicChanges(); break; } case MOTION_TYPE_DYNAMIC: { From 22e7e150fc7398eb41f028b44f7f140e80b0856b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 19 Jul 2016 18:01:06 -0700 Subject: [PATCH 15/23] remove debug cruft --- libraries/physics/src/ShapeFactory.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/physics/src/ShapeFactory.cpp b/libraries/physics/src/ShapeFactory.cpp index 944e05e571..137038e133 100644 --- a/libraries/physics/src/ShapeFactory.cpp +++ b/libraries/physics/src/ShapeFactory.cpp @@ -69,7 +69,6 @@ static const btVector3 _unitSphereDirections[NUM_UNIT_SPHERE_DIRECTIONS] = { // util method btConvexHullShape* createConvexHull(const ShapeInfo::PointList& points) { - //std::cout << "adebug createConvexHull() points.size() = " << points.size() << std::endl; // adebug assert(points.size() > 0); btConvexHullShape* hull = new btConvexHullShape(); @@ -241,7 +240,6 @@ void deleteStaticMeshArray(btTriangleIndexVertexArray* dataArray) { btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) { btCollisionShape* shape = NULL; int type = info.getType(); - //std::cout << "adebug createShapeFromInfo() type = " << type << std::endl; // adebug switch(type) { case SHAPE_TYPE_BOX: { shape = new btBoxShape(glmToBullet(info.getHalfExtents())); From 2afd65467a963a27d405c28b7c00e8452199fce3 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 19 Jul 2016 18:01:22 -0700 Subject: [PATCH 16/23] fix bug where model is not yet ready for col shape --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 6 +++--- libraries/render-utils/src/Model.h | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index bef790299c..dde8d7f1c8 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -347,7 +347,6 @@ void RenderableModelEntityItem::updateModelBounds() { return; } - bool movingOrAnimating = isMovingRelativeToParent() || isAnimatingSomething(); glm::vec3 dimensions = getDimensions(); bool success; @@ -701,11 +700,12 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { } info.setParams(type, dimensions, _compoundShapeURL); } else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) { - updateModelBounds(); - // should never fall in here when model not fully loaded assert(_model && _model->isLoaded()); + updateModelBounds(); + _model->updateGeometry(); + // compute meshPart local transforms QVector localTransforms; const FBXGeometry& fbxGeometry = _model->getFBXGeometry(); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index aa0c49f720..98e50c66f4 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -84,6 +84,7 @@ public: bool readyToAddToScene(RenderArgs* renderArgs = nullptr) const { return !_needsReload && isRenderable() && isActive(); } + bool needsReload() const { return _needsReload; } bool initWhenReady(render::ScenePointer scene); bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges, @@ -232,6 +233,9 @@ public: const glm::vec3& getRegistrationPoint() const { return _registrationPoint; } + // returns 'true' if needs fullUpdate after geometry change + bool updateGeometry(); + protected: void setPupilDilation(float dilation) { _pupilDilation = dilation; } @@ -297,9 +301,6 @@ protected: std::unordered_set _cauterizeBoneSet; bool _cauterizeBones; - // returns 'true' if needs fullUpdate after geometry change - bool updateGeometry(); - virtual void initJointStates(); void setScaleInternal(const glm::vec3& scale); From 5394c092d006f666b98e74d8d15b4afdc9ba1ad9 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Wed, 20 Jul 2016 13:07:45 -0700 Subject: [PATCH 17/23] Fix bug with dropdown --- .../resources/qml/controls-uit/ComboBox.qml | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/controls-uit/ComboBox.qml b/interface/resources/qml/controls-uit/ComboBox.qml index df3210a20d..eb0c08624b 100644 --- a/interface/resources/qml/controls-uit/ComboBox.qml +++ b/interface/resources/qml/controls-uit/ComboBox.qml @@ -117,19 +117,22 @@ FocusScope { function showList() { var r = desktop.mapFromItem(root, 0, 0, root.width, root.height); - listView.currentIndex = root.currentIndex - scrollView.x = r.x; - scrollView.y = r.y + r.height; - var bottom = scrollView.y + scrollView.height; + var y = r.y + r.height; + var bottom = y + scrollView.height; if (bottom > desktop.height) { - scrollView.y -= bottom - desktop.height + 8; + y -= bottom - desktop.height + 8; } + scrollView.x = r.x; + scrollView.y = y; popup.visible = true; popup.forceActiveFocus(); + listView.currentIndex = root.currentIndex; + scrollView.hoverEnabled = true; } function hideList() { popup.visible = false; + scrollView.hoverEnabled = false; } FocusScope { @@ -161,6 +164,7 @@ FocusScope { id: scrollView height: 480 width: root.width + 4 + property bool hoverEnabled: false; style: ScrollViewStyle { decrementControl: Item { @@ -193,7 +197,8 @@ FocusScope { delegate: Rectangle { width: root.width + 4 height: popupText.implicitHeight * 1.4 - color: popupHover.containsMouse ? hifi.colors.primaryHighlight : (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark) + color: (listView.currentIndex === index) ? hifi.colors.primaryHighlight : + (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark) FiraSansSemiBold { anchors.left: parent.left anchors.leftMargin: hifi.dimensions.textPadding @@ -206,9 +211,9 @@ FocusScope { MouseArea { id: popupHover anchors.fill: parent; - hoverEnabled: true + hoverEnabled: scrollView.hoverEnabled; onEntered: listView.currentIndex = index; - onClicked: popup.selectSpecificItem(index) + onClicked: popup.selectSpecificItem(index); } } } From 0992e80254d746645d73b1c1fc7cf9dcdda9500d Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 21 Jul 2016 15:44:05 -0700 Subject: [PATCH 18/23] Add Toolbars to eslint globals --- .eslintrc.js | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc.js b/.eslintrc.js index a7f4291257..ecdae56594 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -40,6 +40,7 @@ module.exports = { "SoundCache": false, "Stats": false, "TextureCache": false, + "Toolbars": false, "Uuid": false, "UndoStack": false, "Vec3": false, From 72978c5d96b0a8af7b8965196fef2ccfcafcdf9e Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 21 Jul 2016 15:44:42 -0700 Subject: [PATCH 19/23] Rename examples -> marketplace Includes the title of the marketplace web window. --- scripts/defaultScripts.js | 2 +- .../system/{examples.js => marketplace.js} | 37 +++++++++---------- 2 files changed, 19 insertions(+), 20 deletions(-) rename scripts/system/{examples.js => marketplace.js} (56%) diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index 6880de99b5..817d63582d 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -15,7 +15,7 @@ Script.load("system/users.js"); Script.load("system/mute.js"); Script.load("system/goto.js"); Script.load("system/hmd.js"); -Script.load("system/examples.js"); +Script.load("system/marketplace.js"); Script.load("system/edit.js"); Script.load("system/ignore.js"); Script.load("system/selectAudioDevice.js"); diff --git a/scripts/system/examples.js b/scripts/system/marketplace.js similarity index 56% rename from scripts/system/examples.js rename to scripts/system/marketplace.js index 6fdb2a2874..6526fb3460 100644 --- a/scripts/system/examples.js +++ b/scripts/system/marketplace.js @@ -1,6 +1,5 @@ // -// examples.js -// examples +// marketplace.js // // Created by Eric Levin on 8 Jan 2016 // Copyright 2016 High Fidelity, Inc. @@ -11,9 +10,9 @@ var toolIconUrl = Script.resolvePath("assets/images/tools/"); -var EXAMPLES_URL = "https://metaverse.highfidelity.com/examples"; -var examplesWindow = new OverlayWebWindow({ - title: 'Examples', +var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; +var marketplaceWindow = new OverlayWebWindow({ + title: "Marketplace", source: "about:blank", width: 900, height: 700, @@ -26,24 +25,24 @@ var TOOLBAR_MARGIN_Y = 0; function showExamples(marketplaceID) { - var url = EXAMPLES_URL; + var url = MARKETPLACE_URL; if (marketplaceID) { url = url + "/items/" + marketplaceID; } - print("setting examples URL to " + url); - examplesWindow.setURL(url); - examplesWindow.setVisible(true); + print("setting marketplace URL to " + url); + marketplaceWindow.setURL(url); + marketplaceWindow.setVisible(true); UserActivityLogger.openedMarketplace(); } function hideExamples() { - examplesWindow.setVisible(false); - examplesWindow.setURL("about:blank"); + marketplaceWindow.setVisible(false); + marketplaceWindow.setURL("about:blank"); } function toggleExamples() { - if (examplesWindow.visible) { + if (marketplaceWindow.visible) { hideExamples(); } else { showExamples(); @@ -54,7 +53,7 @@ var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); var browseExamplesButton = toolBar.addButton({ imageURL: toolIconUrl + "market.svg", - objectName: "examples", + objectName: "marketplace", buttonState: 1, defaultState: 1, hoverState: 3, @@ -62,18 +61,18 @@ var browseExamplesButton = toolBar.addButton({ }); function onExamplesWindowVisibilityChanged() { - browseExamplesButton.writeProperty('buttonState', examplesWindow.visible ? 0 : 1); - browseExamplesButton.writeProperty('defaultState', examplesWindow.visible ? 0 : 1); - browseExamplesButton.writeProperty('hoverState', examplesWindow.visible ? 2 : 3); + browseExamplesButton.writeProperty('buttonState', marketplaceWindow.visible ? 0 : 1); + browseExamplesButton.writeProperty('defaultState', marketplaceWindow.visible ? 0 : 1); + browseExamplesButton.writeProperty('hoverState', marketplaceWindow.visible ? 2 : 3); } function onClick() { toggleExamples(); } browseExamplesButton.clicked.connect(onClick); -examplesWindow.visibleChanged.connect(onExamplesWindowVisibilityChanged); +marketplaceWindow.visibleChanged.connect(onExamplesWindowVisibilityChanged); Script.scriptEnding.connect(function () { - toolBar.removeButton("examples"); + toolBar.removeButton("marketplace"); browseExamplesButton.clicked.disconnect(onClick); - examplesWindow.visibleChanged.disconnect(onExamplesWindowVisibilityChanged); + marketplaceWindow.visibleChanged.disconnect(onExamplesWindowVisibilityChanged); }); From 30c5f277a099118e18cb8a574128ebaccbf7df7b Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 21 Jul 2016 15:52:19 -0700 Subject: [PATCH 20/23] Finish renaming functions --- scripts/system/marketplace.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/system/marketplace.js b/scripts/system/marketplace.js index 6526fb3460..3d28ff48f5 100644 --- a/scripts/system/marketplace.js +++ b/scripts/system/marketplace.js @@ -24,7 +24,7 @@ var toolWidth = 50; var TOOLBAR_MARGIN_Y = 0; -function showExamples(marketplaceID) { +function showMarketplace(marketplaceID) { var url = MARKETPLACE_URL; if (marketplaceID) { url = url + "/items/" + marketplaceID; @@ -36,16 +36,16 @@ function showExamples(marketplaceID) { UserActivityLogger.openedMarketplace(); } -function hideExamples() { +function hideMarketplace() { marketplaceWindow.setVisible(false); marketplaceWindow.setURL("about:blank"); } -function toggleExamples() { +function toggleMarketplace() { if (marketplaceWindow.visible) { - hideExamples(); + hideMarketplace(); } else { - showExamples(); + showMarketplace(); } } @@ -66,7 +66,7 @@ function onExamplesWindowVisibilityChanged() { browseExamplesButton.writeProperty('hoverState', marketplaceWindow.visible ? 2 : 3); } function onClick() { - toggleExamples(); + toggleMarketplace(); } browseExamplesButton.clicked.connect(onClick); marketplaceWindow.visibleChanged.connect(onExamplesWindowVisibilityChanged); From f9e8ada954215deb111a3c743a8d18fcf919e540 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 21 Jul 2016 17:18:45 -0700 Subject: [PATCH 21/23] new whiteboard for home --- .../DomainContent/Home/reset.js | 29 +- .../Home/whiteboard/eraserEntityScript.js | 113 ++---- .../Home/whiteboard/markerEntityScript.js | 123 ++----- .../Home/whiteboard/singleSpawner.js | 23 -- .../DomainContent/Home/whiteboard/swiper.js | 62 ++++ .../DomainContent/Home/whiteboard/utils.js | 347 ++++++++++++++++++ .../Home/whiteboard/whiteboard.js | 211 +++++++++++ .../Home/whiteboard/whiteboardWithSwiper.json | 149 ++++++++ .../DomainContent/Home/whiteboard/wrapper.js | 282 -------------- 9 files changed, 845 insertions(+), 494 deletions(-) delete mode 100644 unpublishedScripts/DomainContent/Home/whiteboard/singleSpawner.js create mode 100644 unpublishedScripts/DomainContent/Home/whiteboard/swiper.js create mode 100644 unpublishedScripts/DomainContent/Home/whiteboard/utils.js create mode 100644 unpublishedScripts/DomainContent/Home/whiteboard/whiteboard.js create mode 100644 unpublishedScripts/DomainContent/Home/whiteboard/whiteboardWithSwiper.json delete mode 100644 unpublishedScripts/DomainContent/Home/whiteboard/wrapper.js diff --git a/unpublishedScripts/DomainContent/Home/reset.js b/unpublishedScripts/DomainContent/Home/reset.js index cd1dcea76e..bfb2807bfb 100644 --- a/unpublishedScripts/DomainContent/Home/reset.js +++ b/unpublishedScripts/DomainContent/Home/reset.js @@ -35,8 +35,6 @@ var tiltMazePath = Script.resolvePath("atp:/tiltMaze/wrapper.js") - var whiteboardPath = Script.resolvePath("atp:/whiteboard/wrapper.js"); - var cuckooClockPath = Script.resolvePath("atp:/cuckooClock/wrapper.js"); var pingPongGunPath = Script.resolvePath("atp:/pingPongGun/wrapper.js"); @@ -51,7 +49,6 @@ Script.include(fishTankPath); Script.include(tiltMazePath); - Script.include(whiteboardPath); Script.include(cuckooClockPath); Script.include(pingPongGunPath); Script.include(transformerPath); @@ -201,6 +198,7 @@ Script.setTimeout(function() { _this.createKineticEntities(); _this.createScriptedEntities(); + _this.createWhiteboard(); _this.setupDressingRoom(); _this.createMilkPailBalls(); _this.createTarget(); @@ -296,6 +294,21 @@ print('HOME after deleting home entities'); }, + createWhiteboard: function() { + var WHITEBOARD_URL = "atp:/whiteboard/whiteboardWithSwiper.json" + var success = Clipboard.importEntities(WHITEBOARD_URL); + if (success === true) { + created = Clipboard.pasteEntities({ + x: 1105.0955, + y: 460.5000, + z: -77.4409 + }) + print('created ' + created); + } else { + print('failed to import whiteboard'); + } + }, + createScriptedEntities: function() { var fishTank = new FishTank({ x: 1099.2200, @@ -313,16 +326,6 @@ z: -80.4891 }); - var whiteboard = new Whiteboard({ - x: 1105.0955, - y: 460.5000, - z: -77.4409 - }, { - x: -0.0013, - y: -133.0056, - z: -0.0013 - }); - var pingPongGun = new HomePingPongGun({ x: 1101.2123, y: 460.2328, diff --git a/unpublishedScripts/DomainContent/Home/whiteboard/eraserEntityScript.js b/unpublishedScripts/DomainContent/Home/whiteboard/eraserEntityScript.js index 4175c65e96..ad915086fa 100644 --- a/unpublishedScripts/DomainContent/Home/whiteboard/eraserEntityScript.js +++ b/unpublishedScripts/DomainContent/Home/whiteboard/eraserEntityScript.js @@ -1,128 +1,59 @@ // // eraserEntityScript.js -// examples/homeContent/eraserEntityScript // // Created by Eric Levin on 2/17/15. +// Additions by James B. Pollack @imgntn 6/9/2016 // Copyright 2016 High Fidelity, Inc. // // This entity script provides logic for an object with attached script to erase nearby marker strokes // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - - (function() { - Script.include('../utils.js'); - var TRIGGER_CONTROLS = [ - Controller.Standard.LT, - Controller.Standard.RT, - ]; + Script.include('atp:/whiteboard/utils.js'); + var _this; + Eraser = function() { _this = this; - - _this.ERASER_TRIGGER_THRESHOLD = 0.2; - _this.STROKE_NAME = "home_polyline_markerStroke"; - _this.ERASER_TO_STROKE_SEARCH_RADIUS = 0.7; - _this.ERASER_RESET_WAIT_TIME = 3000; + _this.STROKE_NAME = "hifi_polyline_markerStroke"; + _this.ERASER_TO_STROKE_SEARCH_RADIUS = 0.1; }; Eraser.prototype = { - startEquip: function(id, params) { - _this.equipped = true; - _this.hand = params[0] == "left" ? 0 : 1; - // We really only need to grab position of marker strokes once, and then just check to see if eraser comes near enough to those strokes - Overlays.editOverlay(_this.searchSphere, { - visible: true - }); - }, - continueEquip: function() { + continueNearGrab: function() { _this.eraserPosition = Entities.getEntityProperties(_this.entityID, "position").position; - Overlays.editOverlay(_this.searchSphere, { - position: _this.eraserPosition - }); - this.triggerValue = Controller.getValue(TRIGGER_CONTROLS[_this.hand]); - if (_this.triggerValue > _this.ERASER_TRIGGER_THRESHOLD) { - _this.continueHolding(); - } + _this.continueHolding(); }, - continueHolding: function() { - var strokeIDs = Entities.findEntities(_this.eraserPosition, _this.ERASER_TO_STROKE_SEARCH_RADIUS); + var results = Entities.findEntities(_this.eraserPosition, _this.ERASER_TO_STROKE_SEARCH_RADIUS); // Create a map of stroke entities and their positions - strokeIDs.forEach(function(strokeID) { - var strokeProps = Entities.getEntityProperties(strokeID, ["position", "name"]); - if (strokeProps.name === _this.STROKE_NAME && Vec3.distance(_this.eraserPosition, strokeProps.position) < _this.ERASER_TO_STROKE_SEARCH_RADIUS) { - Entities.deleteEntity(strokeID); + results.forEach(function(stroke) { + var props = Entities.getEntityProperties(stroke, ["position", "name"]); + if (props.name === _this.STROKE_NAME && Vec3.distance(_this.eraserPosition, props.position) < _this.ERASER_TO_STROKE_SEARCH_RADIUS) { + Entities.deleteEntity(stroke); } }); }, - releaseEquip: function() { - Overlays.editOverlay(_this.searchSphere, { - visible: false - }); - - // Once user releases eraser, wait a bit then put marker back to its original position and rotation - // Script.setTimeout(function() { - // var userData = getEntityUserData(_this.entityID); - // Entities.editEntity(_this.entityID, { - // position: userData.originalPosition, - // rotation: userData.originalRotation, - // velocity: { - // x: 0, - // y: -0.01, - // z: 0 - // } - // }); - // }, _this.ERASER_RESET_WAIT_TIME); - }, - collisionWithEntity: function(myID, otherID, collision) { - var otherProps = Entities.getEntityProperties(otherID); - if (otherProps.name === 'home_model_homeset') { - var userData = getEntityUserData(_this.entityID); - Entities.editEntity(_this.entityID, { - position: userData.originalPosition, - rotation: userData.originalRotation, - velocity: { - x: 0, - y: -0.01, - z: 0 - }, - angularVelocity: { - x: 0, - y: 0, - z: 0 - } - }); - } - }, - - preload: function(entityID) { _this.entityID = entityID; - _this.searchSphere = Overlays.addOverlay('sphere', { - size: _this.ERASER_TO_STROKE_SEARCH_RADIUS, - color: { - red: 200, - green: 10, - blue: 10 - }, - alpha: 0.2, - solid: true, - visible: false - }) }, - unload: function() { - Overlays.deleteOverlay(_this.searchSphere); - } + startEquip: function() { + _this.startNearGrab(); + }, + + continueEquip: function() { + _this.continueNearGrab(); + }, + + }; - // entity scripts always need to return a newly constructed object of our type return new Eraser(); }); \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/Home/whiteboard/markerEntityScript.js b/unpublishedScripts/DomainContent/Home/whiteboard/markerEntityScript.js index 1f07172a45..599f8979d1 100644 --- a/unpublishedScripts/DomainContent/Home/whiteboard/markerEntityScript.js +++ b/unpublishedScripts/DomainContent/Home/whiteboard/markerEntityScript.js @@ -1,8 +1,8 @@ // // markerTipEntityScript.js -// examples/homeContent/markerTipEntityScript // // Created by Eric Levin on 2/17/15. +// Additions by James B. Pollack @imgntn 6/9/2016 // Copyright 2016 High Fidelity, Inc. // // This script provides the logic for an object to draw marker strokes on its associated whiteboard @@ -10,15 +10,9 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - - (function() { - Script.include('../utils.js'); - var TRIGGER_CONTROLS = [ - Controller.Standard.LT, - Controller.Standard.RT, - ]; + Script.include('atp:/whiteboard/utils.js'); var MAX_POINTS_PER_STROKE = 40; var _this; @@ -31,95 +25,74 @@ min: 0.002, max: 0.01 }; - _this.MAX_MARKER_TO_BOARD_DISTANCE = 1.4; _this.MIN_DISTANCE_BETWEEN_POINTS = 0.002; _this.MAX_DISTANCE_BETWEEN_POINTS = 0.1; _this.strokes = []; - _this.PAINTING_TRIGGER_THRESHOLD = 0.2; - _this.STROKE_NAME = "home_polyline_markerStroke"; - _this.WHITEBOARD_SURFACE_NAME = "home_box_whiteboardDrawingSurface" - _this.MARKER_RESET_WAIT_TIME = 3000; + _this.STROKE_NAME = "hifi_polyline_markerStroke"; + _this.WHITEBOARD_SURFACE_NAME = "hifi-whiteboardDrawingSurface" }; MarkerTip.prototype = { - startEquip: function(id, params) { - print('start equip') + startNearGrab: function() { _this.whiteboards = []; - _this.equipped = true; - _this.hand = params[0] == "left" ? 0 : 1; _this.markerColor = getEntityUserData(_this.entityID).markerColor; - // search for whiteboards - var markerPosition = Entities.getEntityProperties(_this.entityID, "position").position; - var entities = Entities.findEntities(markerPosition, 10); - entities.forEach(function(entity) { - + var markerProps = Entities.getEntityProperties(_this.entityID); + _this.DRAW_ON_BOARD_DISTANCE = markerProps.dimensions.z / 2; + var markerPosition = markerProps.position; + var results = Entities.findEntities(markerPosition, 5); + results.forEach(function(entity) { var entityName = Entities.getEntityProperties(entity, "name").name; if (entityName === _this.WHITEBOARD_SURFACE_NAME) { _this.whiteboards.push(entity); } }); + }, - releaseEquip: function() { + releaseGrab: function() { _this.resetStroke(); - Overlays.editOverlay(_this.laserPointer, { - visible: false - }); }, - collisionWithEntity: function(myID, otherID, collision) { - var otherProps = Entities.getEntityProperties(otherID); - if (otherProps.name === 'home_model_homeset') { - var userData = getEntityUserData(_this.entityID); - Entities.editEntity(_this.entityID, { - position: userData.originalPosition, - rotation: userData.originalRotation, - velocity: { - x: 0, - y: -0.01, - z: 0 - }, - angularVelocity: {x: 0, y: 0, z: 0} - }) - } - }, - continueEquip: function() { + continueNearGrab: function() { // cast a ray from marker and see if it hits anything - var markerProps = Entities.getEntityProperties(_this.entityID, ["position", "rotation"]); + var markerProps = Entities.getEntityProperties(_this.entityID); + + //need to back up the ray to the back of the marker + + var markerFront = Quat.getFront(markerProps.rotation); + var howFarBack = markerProps.dimensions.z / 2; + var pulledBack = Vec3.multiply(markerFront, -howFarBack); + var backedOrigin = Vec3.sum(markerProps.position, pulledBack); var pickRay = { - origin: markerProps.position, + origin: backedOrigin, direction: Quat.getFront(markerProps.rotation) } - var intersection = Entities.findRayIntersectionBlocking(pickRay, true, _this.whiteboards); + var intersection = Entities.findRayIntersection(pickRay, true, _this.whiteboards); - if (intersection.intersects && Vec3.distance(intersection.intersection, markerProps.position) < _this.MAX_MARKER_TO_BOARD_DISTANCE) { + if (intersection.intersects && Vec3.distance(intersection.intersection, markerProps.position) <= _this.DRAW_ON_BOARD_DISTANCE) { _this.currentWhiteboard = intersection.entityID; var whiteboardRotation = Entities.getEntityProperties(_this.currentWhiteboard, "rotation").rotation; _this.whiteboardNormal = Quat.getFront(whiteboardRotation); - Overlays.editOverlay(_this.laserPointer, { - visible: true, - position: intersection.intersection, - rotation: whiteboardRotation - }) - _this.triggerValue = Controller.getValue(TRIGGER_CONTROLS[_this.hand]); - if (_this.triggerValue > _this.PAINTING_TRIGGER_THRESHOLD) { - _this.paint(intersection.intersection) - } else { - _this.resetStroke(); - } + + _this.paint(intersection.intersection) + } else { if (_this.currentStroke) { _this.resetStroke(); } - Overlays.editOverlay(_this.laserPointer, { - visible: false - }); } + }, + startEquip: function() { + _this.startNearGrab(); + }, + + continueEquip: function() { + _this.continueNearGrab(); }, newStroke: function(position) { @@ -135,12 +108,7 @@ position: position, textures: _this.MARKER_TEXTURE_URL, color: _this.markerColor, - lifetime: 5000, - userData: JSON.stringify({ - 'hifiHomeKey': { - 'reset': true - } - }), + lifetime: 5000 }); _this.linePoints = []; @@ -170,7 +138,8 @@ _this.normals.push(_this.whiteboardNormal); var strokeWidths = []; - for (var i = 0; i < _this.linePoints.length; i++) { + var i; + for (i = 0; i < _this.linePoints.length; i++) { // Create a temp array of stroke widths for calligraphy effect - start and end should be less wide var pointsFromCenter = Math.abs(_this.linePoints.length / 2 - i); var pointWidth = map(pointsFromCenter, 0, this.linePoints.length / 2, _this.STROKE_WIDTH_RANGE.max, this.STROKE_WIDTH_RANGE.min); @@ -191,6 +160,7 @@ _this.oldPosition = position; } }, + resetStroke: function() { Entities.editEntity(_this.currentStroke, { @@ -203,26 +173,9 @@ preload: function(entityID) { this.entityID = entityID; - _this.laserPointer = Overlays.addOverlay("circle3d", { - color: { - red: 220, - green: 35, - blue: 53 - }, - solid: true, - size: 0.01, - }); - }, - unload: function() { - Overlays.deleteOverlay(_this.laserPointer); - _this.strokes.forEach(function(stroke) { - Entities.deleteEntity(stroke); - }); - } }; - // entity scripts always need to return a newly constructed object of our type return new MarkerTip(); }); \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/Home/whiteboard/singleSpawner.js b/unpublishedScripts/DomainContent/Home/whiteboard/singleSpawner.js deleted file mode 100644 index 48c0a48755..0000000000 --- a/unpublishedScripts/DomainContent/Home/whiteboard/singleSpawner.js +++ /dev/null @@ -1,23 +0,0 @@ -// -// -// Created by The Content Team 4/10/216 -// Copyright 2016 High Fidelity, Inc. -// -// -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var whiteboardPath = Script.resolvePath('wrapper.js'); -Script.include(whiteboardPath); - -var whiteboard = new Whiteboard({ - x: 1104, - y: 460.5, - z: -77 -}, { - x: 0, - y: -133, - z: 0 -}); \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/Home/whiteboard/swiper.js b/unpublishedScripts/DomainContent/Home/whiteboard/swiper.js new file mode 100644 index 0000000000..cd19c6eeee --- /dev/null +++ b/unpublishedScripts/DomainContent/Home/whiteboard/swiper.js @@ -0,0 +1,62 @@ +// Created by James B. Pollack @imgntn 6/8/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +// + +(function() { + + var _this; + + Swiper = function() { + _this = this; + } + + Swiper.prototype = { + busy: false, + preload: function(entityID) { + this.entityID = entityID; + Script.update.connect(this.update); + }, + clickReleaseOnEntity: function() { + this.createSupplies(); + }, + update: function() { + if (_this.busy === true) { + return; + } + + var position = Entities.getEntityProperties(_this.entityID).position; + var TRIGGER_THRESHOLD = 0.11; + + var leftHandPosition = MyAvatar.getLeftPalmPosition(); + var rightHandPosition = MyAvatar.getRightPalmPosition(); + + var leftDistance = Vec3.distance(leftHandPosition, position) + var rightDistance = Vec3.distance(rightHandPosition, position) + + if (rightDistance < TRIGGER_THRESHOLD || leftDistance < TRIGGER_THRESHOLD) { + _this.createSupplies(); + _this.busy = true; + Script.setTimeout(function() { + _this.busy = false; + }, 2000) + } + }, + + createSupplies: function() { + var myProperties = Entities.getEntityProperties(this.entityID); + + Entities.callEntityMethod(myProperties.parentID, "createMarkers"); + Entities.callEntityMethod(myProperties.parentID, "createEraser"); + + }, + unload: function() { + Script.update.disconnect(this.update); + } + + } + return new Swiper +}) \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/Home/whiteboard/utils.js b/unpublishedScripts/DomainContent/Home/whiteboard/utils.js new file mode 100644 index 0000000000..d960fea5df --- /dev/null +++ b/unpublishedScripts/DomainContent/Home/whiteboard/utils.js @@ -0,0 +1,347 @@ +// +// Created by Bradley Austin Davis on 2015/08/29 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +map = function(value, min1, max1, min2, max2) { + return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); +} + +vec3toStr = function(v, digits) { + if (!digits) { + digits = 3; + } + return "{ " + v.x.toFixed(digits) + ", " + v.y.toFixed(digits) + ", " + v.z.toFixed(digits) + " }"; +} + +quatToStr = function(q, digits) { + if (!digits) { + digits = 3; + } + return "{ " + q.w.toFixed(digits) + ", " + q.x.toFixed(digits) + ", " + + q.y.toFixed(digits) + ", " + q.z.toFixed(digits) + " }"; +} + +vec3equal = function(v0, v1) { + return (v0.x == v1.x) && (v0.y == v1.y) && (v0.z == v1.z); +} + +colorMix = function(colorA, colorB, mix) { + var result = {}; + for (var key in colorA) { + result[key] = (colorA[key] * (1 - mix)) + (colorB[key] * mix); + } + return result; +} + +scaleLine = function(start, end, scale) { + var v = Vec3.subtract(end, start); + var length = Vec3.length(v); + v = Vec3.multiply(scale, v); + return Vec3.sum(start, v); +} + +findAction = function(name) { + return Controller.findAction(name); +} + +addLine = function(origin, vector, color) { + if (!color) { + color = COLORS.WHITE + } + return Entities.addEntity(mergeObjects(LINE_PROTOTYPE, { + position: origin, + linePoints: [ + ZERO_VECTOR, + vector, + ], + color: color + })); +} + +// FIXME fetch from a subkey of user data to support non-destructive modifications +setEntityUserData = function(id, data) { + var json = JSON.stringify(data) + Entities.editEntity(id, { + userData: json + }); +} + +// FIXME do non-destructive modification of the existing user data +getEntityUserData = function(id) { + var results = null; + var properties = Entities.getEntityProperties(id, "userData"); + if (properties.userData) { + try { + results = JSON.parse(properties.userData); + } catch (err) { + logDebug(err); + logDebug(properties.userData); + } + } + return results ? results : {}; +} + + +// Non-destructively modify the user data of an entity. +setEntityCustomData = function(customKey, id, data) { + var userData = getEntityUserData(id); + if (data == null) { + delete userData[customKey]; + } else { + userData[customKey] = data; + } + setEntityUserData(id, userData); +} + +getEntityCustomData = function(customKey, id, defaultValue) { + var userData = getEntityUserData(id); + if (undefined != userData[customKey]) { + return userData[customKey]; + } else { + return defaultValue; + } +} + +mergeObjects = function(proto, custom) { + var result = {}; + for (var attrname in proto) { + result[attrname] = proto[attrname]; + } + for (var attrname in custom) { + result[attrname] = custom[attrname]; + } + return result; +} + +LOG_WARN = 1; + +logWarn = function(str) { + if (LOG_WARN) { + print(str); + } +} + +LOG_ERROR = 1; + +logError = function(str) { + if (LOG_ERROR) { + print(str); + } +} + +LOG_INFO = 1; + +logInfo = function(str) { + if (LOG_INFO) { + print(str); + } +} + +LOG_DEBUG = 0; + +logDebug = function(str) { + if (LOG_DEBUG) { + print(str); + } +} + +LOG_TRACE = 0; + +logTrace = function(str) { + if (LOG_TRACE) { + print(str); + } +} + +// Computes the penetration between a point and a sphere (centered at the origin) +// if point is inside sphere: returns true and stores the result in 'penetration' +// (the vector that would move the point outside the sphere) +// otherwise returns false +findSphereHit = function(point, sphereRadius) { + var EPSILON = 0.000001; //smallish positive number - used as margin of error for some computations + var vectorLength = Vec3.length(point); + if (vectorLength < EPSILON) { + return true; + } + var distance = vectorLength - sphereRadius; + if (distance < 0.0) { + return true; + } + return false; +} + +findSpherePointHit = function(sphereCenter, sphereRadius, point) { + return findSphereHit(Vec3.subtract(point, sphereCenter), sphereRadius); +} + +findSphereSphereHit = function(firstCenter, firstRadius, secondCenter, secondRadius) { + return findSpherePointHit(firstCenter, firstRadius + secondRadius, secondCenter); +} + +// Given a vec3 v, return a vec3 that is the same vector relative to the avatars +// DEFAULT eye position, rotated into the avatars reference frame. +getEyeRelativePosition = function(v) { + return Vec3.sum(MyAvatar.getDefaultEyePosition(), Vec3.multiplyQbyV(MyAvatar.orientation, v)); +} + +getAvatarRelativeRotation = function(q) { + return Quat.multiply(MyAvatar.orientation, q); +} + +pointInExtents = function(point, minPoint, maxPoint) { + return (point.x >= minPoint.x && point.x <= maxPoint.x) && + (point.y >= minPoint.y && point.y <= maxPoint.y) && + (point.z >= minPoint.z && point.z <= maxPoint.z); +} + +/** + * Converts an HSL color value to RGB. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSL_color_space. + * Assumes h, s, and l are contained in the set [0, 1] and + * returns r, g, and b in the set [0, 255]. + * + * @param Number h The hue + * @param Number s The saturation + * @param Number l The lightness + * @return Array The RGB representation + */ +hslToRgb = function(hsl) { + var r, g, b; + if (hsl.s == 0) { + r = g = b = hsl.l; // achromatic + } else { + var hue2rgb = function hue2rgb(p, q, t) { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + } + + var q = hsl.l < 0.5 ? hsl.l * (1 + hsl.s) : hsl.l + hsl.s - hsl.l * hsl.s; + var p = 2 * hsl.l - q; + r = hue2rgb(p, q, hsl.h + 1 / 3); + g = hue2rgb(p, q, hsl.h); + b = hue2rgb(p, q, hsl.h - 1 / 3); + } + + return { + red: Math.round(r * 255), + green: Math.round(g * 255), + blue: Math.round(b * 255) + }; +} + + + +orientationOf = function(vector) { + var Y_AXIS = { + x: 0, + y: 1, + z: 0 + }; + var X_AXIS = { + x: 1, + y: 0, + z: 0 + }; + + var theta = 0.0; + + var RAD_TO_DEG = 180.0 / Math.PI; + var direction, yaw, pitch; + direction = Vec3.normalize(vector); + yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * RAD_TO_DEG, Y_AXIS); + pitch = Quat.angleAxis(Math.asin(-direction.y) * RAD_TO_DEG, X_AXIS); + return Quat.multiply(yaw, pitch); +} + +randFloat = function(low, high) { + return low + Math.random() * (high - low); +} + + +randInt = function(low, high) { + return Math.floor(randFloat(low, high)); +} + +hexToRgb = function(hex) { + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + red: parseInt(result[1], 16), + green: parseInt(result[2], 16), + blue: parseInt(result[3], 16) + } : null; +} + +calculateHandSizeRatio = function() { + // Get the ratio of the current avatar's hand to Owen's hand + + var standardCenterHandPoint = 0.11288; + var jointNames = MyAvatar.getJointNames(); + //get distance from handJoint up to leftHandIndex3 as a proxy for center of hand + var wristToFingertipDistance = 0;; + for (var i = 0; i < jointNames.length; i++) { + var jointName = jointNames[i]; + print(jointName) + if (jointName.indexOf("LeftHandIndex") !== -1) { + // translations are relative to parent joint, so simply add them together + // joints face down the y-axis + var translation = MyAvatar.getDefaultJointTranslation(i).y; + wristToFingertipDistance += translation; + } + } + // Right now units are in cm, so convert to meters + wristToFingertipDistance /= 100; + + var centerHandPoint = wristToFingertipDistance / 2; + + // Compare against standard hand (Owen) + var handSizeRatio = centerHandPoint / standardCenterHandPoint; + return handSizeRatio; +} + +clamp = function(val, min, max) { + return Math.max(min, Math.min(max, val)) +} + +attachChildToParent = function(childName, parentName, position, searchRadius) { + var childEntity, parentEntity; + var entities = Entities.findEntities(position, searchRadius) + for (var i = 0; i < entities.length; i++) { + // first go through and find the entity we want to attach to its parent + var entity = entities[i]; + var name = Entities.getEntityProperties(entity, "name").name; + if (name === childName) { + childEntity = entity; + break; + } + } + + if (!childEntity) { + print("You are trying to attach an entity that doesn't exist! Returning"); + } + + for (var i = 0; i < entities.length; i++) { + // first go through and find the entity we want to attach to its parent + var entity = entities[i]; + var name = Entities.getEntityProperties(entity, "name").name; + if (name === parentName) { + parentEntity = entity; + break; + } + } + + if (!parentEntity) { + print("You are trying to attach an entity to a parent that doesn't exist! Returning"); + return; + } + + print("Successfully attached " + childName + " to " + parentName); + Entities.editEntity(childEntity, {parentID: parentEntity}); +} \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/Home/whiteboard/whiteboard.js b/unpublishedScripts/DomainContent/Home/whiteboard/whiteboard.js new file mode 100644 index 0000000000..3847e580c8 --- /dev/null +++ b/unpublishedScripts/DomainContent/Home/whiteboard/whiteboard.js @@ -0,0 +1,211 @@ +// Created by James B. Pollack @imgntn 6/8/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +// + +(function() { + + var _this; + var MARKER_SCRIPT_URL = "atp:/whiteboard/markerEntityScript.js"; + var ERASER_SCRIPT_URL = "atp:/whiteboard/eraserEntityScript.js"; + + Whiteboard = function() { + _this = this; + } + + Whiteboard.prototype = { + preload: function(entityID) { + this.entityID = entityID; + this.setup(); + }, + unload: function() { + + }, + setup: function() { + + var props = Entities.getEntityProperties(_this.entityID); + this.spawnRotation = Quat.safeEulerAngles(props.rotation); + this.spawnPosition = props.position; + this.orientation = Quat.fromPitchYawRollDegrees(this.spawnRotation.x, this.spawnRotation.y, this.spawnRotation.z); + this.markerRotation = Quat.fromVec3Degrees({ + x: this.spawnRotation.x + 10, + y: this.spawnRotation.y - 90, + z: this.spawnRotation.z + }); + + }, + createMarkers: function() { + _this.setup(); + var modelURLS = [ + "atp:/whiteboard/marker-blue.fbx", + "atp:/whiteboard/marker-red.fbx", + "atp:/whiteboard/marker-black.fbx", + ]; + + var markerPosition = Vec3.sum(_this.spawnPosition, Vec3.multiply(Quat.getFront(_this.orientation), -0.1)); + + _this.createMarker(modelURLS[0], markerPosition, { + red: 10, + green: 10, + blue: 200 + }); + + _this.createMarker(modelURLS[1], markerPosition, { + red: 200, + green: 10, + blue: 10 + }); + + _this.createMarker(modelURLS[2], markerPosition, { + red: 10, + green: 10, + blue: 10 + }); + }, + createMarker: function(modelURL, markerPosition, markerColor) { + + var markerProperties = { + type: "Model", + modelURL: modelURL, + rotation: _this.markerRotation, + shapeType: "box", + name: "hifi_model_marker", + dynamic: true, + gravity: { + x: 0, + y: -5, + z: 0 + }, + velocity: { + x: 0, + y: -0.1, + z: 0 + }, + position: markerPosition, + dimensions: { + x: 0.027, + y: 0.027, + z: 0.164 + }, + lifetime: 86400, + script: MARKER_SCRIPT_URL, + userData: JSON.stringify({ + 'grabbableKey': { + 'grabbable': true + }, + 'hifiHomeKey': { + 'reset': true + }, + originalPosition: markerPosition, + originalRotation: _this.markerRotation, + markerColor: markerColor, + wearable: { + joints: { + RightHand: [{ + x: 0.001, + y: 0.139, + z: 0.050 + }, { + x: -0.73, + y: -0.043, + z: -0.108, + w: -0.666 + }], + LeftHand: [{ + x: 0.007, + y: 0.151, + z: 0.061 + }, { + x: -0.417, + y: 0.631, + z: -0.389, + w: -0.525 + }] + } + } + }) + } + + var marker = Entities.addEntity(markerProperties); + + }, + createEraser: function() { + _this.setup(); + var ERASER_MODEL_URL = "atp:/whiteboard/eraser-2.fbx"; + + var eraserPosition = Vec3.sum(_this.spawnPosition, Vec3.multiply(Quat.getFront(_this.orientation), -0.1)); + eraserPosition = Vec3.sum(eraserPosition, Vec3.multiply(-0.5, Quat.getRight(_this.orientation))); + var eraserRotation = _this.markerRotation; + + var eraserProps = { + type: "Model", + name: "hifi_model_whiteboardEraser", + modelURL: ERASER_MODEL_URL, + position: eraserPosition, + script: ERASER_SCRIPT_URL, + shapeType: "box", + lifetime: 86400, + dimensions: { + x: 0.0858, + y: 0.0393, + z: 0.2083 + }, + rotation: eraserRotation, + dynamic: true, + gravity: { + x: 0, + y: -10, + z: 0 + }, + velocity: { + x: 0, + y: -0.1, + z: 0 + }, + userData: JSON.stringify({ + 'hifiHomeKey': { + 'reset': true + }, + 'grabbableKey': { + 'grabbable': true + }, + originalPosition: eraserPosition, + originalRotation: eraserRotation, + wearable: { + joints: { + RightHand: [{ + x: 0.020, + y: 0.120, + z: 0.049 + }, { + x: 0.1004, + y: 0.6424, + z: 0.717, + w: 0.250 + }], + LeftHand: [{ + x: -0.005, + y: 0.1101, + z: 0.053 + }, { + x: 0.723, + y: 0.289, + z: 0.142, + w: 0.610 + }] + } + } + }) + } + + var eraser = Entities.addEntity(eraserProps); + } + + } + + + return new Whiteboard(); +}) \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/Home/whiteboard/whiteboardWithSwiper.json b/unpublishedScripts/DomainContent/Home/whiteboard/whiteboardWithSwiper.json new file mode 100644 index 0000000000..9bebb6a492 --- /dev/null +++ b/unpublishedScripts/DomainContent/Home/whiteboard/whiteboardWithSwiper.json @@ -0,0 +1,149 @@ +{ + "Entities": [{ + "clientOnly": 0, + "compoundShapeURL": "atp:/whiteboard/handScannerSwitch_phys.obj", + "created": "2016-06-14T18:08:49Z", + "dimensions": { + "x": 0.11707025021314621, + "y": 0.16469044983386993, + "z": 0.10442595928907394 + }, + "id": "{21d2185f-4161-484d-bb0f-70bdc307700d}", + "modelURL": "atp:/whiteboard/handScannerSwitch_tall_VR.fbx", + "name": "hifi_whiteboardSwiper", + "owningAvatarID": "{00000000-0000-0000-0000-000000000000}", + "parentID": "{7b380903-a6d5-46e8-a4b3-4d58eaaa0419}", + "position": { + "x": -0.86872124671936035, + "y": -0.33092412352561951, + "z": 0.072394371032714844 + }, + "queryAACube": { + "scale": 0.22744926810264587, + "x": 4.9953713417053223, + "y": 0.33575963973999023, + "z": 1.1766284704208374 + }, + "rotation": { + "w": 0.71929502487182617, + "x": -4.57763671875e-05, + "y": -0.69472801685333252, + "z": -1.52587890625e-05 + }, + "script": "atp:/whiteboard/swiper.js", + "shapeType": "compound", + "type": "Model", + "userData": "{\"hifiHomeKey\":{\"reset\":true}}" + }, { + "clientOnly": 0, + "color": { + "blue": 200, + "green": 10, + "red": 200 + }, + "created": "2016-06-14T18:08:49Z", + "dimensions": { + "x": 1.8200000524520874, + "y": 1.7999999523162842, + "z": 0.0099999997764825821 + }, + "id": "{5572abff-1575-48e8-bc79-1d6373046fe9}", + "name": "hifi-whiteboardDrawingSurface", + "owningAvatarID": "{00000000-0000-0000-0000-000000000000}", + "parentID": "{7b380903-a6d5-46e8-a4b3-4d58eaaa0419}", + "position": { + "x": -0.019987192004919052, + "y": 0.45400944352149963, + "z": 0.020008884370326996 + }, + "queryAACube": { + "scale": 2.5597851276397705, + "x": 3.3173346519470215, + "y": -0.045509219169616699, + "z": -0.66857552528381348 + }, + "rotation": { + "w": 1, + "x": -1.52587890625e-05, + "y": -1.52587890625e-05, + "z": -1.52587890625e-05 + }, + "shape": "Cube", + "type": "Box", + "visible": 0, + "userData": "{\"hifiHomeKey\":{\"reset\":true}}" + }, { + "clientOnly": 0, + "color": { + "blue": 200, + "green": 10, + "red": 200 + }, + "created": "2016-06-14T18:08:49Z", + "dimensions": { + "x": 1.8200000524520874, + "y": 1.7999999523162842, + "z": 0.0099999997764825821 + }, + "id": "{22152131-5ac7-4758-a5bc-3dda3f034eb4}", + "name": "hifi-whiteboardDrawingSurface", + "owningAvatarID": "{00000000-0000-0000-0000-000000000000}", + "parentID": "{7b380903-a6d5-46e8-a4b3-4d58eaaa0419}", + "position": { + "x": -0.020041000097990036, + "y": 0.45001220703125, + "z": -0.019985578954219818 + }, + "queryAACube": { + "scale": 2.5597851276397705, + "x": 3.2840065956115723, + "y": -0.049505829811096191, + "z": -0.6464693546295166 + }, + "rotation": { + "w": 1, + "x": -1.52587890625e-05, + "y": -1.52587890625e-05, + "z": -1.52587890625e-05 + }, + "shape": "Cube", + "type": "Box", + "visible": 0, + "userData": "{\"hifiHomeKey\":{\"reset\":true}}" + }, { + "clientOnly": 0, + "compoundShapeURL": "atp:/whiteboard/whiteboardCollisionHull.obj", + "created": "2016-06-14T18:08:49Z", + "dimensions": { + "x": 1.8600000143051147, + "y": 2.7000000476837158, + "z": 0.46360000967979431 + }, + "gravity": { + "x": 0, + "y": -9.8, + "z": 0 + }, + "id": "{7b380903-a6d5-46e8-a4b3-4d58eaaa0419}", + "modelURL": "atp:/whiteboard/Whiteboard-4.fbx", + "name": "hifi_whiteboard", + "owningAvatarID": "{00000000-0000-0000-0000-000000000000}", + "queryAACube": { + "scale": 3.3112723827362061, + "x": -1.655636191368103, + "y": -1.655636191368103, + "z": -1.655636191368103 + }, + "rotation": { + "w": -0.30053186416625977, + "x": -2.1577336156042293e-05, + "y": 0.95376050472259521, + "z": 2.824626790243201e-07 + }, + "script": "atp:/whiteboard/whiteboard.js", + "shapeType": "compound", + "type": "Model", + "userData": "{\"hifiHomeKey\":{\"reset\":true}}" + }], + "Version": 60 +} \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/Home/whiteboard/wrapper.js b/unpublishedScripts/DomainContent/Home/whiteboard/wrapper.js deleted file mode 100644 index 67712c840d..0000000000 --- a/unpublishedScripts/DomainContent/Home/whiteboard/wrapper.js +++ /dev/null @@ -1,282 +0,0 @@ -// -// whiteboardSpawner.js -// examples/homeContent/whiteboardV2 -// -// Created by Eric Levina on 2/17/16 -// Copyright 2016 High Fidelity, Inc. -// -// Run this script to spawn a whiteboard, markers, and an eraser. -// To draw on the whiteboard, equip a marker and hold down trigger with marker tip pointed at whiteboard -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -var ERASER_SCRIPT_URL = Script.resolvePath("eraserEntityScript.js"); - -var MARKER_SCRIPT_URL = Script.resolvePath("markerEntityScript.js"); - -Whiteboard = function(spawnPosition, spawnRotation) { - - var orientation = Quat.fromPitchYawRollDegrees(spawnRotation.x, spawnRotation.y, spawnRotation.z); - var markers = []; - var markerRotation = Quat.fromVec3Degrees({ - x: spawnRotation.x + 10, - y: spawnRotation.y - 90, - z: spawnRotation.z - }); - var whiteboardPosition = spawnPosition; - var whiteboardRotation = orientation; - - var WHITEBOARD_MODEL_URL = "atp:/whiteboard/Whiteboard-6.fbx"; - var WHITEBOARD_COLLISION_HULL_URL = "atp:/whiteboard/whiteboardCollisionHull.obj"; - - var whiteboard = Entities.addEntity({ - type: "Model", - name: "home_model_whiteboard", - modelURL: WHITEBOARD_MODEL_URL, - position: whiteboardPosition, - rotation: whiteboardRotation, - shapeType: 'compound', - compoundShapeURL: WHITEBOARD_COLLISION_HULL_URL, - dimensions: { - x: 1.86, - y: 2.7, - z: 0.4636 - }, - userData: JSON.stringify({ - 'hifiHomeKey': { - 'reset': true - } - }), - }); - - - - var whiteboardSurfacePosition = Vec3.sum(whiteboardPosition, { - x: 0.0, - y: 0.45, - z: 0.0 - }); - whiteboardSurfacePosition = Vec3.sum(whiteboardSurfacePosition, Vec3.multiply(-0.02, Quat.getRight(whiteboardRotation))); - var moveForwardDistance = 0.02; - whiteboardFrontSurfacePosition = Vec3.sum(whiteboardSurfacePosition, Vec3.multiply(-moveForwardDistance, Quat.getFront(whiteboardRotation))); - var WHITEBOARD_SURFACE_NAME = "home_box_whiteboardDrawingSurface"; - var whiteboardSurfaceSettings = { - type: "Box", - name: WHITEBOARD_SURFACE_NAME, - dimensions: { - x: 1.82, - y: 1.8, - z: 0.01 - }, - color: { - red: 200, - green: 10, - blue: 200 - }, - position: whiteboardFrontSurfacePosition, - rotation: whiteboardRotation, - visible: false, - parentID: whiteboard, - userData: JSON.stringify({ - 'hifiHomeKey': { - 'reset': true - } - }), - } - var whiteboardFrontDrawingSurface = Entities.addEntity(whiteboardSurfaceSettings); - - - whiteboardBackSurfacePosition = Vec3.sum(whiteboardSurfacePosition, Vec3.multiply(moveForwardDistance, Quat.getFront(whiteboardRotation))); - whiteboardSurfaceSettings.position = whiteboardBackSurfacePosition; - - var whiteboardBackDrawingSurface = Entities.addEntity(whiteboardSurfaceSettings); - - - var WHITEBOARD_RACK_DEPTH = 1.9; - - - - // ************ ERASER ************************************************ - var ERASER_MODEL_URL = "atp:/whiteboard/eraser-2.fbx"; - - - - var eraserPosition = Vec3.sum(spawnPosition, Vec3.multiply(Quat.getFront(whiteboardRotation), -0.1)); - eraserPosition = Vec3.sum(eraserPosition, Vec3.multiply(-0.5, Quat.getRight(whiteboardRotation))); - var eraserRotation = markerRotation; - - var eraserProps = { - type: "Model", - name: "home_model_whiteboardEraser", - modelURL: ERASER_MODEL_URL, - position: eraserPosition, - script: ERASER_SCRIPT_URL, - shapeType: "box", - dimensions: { - x: 0.0858, - y: 0.0393, - z: 0.2083 - }, - rotation: eraserRotation, - dynamic: true, - gravity: { - x: 0, - y: -10, - z: 0 - }, - velocity: { - x: 0, - y: -0.1, - z: 0 - }, - userData: JSON.stringify({ - 'hifiHomeKey': { - 'reset': true - }, - originalPosition: eraserPosition, - originalRotation: eraserRotation, - wearable: { - joints: { - RightHand: [{ - x: 0.020, - y: 0.120, - z: 0.049 - }, { - x: 0.1004, - y: 0.6424, - z: 0.717, - w: 0.250 - }], - LeftHand: [{ - x: -0.005, - y: 0.1101, - z: 0.053 - }, { - x: 0.723, - y: 0.289, - z: 0.142, - w: 0.610 - }] - } - } - }) - } - - - // ************************************************************************************************* - - function createMarkers() { - var modelURLS = [ - "atp:/whiteboard/marker-blue.fbx", - "atp:/whiteboard/marker-red.fbx", - "atp:/whiteboard/marker-black.fbx", - ]; - - - var markerPosition = Vec3.sum(spawnPosition, Vec3.multiply(Quat.getFront(whiteboardRotation), -0.1)); - - createMarker(modelURLS[0], markerPosition, { - red: 10, - green: 10, - blue: 200 - }); - - markerPosition = Vec3.sum(markerPosition, Vec3.multiply(-0.2, Quat.getFront(markerRotation))); - createMarker(modelURLS[1], markerPosition, { - red: 200, - green: 10, - blue: 10 - }); - - markerPosition = Vec3.sum(markerPosition, Vec3.multiply(0.4, Quat.getFront(markerRotation))); - createMarker(modelURLS[2], markerPosition, { - red: 10, - green: 10, - blue: 10 - }); - } - - - function createMarker(modelURL, markerPosition, markerColor) { - var marker = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - rotation: markerRotation, - shapeType: "box", - name: "home_model_marker", - dynamic: true, - gravity: { - x: 0, - y: -5, - z: 0 - }, - velocity: { - x: 0, - y: -0.1, - z: 0 - }, - position: markerPosition, - dimensions: { - x: 0.027, - y: 0.027, - z: 0.164 - }, - script: MARKER_SCRIPT_URL, - userData: JSON.stringify({ - 'hifiHomeKey': { - 'reset': true - }, - originalPosition: markerPosition, - originalRotation: markerRotation, - markerColor: markerColor, - wearable: { - joints: { - RightHand: [{ - x: 0.001, - y: 0.139, - z: 0.050 - }, { - x: -0.73, - y: -0.043, - z: -0.108, - w: -0.666 - }], - LeftHand: [{ - x: 0.007, - y: 0.151, - z: 0.061 - }, { - x: -0.417, - y: 0.631, - z: -0.389, - w: -0.525 - }] - } - } - }) - }); - - markers.push(marker); - - } - var eraser; - Script.setTimeout(function() { - eraser = Entities.addEntity(eraserProps); - createMarkers(); - }, 1500) - - function cleanup() { - print('WHITEBOARD CLEANUP') - Entities.deleteEntity(whiteboard); - Entities.deleteEntity(whiteboardFrontDrawingSurface); - Entities.deleteEntity(whiteboardBackDrawingSurface); - Entities.deleteEntity(eraser); - markers.forEach(function(marker) { - Entities.deleteEntity(marker); - }); - } - - this.cleanup = cleanup; - - print('CREATED WHITEBOARD') -} \ No newline at end of file From 8976f1829006f4b3fb764486527789190e987533 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 21 Jul 2016 18:36:58 -0700 Subject: [PATCH 22/23] Change 3.14 literal to Math.PI --- scripts/system/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 52babf6f49..25c25a9a7e 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -727,7 +727,7 @@ function mouseClickEvent(event) { var x = Vec3.dot(Vec3.subtract(P, A), B); var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * - 180 / 3.14; + 180 / Math.PI; var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); From cc7e723e072344b51062967b9f9c57588a721dc1 Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Fri, 22 Jul 2016 15:23:39 -0700 Subject: [PATCH 23/23] Remove extra debug print --- scripts/system/marketplace.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/system/marketplace.js b/scripts/system/marketplace.js index 3d28ff48f5..356ed8e8cf 100644 --- a/scripts/system/marketplace.js +++ b/scripts/system/marketplace.js @@ -29,7 +29,6 @@ function showMarketplace(marketplaceID) { if (marketplaceID) { url = url + "/items/" + marketplaceID; } - print("setting marketplace URL to " + url); marketplaceWindow.setURL(url); marketplaceWindow.setVisible(true);