bzr branch
http://9ix.org/bzr/ld27
1
by Josh C
zoetrope 1.4 |
1 |
-- Class: Text |
2 |
-- Shows text onscreen using an outline (e.g. TrueType) or bitmap font. |
|
3 |
-- You can control the width of the text but the height is ignored for |
|
4 |
-- display purposes; it will always draw the entirety of its text property. |
|
5 |
-- If you do not specify a height and width, the sprite will size itself |
|
6 |
-- so that it fits its entire text as a single line. |
|
7 |
-- |
|
8 |
-- By default, an outline font will display as white. To change its color, |
|
9 |
-- change its <Sprite.tint> property. |
|
10 |
-- |
|
11 |
-- Extends: |
|
12 |
-- <Sprite> |
|
13 |
||
14 |
Text = Sprite:extend{ |
|
15 |
-- Property: text |
|
16 |
-- Text string to draw. |
|
17 |
text = '', |
|
18 |
||
19 |
-- Property: font |
|
20 |
-- Font to use to draw. See <Cached.font> for possible values here; if |
|
21 |
-- you need more than one value, use table notation. Some example values: |
|
22 |
-- * 12 (default font, size 12) |
|
23 |
-- * 'fonts/bitmapfont.png' (bitmap font, default character order) |
|
24 |
-- * { 'fonts/outlinefont.ttf', 12 } (outline font, font size) |
|
25 |
-- * { 'fonts/bitmapfont.ttf', 'ABCDEF' } (bitmap font, custom character order) |
|
26 |
font = 12, |
|
27 |
||
28 |
-- Property: align |
|
29 |
-- Horizontal alignment, see http://love2d.org/wiki/AlignMode. |
|
30 |
-- This affects how lines wrap relative to each other, not how |
|
31 |
-- a single line will wrap relative to the sprite's width and height. |
|
32 |
-- If <wordWrap> is set to false, then this has no effect. |
|
33 |
align = 'left', |
|
34 |
||
35 |
-- Property: wordWrap |
|
36 |
-- Wrap lines to the width of the sprite? |
|
37 |
wordWrap = true, |
|
38 |
||
39 |
-- private property: used to check whether our font has changed |
|
40 |
_set = { font = {} }, |
|
41 |
||
42 |
new = function (self, obj) |
|
43 |
obj = obj or {} |
|
44 |
self:extend(obj) |
|
45 |
obj:updateFont() |
|
46 |
if obj.onNew then obj:onNew() end |
|
47 |
return obj |
|
48 |
end, |
|
49 |
||
50 |
-- Method: getSize |
|
51 |
-- Returns the width and height of the text onscreen as line-wrapped |
|
52 |
-- to the sprite's boundaries. This disregards the sprite's height property. |
|
53 |
-- |
|
54 |
-- Arguments: |
|
55 |
-- none |
|
56 |
-- |
|
57 |
-- Returns: |
|
58 |
-- width, height in pixels |
|
59 |
||
60 |
getSize = function (self) |
|
61 |
if self.text == '' then return 0, 0 end |
|
62 |
||
63 |
-- did our font change on us? |
|
64 |
||
65 |
if type(self.font) == 'table' then |
|
66 |
for key, value in pairs(self.font) do |
|
67 |
if self._set.font[key] ~= self.font[key] then |
|
68 |
self:updateFont() |
|
69 |
break |
|
70 |
end |
|
71 |
end |
|
72 |
else |
|
73 |
if self.font ~= self._set.font then |
|
74 |
self:updateFont() |
|
75 |
end |
|
76 |
end |
|
77 |
||
78 |
local _, lines = self._fontObj:getWrap(self.text, self.width) |
|
79 |
local lineHeight = self._fontObj:getHeight() |
|
80 |
||
81 |
return self.width, lines * lineHeight |
|
82 |
end, |
|
83 |
||
84 |
-- Method: centerAround |
|
85 |
-- Centers the text around a position onscreen. |
|
86 |
-- |
|
87 |
-- Arguments: |
|
88 |
-- x - center's x coordinate |
|
89 |
-- y - center's y coordinate |
|
90 |
-- centering - can be either 'horizontal', 'vertical', or 'both'; |
|
91 |
-- default 'both' |
|
92 |
||
93 |
centerAround = function (self, x, y, centering) |
|
94 |
centering = centering or 'both' |
|
95 |
local width, height = self:getSize() |
|
96 |
||
97 |
if width == 0 then return end |
|
98 |
||
99 |
if centering == 'both' or centering == 'horizontal' then |
|
100 |
self.x = x - width / 2 |
|
101 |
end |
|
102 |
||
103 |
if centering == 'both' or centering == 'vertical' then |
|
104 |
self.y = y - height / 2 |
|
105 |
end |
|
106 |
end, |
|
107 |
||
108 |
-- private method: updateFont |
|
109 |
-- Updates the _fontObj property based on self.font. |
|
110 |
-- |
|
111 |
-- Arguments: |
|
112 |
-- none |
|
113 |
-- |
|
114 |
-- Returns: |
|
115 |
-- nothing |
|
116 |
||
117 |
updateFont = function (self) |
|
118 |
if self.font then |
|
119 |
if type(self.font) == 'table' then |
|
120 |
self._fontObj = Cached:font(unpack(self.font)) |
|
121 |
else |
|
122 |
self._fontObj = Cached:font(self.font) |
|
123 |
end |
|
124 |
||
125 |
if not self.height then self.height = self._fontObj:getHeight() end |
|
126 |
if not self.width and self.text then self.width = self._fontObj:getWidth(self.text) end |
|
127 |
end |
|
128 |
end, |
|
129 |
||
130 |
draw = function (self, x, y) |
|
131 |
if not self.visible or self.alpha <= 0 or not self.text or not self.font then return end |
|
132 |
||
133 |
x = math.floor(x or self.x) |
|
134 |
y = math.floor(y or self.y) |
|
135 |
||
136 |
if STRICT then |
|
137 |
assert(type(x) == 'number', 'visible text sprite does not have a numeric x property') |
|
138 |
assert(type(y) == 'number', 'visible text sprite does not have a numeric y property') |
|
139 |
assert(type(self.width) == 'number', 'visible text sprite does not have a numeric width property') |
|
140 |
assert(type(self.height) == 'number', 'visible text sprite does not have a numeric height property') |
|
141 |
if not self.text then error('visible text sprite has no text property') end |
|
142 |
if not self.font then error('visible text sprite has no font property') end |
|
143 |
end |
|
144 |
||
145 |
-- did our font change on us? |
|
146 |
||
147 |
if type(self.font) == 'table' then |
|
148 |
for key, value in pairs(self.font) do |
|
149 |
if self._set.font[key] ~= self.font[key] then |
|
150 |
self:updateFont() |
|
151 |
break |
|
152 |
end |
|
153 |
end |
|
154 |
else |
|
155 |
if self.font ~= self._set.font then |
|
156 |
self:updateFont() |
|
157 |
end |
|
158 |
end |
|
159 |
||
160 |
-- rotate and scale |
|
161 |
||
162 |
local scaleX = self.scale * self.distort.x |
|
163 |
local scaleY = self.scale * self.distort.y |
|
164 |
||
165 |
if self.flipX then scaleX = scaleX * -1 end |
|
166 |
if self.flipY then scaleY = scaleY * -1 end |
|
167 |
||
168 |
if scaleX ~= 1 or scaleY ~= 1 or self.rotation ~= 0 then |
|
169 |
love.graphics.push() |
|
170 |
love.graphics.translate(x + self.width / 2, y + self.height / 2) |
|
171 |
love.graphics.scale(scaleX, scaleY) |
|
172 |
love.graphics.rotate(self.rotation) |
|
173 |
love.graphics.translate(- (x + self.width / 2), - (y + self.height / 2)) |
|
174 |
end |
|
175 |
||
176 |
-- set color if needed |
|
177 |
||
178 |
local colored = self.alpha ~= 1 or self.tint[1] ~= 1 or self.tint[2] ~= 1 or self.tint[3] ~= 1 |
|
179 |
||
180 |
if colored then |
|
181 |
love.graphics.setColor(self.tint[1] * 255, self.tint[2] * 255, self.tint[3] * 255, self.alpha * 255) |
|
182 |
end |
|
183 |
||
184 |
love.graphics.setFont(self._fontObj) |
|
185 |
||
186 |
if self.wordWrap then |
|
187 |
love.graphics.printf(self.text, x, y, self.width, self.align) |
|
188 |
else |
|
189 |
love.graphics.print(self.text, x, y) |
|
190 |
end |
|
191 |
||
192 |
-- reset color and rotation |
|
193 |
||
194 |
if colored then love.graphics.setColor(255, 255, 255, 255) end |
|
195 |
||
196 |
if scaleX ~= 1 or scaleY ~= 1 or self.rotation ~= 0 then |
|
197 |
love.graphics.pop() |
|
198 |
end |
|
199 |
end, |
|
200 |
||
201 |
__tostring = function (self) |
|
202 |
local result = 'Text (x: ' .. self.x .. ', y: ' .. self.y .. |
|
203 |
', w: ' .. self.width .. ', h: ' .. self.height .. ', ' |
|
204 |
||
205 |
result = result .. 'font ' .. dump(self.font) .. ', ' .. string.len(self.text) .. ' chars, ' |
|
206 |
||
207 |
if self.active then |
|
208 |
result = result .. 'active, ' |
|
209 |
else |
|
210 |
result = result .. 'inactive, ' |
|
211 |
end |
|
212 |
||
213 |
if self.visible then |
|
214 |
result = result .. 'visible, ' |
|
215 |
else |
|
216 |
result = result .. 'invisible, ' |
|
217 |
end |
|
218 |
||
219 |
if self.solid then |
|
220 |
result = result .. 'solid' |
|
221 |
else |
|
222 |
result = result .. 'not solid' |
|
223 |
end |
|
224 |
||
225 |
return result .. ')' |
|
226 |
end |
|
227 |
} |