├── CONTRIBUTING.md ├── GLTFLoader.js ├── LICENSING ├── Makefile ├── README.md ├── acnl.js ├── acnltool.html ├── acnltool.zip ├── dress_half.gltf ├── dress_long.gltf ├── dress_none.gltf ├── filesaver.js ├── index.html ├── jquery.min.js ├── jquery.qrcode.js ├── jsqrcode.min.js ├── page.js ├── qrcode.js ├── shirt_half.gltf ├── shirt_long.gltf ├── shirt_none.gltf └── three.js /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Code contribution guidelines 2 | ============================ 3 | 4 | There aren't any yet. Let's see what happens and/of if this turns out to be needed. 5 | Reach out to me if you want to contribute and let's discuss! 6 | 7 | -------------------------------------------------------------------------------- /LICENSING: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | default: acnltool.zip 2 | 3 | acnl.min.js: jquery.min.js qrcode.js jquery.qrcode.js filesaver.js jsqrcode.min.js acnl.js page.js 4 | uglifyjs jquery.min.js qrcode.js jquery.qrcode.js filesaver.js jsqrcode.min.js acnl.js page.js -mc > acnl.min.js 5 | oneliner.html: acnl.min.js 6 | echo "" >> oneliner.html 9 | acnltool.html: oneliner.html index.html 10 | cat index.html | sed '//,// {//!d}; //r oneliner.html' > acnltool.html 11 | acnltool.zip: acnltool.html 12 | zip -9 acnltool.zip acnltool.html 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Animal Crossing: New Leaf Pattern Tool 2 | ====================================== 3 | This originally started as a short project made over the span of a few days. 4 | After the main problems were solved, work on the project was mostly halted. 5 | A year or so after the original development, several bug fixes powered by a collection of user reports was pushed through. 6 | Recent interest (mostly due to the upcoming new Animal Crossing game announced for Nintendo Switch), caused me to open up this repository to public viewing, and allow others to more directly contribute code. 7 | 8 | License Information 9 | =================== 10 | This code should be considered public domain (technically, it's licensed under the [Do What The Fuck You Want To Public License](LICENSING)). In short: use it however you like, for any purpose. 11 | 12 | I do have a request: __I would appreciate it if you included a mention of the source somewhere in your project along the lines of "Based on the ACNL Pattern tool by Thulinma".__ 13 | This is not a requirement or condition, just a request. The only repercussion you will face for not doing so is me being very disappointed with you. 14 | 15 | I make no claims regarding the licenses of libraries used by this project. Specifically, the following dependencies are used: 16 | 17 | - [FileSaver.js by eligrey](//github.com/eligrey/FileSaver.js/) is used for saving patterns as .acnl files (MIT license). 18 | - [jquery-qrcode by Lars Jung](//github.com/lrsjng/jquery-qrcode) is used for QR code generation (MIT license). 19 | - [QR Code Generator by Kazuhiko Arase](http://www.d-project.com/qrcode/index.html) is used for QR code generation (MIT license). 20 | - [JavaScript QR code reader by Lazar Laszlo](https://github.com/LazarSoft/jsqrcode) is used for QR code reading (Apache License 2.0), with a [minor contribution](https://github.com/LazarSoft/jsqrcode/pull/20) from me. 21 | - [jQuery by the jQuery Foundation](//jquery.com/) is used for easy accessing of HTML elements (MIT license). 22 | - [three.js and GLTFLoader by the three.js authors](//github.com/mrdoob/three.js/) is used for 3D rendering (MIT license). 23 | - 3D models were ripped from the game by [Centrixe (previously Tiramisu6) @ The Models Resource](//www.models-resource.com/submitter/Centrixe/). 24 | 25 | Contibuting 26 | =========== 27 | There are no contribution guidelines yet. Get in touch if you want to help! 28 | 29 | -------------------------------------------------------------------------------- /acnl.js: -------------------------------------------------------------------------------- 1 | 2 | //ACNL data layout (identical to binary QR code contents): 3 | // 4 | //0x 00 - 0x 29 ( 42) = Pattern Title 5 | //0x 2A - 0x 2B ( 2) = User ID 6 | //0x 2C - 0x 3F ( 20) = User Name 7 | //0x 40 - 0x 41 ( 2) = Town ID 8 | //0x 42 - 0x 55 ( 20) = Town Name 9 | //0x 56 - 0x 57 ( 2) = Unknown (values are usually random - changing seems to have no effect) 10 | //0x 58 - 0x 66 ( 15) = Color code indexes 11 | //0x 67 ( 1) = Unknown (value is usually random - changing seems to have no effect) 12 | //0x 68 ( 1) = Ten? (seems to always be 0x0A or 0x00) 13 | //0x 69 ( 1) = Pattern type (see below) 14 | //0x 6A - 0x 6B ( 2) = Zero? (seems to always be 0x0000) 15 | //0x 6C - 0x26B (512) = Pattern Data 1 (mandatory) 16 | //0x26C - 0x46B (512) = Pattern Data 2 (optional) 17 | //0x46C - 0x66B (512) = Pattern Data 3 (optional) 18 | //0x66C - 0x86B (512) = Pattern Data 4 (optional) 19 | //0x86C - 0x86F ( 4) = Zero padding (optional) 20 | // 21 | // Pattern types: 22 | // 0x00 = fullsleeve dress (pro) 23 | // 0x01 = halfsleeve dress (pro) 24 | // 0x02 = sleeveless dress (pro) 25 | // 0x03 = Longsleeve shirt (pro) 26 | // 0x04 = Midsleeve shirt (pro) 27 | // 0x07 = Plain pattern (hat) 28 | // 0x08 = Standee (pro) 29 | // 0x09 = Plain pattern (easel) 30 | // 31 | // 32 | var ACNL = function(){ 33 | 34 | function widthForType(t){ 35 | return (t < 6 || t == 8) ? 64 : 32; 36 | }; 37 | 38 | function emptyPattern(type){ 39 | var temp; 40 | if (type < 6 || type == 8){ 41 | temp = window.atob("RQBtAHAAdAB5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVAG4AawBuAG8AdwBuAAAAAAAAAAAAVQBuAGsAbgBvAHcAbgAAAAAAAAAxGQ8fLz9PX29/j5+vz8/f78wKCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); 42 | }else{ 43 | temp = window.atob("RQBtAHAAdAB5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVAG4AawBuAG8AdwBuAAAAAAAAAAAAVQBuAGsAbgBvAHcAbgAAAAAAAABeCw8fLz9PX29/j5+vv8/f73YKCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") 44 | } 45 | return temp.substr(0,0x69) + String.fromCharCode(type) + temp.substr(0x69+1); 46 | } 47 | 48 | var data; 49 | var creator_data = null; 50 | var canvasses = []; 51 | 52 | function setByte(offset, val){ 53 | data = data.substr(0,offset) + String.fromCharCode(val) + data.substr(offset+1); 54 | }; 55 | function utf16(offset, len){ 56 | var tmp = ""; 57 | for (var i = offset; i < offset + len; i += 2){ 58 | var char = (data.charCodeAt(i+1) << 8) + data.charCodeAt(i); 59 | if (char == 0){return tmp;} 60 | tmp += String.fromCharCode(char); 61 | } 62 | return tmp; 63 | }; 64 | function to_utf16(offset, len, str){ 65 | for (var i = 0; i < len; i++){ 66 | if (i >= str.length){ 67 | setByte(offset + i*2, 0); 68 | setByte(offset + i*2+1, 0); 69 | }else{ 70 | setByte(offset + i*2, str.charCodeAt(i) & 0xFF); 71 | setByte(offset + i*2+1, (str.charCodeAt(i) >> 8) & 0xFF); 72 | } 73 | } 74 | }; 75 | 76 | function copyCreator(){ 77 | creator_data = data.substr(0x2A, 44); 78 | }; 79 | 80 | function pasteCreator(){ 81 | if (creator_data === null){ 82 | alert("Please copy creator data before attempting to paste."); 83 | return; 84 | } 85 | data = data.substr(0,0x2A) + creator_data + data.substr(0x56); 86 | }; 87 | 88 | function getCreatorID(){ 89 | return ((data.charCodeAt(0x2A) << 8) + data.charCodeAt(0x2B)).toString(16); 90 | }; 91 | 92 | function getTownID(){ 93 | return ((data.charCodeAt(0x40) << 8) + data.charCodeAt(0x41)).toString(16); 94 | }; 95 | 96 | function getUnknownID(){ 97 | return ((data.charCodeAt(0x56) << 8) + data.charCodeAt(0x57)).toString(16); 98 | }; 99 | 100 | function setCreatorID(id){ 101 | var num = parseInt(id, 16); 102 | setByte(0x2A, (num >> 8) & 0xFF); 103 | setByte(0x2B, num & 0xFF); 104 | }; 105 | 106 | function setTownID(id){ 107 | var num = parseInt(id, 16); 108 | setByte(0x40, (num >> 8) & 0xFF); 109 | setByte(0x41, num & 0xFF); 110 | }; 111 | 112 | function setUnknownID(id){ 113 | var num = parseInt(id, 16); 114 | setByte(0x56, (num >> 8) & 0xFF); 115 | setByte(0x57, num & 0xFF); 116 | }; 117 | 118 | function getTitle(){return utf16(0, 40);}; 119 | function getCreator(){return utf16(0x2c, 20);}; 120 | function getTown(){return utf16(0x42, 20);}; 121 | 122 | function setTitle(str){to_utf16(0, 20, str);}; 123 | function setCreator(str){to_utf16(0x2c, 10, str);}; 124 | function setTown(str){to_utf16(0x42, 10, str);}; 125 | 126 | function getWidth(){ 127 | if (data.length == 0x870){return 64;} 128 | return 32; 129 | }; 130 | 131 | function getZoom(cnvs){ 132 | if (cnvs.width && cnvs.height){ 133 | if (cnvs.width == cnvs.height/4){ 134 | return cnvs.width/32; 135 | } 136 | } 137 | if ($(cnvs).width() < $(cnvs).height()){ 138 | return Math.floor($(cnvs).width() / getWidth()); 139 | }else{ 140 | return Math.floor($(cnvs).height() / getWidth()); 141 | } 142 | return 1; 143 | }; 144 | 145 | function getTypeNum(){ 146 | return data.charCodeAt(0x69); 147 | }; 148 | 149 | function getTypeStr(){ 150 | switch (getTypeNum()){ 151 | case 0: return "Long sleeves dress"; 152 | case 1: return "Short sleeves dress"; 153 | case 2: return "Sleeveless dress"; 154 | case 3: return "Long sleeves shirt"; 155 | case 4: return "Short sleeves shirt"; 156 | case 5: return "Sleeveless shirt"; 157 | case 7: return "Hat"; 158 | case 8: return "Standee"; 159 | case 9: return "Normal pattern (Easel)"; 160 | default: return "Unimplemented pattern type"; 161 | } 162 | } 163 | 164 | function getTypeModel(){ 165 | switch (getTypeNum()){ 166 | case 0: return "dress_long.gltf"; 167 | case 1: return "dress_half.gltf"; 168 | case 2: return "dress_none.gltf"; 169 | case 3: return "shirt_long.gltf"; 170 | case 4: return "shirt_half.gltf"; 171 | case 5: return "shirt_none.gltf"; 172 | default: return ""; 173 | } 174 | } 175 | 176 | function download(){ 177 | try{ 178 | var ab = new ArrayBuffer(data.length); 179 | var ia = new Uint8Array(ab); 180 | for (var i = 0; i < data.length; i++) { 181 | ia[i] = data.charCodeAt(i); 182 | } 183 | var blob = new Blob([ia], {"type": "application/octet-stream"}); 184 | saveAs(blob, utf16(0, 42)+".acnl"); 185 | }catch(e){ 186 | alert("Failed to save file. Try using a different browser. :-("); 187 | } 188 | }; 189 | 190 | function qr(obj){ 191 | obj.html(""); 192 | if (getWidth() == 64){ 193 | obj.qrcode({"correctLevel":0, "text":data.substr(0, 0x21C), "render":"canvas", "width":512, "height":512, "multipart_num":0, "multipart_total":3, "multipart_parity":0x77}); 194 | obj.qrcode({"correctLevel":0, "text":data.substr(0x21C, 0x21C), "render":"canvas", "width":512, "height":512, "multipart_num":1, "multipart_total":3, "multipart_parity":0x77}); 195 | obj.qrcode({"correctLevel":0, "text":data.substr(0x21C*2, 0x21C), "render":"canvas", "width":512, "height":512, "multipart_num":2, "multipart_total":3, "multipart_parity":0x77}); 196 | obj.qrcode({"correctLevel":0, "text":data.substr(0x21C*3, 0x21C), "render":"canvas", "width":512, "height":512, "multipart_num":3, "multipart_total":3, "multipart_parity":0x77}); 197 | }else{ 198 | obj.qrcode({"correctLevel":0, "text":data, "render":"canvas", "width":512, "height":512}); 199 | } 200 | }; 201 | 202 | function draw_offset(ctx, j, col, zoom){ 203 | var x = (j % 32); 204 | var y = Math.floor(j / 32); 205 | drawPixel(ctx, x, y, col, zoom); 206 | }; 207 | 208 | function draw(canvas_draw){ 209 | var zoom = getZoom(canvas_draw); 210 | var ctx=canvas_draw.getContext("2d"); 211 | if ($.inArray(ctx, canvasses) == -1){ 212 | canvasses.push(ctx); 213 | } 214 | var offset = 0x6C; 215 | for (var i = offset; i < data.length; i++){ 216 | dpoint = data.charCodeAt(i); 217 | draw_offset(ctx, (i - offset)*2, dpoint & 0x0F, zoom); 218 | draw_offset(ctx, (i - offset)*2 + 1, (dpoint >> 4) & 0x0F, zoom); 219 | } 220 | };//draw 221 | 222 | function drawPixel(context, x, y, col, zoom){ 223 | if (y > 63 && (zoom > 1 || context.canvas.width == context.canvas.height)){ 224 | y -= 64; x += 32; 225 | } 226 | try{ 227 | //draw the pixel 228 | context.fillStyle=getColor(col); 229 | context.fillRect(x*zoom,y*zoom,zoom,zoom); 230 | //if zoom > 5, draw a line 231 | if (zoom > 5){ 232 | context.fillStyle="#AAAAAA"; 233 | context.fillRect(x*zoom+zoom-1,y*zoom,1,zoom); 234 | context.fillRect(x*zoom,y*zoom+zoom-1,zoom,1); 235 | } 236 | }catch(e){}; 237 | }; 238 | 239 | function setColor(x, y, c){ 240 | if (x < 0 || y < 0 || c < 0 || c > 15 || x > 63 || y > 63 || isNaN(x) || isNaN(y)){return false;} 241 | if (data.length != 0x870 && (x > 31 || y > 31)){return false;} 242 | if (x > 31){ 243 | x -= 32; 244 | y += 64; 245 | } 246 | var offset = 0x6C + Math.floor(x/2) + y*16; 247 | var val = data.charCodeAt(offset) & 0xFF; 248 | var oldval = val; 249 | if ((x % 2) == 1){ 250 | val = (val & 0x0F) + (c << 4); 251 | }else{ 252 | val = (val & 0xF0) + c; 253 | } 254 | if (val == oldval){ 255 | return; 256 | } 257 | setByte(offset, val); 258 | for (var i in canvasses){ 259 | drawPixel(canvasses[i], x, y, c, getZoom(canvasses[i].canvas)); 260 | } 261 | }; 262 | 263 | function getPal(clr){ 264 | switch (clr){ 265 | //pinks 266 | case 0x00: return "#FFEFFF"; 267 | case 0x01: return "#FF9AAD"; 268 | case 0x02: return "#EF559C"; 269 | case 0x03: return "#FF65AD"; 270 | case 0x04: return "#FF0063"; 271 | case 0x05: return "#BD4573"; 272 | case 0x06: return "#CE0052"; 273 | case 0x07: return "#9C0031"; 274 | case 0x08: return "#522031"; 275 | 276 | //reds 277 | case 0x10: return "#FFBACE"; 278 | case 0x11: return "#FF7573"; 279 | case 0x12: return "#DE3010"; 280 | case 0x13: return "#FF5542"; 281 | case 0x14: return "#FF0000"; 282 | case 0x15: return "#CE6563"; 283 | case 0x16: return "#BD4542"; 284 | case 0x17: return "#BD0000"; 285 | case 0x18: return "#8C2021"; 286 | 287 | //oranges 288 | case 0x20: return "#DECFBD"; 289 | case 0x21: return "#FFCF63"; 290 | case 0x22: return "#DE6521"; 291 | case 0x23: return "#FFAA21"; 292 | case 0x24: return "#FF6500"; 293 | case 0x25: return "#BD8A52"; 294 | case 0x26: return "#DE4500"; 295 | case 0x27: return "#BD4500"; 296 | case 0x28: return "#633010"; 297 | 298 | //pastels or something, I guess? 299 | case 0x30: return "#FFEFDE"; 300 | case 0x31: return "#FFDFCE"; 301 | case 0x32: return "#FFCFAD"; 302 | case 0x33: return "#FFBA8C"; 303 | case 0x34: return "#FFAA8C"; 304 | case 0x35: return "#DE8A63"; 305 | case 0x36: return "#BD6542"; 306 | case 0x37: return "#9C5531"; 307 | case 0x38: return "#8C4521"; 308 | 309 | //purple 310 | case 0x40: return "#FFCFFF"; 311 | case 0x41: return "#EF8AFF"; 312 | case 0x42: return "#CE65DE"; 313 | case 0x43: return "#BD8ACE"; 314 | case 0x44: return "#CE00FF"; 315 | case 0x45: return "#9C659C"; 316 | case 0x46: return "#8C00AD"; 317 | case 0x47: return "#520073"; 318 | case 0x48: return "#310042"; 319 | 320 | //pink 321 | case 0x50: return "#FFBAFF"; 322 | case 0x51: return "#FF9AFF"; 323 | case 0x52: return "#DE20BD"; 324 | case 0x53: return "#FF55EF"; 325 | case 0x54: return "#FF00CE"; 326 | case 0x55: return "#8C5573"; 327 | case 0x56: return "#BD009C"; 328 | case 0x57: return "#8C0063"; 329 | case 0x58: return "#520042"; 330 | 331 | //brown 332 | case 0x60: return "#DEBA9C"; 333 | case 0x61: return "#CEAA73"; 334 | case 0x62: return "#734531"; 335 | case 0x63: return "#AD7542"; 336 | case 0x64: return "#9C3000"; 337 | case 0x65: return "#733021"; 338 | case 0x66: return "#522000"; 339 | case 0x67: return "#311000"; 340 | case 0x68: return "#211000"; 341 | 342 | //yellow 343 | case 0x70: return "#FFFFCE"; 344 | case 0x71: return "#FFFF73"; 345 | case 0x72: return "#DEDF21"; 346 | case 0x73: return "#FFFF00"; 347 | case 0x74: return "#FFDF00"; 348 | case 0x75: return "#CEAA00"; 349 | case 0x76: return "#9C9A00"; 350 | case 0x77: return "#8C7500"; 351 | case 0x78: return "#525500"; 352 | 353 | //blue 354 | case 0x80: return "#DEBAFF"; 355 | case 0x81: return "#BD9AEF"; 356 | case 0x82: return "#6330CE"; 357 | case 0x83: return "#9C55FF"; 358 | case 0x84: return "#6300FF"; 359 | case 0x85: return "#52458C"; 360 | case 0x86: return "#42009C"; 361 | case 0x87: return "#210063"; 362 | case 0x88: return "#211031"; 363 | 364 | //ehm... also blue? 365 | case 0x90: return "#BDBAFF"; 366 | case 0x91: return "#8C9AFF"; 367 | case 0x92: return "#3130AD"; 368 | case 0x93: return "#3155EF"; 369 | case 0x94: return "#0000FF"; 370 | case 0x95: return "#31308C"; 371 | case 0x96: return "#0000AD"; 372 | case 0x97: return "#101063"; 373 | case 0x98: return "#000021"; 374 | 375 | //green 376 | case 0xA0: return "#9CEFBD"; 377 | case 0xA1: return "#63CF73"; 378 | case 0xA2: return "#216510"; 379 | case 0xA3: return "#42AA31"; 380 | case 0xA4: return "#008A31"; 381 | case 0xA5: return "#527552"; 382 | case 0xA6: return "#215500"; 383 | case 0xA7: return "#103021"; 384 | case 0xA8: return "#002010"; 385 | 386 | //icky greenish yellow 387 | case 0xB0: return "#DEFFBD"; 388 | case 0xB1: return "#CEFF8C"; 389 | case 0xB2: return "#8CAA52"; 390 | case 0xB3: return "#ADDF8C"; 391 | case 0xB4: return "#8CFF00"; 392 | case 0xB5: return "#ADBA9C"; 393 | case 0xB6: return "#63BA00"; 394 | case 0xB7: return "#529A00"; 395 | case 0xB8: return "#316500"; 396 | 397 | //Wtf? More blue? 398 | case 0xC0: return "#BDDFFF"; 399 | case 0xC1: return "#73CFFF"; 400 | case 0xC2: return "#31559C"; 401 | case 0xC3: return "#639AFF"; 402 | case 0xC4: return "#1075FF"; 403 | case 0xC5: return "#4275AD"; 404 | case 0xC6: return "#214573"; 405 | case 0xC7: return "#002073"; 406 | case 0xC8: return "#001042"; 407 | 408 | //gonna call this cyan 409 | case 0xD0: return "#ADFFFF"; 410 | case 0xD1: return "#52FFFF"; 411 | case 0xD2: return "#008ABD"; 412 | case 0xD3: return "#52BACE"; 413 | case 0xD4: return "#00CFFF"; 414 | case 0xD5: return "#429AAD"; 415 | case 0xD6: return "#00658C"; 416 | case 0xD7: return "#004552"; 417 | case 0xD8: return "#002031"; 418 | 419 | //more cyan, because we didn't have enough blue-like colors yet 420 | case 0xE0: return "#CEFFEF"; 421 | case 0xE1: return "#ADEFDE"; 422 | case 0xE2: return "#31CFAD"; 423 | case 0xE3: return "#52EFBD"; 424 | case 0xE4: return "#00FFCE"; 425 | case 0xE5: return "#73AAAD"; 426 | case 0xE6: return "#00AA9C"; 427 | case 0xE7: return "#008A73"; 428 | case 0xE8: return "#004531"; 429 | 430 | //also green. Fuck it, whatever. 431 | case 0xF0: return "#ADFFAD"; 432 | case 0xF1: return "#73FF73"; 433 | case 0xF2: return "#63DF42"; 434 | case 0xF3: return "#00FF00"; 435 | case 0xF4: return "#21DF21"; 436 | case 0xF5: return "#52BA52"; 437 | case 0xF6: return "#00BA00"; 438 | case 0xF7: return "#008A00"; 439 | case 0xF8: return "#214521"; 440 | 441 | //greys 442 | case 0x0F: return "#FFFFFF"; 443 | case 0x1F: return "#ECECEC"; 444 | case 0x2F: return "#DADADA"; 445 | case 0x3F: return "#C8C8C8"; 446 | case 0x4F: return "#B6B6B6"; 447 | case 0x5F: return "#A3A3A3"; 448 | case 0x6F: return "#919191"; 449 | case 0x7F: return "#7F7F7F"; 450 | case 0x8F: return "#6D6D6D"; 451 | case 0x9F: return "#5B5B5B"; 452 | case 0xAF: return "#484848"; 453 | case 0xBF: return "#363636"; 454 | case 0xCF: return "#242424"; 455 | case 0xDF: return "#121212"; 456 | case 0xEF: return "#000000"; 457 | 458 | default: 459 | //0x?9 - 0x?E aren't used. Not sure what they do in-game. Can somebody test this? 460 | //0xFF is displayed as white in-game, editing it causes a game freeze. 461 | return ""; 462 | } 463 | }; 464 | 465 | function setIndex(index, clr){ 466 | setByte(0x58 + index, clr); 467 | var offset = 0x6C; 468 | for (var z in canvasses){ 469 | var zoom = getZoom(canvasses[z].canvas); 470 | for (var i = offset; i < data.length; i++){ 471 | dpoint = data.charCodeAt(i); 472 | col = dpoint & 0x0F; 473 | if (col == index){ 474 | j = (i - offset)*2; 475 | drawPixel(canvasses[z], (j % 32), Math.floor(j / 32), index, zoom); 476 | } 477 | col = (dpoint >> 4) & 0x0F; 478 | if (col == index){ 479 | j = (i - offset)*2 + 1; 480 | drawPixel(canvasses[z], (j % 32), Math.floor(j / 32), index, zoom); 481 | } 482 | } 483 | } 484 | }; 485 | 486 | function getIndex(col){ 487 | return data.charCodeAt(0x58 + col); 488 | }; 489 | 490 | function getColor(col){ 491 | return getPal(getIndex(col)); 492 | }; 493 | 494 | return {"download":download, "load":function(d){data = d;}, "draw":draw, "qr":qr, "getColor":getColor, "getTitle":getTitle, "getCreator":getCreator, "getTown":getTown, "getCreatorID":getCreatorID, "getTownID":getTownID, "getUnknownID":getUnknownID, "setColor":setColor, "setTitle":setTitle, "setCreator":setCreator, "setTown":setTown, "setCreatorID":setCreatorID, "setTownID":setTownID, "setUnknownID":setUnknownID, "getPal":getPal, "setIndex":setIndex, "getIndex":getIndex, "copyCreator":copyCreator, "pasteCreator":pasteCreator, "getWidth":getWidth, "getTypeNum":getTypeNum, "getTypeStr":getTypeStr, "getTypeModel":getTypeModel, "emptyPattern":emptyPattern, "setByte":setByte, "widthForType":widthForType, "getData":function(){return data;}}; 495 | }(); 496 | -------------------------------------------------------------------------------- /acnltool.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duanqiao/ACNLPatternTool/1ff97e2efb47a65446b3a7ae7c9139dbf798b77a/acnltool.zip -------------------------------------------------------------------------------- /dress_none.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "asset": { 3 | "generator": "COLLADA2GLTF", 4 | "version": "2.0" 5 | }, 6 | "scenes": [ 7 | { 8 | "nodes": [ 9 | 0 10 | ] 11 | } 12 | ], 13 | "scene": 0, 14 | "nodes": [ 15 | { 16 | "children": [ 17 | 2, 18 | 1 19 | ], 20 | "name": "Y_UP" 21 | }, 22 | { 23 | "mesh": 0, 24 | "skin": 0, 25 | "name": "mesh_0_" 26 | }, 27 | { 28 | "children": [ 29 | 3 30 | ], 31 | "name": "root" 32 | }, 33 | { 34 | "children": [ 35 | 11, 36 | 4 37 | ], 38 | "matrix": [ 39 | -0.000003000000106112566, 40 | 1.0, 41 | 0.0, 42 | 0.0, 43 | -1.0, 44 | -0.000003000000106112566, 45 | 0.0, 46 | 0.0, 47 | 0.0, 48 | 0.0, 49 | 1.0, 50 | 0.0, 51 | 0.0, 52 | 14.0, 53 | 0.0, 54 | 1.0 55 | ], 56 | "name": "base" 57 | }, 58 | { 59 | "children": [ 60 | 8, 61 | 5 62 | ], 63 | "matrix": [ 64 | -1.0, 65 | -0.0000019999999949504856, 66 | 0.0, 67 | 0.0, 68 | 0.0000019999999949504856, 69 | -1.0, 70 | 0.0, 71 | 0.0, 72 | 0.0, 73 | 0.0, 74 | 1.0, 75 | 0.0, 76 | 0.0, 77 | 0.0, 78 | 0.0, 79 | 1.0 80 | ], 81 | "name": "waist" 82 | }, 83 | { 84 | "children": [ 85 | 6 86 | ], 87 | "matrix": [ 88 | 1.0, 89 | 0.0, 90 | 0.0, 91 | 0.0, 92 | 0.0, 93 | 1.0, 94 | 0.0, 95 | 0.0, 96 | 0.0, 97 | 0.0, 98 | 1.0, 99 | 0.0, 100 | 2.0, 101 | -2.799999952316284, 102 | 0.0, 103 | 1.0 104 | ], 105 | "name": "Rfoot1" 106 | }, 107 | { 108 | "children": [ 109 | 7 110 | ], 111 | "matrix": [ 112 | 1.0, 113 | 0.0, 114 | 0.0, 115 | 0.0, 116 | 0.0, 117 | 1.0, 118 | 0.0, 119 | 0.0, 120 | 0.0, 121 | 0.0, 122 | 1.0, 123 | 0.0, 124 | 5.099999904632568, 125 | -0.0, 126 | 0.0, 127 | 1.0 128 | ], 129 | "name": "Rfoot2" 130 | }, 131 | { 132 | "matrix": [ 133 | 1.0, 134 | 0.0, 135 | 0.0, 136 | 0.0, 137 | 0.0, 138 | 1.0, 139 | 0.0, 140 | 0.0, 141 | 0.0, 142 | 0.0, 143 | 1.0, 144 | 0.0, 145 | 5.699999809265137, 146 | 0.0, 147 | 0.0, 148 | 1.0 149 | ], 150 | "name": "Rfoot3" 151 | }, 152 | { 153 | "children": [ 154 | 9 155 | ], 156 | "matrix": [ 157 | 0.9997860193252564, 158 | -0.0009200000204145908, 159 | 0.02065500058233738, 160 | 0.0, 161 | 0.0010809999657794834, 162 | 0.9999690055847168, 163 | -0.00776199996471405, 164 | 0.0, 165 | -0.020647000521421434, 166 | 0.007782999891787767, 167 | 0.9997569918632508, 168 | 0.0, 169 | 2.0, 170 | 2.799999952316284, 171 | 0.0, 172 | 1.0 173 | ], 174 | "name": "Lfoot1" 175 | }, 176 | { 177 | "children": [ 178 | 10 179 | ], 180 | "matrix": [ 181 | 1.0, 182 | 0.0, 183 | 0.0, 184 | 0.0, 185 | 0.0, 186 | 1.0, 187 | 0.0, 188 | 0.0, 189 | 0.0, 190 | 0.0, 191 | 1.0, 192 | 0.0, 193 | 5.099999904632568, 194 | 0.0, 195 | 0.0, 196 | 1.0 197 | ], 198 | "name": "Lfoot2" 199 | }, 200 | { 201 | "matrix": [ 202 | 1.0, 203 | 0.0, 204 | 0.0, 205 | 0.0, 206 | 0.0, 207 | 1.0, 208 | 0.0, 209 | 0.0, 210 | 0.0, 211 | 0.0, 212 | 1.0, 213 | 0.0, 214 | 5.699999809265137, 215 | 0.0, 216 | 0.0, 217 | 1.0 218 | ], 219 | "name": "Lfoot3" 220 | }, 221 | { 222 | "children": [ 223 | 17, 224 | 14, 225 | 12 226 | ], 227 | "matrix": [ 228 | 1.0, 229 | 0.0, 230 | 0.0, 231 | 0.0, 232 | 0.0, 233 | 1.0, 234 | 0.0, 235 | 0.0, 236 | 0.0, 237 | 0.0, 238 | 1.0, 239 | 0.0, 240 | 3.795880079269409, 241 | 0.0, 242 | 0.0, 243 | 1.0 244 | ], 245 | "name": "chest" 246 | }, 247 | { 248 | "children": [ 249 | 13 250 | ], 251 | "matrix": [ 252 | 0.9999470114707948, 253 | -0.003902999917045236, 254 | 0.00953999999910593, 255 | 0.0, 256 | 0.00418000016361475, 257 | 0.9995660185813904, 258 | -0.02917199954390526, 259 | 0.0, 260 | -0.009421999566257, 261 | 0.02920999936759472, 262 | 0.9995290040969848, 263 | 0.0, 264 | 8.604129791259766, 265 | 0.0, 266 | 0.0, 267 | 1.0 268 | ], 269 | "name": "head" 270 | }, 271 | { 272 | "matrix": [ 273 | -0.000003000000106112566, 274 | -1.0, 275 | 0.0, 276 | 0.0, 277 | 1.0, 278 | -0.000003000000106112566, 279 | 0.0, 280 | 0.0, 281 | 0.0, 282 | 0.0, 283 | 1.0, 284 | 0.0, 285 | 10.996000289916993, 286 | 0.0, 287 | 0.0, 288 | 1.0 289 | ], 290 | "name": "feel" 291 | }, 292 | { 293 | "children": [ 294 | 15 295 | ], 296 | "matrix": [ 297 | -0.000003000000106112566, 298 | 1.0, 299 | 0.0, 300 | 0.0, 301 | -1.0, 302 | -0.000003000000106112566, 303 | 0.0, 304 | 0.0, 305 | 0.0, 306 | 0.0, 307 | 1.0, 308 | 0.0, 309 | 7.604129791259766, 310 | 3.5999999046325685, 311 | 0.0, 312 | 1.0 313 | ], 314 | "name": "Rarm1" 315 | }, 316 | { 317 | "children": [ 318 | 16 319 | ], 320 | "matrix": [ 321 | 1.0, 322 | 0.0, 323 | 0.0, 324 | 0.0, 325 | 0.0, 326 | 1.0, 327 | 0.0, 328 | 0.0, 329 | 0.0, 330 | 0.0, 331 | 1.0, 332 | 0.0, 333 | 6.75, 334 | 9.999999974752428e-7, 335 | 0.0, 336 | 1.0 337 | ], 338 | "name": "Rarm2" 339 | }, 340 | { 341 | "matrix": [ 342 | 1.0, 343 | 0.0, 344 | 0.0, 345 | 0.0, 346 | 0.0, 347 | 1.0, 348 | 0.0, 349 | 0.0, 350 | 0.0, 351 | 0.0, 352 | 1.0, 353 | 0.0, 354 | 6.75, 355 | 0.0, 356 | 0.0, 357 | 1.0 358 | ], 359 | "name": "Rhand" 360 | }, 361 | { 362 | "children": [ 363 | 18 364 | ], 365 | "matrix": [ 366 | -0.000003000000106112566, 367 | -1.0, 368 | 0.0, 369 | 0.0, 370 | 1.0, 371 | -0.000003000000106112566, 372 | 0.0, 373 | 0.0, 374 | 0.0, 375 | 0.0, 376 | 1.0, 377 | 0.0, 378 | 7.604129791259766, 379 | -3.5999999046325685, 380 | 0.0, 381 | 1.0 382 | ], 383 | "name": "Larm1" 384 | }, 385 | { 386 | "children": [ 387 | 19 388 | ], 389 | "matrix": [ 390 | 1.0, 391 | 0.0, 392 | 0.0, 393 | 0.0, 394 | 0.0, 395 | 1.0, 396 | 0.0, 397 | 0.0, 398 | 0.0, 399 | 0.0, 400 | 1.0, 401 | 0.0, 402 | 6.75, 403 | 0.0, 404 | 0.0, 405 | 1.0 406 | ], 407 | "name": "Larm2" 408 | }, 409 | { 410 | "matrix": [ 411 | 1.0, 412 | 0.0, 413 | 0.0, 414 | 0.0, 415 | 0.0, 416 | 1.0, 417 | 0.0, 418 | 0.0, 419 | 0.0, 420 | 0.0, 421 | 1.0, 422 | 0.0, 423 | 6.75, 424 | 0.0, 425 | 0.0, 426 | 1.0 427 | ], 428 | "name": "Lhand" 429 | } 430 | ], 431 | "meshes": [ 432 | { 433 | "primitives": [ 434 | { 435 | "attributes": { 436 | "COLOR_0": 1, 437 | "JOINTS_0": 2, 438 | "NORMAL": 3, 439 | "POSITION": 4, 440 | "TEXCOORD_0": 5, 441 | "WEIGHTS_0": 6 442 | }, 443 | "indices": 0, 444 | "mode": 4 445 | } 446 | ], 447 | "name": "mesh_0_" 448 | } 449 | ], 450 | "skins": [ 451 | { 452 | "inverseBindMatrices": 7, 453 | "skeleton": 2, 454 | "joints": [ 455 | 19, 456 | 18, 457 | 17, 458 | 16, 459 | 15, 460 | 14, 461 | 13, 462 | 12, 463 | 11, 464 | 10, 465 | 9, 466 | 8, 467 | 7, 468 | 6, 469 | 5, 470 | 4, 471 | 3, 472 | 2 473 | ], 474 | "name": "Controller" 475 | } 476 | ], 477 | "accessors": [ 478 | { 479 | "bufferView": 0, 480 | "byteOffset": 0, 481 | "componentType": 5123, 482 | "count": 1026, 483 | "max": [ 484 | 230 485 | ], 486 | "min": [ 487 | 0 488 | ], 489 | "type": "SCALAR" 490 | }, 491 | { 492 | "bufferView": 1, 493 | "byteOffset": 0, 494 | "componentType": 5126, 495 | "count": 231, 496 | "max": [ 497 | 1.0, 498 | 1.0, 499 | 1.0 500 | ], 501 | "min": [ 502 | 1.0, 503 | 1.0, 504 | 1.0 505 | ], 506 | "type": "VEC3" 507 | }, 508 | { 509 | "bufferView": 2, 510 | "byteOffset": 0, 511 | "componentType": 5123, 512 | "count": 231, 513 | "max": [ 514 | 16, 515 | 14, 516 | 0, 517 | 0 518 | ], 519 | "min": [ 520 | 1, 521 | 0, 522 | 0, 523 | 0 524 | ], 525 | "type": "VEC4" 526 | }, 527 | { 528 | "bufferView": 1, 529 | "byteOffset": 2772, 530 | "componentType": 5126, 531 | "count": 231, 532 | "max": [ 533 | 0.999504029750824, 534 | 0.9994419813156128, 535 | 0.996638000011444 536 | ], 537 | "min": [ 538 | -0.999504029750824, 539 | -0.9998760223388672, 540 | -0.9895219802856444 541 | ], 542 | "type": "VEC3" 543 | }, 544 | { 545 | "bufferView": 1, 546 | "byteOffset": 5544, 547 | "componentType": 5126, 548 | "count": 231, 549 | "max": [ 550 | 19.5, 551 | 30.200000762939458, 552 | 8.190030097961426 553 | ], 554 | "min": [ 555 | -19.5, 556 | 9.965129852294922, 557 | -7.9731597900390629 558 | ], 559 | "type": "VEC3" 560 | }, 561 | { 562 | "bufferView": 2, 563 | "byteOffset": 1848, 564 | "componentType": 5126, 565 | "count": 231, 566 | "max": [ 567 | 1.0000300407409669, 568 | 0.9921879768371582 569 | ], 570 | "min": [ 571 | 0.0, 572 | -0.03905999660491944 573 | ], 574 | "type": "VEC2" 575 | }, 576 | { 577 | "bufferView": 3, 578 | "byteOffset": 0, 579 | "componentType": 5126, 580 | "count": 231, 581 | "max": [ 582 | 1.0, 583 | 0.5, 584 | 0.0, 585 | 0.0 586 | ], 587 | "min": [ 588 | 0.5, 589 | 0.0, 590 | 0.0, 591 | 0.0 592 | ], 593 | "type": "VEC4" 594 | }, 595 | { 596 | "bufferView": 4, 597 | "byteOffset": 0, 598 | "componentType": 5126, 599 | "count": 18, 600 | "max": [ 601 | 1.0, 602 | 1.0, 603 | 0.007782999891787767, 604 | 0.0, 605 | 1.0, 606 | 1.0, 607 | 0.020647000521421434, 608 | 0.0, 609 | 0.02917199954390526, 610 | 0.00953999999910593, 611 | 1.0, 612 | 0.0, 613 | 14.0, 614 | 25.399999618530278, 615 | 0.248758003115654, 616 | 1.0 617 | ], 618 | "min": [ 619 | -1.0, 620 | -1.0, 621 | -0.02920999936759472, 622 | 0.0, 623 | -1.0, 624 | -1.0, 625 | -0.009421999566257, 626 | 0.0, 627 | 0.0, 628 | -0.02917199954390526, 629 | 0.9995290040969848, 630 | 0.0, 631 | -26.39859962463379, 632 | -37.39459991455078, 633 | -0.2695640027523041, 634 | 1.0 635 | ], 636 | "type": "MAT4" 637 | } 638 | ], 639 | "bufferViews": [ 640 | { 641 | "buffer": 0, 642 | "byteOffset": 16860, 643 | "byteLength": 2052, 644 | "target": 34963 645 | }, 646 | { 647 | "buffer": 0, 648 | "byteOffset": 4848, 649 | "byteLength": 8316, 650 | "byteStride": 12, 651 | "target": 34962 652 | }, 653 | { 654 | "buffer": 0, 655 | "byteOffset": 13164, 656 | "byteLength": 3696, 657 | "byteStride": 8, 658 | "target": 34962 659 | }, 660 | { 661 | "buffer": 0, 662 | "byteOffset": 1152, 663 | "byteLength": 3696, 664 | "byteStride": 16, 665 | "target": 34962 666 | }, 667 | { 668 | "buffer": 0, 669 | "byteOffset": 0, 670 | "byteLength": 1152 671 | } 672 | ], 673 | "buffers": [ 674 | { 675 | "byteLength": 18912, 676 | "uri": "data:application/octet-stream;base64,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AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAA/AAAAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAzMzM/mpmZPgAAAAAAAAAAZmZmP83MzD0AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAzMzM/mpmZPgAAAAAAAAAAMzMzP5qZmT4AAAAAAAAAAAAAAD8AAAA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAPwAAAD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAD8AAAA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAMzMzP5qZmT4AAAAAAAAAADMzMz+amZk+AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAADMzMz+amZk+AAAAAAAAAABmZmY/zczMPQAAAAAAAAAAAACAPwAAAAAAAAAAAAAAADMzMz+amZk+AAAAAAAAAAAAAAA/AAAAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAD8AAAA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAPwAAAD8AAAAAAAAAADMzMz+amZk+AAAAAAAAAABmZmY/zczMPQAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAABmZmY/zczMPQAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/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CAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAPAAAAAAAAAA8AAAAAAAAAEAAAAAAAAAAQAAAAAAAAAA8AAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAFAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAFAAAAAAAAAAUAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAFAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAFAAAAAAAAAAgAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAQAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAACAAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAgAAAAAAAAACAAAAAAAAAACAAAAAAAAAAIAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAAgAAAAAAAAABAAAA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JwAoACQAIwAkACkAJAAoACkAHgAgACoAKgAgACMAKQAqACMAKwAqACkAKQAsACsAKQAoACwALAAoAC0ALAAtAC4ALAAuAC8ALAAvADAAKwAsADAAMQArADAAKwAyACoAMQAyACsAMQAzADIANAAzADEANQAzADQANQA2ADMANQA3ADYAOAA3ADUAHgA5AB8ANwA5ADYAOgA5ADcAOwAfADkAOwA5ADoAMwA2ADwAOQA8ADYAMwA8ADIAPAAqADIAHgA8ADkAPAAeACoAHQA9AD4AIQAdAD4APwAdAB8AHQA/AD0ADABAABAAQAAMAA4AQAAOAEEAQABBAEIAQABDABAAQgBDAEAARABDAEIARABCAEUARgBFAEIAQgBBAEcAQgBHAEYASABHAEEASABBAEkASQAOABcASQBBAA4ASgBIAEkASwBIAEoASwBMAEgATQBIAEwARwBIAE0AFwAYAE4ASgBJAE4ATgBJABcATwBKAE4ATgAYAE8ATwBQAEoAUABLAEoAUABRAEsAUgBTAFQAUgBVAFMAVQBSAFYAVwBVAFYAVQBXAFgAWABZAFUAWQBTAFUAWABaAFkAWABbAFoAWABXAFsAWwBXAFwAXQBbAFwAXQBeAFsAWwBeAFoAXQBfAF4AXgBfAGAAYQBeAGAAXgBhAFoAYQBiAFoAYQBjAGIAYwBhAGAAYABkAGMAYwBkAFIAUgBkAFYAXwBlAGAAZABgAGUAZABmAFYAZgBkAGUAUgBUAGcAUgBnAGMAYwBnAGIAVABoAGcAaQBoAFQAaQBqAGgAawBqAGkAawBsAGoAbABrAG0AbABtAG4AbABuAG8AbABvAGoAYgBnAHAAYgBwAFoAZwBoAHAAcABoAGoAagBvAHAAcABxAFoAbwByAHAAcgBxAHAAbgByAG8AbgBzAHIAcwBuAHQAcwB0AHUAcQByAHYAcwB2AHIAcwB1AHYAWgBxAHcAcQB2AHcAWQBaAHcAWQB3AFMAdwB4AFMAUwB4AFQAdgB5AHcAdQB5AHYAeAB3AHkAeAB5AHoAeAB6AFQAewBpAFQAegB7AFQAfABpAHsAfABrAGkAfQBrAHwAawB9AG0AfgB9AHwAfwB8AHsAfwB7AHoAfgB8AH8AfgB/AIAAgAB6AHkAgAB/AHoAdQCAAHkAgQCAAHUAdACBAHUAgQB+AIAAbQCCAG4AbQB9AIIAbgCCAHQAdACCAIEAfQCDAIIAggCDAIEAfQB+AIMAgQCDAH4AVwCEAFwAhABXAFYAhABWAGYAhQCGAIcAiACFAIcAiACJAIUAiQCIAIoAigCLAIkAjACLAIoAigCNAIwAiACOAIoAiACHAI4AjgCNAIoAjgCHAI8AkACOAI8AkACNAI4AkACPAJEAjwCSAJEAjwCHAJMAkwCSAI8AkwCHAJQAkwCUAJUAlQCSAJMAkgCVAJYAkQCSAJcAlgCXAJIAmACXAJYAjACYAIsAlgCLAJgAmQCLAJYAlQCZAJYAiQCLAJkAiQCaAIUAmQCaAIkAhQCaAIYAmQCbAJoAmQCcAJsAmQCVAJwAlACcAJUAlACHAJ0AlACdAJwAhwCeAJ0AhgCeAIcAngCGAJ8AngCfAKAAnQCeAKAAoQCdAKAAoQCgAKIAowChAKIAowCiAKQAowCkAKUApQCmAKMApgCdAKEApgChAKMApwCmAKUAqACnAKUAqQCbAKcAqQCnAKgAqgCpAKgAqwCqAKgArACoAKUApACsAKUAqwCoAKwArACtAKsArgCtAKwAogCuAKQApACuAKwArwCrAK0ArwCtAK4AsACvAK4AsACuAKIAsQCvALAAqwCyAKoArwCxALIArwCyAKsAsgCzAKoAswCbAKkAswCpAKoAtACzALIAnwCGALQAsQC0ALIAnwC0ALEAtQCfALEAtQCwAKIAogCgALUAoACfALUAtQCxALAAmgC2AIYAtgC0AIYAtgCbALMAtgCzALQAmwC2AJoApwC3AKYAnQCmALcAnQC3AJwAnAC3AJsAmwC3AKcAuAC5ALoAuwC8AL0AvgC7AL8AvgDAAMEAwgC+AMEAuwDDALoAwwC7AL4AwwC+AMIAGADEAE8AxAAYABkAxQAZABoAxAAZAMUAxQAaAMYALwDHADAAxwAxADAAxwDIADEAyAA0ADEAyQDHAC8AygDLAMwAzQDKAMwAzQDOAMoAzgDNAM8AywDQAMwAywDRANAAywDSANEA0gDTANEA1ADVANYA1ADXANUA2ADZANoA2wDZANgA2wDcANkA2wDdANwA3gDdANsA1ADfAOAAuQC8ALsAuQC7ALoA4QC5ALgA4gC5AOEAvAC5AOIA4wC7AL0AvwC7AOMAvwDAAL4AzwDkAM4A0wDSAOUA1gDfANQA1QDXAOYA5gDXANgA2gDmANgA" 677 | } 678 | ] 679 | } 680 | -------------------------------------------------------------------------------- /filesaver.js: -------------------------------------------------------------------------------- 1 | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ 2 | var saveAs=saveAs||(navigator.msSaveBlob&&navigator.msSaveBlob.bind(navigator))||(function(h){var r=h.document,l=function(){return h.URL||h.webkitURL||h},e=h.URL||h.webkitURL||h,n=r.createElementNS("http://www.w3.org/1999/xhtml","a"),g="download" in n,j=function(t){var s=r.createEvent("MouseEvents");s.initMouseEvent("click",true,false,h,0,0,0,0,0,false,false,false,false,0,null);t.dispatchEvent(s)},o=h.webkitRequestFileSystem,p=h.requestFileSystem||o||h.mozRequestFileSystem,m=function(s){(h.setImmediate||h.setTimeout)(function(){throw s},0)},c="application/octet-stream",k=0,b=[],i=function(){var t=b.length;while(t--){var s=b[t];if(typeof s==="string"){e.revokeObjectURL(s)}else{s.remove()}}b.length=0},q=function(t,s,w){s=[].concat(s);var v=s.length;while(v--){var x=t["on"+s[v]];if(typeof x==="function"){try{x.call(t,w||t)}catch(u){m(u)}}}},f=function(t,u){var v=this,B=t.type,E=false,x,w,s=function(){var F=l().createObjectURL(t);b.push(F);return F},A=function(){q(v,"writestart progress write writeend".split(" "))},D=function(){if(E||!x){x=s(t)}if(w){w.location.href=x}v.readyState=v.DONE;A()},z=function(F){return function(){if(v.readyState!==v.DONE){return F.apply(this,arguments)}}},y={create:true,exclusive:false},C;v.readyState=v.INIT;if(!u){u="download"}if(g){x=s(t);n.href=x;n.download=u;j(n);v.readyState=v.DONE;A();return}if(h.chrome&&B&&B!==c){C=t.slice||t.webkitSlice;t=C.call(t,0,t.size,c);E=true}if(o&&u!=="download"){u+=".download"}if(B===c||o){w=h}else{w=h.open()}if(!p){D();return}k+=t.size;p(h.TEMPORARY,k,z(function(F){F.root.getDirectory("saved",y,z(function(G){var H=function(){G.getFile(u,y,z(function(I){I.createWriter(z(function(J){J.onwriteend=function(K){w.location.href=I.toURL();b.push(I);v.readyState=v.DONE;q(v,"writeend",K)};J.onerror=function(){var K=J.error;if(K.code!==K.ABORT_ERR){D()}};"writestart progress write abort".split(" ").forEach(function(K){J["on"+K]=v["on"+K]});J.write(t);v.abort=function(){J.abort();v.readyState=v.DONE};v.readyState=v.WRITING}),D)}),D)};G.getFile(u,{create:false},z(function(I){I.remove();H()}),z(function(I){if(I.code===I.NOT_FOUND_ERR){H()}else{D()}}))}),D)}),D)},d=f.prototype,a=function(s,t){return new f(s,t)};d.abort=function(){var s=this;s.readyState=s.DONE;q(s,"abort")};d.readyState=d.INIT=0;d.WRITING=1;d.DONE=2;d.error=d.onwritestart=d.onprogress=d.onwrite=d.onabort=d.onerror=d.onwriteend=null;h.addEventListener("unload",i,false);return a}(self)); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Animal Crossing: New Leaf Pattern Tool - By Thulinma (ACNL Pattern Maker) 6 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 |
203 |

