├── .gitignore
├── Landscape.rscd
├── README.md
├── css
├── light.css
└── main.css
├── img
├── 11.png
├── 11v.png
├── 14.png
├── 14v.png
├── 3221.png
├── 3222.png
├── 3222v.png
├── 3222vw.png
├── 3222w.png
├── 3223.png
├── 3226.png
├── 3230.png
├── 3230v.png
├── 3241.png
├── 3241v.png
├── 3241vw.png
├── 3241w.png
├── 3243.png
├── 3243v.png
├── 35.bmp
├── 35v.bmp
├── 42.png
├── 42v.png
├── 6.png
├── 6v.png
├── 7.bmp
└── 7v.bmp
├── index.html
├── js
├── CanvasRenderer.js
├── OrbitControls.js
├── Projector.js
├── TrackballControls.js
├── dat.gui.js
├── jszip-utils.js
├── jszip.js
├── stats.js
├── three.js
├── ui.js
└── ui.three.js
└── src
├── Editor.js
├── Materials.js
├── Tile.js
├── Util.js
└── ui
├── Menubar.Edit.js
├── Menubar.File.js
├── Menubar.Sector.js
├── Menubar.js
├── Sidebar.EditMode.js
├── Sidebar.Settings.js
├── Sidebar.ViewMode.js
├── Sidebar.js
└── Toolbar.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/modules.xml
2 | .idea/vcs.xml
3 | *.xml
4 | .idea/Starter.iml
--------------------------------------------------------------------------------
/Landscape.rscd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/Landscape.rscd
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RSC-Landscape-Editor-HTML5
2 | A 3D Landscape Editor for RuneScape Classic using WebGL/HTML5
3 |
4 | You will need to host these files under a web server, due to HTML5's permissions of reading local files
5 |
6 | 
7 |
8 | Credits to Fish for helping.
9 |
--------------------------------------------------------------------------------
/css/light.css:
--------------------------------------------------------------------------------
1 | .Outliner {
2 | color: #444;
3 | background: #fff;
4 | padding: 0;
5 | width: 100%;
6 | height: 140px;
7 | font-size: 12px;
8 | cursor: default;
9 | overflow: auto;
10 | outline: none;
11 | }
12 |
13 | .Outliner .option {
14 | padding: 4px;
15 | color: #666;
16 | white-space: nowrap;
17 | }
18 |
19 | .Outliner .option:hover {
20 | background-color: rgba(0,0,0,0.02);
21 | }
22 |
23 | .Outliner .option.active {
24 | background-color: rgba(0,0,0,0.04);
25 | }
26 |
27 | input.Number {
28 | color: #0080f0!important;
29 | font-size: 12px;
30 | border: 0px;
31 | padding: 2px;
32 | cursor: col-resize;
33 | }
34 |
35 | #viewport {
36 | position: absolute;
37 | top: 32px;
38 | left: 0;
39 | right: 300px;
40 | bottom: 32px;
41 | }
42 |
43 | #viewport #info {
44 | text-shadow: 1px 1px 0 rgba(0,0,0,0.25);
45 | pointer-events: none;
46 | }
47 |
48 | #script {
49 | position: absolute;
50 | top: 32px;
51 | left: 0;
52 | right: 300px;
53 | bottom: 32px;
54 | opacity: 0.9;
55 | }
56 |
57 | #player {
58 | position: absolute;
59 | top: 32px;
60 | left: 0;
61 | right: 300px;
62 | bottom: 32px;
63 | }
64 |
65 | #menubar {
66 | position: absolute;
67 | width: 100%;
68 | height: 32px;
69 | background: #eee;
70 | padding: 0;
71 | margin: 0;
72 | right: 0;
73 | top: 0;
74 | }
75 |
76 | #menubar .menu {
77 | float: left;
78 | cursor: pointer;
79 | padding-right: 8px;
80 | }
81 |
82 | #menubar .menu.right {
83 | float: right;
84 | cursor: auto;
85 | padding-right: 0;
86 | text-align: right;
87 | }
88 |
89 | #menubar .menu .title {
90 | display: inline-block;
91 | color: #888;
92 | margin: 0;
93 | padding: 8px;
94 | }
95 |
96 | #menubar .menu .options {
97 | position: absolute;
98 | display: none;
99 | padding: 5px 0;
100 | background: #eee;
101 | width: 150px;
102 | }
103 |
104 | #menubar .menu:hover .options {
105 | display: block;
106 | }
107 |
108 | #menubar .menu .options hr {
109 | border-color: #ddd;
110 | }
111 |
112 | #menubar .menu .options .option {
113 | color: #666;
114 | background-color: transparent;
115 | padding: 5px 10px;
116 | margin: 0 !important;
117 | }
118 |
119 | #menubar .menu .options .option:hover {
120 | color: #fff;
121 | background-color: #08f;
122 | }
123 |
124 | #menubar .menu .options .option:active {
125 | color: #666;
126 | background: transparent;
127 | }
128 |
129 | #menubar .menu .options .inactive {
130 | color: #bbb;
131 | background-color: transparent;
132 | padding: 5px 10px;
133 | margin: 0 !important;
134 | }
135 |
136 | #sidebar {
137 | position: absolute;
138 | right: 0;
139 | top: 32px;
140 | bottom: 0;
141 | width: 300px;
142 | background: #eee;
143 | overflow: auto;
144 | }
145 |
146 | #sidebar * {
147 | vertical-align: middle;
148 | }
149 |
150 | #sidebar input,
151 | #sidebar textarea,
152 | #sidebar select {
153 | border: 1px solid transparent;
154 | color: #444;
155 | }
156 |
157 | #sidebar .Panel {
158 | color: #888;
159 | padding: 10px;
160 | border-top: 1px solid #ccc;
161 | }
162 |
163 | #sidebar .Panel.collapsed {
164 | margin-bottom: 0;
165 | }
166 |
167 | #sidebar .Row {
168 | min-height: 20px;
169 | margin-bottom: 10px;
170 | }
171 |
172 | #tabs {
173 | background-color: #ddd;
174 | border-top: 1px solid #ccc;
175 | }
176 |
177 | #tabs span {
178 | color: #aaa;
179 | border-right: 1px solid #ccc;
180 | padding: 10px;
181 | }
182 |
183 | #tabs span.selected {
184 | color: #888;
185 | background-color: #eee;
186 | }
187 |
188 | #toolbar {
189 | position: absolute;
190 | left: 0;
191 | right: 300px;
192 | bottom: 0;
193 | height: 32px;
194 | background: #eee;
195 | color: #333;
196 | }
197 |
198 | #toolbar * {
199 | vertical-align: middle;
200 | }
201 |
202 | #toolbar .Panel {
203 | padding: 4px;
204 | color: #888;
205 | }
206 |
207 | #toolbar button {
208 | margin-right: 6px;
209 | }
210 |
--------------------------------------------------------------------------------
/css/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: Helvetica, Arial, sans-serif;
3 | font-size: 14px;
4 | margin: 0;
5 | overflow: hidden;
6 | }
7 |
8 | hr {
9 | border: 0;
10 | border-top: 1px solid #ccc;
11 | }
12 |
13 | button {
14 | position: relative;
15 | }
16 |
17 | textarea {
18 | tab-size: 4;
19 | white-space: pre;
20 | word-wrap: normal;
21 | }
22 |
23 | textarea.success {
24 | border-color: #8b8 !important;
25 | }
26 |
27 | textarea.fail {
28 | border-color: #f00 !important;
29 | background-color: rgba(255,0,0,0.05);
30 | }
31 |
32 | textarea, input { outline: none; } /* osx */
33 |
34 | .Panel {
35 | -moz-user-select: none;
36 | -webkit-user-select: none;
37 | -ms-user-select: none;
38 |
39 | /* No support for these yet */
40 | -o-user-select: none;
41 | user-select: none;
42 | }
43 |
44 | .Panel.Collapsible .Static {
45 | margin: 0;
46 | }
47 |
48 | .Panel.Collapsible .Static .Button {
49 | float: left;
50 | margin-right: 6px;
51 | width: 0;
52 | height: 0;
53 | border: 6px solid transparent;
54 | }
55 |
56 | .Panel.Collapsible.collapsed .Static .Button {
57 | margin-top: 2px;
58 | border-left-color: #bbb;
59 | }
60 |
61 | .Panel.Collapsible:not(.collapsed) .Static .Button {
62 | margin-top: 6px;
63 | border-top-color: #bbb;
64 | }
65 |
66 | .Panel.Collapsible.collapsed .Content {
67 | display: none;
68 | }
69 |
70 | /* CodeMirror */
71 |
72 | .CodeMirror {
73 |
74 | position: absolute !important;
75 | top: 37px;
76 | width: 100% !important;
77 | height: calc(100% - 37px) !important;
78 |
79 | }
80 |
81 | .CodeMirror .errorLine {
82 |
83 | background: rgba(255,0,0,0.25);
84 |
85 | }
86 |
87 | .CodeMirror .esprima-error {
88 |
89 | color: #f00;
90 | text-align: right;
91 | padding: 0 20px;
92 |
93 | }
94 |
95 | /* outliner */
96 |
97 | #outliner .option {
98 |
99 | border: 1px solid transparent;
100 | }
101 |
102 | #outliner .option.drag {
103 |
104 | border: 1px dashed #999;
105 |
106 | }
107 |
108 | #outliner .option.dragTop {
109 |
110 | border-top: 1px dashed #999;
111 |
112 | }
113 |
114 | #outliner .option.dragBottom {
115 |
116 | border-bottom: 1px dashed #999;
117 |
118 | }
119 |
120 | #outliner .type {
121 | position:relative;
122 | top:-2px;
123 | padding: 0 2px;
124 | color: #ddd;
125 | }
126 |
127 | #outliner .type:after {
128 | content: '■';
129 | }
130 |
131 | #outliner .Scene {
132 | color: #ccccff;
133 | }
134 |
135 | #outliner .Object3D {
136 | color: #aaaaee;
137 | }
138 |
139 | #outliner .Mesh {
140 | color: #8888ee;
141 | }
142 |
143 | #outliner .Line {
144 | color: #88ee88;
145 | }
146 |
147 | #outliner .LineSegments {
148 | color: #88ee88;
149 | }
150 |
151 | #outliner .Points {
152 | color: #ee8888;
153 | }
154 |
155 | /* */
156 |
157 | #outliner .PointLight {
158 | color: #dddd00;
159 | }
160 |
161 | /* */
162 |
163 | #outliner .Geometry {
164 | color: #88ff88;
165 | }
166 |
167 | #outliner .BoxGeometry {
168 | color: #bbeebb;
169 | }
170 |
171 | #outliner .TorusGeometry {
172 | color: #aaeeaa;
173 | }
174 |
175 | /* */
176 |
177 | #outliner .Material {
178 | color: #ff8888;
179 | }
180 |
181 | #outliner .MeshPhongMaterial {
182 | color: #ffaa88;
183 | }
184 |
185 | /* */
186 |
187 | #outliner .Script:after {
188 | content: '{...}' /* ❮/❯ */
189 | }
190 |
--------------------------------------------------------------------------------
/img/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/11.png
--------------------------------------------------------------------------------
/img/11v.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/11v.png
--------------------------------------------------------------------------------
/img/14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/14.png
--------------------------------------------------------------------------------
/img/14v.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/14v.png
--------------------------------------------------------------------------------
/img/3221.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3221.png
--------------------------------------------------------------------------------
/img/3222.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3222.png
--------------------------------------------------------------------------------
/img/3222v.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3222v.png
--------------------------------------------------------------------------------
/img/3222vw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3222vw.png
--------------------------------------------------------------------------------
/img/3222w.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3222w.png
--------------------------------------------------------------------------------
/img/3223.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3223.png
--------------------------------------------------------------------------------
/img/3226.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3226.png
--------------------------------------------------------------------------------
/img/3230.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3230.png
--------------------------------------------------------------------------------
/img/3230v.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3230v.png
--------------------------------------------------------------------------------
/img/3241.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3241.png
--------------------------------------------------------------------------------
/img/3241v.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3241v.png
--------------------------------------------------------------------------------
/img/3241vw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3241vw.png
--------------------------------------------------------------------------------
/img/3241w.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3241w.png
--------------------------------------------------------------------------------
/img/3243.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3243.png
--------------------------------------------------------------------------------
/img/3243v.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/3243v.png
--------------------------------------------------------------------------------
/img/35.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/35.bmp
--------------------------------------------------------------------------------
/img/35v.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/35v.bmp
--------------------------------------------------------------------------------
/img/42.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/42.png
--------------------------------------------------------------------------------
/img/42v.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/42v.png
--------------------------------------------------------------------------------
/img/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/6.png
--------------------------------------------------------------------------------
/img/6v.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/6v.png
--------------------------------------------------------------------------------
/img/7.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/7.bmp
--------------------------------------------------------------------------------
/img/7v.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unravl/RSC-Landscape-Editor-HTML5/cca5b1f9f7da15ede04fb645d845c28bf1372d05/img/7v.bmp
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Editor
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/js/CanvasRenderer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author mrdoob / http://mrdoob.com/
3 | */
4 |
5 | THREE.SpriteCanvasMaterial = function ( parameters ) {
6 |
7 | THREE.Material.call( this );
8 |
9 | this.type = 'SpriteCanvasMaterial';
10 |
11 | this.color = new THREE.Color( 0xffffff );
12 | this.program = function ( context, color ) {};
13 |
14 | this.setValues( parameters );
15 |
16 | };
17 |
18 | THREE.SpriteCanvasMaterial.prototype = Object.create( THREE.Material.prototype );
19 | THREE.SpriteCanvasMaterial.prototype.constructor = THREE.SpriteCanvasMaterial;
20 |
21 | THREE.SpriteCanvasMaterial.prototype.clone = function () {
22 |
23 | var material = new THREE.SpriteCanvasMaterial();
24 |
25 | material.copy( this );
26 | material.color.copy( this.color );
27 | material.program = this.program;
28 |
29 | return material;
30 |
31 | };
32 |
33 | //
34 |
35 | THREE.CanvasRenderer = function ( parameters ) {
36 |
37 | console.log( 'THREE.CanvasRenderer', THREE.REVISION );
38 |
39 | parameters = parameters || {};
40 |
41 | var _this = this,
42 | _renderData, _elements, _lights,
43 | _projector = new THREE.Projector(),
44 |
45 | _canvas = parameters.canvas !== undefined
46 | ? parameters.canvas
47 | : document.createElement( 'canvas' ),
48 |
49 | _canvasWidth = _canvas.width,
50 | _canvasHeight = _canvas.height,
51 | _canvasWidthHalf = Math.floor( _canvasWidth / 2 ),
52 | _canvasHeightHalf = Math.floor( _canvasHeight / 2 ),
53 |
54 | _viewportX = 0,
55 | _viewportY = 0,
56 | _viewportWidth = _canvasWidth,
57 | _viewportHeight = _canvasHeight,
58 |
59 | _pixelRatio = 1,
60 |
61 | _context = _canvas.getContext( '2d', {
62 | alpha: parameters.alpha === true
63 | } ),
64 |
65 | _clearColor = new THREE.Color( 0x000000 ),
66 | _clearAlpha = parameters.alpha === true ? 0 : 1,
67 |
68 | _contextGlobalAlpha = 1,
69 | _contextGlobalCompositeOperation = 0,
70 | _contextStrokeStyle = null,
71 | _contextFillStyle = null,
72 | _contextLineWidth = null,
73 | _contextLineCap = null,
74 | _contextLineJoin = null,
75 | _contextLineDash = [],
76 |
77 | _camera,
78 |
79 | _v1, _v2, _v3, _v4,
80 | _v5 = new THREE.RenderableVertex(),
81 | _v6 = new THREE.RenderableVertex(),
82 |
83 | _v1x, _v1y, _v2x, _v2y, _v3x, _v3y,
84 | _v4x, _v4y, _v5x, _v5y, _v6x, _v6y,
85 |
86 | _color = new THREE.Color(),
87 | _color1 = new THREE.Color(),
88 | _color2 = new THREE.Color(),
89 | _color3 = new THREE.Color(),
90 | _color4 = new THREE.Color(),
91 |
92 | _diffuseColor = new THREE.Color(),
93 | _emissiveColor = new THREE.Color(),
94 |
95 | _lightColor = new THREE.Color(),
96 |
97 | _patterns = {},
98 |
99 | _image, _uvs,
100 | _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y,
101 |
102 | _clipBox = new THREE.Box2(),
103 | _clearBox = new THREE.Box2(),
104 | _elemBox = new THREE.Box2(),
105 |
106 | _ambientLight = new THREE.Color(),
107 | _directionalLights = new THREE.Color(),
108 | _pointLights = new THREE.Color(),
109 |
110 | _vector3 = new THREE.Vector3(), // Needed for PointLight
111 | _centroid = new THREE.Vector3(),
112 | _normal = new THREE.Vector3(),
113 | _normalViewMatrix = new THREE.Matrix3();
114 |
115 | /* TODO
116 | _canvas.mozImageSmoothingEnabled = false;
117 | _canvas.webkitImageSmoothingEnabled = false;
118 | _canvas.msImageSmoothingEnabled = false;
119 | _canvas.imageSmoothingEnabled = false;
120 | */
121 |
122 | // dash+gap fallbacks for Firefox and everything else
123 |
124 | if ( _context.setLineDash === undefined ) {
125 |
126 | _context.setLineDash = function () {};
127 |
128 | }
129 |
130 | this.domElement = _canvas;
131 |
132 | this.autoClear = true;
133 | this.sortObjects = true;
134 | this.sortElements = true;
135 |
136 | this.info = {
137 |
138 | render: {
139 |
140 | vertices: 0,
141 | faces: 0
142 |
143 | }
144 |
145 | };
146 |
147 | // WebGLRenderer compatibility
148 |
149 | this.supportsVertexTextures = function () {};
150 | this.setFaceCulling = function () {};
151 |
152 | // API
153 |
154 | this.getContext = function () {
155 |
156 | return _context;
157 |
158 | };
159 |
160 | this.getContextAttributes = function () {
161 |
162 | return _context.getContextAttributes();
163 |
164 | };
165 |
166 | this.getPixelRatio = function () {
167 |
168 | return _pixelRatio;
169 |
170 | };
171 |
172 | this.setPixelRatio = function ( value ) {
173 |
174 | if ( value !== undefined ) _pixelRatio = value;
175 |
176 | };
177 |
178 | this.setSize = function ( width, height, updateStyle ) {
179 |
180 | _canvasWidth = width * _pixelRatio;
181 | _canvasHeight = height * _pixelRatio;
182 |
183 | _canvas.width = _canvasWidth;
184 | _canvas.height = _canvasHeight;
185 |
186 | _canvasWidthHalf = Math.floor( _canvasWidth / 2 );
187 | _canvasHeightHalf = Math.floor( _canvasHeight / 2 );
188 |
189 | if ( updateStyle !== false ) {
190 |
191 | _canvas.style.width = width + 'px';
192 | _canvas.style.height = height + 'px';
193 |
194 | }
195 |
196 | _clipBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf );
197 | _clipBox.max.set( _canvasWidthHalf, _canvasHeightHalf );
198 |
199 | _clearBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf );
200 | _clearBox.max.set( _canvasWidthHalf, _canvasHeightHalf );
201 |
202 | _contextGlobalAlpha = 1;
203 | _contextGlobalCompositeOperation = 0;
204 | _contextStrokeStyle = null;
205 | _contextFillStyle = null;
206 | _contextLineWidth = null;
207 | _contextLineCap = null;
208 | _contextLineJoin = null;
209 |
210 | this.setViewport( 0, 0, width, height );
211 |
212 | };
213 |
214 | this.setViewport = function ( x, y, width, height ) {
215 |
216 | _viewportX = x * _pixelRatio;
217 | _viewportY = y * _pixelRatio;
218 |
219 | _viewportWidth = width * _pixelRatio;
220 | _viewportHeight = height * _pixelRatio;
221 |
222 | };
223 |
224 | this.setScissor = function () {};
225 | this.setScissorTest = function () {};
226 |
227 | this.setClearColor = function ( color, alpha ) {
228 |
229 | _clearColor.set( color );
230 | _clearAlpha = alpha !== undefined ? alpha : 1;
231 |
232 | _clearBox.min.set( - _canvasWidthHalf, - _canvasHeightHalf );
233 | _clearBox.max.set( _canvasWidthHalf, _canvasHeightHalf );
234 |
235 | };
236 |
237 | this.setClearColorHex = function ( hex, alpha ) {
238 |
239 | console.warn( 'THREE.CanvasRenderer: .setClearColorHex() is being removed. Use .setClearColor() instead.' );
240 | this.setClearColor( hex, alpha );
241 |
242 | };
243 |
244 | this.getClearColor = function () {
245 |
246 | return _clearColor;
247 |
248 | };
249 |
250 | this.getClearAlpha = function () {
251 |
252 | return _clearAlpha;
253 |
254 | };
255 |
256 | this.getMaxAnisotropy = function () {
257 |
258 | return 0;
259 |
260 | };
261 |
262 | this.clear = function () {
263 |
264 | if ( _clearBox.isEmpty() === false ) {
265 |
266 | _clearBox.intersect( _clipBox );
267 | _clearBox.expandByScalar( 2 );
268 |
269 | _clearBox.min.x = _clearBox.min.x + _canvasWidthHalf;
270 | _clearBox.min.y = - _clearBox.min.y + _canvasHeightHalf; // higher y value !
271 | _clearBox.max.x = _clearBox.max.x + _canvasWidthHalf;
272 | _clearBox.max.y = - _clearBox.max.y + _canvasHeightHalf; // lower y value !
273 |
274 | if ( _clearAlpha < 1 ) {
275 |
276 | _context.clearRect(
277 | _clearBox.min.x | 0,
278 | _clearBox.max.y | 0,
279 | ( _clearBox.max.x - _clearBox.min.x ) | 0,
280 | ( _clearBox.min.y - _clearBox.max.y ) | 0
281 | );
282 |
283 | }
284 |
285 | if ( _clearAlpha > 0 ) {
286 |
287 | setBlending( THREE.NormalBlending );
288 | setOpacity( 1 );
289 |
290 | setFillStyle( 'rgba(' + Math.floor( _clearColor.r * 255 ) + ',' + Math.floor( _clearColor.g * 255 ) + ',' + Math.floor( _clearColor.b * 255 ) + ',' + _clearAlpha + ')' );
291 |
292 | _context.fillRect(
293 | _clearBox.min.x | 0,
294 | _clearBox.max.y | 0,
295 | ( _clearBox.max.x - _clearBox.min.x ) | 0,
296 | ( _clearBox.min.y - _clearBox.max.y ) | 0
297 | );
298 |
299 | }
300 |
301 | _clearBox.makeEmpty();
302 |
303 | }
304 |
305 | };
306 |
307 | // compatibility
308 |
309 | this.clearColor = function () {};
310 | this.clearDepth = function () {};
311 | this.clearStencil = function () {};
312 |
313 | this.render = function ( scene, camera ) {
314 |
315 | if ( camera instanceof THREE.Camera === false ) {
316 |
317 | console.error( 'THREE.CanvasRenderer.render: camera is not an instance of THREE.Camera.' );
318 | return;
319 |
320 | }
321 |
322 | if ( this.autoClear === true ) this.clear();
323 |
324 | _this.info.render.vertices = 0;
325 | _this.info.render.faces = 0;
326 |
327 | _context.setTransform( _viewportWidth / _canvasWidth, 0, 0, - _viewportHeight / _canvasHeight, _viewportX, _canvasHeight - _viewportY );
328 | _context.translate( _canvasWidthHalf, _canvasHeightHalf );
329 |
330 | _renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements );
331 | _elements = _renderData.elements;
332 | _lights = _renderData.lights;
333 | _camera = camera;
334 |
335 | _normalViewMatrix.getNormalMatrix( camera.matrixWorldInverse );
336 |
337 | /* DEBUG
338 | setFillStyle( 'rgba( 0, 255, 255, 0.5 )' );
339 | _context.fillRect( _clipBox.min.x, _clipBox.min.y, _clipBox.max.x - _clipBox.min.x, _clipBox.max.y - _clipBox.min.y );
340 | */
341 |
342 | calculateLights();
343 |
344 | for ( var e = 0, el = _elements.length; e < el; e ++ ) {
345 |
346 | var element = _elements[ e ];
347 |
348 | var material = element.material;
349 |
350 | if ( material === undefined || material.opacity === 0 ) continue;
351 |
352 | _elemBox.makeEmpty();
353 |
354 | if ( element instanceof THREE.RenderableSprite ) {
355 |
356 | _v1 = element;
357 | _v1.x *= _canvasWidthHalf; _v1.y *= _canvasHeightHalf;
358 |
359 | renderSprite( _v1, element, material );
360 |
361 | } else if ( element instanceof THREE.RenderableLine ) {
362 |
363 | _v1 = element.v1; _v2 = element.v2;
364 |
365 | _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
366 | _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
367 |
368 | _elemBox.setFromPoints( [
369 | _v1.positionScreen,
370 | _v2.positionScreen
371 | ] );
372 |
373 | if ( _clipBox.intersectsBox( _elemBox ) === true ) {
374 |
375 | renderLine( _v1, _v2, element, material );
376 |
377 | }
378 |
379 | } else if ( element instanceof THREE.RenderableFace ) {
380 |
381 | _v1 = element.v1; _v2 = element.v2; _v3 = element.v3;
382 |
383 | if ( _v1.positionScreen.z < - 1 || _v1.positionScreen.z > 1 ) continue;
384 | if ( _v2.positionScreen.z < - 1 || _v2.positionScreen.z > 1 ) continue;
385 | if ( _v3.positionScreen.z < - 1 || _v3.positionScreen.z > 1 ) continue;
386 |
387 | _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
388 | _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
389 | _v3.positionScreen.x *= _canvasWidthHalf; _v3.positionScreen.y *= _canvasHeightHalf;
390 |
391 | if ( material.overdraw > 0 ) {
392 |
393 | expand( _v1.positionScreen, _v2.positionScreen, material.overdraw );
394 | expand( _v2.positionScreen, _v3.positionScreen, material.overdraw );
395 | expand( _v3.positionScreen, _v1.positionScreen, material.overdraw );
396 |
397 | }
398 |
399 | _elemBox.setFromPoints( [
400 | _v1.positionScreen,
401 | _v2.positionScreen,
402 | _v3.positionScreen
403 | ] );
404 |
405 | if ( _clipBox.intersectsBox( _elemBox ) === true ) {
406 |
407 | renderFace3( _v1, _v2, _v3, 0, 1, 2, element, material );
408 |
409 | }
410 |
411 | }
412 |
413 | /* DEBUG
414 | setLineWidth( 1 );
415 | setStrokeStyle( 'rgba( 0, 255, 0, 0.5 )' );
416 | _context.strokeRect( _elemBox.min.x, _elemBox.min.y, _elemBox.max.x - _elemBox.min.x, _elemBox.max.y - _elemBox.min.y );
417 | */
418 |
419 | _clearBox.union( _elemBox );
420 |
421 | }
422 |
423 | /* DEBUG
424 | setLineWidth( 1 );
425 | setStrokeStyle( 'rgba( 255, 0, 0, 0.5 )' );
426 | _context.strokeRect( _clearBox.min.x, _clearBox.min.y, _clearBox.max.x - _clearBox.min.x, _clearBox.max.y - _clearBox.min.y );
427 | */
428 |
429 | _context.setTransform( 1, 0, 0, 1, 0, 0 );
430 |
431 | };
432 |
433 | //
434 |
435 | function calculateLights() {
436 |
437 | _ambientLight.setRGB( 0, 0, 0 );
438 | _directionalLights.setRGB( 0, 0, 0 );
439 | _pointLights.setRGB( 0, 0, 0 );
440 |
441 | for ( var l = 0, ll = _lights.length; l < ll; l ++ ) {
442 |
443 | var light = _lights[ l ];
444 | var lightColor = light.color;
445 |
446 | if ( light instanceof THREE.AmbientLight ) {
447 |
448 | _ambientLight.add( lightColor );
449 |
450 | } else if ( light instanceof THREE.DirectionalLight ) {
451 |
452 | // for sprites
453 |
454 | _directionalLights.add( lightColor );
455 |
456 | } else if ( light instanceof THREE.PointLight ) {
457 |
458 | // for sprites
459 |
460 | _pointLights.add( lightColor );
461 |
462 | }
463 |
464 | }
465 |
466 | }
467 |
468 | function calculateLight( position, normal, color ) {
469 |
470 | for ( var l = 0, ll = _lights.length; l < ll; l ++ ) {
471 |
472 | var light = _lights[ l ];
473 |
474 | _lightColor.copy( light.color );
475 |
476 | if ( light instanceof THREE.DirectionalLight ) {
477 |
478 | var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ).normalize();
479 |
480 | var amount = normal.dot( lightPosition );
481 |
482 | if ( amount <= 0 ) continue;
483 |
484 | amount *= light.intensity;
485 |
486 | color.add( _lightColor.multiplyScalar( amount ) );
487 |
488 | } else if ( light instanceof THREE.PointLight ) {
489 |
490 | var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld );
491 |
492 | var amount = normal.dot( _vector3.subVectors( lightPosition, position ).normalize() );
493 |
494 | if ( amount <= 0 ) continue;
495 |
496 | amount *= light.distance == 0 ? 1 : 1 - Math.min( position.distanceTo( lightPosition ) / light.distance, 1 );
497 |
498 | if ( amount == 0 ) continue;
499 |
500 | amount *= light.intensity;
501 |
502 | color.add( _lightColor.multiplyScalar( amount ) );
503 |
504 | }
505 |
506 | }
507 |
508 | }
509 |
510 | function renderSprite( v1, element, material ) {
511 |
512 | setOpacity( material.opacity );
513 | setBlending( material.blending );
514 |
515 | var scaleX = element.scale.x * _canvasWidthHalf;
516 | var scaleY = element.scale.y * _canvasHeightHalf;
517 |
518 | var dist = 0.5 * Math.sqrt( scaleX * scaleX + scaleY * scaleY ); // allow for rotated sprite
519 | _elemBox.min.set( v1.x - dist, v1.y - dist );
520 | _elemBox.max.set( v1.x + dist, v1.y + dist );
521 |
522 | if ( material instanceof THREE.SpriteMaterial ) {
523 |
524 | var texture = material.map;
525 |
526 | if ( texture !== null ) {
527 |
528 | var pattern = _patterns[ texture.id ];
529 |
530 | if ( pattern === undefined || pattern.version !== texture.version ) {
531 |
532 | pattern = textureToPattern( texture );
533 | _patterns[ texture.id ] = pattern;
534 |
535 | }
536 |
537 | if ( pattern.canvas !== undefined ) {
538 |
539 | setFillStyle( pattern.canvas );
540 |
541 | var bitmap = texture.image;
542 |
543 | var ox = bitmap.width * texture.offset.x;
544 | var oy = bitmap.height * texture.offset.y;
545 |
546 | var sx = bitmap.width * texture.repeat.x;
547 | var sy = bitmap.height * texture.repeat.y;
548 |
549 | var cx = scaleX / sx;
550 | var cy = scaleY / sy;
551 |
552 | _context.save();
553 | _context.translate( v1.x, v1.y );
554 | if ( material.rotation !== 0 ) _context.rotate( material.rotation );
555 | _context.translate( - scaleX / 2, - scaleY / 2 );
556 | _context.scale( cx, cy );
557 | _context.translate( - ox, - oy );
558 | _context.fillRect( ox, oy, sx, sy );
559 | _context.restore();
560 |
561 | }
562 |
563 | } else {
564 |
565 | // no texture
566 |
567 | setFillStyle( material.color.getStyle() );
568 |
569 | _context.save();
570 | _context.translate( v1.x, v1.y );
571 | if ( material.rotation !== 0 ) _context.rotate( material.rotation );
572 | _context.scale( scaleX, - scaleY );
573 | _context.fillRect( - 0.5, - 0.5, 1, 1 );
574 | _context.restore();
575 |
576 | }
577 |
578 | } else if ( material instanceof THREE.SpriteCanvasMaterial ) {
579 |
580 | setStrokeStyle( material.color.getStyle() );
581 | setFillStyle( material.color.getStyle() );
582 |
583 | _context.save();
584 | _context.translate( v1.x, v1.y );
585 | if ( material.rotation !== 0 ) _context.rotate( material.rotation );
586 | _context.scale( scaleX, scaleY );
587 |
588 | material.program( _context );
589 |
590 | _context.restore();
591 |
592 | }
593 |
594 | /* DEBUG
595 | setStrokeStyle( 'rgb(255,255,0)' );
596 | _context.beginPath();
597 | _context.moveTo( v1.x - 10, v1.y );
598 | _context.lineTo( v1.x + 10, v1.y );
599 | _context.moveTo( v1.x, v1.y - 10 );
600 | _context.lineTo( v1.x, v1.y + 10 );
601 | _context.stroke();
602 | */
603 |
604 | }
605 |
606 | function renderLine( v1, v2, element, material ) {
607 |
608 | setOpacity( material.opacity );
609 | setBlending( material.blending );
610 |
611 | _context.beginPath();
612 | _context.moveTo( v1.positionScreen.x, v1.positionScreen.y );
613 | _context.lineTo( v2.positionScreen.x, v2.positionScreen.y );
614 |
615 | if ( material instanceof THREE.LineBasicMaterial ) {
616 |
617 | setLineWidth( material.linewidth );
618 | setLineCap( material.linecap );
619 | setLineJoin( material.linejoin );
620 |
621 | if ( material.vertexColors !== THREE.VertexColors ) {
622 |
623 | setStrokeStyle( material.color.getStyle() );
624 |
625 | } else {
626 |
627 | var colorStyle1 = element.vertexColors[ 0 ].getStyle();
628 | var colorStyle2 = element.vertexColors[ 1 ].getStyle();
629 |
630 | if ( colorStyle1 === colorStyle2 ) {
631 |
632 | setStrokeStyle( colorStyle1 );
633 |
634 | } else {
635 |
636 | try {
637 |
638 | var grad = _context.createLinearGradient(
639 | v1.positionScreen.x,
640 | v1.positionScreen.y,
641 | v2.positionScreen.x,
642 | v2.positionScreen.y
643 | );
644 | grad.addColorStop( 0, colorStyle1 );
645 | grad.addColorStop( 1, colorStyle2 );
646 |
647 | } catch ( exception ) {
648 |
649 | grad = colorStyle1;
650 |
651 | }
652 |
653 | setStrokeStyle( grad );
654 |
655 | }
656 |
657 | }
658 |
659 | _context.stroke();
660 | _elemBox.expandByScalar( material.linewidth * 2 );
661 |
662 | } else if ( material instanceof THREE.LineDashedMaterial ) {
663 |
664 | setLineWidth( material.linewidth );
665 | setLineCap( material.linecap );
666 | setLineJoin( material.linejoin );
667 | setStrokeStyle( material.color.getStyle() );
668 | setLineDash( [ material.dashSize, material.gapSize ] );
669 |
670 | _context.stroke();
671 |
672 | _elemBox.expandByScalar( material.linewidth * 2 );
673 |
674 | setLineDash( [] );
675 |
676 | }
677 |
678 | }
679 |
680 | function renderFace3( v1, v2, v3, uv1, uv2, uv3, element, material ) {
681 |
682 | _this.info.render.vertices += 3;
683 | _this.info.render.faces ++;
684 |
685 | setOpacity( material.opacity );
686 | setBlending( material.blending );
687 |
688 | _v1x = v1.positionScreen.x; _v1y = v1.positionScreen.y;
689 | _v2x = v2.positionScreen.x; _v2y = v2.positionScreen.y;
690 | _v3x = v3.positionScreen.x; _v3y = v3.positionScreen.y;
691 |
692 | drawTriangle( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y );
693 |
694 | if ( ( material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial ) && material.map === null ) {
695 |
696 | _diffuseColor.copy( material.color );
697 | _emissiveColor.copy( material.emissive );
698 |
699 | if ( material.vertexColors === THREE.FaceColors ) {
700 |
701 | _diffuseColor.multiply( element.color );
702 |
703 | }
704 |
705 | _color.copy( _ambientLight );
706 |
707 | _centroid.copy( v1.positionWorld ).add( v2.positionWorld ).add( v3.positionWorld ).divideScalar( 3 );
708 |
709 | calculateLight( _centroid, element.normalModel, _color );
710 |
711 | _color.multiply( _diffuseColor ).add( _emissiveColor );
712 |
713 | material.wireframe === true
714 | ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
715 | : fillPath( _color );
716 |
717 | } else if ( material instanceof THREE.MeshBasicMaterial ||
718 | material instanceof THREE.MeshLambertMaterial ||
719 | material instanceof THREE.MeshPhongMaterial ) {
720 |
721 | if ( material.map !== null ) {
722 |
723 | var mapping = material.map.mapping;
724 |
725 | if ( mapping === THREE.UVMapping ) {
726 |
727 | _uvs = element.uvs;
728 | patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uvs[ uv1 ].x, _uvs[ uv1 ].y, _uvs[ uv2 ].x, _uvs[ uv2 ].y, _uvs[ uv3 ].x, _uvs[ uv3 ].y, material.map );
729 |
730 | }
731 |
732 | } else if ( material.envMap !== null ) {
733 |
734 | if ( material.envMap.mapping === THREE.SphericalReflectionMapping ) {
735 |
736 | _normal.copy( element.vertexNormalsModel[ uv1 ] ).applyMatrix3( _normalViewMatrix );
737 | _uv1x = 0.5 * _normal.x + 0.5;
738 | _uv1y = 0.5 * _normal.y + 0.5;
739 |
740 | _normal.copy( element.vertexNormalsModel[ uv2 ] ).applyMatrix3( _normalViewMatrix );
741 | _uv2x = 0.5 * _normal.x + 0.5;
742 | _uv2y = 0.5 * _normal.y + 0.5;
743 |
744 | _normal.copy( element.vertexNormalsModel[ uv3 ] ).applyMatrix3( _normalViewMatrix );
745 | _uv3x = 0.5 * _normal.x + 0.5;
746 | _uv3y = 0.5 * _normal.y + 0.5;
747 |
748 | patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap );
749 |
750 | }
751 |
752 | } else {
753 |
754 | _color.copy( material.color );
755 |
756 | if ( material.vertexColors === THREE.FaceColors ) {
757 |
758 | _color.multiply( element.color );
759 |
760 | }
761 |
762 | material.wireframe === true
763 | ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
764 | : fillPath( _color );
765 |
766 | }
767 |
768 | } else if ( material instanceof THREE.MeshNormalMaterial ) {
769 |
770 | _normal.copy( element.normalModel ).applyMatrix3( _normalViewMatrix );
771 |
772 | _color.setRGB( _normal.x, _normal.y, _normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 );
773 |
774 | material.wireframe === true
775 | ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
776 | : fillPath( _color );
777 |
778 | } else {
779 |
780 | _color.setRGB( 1, 1, 1 );
781 |
782 | material.wireframe === true
783 | ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
784 | : fillPath( _color );
785 |
786 | }
787 |
788 | }
789 |
790 | //
791 |
792 | function drawTriangle( x0, y0, x1, y1, x2, y2 ) {
793 |
794 | _context.beginPath();
795 | _context.moveTo( x0, y0 );
796 | _context.lineTo( x1, y1 );
797 | _context.lineTo( x2, y2 );
798 | _context.closePath();
799 |
800 | }
801 |
802 | function strokePath( color, linewidth, linecap, linejoin ) {
803 |
804 | setLineWidth( linewidth );
805 | setLineCap( linecap );
806 | setLineJoin( linejoin );
807 | setStrokeStyle( color.getStyle() );
808 |
809 | _context.stroke();
810 |
811 | _elemBox.expandByScalar( linewidth * 2 );
812 |
813 | }
814 |
815 | function fillPath( color ) {
816 |
817 | setFillStyle( color.getStyle() );
818 | _context.fill();
819 |
820 | }
821 |
822 | function textureToPattern( texture ) {
823 |
824 | if ( texture.version === 0 ||
825 | texture instanceof THREE.CompressedTexture ||
826 | texture instanceof THREE.DataTexture ) {
827 |
828 | return {
829 | canvas: undefined,
830 | version: texture.version
831 | };
832 |
833 | }
834 |
835 | var image = texture.image;
836 |
837 | if ( image.complete === false ) {
838 |
839 | return {
840 | canvas: undefined,
841 | version: 0
842 | };
843 |
844 | }
845 |
846 | var canvas = document.createElement( 'canvas' );
847 | canvas.width = image.width;
848 | canvas.height = image.height;
849 |
850 | var context = canvas.getContext( '2d' );
851 | context.setTransform( 1, 0, 0, - 1, 0, image.height );
852 | context.drawImage( image, 0, 0 );
853 |
854 | var repeatX = texture.wrapS === THREE.RepeatWrapping;
855 | var repeatY = texture.wrapT === THREE.RepeatWrapping;
856 |
857 | var repeat = 'no-repeat';
858 |
859 | if ( repeatX === true && repeatY === true ) {
860 |
861 | repeat = 'repeat';
862 |
863 | } else if ( repeatX === true ) {
864 |
865 | repeat = 'repeat-x';
866 |
867 | } else if ( repeatY === true ) {
868 |
869 | repeat = 'repeat-y';
870 |
871 | }
872 |
873 | var pattern = _context.createPattern( canvas, repeat );
874 |
875 | if ( texture.onUpdate ) texture.onUpdate( texture );
876 |
877 | return {
878 | canvas: pattern,
879 | version: texture.version
880 | };
881 |
882 | }
883 |
884 | function patternPath( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, texture ) {
885 |
886 | var pattern = _patterns[ texture.id ];
887 |
888 | if ( pattern === undefined || pattern.version !== texture.version ) {
889 |
890 | pattern = textureToPattern( texture );
891 | _patterns[ texture.id ] = pattern;
892 |
893 | }
894 |
895 | if ( pattern.canvas !== undefined ) {
896 |
897 | setFillStyle( pattern.canvas );
898 |
899 | } else {
900 |
901 | setFillStyle( 'rgba( 0, 0, 0, 1)' );
902 | _context.fill();
903 | return;
904 |
905 | }
906 |
907 | // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
908 |
909 | var a, b, c, d, e, f, det, idet,
910 | offsetX = texture.offset.x / texture.repeat.x,
911 | offsetY = texture.offset.y / texture.repeat.y,
912 | width = texture.image.width * texture.repeat.x,
913 | height = texture.image.height * texture.repeat.y;
914 |
915 | u0 = ( u0 + offsetX ) * width;
916 | v0 = ( v0 + offsetY ) * height;
917 |
918 | u1 = ( u1 + offsetX ) * width;
919 | v1 = ( v1 + offsetY ) * height;
920 |
921 | u2 = ( u2 + offsetX ) * width;
922 | v2 = ( v2 + offsetY ) * height;
923 |
924 | x1 -= x0; y1 -= y0;
925 | x2 -= x0; y2 -= y0;
926 |
927 | u1 -= u0; v1 -= v0;
928 | u2 -= u0; v2 -= v0;
929 |
930 | det = u1 * v2 - u2 * v1;
931 |
932 | if ( det === 0 ) return;
933 |
934 | idet = 1 / det;
935 |
936 | a = ( v2 * x1 - v1 * x2 ) * idet;
937 | b = ( v2 * y1 - v1 * y2 ) * idet;
938 | c = ( u1 * x2 - u2 * x1 ) * idet;
939 | d = ( u1 * y2 - u2 * y1 ) * idet;
940 |
941 | e = x0 - a * u0 - c * v0;
942 | f = y0 - b * u0 - d * v0;
943 |
944 | _context.save();
945 | _context.transform( a, b, c, d, e, f );
946 | _context.fill();
947 | _context.restore();
948 |
949 | }
950 |
951 | function clipImage( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, image ) {
952 |
953 | // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
954 |
955 | var a, b, c, d, e, f, det, idet,
956 | width = image.width - 1,
957 | height = image.height - 1;
958 |
959 | u0 *= width; v0 *= height;
960 | u1 *= width; v1 *= height;
961 | u2 *= width; v2 *= height;
962 |
963 | x1 -= x0; y1 -= y0;
964 | x2 -= x0; y2 -= y0;
965 |
966 | u1 -= u0; v1 -= v0;
967 | u2 -= u0; v2 -= v0;
968 |
969 | det = u1 * v2 - u2 * v1;
970 |
971 | idet = 1 / det;
972 |
973 | a = ( v2 * x1 - v1 * x2 ) * idet;
974 | b = ( v2 * y1 - v1 * y2 ) * idet;
975 | c = ( u1 * x2 - u2 * x1 ) * idet;
976 | d = ( u1 * y2 - u2 * y1 ) * idet;
977 |
978 | e = x0 - a * u0 - c * v0;
979 | f = y0 - b * u0 - d * v0;
980 |
981 | _context.save();
982 | _context.transform( a, b, c, d, e, f );
983 | _context.clip();
984 | _context.drawImage( image, 0, 0 );
985 | _context.restore();
986 |
987 | }
988 |
989 | // Hide anti-alias gaps
990 |
991 | function expand( v1, v2, pixels ) {
992 |
993 | var x = v2.x - v1.x, y = v2.y - v1.y,
994 | det = x * x + y * y, idet;
995 |
996 | if ( det === 0 ) return;
997 |
998 | idet = pixels / Math.sqrt( det );
999 |
1000 | x *= idet; y *= idet;
1001 |
1002 | v2.x += x; v2.y += y;
1003 | v1.x -= x; v1.y -= y;
1004 |
1005 | }
1006 |
1007 | // Context cached methods.
1008 |
1009 | function setOpacity( value ) {
1010 |
1011 | if ( _contextGlobalAlpha !== value ) {
1012 |
1013 | _context.globalAlpha = value;
1014 | _contextGlobalAlpha = value;
1015 |
1016 | }
1017 |
1018 | }
1019 |
1020 | function setBlending( value ) {
1021 |
1022 | if ( _contextGlobalCompositeOperation !== value ) {
1023 |
1024 | if ( value === THREE.NormalBlending ) {
1025 |
1026 | _context.globalCompositeOperation = 'source-over';
1027 |
1028 | } else if ( value === THREE.AdditiveBlending ) {
1029 |
1030 | _context.globalCompositeOperation = 'lighter';
1031 |
1032 | } else if ( value === THREE.SubtractiveBlending ) {
1033 |
1034 | _context.globalCompositeOperation = 'darker';
1035 |
1036 | } else if ( value === THREE.MultiplyBlending ) {
1037 |
1038 | _context.globalCompositeOperation = 'multiply';
1039 |
1040 | }
1041 |
1042 | _contextGlobalCompositeOperation = value;
1043 |
1044 | }
1045 |
1046 | }
1047 |
1048 | function setLineWidth( value ) {
1049 |
1050 | if ( _contextLineWidth !== value ) {
1051 |
1052 | _context.lineWidth = value;
1053 | _contextLineWidth = value;
1054 |
1055 | }
1056 |
1057 | }
1058 |
1059 | function setLineCap( value ) {
1060 |
1061 | // "butt", "round", "square"
1062 |
1063 | if ( _contextLineCap !== value ) {
1064 |
1065 | _context.lineCap = value;
1066 | _contextLineCap = value;
1067 |
1068 | }
1069 |
1070 | }
1071 |
1072 | function setLineJoin( value ) {
1073 |
1074 | // "round", "bevel", "miter"
1075 |
1076 | if ( _contextLineJoin !== value ) {
1077 |
1078 | _context.lineJoin = value;
1079 | _contextLineJoin = value;
1080 |
1081 | }
1082 |
1083 | }
1084 |
1085 | function setStrokeStyle( value ) {
1086 |
1087 | if ( _contextStrokeStyle !== value ) {
1088 |
1089 | _context.strokeStyle = value;
1090 | _contextStrokeStyle = value;
1091 |
1092 | }
1093 |
1094 | }
1095 |
1096 | function setFillStyle( value ) {
1097 |
1098 | if ( _contextFillStyle !== value ) {
1099 |
1100 | _context.fillStyle = value;
1101 | _contextFillStyle = value;
1102 |
1103 | }
1104 |
1105 | }
1106 |
1107 | function setLineDash( value ) {
1108 |
1109 | if ( _contextLineDash.length !== value.length ) {
1110 |
1111 | _context.setLineDash( value );
1112 | _contextLineDash = value;
1113 |
1114 | }
1115 |
1116 | }
1117 |
1118 | };
--------------------------------------------------------------------------------
/js/OrbitControls.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author qiao / https://github.com/qiao
3 | * @author mrdoob / http://mrdoob.com
4 | * @author alteredq / http://alteredqualia.com/
5 | * @author WestLangley / http://github.com/WestLangley
6 | * @author erich666 / http://erichaines.com
7 | * @author mrflix / http://felixniklas.de
8 | *
9 | * released under MIT License (MIT)
10 | */
11 | /*global THREE, console */
12 |
13 | // This set of controls performs orbiting, dollying (zooming), and panning. It maintains
14 | // the "up" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is
15 | // supported.
16 | //
17 | // Orbit - left mouse / touch: one finger move
18 | // Zoom - middle mouse, or mousewheel / touch: two finger spread or squish
19 | // Pan - right mouse, or arrow keys / touch: three finter swipe
20 | //
21 | // This is a drop-in replacement for (most) TrackballControls used in examples.
22 | // That is, include this js file and wherever you see:
23 | // controls = new THREE.TrackballControls( camera );
24 | // controls.target.z = 150;
25 | // Simple substitute "OrbitControls" and the control should work as-is.
26 |
27 | THREE.OrbitControls = function ( object, domElement, localElement ) {
28 |
29 | this.object = object;
30 | this.domElement = ( domElement !== undefined ) ? domElement : document;
31 | this.localElement = ( localElement !== undefined ) ? localElement : document;
32 |
33 | // API
34 |
35 | // Set to false to disable this control
36 | this.enabled = true;
37 |
38 | // "target" sets the location of focus, where the control orbits around
39 | // and where it pans with respect to.
40 | this.target = new THREE.Vector3();
41 | // center is old, deprecated; use "target" instead
42 | this.center = this.target;
43 |
44 | // This option actually enables dollying in and out; left as "zoom" for
45 | // backwards compatibility
46 | this.noZoom = false;
47 | this.zoomSpeed = 1.0;
48 | // Limits to how far you can dolly in and out
49 | this.minDistance = 0;
50 | this.maxDistance = Infinity;
51 |
52 | // Set to true to disable this control
53 | this.noRotate = false;
54 | this.rotateSpeed = 1.0;
55 |
56 | // Set to true to disable this control
57 | this.noPan = false;
58 | this.keyPanSpeed = 7.0; // pixels moved per arrow key push
59 |
60 | // Set to true to automatically rotate around the target
61 | this.autoRotate = false;
62 | this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
63 |
64 | // How far you can orbit vertically, upper and lower limits.
65 | // Range is 0 to Math.PI radians.
66 | this.minPolarAngle = 0; // radians
67 | this.maxPolarAngle = Math.PI; // radians
68 |
69 | // Set to true to disable use of the keys
70 | this.noKeys = false;
71 | // The four arrow keys
72 | this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
73 |
74 | ////////////
75 | // internals
76 |
77 | var scope = this;
78 |
79 | var EPS = 0.000001;
80 |
81 | var rotateStart = new THREE.Vector2();
82 | var rotateEnd = new THREE.Vector2();
83 | var rotateDelta = new THREE.Vector2();
84 |
85 | var panStart = new THREE.Vector2();
86 | var panEnd = new THREE.Vector2();
87 | var panDelta = new THREE.Vector2();
88 |
89 | var dollyStart = new THREE.Vector2();
90 | var dollyEnd = new THREE.Vector2();
91 | var dollyDelta = new THREE.Vector2();
92 |
93 | var phiDelta = 0;
94 | var thetaDelta = 0;
95 | var scale = 1;
96 | var pan = new THREE.Vector3();
97 |
98 | var lastPosition = new THREE.Vector3();
99 |
100 | var STATE = { NONE : -1, ROTATE : 0, DOLLY : 1, PAN : 2, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5 };
101 | var state = STATE.NONE;
102 |
103 | // events
104 |
105 | var changeEvent = { type: 'change' };
106 |
107 |
108 | this.rotateLeft = function ( angle ) {
109 |
110 | if ( angle === undefined ) {
111 |
112 | angle = getAutoRotationAngle();
113 |
114 | }
115 |
116 | thetaDelta -= angle;
117 |
118 | };
119 |
120 | this.rotateUp = function ( angle ) {
121 |
122 | if ( angle === undefined ) {
123 |
124 | angle = getAutoRotationAngle();
125 |
126 | }
127 |
128 | phiDelta -= angle;
129 |
130 | };
131 |
132 | // pass in distance in world space to move left
133 | this.panLeft = function ( distance ) {
134 |
135 | var panOffset = new THREE.Vector3();
136 | var te = this.object.matrix.elements;
137 | // get X column of matrix
138 | panOffset.set( te[0], te[1], te[2] );
139 | panOffset.multiplyScalar(-distance);
140 |
141 | pan.add( panOffset );
142 |
143 | };
144 |
145 | // pass in distance in world space to move up
146 | this.panUp = function ( distance ) {
147 |
148 | var panOffset = new THREE.Vector3();
149 | var te = this.object.matrix.elements;
150 | // get Y column of matrix
151 | panOffset.set( te[4], te[5], te[6] );
152 | panOffset.multiplyScalar(distance);
153 |
154 | pan.add( panOffset );
155 | };
156 |
157 | // main entry point; pass in Vector2 of change desired in pixel space,
158 | // right and down are positive
159 | this.pan = function ( delta ) {
160 |
161 | var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
162 |
163 | if ( scope.object.fov !== undefined ) {
164 |
165 | // perspective
166 | var position = scope.object.position;
167 | var offset = position.clone().sub( scope.target );
168 | var targetDistance = offset.length();
169 |
170 | // half of the fov is center to top of screen
171 | targetDistance *= Math.tan( (scope.object.fov/2) * Math.PI / 180.0 );
172 | // we actually don't use screenWidth, since perspective camera is fixed to screen height
173 | scope.panLeft( 2 * delta.x * targetDistance / element.clientHeight );
174 | scope.panUp( 2 * delta.y * targetDistance / element.clientHeight );
175 |
176 | } else if ( scope.object.top !== undefined ) {
177 |
178 | // orthographic
179 | scope.panLeft( delta.x * (scope.object.right - scope.object.left) / element.clientWidth );
180 | scope.panUp( delta.y * (scope.object.top - scope.object.bottom) / element.clientHeight );
181 |
182 | } else {
183 |
184 | // camera neither orthographic or perspective - warn user
185 | console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
186 |
187 | }
188 |
189 | };
190 |
191 | this.dollyIn = function ( dollyScale ) {
192 |
193 | if ( dollyScale === undefined ) {
194 |
195 | dollyScale = getZoomScale();
196 |
197 | }
198 |
199 | scale /= dollyScale;
200 |
201 | };
202 |
203 | this.dollyOut = function ( dollyScale ) {
204 |
205 | if ( dollyScale === undefined ) {
206 |
207 | dollyScale = getZoomScale();
208 |
209 | }
210 |
211 | scale *= dollyScale;
212 |
213 | };
214 |
215 | this.update = function () {
216 |
217 | var position = this.object.position;
218 | var offset = position.clone().sub( this.target );
219 |
220 | // angle from z-axis around y-axis
221 |
222 | var theta = Math.atan2( offset.x, offset.z );
223 |
224 | // angle from y-axis
225 |
226 | var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
227 |
228 | if ( this.autoRotate ) {
229 |
230 | this.rotateLeft( getAutoRotationAngle() );
231 |
232 | }
233 |
234 | theta += thetaDelta;
235 | phi += phiDelta;
236 |
237 | // restrict phi to be between desired limits
238 | phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
239 |
240 | // restrict phi to be betwee EPS and PI-EPS
241 | phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
242 |
243 | var radius = offset.length() * scale;
244 |
245 | // restrict radius to be between desired limits
246 | radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );
247 |
248 | // move target to panned location
249 | this.target.add( pan );
250 |
251 | offset.x = radius * Math.sin( phi ) * Math.sin( theta );
252 | offset.y = radius * Math.cos( phi );
253 | offset.z = radius * Math.sin( phi ) * Math.cos( theta );
254 |
255 | position.copy( this.target ).add( offset );
256 |
257 | this.object.lookAt( this.target );
258 |
259 | thetaDelta = 0;
260 | phiDelta = 0;
261 | scale = 1;
262 | pan.set(0,0,0);
263 |
264 | if ( lastPosition.distanceTo( this.object.position ) > 0 ) {
265 |
266 | this.dispatchEvent( changeEvent );
267 |
268 | lastPosition.copy( this.object.position );
269 |
270 | }
271 |
272 | };
273 |
274 |
275 | function getAutoRotationAngle() {
276 |
277 | return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
278 |
279 | }
280 |
281 | function getZoomScale() {
282 |
283 | return Math.pow( 0.95, scope.zoomSpeed );
284 |
285 | }
286 |
287 | function onMouseDown( event ) {
288 |
289 | if ( scope.enabled === false ) { return; }
290 | event.preventDefault();
291 |
292 | if ( event.button === 0 ) {
293 | if ( scope.noRotate === true ) { return; }
294 |
295 | state = STATE.ROTATE;
296 |
297 | rotateStart.set( event.clientX, event.clientY );
298 |
299 | } else if ( event.button === 1 ) {
300 | if ( scope.noZoom === true ) { return; }
301 |
302 | state = STATE.DOLLY;
303 |
304 | dollyStart.set( event.clientX, event.clientY );
305 |
306 | } else if ( event.button === 2 ) {
307 | if ( scope.noPan === true ) { return; }
308 |
309 | state = STATE.PAN;
310 |
311 | panStart.set( event.clientX, event.clientY );
312 |
313 | }
314 |
315 | // Greggman fix: https://github.com/greggman/three.js/commit/fde9f9917d6d8381f06bf22cdff766029d1761be
316 | scope.domElement.addEventListener( 'mousemove', onMouseMove, false );
317 | scope.domElement.addEventListener( 'mouseup', onMouseUp, false );
318 |
319 | }
320 |
321 | function onMouseMove( event ) {
322 |
323 | if ( scope.enabled === false ) return;
324 |
325 | event.preventDefault();
326 |
327 | var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
328 |
329 | if ( state === STATE.ROTATE ) {
330 |
331 | if ( scope.noRotate === true ) return;
332 |
333 | rotateEnd.set( event.clientX, event.clientY );
334 | rotateDelta.subVectors( rotateEnd, rotateStart );
335 |
336 | // rotating across whole screen goes 360 degrees around
337 | scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
338 | // rotating up and down along whole screen attempts to go 360, but limited to 180
339 | scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
340 |
341 | rotateStart.copy( rotateEnd );
342 |
343 | } else if ( state === STATE.DOLLY ) {
344 |
345 | if ( scope.noZoom === true ) return;
346 |
347 | dollyEnd.set( event.clientX, event.clientY );
348 | dollyDelta.subVectors( dollyEnd, dollyStart );
349 |
350 | if ( dollyDelta.y > 0 ) {
351 |
352 | scope.dollyIn();
353 |
354 | } else {
355 |
356 | scope.dollyOut();
357 |
358 | }
359 |
360 | dollyStart.copy( dollyEnd );
361 |
362 | } else if ( state === STATE.PAN ) {
363 |
364 | if ( scope.noPan === true ) return;
365 |
366 | panEnd.set( event.clientX, event.clientY );
367 | panDelta.subVectors( panEnd, panStart );
368 |
369 | scope.pan( panDelta );
370 |
371 | panStart.copy( panEnd );
372 |
373 | }
374 |
375 | // Greggman fix: https://github.com/greggman/three.js/commit/fde9f9917d6d8381f06bf22cdff766029d1761be
376 | scope.update();
377 |
378 | }
379 |
380 | function onMouseUp( /* event */ ) {
381 |
382 | if ( scope.enabled === false ) return;
383 |
384 | // Greggman fix: https://github.com/greggman/three.js/commit/fde9f9917d6d8381f06bf22cdff766029d1761be
385 | scope.domElement.removeEventListener( 'mousemove', onMouseMove, false );
386 | scope.domElement.removeEventListener( 'mouseup', onMouseUp, false );
387 |
388 | state = STATE.NONE;
389 |
390 | }
391 |
392 | function onMouseWheel( event ) {
393 |
394 | if ( scope.enabled === false || scope.noZoom === true ) return;
395 |
396 | var delta = 0;
397 |
398 | if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
399 |
400 | delta = event.wheelDelta;
401 |
402 | } else if ( event.detail ) { // Firefox
403 |
404 | delta = - event.detail;
405 |
406 | }
407 |
408 | if ( delta > 0 ) {
409 |
410 | scope.dollyOut();
411 |
412 | } else {
413 |
414 | scope.dollyIn();
415 |
416 | }
417 |
418 | }
419 |
420 | function onKeyDown( event ) {
421 |
422 | if ( scope.enabled === false ) { return; }
423 | if ( scope.noKeys === true ) { return; }
424 | if ( scope.noPan === true ) { return; }
425 |
426 | // pan a pixel - I guess for precise positioning?
427 | // Greggman fix: https://github.com/greggman/three.js/commit/fde9f9917d6d8381f06bf22cdff766029d1761be
428 | var needUpdate = false;
429 |
430 | switch ( event.keyCode ) {
431 |
432 | case scope.keys.UP:
433 | scope.pan( new THREE.Vector2( 0, scope.keyPanSpeed ) );
434 | needUpdate = true;
435 | break;
436 | case scope.keys.BOTTOM:
437 | scope.pan( new THREE.Vector2( 0, -scope.keyPanSpeed ) );
438 | needUpdate = true;
439 | break;
440 | case scope.keys.LEFT:
441 | scope.pan( new THREE.Vector2( scope.keyPanSpeed, 0 ) );
442 | needUpdate = true;
443 | break;
444 | case scope.keys.RIGHT:
445 | scope.pan( new THREE.Vector2( -scope.keyPanSpeed, 0 ) );
446 | needUpdate = true;
447 | break;
448 | }
449 |
450 | // Greggman fix: https://github.com/greggman/three.js/commit/fde9f9917d6d8381f06bf22cdff766029d1761be
451 | if ( needUpdate ) {
452 |
453 | scope.update();
454 |
455 | }
456 |
457 | }
458 |
459 | function touchstart( event ) {
460 |
461 | if ( scope.enabled === false ) { return; }
462 |
463 | switch ( event.touches.length ) {
464 |
465 | case 1: // one-fingered touch: rotate
466 | if ( scope.noRotate === true ) { return; }
467 |
468 | state = STATE.TOUCH_ROTATE;
469 |
470 | rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
471 | break;
472 |
473 | case 2: // two-fingered touch: dolly
474 | if ( scope.noZoom === true ) { return; }
475 |
476 | state = STATE.TOUCH_DOLLY;
477 |
478 | var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
479 | var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
480 | var distance = Math.sqrt( dx * dx + dy * dy );
481 | dollyStart.set( 0, distance );
482 | break;
483 |
484 | case 3: // three-fingered touch: pan
485 | if ( scope.noPan === true ) { return; }
486 |
487 | state = STATE.TOUCH_PAN;
488 |
489 | panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
490 | break;
491 |
492 | default:
493 | state = STATE.NONE;
494 |
495 | }
496 | }
497 |
498 | function touchmove( event ) {
499 |
500 | if ( scope.enabled === false ) { return; }
501 |
502 | event.preventDefault();
503 | event.stopPropagation();
504 |
505 | var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
506 |
507 | switch ( event.touches.length ) {
508 |
509 | case 1: // one-fingered touch: rotate
510 | if ( scope.noRotate === true ) { return; }
511 | if ( state !== STATE.TOUCH_ROTATE ) { return; }
512 |
513 | rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
514 | rotateDelta.subVectors( rotateEnd, rotateStart );
515 |
516 | // rotating across whole screen goes 360 degrees around
517 | scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
518 | // rotating up and down along whole screen attempts to go 360, but limited to 180
519 | scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
520 |
521 | rotateStart.copy( rotateEnd );
522 | break;
523 |
524 | case 2: // two-fingered touch: dolly
525 | if ( scope.noZoom === true ) { return; }
526 | if ( state !== STATE.TOUCH_DOLLY ) { return; }
527 |
528 | var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
529 | var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
530 | var distance = Math.sqrt( dx * dx + dy * dy );
531 |
532 | dollyEnd.set( 0, distance );
533 | dollyDelta.subVectors( dollyEnd, dollyStart );
534 |
535 | if ( dollyDelta.y > 0 ) {
536 |
537 | scope.dollyOut();
538 |
539 | } else {
540 |
541 | scope.dollyIn();
542 |
543 | }
544 |
545 | dollyStart.copy( dollyEnd );
546 | break;
547 |
548 | case 3: // three-fingered touch: pan
549 | if ( scope.noPan === true ) { return; }
550 | if ( state !== STATE.TOUCH_PAN ) { return; }
551 |
552 | panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
553 | panDelta.subVectors( panEnd, panStart );
554 |
555 | scope.pan( panDelta );
556 |
557 | panStart.copy( panEnd );
558 | break;
559 |
560 | default:
561 | state = STATE.NONE;
562 |
563 | }
564 |
565 | }
566 |
567 | function touchend( /* event */ ) {
568 |
569 | if ( scope.enabled === false ) { return; }
570 |
571 | state = STATE.NONE;
572 | }
573 |
574 | this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
575 | this.localElement.addEventListener( 'mousedown', onMouseDown, false );
576 | this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
577 | this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
578 |
579 | this.domElement.addEventListener( 'keydown', onKeyDown, false );
580 |
581 | this.localElement.addEventListener( 'touchstart', touchstart, false );
582 | this.domElement.addEventListener( 'touchend', touchend, false );
583 | this.domElement.addEventListener( 'touchmove', touchmove, false );
584 |
585 | };
586 |
587 | THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
--------------------------------------------------------------------------------
/js/Projector.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author mrdoob / http://mrdoob.com/
3 | * @author supereggbert / http://www.paulbrunt.co.uk/
4 | * @author julianwa / https://github.com/julianwa
5 | */
6 |
7 | THREE.RenderableObject = function () {
8 |
9 | this.id = 0;
10 |
11 | this.object = null;
12 | this.z = 0;
13 | this.renderOrder = 0;
14 |
15 | };
16 |
17 | //
18 |
19 | THREE.RenderableFace = function () {
20 |
21 | this.id = 0;
22 |
23 | this.v1 = new THREE.RenderableVertex();
24 | this.v2 = new THREE.RenderableVertex();
25 | this.v3 = new THREE.RenderableVertex();
26 |
27 | this.normalModel = new THREE.Vector3();
28 |
29 | this.vertexNormalsModel = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
30 | this.vertexNormalsLength = 0;
31 |
32 | this.color = new THREE.Color();
33 | this.material = null;
34 | this.uvs = [ new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() ];
35 |
36 | this.z = 0;
37 | this.renderOrder = 0;
38 |
39 | };
40 |
41 | //
42 |
43 | THREE.RenderableVertex = function () {
44 |
45 | this.position = new THREE.Vector3();
46 | this.positionWorld = new THREE.Vector3();
47 | this.positionScreen = new THREE.Vector4();
48 |
49 | this.visible = true;
50 |
51 | };
52 |
53 | THREE.RenderableVertex.prototype.copy = function ( vertex ) {
54 |
55 | this.positionWorld.copy( vertex.positionWorld );
56 | this.positionScreen.copy( vertex.positionScreen );
57 |
58 | };
59 |
60 | //
61 |
62 | THREE.RenderableLine = function () {
63 |
64 | this.id = 0;
65 |
66 | this.v1 = new THREE.RenderableVertex();
67 | this.v2 = new THREE.RenderableVertex();
68 |
69 | this.vertexColors = [ new THREE.Color(), new THREE.Color() ];
70 | this.material = null;
71 |
72 | this.z = 0;
73 | this.renderOrder = 0;
74 |
75 | };
76 |
77 | //
78 |
79 | THREE.RenderableSprite = function () {
80 |
81 | this.id = 0;
82 |
83 | this.object = null;
84 |
85 | this.x = 0;
86 | this.y = 0;
87 | this.z = 0;
88 |
89 | this.rotation = 0;
90 | this.scale = new THREE.Vector2();
91 |
92 | this.material = null;
93 | this.renderOrder = 0;
94 |
95 | };
96 |
97 | //
98 |
99 | THREE.Projector = function () {
100 |
101 | var _object, _objectCount, _objectPool = [], _objectPoolLength = 0,
102 | _vertex, _vertexCount, _vertexPool = [], _vertexPoolLength = 0,
103 | _face, _faceCount, _facePool = [], _facePoolLength = 0,
104 | _line, _lineCount, _linePool = [], _linePoolLength = 0,
105 | _sprite, _spriteCount, _spritePool = [], _spritePoolLength = 0,
106 |
107 | _renderData = { objects: [], lights: [], elements: [] },
108 |
109 | _vector3 = new THREE.Vector3(),
110 | _vector4 = new THREE.Vector4(),
111 |
112 | _clipBox = new THREE.Box3( new THREE.Vector3( - 1, - 1, - 1 ), new THREE.Vector3( 1, 1, 1 ) ),
113 | _boundingBox = new THREE.Box3(),
114 | _points3 = new Array( 3 ),
115 | _points4 = new Array( 4 ),
116 |
117 | _viewMatrix = new THREE.Matrix4(),
118 | _viewProjectionMatrix = new THREE.Matrix4(),
119 |
120 | _modelMatrix,
121 | _modelViewProjectionMatrix = new THREE.Matrix4(),
122 |
123 | _normalMatrix = new THREE.Matrix3(),
124 |
125 | _frustum = new THREE.Frustum(),
126 |
127 | _clippedVertex1PositionScreen = new THREE.Vector4(),
128 | _clippedVertex2PositionScreen = new THREE.Vector4();
129 |
130 | //
131 |
132 | this.projectVector = function ( vector, camera ) {
133 |
134 | console.warn( 'THREE.Projector: .projectVector() is now vector.project().' );
135 | vector.project( camera );
136 |
137 | };
138 |
139 | this.unprojectVector = function ( vector, camera ) {
140 |
141 | console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );
142 | vector.unproject( camera );
143 |
144 | };
145 |
146 | this.pickingRay = function ( vector, camera ) {
147 |
148 | console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
149 |
150 | };
151 |
152 | //
153 |
154 | var RenderList = function () {
155 |
156 | var normals = [];
157 | var uvs = [];
158 |
159 | var object = null;
160 | var material = null;
161 |
162 | var normalMatrix = new THREE.Matrix3();
163 |
164 | function setObject( value ) {
165 |
166 | object = value;
167 | material = object.material;
168 |
169 | normalMatrix.getNormalMatrix( object.matrixWorld );
170 |
171 | normals.length = 0;
172 | uvs.length = 0;
173 |
174 | }
175 |
176 | function projectVertex( vertex ) {
177 |
178 | var position = vertex.position;
179 | var positionWorld = vertex.positionWorld;
180 | var positionScreen = vertex.positionScreen;
181 |
182 | positionWorld.copy( position ).applyMatrix4( _modelMatrix );
183 | positionScreen.copy( positionWorld ).applyMatrix4( _viewProjectionMatrix );
184 |
185 | var invW = 1 / positionScreen.w;
186 |
187 | positionScreen.x *= invW;
188 | positionScreen.y *= invW;
189 | positionScreen.z *= invW;
190 |
191 | vertex.visible = positionScreen.x >= - 1 && positionScreen.x <= 1 &&
192 | positionScreen.y >= - 1 && positionScreen.y <= 1 &&
193 | positionScreen.z >= - 1 && positionScreen.z <= 1;
194 |
195 | }
196 |
197 | function pushVertex( x, y, z ) {
198 |
199 | _vertex = getNextVertexInPool();
200 | _vertex.position.set( x, y, z );
201 |
202 | projectVertex( _vertex );
203 |
204 | }
205 |
206 | function pushNormal( x, y, z ) {
207 |
208 | normals.push( x, y, z );
209 |
210 | }
211 |
212 | function pushUv( x, y ) {
213 |
214 | uvs.push( x, y );
215 |
216 | }
217 |
218 | function checkTriangleVisibility( v1, v2, v3 ) {
219 |
220 | if ( v1.visible === true || v2.visible === true || v3.visible === true ) return true;
221 |
222 | _points3[ 0 ] = v1.positionScreen;
223 | _points3[ 1 ] = v2.positionScreen;
224 | _points3[ 2 ] = v3.positionScreen;
225 |
226 | return _clipBox.intersectsBox( _boundingBox.setFromPoints( _points3 ) );
227 |
228 | }
229 |
230 | function checkBackfaceCulling( v1, v2, v3 ) {
231 |
232 | return ( ( v3.positionScreen.x - v1.positionScreen.x ) *
233 | ( v2.positionScreen.y - v1.positionScreen.y ) -
234 | ( v3.positionScreen.y - v1.positionScreen.y ) *
235 | ( v2.positionScreen.x - v1.positionScreen.x ) ) < 0;
236 |
237 | }
238 |
239 | function pushLine( a, b ) {
240 |
241 | var v1 = _vertexPool[ a ];
242 | var v2 = _vertexPool[ b ];
243 |
244 | _line = getNextLineInPool();
245 |
246 | _line.id = object.id;
247 | _line.v1.copy( v1 );
248 | _line.v2.copy( v2 );
249 | _line.z = ( v1.positionScreen.z + v2.positionScreen.z ) / 2;
250 | _line.renderOrder = object.renderOrder;
251 |
252 | _line.material = object.material;
253 |
254 | _renderData.elements.push( _line );
255 |
256 | }
257 |
258 | function pushTriangle( a, b, c ) {
259 |
260 | var v1 = _vertexPool[ a ];
261 | var v2 = _vertexPool[ b ];
262 | var v3 = _vertexPool[ c ];
263 |
264 | if ( checkTriangleVisibility( v1, v2, v3 ) === false ) return;
265 |
266 | if ( material.side === THREE.DoubleSide || checkBackfaceCulling( v1, v2, v3 ) === true ) {
267 |
268 | _face = getNextFaceInPool();
269 |
270 | _face.id = object.id;
271 | _face.v1.copy( v1 );
272 | _face.v2.copy( v2 );
273 | _face.v3.copy( v3 );
274 | _face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;
275 | _face.renderOrder = object.renderOrder;
276 |
277 | // use first vertex normal as face normal
278 |
279 | _face.normalModel.fromArray( normals, a * 3 );
280 | _face.normalModel.applyMatrix3( normalMatrix ).normalize();
281 |
282 | for ( var i = 0; i < 3; i ++ ) {
283 |
284 | var normal = _face.vertexNormalsModel[ i ];
285 | normal.fromArray( normals, arguments[ i ] * 3 );
286 | normal.applyMatrix3( normalMatrix ).normalize();
287 |
288 | var uv = _face.uvs[ i ];
289 | uv.fromArray( uvs, arguments[ i ] * 2 );
290 |
291 | }
292 |
293 | _face.vertexNormalsLength = 3;
294 |
295 | _face.material = object.material;
296 |
297 | _renderData.elements.push( _face );
298 |
299 | }
300 |
301 | }
302 |
303 | return {
304 | setObject: setObject,
305 | projectVertex: projectVertex,
306 | checkTriangleVisibility: checkTriangleVisibility,
307 | checkBackfaceCulling: checkBackfaceCulling,
308 | pushVertex: pushVertex,
309 | pushNormal: pushNormal,
310 | pushUv: pushUv,
311 | pushLine: pushLine,
312 | pushTriangle: pushTriangle
313 | }
314 |
315 | };
316 |
317 | var renderList = new RenderList();
318 |
319 | this.projectScene = function ( scene, camera, sortObjects, sortElements ) {
320 |
321 | _faceCount = 0;
322 | _lineCount = 0;
323 | _spriteCount = 0;
324 |
325 | _renderData.elements.length = 0;
326 |
327 | if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
328 | if ( camera.parent === null ) camera.updateMatrixWorld();
329 |
330 | _viewMatrix.copy( camera.matrixWorldInverse.getInverse( camera.matrixWorld ) );
331 | _viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix );
332 |
333 | _frustum.setFromMatrix( _viewProjectionMatrix );
334 |
335 | //
336 |
337 | _objectCount = 0;
338 |
339 | _renderData.objects.length = 0;
340 | _renderData.lights.length = 0;
341 |
342 | function addObject( object ) {
343 |
344 | _object = getNextObjectInPool();
345 | _object.id = object.id;
346 | _object.object = object;
347 |
348 | _vector3.setFromMatrixPosition( object.matrixWorld );
349 | _vector3.applyProjection( _viewProjectionMatrix );
350 | _object.z = _vector3.z;
351 | _object.renderOrder = object.renderOrder;
352 |
353 | _renderData.objects.push( _object );
354 |
355 | }
356 |
357 | scene.traverseVisible( function ( object ) {
358 |
359 | if ( object instanceof THREE.Light ) {
360 |
361 | _renderData.lights.push( object );
362 |
363 | } else if ( object instanceof THREE.Mesh || object instanceof THREE.Line ) {
364 |
365 | if ( object.material.visible === false ) return;
366 | if ( object.frustumCulled === true && _frustum.intersectsObject( object ) === false ) return;
367 |
368 | addObject( object );
369 |
370 | } else if ( object instanceof THREE.Sprite ) {
371 |
372 | if ( object.material.visible === false ) return;
373 | if ( object.frustumCulled === true && _frustum.intersectsSprite( object ) === false ) return;
374 |
375 | addObject( object );
376 |
377 | }
378 |
379 | } );
380 |
381 | if ( sortObjects === true ) {
382 |
383 | _renderData.objects.sort( painterSort );
384 |
385 | }
386 |
387 | //
388 |
389 | for ( var o = 0, ol = _renderData.objects.length; o < ol; o ++ ) {
390 |
391 | var object = _renderData.objects[ o ].object;
392 | var geometry = object.geometry;
393 |
394 | renderList.setObject( object );
395 |
396 | _modelMatrix = object.matrixWorld;
397 |
398 | _vertexCount = 0;
399 |
400 | if ( object instanceof THREE.Mesh ) {
401 |
402 | if ( geometry instanceof THREE.BufferGeometry ) {
403 |
404 | var attributes = geometry.attributes;
405 | var groups = geometry.groups;
406 |
407 | if ( attributes.position === undefined ) continue;
408 |
409 | var positions = attributes.position.array;
410 |
411 | for ( var i = 0, l = positions.length; i < l; i += 3 ) {
412 |
413 | renderList.pushVertex( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
414 |
415 | }
416 |
417 | if ( attributes.normal !== undefined ) {
418 |
419 | var normals = attributes.normal.array;
420 |
421 | for ( var i = 0, l = normals.length; i < l; i += 3 ) {
422 |
423 | renderList.pushNormal( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] );
424 |
425 | }
426 |
427 | }
428 |
429 | if ( attributes.uv !== undefined ) {
430 |
431 | var uvs = attributes.uv.array;
432 |
433 | for ( var i = 0, l = uvs.length; i < l; i += 2 ) {
434 |
435 | renderList.pushUv( uvs[ i ], uvs[ i + 1 ] );
436 |
437 | }
438 |
439 | }
440 |
441 | if ( geometry.index !== null ) {
442 |
443 | var indices = geometry.index.array;
444 |
445 | if ( groups.length > 0 ) {
446 |
447 | for ( var o = 0; o < groups.length; o ++ ) {
448 |
449 | var group = groups[ o ];
450 |
451 | for ( var i = group.start, l = group.start + group.count; i < l; i += 3 ) {
452 |
453 | renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
454 |
455 | }
456 |
457 | }
458 |
459 | } else {
460 |
461 | for ( var i = 0, l = indices.length; i < l; i += 3 ) {
462 |
463 | renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
464 |
465 | }
466 |
467 | }
468 |
469 | } else {
470 |
471 | for ( var i = 0, l = positions.length / 3; i < l; i += 3 ) {
472 |
473 | renderList.pushTriangle( i, i + 1, i + 2 );
474 |
475 | }
476 |
477 | }
478 |
479 | } else if ( geometry instanceof THREE.Geometry ) {
480 |
481 | var vertices = geometry.vertices;
482 | var faces = geometry.faces;
483 | var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
484 |
485 | _normalMatrix.getNormalMatrix( _modelMatrix );
486 |
487 | var material = object.material;
488 |
489 | var isFaceMaterial = material instanceof THREE.MultiMaterial;
490 | var objectMaterials = isFaceMaterial === true ? object.material : null;
491 |
492 | for ( var v = 0, vl = vertices.length; v < vl; v ++ ) {
493 |
494 | var vertex = vertices[ v ];
495 |
496 | _vector3.copy( vertex );
497 |
498 | if ( material.morphTargets === true ) {
499 |
500 | var morphTargets = geometry.morphTargets;
501 | var morphInfluences = object.morphTargetInfluences;
502 |
503 | for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
504 |
505 | var influence = morphInfluences[ t ];
506 |
507 | if ( influence === 0 ) continue;
508 |
509 | var target = morphTargets[ t ];
510 | var targetVertex = target.vertices[ v ];
511 |
512 | _vector3.x += ( targetVertex.x - vertex.x ) * influence;
513 | _vector3.y += ( targetVertex.y - vertex.y ) * influence;
514 | _vector3.z += ( targetVertex.z - vertex.z ) * influence;
515 |
516 | }
517 |
518 | }
519 |
520 | renderList.pushVertex( _vector3.x, _vector3.y, _vector3.z );
521 |
522 | }
523 |
524 | for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
525 |
526 | var face = faces[ f ];
527 |
528 | material = isFaceMaterial === true
529 | ? objectMaterials.materials[ face.materialIndex ]
530 | : object.material;
531 |
532 | if ( material === undefined ) continue;
533 |
534 | var side = material.side;
535 |
536 | var v1 = _vertexPool[ face.a ];
537 | var v2 = _vertexPool[ face.b ];
538 | var v3 = _vertexPool[ face.c ];
539 |
540 | if ( renderList.checkTriangleVisibility( v1, v2, v3 ) === false ) continue;
541 |
542 | var visible = renderList.checkBackfaceCulling( v1, v2, v3 );
543 |
544 | if ( side !== THREE.DoubleSide ) {
545 |
546 | if ( side === THREE.FrontSide && visible === false ) continue;
547 | if ( side === THREE.BackSide && visible === true ) continue;
548 |
549 | }
550 |
551 | _face = getNextFaceInPool();
552 |
553 | _face.id = object.id;
554 | _face.v1.copy( v1 );
555 | _face.v2.copy( v2 );
556 | _face.v3.copy( v3 );
557 |
558 | _face.normalModel.copy( face.normal );
559 |
560 | if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {
561 |
562 | _face.normalModel.negate();
563 |
564 | }
565 |
566 | _face.normalModel.applyMatrix3( _normalMatrix ).normalize();
567 |
568 | var faceVertexNormals = face.vertexNormals;
569 |
570 | for ( var n = 0, nl = Math.min( faceVertexNormals.length, 3 ); n < nl; n ++ ) {
571 |
572 | var normalModel = _face.vertexNormalsModel[ n ];
573 | normalModel.copy( faceVertexNormals[ n ] );
574 |
575 | if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {
576 |
577 | normalModel.negate();
578 |
579 | }
580 |
581 | normalModel.applyMatrix3( _normalMatrix ).normalize();
582 |
583 | }
584 |
585 | _face.vertexNormalsLength = faceVertexNormals.length;
586 |
587 | var vertexUvs = faceVertexUvs[ f ];
588 |
589 | if ( vertexUvs !== undefined ) {
590 |
591 | for ( var u = 0; u < 3; u ++ ) {
592 |
593 | _face.uvs[ u ].copy( vertexUvs[ u ] );
594 |
595 | }
596 |
597 | }
598 |
599 | _face.color = face.color;
600 | _face.material = material;
601 |
602 | _face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;
603 | _face.renderOrder = object.renderOrder;
604 |
605 | _renderData.elements.push( _face );
606 |
607 | }
608 |
609 | }
610 |
611 | } else if ( object instanceof THREE.Line ) {
612 |
613 | if ( geometry instanceof THREE.BufferGeometry ) {
614 |
615 | var attributes = geometry.attributes;
616 |
617 | if ( attributes.position !== undefined ) {
618 |
619 | var positions = attributes.position.array;
620 |
621 | for ( var i = 0, l = positions.length; i < l; i += 3 ) {
622 |
623 | renderList.pushVertex( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
624 |
625 | }
626 |
627 | if ( geometry.index !== null ) {
628 |
629 | var indices = geometry.index.array;
630 |
631 | for ( var i = 0, l = indices.length; i < l; i += 2 ) {
632 |
633 | renderList.pushLine( indices[ i ], indices[ i + 1 ] );
634 |
635 | }
636 |
637 | } else {
638 |
639 | var step = object instanceof THREE.LineSegments ? 2 : 1;
640 |
641 | for ( var i = 0, l = ( positions.length / 3 ) - 1; i < l; i += step ) {
642 |
643 | renderList.pushLine( i, i + 1 );
644 |
645 | }
646 |
647 | }
648 |
649 | }
650 |
651 | } else if ( geometry instanceof THREE.Geometry ) {
652 |
653 | _modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix );
654 |
655 | var vertices = object.geometry.vertices;
656 |
657 | if ( vertices.length === 0 ) continue;
658 |
659 | v1 = getNextVertexInPool();
660 | v1.positionScreen.copy( vertices[ 0 ] ).applyMatrix4( _modelViewProjectionMatrix );
661 |
662 | var step = object instanceof THREE.LineSegments ? 2 : 1;
663 |
664 | for ( var v = 1, vl = vertices.length; v < vl; v ++ ) {
665 |
666 | v1 = getNextVertexInPool();
667 | v1.positionScreen.copy( vertices[ v ] ).applyMatrix4( _modelViewProjectionMatrix );
668 |
669 | if ( ( v + 1 ) % step > 0 ) continue;
670 |
671 | v2 = _vertexPool[ _vertexCount - 2 ];
672 |
673 | _clippedVertex1PositionScreen.copy( v1.positionScreen );
674 | _clippedVertex2PositionScreen.copy( v2.positionScreen );
675 |
676 | if ( clipLine( _clippedVertex1PositionScreen, _clippedVertex2PositionScreen ) === true ) {
677 |
678 | // Perform the perspective divide
679 | _clippedVertex1PositionScreen.multiplyScalar( 1 / _clippedVertex1PositionScreen.w );
680 | _clippedVertex2PositionScreen.multiplyScalar( 1 / _clippedVertex2PositionScreen.w );
681 |
682 | _line = getNextLineInPool();
683 |
684 | _line.id = object.id;
685 | _line.v1.positionScreen.copy( _clippedVertex1PositionScreen );
686 | _line.v2.positionScreen.copy( _clippedVertex2PositionScreen );
687 |
688 | _line.z = Math.max( _clippedVertex1PositionScreen.z, _clippedVertex2PositionScreen.z );
689 | _line.renderOrder = object.renderOrder;
690 |
691 | _line.material = object.material;
692 |
693 | if ( object.material.vertexColors === THREE.VertexColors ) {
694 |
695 | _line.vertexColors[ 0 ].copy( object.geometry.colors[ v ] );
696 | _line.vertexColors[ 1 ].copy( object.geometry.colors[ v - 1 ] );
697 |
698 | }
699 |
700 | _renderData.elements.push( _line );
701 |
702 | }
703 |
704 | }
705 |
706 | }
707 |
708 | } else if ( object instanceof THREE.Sprite ) {
709 |
710 | _vector4.set( _modelMatrix.elements[ 12 ], _modelMatrix.elements[ 13 ], _modelMatrix.elements[ 14 ], 1 );
711 | _vector4.applyMatrix4( _viewProjectionMatrix );
712 |
713 | var invW = 1 / _vector4.w;
714 |
715 | _vector4.z *= invW;
716 |
717 | if ( _vector4.z >= - 1 && _vector4.z <= 1 ) {
718 |
719 | _sprite = getNextSpriteInPool();
720 | _sprite.id = object.id;
721 | _sprite.x = _vector4.x * invW;
722 | _sprite.y = _vector4.y * invW;
723 | _sprite.z = _vector4.z;
724 | _sprite.renderOrder = object.renderOrder;
725 | _sprite.object = object;
726 |
727 | _sprite.rotation = object.rotation;
728 |
729 | _sprite.scale.x = object.scale.x * Math.abs( _sprite.x - ( _vector4.x + camera.projectionMatrix.elements[ 0 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 12 ] ) );
730 | _sprite.scale.y = object.scale.y * Math.abs( _sprite.y - ( _vector4.y + camera.projectionMatrix.elements[ 5 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 13 ] ) );
731 |
732 | _sprite.material = object.material;
733 |
734 | _renderData.elements.push( _sprite );
735 |
736 | }
737 |
738 | }
739 |
740 | }
741 |
742 | if ( sortElements === true ) {
743 |
744 | _renderData.elements.sort( painterSort );
745 |
746 | }
747 |
748 | return _renderData;
749 |
750 | };
751 |
752 | // Pools
753 |
754 | function getNextObjectInPool() {
755 |
756 | if ( _objectCount === _objectPoolLength ) {
757 |
758 | var object = new THREE.RenderableObject();
759 | _objectPool.push( object );
760 | _objectPoolLength ++;
761 | _objectCount ++;
762 | return object;
763 |
764 | }
765 |
766 | return _objectPool[ _objectCount ++ ];
767 |
768 | }
769 |
770 | function getNextVertexInPool() {
771 |
772 | if ( _vertexCount === _vertexPoolLength ) {
773 |
774 | var vertex = new THREE.RenderableVertex();
775 | _vertexPool.push( vertex );
776 | _vertexPoolLength ++;
777 | _vertexCount ++;
778 | return vertex;
779 |
780 | }
781 |
782 | return _vertexPool[ _vertexCount ++ ];
783 |
784 | }
785 |
786 | function getNextFaceInPool() {
787 |
788 | if ( _faceCount === _facePoolLength ) {
789 |
790 | var face = new THREE.RenderableFace();
791 | _facePool.push( face );
792 | _facePoolLength ++;
793 | _faceCount ++;
794 | return face;
795 |
796 | }
797 |
798 | return _facePool[ _faceCount ++ ];
799 |
800 |
801 | }
802 |
803 | function getNextLineInPool() {
804 |
805 | if ( _lineCount === _linePoolLength ) {
806 |
807 | var line = new THREE.RenderableLine();
808 | _linePool.push( line );
809 | _linePoolLength ++;
810 | _lineCount ++;
811 | return line;
812 |
813 | }
814 |
815 | return _linePool[ _lineCount ++ ];
816 |
817 | }
818 |
819 | function getNextSpriteInPool() {
820 |
821 | if ( _spriteCount === _spritePoolLength ) {
822 |
823 | var sprite = new THREE.RenderableSprite();
824 | _spritePool.push( sprite );
825 | _spritePoolLength ++;
826 | _spriteCount ++;
827 | return sprite;
828 |
829 | }
830 |
831 | return _spritePool[ _spriteCount ++ ];
832 |
833 | }
834 |
835 | //
836 |
837 | function painterSort( a, b ) {
838 |
839 | if ( a.renderOrder !== b.renderOrder ) {
840 |
841 | return a.renderOrder - b.renderOrder;
842 |
843 | } else if ( a.z !== b.z ) {
844 |
845 | return b.z - a.z;
846 |
847 | } else if ( a.id !== b.id ) {
848 |
849 | return a.id - b.id;
850 |
851 | } else {
852 |
853 | return 0;
854 |
855 | }
856 |
857 | }
858 |
859 | function clipLine( s1, s2 ) {
860 |
861 | var alpha1 = 0, alpha2 = 1,
862 |
863 | // Calculate the boundary coordinate of each vertex for the near and far clip planes,
864 | // Z = -1 and Z = +1, respectively.
865 | bc1near = s1.z + s1.w,
866 | bc2near = s2.z + s2.w,
867 | bc1far = - s1.z + s1.w,
868 | bc2far = - s2.z + s2.w;
869 |
870 | if ( bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0 ) {
871 |
872 | // Both vertices lie entirely within all clip planes.
873 | return true;
874 |
875 | } else if ( ( bc1near < 0 && bc2near < 0 ) || ( bc1far < 0 && bc2far < 0 ) ) {
876 |
877 | // Both vertices lie entirely outside one of the clip planes.
878 | return false;
879 |
880 | } else {
881 |
882 | // The line segment spans at least one clip plane.
883 |
884 | if ( bc1near < 0 ) {
885 |
886 | // v1 lies outside the near plane, v2 inside
887 | alpha1 = Math.max( alpha1, bc1near / ( bc1near - bc2near ) );
888 |
889 | } else if ( bc2near < 0 ) {
890 |
891 | // v2 lies outside the near plane, v1 inside
892 | alpha2 = Math.min( alpha2, bc1near / ( bc1near - bc2near ) );
893 |
894 | }
895 |
896 | if ( bc1far < 0 ) {
897 |
898 | // v1 lies outside the far plane, v2 inside
899 | alpha1 = Math.max( alpha1, bc1far / ( bc1far - bc2far ) );
900 |
901 | } else if ( bc2far < 0 ) {
902 |
903 | // v2 lies outside the far plane, v2 inside
904 | alpha2 = Math.min( alpha2, bc1far / ( bc1far - bc2far ) );
905 |
906 | }
907 |
908 | if ( alpha2 < alpha1 ) {
909 |
910 | // The line segment spans two boundaries, but is outside both of them.
911 | // (This can't happen when we're only clipping against just near/far but good
912 | // to leave the check here for future usage if other clip planes are added.)
913 | return false;
914 |
915 | } else {
916 |
917 | // Update the s1 and s2 vertices to match the clipped line segment.
918 | s1.lerp( s2, alpha1 );
919 | s2.lerp( s1, 1 - alpha2 );
920 |
921 | return true;
922 |
923 | }
924 |
925 | }
926 |
927 | }
928 |
929 | };
--------------------------------------------------------------------------------
/js/TrackballControls.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Eberhard Graether / http://egraether.com/
3 | * @author Mark Lundin / http://mark-lundin.com
4 | * @author Simone Manini / http://daron1337.github.io
5 | * @author Luca Antiga / http://lantiga.github.io
6 | */
7 |
8 | THREE.TrackballControls = function ( object, domElement ) {
9 |
10 | var _this = this;
11 | var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
12 |
13 | this.object = object;
14 | this.domElement = ( domElement !== undefined ) ? domElement : document;
15 |
16 | // API
17 |
18 | this.enabled = true;
19 |
20 | this.screen = { left: 0, top: 0, width: 0, height: 0 };
21 |
22 | this.rotateSpeed = 1.0;
23 | this.zoomSpeed = 1.2;
24 | this.panSpeed = 0.3;
25 |
26 | this.noRotate = false;
27 | this.noZoom = false;
28 | this.noPan = false;
29 |
30 | this.staticMoving = false;
31 | this.dynamicDampingFactor = 0.2;
32 |
33 | this.minDistance = 0;
34 | this.maxDistance = Infinity;
35 |
36 | this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];
37 |
38 | // internals
39 |
40 | this.target = new THREE.Vector3();
41 |
42 | var EPS = 0.000001;
43 |
44 | var lastPosition = new THREE.Vector3();
45 |
46 | var _state = STATE.NONE,
47 | _prevState = STATE.NONE,
48 |
49 | _eye = new THREE.Vector3(),
50 |
51 | _movePrev = new THREE.Vector2(),
52 | _moveCurr = new THREE.Vector2(),
53 |
54 | _lastAxis = new THREE.Vector3(),
55 | _lastAngle = 0,
56 |
57 | _zoomStart = new THREE.Vector2(),
58 | _zoomEnd = new THREE.Vector2(),
59 |
60 | _touchZoomDistanceStart = 0,
61 | _touchZoomDistanceEnd = 0,
62 |
63 | _panStart = new THREE.Vector2(),
64 | _panEnd = new THREE.Vector2();
65 |
66 | // for reset
67 |
68 | this.target0 = this.target.clone();
69 | this.position0 = this.object.position.clone();
70 | this.up0 = this.object.up.clone();
71 |
72 | // events
73 |
74 | var changeEvent = { type: 'change' };
75 | var startEvent = { type: 'start' };
76 | var endEvent = { type: 'end' };
77 |
78 |
79 | // methods
80 |
81 | this.handleResize = function () {
82 |
83 | if ( this.domElement === document ) {
84 |
85 | this.screen.left = 0;
86 | this.screen.top = 0;
87 | this.screen.width = window.innerWidth;
88 | this.screen.height = window.innerHeight;
89 |
90 | } else {
91 |
92 | var box = this.domElement.getBoundingClientRect();
93 | // adjustments come from similar code in the jquery offset() function
94 | var d = this.domElement.ownerDocument.documentElement;
95 | this.screen.left = box.left + window.pageXOffset - d.clientLeft;
96 | this.screen.top = box.top + window.pageYOffset - d.clientTop;
97 | this.screen.width = box.width;
98 | this.screen.height = box.height;
99 |
100 | }
101 |
102 | };
103 |
104 | this.handleEvent = function ( event ) {
105 |
106 | if ( typeof this[ event.type ] == 'function' ) {
107 |
108 | this[ event.type ]( event );
109 |
110 | }
111 |
112 | };
113 |
114 | var getMouseOnScreen = ( function () {
115 |
116 | var vector = new THREE.Vector2();
117 |
118 | return function getMouseOnScreen( pageX, pageY ) {
119 |
120 | vector.set(
121 | ( pageX - _this.screen.left ) / _this.screen.width,
122 | ( pageY - _this.screen.top ) / _this.screen.height
123 | );
124 |
125 | return vector;
126 |
127 | };
128 |
129 | }() );
130 |
131 | var getMouseOnCircle = ( function () {
132 |
133 | var vector = new THREE.Vector2();
134 |
135 | return function getMouseOnCircle( pageX, pageY ) {
136 |
137 | vector.set(
138 | ( ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ) ),
139 | ( ( _this.screen.height + 2 * ( _this.screen.top - pageY ) ) / _this.screen.width ) // screen.width intentional
140 | );
141 |
142 | return vector;
143 |
144 | };
145 |
146 | }() );
147 |
148 | this.rotateCamera = ( function() {
149 |
150 | var axis = new THREE.Vector3(),
151 | quaternion = new THREE.Quaternion(),
152 | eyeDirection = new THREE.Vector3(),
153 | objectUpDirection = new THREE.Vector3(),
154 | objectSidewaysDirection = new THREE.Vector3(),
155 | moveDirection = new THREE.Vector3(),
156 | angle;
157 |
158 | return function rotateCamera() {
159 |
160 | moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 );
161 | angle = moveDirection.length();
162 |
163 | if ( angle ) {
164 |
165 | _eye.copy( _this.object.position ).sub( _this.target );
166 |
167 | eyeDirection.copy( _eye ).normalize();
168 | objectUpDirection.copy( _this.object.up ).normalize();
169 | objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize();
170 |
171 | objectUpDirection.setLength( _moveCurr.y - _movePrev.y );
172 | objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x );
173 |
174 | moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) );
175 |
176 | axis.crossVectors( moveDirection, _eye ).normalize();
177 |
178 | angle *= _this.rotateSpeed;
179 | quaternion.setFromAxisAngle( axis, angle );
180 |
181 | _eye.applyQuaternion( quaternion );
182 | _this.object.up.applyQuaternion( quaternion );
183 |
184 | _lastAxis.copy( axis );
185 | _lastAngle = angle;
186 |
187 | } else if ( ! _this.staticMoving && _lastAngle ) {
188 |
189 | _lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor );
190 | _eye.copy( _this.object.position ).sub( _this.target );
191 | quaternion.setFromAxisAngle( _lastAxis, _lastAngle );
192 | _eye.applyQuaternion( quaternion );
193 | _this.object.up.applyQuaternion( quaternion );
194 |
195 | }
196 |
197 | _movePrev.copy( _moveCurr );
198 |
199 | };
200 |
201 | }() );
202 |
203 |
204 | this.zoomCamera = function () {
205 |
206 | var factor;
207 |
208 | if ( _state === STATE.TOUCH_ZOOM_PAN ) {
209 |
210 | factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
211 | _touchZoomDistanceStart = _touchZoomDistanceEnd;
212 | _eye.multiplyScalar( factor );
213 |
214 | } else {
215 |
216 | factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
217 |
218 | if ( factor !== 1.0 && factor > 0.0 ) {
219 |
220 | _eye.multiplyScalar( factor );
221 |
222 | }
223 |
224 | if ( _this.staticMoving ) {
225 |
226 | _zoomStart.copy( _zoomEnd );
227 |
228 | } else {
229 |
230 | _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
231 |
232 | }
233 |
234 | }
235 |
236 | };
237 |
238 | this.panCamera = ( function() {
239 |
240 | var mouseChange = new THREE.Vector2(),
241 | objectUp = new THREE.Vector3(),
242 | pan = new THREE.Vector3();
243 |
244 | return function panCamera() {
245 |
246 | mouseChange.copy( _panEnd ).sub( _panStart );
247 |
248 | if ( mouseChange.lengthSq() ) {
249 |
250 | mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );
251 |
252 | pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x );
253 | pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) );
254 |
255 | _this.object.position.add( pan );
256 | _this.target.add( pan );
257 |
258 | if ( _this.staticMoving ) {
259 |
260 | _panStart.copy( _panEnd );
261 |
262 | } else {
263 |
264 | _panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
265 |
266 | }
267 |
268 | }
269 |
270 | };
271 |
272 | }() );
273 |
274 | this.checkDistances = function () {
275 |
276 | if ( ! _this.noZoom || ! _this.noPan ) {
277 |
278 | if ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) {
279 |
280 | _this.object.position.addVectors( _this.target, _eye.setLength( _this.maxDistance ) );
281 | _zoomStart.copy( _zoomEnd );
282 |
283 | }
284 |
285 | if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) {
286 |
287 | _this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) );
288 | _zoomStart.copy( _zoomEnd );
289 |
290 | }
291 |
292 | }
293 |
294 | };
295 |
296 | this.update = function () {
297 |
298 | _eye.subVectors( _this.object.position, _this.target );
299 |
300 | if ( ! _this.noRotate ) {
301 |
302 | _this.rotateCamera();
303 |
304 | }
305 |
306 | if ( ! _this.noZoom ) {
307 |
308 | _this.zoomCamera();
309 |
310 | }
311 |
312 | if ( ! _this.noPan ) {
313 |
314 | _this.panCamera();
315 |
316 | }
317 |
318 | _this.object.position.addVectors( _this.target, _eye );
319 |
320 | _this.checkDistances();
321 |
322 | _this.object.lookAt( _this.target );
323 |
324 | if ( lastPosition.distanceToSquared( _this.object.position ) > EPS ) {
325 |
326 | _this.dispatchEvent( changeEvent );
327 |
328 | lastPosition.copy( _this.object.position );
329 |
330 | }
331 |
332 | };
333 |
334 | this.reset = function () {
335 |
336 | _state = STATE.NONE;
337 | _prevState = STATE.NONE;
338 |
339 | _this.target.copy( _this.target0 );
340 | _this.object.position.copy( _this.position0 );
341 | _this.object.up.copy( _this.up0 );
342 |
343 | _eye.subVectors( _this.object.position, _this.target );
344 |
345 | _this.object.lookAt( _this.target );
346 |
347 | _this.dispatchEvent( changeEvent );
348 |
349 | lastPosition.copy( _this.object.position );
350 |
351 | };
352 |
353 | // listeners
354 |
355 | function keydown( event ) {
356 |
357 | if ( _this.enabled === false ) return;
358 |
359 | window.removeEventListener( 'keydown', keydown );
360 |
361 | _prevState = _state;
362 |
363 | if ( _state !== STATE.NONE ) {
364 |
365 | return;
366 |
367 | } else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && ! _this.noRotate ) {
368 |
369 | _state = STATE.ROTATE;
370 |
371 | } else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && ! _this.noZoom ) {
372 |
373 | _state = STATE.ZOOM;
374 |
375 | } else if ( event.keyCode === _this.keys[ STATE.PAN ] && ! _this.noPan ) {
376 |
377 | _state = STATE.PAN;
378 |
379 | }
380 |
381 | }
382 |
383 | function keyup( event ) {
384 |
385 | if ( _this.enabled === false ) return;
386 |
387 | _state = _prevState;
388 |
389 | window.addEventListener( 'keydown', keydown, false );
390 |
391 | }
392 |
393 | function mousedown( event ) {
394 |
395 | if ( _this.enabled === false ) return;
396 |
397 | event.preventDefault();
398 | event.stopPropagation();
399 |
400 | if ( _state === STATE.NONE ) {
401 |
402 | _state = event.button;
403 |
404 | }
405 |
406 | if ( _state === STATE.ROTATE && ! _this.noRotate ) {
407 |
408 | _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
409 | _movePrev.copy( _moveCurr );
410 |
411 | } else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
412 |
413 | _zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
414 | _zoomEnd.copy( _zoomStart );
415 |
416 | } else if ( _state === STATE.PAN && ! _this.noPan ) {
417 |
418 | _panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
419 | _panEnd.copy( _panStart );
420 |
421 | }
422 |
423 | document.addEventListener( 'mousemove', mousemove, false );
424 | document.addEventListener( 'mouseup', mouseup, false );
425 |
426 | _this.dispatchEvent( startEvent );
427 |
428 | }
429 |
430 | function mousemove( event ) {
431 |
432 | if ( _this.enabled === false ) return;
433 |
434 | event.preventDefault();
435 | event.stopPropagation();
436 |
437 | if ( _state === STATE.ROTATE && ! _this.noRotate ) {
438 |
439 | _movePrev.copy( _moveCurr );
440 | _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
441 |
442 | } else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
443 |
444 | _zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
445 |
446 | } else if ( _state === STATE.PAN && ! _this.noPan ) {
447 |
448 | _panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
449 |
450 | }
451 |
452 | }
453 |
454 | function mouseup( event ) {
455 |
456 | if ( _this.enabled === false ) return;
457 |
458 | event.preventDefault();
459 | event.stopPropagation();
460 |
461 | _state = STATE.NONE;
462 |
463 | document.removeEventListener( 'mousemove', mousemove );
464 | document.removeEventListener( 'mouseup', mouseup );
465 | _this.dispatchEvent( endEvent );
466 |
467 | }
468 |
469 | function mousewheel( event ) {
470 |
471 | if ( _this.enabled === false ) return;
472 |
473 | event.preventDefault();
474 | event.stopPropagation();
475 |
476 | _zoomStart.y -= event.deltaY * 0.01;
477 |
478 | _this.dispatchEvent( startEvent );
479 | _this.dispatchEvent( endEvent );
480 |
481 | }
482 |
483 | function touchstart( event ) {
484 |
485 | if ( _this.enabled === false ) return;
486 |
487 | switch ( event.touches.length ) {
488 |
489 | case 1:
490 | _state = STATE.TOUCH_ROTATE;
491 | _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
492 | _movePrev.copy( _moveCurr );
493 | break;
494 |
495 | default: // 2 or more
496 | _state = STATE.TOUCH_ZOOM_PAN;
497 | var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
498 | var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
499 | _touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
500 |
501 | var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
502 | var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
503 | _panStart.copy( getMouseOnScreen( x, y ) );
504 | _panEnd.copy( _panStart );
505 | break;
506 |
507 | }
508 |
509 | _this.dispatchEvent( startEvent );
510 |
511 | }
512 |
513 | function touchmove( event ) {
514 |
515 | if ( _this.enabled === false ) return;
516 |
517 | event.preventDefault();
518 | event.stopPropagation();
519 |
520 | switch ( event.touches.length ) {
521 |
522 | case 1:
523 | _movePrev.copy( _moveCurr );
524 | _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
525 | break;
526 |
527 | default: // 2 or more
528 | var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
529 | var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
530 | _touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
531 |
532 | var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
533 | var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
534 | _panEnd.copy( getMouseOnScreen( x, y ) );
535 | break;
536 |
537 | }
538 |
539 | }
540 |
541 | function touchend( event ) {
542 |
543 | if ( _this.enabled === false ) return;
544 |
545 | switch ( event.touches.length ) {
546 |
547 | case 0:
548 | _state = STATE.NONE;
549 | break;
550 |
551 | case 1:
552 | _state = STATE.TOUCH_ROTATE;
553 | _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
554 | _movePrev.copy( _moveCurr );
555 | break;
556 |
557 | }
558 |
559 | _this.dispatchEvent( endEvent );
560 |
561 | }
562 |
563 | function contextmenu( event ) {
564 |
565 | event.preventDefault();
566 |
567 | }
568 |
569 | this.dispose = function() {
570 |
571 | this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
572 | this.domElement.removeEventListener( 'mousedown', mousedown, false );
573 | this.domElement.removeEventListener( 'wheel', mousewheel, false );
574 |
575 | this.domElement.removeEventListener( 'touchstart', touchstart, false );
576 | this.domElement.removeEventListener( 'touchend', touchend, false );
577 | this.domElement.removeEventListener( 'touchmove', touchmove, false );
578 |
579 | document.removeEventListener( 'mousemove', mousemove, false );
580 | document.removeEventListener( 'mouseup', mouseup, false );
581 |
582 | window.removeEventListener( 'keydown', keydown, false );
583 | window.removeEventListener( 'keyup', keyup, false );
584 |
585 | };
586 |
587 | this.domElement.addEventListener( 'contextmenu', contextmenu, false );
588 | this.domElement.addEventListener( 'mousedown', mousedown, false );
589 | this.domElement.addEventListener( 'wheel', mousewheel, false );
590 |
591 | this.domElement.addEventListener( 'touchstart', touchstart, false );
592 | this.domElement.addEventListener( 'touchend', touchend, false );
593 | this.domElement.addEventListener( 'touchmove', touchmove, false );
594 |
595 | window.addEventListener( 'keydown', keydown, false );
596 | window.addEventListener( 'keyup', keyup, false );
597 |
598 | this.handleResize();
599 |
600 | // force an update at start
601 | this.update();
602 |
603 | };
604 |
605 | THREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );
606 | THREE.TrackballControls.prototype.constructor = THREE.TrackballControls;
--------------------------------------------------------------------------------
/js/jszip-utils.js:
--------------------------------------------------------------------------------
1 | /*!
2 |
3 | JSZipUtils - A collection of cross-browser utilities to go along with JSZip.
4 |
5 |
6 | (c) 2014 Stuart Knightley, David Duponchel
7 | Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown.
8 |
9 | */
10 | !function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSZipUtils=e():"undefined"!=typeof global?global.JSZipUtils=e():"undefined"!=typeof self&&(self.JSZipUtils=e())}(function(){var define,module,exports;return (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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;oe+1E3&&(r.update(1E3*a/(c-e),100),e=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){g=this.end()},domElement:c,setMode:k}};
4 | Stats.Panel=function(h,k,l){var c=Infinity,g=0,e=Math.round,a=e(window.devicePixelRatio||1),r=80*a,f=48*a,t=3*a,u=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement("canvas");q.width=r;q.height=f;q.style.cssText="width:80px;height:48px";var b=q.getContext("2d");b.font="bold "+9*a+"px Helvetica,Arial,sans-serif";b.textBaseline="top";b.fillStyle=l;b.fillRect(0,0,r,f);b.fillStyle=k;b.fillText(h,t,u);b.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(f,
5 | v){c=Math.min(c,f);g=Math.max(g,f);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=k;b.fillText(e(f)+" "+h+" ("+e(c)+"-"+e(g)+")",t,u);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,e((1-f/v)*p))}}};"object"===typeof module&&(module.exports=Stats);
--------------------------------------------------------------------------------
/js/ui.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author mrdoob / http://mrdoob.com/
3 | */
4 |
5 | var UI = {};
6 |
7 | UI.Element = function ( dom ) {
8 |
9 | this.dom = dom;
10 |
11 | };
12 |
13 | UI.Element.prototype = {
14 |
15 | add: function () {
16 |
17 | for ( var i = 0; i < arguments.length; i ++ ) {
18 |
19 | var argument = arguments[ i ];
20 |
21 | if ( argument instanceof UI.Element ) {
22 |
23 | this.dom.appendChild( argument.dom );
24 |
25 | } else {
26 |
27 | console.error( 'UI.Element:', argument, 'is not an instance of UI.Element.' );
28 |
29 | }
30 |
31 | }
32 |
33 | return this;
34 |
35 | },
36 |
37 | remove: function () {
38 |
39 | for ( var i = 0; i < arguments.length; i ++ ) {
40 |
41 | var argument = arguments[ i ];
42 |
43 | if ( argument instanceof UI.Element ) {
44 |
45 | this.dom.removeChild( argument.dom );
46 |
47 | } else {
48 |
49 | console.error( 'UI.Element:', argument, 'is not an instance of UI.Element.' );
50 |
51 | }
52 |
53 | }
54 |
55 | return this;
56 |
57 | },
58 |
59 | clear: function () {
60 |
61 | while ( this.dom.children.length ) {
62 |
63 | this.dom.removeChild( this.dom.lastChild );
64 |
65 | }
66 |
67 | },
68 |
69 | setId: function ( id ) {
70 |
71 | this.dom.id = id;
72 |
73 | return this;
74 |
75 | },
76 |
77 | setClass: function ( name ) {
78 |
79 | this.dom.className = name;
80 |
81 | return this;
82 |
83 | },
84 |
85 | setStyle: function ( style, array ) {
86 |
87 | for ( var i = 0; i < array.length; i ++ ) {
88 |
89 | this.dom.style[ style ] = array[ i ];
90 |
91 | }
92 |
93 | return this;
94 |
95 | },
96 |
97 | setDisabled: function ( value ) {
98 |
99 | this.dom.disabled = value;
100 |
101 | return this;
102 |
103 | },
104 |
105 | setTextContent: function ( value ) {
106 |
107 | this.dom.textContent = value;
108 |
109 | return this;
110 |
111 | }
112 |
113 | };
114 |
115 | // properties
116 |
117 | var properties = [ 'position', 'left', 'top', 'right', 'bottom', 'width', 'height', 'border', 'borderLeft',
118 | 'borderTop', 'borderRight', 'borderBottom', 'borderColor', 'display', 'overflow', 'margin', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'color',
119 | 'background', 'backgroundColor', 'opacity', 'fontSize', 'fontWeight', 'textAlign', 'textDecoration', 'textTransform', 'cursor', 'zIndex' ];
120 |
121 | properties.forEach( function ( property ) {
122 |
123 | var method = 'set' + property.substr( 0, 1 ).toUpperCase() + property.substr( 1, property.length );
124 |
125 | UI.Element.prototype[ method ] = function () {
126 |
127 | this.setStyle( property, arguments );
128 |
129 | return this;
130 |
131 | };
132 |
133 | } );
134 |
135 | // events
136 |
137 | var events = [ 'KeyUp', 'KeyDown', 'MouseOver', 'MouseOut', 'Click', 'DblClick', 'Change' ];
138 |
139 | events.forEach( function ( event ) {
140 |
141 | var method = 'on' + event;
142 |
143 | UI.Element.prototype[ method ] = function ( callback ) {
144 |
145 | this.dom.addEventListener( event.toLowerCase(), callback.bind( this ), false );
146 |
147 | return this;
148 |
149 | };
150 |
151 | } );
152 |
153 | // Span
154 |
155 | UI.Span = function () {
156 |
157 | UI.Element.call( this );
158 |
159 | this.dom = document.createElement( 'span' );
160 |
161 | return this;
162 |
163 | };
164 |
165 | UI.Span.prototype = Object.create( UI.Element.prototype );
166 | UI.Span.prototype.constructor = UI.Span;
167 |
168 | // Div
169 |
170 | UI.Div = function () {
171 |
172 | UI.Element.call( this );
173 |
174 | this.dom = document.createElement( 'div' );
175 |
176 | return this;
177 |
178 | };
179 |
180 | UI.Div.prototype = Object.create( UI.Element.prototype );
181 | UI.Div.prototype.constructor = UI.Div;
182 |
183 | // Row
184 |
185 | UI.Row = function () {
186 |
187 | UI.Element.call( this );
188 |
189 | var dom = document.createElement( 'div' );
190 | dom.className = 'Row';
191 |
192 | this.dom = dom;
193 |
194 | return this;
195 |
196 | };
197 |
198 | UI.Row.prototype = Object.create( UI.Element.prototype );
199 | UI.Row.prototype.constructor = UI.Row;
200 |
201 | // Panel
202 |
203 | UI.Panel = function () {
204 |
205 | UI.Element.call( this );
206 |
207 | var dom = document.createElement( 'div' );
208 | dom.className = 'Panel';
209 |
210 | this.dom = dom;
211 |
212 | return this;
213 |
214 | };
215 |
216 | UI.Panel.prototype = Object.create( UI.Element.prototype );
217 | UI.Panel.prototype.constructor = UI.Panel;
218 |
219 |
220 | // Collapsible Panel
221 |
222 | UI.CollapsiblePanel = function () {
223 |
224 | UI.Panel.call( this );
225 |
226 | this.setClass( 'Panel Collapsible' );
227 |
228 | var scope = this;
229 |
230 | this.static = new UI.Panel();
231 | this.static.setClass( 'Static' );
232 | this.static.onClick( function () {
233 |
234 | scope.toggle();
235 |
236 | } );
237 | this.dom.appendChild( this.static.dom );
238 |
239 | this.contents = new UI.Panel();
240 | this.contents.setClass( 'Content' );
241 | this.dom.appendChild( this.contents.dom );
242 |
243 | var button = new UI.Panel();
244 | button.setClass( 'Button' );
245 | this.static.add( button );
246 |
247 | this.isCollapsed = false;
248 |
249 | return this;
250 |
251 | };
252 |
253 | UI.CollapsiblePanel.prototype = Object.create( UI.Panel.prototype );
254 | UI.CollapsiblePanel.prototype.constructor = UI.CollapsiblePanel;
255 |
256 | UI.CollapsiblePanel.prototype.addStatic = function () {
257 |
258 | this.static.add.apply( this.static, arguments );
259 | return this;
260 |
261 | };
262 |
263 | UI.CollapsiblePanel.prototype.removeStatic = function () {
264 |
265 | this.static.remove.apply( this.static, arguments );
266 | return this;
267 |
268 | };
269 |
270 | UI.CollapsiblePanel.prototype.clearStatic = function () {
271 |
272 | this.static.clear();
273 | return this;
274 |
275 | };
276 |
277 | UI.CollapsiblePanel.prototype.add = function () {
278 |
279 | this.contents.add.apply( this.contents, arguments );
280 | return this;
281 |
282 | };
283 |
284 | UI.CollapsiblePanel.prototype.remove = function () {
285 |
286 | this.contents.remove.apply( this.contents, arguments );
287 | return this;
288 |
289 | };
290 |
291 | UI.CollapsiblePanel.prototype.clear = function () {
292 |
293 | this.contents.clear();
294 | return this;
295 |
296 | };
297 |
298 | UI.CollapsiblePanel.prototype.toggle = function() {
299 |
300 | this.setCollapsed( ! this.isCollapsed );
301 |
302 | };
303 |
304 | UI.CollapsiblePanel.prototype.collapse = function() {
305 |
306 | this.setCollapsed( true );
307 |
308 | };
309 |
310 | UI.CollapsiblePanel.prototype.expand = function() {
311 |
312 | this.setCollapsed( false );
313 |
314 | };
315 |
316 | UI.CollapsiblePanel.prototype.setCollapsed = function( boolean ) {
317 |
318 | if ( boolean ) {
319 |
320 | this.dom.classList.add( 'collapsed' );
321 |
322 | } else {
323 |
324 | this.dom.classList.remove( 'collapsed' );
325 |
326 | }
327 |
328 | this.isCollapsed = boolean;
329 |
330 | if ( this.onCollapsedChangeCallback !== undefined ) {
331 |
332 | this.onCollapsedChangeCallback( boolean );
333 |
334 | }
335 |
336 | };
337 |
338 | UI.CollapsiblePanel.prototype.onCollapsedChange = function ( callback ) {
339 |
340 | this.onCollapsedChangeCallback = callback;
341 |
342 | };
343 |
344 | // Text
345 |
346 | UI.Text = function ( text ) {
347 |
348 | UI.Element.call( this );
349 |
350 | var dom = document.createElement( 'span' );
351 | dom.className = 'Text';
352 | dom.style.cursor = 'default';
353 | dom.style.display = 'inline-block';
354 | dom.style.verticalAlign = 'middle';
355 |
356 | this.dom = dom;
357 | this.setValue( text );
358 |
359 | return this;
360 |
361 | };
362 |
363 | UI.Text.prototype = Object.create( UI.Element.prototype );
364 | UI.Text.prototype.constructor = UI.Text;
365 |
366 | UI.Text.prototype.getValue = function () {
367 |
368 | return this.dom.textContent;
369 |
370 | };
371 |
372 | UI.Text.prototype.setValue = function ( value ) {
373 |
374 | if ( value !== undefined ) {
375 |
376 | this.dom.textContent = value;
377 |
378 | }
379 |
380 | return this;
381 |
382 | };
383 |
384 |
385 | // Input
386 |
387 | UI.Input = function ( text ) {
388 |
389 | UI.Element.call( this );
390 |
391 | var scope = this;
392 |
393 | var dom = document.createElement( 'input' );
394 | dom.className = 'Input';
395 | dom.style.padding = '2px';
396 | dom.style.border = '1px solid transparent';
397 |
398 | dom.addEventListener( 'keydown', function ( event ) {
399 |
400 | event.stopPropagation();
401 |
402 | }, false );
403 |
404 | this.dom = dom;
405 | this.setValue( text );
406 |
407 | return this;
408 |
409 | };
410 |
411 | UI.Input.prototype = Object.create( UI.Element.prototype );
412 | UI.Input.prototype.constructor = UI.Input;
413 |
414 | UI.Input.prototype.getValue = function () {
415 |
416 | return this.dom.value;
417 |
418 | };
419 |
420 | UI.Input.prototype.setValue = function ( value ) {
421 |
422 | this.dom.value = value;
423 |
424 | return this;
425 |
426 | };
427 |
428 |
429 | // TextArea
430 |
431 | UI.TextArea = function () {
432 |
433 | UI.Element.call( this );
434 |
435 | var scope = this;
436 |
437 | var dom = document.createElement( 'textarea' );
438 | dom.className = 'TextArea';
439 | dom.style.padding = '2px';
440 | dom.spellcheck = false;
441 |
442 | dom.addEventListener( 'keydown', function ( event ) {
443 |
444 | event.stopPropagation();
445 |
446 | if ( event.keyCode === 9 ) {
447 |
448 | event.preventDefault();
449 |
450 | var cursor = dom.selectionStart;
451 |
452 | dom.value = dom.value.substring( 0, cursor ) + '\t' + dom.value.substring( cursor );
453 | dom.selectionStart = cursor + 1;
454 | dom.selectionEnd = dom.selectionStart;
455 |
456 | }
457 |
458 | }, false );
459 |
460 | this.dom = dom;
461 |
462 | return this;
463 |
464 | };
465 |
466 | UI.TextArea.prototype = Object.create( UI.Element.prototype );
467 | UI.TextArea.prototype.constructor = UI.TextArea;
468 |
469 | UI.TextArea.prototype.getValue = function () {
470 |
471 | return this.dom.value;
472 |
473 | };
474 |
475 | UI.TextArea.prototype.setValue = function ( value ) {
476 |
477 | this.dom.value = value;
478 |
479 | return this;
480 |
481 | };
482 |
483 |
484 | // Select
485 |
486 | UI.Select = function () {
487 |
488 | UI.Element.call( this );
489 |
490 | var scope = this;
491 |
492 | var dom = document.createElement( 'select' );
493 | dom.className = 'Select';
494 | dom.style.padding = '2px';
495 |
496 | this.dom = dom;
497 |
498 | return this;
499 |
500 | };
501 |
502 | UI.Select.prototype = Object.create( UI.Element.prototype );
503 | UI.Select.prototype.constructor = UI.Select;
504 |
505 | UI.Select.prototype.setMultiple = function ( boolean ) {
506 |
507 | this.dom.multiple = boolean;
508 |
509 | return this;
510 |
511 | };
512 |
513 | UI.Select.prototype.setOptions = function ( options ) {
514 |
515 | var selected = this.dom.value;
516 |
517 | while ( this.dom.children.length > 0 ) {
518 |
519 | this.dom.removeChild( this.dom.firstChild );
520 |
521 | }
522 |
523 | for ( var key in options ) {
524 |
525 | var option = document.createElement( 'option' );
526 | option.value = key;
527 | option.innerHTML = options[ key ];
528 | this.dom.appendChild( option );
529 |
530 | }
531 |
532 | this.dom.value = selected;
533 |
534 | return this;
535 |
536 | };
537 |
538 | UI.Select.prototype.getValue = function () {
539 |
540 | return this.dom.value;
541 |
542 | };
543 |
544 | UI.Select.prototype.setValue = function ( value ) {
545 |
546 | value = String( value );
547 |
548 | if ( this.dom.value !== value ) {
549 |
550 | this.dom.value = value;
551 |
552 | }
553 |
554 | return this;
555 |
556 | };
557 |
558 | // Checkbox
559 |
560 | UI.Checkbox = function ( boolean ) {
561 |
562 | UI.Element.call( this );
563 |
564 | var scope = this;
565 |
566 | var dom = document.createElement( 'input' );
567 | dom.className = 'Checkbox';
568 | dom.type = 'checkbox';
569 |
570 | this.dom = dom;
571 | this.setValue( boolean );
572 |
573 | return this;
574 |
575 | };
576 |
577 | UI.Checkbox.prototype = Object.create( UI.Element.prototype );
578 | UI.Checkbox.prototype.constructor = UI.Checkbox;
579 |
580 | UI.Checkbox.prototype.getValue = function () {
581 |
582 | return this.dom.checked;
583 |
584 | };
585 |
586 | UI.Checkbox.prototype.setValue = function ( value ) {
587 |
588 | if ( value !== undefined ) {
589 |
590 | this.dom.checked = value;
591 |
592 | }
593 |
594 | return this;
595 |
596 | };
597 |
598 |
599 | // Color
600 |
601 | UI.Color = function () {
602 |
603 | UI.Element.call( this );
604 |
605 | var scope = this;
606 |
607 | var dom = document.createElement( 'input' );
608 | dom.className = 'Color';
609 | dom.style.width = '64px';
610 | dom.style.height = '17px';
611 | dom.style.border = '0px';
612 | dom.style.padding = '2px';
613 | dom.style.backgroundColor = 'transparent';
614 |
615 | try {
616 |
617 | dom.type = 'color';
618 | dom.value = '#ffffff';
619 |
620 | } catch ( exception ) {}
621 |
622 | this.dom = dom;
623 |
624 | return this;
625 |
626 | };
627 |
628 | UI.Color.prototype = Object.create( UI.Element.prototype );
629 | UI.Color.prototype.constructor = UI.Color;
630 |
631 | UI.Color.prototype.getValue = function () {
632 |
633 | return this.dom.value;
634 |
635 | };
636 |
637 | UI.Color.prototype.getHexValue = function () {
638 |
639 | return parseInt( this.dom.value.substr( 1 ), 16 );
640 |
641 | };
642 |
643 | UI.Color.prototype.setValue = function ( value ) {
644 |
645 | this.dom.value = value;
646 |
647 | return this;
648 |
649 | };
650 |
651 | UI.Color.prototype.setHexValue = function ( hex ) {
652 |
653 | this.dom.value = '#' + ( '000000' + hex.toString( 16 ) ).slice( - 6 );
654 |
655 | return this;
656 |
657 | };
658 |
659 |
660 | // Number
661 |
662 | UI.Number = function ( number ) {
663 |
664 | UI.Element.call( this );
665 |
666 | var scope = this;
667 |
668 | var dom = document.createElement( 'input' );
669 | dom.className = 'Number';
670 | dom.value = '0.00';
671 |
672 | dom.addEventListener( 'keydown', function ( event ) {
673 |
674 | event.stopPropagation();
675 |
676 | if ( event.keyCode === 13 ) dom.blur();
677 |
678 | }, false );
679 |
680 | this.value = 0;
681 |
682 | this.min = - Infinity;
683 | this.max = Infinity;
684 |
685 | this.precision = 2;
686 | this.step = 1;
687 | this.unit = '';
688 |
689 | this.dom = dom;
690 |
691 | this.setValue( number );
692 |
693 | var changeEvent = document.createEvent( 'HTMLEvents' );
694 | changeEvent.initEvent( 'change', true, true );
695 |
696 | var distance = 0;
697 | var onMouseDownValue = 0;
698 |
699 | var pointer = [ 0, 0 ];
700 | var prevPointer = [ 0, 0 ];
701 |
702 | function onMouseDown( event ) {
703 |
704 | event.preventDefault();
705 |
706 | distance = 0;
707 |
708 | onMouseDownValue = scope.value;
709 |
710 | prevPointer = [ event.clientX, event.clientY ];
711 |
712 | document.addEventListener( 'mousemove', onMouseMove, false );
713 | document.addEventListener( 'mouseup', onMouseUp, false );
714 |
715 | }
716 |
717 | function onMouseMove( event ) {
718 |
719 | var currentValue = scope.value;
720 |
721 | pointer = [ event.clientX, event.clientY ];
722 |
723 | distance += ( pointer[ 0 ] - prevPointer[ 0 ] ) - ( pointer[ 1 ] - prevPointer[ 1 ] );
724 |
725 | var value = onMouseDownValue + ( distance / ( event.shiftKey ? 5 : 50 ) ) * scope.step;
726 | value = Math.min( scope.max, Math.max( scope.min, value ) );
727 |
728 | if ( currentValue !== value ) {
729 |
730 | scope.setValue( value );
731 | dom.dispatchEvent( changeEvent );
732 |
733 | }
734 |
735 | prevPointer = [ event.clientX, event.clientY ];
736 |
737 | }
738 |
739 | function onMouseUp( event ) {
740 |
741 | document.removeEventListener( 'mousemove', onMouseMove, false );
742 | document.removeEventListener( 'mouseup', onMouseUp, false );
743 |
744 | if ( Math.abs( distance ) < 2 ) {
745 |
746 | dom.focus();
747 | dom.select();
748 |
749 | }
750 |
751 | }
752 |
753 | function onChange( event ) {
754 |
755 | scope.setValue( dom.value );
756 |
757 | }
758 |
759 | function onFocus( event ) {
760 |
761 | dom.style.backgroundColor = '';
762 | dom.style.cursor = '';
763 |
764 | }
765 |
766 | function onBlur( event ) {
767 |
768 | dom.style.backgroundColor = 'transparent';
769 | dom.style.cursor = 'col-resize';
770 |
771 | }
772 |
773 | onBlur();
774 |
775 | dom.addEventListener( 'mousedown', onMouseDown, false );
776 | dom.addEventListener( 'change', onChange, false );
777 | dom.addEventListener( 'focus', onFocus, false );
778 | dom.addEventListener( 'blur', onBlur, false );
779 |
780 | return this;
781 |
782 | };
783 |
784 | UI.Number.prototype = Object.create( UI.Element.prototype );
785 | UI.Number.prototype.constructor = UI.Number;
786 |
787 | UI.Number.prototype.getValue = function () {
788 |
789 | return this.value;
790 |
791 | };
792 |
793 | UI.Number.prototype.setValue = function ( value ) {
794 |
795 | if ( value !== undefined ) {
796 |
797 | value = parseFloat( value );
798 |
799 | if ( value < this.min ) value = this.min;
800 | if ( value > this.max ) value = this.max;
801 |
802 | this.value = value;
803 | this.dom.value = value.toFixed( this.precision ) + ' ' + this.unit;
804 |
805 | }
806 |
807 | return this;
808 |
809 | };
810 |
811 | UI.Number.prototype.setPrecision = function ( precision ) {
812 |
813 | this.precision = precision;
814 |
815 | return this;
816 |
817 | };
818 |
819 | UI.Number.prototype.setStep = function ( step ) {
820 |
821 | this.step = step;
822 |
823 | return this;
824 |
825 | };
826 |
827 | UI.Number.prototype.setRange = function ( min, max ) {
828 |
829 | this.min = min;
830 | this.max = max;
831 |
832 | return this;
833 |
834 | };
835 |
836 | UI.Number.prototype.setUnit = function ( unit ) {
837 |
838 | this.unit = unit;
839 |
840 | return this;
841 |
842 | };
843 |
844 | // Integer
845 |
846 | UI.Integer = function ( number ) {
847 |
848 | UI.Element.call( this );
849 |
850 | var scope = this;
851 |
852 | var dom = document.createElement( 'input' );
853 | dom.className = 'Number';
854 | dom.value = '0';
855 |
856 | dom.addEventListener( 'keydown', function ( event ) {
857 |
858 | event.stopPropagation();
859 |
860 | }, false );
861 |
862 | this.value = 0;
863 |
864 | this.min = - Infinity;
865 | this.max = Infinity;
866 |
867 | this.step = 1;
868 |
869 | this.dom = dom;
870 |
871 | this.setValue( number );
872 |
873 | var changeEvent = document.createEvent( 'HTMLEvents' );
874 | changeEvent.initEvent( 'change', true, true );
875 |
876 | var distance = 0;
877 | var onMouseDownValue = 0;
878 |
879 | var pointer = [ 0, 0 ];
880 | var prevPointer = [ 0, 0 ];
881 |
882 | function onMouseDown( event ) {
883 |
884 | event.preventDefault();
885 |
886 | distance = 0;
887 |
888 | onMouseDownValue = scope.value;
889 |
890 | prevPointer = [ event.clientX, event.clientY ];
891 |
892 | document.addEventListener( 'mousemove', onMouseMove, false );
893 | document.addEventListener( 'mouseup', onMouseUp, false );
894 |
895 | }
896 |
897 | function onMouseMove( event ) {
898 |
899 | var currentValue = scope.value;
900 |
901 | pointer = [ event.clientX, event.clientY ];
902 |
903 | distance += ( pointer[ 0 ] - prevPointer[ 0 ] ) - ( pointer[ 1 ] - prevPointer[ 1 ] );
904 |
905 | var value = onMouseDownValue + ( distance / ( event.shiftKey ? 5 : 50 ) ) * scope.step;
906 | value = Math.min( scope.max, Math.max( scope.min, value ) ) | 0;
907 |
908 | if ( currentValue !== value ) {
909 |
910 | scope.setValue( value );
911 | dom.dispatchEvent( changeEvent );
912 |
913 | }
914 |
915 | prevPointer = [ event.clientX, event.clientY ];
916 |
917 | }
918 |
919 | function onMouseUp( event ) {
920 |
921 | document.removeEventListener( 'mousemove', onMouseMove, false );
922 | document.removeEventListener( 'mouseup', onMouseUp, false );
923 |
924 | if ( Math.abs( distance ) < 2 ) {
925 |
926 | dom.focus();
927 | dom.select();
928 |
929 | }
930 |
931 | }
932 |
933 | function onChange( event ) {
934 |
935 | scope.setValue( dom.value );
936 |
937 | }
938 |
939 | function onFocus( event ) {
940 |
941 | dom.style.backgroundColor = '';
942 | dom.style.cursor = '';
943 |
944 | }
945 |
946 | function onBlur( event ) {
947 |
948 | dom.style.backgroundColor = 'transparent';
949 | dom.style.cursor = 'col-resize';
950 |
951 | }
952 |
953 | onBlur();
954 |
955 | dom.addEventListener( 'mousedown', onMouseDown, false );
956 | dom.addEventListener( 'change', onChange, false );
957 | dom.addEventListener( 'focus', onFocus, false );
958 | dom.addEventListener( 'blur', onBlur, false );
959 |
960 | return this;
961 |
962 | };
963 |
964 | UI.Integer.prototype = Object.create( UI.Element.prototype );
965 | UI.Integer.prototype.constructor = UI.Integer;
966 |
967 | UI.Integer.prototype.getValue = function () {
968 |
969 | return this.value;
970 |
971 | };
972 |
973 | UI.Integer.prototype.setValue = function ( value ) {
974 |
975 | if ( value !== undefined ) {
976 |
977 | value = parseInt( value );
978 |
979 | this.value = value;
980 | this.dom.value = value;
981 |
982 | }
983 |
984 | return this;
985 |
986 | };
987 |
988 | UI.Number.prototype.setStep = function ( step ) {
989 |
990 | this.step = step;
991 |
992 | return this;
993 |
994 | };
995 |
996 | UI.Integer.prototype.setRange = function ( min, max ) {
997 |
998 | this.min = min;
999 | this.max = max;
1000 |
1001 | return this;
1002 |
1003 | };
1004 |
1005 |
1006 | // Break
1007 |
1008 | UI.Break = function () {
1009 |
1010 | UI.Element.call( this );
1011 |
1012 | var dom = document.createElement( 'br' );
1013 | dom.className = 'Break';
1014 |
1015 | this.dom = dom;
1016 |
1017 | return this;
1018 |
1019 | };
1020 |
1021 | UI.Break.prototype = Object.create( UI.Element.prototype );
1022 | UI.Break.prototype.constructor = UI.Break;
1023 |
1024 |
1025 | // HorizontalRule
1026 |
1027 | UI.HorizontalRule = function () {
1028 |
1029 | UI.Element.call( this );
1030 |
1031 | var dom = document.createElement( 'hr' );
1032 | dom.className = 'HorizontalRule';
1033 |
1034 | this.dom = dom;
1035 |
1036 | return this;
1037 |
1038 | };
1039 |
1040 | UI.HorizontalRule.prototype = Object.create( UI.Element.prototype );
1041 | UI.HorizontalRule.prototype.constructor = UI.HorizontalRule;
1042 |
1043 |
1044 | // Button
1045 |
1046 | UI.Button = function ( value ) {
1047 |
1048 | UI.Element.call( this );
1049 |
1050 | var dom = document.createElement( 'button' );
1051 | dom.className = 'Button';
1052 |
1053 | this.dom = dom;
1054 | this.dom.textContent = value;
1055 |
1056 | return this;
1057 |
1058 | };
1059 |
1060 | UI.Button.prototype = Object.create( UI.Element.prototype );
1061 | UI.Button.prototype.constructor = UI.Button;
1062 |
1063 | UI.Button.prototype.setLabel = function ( value ) {
1064 |
1065 | this.dom.textContent = value;
1066 |
1067 | return this;
1068 |
1069 | };
1070 |
1071 |
1072 | // Modal
1073 |
1074 | UI.Modal = function ( value ) {
1075 |
1076 | var scope = this;
1077 |
1078 | var dom = document.createElement( 'div' );
1079 |
1080 | dom.style.position = 'absolute';
1081 | dom.style.width = '100%';
1082 | dom.style.height = '100%';
1083 | dom.style.backgroundColor = 'rgba(0,0,0,0.5)';
1084 | dom.style.display = 'none';
1085 | dom.style.alignItems = 'center';
1086 | dom.style.justifyContent = 'center';
1087 | dom.addEventListener( 'click', function ( event ) {
1088 |
1089 | scope.hide();
1090 |
1091 | } );
1092 |
1093 | this.dom = dom;
1094 |
1095 | this.container = new UI.Panel();
1096 | this.container.dom.style.width = '200px';
1097 | this.container.dom.style.padding = '20px';
1098 | this.container.dom.style.backgroundColor = '#ffffff';
1099 | this.container.dom.style.boxShadow = '0px 5px 10px rgba(0,0,0,0.5)';
1100 |
1101 | this.add( this.container );
1102 |
1103 | return this;
1104 |
1105 | };
1106 |
1107 | UI.Modal.prototype = Object.create( UI.Element.prototype );
1108 | UI.Modal.prototype.constructor = UI.Modal;
1109 |
1110 | UI.Modal.prototype.show = function ( content ) {
1111 |
1112 | this.container.clear();
1113 | this.container.add( content );
1114 |
1115 | this.dom.style.display = 'flex';
1116 |
1117 | return this;
1118 |
1119 | };
1120 |
1121 | UI.Modal.prototype.hide = function () {
1122 |
1123 | this.dom.style.display = 'none';
1124 |
1125 | return this;
1126 |
1127 | };
--------------------------------------------------------------------------------
/js/ui.three.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author mrdoob / http://mrdoob.com/
3 | */
4 |
5 | UI.Texture = function ( mapping ) {
6 |
7 | UI.Element.call( this );
8 |
9 | var scope = this;
10 |
11 | var dom = document.createElement( 'span' );
12 |
13 | var form = document.createElement( 'form' );
14 |
15 | var input = document.createElement( 'input' );
16 | input.type = 'file';
17 | input.addEventListener( 'change', function ( event ) {
18 |
19 | loadFile( event.target.files[ 0 ] );
20 |
21 | } );
22 | form.appendChild( input );
23 |
24 | var canvas = document.createElement( 'canvas' );
25 | canvas.width = 32;
26 | canvas.height = 16;
27 | canvas.style.cursor = 'pointer';
28 | canvas.style.marginRight = '5px';
29 | canvas.style.border = '1px solid #888';
30 | canvas.addEventListener( 'click', function ( event ) {
31 |
32 | input.click();
33 |
34 | }, false );
35 | canvas.addEventListener( 'drop', function ( event ) {
36 |
37 | event.preventDefault();
38 | event.stopPropagation();
39 | loadFile( event.dataTransfer.files[ 0 ] );
40 |
41 | }, false );
42 | dom.appendChild( canvas );
43 |
44 | var name = document.createElement( 'input' );
45 | name.disabled = true;
46 | name.style.width = '64px';
47 | name.style.border = '1px solid #ccc';
48 | dom.appendChild( name );
49 |
50 | function loadFile( file ) {
51 |
52 | if ( file.type.match( 'image.*' ) ) {
53 |
54 | var reader = new FileReader();
55 |
56 | if ( file.type === 'image/targa' ) {
57 |
58 | reader.addEventListener( 'load', function ( event ) {
59 |
60 | var canvas = new THREE.TGALoader().parse( event.target.result );
61 |
62 | var texture = new THREE.CanvasTexture( canvas, mapping );
63 | texture.sourceFile = file.name;
64 |
65 | scope.setValue( texture );
66 |
67 | if ( scope.onChangeCallback ) scope.onChangeCallback();
68 |
69 | }, false );
70 |
71 | reader.readAsArrayBuffer( file );
72 |
73 | } else {
74 |
75 | reader.addEventListener( 'load', function ( event ) {
76 |
77 | var image = document.createElement( 'img' );
78 | image.addEventListener( 'load', function( event ) {
79 |
80 | var texture = new THREE.Texture( this, mapping );
81 | texture.sourceFile = file.name;
82 | texture.needsUpdate = true;
83 |
84 | scope.setValue( texture );
85 |
86 | if ( scope.onChangeCallback ) scope.onChangeCallback();
87 |
88 | }, false );
89 |
90 | image.src = event.target.result;
91 |
92 | }, false );
93 |
94 | reader.readAsDataURL( file );
95 |
96 | }
97 |
98 | }
99 |
100 | form.reset();
101 |
102 | }
103 |
104 | this.dom = dom;
105 | this.texture = null;
106 | this.onChangeCallback = null;
107 |
108 | return this;
109 |
110 | };
111 |
112 | UI.Texture.prototype = Object.create( UI.Element.prototype );
113 | UI.Texture.prototype.constructor = UI.Texture;
114 |
115 | UI.Texture.prototype.getValue = function () {
116 |
117 | return this.texture;
118 |
119 | };
120 |
121 | UI.Texture.prototype.setValue = function ( texture ) {
122 |
123 | var canvas = this.dom.children[ 0 ];
124 | var name = this.dom.children[ 1 ];
125 | var context = canvas.getContext( '2d' );
126 |
127 | if ( texture !== null ) {
128 |
129 | var image = texture.image;
130 |
131 | if ( image !== undefined && image.width > 0 ) {
132 |
133 | name.value = texture.sourceFile;
134 |
135 | var scale = canvas.width / image.width;
136 | context.drawImage( image, 0, 0, image.width * scale, image.height * scale );
137 |
138 | } else {
139 |
140 | name.value = texture.sourceFile + ' (error)';
141 | context.clearRect( 0, 0, canvas.width, canvas.height );
142 |
143 | }
144 |
145 | } else {
146 |
147 | name.value = '';
148 |
149 | if ( context !== null ) {
150 |
151 | // Seems like context can be null if the canvas is not visible
152 |
153 | context.clearRect( 0, 0, canvas.width, canvas.height );
154 |
155 | }
156 |
157 | }
158 |
159 | this.texture = texture;
160 |
161 | };
162 |
163 | UI.Texture.prototype.onChange = function ( callback ) {
164 |
165 | this.onChangeCallback = callback;
166 |
167 | return this;
168 |
169 | };
170 |
171 | // Outliner
172 |
173 | UI.Outliner = function ( editor ) {
174 |
175 | UI.Element.call( this );
176 |
177 | var scope = this;
178 |
179 | var dom = document.createElement( 'div' );
180 | dom.className = 'Outliner';
181 | dom.tabIndex = 0; // keyup event is ignored without setting tabIndex
182 |
183 | // hack
184 | this.scene = editor.scene;
185 |
186 | // Prevent native scroll behavior
187 | dom.addEventListener( 'keydown', function ( event ) {
188 |
189 | switch ( event.keyCode ) {
190 | case 38: // up
191 | case 40: // down
192 | event.preventDefault();
193 | event.stopPropagation();
194 | break;
195 | }
196 |
197 | }, false );
198 |
199 | // Keybindings to support arrow navigation
200 | dom.addEventListener( 'keyup', function ( event ) {
201 |
202 | switch ( event.keyCode ) {
203 | case 38: // up
204 | scope.selectIndex( scope.selectedIndex - 1 );
205 | break;
206 | case 40: // down
207 | scope.selectIndex( scope.selectedIndex + 1 );
208 | break;
209 | }
210 |
211 | }, false );
212 |
213 | this.dom = dom;
214 |
215 | this.options = [];
216 | this.selectedIndex = - 1;
217 | this.selectedValue = null;
218 |
219 | return this;
220 |
221 | };
222 |
223 | UI.Outliner.prototype = Object.create( UI.Element.prototype );
224 | UI.Outliner.prototype.constructor = UI.Outliner;
225 |
226 | UI.Outliner.prototype.selectIndex = function ( index ) {
227 |
228 | if ( index >= 0 && index < this.options.length ) {
229 |
230 | this.setValue( this.options[ index ].value );
231 |
232 | var changeEvent = document.createEvent( 'HTMLEvents' );
233 | changeEvent.initEvent( 'change', true, true );
234 | this.dom.dispatchEvent( changeEvent );
235 |
236 | }
237 |
238 | };
239 |
240 | UI.Outliner.prototype.setOptions = function ( options ) {
241 |
242 | var scope = this;
243 |
244 | while ( scope.dom.children.length > 0 ) {
245 |
246 | scope.dom.removeChild( scope.dom.firstChild );
247 |
248 | }
249 |
250 | function onClick() {
251 |
252 | scope.setValue( this.value );
253 |
254 | var changeEvent = document.createEvent( 'HTMLEvents' );
255 | changeEvent.initEvent( 'change', true, true );
256 | scope.dom.dispatchEvent( changeEvent );
257 |
258 | }
259 |
260 | // Drag
261 |
262 | var currentDrag;
263 |
264 | function onDrag( event ) {
265 |
266 | currentDrag = this;
267 |
268 | }
269 |
270 | function onDragStart( event ) {
271 |
272 | event.dataTransfer.setData( 'text', 'foo' );
273 |
274 | }
275 |
276 | function onDragOver( event ) {
277 |
278 | if ( this === currentDrag ) return;
279 |
280 | var area = event.offsetY / this.clientHeight;
281 |
282 | if ( area < 0.25 ) {
283 |
284 | this.className = 'option dragTop';
285 |
286 | } else if ( area > 0.75 ) {
287 |
288 | this.className = 'option dragBottom';
289 |
290 | } else {
291 |
292 | this.className = 'option drag';
293 |
294 | }
295 |
296 | }
297 |
298 | function onDragLeave() {
299 |
300 | if ( this === currentDrag ) return;
301 |
302 | this.className = 'option';
303 |
304 | }
305 |
306 | function onDrop( event ) {
307 |
308 | if ( this === currentDrag ) return;
309 |
310 | this.className = 'option';
311 |
312 | var scene = scope.scene;
313 | var object = scene.getObjectById( currentDrag.value );
314 |
315 | var area = event.offsetY / this.clientHeight;
316 |
317 | if ( area < 0.25 ) {
318 |
319 | var nextObject = scene.getObjectById( this.value );
320 | moveObject( object, nextObject.parent, nextObject );
321 |
322 | } else if ( area > 0.75 ) {
323 |
324 | var nextObject = scene.getObjectById( this.nextSibling.value );
325 | moveObject( object, nextObject.parent, nextObject );
326 |
327 | } else {
328 |
329 | var parentObject = scene.getObjectById( this.value );
330 | moveObject( object, parentObject );
331 |
332 | }
333 |
334 | }
335 |
336 | function moveObject( object, newParent, nextObject ) {
337 |
338 | if ( nextObject === null ) nextObject = undefined;
339 |
340 | var newParentIsChild = false;
341 |
342 | object.traverse( function ( child ) {
343 |
344 | if ( child === newParent ) newParentIsChild = true;
345 |
346 | } );
347 |
348 | if ( newParentIsChild ) return;
349 |
350 | editor.execute( new MoveObjectCommand( object, newParent, nextObject ) );
351 |
352 | var changeEvent = document.createEvent( 'HTMLEvents' );
353 | changeEvent.initEvent( 'change', true, true );
354 | scope.dom.dispatchEvent( changeEvent );
355 |
356 | }
357 |
358 | //
359 |
360 | scope.options = [];
361 |
362 | for ( var i = 0; i < options.length; i ++ ) {
363 |
364 | var div = options[ i ];
365 | div.className = 'option';
366 | scope.dom.appendChild( div );
367 |
368 | scope.options.push( div );
369 |
370 | div.addEventListener( 'click', onClick, false );
371 |
372 | if ( div.draggable === true ) {
373 |
374 | div.addEventListener( 'drag', onDrag, false );
375 | div.addEventListener( 'dragstart', onDragStart, false ); // Firefox needs this
376 |
377 | div.addEventListener( 'dragover', onDragOver, false );
378 | div.addEventListener( 'dragleave', onDragLeave, false );
379 | div.addEventListener( 'drop', onDrop, false );
380 |
381 | }
382 |
383 |
384 | }
385 |
386 | return scope;
387 |
388 | };
389 |
390 | UI.Outliner.prototype.getValue = function () {
391 |
392 | return this.selectedValue;
393 |
394 | };
395 |
396 | UI.Outliner.prototype.setValue = function ( value ) {
397 |
398 | for ( var i = 0; i < this.options.length; i ++ ) {
399 |
400 | var element = this.options[ i ];
401 |
402 | if ( element.value === value ) {
403 |
404 | element.classList.add( 'active' );
405 |
406 | // scroll into view
407 |
408 | var y = element.offsetTop - this.dom.offsetTop;
409 | var bottomY = y + element.offsetHeight;
410 | var minScroll = bottomY - this.dom.offsetHeight;
411 |
412 | if ( this.dom.scrollTop > y ) {
413 |
414 | this.dom.scrollTop = y;
415 |
416 | } else if ( this.dom.scrollTop < minScroll ) {
417 |
418 | this.dom.scrollTop = minScroll;
419 |
420 | }
421 |
422 | this.selectedIndex = i;
423 |
424 | } else {
425 |
426 | element.classList.remove( 'active' );
427 |
428 | }
429 |
430 | }
431 |
432 | this.selectedValue = value;
433 |
434 | return this;
435 |
436 | };
437 |
438 | UI.THREE = {};
439 |
440 | UI.THREE.Boolean = function ( boolean, text ) {
441 |
442 | UI.Span.call( this );
443 |
444 | this.setMarginRight( '10px' );
445 |
446 | this.checkbox = new UI.Checkbox( boolean );
447 | this.text = new UI.Text( text ).setMarginLeft( '3px' );
448 |
449 | this.add( this.checkbox );
450 | this.add( this.text );
451 |
452 | };
453 |
454 | UI.THREE.Boolean.prototype = Object.create( UI.Span.prototype );
455 | UI.THREE.Boolean.prototype.constructor = UI.THREE.Boolean;
456 |
457 | UI.THREE.Boolean.prototype.getValue = function () {
458 |
459 | return this.checkbox.getValue();
460 |
461 | };
462 |
463 | UI.THREE.Boolean.prototype.setValue = function ( value ) {
464 |
465 | return this.checkbox.setValue( value );
466 |
467 | };
--------------------------------------------------------------------------------
/src/Editor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Unravel with help from Fish on 12/1/2016.
3 | */
4 |
5 | var TILE_COUNT = 48;
6 | var TILE_MESH_SIZE = 1;
7 | var SectorX = 51;
8 | var SectorY = 47;
9 | var sectorsLoaded = false;
10 | var container;
11 | var camera, scene, renderer, controls;
12 | var mouse, raycaster, isShiftDown = false;
13 | var camera, stats;
14 | var Sectors = new Array();
15 | var selected;
16 | var overlay_map = {};
17 | var Tiles;
18 | var mesh;
19 | var masterGeometry;
20 | var offsets = [[-1, -1],[0, -1],[1, -1], [-1, 0],[0, 0],[1, 0], [-1, 1],[0, 1],[1, 1]];
21 | var gui = new dat.GUI();
22 | var guiItems =
23 | {
24 | localXY: "0, 0",
25 | sectorName: "0",
26 | sectorIdx: 0,
27 | tileIdx: 0,
28 | rscXY: "0",
29 | tile_elevation: 0,
30 | tile_texture: 0,
31 | tile_overlay: 0,
32 | tile_horizontal: 0,
33 | tile_vertical: 0,
34 | tile_diagonal: 0,
35 | tile_roof: 0
36 |
37 | };
38 |
39 |
40 | function initEditor() {
41 | try {
42 | setup();
43 | html();
44 | animate();
45 | } catch(err) {
46 | alert(err);
47 | }
48 | }
49 |
50 | function openFile(event) {
51 | var file = event.target.files[0];
52 | var jsZip = new JSZip()
53 | jsZip.loadAsync(file).then(function (zip) {
54 |
55 | for(var i=0; i < offsets.length; i++) {
56 | var name = "h0x" + (SectorX + offsets[i][0]) + "y" + (SectorY + offsets[i][1]);
57 | console.error("reading " + name);
58 | zip.file(name).async('arraybuffer').then(function (fileData) {
59 | var view = new DataView(fileData);
60 | Sectors.push(view);
61 | })
62 | }
63 | })
64 | var timer = setInterval(load_timer, 500);
65 | function load_timer() {
66 | if(sectorsLoaded) {
67 | clearInterval(timer);
68 | sectorsLoaded = false;
69 | unpackSectors();
70 | updateSectors();
71 | camera.position.set(0,0,200);
72 | //camera.target.set(0, 0, 0);
73 | camera.rotation.set(-200, 0, 0);
74 | controls = new THREE.OrbitControls( camera, renderer.domElement );
75 | controls.enableDamping = true;
76 | controls.dampingFactor = 0.25;
77 | controls.zoomSpeed = 0.5;
78 | //controls.target..x -= 100;
79 | //controls.target.set(50, (48/2*3), -100);
80 |
81 | controls.enabled = true;
82 | controls.enablePan = true;
83 | controls.enableZoom = true;
84 | controls.update();
85 | animate();
86 | }
87 | }
88 |
89 | }
90 |
91 |
92 | function unpackSectors() {
93 | Tiles = new Array((TILE_COUNT*TILE_COUNT) * Sectors.length);
94 | var sectX = 0;
95 | var sectY = 0;
96 | for(var s=0; s < Sectors.length; s++) {
97 | if (sectX == Math.sqrt(Sectors.length)) {
98 | sectX = 0;
99 | sectY++;
100 | }
101 | var sectorIndex = s;
102 | var idx = 0;
103 | var view = Sectors[s];
104 | for (var x = 0; x < TILE_COUNT; x++) {
105 | for (var y = 0; y < TILE_COUNT; y++) {
106 | var tile = new Tile(sectorIndex, sectX, sectY, x, y, view.getUint8(idx), view.getUint8(idx + 1), view.getUint8(idx + 2), view.getUint8(idx + 3), view.getUint8(idx + 4), view.getUint8(idx + 5), view.getUint32(idx + 6), s, (SectorX + offsets[sectorIndex][0]),(SectorY + offsets[sectorIndex][1]) );
107 |
108 | Tiles[((x * 48) + y) + 48 * 48 * sectorIndex] = tile;
109 | idx += 10;
110 | }
111 | }
112 | sectX++;
113 | }
114 | sectorsLoaded = true;
115 | }
116 |
117 |
118 | <<<<<<< HEAD
119 | =======
120 | function updateSectors() {
121 |
122 |
123 | //scene.remove(mesh);
124 | masterGeometry = new THREE.PlaneGeometry(0 , 0 , 0, 0);
125 |
126 | var sectX = 0;
127 | var sectY = 0;
128 |
129 | for(var s=0; s < Sectors.length; s++) {
130 | if (sectX == Math.sqrt(Sectors.length)) {
131 | sectX = 0;
132 | sectY++;
133 | }
134 | var sectorIndex = s;
135 | var idx = 0;
136 | var view = Sectors[s];
137 | var tmesh = drawSector(sectorIndex);
138 | tmesh.position.set(-(TILE_MESH_SIZE * TILE_COUNT / 2) - 48 * sectX, -(TILE_MESH_SIZE * TILE_COUNT / 2) - 48 * sectY, 0);
139 | tmesh.rotation.z = -Math.PI / 2;
140 |
141 | tmesh.updateMatrix();
142 | masterGeometry.merge(tmesh.geometry, tmesh.matrix);
143 | sectX++;
144 |
145 | }
146 |
147 |
148 |
149 |
150 | //if(mesh != null) {
151 | mesh = new THREE.Mesh(masterGeometry, new THREE.MeshFaceMaterial(materials));
152 |
153 | /// var geo = new THREE.WireframeGeometry( masterGeometry); // or WireframeGeometry
154 | //var mat = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 2 } );
155 | //var wireframe = new THREE.LineSegments( geo, mat );
156 | //mesh.add( wireframe );
157 | scene.add(mesh);
158 | // }
159 |
160 | }
161 |
162 | >>>>>>> origin/master
163 | function drawSector(sectorIndex) {
164 |
165 | var geometry = new THREE.PlaneGeometry((TILE_MESH_SIZE * TILE_COUNT), (TILE_MESH_SIZE * TILE_COUNT), TILE_COUNT, TILE_COUNT);
166 |
167 | /**
168 | *
169 | * Tile Elevations
170 | *
171 | */
172 |
173 | for (var xx = 0; xx < 48; xx++) {
174 | for (var yy = 0; yy < 48; yy++) {
175 | t = (xx * 48 + yy) + 48 * 48 * sectorIndex;
176 | v = (xx * 49 + yy);
177 | if (Tiles[t] == null) continue;
178 |
179 | var base = 0;
180 | var multi = 0.025;
181 | if(Tiles[t].groundElevation < 128) {
182 | base -= multi * (128 - Tiles[t].groundElevation);
183 | } else {
184 | base += multi * Math.abs((128 - Tiles[t].groundElevation));
185 | }
186 | geometry.vertices[v].z = base;
187 | }
188 | }
189 |
190 |
191 |
192 | /**
193 | *
194 | * Tile gradients & overlays
195 | *
196 | */
197 | l = geometry.faces.length / 2;
198 | for (var i = 0; i < l; i++) {
199 | var j = 2 * i;
200 | var tmpIdx = i + 48 * 48 * sectorIndex;
201 | var til = Tiles[tmpIdx];
202 |
203 | if (til == null)
204 | continue;
205 |
206 | if (til.groundTexture > 0) { // tile gradient
207 | geometry.faces[j].materialIndex = til.groundTexture + 500;
208 | geometry.faces[j + 1].materialIndex = til.groundTexture + 500;
209 | }
210 | til.faceIdx = j;
211 | // fix all this BS
212 | var obj = overlay_map[til.groundOverlay];
213 | if(obj != null) {
214 | if(til.groundOverlay != 1111) { // change this to 1, to work with roads
215 | // var tempTil = Tiles[tmpIdx - 1];
216 | // var tempTil2 = Tiles[tmpIdx + 1];
217 | var tempTil = Tiles[tmpIdx - 1];
218 | var tempTil2 = Tiles[tmpIdx - (TILE_COUNT * 1)];
219 |
220 | var top = Tiles[tmpIdx - (TILE_COUNT * 1)];
221 | var topRight = Tiles[tmpIdx - (TILE_COUNT * 1) - 1];
222 | var topLeft = Tiles[tmpIdx - (TILE_COUNT * 1) + 1];
223 | var right = Tiles[tmpIdx - 1];
224 | var left = Tiles[tmpIdx + 1];
225 |
226 | var bottom = Tiles[tmpIdx + (TILE_COUNT * 1)];
227 | var bottomRight = Tiles[tmpIdx + (TILE_COUNT * 1) - 1];
228 | var bottomLeft = Tiles[tmpIdx + (TILE_COUNT * 1) + 1];
229 |
230 | if(til.groundOverlay != 1) {
231 | geometry.faces[j].materialIndex = til.groundOverlay;
232 | geometry.faces[j + 1].materialIndex = til.groundOverlay;
233 | continue;
234 |
235 | }
236 | if(top != null && topRight != null && right != null && bottom != null && bottomRight != null) {
237 | geometry.faces[j].materialIndex = til.groundOverlay;
238 | geometry.faces[j + 1].materialIndex = til.groundOverlay;
239 | /*if(top.groundOverlay != til.groundOverlay && topRight.groundOverlay != til.groundOverlay && right.groundOverlay != til.groundOverlay && bottom.groundOverlay == til.groundOverlay && bottomRight.groundOverlay == til.groundOverlay) {
240 | geometry.faces[j + 1].materialIndex = til.groundOverlay;
241 | continue;
242 | } else if(bottom.groundOverlay != til.groundOverlay && left.groundOverlay != til.groundOverlay && bottomLeft.groundOverlay != til.groundOverlay && top.groundOverlay == til.groundOverlay && topRight.groundOverlay == til.groundOverlay) {
243 |
244 |
245 | geometry.faces[j].materialIndex = til.groundOverlay;
246 | continue;
247 | }*/
248 | /* if(left.horizontalWall > 0 || til.horizontalWall > 0) {
249 | geometry.faces[j].materialIndex = til.groundOverlay;
250 | geometry.faces[j + 1].materialIndex = til.groundOverlay;
251 |
252 |
253 | }
254 | else*/
255 |
256 |
257 | if(top.groundOverlay != til.groundOverlay && right.groundOverlay != til.groundOverlay) {
258 |
259 | geometry.faces[j + 1].materialIndex = til.groundOverlay;
260 | } else if(bottom.groundOverlay != til.groundOverlay && left.groundOverlay != til.groundOverlay) {
261 | geometry.faces[j].materialIndex = til.groundOverlay;
262 | geometry.faces[j + 1].materialIndex = til.groundOverlay;
263 | }
264 | else {
265 | geometry.faces[j].materialIndex = til.groundOverlay;
266 | geometry.faces[j + 1].materialIndex = til.groundOverlay;
267 | }
268 | }
269 |
270 | if(tempTil != null && tempTil2 != null) {
271 | /* if(tempTil.groundOverlay == til.groundOverlay && tempTil2.groundOverlay == til.groundOverlay) {
272 | geometry.faces[j].materialIndex = til.groundOverlay;
273 | geometry.faces[j + 1].materialIndex = til.groundOverlay;
274 | } else if(tempTil.groundOverlay == til.groundOverlay && tempTil2.groundOverlay != til.groundOverlay) {
275 | geometry.faces[j].materialIndex = til.groundOverlay;
276 |
277 | } else if(tempTil.groundOverlay != til.groundOverlay && tempTil2.groundOverlay == til.groundOverlay) {
278 | geometry.faces[j + 1].materialIndex = til.groundOverlay;
279 | }*/
280 | }
281 |
282 | var tempTil = Tiles[tmpIdx + 1];
283 | var tempTil2 = Tiles[tmpIdx + (TILE_COUNT * 1)];
284 | if(tempTil != null && tempTil2 != null) {
285 | /* if(tempTil.groundOverlay == til.groundOverlay && tempTil2.groundOverlay == til.groundOverlay) {
286 | geometry.faces[j].materialIndex = til.groundOverlay;
287 | geometry.faces[j + 1].materialIndex = til.groundOverlay;
288 | } else if(tempTil.groundOverlay == til.groundOverlay && tempTil2.groundOverlay != til.groundOverlay) {
289 | // geometry.faces[j].materialIndex = til.groundOverlay;
290 | } else if(tempTil.groundOverlay != til.groundOverlay && tempTil2.groundOverlay == til.groundOverlay) {
291 | // geometry.faces[j + 1].materialIndex = til.groundOverlay;
292 | }*/
293 | }
294 | // geometry.faces[j].materialIndex = til.groundOverlay; // top right face
295 | } else {
296 | geometry.faces[j].materialIndex = til.groundOverlay;
297 | geometry.faces[j + 1].materialIndex = til.groundOverlay; // bottom left face
298 | }
299 |
300 | }
301 | }
302 | /**
303 | *
304 | * Walls
305 | *
306 | */
307 | var tempGeom = new THREE.PlaneGeometry(0, 0);
308 | var tempMesh = new THREE.Mesh(tempGeom, new THREE.MeshFaceMaterial(materials));
309 | l = geometry.faces.length / 2;
310 |
311 |
312 |
313 |
314 | for (var i = 0; i < l; i++) {
315 | var j = 2 * i;
316 | var til = Tiles[i + 48 * 48 * sectorIndex];
317 | if (til == null)
318 | continue;
319 |
320 | var base = 0;
321 | var multi = 0.025;
322 | if(til.groundElevation < 128) {
323 | base -= multi * (128 - til.groundElevation);
324 | } else {
325 | base += multi * Math.abs((128 - til.groundElevation));
326 | }
327 | if (til.verticalWall > 0) {
328 | var overlayGeom = new THREE.PlaneGeometry(1, 1);
329 | var obj = overlay_map[til.verticalWall + 300];
330 | if(obj != null) {
331 | overlayGeom.faces[0].materialIndex = til.verticalWall + 300;
332 | overlayGeom.faces[1].materialIndex = til.verticalWall + 300;
333 | var wall = new THREE.Mesh(overlayGeom, new THREE.MeshFaceMaterial(materials));
334 | wall.rotation.x = Math.PI / 2;
335 | wall.position.x = til.x - (TILE_COUNT / 2) + 0.5;
336 | wall.position.y = til.y - (TILE_COUNT / 2);
337 | wall.position.z = base + 0.5;
338 | wall.updateMatrix();
339 | tempGeom.merge(wall.geometry, wall.matrix);
340 | }
341 | }
342 |
343 | if (til.horizontalWall > 0) {
344 | var overlayGeom = new THREE.PlaneGeometry(1, 1);
345 | var obj = overlay_map[til.horizontalWall + 350];
346 | if(obj != null) {
347 | overlayGeom.faces[0].materialIndex = til.horizontalWall + 350;
348 | overlayGeom.faces[1].materialIndex = til.horizontalWall + 350;
349 |
350 | var wall = new THREE.Mesh(overlayGeom, new THREE.MeshFaceMaterial(materials));
351 | wall.rotation.y = Math.PI / 2;
352 | wall.position.x = til.x - (TILE_COUNT / 2);
353 | wall.position.y = til.y - (TILE_COUNT / 2) + 0.5;
354 | wall.position.z = base + 0.5;
355 | wall.updateMatrix();
356 | tempGeom.merge(wall.geometry, wall.matrix);
357 | }
358 | }
359 |
360 | if (til.diagonalWall > 0) {
361 | var overlayGeom = new THREE.PlaneGeometry(1, 1);
362 |
363 | var obj = overlay_map[(til.diagonalWall >= 12000 ? (til.diagonalWall - 12000) : til.diagonalWall) + 300];
364 | if(obj != null) {
365 |
366 | overlayGeom.faces[0].materialIndex = (til.diagonalWall >= 12000 ? (til.diagonalWall - 12000) : til.diagonalWall) + 300;
367 | overlayGeom.faces[1].materialIndex = (til.diagonalWall >= 12000 ? (til.diagonalWall - 12000) : til.diagonalWall) + 300;
368 |
369 | var wall = new THREE.Mesh(overlayGeom, new THREE.MeshFaceMaterial(materials));
370 | wall.scale.set(1.42,1.42,1)
371 | var left = til.diagonalWall >= 12000;
372 |
373 | wall.position.y = til.y - (TILE_COUNT / 2) + 0.5;
374 | wall.position.z = base + 0.5;
375 | wall.position.x = til.x - (TILE_COUNT / 2) + 0.5;
376 | if(left) {
377 | wall.rotation.y = -(Math.PI / 4);
378 | wall.rotation.x = -(-1 * Math.PI / 2);
379 |
380 | } else {
381 | wall.rotation.y = (Math.PI / 4);
382 | wall.rotation.x = (1 * Math.PI / 2);
383 |
384 | }
385 |
386 | wall.updateMatrix();
387 | tempGeom.merge(wall.geometry, wall.matrix);
388 | } else {
389 | console.log("null diagonal wall: " + til.diagonalWall + " : " + (til.diagonalWall >= 12000 ? (til.diagonalWall - 12000) : til.diagonalWall) + 400);
390 | }
391 | }
392 | }
393 |
394 | tempMesh.rotation.z = -Math.PI / 2;
395 | tempMesh.updateMatrix();
396 | geometry.merge(tempMesh.geometry, tempMesh.matrix);
397 |
398 | var tmesh = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(materials));
399 | return tmesh;
400 |
401 | }
402 |
403 | function updateSectors() {
404 | console.time('someFunction');
405 |
406 | //scene.remove(mesh);
407 | masterGeometry = new THREE.PlaneGeometry(0 , 0 , 0, 0);
408 |
409 | var sectX = 0;
410 | var sectY = 0;
411 |
412 | for(var s=0; s < Sectors.length; s++) {
413 | if (sectX == Math.sqrt(Sectors.length)) {
414 | sectX = 0;
415 | sectY++;
416 | }
417 | var sectorIndex = s;
418 | var idx = 0;
419 | var view = Sectors[s];
420 | var tmesh = drawSector(sectorIndex);
421 | tmesh.position.set(-(TILE_MESH_SIZE * TILE_COUNT / 2) - 48 * sectX, -(TILE_MESH_SIZE * TILE_COUNT / 2) - 48 * sectY, 0);
422 | tmesh.rotation.z = -Math.PI / 2;
423 |
424 | tmesh.updateMatrix();
425 | masterGeometry.merge(tmesh.geometry, tmesh.matrix);
426 | sectX++;
427 |
428 | }
429 |
430 |
431 |
432 | console.timeEnd('someFunction');
433 | var add = mesh == null;
434 | mesh = new THREE.Mesh(masterGeometry, new THREE.MeshFaceMaterial(materials));
435 |
436 | var geo = new THREE.WireframeGeometry( masterGeometry); // or WireframeGeometry
437 | var mat = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 2 } );
438 | var wireframe = new THREE.LineSegments( geo, mat );
439 | //mesh.add( wireframe );
440 | scene.add(mesh);
441 |
442 | }
443 |
444 | function setup() {
445 |
446 | prepMaterials();
447 | scene = new THREE.Scene();
448 | camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
449 | var light = new THREE.AmbientLight( 0x404040 ); // soft white light
450 | // scene.add( light );
451 | raycaster = new THREE.Raycaster();
452 | mouse = new THREE.Vector2();
453 | renderer = new THREE.WebGLRenderer({ alpha: true } );
454 | renderer.setClearColor( 0x000000 );
455 | scene.background = new THREE.Color( 0xaaaaaa );
456 | renderer.setPixelRatio( window.devicePixelRatio );
457 | renderer.setSize( window.innerWidth, window.innerHeight );
458 | // var axisHelper = new THREE.AxisHelper( 5 );
459 | // scene.add( axisHelper );
460 |
461 | camera.updateProjectionMatrix();
462 |
463 | // controls.update();
464 | document.addEventListener( 'mousedown', onDocumentMouseDown, false );
465 | // document.addEventListener( 'keydown', onDocumentKeyDown, false );
466 | // document.addEventListener( 'keyup', onDocumentKeyUp, false );
467 |
468 | }
469 |
470 | function animate() {
471 | stats.begin();
472 |
473 |
474 | requestAnimationFrame(animate);
475 | renderer.render(scene, camera);
476 |
477 | if(controls != null)
478 | controls.update();
479 | stats.end();
480 | }
481 |
482 | function html() {
483 | stats = new Stats();
484 | stats.showPanel( 0 );
485 | // document.body.appendChild( stats.dom );
486 | //var top = document.createElement('div');
487 | //top.innerHTML = '
';
488 | //document.body.appendChild(top);
489 | container = document.createElement('div');
490 | document.body.appendChild(container);
491 | var info = document.createElement('div');
492 | info.style.position = 'absolute';
493 | info.style.top = '10px';
494 | info.style.width = '100%';
495 | info.style.textAlign = 'center';
496 | // info.innerHTML = '
';
497 |
498 | //container.appendChild(info);
499 | container.appendChild(renderer.domElement);
500 | window.addEventListener( 'resize', onWindowResize, false );
501 |
502 |
503 | /* var button = document.getElementById("rendButton");
504 | button.addEventListener("click",function(e){
505 | unpackSectors();
506 | updateSectors();
507 | controls = new THREE.OrbitControls( camera, renderer.domElement );
508 | controls.enableDamping = true;
509 | controls.dampingFactor = 0.25;
510 | controls.zoomSpeed = 0.5;
511 | camera.position.set(0, 0, 200);
512 | controls.enabled = false;
513 | controls.enabled = true;
514 | controls.enablePan = true;
515 | controls.enableZoom = true;
516 | controls.update();
517 | animate();
518 |
519 | },false);*/
520 | }
521 |
522 | function onWindowResize() {
523 | console.error(camera.position.x + ", " + camera.position.y + ", " +camera.position.z);
524 | console.error(camera.rotation.x + ", " + camera.rotation.y + ", " +camera.rotation.z);
525 | console.error("tgt: " + controls.target.x + ", " + controls.target.y + ", " + controls.target.z);
526 | console.error("obj: " + controls.object.position.x + ", " + controls.object.position.y + ", " + controls.object.position.z);
527 | console.error(controls.zoom);
528 | camera.aspect = window.innerWidth / window.innerHeight;
529 | camera.updateProjectionMatrix();
530 | renderer.setSize(window.innerWidth, window.innerHeight);
531 | animate();
532 | }
533 |
534 | function onDocumentMouseDown( event ) {
535 |
536 | if(event.button != 0)
537 | return;
538 | event.preventDefault();
539 | mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
540 | mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
541 | raycaster.setFromCamera( mouse, camera );
542 |
543 | var intersects = raycaster.intersectObjects(scene.children );
544 | if ( intersects.length > 0 ) {
545 |
546 | var intersect = intersects[ 0 ];
547 |
548 | var x = Math.floor(Math.abs(intersect.point.x));
549 | var y = Math.floor(Math.abs(intersect.point.y));
550 |
551 | var tempSectX = 0;
552 | var tempSectY = 0;
553 | while(x >= 48){
554 | x -= 48;
555 | tempSectX++;
556 | }
557 | while(y >= 48){
558 | y -= 48;
559 | tempSectY++;
560 | }
561 |
562 | var sectorIndex = 3 * tempSectY + tempSectX;
563 |
564 | //console.log(" X: " + x + " Y: " + y + " SX: " + tempSectX + " SY: " + tempSectY + " sectorIndex: " + sectorIndex) ;
565 |
566 | var tile = ((x * 48) + y) + 48 * 48 * sectorIndex;
567 | if(Tiles == null)
568 | return;
569 | var tt = Tiles[tile];
570 | if(tt == null)
571 | return;
572 |
573 | if (tt.x == x && tt.y == y) {
574 |
575 | // selected.open();
576 | tt.groundElevation = 255;
577 | // updateSectors();
578 | console.log("SUCCESS");
579 |
580 | var sectName = "h0x" + (SectorX + offsets[tt.sector][0]) + "y" + (SectorY + offsets[tt.sector][1]);
581 | guiItems.localXY = tt.x + ", " + tt.y;
582 | var rscX = ((tt.absoluteSectorX - 48) * 48) + tt.x;
583 | var rscY = ((((tt.absoluteSectorY - 36) * 48) + tt.y + 96) - 144) + (0 * 944) + 48 - 48;
584 | guiItems.rscXY = rscX + ", " + rscY;
585 | ui_coords.setValue("RSC XY: " + rscX + ", " + rscY);
586 | ui_local_coords.setValue("Local XY: " + tt.x + ", " + tt.y);
587 | sectorIdx.setValue("Sector Index: " + tt.sector);
588 | sectorName.setValue("Sector Name: " + sectName);
589 | tileIdx.setValue("Tile Index: " + tile);
590 | tile_elevation.setValue("Elevation: " + tt.groundElevation);
591 | tile_overlay.setValue("Overlay: " + tt.groundOverlay);
592 | tile_texture.setValue("Texture: " + tt.groundTexture);
593 | tile_horizontal.setValue("Horizontal Wall: " + tt.horizontalWall);
594 | tile_vertical.setValue("Vertical Wall: " + tt.verticalWall);
595 | tile_diagonal.setValue("Diagonal Wall: " + tt.diagonalWall);
596 | tile_roof.setValue("Roof Texture: " + tt.roofTexture);
597 |
598 | // tt.groundElevation = 255;
599 | masterGeometry.faces[j].materialIndex = til.groundTexture + 500;
600 | masterGeometry.faces[j + 1].materialIndex = til.groundTexture + 500;
601 |
602 | /* // scene.remove(mesh);
603 | var tmesh = drawSector(sectorIndex);
604 | tmesh.position.set(-(TILE_MESH_SIZE * TILE_COUNT / 2) - 48 * tt.sectX, -(TILE_MESH_SIZE * TILE_COUNT / 2) - 48 * tt.sectY, 0);
605 | tmesh.rotation.z = -Math.PI / 2;
606 |
607 | tmesh.updateMatrix();
608 | masterGeometry.merge(tmesh.geometry, tmesh.matrix);
609 | mesh.geometry.computeFaceNormals();
610 | mesh.geometry.computeVertexNormals();
611 | mesh.geometry.normalsNeedUpdate = true;
612 | mesh.geometry.verticesNeedUpdate = true;
613 | mesh.geometry.dynamic = true;
614 | //scene.add(mesh);
615 | animate();*/
616 |
617 |
618 | }
619 | else console.log("FAIL");
620 | // var voxel = new THREE.Mesh( cubeGeometry, cubeMaterial );
621 | // voxel.position.copy( intersect.point ).add( intersect.face.normal );
622 | // voxel.position.divideScalar( 50 ).floor().multiplyScalar( 50 ).addScalar( 25 );
623 | //scene.add( voxel );
624 |
625 | //objects.push( voxel );
626 |
627 |
628 | }
629 |
630 | }
631 |
632 | function onDocumentKeyDown( event ) {
633 | /*switch( event.keyCode ) {
634 | case 16: isShiftDown = true; break;
635 | }*/
636 | }
637 |
638 | function onDocumentKeyUp( event ) {
639 | /* switch( event.keyCode ) {
640 | case 16: isShiftDown = false; break;
641 | }*/
642 | }
--------------------------------------------------------------------------------
/src/Materials.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Hayden on 12/10/2016.
3 | */
4 |
5 | var materials = [];
6 |
7 | function prepMaterials() {
8 |
9 | // ground textures start at 500, to give room for other materials
10 | materials[0] = new THREE.MeshBasicMaterial({color: 0xffffff});
11 | for (var i = 0; i < tileColors.length; i++) {
12 | materials[500 + i] = new THREE.MeshBasicMaterial({
13 | color: tileColors[i]
14 | });
15 | }
16 |
17 | var floor = new THREE.ImageUtils.loadTexture('img/3223.png');
18 | floor.wrapS = floor.wrapT = THREE.RepeatWrapping;
19 | floor.repeat.set(64, 64);
20 |
21 | var water = new THREE.ImageUtils.loadTexture('img/3221.png');
22 | water.wrapS = water.wrapT = THREE.RepeatWrapping;
23 | water.repeat.set(64, 64);
24 |
25 |
26 | // index is the overlay ID.
27 | overlay_map[1] = new THREE.MeshBasicMaterial({color: 0x404040}); // grey tile
28 |
29 | overlay_map[5] = new THREE.MeshBasicMaterial({color: 0x404040}); //grey tile
30 | overlay_map[6] = new THREE.MeshBasicMaterial({color: 0x6F0410}); // red tile
31 | overlay_map[16] = new THREE.MeshBasicMaterial({color: 0x000000}); // black tile
32 | overlay_map[8] = new THREE.MeshBasicMaterial({color: 0x000000}); // black tile
33 | overlay_map[9] = new THREE.MeshBasicMaterial({color: 0xA9A9A9}); // grey mountain side surface
34 | // new THREE.MeshBasicMaterial({color: 0x367f23});
35 |
36 | overlay_map[3] = new THREE.MeshBasicMaterial({map: floor}); // floor wooden
37 | overlay_map[2] = new THREE.MeshBasicMaterial({map: water}); // water
38 | // vertical walls starts at 300
39 | overlay_map[300 + 1] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3222.png'), side: THREE.DoubleSide});
40 | overlay_map[300 + 8] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3222.png'), side: THREE.DoubleSide});
41 | overlay_map[300 + 4] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3222w.png'), side: THREE.DoubleSide});
42 | overlay_map[300 + 5] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3230.png'), side: THREE.DoubleSide, transparent: true});
43 | overlay_map[300 + 128] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3230.png'), side: THREE.DoubleSide, transparent: true});
44 | overlay_map[300 + 15] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3241.png'), side: THREE.DoubleSide});
45 | overlay_map[300 + 16] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3241w.png'), side: THREE.DoubleSide});
46 | overlay_map[300 + 6] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/6.png'), side: THREE.DoubleSide, transparent: true});
47 | overlay_map[300 + 7] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/7.bmp'), side: THREE.DoubleSide});
48 | overlay_map[300 + 14] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/14.png'), side: THREE.DoubleSide});
49 | overlay_map[300 + 35] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/35.bmp'), side: THREE.DoubleSide});
50 | overlay_map[300 + 19] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3243.png'), side: THREE.DoubleSide});
51 | overlay_map[300 + 42] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/42.png'), side: THREE.DoubleSide, transparent: true});
52 | overlay_map[300 + 11] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/11.png'), side: THREE.DoubleSide, transparent: true});
53 |
54 |
55 | // horizontal walls start at 350
56 | overlay_map[350 + 1] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3222v.png'), side: THREE.DoubleSide});
57 | overlay_map[350 + 11] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/11v.png'), side: THREE.DoubleSide, transparent: true});
58 | overlay_map[350 + 6] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/6v.png'), side: THREE.DoubleSide, transparent: true});
59 | overlay_map[350 + 7] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/7v.bmp'), side: THREE.DoubleSide});
60 | overlay_map[350 + 14] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/14v.png'), side: THREE.DoubleSide});
61 | overlay_map[350 + 35] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/35v.bmp'), side: THREE.DoubleSide});
62 | overlay_map[350 + 19] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3243v.png'), side: THREE.DoubleSide});
63 | overlay_map[350 + 8] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3222v.png'), side: THREE.DoubleSide});
64 | overlay_map[350 + 4] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3222vw.png'), side: THREE.DoubleSide});
65 | overlay_map[350 + 5] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3230v.png'), side: THREE.DoubleSide, transparent: true});
66 | overlay_map[350 + 128] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3230v.png'), side: THREE.DoubleSide, transparent: true});
67 | overlay_map[350 + 42] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/42v.png'), side: THREE.DoubleSide, transparent: true});
68 | overlay_map[350 + 15] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3241v.png'), side: THREE.DoubleSide});
69 | overlay_map[350 + 16] = new THREE.MeshBasicMaterial({map: new THREE.ImageUtils.loadTexture('img/3241vw.png'), side: THREE.DoubleSide});
70 |
71 |
72 |
73 | // dump into materials
74 | for (var i = 0; i < 500; i++) {
75 | var obj = overlay_map[i];
76 | if (obj != null) {
77 | materials[i] = obj;
78 | }
79 | }
80 | materials[0] = new THREE.MeshBasicMaterial({color: 0xffffff});
81 |
82 | }
83 |
84 |
85 |
86 | var tileColors = new Array(new THREE.Color("rgb(255, 255, 255)"), new THREE.Color("rgb(251, 254, 251)"), new THREE.Color("rgb(247, 252, 247)"),
87 | new THREE.Color("rgb(243, 250, 243)"), new THREE.Color("rgb(239, 248, 239)"), new THREE.Color("rgb(235, 247, 235)"), new THREE.Color("rgb(231, 245, 231)"),
88 | new THREE.Color("rgb(227, 243, 227)"), new THREE.Color("rgb(223, 241, 223)"), new THREE.Color("rgb(219, 240, 219)"), new THREE.Color("rgb(215, 238, 215)"),
89 | new THREE.Color("rgb(211, 236, 211)"), new THREE.Color("rgb(207, 234, 207)"), new THREE.Color("rgb(203, 233, 203)"), new THREE.Color("rgb(199, 231, 199)"),
90 | new THREE.Color("rgb(195, 229, 195)"), new THREE.Color("rgb(191, 227, 191)"), new THREE.Color("rgb(187, 226, 187)"), new THREE.Color("rgb(183, 224, 183)"),
91 | new THREE.Color("rgb(179, 222, 179)"), new THREE.Color("rgb(175, 220, 175)"), new THREE.Color("rgb(171, 219, 171)"), new THREE.Color("rgb(167, 217, 167)"),
92 | new THREE.Color("rgb(163, 215, 163)"), new THREE.Color("rgb(159, 213, 159)"), new THREE.Color("rgb(155, 212, 155)"), new THREE.Color("rgb(151, 210, 151)"),
93 | new THREE.Color("rgb(147, 208, 147)"), new THREE.Color("rgb(143, 206, 143)"), new THREE.Color("rgb(139, 205, 139)"), new THREE.Color("rgb(135, 203, 135)"),
94 | new THREE.Color("rgb(131, 201, 131)"), new THREE.Color("rgb(127, 199, 127)"), new THREE.Color("rgb(123, 198, 123)"), new THREE.Color("rgb(119, 196, 119)"),
95 | new THREE.Color("rgb(115, 194, 115)"), new THREE.Color("rgb(111, 192, 111)"), new THREE.Color("rgb(107, 191, 107)"), new THREE.Color("rgb(103, 189, 103)"),
96 | new THREE.Color("rgb(99, 187, 99)"), new THREE.Color("rgb(95, 185, 95)"), new THREE.Color("rgb(91, 184, 91)"), new THREE.Color("rgb(87, 182, 87)"),
97 | new THREE.Color("rgb(83, 180, 83)"), new THREE.Color("rgb(79, 178, 79)"), new THREE.Color("rgb(75, 177, 75)"), new THREE.Color("rgb(71, 175, 71)"),
98 | new THREE.Color("rgb(67, 173, 67)"), new THREE.Color("rgb(63, 171, 63)"), new THREE.Color("rgb(59, 170, 59)"), new THREE.Color("rgb(55, 168, 55)"),
99 | new THREE.Color("rgb(51, 166, 51)"), new THREE.Color("rgb(47, 164, 47)"), new THREE.Color("rgb(43, 163, 43)"), new THREE.Color("rgb(39, 161, 39)"),
100 | new THREE.Color("rgb(35, 159, 35)"), new THREE.Color("rgb(31, 157, 31)"), new THREE.Color("rgb(27, 156, 27)"), new THREE.Color("rgb(23, 154, 23)"),
101 | new THREE.Color("rgb(19, 152, 19)"), new THREE.Color("rgb(15, 150, 15)"), new THREE.Color("rgb(11, 149, 11)"), new THREE.Color("rgb(7, 147, 7)"),
102 | new THREE.Color("rgb(3, 145, 3)"), new THREE.Color("rgb(0, 144, 0)"), new THREE.Color("rgb(3, 144, 0)"), new THREE.Color("rgb(6, 144, 0)"),
103 | new THREE.Color("rgb(9, 144, 0)"), new THREE.Color("rgb(12, 144, 0)"), new THREE.Color("rgb(15, 144, 0)"), new THREE.Color("rgb(18, 144, 0)"),
104 | new THREE.Color("rgb(21, 144, 0)"), new THREE.Color("rgb(24, 144, 0)"), new THREE.Color("rgb(27, 144, 0)"), new THREE.Color("rgb(30, 144, 0)"),
105 | new THREE.Color("rgb(33, 144, 0)"), new THREE.Color("rgb(36, 144, 0)"), new THREE.Color("rgb(39, 144, 0)"), new THREE.Color("rgb(42, 144, 0)"),
106 | new THREE.Color("rgb(45, 144, 0)"), new THREE.Color("rgb(48, 144, 0)"), new THREE.Color("rgb(51, 144, 0)"), new THREE.Color("rgb(54, 144, 0)"),
107 | new THREE.Color("rgb(57, 144, 0)"), new THREE.Color("rgb(60, 144, 0)"), new THREE.Color("rgb(63, 144, 0)"), new THREE.Color("rgb(66, 144, 0)"),
108 | new THREE.Color("rgb(69, 144, 0)"), new THREE.Color("rgb(72, 144, 0)"), new THREE.Color("rgb(75, 144, 0)"), new THREE.Color("rgb(78, 144, 0)"),
109 | new THREE.Color("rgb(81, 144, 0)"), new THREE.Color("rgb(84, 144, 0)"), new THREE.Color("rgb(87, 144, 0)"), new THREE.Color("rgb(90, 144, 0)"),
110 | new THREE.Color("rgb(93, 144, 0)"), new THREE.Color("rgb(96, 144, 0)"), new THREE.Color("rgb(99, 144, 0)"), new THREE.Color("rgb(102, 144, 0)"),
111 | new THREE.Color("rgb(105, 144, 0)"), new THREE.Color("rgb(108, 144, 0)"), new THREE.Color("rgb(111, 144, 0)"), new THREE.Color("rgb(114, 144, 0)"),
112 | new THREE.Color("rgb(117, 144, 0)"), new THREE.Color("rgb(120, 144, 0)"), new THREE.Color("rgb(123, 144, 0)"), new THREE.Color("rgb(126, 144, 0)"),
113 | new THREE.Color("rgb(129, 144, 0)"), new THREE.Color("rgb(132, 144, 0)"), new THREE.Color("rgb(135, 144, 0)"), new THREE.Color("rgb(138, 144, 0)"),
114 | new THREE.Color("rgb(141, 144, 0)"), new THREE.Color("rgb(144, 144, 0)"), new THREE.Color("rgb(147, 144, 0)"), new THREE.Color("rgb(150, 144, 0)"),
115 | new THREE.Color("rgb(153, 144, 0)"), new THREE.Color("rgb(156, 144, 0)"), new THREE.Color("rgb(159, 144, 0)"), new THREE.Color("rgb(162, 144, 0)"),
116 | new THREE.Color("rgb(165, 144, 0)"), new THREE.Color("rgb(168, 144, 0)"), new THREE.Color("rgb(171, 144, 0)"), new THREE.Color("rgb(174, 144, 0)"),
117 | new THREE.Color("rgb(177, 144, 0)"), new THREE.Color("rgb(180, 144, 0)"), new THREE.Color("rgb(183, 144, 0)"), new THREE.Color("rgb(186, 144, 0)"),
118 | new THREE.Color("rgb(189, 144, 0)"), new THREE.Color("rgb(192, 144, 0)"), new THREE.Color("rgb(191, 143, 0)"), new THREE.Color("rgb(189, 141, 0)"),
119 | new THREE.Color("rgb(188, 140, 0)"), new THREE.Color("rgb(186, 138, 0)"), new THREE.Color("rgb(185, 137, 0)"), new THREE.Color("rgb(183, 135, 0)"),
120 | new THREE.Color("rgb(182, 134, 0)"), new THREE.Color("rgb(180, 132, 0)"), new THREE.Color("rgb(179, 131, 0)"), new THREE.Color("rgb(177, 129, 0)"),
121 | new THREE.Color("rgb(176, 128, 0)"), new THREE.Color("rgb(174, 126, 0)"), new THREE.Color("rgb(173, 125, 0)"), new THREE.Color("rgb(171, 123, 0)"),
122 | new THREE.Color("rgb(170, 122, 0)"), new THREE.Color("rgb(168, 120, 0)"), new THREE.Color("rgb(167, 119, 0)"), new THREE.Color("rgb(165, 117, 0)"),
123 | new THREE.Color("rgb(164, 116, 0)"), new THREE.Color("rgb(162, 114, 0)"), new THREE.Color("rgb(161, 113, 0)"), new THREE.Color("rgb(159, 111, 0)"),
124 | new THREE.Color("rgb(158, 110, 0)"), new THREE.Color("rgb(156, 108, 0)"), new THREE.Color("rgb(155, 107, 0)"), new THREE.Color("rgb(153, 105, 0)"),
125 | new THREE.Color("rgb(152, 104, 0)"), new THREE.Color("rgb(150, 102, 0)"), new THREE.Color("rgb(149, 101, 0)"), new THREE.Color("rgb(147, 99, 0)"),
126 | new THREE.Color("rgb(146, 98, 0)"), new THREE.Color("rgb(144, 96, 0)"), new THREE.Color("rgb(143, 95, 0)"), new THREE.Color("rgb(141, 93, 0)"),
127 | new THREE.Color("rgb(140, 92, 0)"), new THREE.Color("rgb(138, 90, 0)"), new THREE.Color("rgb(137, 89, 0)"), new THREE.Color("rgb(135, 87, 0)"),
128 | new THREE.Color("rgb(134, 86, 0)"), new THREE.Color("rgb(132, 84, 0)"), new THREE.Color("rgb(131, 83, 0)"), new THREE.Color("rgb(129, 81, 0)"),
129 | new THREE.Color("rgb(128, 80, 0)"), new THREE.Color("rgb(126, 78, 0)"), new THREE.Color("rgb(125, 77, 0)"), new THREE.Color("rgb(123, 75, 0)"),
130 | new THREE.Color("rgb(122, 74, 0)"), new THREE.Color("rgb(120, 72, 0)"), new THREE.Color("rgb(119, 71, 0)"), new THREE.Color("rgb(117, 69, 0)"),
131 | new THREE.Color("rgb(116, 68, 0)"), new THREE.Color("rgb(114, 66, 0)"), new THREE.Color("rgb(113, 65, 0)"), new THREE.Color("rgb(111, 63, 0)"),
132 | new THREE.Color("rgb(110, 62, 0)"), new THREE.Color("rgb(108, 60, 0)"), new THREE.Color("rgb(107, 59, 0)"), new THREE.Color("rgb(105, 57, 0)"),
133 | new THREE.Color("rgb(104, 56, 0)"), new THREE.Color("rgb(102, 54, 0)"), new THREE.Color("rgb(101, 53, 0)"), new THREE.Color("rgb(99, 51, 0)"),
134 | new THREE.Color("rgb(98, 50, 0)"), new THREE.Color("rgb(96, 48, 0)"), new THREE.Color("rgb(95, 49, 0)"), new THREE.Color("rgb(93, 51, 0)"),
135 | new THREE.Color("rgb(92, 52, 0)"), new THREE.Color("rgb(90, 54, 0)"), new THREE.Color("rgb(89, 55, 0)"), new THREE.Color("rgb(87, 57, 0)"),
136 | new THREE.Color("rgb(86, 58, 0)"), new THREE.Color("rgb(84, 60, 0)"), new THREE.Color("rgb(83, 61, 0)"), new THREE.Color("rgb(81, 63, 0)"),
137 | new THREE.Color("rgb(80, 64, 0)"), new THREE.Color("rgb(78, 66, 0)"), new THREE.Color("rgb(77, 67, 0)"), new THREE.Color("rgb(75, 69, 0)"),
138 | new THREE.Color("rgb(74, 70, 0)"), new THREE.Color("rgb(72, 72, 0)"), new THREE.Color("rgb(71, 73, 0)"), new THREE.Color("rgb(69, 75, 0)"),
139 | new THREE.Color("rgb(68, 76, 0)"), new THREE.Color("rgb(66, 78, 0)"), new THREE.Color("rgb(65, 79, 0)"), new THREE.Color("rgb(63, 81, 0)"),
140 | new THREE.Color("rgb(62, 82, 0)"), new THREE.Color("rgb(60, 84, 0)"), new THREE.Color("rgb(59, 85, 0)"), new THREE.Color("rgb(57, 87, 0)"),
141 | new THREE.Color("rgb(56, 88, 0)"), new THREE.Color("rgb(54, 90, 0)"), new THREE.Color("rgb(53, 91, 0)"), new THREE.Color("rgb(51, 93, 0)"),
142 | new THREE.Color("rgb(50, 94, 0)"), new THREE.Color("rgb(48, 96, 0)"), new THREE.Color("rgb(47, 97, 0)"), new THREE.Color("rgb(45, 99, 0)"),
143 | new THREE.Color("rgb(44, 100, 0)"), new THREE.Color("rgb(42, 102, 0)"), new THREE.Color("rgb(41, 103, 0)"), new THREE.Color("rgb(39, 105, 0)"),
144 | new THREE.Color("rgb(38, 106, 0)"), new THREE.Color("rgb(36, 108, 0)"), new THREE.Color("rgb(35, 109, 0)"), new THREE.Color("rgb(33, 111, 0)"),
145 | new THREE.Color("rgb(32, 112, 0)"), new THREE.Color("rgb(30, 114, 0)"), new THREE.Color("rgb(29, 115, 0)"), new THREE.Color("rgb(27, 117, 0)"),
146 | new THREE.Color("rgb(26, 118, 0)"), new THREE.Color("rgb(24, 120, 0)"), new THREE.Color("rgb(23, 121, 0)"), new THREE.Color("rgb(21, 123, 0)"),
147 | new THREE.Color("rgb(20, 124, 0)"), new THREE.Color("rgb(18, 126, 0)"), new THREE.Color("rgb(17, 127, 0)"), new THREE.Color("rgb(15, 129, 0)"),
148 | new THREE.Color("rgb(14, 130, 0)"), new THREE.Color("rgb(12, 132, 0)"), new THREE.Color("rgb(11, 133, 0)"), new THREE.Color("rgb(9, 135, 0)"),
149 | new THREE.Color("rgb(8, 136, 0)"), new THREE.Color("rgb(6, 138, 0)"), new THREE.Color("rgb(5, 139, 0)"), new THREE.Color("rgb(3, 141, 0)"),
150 | new THREE.Color("rgb(2, 142, 0)")
151 | );
--------------------------------------------------------------------------------
/src/Tile.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Hayden on 12/1/2016.
3 | */
4 |
5 | function Tile(sector, sectX, sectY, x, y, groundElevation, groundTexture, groundOverlay, roofTexture, horizontalWall, verticalWall, diagonalWall, sect, absoluteSectorX, absoluteSectorY) {
6 |
7 | this.x = x;
8 | this.y = y;
9 | this.sector = sector;
10 | this.sectX = sectX;
11 | this.sectY = sectY;
12 | this.absoluteSectorX = absoluteSectorX;
13 | this.absoluteSectorY = absoluteSectorY;
14 | this.faceIdx = -1;
15 |
16 |
17 |
18 | this.groundElevation = groundElevation;
19 | this.groundTexture = groundTexture;
20 | this.groundOverlay = groundOverlay;
21 | this.roofTexture = roofTexture;
22 | this.horizontalWall = horizontalWall;
23 | this.verticalWall = verticalWall;
24 | this.diagonalWall = diagonalWall;
25 | this.meshColor = tileColors[this.groundTexture].getHex();
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/Util.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Hayden on 12/1/2016.
3 | */
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/ui/Menubar.Edit.js:
--------------------------------------------------------------------------------
1 |
2 | Menubar.Edit = function ( editor ) {
3 |
4 | var container = new UI.Panel();
5 | container.setClass( 'menu' );
6 |
7 | var title = new UI.Panel();
8 | title.setClass( 'title' );
9 | title.setTextContent( 'Edit' );
10 | container.add( title );
11 |
12 | var options = new UI.Panel();
13 | options.setClass( 'options' );
14 | container.add( options );
15 |
16 |
17 | var open = new UI.Row();
18 | open.setClass( 'option' );
19 | open.setTextContent( 'Undo' );
20 | open.onClick( function () {
21 |
22 | var fileInput = document.createElement( 'input' );
23 | fileInput.type = 'file';
24 | fileInput.addEventListener( 'change', function ( event ) {
25 |
26 |
27 |
28 | } );
29 | fileInput.click();
30 |
31 |
32 | } );
33 |
34 | options.add(open);
35 | var open = new UI.Row();
36 | open.setClass( 'option' );
37 | open.setTextContent( 'Redo' );
38 | open.onClick( function () {
39 |
40 | var fileInput = document.createElement( 'input' );
41 | fileInput.type = 'file';
42 | fileInput.addEventListener( 'change', function ( event ) {
43 |
44 |
45 |
46 | } );
47 | fileInput.click();
48 |
49 |
50 | } );
51 |
52 | options.add(open);
53 | //
54 |
55 | options.add( new UI.HorizontalRule() );
56 |
57 |
58 | var open = new UI.Row();
59 | open.setClass( 'option' );
60 | open.setTextContent( 'Copy Tile' );
61 | open.onClick( function () {
62 | var fileInput = document.createElement( 'input' );
63 | fileInput.type = 'file';
64 | fileInput.addEventListener( 'change', function ( event ) {
65 |
66 |
67 |
68 | } );
69 | fileInput.click();
70 | } );
71 | options.add(open);
72 |
73 | var open = new UI.Row();
74 | open.setClass( 'option' );
75 | open.setTextContent( 'Paste Tile' );
76 | open.onClick( function () {
77 | var fileInput = document.createElement( 'input' );
78 | fileInput.type = 'file';
79 | fileInput.addEventListener( 'change', function ( event ) {
80 |
81 |
82 |
83 | } );
84 | fileInput.click();
85 | } );
86 | options.add(open);
87 |
88 |
89 |
90 | var link = document.createElement( 'a' );
91 | link.style.display = 'none';
92 | document.body.appendChild( link ); // Firefox workaround, see #6594
93 |
94 | function save( blob, filename ) {
95 |
96 | link.href = URL.createObjectURL( blob );
97 | link.download = filename || 'data.json';
98 | link.click();
99 |
100 | // URL.revokeObjectURL( url ); breaks Firefox...
101 |
102 | }
103 |
104 | function saveString( text, filename ) {
105 |
106 | save( new Blob( [ text ], { type: 'text/plain' } ), filename );
107 |
108 | }
109 |
110 | return container;
111 |
112 | };
--------------------------------------------------------------------------------
/src/ui/Menubar.File.js:
--------------------------------------------------------------------------------
1 |
2 | Menubar.File = function ( editor ) {
3 |
4 | var container = new UI.Panel();
5 | container.setClass( 'menu' );
6 |
7 | var title = new UI.Panel();
8 | title.setClass( 'title' );
9 | title.setTextContent( 'File' );
10 | container.add( title );
11 |
12 | var options = new UI.Panel();
13 | options.setClass( 'options' );
14 | container.add( options );
15 |
16 | // New
17 |
18 | var open = new UI.Row();
19 | open.setClass( 'option' );
20 | open.setTextContent( 'Load .RSCD' );
21 | open.onClick( function () {
22 |
23 | var fileInput = document.createElement( 'input' );
24 | fileInput.type = 'file';
25 | fileInput.addEventListener( 'change', function ( event ) {
26 |
27 | openFile( event );
28 | unpackSectors();
29 | updateSectors();
30 | controls = new THREE.OrbitControls( camera, renderer.domElement );
31 | controls.enableDamping = true;
32 | controls.dampingFactor = 0.25;
33 | controls.zoomSpeed = 0.5;
34 | camera.position.set(0, 0, 200);
35 | controls.enabled = false;
36 | controls.enabled = true;
37 | controls.enablePan = true;
38 | controls.enableZoom = true;
39 | controls.update();
40 | animate();
41 |
42 | } );
43 | fileInput.click();
44 |
45 |
46 | } );
47 |
48 | options.add(open);
49 |
50 | var open = new UI.Row();
51 | open.setClass( 'option' );
52 | open.setTextContent( 'Load .JAG' );
53 | open.onClick( function () {
54 | var fileInput = document.createElement( 'input' );
55 | fileInput.type = 'file';
56 | fileInput.addEventListener( 'change', function ( event ) {
57 |
58 |
59 |
60 | } );
61 | fileInput.click();
62 | } );
63 | options.add(open);
64 |
65 | //
66 |
67 | options.add( new UI.HorizontalRule() );
68 |
69 |
70 | var open = new UI.Row();
71 | open.setClass( 'option' );
72 | open.setTextContent( 'Export .RSCD' );
73 | open.onClick( function () {
74 | var fileInput = document.createElement( 'input' );
75 | fileInput.type = 'file';
76 | fileInput.addEventListener( 'change', function ( event ) {
77 |
78 |
79 |
80 | } );
81 | fileInput.click();
82 | } );
83 | options.add(open);
84 |
85 | var open = new UI.Row();
86 | open.setClass( 'option' );
87 | open.setTextContent( 'Export .JAG' );
88 | open.onClick( function () {
89 | var fileInput = document.createElement( 'input' );
90 | fileInput.type = 'file';
91 | fileInput.addEventListener( 'change', function ( event ) {
92 |
93 |
94 |
95 | } );
96 | fileInput.click();
97 | } );
98 | options.add(open);
99 |
100 | var open = new UI.Row();
101 | open.setClass( 'option' );
102 | open.setTextContent( 'Export Sector' );
103 | open.onClick( function () {
104 | var fileInput = document.createElement( 'input' );
105 | fileInput.type = 'file';
106 | fileInput.addEventListener( 'change', function ( event ) {
107 |
108 |
109 |
110 | } );
111 | fileInput.click();
112 | } );
113 | options.add(open);
114 |
115 |
116 |
117 |
118 | var link = document.createElement( 'a' );
119 | link.style.display = 'none';
120 | document.body.appendChild( link ); // Firefox workaround, see #6594
121 |
122 | function save( blob, filename ) {
123 |
124 | link.href = URL.createObjectURL( blob );
125 | link.download = filename || 'data.json';
126 | link.click();
127 |
128 | // URL.revokeObjectURL( url ); breaks Firefox...
129 |
130 | }
131 |
132 | function saveString( text, filename ) {
133 |
134 | save( new Blob( [ text ], { type: 'text/plain' } ), filename );
135 |
136 | }
137 |
138 | return container;
139 |
140 | };
--------------------------------------------------------------------------------
/src/ui/Menubar.Sector.js:
--------------------------------------------------------------------------------
1 |
2 | Menubar.Sector = function ( editor ) {
3 |
4 | var container = new UI.Panel();
5 | container.setClass( 'menu' );
6 |
7 | var title = new UI.Panel();
8 | title.setClass( 'title' );
9 | title.setTextContent( 'Sector' );
10 | container.add( title );
11 |
12 | var options = new UI.Panel();
13 | options.setClass( 'options' );
14 | container.add( options );
15 |
16 | // New
17 | var open = new UI.Row();
18 | open.setClass( 'option' );
19 | open.setTextContent( 'Sector ->' );
20 | open.onClick( function () {
21 |
22 | var fileInput = document.createElement( 'input' );
23 | fileInput.type = 'file';
24 | fileInput.addEventListener( 'change', function ( event ) {
25 |
26 |
27 |
28 | } );
29 | fileInput.click();
30 | } );
31 |
32 | options.add(open);
33 |
34 | options.add( new UI.HorizontalRule() );
35 |
36 | var open = new UI.Row();
37 | open.setClass( 'option' );
38 | open.setTextContent( 'Varrock' );
39 | open.onClick( function () {
40 |
41 | var fileInput = document.createElement( 'input' );
42 | fileInput.type = 'file';
43 | fileInput.addEventListener( 'change', function ( event ) {
44 |
45 |
46 |
47 | } );
48 | fileInput.click();
49 | } );
50 |
51 | options.add(open);
52 |
53 | var open = new UI.Row();
54 | open.setClass( 'option' );
55 | open.setTextContent( 'Falador' );
56 | open.onClick( function () {
57 |
58 | var fileInput = document.createElement( 'input' );
59 | fileInput.type = 'file';
60 | fileInput.addEventListener( 'change', function ( event ) {
61 |
62 |
63 |
64 | } );
65 | fileInput.click();
66 | } );
67 |
68 | options.add(open);
69 |
70 | var open = new UI.Row();
71 | open.setClass( 'option' );
72 | open.setTextContent( 'Lumbridge' );
73 | open.onClick( function () {
74 |
75 | var fileInput = document.createElement( 'input' );
76 | fileInput.type = 'file';
77 | fileInput.addEventListener( 'change', function ( event ) {
78 |
79 |
80 |
81 | } );
82 | fileInput.click();
83 | } );
84 |
85 | options.add(open);
86 |
87 | var open = new UI.Row();
88 | open.setClass( 'option' );
89 | open.setTextContent( 'Edgeville' );
90 | open.onClick( function () {
91 |
92 | var fileInput = document.createElement( 'input' );
93 | fileInput.type = 'file';
94 | fileInput.addEventListener( 'change', function ( event ) {
95 |
96 |
97 |
98 | } );
99 | fileInput.click();
100 | } );
101 |
102 | options.add(open);
103 |
104 | var open = new UI.Row();
105 | open.setClass( 'option' );
106 | open.setTextContent( 'Draynor' );
107 | open.onClick( function () {
108 |
109 | var fileInput = document.createElement( 'input' );
110 | fileInput.type = 'file';
111 | fileInput.addEventListener( 'change', function ( event ) {
112 |
113 |
114 |
115 | } );
116 | fileInput.click();
117 | } );
118 |
119 | options.add(open);
120 |
121 | var open = new UI.Row();
122 | open.setClass( 'option' );
123 | open.setTextContent( 'Karamja' );
124 | open.onClick( function () {
125 |
126 | var fileInput = document.createElement( 'input' );
127 | fileInput.type = 'file';
128 | fileInput.addEventListener( 'change', function ( event ) {
129 |
130 |
131 |
132 | } );
133 | fileInput.click();
134 | } );
135 |
136 | options.add(open);
137 |
138 | var open = new UI.Row();
139 | open.setClass( 'option' );
140 | open.setTextContent( 'Al Kharid' );
141 | open.onClick( function () {
142 |
143 | var fileInput = document.createElement( 'input' );
144 | fileInput.type = 'file';
145 | fileInput.addEventListener( 'change', function ( event ) {
146 |
147 |
148 |
149 | } );
150 | fileInput.click();
151 | } );
152 |
153 | options.add(open);
154 |
155 | var open = new UI.Row();
156 | open.setClass( 'option' );
157 | open.setTextContent( 'Ardougne' );
158 | open.onClick( function () {
159 |
160 | var fileInput = document.createElement( 'input' );
161 | fileInput.type = 'file';
162 | fileInput.addEventListener( 'change', function ( event ) {
163 |
164 |
165 |
166 | } );
167 | fileInput.click();
168 | } );
169 |
170 | options.add(open);
171 |
172 | var open = new UI.Row();
173 | open.setClass( 'option' );
174 | open.setTextContent( 'Catherby' );
175 | open.onClick( function () {
176 |
177 | var fileInput = document.createElement( 'input' );
178 | fileInput.type = 'file';
179 | fileInput.addEventListener( 'change', function ( event ) {
180 |
181 |
182 |
183 | } );
184 | fileInput.click();
185 | } );
186 |
187 | options.add(open);
188 |
189 | var link = document.createElement( 'a' );
190 | link.style.display = 'none';
191 | document.body.appendChild( link ); // Firefox workaround, see #6594
192 |
193 | function save( blob, filename ) {
194 |
195 | link.href = URL.createObjectURL( blob );
196 | link.download = filename || 'data.json';
197 | link.click();
198 |
199 | // URL.revokeObjectURL( url ); breaks Firefox...
200 |
201 | }
202 |
203 | function saveString( text, filename ) {
204 |
205 | save( new Blob( [ text ], { type: 'text/plain' } ), filename );
206 |
207 | }
208 |
209 | return container;
210 |
211 | };
--------------------------------------------------------------------------------
/src/ui/Menubar.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | var Menubar = function ( editor ) {
4 |
5 | var container = new UI.Panel();
6 | container.setId( 'menubar' );
7 |
8 | container.add( new Menubar.File( null ) );
9 | container.add( new Menubar.Edit(null ) );
10 | container.add( new Menubar.Sector( null ) );
11 |
12 | //var wireframe = new UI.THREE.Boolean( false, 'Edit Mode' ).setWidth(100);
13 | //container.add( wireframe );
14 | //container.add( new Menubar.Edit( editor ) );
15 | //container.add( new Menubar.Add( editor ) );
16 | //container.add( new Menubar.Play( editor ) );
17 | //container.add( new Menubar.View( editor ) );
18 | // container.add( new Menubar.Examples( editor ) );
19 | //container.add( new Menubar.Help( editor ) );
20 |
21 | //container.add( new Menubar.Status( editor ) );
22 |
23 | return container;
24 |
25 | };
--------------------------------------------------------------------------------
/src/ui/Sidebar.EditMode.js:
--------------------------------------------------------------------------------
1 | Sidebar.EditMode = function ( editor ) {
2 |
3 | // var signals = editor.signals;
4 |
5 | var container = new UI.Span();
6 | var buttons = new UI.Panel();
7 | // container.add( buttons );
8 | // buttons.add( new UI.Text( 'X: 444 ' ) );
9 | // buttons.add( new UI.Text( 'Y: 544 ' ) );
10 |
11 | /* var objectTab = new UI.Text( 'OBJECT' ).onClick( onClick );
12 | var geometryTab = new UI.Text( 'GEOMETRY' ).onClick( onClick );
13 | var materialTab = new UI.Text( 'MATERIAL' ).onClick( onClick );
14 |
15 | var tabs = new UI.Div();
16 | tabs.setId( 'tabs' );
17 | tabs.add( objectTab, geometryTab, materialTab );
18 | container.add( tabs );
19 |
20 | function onClick( event ) {
21 | select( event.target.textContent );
22 | }
23 |
24 | //
25 |
26 | var object = new UI.Span().add(
27 | new Sidebar.Object( editor )
28 | );
29 | container.add( object );
30 |
31 | var geometry = new UI.Span().add(
32 | new Sidebar.Geometry( editor )
33 | );
34 | container.add( geometry );
35 |
36 | var material = new UI.Span().add(
37 | new Sidebar.Material( editor )
38 | );
39 | container.add( material );
40 |
41 | //
42 |
43 | function select( section ) {
44 |
45 | objectTab.setClass( '' );
46 | geometryTab.setClass( '' );
47 | materialTab.setClass( '' );
48 |
49 | object.setDisplay( 'none' );
50 | geometry.setDisplay( 'none' );
51 | material.setDisplay( 'none' );
52 |
53 | switch ( section ) {
54 | case 'OBJECT':
55 | objectTab.setClass( 'selected' );
56 | object.setDisplay( '' );
57 | break;
58 | case 'GEOMETRY':
59 | geometryTab.setClass( 'selected' );
60 | geometry.setDisplay( '' );
61 | break;
62 | case 'MATERIAL':
63 | materialTab.setClass( 'selected' );
64 | material.setDisplay( '' );
65 | break;
66 | }
67 |
68 | }
69 |
70 | select( 'OBJECT' );
71 | */
72 |
73 | return container;
74 |
75 | };
--------------------------------------------------------------------------------
/src/ui/Sidebar.Settings.js:
--------------------------------------------------------------------------------
1 | Sidebar.Settings = function ( editor ) {
2 |
3 | // var signals = editor.signals;
4 |
5 | var container = new UI.Span();
6 | var buttons = new UI.Panel();
7 | // container.add( buttons );
8 | // buttons.add( new UI.Text( 'X: 444 ' ) );
9 | // buttons.add( new UI.Text( 'Y: 544 ' ) );
10 |
11 | /* var objectTab = new UI.Text( 'OBJECT' ).onClick( onClick );
12 | var geometryTab = new UI.Text( 'GEOMETRY' ).onClick( onClick );
13 | var materialTab = new UI.Text( 'MATERIAL' ).onClick( onClick );
14 |
15 | var tabs = new UI.Div();
16 | tabs.setId( 'tabs' );
17 | tabs.add( objectTab, geometryTab, materialTab );
18 | container.add( tabs );
19 |
20 | function onClick( event ) {
21 | select( event.target.textContent );
22 | }
23 |
24 | //
25 |
26 | var object = new UI.Span().add(
27 | new Sidebar.Object( editor )
28 | );
29 | container.add( object );
30 |
31 | var geometry = new UI.Span().add(
32 | new Sidebar.Geometry( editor )
33 | );
34 | container.add( geometry );
35 |
36 | var material = new UI.Span().add(
37 | new Sidebar.Material( editor )
38 | );
39 | container.add( material );
40 |
41 | //
42 |
43 | function select( section ) {
44 |
45 | objectTab.setClass( '' );
46 | geometryTab.setClass( '' );
47 | materialTab.setClass( '' );
48 |
49 | object.setDisplay( 'none' );
50 | geometry.setDisplay( 'none' );
51 | material.setDisplay( 'none' );
52 |
53 | switch ( section ) {
54 | case 'OBJECT':
55 | objectTab.setClass( 'selected' );
56 | object.setDisplay( '' );
57 | break;
58 | case 'GEOMETRY':
59 | geometryTab.setClass( 'selected' );
60 | geometry.setDisplay( '' );
61 | break;
62 | case 'MATERIAL':
63 | materialTab.setClass( 'selected' );
64 | material.setDisplay( '' );
65 | break;
66 | }
67 |
68 | }
69 |
70 | select( 'OBJECT' );
71 | */
72 |
73 | return container;
74 |
75 | };
--------------------------------------------------------------------------------
/src/ui/Sidebar.ViewMode.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | var ui_coords = new UI.Text( "" );
4 | var ui_local_coords = new UI.Text( "" );
5 | var sectorIdx = new UI.Text( "" );
6 | var sectorName = new UI.Text( "" );
7 | var tileIdx = new UI.Text( "" );
8 | var tile_elevation = new UI.Text( "" );
9 | var tile_overlay = new UI.Text( "" );
10 | var tile_texture = new UI.Text( "" );
11 | var tile_vertical = new UI.Text( "" );
12 | var tile_diagonal = new UI.Text( "" );
13 | var tile_horizontal = new UI.Text( "" );
14 | var tile_roof = new UI.Text( "" );
15 |
16 | Sidebar.ViewMode = function ( editor ) {
17 |
18 |
19 | var buttons = new UI.Panel();
20 |
21 | buttons.add(new UI.Row().add( ui_coords ));
22 | buttons.add(new UI.Row().add( ui_local_coords ));
23 | buttons.add(new UI.Row().add(sectorName ));
24 | buttons.add(new UI.Row().add(tileIdx ));
25 | buttons.add(new UI.Row().add( tile_elevation));
26 | buttons.add(new UI.Row().add(tile_overlay ));
27 | buttons.add(new UI.Row().add(tile_texture ));
28 | buttons.add(new UI.Row().add(tile_vertical));
29 | buttons.add(new UI.Row().add( tile_horizontal ));
30 | buttons.add(new UI.Row().add( tile_diagonal ));
31 | buttons.add(new UI.Row().add( tile_roof));
32 |
33 |
34 | /* var objectTab = new UI.Text( 'OBJECT' ).onClick( onClick );
35 | var geometryTab = new UI.Text( 'GEOMETRY' ).onClick( onClick );
36 | var materialTab = new UI.Text( 'MATERIAL' ).onClick( onClick );
37 |
38 | var tabs = new UI.Div();
39 | tabs.setId( 'tabs' );
40 | tabs.add( objectTab, geometryTab, materialTab );
41 | container.add( tabs );
42 |
43 | function onClick( event ) {
44 | select( event.target.textContent );
45 | }
46 |
47 | //
48 |
49 | var object = new UI.Span().add(
50 | new Sidebar.Object( editor )
51 | );
52 | container.add( object );
53 |
54 | var geometry = new UI.Span().add(
55 | new Sidebar.Geometry( editor )
56 | );
57 | container.add( geometry );
58 |
59 | var material = new UI.Span().add(
60 | new Sidebar.Material( editor )
61 | );
62 | container.add( material );
63 |
64 | //
65 |
66 | function select( section ) {
67 |
68 | objectTab.setClass( '' );
69 | geometryTab.setClass( '' );
70 | materialTab.setClass( '' );
71 |
72 | object.setDisplay( 'none' );
73 | geometry.setDisplay( 'none' );
74 | material.setDisplay( 'none' );
75 |
76 | switch ( section ) {
77 | case 'OBJECT':
78 | objectTab.setClass( 'selected' );
79 | object.setDisplay( '' );
80 | break;
81 | case 'GEOMETRY':
82 | geometryTab.setClass( 'selected' );
83 | geometry.setDisplay( '' );
84 | break;
85 | case 'MATERIAL':
86 | materialTab.setClass( 'selected' );
87 | material.setDisplay( '' );
88 | break;
89 | }
90 |
91 | }
92 |
93 | select( 'OBJECT' );
94 | */
95 |
96 | return buttons;
97 |
98 | };
--------------------------------------------------------------------------------
/src/ui/Sidebar.js:
--------------------------------------------------------------------------------
1 |
2 | var Sidebar = function ( editor ) {
3 |
4 | var container = new UI.Panel();
5 | container.setId( 'sidebar' );
6 |
7 | //
8 |
9 | var viewTab = new UI.Text( 'VIEW MODE' ).onClick( onClick );
10 | var editTab = new UI.Text( 'EDIT MODE' ).onClick( onClick );
11 | var settingsTab = new UI.Text( 'SETTINGS' ).onClick( onClick );
12 |
13 | var tabs = new UI.Div();
14 | tabs.setId( 'tabs' );
15 | tabs.add( viewTab, editTab, settingsTab );
16 | container.add( tabs );
17 |
18 | function onClick( event ) {
19 |
20 | select( event.target.textContent );
21 |
22 | }
23 |
24 | //
25 |
26 | var view = new UI.Span().add(
27 | new Sidebar.ViewMode(null)
28 | );
29 | var edit = new UI.Span().add(
30 | new Sidebar.EditMode(null)
31 | );
32 | var settings = new UI.Span().add(
33 | new Sidebar.Settings(null)
34 | );
35 | container.add( view );
36 | container.add( edit );
37 | container.add( settings );
38 | /*
39 | var project = new UI.Span().add(
40 | new Sidebar.Project( editor )
41 | );
42 | container.add( project );
43 |
44 | var settings = new UI.Span().add(
45 | new Sidebar.Settings( editor ),
46 | new Sidebar.History( editor )
47 | );
48 | container.add( settings );
49 | */
50 | //
51 |
52 | function select( section ) {
53 |
54 | viewTab.setClass( '' );
55 | editTab.setClass( '' );
56 | settingsTab.setClass( '' );
57 |
58 | view.setDisplay( 'none' );
59 | edit.setDisplay( 'none' );
60 | settings.setDisplay( 'none' );
61 |
62 | switch ( section ) {
63 | case 'VIEW MODE':
64 | viewTab.setClass( 'selected' );
65 | view.setDisplay( '' );
66 | break;
67 | case 'EDIT MODE':
68 | editTab.setClass( 'selected' );
69 | edit.setDisplay( '' );
70 | break;
71 | case 'SETTINGS':
72 | settingsTab.setClass( 'selected' );
73 | settings.setDisplay( '' );
74 | break;
75 | }
76 |
77 |
78 | }
79 |
80 | select( 'VIEW MODE' );
81 |
82 | return container;
83 |
84 | };
--------------------------------------------------------------------------------
/src/ui/Toolbar.js:
--------------------------------------------------------------------------------
1 |
2 | var Toolbar = function ( editor ) {
3 |
4 |
5 |
6 | var container = new UI.Panel();
7 | container.setId( 'toolbar' );
8 |
9 | var buttons = new UI.Panel();
10 | container.add( buttons );
11 |
12 | //buttons.add( new UI.Text( 'FPS: 60 ' ).setWidth('80px') );
13 |
14 |
15 | //buttons.add( grid );
16 | var wireframe = new UI.THREE.Boolean( false, 'Wireframe' ).onChange( update );
17 | buttons.add( wireframe );
18 | var axis = new UI.THREE.Boolean( false, 'Axis' ).onChange( update );
19 | buttons.add( axis );
20 | var sects = new UI.THREE.Boolean( false, 'Surrounding Sectors' ).onChange( update );
21 | buttons.add( sects );
22 | sects.setValue(true);
23 |
24 | var roofs = new UI.THREE.Boolean( false, 'Roofs' ).onChange( update );
25 | buttons.add( roofs );
26 |
27 |
28 | /*
29 |
30 | var local = new UI.THREE.Boolean( false, 'local' ).onChange( update );
31 | buttons.add( local );
32 |
33 | var showGrid = new UI.THREE.Boolean( true, 'show' ).onChange( update );
34 | buttons.add( showGrid );*/
35 |
36 | function update() {
37 |
38 | //signals.snapChanged.dispatch( snap.getValue() === true ? grid.getValue() : null );
39 | //signals.spaceChanged.dispatch( local.getValue() === true ? "local" : "world" );
40 | //signals.showGridChanged.dispatch( showGrid.getValue() );
41 |
42 | }
43 |
44 | return container;
45 |
46 | };
--------------------------------------------------------------------------------