aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/CTextSceneNode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CTextSceneNode.cpp')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/CTextSceneNode.cpp471
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
14namespace irr
15{
16namespace scene
17{
18
19
20//! constructor
21CTextSceneNode::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
40CTextSceneNode::~CTextSceneNode()
41{
42 if (Font)
43 Font->drop();
44}
45
46void CTextSceneNode::OnRegisterSceneNode()
47{
48 if (IsVisible)
49 SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT);
50
51 ISceneNode::OnRegisterSceneNode();
52}
53
54//! renders the node.
55void 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
69const core::aabbox3d<f32>& CTextSceneNode::getBoundingBox() const
70{
71 return Box;
72}
73
74//! sets the text string
75void CTextSceneNode::setText(const wchar_t* text)
76{
77 Text = text;
78}
79
80
81//! sets the color of the text
82void CTextSceneNode::setTextColor(video::SColor color)
83{
84 Color = color;
85}
86
87
88//!--------------------------------- CBillboardTextSceneNode ----------------------------------------------
89
90
91//! constructor
92CBillboardTextSceneNode::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
143CBillboardTextSceneNode::~CBillboardTextSceneNode()
144{
145 if (Font)
146 Font->drop();
147
148 if (Mesh)
149 Mesh->drop();
150
151}
152
153
154//! sets the text string
155void 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
239void 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
326void CBillboardTextSceneNode::OnRegisterSceneNode()
327{
328 SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT);
329 ISceneNode::OnRegisterSceneNode();
330}
331
332
333//! render
334void 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
363const core::aabbox3d<f32>& CBillboardTextSceneNode::getBoundingBox() const
364{
365 return BBox;
366}
367
368
369//! sets the size of the billboard
370void 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
386video::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.
396u32 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
406const core::dimension2d<f32>& CBillboardTextSceneNode::getSize() const
407{
408 return Size;
409}
410
411
412//! sets the color of the text
413void 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
420void 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
440void 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
462void 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