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.
Files changed (104) hide show
  1. package/.babelrc +3 -0
  2. package/.editorconfig +12 -0
  3. package/.eslintignore +2 -0
  4. package/.eslintrc +40 -0
  5. package/.github/workflows/ci.yml +39 -0
  6. package/.husky/pre-commit +4 -0
  7. package/.prettierignore +1 -0
  8. package/.prettierrc.json +5 -0
  9. package/.stylelintrc +12 -0
  10. package/LICENSE +21 -0
  11. package/README.md +75 -0
  12. package/assets/gltf.svg +49 -0
  13. package/dist/aframe-inspector.js +106250 -0
  14. package/dist/aframe-inspector.js.map +1 -0
  15. package/dist/aframe-inspector.min.js +29040 -0
  16. package/dist/aframe-inspector.min.js.LICENSE.txt +56 -0
  17. package/dist/aframe-inspector.min.js.map +1 -0
  18. package/examples/360video.html +48 -0
  19. package/examples/colors.html +18 -0
  20. package/examples/controllers.html +60 -0
  21. package/examples/embedded-zoom.html +78 -0
  22. package/examples/embedded.html +79 -0
  23. package/examples/empty.html +13 -0
  24. package/examples/index-aframe.html +66 -0
  25. package/examples/index.html +71 -0
  26. package/examples/supercraft.html +6 -0
  27. package/index.html +8 -0
  28. package/package.json +84 -0
  29. package/senangwebs-webverse-editor.png +0 -0
  30. package/src/components/AwesomeIcon.js +53 -0
  31. package/src/components/Collapsible.js +57 -0
  32. package/src/components/EntityRepresentation.js +83 -0
  33. package/src/components/Main.js +222 -0
  34. package/src/components/__tests__/Collapsible.test.js +30 -0
  35. package/src/components/components/AddComponent.js +104 -0
  36. package/src/components/components/CommonComponents.js +160 -0
  37. package/src/components/components/Component.js +151 -0
  38. package/src/components/components/ComponentsContainer.js +52 -0
  39. package/src/components/components/DefaultComponents.js +1 -0
  40. package/src/components/components/Mixins.js +83 -0
  41. package/src/components/components/PropertyRow.js +145 -0
  42. package/src/components/components/Sidebar.js +51 -0
  43. package/src/components/icons/BackViewIcon.js +27 -0
  44. package/src/components/icons/BottomViewIcon.js +26 -0
  45. package/src/components/icons/FrontViewIcon.js +23 -0
  46. package/src/components/icons/LeftViewIcon.js +24 -0
  47. package/src/components/icons/PerspectiveIcon.js +23 -0
  48. package/src/components/icons/PrimitiveBoxIcon.js +143 -0
  49. package/src/components/icons/PrimitiveConeIcon.js +44 -0
  50. package/src/components/icons/PrimitiveCylinderIcon.js +51 -0
  51. package/src/components/icons/PrimitiveEmptyEntityIcon.js +78 -0
  52. package/src/components/icons/PrimitiveImageIcon.js +86 -0
  53. package/src/components/icons/PrimitiveLightIcon.js +107 -0
  54. package/src/components/icons/PrimitivePlaneIcon.js +87 -0
  55. package/src/components/icons/PrimitiveSphereIcon.js +39 -0
  56. package/src/components/icons/PrimitiveTextIcon.js +89 -0
  57. package/src/components/icons/PrimitiveTorusIcon.js +31 -0
  58. package/src/components/icons/RightViewIcon.js +24 -0
  59. package/src/components/icons/TopViewIcon.js +24 -0
  60. package/src/components/modals/Modal.js +107 -0
  61. package/src/components/modals/ModalHelp.js +97 -0
  62. package/src/components/modals/ModalPrimitive.js +114 -0
  63. package/src/components/modals/ModalTextures.js +430 -0
  64. package/src/components/scenegraph/Entity.js +142 -0
  65. package/src/components/scenegraph/SceneGraph.js +337 -0
  66. package/src/components/scenegraph/Toolbar.js +147 -0
  67. package/src/components/viewport/CameraToolbar.js +122 -0
  68. package/src/components/viewport/TransformToolbar.js +102 -0
  69. package/src/components/viewport/ViewportHUD.js +33 -0
  70. package/src/components/widgets/BooleanWidget.js +49 -0
  71. package/src/components/widgets/ColorWidget.js +89 -0
  72. package/src/components/widgets/InputWidget.js +42 -0
  73. package/src/components/widgets/NumberWidget.js +179 -0
  74. package/src/components/widgets/SelectWidget.js +58 -0
  75. package/src/components/widgets/TextureWidget.js +252 -0
  76. package/src/components/widgets/Vec2Widget.js +55 -0
  77. package/src/components/widgets/Vec3Widget.js +58 -0
  78. package/src/components/widgets/Vec4Widget.js +61 -0
  79. package/src/components/widgets/index.js +9 -0
  80. package/src/index.js +301 -0
  81. package/src/lib/EditorControls.js +336 -0
  82. package/src/lib/Events.js +6 -0
  83. package/src/lib/TransformControls.js +1365 -0
  84. package/src/lib/assetsLoader.js +43 -0
  85. package/src/lib/assetsUtils.js +30 -0
  86. package/src/lib/cameras.js +121 -0
  87. package/src/lib/entity.js +556 -0
  88. package/src/lib/history.js +30 -0
  89. package/src/lib/raycaster.js +129 -0
  90. package/src/lib/shortcuts.js +211 -0
  91. package/src/lib/utils.js +118 -0
  92. package/src/lib/viewport.js +268 -0
  93. package/src/style/components.styl +275 -0
  94. package/src/style/entity.styl +22 -0
  95. package/src/style/help.styl +40 -0
  96. package/src/style/index.styl +358 -0
  97. package/src/style/lib.styl +41 -0
  98. package/src/style/primitiveModal.styl +90 -0
  99. package/src/style/scenegraph.styl +173 -0
  100. package/src/style/select.styl +71 -0
  101. package/src/style/textureModal.styl +220 -0
  102. package/src/style/viewport.styl +168 -0
  103. package/src/style/widgets.styl +71 -0
  104. package/webpack.config.js +65 -0
