diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CTextSceneNode.cpp')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CTextSceneNode.cpp | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CTextSceneNode.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CTextSceneNode.cpp new file mode 100644 index 0000000..7edf2f5 --- /dev/null +++ b/libraries/irrlicht-1.8/source/Irrlicht/CTextSceneNode.cpp | |||
@@ -0,0 +1,471 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | ||
2 | // This file is part of the "Irrlicht Engine". | ||
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | ||
4 | |||
5 | #include "CTextSceneNode.h" | ||
6 | #include "ISceneManager.h" | ||
7 | #include "IVideoDriver.h" | ||
8 | #include "ICameraSceneNode.h" | ||
9 | #include "IGUISpriteBank.h" | ||
10 | #include "SMeshBuffer.h" | ||
11 | #include "os.h" | ||
12 | |||
13 | |||
14 | namespace irr | ||
15 | { | ||
16 | namespace scene | ||
17 | { | ||
18 | |||
19 | |||
20 | //! constructor | ||
21 | CTextSceneNode::CTextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, | ||
22 | gui::IGUIFont* font, scene::ISceneCollisionManager* coll, | ||
23 | const core::vector3df& position, const wchar_t* text, | ||
24 | video::SColor color) | ||
25 | : ITextSceneNode(parent, mgr, id, position), Text(text), Color(color), | ||
26 | Font(font), Coll(coll) | ||
27 | |||
28 | { | ||
29 | #ifdef _DEBUG | ||
30 | setDebugName("CTextSceneNode"); | ||
31 | #endif | ||
32 | |||
33 | if (Font) | ||
34 | Font->grab(); | ||
35 | |||
36 | setAutomaticCulling(scene::EAC_OFF); | ||
37 | } | ||
38 | |||
39 | //! destructor | ||
40 | CTextSceneNode::~CTextSceneNode() | ||
41 | { | ||
42 | if (Font) | ||
43 | Font->drop(); | ||
44 | } | ||
45 | |||
46 | void CTextSceneNode::OnRegisterSceneNode() | ||
47 | { | ||
48 | if (IsVisible) | ||
49 | SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT); | ||
50 | |||
51 | ISceneNode::OnRegisterSceneNode(); | ||
52 | } | ||
53 | |||
54 | //! renders the node. | ||
55 | void CTextSceneNode::render() | ||
56 | { | ||
57 | if (!Font || !Coll) | ||
58 | return; | ||
59 | |||
60 | core::position2d<s32> pos = Coll->getScreenCoordinatesFrom3DPosition(getAbsolutePosition(), | ||
61 | SceneManager->getActiveCamera()); | ||
62 | |||
63 | core::rect<s32> r(pos, core::dimension2d<s32>(1,1)); | ||
64 | Font->draw(Text.c_str(), r, Color, true, true); | ||
65 | } | ||
66 | |||
67 | |||
68 | //! returns the axis aligned bounding box of this node | ||
69 | const core::aabbox3d<f32>& CTextSceneNode::getBoundingBox() const | ||
70 | { | ||
71 | return Box; | ||
72 | } | ||
73 | |||
74 | //! sets the text string | ||
75 | void CTextSceneNode::setText(const wchar_t* text) | ||
76 | { | ||
77 | Text = text; | ||
78 | } | ||
79 | |||
80 | |||
81 | //! sets the color of the text | ||
82 | void CTextSceneNode::setTextColor(video::SColor color) | ||
83 | { | ||
84 | Color = color; | ||
85 | } | ||
86 | |||
87 | |||
88 | //!--------------------------------- CBillboardTextSceneNode ---------------------------------------------- | ||
89 | |||
90 | |||
91 | //! constructor | ||
92 | CBillboardTextSceneNode::CBillboardTextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, | ||
93 | gui::IGUIFont* font,const wchar_t* text, | ||
94 | const core::vector3df& position, const core::dimension2d<f32>& size, | ||
95 | video::SColor colorTop,video::SColor shade_bottom ) | ||
96 | : IBillboardTextSceneNode(parent, mgr, id, position), | ||
97 | Font(0), ColorTop(colorTop), ColorBottom(shade_bottom), Mesh(0) | ||
98 | { | ||
99 | #ifdef _DEBUG | ||
100 | setDebugName("CBillboardTextSceneNode"); | ||
101 | #endif | ||
102 | |||
103 | Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; | ||
104 | Material.MaterialTypeParam = 1.f / 255.f; | ||
105 | Material.BackfaceCulling = false; | ||
106 | Material.Lighting = false; | ||
107 | Material.ZBuffer = video::ECFN_LESSEQUAL; | ||
108 | Material.ZWriteEnable = false; | ||
109 | |||
110 | if (font) | ||
111 | { | ||
112 | // doesn't support other font types | ||
113 | if (font->getType() == gui::EGFT_BITMAP) | ||
114 | { | ||
115 | Font = (gui::IGUIFontBitmap*)font; | ||
116 | Font->grab(); | ||
117 | |||
118 | // mesh with one buffer per texture | ||
119 | Mesh = new SMesh(); | ||
120 | for (u32 i=0; i<Font->getSpriteBank()->getTextureCount(); ++i) | ||
121 | { | ||
122 | SMeshBuffer *mb = new SMeshBuffer(); | ||
123 | mb->Material = Material; | ||
124 | mb->Material.setTexture(0, Font->getSpriteBank()->getTexture(i)); | ||
125 | Mesh->addMeshBuffer(mb); | ||
126 | mb->drop(); | ||
127 | } | ||
128 | } | ||
129 | else | ||
130 | { | ||
131 | os::Printer::log("Sorry, CBillboardTextSceneNode does not support this font type", ELL_INFORMATION); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | setText(text); | ||
136 | setSize(size); | ||
137 | |||
138 | setAutomaticCulling ( scene::EAC_BOX ); | ||
139 | } | ||
140 | |||
141 | |||
142 | |||
143 | CBillboardTextSceneNode::~CBillboardTextSceneNode() | ||
144 | { | ||
145 | if (Font) | ||
146 | Font->drop(); | ||
147 | |||
148 | if (Mesh) | ||
149 | Mesh->drop(); | ||
150 | |||
151 | } | ||
152 | |||
153 | |||
154 | //! sets the text string | ||
155 | void CBillboardTextSceneNode::setText(const wchar_t* text) | ||
156 | { | ||
157 | if ( !Mesh ) | ||
158 | return; | ||
159 | |||
160 | Text = text; | ||
161 | |||
162 | Symbol.clear(); | ||
163 | |||
164 | // clear mesh | ||
165 | for (u32 j=0; j < Mesh->getMeshBufferCount(); ++j) | ||
166 | { | ||
167 | ((SMeshBuffer*)Mesh->getMeshBuffer(j))->Indices.clear(); | ||
168 | ((SMeshBuffer*)Mesh->getMeshBuffer(j))->Vertices.clear(); | ||
169 | } | ||
170 | |||
171 | if (!Font) | ||
172 | return; | ||
173 | |||
174 | const core::array< core::rect<s32> > &sourceRects = Font->getSpriteBank()->getPositions(); | ||
175 | const core::array< gui::SGUISprite > &sprites = Font->getSpriteBank()->getSprites(); | ||
176 | |||
177 | f32 dim[2]; | ||
178 | f32 tex[4]; | ||
179 | |||
180 | u32 i; | ||
181 | for ( i = 0; i != Text.size (); ++i ) | ||
182 | { | ||
183 | SSymbolInfo info; | ||
184 | |||
185 | u32 spriteno = Font->getSpriteNoFromChar( &text[i] ); | ||
186 | u32 rectno = sprites[spriteno].Frames[0].rectNumber; | ||
187 | u32 texno = sprites[spriteno].Frames[0].textureNumber; | ||
188 | |||
189 | dim[0] = core::reciprocal ( (f32) Font->getSpriteBank()->getTexture(texno)->getSize().Width ); | ||
190 | dim[1] = core::reciprocal ( (f32) Font->getSpriteBank()->getTexture(texno)->getSize().Height ); | ||
191 | |||
192 | const core::rect<s32>& s = sourceRects[rectno]; | ||
193 | |||
194 | // add space for letter to buffer | ||
195 | SMeshBuffer* buf = (SMeshBuffer*)Mesh->getMeshBuffer(texno); | ||
196 | u32 firstInd = buf->Indices.size(); | ||
197 | u32 firstVert = buf->Vertices.size(); | ||
198 | buf->Indices.set_used(firstInd + 6); | ||
199 | buf->Vertices.set_used(firstVert + 4); | ||
200 | |||
201 | tex[0] = (s.LowerRightCorner.X * dim[0]) + 0.5f*dim[0]; // half pixel | ||
202 | tex[1] = (s.LowerRightCorner.Y * dim[1]) + 0.5f*dim[1]; | ||
203 | tex[2] = (s.UpperLeftCorner.Y * dim[1]) - 0.5f*dim[1]; | ||
204 | tex[3] = (s.UpperLeftCorner.X * dim[0]) - 0.5f*dim[0]; | ||
205 | |||
206 | buf->Vertices[firstVert+0].TCoords.set(tex[0], tex[1]); | ||
207 | buf->Vertices[firstVert+1].TCoords.set(tex[0], tex[2]); | ||
208 | buf->Vertices[firstVert+2].TCoords.set(tex[3], tex[2]); | ||
209 | buf->Vertices[firstVert+3].TCoords.set(tex[3], tex[1]); | ||
210 | |||
211 | buf->Vertices[firstVert+0].Color = ColorBottom; | ||
212 | buf->Vertices[firstVert+3].Color = ColorBottom; | ||
213 | buf->Vertices[firstVert+1].Color = ColorTop; | ||
214 | buf->Vertices[firstVert+2].Color = ColorTop; | ||
215 | |||
216 | buf->Indices[firstInd+0] = (u16)firstVert+0; | ||
217 | buf->Indices[firstInd+1] = (u16)firstVert+2; | ||
218 | buf->Indices[firstInd+2] = (u16)firstVert+1; | ||
219 | buf->Indices[firstInd+3] = (u16)firstVert+0; | ||
220 | buf->Indices[firstInd+4] = (u16)firstVert+3; | ||
221 | buf->Indices[firstInd+5] = (u16)firstVert+2; | ||
222 | |||
223 | wchar_t *tp = 0; | ||
224 | if (i>0) | ||
225 | tp = &Text[i-1]; | ||
226 | |||
227 | info.Width = (f32)s.getWidth(); | ||
228 | info.bufNo = texno; | ||
229 | info.Kerning = (f32)Font->getKerningWidth(&Text[i], tp); | ||
230 | info.firstInd = firstInd; | ||
231 | info.firstVert = firstVert; | ||
232 | |||
233 | Symbol.push_back(info); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | |||
238 | //! pre render event | ||
239 | void CBillboardTextSceneNode::OnAnimate(u32 timeMs) | ||
240 | { | ||
241 | ISceneNode::OnAnimate(timeMs); | ||
242 | |||
243 | if (!IsVisible || !Font || !Mesh) | ||
244 | return; | ||
245 | |||
246 | ICameraSceneNode* camera = SceneManager->getActiveCamera(); | ||
247 | if (!camera) | ||
248 | return; | ||
249 | |||
250 | // get text width | ||
251 | f32 textLength = 0.f; | ||
252 | u32 i; | ||
253 | for(i=0; i!=Symbol.size(); ++i) | ||
254 | { | ||
255 | SSymbolInfo &info = Symbol[i]; | ||
256 | textLength += info.Kerning + info.Width; | ||
257 | } | ||
258 | if (textLength<0.0f) | ||
259 | textLength=1.0f; | ||
260 | |||
261 | //const core::matrix4 &m = camera->getViewFrustum()->Matrices[ video::ETS_VIEW ]; | ||
262 | |||
263 | // make billboard look to camera | ||
264 | core::vector3df pos = getAbsolutePosition(); | ||
265 | |||
266 | core::vector3df campos = camera->getAbsolutePosition(); | ||
267 | core::vector3df target = camera->getTarget(); | ||
268 | core::vector3df up = camera->getUpVector(); | ||
269 | core::vector3df view = target - campos; | ||
270 | view.normalize(); | ||
271 | |||
272 | core::vector3df horizontal = up.crossProduct(view); | ||
273 | if ( horizontal.getLength() == 0 ) | ||
274 | { | ||
275 | horizontal.set(up.Y,up.X,up.Z); | ||
276 | } | ||
277 | |||
278 | horizontal.normalize(); | ||
279 | core::vector3df space = horizontal; | ||
280 | |||
281 | horizontal *= 0.5f * Size.Width; | ||
282 | |||
283 | core::vector3df vertical = horizontal.crossProduct(view); | ||
284 | vertical.normalize(); | ||
285 | vertical *= 0.5f * Size.Height; | ||
286 | |||
287 | view *= -1.0f; | ||
288 | |||
289 | // center text | ||
290 | pos += space * (Size.Width * -0.5f); | ||
291 | |||
292 | for ( i = 0; i!= Symbol.size(); ++i ) | ||
293 | { | ||
294 | SSymbolInfo &info = Symbol[i]; | ||
295 | f32 infw = info.Width / textLength; | ||
296 | f32 infk = info.Kerning / textLength; | ||
297 | f32 w = (Size.Width * infw * 0.5f); | ||
298 | pos += space * w; | ||
299 | |||
300 | SMeshBuffer* buf = (SMeshBuffer*)Mesh->getMeshBuffer(info.bufNo); | ||
301 | |||
302 | buf->Vertices[info.firstVert+0].Normal = view; | ||
303 | buf->Vertices[info.firstVert+1].Normal = view; | ||
304 | buf->Vertices[info.firstVert+2].Normal = view; | ||
305 | buf->Vertices[info.firstVert+3].Normal = view; | ||
306 | |||
307 | buf->Vertices[info.firstVert+0].Pos = pos + (space * w) + vertical; | ||
308 | buf->Vertices[info.firstVert+1].Pos = pos + (space * w) - vertical; | ||
309 | buf->Vertices[info.firstVert+2].Pos = pos - (space * w) - vertical; | ||
310 | buf->Vertices[info.firstVert+3].Pos = pos - (space * w) + vertical; | ||
311 | |||
312 | pos += space * (Size.Width*infk + w); | ||
313 | } | ||
314 | |||
315 | // make bounding box | ||
316 | |||
317 | for (i=0; i< Mesh->getMeshBufferCount() ; ++i) | ||
318 | Mesh->getMeshBuffer(i)->recalculateBoundingBox(); | ||
319 | Mesh->recalculateBoundingBox(); | ||
320 | |||
321 | BBox = Mesh->getBoundingBox(); | ||
322 | core::matrix4 mat( getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE ); | ||
323 | mat.transformBoxEx(BBox); | ||
324 | } | ||
325 | |||
326 | void CBillboardTextSceneNode::OnRegisterSceneNode() | ||
327 | { | ||
328 | SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT); | ||
329 | ISceneNode::OnRegisterSceneNode(); | ||
330 | } | ||
331 | |||
332 | |||
333 | //! render | ||
334 | void CBillboardTextSceneNode::render() | ||
335 | { | ||
336 | if ( !Mesh ) | ||
337 | return; | ||
338 | |||
339 | video::IVideoDriver* driver = SceneManager->getVideoDriver(); | ||
340 | |||
341 | // draw | ||
342 | core::matrix4 mat; | ||
343 | driver->setTransform(video::ETS_WORLD, mat); | ||
344 | |||
345 | for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) | ||
346 | { | ||
347 | driver->setMaterial(Mesh->getMeshBuffer(i)->getMaterial()); | ||
348 | driver->drawMeshBuffer(Mesh->getMeshBuffer(i)); | ||
349 | } | ||
350 | |||
351 | if ( DebugDataVisible & scene::EDS_BBOX ) | ||
352 | { | ||
353 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); | ||
354 | video::SMaterial m; | ||
355 | m.Lighting = false; | ||
356 | driver->setMaterial(m); | ||
357 | driver->draw3DBox(BBox, video::SColor(0,208,195,152)); | ||
358 | } | ||
359 | } | ||
360 | |||
361 | |||
362 | //! returns the axis aligned bounding box of this node | ||
363 | const core::aabbox3d<f32>& CBillboardTextSceneNode::getBoundingBox() const | ||
364 | { | ||
365 | return BBox; | ||
366 | } | ||
367 | |||
368 | |||
369 | //! sets the size of the billboard | ||
370 | void CBillboardTextSceneNode::setSize(const core::dimension2d<f32>& size) | ||
371 | { | ||
372 | Size = size; | ||
373 | |||
374 | if (Size.Width == 0.0f) | ||
375 | Size.Width = 1.0f; | ||
376 | |||
377 | if (Size.Height == 0.0f ) | ||
378 | Size.Height = 1.0f; | ||
379 | |||
380 | //f32 avg = (size.Width + size.Height)/6; | ||
381 | //BBox.MinEdge.set(-avg,-avg,-avg); | ||
382 | //BBox.MaxEdge.set(avg,avg,avg); | ||
383 | } | ||
384 | |||
385 | |||
386 | video::SMaterial& CBillboardTextSceneNode::getMaterial(u32 i) | ||
387 | { | ||
388 | if (Mesh && Mesh->getMeshBufferCount() > i ) | ||
389 | return Mesh->getMeshBuffer(i)->getMaterial(); | ||
390 | else | ||
391 | return Material; | ||
392 | } | ||
393 | |||
394 | |||
395 | //! returns amount of materials used by this scene node. | ||
396 | u32 CBillboardTextSceneNode::getMaterialCount() const | ||
397 | { | ||
398 | if (Mesh) | ||
399 | return Mesh->getMeshBufferCount(); | ||
400 | else | ||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | |||
405 | //! gets the size of the billboard | ||
406 | const core::dimension2d<f32>& CBillboardTextSceneNode::getSize() const | ||
407 | { | ||
408 | return Size; | ||
409 | } | ||
410 | |||
411 | |||
412 | //! sets the color of the text | ||
413 | void CBillboardTextSceneNode::setTextColor(video::SColor color) | ||
414 | { | ||
415 | Color = color; | ||
416 | } | ||
417 | |||
418 | //! Set the color of all vertices of the billboard | ||
419 | //! \param overallColor: the color to set | ||
420 | void CBillboardTextSceneNode::setColor(const video::SColor & overallColor) | ||
421 | { | ||
422 | if ( !Mesh ) | ||
423 | return; | ||
424 | |||
425 | for ( u32 i = 0; i != Text.size (); ++i ) | ||
426 | { | ||
427 | const SSymbolInfo &info = Symbol[i]; | ||
428 | SMeshBuffer* buf = (SMeshBuffer*)Mesh->getMeshBuffer(info.bufNo); | ||
429 | buf->Vertices[info.firstVert+0].Color = overallColor; | ||
430 | buf->Vertices[info.firstVert+1].Color = overallColor; | ||
431 | buf->Vertices[info.firstVert+2].Color = overallColor; | ||
432 | buf->Vertices[info.firstVert+3].Color = overallColor; | ||
433 | } | ||
434 | } | ||
435 | |||
436 | |||
437 | //! Set the color of the top and bottom vertices of the billboard | ||
438 | //! \param topColor: the color to set the top vertices | ||
439 | //! \param bottomColor: the color to set the bottom vertices | ||
440 | void CBillboardTextSceneNode::setColor(const video::SColor & topColor, const video::SColor & bottomColor) | ||
441 | { | ||
442 | if ( !Mesh ) | ||
443 | return; | ||
444 | |||
445 | ColorBottom = bottomColor; | ||
446 | ColorTop = topColor; | ||
447 | for ( u32 i = 0; i != Text.size (); ++i ) | ||
448 | { | ||
449 | const SSymbolInfo &info = Symbol[i]; | ||
450 | SMeshBuffer* buf = (SMeshBuffer*)Mesh->getMeshBuffer(info.bufNo); | ||
451 | buf->Vertices[info.firstVert+0].Color = ColorBottom; | ||
452 | buf->Vertices[info.firstVert+3].Color = ColorBottom; | ||
453 | buf->Vertices[info.firstVert+1].Color = ColorTop; | ||
454 | buf->Vertices[info.firstVert+2].Color = ColorTop; | ||
455 | } | ||
456 | } | ||
457 | |||
458 | |||
459 | //! Gets the color of the top and bottom vertices of the billboard | ||
460 | //! \param topColor: stores the color of the top vertices | ||
461 | //! \param bottomColor: stores the color of the bottom vertices | ||
462 | void CBillboardTextSceneNode::getColor(video::SColor & topColor, video::SColor & bottomColor) const | ||
463 | { | ||
464 | topColor = ColorTop; | ||
465 | bottomColor = ColorBottom; | ||
466 | } | ||
467 | |||
468 | |||
469 | } // end namespace scene | ||
470 | } // end namespace irr | ||
471 | |||