Skip to content

Commit

Permalink
update filter mixin
Browse files Browse the repository at this point in the history
  • Loading branch information
GoodBoyDigital committed May 13, 2024
1 parent 78824e4 commit c31ba5a
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 51 deletions.
20 changes: 13 additions & 7 deletions src/filters/FilterEffect.ts
Expand Up @@ -2,20 +2,26 @@ import type { Rectangle } from '../maths/shapes/Rectangle';
import type { Effect } from '../scene/container/Effect';
import type { Filter } from './Filter';

/**
* A filter effect is an effect that can be applied to a container that involves applying special pixel effects
* to that container as it is rendered. Used internally when the filters property is modified on a container
*/
export class FilterEffect implements Effect
{
public filters: Filter[];
/** read only filters array - to modify, set it again! */
public filters: readonly Filter[];
/**
* If specified, rather than calculating the bounds of the container that the filter
* will apply to, we use this rect instead. This is a local rect - so will have the containers transform
* applied to it
*/
public filterArea?: Rectangle;

/** the pipe that knows how to handle this effect */
public pipe = 'filter';
/** the priority of this effect */
public priority = 1;

constructor(options?: {filters: Filter[], filterArea?: Rectangle})
{
this.filters = options?.filters;
this.filterArea = options?.filterArea;
}

public destroy(): void
{
for (let i = 0; i < this.filters.length; i++)
Expand Down
10 changes: 5 additions & 5 deletions src/rendering/mask/alpha/AlphaMaskPipe.ts
Expand Up @@ -27,11 +27,11 @@ class AlphaMaskEffect extends FilterEffect implements PoolItem
{
constructor()
{
super({
filters: [new MaskFilter({
sprite: new Sprite(Texture.EMPTY)
})]
});
super();

this.filters = [new MaskFilter({
sprite: new Sprite(Texture.EMPTY)
})];
}

get sprite(): Sprite
Expand Down
12 changes: 7 additions & 5 deletions src/rendering/renderers/shared/blendModes/BlendModePipe.ts
Expand Up @@ -119,19 +119,21 @@ export class BlendModePipe implements InstructionPipe<AdvancedBlendInstruction>
return;
}

let filterEffect = this._filterHash[blendMode];

// this does need an execute?
if (!this._filterHash[blendMode])
if (!filterEffect)
{
this._filterHash[blendMode] = new FilterEffect({
filters: [new BLEND_MODE_FILTERS[blendMode as keyof typeof BLEND_MODE_FILTERS]()]
});
filterEffect = this._filterHash[blendMode] = new FilterEffect();

filterEffect.filters = [new BLEND_MODE_FILTERS[blendMode as keyof typeof BLEND_MODE_FILTERS]()];
}

const instruction: FilterInstruction = {
renderPipeId: 'filter',
action: 'pushFilter',
renderables: [],
filterEffect: this._filterHash[blendMode],
filterEffect,
canBundle: false,
};

Expand Down
2 changes: 1 addition & 1 deletion src/scene/container/Container.ts
Expand Up @@ -1346,7 +1346,7 @@ export class Container<C extends ContainerChild = ContainerChild> extends EventE
this.removeFromParent();
this.parent = null;
this._mask = null;
this._filters = null;
this._filterEffect = null;
this.effects = null;
this._position = null;
this._scale = null;
Expand Down
47 changes: 14 additions & 33 deletions src/scene/container/container-mixins/effectsMixin.ts
@@ -1,10 +1,8 @@
import { FilterEffect } from '../../../filters/FilterEffect';
import { MaskEffectManager } from '../../../rendering/mask/MaskEffectManager';
import { BigPool } from '../../../utils/pool/PoolGroup';

import type { Filter } from '../../../filters/Filter';
import type { Rectangle } from '../../../maths/shapes/Rectangle';
import type { PoolItem } from '../../../utils/pool/Pool';
import type { Container } from '../Container';
import type { Effect } from '../Effect';

Expand All @@ -16,11 +14,7 @@ export interface EffectsMixinConstructor
export interface EffectsMixin extends Required<EffectsMixinConstructor>
{
_mask?: {mask: unknown, effect: Effect};
_filters?: {
filters: readonly Filter[],
effect: FilterEffect
filterArea?: Rectangle,
},
_filterEffect?: FilterEffect,
filterArea?: Rectangle,
effects?: Effect[];
addEffect(effect: Effect): void;
Expand All @@ -29,7 +23,7 @@ export interface EffectsMixin extends Required<EffectsMixinConstructor>

export const effectsMixin: Partial<Container> = {
_mask: null,
_filters: null,
_filterEffect: null,

/**
* @todo Needs docs.
Expand Down Expand Up @@ -139,49 +133,36 @@ export const effectsMixin: Partial<Container> = {
{
if (!Array.isArray(value) && value) value = [value];

const effect = this._filterEffect ||= new FilterEffect();

// Ignore the Filter type
value = value as Filter[] | null | undefined;

// by reusing the same effect.. rather than adding and removing from the pool!
this._filters ||= { filters: null, effect: null, filterArea: null };

const hasFilters = value?.length > 0;
const didChange = (this._filters.effect && !hasFilters) || (!this._filters.effect && hasFilters);
const hadFilters = effect.filters?.length > 0;

const didChange = hasFilters !== hadFilters;

// Clone the filters array so we don't freeze the user-input
value = Array.isArray(value) ? value.slice(0) : value;

// Ensure filters are immutable via filters getter
this._filters.filters = Object.freeze(value);
effect.filters = Object.freeze(value);

if (didChange)
{
if (hasFilters)
{
const effect = BigPool.get(FilterEffect);

this._filters.effect = effect;
this.addEffect(effect);
}
else
{
const effect = this._filters.effect;

this.removeEffect(effect);

effect.filterArea = null;
effect.filters = null;

this._filters.effect = null;
BigPool.return(effect as PoolItem);
// sets the empty array...
effect.filters = value ?? null;
}
}

if (hasFilters)
{
this._filters.effect.filters = value as Filter[];
this._filters.effect.filterArea = this.filterArea;
}
},

/**
Expand All @@ -192,14 +173,14 @@ export const effectsMixin: Partial<Container> = {
*/
get filters(): readonly Filter[]
{
return this._filters?.filters;
return this._filterEffect?.filters;
},

set filterArea(value: Rectangle)
{
this._filters ||= { filters: null, effect: null, filterArea: null };
this._filterEffect ||= new FilterEffect();

this._filters.filterArea = value;
this._filterEffect.filterArea = value;
},

/**
Expand All @@ -211,7 +192,7 @@ export const effectsMixin: Partial<Container> = {
*/
get filterArea(): Rectangle
{
return this._filters?.filterArea;
return this._filterEffect?.filterArea;
},

} as Container;

0 comments on commit c31ba5a

Please sign in to comment.