diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..fdd8651 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "plugins": ["@babel/plugin-proposal-class-properties"] +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4972456..e8c7d3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.0.3] - 2020-02-08 +### Added +- Added tools panel +- Added save/open functionality +### Changed +- Changed plugin system + ## [0.0.2] - 2020-02-02 ### Added - Added orbit camera control @@ -7,5 +14,6 @@ ## [0.0.1] - 2020-02-01 ### Initial release +[0.0.3]: https://github.com/Perkovec/Vuxel/compare/v0.0.2...v0.0.3 [0.0.2]: https://github.com/Perkovec/Vuxel/compare/v0.0.1...v0.0.2 [0.0.1]: https://github.com/Perkovec/Vuxel/releases/tag/v0.0.1 \ No newline at end of file diff --git a/README.md b/README.md index 03dab61..2cbead3 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/Perkovec/Vuxel.svg?branch=master)](https://travis-ci.org/Perkovec/Vuxel) [![Greenkeeper badge](https://badges.greenkeeper.io/Perkovec/Vuxel.svg)](https://greenkeeper.io/) -Version 0.0.2 +Version 0.0.3 By Ilya Karpuk perkovec24@gmail.com @@ -37,7 +37,7 @@ npm run build - [ ] Orientation indicator and controller - [ ] Painting tools - [ ] Advanced color picker -- [ ] Export/import models +- [x] Export/import models - [ ] Layers ## Licence diff --git a/demo.png b/demo.png index 6789476..f36d4a3 100644 Binary files a/demo.png and b/demo.png differ diff --git a/package-lock.json b/package-lock.json index d6d4cc7..57cf171 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "vuxel", - "version": "0.0.1", + "version": "0.0.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -137,6 +137,20 @@ "semver": "^5.5.0" } }, + "@babel/helper-create-class-features-plugin": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz", + "integrity": "sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3" + } + }, "@babel/helper-create-regexp-features-plugin": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz", @@ -348,6 +362,16 @@ "@babel/plugin-syntax-async-generators": "^7.8.0" } }, + "@babel/plugin-proposal-class-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz", + "integrity": "sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, "@babel/plugin-proposal-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz", @@ -2822,6 +2846,11 @@ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "dev": true }, + "event-lite": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/event-lite/-/event-lite-0.1.2.tgz", + "integrity": "sha512-HnSYx1BsJ87/p6swwzv+2v6B4X+uxUteoDfRxsAb1S1BePzQqOLevVmkdA15GHJVd9A9Ok6wygUR18Hu0YeV9g==" + }, "events": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", @@ -4684,6 +4713,11 @@ "to-regex": "^3.0.2" } }, + "micromodal": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/micromodal/-/micromodal-0.4.2.tgz", + "integrity": "sha512-tL8Z6Vi72haNUNlkhLjJJv1Q16eqUWMPAGT4RF7mwDM5DNyJXC67Yj8jw/yVgGYdhnCEBBf3X5JM3d/MpXSEKg==" + }, "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", diff --git a/package.json b/package.json index 3531581..4a1dc19 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vuxel", - "version": "0.0.2", + "version": "0.0.3", "description": "Open Source Voxel editor", "scripts": { "start": "parcel src/index.html", @@ -10,10 +10,14 @@ "author": "perkovec", "license": "MIT", "dependencies": { + "event-lite": "^0.1.2", + "micromodal": "^0.4.2", "purecss": "^1.0.1", "three": "^0.113.1" }, "devDependencies": { + "@babel/core": "^7.8.4", + "@babel/plugin-proposal-class-properties": "^7.8.3", "parcel": "^1.12.4", "posthtml-include": "^1.3.3" } diff --git a/src/app.js b/src/app.js index f7f8f02..4e0dec2 100644 --- a/src/app.js +++ b/src/app.js @@ -2,6 +2,7 @@ export class App { constructor(THREE, plugins) { this.THREE = THREE; this.objects = []; + this.sceneObjects = []; this.isShiftDown = false; this.editorContainer = document.getElementById('editor'); @@ -24,30 +25,30 @@ export class App { this.createLight(); this.createGround(); - this.createCubes(); window.addEventListener('resize', () => this.onWindowResize(), false); - this.editorContainer.addEventListener('mousemove', event => this.onDocumentMouseMove(event), false); - this.editorContainer.addEventListener('mousedown', event => this.onDocumentMouseDown(event), false); - document.addEventListener('keydown', event => this.onDocumentKeyDown(event), false); - document.addEventListener('keyup', event => this.onDocumentKeyUp(event), false); - this.renderer = new THREE.WebGLRenderer({ antialias: true }); this.renderer.setSize(this.editorContainer.clientWidth, this.editorContainer.clientHeight); this.editorContainer.appendChild(this.renderer.domElement); this.rect = this.renderer.domElement.getBoundingClientRect(); + + this.pluginsInstances = {}; const pluginsConfig = { THREE, - brushMaterial: this.cubeMaterial, renderer: this.renderer, camera: this.camera, render: this.render.bind(this), + scene: this.scene, + sceneObjects: this.sceneObjects, + objects: this.objects, + plugins: this.pluginsInstances, + rect: this.rect, } plugins.forEach(Plugin => { - new Plugin(pluginsConfig); + this.pluginsInstances[Plugin.meta.name] = new Plugin(pluginsConfig); }); } @@ -62,18 +63,6 @@ export class App { this.scene.add(directionalLight); } - createCubes() { - const THREE = this.THREE; - - const rollOverGeo = new THREE.BoxBufferGeometry(50, 50, 50); - const rollOverMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, opacity: 0.5, transparent: true }); - this.rollOverMesh = new THREE.Mesh(rollOverGeo, rollOverMaterial); - this.scene.add(this.rollOverMesh); - - this.cubeGeo = new THREE.BoxBufferGeometry(50, 50, 50); - this.cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff }); - } - createGround() { const THREE = this.THREE; const geometry = new THREE.PlaneBufferGeometry(1000, 1000); @@ -88,73 +77,10 @@ export class App { this.camera.aspect = this.editorContainer.clientWidth / this.editorContainer.clientHeight; this.camera.updateProjectionMatrix(); - this.renderer.setSize(this.editorContainer.clientWidth, this.editorContainer.clientHeight); - } - - onDocumentMouseMove(event) { - event.preventDefault(); - - this.mouse.set( - ((event.clientX - this.rect.left) / this.editorContainer.clientWidth) * 2 - 1, - -((event.clientY - this.rect.top) / this.editorContainer.clientHeight) * 2 + 1 - ); - this.raycaster.setFromCamera(this.mouse, this.camera); - - const intersects = this.raycaster.intersectObjects(this.objects); - if (intersects.length > 0) { - const intersect = intersects[0]; - this.rollOverMesh.position.copy(intersect.point).add(intersect.face.normal); - this.rollOverMesh.position.divideScalar(50).floor().multiplyScalar(50).addScalar(25); - } - + this.renderer.setSize(this.editorContainer.clientWidth, this.editorContainer.clientHeight); this.render(); } - onDocumentMouseDown(event) { - event.preventDefault(); - const THREE = this.THREE; - - this.mouse.set( - ((event.clientX - this.rect.left) / this.editorContainer.clientWidth) * 2 - 1, - -((event.clientY - this.rect.top) / this.editorContainer.clientHeight) * 2 + 1 - ); - this.raycaster.setFromCamera(this.mouse, this.camera); - - const intersects = this.raycaster.intersectObjects(this.objects); - if (intersects.length > 0) { - const intersect = intersects[0]; - - // delete cube - if (this.isShiftDown) { - if (intersect.object !== this.plane) { - this.scene.remove(intersect.object); - this.objects.splice(this.objects.indexOf(intersect.object), 1); - } - } else { - // create cube - const voxel = new THREE.Mesh(this.cubeGeo, this.cubeMaterial.clone()); - voxel.position.copy(intersect.point).add(intersect.face.normal); - voxel.position.divideScalar(50).floor().multiplyScalar(50).addScalar(25); - this.scene.add(voxel); - - this.objects.push(voxel); - } - this.render(); - } - } - - onDocumentKeyDown(event) { - switch (event.keyCode) { - case 16: this.isShiftDown = true; break; - } - } - - onDocumentKeyUp(event) { - switch (event.keyCode) { - case 16: this.isShiftDown = false; break; - } - } - render() { this.renderer.render(this.scene, this.camera); } diff --git a/src/fonts/Flaticon.eot b/src/fonts/Flaticon.eot new file mode 100644 index 0000000..67ccf30 Binary files /dev/null and b/src/fonts/Flaticon.eot differ diff --git a/src/fonts/Flaticon.svg b/src/fonts/Flaticon.svg new file mode 100644 index 0000000..a09317e --- /dev/null +++ b/src/fonts/Flaticon.svg @@ -0,0 +1,48 @@ + + + + diff --git a/src/fonts/Flaticon.ttf b/src/fonts/Flaticon.ttf new file mode 100644 index 0000000..1c4c1be Binary files /dev/null and b/src/fonts/Flaticon.ttf differ diff --git a/src/fonts/Flaticon.woff b/src/fonts/Flaticon.woff new file mode 100644 index 0000000..41bc485 Binary files /dev/null and b/src/fonts/Flaticon.woff differ diff --git a/src/fonts/Flaticon.woff2 b/src/fonts/Flaticon.woff2 new file mode 100644 index 0000000..3b1d80d Binary files /dev/null and b/src/fonts/Flaticon.woff2 differ diff --git a/src/index.css b/src/index.css deleted file mode 100644 index 30ccd43..0000000 --- a/src/index.css +++ /dev/null @@ -1,117 +0,0 @@ -/* GLOBAL */ - -html, body { - width: 100%; - height: 100%; -} - -.editor-layout { - width: 100%; - height: 100%; - display: flex; -} - -.editor-layout #editor { - width: 100%; -} - -.editor-layout #editor canvas { - outline: none; -} - -.brush-color-container { - padding: 0px 15px; -} - -.brush-color { - width: 20px; - height: 20px; - padding: 0; - border: 1px solid black; - margin: 5px; -} - -.brush-color.brown { - background-color: #800000; -} - -.brush-color.red { - background-color: #FF0000; -} - -.brush-color.black { - background-color: #000000; -} - -.brush-color.white { - background-color: #FFFFFF; -} - -.brush-color.yellow { - background-color: #FFFF00; -} - -.brush-color.lime { - background-color: #00FF00; -} - -.brush-color.green { - background-color: #008000; -} - -.brush-color.aqua { - background-color: #00FFFF; -} - -.brush-color.blue { - background-color: #0000FF; -} - -.brush-color.fuchsia { - background-color: #FF00FF; -} - -.brush-color.purple { - background-color: #800080; -} - -.brush-color.orange { - background-color: #FF8000; -} - -.brush-color-input { - margin: 20px 0px; -} - -/* (UI) LOADER */ - -.ui-loader { - position: fixed; - top: 0; - bottom: 0; - left: 0; - right: 0; - background-color: #191818; - color: #ffffff; - display: flex; - justify-content: center; - align-items: center; -} - -/* (UI) SIDEBAR */ - -.ui-sidebar { - width: 275px; - display: flex; - flex-direction: column; -} - -.ui-sidebar .pure-menu-list { - flex: 1; -} - -.ui-sidebar .ui-sidebar-guide-block { - padding: 10px; - font-size: 14px; - color: grey; -} diff --git a/src/index.html b/src/index.html index cadc533..d4b4497 100644 --- a/src/index.html +++ b/src/index.html @@ -5,10 +5,18 @@
-