/ld26

To get this branch, use:
bzr branch http://9ix.org/bzr/ld26
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
}