asciiblaster- draw irc art in your web browser |
git clone git://git.acid.vegas/asciiblaster.git |
Log | Files | Refs | Archive | README |
nopaint.js (22684B)
1 var nopaint = (function(){ 2 3 controls.no = new Tool (nopaint_no_el) 4 controls.no.use = function(state){ 5 undo.undo() 6 controls.paint.focus() 7 } 8 controls.no.context = function(e){ 9 e.preventDefault() 10 nopaint.turbo() 11 } 12 13 controls.paint = new Tool (nopaint_paint_el) 14 controls.paint.use = function(state){ 15 nopaint.paint() 16 nopaint_pause_el.classList.toggle("hidden", false) 17 focused = controls.paint.lex 18 } 19 controls.paint.context = function(e){ 20 e.preventDefault() 21 nopaint.autoplay() 22 } 23 24 controls.nopaint_pause = new Tool (nopaint_pause_el) 25 controls.nopaint_pause.use = function(state){ 26 // nopaint.pause() 27 nopaint.autoplay(false) 28 nopaint_pause_el.classList.toggle("hidden", true) 29 focused = canvas.aa[0][0] 30 } 31 32 // use own stepwise clock to drive tweens 33 oktween.raf = function(){} 34 35 var nopaint = {} 36 nopaint.debug = true 37 nopaint.delay = nopaint.normal_delay = 100 38 nopaint.turbo_delay = 0 39 nopaint.tool = null 40 nopaint.tools = {} 41 nopaint.keys = [] 42 nopaint.weights = [] 43 nopaint.step = 0 44 nopaint.time = 0 45 nopaint.timeout = false 46 nopaint.toggle = function(state){ 47 var state = typeof state == "boolean" ? state : nopaint_rapper.classList.contains("hidden") 48 nopaint_rapper.classList.toggle("hidden", ! state) 49 nopaint_pause_el.classList.toggle("hidden", true) 50 document.body.classList.toggle("nopaint", state) 51 return state 52 } 53 nopaint.no = function(){ 54 undo.undo() 55 nopaint.paint() 56 } 57 nopaint.raw_key = controls.paint.lex.raw_key = keys.left_right_key(function(n){ 58 if (! nopaint.timeout) return 59 if (n < 0) nopaint.no() 60 else if (n > 0) nopaint.paint() 61 else nopaint.pause() 62 }) 63 nopaint.pause = nopaint.blur = function(){ 64 clearTimeout(nopaint.timeout) 65 nopaint.timeout = 0 66 nopaint.step = 0 67 } 68 nopaint.paint = function(){ 69 var state = undo.new() 70 delete state.focus 71 nopaint.pause() 72 nopaint.switch_tool() 73 nopaint.go() 74 } 75 nopaint.go = function(){ 76 nopaint.timeout = setTimeout(nopaint.go, nopaint.delay) 77 oktween.update(nopaint.time) 78 nopaint.tool.paint( nopaint.step ) 79 nopaint.time += 1 80 nopaint.step += 1 81 } 82 nopaint.switch_tool = function(){ 83 last_tool = nopaint.tool 84 last_tool && last_tool.finish() 85 nopaint.tool = nopaint.get_random_tool( last_tool ) 86 nopaint.tool.start( last_tool ) 87 nopaint.debug && console.log("> %s", nopaint.tool.type) 88 } 89 nopaint.add_tool = function(fn){ 90 nopaint.tools[fn.type] = fn 91 } 92 nopaint.disable_all_tools = function(){ 93 Object.keys(nopaint.tools).forEach(function(key){ 94 nopaint.tools[key].disabled = true 95 }) 96 } 97 nopaint.enable_tools = function(keys){ 98 keys.forEach(function(key){ 99 if (nopaint.tools[key]) nopaint.tools[key].disabled = false 100 }) 101 } 102 nopaint.get_random_tool = function( last_tool ){ 103 var n = rand( nopaint.sum ) 104 for (var i = 0, _len = nopaint.weights.length; i < _len; i++) { 105 if (n < nopaint.weights[i] && (! last_tool || nopaint.keys[i] !== last_tool.key)) { 106 return nopaint.tools[ nopaint.keys[i] ] 107 } 108 } 109 return nopaint.tools[ choice(nopaint.keys) ] 110 } 111 nopaint.regenerate_weights = function(){ 112 nopaint.sum = 0 113 nopaint.weights = [] 114 nopaint.keys = Object.keys( nopaint.tools ).sort(function(a,b){ 115 return nopaint.tools[b].opt.weight-nopaint.tools[a].opt.weight 116 }).filter(function(key){ 117 return ! nopaint.tools[key].disabled 118 }) 119 nopaint.keys.forEach(function(key){ 120 nopaint.sum += nopaint.tools[key].opt.weight 121 nopaint.weights.push( nopaint.sum ) 122 }) 123 } 124 125 nopaint.is_turbo = false 126 nopaint.turbo = function(state){ 127 nopaint.is_turbo = typeof state == "boolean" ? state : ! nopaint.is_turbo 128 nopaint.delay = nopaint.is_turbo ? nopaint.turbo_delay : nopaint.normal_delay 129 if (nopaint.is_turbo) { 130 nopaint_no_el.classList.add("locked") 131 } 132 else { 133 nopaint_no_el.classList.remove("locked") 134 } 135 } 136 137 nopaint.is_autoplay = false 138 nopaint.autoplay = function(state){ 139 nopaint.is_autoplay = typeof state == "boolean" ? state : ! nopaint.is_autoplay 140 if (nopaint.is_autoplay) { 141 nopaint_paint_el.classList.add("locked") 142 if (! nopaint.player) { 143 nopaint.player = new RandomPlayer () 144 } 145 if (! nopaint.timeout) nopaint.paint() 146 nopaint.player.play() 147 } 148 else { 149 nopaint_paint_el.classList.remove("locked") 150 nopaint.pause() 151 nopaint.player && nopaint.player.pause() 152 } 153 } 154 155 var NopaintPlayer = Model({ 156 type: "player", 157 upload_png: false, 158 upload_interval: 100, 159 step: 0, 160 timeout: null, 161 delay: function(){ 162 return nopaint.is_turbo ? randrange(150, 300) : randrange(400, 800) 163 }, 164 reset: function(){ 165 this.no_count = 0 166 this.paint_count = 0 167 }, 168 pause: function(){ 169 clearTimeout(this.timeout) 170 this.timeout = 0 171 }, 172 play: function(){ 173 clearTimeout(this.timeout) 174 var delay = this.delay() 175 this.timeout = setTimeout(this.play.bind(this), delay) 176 this.check_fitness() 177 this.step += 1 178 }, 179 check_fitness: function(){ 180 switch (this.fitness()) { 181 case "no": 182 nopaint.no_count += 1 183 nopaint.since_last_no = 0 184 nopaint.since_last_paint += 1 185 nopaint.no() 186 break 187 case "paint": 188 nopaint.paint_count += 1 189 nopaint.since_last_no += 1 190 nopaint.since_last_paint = 0 191 nopaint.paint() 192 break 193 case "screenshot": 194 if (this.save_as_png) break 195 console.log("uploading...") 196 setTimeout(clipboard.upload_png, 0) 197 // fall thru 198 default: 199 nopaint.since_last_no += 1 200 nopaint.since_last_paint += 1 201 break 202 } 203 }, 204 fitness: function(){}, 205 }) 206 207 var RandomPlayer = NopaintPlayer.extend({ 208 type: "random_player", 209 upload_png: false, 210 fitness: function(){ 211 var no_prob = random() 212 var paint_prob = 1 - no_prob 213 if (paint_prob < 0.3) { 214 return "paint" 215 } 216 else if (no_prob < 0.5) { 217 return "no" 218 } 219 else if ( this.paint_count > 100 && (this.step % 100) == 99 ) { 220 return "screenshot" 221 } 222 } 223 }) 224 225 var StylePlayer = NopaintPlayer.extend({ 226 type: "style_player", 227 upload_png: false, 228 fitness: function(){ 229 var no_prob = random() 230 var paint_prob = 1 - no_prob 231 var np, pp 232 var steps = this.since_last_paint 233 234 if (nopaint.tool.is_brush) { 235 if (nopaint.tool.is_clone) { 236 if (steps < randrange(3,8)) return 237 np = 0.3 238 pp = 0.4 239 } 240 else if (nopaint.tool.is_erase) { 241 if (steps < randrange(2,6)) return 242 np = 0.3 243 pp = 0.4 244 } 245 else { 246 if (steps < randrange(2,4)) return 247 np = 0.1 248 pp = 0.3 249 } 250 } 251 if (nopaint.tool.is_shader) { 252 switch (nopaint.tool.name) { 253 case "rotate": 254 case "scale": 255 if (steps < randrange(2,4)) return 256 np = 0.1 257 pp = 0.2 258 break 259 default: 260 np = 0.2 261 pp = 0.2 262 } 263 } 264 if (nopaint.tool.is_fill) { 265 np = 0.4 266 pp = 0.1 267 } 268 269 if (steps > 10) { 270 np *= 0.7 271 pp *= 1.5 272 273 if (nopaint.is_turbo) { 274 np *= 1.2 275 pp *= 1.2 276 } 277 } 278 279 if (paint_prob < np) { 280 return "paint" 281 } 282 else if (no_prob < np) { 283 return "no" 284 } 285 else if ( this.paint_count > 100 && (this.step % 100) == 99 ) { 286 return "screenshot" 287 } 288 } 289 }) 290 291 /* Base models for brushes */ 292 293 var NopaintTool = Model({ 294 type: "none", 295 init: function(opt){ 296 this.opt = opt || {} 297 }, 298 start: function(){}, 299 paint: function(t){}, 300 update: function(t){}, 301 finish: function(){}, 302 }) 303 304 var NopaintBrush = NopaintTool.extend({ 305 type: "brush", 306 is_brush: true, 307 init: function(opt){ 308 this.opt = opt || {} 309 this.opt.max_radius = this.opt.max_radius || 10 310 this.p = {x: randint(canvas.w), y: randint(canvas.h)} 311 this.fg = 0 312 this.bg = 1 313 this.char = " " 314 this.tweens = [] 315 }, 316 317 start: function(last_brush){ 318 this.set_brush_mask() 319 this.toggle_channels() 320 this.reset( last_brush ) 321 this.regenerate() 322 draw.down({}, null, [this.p.x, this.p.y]) 323 }, 324 325 paint: function(t){ 326 this.update(t) 327 draw.move_toroidal({}, null, [this.p.x, this.p.y]) 328 }, 329 330 finish: function(){ 331 this.tweens.forEach(function(t){ t.cancel() }) 332 this.tweens = [] 333 }, 334 335 reorient: function(last_brush){ 336 var a = {}, b 337 338 if (last_brush) { 339 this.p.x = a.x = randint(canvas.w) 340 this.p.y = a.y = randint(canvas.h) 341 } 342 else { 343 a.x = this.p.x 344 a.y = this.p.y 345 } 346 347 b = this.get_next_point() 348 349 var tween = oktween.add({ 350 obj: this.p, 351 from: a, 352 to: b, 353 duration: b.duration, 354 easing: b.easing, 355 update: b.update, 356 finished: function(){ 357 this.iterate() 358 this.regenerate() 359 }.bind(this) 360 }) 361 this.tweens.push(tween) 362 }, 363 364 get_next_point: function(){ 365 var radius = randrange(2, this.opt.max_radius) 366 var b = {} 367 b.duration = randrange(1, 7) 368 b.easing = choice(easings) 369 b.x = this.p.x + randrange(-radius, radius) 370 b.y = this.p.y + randrange(-radius, radius) 371 return b 372 }, 373 374 set_brush_mask: function(){ 375 var r = Math.random() 376 if (r < 0.2) { 377 brush.mask = blit.square 378 } 379 else if (r < 0.6) { 380 brush.mask = blit.circle 381 } 382 else if (r < 0.9) { 383 brush.mask = blit.cross 384 } 385 else{ 386 brush.mask = blit.inverted_cross 387 } 388 }, 389 390 toggle_channels: function(){ 391 if (Math.random() < 0.001) { controls.bg.use(false) } 392 else if (! brush.draw_bg && Math.random() < 0.25) { controls.bg.use(true) } 393 394 if (Math.random() < 0.1) { controls.fg.use(false) } 395 else if (! brush.draw_fg && Math.random() < 0.5) { controls.fg.use(true) } 396 397 if (Math.random() < 0.02) { controls.char.use(false) } 398 else if (! brush.draw_char && Math.random() < 0.2) { controls.char.use(true) } 399 }, 400 401 iterate: function( last_brush ){ 402 this.reorient( last_brush ) 403 }, 404 405 regenerate: function(){ 406 brush.load( this ) 407 brush.generate() 408 } 409 }) 410 411 var easings = "linear circ_out circ_in circ_in_out quad_in quad_out quad_in_out".split(" ") 412 413 /* Standard brushes */ 414 415 var SolidBrush = NopaintBrush.extend({ 416 type: "solid", 417 418 recolor: function(){ 419 this.fg = this.bg = randint(16) 420 this.char = " " 421 }, 422 423 resize: function(m,n){ 424 m = m || 3 425 n = n || 0 426 var bw = xrandrange(5, 0, m) + n 427 brush.resize( round(bw * randrange(0.9, 1.8)) || 1, round(bw) || 1 ) 428 }, 429 430 reset: function( last_brush ){ 431 this.opt.max_radius = randrange(5,20) 432 this.resize() 433 this.reorient( last_brush ) 434 this.recolor( last_brush ) 435 this.regenerate() 436 }, 437 438 iterate: function( last_brush ){ 439 this.resize() 440 this.reorient( last_brush ) 441 }, 442 }) 443 444 var EraseBrush = SolidBrush.extend({ 445 type: "erase", 446 reset: function( last_brush ){ 447 this.opt.max_radius = randrange(8, 20) 448 this.reorient( last_brush ) 449 this.bg = random() < 0.2 ? colors.white : colors.black 450 this.char = " " 451 brush.load( this ) 452 this.resize(3,2) 453 }, 454 }) 455 456 var ShadowBrush = NopaintBrush.extend({ 457 type: "shadow", 458 pairs: [ 459 [ colors.yellow, colors.orange ], 460 [ colors.orange, colors.darkred ], 461 [ colors.red, colors.darkred ], 462 [ colors.lime, colors.green ], 463 [ colors.cyan, colors.teal ], 464 [ colors.cyan, colors.blue ], 465 [ colors.blue, colors.darkblue ], 466 [ colors.magenta, colors.purple ], 467 [ colors.lightgray, colors.darkgray ], 468 [ colors.darkgray, colors.black ], 469 [ colors.white, colors.lightgray ], 470 [ colors.white, colors.black ], 471 ], 472 shapes: [ 473 [[0],[1]], 474 [[0,0],[1,1]], 475 [[1,0,0],[1,1,1]], 476 [[0,0,1],[1,1,1]], 477 [[0,0,0],[1,1,1]], 478 [[0,0,0,0],[1,1,1,1]], 479 [[1,0,0,0],[null,1,1,1]], 480 [[0,0,0,1],[1,1,1,null]], 481 [[0,0],[1,0],[1,1]], 482 [[0,0],[0,1],[1,1]], 483 ], 484 reset: function( last_brush ){ 485 var pair = choice(this.pairs) 486 var shape = choice(this.shapes) 487 this.reorient( last_brush ) 488 brush.char = " " 489 brush.resize(shape[0].length, shape.length) 490 brush.generate() 491 brush.rebuild() 492 brush.forEach(function(lex,x,y){ 493 if (shape[y][x] == null) { 494 lex.opacity = 0 495 } 496 else { 497 lex.fg = lex.bg = pair[ shape[y][x] ] 498 lex.opacity = 1 499 } 500 lex.build() 501 }) 502 }, 503 regenerate: function(){}, 504 }) 505 506 var RandomBrush = SolidBrush.extend({ 507 type: "random", 508 iterate: function( last_brush ){ 509 this.reorient( last_brush ) 510 this.recolor( last_brush ) 511 }, 512 }) 513 514 var HueBrush = SolidBrush.extend({ 515 type: "hue", 516 recolor: function(){ 517 this.fg = this.bg = rand_hue() 518 this.char = " " 519 }, 520 }) 521 522 var GrayBrush = SolidBrush.extend({ 523 type: "gray", 524 recolor: function(){ 525 this.fg = this.bg = rand_gray() 526 this.char = " " 527 }, 528 }) 529 530 var LetterBrush = SolidBrush.extend({ 531 type: "letter", 532 recolor: function(){ 533 this.fg = rand_hue() 534 this.bg = rand_hue() 535 this.char = choice( unicode.block(letters.charset, 32) ) 536 }, 537 }) 538 539 var RandomLetterBrush = LetterBrush.extend({ 540 type: "random-letter", 541 iterate: function(){ 542 if (Math.random() < 0.01) { 543 this.fg += 1 544 } 545 if (Math.random() < 0.05) { 546 var n = this.fg 547 this.fg = this.bg 548 this.bg = n 549 } 550 if (Math.random() < 0.7) { 551 this.char = choice( unicode.block(letters.charset, 32) ) 552 } 553 this.regenerate() 554 this.__iterate() 555 }, 556 update: function(){ 557 if (Math.random() < 0.3) { 558 this.char = choice( unicode.block(letters.charset, 32) ) 559 } 560 this.regenerate() 561 }, 562 }) 563 564 var CloneBrush = SolidBrush.extend({ 565 type: "clone", 566 567 is_clone: true, 568 569 reset: function( last_brush ){ 570 this.opt.max_radius = randrange(5, 20) 571 this.reorient( last_brush ) 572 this.resize(4,2) 573 this.clone_random_region() 574 }, 575 576 clone_random_region: function(x, y){ 577 var x = randrange(0, canvas.w - brush.w) 578 var y = randrange(0, canvas.h - brush.h) 579 this.clone_region(x, y) 580 }, 581 582 clone_region: function(x, y){ 583 blit.copy_toroidal_from(canvas, brush, round(x-brush.w/2), round(y-brush.h/2)) 584 brush.mask(brush) 585 }, 586 587 iterate: function( last_brush ){ 588 this.reorient( last_brush ) 589 }, 590 591 regenerate: function(){}, 592 }) 593 594 var SmearBrush = CloneBrush.extend({ 595 type: "smear", 596 597 update: function(){ 598 var r = random() 599 var jitter_x = randnullsign() * xrand(2, 2) 600 var jitter_y = randnullsign() * xrand(2, 2) 601 this.clone_region( this.p.x + jitter_x, this.p.y + jitter_y ) 602 }, 603 604 iterate: function( last_brush ){ 605 this.resize(4, 2) 606 this.update() 607 this.reorient( last_brush ) 608 } 609 }) 610 611 var StarsTool = NopaintBrush.extend({ 612 type: "stars", 613 chars: "....,,'''*", 614 615 start: function(last_brush){ 616 this.reorient( last_brush ) 617 }, 618 619 paint: function(t){ 620 if (Math.random() < 0.5) { 621 var lex = canvas.get(this.p.x, this.p.y) 622 undo.save_lex(lex.x, lex.y, lex) 623 lex.fg = rand_hue() 624 // lex.bg = colors.black 625 lex.char = choice(this.chars) 626 lex.build() 627 } 628 }, 629 }) 630 631 /* Fill tool */ 632 633 var FillTool = NopaintTool.extend({ 634 type: "fill", 635 rate: 25, 636 is_fill: true, 637 start: function(){ 638 this.fill() 639 }, 640 paint: function(t){ 641 if ((t % this.rate) == this.rate-1) { 642 this.fill() 643 } 644 }, 645 recolor: function(){ 646 this.fg = this.bg = randint(16) 647 this.char = " " 648 this.opacity = 1 649 }, 650 fill: function(){ 651 var x = randint(canvas.w) 652 var y = randint(canvas.h) 653 this.recolor() 654 draw.fill(this, x, y) 655 } 656 }) 657 658 var FillLetterTool = FillTool.extend({ 659 type: "fill-letter", 660 rate: 25, 661 recolor: function(){ 662 this.fg = randint(16) 663 this.bg = randint(16) 664 this.char = choice( unicode.block(letters.charset, 32) ) 665 this.opacity = 1 666 }, 667 }) 668 669 /* Shader Tools */ 670 671 var ShaderTool = NopaintTool.extend({ 672 type: "shader", 673 speed: 3, 674 is_shader: true, 675 is_recursive: false, 676 start: function(){ 677 undo.save_rect(0, 0, canvas.w, canvas.h) 678 this.canvas = canvas.clone() 679 }, 680 paint: function(t){ 681 if ((t % this.speed) == 0) { 682 var w = canvas.w 683 var h = canvas.h 684 var lex 685 if (this.is_recursive) { 686 this.canvas.assign(canvas) 687 } 688 this.before_shade() 689 for (var x = 0; x < w; x++) { 690 for (var y = 0; y < h; y++) { 691 lex = canvas.get(x, y) 692 if (! this.shade( this.canvas, canvas, lex, x, y, w, h )) { 693 lex.build() 694 } 695 } 696 } 697 } 698 }, 699 before_shade: function(){}, 700 shade: function(src, dest, lex, x, y, w, h){}, 701 finish: function(){ 702 this.canvas.demolish() 703 } 704 }) 705 706 var ColorizeTool = ShaderTool.extend({ 707 type: "colorize", 708 fns: [mirc_color_reverse,hue,inv_hue,gray,fire,red,yellow,green,blue,purple,dark_gray], 709 speed: 5, 710 start: function(){ 711 this.__start() 712 this.i = randint(this.fns.length) 713 }, 714 before_shade: function(){ 715 this.i = (this.i + 1) % this.fns.length 716 this.fn = this.fns[this.i] 717 }, 718 shade: function(src, dest, lex, x, y, w, h){ 719 lex.bg = this.fn( lex.bg ) 720 return false 721 }, 722 }) 723 724 var TranslateTool = ShaderTool.extend({ 725 type: "translate", 726 dx: 0, 727 dy: 0, 728 speed: 3, 729 start: function(){ 730 this.__start() 731 this.dx = randint(3)-1 732 this.dy = randint(3)-1 733 this.x = this.y = 0 734 if (! this.dx && ! this.dy) { 735 this.dx = 1 736 this.dy = 0 737 } 738 }, 739 before_shade: function(){ 740 this.x += this.dx 741 this.y += this.dy 742 }, 743 shade: function(src, dest, lex, x, y, w, h){ 744 var copy = src.get(x+this.x, y+this.y) 745 lex.assign(copy) 746 return true 747 }, 748 }) 749 750 var SliceTool = ShaderTool.extend({ 751 type: "slice", 752 dx: 0, 753 dy: 0, 754 speed: 1, 755 is_recursive: true, 756 start: function(){ 757 this.__start() 758 this.is_y = Math.random() > 0.3 759 this.limit = this.is_y ? canvas.h : canvas.w 760 this.position = randint(this.limit) 761 this.direction = 1 762 }, 763 before_shade: function(){ 764 if (Math.random() < 0.6) { 765 this.position = mod(this.position + 1, this.limit) 766 } 767 if (Math.random() > 0.8) { 768 this.direction = randsign() 769 } 770 }, 771 shade: function(src, dest, lex, x, y, w, h){ 772 if (this.is_y) { 773 if (y >= this.position) { 774 var copy = src.get(x + this.direction, y) 775 lex.assign(copy) 776 } 777 } 778 else if (x >= this.position) { 779 var copy = src.get(x, y + this.direction) 780 lex.assign(copy) 781 } 782 return true 783 }, 784 }) 785 786 var ScaleTool = ShaderTool.extend({ 787 type: "scale", 788 scale: 1, 789 dscale: 0, 790 speed: 3, 791 start: function(){ 792 this.__start() 793 var sign = randsign() 794 this.x_scale = 1 795 this.y_scale = 1 796 this.dx_scale = randsign() * randrange(0.0005, 0.01) 797 var r = Math.random() 798 if (r < 0.333) { 799 this.dy_scale = this.dx_scale * randrange(0.85, 1.25) 800 } 801 else if (r < 0.666) { 802 this.dy_scale = this.dx_scale 803 } 804 else { 805 this.dy_scale = randsign() * randrange(0.0005, 0.01) 806 } 807 }, 808 before_shade: function(){ 809 this.x_scale += this.dx_scale 810 this.y_scale += this.dy_scale 811 }, 812 shade: function(src, dest, lex, x, y, w, h){ 813 x = (x/w) * 2 - 1 814 y = (y/h) * 2 - 1 815 x *= this.x_scale 816 y *= this.y_scale 817 x = (x + 1) / 2 * w 818 y = (y + 1) / 2 * h 819 var copy = src.get(x, y) 820 lex.assign(copy) 821 return true 822 }, 823 }) 824 825 var RotateTool = ShaderTool.extend({ 826 type: "rotate", 827 theta: 0, 828 d_theta: 0, 829 830 start: function(){ 831 this.__start() 832 var sign = randsign() 833 this.theta = 0 834 this.d_theta = randsign() * randrange(0.001, 0.05) 835 }, 836 before_shade: function(){ 837 this.theta += this.d_theta 838 }, 839 shade: function(src, dest, lex, x, y, w, h){ 840 x = (x/w) * 2 - 1 841 y = (y/h) * 2 - 1 842 var ca = cos(this.theta) 843 var sa = sin(this.theta) 844 var a = x * ca - y * sa 845 var b = x * sa + y * ca 846 x = (a + 1) / 2 * w 847 y = (b + 1) / 2 * h 848 var copy = src.get(x, y) 849 lex.assign(copy) 850 return true 851 }, 852 }) 853 854 var CycleTool = ShaderTool.extend({ 855 type: "cycle", 856 n: 0, 857 speed: 5, 858 is_recursive: true, 859 start: function(){ 860 this.__start() 861 this.n = randsign() 862 if (random() < 0.2) this.n *= randint(15) 863 }, 864 shade: function(src, dest, lex, x, y){ 865 lex.bg += this.n 866 return false 867 }, 868 }) 869 870 nopaint.add_tool( new SolidBrush({ weight: 5 }) ) 871 nopaint.add_tool( new ShadowBrush({ weight: 10 }) ) 872 nopaint.add_tool( new EraseBrush({ weight: 5 }) ) 873 nopaint.add_tool( new RandomBrush({ weight: 4 }) ) 874 nopaint.add_tool( new HueBrush({ weight: 5 }) ) 875 nopaint.add_tool( new GrayBrush({ weight: 5 }) ) 876 nopaint.add_tool( new LetterBrush({ weight: 2 }) ) 877 nopaint.add_tool( new RandomLetterBrush({ weight: 12 }) ) 878 nopaint.add_tool( new CloneBrush({ weight: 8 }) ) 879 nopaint.add_tool( new SmearBrush({ weight: 10 }) ) 880 nopaint.add_tool( new FillTool({ weight: 3 }) ) 881 nopaint.add_tool( new FillLetterTool({ weight: 6 }) ) 882 nopaint.add_tool( new StarsTool({ weight: 2 }) ) 883 nopaint.add_tool( new TranslateTool({ weight: 4 }) ) 884 nopaint.add_tool( new CycleTool({ weight: 1 }) ) 885 nopaint.add_tool( new ScaleTool({ weight: 3 }) ) 886 nopaint.add_tool( new RotateTool({ weight: 3 }) ) 887 nopaint.add_tool( new SliceTool({ weight: 4 }) ) 888 nopaint.add_tool( new ColorizeTool({ weight: 1 }) ) 889 nopaint.regenerate_weights() 890 891 nopaint.toggle(true) 892 893 nopaint.player = new StylePlayer () 894 895 return nopaint 896 })()