@@ -0,0 +1,55 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ import NumberWidget from './NumberWidget';
5
+ import { areVectorsEqual } from '../../lib/utils';
6
+
7
+ export default class Vec2Widget extends React.Component {
8
+ static propTypes = {
9
+ componentname: PropTypes.string,
10
+ entity: PropTypes.object,
11
+ onChange: PropTypes.func,
12
+ value: PropTypes.object.isRequired
13
+ };
14
+
15
+ constructor(props) {
16
+ super(props);
17
+ this.state = {
18
+ x: props.value.x,
19
+ y: props.value.y
20
+ };
21
+ }
22
+
23
+ onChange = (name, value) => {
24
+ this.setState({ [name]: parseFloat(value.toFixed(5)) }, () => {
25
+ if (this.props.onChange) {
26
+ this.props.onChange(name, this.state);
27
+ }
28
+ });
29
+ };
30
+
31
+ componentDidUpdate() {
32
+ const props = this.props;
33
+ if (!areVectorsEqual(props.value, this.state)) {
34
+ this.setState({
35
+ x: props.value.x,
36
+ y: props.value.y
37
+ });
38
+ }
39
+ }
40
+
41
+ render() {
42
+ const widgetProps = {
43
+ componentname: this.props.componentname,
44
+ entity: this.props.entity,
45
+ onChange: this.onChange
46
+ };
47
+
48
+ return (
49
+ <div className="vec2">
50
+ <NumberWidget name="x" value={this.state.x} {...widgetProps} />
51
+ <NumberWidget name="y" value={this.state.y} {...widgetProps} />
52
+ </div>
53
+ );
54
+ }
55
+ }
@@ -0,0 +1,58 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ import NumberWidget from './NumberWidget';
5
+ import { areVectorsEqual } from '../../lib/utils';
6
+
7
+ export default class Vec3Widget extends React.Component {
8
+ static propTypes = {
9
+ componentname: PropTypes.string,
10
+ entity: PropTypes.object,
11
+ onChange: PropTypes.func,
12
+ value: PropTypes.object.isRequired
13
+ };
14
+
15
+ constructor(props) {
16
+ super(props);
17
+ this.state = {
18
+ x: props.value.x,
19
+ y: props.value.y,
20
+ z: props.value.z
21
+ };
22
+ }
23
+
24
+ onChange = (name, value) => {
25
+ this.setState({ [name]: parseFloat(value.toFixed(5)) }, () => {
26
+ if (this.props.onChange) {
27
+ this.props.onChange(name, this.state);
28
+ }
29
+ });
30
+ };
31
+
32
+ componentDidUpdate() {
33
+ const props = this.props;
34
+ if (!areVectorsEqual(props.value, this.state)) {
35
+ this.setState({
36
+ x: props.value.x,
37
+ y: props.value.y,
38
+ z: props.value.z
39
+ });
40
+ }
41
+ }
42
+
43
+ render() {
44
+ const widgetProps = {
45
+ componentname: this.props.componentname,
46
+ entity: this.props.entity,
47
+ onChange: this.onChange
48
+ };
49
+
50
+ return (
51
+ <div className="vec3">
52
+ <NumberWidget name="x" value={this.state.x} {...widgetProps} />
53
+ <NumberWidget name="y" value={this.state.y} {...widgetProps} />
54
+ <NumberWidget name="z" value={this.state.z} {...widgetProps} />
55
+ </div>
56
+ );
57
+ }
58
+ }
@@ -0,0 +1,61 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ import NumberWidget from './NumberWidget';
5
+ import { areVectorsEqual } from '../../lib/utils';
6
+
7
+ export default class Vec4Widget extends React.Component {
8
+ static propTypes = {
9
+ componentname: PropTypes.string,
10
+ entity: PropTypes.object,
11
+ onChange: PropTypes.func,
12
+ value: PropTypes.object.isRequired
13
+ };
14
+
15
+ constructor(props) {
16
+ super(props);
17
+ this.state = {
18
+ x: props.value.x,
19
+ y: props.value.y,
20
+ z: props.value.z,
21
+ w: props.value.w
22
+ };
23
+ }
24
+
25
+ onChange = (name, value) => {
26
+ this.setState({ [name]: parseFloat(value.toFixed(5)) }, () => {
27
+ if (this.props.onChange) {
28
+ this.props.onChange(name, this.state);
29
+ }
30
+ });
31
+ };
32
+
33
+ componentDidUpdate() {
34
+ const props = this.props;
35
+ if (!areVectorsEqual(props.value, this.state)) {
36
+ this.setState({
37
+ x: props.value.x,
38
+ y: props.value.y,
39
+ z: props.value.z,
40
+ w: props.value.w
41
+ });
42
+ }
43
+ }
44
+
45
+ render() {
46
+ const widgetProps = {
47
+ componentname: this.props.componentname,
48
+ entity: this.props.entity,
49
+ onChange: this.onChange
50
+ };
51
+
52
+ return (
53
+ <div className="vec4">
54
+ <NumberWidget name="x" value={this.state.x} {...widgetProps} />
55
+ <NumberWidget name="y" value={this.state.y} {...widgetProps} />
56
+ <NumberWidget name="z" value={this.state.z} {...widgetProps} />
57
+ <NumberWidget name="w" value={this.state.w} {...widgetProps} />
58
+ </div>
59
+ );
60
+ }
61
+ }
@@ -0,0 +1,9 @@
1
+ export { default as BooleanWidget } from './BooleanWidget';
2
+ export { default as ColorWidget } from './ColorWidget';
3
+ export { default as InputWidget } from './InputWidget';
4
+ export { default as NumberWidget } from './NumberWidget';
5
+ export { default as SelectWidget } from './SelectWidget';
6
+ export { default as TextureWidget } from './TextureWidget';
7
+ export { default as Vec4Widget } from './Vec4Widget';
8
+ export { default as Vec3Widget } from './Vec3Widget';
9
+ export { default as Vec2Widget } from './Vec2Widget';
package/src/index.js ADDED
@@ -0,0 +1,301 @@
1
+ import { createRoot } from 'react-dom/client';
2
+ import Events from './lib/Events';
3
+ import { Viewport } from './lib/viewport';
4
+ import { AssetsLoader } from './lib/assetsLoader';
5
+ import { Shortcuts } from './lib/shortcuts';
6
+
7
+ import Main from './components/Main';
8
+ import { initCameras } from './lib/cameras';
9
+ import { createEntity } from './lib/entity';
10
+ import { GLTFExporter } from 'three/addons/exporters/GLTFExporter';
11
+
12
+ import './style/index.styl';
13
+
14
+ function Inspector() {
15
+ this.assetsLoader = new AssetsLoader();
16
+ this.exporters = { gltf: new GLTFExporter() };
17
+ this.history = require('./lib/history');
18
+ this.isFirstOpen = true;
19
+ this.modules = {};
20
+ this.opened = false;
21
+
22
+ // Wait for stuff.
23
+ const doInit = () => {
24
+ if (!AFRAME.scenes.length) {
25
+ setTimeout(() => {
26
+ doInit();
27
+ }, 100);
28
+ return;
29
+ }
30
+
31
+ this.sceneEl = AFRAME.scenes[0];
32
+ if (this.sceneEl.hasLoaded) {
33
+ this.init();
34
+ return;
35
+ }
36
+ this.sceneEl.addEventListener('loaded', this.init.bind(this), {
37
+ once: true
38
+ });
39
+ };
40
+ doInit();
41
+ }
42
+
43
+ Inspector.prototype = {
44
+ init: function () {
45
+ // Wait for camera.
46
+ if (!this.sceneEl.camera) {
47
+ this.sceneEl.addEventListener(
48
+ 'camera-set-active',
49
+ () => {
50
+ this.init();
51
+ },
52
+ { once: true }
53
+ );
54
+ return;
55
+ }
56
+
57
+ this.container = document.querySelector('.a-canvas');
58
+ initCameras(this);
59
+ this.initUI();
60
+ },
61
+
62
+ initUI: function () {
63
+ Shortcuts.init(this);
64
+ this.initEvents();
65
+
66
+ this.selected = null;
67
+
68
+ // Init React.
69
+ const div = document.createElement('div');
70
+ div.id = 'aframeInspector';
71
+ div.setAttribute('data-aframe-inspector', 'app');
72
+ document.body.appendChild(div);
73
+ const root = createRoot(div);
74
+ root.render(<Main />);
75
+
76
+ this.scene = this.sceneEl.object3D;
77
+ this.helpers = {};
78
+ this.sceneHelpers = new THREE.Scene();
79
+ this.sceneHelpers.userData.source = 'INSPECTOR';
80
+ this.sceneHelpers.visible = true;
81
+ this.inspectorActive = false;
82
+
83
+ this.viewport = new Viewport(this);
84
+
85
+ this.sceneEl.object3D.traverse((node) => {
86
+ this.addHelper(node);
87
+ });
88
+
89
+ this.scene.add(this.sceneHelpers);
90
+ this.open();
91
+ },
92
+
93
+ removeObject: function (object) {
94
+ // Remove just the helper as the object will be deleted by A-Frame
95
+ this.removeHelpers(object);
96
+ Events.emit('objectremove', object);
97
+ },
98
+
99
+ addHelper: function (object) {
100
+ let helper;
101
+
102
+ if (object instanceof THREE.Camera) {
103
+ this.cameraHelper = helper = new THREE.CameraHelper(object);
104
+ } else if (object instanceof THREE.PointLight) {
105
+ helper = new THREE.PointLightHelper(object, 1);
106
+ } else if (object instanceof THREE.DirectionalLight) {
107
+ helper = new THREE.DirectionalLightHelper(object, 1);
108
+ } else if (object instanceof THREE.SpotLight) {
109
+ helper = new THREE.SpotLightHelper(object, 1);
110
+ } else if (object instanceof THREE.HemisphereLight) {
111
+ helper = new THREE.HemisphereLightHelper(object, 1);
112
+ } else if (object instanceof THREE.SkinnedMesh) {
113
+ helper = new THREE.SkeletonHelper(object);
114
+ } else {
115
+ // no helper for this object type
116
+ return;
117
+ }
118
+
119
+ helper.visible = false;
120
+ this.sceneHelpers.add(helper);
121
+ this.helpers[object.uuid] = helper;
122
+ // SkeletonHelper doesn't have an update method
123
+ if (helper.update) {
124
+ helper.update();
125
+ }
126
+ },
127
+
128
+ removeHelpers: function (object) {
129
+ object.traverse((node) => {
130
+ const helper = this.helpers[node.uuid];
131
+ if (helper) {
132
+ this.sceneHelpers.remove(helper);
133
+ helper.dispose();
134
+ delete this.helpers[node.uuid];
135
+ Events.emit('helperremove', this.helpers[node.uuid]);
136
+ }
137
+ });
138
+ },
139
+
140
+ selectEntity: function (entity, emit) {
141
+ this.selectedEntity = entity;
142
+ if (entity) {
143
+ this.select(entity.object3D);
144
+ } else {
145
+ this.select(null);
146
+ }
147
+
148
+ if (entity && emit === undefined) {
149
+ Events.emit('entityselect', entity);
150
+ }
151
+
152
+ // Update helper visibilities.
153
+ for (const id in this.helpers) {
154
+ this.helpers[id].visible = false;
155
+ }
156
+
157
+ if (entity === this.sceneEl) {
158
+ return;
159
+ }
160
+
161
+ if (entity) {
162
+ entity.object3D.traverse((node) => {
163
+ if (this.helpers[node.uuid]) {
164
+ this.helpers[node.uuid].visible = true;
165
+ }
166
+ });
167
+ }
168
+ },
169
+
170
+ initEvents: function () {
171
+ window.addEventListener('keydown', (evt) => {
172
+ // Alt + Ctrl + i: Shorcut to toggle the inspector
173
+ const shortcutPressed =
174
+ evt.keyCode === 73 &&
175
+ ((evt.ctrlKey && evt.altKey) || evt.getModifierState('AltGraph'));
176
+ if (shortcutPressed) {
177
+ this.toggle();
178
+ }
179
+ });
180
+
181
+ Events.on('entityselect', (entity) => {
182
+ this.selectEntity(entity, false);
183
+ });
184
+
185
+ Events.on('inspectortoggle', (active) => {
186
+ this.inspectorActive = active;
187
+ this.sceneHelpers.visible = this.inspectorActive;
188
+ });
189
+
190
+ Events.on('entitycreate', (definition) => {
191
+ createEntity(definition, (entity) => {
192
+ this.selectEntity(entity);
193
+ });
194
+ });
195
+
196
+ document.addEventListener('child-detached', (event) => {
197
+ const entity = event.detail.el;
198
+ AFRAME.INSPECTOR.removeObject(entity.object3D);
199
+ });
200
+ },
201
+
202
+ selectById: function (id) {
203
+ if (id === this.camera.id) {
204
+ this.select(this.camera);
205
+ return;
206
+ }
207
+ this.select(this.scene.getObjectById(id, true));
208
+ },
209
+
210
+ /**
211
+ * Change to select object.
212
+ */
213
+ select: function (object3D) {
214
+ if (this.selected === object3D) {
215
+ return;
216
+ }
217
+ this.selected = object3D;
218
+ Events.emit('objectselect', object3D);
219
+ },
220
+
221
+ deselect: function () {
222
+ this.select(null);
223
+ },
224
+
225
+ /**
226
+ * Toggle the editor
227
+ */
228
+ toggle: function () {
229
+ if (this.opened) {
230
+ this.close();
231
+ } else {
232
+ this.open();
233
+ }
234
+ },
235
+
236
+ /**
237
+ * Open the editor UI
238
+ */
239
+ open: function (focusEl) {
240
+ this.opened = true;
241
+ Events.emit('inspectortoggle', true);
242
+
243
+ if (this.sceneEl.hasAttribute('embedded')) {
244
+ // Remove embedded styles, but keep track of it.
245
+ this.sceneEl.removeAttribute('embedded');
246
+ this.sceneEl.setAttribute('aframe-inspector-removed-embedded');
247
+ }
248
+
249
+ document.body.classList.add('aframe-inspector-opened');
250
+ this.sceneEl.resize();
251
+ this.sceneEl.pause();
252
+ this.sceneEl.exitVR();
253
+
254
+ Shortcuts.enable();
255
+
256
+ // Trick scene to run the cursor tick.
257
+ this.sceneEl.isPlaying = true;
258
+ this.cursor.play();
259
+
260
+ if (
261
+ !focusEl &&
262
+ this.isFirstOpen &&
263
+ AFRAME.utils.getUrlParameter('inspector')
264
+ ) {
265
+ // Focus entity with URL parameter on first open.
266
+ focusEl = document.getElementById(
267
+ AFRAME.utils.getUrlParameter('inspector')
268
+ );
269
+ }
270
+ if (focusEl) {
271
+ this.selectEntity(focusEl);
272
+ Events.emit('objectfocus', focusEl.object3D);
273
+ }
274
+ this.isFirstOpen = false;
275
+ },
276
+
277
+ /**
278
+ * Closes the editor and gives the control back to the scene
279
+ * @return {[type]} [description]
280
+ */
281
+ close: function () {
282
+ this.opened = false;
283
+ Events.emit('inspectortoggle', false);
284
+
285
+ // Untrick scene when we enabled this to run the cursor tick.
286
+ this.sceneEl.isPlaying = false;
287
+
288
+ this.sceneEl.play();
289
+ this.cursor.pause();
290
+
291
+ if (this.sceneEl.hasAttribute('aframe-inspector-removed-embedded')) {
292
+ this.sceneEl.setAttribute('embedded', '');
293
+ this.sceneEl.removeAttribute('aframe-inspector-removed-embedded');
294
+ }
295
+ document.body.classList.remove('aframe-inspector-opened');
296
+ this.sceneEl.resize();
297
+ Shortcuts.disable();
298
+ }
299
+ };
300
+
301
+ AFRAME.INSPECTOR = new Inspector();