/**
* @module core/Editor
* @description Creates all the mouse events necessary to allow the user to add and remove blocks from a World with the added option to autosave all changes.
**/
'use strict';
const {assign} = Object;
/**
* @name Editor
* @constructor
* @param {module:core/World~World} world World to edit
* @param {object} options Options to configure editor
* @param {boolean} [options.autosave=true] Flag to enable auto saving functionality
* @example <caption>Create an editor and add a voxel</caption>
* const Voxelcss = require('voxelcss');
* let scene = new Voxelcss.Scene();
* let world = new Voxelcss.World(scene);
* scene.attach(document.body);
* let editor = new Voxelcss.Editor(world);
* let position = [10, 10, 10];
* let size = 100;
* editor.add(new Voxelcss.Voxel(position, size));
* @example <caption>Add a voxel with grass mesh</caption>
* let mesh = Voxelcss.meshes.grass;
* let grass = new Voxelcss.Voxel(position, size, {mesh});
* editor.add(grass);
**/
module.exports = function(world, options) {
if (world === undefined) {
throw 'Editor requires World instance for initialization';
}
let self = this;
let canAutoSave = (options !== undefined && options.autosave === true);
let isEnabled = true;
const bindVoxel = voxel => voxel.on({
'change:mesh': () => (self.canAutoSave() && self.save()),
'contextmenu': e => (self.isEnabled() && remove(e.target)),
'click:top': e => performAddativeShift(e, [0, 1, 0]),
'click:bottom': e => performAddativeShift(e, [0, -1, 0]),
'click:front': e => performAddativeShift(e, [0, 0, 1]),
'click:back': e => performAddativeShift(e, [0, 0, -1]),
'click:left': e => performAddativeShift(e, [-1, 0, 0]),
'click:right': e => performAddativeShift(e, [1, 0, 0])
});
const loadWorldVoxels = () => world.getVoxels().forEach(bindVoxel);
assign(self, {
add,
remove,
getWorld: () => world,
isEnabled: () => isEnabled,
enable: () => (isEnabled = true),
disable: () => (isEnabled = false),
canAutoSave: () => canAutoSave,
enableAutoSave: () => (canAutoSave = true),
disableAutoSave: () => (canAutoSave = false),
isSaved: () => world.isSaved(),
deleteSave: () => world.deleteSave(),
export: () => world.export(),
import: (data) => {
world.import(data);
loadWorldVoxels();
},
save: () => world.save(),
load: () => {
world.load();
loadWorldVoxels();
}
});
loadWorldVoxels();
function add(voxel) {
voxel.off();
bindVoxel(voxel);
world.add(voxel);
self.canAutoSave() && world.save();
return self;
}
function remove(voxel) {
world.remove(voxel) && voxel.off();
self.canAutoSave() && world.save();
return self;
}
function performAddativeShift(event, position) {
if (self.isEnabled()) {
let voxel = event.target;
let dimension = voxel.getDimension();
position = position.map(val => val * dimension);
add(voxel.clone().translate(...position));
}
}
};