├── .npmignore
├── .travis.yml
├── DOC-API.md
├── Gruntfile.js
├── LICENSE
├── README.md
├── browser.js
├── dist
├── aframe-border-component.js
└── aframe-border-component.min.js
├── examples
├── cdn-example
│ ├── img
│ │ ├── arrow-left-blue.png
│ │ ├── arrow-left-red.png
│ │ └── arrow-left.png
│ └── index.html
├── client-example
│ ├── img
│ │ ├── arrow-left-blue.png
│ │ ├── arrow-left-red.png
│ │ └── arrow-left.png
│ └── index.html
├── gif
│ └── border-demo.png
└── simple
│ ├── img
│ ├── arrow-left-blue.png
│ ├── arrow-left-red.png
│ └── arrow-left.png
│ └── index.html
├── modules
└── index.js
├── package.json
├── test
└── module
│ └── module-smoke-test.js
└── upcoming-info.json
/.npmignore:
--------------------------------------------------------------------------------
1 | Gruntfile.js
2 | test
3 | coverage
4 | example
5 | examples
6 | support
7 | .gitignore
8 | .travis.yml
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "stable"
4 | script:
5 | - npm run test-coverage
6 | after_success:
7 | - bash <(curl -s https://codecov.io/bash)
--------------------------------------------------------------------------------
/DOC-API.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## aframe-border-component
4 | Module
5 |
6 |
7 | * [aframe-border-component](#module_aframe-border-component)
8 | * [.schema](#module_aframe-border-component.schema)
9 | * [.Component()](#module_aframe-border-component.Component)
10 | * [.init()](#module_aframe-border-component.init)
11 |
12 |
13 |
14 | ### aframe-border-component.schema
15 | defines the attribute properties
16 |
17 | **Kind**: static property of [aframe-border-component](#module_aframe-border-component)
18 | **Object**:
19 |
20 |
21 | ### aframe-border-component.Component()
22 | Specification for registering a border component with Aframe
23 |
24 | **Kind**: static method of [aframe-border-component](#module_aframe-border-component)
25 | **Example** *(browserify example)*
26 | ```js
27 | var border = require('aframe-border-component');
28 | if (AFRAME.aframeCore) {
29 | AFRAME.aframeCore.registerComponent("border", border.Component);
30 | } else {
31 | AFRAME.registerComponent("border", border.Component);
32 | }
33 | ```
34 |
35 |
36 | ### aframe-border-component.init()
37 | Called once when component is attached. Generally for initial setup.
38 |
39 | **Kind**: static method of [aframe-border-component](#module_aframe-border-component)
40 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function (grunt) {
2 |
3 | grunt.loadNpmTasks('grunt-contrib-jshint');
4 | grunt.loadNpmTasks('grunt-bump');
5 | grunt.loadNpmTasks('grunt-shell');
6 | grunt.loadNpmTasks("grunt-browserify");
7 | grunt.loadNpmTasks('grunt-contrib-uglify');
8 | grunt.loadNpmTasks("grunt-contrib-watch");
9 | grunt.loadNpmTasks('grunt-jsdoc-to-markdown');
10 |
11 | grunt.initConfig({
12 |
13 | // used by the changelog task
14 | pkg: grunt.file.readJSON('package.json'),
15 |
16 | jshint: {
17 | options: {
18 | node: true
19 | },
20 | all: ['*.js','./modules/*.js']
21 | },
22 |
23 | shell: {
24 | publish: {
25 | command: 'npm publish'
26 | },
27 | pubinit: {
28 | // command: 'npm publish --access public'
29 | command: [
30 | 'npm publish --access public',
31 | 'git tag v0.1.0',
32 | 'git push origin --tags',
33 | ].join('&&')
34 | },
35 | },
36 |
37 | // To test: grunt bump --dry-run
38 |
39 | bump: {
40 | options: {
41 |
42 | commit: true,
43 | createTag: true,
44 | push: true,
45 | pushTo: 'origin',
46 |
47 | updateConfigs: ['pkg'],
48 | commitFiles: ['package.json']
49 | }
50 | },
51 |
52 |
53 | browserify: {
54 | dist: {
55 | options: {
56 | browserifyOptions: {
57 | // dashes will be converted to caps in actual name
58 | // i.e.: -test-zeta becomes TestZeta
59 | // standalone: 'MitchAllen.-aframe-border-component'
60 | // standalone: 'mitchallen.-aframe-border-component'
61 | },
62 | transform: [['babelify', {presets: ['es2015']}]],
63 | plugin: [[ "browserify-derequire" ]]
64 | },
65 | files: {
66 | // if the source file has an extension of es6 then
67 | // we change the name of the source file accordingly.
68 | // The result file's extension is always .js
69 | "./dist/aframe-border-component.js": ["./browser.js"]
70 | // For non-standalone, use ./browser.js instead.
71 | // "./dist/aframe-border-component.js": ["./browser.js"]
72 | }
73 | }
74 | },
75 |
76 | uglify: {
77 | my_target: {
78 | files: {
79 | './dist/aframe-border-component.min.js': ['./dist/aframe-border-component.js']
80 | }
81 | }
82 | },
83 |
84 | watch: {
85 | scripts: {
86 | files: ["./modules/*.js","./*.js"],
87 | tasks: ['jshint','browserify','uglify']
88 | }
89 | },
90 |
91 | jsdoc2md: {
92 | oneOutputFile: {
93 | src: 'modules/*.js',
94 | dest: 'DOC-API.md'
95 | }
96 | },
97 |
98 | upcoming: {
99 | default: {
100 | files: [
101 | { src: 'package.json', dest: ['upcoming-info.json'] }
102 | ]
103 | }
104 | }
105 |
106 | });
107 |
108 | grunt.loadNpmTasks('grunt-upcoming');
109 |
110 | grunt.registerTask('default', ['upcoming:patch','build']);
111 | grunt.registerTask("build", ['jshint','browserify','uglify']);
112 | grunt.registerTask('pubinit', ['build','shell:pubinit']);
113 | grunt.registerTask('publish', ['upcoming:patch','build','bump','shell:publish']);
114 | };
115 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright 2017 Mitch Allen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | aframe-border-component
2 | ==
3 | A component for creating borders in VR
4 | --
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | ## Browser Usage
29 |
30 | ### Live Example
31 |
32 | Here are some live examples of the component. The simpler demo is ideal for mobile.
33 |
34 | * https://mitchallen.bitbucket.io/border/index.html - best viewed in Chrome
35 | * https://mitchallen.bitbucket.io/border/simple.html - simpler demo for mobile
36 |
37 | Demo notes:
38 |
39 | * Works fine in Chrome on a Mac
40 | * Having issues with player falling through floor on iOS for complex demos (keep it simple on mobile)
41 | * On Windows 10 machine (Lenovo Yoga 710 laptop) can't seem to walk and turn at the same time
42 |
43 | * * *
44 |
45 | ### HTML Example
46 |
47 | Run this example in a browser (you'll need to add your own image files or get them from my repo). Step off the birds-eye view platform and wander around.
48 |
49 |
50 |
51 |
52 |
53 | simple aframe-border-component example
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
70 |
73 |
77 |
80 |
83 |
86 |
87 |
88 |
92 |
97 |
98 |
99 |
103 |
104 |
105 |
109 |
110 |
111 |
115 |
119 |
120 |
121 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | ### Include Script
134 |
135 | Include the latest script. Update the @version in the URL as needed:
136 |
137 |
138 |
139 | ### Define Assets
140 |
141 | Create an __a-assets__ section and add the following:
142 |
143 | * an __img__ to act as a material for the border
144 | * an entity, like __a-box__, __a-cylinder__ or __a-sphere__, to act as a border
145 |
146 | Be sure to give each entity unique __id__ attributes. They will be needed to define the border.
147 |
148 | The example below uses the __static-body__ component from __[aframe-extras](https://github.com/donmccurdy/aframe-extras)__ so the player can not go through the borders.
149 |
150 |
151 |
152 |
155 |
156 |
157 | You can also set the __rotation__ for an asset. It will rotate relative to it's position and rotation along the border.
158 |
159 | ### Create an Entity with a Border Component
160 |
161 | A __border__ component can consist of the following:
162 |
163 | * __sides__ - the number of sides to create for the border (__sides: 6;__)
164 | * __radius__ - the distance from the parent entity to create each border wall (__radius: 10;__)
165 | * __wall__ - the __id__ of the entity asset that will be used to create walls of the border (__wall: #wall-one;__)
166 | * __open__ - a zero-based list of border walls that can be opened (not drawn) to allow entering and exiting (__open: 0 2;__)
167 |
168 | Example border with no open walls:
169 |
170 |
173 |
174 | A border with open walls:
175 |
176 |
179 |
180 | ### Adding / Removing Through JavaScript
181 |
182 | An example of how to remove and add border attributes though JavaScript. The target element should be an __a-entity__.
183 |
184 |
190 |
191 | * * *
192 |
193 | ## NPM Installation
194 |
195 | $ npm init
196 | $ npm install aframe-border-component --save
197 |
198 | ### Browserify Example
199 |
200 | Below is an example of requiring the module within a file to be passed to browserify.
201 |
202 | The modules named export, __Component__, should be passed to __AFRAME.aframeCore.registerComponent__:
203 |
204 | // Browser distribution of the A-Frame component.
205 | (function () {
206 | if (typeof AFRAME === 'undefined') {
207 | console.error('Component attempted to register before AFRAME was available.');
208 | return;
209 | }
210 |
211 | var border = require('aframe-border-component');
212 |
213 | // Register all components here.
214 | var components = {
215 | "border": border.Component
216 | };
217 |
218 | var primitives = {
219 | };
220 |
221 | Object.keys(components).forEach(function (name) {
222 | if (AFRAME.aframeCore) {
223 | AFRAME.aframeCore.registerComponent(name, components[name]);
224 | } else {
225 | AFRAME.registerComponent(name, components[name]);
226 | }
227 | });
228 |
229 | Object.keys(primitives).forEach(function (name) {
230 | if (AFRAME.aframeCore) {
231 | AFRAME.aframeCore.registerPrimitive(name, primitives[name]);
232 | } else {
233 | AFRAME.registerPrimitive(name, primitives[name]);
234 | }
235 | });
236 |
237 | })();
238 |
239 | ### Build with grunt
240 |
241 | Use a [grunt](http://gruntjs.com/) task to build the distribution file:
242 |
243 | browserify: {
244 | dist: {
245 | options: {
246 | browserifyOptions: {
247 | // ...
248 | },
249 | transform: [['babelify', {presets: ['es2015']}]],
250 | plugin: [[ "browserify-derequire" ]]
251 | },
252 | files: {
253 | // substitute your component name for the distribution file
254 | "./dist/YOUR-COMPONENT.js": ["./browser.js"]
255 | }
256 | }
257 | },
258 |
259 | For more information, review the __Gruntfile.js__ and __package.json__ files in the root of this projects source code.
260 |
261 | * * *
262 |
263 | ## Testing
264 |
265 | To test, go to the root folder and type (sans __$__):
266 |
267 | $ npm test
268 |
269 | * * *
270 |
271 | ## Repo(s)
272 |
273 | * [bitbucket.org/mitchallen/aframe-border-component.git](https://bitbucket.org/mitchallen/aframe-border-component.git)
274 | * [github.com/mitchallen/aframe-border-component.git](https://github.com/mitchallen/aframe-border-component.git)
275 |
276 | * * *
277 |
278 | ## Contributing
279 |
280 | In lieu of a formal style guide, take care to maintain the existing coding style.
281 | Add unit tests for any new or changed functionality. Lint and test your code.
282 |
283 | * * *
284 |
285 | ## Version History
286 |
287 | #### Version 0.1.6
288 |
289 | * updated doc to point to demos in their new location on bitbucket
290 |
291 | #### Version 0.1.5
292 |
293 | * brought code coverage up to 100%
294 |
295 | #### Version 0.1.4
296 |
297 | * added logging of name and version to console
298 | * integrated travis-ci and codecov
299 |
300 | #### Version 0.1.3
301 |
302 | * code cleanup
303 | * added MIT license
304 | * updated examples to latest CDN
305 |
306 | #### Version 0.1.2
307 |
308 | * fixed / updated documentation
309 |
310 | #### Version 0.1.1
311 |
312 | * added cdn example
313 |
314 | #### Version 0.1.0
315 |
316 | * initial release
317 |
318 | * * *
319 |
--------------------------------------------------------------------------------
/browser.js:
--------------------------------------------------------------------------------
1 | // Browser distribution of the A-Frame component.
2 | (function () {
3 | if (typeof AFRAME === 'undefined') {
4 | console.error('Component attempted to register before AFRAME was available.');
5 | return;
6 | }
7 |
8 | var border = require('./modules/index');
9 |
10 | console.log( border.Component.name() + ": " + border.Component.version() );
11 |
12 | // Register all components here.
13 | var components = {
14 | "border": border.Component
15 | };
16 |
17 | var primitives = {
18 | };
19 |
20 | Object.keys(components).forEach(function (name) {
21 | if (AFRAME.aframeCore) {
22 | AFRAME.aframeCore.registerComponent(name, components[name]);
23 | } else {
24 | AFRAME.registerComponent(name, components[name]);
25 | }
26 | });
27 |
28 | Object.keys(primitives).forEach(function (name) {
29 | if (AFRAME.aframeCore) {
30 | AFRAME.aframeCore.registerPrimitive(name, primitives[name]);
31 | } else {
32 | AFRAME.registerPrimitive(name, primitives[name]);
33 | }
34 | });
35 |
36 | })();
--------------------------------------------------------------------------------
/dist/aframe-border-component.js:
--------------------------------------------------------------------------------
1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;obrowserify example
62 | * var border = require('aframe-border-component');
63 | * if (AFRAME.aframeCore) {
64 | * AFRAME.aframeCore.registerComponent("border", border.Component);
65 | * } else {
66 | * AFRAME.registerComponent("border", border.Component);
67 | * }
68 | */
69 | module.exports.Component = {
70 |
71 | version: function version() {
72 | return packageVersion;
73 | },
74 | name: function name() {
75 | return packageName;
76 | },
77 |
78 | dependencies: ['position', 'rotation'],
79 |
80 | /** defines the attribute properties
81 | * @Object
82 | * @memberof module:aframe-border-component
83 | */
84 |
85 | schema: {
86 | enabled: { default: true },
87 | sides: {
88 | type: 'int',
89 | default: 6
90 | },
91 | radius: {
92 | type: 'int',
93 | default: 10
94 | },
95 | open: {
96 | default: ""
97 | },
98 | wall: { default: "" }
99 | },
100 |
101 | /** Called once when component is attached. Generally for initial setup.
102 | * @function
103 | * @memberof module:aframe-border-component
104 | */
105 | init: function init() {
106 |
107 | this.borderData = {};
108 |
109 | var wallId = this.data.wall;
110 |
111 | wallId = wallId[0] == '#' ? wallId.substring(1) : wallId;
112 |
113 | var p = document.getElementById(wallId);
114 | if (p) {
115 | this.borderData.wallWidth = p.getAttribute("width");
116 | this.borderData.wallDepth = p.getAttribute("depth");
117 | this.borderData.wallHeight = p.getAttribute("height");
118 | this.borderData.wallRotation = p.getAttribute("rotation");
119 | } else {
120 | this.borderData.wallWidth = 4;
121 | this.borderData.wallDepth = 1;
122 | this.borderData.wallHeight = 1;
123 | this.borderData.wallRotation = { x: 0, y: 0, z: 0 };
124 | }
125 |
126 | this.borderData.openList = [];
127 |
128 | this.buildOpenList();
129 | },
130 |
131 | buildOpenList: function buildOpenList() {
132 | // build open border list
133 |
134 | var tokens = this.data.open.split(' ');
135 | for (var key in tokens) {
136 | var token = tokens[key];
137 | var i = parseInt(token, 10);
138 | if (!isNaN(i)) {
139 | if (i >= 0) {
140 | this.borderData.openList[i] = true;
141 | }
142 | }
143 | }
144 | },
145 |
146 | drawBorderWall: function drawBorderWall(spec) {
147 |
148 | spec = spec || {};
149 | var position = spec.position || { x: 0, y: 0, z: 0 },
150 | rotation = spec.rotation || { x: 0, y: 0, z: 0 },
151 | wallId = this.data.wall;
152 |
153 | wallId = wallId[0] == '#' ? wallId.substring(1) : wallId;
154 |
155 | var w = null;
156 | var p = document.getElementById(wallId);
157 | if (!p) {
158 | w = document.createElement('a-box');
159 | this.el.appendChild(w);
160 | w.setAttribute('color', 'tomato');
161 | w.setAttribute('width', this.borderData.wallWidth);
162 | w.setAttribute('depth', this.borderData.wallDepth);
163 | w.setAttribute('height', this.borderData.wallHeight);
164 | w.setAttribute('static-body', '');
165 | } else {
166 | w = p.cloneNode(true);
167 | this.el.appendChild(w);
168 | }
169 | w.setAttribute('rotation', rotation);
170 | w.setAttribute('position', position);
171 | },
172 |
173 | update: function update() {
174 | if (!this.data.enabled) {
175 | return;
176 | }
177 | var sides = this.data.sides,
178 | radius = this.data.radius;
179 |
180 | var WALL_WIDTH = this.borderData.wallWidth,
181 | WALL_DEPTH = this.borderData.wallDepth,
182 | WALL_HEIGHT = this.borderData.wallHeight,
183 | yPos = 0;
184 |
185 | var wallRotation = this.borderData.wallRotation;
186 |
187 | var step = 2 * Math.PI / sides,
188 | turn = 360 / sides;
189 | for (var i = 0, angle = 0; i < sides; i++, angle += step) {
190 |
191 | var xPos = radius * Math.cos(angle);
192 | var zPos = radius * Math.sin(angle);
193 |
194 | if (!this.borderData.openList[i]) {
195 |
196 | this.drawBorderWall({
197 | position: {
198 | x: xPos,
199 | y: 0,
200 | z: zPos
201 | },
202 | rotation: {
203 | x: wallRotation.x,
204 | y: wallRotation.y + 90 - i * turn,
205 | z: wallRotation.z
206 | }
207 | });
208 | }
209 | }
210 | },
211 |
212 | remove: function remove() {}
213 | };
214 |
215 | },{"../upcoming-info":3}],3:[function(_dereq_,module,exports){
216 | module.exports={"name":"aframe-border-component","version":"0.1.4","upcoming":{"release":"patch","version":"0.1.5"}}
217 | },{}]},{},[1]);
218 |
--------------------------------------------------------------------------------
/dist/aframe-border-component.min.js:
--------------------------------------------------------------------------------
1 | !function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g=0&&(this.borderData.openList[d]=!0)}},drawBorderWall:function(a){a=a||{};var b=a.position||{x:0,y:0,z:0},c=a.rotation||{x:0,y:0,z:0},d=this.data.wall;d="#"==d[0]?d.substring(1):d;var e=null,f=document.getElementById(d);f?(e=f.cloneNode(!0),this.el.appendChild(e)):(e=document.createElement("a-box"),this.el.appendChild(e),e.setAttribute("color","tomato"),e.setAttribute("width",this.borderData.wallWidth),e.setAttribute("depth",this.borderData.wallDepth),e.setAttribute("height",this.borderData.wallHeight),e.setAttribute("static-body","")),e.setAttribute("rotation",c),e.setAttribute("position",b)},update:function(){if(this.data.enabled)for(var a=this.data.sides,b=this.data.radius,c=(this.borderData.wallWidth,this.borderData.wallDepth,this.borderData.wallHeight,this.borderData.wallRotation),d=2*Math.PI/a,e=360/a,f=0,g=0;f
2 |
3 |
4 |
5 | simple aframe-border-component example
6 |
7 |
8 |
9 |
10 |
11 |
12 | -->
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
23 |
26 |
30 |
33 |
36 |
39 |
40 |
41 |
45 |
50 |
51 |
52 |
56 |
57 |
58 |
62 |
63 |
64 |
68 |
72 |
73 |
74 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/examples/client-example/img/arrow-left-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchallen/aframe-border-component/b582e83730b8c00ef85eede849be59442d7f3168/examples/client-example/img/arrow-left-blue.png
--------------------------------------------------------------------------------
/examples/client-example/img/arrow-left-red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchallen/aframe-border-component/b582e83730b8c00ef85eede849be59442d7f3168/examples/client-example/img/arrow-left-red.png
--------------------------------------------------------------------------------
/examples/client-example/img/arrow-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchallen/aframe-border-component/b582e83730b8c00ef85eede849be59442d7f3168/examples/client-example/img/arrow-left.png
--------------------------------------------------------------------------------
/examples/client-example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | aframe-border-component example
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
32 |
36 |
39 |
42 |
45 |
49 |
52 |
55 |
58 |
62 |
66 |
71 |
76 |
80 |
81 |
82 |
86 |
91 |
92 |
93 |
97 |
98 |
99 |
103 |
104 |
105 |
109 |
113 |
114 |
115 |
119 |
120 |
121 |
125 |
126 |
127 |
128 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
--------------------------------------------------------------------------------
/examples/gif/border-demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchallen/aframe-border-component/b582e83730b8c00ef85eede849be59442d7f3168/examples/gif/border-demo.png
--------------------------------------------------------------------------------
/examples/simple/img/arrow-left-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchallen/aframe-border-component/b582e83730b8c00ef85eede849be59442d7f3168/examples/simple/img/arrow-left-blue.png
--------------------------------------------------------------------------------
/examples/simple/img/arrow-left-red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchallen/aframe-border-component/b582e83730b8c00ef85eede849be59442d7f3168/examples/simple/img/arrow-left-red.png
--------------------------------------------------------------------------------
/examples/simple/img/arrow-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mitchallen/aframe-border-component/b582e83730b8c00ef85eede849be59442d7f3168/examples/simple/img/arrow-left.png
--------------------------------------------------------------------------------
/examples/simple/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | simple aframe-border-component example
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
31 |
34 |
38 |
41 |
44 |
47 |
48 |
49 |
53 |
58 |
59 |
60 |
64 |
65 |
66 |
70 |
71 |
72 |
76 |
80 |
81 |
82 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/modules/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | Module: @mitchallen/aframe-border-component
3 | Author: Mitch Allen
4 | */
5 | /*jshint browser: true */
6 | /*jshint node: true */
7 | /*jshint esversion: 6 */
8 |
9 |
10 | "use strict";
11 |
12 | /**
13 | * Module
14 | * @module aframe-border-component
15 | */
16 |
17 | var packageName = require("../upcoming-info").name,
18 | packageVersion = require("../upcoming-info").upcoming.version;
19 |
20 | /**
21 | * Specification for registering a border component with Aframe
22 | * @function
23 | * @example browserify example
24 | * var border = require('aframe-border-component');
25 | * if (AFRAME.aframeCore) {
26 | * AFRAME.aframeCore.registerComponent("border", border.Component);
27 | * } else {
28 | * AFRAME.registerComponent("border", border.Component);
29 | * }
30 | */
31 | module.exports.Component = {
32 |
33 | version: function() { return packageVersion; },
34 | name: function() { return packageName; },
35 |
36 | dependencies: ['position', 'rotation'],
37 |
38 | /** defines the attribute properties
39 | * @Object
40 | * @memberof module:aframe-border-component
41 | */
42 |
43 | schema: {
44 | enabled: { default: true },
45 | sides: {
46 | type: 'int',
47 | default: 6
48 | },
49 | radius: {
50 | type: 'int',
51 | default: 10
52 | },
53 | open: {
54 | default: ""
55 | },
56 | wall: { default: "" }
57 | },
58 |
59 | /** Called once when component is attached. Generally for initial setup.
60 | * @function
61 | * @memberof module:aframe-border-component
62 | */
63 | init: function () {
64 |
65 | this.borderData = {};
66 |
67 | var wallId = this.data.wall;
68 |
69 | wallId = wallId[0] == '#' ? wallId.substring(1) : wallId;
70 |
71 | var p = document.getElementById(wallId);
72 | if(p) {
73 | this.borderData.wallWidth = p.getAttribute("width");
74 | this.borderData.wallDepth = p.getAttribute("depth");
75 | this.borderData.wallHeight = p.getAttribute("height");
76 | this.borderData.wallRotation = p.getAttribute("rotation");
77 | } else {
78 | this.borderData.wallWidth = 4;
79 | this.borderData.wallDepth = 1;
80 | this.borderData.wallHeight = 1;
81 | this.borderData.wallRotation = { x: 0, y: 0, z: 0 };
82 | }
83 |
84 | this.borderData.openList = [];
85 |
86 | this.buildOpenList();
87 | },
88 |
89 | buildOpenList: function() {
90 | // build open border list
91 |
92 | var tokens = this.data.open.split(' ');
93 | for( var key in tokens ) {
94 | var token = tokens[key];
95 | var i = parseInt(token,10);
96 | if(!isNaN(i)) {
97 | if(i >= 0) {
98 | this.borderData.openList[i] = true;
99 | }
100 | }
101 | }
102 | },
103 |
104 | drawBorderWall: function(spec) {
105 |
106 | spec = spec || {};
107 | var position = spec.position || { x: 0, y: 0, z: 0 },
108 | rotation = spec.rotation || { x: 0, y: 0, z: 0 },
109 | wallId = this.data.wall;
110 |
111 | wallId = wallId[0] == '#' ? wallId.substring(1) : wallId;
112 |
113 | var w = null;
114 | var p = document.getElementById(wallId);
115 | if(!p) {
116 | w = document.createElement('a-box');
117 | this.el.appendChild(w);
118 | w.setAttribute('color', 'tomato' );
119 | w.setAttribute('width', this.borderData.wallWidth );
120 | w.setAttribute('depth', this.borderData.wallDepth );
121 | w.setAttribute('height', this.borderData.wallHeight );
122 | w.setAttribute('static-body', '');
123 | } else {
124 | w = p.cloneNode(true);
125 | this.el.appendChild(w);
126 | }
127 | w.setAttribute('rotation', rotation);
128 | w.setAttribute('position', position);
129 | },
130 |
131 | update: function () {
132 | if (!this.data.enabled) { return; }
133 | var sides = this.data.sides,
134 | radius = this.data.radius;
135 |
136 | var WALL_WIDTH = this.borderData.wallWidth,
137 | WALL_DEPTH = this.borderData.wallDepth,
138 | WALL_HEIGHT = this.borderData.wallHeight,
139 | yPos = 0;
140 |
141 | var wallRotation = this.borderData.wallRotation;
142 |
143 | var step = (2*Math.PI) / sides,
144 | turn = 360 / sides;
145 | for(var i = 0, angle = 0; i < sides; i++, angle += step) {
146 |
147 | var xPos = radius * Math.cos(angle);
148 | var zPos = radius * Math.sin(angle);
149 |
150 | if( !this.borderData.openList[i] ) {
151 |
152 | this.drawBorderWall({
153 | position: {
154 | x: xPos,
155 | y: 0,
156 | z: zPos
157 | },
158 | rotation: {
159 | x: wallRotation.x,
160 | y: wallRotation.y + 90 - i * turn,
161 | z: wallRotation.z
162 | }
163 | });
164 | }
165 | }
166 | },
167 |
168 | remove: function () {
169 | }
170 | };
171 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aframe-border-component",
3 | "version": "0.1.6",
4 | "description": "A component for creating borders in VR",
5 | "main": "modules/index.js",
6 | "scripts": {
7 | "//": "To use: npm run test-nodemon (assumes global location of mocha)",
8 | "start": "node dist/aframe-border-component.js",
9 | "test": "grunt && /usr/local/bin/mocha --recursive --timeout 20000",
10 | "test-coverage": "./node_modules/.bin/istanbul cover _mocha --recursive test/**/*",
11 | "test-nodemon": "nodemon /usr/local/bin/mocha --timeout 5000",
12 | "test-debug": "nodemon /usr/local/bin/mocha -g '@DEBUG' --recursive --timeout 20000",
13 | "test-jenkins": "grunt && /usr/local/bin/mocha --recursive --timeout 20000 -R xunit test/ > test-reports.xml",
14 | "web-server": "python -m SimpleHTTPServer $PORT || 8000"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "https://github.com/mitchallen/aframe-border-component.git"
19 | },
20 | "author": "Mitch Allen (http://mitchallen.com)",
21 | "license": "MIT",
22 | "dependencies": {},
23 | "devDependencies": {
24 | "babel-preset-es2015": "^6.18.0",
25 | "babelify": "^7.3.0",
26 | "browserify-derequire": "^0.9.4",
27 | "grunt": "^1.0.1",
28 | "grunt-browserify": "^5.0.0",
29 | "grunt-bump": "^0.8.0",
30 | "grunt-contrib-jshint": "^1.0.0",
31 | "grunt-contrib-uglify": "^2.0.0",
32 | "grunt-contrib-watch": "^1.0.0",
33 | "grunt-jsdoc-to-markdown": "^2.0.0",
34 | "grunt-shell": "^1.3.0",
35 | "grunt-upcoming": "^0.2.0",
36 | "istanbul": "^0.4.5",
37 | "mocha": "^3.2.0",
38 | "mockbot-document": "^0.1.14",
39 | "should": "^10.0.0",
40 | "supertest": "^2.0.0"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/test/module/module-smoke-test.js:
--------------------------------------------------------------------------------
1 | /**
2 | Module: @mitchallen/aframe-border-component
3 | Test: smoke-test-module
4 | Author: Mitch Allen
5 | */
6 |
7 | "use strict";
8 |
9 | var request = require('supertest'),
10 | should = require('should'),
11 | documentFactory = require("mockbot-document"),
12 | modulePath = "../../modules/index";
13 |
14 | describe('module smoke test', () => {
15 |
16 | var module = null;
17 |
18 | var component = {};
19 |
20 | before( done => {
21 | // Call before all tests
22 |
23 | // mock browser document
24 |
25 | global.document = documentFactory.create();
26 |
27 | document.mockElement( { tagName: "a-box", id: "wall-one" } );
28 |
29 | done();
30 | });
31 |
32 | after( done => {
33 | // Call after all tests
34 |
35 | delete global.document;
36 |
37 | done();
38 | });
39 |
40 | beforeEach( done => {
41 | // Call before each test
42 | delete require.cache[require.resolve(modulePath)];
43 | module = require(modulePath);
44 |
45 | component = module.Component;
46 | component.el = {
47 | appendChild: function(el) {},
48 | }
49 | component.data = {};
50 | // copy defaults from schema
51 | for(var k in component.schema) {
52 | var cType = component.schema[k].type;
53 | switch(cType) {
54 | default:
55 | component.data[k] = component.schema[k].default;
56 | break;
57 | }
58 | }
59 | done();
60 | });
61 |
62 | afterEach( done => {
63 | // Call after eeach test
64 | done();
65 | });
66 |
67 | it('module should exist', done => {
68 | should.exist(module);
69 | done();
70 | })
71 |
72 |
73 | it('Component should return component object', done => {
74 | should.exist(module);
75 | var component = module.Component;
76 | should.exist(component);
77 | done();
78 | })
79 |
80 | it('component.version should match upcoming version', done => {
81 | var component = module.Component;
82 | should.exist(component.version);
83 | console.log(component.version());
84 | component.version().should.eql(require("../../upcoming-info").upcoming.version);
85 | done();
86 | })
87 |
88 | it('component.name should match package name', done => {
89 | var component = module.Component;
90 | should.exist(component.name);
91 | console.log(component.name());
92 | component.name().should.eql(require("../../upcoming-info").name);
93 | done();
94 | })
95 |
96 | it('component init should succeed', done => {
97 | component.init();
98 | done();
99 | })
100 |
101 | it('component init should succeed for found wall element', done => {
102 | var wallId = "wall-one";
103 | var el = document.getElementById(wallId);
104 | should.exist(el);
105 | var w = el.getAttribute("width");
106 | component.data.wall = wallId;
107 | component.init();
108 | done();
109 | })
110 |
111 | it('component init should succeed for found wall element with pound sign starting name', done => {
112 | component.data.wall = "#wall-one";
113 | component.init();
114 | done();
115 | })
116 |
117 |
118 | it('component init should succeed for open data', done => {
119 | component.data.open = "N 0";
120 | component.init();
121 | done();
122 | })
123 |
124 | it('component init should succeed for open data has negative value', done => {
125 | component.data.open = "N -1";
126 | component.init();
127 | done();
128 | })
129 |
130 | it('component update should succeed', done => {
131 | component.init();
132 | component.update();
133 | done();
134 | })
135 |
136 | it('component update should succeed if enabled = false', done => {
137 | component.init();
138 | component.data.enabled = false;
139 | component.update();
140 | done();
141 | })
142 |
143 | it('component update with valid wall id should succeed', done => {
144 | component.init();
145 | component.data.wall = "#wall-one";
146 | component.update();
147 | done();
148 | })
149 |
150 | it('component update should succeed for found wall element', done => {
151 | component.data.wall = "wall-one";
152 | component.init();
153 | component.update();
154 | done();
155 | })
156 |
157 | it('component update should succeed for found wall element with pound sign starting name', done => {
158 | component.data.wall = "#wall-one";
159 | component.init();
160 | component.update();
161 | done();
162 | })
163 |
164 | it('component update should succeed for open data', done => {
165 | component.data.open = "N 0";
166 | component.init();
167 | component.update();
168 | done();
169 | })
170 |
171 | it('drawBorderWall with no spec should succeed', done => {
172 | component.init();
173 | component.drawBorderWall();
174 | done();
175 | })
176 |
177 | it('remove should succeed', done => {
178 | component.remove();
179 | done();
180 | })
181 |
182 | it('remove after init should succeed', done => {
183 | component.init();
184 | component.remove();
185 | done();
186 | })
187 |
188 | it('remove after update should succeed', done => {
189 | component.init();
190 | component.update();
191 | component.remove();
192 | done();
193 | })
194 | });
195 |
--------------------------------------------------------------------------------
/upcoming-info.json:
--------------------------------------------------------------------------------
1 | {"name":"aframe-border-component","version":"0.1.4","upcoming":{"release":"patch","version":"0.1.5"}}
--------------------------------------------------------------------------------