Animal Crossing: New Leaf Pattern Tool

204 |

By Thulinma

205 | Last updated: December 14, 2018
206 |

Questions / remarks / cookies? Please read the FAQ on the bottom of the page!

207 |
208 |
209 |
210 |
211 | 212 | 213 | 214 |
215 |
+
216 |
-
217 |
218 |
219 | 220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 | 253 | 254 |
255 | 256 | 268 |
269 | 270 | 271 |
272 | 273 | 274 |
275 | 276 | 277 | 278 |
279 | 280 | 281 |
282 | 283 | 284 | 290 | 291 |
292 |
293 |
294 | 295 |

FAQ

296 |
297 |
298 |

ZOMG This thing doesn't work!

299 |

The ACNL pattern tool is completely written in HTML5 and JavaScript. As such, it requires a decently standards-compliant browser. The latest versions of Chrome / Chromium / Firefox work. No promises on anything else. Internet Explorer will probably choke on this entire page.

300 |
301 |
302 |

How do I use this thing?

303 |

Click a color on the 3x5 palette and then just "draw" on one of the pattern representations. All of the zoom levels are drawable and they will all update at the same time. When you want to import to ACNL, simply scan the QR code at the bottom using the QR machine at the Able Sisters in-game. Don't have the QR machine yet? Talk to the quiet sister in the back for 10 days in a row to unlock it. The download ACNL file button lets you save the pattern to your computer for later use. You can also upload ACNL files or images containing QR codes. Don't upload images containing multiple QR codes - multi-part codes need to be uploaded one at a time, in order.

