doodles-py/src/doodles/text.py

80 lines
2.5 KiB
Python
Raw Normal View History

2024-04-26 19:48:30 +00:00
"""
This is the most complicated Doodle-derived class.
Like shapes, the interface is mostly identical to Line.
If you are mainly trying to understand the interfaces it is
safe to skip this one.
There is some more complexity here because fonts need to be
pre-rendered. This means that when `text` is called, an internal
cached copy of the font already drawn to a temporary piece of memory
"surface" in graphics programming parlance.
This is an example of a type of class where when a property changes
some additional computation can be done to precompute/cache
some expensive logic.
Look at _render() for more.
"""
2024-04-23 01:53:30 +00:00
from .doodles import Doodle
2024-04-24 03:07:25 +00:00
from .world import world
2024-04-23 01:53:30 +00:00
class Text(Doodle):
def __init__(self, parent=None):
"""
2024-04-26 19:48:30 +00:00
A text object stores a reference to a pre-loaded font,
the text to be drawn, and an internal `_rendered` object
that *can* be used to store the cached text.
Not all implementations will require pre-rendering, but
Pygame (the first implementation) does, so it is necessary
for the interface as written here.
When drawn, text will be centered at `pos`
2024-04-23 01:53:30 +00:00
"""
super().__init__(parent)
self._text = ""
2024-04-24 03:07:25 +00:00
self._rendered = None # the surface we pre-render the text to
2024-04-23 01:53:30 +00:00
self._font = None
def __repr__(self):
return f"Text(pos={self.pos_vec}, text={self._text}, parent={self._parent})"
2024-04-24 03:07:25 +00:00
def draw(self):
world.draw_engine.text_draw(self)
2024-04-23 01:53:30 +00:00
def text(self, text: str) -> "Doodle":
"""
2024-04-24 03:07:25 +00:00
A setter for the text.
This is the only place text can change,
so we can pre-render the surface here.
2024-04-23 01:53:30 +00:00
"""
self._text = text
2024-04-24 03:07:25 +00:00
self._render()
return self
def _render(self):
"""
This function needs to set the _rendered property.
_rendered may be relied upon by draw_engine.draw_text.
2024-04-26 19:48:30 +00:00
Text needs to be rendered once on change to be performant.
Doing this in draw would be much slower since it is called
much more often than the text changes.
(draw called ~60 times per second, _render only called when
text is updated.)
2024-04-24 03:07:25 +00:00
"""
2024-04-23 01:53:30 +00:00
if not self._font:
2024-04-24 03:07:25 +00:00
self._font = world.draw_engine.get_font() # default font
self._rendered = world.draw_engine.text_render(
self._text, self._font, self._color
)
2024-04-23 01:53:30 +00:00
def font(self, font: str) -> "Doodle":
2024-04-24 03:07:25 +00:00
self._font = world.draw_engine.get_font(font)
2024-04-23 01:53:30 +00:00
return self