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,89 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const PrimitiveTextIcon = ({ color = '#A3A3A3' }) => (
|
|
4
|
+
<svg
|
|
5
|
+
width="100%"
|
|
6
|
+
height="100%"
|
|
7
|
+
viewBox="0 0 406 406"
|
|
8
|
+
style={{ overflow: 'hidden' }}
|
|
9
|
+
>
|
|
10
|
+
<g transform="translate(-1309 -1574)">
|
|
11
|
+
<path
|
|
12
|
+
d="M1323.5 1587.5 1323.5 1965.45"
|
|
13
|
+
stroke={color}
|
|
14
|
+
strokeWidth="26.6667"
|
|
15
|
+
strokeLinecap="round"
|
|
16
|
+
strokeLinejoin="round"
|
|
17
|
+
strokeMiterlimit="10"
|
|
18
|
+
fill="none"
|
|
19
|
+
fillRule="evenodd"
|
|
20
|
+
/>
|
|
21
|
+
<path
|
|
22
|
+
d="M1701.5 1587.5 1701.5 1965.45"
|
|
23
|
+
stroke={color}
|
|
24
|
+
strokeWidth="26.6667"
|
|
25
|
+
strokeLinecap="round"
|
|
26
|
+
strokeLinejoin="round"
|
|
27
|
+
strokeMiterlimit="10"
|
|
28
|
+
fill="none"
|
|
29
|
+
fillRule="evenodd"
|
|
30
|
+
/>
|
|
31
|
+
<path
|
|
32
|
+
d="M0 0 377.953 0.000104987"
|
|
33
|
+
stroke={color}
|
|
34
|
+
strokeWidth="26.6667"
|
|
35
|
+
strokeLinecap="round"
|
|
36
|
+
strokeLinejoin="round"
|
|
37
|
+
strokeMiterlimit="10"
|
|
38
|
+
fill="none"
|
|
39
|
+
fillRule="evenodd"
|
|
40
|
+
transform="matrix(-1 0 0 1 1701.45 1965.5)"
|
|
41
|
+
/>
|
|
42
|
+
<path
|
|
43
|
+
d="M0 0 377.953 0.000104987"
|
|
44
|
+
stroke={color}
|
|
45
|
+
strokeWidth="26.6667"
|
|
46
|
+
strokeLinecap="round"
|
|
47
|
+
strokeLinejoin="round"
|
|
48
|
+
strokeMiterlimit="10"
|
|
49
|
+
fill="none"
|
|
50
|
+
fillRule="evenodd"
|
|
51
|
+
transform="matrix(-1 0 0 1 1701.45 1587.5)"
|
|
52
|
+
/>
|
|
53
|
+
<path
|
|
54
|
+
d="M0 0 151.181 0.000104987"
|
|
55
|
+
stroke={color}
|
|
56
|
+
strokeWidth="26.6667"
|
|
57
|
+
strokeLinecap="round"
|
|
58
|
+
strokeLinejoin="round"
|
|
59
|
+
strokeMiterlimit="10"
|
|
60
|
+
fill="none"
|
|
61
|
+
fillRule="evenodd"
|
|
62
|
+
transform="matrix(-1 0 0 1 1587.68 1890.5)"
|
|
63
|
+
/>
|
|
64
|
+
<path
|
|
65
|
+
d="M1512.5 1663.5 1512.5 1890.27"
|
|
66
|
+
stroke={color}
|
|
67
|
+
strokeWidth="26.6667"
|
|
68
|
+
strokeLinecap="round"
|
|
69
|
+
strokeLinejoin="round"
|
|
70
|
+
strokeMiterlimit="10"
|
|
71
|
+
fill="none"
|
|
72
|
+
fillRule="evenodd"
|
|
73
|
+
/>
|
|
74
|
+
<path
|
|
75
|
+
d="M0 0 151.181 0.000104987"
|
|
76
|
+
stroke={color}
|
|
77
|
+
strokeWidth="26.6667"
|
|
78
|
+
strokeLinecap="round"
|
|
79
|
+
strokeLinejoin="round"
|
|
80
|
+
strokeMiterlimit="10"
|
|
81
|
+
fill="none"
|
|
82
|
+
fillRule="evenodd"
|
|
83
|
+
transform="matrix(-1 0 0 1 1587.68 1663.5)"
|
|
84
|
+
/>
|
|
85
|
+
</g>
|
|
86
|
+
</svg>
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
export default PrimitiveTextIcon;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const PrimitiveTorusIcon = ({ color = '#A3A3A3' }) => (
|
|
4
|
+
<svg
|
|
5
|
+
width="100%"
|
|
6
|
+
height="100%"
|
|
7
|
+
viewBox="0 0 406 406"
|
|
8
|
+
style={{ overflow: 'hidden' }}
|
|
9
|
+
>
|
|
10
|
+
<g transform="translate(-2292 -1044)">
|
|
11
|
+
<path
|
|
12
|
+
d="M2306.5 1247.5C2306.5 1143.12 2390.89 1058.5 2495 1058.5 2599.11 1058.5 2683.5 1143.12 2683.5 1247.5 2683.5 1351.88 2599.11 1436.5 2495 1436.5 2390.89 1436.5 2306.5 1351.88 2306.5 1247.5Z"
|
|
13
|
+
stroke={color}
|
|
14
|
+
strokeWidth="26.6667"
|
|
15
|
+
strokeMiterlimit="8"
|
|
16
|
+
fill="none"
|
|
17
|
+
fillRule="evenodd"
|
|
18
|
+
/>
|
|
19
|
+
<path
|
|
20
|
+
d="M2381.5 1248C2381.5 1185.32 2432.32 1134.5 2495 1134.5 2557.68 1134.5 2608.5 1185.32 2608.5 1248 2608.5 1310.68 2557.68 1361.5 2495 1361.5 2432.32 1361.5 2381.5 1310.68 2381.5 1248Z"
|
|
21
|
+
stroke={color}
|
|
22
|
+
strokeWidth="26.6667"
|
|
23
|
+
strokeMiterlimit="8"
|
|
24
|
+
fill="none"
|
|
25
|
+
fillRule="evenodd"
|
|
26
|
+
/>
|
|
27
|
+
</g>
|
|
28
|
+
</svg>
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
export default PrimitiveTorusIcon;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const RightViewIcon = (props) => (
|
|
4
|
+
<svg
|
|
5
|
+
viewBox="0 0 24 24"
|
|
6
|
+
fill="none"
|
|
7
|
+
stroke="currentColor"
|
|
8
|
+
strokeWidth="1.5"
|
|
9
|
+
strokeLinecap="round"
|
|
10
|
+
strokeLinejoin="round"
|
|
11
|
+
{...props}
|
|
12
|
+
>
|
|
13
|
+
{/* Cube Outline */}
|
|
14
|
+
<path d="M 5 5 L 19 5 L 19 19 L 5 19 Z" /> {/* Front Face */}
|
|
15
|
+
<path d="M 5 5 L 10 2 L 24 2 L 19 5" /> {/* Top Face */}
|
|
16
|
+
<path d="M 19 5 L 24 2 L 24 16 L 19 19" /> {/* Right Edge */}
|
|
17
|
+
<path d="M 5 19 L 10 16 L 10 2" /> {/* Left Edge */}
|
|
18
|
+
<path d="M 10 16 L 24 16" /> {/* Bottom Edge */}
|
|
19
|
+
{/* Highlight Right Face */}
|
|
20
|
+
<path d="M 19 5 L 24 2 L 24 16 L 19 19 Z" fill="#00ff99" />
|
|
21
|
+
</svg>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export default RightViewIcon;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const TopViewIcon = (props) => (
|
|
4
|
+
<svg
|
|
5
|
+
viewBox="0 0 24 24"
|
|
6
|
+
fill="none"
|
|
7
|
+
stroke="currentColor"
|
|
8
|
+
strokeWidth="1.5"
|
|
9
|
+
strokeLinecap="round"
|
|
10
|
+
strokeLinejoin="round"
|
|
11
|
+
{...props}
|
|
12
|
+
>
|
|
13
|
+
{/* Cube Outline */}
|
|
14
|
+
<path d="M 5 5 L 19 5 L 19 19 L 5 19 Z" /> {/* Front Face */}
|
|
15
|
+
<path d="M 5 5 L 10 2 L 24 2 L 19 5" /> {/* Top Edge */}
|
|
16
|
+
<path d="M 19 5 L 24 2 L 24 16 L 19 19" /> {/* Right Edge */}
|
|
17
|
+
<path d="M 5 19 L 10 16 L 10 2" /> {/* Left Edge */}
|
|
18
|
+
<path d="M 10 16 L 24 16" /> {/* Bottom Edge */}
|
|
19
|
+
{/* Highlight Top Face */}
|
|
20
|
+
<path d="M 5 5 L 10 2 L 24 2 L 19 5 Z" fill="#00ff99" />
|
|
21
|
+
</svg>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export default TopViewIcon;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
|
|
4
|
+
export default class Modal extends React.Component {
|
|
5
|
+
static propTypes = {
|
|
6
|
+
id: PropTypes.string,
|
|
7
|
+
children: PropTypes.oneOfType([PropTypes.array, PropTypes.element])
|
|
8
|
+
.isRequired,
|
|
9
|
+
isOpen: PropTypes.bool,
|
|
10
|
+
extraCloseKeyCode: PropTypes.number,
|
|
11
|
+
closeOnClickOutside: PropTypes.bool,
|
|
12
|
+
onClose: PropTypes.func,
|
|
13
|
+
title: PropTypes.string
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
static defaultProps = {
|
|
17
|
+
closeOnClickOutside: true
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
constructor(props) {
|
|
21
|
+
super(props);
|
|
22
|
+
this.state = { isOpen: this.props.isOpen };
|
|
23
|
+
this.self = React.createRef();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
componentDidMount() {
|
|
27
|
+
document.addEventListener('keyup', this.handleGlobalKeydown);
|
|
28
|
+
document.addEventListener('mousedown', this.handleGlobalMousedown);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
handleGlobalKeydown = (event) => {
|
|
32
|
+
if (
|
|
33
|
+
this.state.isOpen &&
|
|
34
|
+
(event.keyCode === 27 ||
|
|
35
|
+
(this.props.extraCloseKeyCode &&
|
|
36
|
+
event.keyCode === this.props.extraCloseKeyCode))
|
|
37
|
+
) {
|
|
38
|
+
this.close();
|
|
39
|
+
|
|
40
|
+
// Prevent closing the inspector
|
|
41
|
+
event.stopPropagation();
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
shouldClickDismiss = (event) => {
|
|
46
|
+
var target = event.target;
|
|
47
|
+
// This piece of code isolates targets which are fake clicked by things
|
|
48
|
+
// like file-drop handlers
|
|
49
|
+
if (target.tagName === 'INPUT' && target.type === 'file') {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
if (target === this.self.current || this.self.current.contains(target)) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
handleGlobalMousedown = (event) => {
|
|
59
|
+
if (
|
|
60
|
+
this.props.closeOnClickOutside &&
|
|
61
|
+
this.state.isOpen &&
|
|
62
|
+
this.shouldClickDismiss(event)
|
|
63
|
+
) {
|
|
64
|
+
if (typeof this.props.onClose === 'function') {
|
|
65
|
+
this.props.onClose();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
componentWillUnmount() {
|
|
71
|
+
document.removeEventListener('keyup', this.handleGlobalKeydown);
|
|
72
|
+
document.removeEventListener('mousedown', this.handleGlobalMousedown);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static getDerivedStateFromProps(props, state) {
|
|
76
|
+
if (state.isOpen !== props.isOpen) {
|
|
77
|
+
return { isOpen: props.isOpen };
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
close = () => {
|
|
83
|
+
this.setState({ isOpen: false });
|
|
84
|
+
if (this.props.onClose) {
|
|
85
|
+
this.props.onClose();
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
render() {
|
|
90
|
+
return (
|
|
91
|
+
<div
|
|
92
|
+
id={this.props.id}
|
|
93
|
+
className={this.state.isOpen ? 'modal' : 'modal hide'}
|
|
94
|
+
>
|
|
95
|
+
<div className="modal-content" ref={this.self}>
|
|
96
|
+
<div className="modal-header">
|
|
97
|
+
<span className="close" onClick={this.close}>
|
|
98
|
+
×
|
|
99
|
+
</span>
|
|
100
|
+
<h3>{this.props.title}</h3>
|
|
101
|
+
</div>
|
|
102
|
+
<div className="modal-body">{this.props.children}</div>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import Modal from './Modal';
|
|
4
|
+
|
|
5
|
+
export default class ModalHelp extends React.Component {
|
|
6
|
+
static propTypes = {
|
|
7
|
+
isOpen: PropTypes.bool,
|
|
8
|
+
onClose: PropTypes.func
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
constructor(props) {
|
|
12
|
+
super(props);
|
|
13
|
+
this.state = {
|
|
14
|
+
isOpen: this.props.isOpen
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static getDerivedStateFromProps(props, state) {
|
|
19
|
+
if (state.isOpen !== props.isOpen) {
|
|
20
|
+
return { isOpen: props.isOpen };
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
onClose = () => {
|
|
26
|
+
if (this.props.onClose) {
|
|
27
|
+
this.props.onClose();
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
render() {
|
|
32
|
+
let shortcuts = [
|
|
33
|
+
[
|
|
34
|
+
{ key: ['w'], description: 'Translate' },
|
|
35
|
+
{ key: ['e'], description: 'Rotate' },
|
|
36
|
+
{ key: ['r'], description: 'Scale' },
|
|
37
|
+
{ key: ['d'], description: 'Duplicate selected entity' },
|
|
38
|
+
{ key: ['f'], description: 'Focus on selected entity' },
|
|
39
|
+
{ key: ['g'], description: 'Toggle grid visibility' },
|
|
40
|
+
{ key: ['n'], description: 'Add new entity' },
|
|
41
|
+
{ key: ['o'], description: 'Toggle local between global transform' },
|
|
42
|
+
{ key: ['supr | backspace'], description: 'Delete selected entity' }
|
|
43
|
+
],
|
|
44
|
+
[
|
|
45
|
+
{ key: ['0'], description: 'Toggle panels' },
|
|
46
|
+
{ key: ['1'], description: 'Perspective view' },
|
|
47
|
+
{ key: ['2'], description: 'Left view' },
|
|
48
|
+
{ key: ['3'], description: 'Right view' },
|
|
49
|
+
{ key: ['4'], description: 'Top view' },
|
|
50
|
+
{ key: ['5'], description: 'Bottom view' },
|
|
51
|
+
{ key: ['6'], description: 'Back view' },
|
|
52
|
+
{ key: ['7'], description: 'Front view' },
|
|
53
|
+
|
|
54
|
+
{ key: ['ctrl | cmd', 'x'], description: 'Cut selected entity' },
|
|
55
|
+
{ key: ['ctrl | cmd', 'c'], description: 'Copy selected entity' },
|
|
56
|
+
{ key: ['ctrl | cmd', 'v'], description: 'Paste entity' },
|
|
57
|
+
{ key: ['h'], description: 'Show this help' },
|
|
58
|
+
{ key: ['Esc'], description: 'Unselect entity' },
|
|
59
|
+
{ key: ['ctrl', 'alt', 'i'], description: 'Switch Edit and VR Modes' }
|
|
60
|
+
]
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<Modal
|
|
65
|
+
title="Shortcuts"
|
|
66
|
+
isOpen={this.state.isOpen}
|
|
67
|
+
onClose={this.onClose}
|
|
68
|
+
extraCloseKeyCode={72}
|
|
69
|
+
>
|
|
70
|
+
<div className="help-lists">
|
|
71
|
+
{shortcuts.map(function (column, idx) {
|
|
72
|
+
return (
|
|
73
|
+
<ul className="help-list" key={idx}>
|
|
74
|
+
{column.map(function (shortcut) {
|
|
75
|
+
return (
|
|
76
|
+
<li key={shortcut.key} className="help-key-unit">
|
|
77
|
+
{shortcut.key.map(function (key) {
|
|
78
|
+
return (
|
|
79
|
+
<kbd key={key} className="help-key">
|
|
80
|
+
<span>{key}</span>
|
|
81
|
+
</kbd>
|
|
82
|
+
);
|
|
83
|
+
})}
|
|
84
|
+
<span className="help-key-def">
|
|
85
|
+
{shortcut.description}
|
|
86
|
+
</span>
|
|
87
|
+
</li>
|
|
88
|
+
);
|
|
89
|
+
})}
|
|
90
|
+
</ul>
|
|
91
|
+
);
|
|
92
|
+
})}
|
|
93
|
+
</div>
|
|
94
|
+
</Modal>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import PrimitiveBoxIcon from '../icons/primitiveBoxIcon';
|
|
4
|
+
import PrimitiveConeIcon from '../icons/PrimitiveConeIcon';
|
|
5
|
+
import PrimitiveCylinderIcon from '../icons/PrimitiveCylinderIcon';
|
|
6
|
+
import PrimitiveEmptyEntityIcon from '../icons/PrimitiveEmptyEntityIcon';
|
|
7
|
+
import PrimitiveImageIcon from '../icons/PrimitiveImageIcon';
|
|
8
|
+
import PrimitiveLightIcon from '../icons/PrimitiveLightIcon';
|
|
9
|
+
import PrimitivePlaneIcon from '../icons/PrimitivePlaneIcon';
|
|
10
|
+
import PrimitiveSphereIcon from '../icons/PrimitiveSphereIcon';
|
|
11
|
+
import PrimitiveTorusIcon from '../icons/PrimitiveTorusIcon';
|
|
12
|
+
import PrimitiveTextIcon from '../icons/PrimitiveTextIcon';
|
|
13
|
+
|
|
14
|
+
const PRIMITIVES = [
|
|
15
|
+
{ type: 'a-box', label: 'Box', icon: <PrimitiveBoxIcon color="#ffffff" /> },
|
|
16
|
+
{
|
|
17
|
+
type: 'a-sphere',
|
|
18
|
+
label: 'Sphere',
|
|
19
|
+
icon: <PrimitiveSphereIcon color="#ffffff" />
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
type: 'a-cylinder',
|
|
23
|
+
label: 'Cylinder',
|
|
24
|
+
icon: <PrimitiveCylinderIcon color="#ffffff" />
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
type: 'a-cone',
|
|
28
|
+
label: 'Cone',
|
|
29
|
+
icon: <PrimitiveConeIcon color="#ffffff" />
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
type: 'a-torus',
|
|
33
|
+
label: 'Torus',
|
|
34
|
+
icon: <PrimitiveTorusIcon color="#ffffff" />
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: 'a-plane',
|
|
38
|
+
label: 'Plane',
|
|
39
|
+
icon: <PrimitivePlaneIcon color="#ffffff" />
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
type: 'a-image',
|
|
43
|
+
label: 'Image',
|
|
44
|
+
icon: <PrimitiveImageIcon color="#ffffff" />
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
type: 'a-text',
|
|
48
|
+
label: 'Text',
|
|
49
|
+
icon: <PrimitiveTextIcon color="#ffffff" />
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
type: 'a-light',
|
|
53
|
+
label: 'Light',
|
|
54
|
+
icon: <PrimitiveLightIcon color="#ffffff" />
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: 'a-entity',
|
|
58
|
+
label: 'Empty Entity',
|
|
59
|
+
icon: <PrimitiveEmptyEntityIcon color="#ffffff" />
|
|
60
|
+
}
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
export default function ModalPrimitive({ isOpen, onClose, onSelectPrimitive }) {
|
|
64
|
+
if (!isOpen) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const handleSelect = (primitiveType) => {
|
|
69
|
+
onSelectPrimitive(primitiveType);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// Stop propagation to prevent closing modal when clicking inside
|
|
73
|
+
const handleModalContentClick = (e) => {
|
|
74
|
+
e.stopPropagation();
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<div className="modal-overlay" onClick={onClose}>
|
|
79
|
+
<div
|
|
80
|
+
className="modal-content"
|
|
81
|
+
id="primitive-modal"
|
|
82
|
+
onClick={handleModalContentClick}
|
|
83
|
+
>
|
|
84
|
+
<div className="modal-header">
|
|
85
|
+
<h3>Select Primitive</h3>
|
|
86
|
+
<span className="close" onClick={onClose}>
|
|
87
|
+
×
|
|
88
|
+
</span>
|
|
89
|
+
</div>
|
|
90
|
+
<div className="modal-body">
|
|
91
|
+
<div className="primitive-grid">
|
|
92
|
+
{PRIMITIVES.map((primitive) => (
|
|
93
|
+
<button
|
|
94
|
+
key={primitive.type}
|
|
95
|
+
className="primitive-button"
|
|
96
|
+
onClick={() => handleSelect(primitive.type)}
|
|
97
|
+
title={`Add ${primitive.label}`}
|
|
98
|
+
>
|
|
99
|
+
{primitive.icon}
|
|
100
|
+
{primitive.label}
|
|
101
|
+
</button>
|
|
102
|
+
))}
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
ModalPrimitive.propTypes = {
|
|
111
|
+
isOpen: PropTypes.bool.isRequired,
|
|
112
|
+
onClose: PropTypes.func.isRequired,
|
|
113
|
+
onSelectPrimitive: PropTypes.func.isRequired
|
|
114
|
+
};
|