Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FlxTextBorderStyle: Add SHADOW_XY, prevent border clipping #3236

Merged
merged 9 commits into from
Aug 20, 2024

Conversation

Geokureli
Copy link
Member

@Geokureli Geokureli commented Aug 15, 2024

Fixes #3235

Changes

  • Adds new FlxTextBorderStyle.SHADOW_XY
  • Deprecates shadowOffset
  • Expands image size to fit outline (sets width, height and offset to keep text in the same position)

Concerns

  • offset is now changed whenever the graphic is redrawn, this could be a breaking change, we should try to offset its draw position without affecting offset - added _graphicOffset which offsets the position without using offset

Test State:

package states;

import flixel.system.debug.log.LogStyle;
import flixel.FlxG;
import flixel.text.FlxText;
import flixel.text.FlxBitmapText;

class TextShadowTestState extends flixel.FlxState
{
	final styles:Array<()->FlxTextBorderStyle> = [];
	
	var text:FlxText;
	var bmText:FlxBitmapText;
	var showBorder = true;
	var size = 4;
	var quality = 0;
	var styleIndex = 0;
	var offsetX = 1;
	var offsetY = 1;
	
	var instructions:FlxText;
	
	override public function create()
	{
		super.create();
		bgColor = 0xFF808080;
		
		styles.push(()->SHADOW);
		styles.push(()->SHADOW_XY(offsetX, offsetY));
		styles.push(()->OUTLINE);
		styles.push(()->OUTLINE_FAST);
		
		// text = new flixel.addons.ui.FlxInputText(0, 0, FlxG.width, "FlxText shadow clipping test lol", 8);
		text = new FlxText(0, 0, 0, "FlxText shadow clipping test lol", 8);
		text.screenCenter();
		add(text);
		
		bmText = new FlxBitmapText(0, 0, "FlxText shadow clipping test lol");
		bmText.screenCenter();
		add(bmText);
		
		final gap = (text.height + bmText.height) * 0.5;
		text.y -= gap;
		bmText.y += gap;
		
		applyShadow();
		
		// debug watch
		FlxG.watch.addFunction("bmd", function ()
		{
			final bmp = text.graphic.bitmap;
			return '( w: ${bmp.width} | h: ${bmp.height} )';
		});
		FlxG.watch.addFunction("shd.offset", ()->'( x: $offsetX | y: $offsetY )');
		FlxG.watch.addFunction("shd.size", ()->size);
		FlxG.watch.addFunction("shd.quality", ()->quality);
		FlxG.watch.addFunction("shd.style", ()->'$styleIndex : ${text.borderStyle}');
		FlxG.log.notice("LEFT RIGHT UP DOWN: change shadowOffset");
		FlxG.log.notice("SPACE: reset shadowOffset");
		FlxG.log.notice("< >: change borderSize");
		FlxG.log.notice("SHIFT + < >: change borderQuality");
		FlxG.log.notice("CLICK: toggle border");
		FlxG.log.notice("ENTER: change style");
		FlxG.debugger.visible = true;
		FlxG.debugger.drawDebug = true;
		
		LogStyle.WARNING.callbackFunction = function ()
		{
			trace("Warning");
		}
	}
	
	function applyShadow()
	{
		if (showBorder)
		{
			text.setBorderStyle(styles[styleIndex](), 0xFF000000, size, quality);
			bmText.setBorderStyle(styles[styleIndex](), 0xFF000000, size, quality);
		}
		else
		{
			text.setBorderStyle(NONE);
			bmText.setBorderStyle(NONE);
		}
		
		@:privateAccess text._regen = true;
		@:privateAccess text.regenGraphic();
		FlxG.bitmapLog.clear();
		FlxG.bitmapLog.add(text.graphic.bitmap);
	}