304 |
305 |
306 |

How did you make this?

307 |
308 |

Mostly magic. It helped that I made the ACWW pattern tool, and ACNL patterns are mostly in the same format. As to how exactly it works - HTML5 and JavaScript.

I make use of the following JavaScript libraries from others (some with my own modifications or fixes), everything else is my work:

309 | 318 |
319 |
320 |
321 |

Wait if you made the ACWW Pattern tool - does that mean ACWW patterns can be imported?

322 |

Yeah, I plan to add that as a feature in the future.

323 |
324 |
325 |

This is open source? So I can re-use this code for my own projects?

326 |

Yes. Please don't claim you wrote it all yourself, and try to include a notice "Based on the ACNL Pattern tool by Thulinma" somewhere. You don't *have* to include a notice like that, but I will be very very disappointed in you if you don't.

327 |
328 |
329 |

Is there an offline version I can use without an internet connection?

330 |

Yes. This is the download link.

331 |
332 |
333 |

I made something better / fixed something / added more browser support!

334 |

That's not a question! But - yay! Drop me a line with your code changes and if I like them I'll migrate them into the main project.

335 |
336 |
337 |

Can I make a suggestion?

338 |

If you think you can program your suggestion yourself - go ahead, and see the "question" above this one. If you can't - I probably don't have interest in implementing it myself unless your idea is truly awesome (and/or I'm already working on it) - but you can always suggest it and who knows.

339 |
340 |
341 |

Why isn't my QR code being read? It works in the game!

342 |

I'm using the jsqrcode port from the zxing QR libraries. Unfortunately this port isn't very accurate and it has trouble with some QR codes. In fact, I had to make some fixes to get it to read ACNL QR codes at all (I've submitted the needed fixes to the author of the port, so everyone can benefit from them). Feel free to improve the library yourself and let me know if/when more fixes become available and I'll integrate them as soon as I can.

343 |
344 |
345 |

What are ".ACNL" files?

346 |

A small binary format storage for ACNL patterns. Similar to ACWW files, they contain the pattern and nothing more. For ACNL files I used the exact binary contents of the QR codes - so any QR code can be decoded into an ACNL file and any ACNL file encoded into QR.

347 |
348 |
349 |

What features are you still working on?

350 |
351 |

Some of the stuff I have in mind includes:

352 |
    353 |
  • Importing stored ACWW files
  • 354 |
  • Adding a pattern database with tagging/search
  • 355 |
  • Experimenting with out of bounds color values (many values are not used in-game...)
  • 356 |
  • Adding image conversion for pro designs
  • 357 |
  • Figure out what the 6 bytes of unknown data represent
  • 358 |
  • Add support for viewing/changing the pattern type
  • 359 |
360 |
361 |
362 |
363 |

What is the changelog?

364 |
    365 |
  • June 24, 2013: First working version, QR code generation.
  • 366 |
  • June 25, 2013: Pattern editing (drawing), palette editing, title/creator/town and all related ID editing.
  • 367 |
  • June 28, 2013: Firefox support, creator copy/paste buttons, loading ACNL files.
  • 368 |
  • June 29, 2013: Loading QR code images now works, added an empty default pattern, removed old preset patterns (they were used without permission), added preliminary support for converting images to patterns (pretty low quality, but it works), improved the colors (now actual colors as they are in-game)
  • 369 |
  • June 30, 2013: Support for pro patterns (both import and export), added pixel grid, added zoom buttons, added offline version download link in FAQ, added a selection box with 4 different image conversion optimizers
  • 370 |
  • May 24, 2014: Still alive! Fixed a bug causing drawing to get stuck in several browsers. Fixed bug of having 16 shades of grey instead of the 15 from in-game. Updated jsqrcode for better QR code recognition. Added support for automatically attempting to recover from some corrupt QR codes. Special thanks to "Kiddiecat" for pointing out the drawing bug. Special thanks to "Michael New" for pointing out the 16 shades of grey bug. Special thanks to "Edel Fernández" for supplying a corrupt QR code.
  • 371 |
  • December 14, 2018: A special update in honor of an important day exactly three years ago. Spit-shine and polish, CSS improvements and some minor typos corrected by "Myumi Kalinowski". Added 3D render for shirt and dress modes. Added ability to change pattern type as well as create other types than the standard type from scratch. More updates coming soon. Maybe. We'll see!
  • 372 |
373 |
374 |
375 |

How do I contact you?

376 |

You can e-mail me at thulinma@thulinma.com - but please keep in mind I'm a busy guy so don't e-mail me unless you have a worthwhile contribution or something similar. :-)

377 |
378 |
379 |
380 | 381 | 382 | 383 | -------------------------------------------------------------------------------- /jquery.qrcode.js: -------------------------------------------------------------------------------- 1 | /*! {{pkg.displayName}} {{pkg.version}} - //larsjung.de/qrcode - MIT License */ 2 | 3 | // Uses [QR Code Generator](http://www.d-project.com/qrcode/index.html) (MIT), appended to the end of this file. 4 | // Kudos to [jquery.qrcode.js](http://github.com/jeromeetienne/jquery-qrcode) (MIT). 5 | 6 | (function ($) { 7 | 'use strict'; 8 | 9 | // Check if canvas is available in the browser (as Modernizr does) 10 | var canvasAvailable = (function () { 11 | 12 | var elem = document.createElement('canvas'); 13 | return !!(elem.getContext && elem.getContext('2d')); 14 | }()), 15 | 16 | // Wrapper for the original QR code generator. 17 | createQr = function (typeNumber, correctLevel, text, multipart_num, multipart_total, multipart_parity) { 18 | 19 | // `qrcode` is the single public function that will be defined by the `QR Code Generator` 20 | // at the end of the file. 21 | var qr = qrencode(typeNumber, correctLevel, multipart_num, multipart_total, multipart_parity); 22 | qr.addData(text); 23 | qr.make(); 24 | 25 | return qr; 26 | }, 27 | 28 | // Returns a minimal QR code for the given text. Returns `null` if `text` 29 | // is to long to be encoded. At the moment it should work with up to 271 characters. 30 | createBestQr = function (text, multipart_num, multipart_total, multipart_parity) { 31 | 32 | for (var type = 2; type <= 40; type += 1) { 33 | try { 34 | return createQr(type, 'L', text, multipart_num, multipart_total, multipart_parity); 35 | } catch (err) {} 36 | } 37 | 38 | return null; 39 | }, 40 | 41 | // Draws QR code to the given `canvas` and returns it. 42 | drawOnCanvas = function (canvas, settings) { 43 | 44 | // some shortcuts to improve compression 45 | var settings_text = settings.text, 46 | settings_left = settings.left, 47 | settings_top = settings.top, 48 | settings_width = settings.width, 49 | settings_height = settings.height, 50 | settings_color = settings.color, 51 | settings_bgColor = settings.bgColor, 52 | 53 | qr = createBestQr(settings_text, settings.multipart_num, settings.multipart_total, settings.multipart_parity), 54 | $canvas = $(canvas), 55 | ctx = $canvas[0].getContext('2d'); 56 | 57 | if (settings_bgColor) { 58 | ctx.fillStyle = settings_bgColor; 59 | ctx.fillRect(settings_left, settings_top, settings_width, settings_height); 60 | } 61 | 62 | if (qr) { 63 | var moduleCount = qr.getModuleCount(), 64 | moduleWidth = settings_width / moduleCount, 65 | moduleHeight = settings_height / moduleCount, 66 | row, col; 67 | 68 | ctx.beginPath(); 69 | for (row = 0; row < moduleCount; row += 1) { 70 | for (col = 0; col < moduleCount; col += 1) { 71 | if (qr.isDark(row, col)) { 72 | ctx.rect(settings_left + col * moduleWidth, settings_top + row * moduleHeight, moduleWidth, moduleHeight); 73 | } 74 | } 75 | } 76 | ctx.fillStyle = settings_color; 77 | ctx.fill(); 78 | } 79 | 80 | return $canvas; 81 | }, 82 | 83 | // Returns a `canvas` element representing the QR code for the given settings. 84 | createCanvas = function (settings) { 85 | 86 | var $canvas = $('').attr('width', settings.width).attr('height', settings.height).css("margin-bottom", "40px"); 87 | 88 | return drawOnCanvas($canvas, settings); 89 | }, 90 | 91 | // Returns a `div` element representing the QR code for the given settings. 92 | createDiv = function (settings) { 93 | 94 | // some shortcuts to improve compression 95 | var settings_text = settings.text, 96 | settings_width = settings.width, 97 | settings_height = settings.height, 98 | settings_color = settings.color, 99 | settings_bgColor = settings.bgColor, 100 | math_floor = Math.floor, 101 | 102 | qr = createBestQr(settings_text), 103 | $div = $('
').css({ 104 | position: 'relative', 105 | left: 0, 106 | top: 0, 107 | padding: 0, 108 | margin: 0, 109 | width: settings_width, 110 | height: settings_height 111 | }); 112 | 113 | if (settings_bgColor) { 114 | $div.css('background-color', settings_bgColor); 115 | } 116 | 117 | if (qr) { 118 | var moduleCount = qr.getModuleCount(), 119 | moduleWidth = math_floor(settings_width / moduleCount), 120 | moduleHeight = math_floor(settings_height / moduleCount), 121 | offsetLeft = math_floor(0.5 * (settings_width - moduleWidth * moduleCount)), 122 | offsetTop = math_floor(0.5 * (settings_height - moduleHeight * moduleCount)), 123 | row, col; 124 | 125 | for (row = 0; row < moduleCount; row += 1) { 126 | for (col = 0; col < moduleCount; col += 1) { 127 | if (qr.isDark(row, col)) { 128 | $('
') 129 | .css({ 130 | left: offsetLeft + col * moduleWidth, 131 | top: offsetTop + row * moduleHeight 132 | }) 133 | .appendTo($div); 134 | } 135 | } 136 | } 137 | 138 | $div.children() 139 | .css({ 140 | position: 'absolute', 141 | padding: 0, 142 | margin: 0, 143 | width: moduleWidth, 144 | height: moduleHeight, 145 | 'background-color': settings_color 146 | }); 147 | } 148 | 149 | return $div; 150 | }, 151 | 152 | createHTML = function (options) { 153 | 154 | var settings = $.extend({}, defaults, options); 155 | 156 | return canvasAvailable && settings.render === 'canvas' ? createCanvas(settings) : createDiv(settings); 157 | }, 158 | 159 | // Plugin 160 | // ====== 161 | 162 | // Default settings 163 | // ---------------- 164 | defaults = { 165 | 166 | // render method: `'canvas'` or `'div'` 167 | render: 'canvas', 168 | 169 | // left and top in pixel if drawn onto existing canvas 170 | left: 0, 171 | top: 0, 172 | 173 | // width and height in pixel 174 | width: 256, 175 | height: 256, 176 | 177 | // code color 178 | color: '#000', 179 | 180 | // background color, `null` for transparent background 181 | bgColor: null, 182 | 183 | // the encoded text 184 | text: 'no text' 185 | }; 186 | 187 | // Register the plugin 188 | // ------------------- 189 | $.fn.qrcode = function(options) { 190 | 191 | return this.each(function () { 192 | 193 | if (this.nodeName.toLowerCase() === 'canvas') { 194 | drawOnCanvas(this, options); 195 | } else { 196 | $(this).append(createHTML(options)); 197 | } 198 | }); 199 | }; 200 | 201 | // jQuery.qrcode plug in code ends here 202 | 203 | // QR Code Generator 204 | // ================= 205 | // @include "qrcode.js" 206 | 207 | }(jQuery)); 208 | -------------------------------------------------------------------------------- /page.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | 3 | 4 | 5 | var scene = new THREE.Scene(); 6 | var camera = new THREE.PerspectiveCamera( 75, 1, 0.1, 1000 ); 7 | var renderer = new THREE.WebGLRenderer({"canvas":$("#acnl_preview")[0]}); 8 | var texture; 9 | var renderCanvas = document.createElement('canvas'); 10 | renderCanvas.width = 32; 11 | renderCanvas.height = 128; 12 | 13 | var renderContext = renderCanvas.getContext('2d'); 14 | renderContext.fillStyle = "rgba(255,255,255,1)"; 15 | renderContext.fillRect(0, 0, 32, 128); 16 | 17 | renderer.gammaOutput = true; 18 | renderer.gammaFactor = 2.2; 19 | renderer.setSize(128, 128); 20 | camera.position.z = 15; 21 | camera.position.y = 30; 22 | camera.rotation.x = 5.6; 23 | 24 | var model = false; 25 | function animate() { 26 | if (model){ 27 | model.rotation.y += 0.01; 28 | } 29 | requestAnimationFrame(animate); 30 | renderer.render(scene, camera); 31 | } 32 | animate(); 33 | 34 | function loadModel(path){ 35 | if (model){ 36 | scene.remove(model); 37 | model = false; 38 | } 39 | if (path == ""){ 40 | return; 41 | } 42 | var loader = new THREE.GLTFLoader(); 43 | loader.load(path, function(gltf){ 44 | model = gltf.scene.children[0]; 45 | model.traverse(function (child) { 46 | if (child instanceof THREE.Mesh) { 47 | texture = new THREE.Texture(renderCanvas) 48 | texture.needsUpdate = true; 49 | texture.encoding = THREE.sRGBEncoding; 50 | texture.flipY = false; 51 | texture.magFilter = THREE.NearestFilter; 52 | child.material = new THREE.MeshBasicMaterial({map:texture}); 53 | } 54 | }); 55 | scene.add(model); 56 | }, undefined, console.error); 57 | } 58 | 59 | var goingToRefresh = false; 60 | function triggerRefresh(){ 61 | if (model){ 62 | model.traverse(function (child) { 63 | if (child instanceof THREE.Mesh) { 64 | child.material.map.needsUpdate = true; 65 | } 66 | }); 67 | } 68 | if (goingToRefresh){clearTimeout(goingToRefresh);} 69 | goingToRefresh = setTimeout(function(){ACNL.qr($("#qr"));}, 3000); 70 | } 71 | 72 | function noRefresh(){ 73 | if (goingToRefresh){clearTimeout(goingToRefresh);} 74 | goingToRefresh = false; 75 | } 76 | 77 | var chosen_color = 0; 78 | 79 | function newIcon(data){ 80 | ACNL.load(data); 81 | for (var i = 0; i < 15; i++){ 82 | $("#col"+i).css("background-color", ACNL.getColor(i)); 83 | } 84 | chosen_color = 0; 85 | $(".col_pal").attr("class", "col_pal").each(function(){ 86 | if ($(this).data("color") == ACNL.getIndex(chosen_color)){ 87 | $(this).attr("class", "col_pal picked"); 88 | } 89 | }); 90 | $("#icon_title").val(ACNL.getTitle()); 91 | $("#icon_creator").val(ACNL.getCreator()); 92 | $("#icon_creator_id").val(ACNL.getCreatorID()); 93 | $("#icon_town").val(ACNL.getTown()); 94 | $("#icon_town_id").val(ACNL.getTownID()); 95 | $("#icon_type").val(ACNL.getTypeNum()); 96 | ACNL.draw($("#acnl_icon")[0]); 97 | ACNL.draw($("#acnl_icon_zoom")[0]); 98 | ACNL.draw($("#acnl_icon_zoomier")[0]); 99 | ACNL.draw(renderCanvas); 100 | loadModel(ACNL.getTypeModel()); 101 | triggerRefresh(); 102 | }; 103 | 104 | $("#icon_title").keyup(function(){ 105 | if ($(this).val().length > 20){ 106 | $(this).val($(this).val().substr(0, 20)); 107 | } 108 | ACNL.setTitle($(this).val()); 109 | triggerRefresh(); 110 | }); 111 | 112 | $("#icon_creator").keyup(function(){ 113 | if ($(this).val().length > 10){ 114 | $(this).val($(this).val().substr(0, 10)); 115 | } 116 | ACNL.setCreator($(this).val()); 117 | triggerRefresh(); 118 | }); 119 | 120 | $("#icon_town").keyup(function(){ 121 | if ($(this).val().length > 10){ 122 | $(this).val($(this).val().substr(0, 10)); 123 | } 124 | ACNL.setTown($(this).val()); 125 | triggerRefresh(); 126 | }); 127 | 128 | $("#icon_creator_id").keyup(function(){ 129 | ACNL.setCreatorID($(this).val()); 130 | triggerRefresh(); 131 | }); 132 | 133 | $("#icon_town_id").keyup(function(){ 134 | ACNL.setTownID($(this).val()); 135 | triggerRefresh(); 136 | }); 137 | 138 | $("#unknown_id").keyup(function(){ 139 | ACNL.setUnknownID($(this).val()); 140 | triggerRefresh(); 141 | }); 142 | 143 | $("#acnl_gen").click(function(){ 144 | ACNL.download(); 145 | }); 146 | 147 | var drawing = false; 148 | $("#acnl_icon, #acnl_icon_zoom, #acnl_icon_zoomier").click(function(e){ 149 | var xpos = 0, ypos = 0; 150 | if (e.offsetX == undefined){ 151 | xpos = e.pageX-$(e.target).offset().left; 152 | ypos = e.pageY-$(e.target).offset().top; 153 | }else{ 154 | xpos = e.offsetX; 155 | ypos = e.offsetY; 156 | } 157 | var x = Math.floor(xpos / ($(this).width() / ACNL.getWidth())); 158 | var y = Math.floor(ypos / ($(this).height() / ACNL.getWidth())); 159 | ACNL.setColor(x, y, chosen_color); 160 | triggerRefresh(); 161 | }).mousemove(function(e){ 162 | if (drawing && e.which == 1){ 163 | noRefresh(); 164 | var xpos = 0, ypos = 0; 165 | if (e.offsetX == undefined){ 166 | xpos = e.pageX-$(e.target).offset().left; 167 | ypos = e.pageY-$(e.target).offset().top; 168 | }else{ 169 | xpos = e.offsetX; 170 | ypos = e.offsetY; 171 | } 172 | var x = Math.floor(xpos / ($(this).width() / ACNL.getWidth())); 173 | var y = Math.floor(ypos / ($(this).height() / ACNL.getWidth())); 174 | ACNL.setColor(x, y, chosen_color); 175 | } 176 | }).mouseup(function(){ 177 | drawing = false; 178 | triggerRefresh(); 179 | }).mousedown(function(){ 180 | drawing = true; 181 | }); 182 | 183 | for (var i = 0; i < 15; i++){ 184 | $("#col"+i).data("col", i).click(function(){ 185 | $(".col_block").attr("class", "col_block"); 186 | $(this).attr("class", "col_block picked"); 187 | chosen_color = $(this).data("col"); 188 | $(".col_pal").attr("class", "col_pal").each(function(){ 189 | if ($(this).data("color") == ACNL.getIndex(chosen_color)){ 190 | $(this).attr("class", "col_pal picked"); 191 | } 192 | }); 193 | }); 194 | } 195 | 196 | $(".question").click(function(){ 197 | $(this).children(".ans").toggle(); 198 | }); 199 | $(".ans").hide(); 200 | 201 | function create_block(p){ 202 | var block = $("
").attr("class", "col_pal_block"); 203 | for (var i = 0; i < 9; i++){ 204 | block.append($("
").attr("class", "col_pal").css("background-color", ACNL.getPal(p+i)).data("color", p+i)); 205 | } 206 | return block; 207 | }; 208 | 209 | for (var i = 0x00; i < 0xFF; i += 0x10){ 210 | $("#color_pal").append(create_block(i)); 211 | } 212 | var grey_row = $("
").attr("class", "col_pal_row"); 213 | for (var i = 0; i < 15; i++){ 214 | grey_row.append($("
").attr("class", "col_pal").css("background-color", ACNL.getPal((i << 4) + 0x0F)).data("color", (i << 4) + 0x0F)); 215 | } 216 | $("#color_pal").append(grey_row); 217 | $(".col_pal").click(function(){ 218 | $(".col_pal").attr("class", "col_pal"); 219 | $(this).attr("class", "col_pal picked"); 220 | var newindex = $(this).data("color"); 221 | ACNL.setIndex(chosen_color, newindex); 222 | $("#col"+chosen_color).css("background-color", ACNL.getColor(chosen_color)); 223 | triggerRefresh(); 224 | }); 225 | 226 | /* 227 | $(".pattern_preset").each(function(){ 228 | var name = $(this).data("name"); 229 | var pattern = $(this).data("pattern"); 230 | $("#load_pattern").append($("