From a3b874f9aa77c3c63b106054be3fee8bb6bfe391 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 18 Oct 2018 01:14:13 +0200 Subject: [PATCH 1/5] property tooltips --- .../system/assets/data/createAppTooltips.json | 458 ++++++++++++++++++ scripts/system/edit.js | 5 + scripts/system/html/css/edit-style.css | 22 + scripts/system/html/entityProperties.html | 1 + scripts/system/html/js/createAppTooltip.js | 84 ++++ scripts/system/html/js/entityProperties.js | 8 +- 6 files changed, 577 insertions(+), 1 deletion(-) create mode 100644 scripts/system/assets/data/createAppTooltips.json create mode 100644 scripts/system/html/js/createAppTooltip.js diff --git a/scripts/system/assets/data/createAppTooltips.json b/scripts/system/assets/data/createAppTooltips.json new file mode 100644 index 0000000000..f8c037297f --- /dev/null +++ b/scripts/system/assets/data/createAppTooltips.json @@ -0,0 +1,458 @@ +{ + "shape": { + "tooltip": "The shape of this entity's geometry." + }, + "color": { + "tooltip": "The RGB value of this entity." + }, + "materialURL": { + "tooltip": "The URL of a JSON file containing the material. Use this to change the entity's look. " + }, + "text": { + "tooltip": "The text to display on the entity." + }, + "textColor": { + "tooltip": "The color of the text." + }, + "backgroundColor": { + "tooltip": "The color of the background." + }, + "lineHeight": { + "tooltip": "The height of each line of text. This determines the size of the text." + }, + "faceCamera": { + "tooltip": "If enabled, the entity follows the camera of each user, creating a billboard effect." + }, + "flyingAllowed": { + "tooltip": "If enabled, users can fly in the zone." + }, + "ghostingAllowed": { + "tooltip": "If enabled, users with avatar collisions turned off will not collide with content in the zone." + }, + "filterURL": { + "tooltip": "The URL of a JS file that checks for changes to entity properties within the zone. Runs periodically." + }, + "keyLightMode": { + "tooltip": "Configures the key light in the zone. This light is directional." + }, + "keyLightColor": { + "tooltip": "The color of the key light." + }, + "keyLight.intensity": { + "tooltip": "The intensity of the key light." + }, + "keyLight.direction.y": { + "tooltip": "The angle in deg at which light emits. Starts in the entity's -z direction, and rotates around its y axis." + }, + "keyLight.direction.x": { + "tooltip": "The angle in deg at which light emits. Starts in the entity's -z direction, and rotates around its x axis." + }, + "keyLight.castShadows": { + "tooltip": "If enabled, shadows are cast. The entity or avatar casting the shadow must also have Cast Shadows enabled." + }, + "skyboxMode": { + "tooltip": "Configures the skybox in the zone. The skybox is a cube map image." + }, + "skybox.color": { + "tooltip": "If the URL is blank, this changes the color of the sky, otherwise it modifies the color of the skybox." + }, + "skybox.url": { + "tooltip": "A cube map image that is used to render the sky." + }, + "ambientLightMode": { + "tooltip": "Configures the ambient light in the zone. Use this if you want your skybox to reflect light on the content." + }, + "ambientLight.ambientIntensity": { + "tooltip": "The intensity of the ambient light." + }, + "ambientLight.ambientURL": { + "tooltip": "A cube map image that defines the color of the light coming from each direction." + }, + "hazeMode": { + "tooltip": "Configures the haze in the scene." + }, + "haze.hazeRange": { + "tooltip": "How far the haze extends out. This is measured in meters." + }, + "haze.hazeAltitudeEffect": { + "tooltip": "If enabled, this adjusts the haze intensity as it gets higher." + }, + "haze.hazeBaseRef": { + "tooltip": "The base of the altitude range. Measured in entity space." + }, + "haze.hazeCeiling": { + "tooltip": "The ceiling of the altitude range. Measured in entity space." + }, + "haze.hazeColor": { + "tooltip": "The color of the haze." + }, + "haze.hazeBackgroundBlend": { + "tooltip": "How much the skybox shows through the haze. The higher the value, the more it shows through." + }, + "haze.hazeEnableGlare": { + "tooltip": "If enabled, a glare is enabled on the skybox, based on the key light." + }, + "haze.hazeGlareColor": { + "tooltip": "The color of the glare based on the key light." + }, + "haze.hazeGlareAngle": { + "tooltip": "The angular size of the glare and how much it encompasses the skybox, based on the key light." + }, + "bloomMode": { + "tooltip": "Configures how much bright areas of the scene glow." + }, + "bloom.bloomIntensity": { + "tooltip": "The intensity, or brightness, of the bloom effect." + }, + "bloom.bloomThreshold": { + "tooltip": "The cutoff of the bloom. The higher the value, the more only bright areas of the scene will glow." + }, + "bloom.bloomSize": { + "tooltip": "The radius of bloom. The higher the value, the larger the bloom." + }, + "modelURL": { + "tooltip": "A mesh model from an FBX or OBJ file." + }, + "shapeType": { + "tooltip": "The shape of the collision hull used if collisions are enabled. This affects how an entity collides." + }, + "compoundShapeURL": { + "tooltip": "The OBJ file to use for the compound shape if Collision Shape is \"compound\"." + }, + "animation.url": { + "tooltip": "An animation to play on the model." + }, + "animation.running": { + "tooltip": "If enabled, the animation on the model will play automatically." + }, + "animation.allowTranslation": { + "tooltip": "If enabled, this allows an entity to move in space during an animation." + }, + "animation.loop": { + "tooltip": "If enabled, then the animation will continuously repeat." + }, + "animation.hold": { + "tooltip": "If enabled, then rotations and translations of the last frame played are maintained when the animation stops." + }, + "animation.currentFrame": { + "tooltip": "The current frame being played in the animation." + }, + "animation.firstFrame": { + "tooltip": "The first frame to play in the animation." + }, + "animation.lastFrame": { + "tooltip": "The last frame to play in the animation." + }, + "animation.fps": { + "tooltip": "The speed of the animation." + }, + "textures": { + "tooltip": "The URL of a JPG or PNG image file to display for each particle." + }, + "originalTextures": { + "tooltip": "A JSON string containing the original texture used on the model." + }, + "imageUrl": { + "tooltip": "The URL for the image source.", + "jsPropertyName": "textures" + }, + "sourceUrl": { + "tooltip": "The URL for the web page source." + }, + "dpi": { + "tooltip": "The resolution to display the page at, in pixels per inch. Use this to resize your web source in the frame." + }, + "isEmitting": { + "tooltip": "If enabled, then particles are emitted." + }, + "lifespan": { + "tooltip": "How long each particle lives, measured in seconds." + }, + "maxParticles": { + "tooltip": "The maximum number of particles to render at one time. Older particles are swapped out for new ones." + }, + "emitRate": { + "tooltip": "The number of particles per second to emit." + }, + "emitSpeed": { + "tooltip": "The speed that each particle is emitted at, measured in m/s." + }, + "speedSpread": { + "tooltip": "The spread in speeds at which particles are emitted at, resulting in a variety of speeds." + }, + "emitDimensions": { + "tooltip": "The outer limit radius in dimensions that the particles can be emitted from." + }, + "emitOrientation": { + "tooltip": "The orientation of particle emission relative to the entity's axes." + }, + "emitRadiusStart": { + "tooltip": "The inner limit radius in dimensions that the particles start emitting from." + }, + "emitterShouldTrail": { + "tooltip": "If enabled, then particles are \"left behind\" as the emitter moves, otherwise they are not." + }, + "particleRadius": { + "tooltip": "The size of each particle." + }, + "radiusStart": { + "tooltip": "" + }, + "radiusFinish": { + "tooltip": "" + }, + "radiusSpread": { + "tooltip": "The spread in size that each particle is given, resulting in a variety of sizes." + }, + "particleColor": { + "tooltip": "The color of each particle.", + "jsPropertyName": "color" + }, + "colorSpread": { + "tooltip": "The spread in color that each particle is given, resulting in a variety of colors." + }, + "alpha": { + "tooltip": "The alpha of each particle." + }, + "alphaStart": { + "tooltip": "" + }, + "alphaFinish": { + "tooltip": "" + }, + "alphaSpread": { + "tooltip": "The spread in alpha that each particle is given, resulting in a variety of alphas." + }, + "emitAcceleration": { + "tooltip": "The acceleration that is applied to each particle during its lifetime." + }, + "accelerationSpread": { + "tooltip": "The spread in accelerations that each particle is given, resulting in a variety of accelerations." + }, + "particleSpin": { + "tooltip": "The spin of each particle in the system." + }, + "spinStart": { + "tooltip": "" + }, + "spinFinish": { + "tooltip": "" + }, + "spinSpread": { + "tooltip": "The spread in spin that each particle is given, resulting in a variety of spins." + }, + "rotateWithEntity": { + "tooltip": "If enabled, each particle will spin relative to the roation of the entity as a whole." + }, + "azimuthStart": { + "tooltip": "The angle in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis." + }, + "azimuthFinish": { + "tooltip": "" + }, + "polarStart": { + "tooltip": "The angle in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis." + }, + "polarFinish": { + "tooltip": "" + }, + "lightColor": { + "tooltip": "The color of the light emitted.", + "jsPropertyName": "color" + }, + "intensity": { + "tooltip": "The brightness of the light." + }, + "falloffRadius": { + "tooltip": "The distance from the light's center where the intensity is reduced." + }, + "isSpotlight": { + "tooltip": "If enabled, then the light is directional, otherwise the light is a point light which emits light in all directions." + }, + "exponent": { + "tooltip": "Affects the softness of the spotlight beam; the higher the value, the softer the beam." + }, + "cutoff": { + "tooltip": "Affects the size of the spotlight beam; the higher the value, the larger the beam." + }, + "id": { + "tooltip": "The unique identifier of this entity." + }, + "name": { + "tooltip": "The name of this entity." + }, + "description": { + "tooltip": "Use this field to describe the entity." + }, + "position": { + "tooltip": "The global position of this entity." + }, + "rotation": { + "tooltip": "The rotation of the entity with respect to world coordinates." + }, + "dimensions": { + "tooltip": "The global dimensions of this entity." + }, + "scale": { + "tooltip": "The global scaling of this entity,", + "skipJSProperty": true + }, + "registrationPoint": { + "tooltip": "The point in the entity at which the entity is rotated about." + }, + "collisionless": { + "tooltip": "If enabled, this entity will collide with other entities or avatars." + }, + "dynamic": { + "tooltip": "If enabled, this entity has collisions associated with it that can affect its movement." + }, + "collidesWithStatic": { + "tooltip": "If enabled, this entity will collide with other non-moving, static entities.", + "jsPropertyName": "collidesWith" + }, + "collidesWithDynamic": { + "tooltip": "If enabled, this entity will collide with other dynamic entities.", + "jsPropertyName": "collidesWith" + }, + "collidesWithKinematic": { + "tooltip": "If enabled, this entity will collide with other kinematic entities (they have velocity but are not dynamic).", + "jsPropertyName": "collidesWith" + }, + "collidesWithOtherAvatars": { + "tooltip": "If enabled, this entity will collide with other user's avatars.", + "jsPropertyName": "collidesWith" + }, + "collisionSoundURL": { + "tooltip": "The URL of a sound to play when the entity collides with something else." + }, + "grabbable": { + "tooltip": "If enabled, this entity will allow grabbing input and will be moveable.", + "jsPropertyName": "userData[\"grabbableKey\"][\"grabbable\"]" + }, + "triggerable": { + "tooltip": "If enabled, the collider on this entity is used for triggering events.", + "jsPropertyName": "userData[\"grabbableKey\"][\"triggerable\"]" + }, + "cloneable": { + "tooltip": "If enabled, this entity can be duplicated." + }, + "cloneLifetime": { + "tooltip": "The lifetime for clones of this entity." + }, + "cloneLimit": { + "tooltip": "The total number of clones of this entity that can exist in the domain at any given time." + }, + "cloneDynamic": { + "tooltip": "If enabled, then clones created from this entity will be dynamic, allowing the clone to collide." + }, + "cloneAvatarEntity": { + "tooltip": "If enabled, then clones created from this entity will be created as avatar entities." + }, + "ignoreIK": { + "tooltip": "If enabled, grabbed entities will follow the movements of your hand controller instead of your avatar's hand.", + "jsPropertyName": "userData[\"grabbableKey\"][\"ignoreIK\"]" + }, + "canCastShadow": { + "tooltip": "If enabled, this geometry of this entity casts shadows when a shadow-casting light source shines on it." + }, + "parentID": { + "tooltip": "The ID of the entity or avatar that this entity is parented to." + }, + "parentJointIndex": { + "tooltip": "If the entity is parented to an avatar, this joint defines where on the avatar the entity is parented." + }, + "href": { + "tooltip": "The URL that will be opened when a user clicks on this entity. Useful for web pages and portals." + }, + "script": { + "tooltip": "The URL to an external JS file to add behaviors to the client." + }, + "serverScripts": { + "tooltip": "The URL to an external JS file to add behaviors to the server." + }, + "serverScriptsStatus": { + "tooltip": "The status of the server script, if provided. This shows if it's running or has an error.", + "skipJSProperty": true + }, + "hasLifetime": { + "tooltip": "If enabled, the entity will disappear after a certain amount of time specified by Lifetime.", + "jsPropertyName": "lifetime" + }, + "lifetime": { + "tooltip": "The time this entity will exist in the environment for." + }, + "userData": { + "tooltip": "Used to store extra data about the entity in JSON format." + }, + "velocity": { + "tooltip": "The linear velocity vector of the entity. The velocity at which this entity moves forward in space." + }, + "damping": { + "tooltip": "The linear damping to slow down the linear velocity of an entity over time." + }, + "angularVelocity": { + "tooltip": "The angular velocity of the entity in rad/s with respect to its axes, about its pivot point." + }, + "angularDamping": { + "tooltip": "The angular damping to slow down the angular velocity of an entity over time." + }, + "restitution": { + "tooltip": "If enabled, the entity can bounce against other objects that also have Bounciness." + }, + "friction": { + "tooltip": "The friction applied to slow down an entity when it's moving against another entity." + }, + "density": { + "tooltip": "The density of the entity. The higher the density, the harder the entity is to move." + }, + "gravity": { + "tooltip": "The acceleration due to gravity that the entity should move with, in world space." + }, + "acceleration": { + "tooltip": "A acceleration that the entity should move with, in world space." + }, + "createModel": { + "tooltip": "An entity that is based on a custom mesh created from an .OBJ or .FBX.", + "skipJSProperty": true + }, + "createShape": { + "tooltip": "An entity that has many different primitive shapes.", + "skipJSProperty": true + }, + "createLight": { + "tooltip": "An entity that emits light.", + "skipJSProperty": true + }, + "createText": { + "tooltip": "An entity that displays text on a panel.", + "skipJSProperty": true + }, + "createImage": { + "tooltip": "An entity that displays an image on a panel.", + "skipJSProperty": true + }, + "createWeb": { + "tooltip": "An entity that displays a web page on a panel.", + "skipJSProperty": true + }, + "createZone": { + "tooltip": "An entity that can be used for skyboxes, lighting, and can constrain or change avatar behaviors.", + "skipJSProperty": true + }, + "createParticle": { + "tooltip": "An entity that emits particles.", + "skipJSProperty": true + }, + "createMaterial": { + "tooltip": "An entity that creates a material that can be attached to a Shape or Model.", + "skipJSProperty": true + }, + "useAssetServer": { + "tooltip": "A server that hosts content and assets. You can't take items that are hosted here into other domains.", + "skipJSProperty": true + }, + "importNewEntity": { + "tooltip": "Import a local or hosted file that can be used across domains.", + "skipJSProperty": true + } +} diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 9f4ec3c62b..c6432ac2f9 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -2481,6 +2481,11 @@ var PropertiesTool = function (opts) { } } else if (data.type === "propertiesPageReady") { updateSelections(true); + } else if (data.type === "tooltipsRequest") { + emitScriptEvent({ + type: 'tooltipsReply', + tooltips: Script.require('./assets/data/createAppTooltips.json') + }); } }; diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 2db7fce065..4ad886f1b7 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1598,3 +1598,25 @@ input.rename-entity { padding-left: 2px; } +.createAppTooltip { + position: absolute; + background: #6a6a6a; + border: 1px solid black; + width: 258px; + min-height: 20px; + padding: 5px; +} + +.createAppTooltip .createAppTooltipDescription { + font-size: 12px; + font-style: italic; + color: #ffffff; +} + +.createAppTooltip .createAppTooltipJSAttribute { + font-size: 10px; + color: #000000; + bottom: 0; + margin-top: 5px; +} + diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 03b034fc83..b56ad346e2 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -21,6 +21,7 @@ + diff --git a/scripts/system/html/js/createAppTooltip.js b/scripts/system/html/js/createAppTooltip.js new file mode 100644 index 0000000000..10ad73e1ee --- /dev/null +++ b/scripts/system/html/js/createAppTooltip.js @@ -0,0 +1,84 @@ +// createAppTooltip.js +// +// Created by Thijs Wenker on 17 Oct 2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +const CREATE_APP_TOOLTIP_OFFSET = 20; + +function CreateAppTooltip() { + this._tooltipData = null; + this._tooltipDiv = null; +} + +CreateAppTooltip.prototype = { + _tooltipData: null, + _tooltipDiv: null, + + _removeTooltipIfExists: function() { + if (this._tooltipDiv !== null) { + this._tooltipDiv.remove(); + this._tooltipDiv = null; + } + }, + + setTooltipData: function(tooltipData) { + this._tooltipData = tooltipData; + }, + + registerTooltipElement: function(element, tooltipID) { + element.addEventListener("mouseover", function() { + + this._removeTooltipIfExists(); + + let tooltipData = this._tooltipData[tooltipID]; + + if (!tooltipData || tooltipData.tooltip === "") { + return; + } + + let elementRect = element.getBoundingClientRect(); + let elTip = document.createElement("div"); + elTip.className = "createAppTooltip"; + + let elTipDescription = document.createElement("div"); + elTipDescription.className = "createAppTooltipDescription"; + elTipDescription.innerText = tooltipData.tooltip; + elTip.appendChild(elTipDescription); + + let jsAttribute = tooltipID; + if (tooltipData.jsPropertyName) { + jsAttribute = tooltipData.jsPropertyName; + } + + if (!tooltipData.skipJSProperty) { + let elTipJSAttribute = document.createElement("div"); + elTipJSAttribute.className = "createAppTooltipJSAttribute"; + elTipJSAttribute.innerText = `JS Attribute: ${jsAttribute}`; + elTip.appendChild(elTipJSAttribute); + } + + document.body.appendChild(elTip); + + let elementTop = window.pageYOffset + elementRect.top; + + let desiredTooltipTop = elementTop + element.clientHeight + CREATE_APP_TOOLTIP_OFFSET; + + if ((window.innerHeight + window.pageYOffset) < (desiredTooltipTop + elTip.clientHeight)) { + // show above when otherwise out of bounds + elTip.style.top = elementTop - CREATE_APP_TOOLTIP_OFFSET - elTip.clientHeight; + } else { + // show tooltip on below by default + elTip.style.top = desiredTooltipTop; + } + elTip.style.left = window.pageXOffset + elementRect.left; + + this._tooltipDiv = elTip; + }.bind(this), false); + element.addEventListener("mouseout", function() { + this._removeTooltipIfExists(); + }.bind(this), false); + } +}; diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 676ecaf289..59c2ba702b 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1307,6 +1307,7 @@ var colorPickers = {}; var particlePropertyUpdates = {}; var selectedEntityProperties; var lastEntityID = null; +var createAppTooltip = new CreateAppTooltip(); function debugPrint(message) { EventBridge.emitWebEvent( @@ -2659,7 +2660,7 @@ function showParentMaterialNameBox(number, elNumber, elString) { function loaded() { - openEventBridge(function() { + openEventBridge(function() { let elPropertiesList = document.getElementById("properties-list"); GROUPS.forEach(function(group) { @@ -2728,6 +2729,8 @@ function loaded() { let elLabel = document.createElement('label'); elLabel.innerText = propertyData.label; elLabel.setAttribute("for", propertyElementID); + + createAppTooltip.registerTooltipElement(elLabel, propertyID); let property = { data: propertyData, @@ -3150,6 +3153,8 @@ function loaded() { activeElement.select(); } } + } else if (data.type === 'tooltipsReply') { + createAppTooltip.setTooltipData(data.tooltips); } }); } @@ -3381,5 +3386,6 @@ function loaded() { setTimeout(function() { EventBridge.emitWebEvent(JSON.stringify({ type: 'propertiesPageReady' })); + EventBridge.emitWebEvent(JSON.stringify({ type: 'tooltipsRequest' })); }, 1000); } From 358b0b76d1f869882b02eead537d6a20e70f2d41 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 19 Oct 2018 16:32:38 +0200 Subject: [PATCH 2/5] tooltip delay of 500ms --- .../system/assets/data/createAppTooltips.json | 2 +- scripts/system/html/js/createAppTooltip.js | 76 +++++++++++-------- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/scripts/system/assets/data/createAppTooltips.json b/scripts/system/assets/data/createAppTooltips.json index f8c037297f..7cc9e0a97e 100644 --- a/scripts/system/assets/data/createAppTooltips.json +++ b/scripts/system/assets/data/createAppTooltips.json @@ -294,7 +294,7 @@ "tooltip": "The global dimensions of this entity." }, "scale": { - "tooltip": "The global scaling of this entity,", + "tooltip": "The global scaling of this entity.", "skipJSProperty": true }, "registrationPoint": { diff --git a/scripts/system/html/js/createAppTooltip.js b/scripts/system/html/js/createAppTooltip.js index 10ad73e1ee..edd0f6366a 100644 --- a/scripts/system/html/js/createAppTooltip.js +++ b/scripts/system/html/js/createAppTooltip.js @@ -7,17 +7,25 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html const CREATE_APP_TOOLTIP_OFFSET = 20; +const TOOLTIP_DELAY = 500; // ms function CreateAppTooltip() { this._tooltipData = null; this._tooltipDiv = null; + this._delayTimeout = null; } CreateAppTooltip.prototype = { _tooltipData: null, _tooltipDiv: null, + _delayTimeout: null, _removeTooltipIfExists: function() { + if (this._delayTimeout !== null) { + window.clearTimeout(this._delayTimeout); + this._delayTimeout = null; + } + if (this._tooltipDiv !== null) { this._tooltipDiv.remove(); this._tooltipDiv = null; @@ -33,49 +41,51 @@ CreateAppTooltip.prototype = { this._removeTooltipIfExists(); - let tooltipData = this._tooltipData[tooltipID]; + this._delayTimeout = window.setTimeout(function() { + let tooltipData = this._tooltipData[tooltipID]; - if (!tooltipData || tooltipData.tooltip === "") { - return; - } + if (!tooltipData || tooltipData.tooltip === "") { + return; + } - let elementRect = element.getBoundingClientRect(); - let elTip = document.createElement("div"); - elTip.className = "createAppTooltip"; + let elementRect = element.getBoundingClientRect(); + let elTip = document.createElement("div"); + elTip.className = "createAppTooltip"; - let elTipDescription = document.createElement("div"); - elTipDescription.className = "createAppTooltipDescription"; - elTipDescription.innerText = tooltipData.tooltip; - elTip.appendChild(elTipDescription); + let elTipDescription = document.createElement("div"); + elTipDescription.className = "createAppTooltipDescription"; + elTipDescription.innerText = tooltipData.tooltip; + elTip.appendChild(elTipDescription); - let jsAttribute = tooltipID; - if (tooltipData.jsPropertyName) { - jsAttribute = tooltipData.jsPropertyName; - } + let jsAttribute = tooltipID; + if (tooltipData.jsPropertyName) { + jsAttribute = tooltipData.jsPropertyName; + } - if (!tooltipData.skipJSProperty) { - let elTipJSAttribute = document.createElement("div"); - elTipJSAttribute.className = "createAppTooltipJSAttribute"; - elTipJSAttribute.innerText = `JS Attribute: ${jsAttribute}`; - elTip.appendChild(elTipJSAttribute); - } + if (!tooltipData.skipJSProperty) { + let elTipJSAttribute = document.createElement("div"); + elTipJSAttribute.className = "createAppTooltipJSAttribute"; + elTipJSAttribute.innerText = `JS Attribute: ${jsAttribute}`; + elTip.appendChild(elTipJSAttribute); + } - document.body.appendChild(elTip); + document.body.appendChild(elTip); - let elementTop = window.pageYOffset + elementRect.top; + let elementTop = window.pageYOffset + elementRect.top; - let desiredTooltipTop = elementTop + element.clientHeight + CREATE_APP_TOOLTIP_OFFSET; + let desiredTooltipTop = elementTop + element.clientHeight + CREATE_APP_TOOLTIP_OFFSET; - if ((window.innerHeight + window.pageYOffset) < (desiredTooltipTop + elTip.clientHeight)) { - // show above when otherwise out of bounds - elTip.style.top = elementTop - CREATE_APP_TOOLTIP_OFFSET - elTip.clientHeight; - } else { - // show tooltip on below by default - elTip.style.top = desiredTooltipTop; - } - elTip.style.left = window.pageXOffset + elementRect.left; + if ((window.innerHeight + window.pageYOffset) < (desiredTooltipTop + elTip.clientHeight)) { + // show above when otherwise out of bounds + elTip.style.top = elementTop - CREATE_APP_TOOLTIP_OFFSET - elTip.clientHeight; + } else { + // show tooltip on below by default + elTip.style.top = desiredTooltipTop; + } + elTip.style.left = window.pageXOffset + elementRect.left; - this._tooltipDiv = elTip; + this._tooltipDiv = elTip; + }.bind(this), TOOLTIP_DELAY); }.bind(this), false); element.addEventListener("mouseout", function() { this._removeTooltipIfExists(); From 83051940a854d8bee91e23f6542fa45554503e98 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 23 Oct 2018 04:49:45 +0200 Subject: [PATCH 3/5] Fix QA feedback --- .../system/assets/data/createAppTooltips.json | 45 ++++++++++++------- scripts/system/edit.js | 3 +- scripts/system/html/js/createAppTooltip.js | 26 ++++++++++- scripts/system/html/js/entityProperties.js | 2 + 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/scripts/system/assets/data/createAppTooltips.json b/scripts/system/assets/data/createAppTooltips.json index 7cc9e0a97e..0e6818c512 100644 --- a/scripts/system/assets/data/createAppTooltips.json +++ b/scripts/system/assets/data/createAppTooltips.json @@ -147,7 +147,7 @@ "tooltip": "The speed of the animation." }, "textures": { - "tooltip": "The URL of a JPG or PNG image file to display for each particle." + "tooltip": "A JSON string containing a texture. Use a name from the Original Texture property to override it." }, "originalTextures": { "tooltip": "A JSON string containing the original texture used on the model." @@ -171,6 +171,10 @@ "maxParticles": { "tooltip": "The maximum number of particles to render at one time. Older particles are swapped out for new ones." }, + "particleTextures": { + "tooltip": "The URL of a JPG or PNG image file to display for each particle.", + "jsPropertyName": "textures" + }, "emitRate": { "tooltip": "The number of particles per second to emit." }, @@ -244,16 +248,16 @@ "rotateWithEntity": { "tooltip": "If enabled, each particle will spin relative to the roation of the entity as a whole." }, - "azimuthStart": { + "polarStart": { "tooltip": "The angle in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis." }, - "azimuthFinish": { + "polarFinish": { "tooltip": "" }, - "polarStart": { + "azimuthStart": { "tooltip": "The angle in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis." }, - "polarFinish": { + "azimuthFinish": { "tooltip": "" }, "lightColor": { @@ -300,6 +304,12 @@ "registrationPoint": { "tooltip": "The point in the entity at which the entity is rotated about." }, + "visible": { + "tooltip": "If enabled, this entity will be visible." + }, + "locked": { + "tooltip": "If enabled, this entity will be locked." + }, "collisionless": { "tooltip": "If enabled, this entity will collide with other entities or avatars." }, @@ -318,20 +328,22 @@ "tooltip": "If enabled, this entity will collide with other kinematic entities (they have velocity but are not dynamic).", "jsPropertyName": "collidesWith" }, - "collidesWithOtherAvatars": { + "collidesWithOtherAvatar": { "tooltip": "If enabled, this entity will collide with other user's avatars.", "jsPropertyName": "collidesWith" }, + "collidesWithMyAvatar": { + "tooltip": "If enabled, this entity will collide with your own avatar.", + "jsPropertyName": "collidesWith" + }, "collisionSoundURL": { "tooltip": "The URL of a sound to play when the entity collides with something else." }, - "grabbable": { - "tooltip": "If enabled, this entity will allow grabbing input and will be moveable.", - "jsPropertyName": "userData[\"grabbableKey\"][\"grabbable\"]" + "grab.grabbable": { + "tooltip": "If enabled, this entity will allow grabbing input and will be moveable." }, - "triggerable": { - "tooltip": "If enabled, the collider on this entity is used for triggering events.", - "jsPropertyName": "userData[\"grabbableKey\"][\"triggerable\"]" + "grab.triggerable": { + "tooltip": "If enabled, the collider on this entity is used for triggering events." }, "cloneable": { "tooltip": "If enabled, this entity can be duplicated." @@ -348,9 +360,8 @@ "cloneAvatarEntity": { "tooltip": "If enabled, then clones created from this entity will be created as avatar entities." }, - "ignoreIK": { - "tooltip": "If enabled, grabbed entities will follow the movements of your hand controller instead of your avatar's hand.", - "jsPropertyName": "userData[\"grabbableKey\"][\"ignoreIK\"]" + "grab.grabFollowsController": { + "tooltip": "If enabled, grabbed entities will follow the movements of your hand controller instead of your avatar's hand." }, "canCastShadow": { "tooltip": "If enabled, this geometry of this entity casts shadows when a shadow-casting light source shines on it." @@ -411,6 +422,10 @@ "acceleration": { "tooltip": "A acceleration that the entity should move with, in world space." }, + "alignToGrid": { + "tooltip": "Used to align entities to the grid, or floor of the environment.", + "skipJSProperty": true + }, "createModel": { "tooltip": "An entity that is based on a custom mesh created from an .OBJ or .FBX.", "skipJSProperty": true diff --git a/scripts/system/edit.js b/scripts/system/edit.js index c6432ac2f9..6425806771 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -2484,7 +2484,8 @@ var PropertiesTool = function (opts) { } else if (data.type === "tooltipsRequest") { emitScriptEvent({ type: 'tooltipsReply', - tooltips: Script.require('./assets/data/createAppTooltips.json') + tooltips: Script.require('./assets/data/createAppTooltips.json'), + hmdActive: HMD.active, }); } }; diff --git a/scripts/system/html/js/createAppTooltip.js b/scripts/system/html/js/createAppTooltip.js index edd0f6366a..a42e5efe05 100644 --- a/scripts/system/html/js/createAppTooltip.js +++ b/scripts/system/html/js/createAppTooltip.js @@ -8,17 +8,20 @@ const CREATE_APP_TOOLTIP_OFFSET = 20; const TOOLTIP_DELAY = 500; // ms +const TOOLTIP_DEBUG = false; function CreateAppTooltip() { this._tooltipData = null; this._tooltipDiv = null; this._delayTimeout = null; + this._isEnabled = false; } CreateAppTooltip.prototype = { _tooltipData: null, _tooltipDiv: null, _delayTimeout: null, + _isEnabled: null, _removeTooltipIfExists: function() { if (this._delayTimeout !== null) { @@ -32,12 +35,19 @@ CreateAppTooltip.prototype = { } }, + setIsEnabled: function(isEnabled) { + this._isEnabled = isEnabled; + }, + setTooltipData: function(tooltipData) { this._tooltipData = tooltipData; }, registerTooltipElement: function(element, tooltipID) { element.addEventListener("mouseover", function() { + if (!this._isEnabled) { + return; + } this._removeTooltipIfExists(); @@ -45,7 +55,10 @@ CreateAppTooltip.prototype = { let tooltipData = this._tooltipData[tooltipID]; if (!tooltipData || tooltipData.tooltip === "") { - return; + if (!TOOLTIP_DEBUG) { + return; + } + tooltipData = {tooltip: 'PLEASE SET THIS TOOLTIP'}; } let elementRect = element.getBoundingClientRect(); @@ -74,6 +87,7 @@ CreateAppTooltip.prototype = { let elementTop = window.pageYOffset + elementRect.top; let desiredTooltipTop = elementTop + element.clientHeight + CREATE_APP_TOOLTIP_OFFSET; + let desiredTooltipLeft = window.pageXOffset + elementRect.left; if ((window.innerHeight + window.pageYOffset) < (desiredTooltipTop + elTip.clientHeight)) { // show above when otherwise out of bounds @@ -82,12 +96,20 @@ CreateAppTooltip.prototype = { // show tooltip on below by default elTip.style.top = desiredTooltipTop; } - elTip.style.left = window.pageXOffset + elementRect.left; + if ((window.innerWidth + window.pageXOffset) < (desiredTooltipLeft + elTip.clientWidth)) { + elTip.style.left = document.body.clientWidth + window.pageXOffset - elTip.offsetWidth; + } else { + elTip.style.left = desiredTooltipLeft; + } this._tooltipDiv = elTip; }.bind(this), TOOLTIP_DELAY); }.bind(this), false); element.addEventListener("mouseout", function() { + if (!this._isEnabled) { + return; + } + this._removeTooltipIfExists(); }.bind(this), false); } diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 59c2ba702b..173d806d59 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -3154,6 +3154,7 @@ function loaded() { } } } else if (data.type === 'tooltipsReply') { + createAppTooltip.setIsEnabled(!data.hmdActive); createAppTooltip.setTooltipData(data.tooltips); } }); @@ -3170,6 +3171,7 @@ function loaded() { let elLabel = document.createElement('label'); elLabel.setAttribute("for", serverScriptStatusElementID); elLabel.innerText = "Server Script Status"; + createAppTooltip.registerTooltipElement(elLabel, "serverScriptsStatus"); let elServerScriptStatus = document.createElement('span'); elServerScriptStatus.setAttribute("id", serverScriptStatusElementID); elDiv.appendChild(elLabel); From bb7d1f8afb2cef4a47a7b21ebc75f60742235161 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 23 Oct 2018 22:37:21 +0200 Subject: [PATCH 4/5] fix broken and missing tooltips --- .../system/assets/data/createAppTooltips.json | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/scripts/system/assets/data/createAppTooltips.json b/scripts/system/assets/data/createAppTooltips.json index 0e6818c512..83ddcaa34b 100644 --- a/scripts/system/assets/data/createAppTooltips.json +++ b/scripts/system/assets/data/createAppTooltips.json @@ -5,9 +5,6 @@ "color": { "tooltip": "The RGB value of this entity." }, - "materialURL": { - "tooltip": "The URL of a JSON file containing the material. Use this to change the entity's look. " - }, "text": { "tooltip": "The text to display on the entity." }, @@ -35,7 +32,7 @@ "keyLightMode": { "tooltip": "Configures the key light in the zone. This light is directional." }, - "keyLightColor": { + "keyLight.color": { "tooltip": "The color of the key light." }, "keyLight.intensity": { @@ -152,7 +149,7 @@ "originalTextures": { "tooltip": "A JSON string containing the original texture used on the model." }, - "imageUrl": { + "image": { "tooltip": "The URL for the image source.", "jsPropertyName": "textures" }, @@ -279,6 +276,36 @@ "cutoff": { "tooltip": "Affects the size of the spotlight beam; the higher the value, the larger the beam." }, + "materialURL": { + "tooltip": "The URL to an external JSON file or \"materialData\", \"materialData? to use Material Data." + }, + "materialData": { + "tooltip": "Can be used instead of a JSON file when material set to materialData." + }, + "materialNameToReplace": { + "tooltip": "Material name of parent entity to map this material entity on.", + "jsPropertyName": "parentMaterialName" + }, + "submeshToReplace": { + "tooltip": "Submesh index of the parent entity to map this material on.", + "jsPropertyName": "parentMaterialName" + }, + "selectSubmesh": { + "tooltip": "If enabled, \"Select Submesh\" property will show up, otherwise \"Material Name to Replace\" will be shown.", + "skipJSProperty": true + }, + "priority": { + "tooltip": "The priority of the material, where a larger number means higher priority. Original materials = 0." + }, + "materialMappingPos": { + "tooltip": "The offset position of the bottom left of the material within the parent's UV space." + }, + "materialMappingScale": { + "tooltip": "How many times the material will repeat in each direction within the parent's UV space." + }, + "materialMappingRot": { + "tooltip": "How much to rotate the material within the parent's UV-space, in degrees." + }, "id": { "tooltip": "The unique identifier of this entity." }, From 13cad17793d8d5d2751ac3b8dae83d290838a7b3 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 24 Oct 2018 21:35:47 +0200 Subject: [PATCH 5/5] better style js attributes --- scripts/system/html/css/edit-style.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 4ad886f1b7..cf7124d9eb 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1614,7 +1614,8 @@ input.rename-entity { } .createAppTooltip .createAppTooltipJSAttribute { - font-size: 10px; + font-family: Raleway-SemiBold; + font-size: 11px; color: #000000; bottom: 0; margin-top: 5px;