	override public function update(elapsed:Float)
	{
		super.update(elapsed);
		
		var redraw = false;
		
		if (FlxG.keys.anyJustPressed([SPACE, RIGHT, LEFT, UP, DOWN]))
		{
			if (FlxG.keys.justPressed.SPACE) { offsetX = 1; offsetY = 1; }
			if (FlxG.keys.justPressed.RIGHT) offsetX += 1;
			if (FlxG.keys.justPressed.LEFT) offsetX -= 1;
			if (FlxG.keys.justPressed.UP) offsetY -= 1;
			if (FlxG.keys.justPressed.DOWN) offsetY += 1;
			text.shadowOffset.set(offsetX, offsetY);
			bmText.shadowOffset.set(offsetX, offsetY);
			
			redraw = true;
		}
		
		if (FlxG.keys.pressed.D) { text.x += 1; bmText.x += 1; }
		if (FlxG.keys.pressed.A) { text.x -= 1; bmText.x -= 1; }
		if (FlxG.keys.pressed.W) { text.y -= 1; bmText.y -= 1; }
		if (FlxG.keys.pressed.S) { text.y += 1; bmText.y += 1; }
		
		if (FlxG.keys.justPressed.ENTER)
		{
			styleIndex = (styleIndex + 1) % styles.length;
			redraw = true;
		}
		
		if (FlxG.keys.anyJustPressed([COMMA, PERIOD]))
		{
			if (FlxG.keys.pressed.SHIFT)
			{
				if (FlxG.keys.justPressed.PERIOD && quality < 2) quality++;
				if (FlxG.keys.justPressed.COMMA && quality > 0) quality--;
			}
			else
			{
				if (FlxG.keys.justPressed.PERIOD) size++;
				if (FlxG.keys.justPressed.COMMA) size--;
			}
			
			redraw = true;
		}
		
		if (FlxG.mouse.justPressed)
		{
			showBorder = !showBorder;
			redraw = true;
		}
		
		if (redraw)
			applyShadow();
		
		if (FlxG.keys.justPressed.BACKSPACE)
		{
			text.text = text.text == "" ? "FlxText shadow clipping test lol" : "";
			bmText.text = text.text;
		}
	}
}

@Vortex2Oblivion
Copy link
Contributor

image
This fix does not also work with the old method though.

@Vortex2Oblivion
Copy link
Contributor

image This fix does not also work with the old method though.

Code snippet reproducing the issue

package;

import flixel.FlxState;
import flixel.text.FlxText;

class PlayState extends FlxState
{
	override public function create()
	{
		super.create();
		bgColor = 0xFF0000;
		var text:FlxText = new FlxText();
		text.text = "FlxText shadow clipping test lol";
		text.size = 32;
		text.screenCenter();
		text.borderStyle = SHADOW;
		text.shadowOffset.set(35, 35);
		add(text);
	}
}

Copy link
Contributor

@Vortex2Oblivion Vortex2Oblivion left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fix doesn't work with the old deprecated method though.
I was able to fix it by just replacing like 879 and 880 with

		var newWidthFloat:Float = textField.width;
		var newHeightFloat:Float = _autoHeight ? textField.textHeight + VERTICAL_GUTTER : textField.height;

		if (shadowOffset != null)
		{
			newWidthFloat += Math.ceil(Math.abs(_shadowOffset.x));
			newHeightFloat += Math.ceil(Math.abs(_shadowOffset.y));
		}
		

image
It works both ways now.

@Geokureli
Copy link
Member Author

Geokureli commented Aug 16, 2024

I was able to fix it by ...

Thanks! truthfully I hadn't tested shadowOffset yet, but was planning to before merging, I'll try this

Does the new SHADOW_CUSTOM work for your project's needs?

@Geokureli
Copy link
Member Author

TODO: fix isOnScreen when shadow is above or left

@Vortex2Oblivion
Copy link
Contributor

Vortex2Oblivion commented Aug 16, 2024

Does the new SHADOW_CUSTOM work for your project's needs?

Yes. Honestly though it seems to be like not a good solution. I feel like it would just be easier to keep the shadow style, then you can customize the offset to your liking, rather than having a whole other style for changing the offsets.

@Vortex2Oblivion
Copy link
Contributor

Would it be possible to make SHADOW work like before but optionally be able to add a constructor (not sure if that's the right term here but whatever) to do SHADOW(offsetX, offsetY)

@Geokureli
Copy link
Member Author

Geokureli commented Aug 17, 2024

Would it be possible to make SHADOW work like before but optionally be able to add a constructor (not sure if that's the right term here but whatever) to do SHADOW(offsetX, offsetY)

No, I can change SHADOW to SHADOW(?x,?y) and make it possible to do SHADOW() with no args but that would break all previous usage of SHADOW

Yes. Honestly though it seems to be like not a good solution. I feel like it would just be easier to keep the shadow style, then you can customize the offset to your liking, rather than having a whole other style for changing the offsets.

Why is it not a good solution? this is the exact reason enums can have args rather than using secondary fields that only effect certain enum values. Also shadowOffset moves the text and keeps the shadow in the same place, which is crazy dumb

Furthermore, this is a very niche feature, I've never seen it used until now

If i was making this feature now, I would make it

NONE;
SHADOW(x:Float, ?y:Float);//y=x if null
OUTLINE(thickness:Float, ?cornersOnly:Bool);// cornersOnly = false if null

and do away with borderSize altogether

@Geokureli Geokureli added this to the 5.9.0 milestone Aug 19, 2024
@Geokureli Geokureli merged commit 3f0ddae into HaxeFlixel:dev Aug 20, 2024
11 checks passed
@Geokureli Geokureli changed the title FlxTextBorderStyle: Add SHADOW_CUSTOM, always draw full outline FlxTextBorderStyle: Add SHADOW_XY, prevent border clipping Aug 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

FlxText shadow/outline issues
2 participants