I don't understand the change from "FlxSpriteFilter" to "FlxFilterFrames?"



  • I've got some code which applies a drop shadow to a button, so that when the button is pressed, the drop shadow raises and lowers. This code worked OK in Flixel 3.3.12 but I'm struggling to transition it to Flixel 4.1.1.

    	var undoButton:FlxButton = new FlxButton(X, Y);
    	undoButton.loadGraphic(Graphic, true, Width, Height);
    	var spriteFilter:FlxSpriteFilter = new FlxSpriteFilter(undoButton, 0, 5);
    	var filter:DropShadowFilter = new DropShadowFilter(3, 90, 0, 0.25, 0, 0);
    	filter.distance = 3;
    	spriteFilter.addFilter(filter);
    	
    	undoButton.onDown.callback = function() {
    		undoButton.offset.y = -3;
    		filter.distance = 0;
    		spriteFilter.applyFilters();
    	}
    

    This code no longer compiles in Flixel 4.1.1 because the FlxSpriteFilter class was removed. So doing my best to follow along with the changes to the FlxSpriteFilters demo, I've changed the code to something like this...

    	var undoButton:FlxButton = new FlxButton(X, Y);
    	undoButton.loadGraphic(Graphic, true, Width, Height);
    	var filter:DropShadowFilter = new DropShadowFilter(3, 90, 0, 0.25, 0, 0);
    	var spriteFilter:FlxFilterFrames = FlxFilterFrames.fromFrames(undoButton.frames, 0, 5, [filter]);
    	filter.distance = 3;
    	spriteFilter.applyToSprite(undoButton, false, true);
    	
    	undoButton.onDown.callback = function() {
    		undoButton.offset.y = -3;
    		filter.distance = 0;
    		spriteFilter.applyToSprite(undoButton);
    	}
    

    The "onDown" callback no longer has any effect though -- the filter doesn't update. Looking at the FlxSpriteFilterDemo, I can see that they pass in "true" for the updateFrames parameter. However if I set updateFrames to true in the callback function, I get an error, "Invalid BitmapData". Maybe the filter's not meant to be reused in that way?

    What is this "applyToSprite" function supposed to do? According to the documentation it is "just helper method which centers sprite offsets". This doesn't really sound like what I want. Is there a one-to-one analog for this "applyFilters" method which used to exist? Just something to tell the dropShadowFilter to recalculate its state and update the sprite? Or was this functionality perhaps moved to a new class or tucked away somewhere?



  • @Aaron-Pieper

    So it turns out that in Flixel 4.1.1, applying a filter to a sprite wipes out its offsets. I've created an awful workaround:

    class FlxFilterFramesKludge extends FlxFilterFrames
    {
    	public var secretOffset:FlxPoint = new FlxPoint();
    	
    	private function new(sourceFrames:FlxFramesCollection, widthInc:Int = 0, heightInc:Int = 0, ?filters:Array<BitmapFilter>) {
    		super(sourceFrames, widthInc, heightInc, filters);
    	}
    	
    	static public function fromFrames(frames:FlxFramesCollection, widthInc:Int = 0, heightInc:Int = 0, ?filters:Array<BitmapFilter>):FlxFilterFramesKludge
    	{
    		return new FlxFilterFramesKludge(frames, widthInc, heightInc, filters);
    	}
    	
    	override public function applyToSprite(spr:FlxSprite, saveAnimations:Bool = false, updateFrames:Bool = false):Void 
    	{
    		super.applyToSprite(spr, saveAnimations, updateFrames);
    		spr.offset.addPoint(secretOffset);
    	}
    }
    

    So to apply a filter to a sprite that has offsets, the resulting code looks something like this:

    	var filter:DropShadowFilter = new DropShadowFilter(3, 90, 0, 0.75, 0, 0);
    	var spriteFilter:FlxFilterFramesKludge = FlxFilterFramesKludge.fromFrames(undoButton.frames, 0, 5, [filter]);
    	filter.distance = 3;
    	spriteFilter.applyToSprite(undoButton, false, true);
    	
    	undoButton.onDown.callback = function() {
    			spriteFilter.secretOffset.y = -3;
    			filter.distance = 0;
    			spriteFilter.applyToSprite(undoButton);
    	}
    

    This only really addresses half of the bug, as trying to update the button's frames still results in an "Invalid BitmapData" call. Bizarrely, it seems like Flixel 4.1.1 doesn't let you use images for clickable buttons, unless you first load those images into a completely unrelated and discarded FlxSprite first. Here's a self-contained demo showing the bug:

    package;
    
    import flash.filters.DropShadowFilter;
    import flixel.FlxG;
    import flixel.FlxState;
    import flixel.graphics.FlxGraphic;
    import flixel.graphics.frames.FlxFilterFrames;
    import flixel.system.FlxAssets.GraphicLogo;
    import flixel.ui.FlxButton;
    
    class FilterBugDemo extends FlxState
    {
    	override public function create():Void 
    	{
    		FlxG.camera.bgColor = 0xFF01355F;
    		
    		// this line of code is necessary...?
    		//new FlxSprite().loadGraphic(FlxGraphic.fromClass(GraphicLogo));
    		
    		var button:FlxButton = new FlxButton(0, 0);
    		button.loadGraphic(FlxGraphic.fromClass(GraphicLogo));
    		var filter:DropShadowFilter = new DropShadowFilter(15, 90, 0, 0.75, 0, 0);
    		var spriteFilter:FlxFilterFrames = FlxFilterFrames.fromFrames(button.frames, 0, 15, [filter]);
    		spriteFilter.applyToSprite(button, false, true);
    		
    		button.onDown.callback = function() {
    			filter.distance = 15 - filter.distance;
    			spriteFilter.applyToSprite(button, false, true);
    		}
    		add(button);
    	}
    }
    

    Running this code results in an "Invalid BitmapData" error unless you uncomment that line of code.

    So, I guess I have workarounds for both of my issues, but is this working as intended? Is there a cleaner way to initialize filters with offsets, or to apply filters to buttons?


Log in to reply