gamnit: add customization settings to `TextSprites`
[nit.git] / lib / gamnit / font.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Abstract font drawing services, implemented by `bmfont` and `tileset`
16 module font
17
18 import flat
19
20 # Abstract font, drawn by a `TextSprites`
21 abstract class Font
22
23 # Line spacing modifier for `pld` and `plu`
24 #
25 # This value acts as multiplier to the standard line height.
26 # Defaults to 0.4, so a `pld` moves chars down by about half a line.
27 var partial_line_mod: Numeric = 0.4 is writable
28
29 # Backend writing service, clients should use `TextSprites.text=`
30 protected fun write_into(text_sprites: TextSprites, text: Text) is abstract
31 end
32
33 # Manage a set of sprites to display some text
34 class TextSprites
35
36 # Font used to draw text
37 var font: Font
38
39 # Reference coordinates of this block of text
40 #
41 # When left aligned, the default at `align == 0.0`, the anchor is the
42 # left coordinate of the first character of the first line.
43 # When right aligned, at `align == 1.0`, the anchor is the right
44 # coordinate of the last character.
45 # When centered, at `align == 0.5`, the anchor is at the center.
46 #
47 # When top aligned, the default at `valign == 0.0`, the anchor is at the
48 # top of this block of text.
49 # When bottom aligned, at `valign == 1.0`, the anchor is at the bottom.
50 var anchor: Point3d[Float]
51
52 # Last set of sprites generated to display `text=`
53 var sprites = new Array[Sprite]
54
55 # Sprite set where to put created sprites
56 #
57 # Defaults to `app::ui_sprites`, but it could also be set to a
58 # `app::sprites` or a custom collection.
59 var target_sprite_set: Set[Sprite] = app.ui_sprites is lazy, writable
60
61 private var cached_text: nullable Text = null
62
63 private var init_complete = false
64
65 # Last text drawn
66 fun text: nullable Text do return cached_text
67
68 # Update the text displayed by inserting new sprites into `app.ui_sprites`
69 #
70 # Does not redraw if `text` has not changed.
71 fun text=(text: nullable Text)
72 is autoinit do
73 # Don't redraw if text hasn't changed
74 if text == cached_text then return
75 cached_text = text
76
77 if not init_complete then return
78
79 # Clean up last used sprites
80 for s in sprites do if target_sprite_set.has(s) then target_sprite_set.remove s
81 sprites.clear
82
83 if text == null then return
84
85 font.write_into(self, text)
86
87 # Register sprites to be drawn by `app.ui_camera`
88 target_sprite_set.add_all sprites
89 end
90
91 # Horizontal text alignment
92 #
93 # Use 0.0 to align left (the default), 0.5 to align in the center or
94 # 1.0 to align on the right.
95 #
96 # See: `valign`
97 var align = 0.0 is optional, writable
98
99 # Vertical text alignment
100 #
101 # Use 0.0 for top alignment (the default) where the text is under the `anchor`,
102 # 0.5 to vertically center the text on the `anchor` or
103 # or 1.0 to bottom align the text above the `anchor`.
104 #
105 # See: `align`
106 var valign = 0.0 is optional, writable
107
108 # Maximum width of each line of text
109 #
110 # The first word of each line is exempt and may overflow.
111 #
112 # The behavior when a line overflow depends on `wrap`.
113 var max_width: nullable Float is writable
114
115 # Maximum height of this block of text
116 #
117 # The first line is exempt and may overflow.
118 # Overflowing lines are cut.
119 var max_height: nullable Float is writable
120
121 # Should overflowing lines wrap to the next line?
122 #
123 # If `true`, the default, overflowing lines continue on the next line.
124 # Otherwise, lines are cut before overflowing.
125 var wrap = true is optional, writable
126
127 # Width of the currently displayed text
128 var width = 0.0
129
130 # Height of the currently displayed text
131 var height = 0.0
132
133 # Force drawing of the text sprites
134 #
135 # This method may be called after changing a setting (`align`, `wrap`, etc.)
136 # to update the displayed text.
137 fun force_redraw
138 do
139 var t = cached_text
140 cached_text = null
141 text = t
142 end
143
144 init
145 do
146 init_complete = true
147 force_redraw
148 end
149 end
150
151 # Partial line forward (U+008B)
152 fun pld: Char do return '\8b'
153
154 # Partial line backward (U+008C)
155 fun plu: Char do return '\8c'