Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/coord/p_node.cc @ 5037

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

orxonox/trunk: now the PNodes get aligned real smoothely on the Screen, no more hicking :)-

File size: 21.2 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: Patrick Boenzli
13   co-programmer:
14
15   @todo Smooth-Parent: delay, speed
16*/
17
18#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_PNODE
19
20#include "p_node.h"
21#include "null_parent.h"
22
23#include "load_param.h"
24#include "class_list.h"
25
26#include "stdincl.h"
27#include "compiler.h"
28#include "error.h"
29#include "debug.h"
30#include "list.h"
31#include "vector.h"
32
33//#include "vector.h"
34//#include "quaternion.h"
35
36using namespace std;
37
38
39/**
40 *  standard constructor
41*/
42PNode::PNode ()
43{
44  init(NULL);
45
46  NullParent::getInstance()->addChild(this);
47}
48
49/**
50 * @param root the load-Element for the PNode
51*/
52PNode::PNode(const TiXmlElement* root)
53{
54  this->init(NULL);
55  this->loadParams(root);
56
57  NullParent::getInstance()->addChild(this);
58}
59
60/**
61 *  constructor with coodinates
62 * @param absCoordinate the Absolute coordinate of the Object
63 * @param parent The parent-node of this node.
64*/
65PNode::PNode (const Vector& absCoor, PNode* parent )
66{
67  this->init(parent);
68
69  if (likely(parent != NULL))
70    parent->addChild (this);
71
72  this->setAbsCoor(absCoor);
73}
74
75/**
76 *  standard deconstructor
77*/
78PNode::~PNode ()
79{
80  tIterator<PNode>* iterator = this->children->getIterator();
81  PNode* pn = iterator->nextElement();
82  while( pn != NULL)
83    {
84      delete pn;
85      pn = iterator->nextElement();
86    }
87  delete iterator;
88  /* this deletes all children in the list */
89  delete this->children;
90  if (this->parent)
91    this->parent->removeChild(this);
92}
93
94/**
95 *  initializes a PNode
96 * @param parent the parent for this PNode
97*/
98void PNode::init(PNode* parent)
99{
100  this->setClassID(CL_PARENT_NODE, "PNode");
101  this->children = new tList<PNode>();
102  this->bRelCoorChanged = true;
103  this->bRelDirChanged = true;
104  this->parent = parent;
105
106  // iterators
107  this->toCoordinate = NULL;
108  this->toDirection = NULL;
109  this->bias = 1.0;
110}
111
112/**
113 *  loads parameters of the PNode
114 * @param root the XML-element to load the properties of
115*/
116void PNode::loadParams(const TiXmlElement* root)
117{
118  static_cast<BaseObject*>(this)->loadParams(root);
119
120  LoadParam<PNode>(root, "rel-coor", this, &PNode::setRelCoor)
121      .describe("Sets The relative position of the Node to its parent.");
122
123  LoadParam<PNode>(root, "abs-coor", this, &PNode::setAbsCoor)
124      .describe("Sets The absolute Position of the Node.");
125
126  LoadParam<PNode>(root, "rel-dir", this, &PNode::setRelDir)
127      .describe("Sets The relative rotation of the Node to its parent.");
128
129  LoadParam<PNode>(root, "abs-dir", this, &PNode::setAbsDir)
130      .describe("Sets The absolute rotation of the Node.");
131
132  LoadParam<PNode>(root, "parent", this, &PNode::setParent)
133      .describe("the Name of the Parent of this PNode");
134
135  LoadParam<PNode>(root, "parent-mode", this, &PNode::setParentMode)
136      .describe("the mode to connect this node to its parent ()");
137
138  // cycling properties
139  if (root != NULL)
140  {
141    const TiXmlElement* element = root->FirstChildElement();
142    while (element != NULL)
143    {
144      LoadParam<PNode>(root, "parent", this, &PNode::addChild, true)
145          .describe("adds a new Child to the current Node.");
146
147      element = element->NextSiblingElement();
148    }
149  }
150}
151
152/**
153 *  set relative coordinates
154 * @param relCoord relative coordinates to its parent
155
156   it is very importand, that you use this function, if you want to update the
157   relCoordinates. If you don't use this, the PNode won't recognize, that something
158   has changed and won't update the children Nodes.
159*/
160void PNode::setRelCoor (const Vector& relCoord)
161{
162  this->relCoordinate = relCoord;
163  this->bRelCoorChanged = true;
164}
165
166/**
167 *  set relative coordinates
168 * @param x x-relative coordinates to its parent
169 * @param y y-relative coordinates to its parent
170 * @param z z-relative coordinates to its parent
171 * @see  void PNode::setRelCoor (const Vector& relCoord)
172*/
173void PNode::setRelCoor (float x, float y, float z)
174{
175  this->setRelCoor(Vector(x, y, z));
176}
177
178/**
179 * sets a new relative position smoothely
180 * @param relCoordSoft the new Position to iterate to
181 * @param bias how fast to iterate to this position
182 */
183void PNode::setRelCoorSoft(const Vector& relCoordSoft, float bias)
184{
185  if (likely(this->toCoordinate == NULL))
186    this->toCoordinate = new Vector();
187
188  *this->toCoordinate = relCoordSoft;
189  this->bias = bias;
190}
191
192
193/**
194 *  set relative coordinates smoothely
195 * @param x x-relative coordinates to its parent
196 * @param y y-relative coordinates to its parent
197 * @param z z-relative coordinates to its parent
198 * @see  void PNode::setRelCoorSoft (const Vector&, float)
199 */
200void PNode::setRelCoorSoft (float x, float y, float z, float bias)
201{
202  this->setRelCoorSoft(Vector(x, y, z), bias);
203}
204
205/**
206 * @param absCoord set absolute coordinate
207
208   it is very importand, that you use this function, if you want to update the
209   absCoordinates. If you don't use this, the PNode won't recognize, that something
210   has changed and won't update the children Nodes.
211*/
212void PNode::setAbsCoor (const Vector& absCoord)
213{
214  if( likely(this->parentMode & PNODE_MOVEMENT))
215  {
216      /* if you have set the absolute coordinates this overrides all other changes */
217    if (likely(this->parent != NULL))
218      this->relCoordinate = absCoord - parent->getAbsCoor ();
219    else
220      this->relCoordinate = absCoord;
221  }
222  if( this->parentMode & PNODE_ROTATE_MOVEMENT)
223  {
224    if (likely(this->parent != NULL))
225      this->relCoordinate = absCoord - parent->getAbsCoor ();
226    else
227      this->relCoordinate = absCoord;
228  }
229
230  this->bRelCoorChanged = true;
231//  this->absCoordinate = absCoord;
232}
233
234/**
235 * @param x x-coordinate.
236 * @param y y-coordinate.
237 * @param z z-coordinate.
238 * @see void PNode::setAbsCoor (const Vector& absCoord)
239 */
240void PNode::setAbsCoor(float x, float y, float z)
241{
242  this->setAbsCoor(Vector(x, y, z));
243}
244
245/**
246 *  shift coordinate (abs and rel)
247 * @param shift shift vector
248
249   this function shifts the current coordinates about the vector shift. this is
250   usefull because from some place else you can:
251   PNode* someNode = ...;
252   Vector objectMovement = calculateShift();
253   someNode->shiftCoor(objectMovement);
254
255   elsewhere you would have to:
256   PNode* someNode = ...;
257   Vector objectMovement = calculateShift();
258   Vector currentCoor = someNode->getRelCoor();
259   Vector newCoor = currentCoor + objectMovement;
260   someNode->setRelCoor(newCoor);
261
262   yea right... shorter...
263 *
264 * @todo this is ambiguous, from the outside one does not know it absCoor has been changed
265 * this might lead to strange artefacts !!
266
267*/
268void PNode::shiftCoor (const Vector& shift)
269{
270  this->relCoordinate += shift;
271  this->bRelCoorChanged = true;
272}
273
274/**
275 *  set relative direction
276 * @param relDir to its parent
277
278   it is very importand, that you use this function, if you want to update the
279   relDirection. If you don't use this, the PNode won't recognize, that something
280   has changed and won't update the children Nodes.
281*/
282void PNode::setRelDir (const Quaternion& relDir)
283{
284  this->relDirection = relDir;
285  this->bRelCoorChanged = true;
286}
287
288/**
289 * @see void PNode::setRelDir (const Quaternion& relDir)
290 * @param x the x direction
291 * @param y the y direction
292 * @param z the z direction
293 *
294 * main difference is, that here you give a directional vector, that will be translated into a Quaternion
295 */
296void PNode::setRelDir (float x, float y, float z)
297{
298  this->setRelDir(Quaternion(Vector(x,y,z), Vector(0,1,0)));
299}
300
301
302/**
303 * sets the Relative Direction of this node to its parent in a Smoothed way
304 * @param relDirSoft the direction to iterate to smoothely.
305 * @param bias how fast to iterate to the new Direction
306 */
307void PNode::setRelDirSoft(const Quaternion& relDirSoft, float bias)
308{
309  if (likely(this->toDirection == NULL))
310    this->toDirection = new Quaternion();
311
312  *this->toDirection = relDirSoft;
313  this->bias = bias;
314}
315
316/**
317 * @see void PNode::setRelDirSoft (const Quaternion& relDir)
318 * @param x the x direction
319 * @param y the y direction
320 * @param z the z direction
321 *
322 * main difference is, that here you give a directional vector, that will be translated into a Quaternion
323 */
324void PNode::setRelDirSoft(float x, float y, float z, float bias)
325{
326  this->setRelDirSoft(Quaternion(Vector(x,y,z), Vector(0,1,0)), bias);
327}
328
329/**
330 *  sets the absolute direction (0,0,1)
331 * @param absDir absolute coordinates
332 *
333 * it is very importand, that you use this function, if you want to update the
334 * absDirection. If you don't use this, the PNode won't recognize, that something
335 * has changed and won't update the children Nodes.
336*/
337void PNode::setAbsDir (const Quaternion& absDir)
338{
339  if (likely(this->parent != NULL))
340    this->relDirection = absDir / this->parent->getAbsDir();
341  else
342   this->relDirection = absDir;
343
344  this->bRelDirChanged = true;
345}
346
347/**
348 * @see void PNode::setAbsDir (const Quaternion& relDir)
349 * @param x the x direction
350 * @param y the y direction
351 * @param z the z direction
352 *
353 * main difference is, that here you give a directional vector, that will be translated into a Quaternion
354 */
355void PNode::setAbsDir (float x, float y, float z)
356{
357  this->setAbsDir(Quaternion(Vector(x,y,z), Vector(0,1,0)));
358}
359
360/**
361 *  shift coordinate (abs and rel)
362 * @param shift vector
363 * @todo implement this
364*/
365void PNode::shiftDir (const Quaternion& shift)
366{
367  this->relDirection = this->relDirection * shift;
368  this->bRelDirChanged = true;
369}
370
371/**
372 *  adds a child and makes this node to a parent
373 * @param pNode child reference
374 * @param parentMode on which changes the child should also change ist state
375 *
376 * use this to add a child to this node.
377*/
378void PNode::addChild (PNode* child, int parentMode)
379{
380  if( likely(child->parent != NULL))
381    {
382      PRINTF(4)("PNode::addChild() - reparenting node: removing it and adding it again\n");
383      child->parent->children->remove(child);
384    }
385  child->parentMode = parentMode;
386  child->parent = this;
387  this->children->add(child);
388  child->parentCoorChanged();
389}
390
391/**
392 * @see PNode::addChild(PNode* parent);
393 * @param childName the name of the child to add to this PNode
394 */
395void PNode::addChild (const char* childName)
396{
397  PNode* childNode = dynamic_cast<PNode*>(ClassList::getObject(childName, CL_PARENT_NODE));
398  if (childNode != NULL)
399    this->addChild(childNode);
400}
401
402/**
403 *  removes a child from the node
404 * @param pNode the child to remove from this pNode.
405 *
406 * Children from pNode will not be lost, they are referenced to NullPointer
407*/
408void PNode::removeChild (PNode* child)
409{
410  child->remove();
411  this->children->remove(child);
412  child->parent = NULL;
413}
414
415/**
416 *  remove this pnode from the tree and adds all following to NullParent
417
418   this can be the case, if an entity in the world is been destroyed.
419*/
420void PNode::remove()
421{
422  NullParent* nullParent = NullParent::getInstance();
423
424  tIterator<PNode>* iterator = this->children->getIterator();
425  PNode* pn = iterator->nextElement();
426
427  while( pn != NULL)
428    {
429      nullParent->addChild(pn, pn->getParentMode());
430      pn = iterator->nextElement();
431    }
432  delete iterator;
433  this->parent->children->remove(this);
434}
435
436/**
437 * sets the parent of this PNode
438 * @param parent the Parent to set
439*/
440void PNode::setParent (PNode* parent)
441{
442  parent->addChild(this);
443}
444
445/**
446 * @see PNode::setParent(PNode* parent);
447 * @param parentName the name of the Parent to set to this PNode
448 */
449void PNode::setParent (const char* parentName)
450{
451  PNode* parentNode = dynamic_cast<PNode*>(ClassList::getObject(parentName, CL_PARENT_NODE));
452  if (parentNode != NULL)
453    parentNode->addChild(this);
454}
455
456/**
457 * does the reparenting in a very smooth way
458 * @param parentNode the new Node to connect this node to.
459 * @param bias the speed to iterate to this new Positions
460 */
461void PNode::softReparent(PNode* parentNode, float bias)
462{
463  if (this->parent == parentNode)
464    return;
465
466  if (likely(this->toCoordinate == NULL))
467  {
468    this->toCoordinate = new Vector();
469    *this->toCoordinate = this->getRelCoor();
470  }
471  if (likely(this->toDirection == NULL))
472  {
473    this->toDirection = new Quaternion();
474    *this->toDirection = this->getRelDir();
475  }
476  this->bias = bias;
477
478
479  Vector tmpV = this->getAbsCoor();
480  Quaternion tmpQ = this->getAbsDir();
481
482  parentNode->addChild(this);
483
484 if (this->parentMode & PNODE_ROTATE_MOVEMENT)
485   this->setRelCoor(this->parent->getAbsDir().inverse().apply(tmpV - this->parent->getAbsCoor()));
486 else
487   this->setRelCoor(tmpV - parentNode->getAbsCoor());
488
489  this->setRelDir(tmpQ / parentNode->getAbsDir());
490}
491
492/**
493 * does the reparenting in a very smooth way
494 * @param parentName the name of the Parent to reconnect to
495 * @param bias the speed to iterate to this new Positions
496 */
497void PNode::softReparent(const char* parentName, float bias)
498{
499  PNode* parentNode = dynamic_cast<PNode*>(ClassList::getObject(parentName, CL_PARENT_NODE));
500  if (parentNode != NULL)
501    this->softReparent(parentNode, bias);
502}
503
504/**
505 *  sets the mode of this parent manually
506 * @param parentMode a String representing this parentingMode
507 */
508void PNode::setParentMode (const char* parentingMode)
509{
510  this->setParentMode(PNode::charToParentingMode(parentingMode));
511}
512
513/**
514 *  updates the absCoordinate/absDirection
515 * @param dt The time passed since the last update
516
517   this is used to go through the parent-tree to update all the absolute coordinates
518   and directions. this update should be done by the engine, so you don't have to
519   worry, normaly...
520*/
521void PNode::update (float dt)
522{
523  if( likely(this->parent != NULL))
524    {
525      // movement for nodes with smoothMove enabled
526      if (unlikely(this->toCoordinate != NULL))
527      {
528        Vector moveVect = (*this->toCoordinate - this->getRelCoor()) *dt*bias;
529
530        if (likely(moveVect.len() >= PNODE_ITERATION_DELTA))
531        {
532          this->shiftCoor(moveVect);
533        }
534        else
535        {
536          delete this->toCoordinate;
537          this->toCoordinate = NULL;
538          PRINTF(5)("SmoothMove of %s finished\n", this->getName());
539        }
540      }
541      if (unlikely(this->toDirection != NULL))
542      {
543        Quaternion rotQuat = Quaternion::quatSlerp(Quaternion(), (*this->toDirection / this->relDirection), dt*this->bias);
544        if (likely(rotQuat.getSpacialAxisAngle() > PNODE_ITERATION_DELTA))
545        {
546          this->shiftDir(rotQuat);
547        }
548        else
549        {
550          delete this->toDirection;
551          this->toDirection = NULL;
552          PRINTF(0)("SmoothRotate of %s finished\n", this->getName());
553        }
554      }
555
556      // MAIN UPDATE /////////////////////////////////////
557      this->lastAbsCoordinate = this->absCoordinate;
558
559      PRINTF(5)("PNode::update - %s - (%f, %f, %f)\n", this->getName(), this->absCoordinate.x, this->absCoordinate.y, this->absCoordinate.z);
560
561
562      if( this->parentMode & PNODE_LOCAL_ROTATE && this->bRelDirChanged)
563      {
564        /* update the current absDirection - remember * means rotation around sth.*/
565        this->absDirection = this->relDirection * parent->getAbsDir();;
566      }
567
568      if(likely(this->parentMode & PNODE_MOVEMENT))
569      {
570        /* update the current absCoordinate */
571        this->absCoordinate = this->parent->getAbsCoor() + this->relCoordinate;
572      }
573      else if( this->parentMode & PNODE_ROTATE_MOVEMENT)
574      {
575        /* update the current absCoordinate */
576        this->absCoordinate = this->parent->getAbsCoor() + parent->getAbsDir().apply(this->relCoordinate);
577      }
578      /////////////////////////////////////////////////
579   }
580  else
581    {
582      PRINTF(4)("NullParent::update - (%f, %f, %f)\n", this->absCoordinate.x, this->absCoordinate.y, this->absCoordinate.z);
583      if (this->bRelCoorChanged)
584        this->absCoordinate = this->relCoordinate;
585      if (this->bRelDirChanged)
586        this->absDirection = this->getAbsDir () * this->relDirection;
587    }
588
589    if(this->children->getSize() > 0)
590    {
591      tIterator<PNode>* iterator = this->children->getIterator();
592      PNode* pn = iterator->nextElement();
593      while( pn != NULL)
594      {
595        /* if this node has changed, make sure, that all children are updated also */
596        if( likely(this->bRelCoorChanged))
597          pn->parentCoorChanged ();
598        if( likely(this->bRelDirChanged))
599          pn->parentDirChanged ();
600
601        pn->update(dt);
602          //pn = this->children->nextElement();
603        pn = iterator->nextElement();
604      }
605      delete iterator;
606    }
607    this->velocity = (this->absCoordinate - this->lastAbsCoordinate) / dt;
608    this->bRelCoorChanged = false;
609    this->bRelDirChanged = false;
610}
611
612/**
613 *  displays some information about this pNode
614 * @param depth The deph into which to debug the children of this PNode to.
615  (0: all children will be debugged, 1: only this PNode, 2: this and direct children...)
616 * @param level The n-th level of the Node we draw (this is internal and only for nice output)
617*/
618void PNode::debug(unsigned int depth, unsigned int level) const
619{
620  for (unsigned int i = 0; i < level; i++)
621    PRINT(0)(" |");
622  if (this->children->getSize() > 0)
623    PRINT(0)(" +");
624  else
625    PRINT(0)(" -");
626  PRINT(0)("PNode(%s::%s) - absCoord: (%0.2f, %0.2f, %0.2f), relCoord(%0.2f, %0.2f, %0.2f), direction(%0.2f, %0.2f, %0.2f) - %s\n",
627           this->getClassName(),
628           this->getName(),
629           this->absCoordinate.x,
630           this->absCoordinate.y,
631           this->absCoordinate.z,
632           this->relCoordinate.x,
633           this->relCoordinate.y,
634           this->relCoordinate.z,
635           this->getAbsDirV().x,
636           this->getAbsDirV().y,
637           this->getAbsDirV().z,
638           this->parentingModeToChar(parentMode));
639  if (depth >= 2 || depth == 0)
640  {
641    tIterator<PNode>* iterator = this->children->getIterator();
642      //PNode* pn = this->children->enumerate ();
643    PNode* pn = iterator->nextElement();
644    while( pn != NULL)
645    {
646      if (depth == 0)
647        pn->debug(0, level + 1);
648      else
649        pn->debug(depth - 1, level +1);
650      pn = iterator->nextElement();
651    }
652    delete iterator;
653  }
654}
655#include "color.h"
656
657/**
658   displays the PNode at its position with its rotation as a cube.
659*/
660void PNode::debugDraw(unsigned int depth, float size, Vector color) const
661{
662  glMatrixMode(GL_MODELVIEW);
663  glPushMatrix();
664  glDisable(GL_LIGHTING);
665
666  /* translate */
667  glTranslatef (this->getAbsCoor ().x,
668                this->getAbsCoor ().y,
669                this->getAbsCoor ().z);
670  /* rotate */
671//  this->getAbsDir ().matrix (matrix);
672//  glMultMatrixf((float*)matrix);
673
674  Vector tmpRot = this->getAbsDir().getSpacialAxis();
675  glColor3f(color.x, color.y, color.z);
676  glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
677  {
678    glBegin(GL_LINE_STRIP);
679    glVertex3f(-.5*size, -.5*size,  -.5*size);
680    glVertex3f(+.5*size, -.5*size,  -.5*size);
681    glVertex3f(+.5*size, -.5*size,  +.5*size);
682    glVertex3f(-.5*size, -.5*size,  +.5*size);
683    glVertex3f(-.5*size, -.5*size,  -.5*size);
684    glEnd();
685    glBegin(GL_LINE_STRIP);
686    glVertex3f(-.5*size, +.5*size,  -.5*size);
687    glVertex3f(+.5*size, +.5*size,  -.5*size);
688    glVertex3f(+.5*size, +.5*size,  +.5*size);
689    glVertex3f(-.5*size, +.5*size,  +.5*size);
690    glVertex3f(-.5*size, +.5*size,  -.5*size);
691    glEnd();
692
693    glBegin(GL_LINES);
694    glVertex3f(-.5*size, -.5*size,  -.5*size);
695    glVertex3f(-.5*size, +.5*size,  -.5*size);
696    glVertex3f(+.5*size, -.5*size,  -.5*size);
697    glVertex3f(+.5*size, +.5*size,  -.5*size);
698    glVertex3f(+.5*size, -.5*size,  +.5*size);
699    glVertex3f(+.5*size, +.5*size,  +.5*size);
700    glVertex3f(-.5*size, -.5*size,  +.5*size);
701    glVertex3f(-.5*size, +.5*size,  +.5*size);
702    glEnd();
703  }
704
705  glPopMatrix();
706  glEnable(GL_LIGHTING);
707  if (depth >= 2 || depth == 0)
708  {
709    tIterator<PNode>* iterator = this->children->getIterator();
710      //PNode* pn = this->children->enumerate ();
711    Vector childColor =  Color::HSVtoRGB(Color::RGBtoHSV(color)+Vector(20,0,.0));
712    PNode* pn = iterator->nextElement();
713    while( pn != NULL)
714    {
715      if (depth == 0)
716        pn->debugDraw(0, size, childColor);
717      else
718        pn->debugDraw(depth - 1, size, childColor);
719      pn = iterator->nextElement();
720    }
721    delete iterator;
722  }
723}
724
725
726
727/////////////////////
728// HELPER_FUCTIONS //
729/////////////////////
730
731/**
732 * converts a parentingMode into a string that is the name of it
733 * @param parentingMode the ParentingMode to convert
734 * @return the converted string
735 */
736const char* PNode::parentingModeToChar(int parentingMode)
737{
738  if (parentingMode == PNODE_LOCAL_ROTATE)
739    return "local-rotate";
740  else if (parentingMode == PNODE_ROTATE_MOVEMENT)
741    return "rotate-movement";
742  else if (parentingMode == PNODE_MOVEMENT)
743    return "movement";
744  else if (parentingMode == PNODE_ALL)
745    return "all";
746  else if (parentingMode == PNODE_ROTATE_AND_MOVE)
747    return "rotate-and-move";
748}
749
750/**
751 * converts a parenting-mode-string into a int
752 * @param parentingMode the string naming the parentingMode
753 * @return the int corresponding to the named parentingMode
754 */
755PARENT_MODE PNode::charToParentingMode(const char* parentingMode)
756{
757  if (!strcmp(parentingMode, "local-rotate"))
758    return (PNODE_LOCAL_ROTATE);
759  else  if (!strcmp(parentingMode, "rotate-movement"))
760    return (PNODE_ROTATE_MOVEMENT);
761  else  if (!strcmp(parentingMode, "movement"))
762    return (PNODE_MOVEMENT);
763  else  if (!strcmp(parentingMode, "all"))
764    return (PNODE_ALL);
765  else  if (!strcmp(parentingMode, "rotate-and-move"))
766    return (PNODE_ROTATE_AND_MOVE);
767}
Note: See TracBrowser for help on using the repository browser.