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);
}