Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/render2D/element_2d.cc @ 5084

Last change on this file since 5084 was 5084, checked in by bensch, 19 years ago

orxonox/trunk: flush
i am going into the weekend now
@patrick: ther might be some strange behaviour, and i noticed, that the CD-engine is iterating more through the entities, than it should
I hope, this is just a minor bug, because it almost killed me in the process of developing
i do not exactly know if it is from the CD-engine, but it is producing different outputs when i start the game five times in a row

File size: 15.5 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14*/
15
16//#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_
17
18#include "element_2d.h"
19#include "render_2d.h"
20
21#include "graphics_engine.h"
22#include "p_node.h"
23#include "load_param.h"
24#include "tinyxml.h"
25#include "class_list.h"
26#include "list.h"
27
28using namespace std;
29
30
31/**
32 * standard constructor
33 * @todo this constructor is not jet implemented - do it
34*/
35Element2D::Element2D (Element2D* parent)
36{
37  this->init(parent);
38}
39
40/**
41 * standard deconstructor
42*/
43Element2D::~Element2D ()
44{
45  // delete what has to be deleted here
46  Render2D::getInstance()->unregisterElement2D(this);
47}
48
49
50/**
51 * initializes a Element2D
52 */
53void Element2D::init(Element2D* parent)
54{
55  this->setClassID(CL_ELEMENT_2D, "Element2D");
56
57  this->setVisibility(true);
58  this->setActiveness(true);
59  this->setPosition2D(0,0);
60  this->setAlignment(E2D_ALIGN_NONE);
61  this->layer = E2D_TOP;
62
63  this->setParentMode2D(E2D_PARENT_ALL);
64  this->children = new tList<Element2D>;
65  this->bRelCoorChanged = true;
66  this->bRelDirChanged = true;
67  if (parent == NULL)
68    this->parent = NULL;
69//  else
70  //  this->setParent2D(parent);
71
72  Render2D::getInstance()->registerElement2D(this);
73}
74
75/**
76 * Loads the Parameters of an Element2D from...
77 * @param root The XML-element to load from
78 */
79void Element2D::loadParams(const TiXmlElement* root)
80{
81  LoadParam<Element2D>(root, "alignment", this, &Element2D::setAlignment)
82      .describe("loads the alignment: (either: center, left, right or screen-center)");
83
84  LoadParam<Element2D>(root, "layer", this, &Element2D::setLayer)
85      .describe("loads the layer onto which to project: (either: top, medium, bottom, below-all)");
86
87  LoadParam<Element2D>(root, "bind-node", this, &Element2D::setBindNode)
88      .describe("sets a node, this 2D-Element should be shown upon (name of the node)");
89
90  LoadParam<Element2D>(root, "2d-position", this, &Element2D::setPosition2D)
91      .describe("the _relative_ position (away from alignment) this 2d-element shows");
92
93  LoadParam<Element2D>(root, "visibility", this, &Element2D::setVisibility)
94      .describe("if the Element is visible or not");
95}
96
97/**
98 * sets the alignment of the 2D-element in form of a String
99 * @param alignment the alignment @see loadParams
100*/
101void Element2D::setAlignment(const char* alignment)
102{
103  if (!strcmp(alignment, "center"))
104    this->setAlignment(E2D_ALIGN_CENTER);
105  else if (!strcmp(alignment, "left"))
106    this->setAlignment(E2D_ALIGN_LEFT);
107  else if (!strcmp(alignment, "right"))
108    this->setAlignment(E2D_ALIGN_RIGHT);
109  else if (!strcmp(alignment, "screen-center"))
110    this->setAlignment(E2D_ALIGN_SCREEN_CENTER);
111}
112
113
114/**
115 * moves a Element to another layer
116 * @param layer the Layer this is drawn on
117 */
118void Element2D::setLayer(E2D_LAYER layer)
119{
120  Render2D::getInstance()->moveToLayer(this, layer);
121  this->layer = layer;
122}
123
124/**
125 * sets the layer onto which this 2D-element is projected to.
126 * @param layer the layer @see loadParams
127 */
128void Element2D::setLayer(const char* layer)
129{
130  if (!strcmp(layer, "top"))
131    this->setLayer(E2D_TOP);
132  else if (!strcmp(layer, "medium"))
133    this->setLayer(E2D_MEDIUM);
134  else if (!strcmp(layer, "bottom"))
135    this->setLayer(E2D_BOTTOM);
136  else if (!strcmp(layer, "below-all"))
137    this->setLayer(E2D_BELOW_ALL);
138}
139
140
141/**
142 * sets a node, this 2D-Element should be shown upon
143 * @param bindNode the name of the Node (should be existing)
144 */
145void Element2D::setBindNode(const char* bindNode)
146{
147  const PNode* tmpBindNode = dynamic_cast<const PNode*>(ClassList::getObject(bindNode, CL_PARENT_NODE));
148  if (tmpBindNode != NULL)
149    this->bindNode = tmpBindNode;
150}
151
152/**
153 * this sets the position of the Element on the screen.
154 * Use this in the your tick function, if you want the element to be automatically positioned.
155 *
156 * @todo must be in update
157 */
158void Element2D::positioning()
159{
160  // setting the Position of this 2D-Element.
161  if (this->alignment == E2D_ALIGN_SCREEN_CENTER)
162  {
163    absPos2D.x = GraphicsEngine::getInstance()->getResolutionX()/2 + this->relPos2D[0];
164    absPos2D.y = GraphicsEngine::getInstance()->getResolutionY()/2 + this->relPos2D[1];
165    absPos2D.depth = 0;
166  }
167  else if (this->bindNode)
168  {
169    GLdouble projectPos[3];
170    gluProject(this->bindNode->getAbsCoor().x,
171               this->bindNode->getAbsCoor().y,
172               this->bindNode->getAbsCoor().z,
173               GraphicsEngine::modMat,
174               GraphicsEngine::projMat,
175               GraphicsEngine::viewPort,
176               projectPos,
177               projectPos+1,
178               projectPos+2);
179    absPos2D.x = projectPos[0] + this->relPos2D[0];
180    absPos2D.y = GraphicsEngine::getInstance()->getResolutionY() - projectPos[1] + this->relPos2D[1];
181    absPos2D.depth = projectPos[2];
182  }
183  else
184  {
185    absPos2D.x = this->relPos2D[0];
186    absPos2D.y = this->relPos2D[1];
187    absPos2D.depth = 0;
188  }
189}
190
191
192void Element2D::setRelCoor2D (const Vector& relCoord)
193{
194  this->relCoordinate = relCoord;
195  this->bRelCoorChanged = true;
196}
197
198
199void Element2D::setRelCoor2D (float x, float y, float z)
200{
201  this->setAbsCoor2D(Vector(x,y,z));
202}
203
204void Element2D::setRelCoorSoft2D(const Vector& relCoordSoft, float bias)
205{
206  if (likely(this->toCoordinate == NULL))
207    this->toCoordinate = new Vector();
208
209  *this->toCoordinate = relCoordSoft;
210  this->bias = bias;
211}
212
213void Element2D::setRelCoorSoft2D(float x, float y, float depth, float bias)
214{
215  this->setRelCoorSoft2D(Vector(x, y, depth), bias);
216}
217
218void Element2D::setAbsCoor2D (const Vector& absCoord)
219{
220  if( likely(this->parentMode & E2D_PARENT_MOVEMENT))
221  {
222    /* if you have set the absolute coordinates this overrides all other changes */
223    if (likely(this->parent != NULL))
224      this->relCoordinate = absCoord - parent->getAbsCoor2D ();
225    else
226      this->relCoordinate = absCoord;
227  }
228  if( this->parentMode & E2D_PARENT_ROTATE_MOVEMENT)
229  {
230    if (likely(this->parent != NULL))
231      this->relCoordinate = absCoord - parent->getAbsCoor2D ();
232    else
233      this->relCoordinate = absCoord;
234  }
235
236  this->bRelCoorChanged = true;
237}
238
239void Element2D::setAbsCoor2D (float x, float y, float depth)
240{
241  this->setAbsCoor2D(Vector(x, y, depth));
242}
243
244void Element2D::shiftCoor2D (const Vector& shift)
245{
246  this->relCoordinate += shift;
247  this->bRelCoorChanged = true;
248
249}
250
251
252void Element2D::setRelDir2D (float relDir)
253{
254  this->relDirection = relDir;
255  this->bRelDirChanged = true;
256}
257
258void Element2D::setRelDirSoft2D(float relDirSoft, float bias)
259{
260  if (likely(this->toDirection == NULL))
261    this->toDirection = new float;
262
263  *this->toDirection = relDirSoft;
264  this->bias = bias;
265}
266
267void Element2D::setAbsDir2D (float absDir)
268{
269  if (likely(this->parent != NULL))
270    this->relDirection = absDir - this->parent->getAbsDir2D();
271  else
272    this->relDirection = absDir;
273
274  this->bRelDirChanged = true;
275}
276
277void Element2D::shiftDir2D (float shiftDir)
278{
279  this->relDirection = this->relDirection + shiftDir;
280  this->bRelDirChanged = true;
281}
282
283
284void Element2D::addChild2D (Element2D* child, int parentingMod)
285{
286  if( likely(child->parent != NULL))
287  {
288    PRINTF(4)("Element2D::addChild() - reparenting node: removing it and adding it again\n");
289    child->parent->children->remove(child);
290  }
291  child->parentMode = parentMode;
292  child->parent = this;
293  this->children->add(child);
294  child->parentCoorChanged();
295}
296
297void Element2D::addChild2D (const char* childName)
298{
299  Element2D* childNode = dynamic_cast<Element2D*>(ClassList::getObject(childName, CL_ELEMENT_2D));
300  if (childNode != NULL)
301    this->addChild2D(childNode);
302}
303
304void Element2D::removeChild2D (Element2D* child)
305{
306  child->remove2D();
307  this->children->remove(child);
308  child->parent = NULL;
309}
310
311void Element2D::remove2D()
312{
313  tIterator<Element2D>* iterator = this->children->getIterator();
314  Element2D* pn = iterator->nextElement();
315
316  while( pn != NULL)
317  {
318    NullElement2D::getInstance()->addChild2D(pn, pn->getParentMode2D());
319    pn = iterator->nextElement();
320  }
321  delete iterator;
322  this->parent->children->remove(this);
323}
324
325
326void Element2D::setParent2D (Element2D* parent)
327{
328  parent->addChild2D(this);
329}
330
331void Element2D::setParent2D (const char* parentName)
332{
333  Element2D* parentNode = dynamic_cast<Element2D*>(ClassList::getObject(parentName, CL_ELEMENT_2D));
334  if (parentNode != NULL)
335    parentNode->addChild2D(this);
336
337}
338
339
340void Element2D::softReparent2D(Element2D* parentNode, float bias)
341{
342  if (this->parent == parentNode)
343    return;
344
345  if (likely(this->toCoordinate == NULL))
346  {
347    this->toCoordinate = new Vector();
348    *this->toCoordinate = this->getRelCoor2D();
349  }
350  if (likely(this->toDirection == NULL))
351  {
352    this->toDirection = new float;
353    *this->toDirection = this->getRelDir2D();
354  }
355  this->bias = bias;
356
357
358  Vector tmpV = this->getAbsCoor2D();
359  float tmpQ = this->getAbsDir2D();
360
361  parentNode->addChild2D(this);
362
363  if (this->parentMode & PNODE_ROTATE_MOVEMENT)
364    ;//this->setRelCoor(this->parent->getAbsDir().inverse().apply(tmpV - this->parent->getAbsCoor()));
365  else
366    this->setRelCoor2D(tmpV - parentNode->getAbsCoor2D());
367
368  this->setRelDir2D(tmpQ - parentNode->getAbsDir2D());
369}
370
371void Element2D::softReparent2D(const char* parentName, float bias)
372{
373  Element2D* parentNode = dynamic_cast<Element2D*>(ClassList::getObject(parentName, CL_ELEMENT_2D));
374  if (parentNode != NULL)
375    this->softReparent2D(parentNode, bias);
376}
377
378
379void Element2D::setParentMode2D (const char* parentingMode)
380{
381  this->setParentMode2D(Element2D::charToParentingMode2D(parentingMode));
382}
383
384
385void Element2D::update2D (float dt)
386{
387  if( likely(this->parent != NULL))
388  {
389      // movement for nodes with smoothMove enabled
390    if (unlikely(this->toCoordinate != NULL))
391    {
392      Vector moveVect = (*this->toCoordinate - this->getRelCoor2D()) *dt*bias;
393
394      if (likely(moveVect.len() >= .001))//PNODE_ITERATION_DELTA))
395      {
396        this->shiftCoor2D(moveVect);
397      }
398      else
399      {
400        delete this->toCoordinate;
401        this->toCoordinate = NULL;
402        PRINTF(5)("SmoothMove of %s finished\n", this->getName());
403      }
404    }
405    if (unlikely(this->toDirection != NULL))
406    {
407      float rotFlot = (*this->toDirection - this->getRelDir2D()) *dt*bias;
408      if (likely(rotFlot >= .001))//PNODE_ITERATION_DELTA))
409      {
410        this->shiftDir2D(rotFlot);
411      }
412      else
413      {
414        delete this->toDirection;
415        this->toDirection = NULL;
416        PRINTF(5)("SmoothRotate of %s finished\n", this->getName());
417      }
418    }
419
420    // MAIN UPDATE /////////////////////////////////////
421    this->lastAbsCoordinate = this->absCoordinate;
422
423    PRINTF(5)("Element2D::update - %s - (%f, %f, %f)\n", this->getName(), this->absCoordinate.x, this->absCoordinate.y, this->absCoordinate.z);
424
425
426    if( this->parentMode & PNODE_LOCAL_ROTATE && this->bRelDirChanged)
427    {
428      /* update the current absDirection - remember * means rotation around sth.*/
429      this->prevRelCoordinate = this->relCoordinate;
430      this->absDirection = this->relDirection + parent->getAbsDir2D();;
431    }
432
433    if(likely(this->parentMode & PNODE_MOVEMENT))
434    {
435      /* update the current absCoordinate */
436      this->prevRelCoordinate = this->relCoordinate;
437      this->absCoordinate = this->parent->getAbsCoor2D() + this->relCoordinate;
438    }
439    else if( this->parentMode & PNODE_ROTATE_MOVEMENT)
440    {
441      /* update the current absCoordinate */
442      this->prevRelCoordinate = this->relCoordinate;
443      this->absCoordinate.x = this->parent->getAbsCoor2D().x + (this->relCoordinate.x*cos(this->parent->getAbsDir2D()) - this->relCoordinate.y * sin(this->parent->getAbsDir2D()));
444      this->absCoordinate.y = this->parent->getAbsCoor2D().y + (this->relCoordinate.x*sin(this->parent->getAbsDir2D()) + this->relCoordinate.y * cos(this->parent->getAbsDir2D()));
445
446    }
447    /////////////////////////////////////////////////
448  }
449  else
450  {
451    PRINTF(5)("Element2D::update - (%f, %f, %f)\n", this->absCoordinate.x, this->absCoordinate.y, this->absCoordinate.z);
452    if (this->bRelCoorChanged)
453      this->absCoordinate = this->relCoordinate;
454    if (this->bRelDirChanged)
455      this->absDirection = this->getAbsDir2D() * this->relDirection;
456  }
457
458  if(this->children->getSize() > 0)
459  {
460    tIterator<Element2D>* iterator = this->children->getIterator();
461    Element2D* pn = iterator->nextElement();
462    while( pn != NULL)
463    {
464      /* if this node has changed, make sure, that all children are updated also */
465      if( likely(this->bRelCoorChanged))
466        pn->parentCoorChanged ();
467      if( likely(this->bRelDirChanged))
468        pn->parentDirChanged ();
469
470      pn->update2D(dt);
471          //pn = this->children->nextElement();
472      pn = iterator->nextElement();
473    }
474    delete iterator;
475  }
476  this->velocity = (this->absCoordinate - this->lastAbsCoordinate) / dt;
477  this->bRelCoorChanged = false;
478  this->bRelDirChanged = false;
479}
480
481
482void Element2D::debug (unsigned int depth, unsigned int level) const
483{
484  for (unsigned int i = 0; i < level; i++)
485    PRINT(0)(" |");
486  if (this->children->getSize() > 0)
487    PRINT(0)(" +");
488  else
489    PRINT(0)(" -");
490  PRINT(0)("Element2D(%s::%s) - absCoord: (%0.2f, %0.2f), relCoord(%0.2f, %0.2f), direction(%0.2f) - %s\n",
491  this->getClassName(),
492  this->getName(),
493  this->absCoordinate.x,
494  this->absCoordinate.y,
495  this->relCoordinate.x,
496  this->relCoordinate.y,
497  this->getAbsDir2D(),
498  Element2D::parentingModeToChar2D(parentMode));
499  if (depth >= 2 || depth == 0)
500  {
501    tIterator<Element2D>* iterator = this->children->getIterator();
502      //PNode* pn = this->children->enumerate ();
503    Element2D* pn = iterator->nextElement();
504    while( pn != NULL)
505    {
506      if (depth == 0)
507        pn->debug(0, level + 1);
508      else
509        pn->debug(depth - 1, level +1);
510      pn = iterator->nextElement();
511    }
512    delete iterator;
513  }
514}
515
516#include "color.h"
517
518void Element2D::debugDraw2D(unsigned int depth, float size, Vector color) const
519{
520
521}
522
523
524// helper functions //
525const char* Element2D::parentingModeToChar2D(int parentingMode)
526{
527  if (parentingMode == E2D_PARENT_LOCAL_ROTATE)
528    return "local-rotate";
529  else if (parentingMode == E2D_PARENT_ROTATE_MOVEMENT)
530    return "rotate-movement";
531  else if (parentingMode == E2D_PARENT_MOVEMENT)
532    return "movement";
533  else if (parentingMode == E2D_PARENT_ALL)
534    return "all";
535  else if (parentingMode == E2D_PARENT_ROTATE_AND_MOVE)
536    return "rotate-and-move";
537}
538
539E2D_PARENT_MODE Element2D::charToParentingMode2D(const char* parentingMode)
540{
541  if (!strcmp(parentingMode, "local-rotate"))
542    return (E2D_PARENT_LOCAL_ROTATE);
543  else  if (!strcmp(parentingMode, "rotate-movement"))
544    return (E2D_PARENT_ROTATE_MOVEMENT);
545  else  if (!strcmp(parentingMode, "movement"))
546    return (E2D_PARENT_MOVEMENT);
547  else  if (!strcmp(parentingMode, "all"))
548    return (E2D_PARENT_ALL);
549  else  if (!strcmp(parentingMode, "rotate-and-move"))
550    return (E2D_PARENT_ROTATE_AND_MOVE);
551}
552
553
554
555
556
557
558/**
559 * ticks the 2d-Element
560 * @param dt the time elapsed since the last tick
561 */
562void Element2D::tick(float dt)
563{
564  this->positioning();
565}
566
567
568
569
570
571
572
573NullElement2D* NullElement2D::singletonRef = 0;
574
575/**
576 *  creates the one and only NullElement2D
577 * @param absCoordinate the cordinate of the Parent (normally Vector(0,0,0))
578 */
579NullElement2D::NullElement2D ()
580{
581  this->setClassID(CL_NULL_PARENT, "NullElement2D");
582  this->setName("NullElement2D");
583
584  this->setParentMode2D(E2D_PARENT_ALL);
585  NullElement2D::singletonRef = this;
586}
587
588
589/**
590 *  standard deconstructor
591 */
592NullElement2D::~NullElement2D ()
593{
594  //delete singletonRef;
595  NullElement2D::singletonRef = NULL;
596}
Note: See TracBrowser for help on using the repository browser.