diff --git a/arcade/text.py b/arcade/text.py index a060d686c..31931ea5c 100644 --- a/arcade/text.py +++ b/arcade/text.py @@ -18,6 +18,67 @@ __all__ = ["load_font", "Text", "create_text_sprite", "draw_text"] +class ArcadeTextLayoutGroup(pyglet.text.layout.TextLayoutGroup): + """Create a text layout rendering group. + + Overrides pyglet blending handling to allow for additive blending. + Furthermore, it resets the blend function to the previous state. + """ + + _prev_blend = None + _prev_blend_func = None + + def set_state(self) -> None: + import pyglet.gl as gl + from ctypes import c_int, c_ubyte + + self.program.use() + self.program["scissor"] = False + + gl.glActiveTexture(gl.GL_TEXTURE0) + gl.glBindTexture(self.texture.target, self.texture.id) + + blend = c_ubyte() + gl.glGetBooleanv(gl.GL_BLEND, blend) + self._prev_blend = bool(blend.value) + + src_rgb = c_int() + dst_rgb = c_int() + src_alpha = c_int() + dst_alpha = c_int() + gl.glGetIntegerv(gl.GL_BLEND_SRC_RGB, src_rgb) + gl.glGetIntegerv(gl.GL_BLEND_DST_RGB, dst_rgb) + gl.glGetIntegerv(gl.GL_BLEND_SRC_ALPHA, src_alpha) + gl.glGetIntegerv(gl.GL_BLEND_DST_ALPHA, dst_alpha) + + self._prev_blend_func = (src_rgb.value, dst_rgb.value, src_alpha.value, dst_alpha.value) + + gl.glEnable(gl.GL_BLEND) + gl.glBlendFuncSeparate( + gl.GL_SRC_ALPHA, + gl.GL_ONE_MINUS_SRC_ALPHA, + gl.GL_ONE, + gl.GL_ONE, + ) + + def unset_state(self) -> None: + import pyglet.gl as gl + + if not self._prev_blend: + gl.glDisable(gl.GL_BLEND) + + gl.glBlendFuncSeparate( + self._prev_blend_func[0], + self._prev_blend_func[1], + self._prev_blend_func[2], + self._prev_blend_func[3], + ) + self.program.stop() + + +pyglet.text.layout.TextLayout.group_class = ArcadeTextLayoutGroup + + def load_font(path: str | Path) -> None: """ Load fonts in a file (usually .ttf) adding them to a global font registry. @@ -253,7 +314,8 @@ def __init__( bold=bold, italic=italic, multiline=multiline, - rotation=rotation, # type: ignore # pending https://github.com/pyglet/pyglet/issues/843 + rotation=rotation, + # type: ignore # pending https://github.com/pyglet/pyglet/issues/843 batch=batch, group=group, **kwargs,