Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7031 was 7031, checked in by bensch, 18 years ago

softed stuff

File size: 33.3 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 <algorithm>
22
23#include "p_node.h"
24
25#include "graphics_engine.h"
26#include "load_param.h"
27#include "class_list.h"
28
29#include "color.h"
30
31using namespace std;
32
33/**
34 * @brief standard constructor
35 * @param parent the parent to set for this Element2D
36 *
37 * NullElement2D needs this constructor with parameter NULL to initialize
38 * itself. Otherwise it would result in an endless Loop.
39 */
40Element2D::Element2D (Element2D* parent, E2D_LAYER layer, short nodeFlags)
41{
42  this->setClassID(CL_ELEMENT_2D, "Element2D");
43
44  this->setVisibility(true);
45  this->activate2D();
46  this->setAlignment(E2D_ALIGN_NONE);
47  this->bindNode = NULL;
48
49  this->parentMode = nodeFlags;
50  this->parent = NULL;
51  this->absDirection = 0.0;
52  this->relDirection = 0.0;
53  this->bRelCoorChanged = true;
54  this->bRelDirChanged = true;
55  this->toCoordinate = NULL;
56  this->toDirection = NULL;
57  this->toSize = NULL;
58  this->setSize2D(1, 1);
59
60
61  this->layer = layer;
62  if (parent != NULL)
63    parent->addChild2D(this);
64}
65
66
67/**
68 * @brief the mighty NullElement
69 * TopMost Node of them all.
70 */
71Element2D* Element2D::nullElement = NULL;
72
73
74/**
75 * @brief standard deconstructor
76 *
77 * There are two general ways to delete an Element2D
78 * 1. delete instance;
79 *   -> result
80 *    delete this Node and all its children and children's children...
81 *    (danger if you still want the instance!!)
82 *
83 * 2. instance->remove2D(); delete instance;
84 *   -> result:
85 *    moves its children to the NullElement2D
86 *    then deletes the Element.
87 */
88Element2D::~Element2D ()
89{
90  this->debug();
91  // remove the Element2D, delete it's children (if required).
92  std::list<Element2D*>::iterator tmp = this->children.begin();
93  std::list<Element2D*>::iterator deleteNode;
94  while(!this->children.empty())
95    while (tmp != this->children.end())
96    {
97      deleteNode = tmp;
98      tmp++;
99//      printf("TEST::%s(%s) %s\n", (*deleteNode)->getName(), (*deleteNode)->getClassName(), this->getName());
100      if ((this->parentMode & E2D_PROHIBIT_CHILD_DELETE) ||
101          ((*deleteNode)->parentMode & E2D_PROHIBIT_DELETE_WITH_PARENT))
102      {
103        if (this == Element2D::nullElement && (*deleteNode)->parentMode & E2D_REPARENT_TO_NULL)
104          delete (*deleteNode);
105        else
106          (*deleteNode)->reparent2D();
107      }
108      else
109        delete (*deleteNode);
110    }
111
112  if (this->parent != NULL)
113  {
114    this->parent->eraseChild2D(this);
115    this->parent = NULL;
116  }
117
118  // remove all other allocated memory.
119  if (this->toCoordinate != NULL)
120    delete this->toCoordinate;
121  if (this->toDirection != NULL)
122    delete this->toDirection;
123
124  if (this == Element2D::nullElement)
125    Element2D::nullElement = NULL;
126}
127
128
129/**
130 * @brief Loads the Parameters of an Element2D from...
131 * @param root The XML-element to load from
132 */
133void Element2D::loadParams(const TiXmlElement* root)
134{
135  BaseObject::loadParams(root);
136
137  // ELEMENT2D-native settings.
138  LoadParam(root, "alignment", this, Element2D, setAlignment)
139      .describe("loads the alignment: (either: center, left, right or screen-center)");
140
141  LoadParam(root, "layer", this, Element2D, setLayer)
142      .describe("loads the layer onto which to project: (either: top, medium, bottom, below-all)");
143
144  LoadParam(root, "bind-node", this, Element2D, setBindNode)
145      .describe("sets a node, this 2D-Element should be shown upon (name of the node)")
146      .defaultValues(1, NULL);
147
148  LoadParam(root, "visibility", this, Element2D, setVisibility)
149      .describe("if the Element is visible or not");
150
151
152// PNode-style:
153  LoadParam(root, "rel-coor-2d", this, Element2D, setRelCoor2D)
154      .describe("Sets The relative position of the Node to its parent.");
155
156  LoadParam(root, "abs-coor-2d", this, Element2D, setAbsCoor2D)
157      .describe("Sets The absolute Position of the Node.");
158
159  LoadParam(root, "rel-dir-2d", this, Element2D, setRelDir2D)
160      .describe("Sets The relative rotation of the Node to its parent.");
161
162  LoadParam(root, "abs-dir-2d", this, Element2D, setAbsDir2D)
163      .describe("Sets The absolute rotation of the Node.");
164
165  LoadParam(root, "parent", this, Element2D, setParent2D)
166      .describe("the Name of the Parent of this Element2D");
167
168  LoadParam(root, "parent-mode", this, Element2D, setParentMode2D)
169      .describe("the mode to connect this node to its parent ()");
170
171  // cycling properties
172  LOAD_PARAM_START_CYCLE(root, element);
173  {
174    LoadParam_CYCLE(element, "child", this, Element2D, addChild2D)
175        .describe("adds a new Child to the current Node.");
176  }
177  LOAD_PARAM_END_CYCLE(element);
178}
179
180/**
181 * sets the alignment of the 2D-element in form of a String
182 * @param alignment the alignment @see loadParams
183*/
184void Element2D::setAlignment(const char* alignment)
185{
186  if (!strcmp(alignment, "center"))
187    this->setAlignment(E2D_ALIGN_CENTER);
188  else if (!strcmp(alignment, "left"))
189    this->setAlignment(E2D_ALIGN_LEFT);
190  else if (!strcmp(alignment, "right"))
191    this->setAlignment(E2D_ALIGN_RIGHT);
192  else if (!strcmp(alignment, "screen-center"))
193    this->setAlignment(E2D_ALIGN_SCREEN_CENTER);
194}
195
196
197/**
198 * moves a Element to another layer
199 * @param layer the Layer this is drawn on
200 */
201void Element2D::setLayer(E2D_LAYER layer)
202{
203  if (this->parent != NULL && this->parent->getLayer() > layer)
204  {
205    PRINTF(2)("Unable to set %s to layer %s, because it's parent(%s) is of higher layer %s\n",
206              this->getName(),
207              Element2D::layer2DToChar(layer),
208              this->parent->getName(),
209              Element2D::layer2DToChar(this->parent->getLayer()));
210    layer = this->parent->getLayer();
211  }
212  this->layer = layer;
213}
214
215/**
216 * sets the layer onto which this 2D-element is projected to.
217 * @param layer the layer @see loadParams @see Element2D::charToLayer2D(const char* layer)
218 */
219void Element2D::setLayer(const char* layer)
220{
221  this->setLayer(Element2D::charToLayer2D(layer));
222}
223
224void Element2D::setSizeSoft2D(float x, float y, float bias)
225{
226  if (likely(this->toSize == NULL))
227    this->toSize = new Vector2D();
228
229  *this->toSize = Vector2D(x,y);;
230  this->bias = bias;
231}
232
233
234
235/**
236 * @brief sets a node, this 2D-Element should be shown upon
237 * @param bindNode the name of the Node (should be existing)
238 */
239void Element2D::setBindNode(const char* bindNode)
240{
241  const PNode* tmpBindNode = dynamic_cast<const PNode*>(ClassList::getObject(bindNode, CL_PARENT_NODE));
242  if (tmpBindNode != NULL)
243    this->bindNode = tmpBindNode;
244}
245
246/**
247 * sets the relative coordinate of the Element2D to its parent
248 * @param relCoord the relative coordinate to the parent
249 */
250void Element2D::setRelCoor2D (const Vector& relCoord)
251{
252  if (this->toCoordinate!= NULL)
253  {
254    delete this->toCoordinate;
255    this->toCoordinate = NULL;
256  }
257  this->relCoordinate = relCoord;
258  this->bRelCoorChanged = true;
259}
260
261/**
262 * sets the relative coordinate of the Element2D to its Parent
263 * @param x the x coordinate
264 * @param y the y coordinate
265 * @param z the z coordinate
266 */
267void Element2D::setRelCoor2D (float x, float y, float z)
268{
269  this->setRelCoor2D(Vector(x,y,z));
270}
271
272/**
273 * sets the Relative coordinate to the parent in Pixels
274 * @param x the relCoord X
275 * @param y the relCoord Y
276 */
277void Element2D::setRelCoor2Dpx (int x, int y)
278{
279  this->setRelCoor2D(Vector((float)x/(float)GraphicsEngine::getInstance()->getResolutionX(),
280                     (float)y/(float)GraphicsEngine::getInstance()->getResolutionY(),
281                     0
282                           ));
283}
284
285/**
286 * sets a new relative position smoothely
287 * @param relCoordSoft the new Position to iterate to
288 * @param bias how fast to iterate to this position
289 */
290void Element2D::setRelCoorSoft2D(const Vector& relCoordSoft, float bias)
291{
292  if (likely(this->toCoordinate == NULL))
293    this->toCoordinate = new Vector();
294
295  *this->toCoordinate = relCoordSoft;
296  this->bias = bias;
297}
298
299/**
300 * sets a new relative position smoothely
301 * @param x the new x-coordinate in Pixels of the Position to iterate to
302 * @param y the new y-coordinate in Pixels of the Position to iterate to
303 * @param bias how fast to iterate to this position
304 */
305void Element2D::setRelCoorSoft2Dpx (int x, int y, float bias)
306{
307  this->setRelCoorSoft2D(Vector((float)x/(float)GraphicsEngine::getInstance()->getResolutionX(),
308                         (float)y/(float)GraphicsEngine::getInstance()->getResolutionY(),
309                         0),
310                         bias);
311}
312
313/**
314 * set relative coordinates smoothely
315 * @param x x-relative coordinates to its parent
316 * @param y y-relative coordinates to its parent
317 * @param z z-relative coordinates to its parent
318 * @see  void PNode::setRelCoorSoft (const Vector&, float)
319 */
320void Element2D::setRelCoorSoft2D(float x, float y, float depth, float bias)
321{
322  this->setRelCoorSoft2D(Vector(x, y, depth), bias);
323}
324
325/**
326 * @param absCoord set absolute coordinate
327 */
328void Element2D::setAbsCoor2D (const Vector& absCoord)
329{
330  if (this->toCoordinate!= NULL)
331  {
332    delete this->toCoordinate;
333    this->toCoordinate = NULL;
334  }
335
336  if( likely(this->parentMode & E2D_PARENT_MOVEMENT))
337  {
338    /* if you have set the absolute coordinates this overrides all other changes */
339    if (likely(this->parent != NULL))
340      this->relCoordinate = absCoord - parent->getAbsCoor2D ();
341    else
342      this->relCoordinate = absCoord;
343  }
344  if( this->parentMode & E2D_PARENT_ROTATE_MOVEMENT)
345  {
346    if (likely(this->parent != NULL))
347      this->relCoordinate = absCoord - parent->getAbsCoor2D ();
348    else
349      this->relCoordinate = absCoord;
350  }
351
352  this->bRelCoorChanged = true;
353}
354
355/**
356 * @param x x-coordinate.
357 * @param y y-coordinate.
358 * @param z z-coordinate.
359 * @see void PNode::setAbsCoor (const Vector& absCoord)
360 */
361void Element2D::setAbsCoor2D (float x, float y, float depth)
362{
363  this->setAbsCoor2D(Vector(x, y, depth));
364}
365
366/**
367 * @param x x-coordinate in Pixels
368 * @param y y-coordinate in Pixels
369 * @see void PNode::setAbsCoor (const Vector& absCoord)
370 */
371void Element2D::setAbsCoor2Dpx (int x, int y)
372{
373  this->setAbsCoor2D(Vector((float)x/(float)GraphicsEngine::getInstance()->getResolutionX(),
374                     (float)y/(float)GraphicsEngine::getInstance()->getResolutionY(),
375                     0
376                           ));
377}
378
379/**
380 * @param absCoordSoft set absolute coordinate
381 * @param bias how fast to iterato to the new Coordinate
382 */
383void Element2D::setAbsCoorSoft2D (const Vector& absCoordSoft, float bias)
384{
385  if (this->toCoordinate == NULL)
386    this->toCoordinate = new Vector();
387
388  if( likely(this->parentMode & E2D_PARENT_MOVEMENT))
389  {
390    /* if you have set the absolute coordinates this overrides all other changes */
391    if (likely(this->parent != NULL))
392      *this->toCoordinate = absCoordSoft - parent->getAbsCoor2D ();
393    else
394      *this->toCoordinate = absCoordSoft;
395  }
396  if( this->parentMode & E2D_PARENT_ROTATE_MOVEMENT)
397  {
398    if (likely(this->parent != NULL))
399      *this->toCoordinate = absCoordSoft - parent->getAbsCoor2D ();
400    else
401      *this->toCoordinate = absCoordSoft;
402  }
403
404  this->bias = bias;
405}
406
407/**
408 * @param x x-coordinate.
409 * @param y y-coordinate.
410 * @param z z-coordinate.
411 * @see void PNode::setAbsCoor (const Vector& absCoord)
412 */
413void Element2D::setAbsCoorSoft2D (float x, float y, float depth, float bias)
414{
415  this->setAbsCoorSoft2D(Vector(x, y, depth), bias);
416}
417
418/**
419 *  shift coordinate ralative
420 * @param shift shift vector
421 *
422 * This simply adds the shift-Vector to the relative Coordinate
423 */
424void Element2D::shiftCoor2D (const Vector& shift)
425{
426  this->relCoordinate += shift;
427  this->bRelCoorChanged = true;
428
429}
430
431/**
432 * shifts in PixelSpace
433 * @param x the pixels to shift in X
434 * @param y the pixels to shift in Y
435 */
436void Element2D::shiftCoor2Dpx (int x, int y)
437{
438  this->shiftCoor2D(Vector((float)x/(float)GraphicsEngine::getInstance()->getResolutionX(),
439                    (float)y/(float)GraphicsEngine::getInstance()->getResolutionY(),
440                     0));
441}
442
443/**
444 *  set relative direction
445 * @param relDir to its parent
446 */
447void Element2D::setRelDir2D (float relDir)
448{
449  if (this->toDirection!= NULL)
450  {
451    delete this->toDirection;
452    this->toDirection = NULL;
453  }
454
455  this->relDirection = relDir;
456  this->bRelDirChanged = true;
457}
458
459/**
460 * sets the Relative Direction of this node to its parent in a Smoothed way
461 * @param relDirSoft the direction to iterate to smoothely.
462 * @param bias how fast to iterate to the new Direction
463 */
464void Element2D::setRelDirSoft2D(float relDirSoft, float bias)
465{
466  if (likely(this->toDirection == NULL))
467    this->toDirection = new float;
468
469  *this->toDirection = relDirSoft;
470  this->bias = bias;
471}
472
473/**
474 *  sets the absolute direction
475 * @param absDir absolute coordinates
476 */
477void Element2D::setAbsDir2D (float absDir)
478{
479  if (this->toDirection!= NULL)
480  {
481    delete this->toDirection;
482    this->toDirection = NULL;
483  }
484
485  if (likely(this->parent != NULL))
486    this->relDirection = absDir - this->parent->getAbsDir2D();
487  else
488    this->relDirection = absDir;
489
490  this->bRelDirChanged = true;
491}
492
493/**
494 *  sets the absolute direction softly
495 * @param absDir absolute coordinates
496 */
497void Element2D::setAbsDirSoft2D (float absDirSoft, float bias)
498{
499  if (this->toDirection == NULL)
500    this->toDirection = new float;
501
502  if (likely(this->parent != NULL))
503    *this->toDirection = absDirSoft - this->parent->getAbsDir2D();
504  else
505    *this->toDirection = absDirSoft;
506
507  this->bias = bias;
508}
509
510/**
511 * shift Direction
512 * @param shift the direction around which to shift.
513 */
514void Element2D::shiftDir2D (float shiftDir)
515{
516  this->relDirection = this->relDirection + shiftDir;
517  this->bRelDirChanged = true;
518}
519
520/**
521 *  adds a child and makes this node to a parent
522 * @param child child reference
523 * @param parentMode on which changes the child should also change ist state
524 *
525 * use this to add a child to this node.
526 */
527void Element2D::addChild2D (Element2D* child)
528{
529  assert(child != NULL);
530  if( likely(child->parent != NULL))
531  {
532    PRINTF(5)("Element2D::addChild() - reparenting node: removing it and adding it again\n");
533    child->parent->eraseChild2D(child);
534  }
535  if (this->checkIntegrity(child))
536  {
537    child->parent = this;
538    if (likely(this != NULL))
539    {
540     // ELEMENT SORTING TO LAYERS  //
541     unsigned int childCount = this->children.size();
542
543     list<Element2D*>::iterator elem;
544     for (elem = this->children.begin(); elem != this->children.end(); elem++)
545     {
546       if ((*elem)->layer < child->layer)
547       {
548         this->children.insert(elem, child);
549         break;
550       }
551     }
552     if (childCount == this->children.size())
553       this->children.push_back(child);
554     ////////////////////////////////
555     if (unlikely(this->layer > child->getLayer()))
556     {
557       PRINTF(2)("Layer '%s' of Child(%s) lower than parents(%s) layer '%s'. updating...\n",
558       Element2D::layer2DToChar(child->getLayer()),child->getName(), this->getName(), Element2D::layer2DToChar(this->layer));
559       child->setLayer(this->layer);
560     }
561   }
562   else
563   {
564     PRINTF(1)("Tried to reparent2D to own child '%s::%s' to '%s::%s'.\n",
565              this->getClassName(), this->getName(), child->getClassName(), child->getName());
566     child->parent = NULL;
567   }
568  }
569  child->parentCoorChanged2D();
570}
571
572/**
573 * @see Element2D::addChild(Element2D* child);
574 * @param childName the name of the child to add to this PNode
575 */
576void Element2D::addChild2D (const char* childName)
577{
578  Element2D* childNode = dynamic_cast<Element2D*>(ClassList::getObject(childName, CL_ELEMENT_2D));
579  if (childNode != NULL)
580    this->addChild2D(childNode);
581}
582
583/**
584 * removes a child from the node
585 * @param child the child to remove from this Node..
586 *
587 * Children from nodes will not be lost, they are referenced to NullPointer
588 */
589void Element2D::removeChild2D (Element2D* child)
590{
591  if (child != NULL)
592    child->remove2D();
593}
594
595/**
596 * !! PRIVATE FUNCTION
597 * @brief reparents an Element2D (happens on Parents Node delete or remove and Flags are set.)
598 */
599void Element2D::reparent2D()
600{
601  if (this->parentMode & E2D_REPARENT_TO_NULL)
602    this->setParent2D((Element2D*)NULL);
603  else if (this->parentMode & E2D_REPARENT_TO_PARENTS_PARENT && this->parent != NULL)
604    this->setParent2D(this->parent->getParent2D());
605  else
606    this->setParent2D(Element2D::getNullElement());
607}
608
609
610/**
611 * @param child the child to be erased from this Nodes List
612 */
613void Element2D::eraseChild2D(Element2D* child)
614{
615  assert (this != NULL && child != NULL);
616  std::list<Element2D*>::iterator childIT = std::find(this->children.begin(), this->children.end(), child);
617  this->children.erase(childIT);
618}
619
620
621
622/**
623 * remove this Element from the tree and adds all children to NullElement2D
624 *
625 * afterwards this Node is free, and can be reattached, or deleted freely.
626 */
627void Element2D::remove2D()
628{
629  list<Element2D*>::iterator child = this->children.begin();
630  list<Element2D*>::iterator reparenter;
631  while (child != this->children.end())
632  {
633    reparenter = child;
634    child++;
635    if (this->parentMode & E2D_REPARENT_CHILDREN_ON_REMOVE ||
636        (*reparenter)->parentMode & E2D_REPARENT_ON_PARENTS_REMOVE)
637    {
638      printf("TEST----------------%s ---- %s\n", this->getClassName(), (*reparenter)->getClassName());
639      (*reparenter)->reparent2D();
640      printf("REPARENTED TO: %s::%s\n",(*reparenter)->getParent2D()->getClassName(),(*reparenter)->getParent2D()->getName());
641    }
642  }
643  if (this->parent != NULL)
644  {
645    this->parent->eraseChild2D(this);
646    this->parent = NULL;
647  }
648}
649
650
651/**
652 * @see Element2D::setParent(Element2D* parent);
653 * @param parentName the name of the Parent to set to this Element2D
654 */
655void Element2D::setParent2D (const char* parentName)
656{
657  Element2D* parentNode = dynamic_cast<Element2D*>(ClassList::getObject(parentName, CL_ELEMENT_2D));
658  if (parentNode != NULL)
659    parentNode->addChild2D(this);
660  else
661    PRINTF(2)("Not Found Element2D's (%s::%s) new Parent by Name: %s\n",
662                this->getClassName(), this->getName(), parentName);
663}
664
665/**
666 * does the reparenting in a very smooth way
667 * @param parentNode the new Node to connect this node to.
668 * @param bias the speed to iterate to this new Positions
669 */
670void Element2D::setParentSoft2D(Element2D* parentNode, float bias)
671{
672  if (this->parent == parentNode)
673    return;
674
675  if (likely(this->toCoordinate == NULL))
676  {
677    this->toCoordinate = new Vector();
678    *this->toCoordinate = this->getRelCoor2D();
679  }
680  if (likely(this->toDirection == NULL))
681  {
682    this->toDirection = new float;
683    *this->toDirection = this->getRelDir2D();
684  }
685  this->bias = bias;
686
687
688  Vector tmpV = this->getAbsCoor2D();
689  float tmpQ = this->getAbsDir2D();
690
691  parentNode->addChild2D(this);
692
693  if (this->parentMode & E2D_PARENT_ROTATE_MOVEMENT) //! @todo implement this.
694    ;//this->setRelCoor(this->parent->getAbsDir().inverse().apply(tmpV - this->parent->getAbsCoor()));
695  else
696    this->relCoordinate = (tmpV - parentNode->getAbsCoor2D());
697  this->bRelCoorChanged = true;
698
699  this->relDirection = (tmpQ - parentNode->getAbsDir2D());
700  this->bRelDirChanged = true;
701}
702
703/**
704 * does the reparenting in a very smooth way
705 * @param parentName the name of the Parent to reconnect to
706 * @param bias the speed to iterate to this new Positions
707 */
708void Element2D::setParentSoft2D(const char* parentName, float bias)
709{
710  Element2D* parentNode = dynamic_cast<Element2D*>(ClassList::getObject(parentName, CL_ELEMENT_2D));
711  if (parentNode != NULL)
712    this->setParentSoft2D(parentNode, bias);
713}
714
715/**
716 * @param parentMode sets the parentingMode of this Node
717 */
718void Element2D::setParentMode2D(E2D_PARENT_MODE parentMode)
719{
720  this->parentMode = ((this->parentMode & 0xfff0) | parentMode);
721}
722
723
724/**
725 * @brief sets the mode of this parent manually
726 * @param parentMode a String representing this parentingMode
727 */
728void Element2D::setParentMode2D (const char* parentingMode)
729{
730  this->setParentMode2D(Element2D::charToParentingMode2D(parentingMode));
731}
732
733
734/**
735 * @returns the NullElement (and if needed (most probably) creates it)
736 */
737Element2D* Element2D::createNullElement()
738{
739  if (likely(Element2D::nullElement == NULL))
740  {
741    Element2D::nullElement = new Element2D(NULL, E2D_LAYER_BELOW_ALL, E2D_PARENT_MODE_DEFAULT | E2D_REPARENT_TO_NULL);
742    Element2D::nullElement->setName("NullElement");
743  }
744  return Element2D::nullElement;
745}
746
747
748/**
749 * !! PRIVATE FUNCTION
750 * @brief checks the upward integrity (e.g if Element2D is somewhere up the Node tree.)
751 * @param checkParent the Parent to check.
752 * @returns true if the integrity-check succeeds, false otherwise.
753 *
754 * If there is a second occurence of checkParent before NULL, then a loop could get
755 * into the Tree, and we do not want this.
756 */
757bool Element2D::checkIntegrity(const Element2D* checkParent) const
758{
759  const Element2D* parent = this;
760  while ( (parent = parent->getParent2D()) != NULL)
761    if (unlikely(parent == checkParent))
762      return false;
763  return true;
764}
765
766
767/**
768 *  updates the absCoordinate/absDirection
769 * @param dt The time passed since the last update
770
771   this is used to go through the parent-tree to update all the absolute coordinates
772   and directions. this update should be done by the engine, so you don't have to
773   worry, normaly...
774 */
775void Element2D::update2D (float dt)
776{
777  // setting the Position of this 2D-Element.
778  if( likely(this->parent != NULL))
779  {
780      // movement for nodes with smoothMove enabled
781    if (unlikely(this->toCoordinate != NULL))
782    {
783      Vector moveVect = (*this->toCoordinate - this->relCoordinate) *fabsf(dt)*bias;
784
785      if (likely(moveVect.len() >= .001))//PNODE_ITERATION_DELTA))
786      {
787        this->shiftCoor2D(moveVect);
788      }
789      else
790      {
791        Vector tmp = *this->toCoordinate;
792        this->setRelCoor2D(tmp);
793        PRINTF(5)("SmoothMove of %s finished\n", this->getName());
794      }
795    }
796    if (unlikely(this->toDirection != NULL))
797    {
798      float rotFlot = (*this->toDirection - this->relDirection) *fabsf(dt)*bias;
799      if (likely(fabsf(rotFlot) >= .001))//PNODE_ITERATION_DELTA))
800      {
801        this->shiftDir2D(rotFlot);
802      }
803      else
804      {
805        float tmp = *this->toDirection;
806        this->setRelDir2D(tmp);
807        PRINTF(5)("SmoothRotate of %s finished\n", this->getName());
808      }
809    }
810    if (unlikely(this->toSize != NULL))
811    {
812      Vector2D shiftSize = (*this->toSize - Vector2D(this->sizeX, this->sizeY)) *fabsf(dt)*bias;
813      if (likely((shiftSize).len() >= .001))//PNODE_ITERATION_DELTA))
814      {
815        this->sizeX += shiftSize.x;
816        this->sizeY += shiftSize.y;
817      }
818      else
819      {
820        delete this->toSize;
821        this->toSize = NULL;
822        PRINTF(5)("SmoothRotate of %s finished\n", this->getName());
823      }
824    }
825
826    // MAIN UPDATE /////////////////////////////////////
827    this->lastAbsCoordinate = this->absCoordinate;
828
829    PRINTF(5)("Element2D::update - %s - (%f, %f, %f)\n", this->getName(), this->absCoordinate.x, this->absCoordinate.y, this->absCoordinate.z);
830
831
832    if( this->parentMode & E2D_PARENT_LOCAL_ROTATE && this->bRelDirChanged)
833    {
834      /* update the current absDirection - remember * means rotation around sth.*/
835      this->prevRelDirection = this->relDirection;
836      this->absDirection = this->relDirection + parent->getAbsDir2D();;
837    }
838
839
840    if (unlikely(this->alignment & E2D_ALIGN_SCREEN_CENTER && this->bRelCoorChanged))
841    {
842      this->prevRelCoordinate = this->relCoordinate;
843      this->absCoordinate.x = .5 + this->relCoordinate.x;
844      this->absCoordinate.y = .5 + this->relCoordinate.y;
845      this->absCoordinate.z = 0.0;
846    }
847    else if (unlikely(this->bindNode != NULL))
848    {
849      GLdouble projectPos[3] = {0.0, 0.0, 0.0};
850      gluProject(this->bindNode->getAbsCoor().x,
851                 this->bindNode->getAbsCoor().y,
852                 this->bindNode->getAbsCoor().z,
853                 GraphicsEngine::modMat,
854                 GraphicsEngine::projMat,
855                 GraphicsEngine::viewPort,
856                 projectPos,
857                 projectPos+1,
858                 projectPos+2);
859//       printf("%s::%s  == %f %f %f :: %f %f\n", this->getClassName(), this->getName(),
860//              this->bindNode->getAbsCoor().x,
861//              this->bindNode->getAbsCoor().y,
862//              this->bindNode->getAbsCoor().z,
863//              projectPos[0],
864//              projectPos[1]);
865
866      this->prevRelCoordinate.x = this->absCoordinate.x = projectPos[0] /* /(float)GraphicsEngine::getInstance()->getResolutionX() */ + this->relCoordinate.x;
867      this->prevRelCoordinate.y = this->absCoordinate.y = (float)GraphicsEngine::getInstance()->getResolutionY() -  projectPos[1] + this->relCoordinate.y;
868      this->prevRelCoordinate.z = this->absCoordinate.z = projectPos[2] + this->relCoordinate.z;
869      this->bRelCoorChanged = true;
870    }
871    else
872    {
873      if(likely(this->parentMode & PNODE_MOVEMENT && this->bRelCoorChanged))
874      {
875        /* update the current absCoordinate */
876        this->prevRelCoordinate = this->relCoordinate;
877        this->absCoordinate = this->parent->getAbsCoor2D() + this->relCoordinate;
878      }
879      else if( this->parentMode & PNODE_ROTATE_MOVEMENT && this->bRelCoorChanged)
880      {
881        /* update the current absCoordinate */
882        this->prevRelCoordinate = this->relCoordinate;
883        float sine = sin(this->parent->getAbsDir2D());
884        float cose = cos(this->parent->getAbsDir2D());
885//        this->absCoordinate.x = this->relCoordinate.x*cose - this->relCoordinate.y*sine + this->parent->getRelCoor2D().x*(1-cose) +this->parent->getRelCoor2D().y*sine;
886//        this->absCoordinate.y = this->relCoordinate.x*sine + this->relCoordinate.y*cose + this->parent->getRelCoor2D().y*(1-cose) +this->parent->getRelCoor2D().x*sine;
887
888        this->absCoordinate.x = this->parent->getAbsCoor2D().x + (this->relCoordinate.x*cos(this->parent->getAbsDir2D()) - this->relCoordinate.y * sin(this->parent->getAbsDir2D()));
889        this->absCoordinate.y = this->parent->getAbsCoor2D().y + (this->relCoordinate.x*sin(this->parent->getAbsDir2D()) + this->relCoordinate.y * cos(this->parent->getAbsDir2D()));
890
891      }
892    }
893    /////////////////////////////////////////////////
894  }
895  else
896  {
897    PRINTF(5)("Element2D::update - (%f, %f, %f)\n", this->absCoordinate.x, this->absCoordinate.y, this->absCoordinate.z);
898    if (this->bRelCoorChanged)
899    {
900      this->prevRelCoordinate = this->relCoordinate;
901      this->absCoordinate = this->relCoordinate;
902    }
903    if (this->bRelDirChanged)
904    {
905      this->prevRelDirection = this->relDirection;
906      this->absDirection = this->getAbsDir2D() + this->relDirection;
907    }
908  }
909
910
911  // UPDATE CHILDREN
912  if(!this->children.empty() || this->parentMode & E2D_UPDATE_CHILDREN_IF_INACTIVE)
913  {
914    list<Element2D*>::iterator child;
915    for (child = this->children.begin(); child != this->children.end(); child++)
916    {
917      /* if this node has changed, make sure, that all children are updated also */
918      if( likely(this->bRelCoorChanged))
919        (*child)->parentCoorChanged2D();
920      if( likely(this->bRelDirChanged))
921        (*child)->parentDirChanged2D();
922
923      (*child)->update2D(dt);
924    }
925  }
926
927  // FINISHING PROCESS
928  this->velocity = (this->absCoordinate - this->lastAbsCoordinate) / dt;
929  this->bRelCoorChanged = false;
930  this->bRelDirChanged = false;
931}
932
933
934/**
935 *  displays some information about this pNode
936 * @param depth The deph into which to debug the children of this Element2D to.
937 * (0: all children will be debugged, 1: only this Element2D, 2: this and direct children...)
938 * @param level The n-th level of the Node we draw (this is internal and only for nice output)
939 */
940void Element2D::debug (unsigned int depth, unsigned int level) const
941{
942  for (unsigned int i = 0; i < level; i++)
943    PRINT(0)(" |");
944  if (this->children.size() > 0)
945    PRINT(0)(" +");
946  else
947    PRINT(0)(" -");
948  PRINT(0)("Element2D(%s::%s) - absCoord: (%0.2f, %0.2f), relCoord(%0.2f, %0.2f), direction(%0.2f) - %s, layer:%s\n",
949            this->getClassName(),
950            this->getName(),
951            this->absCoordinate.x,
952            this->absCoordinate.y,
953            this->relCoordinate.x,
954            this->relCoordinate.y,
955            this->getAbsDir2D(),
956            Element2D::parentingModeToChar2D(parentMode),
957            Element2D::layer2DToChar(this->layer));
958
959  if (depth >= 2 || depth == 0)
960  {
961    list<Element2D*>::const_iterator child;
962    for (child = this->children.begin(); child != this->children.end(); child++)
963    {
964      if (depth == 0)
965        (*child)->debug(0, level + 1);
966      else
967        (*child)->debug(depth - 1, level +1);
968    }
969  }
970}
971
972/**
973 * ticks the 2d-Element
974 * @param dt the time elapsed since the last tick
975 *
976 * the element only gets tickt, if it is active.
977 * Be aware, that this walks through the entire Element2D-tree,
978 * searching for Elements to be ticked.
979 */
980void Element2D::tick2D(float dt)
981{
982  if (this->bActive)
983    this->tick(dt);
984  if (this->children.size() > 0)
985  {
986    list<Element2D*>::iterator child;
987    for (child = this->children.begin(); child != this->children.end(); child++)
988      (*child)->tick2D(dt);
989  }
990}
991
992/**
993 * draws all the Elements from this element2D downwards
994 * @param layer the maximal Layer to draw. @see E2D_LAYER
995 */
996void Element2D::draw2D(short layer) const
997{
998  if (this->bVisible)
999    this->draw();
1000  if (this->children.size() > 0)
1001  {
1002    list<Element2D*>::const_iterator child;
1003    for (child = this->children.begin(); child != this->children.end(); child++)
1004      if (likely(layer >= this->layer))
1005        (*child)->draw2D(layer);
1006  }
1007}
1008
1009/**
1010 * displays the Element2D at its position with its rotation as a Plane.
1011 */
1012void Element2D::debugDraw2D(unsigned int depth, float size, Vector color, unsigned int level) const
1013{
1014  if (level == 0)
1015  {
1016    glPushAttrib(GL_ENABLE_BIT);
1017    glMatrixMode(GL_MODELVIEW);
1018
1019    glDisable(GL_LIGHTING);
1020    glDisable(GL_BLEND);
1021    glDisable(GL_TEXTURE_2D);
1022  }
1023
1024  glPushMatrix();
1025  /* translate */
1026  /* rotate */
1027  glColor3f(color.x, color.y, color.z);
1028
1029  glTranslatef (this->getAbsCoor2D().x, this->getAbsCoor2D().y, 0);
1030  glRotatef(this->getAbsDir2D(), 0,0,1);
1031  glBegin(GL_LINE_LOOP);
1032  glVertex2f(0, 0);
1033  glVertex2f(0, +this->getSizeY2D());
1034  glVertex2f(+this->getSizeX2D(), +this->getSizeY2D());
1035  glVertex2f(+this->getSizeX2D(), 0);
1036  glEnd();
1037
1038
1039  glPopMatrix();
1040  if (depth >= 2 || depth == 0)
1041  {
1042    Vector childColor =  Color::HSVtoRGB(Color::RGBtoHSV(color)+Vector(20,0,.0));
1043    list<Element2D*>::const_iterator child;
1044    for (child = this->children.begin(); child != this->children.end(); child++)
1045    {
1046      // drawing the Dependency graph
1047      if (this != Element2D::getNullElement())
1048      {
1049        glBegin(GL_LINES);
1050        glColor3f(color.x, color.y, color.z);
1051        glVertex3f(this->getAbsCoor2D ().x,
1052                   this->getAbsCoor2D ().y,
1053                   0);
1054        glColor3f(childColor.x, childColor.y, childColor.z);
1055        glVertex3f((*child)->getAbsCoor2D ().x,
1056                   (*child)->getAbsCoor2D ().y,
1057                   0);
1058        glEnd();
1059      }
1060      if (depth == 0)
1061        (*child)->debugDraw2D(0, size, childColor, level+1);
1062      else
1063        (*child)->debugDraw2D(depth - 1, size, childColor, level +1);
1064    }
1065  }
1066  if (level == 0)
1067    glPopAttrib();
1068
1069}
1070
1071
1072// helper functions //
1073/**
1074 * converts a parentingMode into a string that is the name of it
1075 * @param parentingMode the ParentingMode to convert
1076 * @return the converted string
1077 */
1078const char* Element2D::parentingModeToChar2D(int parentingMode)
1079{
1080  if (parentingMode == E2D_PARENT_LOCAL_ROTATE)
1081    return "local-rotate";
1082  else if (parentingMode == E2D_PARENT_ROTATE_MOVEMENT)
1083    return "rotate-movement";
1084  else if (parentingMode == E2D_PARENT_MOVEMENT)
1085    return "movement";
1086  else if (parentingMode == E2D_PARENT_ALL)
1087    return "all";
1088  else if (parentingMode == E2D_PARENT_ROTATE_AND_MOVE)
1089    return "rotate-and-move";
1090}
1091
1092/**
1093 * converts a parenting-mode-string into a int
1094 * @param parentingMode the string naming the parentingMode
1095 * @return the int corresponding to the named parentingMode
1096 */
1097E2D_PARENT_MODE Element2D::charToParentingMode2D(const char* parentingMode)
1098{
1099  if (!strcmp(parentingMode, "local-rotate"))
1100    return (E2D_PARENT_LOCAL_ROTATE);
1101  else  if (!strcmp(parentingMode, "rotate-movement"))
1102    return (E2D_PARENT_ROTATE_MOVEMENT);
1103  else  if (!strcmp(parentingMode, "movement"))
1104    return (E2D_PARENT_MOVEMENT);
1105  else  if (!strcmp(parentingMode, "all"))
1106    return (E2D_PARENT_ALL);
1107  else  if (!strcmp(parentingMode, "rotate-and-move"))
1108    return (E2D_PARENT_ROTATE_AND_MOVE);
1109}
1110
1111/**
1112 * converts a layer into its corresponding string
1113 * @param layer the layer to get the name-String of.
1114 * @returns the Name of the Layer (on error the default-layer-string is returned)
1115 */
1116const char* Element2D::layer2DToChar(E2D_LAYER layer)
1117{
1118  switch(layer)
1119  {
1120    case E2D_LAYER_TOP:
1121      return "top";
1122      break;
1123    case E2D_LAYER_MEDIUM:
1124      return "medium";
1125      break;
1126    case E2D_LAYER_BOTTOM:
1127      return "bottom";
1128      break;
1129    case E2D_LAYER_BELOW_ALL:
1130      return "below-all";
1131      break;
1132    default:
1133      return layer2DToChar(E2D_DEFAULT_LAYER);
1134      break;
1135  }
1136}
1137
1138/**
1139 * converts a String holding a actual Layer
1140 * @param layer the String to convert into a Layer2D
1141 * @returns the E2D_LAYER on success, E2D_DEFAULT_LAYER on error.
1142 */
1143E2D_LAYER Element2D::charToLayer2D(const char* layer)
1144{
1145  if (!strcmp(layer, "top"))
1146    return (E2D_LAYER_TOP);
1147  else  if (!strcmp(layer, "medium"))
1148    return (E2D_LAYER_MEDIUM);
1149  else  if (!strcmp(layer, "bottom"))
1150    return (E2D_LAYER_BOTTOM);
1151  else  if (!strcmp(layer, "below-all"))
1152    return (E2D_LAYER_BELOW_ALL);
1153  else
1154    return (E2D_DEFAULT_LAYER);
1155}
Note: See TracBrowser for help on using the repository browser.