1 /** 2 Particle filter 3 4 Copyright: (c) Enalye 2017 5 License: Zlib 6 Authors: Enalye 7 */ 8 9 module atelier.core.particlefilter; 10 11 import std.typecons; 12 import std.conv: to; 13 14 import atelier.core.util; 15 import atelier.core.vec2; 16 import atelier.core.color; 17 import atelier.core.stream; 18 import atelier.core.particle; 19 /+ 20 class ParticleFilter { 21 protected { 22 Vec2f _position = Vec2f.zero; 23 Vec2f _size = Vec2f.one * 100f; 24 int _id = -1; 25 uint _nbProperties = 0U; 26 bool _isCircle = false; 27 } 28 29 @property { 30 int id() { return _id; } 31 32 Vec2f position() const { return _position; } 33 Vec2f position(Vec2f newPosition) { return _position = newPosition; } 34 } 35 36 bool isInside(const Vec2f pos) const { 37 if(_isCircle) 38 return _position.distanceSquared(pos) < _size.x * _size.x; 39 else 40 return pos.isBetween(_position - _size / 2f, _position + _size / 2f); 41 } 42 43 void apply(Particle particle, float deltaTime) { 44 if(isInside(particle.position)) 45 updateParticle(particle, deltaTime); 46 } 47 48 protected abstract void updateParticle(Particle particle, float deltaTime); 49 50 alias FilterProperty = Tuple!(string, float, float, uint); 51 abstract FilterProperty[] getProperties() const; 52 abstract float property(uint id) const; 53 abstract void property(uint id, float newValue); 54 55 alias FilterDisplay = Tuple!(string, const bool, const Vec2f, bool, const Vec2f, const Color); 56 abstract FilterDisplay getDisplay() const; 57 58 void save(OutStream stream) const { 59 stream.write!float(_position.x); 60 stream.write!float(_position.y); 61 foreach(uint id; 0.._nbProperties) 62 stream.write!float(property(id)); 63 } 64 65 void load(InStream stream) { 66 _position = Vec2f(stream.read!float(), stream.read!float()); 67 foreach(uint id; 0.._nbProperties) 68 property(id, stream.read!float()); 69 } 70 } 71 72 //Force Filter 73 final class ForceFilterCircle: ParticleFilter { 74 private { 75 float _angle = 0f, _acceleration = 0f; 76 Vec2f _force = Vec2f.zero; 77 } 78 79 this() { 80 _id = 0; 81 _nbProperties = 3U; 82 _isCircle = true; 83 } 84 85 override float property(uint id) const { 86 switch(id) { 87 case 0: 88 return _size.x; 89 case 1: 90 return _angle; 91 case 2: 92 return _acceleration; 93 default: 94 throw new Exception("Filter property out of range"); 95 } 96 } 97 98 override void property(uint id, float newValue) { 99 switch(id) { 100 case 0: 101 _size.x = newValue; 102 _size.y = newValue; 103 break; 104 case 1: 105 _angle = newValue; 106 _force = Vec2f.angled(_angle) * _acceleration; 107 break; 108 case 2: 109 _acceleration = newValue; 110 _force = Vec2f.angled(_angle) * _acceleration; 111 break; 112 default: 113 throw new Exception("Filter property out of range"); 114 } 115 } 116 117 protected override void updateParticle(Particle particle, float deltaTime) { 118 particle.velocity += _force * deltaTime; 119 } 120 121 override FilterProperty[] getProperties() const { 122 return [ 123 tuple("Rayon", 1f, 1000f, 999u), 124 tuple("Angle", 0f, 360f, 360u), 125 tuple("Accel.", 0f, 0.5f, 1000u) 126 ]; 127 } 128 129 override FilterDisplay getDisplay() const { 130 return tuple("Force", _isCircle, _size, true, cast(const Vec2f)(_force * 1000f), Color.red); 131 } 132 } 133 134 final class ForceFilterRect: ParticleFilter { 135 private { 136 float _angle = 0f, _acceleration = 0f; 137 Vec2f _force = Vec2f.zero; 138 } 139 140 this() { 141 _id = 1; 142 _nbProperties = 4U; 143 _isCircle = false; 144 } 145 146 override float property(uint id) const { 147 switch(id) { 148 case 0: 149 return _size.x; 150 case 1: 151 return _size.y; 152 case 2: 153 return _angle; 154 case 3: 155 return _acceleration; 156 default: 157 throw new Exception("Filter property out of range"); 158 } 159 } 160 161 override void property(uint id, float newValue) { 162 switch(id) { 163 case 0: 164 _size.x = newValue; 165 break; 166 case 1: 167 _size.y = newValue; 168 break; 169 case 2: 170 _angle = newValue; 171 _force = Vec2f.angled(_angle) * _acceleration; 172 break; 173 case 3: 174 _acceleration = newValue; 175 _force = Vec2f.angled(_angle) * _acceleration; 176 break; 177 default: 178 throw new Exception("Filter property out of range"); 179 } 180 } 181 182 protected override void updateParticle(Particle particle, float deltaTime) { 183 particle.velocity += _force * deltaTime; 184 } 185 186 override FilterProperty[] getProperties() const { 187 return [ 188 tuple("Longueur", 2f, 2000f, 1998u), 189 tuple("Hauteur", 2f, 2000f, 1998u), 190 tuple("Angle", 0f, 360f, 360u), 191 tuple("Accel.", 0f, 0.5f, 1000u) 192 ]; 193 } 194 195 override FilterDisplay getDisplay() const { 196 return tuple("Force", _isCircle, _size, true, cast(const Vec2f)(_force * 1000f), Color.red); 197 } 198 } 199 200 //SetSpeed Filter 201 final class SetSpeedFilterCircle: ParticleFilter { 202 private { 203 float _speed = 0f; 204 } 205 206 this() { 207 _id = 2; 208 _nbProperties = 2U; 209 _isCircle = true; 210 } 211 212 override float property(uint id) const { 213 switch(id) { 214 case 0: 215 return _size.x; 216 case 1: 217 return _speed; 218 default: 219 throw new Exception("Filter property out of range"); 220 } 221 } 222 223 override void property(uint id, float newValue) { 224 switch(id) { 225 case 0: 226 _size.x = newValue; 227 _size.y = newValue; 228 break; 229 case 1: 230 _speed = newValue; 231 break; 232 default: 233 throw new Exception("Filter property out of range"); 234 } 235 } 236 237 protected override void updateParticle(Particle particle, float deltaTime) { 238 particle.velocity = particle.velocity.normalized * _speed; 239 } 240 241 override FilterProperty[] getProperties() const { 242 return [ 243 tuple("Rayon", 1f, 1000f, 999u), 244 tuple("Vitesse", 0f, 10f, 200u) 245 ]; 246 } 247 248 override FilterDisplay getDisplay() const { 249 return tuple("Vitesse: " ~ to!string(_speed), _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, Color.green); 250 } 251 } 252 253 final class SetSpeedFilterRect: ParticleFilter { 254 private { 255 float _speed = 0f; 256 } 257 258 this() { 259 _id = 3; 260 _nbProperties = 3U; 261 _isCircle = false; 262 } 263 264 override float property(uint id) const { 265 switch(id) { 266 case 0: 267 return _size.x; 268 case 1: 269 return _size.y; 270 case 2: 271 return _speed; 272 default: 273 throw new Exception("Filter property out of range"); 274 } 275 } 276 277 override void property(uint id, float newValue) { 278 switch(id) { 279 case 0: 280 _size.x = newValue; 281 break; 282 case 1: 283 _size.y = newValue; 284 break; 285 case 2: 286 _speed = newValue; 287 break; 288 default: 289 throw new Exception("Filter property out of range"); 290 } 291 } 292 293 protected override void updateParticle(Particle particle, float deltaTime) { 294 particle.velocity = particle.velocity.normalized * _speed; 295 } 296 297 override FilterProperty[] getProperties() const { 298 return [ 299 tuple("Longueur", 2f, 2000f, 1998u), 300 tuple("Hauteur", 2f, 2000f, 1998u), 301 tuple("Vitesse", 0f, 10f, 200u) 302 ]; 303 } 304 305 override FilterDisplay getDisplay() const { 306 return tuple("Vitesse: " ~ to!string(_speed), _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, Color.green); 307 } 308 } 309 310 //SpeedLimit Filter 311 final class SpeedLimitFilterCircle: ParticleFilter { 312 private { 313 float _limit = 0f; 314 } 315 316 this() { 317 _id = 4; 318 _nbProperties = 2U; 319 _isCircle = true; 320 } 321 322 override float property(uint id) const { 323 switch(id) { 324 case 0: 325 return _size.x; 326 case 1: 327 return _limit; 328 default: 329 throw new Exception("Filter property out of range"); 330 } 331 } 332 333 override void property(uint id, float newValue) { 334 switch(id) { 335 case 0: 336 _size.x = newValue; 337 _size.y = newValue; 338 break; 339 case 1: 340 _limit = newValue; 341 break; 342 default: 343 throw new Exception("Filter property out of range"); 344 } 345 } 346 347 protected override void updateParticle(Particle particle, float deltaTime) { 348 if(particle.velocity.lengthSquared > _limit * _limit) 349 particle.velocity = particle.velocity.normalized * _limit; 350 } 351 352 override FilterProperty[] getProperties() const { 353 return [ 354 tuple("Rayon", 1f, 1000f, 999u), 355 tuple("Limite", 0f, 10f, 200u) 356 ]; 357 } 358 359 override FilterDisplay getDisplay() const { 360 return tuple("Vit. Limite: " ~ to!string(_limit), _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, Color.green); 361 } 362 } 363 364 final class SpeedLimitFilterRect: ParticleFilter { 365 private { 366 float _limit = 0f; 367 } 368 369 this() { 370 _id = 5; 371 _nbProperties = 3U; 372 _isCircle = false; 373 } 374 375 override float property(uint id) const { 376 switch(id) { 377 case 0: 378 return _size.x; 379 case 1: 380 return _size.y; 381 case 2: 382 return _limit; 383 default: 384 throw new Exception("Filter property out of range"); 385 } 386 } 387 388 override void property(uint id, float newValue) { 389 switch(id) { 390 case 0: 391 _size.x = newValue; 392 break; 393 case 1: 394 _size.y = newValue; 395 break; 396 case 2: 397 _limit = newValue; 398 break; 399 default: 400 throw new Exception("Filter property out of range"); 401 } 402 } 403 404 protected override void updateParticle(Particle particle, float deltaTime) { 405 if(particle.velocity.lengthSquared > _limit * _limit) 406 particle.velocity = particle.velocity.normalized * _limit; 407 } 408 409 override FilterProperty[] getProperties() const { 410 return [ 411 tuple("Longueur", 2f, 2000f, 1998u), 412 tuple("Hauteur", 2f, 2000f, 1998u), 413 tuple("Limite", 0f, 10f, 200u) 414 ]; 415 } 416 417 override FilterDisplay getDisplay() const { 418 return tuple("Vit. Limite: " ~ to!string(_limit), _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, Color.green); 419 } 420 } 421 422 //Attract Filter 423 final class AttractFilterCircle: ParticleFilter { 424 private { 425 float _acceleration = 0f; 426 } 427 428 this() { 429 _id = 6; 430 _nbProperties = 2U; 431 _isCircle = true; 432 } 433 434 override float property(uint id) const { 435 switch(id) { 436 case 0: 437 return _size.x; 438 case 1: 439 return _acceleration; 440 default: 441 throw new Exception("Filter property out of range"); 442 } 443 } 444 445 override void property(uint id, float newValue) { 446 switch(id) { 447 case 0: 448 _size.x = newValue; 449 _size.y = newValue; 450 break; 451 case 1: 452 _acceleration = newValue; 453 break; 454 default: 455 throw new Exception("Filter property out of range"); 456 } 457 } 458 459 protected override void updateParticle(Particle particle, float deltaTime) { 460 particle.velocity += (_position - particle.position).normalized * _acceleration * deltaTime; 461 } 462 463 override FilterProperty[] getProperties() const { 464 return [ 465 tuple("Rayon", 1f, 1000f, 999u), 466 tuple("Accel.", 0f, 0.5f, 1000u) 467 ]; 468 } 469 470 override FilterDisplay getDisplay() const { 471 return tuple("Attracteur", _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, Color.blue); 472 } 473 } 474 475 final class AttractFilterRect: ParticleFilter { 476 private { 477 float _acceleration = 0f; 478 } 479 480 this() { 481 _id = 7; 482 _nbProperties = 3U; 483 _isCircle = false; 484 } 485 486 override float property(uint id) const { 487 switch(id) { 488 case 0: 489 return _size.x; 490 case 1: 491 return _size.y; 492 case 2: 493 return _acceleration; 494 default: 495 throw new Exception("Filter property out of range"); 496 } 497 } 498 499 override void property(uint id, float newValue) { 500 switch(id) { 501 case 0: 502 _size.x = newValue; 503 break; 504 case 1: 505 _size.y = newValue; 506 break; 507 case 2: 508 _acceleration = newValue; 509 break; 510 default: 511 throw new Exception("Filter property out of range"); 512 } 513 } 514 515 protected override void updateParticle(Particle particle, float deltaTime) { 516 particle.velocity += (_position - particle.position).normalized * _acceleration * deltaTime; 517 } 518 519 override FilterProperty[] getProperties() const { 520 return [ 521 tuple("Longueur", 2f, 2000f, 1998u), 522 tuple("Hauteur", 2f, 2000f, 1998u), 523 tuple("Accel.", 0f, 0.5f, 1000u) 524 ]; 525 } 526 527 override FilterDisplay getDisplay() const { 528 return tuple("Attracteur", _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, Color.blue); 529 } 530 } 531 532 //Repulse Filter 533 final class RepulseFilterCircle: ParticleFilter { 534 private { 535 float _acceleration = 0f; 536 } 537 538 this() { 539 _id = 8; 540 _nbProperties = 2U; 541 _isCircle = true; 542 } 543 544 override float property(uint id) const { 545 switch(id) { 546 case 0: 547 return _size.x; 548 case 1: 549 return _acceleration; 550 default: 551 throw new Exception("Filter property out of range"); 552 } 553 } 554 555 override void property(uint id, float newValue) { 556 switch(id) { 557 case 0: 558 _size.x = newValue; 559 _size.y = newValue; 560 break; 561 case 1: 562 _acceleration = newValue; 563 break; 564 default: 565 throw new Exception("Filter property out of range"); 566 } 567 } 568 569 protected override void updateParticle(Particle particle, float deltaTime) { 570 particle.velocity += (particle.position - _position).normalized * _acceleration * deltaTime; 571 } 572 573 override FilterProperty[] getProperties() const { 574 return [ 575 tuple("Rayon", 1f, 1000f, 999u), 576 tuple("Accel.", 0f, 0.5f, 1000u) 577 ]; 578 } 579 580 override FilterDisplay getDisplay() const { 581 return tuple("Répulseur", _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, Color.cyan); 582 } 583 } 584 585 final class RepulseFilterRect: ParticleFilter { 586 private { 587 float _acceleration = 0f; 588 } 589 590 this() { 591 _id = 9; 592 _nbProperties = 3U; 593 _isCircle = false; 594 } 595 596 override float property(uint id) const { 597 switch(id) { 598 case 0: 599 return _size.x; 600 case 1: 601 return _size.y; 602 case 2: 603 return _acceleration; 604 default: 605 throw new Exception("Filter property out of range"); 606 } 607 } 608 609 override void property(uint id, float newValue) { 610 switch(id) { 611 case 0: 612 _size.x = newValue; 613 break; 614 case 1: 615 _size.y = newValue; 616 break; 617 case 2: 618 _acceleration = newValue; 619 break; 620 default: 621 throw new Exception("Filter property out of range"); 622 } 623 } 624 625 protected override void updateParticle(Particle particle, float deltaTime) { 626 particle.velocity += (particle.position - _position).normalized * _acceleration * deltaTime; 627 } 628 629 override FilterProperty[] getProperties() const { 630 return [ 631 tuple("Longueur", 2f, 2000f, 1998u), 632 tuple("Hauteur", 2f, 2000f, 1998u), 633 tuple("Accel.", 0f, 0.5f, 1000u) 634 ]; 635 } 636 637 override FilterDisplay getDisplay() const { 638 return tuple("Répulseur", _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, Color.cyan); 639 } 640 } 641 642 //Destructor Filter 643 final class DestructorFilterCircle: ParticleFilter { 644 this() { 645 _id = 10; 646 _nbProperties = 1U; 647 _isCircle = true; 648 } 649 650 override float property(uint id) const { 651 switch(id) { 652 case 0: 653 return _size.x; 654 default: 655 throw new Exception("Filter property out of range"); 656 } 657 } 658 659 override void property(uint id, float newValue) { 660 switch(id) { 661 case 0: 662 _size.x = newValue; 663 _size.y = newValue; 664 break; 665 default: 666 throw new Exception("Filter property out of range"); 667 } 668 } 669 670 protected override void updateParticle(Particle particle, float deltaTime) { 671 particle.timeToLive = 0f; 672 } 673 674 override FilterProperty[] getProperties() const { 675 return [ 676 tuple("Rayon", 1f, 1000f, 999u) 677 ]; 678 } 679 680 override FilterDisplay getDisplay() const { 681 return tuple("Destructeur", _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, Color.silver); 682 } 683 } 684 685 final class DestructorFilterRect: ParticleFilter { 686 this() { 687 _id = 11; 688 _nbProperties = 2U; 689 _isCircle = false; 690 } 691 692 override float property(uint id) const { 693 switch(id) { 694 case 0: 695 return _size.x; 696 case 1: 697 return _size.y; 698 default: 699 throw new Exception("Filter property out of range"); 700 } 701 } 702 703 override void property(uint id, float newValue) { 704 switch(id) { 705 case 0: 706 _size.x = newValue; 707 break; 708 case 1: 709 _size.y = newValue; 710 break; 711 default: 712 throw new Exception("Filter property out of range"); 713 } 714 } 715 716 protected override void updateParticle(Particle particle, float deltaTime) { 717 particle.timeToLive = 0f; 718 } 719 720 override FilterProperty[] getProperties() const { 721 return [ 722 tuple("Longueur", 2f, 2000f, 1998u), 723 tuple("Hauteur", 2f, 2000f, 1998u) 724 ]; 725 } 726 727 override FilterDisplay getDisplay() const { 728 return tuple("Destructeur", _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, Color.silver); 729 } 730 } 731 732 //SetScale Filter 733 final class SetScaleFilterCircle: ParticleFilter { 734 private float _scale = 1f; 735 736 this() { 737 _id = 12; 738 _nbProperties = 2U; 739 _isCircle = true; 740 } 741 742 override float property(uint id) const { 743 switch(id) { 744 case 0: 745 return _size.x; 746 case 1: 747 return _scale; 748 default: 749 throw new Exception("Filter property out of range"); 750 } 751 } 752 753 override void property(uint id, float newValue) { 754 switch(id) { 755 case 0: 756 _size.x = newValue; 757 _size.y = newValue; 758 break; 759 case 1: 760 _scale = newValue; 761 break; 762 default: 763 throw new Exception("Filter property out of range"); 764 } 765 } 766 767 protected override void updateParticle(Particle particle, float deltaTime) { 768 particle.scale = _scale; 769 } 770 771 override FilterProperty[] getProperties() const { 772 return [ 773 tuple("Rayon", 1f, 1000f, 999u), 774 tuple("Taille", 0f, 10f, 1000u) 775 ]; 776 } 777 778 override FilterDisplay getDisplay() const { 779 return tuple("Taille", _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, Color.olive); 780 } 781 } 782 783 final class SetScaleFilterRect: ParticleFilter { 784 private float _scale = 1f; 785 786 this() { 787 _id = 13; 788 _nbProperties = 3U; 789 _isCircle = false; 790 } 791 792 override float property(uint id) const { 793 switch(id) { 794 case 0: 795 return _size.x; 796 case 1: 797 return _size.y; 798 case 2: 799 return _scale; 800 default: 801 throw new Exception("Filter property out of range"); 802 } 803 } 804 805 override void property(uint id, float newValue) { 806 switch(id) { 807 case 0: 808 _size.x = newValue; 809 break; 810 case 1: 811 _size.y = newValue; 812 break; 813 case 2: 814 _scale = newValue; 815 break; 816 default: 817 throw new Exception("Filter property out of range"); 818 } 819 } 820 821 protected override void updateParticle(Particle particle, float deltaTime) { 822 particle.scale = _scale; 823 } 824 825 override FilterProperty[] getProperties() const { 826 return [ 827 tuple("Longueur", 2f, 2000f, 1998u), 828 tuple("Hauteur", 2f, 2000f, 1998u), 829 tuple("Taille", 0f, 10f, 1000u) 830 ]; 831 } 832 833 override FilterDisplay getDisplay() const { 834 return tuple("Taille", _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, Color.olive); 835 } 836 } 837 838 //MixScale Filter 839 final class MixScaleFilterCircle: ParticleFilter { 840 private { 841 float _scale = 1f, _blend = 1f; 842 } 843 844 this() { 845 _id = 14; 846 _nbProperties = 3U; 847 _isCircle = true; 848 } 849 850 override float property(uint id) const { 851 switch(id) { 852 case 0: 853 return _size.x; 854 case 1: 855 return _scale; 856 case 2: 857 return _blend; 858 default: 859 throw new Exception("Filter property out of range"); 860 } 861 } 862 863 override void property(uint id, float newValue) { 864 switch(id) { 865 case 0: 866 _size.x = newValue; 867 _size.y = newValue; 868 break; 869 case 1: 870 _scale = newValue; 871 break; 872 case 2: 873 _blend = newValue; 874 break; 875 default: 876 throw new Exception("Filter property out of range"); 877 } 878 } 879 880 protected override void updateParticle(Particle particle, float deltaTime) { 881 particle.scale = lerp(particle.scale, _scale, _blend * deltaTime); 882 } 883 884 override FilterProperty[] getProperties() const { 885 return [ 886 tuple("Rayon", 1f, 1000f, 999u), 887 tuple("Taille", 0f, 10f, 1000u), 888 tuple("Mélange", 0.0001f, 0.1f, 1000u) 889 ]; 890 } 891 892 override FilterDisplay getDisplay() const { 893 return tuple("M.Taille", _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, Color.navy); 894 } 895 } 896 897 final class MixScaleFilterRect: ParticleFilter { 898 private { 899 float _scale = 1f, _blend = 1f; 900 } 901 902 this() { 903 _id = 15; 904 _nbProperties = 4U; 905 _isCircle = false; 906 } 907 908 override float property(uint id) const { 909 switch(id) { 910 case 0: 911 return _size.x; 912 case 1: 913 return _size.y; 914 case 2: 915 return _scale; 916 case 3: 917 return _blend; 918 default: 919 throw new Exception("Filter property out of range"); 920 } 921 } 922 923 override void property(uint id, float newValue) { 924 switch(id) { 925 case 0: 926 _size.x = newValue; 927 break; 928 case 1: 929 _size.y = newValue; 930 break; 931 case 2: 932 _scale = newValue; 933 break; 934 case 3: 935 _blend = newValue; 936 break; 937 default: 938 throw new Exception("Filter property out of range"); 939 } 940 } 941 942 protected override void updateParticle(Particle particle, float deltaTime) { 943 particle.scale = lerp(particle.scale, _scale, _blend * deltaTime); 944 } 945 946 override FilterProperty[] getProperties() const { 947 return [ 948 tuple("Longueur", 2f, 2000f, 1998u), 949 tuple("Hauteur", 2f, 2000f, 1998u), 950 tuple("Taille", 0f, 10f, 1000u), 951 tuple("Mélange", 0.0001f, 0.1f, 1000u) 952 ]; 953 } 954 955 override FilterDisplay getDisplay() const { 956 return tuple("M.Taille", _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, Color.navy); 957 } 958 } 959 960 //SetColor Filter 961 final class SetColorFilterCircle: ParticleFilter { 962 private Color _color; 963 964 this() { 965 _id = 16; 966 _nbProperties = 5U; 967 _isCircle = true; 968 } 969 970 override float property(uint id) const { 971 switch(id) { 972 case 0: 973 return _size.x; 974 case 1: 975 return _color.r; 976 case 2: 977 return _color.g; 978 case 3: 979 return _color.b; 980 case 4: 981 return _color.a; 982 default: 983 throw new Exception("Filter property out of range"); 984 } 985 } 986 987 override void property(uint id, float newValue) { 988 switch(id) { 989 case 0: 990 _size.x = newValue; 991 _size.y = newValue; 992 break; 993 case 1: 994 _color.r = newValue; 995 break; 996 case 2: 997 _color.g = newValue; 998 break; 999 case 3: 1000 _color.b = newValue; 1001 break; 1002 case 4: 1003 _color.a = newValue; 1004 break; 1005 default: 1006 throw new Exception("Filter property out of range"); 1007 } 1008 } 1009 1010 protected override void updateParticle(Particle particle, float deltaTime) { 1011 particle.color = _color; 1012 } 1013 1014 override FilterProperty[] getProperties() const { 1015 return [ 1016 tuple("Rayon", 1f, 1000f, 999u), 1017 tuple("Rouge", 0f, 1f, 256u), 1018 tuple("Vert", 0f, 1f, 256u), 1019 tuple("Bleu", 0f, 1f, 256u), 1020 tuple("Alpha", 0f, 1f, 256u) 1021 ]; 1022 } 1023 1024 override FilterDisplay getDisplay() const { 1025 Color color = _color; 1026 color.a = 1f; 1027 return tuple("Couleur", _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, cast(const Color)color); 1028 } 1029 } 1030 1031 final class SetColorFilterRect: ParticleFilter { 1032 private Color _color; 1033 1034 this() { 1035 _id = 17; 1036 _nbProperties = 6U; 1037 _isCircle = false; 1038 } 1039 1040 override float property(uint id) const { 1041 switch(id) { 1042 case 0: 1043 return _size.x; 1044 case 1: 1045 return _size.y; 1046 case 2: 1047 return _color.r; 1048 case 3: 1049 return _color.g; 1050 case 4: 1051 return _color.b; 1052 case 5: 1053 return _color.a; 1054 default: 1055 throw new Exception("Filter property out of range"); 1056 } 1057 } 1058 1059 override void property(uint id, float newValue) { 1060 switch(id) { 1061 case 0: 1062 _size.x = newValue; 1063 break; 1064 case 1: 1065 _size.y = newValue; 1066 break; 1067 case 2: 1068 _color.r = newValue; 1069 break; 1070 case 3: 1071 _color.g = newValue; 1072 break; 1073 case 4: 1074 _color.b = newValue; 1075 break; 1076 case 5: 1077 _color.a = newValue; 1078 break; 1079 default: 1080 throw new Exception("Filter property out of range"); 1081 } 1082 } 1083 1084 protected override void updateParticle(Particle particle, float deltaTime) { 1085 particle.color = _color; 1086 } 1087 1088 override FilterProperty[] getProperties() const { 1089 return [ 1090 tuple("Longueur", 2f, 2000f, 1998u), 1091 tuple("Hauteur", 2f, 2000f, 1998u), 1092 tuple("Rouge", 0f, 1f, 256u), 1093 tuple("Vert", 0f, 1f, 256u), 1094 tuple("Bleu", 0f, 1f, 256u), 1095 tuple("Alpha", 0f, 1f, 256u) 1096 ]; 1097 } 1098 1099 override FilterDisplay getDisplay() const { 1100 Color color = _color; 1101 color.a = 1f; 1102 return tuple("Couleur", _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, cast(const Color)color); 1103 } 1104 } 1105 1106 1107 //MixColor Filter 1108 final class MixColorFilterCircle: ParticleFilter { 1109 private { 1110 Color _color; 1111 float _blend = 1f; 1112 } 1113 1114 this() { 1115 _id = 18; 1116 _nbProperties = 6U; 1117 _isCircle = true; 1118 } 1119 1120 override float property(uint id) const { 1121 switch(id) { 1122 case 0: 1123 return _size.x; 1124 case 1: 1125 return _color.r; 1126 case 2: 1127 return _color.g; 1128 case 3: 1129 return _color.b; 1130 case 4: 1131 return _color.a; 1132 case 5: 1133 return _blend; 1134 default: 1135 throw new Exception("Filter property out of range"); 1136 } 1137 } 1138 1139 override void property(uint id, float newValue) { 1140 switch(id) { 1141 case 0: 1142 _size.x = newValue; 1143 _size.y = newValue; 1144 break; 1145 case 1: 1146 _color.r = newValue; 1147 break; 1148 case 2: 1149 _color.g = newValue; 1150 break; 1151 case 3: 1152 _color.b = newValue; 1153 break; 1154 case 4: 1155 _color.a = newValue; 1156 break; 1157 case 5: 1158 _blend = newValue; 1159 break; 1160 default: 1161 throw new Exception("Filter property out of range"); 1162 } 1163 } 1164 1165 protected override void updateParticle(Particle particle, float deltaTime) { 1166 particle.color = lerp(particle.color, _color, _blend * deltaTime); 1167 } 1168 1169 override FilterProperty[] getProperties() const { 1170 return [ 1171 tuple("Rayon", 1f, 1000f, 999u), 1172 tuple("Rouge", 0f, 1f, 256u), 1173 tuple("Vert", 0f, 1f, 256u), 1174 tuple("Bleu", 0f, 1f, 256u), 1175 tuple("Alpha", 0f, 1f, 256u), 1176 tuple("Mélange", .001f, .1f, 1000u) 1177 ]; 1178 } 1179 1180 override FilterDisplay getDisplay() const { 1181 Color color = _color; 1182 color.a = 1f; 1183 return tuple("Couleur", _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, cast(const Color)color); 1184 } 1185 } 1186 1187 final class MixColorFilterRect: ParticleFilter { 1188 private { 1189 Color _color; 1190 float _blend = 1f; 1191 } 1192 1193 this() { 1194 _id = 19; 1195 _nbProperties = 7U; 1196 _isCircle = false; 1197 } 1198 1199 override float property(uint id) const { 1200 switch(id) { 1201 case 0: 1202 return _size.x; 1203 case 1: 1204 return _size.y; 1205 case 2: 1206 return _color.r; 1207 case 3: 1208 return _color.g; 1209 case 4: 1210 return _color.b; 1211 case 5: 1212 return _color.a; 1213 case 6: 1214 return _blend; 1215 default: 1216 throw new Exception("Filter property out of range"); 1217 } 1218 } 1219 1220 override void property(uint id, float newValue) { 1221 switch(id) { 1222 case 0: 1223 _size.x = newValue; 1224 break; 1225 case 1: 1226 _size.y = newValue; 1227 break; 1228 case 2: 1229 _color.r = newValue; 1230 break; 1231 case 3: 1232 _color.g = newValue; 1233 break; 1234 case 4: 1235 _color.b = newValue; 1236 break; 1237 case 5: 1238 _color.a = newValue; 1239 break; 1240 case 6: 1241 _blend = newValue; 1242 break; 1243 default: 1244 throw new Exception("Filter property out of range"); 1245 } 1246 } 1247 1248 protected override void updateParticle(Particle particle, float deltaTime) { 1249 particle.color = lerp(particle.color, _color, _blend * deltaTime); 1250 } 1251 1252 override FilterProperty[] getProperties() const { 1253 return [ 1254 tuple("Longueur", 2f, 2000f, 1998u), 1255 tuple("Hauteur", 2f, 2000f, 1998u), 1256 tuple("Rouge", 0f, 1f, 256u), 1257 tuple("Vert", 0f, 1f, 256u), 1258 tuple("Bleu", 0f, 1f, 256u), 1259 tuple("Alpha", 0f, 1f, 256u), 1260 tuple("Mélange", .001f, .1f, 1000u) 1261 ]; 1262 } 1263 1264 override FilterDisplay getDisplay() const { 1265 Color color = _color; 1266 color.a = 1f; 1267 return tuple("Couleur", _isCircle, _size, false, cast(const Vec2f)Vec2f.zero, cast(const Color)color); 1268 } 1269 }+/