diff --git a/demo/css/matter-tools.css b/demo/css/matter-tools.css
index 4870ff0..958da6e 100644
--- a/demo/css/matter-tools.css
+++ b/demo/css/matter-tools.css
@@ -8,40 +8,44 @@ body .dg.main {
body.gui-auto-hide .dg.ac {
right: -233px;
-
- -webkit-transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415);
- -moz-transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415);
- -o-transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415);
- transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415); /* custom */
-
- -webkit-transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415);
- -moz-transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415);
- -o-transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415);
- transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415); /* custom */
-
- transition-delay: 3s;
- -webkit-transition-delay: 3s;
}
body .dg.ac:hover,
body.gui-show .dg.ac {
right: 0px;
+}
+body.gui-auto-hide.gui-transitions .dg.ac {
+ -webkit-transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415);
+ -moz-transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415);
+ -o-transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415);
+ transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415);
+
+ -webkit-transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415);
+ -moz-transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415);
+ -o-transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415);
+ transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415);
+
+ transition-delay: 3s;
+ -webkit-transition-delay: 3s;
+}
+
+body.gui-transitions .dg.ac:hover,
+body.gui-show.gui-transitions .dg.ac {
-webkit-transition: all 500ms cubic-bezier(0.095, 0.665, 0.400, 0.835);
-moz-transition: all 500ms cubic-bezier(0.095, 0.665, 0.400, 0.835);
-o-transition: all 500ms cubic-bezier(0.095, 0.665, 0.400, 0.835);
- transition: all 500ms cubic-bezier(0.095, 0.665, 0.400, 0.835); /* custom */
+ transition: all 500ms cubic-bezier(0.095, 0.665, 0.400, 0.835);
-webkit-transition-timing-function: cubic-bezier(0.095, 0.665, 0.400, 0.835);
-moz-transition-timing-function: cubic-bezier(0.095, 0.665, 0.400, 0.835);
-o-transition-timing-function: cubic-bezier(0.095, 0.665, 0.400, 0.835);
- transition-timing-function: cubic-bezier(0.095, 0.665, 0.400, 0.835); /* custom */
+ transition-timing-function: cubic-bezier(0.095, 0.665, 0.400, 0.835);
transition-delay: 0;
-webkit-transition-delay: 0;
}
-
body .dg.main.taller-than-window .close-button {
border-top: 1px solid #444;
border-right: 4px solid #444;
@@ -89,6 +93,7 @@ body .dg li.save-row .button {
body .dg li.title {
padding-left: 22px;
+ border-bottom: 1px solid #555;
background: #444 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 10px 10px no-repeat;
}
@@ -166,12 +171,12 @@ body .dg.a {
.ins-container {
position: fixed;
overflow: auto;
- width: 220px;
+ width: 260px;
bottom: 0;
top: 0;
left: 0;
background: #3d3d3d;
- padding: 1% 20px;
+ padding: 0;
font-family: Arial;
font-size: 12px;
color: #aaa;
@@ -182,46 +187,106 @@ body .dg.a {
.ins-auto-hide .ins-container {
left: -245px;
border-right: 1px dotted #888;
-
- -webkit-transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415);
- -moz-transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415);
- -o-transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415);
- transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415); /* custom */
-
- -webkit-transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415);
- -moz-transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415);
- -o-transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415);
- transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415); /* custom */
-
- transition-delay: 3s;
- -webkit-transition-delay: 3s;
}
.ins-container:hover,
.ins-show .ins-container {
left: 0px;
border-right: 0px dotted #888;
+}
+.ins-transitions .ins-container {
+ -webkit-transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415);
+ -moz-transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415);
+ -o-transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415);
+ transition: all 500ms cubic-bezier(0.965, 0.025, 0.735, 0.415);
+
+ -webkit-transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415);
+ -moz-transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415);
+ -o-transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415);
+ transition-timing-function: cubic-bezier(0.965, 0.025, 0.735, 0.415);
+
+ transition-delay: 3s;
+ -webkit-transition-delay: 3s;
+}
+
+.ins-transitions .ins-container:hover,
+.ins-transitions.ins-show .ins-container {
-webkit-transition: all 500ms cubic-bezier(0.095, 0.665, 0.400, 0.835);
-moz-transition: all 500ms cubic-bezier(0.095, 0.665, 0.400, 0.835);
-o-transition: all 500ms cubic-bezier(0.095, 0.665, 0.400, 0.835);
- transition: all 500ms cubic-bezier(0.095, 0.665, 0.400, 0.835); /* custom */
+ transition: all 500ms cubic-bezier(0.095, 0.665, 0.400, 0.835);
-webkit-transition-timing-function: cubic-bezier(0.095, 0.665, 0.400, 0.835);
-moz-transition-timing-function: cubic-bezier(0.095, 0.665, 0.400, 0.835);
-o-transition-timing-function: cubic-bezier(0.095, 0.665, 0.400, 0.835);
- transition-timing-function: cubic-bezier(0.095, 0.665, 0.400, 0.835); /* custom */
+ transition-timing-function: cubic-bezier(0.095, 0.665, 0.400, 0.835);
transition-delay: 0;
-webkit-transition-delay: 0;
}
+.ins-search-box {
+ margin: 14px 23px;
+ border: 0;
+ padding: 7px 8px;
+ font-size: 12px;
+ width: 80%;
+ box-sizing: border-box;
+ border-radius: 3px;
+ background: #444;
+ border: 1px solid #444;
+ color: #999;
+}
+
+.ins-search-box:focus {
+ background: #484848;
+ color: #aaa;
+ border: 1px solid rgba(255,255,255,0.1);
+ outline: 0;
+}
+
+.ins-search-box::-webkit-search-cancel-button {
+ -webkit-appearance: none;
+ height: 15px;
+ width: 8px;
+ cursor: pointer;
+}
+
+.ins-search-box::-webkit-search-cancel-button:before {
+ height: 10px;
+ width: 10px;
+ content: 'x';
+ font-family: Arial;
+ line-height: 0;
+ font-size: 13px;
+ color: #999;
+ font-weight: bold;
+ cursor: pointer;
+}
+
+.ins-search-box::-webkit-input-placeholder {
+ color: #777;
+}
+
+.ins-search-box:-moz-placeholder {
+ color: #777;
+}
+
+.ins-search-box::-moz-placeholder {
+ color: #777;
+}
+
+.ins-search-box:-ms-input-placeholder {
+ color: #777;
+}
+
.ins-world-tree {
overflow: auto;
position: absolute;
left: -24px;
right: 0px;
- top: 60px;
+ top: 110px;
bottom: 8px;
}
@@ -229,7 +294,9 @@ body .dg.a {
display: block;
clear: both;
overflow: hidden;
- margin: 8px 0;
+ padding: 14px 20px 12px 20px;
+ background: #444;
+ border-bottom: 1px solid #555;
}
.ins-button {
@@ -237,14 +304,16 @@ body .dg.a {
float: left;
margin: 0 2px;
font-size: 11px;
+ line-height: 1;
padding: 6px 8px;
- min-width: 51px;
+ min-width: 49px;
text-align: center;
background: #333;
border: 0;
color: #aaa;
border-radius: 2px;
border-bottom: 2px solid #2e2e2e;
+ box-sizing: border-box;
}
.ins-button:hover {
@@ -252,6 +321,12 @@ body .dg.a {
border-bottom: 2px solid #2fa1d6;
}
+.jstree-default .jstree-search {
+ font-style: italic;
+ color: #aaa;
+ font-weight: normal;
+}
+
.jstree-default .jstree-wholerow-hovered,
.jstree-default .jstree-hovered {
background: transparent;
@@ -271,11 +346,19 @@ body .dg.a {
transition: none;
}
+.jstree-default .jstree-leaf .jstree-clicked {
+ color: #bbb !important;
+
+ -webkit-transition: color 100ms linear;
+ -moz-transition: color 100ms linear;
+ -o-transition: color 100ms linear;
+ transition: color 100ms linear;
+}
+
.jstree-default .jstree-open > .jstree-children > .jstree-node > .jstree-anchor:before {
content: '';
display: block;
position: absolute;
- z-index: -1;
left: 0;
right: 1px;
height: 26px;
@@ -283,10 +366,22 @@ body .dg.a {
border-radius: 0;
box-shadow: none;
border-right: none;
+ pointer-events: none;
+ background: rgba(0,0,0,0);
+
+ -webkit-transition: background 100ms linear;
+ -moz-transition: background 100ms linear;
+ -o-transition: background 100ms linear;
+ transition: background 100ms linear;
}
.jstree-default .jstree-anchor.jstree-clicked:before {
- background: #373737 !important;
+ background: rgba(0,0,0,0.1) !important;
+
+ -webkit-transition: background 100ms linear;
+ -moz-transition: background 100ms linear;
+ -o-transition: background 100ms linear;
+ transition: background 100ms linear;
}
.jstree-default .jstree-node-type-body > .jstree-anchor:before {
diff --git a/src/render/Render.js b/src/render/Render.js
index cbae199..de09876 100644
--- a/src/render/Render.js
+++ b/src/render/Render.js
@@ -707,7 +707,8 @@ var Render = {};
context.translate(0.5, 0.5);
context.lineWidth = 1;
- context.strokeStyle = 'rgba(255,165,0,0.8)';
+ context.strokeStyle = 'rgba(255,165,0,0.9)';
+ context.setLineDash([1,2]);
switch (item.type) {
@@ -738,6 +739,7 @@ var Render = {};
}
+ context.setLineDash([0]);
context.translate(-0.5, -0.5);
}
@@ -745,15 +747,15 @@ var Render = {};
if (inspector.selectStart !== null) {
context.translate(0.5, 0.5);
context.lineWidth = 1;
- context.setLineDash([1,2]);
- context.strokeStyle = 'rgba(255,165,0,0.5)';
+ context.strokeStyle = 'rgba(255,165,0,0.6)';
+ context.fillStyle = 'rgba(255,165,0,0.1)';
bounds = inspector.selectBounds;
context.beginPath();
context.rect(Math.floor(bounds.min.x), Math.floor(bounds.min.y),
Math.floor(bounds.max.x - bounds.min.x), Math.floor(bounds.max.y - bounds.min.y));
context.closePath();
context.stroke();
- context.setLineDash([0]);
+ context.fill();
context.translate(-0.5, -0.5);
}
};
diff --git a/src/tools/Inspector.js b/src/tools/Inspector.js
index 5873201..acff43f 100644
--- a/src/tools/Inspector.js
+++ b/src/tools/Inspector.js
@@ -10,6 +10,7 @@ var Inspector = {};
(function() {
var _key,
+ _isWebkit = 'WebkitAppearance' in document.documentElement.style,
$body;
/**
@@ -36,13 +37,17 @@ var Inspector = {};
selectStart: null,
selectEnd: null,
selectBounds: Bounds.create(),
- root: Composite.create()
+ autoHide: true,
+ hasTransitions: _isWebkit ? true : false,
+ root: Composite.create({
+ label: 'Root'
+ })
};
inspector = Common.extend(inspector, options);
if (Resurrect) {
- inspector.serializer = new Resurrect({ prefix: '$' });
+ inspector.serializer = new Resurrect({ prefix: '$', cleanup: true });
inspector.serializer.parse = inspector.serializer.resurrect;
} else {
inspector.serializer = JSON;
@@ -52,7 +57,8 @@ var Inspector = {};
_key = window.key || {};
Inspector.instance = inspector;
- $body.addClass('ins-auto-hide gui-auto-hide');
+ $body.toggleClass('ins-auto-hide gui-auto-hide', inspector.autoHide);
+ $body.toggleClass('ins-transitions gui-transitions', inspector.hasTransitions);
Composite.add(inspector.root, engine.world);
engine.world.parent = null;
@@ -71,19 +77,21 @@ var Inspector = {};
var $inspectorContainer = $('
'),
$buttonGroup = $('
'),
+ $searchBox = $('
'),
$importButton = $('
'),
$exportButton = $('
'),
$pauseButton = $('
'),
$helpButton = $('
');
$buttonGroup.append($pauseButton, $importButton, $exportButton, $helpButton);
- $inspectorContainer.prepend($buttonGroup);
+ $inspectorContainer.prepend($buttonGroup, $searchBox);
$body.prepend($inspectorContainer);
controls.pauseButton = $pauseButton;
controls.importButton = $importButton;
controls.exportButton = $exportButton;
controls.helpButton = $helpButton;
+ controls.searchBox = $searchBox;
controls.container = $inspectorContainer;
controls.pauseButton.click(function() {
@@ -99,22 +107,46 @@ var Inspector = {};
});
controls.helpButton.click(function() {
- var help = "matter-inspector quick help \n\n";
-
- help += "drag nodes in the tree to move them between composites \n\n";
- help += "[shift + space] to pause or play simulation \n";
- help += "[right click] and drag to select objects \n";
- help += "[del] or [backspace] to delete selected objects \n";
- help += "[shift + s] to scale-xy selected objects with mouse \n";
- help += "[shift + s + d] to scale-x selected objects with mouse \n";
- help += "[shift + s + f] to scale-y selected objects with mouse \n";
- help += "[shift + r] to rotate selected objects with mouse \n";
- help += "[shift + i] to import objects \n";
- help += "[shift + o] to export selected objects\n";
- help += "\nnote: inspector will only render if the renderer in use supports it";
-
- alert(help);
+ _showHelp(inspector);
});
+
+ var searchTimeout;
+
+ controls.searchBox.keyup(function () {
+ clearTimeout(searchTimeout);
+ searchTimeout = setTimeout(function () {
+ var value = controls.searchBox.val(),
+ worldTree = controls.worldTree.data('jstree');
+ worldTree.search(value);
+ }, 250);
+ });
+ };
+
+ var _showHelp = function(inspector) {
+ var help = "Matter Tools \n\n";
+
+ help += "Drag nodes in the tree to move them between composites. \n\n";
+ help += "Use browser's developer console to inspect selected objects. \n\n";
+ help += "Note: selections only render if renderer supports it. \n\n";
+
+ help += "[shift + space] pause or play simulation. \n";
+ help += "[right click] and drag to select objects. \n";
+ help += "[del] or [backspace] delete selected objects. \n\n";
+
+ help += "[shift + s] scale-xy selected objects with mouse. \n";
+ help += "[shift + s + d] scale-x selected objects with mouse. \n";
+ help += "[shift + s + f] scale-y selected objects with mouse. \n";
+ help += "[shift + r] rotate selected objects with mouse. \n\n";
+
+ help += "[shift + q] set selected objects as static (can't be undone). \n";
+ help += "[shift + i] import objects. \n";
+ help += "[shift + o] export selected objects. \n";
+ help += "[shift + h] toggle Matter.Gui. \n";
+ help += "[shift + y] toggle auto-hide. \n\n";
+
+ help += "[shift + j] show this help message.";
+
+ alert(help);
};
var _initKeybinds = function(inspector) {
@@ -133,13 +165,39 @@ var Inspector = {};
_importFile(inspector);
});
+ _key('shift+j', function() {
+ _showHelp(inspector);
+ });
+
+ _key('shift+y', function() {
+ inspector.autoHide = !inspector.autoHide;
+ $body.toggleClass('ins-auto-hide gui-auto-hide', inspector.autoHide);
+ });
+
+ _key('shift+q', function() {
+ var worldTree = inspector.controls.worldTree.data('jstree');
+ for (var i = 0; i < inspector.selected.length; i++) {
+ var object = inspector.selected[i].data;
+ if (object.type === 'body' && !object.isStatic)
+ Body.setStatic(object, true);
+ }
+ });
+
+ _key('del', function() {
+ _deleteSelectedObjects(inspector);
+ });
+
+ _key('backspace', function() {
+ _deleteSelectedObjects(inspector);
+ });
+
// prevent the backspace key from navigating back
// http://stackoverflow.com/questions/1495219/how-can-i-prevent-the-backspace-key-from-navigating-back
$(document).unbind('keydown').bind('keydown', function (event) {
var doPrevent = false;
if (event.keyCode === 8) {
var d = event.srcElement || event.target;
- if ((d.tagName.toUpperCase() === 'INPUT' && (d.type.toUpperCase() === 'TEXT' || d.type.toUpperCase() === 'PASSWORD' || d.type.toUpperCase() === 'FILE' || d.type.toUpperCase() === 'EMAIL' )) || d.tagName.toUpperCase() === 'TEXTAREA') {
+ if ((d.tagName.toUpperCase() === 'INPUT' && (d.type.toUpperCase() === 'TEXT' || d.type.toUpperCase() === 'PASSWORD' || d.type.toUpperCase() === 'FILE' || d.type.toUpperCase() === 'EMAIL' || d.type.toUpperCase() === 'SEARCH')) || d.tagName.toUpperCase() === 'TEXTAREA') {
doPrevent = d.readOnly || d.disabled;
}
else {
@@ -165,7 +223,14 @@ var Inspector = {};
'dnd': {
'copy': false
},
+ 'search': {
+ 'show_only_matches': true,
+ 'fuzzy': false
+ },
'types': {
+ '#': {
+ 'valid_children': []
+ },
'body': {
'valid_children': []
},
@@ -185,7 +250,7 @@ var Inspector = {};
'valid_children': ['composite']
}
},
- 'plugins' : ['dnd', 'types', 'unique']
+ 'plugins' : ['dnd', 'types', 'unique', 'search']
};
controls.worldTree = $('
').jstree(worldTreeOptions);
@@ -215,17 +280,6 @@ var Inspector = {};
case 'composite':
selected.push(worldObject);
break;
-
- case 'composites':
- case 'bodies':
- case 'constraints':
- var node = worldTree.get_node(nodeId),
- children = worldTree.get_node(nodeId).children;
-
- for (var j = 0; j < children.length; j++)
- worldTree.select_node(children[j], false);
-
- break;
}
}
@@ -257,21 +311,34 @@ var Inspector = {};
newComposite = Composite.get(inspector.root, newCompositeId, 'composite');
Composite.move(prevComposite, worldObject, newComposite);
- node.data.compositeId = newCompositeId;
-
- /*if (newComposite === engine.world) {
- // if moved to the world, remove old tree node
- // it will be regenerated automatically
- worldTree.set_id(nodeId, nodeId + "-dupe");
- //setTimeout(function() {
- // worldTree.delete_node(nodeId);
- //}, 1);
- }*/
}
});
controls.worldTree.on('dblclick.jstree', function(event, data) {
- _setPaused(inspector, true);
+ var worldTree = controls.worldTree.data('jstree'),
+ selected = worldTree.get_selected();
+
+ // select all children of double clicked node
+ for (var i = 0; i < selected.length; i++) {
+ var nodeId = selected[i],
+ objectType = nodeId.split('_')[0],
+ objectId = nodeId.split('_')[1],
+ worldObject = Composite.get(engine.world, objectId, objectType);
+
+ switch (objectType) {
+ case 'composite':
+ case 'composites':
+ case 'bodies':
+ case 'constraints':
+ var node = worldTree.get_node(nodeId),
+ children = worldTree.get_node(nodeId).children;
+
+ for (var j = 0; j < children.length; j++)
+ worldTree.select_node(children[j], false);
+
+ break;
+ }
+ }
});
};
@@ -281,28 +348,10 @@ var Inspector = {};
Events.on(engine, 'tick', function() {
if (engine.world.isModified) {
- var data = _generateCompositeTreeNode(engine.world);
+ var data = _generateCompositeTreeNode(inspector.root, null, true);
_updateTree(controls.worldTree.data('jstree'), data);
_setSelectedObjects(inspector, []);
}
-
- if (key.isPressed('del') || key.isPressed('backspace')) {
- var objects = [],
- worldTree = inspector.controls.worldTree.data('jstree');
-
- for (var i = 0; i < inspector.selected.length; i++) {
- var object = inspector.selected[i].data;
-
- if (object === inspector.engine.world)
- continue;
-
- objects.push(object);
- worldTree.delete_node(object.type + '_' + object.id);
- }
-
- Composite.remove(inspector.root, objects, true);
- _setSelectedObjects(inspector, []);
- }
});
Events.on(engine, 'mouseup', function(event) {
@@ -561,6 +610,24 @@ var Inspector = {};
});
};
+ var _deleteSelectedObjects = function(inspector) {
+ var objects = [],
+ worldTree = inspector.controls.worldTree.data('jstree');
+
+ for (var i = 0; i < inspector.selected.length; i++) {
+ var object = inspector.selected[i].data;
+
+ if (object === inspector.engine.world)
+ continue;
+
+ objects.push(object);
+ worldTree.delete_node(object.type + '_' + object.id);
+ }
+
+ Composite.remove(inspector.root, objects, true);
+ _setSelectedObjects(inspector, []);
+ };
+
var _setPaused = function(inspector, isPaused) {
if (isPaused) {
inspector.engine.timing.timeScale = 0;
@@ -618,37 +685,41 @@ var Inspector = {};
};
var _updateTree = function(tree, data) {
- data.state = data.state || { opened: true };
- tree.settings.core.data = tree.settings.core.data || [data];
- tree.settings.core.data[tree.settings.core.data.length - 1] = data;
+ data[0].state = data[0].state || { opened: true };
+ tree.settings.core.data = data;
tree.refresh(-1);
};
- var _generateCompositeTreeNode = function(composite, compositeId) {
- var node = {
- id: 'composite_' + composite.id,
- data: {
- compositeId: compositeId,
- },
- type: 'composite',
- text: (composite.label ? composite.label : 'Composite') + ' ' + composite.id,
- children: [],
- 'li_attr': {
- 'class': 'jstree-node-type-composite'
- }
- };
+ var _generateCompositeTreeNode = function(composite, compositeId, isRoot) {
+ var children = [],
+ node = {
+ id: 'composite_' + composite.id,
+ data: {
+ compositeId: compositeId,
+ },
+ type: 'composite',
+ text: (composite.label ? composite.label : 'Composite') + ' ' + composite.id,
+ 'li_attr': {
+ 'class': 'jstree-node-type-composite'
+ }
+ };
- var childNode = _generateBodiesTreeNode(composite.bodies, composite.id);
+ var childNode = _generateCompositesTreeNode(composite.composites, composite.id);
+ childNode.id = 'composites_' + composite.id;
+ children.push(childNode);
+
+ if (isRoot)
+ return childNode.children;
+
+ childNode = _generateBodiesTreeNode(composite.bodies, composite.id);
childNode.id = 'bodies_' + composite.id;
- node.children.push(childNode);
+ children.push(childNode);
childNode = _generateConstraintsTreeNode(composite.constraints, composite.id);
childNode.id = 'constraints_' + composite.id;
- node.children.push(childNode);
+ children.push(childNode);
- childNode = _generateCompositesTreeNode(composite.composites, composite.id);
- childNode.id = 'composites_' + composite.id;
- node.children.push(childNode);
+ node.children = children;
return node;
};
@@ -741,11 +812,17 @@ var Inspector = {};
toExport = [];
if (inspector.serializer) {
- var exportComposite = Composite.create({
+ if (inspector.selected.length === 0) {
+ alert('No objects were selected, so export could not be created.');
+ return;
+ }
+
+ var fileName = "export-objects",
+ exportComposite = Composite.create({
label: 'Exported Objects'
});
- // add everything else
+ // add everything else, must be in top-down order
for (var i = 0; i < inspector.selected.length; i++) {
var object = inspector.selected[i].data;
@@ -755,8 +832,15 @@ var Inspector = {};
continue;
Composite.add(exportComposite, object);
+
+ // better filename for small exports
+ if (inspector.selected.length === 1)
+ fileName = 'export-' + object.label + '-' + object.id;
}
+ // santise filename
+ fileName = fileName.toLowerCase().replace(/[^\w\-]/g, '') + '.json';
+
var json = inspector.serializer.stringify(exportComposite, function(key, value) {
// skip non-required values
if (key === 'path')
@@ -764,15 +848,23 @@ var Inspector = {};
// limit precision of floats
if (!/^#/.exec(key) && typeof value === 'number') {
- return parseFloat(value.toFixed(2));
+ var fixed = parseFloat(value.toFixed(3));
+
+ // do not limit if limiting will cause value to zero
+ // TODO: this should ideally dynamically find the SF precision required
+ if (fixed === 0 && value !== 0)
+ return value;
+
+ return fixed;
}
+
return value;
- }, 4);
+ });
var blob = new Blob([json], { type: 'application/json' }),
anchor = document.createElement('a');
- anchor.download = 'world.json';
+ anchor.download = fileName;
anchor.href = (window.webkitURL || window.URL).createObjectURL(blob);
anchor.dataset.downloadurl = ['application/json', anchor.download, anchor.href].join(':');
anchor.click();
@@ -804,13 +896,17 @@ var Inspector = {};
Composite.rebase(importedComposite);
importedComposite.label = 'Imported Objects';
- var worldTree = inspector.controls.worldTree.data('jstree'),
- data = _generateCompositeTreeNode(importedComposite),
- coreData = worldTree.settings.core.data;
-
- coreData.unshift(data);
- worldTree.refresh(-1);
Composite.add(inspector.root, importedComposite);
+
+ // move imported composite to the start
+ // so that it appears top of tree
+ inspector.root.composites.splice(inspector.root.composites.length - 1, 1);
+ inspector.root.composites.unshift(importedComposite);
+
+ var worldTree = inspector.controls.worldTree.data('jstree'),
+ data = _generateCompositeTreeNode(inspector.root, null, true);
+
+ _updateTree(worldTree, data);
}
};