mirror of
https://github.com/tengge1/ShadowEditor.git
synced 2026-01-25 15:08:11 +00:00
539 lines
11 KiB
JavaScript
539 lines
11 KiB
JavaScript
/**
|
|
* @author mrdoob / http://mrdoob.com/
|
|
*/
|
|
|
|
var Editor = function () {
|
|
|
|
this.DEFAULT_CAMERA = new THREE.PerspectiveCamera(50, 1, 0.1, 10000);
|
|
this.DEFAULT_CAMERA.name = 'Camera';
|
|
this.DEFAULT_CAMERA.position.set(20, 10, 20);
|
|
this.DEFAULT_CAMERA.lookAt(new THREE.Vector3());
|
|
|
|
var Signal = signals.Signal;
|
|
|
|
this.signals = {
|
|
|
|
// script
|
|
|
|
editScript: new Signal(),
|
|
|
|
// player
|
|
|
|
startPlayer: new Signal(),
|
|
stopPlayer: new Signal(),
|
|
|
|
// vr
|
|
|
|
enterVR: new Signal(),
|
|
|
|
enteredVR: new Signal(),
|
|
exitedVR: new Signal(),
|
|
|
|
// actions
|
|
|
|
showModal: new Signal(),
|
|
|
|
// notifications
|
|
|
|
editorCleared: new Signal(),
|
|
|
|
savingStarted: new Signal(),
|
|
savingFinished: new Signal(),
|
|
|
|
themeChanged: new Signal(),
|
|
|
|
transformModeChanged: new Signal(),
|
|
snapChanged: new Signal(),
|
|
spaceChanged: new Signal(),
|
|
rendererChanged: new Signal(),
|
|
|
|
sceneBackgroundChanged: new Signal(),
|
|
sceneFogChanged: new Signal(),
|
|
sceneGraphChanged: new Signal(),
|
|
|
|
cameraChanged: new Signal(),
|
|
|
|
geometryChanged: new Signal(),
|
|
|
|
objectSelected: new Signal(),
|
|
objectFocused: new Signal(),
|
|
|
|
objectAdded: new Signal(),
|
|
objectChanged: new Signal(),
|
|
objectRemoved: new Signal(),
|
|
|
|
helperAdded: new Signal(),
|
|
helperRemoved: new Signal(),
|
|
|
|
materialChanged: new Signal(),
|
|
|
|
scriptAdded: new Signal(),
|
|
scriptChanged: new Signal(),
|
|
scriptRemoved: new Signal(),
|
|
|
|
windowResize: new Signal(),
|
|
|
|
showGridChanged: new Signal(),
|
|
refreshSidebarObject3D: new Signal(),
|
|
historyChanged: new Signal(),
|
|
refreshScriptEditor: new Signal()
|
|
|
|
};
|
|
|
|
this.config = new Config('threejs-editor');
|
|
this.history = new History(this);
|
|
this.storage = new Storage();
|
|
this.loader = new Loader(this);
|
|
|
|
this.camera = this.DEFAULT_CAMERA.clone();
|
|
|
|
this.scene = new THREE.Scene();
|
|
this.scene.name = 'Scene';
|
|
this.scene.background = new THREE.Color(0xaaaaaa);
|
|
|
|
this.sceneHelpers = new THREE.Scene();
|
|
|
|
this.object = {};
|
|
this.geometries = {};
|
|
this.materials = {};
|
|
this.textures = {};
|
|
this.scripts = {};
|
|
|
|
this.selected = null;
|
|
this.helpers = {};
|
|
|
|
};
|
|
|
|
Editor.prototype = {
|
|
|
|
setTheme: function (value) {
|
|
|
|
document.getElementById('theme').href = value;
|
|
|
|
this.signals.themeChanged.dispatch(value);
|
|
|
|
},
|
|
|
|
//
|
|
|
|
setScene: function (scene) {
|
|
|
|
this.scene.uuid = scene.uuid;
|
|
this.scene.name = scene.name;
|
|
|
|
if (scene.background !== null) this.scene.background = scene.background.clone();
|
|
if (scene.fog !== null) this.scene.fog = scene.fog.clone();
|
|
|
|
this.scene.userData = JSON.parse(JSON.stringify(scene.userData));
|
|
|
|
// avoid render per object
|
|
|
|
this.signals.sceneGraphChanged.active = false;
|
|
|
|
while (scene.children.length > 0) {
|
|
|
|
this.addObject(scene.children[0]);
|
|
|
|
}
|
|
|
|
this.signals.sceneGraphChanged.active = true;
|
|
this.signals.sceneGraphChanged.dispatch();
|
|
|
|
},
|
|
|
|
//
|
|
|
|
addObject: function (object) {
|
|
|
|
var scope = this;
|
|
|
|
object.traverse(function (child) {
|
|
|
|
if (child.geometry !== undefined) scope.addGeometry(child.geometry);
|
|
if (child.material !== undefined) scope.addMaterial(child.material);
|
|
|
|
scope.addHelper(child);
|
|
|
|
});
|
|
|
|
this.scene.add(object);
|
|
|
|
this.signals.objectAdded.dispatch(object);
|
|
this.signals.sceneGraphChanged.dispatch();
|
|
|
|
},
|
|
|
|
moveObject: function (object, parent, before) {
|
|
|
|
if (parent === undefined) {
|
|
|
|
parent = this.scene;
|
|
|
|
}
|
|
|
|
parent.add(object);
|
|
|
|
// sort children array
|
|
|
|
if (before !== undefined) {
|
|
|
|
var index = parent.children.indexOf(before);
|
|
parent.children.splice(index, 0, object);
|
|
parent.children.pop();
|
|
|
|
}
|
|
|
|
this.signals.sceneGraphChanged.dispatch();
|
|
|
|
},
|
|
|
|
nameObject: function (object, name) {
|
|
|
|
object.name = name;
|
|
this.signals.sceneGraphChanged.dispatch();
|
|
|
|
},
|
|
|
|
removeObject: function (object) {
|
|
|
|
if (object.parent === null) return; // avoid deleting the camera or scene
|
|
|
|
var scope = this;
|
|
|
|
object.traverse(function (child) {
|
|
|
|
scope.removeHelper(child);
|
|
|
|
});
|
|
|
|
object.parent.remove(object);
|
|
|
|
this.signals.objectRemoved.dispatch(object);
|
|
this.signals.sceneGraphChanged.dispatch();
|
|
|
|
},
|
|
|
|
addGeometry: function (geometry) {
|
|
|
|
this.geometries[geometry.uuid] = geometry;
|
|
|
|
},
|
|
|
|
setGeometryName: function (geometry, name) {
|
|
|
|
geometry.name = name;
|
|
this.signals.sceneGraphChanged.dispatch();
|
|
|
|
},
|
|
|
|
addMaterial: function (material) {
|
|
|
|
this.materials[material.uuid] = material;
|
|
|
|
},
|
|
|
|
setMaterialName: function (material, name) {
|
|
|
|
material.name = name;
|
|
this.signals.sceneGraphChanged.dispatch();
|
|
|
|
},
|
|
|
|
addTexture: function (texture) {
|
|
|
|
this.textures[texture.uuid] = texture;
|
|
|
|
},
|
|
|
|
//
|
|
|
|
addHelper: function () {
|
|
|
|
var geometry = new THREE.SphereBufferGeometry(2, 4, 2);
|
|
var material = new THREE.MeshBasicMaterial({ color: 0xff0000, visible: false });
|
|
|
|
return function (object) {
|
|
|
|
var helper;
|
|
|
|
if (object instanceof THREE.Camera) {
|
|
|
|
helper = new THREE.CameraHelper(object, 1);
|
|
|
|
} else if (object instanceof THREE.PointLight) {
|
|
|
|
helper = new THREE.PointLightHelper(object, 1);
|
|
|
|
} else if (object instanceof THREE.DirectionalLight) {
|
|
|
|
helper = new THREE.DirectionalLightHelper(object, 1);
|
|
|
|
} else if (object instanceof THREE.SpotLight) {
|
|
|
|
helper = new THREE.SpotLightHelper(object, 1);
|
|
|
|
} else if (object instanceof THREE.HemisphereLight) {
|
|
|
|
helper = new THREE.HemisphereLightHelper(object, 1);
|
|
|
|
} else if (object instanceof THREE.SkinnedMesh) {
|
|
|
|
helper = new THREE.SkeletonHelper(object);
|
|
|
|
} else {
|
|
|
|
// no helper for this object type
|
|
return;
|
|
|
|
}
|
|
|
|
var picker = new THREE.Mesh(geometry, material);
|
|
picker.name = 'picker';
|
|
picker.userData.object = object;
|
|
helper.add(picker);
|
|
|
|
this.sceneHelpers.add(helper);
|
|
this.helpers[object.id] = helper;
|
|
|
|
this.signals.helperAdded.dispatch(helper);
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
removeHelper: function (object) {
|
|
|
|
if (this.helpers[object.id] !== undefined) {
|
|
|
|
var helper = this.helpers[object.id];
|
|
helper.parent.remove(helper);
|
|
|
|
delete this.helpers[object.id];
|
|
|
|
this.signals.helperRemoved.dispatch(helper);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
//
|
|
|
|
addScript: function (object, script) {
|
|
|
|
if (this.scripts[object.uuid] === undefined) {
|
|
|
|
this.scripts[object.uuid] = [];
|
|
|
|
}
|
|
|
|
this.scripts[object.uuid].push(script);
|
|
|
|
this.signals.scriptAdded.dispatch(script);
|
|
|
|
},
|
|
|
|
removeScript: function (object, script) {
|
|
|
|
if (this.scripts[object.uuid] === undefined) return;
|
|
|
|
var index = this.scripts[object.uuid].indexOf(script);
|
|
|
|
if (index !== -1) {
|
|
|
|
this.scripts[object.uuid].splice(index, 1);
|
|
|
|
}
|
|
|
|
this.signals.scriptRemoved.dispatch(script);
|
|
|
|
},
|
|
|
|
//
|
|
|
|
select: function (object) {
|
|
|
|
if (this.selected === object) return;
|
|
|
|
var uuid = null;
|
|
|
|
if (object !== null) {
|
|
|
|
uuid = object.uuid;
|
|
|
|
}
|
|
|
|
this.selected = object;
|
|
|
|
this.config.setKey('selected', uuid);
|
|
this.signals.objectSelected.dispatch(object);
|
|
|
|
},
|
|
|
|
selectById: function (id) {
|
|
|
|
if (id === this.camera.id) {
|
|
|
|
this.select(this.camera);
|
|
return;
|
|
|
|
}
|
|
|
|
this.select(this.scene.getObjectById(id, true));
|
|
|
|
},
|
|
|
|
selectByUuid: function (uuid) {
|
|
|
|
var scope = this;
|
|
|
|
this.scene.traverse(function (child) {
|
|
|
|
if (child.uuid === uuid) {
|
|
|
|
scope.select(child);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
deselect: function () {
|
|
|
|
this.select(null);
|
|
|
|
},
|
|
|
|
focus: function (object) {
|
|
|
|
this.signals.objectFocused.dispatch(object);
|
|
|
|
},
|
|
|
|
focusById: function (id) {
|
|
|
|
this.focus(this.scene.getObjectById(id, true));
|
|
|
|
},
|
|
|
|
clear: function () {
|
|
|
|
this.history.clear();
|
|
this.storage.clear();
|
|
|
|
this.camera.copy(this.DEFAULT_CAMERA);
|
|
this.scene.background.setHex(0xaaaaaa);
|
|
this.scene.fog = null;
|
|
|
|
var objects = this.scene.children;
|
|
|
|
while (objects.length > 0) {
|
|
|
|
this.removeObject(objects[0]);
|
|
|
|
}
|
|
|
|
this.geometries = {};
|
|
this.materials = {};
|
|
this.textures = {};
|
|
this.scripts = {};
|
|
|
|
this.deselect();
|
|
|
|
this.signals.editorCleared.dispatch();
|
|
|
|
},
|
|
|
|
//
|
|
|
|
fromJSON: function (json) {
|
|
|
|
var loader = new THREE.ObjectLoader();
|
|
|
|
// backwards
|
|
|
|
if (json.scene === undefined) {
|
|
|
|
this.setScene(loader.parse(json));
|
|
return;
|
|
|
|
}
|
|
|
|
var camera = loader.parse(json.camera);
|
|
|
|
this.camera.copy(camera);
|
|
this.camera.aspect = this.DEFAULT_CAMERA.aspect;
|
|
this.camera.updateProjectionMatrix();
|
|
|
|
this.history.fromJSON(json.history);
|
|
this.scripts = json.scripts;
|
|
|
|
this.setScene(loader.parse(json.scene));
|
|
|
|
},
|
|
|
|
toJSON: function () {
|
|
|
|
// scripts clean up
|
|
|
|
var scene = this.scene;
|
|
var scripts = this.scripts;
|
|
|
|
for (var key in scripts) {
|
|
|
|
var script = scripts[key];
|
|
|
|
if (script.length === 0 || scene.getObjectByProperty('uuid', key) === undefined) {
|
|
|
|
delete scripts[key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
|
|
return {
|
|
|
|
metadata: {},
|
|
project: {
|
|
gammaInput: this.config.getKey('project/renderer/gammaInput'),
|
|
gammaOutput: this.config.getKey('project/renderer/gammaOutput'),
|
|
shadows: this.config.getKey('project/renderer/shadows'),
|
|
vr: this.config.getKey('project/vr')
|
|
},
|
|
camera: this.camera.toJSON(),
|
|
scene: this.scene.toJSON(),
|
|
scripts: this.scripts,
|
|
history: this.history.toJSON()
|
|
|
|
};
|
|
|
|
},
|
|
|
|
objectByUuid: function (uuid) {
|
|
|
|
return this.scene.getObjectByProperty('uuid', uuid, true);
|
|
|
|
},
|
|
|
|
execute: function (cmd, optionalName) {
|
|
|
|
this.history.execute(cmd, optionalName);
|
|
|
|
},
|
|
|
|
undo: function () {
|
|
|
|
this.history.undo();
|
|
|
|
},
|
|
|
|
redo: function () {
|
|
|
|
this.history.redo();
|
|
|
|
}
|
|
|
|
};
|