зеркало из https://github.com/mozilla/Spoke.git
Merge branch 'master' of github.com:mozillareality/hubs-editor
This commit is contained in:
Коммит
2d6049cab0
|
@ -6,8 +6,7 @@ module.exports = {
|
|||
node: true
|
||||
},
|
||||
globals: {
|
||||
THREE: true,
|
||||
Components: true
|
||||
THREE: true
|
||||
},
|
||||
plugins: ["prettier", "react"],
|
||||
rules: {
|
||||
|
|
33
.travis.yml
33
.travis.yml
|
@ -1,33 +0,0 @@
|
|||
os: osx
|
||||
language: node_js
|
||||
node_js: '9'
|
||||
cache: yarn
|
||||
branches:
|
||||
only: master
|
||||
before_install:
|
||||
- curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 1.7.0
|
||||
- export PATH="$HOME/.yarn/bin:$PATH"
|
||||
install: yarn
|
||||
script:
|
||||
- yarn build
|
||||
- npx qbrt package desktop
|
||||
- cp hubs-editor.dmg hubs-editor.macos.dmg
|
||||
- npx qbrt package --win desktop
|
||||
- cp hubs-editor.zip hubs-editor.win.zip
|
||||
- npx qbrt package --linux desktop
|
||||
- cp hubs-editor.tgz hubs-editor.linux.tgz
|
||||
before_deploy:
|
||||
- git config --local user.name "hubs-editor bot"
|
||||
- git config --local user.email "hubs-editor-bot@mozilla.com"
|
||||
- git tag "$(date +'%Y-%m-%d_%H-%M-%S')_$(git log --format=%h -1)"
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: fD8SwrudoCqMkignWFKkjnX9rPAKwy2F71MnbPOKeaTY0qcrcabtFp0DUbmypt4POawNEzhRiykwcHTEo86jjhayfb26wXgflSKIS+ZHKxmAAYBuTCQgwwWfOmNGbJYGBEJs3IBETUfr8GKxK2gzJ0F/MJuk9oL+zOckcPSLTAc00biGRcE9WZ9NEeBjckofrUenUHDpjQUnG1jiRfYAkMVUXJKFsGH3shBkAEJ4+2cGpkj32DtRZ96FrkPxHQghZGUDiIysKVllggS2PEiMgYcgcGj00hduUbZ4eXLvDQDu7t7kJuNsCvq+O183eBuYkmTJMwUgpuo7EoBoMMK0Z33pM7GcstT1ceZVn6nSM2qEDYgzKvJya8wLYOprYruzF7fUBPwkMynCDPNJg7USXibZ/90nxrVOoaor1Mgxb1zHwbKx/7HdhBabrNVdQaxxcig/4B6+K9jGLcO9GhIibacobWYXJKdtJDjvB3r8W2sOX+tELwXhvumHf7PcycQbmDVT46UIOMjWk1a+Jyxm3gX+2KWq0KdhKS8NjEP1l0Ws8LWC2qJHtW5fQ69rhNnSRyUQT8XLd51DlJ0dCy7+fiih4stKkF3jgs8cqqceijh+jqGnZkkEhukvSX/+h2hwBc6y55FZv+VoioR8Laoh8++zXtqqA5zmc912cmcrQbs=
|
||||
file:
|
||||
- "hubs-editor.macos.dmg"
|
||||
- "hubs-editor.win.zip"
|
||||
- "hubs-editor.linux.tgz"
|
||||
skip_cleanup: true
|
||||
on:
|
||||
repo: MozillaReality/hubs-editor
|
|
@ -1,16 +0,0 @@
|
|||
const { Runtime } = Components.utils.import("resource://qbrt/modules/Runtime.jsm", {});
|
||||
const { Services } = Components.utils.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
const WINDOW_URL = "chrome://app/content/index.xul";
|
||||
|
||||
const WINDOW_FEATURES = ["chrome", "centerscreen", "dialog=no", "all", "width=1280", "height=768", "resizable"].join(
|
||||
","
|
||||
);
|
||||
|
||||
if (Services.appinfo.OS === "Darwin") {
|
||||
Components.classes["@mozilla.org/widget/macdocksupport;1"]
|
||||
.getService(Components.interfaces.nsIMacDockSupport)
|
||||
.activateApplication(true);
|
||||
}
|
||||
|
||||
Services.ww.openWindow(null, WINDOW_URL, "Hubs Editor", WINDOW_FEATURES, null);
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"node": {
|
||||
"version": "10.4.1",
|
||||
"resolved": "https://registry.npmjs.org/node/-/node-10.4.1.tgz",
|
||||
"integrity": "sha512-mr65ue1CjMUGr8jmpQSC1bpzs8FU0abFUByBYTMovTIrrBXjH7uISt67/cxqIXl5A7U1lEb0jmQiwRc3LKwa5g==",
|
||||
"requires": {
|
||||
"node-bin-setup": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node-bin-setup": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/node-bin-setup/-/node-bin-setup-1.0.6.tgz",
|
||||
"integrity": "sha512-uPIxXNis1CRbv1DwqAxkgBk5NFV3s7cMN/Gf556jSw6jBvV7ca4F9lRL/8cALcZecRibeqU+5dFYqFFmzv5a0Q=="
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"name": "hubs-editor-desktop",
|
||||
"version": "0.1.0",
|
||||
"license": "MPL-2.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"node": "^10.4.1",
|
||||
"hubs-editor-cli": "0.1.0"
|
||||
}
|
||||
}
|
|
@ -17,23 +17,36 @@ class PropertiesPanelContainer extends Component {
|
|||
node: null,
|
||||
components: []
|
||||
};
|
||||
|
||||
this.props.editor.signals.objectSelected.add(node =>
|
||||
this.setState({
|
||||
node,
|
||||
components: (node && node.userData._components) || []
|
||||
})
|
||||
);
|
||||
|
||||
this.props.editor.signals.objectChanged.add(object => {
|
||||
if (this.state.node === object) {
|
||||
this.setState({
|
||||
components: object.userData._components || []
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.editor.signals.objectSelected.add(this.onObjectSelected);
|
||||
this.props.editor.signals.transformChanged.add(this.onNodeChanged);
|
||||
this.props.editor.signals.objectChanged.add(this.onNodeChanged);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.editor.signals.objectSelected.remove(this.onObjectSelected);
|
||||
this.props.editor.signals.transformChanged.remove(this.onNodeChanged);
|
||||
this.props.editor.signals.objectChanged.remove(this.onNodeChanged);
|
||||
}
|
||||
|
||||
onObjectSelected = object => {
|
||||
this.setState({
|
||||
node: object,
|
||||
components: (object && object.userData._components) || []
|
||||
});
|
||||
};
|
||||
|
||||
onNodeChanged = object => {
|
||||
if (this.state.node === object) {
|
||||
this.setState({
|
||||
node: object,
|
||||
components: object.userData._components || []
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { node } = this.state;
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ class ViewportPanelContainer extends Component {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.editor.createRenderer(this.canvasRef.current);
|
||||
this.props.editor.createViewport(this.canvasRef.current);
|
||||
}
|
||||
|
||||
onDropFile = file => {
|
||||
|
|
|
@ -2,7 +2,6 @@ import signals from "signals";
|
|||
|
||||
import THREE from "../vendor/three";
|
||||
import History from "./History";
|
||||
import Storage from "./Storage";
|
||||
import Viewport from "./Viewport";
|
||||
import RemoveObjectCommand from "./commands/RemoveObjectCommand";
|
||||
import AddObjectCommand from "./commands/AddObjectCommand";
|
||||
|
@ -25,38 +24,21 @@ export default class Editor {
|
|||
const Signal = signals.Signal;
|
||||
|
||||
this.signals = {
|
||||
// script
|
||||
|
||||
editScript: new Signal(),
|
||||
|
||||
// player
|
||||
|
||||
startPlayer: new Signal(),
|
||||
stopPlayer: new Signal(),
|
||||
|
||||
// actions
|
||||
|
||||
showModal: new Signal(),
|
||||
|
||||
openScene: new Signal(),
|
||||
popScene: new Signal(),
|
||||
|
||||
// notifications
|
||||
|
||||
editorCleared: new Signal(),
|
||||
|
||||
savingStarted: new Signal(),
|
||||
savingFinished: new Signal(),
|
||||
|
||||
themeChanged: new Signal(),
|
||||
|
||||
deleteSelectedObject: new Signal(),
|
||||
|
||||
transformChanged: new Signal(),
|
||||
transformModeChanged: new Signal(),
|
||||
snapToggled: new Signal(),
|
||||
spaceChanged: new Signal(),
|
||||
viewportInitialized: new Signal(),
|
||||
rendererChanged: new Signal(),
|
||||
|
||||
sceneBackgroundChanged: new Signal(),
|
||||
sceneFogChanged: new Signal(),
|
||||
|
@ -79,21 +61,15 @@ export default class Editor {
|
|||
|
||||
materialChanged: new Signal(),
|
||||
|
||||
scriptAdded: new Signal(),
|
||||
scriptChanged: new Signal(),
|
||||
scriptRemoved: new Signal(),
|
||||
|
||||
windowResize: new Signal(),
|
||||
|
||||
showGridChanged: new Signal(),
|
||||
refreshSidebarObject3D: new Signal(),
|
||||
historyChanged: new Signal(),
|
||||
|
||||
fileChanged: new Signal()
|
||||
};
|
||||
|
||||
this.history = new History(this);
|
||||
this.storage = new Storage();
|
||||
|
||||
this.camera = this.DEFAULT_CAMERA.clone();
|
||||
|
||||
|
@ -118,17 +94,17 @@ export default class Editor {
|
|||
|
||||
this.sceneHelpers = new THREE.Scene();
|
||||
|
||||
this.object = {};
|
||||
this.objects = [];
|
||||
this.geometries = {};
|
||||
this.materials = {};
|
||||
this.textures = {};
|
||||
this.scripts = {};
|
||||
|
||||
// TODO: Support multiple viewports
|
||||
this.viewports = [];
|
||||
|
||||
this.selected = null;
|
||||
this.helpers = {};
|
||||
|
||||
this.viewport = null;
|
||||
|
||||
this.components = new Map();
|
||||
|
||||
for (const componentClass of Components) {
|
||||
|
@ -142,6 +118,12 @@ export default class Editor {
|
|||
this.signals.fileChanged.add(this.onFileChanged);
|
||||
}
|
||||
|
||||
createViewport(canvas) {
|
||||
const viewport = new Viewport(this, canvas);
|
||||
this.viewports.push(viewport);
|
||||
return viewport;
|
||||
}
|
||||
|
||||
onWindowResize = () => {
|
||||
this.signals.windowResize.dispatch();
|
||||
};
|
||||
|
@ -160,26 +142,6 @@ export default class Editor {
|
|||
}
|
||||
};
|
||||
|
||||
setTheme(value) {
|
||||
document.getElementById("theme").href = value;
|
||||
|
||||
this.signals.themeChanged.dispatch(value);
|
||||
}
|
||||
|
||||
createRenderer(canvas) {
|
||||
this.canvas = canvas;
|
||||
|
||||
const renderer = new THREE.WebGLRenderer({
|
||||
canvas
|
||||
});
|
||||
renderer.shadowMap.enabled = true;
|
||||
|
||||
this.viewport = new Viewport(this);
|
||||
this.signals.viewportInitialized.dispatch(this.viewport);
|
||||
|
||||
this.signals.rendererChanged.dispatch(renderer);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
popScene() {
|
||||
|
@ -441,30 +403,6 @@ export default class Editor {
|
|||
|
||||
//
|
||||
|
||||
addScript(object, script) {
|
||||
if (this.scripts[object.uuid] === undefined) {
|
||||
this.scripts[object.uuid] = [];
|
||||
}
|
||||
|
||||
this.scripts[object.uuid].push(script);
|
||||
|
||||
this.signals.scriptAdded.dispatch(script);
|
||||
}
|
||||
|
||||
removeScript(object, script) {
|
||||
if (this.scripts[object.uuid] === undefined) return;
|
||||
|
||||
const index = this.scripts[object.uuid].indexOf(script);
|
||||
|
||||
if (index !== -1) {
|
||||
this.scripts[object.uuid].splice(index, 1);
|
||||
}
|
||||
|
||||
this.signals.scriptRemoved.dispatch(script);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
registerComponent(componentClass) {
|
||||
const { componentName } = componentClass;
|
||||
|
||||
|
@ -657,7 +595,6 @@ export default class Editor {
|
|||
|
||||
clear() {
|
||||
this.history.clear();
|
||||
this.storage.clear();
|
||||
|
||||
this.camera.copy(this.DEFAULT_CAMERA);
|
||||
this.scene.fog = null;
|
||||
|
@ -673,68 +610,12 @@ export default class Editor {
|
|||
this.geometries = {};
|
||||
this.materials = {};
|
||||
this.textures = {};
|
||||
this.scripts = {};
|
||||
|
||||
this.deselect();
|
||||
|
||||
this.signals.editorCleared.dispatch();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
fromJSON(json) {
|
||||
const loader = new THREE.ObjectLoader();
|
||||
|
||||
// backwards
|
||||
|
||||
if (json.scene === undefined) {
|
||||
this.setScene(loader.parse(json));
|
||||
return;
|
||||
}
|
||||
|
||||
const 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() {
|
||||
// scripts clean up
|
||||
|
||||
const scene = this.scene;
|
||||
const scripts = this.scripts;
|
||||
|
||||
for (const key in scripts) {
|
||||
const 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(uuid) {
|
||||
return this.scene.getObjectByProperty("uuid", uuid, true);
|
||||
}
|
||||
|
|
|
@ -18,18 +18,6 @@ export default class History {
|
|||
//Set editor-reference in Command
|
||||
|
||||
Command.editor = editor;
|
||||
|
||||
// signals
|
||||
|
||||
const scope = this;
|
||||
|
||||
this.editor.signals.startPlayer.add(function() {
|
||||
scope.historyDisabled = true;
|
||||
});
|
||||
|
||||
this.editor.signals.stopPlayer.add(function() {
|
||||
scope.historyDisabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
execute(cmd, optionalName) {
|
||||
|
@ -42,15 +30,9 @@ export default class History {
|
|||
cmd.updatable &&
|
||||
lastCmd.object === cmd.object &&
|
||||
lastCmd.type === cmd.type &&
|
||||
lastCmd.script === cmd.script &&
|
||||
lastCmd.attributeName === cmd.attributeName;
|
||||
|
||||
if (isUpdatableCmd && cmd.type === "SetScriptValueCommand") {
|
||||
// When the cmd.type is "SetScriptValueCommand" the timeDifference is ignored
|
||||
|
||||
lastCmd.update(cmd);
|
||||
cmd = lastCmd;
|
||||
} else if (isUpdatableCmd && timeDifference < 500) {
|
||||
if (isUpdatableCmd && timeDifference < 500) {
|
||||
lastCmd.update(cmd);
|
||||
cmd = lastCmd;
|
||||
} else {
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
const Storage = function() {
|
||||
const indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
|
||||
|
||||
if (indexedDB === undefined) {
|
||||
console.warn("Storage: IndexedDB not available.");
|
||||
return { init: function() {}, get: function() {}, set: function() {}, clear: function() {} };
|
||||
}
|
||||
|
||||
const name = "threejs-editor";
|
||||
const version = 1;
|
||||
|
||||
let database;
|
||||
|
||||
return {
|
||||
init: function(callback) {
|
||||
const request = indexedDB.open(name, version);
|
||||
request.onupgradeneeded = function(event) {
|
||||
const db = event.target.result;
|
||||
|
||||
if (db.objectStoreNames.contains("states") === false) {
|
||||
db.createObjectStore("states");
|
||||
}
|
||||
};
|
||||
request.onsuccess = function(event) {
|
||||
database = event.target.result;
|
||||
|
||||
callback();
|
||||
};
|
||||
request.onerror = function(event) {
|
||||
console.error("IndexedDB", event);
|
||||
};
|
||||
},
|
||||
|
||||
get: function(callback) {
|
||||
const transaction = database.transaction(["states"], "readwrite");
|
||||
const objectStore = transaction.objectStore("states");
|
||||
const request = objectStore.get(0);
|
||||
request.onsuccess = function(event) {
|
||||
callback(event.target.result);
|
||||
};
|
||||
},
|
||||
|
||||
set: function(data) {
|
||||
const start = performance.now();
|
||||
|
||||
const transaction = database.transaction(["states"], "readwrite");
|
||||
const objectStore = transaction.objectStore("states");
|
||||
const request = objectStore.put(data, 0);
|
||||
request.onsuccess = function() {
|
||||
console.log(
|
||||
"[" + new Date() + "]",
|
||||
"Saved state to IndexedDB. " + (performance.now() - start).toFixed(2) + "ms"
|
||||
);
|
||||
};
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
if (database === undefined) return;
|
||||
|
||||
const transaction = database.transaction(["states"], "readwrite");
|
||||
const objectStore = transaction.objectStore("states");
|
||||
const request = objectStore.clear();
|
||||
request.onsuccess = function() {
|
||||
console.log("[" + new Date() + "]", "Cleared IndexedDB.");
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default Storage;
|
|
@ -8,19 +8,23 @@ import SetScaleCommand from "./commands/SetScaleCommand";
|
|||
*/
|
||||
|
||||
export default class Viewport {
|
||||
constructor(editor) {
|
||||
constructor(editor, canvas) {
|
||||
const signals = editor.signals;
|
||||
|
||||
//
|
||||
const renderer = new THREE.WebGLRenderer({
|
||||
canvas
|
||||
});
|
||||
|
||||
let renderer = null;
|
||||
renderer.shadowMap.enabled = true;
|
||||
renderer.autoClear = false;
|
||||
renderer.autoUpdateScene = false;
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
renderer.setSize(canvas.parentElement.offsetWidth, canvas.parentElement.offsetHeight);
|
||||
|
||||
const canvas = editor.canvas;
|
||||
const camera = editor.camera;
|
||||
const scene = editor.scene;
|
||||
const sceneHelpers = editor.sceneHelpers;
|
||||
|
||||
const objects = [];
|
||||
const objects = editor.objects;
|
||||
|
||||
// helpers
|
||||
|
||||
|
@ -68,7 +72,7 @@ export default class Viewport {
|
|||
editor.helpers[object.id].update();
|
||||
}
|
||||
|
||||
signals.refreshSidebarObject3D.dispatch(object);
|
||||
signals.transformChanged.dispatch(object);
|
||||
}
|
||||
|
||||
render();
|
||||
|
@ -247,17 +251,6 @@ export default class Viewport {
|
|||
this._transformControls.setSpace(space);
|
||||
});
|
||||
|
||||
signals.rendererChanged.add(function(newRenderer) {
|
||||
renderer = newRenderer;
|
||||
|
||||
renderer.autoClear = false;
|
||||
renderer.autoUpdateScene = false;
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
renderer.setSize(canvas.parentElement.offsetWidth, canvas.parentElement.offsetHeight);
|
||||
|
||||
render();
|
||||
});
|
||||
|
||||
signals.sceneSet.add(function() {
|
||||
render();
|
||||
});
|
||||
|
@ -400,6 +393,8 @@ export default class Viewport {
|
|||
grid.visible = showGrid;
|
||||
render();
|
||||
});
|
||||
|
||||
signals.viewportInitialized.dispatch(this);
|
||||
}
|
||||
|
||||
toggleSnap = enabled => {
|
||||
|
|
Загрузка…
Ссылка в новой задаче