senangwebs-aframe-editor 1.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +3 -0
- package/.editorconfig +12 -0
- package/.eslintignore +2 -0
- package/.eslintrc +40 -0
- package/.github/workflows/ci.yml +39 -0
- package/.husky/pre-commit +4 -0
- package/.prettierignore +1 -0
- package/.prettierrc.json +5 -0
- package/.stylelintrc +12 -0
- package/LICENSE +21 -0
- package/README.md +75 -0
- package/assets/gltf.svg +49 -0
- package/dist/aframe-inspector.js +106250 -0
- package/dist/aframe-inspector.js.map +1 -0
- package/dist/aframe-inspector.min.js +29040 -0
- package/dist/aframe-inspector.min.js.LICENSE.txt +56 -0
- package/dist/aframe-inspector.min.js.map +1 -0
- package/examples/360video.html +48 -0
- package/examples/colors.html +18 -0
- package/examples/controllers.html +60 -0
- package/examples/embedded-zoom.html +78 -0
- package/examples/embedded.html +79 -0
- package/examples/empty.html +13 -0
- package/examples/index-aframe.html +66 -0
- package/examples/index.html +71 -0
- package/examples/supercraft.html +6 -0
- package/index.html +8 -0
- package/package.json +84 -0
- package/senangwebs-webverse-editor.png +0 -0
- package/src/components/AwesomeIcon.js +53 -0
- package/src/components/Collapsible.js +57 -0
- package/src/components/EntityRepresentation.js +83 -0
- package/src/components/Main.js +222 -0
- package/src/components/__tests__/Collapsible.test.js +30 -0
- package/src/components/components/AddComponent.js +104 -0
- package/src/components/components/CommonComponents.js +160 -0
- package/src/components/components/Component.js +151 -0
- package/src/components/components/ComponentsContainer.js +52 -0
- package/src/components/components/DefaultComponents.js +1 -0
- package/src/components/components/Mixins.js +83 -0
- package/src/components/components/PropertyRow.js +145 -0
- package/src/components/components/Sidebar.js +51 -0
- package/src/components/icons/BackViewIcon.js +27 -0
- package/src/components/icons/BottomViewIcon.js +26 -0
- package/src/components/icons/FrontViewIcon.js +23 -0
- package/src/components/icons/LeftViewIcon.js +24 -0
- package/src/components/icons/PerspectiveIcon.js +23 -0
- package/src/components/icons/PrimitiveBoxIcon.js +143 -0
- package/src/components/icons/PrimitiveConeIcon.js +44 -0
- package/src/components/icons/PrimitiveCylinderIcon.js +51 -0
- package/src/components/icons/PrimitiveEmptyEntityIcon.js +78 -0
- package/src/components/icons/PrimitiveImageIcon.js +86 -0
- package/src/components/icons/PrimitiveLightIcon.js +107 -0
- package/src/components/icons/PrimitivePlaneIcon.js +87 -0
- package/src/components/icons/PrimitiveSphereIcon.js +39 -0
- package/src/components/icons/PrimitiveTextIcon.js +89 -0
- package/src/components/icons/PrimitiveTorusIcon.js +31 -0
- package/src/components/icons/RightViewIcon.js +24 -0
- package/src/components/icons/TopViewIcon.js +24 -0
- package/src/components/modals/Modal.js +107 -0
- package/src/components/modals/ModalHelp.js +97 -0
- package/src/components/modals/ModalPrimitive.js +114 -0
- package/src/components/modals/ModalTextures.js +430 -0
- package/src/components/scenegraph/Entity.js +142 -0
- package/src/components/scenegraph/SceneGraph.js +337 -0
- package/src/components/scenegraph/Toolbar.js +147 -0
- package/src/components/viewport/CameraToolbar.js +122 -0
- package/src/components/viewport/TransformToolbar.js +102 -0
- package/src/components/viewport/ViewportHUD.js +33 -0
- package/src/components/widgets/BooleanWidget.js +49 -0
- package/src/components/widgets/ColorWidget.js +89 -0
- package/src/components/widgets/InputWidget.js +42 -0
- package/src/components/widgets/NumberWidget.js +179 -0
- package/src/components/widgets/SelectWidget.js +58 -0
- package/src/components/widgets/TextureWidget.js +252 -0
- package/src/components/widgets/Vec2Widget.js +55 -0
- package/src/components/widgets/Vec3Widget.js +58 -0
- package/src/components/widgets/Vec4Widget.js +61 -0
- package/src/components/widgets/index.js +9 -0
- package/src/index.js +301 -0
- package/src/lib/EditorControls.js +336 -0
- package/src/lib/Events.js +6 -0
- package/src/lib/TransformControls.js +1365 -0
- package/src/lib/assetsLoader.js +43 -0
- package/src/lib/assetsUtils.js +30 -0
- package/src/lib/cameras.js +121 -0
- package/src/lib/entity.js +556 -0
- package/src/lib/history.js +30 -0
- package/src/lib/raycaster.js +129 -0
- package/src/lib/shortcuts.js +211 -0
- package/src/lib/utils.js +118 -0
- package/src/lib/viewport.js +268 -0
- package/src/style/components.styl +275 -0
- package/src/style/entity.styl +22 -0
- package/src/style/help.styl +40 -0
- package/src/style/index.styl +358 -0
- package/src/style/lib.styl +41 -0
- package/src/style/primitiveModal.styl +90 -0
- package/src/style/scenegraph.styl +173 -0
- package/src/style/select.styl +71 -0
- package/src/style/textureModal.styl +220 -0
- package/src/style/viewport.styl +168 -0
- package/src/style/widgets.styl +71 -0
- package/webpack.config.js +65 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import Events from './Events';
|
|
2
|
+
import {
|
|
3
|
+
removeSelectedEntity,
|
|
4
|
+
cloneSelectedEntity,
|
|
5
|
+
cloneEntity
|
|
6
|
+
} from './entity';
|
|
7
|
+
import { getOS } from './utils';
|
|
8
|
+
|
|
9
|
+
const os = getOS();
|
|
10
|
+
|
|
11
|
+
function shouldCaptureKeyEvent(event) {
|
|
12
|
+
return (
|
|
13
|
+
event.target.closest('#cameraToolbar') ||
|
|
14
|
+
(event.target.tagName !== 'INPUT' && event.target.tagName !== 'TEXTAREA')
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const Shortcuts = {
|
|
19
|
+
enabled: false,
|
|
20
|
+
shortcuts: {
|
|
21
|
+
default: {},
|
|
22
|
+
modules: {}
|
|
23
|
+
},
|
|
24
|
+
onKeyUp: function (event) {
|
|
25
|
+
if (!shouldCaptureKeyEvent(event) || !AFRAME.INSPECTOR.opened) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var keyCode = event.keyCode;
|
|
30
|
+
|
|
31
|
+
// h: help
|
|
32
|
+
if (keyCode === 72) {
|
|
33
|
+
Events.emit('openhelpmodal');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// esc: unselect entity
|
|
37
|
+
if (keyCode === 27) {
|
|
38
|
+
if (this.inspector.selectedEntity) {
|
|
39
|
+
this.inspector.selectEntity(null);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// w: translate
|
|
44
|
+
if (keyCode === 87) {
|
|
45
|
+
Events.emit('transformmodechange', 'translate');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// e: rotate
|
|
49
|
+
if (keyCode === 69) {
|
|
50
|
+
Events.emit('transformmodechange', 'rotate');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// r: scale
|
|
54
|
+
if (keyCode === 82) {
|
|
55
|
+
Events.emit('transformmodechange', 'scale');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// o: transform space
|
|
59
|
+
if (keyCode === 79) {
|
|
60
|
+
Events.emit('transformspacechange');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// g: toggle grid
|
|
64
|
+
if (keyCode === 71) {
|
|
65
|
+
Events.emit('togglegrid');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// n: new entity
|
|
69
|
+
if (keyCode === 78) {
|
|
70
|
+
Events.emit('entitycreate', { element: 'a-entity', components: {} });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// backspace & delete: remove selected entity
|
|
74
|
+
if (keyCode === 8 || keyCode === 46) {
|
|
75
|
+
removeSelectedEntity();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// d: clone selected entity
|
|
79
|
+
if (keyCode === 68) {
|
|
80
|
+
cloneSelectedEntity();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// f: Focus on selected entity.
|
|
84
|
+
if (keyCode === 70) {
|
|
85
|
+
const selectedEntity = AFRAME.INSPECTOR.selectedEntity;
|
|
86
|
+
if (selectedEntity !== undefined && selectedEntity !== null) {
|
|
87
|
+
Events.emit('objectfocus', selectedEntity.object3D);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (keyCode === 49) {
|
|
92
|
+
Events.emit('cameraperspectivetoggle');
|
|
93
|
+
} else if (keyCode === 50) {
|
|
94
|
+
Events.emit('cameraorthographictoggle', 'left');
|
|
95
|
+
} else if (keyCode === 51) {
|
|
96
|
+
Events.emit('cameraorthographictoggle', 'right');
|
|
97
|
+
} else if (keyCode === 52) {
|
|
98
|
+
Events.emit('cameraorthographictoggle', 'top');
|
|
99
|
+
} else if (keyCode === 53) {
|
|
100
|
+
Events.emit('cameraorthographictoggle', 'bottom');
|
|
101
|
+
} else if (keyCode === 54) {
|
|
102
|
+
Events.emit('cameraorthographictoggle', 'back');
|
|
103
|
+
} else if (keyCode === 55) {
|
|
104
|
+
Events.emit('cameraorthographictoggle', 'front');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
for (var moduleName in this.shortcuts.modules) {
|
|
108
|
+
var shortcutsModule = this.shortcuts.modules[moduleName];
|
|
109
|
+
if (
|
|
110
|
+
shortcutsModule[keyCode] &&
|
|
111
|
+
(!shortcutsModule[keyCode].mustBeActive ||
|
|
112
|
+
(shortcutsModule[keyCode].mustBeActive &&
|
|
113
|
+
AFRAME.INSPECTOR.modules[moduleName].active))
|
|
114
|
+
) {
|
|
115
|
+
this.shortcuts.modules[moduleName][keyCode].callback();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
onKeyDown: function (event) {
|
|
120
|
+
if (!shouldCaptureKeyEvent(event) || !AFRAME.INSPECTOR.opened) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (
|
|
125
|
+
(event.ctrlKey && os !== 'macos') ||
|
|
126
|
+
(event.metaKey && os === 'macos')
|
|
127
|
+
) {
|
|
128
|
+
if (
|
|
129
|
+
AFRAME.INSPECTOR.selectedEntity &&
|
|
130
|
+
document.activeElement.tagName !== 'INPUT'
|
|
131
|
+
) {
|
|
132
|
+
// c: copy selected entity
|
|
133
|
+
if (event.keyCode === 67) {
|
|
134
|
+
AFRAME.INSPECTOR.entityToCopy = AFRAME.INSPECTOR.selectedEntity;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// v: paste copied entity
|
|
138
|
+
if (event.keyCode === 86) {
|
|
139
|
+
cloneEntity(AFRAME.INSPECTOR.entityToCopy);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// s: focus search input
|
|
144
|
+
if (event.keyCode === 83) {
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
event.stopPropagation();
|
|
147
|
+
document.getElementById('filter').focus();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// 0: toggle sidebars visibility
|
|
152
|
+
if (event.keyCode === 48) {
|
|
153
|
+
Events.emit('togglesidebar', { which: 'all' });
|
|
154
|
+
event.preventDefault();
|
|
155
|
+
event.stopPropagation();
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
enable: function () {
|
|
159
|
+
if (this.enabled) {
|
|
160
|
+
this.disable();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
window.addEventListener('keydown', this.onKeyDown, false);
|
|
164
|
+
window.addEventListener('keyup', this.onKeyUp, false);
|
|
165
|
+
this.enabled = true;
|
|
166
|
+
},
|
|
167
|
+
disable: function () {
|
|
168
|
+
window.removeEventListener('keydown', this.onKeyDown);
|
|
169
|
+
window.removeEventListener('keyup', this.onKeyUp);
|
|
170
|
+
this.enabled = false;
|
|
171
|
+
},
|
|
172
|
+
checkModuleShortcutCollision: function (keyCode, moduleName, mustBeActive) {
|
|
173
|
+
if (
|
|
174
|
+
this.shortcuts.modules[moduleName] &&
|
|
175
|
+
this.shortcuts.modules[moduleName][keyCode]
|
|
176
|
+
) {
|
|
177
|
+
console.warn(
|
|
178
|
+
'Keycode <%s> already registered as shortcut within the same module',
|
|
179
|
+
keyCode
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
registerModuleShortcut: function (
|
|
184
|
+
keyCode,
|
|
185
|
+
callback,
|
|
186
|
+
moduleName,
|
|
187
|
+
mustBeActive
|
|
188
|
+
) {
|
|
189
|
+
if (this.checkModuleShortcutCollision(keyCode, moduleName, mustBeActive)) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (!this.shortcuts.modules[moduleName]) {
|
|
194
|
+
this.shortcuts.modules[moduleName] = {};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (mustBeActive !== false) {
|
|
198
|
+
mustBeActive = true;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
this.shortcuts.modules[moduleName][keyCode] = {
|
|
202
|
+
callback,
|
|
203
|
+
mustBeActive
|
|
204
|
+
};
|
|
205
|
+
},
|
|
206
|
+
init: function (inspector) {
|
|
207
|
+
this.inspector = inspector;
|
|
208
|
+
this.onKeyDown = this.onKeyDown.bind(this);
|
|
209
|
+
this.onKeyUp = this.onKeyUp.bind(this);
|
|
210
|
+
}
|
|
211
|
+
};
|
package/src/lib/utils.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
export function getNumber(value) {
|
|
2
|
+
return parseFloat(value.toFixed(3));
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function getMajorVersion(version) {
|
|
6
|
+
var major = version.split('.');
|
|
7
|
+
var clean = false;
|
|
8
|
+
for (var i = 0; i < major.length; i++) {
|
|
9
|
+
if (clean) {
|
|
10
|
+
major[i] = 0;
|
|
11
|
+
} else if (major[i] !== '0') {
|
|
12
|
+
clean = true;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return major.join('.');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function equal(var1, var2) {
|
|
19
|
+
var keys1;
|
|
20
|
+
var keys2;
|
|
21
|
+
var type1 = typeof var1;
|
|
22
|
+
var type2 = typeof var2;
|
|
23
|
+
if (type1 !== type2) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
if (type1 !== 'object' || var1 === null || var2 === null) {
|
|
27
|
+
return var1 === var2;
|
|
28
|
+
}
|
|
29
|
+
keys1 = Object.keys(var1);
|
|
30
|
+
keys2 = Object.keys(var2);
|
|
31
|
+
if (keys1.length !== keys2.length) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
for (var i = 0; i < keys1.length; i++) {
|
|
35
|
+
if (!equal(var1[keys1[i]], var2[keys2[i]])) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function getOS() {
|
|
43
|
+
var userAgent = window.navigator.userAgent;
|
|
44
|
+
var platform = window.navigator.platform;
|
|
45
|
+
var macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'];
|
|
46
|
+
var windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE'];
|
|
47
|
+
var iosPlatforms = ['iPhone', 'iPad', 'iPod'];
|
|
48
|
+
var os = null;
|
|
49
|
+
|
|
50
|
+
if (macosPlatforms.indexOf(platform) !== -1) {
|
|
51
|
+
os = 'macos';
|
|
52
|
+
} else if (iosPlatforms.indexOf(platform) !== -1) {
|
|
53
|
+
os = 'ios';
|
|
54
|
+
} else if (windowsPlatforms.indexOf(platform) !== -1) {
|
|
55
|
+
os = 'windows';
|
|
56
|
+
} else if (/Android/.test(userAgent)) {
|
|
57
|
+
os = 'android';
|
|
58
|
+
} else if (!os && /Linux/.test(platform)) {
|
|
59
|
+
os = 'linux';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return os;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function injectCSS(url) {
|
|
66
|
+
var link = document.createElement('link');
|
|
67
|
+
link.href = url;
|
|
68
|
+
link.type = 'text/css';
|
|
69
|
+
link.rel = 'stylesheet';
|
|
70
|
+
link.media = 'screen,print';
|
|
71
|
+
link.setAttribute('data-aframe-inspector', 'style');
|
|
72
|
+
document.head.appendChild(link);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function injectJS(url, onLoad, onError) {
|
|
76
|
+
var link = document.createElement('script');
|
|
77
|
+
link.src = url;
|
|
78
|
+
link.charset = 'utf-8';
|
|
79
|
+
link.setAttribute('data-aframe-inspector', 'style');
|
|
80
|
+
|
|
81
|
+
if (onLoad) {
|
|
82
|
+
link.addEventListener('load', onLoad);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (onError) {
|
|
86
|
+
link.addEventListener('error', onError);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
document.head.appendChild(link);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function saveString(text, filename, mimeType) {
|
|
93
|
+
saveBlob(new Blob([text], { type: mimeType }), filename);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function saveBlob(blob, filename) {
|
|
97
|
+
var link = document.createElement('a');
|
|
98
|
+
link.style.display = 'none';
|
|
99
|
+
document.body.appendChild(link);
|
|
100
|
+
const url = URL.createObjectURL(blob);
|
|
101
|
+
link.href = url;
|
|
102
|
+
link.download = filename || 'ascene.html';
|
|
103
|
+
link.click();
|
|
104
|
+
URL.revokeObjectURL(url);
|
|
105
|
+
link.remove();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Compares 2 vector objects up to size 4
|
|
109
|
+
// Expect v1 and v2 to take format {x: number, y: number, z: number, w:number}
|
|
110
|
+
// Smaller vectors (ie. vec2) should work as well since their z & w vals will be the same (undefined)
|
|
111
|
+
export function areVectorsEqual(v1, v2) {
|
|
112
|
+
return (
|
|
113
|
+
Object.is(v1.x, v2.x) &&
|
|
114
|
+
Object.is(v1.y, v2.y) &&
|
|
115
|
+
Object.is(v1.z, v2.z) &&
|
|
116
|
+
Object.is(v1.w, v2.w)
|
|
117
|
+
);
|
|
118
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
import TransformControls from './TransformControls.js';
|
|
3
|
+
import EditorControls from './EditorControls.js';
|
|
4
|
+
|
|
5
|
+
import { initRaycaster } from './raycaster';
|
|
6
|
+
import Events from './Events';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Transform controls stuff mostly.
|
|
10
|
+
*/
|
|
11
|
+
export function Viewport(inspector) {
|
|
12
|
+
// Initialize raycaster and picking in differentpmodule.
|
|
13
|
+
const mouseCursor = initRaycaster(inspector);
|
|
14
|
+
const sceneEl = inspector.sceneEl;
|
|
15
|
+
|
|
16
|
+
sceneEl.addEventListener('camera-set-active', (event) => {
|
|
17
|
+
// If we're in edit mode, save the newly active camera and activate when exiting.
|
|
18
|
+
if (inspector.opened) {
|
|
19
|
+
inspector.cameras.original = event.detail.cameraEl;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Helpers.
|
|
24
|
+
const sceneHelpers = inspector.sceneHelpers;
|
|
25
|
+
const grid = new THREE.GridHelper(30, 60, 0xaaaaaa, 0x262626);
|
|
26
|
+
sceneHelpers.add(grid);
|
|
27
|
+
|
|
28
|
+
const selectionBox = new THREE.BoxHelper();
|
|
29
|
+
selectionBox.material.depthTest = false;
|
|
30
|
+
selectionBox.material.transparent = true;
|
|
31
|
+
selectionBox.material.color.set(0x1faaf2);
|
|
32
|
+
selectionBox.visible = false;
|
|
33
|
+
sceneHelpers.add(selectionBox);
|
|
34
|
+
|
|
35
|
+
function updateHelpers(object) {
|
|
36
|
+
object.traverse((node) => {
|
|
37
|
+
if (inspector.helpers[node.uuid] && inspector.helpers[node.uuid].update) {
|
|
38
|
+
inspector.helpers[node.uuid].update();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const camera = inspector.camera;
|
|
44
|
+
const transformControls = new THREE.TransformControls(
|
|
45
|
+
camera,
|
|
46
|
+
inspector.container
|
|
47
|
+
);
|
|
48
|
+
transformControls.size = 0.75;
|
|
49
|
+
transformControls.addEventListener('objectChange', (evt) => {
|
|
50
|
+
const object = transformControls.object;
|
|
51
|
+
if (object === undefined) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
selectionBox.setFromObject(object);
|
|
56
|
+
|
|
57
|
+
updateHelpers(object);
|
|
58
|
+
|
|
59
|
+
// Emit update event for watcher.
|
|
60
|
+
let component;
|
|
61
|
+
let value;
|
|
62
|
+
if (evt.mode === 'translate') {
|
|
63
|
+
component = 'position';
|
|
64
|
+
value = `${object.position.x} ${object.position.y} ${object.position.z}`;
|
|
65
|
+
} else if (evt.mode === 'rotate') {
|
|
66
|
+
component = 'rotation';
|
|
67
|
+
const d = THREE.MathUtils.radToDeg;
|
|
68
|
+
value = `${d(object.rotation.x)} ${d(object.rotation.y)} ${d(
|
|
69
|
+
object.rotation.z
|
|
70
|
+
)}`;
|
|
71
|
+
} else if (evt.mode === 'scale') {
|
|
72
|
+
component = 'scale';
|
|
73
|
+
value = `${object.scale.x} ${object.scale.y} ${object.scale.z}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// We need to call setAttribute for component attrValue to be up to date,
|
|
77
|
+
// so that entity.flushToDOM() works correctly when duplicating an entity.
|
|
78
|
+
transformControls.object.el.setAttribute(component, value);
|
|
79
|
+
|
|
80
|
+
Events.emit('entityupdate', {
|
|
81
|
+
component: component,
|
|
82
|
+
entity: transformControls.object.el,
|
|
83
|
+
property: '',
|
|
84
|
+
value: value
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
transformControls.addEventListener('mouseDown', () => {
|
|
89
|
+
controls.enabled = false;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
transformControls.addEventListener('mouseUp', () => {
|
|
93
|
+
controls.enabled = true;
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
sceneHelpers.add(transformControls);
|
|
97
|
+
|
|
98
|
+
Events.on('entityupdate', (detail) => {
|
|
99
|
+
const object = detail.entity.object3D;
|
|
100
|
+
if (
|
|
101
|
+
inspector.selected === object &&
|
|
102
|
+
inspector.selectedEntity.object3DMap.mesh
|
|
103
|
+
) {
|
|
104
|
+
selectionBox.setFromObject(inspector.selected);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Controls need to be added *after* main logic.
|
|
109
|
+
const controls = new THREE.EditorControls(camera, inspector.container);
|
|
110
|
+
controls.center.set(0, 1.6, 0);
|
|
111
|
+
controls.rotationSpeed = 0.0035;
|
|
112
|
+
controls.zoomSpeed = 0.05;
|
|
113
|
+
controls.setAspectRatio(sceneEl.canvas.width / sceneEl.canvas.height);
|
|
114
|
+
controls.addEventListener('change', () => {
|
|
115
|
+
transformControls.update(true); // true is updateScale
|
|
116
|
+
Events.emit('camerachanged');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
Events.on('cameratoggle', (data) => {
|
|
120
|
+
controls.setCamera(data.camera);
|
|
121
|
+
transformControls.setCamera(data.camera);
|
|
122
|
+
updateAspectRatio();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
function disableControls() {
|
|
126
|
+
mouseCursor.disable();
|
|
127
|
+
transformControls.dispose();
|
|
128
|
+
controls.enabled = false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function enableControls() {
|
|
132
|
+
mouseCursor.enable();
|
|
133
|
+
transformControls.activate();
|
|
134
|
+
controls.enabled = true;
|
|
135
|
+
}
|
|
136
|
+
enableControls();
|
|
137
|
+
|
|
138
|
+
Events.on('inspectorcleared', () => {
|
|
139
|
+
controls.center.set(0, 0, 0);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
Events.on('transformmodechange', (mode) => {
|
|
143
|
+
transformControls.setMode(mode);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
Events.on('translationsnapchanged', (dist) => {
|
|
147
|
+
transformControls.setTranslationSnap(dist);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
Events.on('rotationsnapchanged', (dist) => {
|
|
151
|
+
transformControls.setRotationSnap(dist);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
Events.on('transformspacechanged', (space) => {
|
|
155
|
+
transformControls.setSpace(space);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
Events.on('objectselect', (object) => {
|
|
159
|
+
selectionBox.visible = false;
|
|
160
|
+
transformControls.detach();
|
|
161
|
+
if (object && object.el) {
|
|
162
|
+
if (object.el.getObject3D('mesh')) {
|
|
163
|
+
selectionBox.setFromObject(object);
|
|
164
|
+
selectionBox.visible = true;
|
|
165
|
+
} else if (object.el.hasAttribute('gltf-model')) {
|
|
166
|
+
const listener = (event) => {
|
|
167
|
+
if (event.target !== object.el) return; // we got an event for a child, ignore
|
|
168
|
+
selectionBox.setFromObject(object);
|
|
169
|
+
selectionBox.visible = true;
|
|
170
|
+
object.el.removeEventListener('model-loaded', listener);
|
|
171
|
+
};
|
|
172
|
+
object.el.addEventListener('model-loaded', listener);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
transformControls.attach(object);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
Events.on('objectfocus', (object) => {
|
|
180
|
+
controls.focus(object);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
Events.on('geometrychanged', (object) => {
|
|
184
|
+
if (object !== null) {
|
|
185
|
+
selectionBox.setFromObject(object);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
Events.on('entityupdate', (detail) => {
|
|
190
|
+
const object = detail.entity.object3D;
|
|
191
|
+
if (inspector.selected === object) {
|
|
192
|
+
// Hack because object3D always has geometry :(
|
|
193
|
+
if (
|
|
194
|
+
object.geometry &&
|
|
195
|
+
((object.geometry.vertices && object.geometry.vertices.length > 0) ||
|
|
196
|
+
(object.geometry.attributes &&
|
|
197
|
+
object.geometry.attributes.position &&
|
|
198
|
+
object.geometry.attributes.position.array.length))
|
|
199
|
+
) {
|
|
200
|
+
selectionBox.setFromObject(object);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
transformControls.update();
|
|
205
|
+
if (object instanceof THREE.PerspectiveCamera) {
|
|
206
|
+
object.updateProjectionMatrix();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
updateHelpers(object);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
function updateAspectRatio() {
|
|
213
|
+
if (!inspector.opened) return;
|
|
214
|
+
// Modifying aspect for perspective camera is done by aframe a-scene.resize function
|
|
215
|
+
// when the perspective camera is the active camera, so we actually do it a second time here,
|
|
216
|
+
// but we need to modify it ourself when we switch from ortho camera to perspective camera (updateAspectRatio() is called in cameratoggle handler).
|
|
217
|
+
const camera = inspector.camera;
|
|
218
|
+
const aspect =
|
|
219
|
+
inspector.container.offsetWidth / inspector.container.offsetHeight;
|
|
220
|
+
if (camera.isPerspectiveCamera) {
|
|
221
|
+
camera.aspect = aspect;
|
|
222
|
+
} else if (camera.isOrthographicCamera) {
|
|
223
|
+
const frustumSize = camera.top - camera.bottom;
|
|
224
|
+
camera.left = (-frustumSize * aspect) / 2;
|
|
225
|
+
camera.right = (frustumSize * aspect) / 2;
|
|
226
|
+
camera.top = frustumSize / 2;
|
|
227
|
+
camera.bottom = -frustumSize / 2;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
controls.setAspectRatio(aspect); // for zoom in/out to work correctly for orthographic camera
|
|
231
|
+
camera.updateProjectionMatrix();
|
|
232
|
+
|
|
233
|
+
const cameraHelper = inspector.helpers[camera.uuid];
|
|
234
|
+
if (cameraHelper) cameraHelper.update();
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
inspector.sceneEl.addEventListener('rendererresize', updateAspectRatio);
|
|
238
|
+
|
|
239
|
+
Events.on('gridvisibilitychanged', (showGrid) => {
|
|
240
|
+
grid.visible = showGrid;
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
Events.on('togglegrid', () => {
|
|
244
|
+
grid.visible = !grid.visible;
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
Events.on('inspectortoggle', (active) => {
|
|
248
|
+
if (active) {
|
|
249
|
+
enableControls();
|
|
250
|
+
AFRAME.scenes[0].camera = inspector.camera;
|
|
251
|
+
Array.prototype.slice
|
|
252
|
+
.call(document.querySelectorAll('.a-enter-vr,.rs-base'))
|
|
253
|
+
.forEach((element) => {
|
|
254
|
+
element.style.display = 'none';
|
|
255
|
+
});
|
|
256
|
+
} else {
|
|
257
|
+
disableControls();
|
|
258
|
+
inspector.cameras.original.setAttribute('camera', 'active', 'true');
|
|
259
|
+
AFRAME.scenes[0].camera =
|
|
260
|
+
inspector.cameras.original.getObject3D('camera');
|
|
261
|
+
Array.prototype.slice
|
|
262
|
+
.call(document.querySelectorAll('.a-enter-vr,.rs-base'))
|
|
263
|
+
.forEach((element) => {
|
|
264
|
+
element.style.display = 'block';
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|