0
0
Fork 0
mirror of https://github.com/liabru/matter-js.git synced 2024-12-25 13:39:06 -05:00

further work on Matter.Inspector

This commit is contained in:
liabru 2014-04-30 12:14:06 +01:00
parent 5f3e69cb70
commit 84c3b79c2c
3 changed files with 330 additions and 137 deletions

View file

@ -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 {

View file

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

View file

@ -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 = $('<div class="ins-container">'),
$buttonGroup = $('<div class="ins-control-group">'),
$searchBox = $('<input class="ins-search-box" type="search" placeholder="search">'),
$importButton = $('<button class="ins-import-button ins-button">Import</button>'),
$exportButton = $('<button class="ins-export-button ins-button">Export</button>'),
$pauseButton = $('<button class="ins-pause-button ins-button">Pause</button>'),
$helpButton = $('<button class="ins-help-button ins-button">Help</button>');
$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 = $('<div class="ins-world-tree">').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);
}
};