Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/lib/graphics/render2D/element_2d.cc @ 9727

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

orxonox/new_class_id: new Executor construct, that is much more typesafe, faster, and easier to extend…

Also changed the LoadParam process, and adapted ScriptEngine calls

Then at the end, some missing headers appeared, and appended them to all the cc-files again.

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