Skip to content

Commit

Permalink
Merge pull request #466 from squirrelo/save-context
Browse files Browse the repository at this point in the history
Save controller and camera settings
  • Loading branch information
ElDeveloper committed May 4, 2016
2 parents 56f769f + 6b32bfc commit ab5c050
Show file tree
Hide file tree
Showing 13 changed files with 331 additions and 27 deletions.
46 changes: 46 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,3 +270,49 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

### contextMenu [2.1.1](https://github.com/swisnl/jQuery-contextMenu)
MIT licensed

--------------------------------------------------------------------------------

### FileSaver [1.1.20160328](https://github.com/eligrey/FileSaver.js/)

Copyright © 2015 Eli Grey.

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

--------------------------------------------------------------------------------

### Blob [079824b] (https://github.com/eligrey/Blob.js/tree/079824b6c118fbcd0b99c561d57ad192d2c6619b)

Copyright © 2015 Eli Grey.

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 changes: 30 additions & 3 deletions emperor/support_files/js/color-view-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ define([
var val = args.item.category, color = args.item.value;
var group = args.item.plottables;
var element = scope.decompViewDict[scope.getActiveDecompViewKey()];
ColorViewController.setPlottableAttributes(element, color, group);
scope.setPlottableAttributes(element, color, group);
},
'categorySelectionCallback':
function(evt, params) {
Expand Down Expand Up @@ -129,7 +129,7 @@ define([
var colorInfo = ColorViewController.getColorList(uniqueVals, colorScheme, discrete, scaled);
var attributes = colorInfo[0];
// fetch the slickgrid-formatted data
var data = decompViewDict.setCategory(attributes, ColorViewController.setPlottableAttributes, category);
var data = decompViewDict.setCategory(attributes, scope.setPlottableAttributes, category);

if (scaled) {
scope.setSlickGridDataset({});
Expand Down Expand Up @@ -257,6 +257,33 @@ define([
return [colors, gradientSVG];
};

/**
* Converts the current instance into a JSON string.
*
* @return {Object} JSON ready representation of self.
*/
ColorViewController.prototype.toJSON = function() {
var json = EmperorAttributeABC.prototype.toJSON.call(this);
json.colormap = this.$colormapSelect.val();
json.continuous = this.$scaled.is(':checked');
return json;
}

/**
* Decodes JSON string and modifies its own instance variables accordingly.
*
* @param {Object} Parsed JSON string representation of self.
*/
ColorViewController.prototype.fromJSON = function(json) {
// Order here is important. We want to set all the extra controller
// settings before we load from json, as they can override the JSON when set
this.$colormapSelect.val(json.colormap);
this.$colormapSelect.trigger('chosen:updated');
this.$scaled.prop('checked', json.continuous);
this.$scaled.trigger('change');
EmperorAttributeABC.prototype.fromJSON.call(this, json);
}

/**
*
* Retrieve a discrete color.
Expand Down Expand Up @@ -297,7 +324,7 @@ define([
* @param {group} array of objects, list of object that should be changed in
* scope
*/
ColorViewController.setPlottableAttributes = function(scope, color, group){
ColorViewController.prototype.setPlottableAttributes = function(scope, color, group){
var idx;

_.each(group, function(element) {
Expand Down
103 changes: 100 additions & 3 deletions emperor/support_files/js/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ define([
"scene3d",
"colorviewcontroller",
"visibilitycontroller",
"shapecontroller"

"shapecontroller",
"filesaver"
], function ($, _, contextMenu, THREE, DecompositionView, ScenePlotView3D,
ColorViewController, VisibilityController, ShapeController) {
ColorViewController, VisibilityController, ShapeController,
FileSaver) {

/**
*
Expand Down Expand Up @@ -262,6 +263,47 @@ define([
selector: '#' + scope.$divId.attr('id') + ' .emperor-plot-wrapper',
trigger: 'none',
items: {
'saveState': {
name: 'Save current settings',
icon: 'edit',
callback: function(key, opts) {
scope.saveConfig();
}
},
'loadState': {
name: 'Load saved settings',
icon: 'paste',
callback: function(key, opts) {
if (!FileReader) {
alert("Your browser does not support file loading. We recommend using Google Chrome for full functionality.");
return;
}
var file = $('<input type="file">');
file.on('change', function(evt) {
var f = evt.target.files[0];
// With help from
// http://www.htmlgoodies.com/beyond/javascript/read-text-files-using-the-javascript-filereader.html
var r = new FileReader();
r.onload = function(e) {
try {
var json = JSON.parse(e.target.result);
} catch (err) {
alert("File given is not a JSON parsable file.");
return;
}
try {
scope.loadConfig(json);
} catch (err) {
alert("Error loading settings from file: " + err.message);
return;
}
};
r.readAsText(f);
});
file.click();
}
},
"sep1": "---------",
'saveImage': {
name: 'Save Image (PNG)',
icon: 'edit',
Expand Down Expand Up @@ -300,6 +342,61 @@ define([
download.get(0).click();
};

/**
*
* Write settings file for the current controller settings
*
* The format is as follows: a javascript object with the camera position
* stored in the 'cameraPosition' key and the quaternion in the
* 'cameraQuaternion' key. Each controller in this.controllers is then saved
* by calling toJSON on them, and the resulting object saved under the same
* key as the controllers object.
*
**/
EmperorController.prototype.saveConfig = function() {
var saveinfo = {};
// Assuming single sceneview for now
sceneview = this.sceneViews[0];
saveinfo.cameraPosition = sceneview.camera.position;
saveinfo.cameraQuaternion = sceneview.camera.quaternion;
// Save settings for each controller in the view
_.each(this.controllers, function(controller, index) {
if (controller !== undefined) {
saveinfo[index] = controller.toJSON();
}
});

// Save the file
var blob = new Blob([JSON.stringify(saveinfo)], {type: "text/json"});
saveAs(blob, "emperor-settings.json");
};

/**
*
* Load a settings file and set all controller variables
*
* @param {object} [json] Emperor save information
*
**/
EmperorController.prototype.loadConfig = function(json) {
//still assuming one sceneview for now
var sceneview = this.sceneViews[0];

sceneview.camera.position.set(json.cameraPosition.x, json.cameraPosition.y, json.cameraPosition.z);
sceneview.camera.quaternion.set(json.cameraQuaternion._x, json.cameraQuaternion._y, json.cameraQuaternion._z, json.cameraQuaternion._w);

//must call updates to reset for camera move
sceneview.camera.updateProjectionMatrix();
sceneview.control.update();

//load the rest of the controller settings
_.each(this.controllers, function(controller, index) {
if (controller !== undefined) {
controller.fromJSON(json[index]);
}
});
};

/**
*
* Helper method to resize the plots.
Expand Down
6 changes: 3 additions & 3 deletions emperor/support_files/js/shape-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ define([
var val = args.item.category, shape = args.item.value;
var group = args.item.plottables;
var element = scope.decompViewDict[scope.getActiveDecompViewKey()];
ShapeController.setPlottableAttributes(element, shape, group);
scope.setPlottableAttributes(element, shape, group);
},
'categorySelectionCallback': function(evt, params) {
var category = scope.$select.val();
Expand All @@ -58,7 +58,7 @@ define([
attributes[uniqueVals[index]] = 'sphere';
}
// fetch the slickgrid-formatted data
var data = decompViewDict.setCategory(attributes, ShapeController.setPlottableAttributes, category);
var data = decompViewDict.setCategory(attributes, scope.setPlottableAttributes, category);

scope.setSlickGridDataset(data);
},
Expand Down Expand Up @@ -88,7 +88,7 @@ define([
* @param {group} array of objects, list of object that should be changed in
* scope
*/
ShapeController.setPlottableAttributes = function(scope, shape, group) {
ShapeController.prototype.setPlottableAttributes = function(scope, shape, group) {
var idx;
var geometry = shapes.shapes[shape];
if (geometry === undefined) {
Expand Down
42 changes: 39 additions & 3 deletions emperor/support_files/js/view-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,18 +155,19 @@ define([
};

/**
*
* Converts the current instance into a JSON string.
*
* @return {String} JSON string representation of self.
* @return {Object} ready to serialize representation of self.
*/
EmperorViewControllerABC.prototype.toJSON = function(){
EmperorViewControllerABC.prototype.toJSON = function() {
throw Error('Not implemented');
};

/**
* Decodes JSON string and modifies its own instance variables accordingly.
*
* @param {String} JSON string representation of an instance.
* @param {Object} parsed JSON string representation of an instance.
*/
EmperorViewControllerABC.prototype.fromJSON = function(jsonString){
throw Error('Not implemented');
Expand Down Expand Up @@ -392,6 +393,41 @@ define([
}
};

/**
* Converts the current instance into a JSON object.
*
* @return {Object} base object ready for JSON conversion.
*/
EmperorAttributeABC.prototype.toJSON = function() {
var json = {};
json.category = this.$select.val();

// Convert SlickGrid list of objects to single object
var gridData = this.bodyGrid.getData();
var jsonData = {};
for(var i = 0; i < gridData.length; i++) {
jsonData[gridData[i].category] = gridData[i].value;
}
json.data = jsonData;
return json;
};

/**
* Decodes JSON string and modifies its own instance variables accordingly.
*
* @param {Object} Parsed JSON string representation of self.
*
*/
EmperorAttributeABC.prototype.fromJSON = function(json) {
this.$select.val(json.category);
this.$select.trigger('chosen:updated');

// fetch and set the SlickGrid-formatted data
var k = this.getActiveDecompViewKey();
var data = this.decompViewDict[k].setCategory(json.data, this.setPlottableAttributes, json.category);
this.setSlickGridDataset(data);
};

return {'EmperorViewControllerABC': EmperorViewControllerABC,
'EmperorAttributeABC': EmperorAttributeABC};
});
7 changes: 3 additions & 4 deletions emperor/support_files/js/visibility-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ define([
var visible = args.item.value;
var group = args.item.plottables;
var element = scope.decompViewDict[scope.getActiveDecompViewKey()];
VisibilityController.setPlottableAttributes(element, visible, group);
scope.setPlottableAttributes(element, visible, group);
},
'categorySelectionCallback':function(evt, params) {
var category = scope.$select.val();
Expand All @@ -73,7 +73,7 @@ define([
attributes[value] = true;
});
// fetch the slickgrid-formatted data
var data = decompViewDict.setCategory(attributes, VisibilityController.setPlottableAttributes, category);
var data = decompViewDict.setCategory(attributes, scope.setPlottableAttributes, category);

scope.setSlickGridDataset(data);
},
Expand All @@ -91,7 +91,6 @@ define([
VisibilityController.prototype = Object.create(EmperorAttributeABC.prototype);
VisibilityController.prototype.constructor = EmperorAttributeABC;


/**
* Helper function to set the visibility of plottable
*
Expand All @@ -100,7 +99,7 @@ define([
* @param {group} array of objects, list of object that should be changed in
* scope
*/
VisibilityController.setPlottableAttributes = function(scope, visible, group){
VisibilityController.prototype.setPlottableAttributes = function(scope, visible, group){
var idx;

_.each(group, function(element) {
Expand Down
5 changes: 5 additions & 0 deletions emperor/support_files/templates/main-template.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
/* other libraries */
'underscore': '{{ base_url }}/vendor/js/underscore-min',
'chroma': '{{ base_url }}/vendor/js/chroma.min',
'filesaver': '{{ base_url }}/vendor/js/FileSaver.min',
'blob': '{{ base_url }}/vendor/js/Blob',


/* THREE.js and plugins */
Expand Down Expand Up @@ -61,6 +63,9 @@
'contextmenu' : {
'deps': ['jquery', 'jqueryui', 'position']
},
'filesaver' : {
'deps': ['blob']
},
'orbitcontrols': {
'deps': ['three']
},
Expand Down
16 changes: 16 additions & 0 deletions emperor/support_files/vendor/js/Blob.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit ab5c050

Please sign in to comment.