diff --git a/examples/edit.js b/examples/edit.js
index 6d170ab254..b2e52eee20 100644
--- a/examples/edit.js
+++ b/examples/edit.js
@@ -26,6 +26,7 @@ Script.include([
"libraries/entityCameraTool.js",
"libraries/gridTool.js",
"libraries/entityList.js",
+ "particle_explorer/particleExplorerTool.js",
"libraries/lightOverlayManager.js",
]);
@@ -37,17 +38,13 @@ var lightOverlayManager = new LightOverlayManager();
var cameraManager = new CameraManager();
var grid = Grid();
-// gridTool = GridTool({
-// horizontalGrid: grid
-// });
-// gridTool.setVisible(false);
var entityListTool = EntityListTool();
selectionManager.addEventListener(function() {
selectionDisplay.updateHandles();
lightOverlayManager.updatePositions();
-});
+});
var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/";
var toolHeight = 50;
@@ -134,9 +131,9 @@ var importingSVOTextOverlay = Overlays.addOverlay("text", {
var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace";
var marketplaceWindow = new OverlayWebWindow({
- title: 'Marketplace',
- source: "about:blank",
- width: 900,
+ title: 'Marketplace',
+ source: "about:blank",
+ width: 900,
height: 700,
visible: false
});
@@ -176,7 +173,8 @@ var toolBar = (function() {
newTextButton,
newWebButton,
newZoneButton,
- newPolyVoxButton;
+ newPolyVoxButton,
+ newParticleButton
function initialize() {
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.edit.toolbar", function(windowDimensions, toolbar) {
@@ -186,7 +184,7 @@ var toolBar = (function() {
};
});
-
+
activeButton = toolBar.addTool({
imageURL: toolIconUrl + "edit-status.svg",
@@ -314,6 +312,20 @@ var toolBar = (function() {
visible: false
});
+ newParticleButton = toolBar.addTool({
+ imageURL: toolIconUrl + "particle.svg",
+ subImage: {
+ x: 0,
+ y: 0,
+ width: 256,
+ height: 256
+ },
+ width: toolWidth,
+ height: toolHeight,
+ alpha: 0.9,
+ visible: false
+ });
+
that.setActive(false);
}
@@ -360,6 +372,7 @@ var toolBar = (function() {
toolBar.showTool(newWebButton, doShow);
toolBar.showTool(newZoneButton, doShow);
toolBar.showTool(newPolyVoxButton, doShow);
+ toolBar.showTool(newParticleButton, doShow);
};
var RESIZE_INTERVAL = 50;
@@ -427,8 +440,8 @@ var toolBar = (function() {
newModelButtonDown = true;
return true;
}
-
-
+
+
if (newCubeButton === toolBar.clicked(clickedOverlay)) {
createNewEntity({
type: "Box",
@@ -616,6 +629,22 @@ var toolBar = (function() {
return true;
}
+ if (newParticleButton === toolBar.clicked(clickedOverlay)) {
+ createNewEntity({
+ type: "ParticleEffect",
+ isEmitting: true,
+ particleRadius: 0.1,
+ emitAcceleration: {x: 0, y: -1, z: 0},
+ accelerationSpread: {x: 5, y: 0, z: 5},
+ emitSpeed: 1,
+ lifespan: 1,
+ particleRadius: 0.025,
+ alphaFinish: 0,
+ emitRate: 100,
+ textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png",
+ });
+ }
+
return false;
};
@@ -636,7 +665,7 @@ var toolBar = (function() {
}
newModelButtonDown = false;
-
+
return handled;
}
@@ -1226,7 +1255,8 @@ function selectAllEtitiesInCurrentSelectionBox(keepIfTouching) {
function deleteSelectedEntities() {
if (SelectionManager.hasSelection()) {
- print(" Delete Entities");
+ selectedParticleEntity = 0;
+ particleExplorerTool.destroyWebView();
SelectionManager.saveProperties();
var savedProperties = [];
for (var i = 0; i < selectionManager.selections.length; i++) {
@@ -1499,8 +1529,8 @@ PropertiesTool = function(opts) {
var url = Script.resolvePath('html/entityProperties.html');
var webView = new OverlayWebWindow({
- title: 'Entity Properties',
- source: url,
+ title: 'Entity Properties',
+ source: url,
toolWindow: true
});
@@ -1554,8 +1584,16 @@ PropertiesTool = function(opts) {
} else {
if (data.properties.dynamic === false) {
// this object is leaving dynamic, so we zero its velocities
- data.properties["velocity"] = {x: 0, y: 0, z: 0};
- data.properties["angularVelocity"] = {x: 0, y: 0, z: 0};
+ data.properties["velocity"] = {
+ x: 0,
+ y: 0,
+ z: 0
+ };
+ data.properties["angularVelocity"] = {
+ x: 0,
+ y: 0,
+ z: 0
+ };
}
if (data.properties.rotation !== undefined) {
var rotation = data.properties.rotation;
@@ -1838,3 +1876,39 @@ propertyMenu.onSelectMenuItem = function(name) {
var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace");
propertiesTool = PropertiesTool();
+var particleExplorerTool = ParticleExplorerTool();
+var selectedParticleEntity = 0;
+entityListTool.webView.eventBridge.webEventReceived.connect(function(data) {
+ var data = JSON.parse(data);
+ if (data.type == "selectionUpdate") {
+ var ids = data.entityIds;
+ if(ids.length === 1) {
+ if (Entities.getEntityProperties(ids[0], "type").type === "ParticleEffect" ) {
+ if (JSON.stringify(selectedParticleEntity) === JSON.stringify(ids[0])) {
+ // This particle entity is already selected, so return
+ return;
+ }
+ // Destroy the old particles web view first
+ particleExplorerTool.destroyWebView();
+ particleExplorerTool.createWebView();
+ var properties = Entities.getEntityProperties(ids[0]);
+ var particleData = {
+ messageType: "particle_settings",
+ currentProperties: properties
+ };
+ selectedParticleEntity = ids[0];
+ particleExplorerTool.setActiveParticleEntity(ids[0]);
+
+ particleExplorerTool.webView.eventBridge.webEventReceived.connect(function(data) {
+ var data = JSON.parse(data);
+ if (data.messageType === "page_loaded") {
+ particleExplorerTool.webView.eventBridge.emitScriptEvent(JSON.stringify(particleData));
+ }
+ });
+ } else {
+ selectedParticleEntity = 0;
+ particleExplorerTool.destroyWebView();
+ }
+ }
+ }
+});
\ No newline at end of file
diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html
index 4b4c5a398e..0c6e37b192 100644
--- a/examples/html/entityProperties.html
+++ b/examples/html/entityProperties.html
@@ -1500,51 +1500,6 @@
-
-
-
-
-
-
- Is Emitting
-
-
-
-
-
-
-
Particle Life Span
-
-
-
-
-
-
Particle Emission Rate
-
-
-
-
-
-
Particle Radius
-
-
-
-
-
-
-
-
-
diff --git a/examples/libraries/entityList.js b/examples/libraries/entityList.js
index b37ba58737..6c6c0aaecb 100644
--- a/examples/libraries/entityList.js
+++ b/examples/libraries/entityList.js
@@ -8,12 +8,16 @@ EntityListTool = function(opts) {
title: 'Entities', source: url, toolWindow: true
});
+
+
var searchRadius = 100;
var visible = false;
webView.setVisible(visible);
+ that.webView = webView;
+
that.setVisible = function(newVisible) {
visible = newVisible;
webView.setVisible(visible);
@@ -71,6 +75,7 @@ EntityListTool = function(opts) {
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
}
+
webView.eventBridge.webEventReceived.connect(function(data) {
data = JSON.parse(data);
if (data.type == "selectionUpdate") {
diff --git a/examples/particle_explorer/main.js b/examples/particle_explorer/main.js
deleted file mode 100644
index 4c82312e44..0000000000
--- a/examples/particle_explorer/main.js
+++ /dev/null
@@ -1,504 +0,0 @@
-//
-// main.js
-//
-// Created by James B. Pollack @imgntn on 9/26/2015
-// Copyright 2015 High Fidelity, Inc.
-// Web app side of the App - contains GUI.
-// This is an example of a new, easy way to do two way bindings between dynamically created GUI and in-world entities.
-//
-// Distributed under the Apache License, Version 2.0.
-// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-//
-/*global window, alert, EventBridge, dat, listenForSettingsUpdates,createVec3Folder,createQuatFolder,writeVec3ToInterface,writeDataToInterface*/
-
-var Settings = function() {
- this.exportSettings = function() {
- //copyExportSettingsToClipboard();
- showPreselectedPrompt();
- };
- this.importSettings = function() {
- importSettings();
- };
-};
-
-//2-way bindings-aren't quite ready yet. see bottom of file.
-var AUTO_UPDATE = false;
-var UPDATE_ALL_FREQUENCY = 100;
-
-var controllers = [];
-var colorControllers = [];
-var folders = [];
-var gui = null;
-var settings = new Settings();
-var updateInterval;
-
-var currentInputField;
-var storedController;
-var keysToIgnore = [
- 'importSettings',
- 'exportSettings',
- 'script',
- 'visible',
- 'locked',
- 'userData',
- 'position',
- 'dimensions',
- 'rotation',
- 'id',
- 'description',
- 'type',
- 'created',
- 'age',
- 'ageAsText',
- 'boundingBox',
- 'naturalDimensions',
- 'naturalPosition',
- 'velocity',
- 'gravity',
- 'acceleration',
- 'damping',
- 'restitution',
- 'friction',
- 'density',
- 'lifetime',
- 'scriptTimestamp',
- 'registrationPoint',
- 'angularVelocity',
- 'angularDamping',
- 'collisionless',
- 'dynamic',
- 'href',
- 'actionData',
- 'marketplaceID',
- 'collisionSoundURL',
- 'shapeType',
- 'isEmitting',
- 'sittingPoints',
- 'originalTextures',
- 'parentJointIndex',
- 'parentID'
-];
-
-var individualKeys = [];
-var vec3Keys = [];
-var quatKeys = [];
-var colorKeys = [];
-
-window.onload = function() {
- if (typeof EventBridge !== 'undefined') {
-
- var stringifiedData = JSON.stringify({
- messageType: 'page_loaded'
- });
-
- EventBridge.emitWebEvent(
- stringifiedData
- );
-
- listenForSettingsUpdates();
- window.onresize = setGUIWidthToWindowWidth;
- } else {
- console.log('No event bridge, probably not in interface.');
- }
-};
-
-function loadGUI() {
- //whether or not to autoplace
- gui = new dat.GUI({
- autoPlace: false
- });
-
- //if not autoplacing, put gui in a custom container
- if (gui.autoPlace === false) {
- var customContainer = document.getElementById('my-gui-container');
- customContainer.appendChild(gui.domElement);
- }
-
- // presets for the GUI itself. a little confusing and import/export is mostly what we want to do at the moment.
- // gui.remember(settings);
-
- var keys = _.keys(settings);
-
- _.each(keys, function(key) {
- var shouldIgnore = _.contains(keysToIgnore, key);
-
- if (shouldIgnore) {
- return;
- }
-
- var subKeys = _.keys(settings[key]);
- var hasX = _.contains(subKeys, 'x');
- var hasY = _.contains(subKeys, 'y');
- var hasZ = _.contains(subKeys, 'z');
- var hasW = _.contains(subKeys, 'w');
- var hasRed = _.contains(subKeys, 'red');
- var hasGreen = _.contains(subKeys, 'green');
- var hasBlue = _.contains(subKeys, 'blue');
-
- if ((hasX && hasY && hasZ) && hasW === false) {
- vec3Keys.push(key);
- } else if (hasX && hasY && hasZ && hasW) {
- quatKeys.push(key);
- } else if (hasRed || hasGreen || hasBlue) {
- colorKeys.push(key);
-
- } else {
- individualKeys.push(key);
- }
-
- });
-
- //alphabetize our keys
- individualKeys.sort();
- vec3Keys.sort();
- quatKeys.sort();
- colorKeys.sort();
-
- //add to gui in the order they should appear
- gui.add(settings, 'importSettings');
- gui.add(settings, 'exportSettings');
- addIndividualKeys();
- addFolders();
-
- //set the gui width to match the web window width
- gui.width = window.innerWidth;
-
- //2-way binding stuff
- // if (AUTO_UPDATE) {
- // setInterval(manuallyUpdateDisplay, UPDATE_ALL_FREQUENCY);
- // registerDOMElementsForListenerBlocking();
- // }
-
-}
-
-function addIndividualKeys() {
- _.each(individualKeys, function(key) {
- //temporary patch for not crashing when this goes below 0
- var controller;
-
- if (key.indexOf('emitRate') > -1) {
- controller = gui.add(settings, key).min(0);
- } else {
- controller = gui.add(settings, key);
-
- }
-
- //2-way - need to fix not being able to input exact values if constantly listening
- //controller.listen();
-
- //keep track of our controller
- controllers.push(controller);
-
- //hook into change events for this gui controller
- controller.onChange(function(value) {
- // Fires on every change, drag, keypress, etc.
- writeDataToInterface(this.property, value);
- });
-
- });
-}
-
-function addFolders() {
- _.each(colorKeys, function(key) {
- createColorPicker(key);
- });
- _.each(vec3Keys, function(key) {
- createVec3Folder(key);
- });
- _.each(quatKeys, function(key) {
- createQuatFolder(key);
- });
-}
-
-function createColorPicker(key) {
- var colorObject = settings[key];
- var colorArray = convertColorObjectToArray(colorObject);
- settings[key] = colorArray;
- var controller = gui.addColor(settings, key);
- controller.onChange(function(value) {
- var obj = {};
- obj[key] = convertColorArrayToObject(value);
- writeVec3ToInterface(obj);
- });
-
- return;
-}
-
-function createVec3Folder(category) {
- var folder = gui.addFolder(category);
-
- folder.add(settings[category], 'x').step(0.1).onChange(function(value) {
- // Fires when a controller loses focus.
- var obj = {};
- obj[category] = {};
- obj[category][this.property] = value;
- obj[category].y = settings[category].y;
- obj[category].z = settings[category].z;
- writeVec3ToInterface(obj);
- });
-
- folder.add(settings[category], 'y').step(0.1).onChange(function(value) {
- // Fires when a controller loses focus.
- var obj = {};
- obj[category] = {};
- obj[category].x = settings[category].x;
- obj[category][this.property] = value;
- obj[category].z = settings[category].z;
- writeVec3ToInterface(obj);
- });
-
- folder.add(settings[category], 'z').step(0.1).onChange(function(value) {
- // Fires when a controller loses focus.
- var obj = {};
- obj[category] = {};
- obj[category].y = settings[category].y;
- obj[category].x = settings[category].x;
- obj[category][this.property] = value;
- writeVec3ToInterface(obj);
- });
-
- folders.push(folder);
- folder.open();
-}
-
-function createQuatFolder(category) {
- var folder = gui.addFolder(category);
-
- folder.add(settings[category], 'x').step(0.1).onChange(function(value) {
- // Fires when a controller loses focus.
- var obj = {};
- obj[category] = {};
- obj[category][this.property] = value;
- obj[category].y = settings[category].y;
- obj[category].z = settings[category].z;
- obj[category].w = settings[category].w;
- writeVec3ToInterface(obj);
- });
-
- folder.add(settings[category], 'y').step(0.1).onChange(function(value) {
- // Fires when a controller loses focus.
- var obj = {};
- obj[category] = {};
- obj[category].x = settings[category].x;
- obj[category][this.property] = value;
- obj[category].z = settings[category].z;
- obj[category].w = settings[category].w;
- writeVec3ToInterface(obj);
- });
-
- folder.add(settings[category], 'z').step(0.1).onChange(function(value) {
- // Fires when a controller loses focus.
- var obj = {};
- obj[category] = {};
- obj[category].x = settings[category].x;
- obj[category].y = settings[category].y;
- obj[category][this.property] = value;
- obj[category].w = settings[category].w;
- writeVec3ToInterface(obj);
- });
-
- folder.add(settings[category], 'w').step(0.1).onChange(function(value) {
- // Fires when a controller loses focus.
- var obj = {};
- obj[category] = {};
- obj[category].x = settings[category].x;
- obj[category].y = settings[category].y;
- obj[category].z = settings[category].z;
- obj[category][this.property] = value;
- writeVec3ToInterface(obj);
- });
-
- folders.push(folder);
- folder.open();
-}
-
-function convertColorObjectToArray(colorObject) {
- var colorArray = [];
-
- _.each(colorObject, function(singleColor) {
- colorArray.push(singleColor);
- });
-
- return colorArray;
-}
-
-function convertColorArrayToObject(colorArray) {
- var colorObject = {
- red: colorArray[0],
- green: colorArray[1],
- blue: colorArray[2]
- };
-
- return colorObject;
-}
-
-function writeDataToInterface(property, value) {
- var data = {};
- data[property] = value;
-
- var sendData = {
- messageType: "settings_update",
- updatedSettings: data
- };
-
- var stringifiedData = JSON.stringify(sendData);
-
- EventBridge.emitWebEvent(stringifiedData);
-}
-
-function writeVec3ToInterface(obj) {
- var sendData = {
- messageType: "settings_update",
- updatedSettings: obj
- };
-
- var stringifiedData = JSON.stringify(sendData);
-
- EventBridge.emitWebEvent(stringifiedData);
-}
-
-function listenForSettingsUpdates() {
- EventBridge.scriptEventReceived.connect(function(data) {
- data = JSON.parse(data);
-
- //2-way
- // if (data.messageType === 'object_update') {
- // _.each(data.objectSettings, function(value, key) {
- // settings[key] = value;
- // });
- // }
-
- if (data.messageType === 'initial_settings') {
- _.each(data.initialSettings, function(value, key) {
- settings[key] = {};
- settings[key] = value;
- });
-
- loadGUI();
- }
- });
-}
-
-function manuallyUpdateDisplay() {
- // Iterate over all controllers
- // this is expensive, write a method for indiviudal controllers and use it when the value is different than a cached value, perhaps.
- var i;
- for (i in gui.__controllers) {
- gui.__controllers[i].updateDisplay();
- }
-}
-
-function setGUIWidthToWindowWidth() {
- if (gui !== null) {
- gui.width = window.innerWidth;
- }
-}
-
-function handleInputKeyPress(e) {
- if (e.keyCode === 13) {
- importSettings();
- }
- return false;
-}
-
-function importSettings() {
- var importInput = document.getElementById('importer-input');
-
- try {
- var importedSettings = JSON.parse(importInput.value);
-
- var keys = _.keys(importedSettings);
-
- _.each(keys, function(key) {
- var shouldIgnore = _.contains(keysToIgnore, key);
-
- if (shouldIgnore) {
- return;
- }
-
- settings[key] = importedSettings[key];
- });
-
- writeVec3ToInterface(settings);
-
- manuallyUpdateDisplay();
- } catch (e) {
- alert('Not properly formatted JSON');
- }
-}
-
-function prepareSettingsForExport() {
- var keys = _.keys(settings);
-
- var exportSettings = {};
-
- _.each(keys, function(key) {
- var shouldIgnore = _.contains(keysToIgnore, key);
-
- if (shouldIgnore) {
- return;
- }
-
- if (key.indexOf('color') > -1) {
- var colorObject = convertColorArrayToObject(settings[key]);
- settings[key] = colorObject;
- }
-
- exportSettings[key] = settings[key];
- });
-
- return JSON.stringify(exportSettings);
-}
-
-function showPreselectedPrompt() {
- window.prompt("Ctrl-C to copy, then Enter.", prepareSettingsForExport());
-}
-
-function removeContainerDomElement() {
- var elem = document.getElementById("my-gui-container");
- elem.parentNode.removeChild(elem);
-}
-
-function removeListenerFromGUI(key) {
- _.each(gui.__listening, function(controller, index) {
- if (controller.property === key) {
- storedController = controller;
- gui.__listening.splice(index, 1);
- }
- });
-}
-
-//the section below is to try to work at achieving two way bindings;
-function addListenersBackToGUI() {
- gui.__listening.push(storedController);
- storedController = null;
-}
-
-function registerDOMElementsForListenerBlocking() {
- _.each(gui.__controllers, function(controller) {
- var input = controller.domElement.childNodes[0];
- input.addEventListener('focus', function() {
- console.log('INPUT ELEMENT GOT FOCUS!' + controller.property);
- removeListenerFromGUI(controller.property);
- });
- });
-
- _.each(gui.__controllers, function(controller) {
- var input = controller.domElement.childNodes[0];
- input.addEventListener('blur', function() {
- console.log('INPUT ELEMENT GOT BLUR!' + controller.property);
- addListenersBackToGUI();
- });
- });
-
- // also listen to inputs inside of folders
- _.each(gui.__folders, function(folder) {
- _.each(folder.__controllers, function(controller) {
- var input = controller.__input;
- input.addEventListener('focus', function() {
- console.log('FOLDER ELEMENT GOT FOCUS!' + controller.property);
- });
- });
- });
-}
-
diff --git a/examples/particle_explorer/index.html b/examples/particle_explorer/particleExplorer.html
similarity index 57%
rename from examples/particle_explorer/index.html
rename to examples/particle_explorer/particleExplorer.html
index 4b9e2a9d36..d69d221306 100644
--- a/examples/particle_explorer/index.html
+++ b/examples/particle_explorer/particleExplorer.html
@@ -1,5 +1,5 @@