effects_manager.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import { get_supported_effects } from '../effects/effects.js';
  2. /// An object to manage effects (by not destroying them all the time)
  3. export const EffectsManager = class EffectsManager {
  4. constructor(connections) {
  5. this.connections = connections;
  6. this.used = [];
  7. this.SUPPORTED_EFFECTS = get_supported_effects();
  8. Object.keys(this.SUPPORTED_EFFECTS).forEach(effect_name => {
  9. // init the arrays containing each unused effect
  10. this[effect_name + '_effects'] = [];
  11. // init the functions for each effect
  12. this['new_' + effect_name + '_effect'] = function (params) {
  13. let effect;
  14. if (this[effect_name + '_effects'].length > 0) {
  15. effect = this[effect_name + '_effects'].splice(0, 1)[0];
  16. effect.set({
  17. ...this.SUPPORTED_EFFECTS[effect_name].class.default_params, ...params
  18. });
  19. } else
  20. effect = new this.SUPPORTED_EFFECTS[effect_name].class({
  21. ...this.SUPPORTED_EFFECTS[effect_name].class.default_params, ...params
  22. });
  23. this.used.push(effect);
  24. this.connect_to_destroy(effect);
  25. return effect;
  26. };
  27. });
  28. }
  29. connect_to_destroy(effect) {
  30. effect.old_actor = effect.get_actor();
  31. if (effect.old_actor)
  32. effect.old_actor_id = effect.old_actor.connect('destroy', _ => {
  33. this.remove(effect, true);
  34. });
  35. this.connections.connect(effect, 'notify::actor', _ => {
  36. let actor = effect.get_actor();
  37. if (effect.old_actor && actor != effect.old_actor)
  38. effect.old_actor.disconnect(effect.old_actor_id);
  39. if (actor && actor != effect.old_actor) {
  40. effect.old_actor_id = actor.connect('destroy', _ => {
  41. this.remove(effect, true);
  42. });
  43. }
  44. });
  45. }
  46. // IMPORTANT: do never call this in a mutable `this.used.forEach`
  47. remove(effect, actor_already_destroyed = false) {
  48. if (!actor_already_destroyed)
  49. try {
  50. effect.get_actor()?.remove_effect(effect);
  51. } catch (e) {
  52. this._warn(`could not remove the effect, continuing: ${e}`);
  53. }
  54. if (effect.old_actor)
  55. effect.old_actor.disconnect(effect.old_actor_id);
  56. delete effect.old_actor;
  57. delete effect.old_actor_id;
  58. let index = this.used.indexOf(effect);
  59. if (index >= 0) {
  60. this.used.splice(index, 1);
  61. Object.keys(this.SUPPORTED_EFFECTS).forEach(effect_name => {
  62. if (effect instanceof this.SUPPORTED_EFFECTS[effect_name].class)
  63. this[effect_name + '_effects'].push(effect);
  64. });
  65. }
  66. }
  67. destroy_all() {
  68. const immutable_used_list = [...this.used];
  69. immutable_used_list.forEach(effect => this.remove(effect));
  70. Object.keys(this.SUPPORTED_EFFECTS).forEach(effect_name => {
  71. this[effect_name + '_effects'].splice(0, this[effect_name + '_effects'].length);
  72. });
  73. }
  74. _warn(str) {
  75. console.warn(`[Blur my Shell > effects mng] ${str}`);
  76. }
  77. };