/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Patrick Boenzli co-programmer: ... \todo Null-Parent => center of the coord system - singleton \todo Smooth-Parent: delay, speed \todo destroy the stuff again, delete... */ #include "p_node.h" using namespace std; /** \brief standard constructor \todo this constructor is not jet implemented - do it */ PNode::PNode () { this->children = new tList(); this->bRelCoorChanged = true; this->bAbsCoorChanged = false; this->bRelDirChanged = true; this->bAbsDirChanged = false; this->parent = NULL; } /** \brief constructor with coodinates */ PNode::PNode (Vector* absCoordinate, PNode* parent ) { this->absCoordinate = *absCoordinate; this->relCoordinate = this->absCoordinate - parent->getAbsCoor (); this->children = new tList(); this->bRelCoorChanged = true; this->bAbsCoorChanged = false; this->bRelDirChanged = true; this->bAbsDirChanged = false; this->parent = parent; parent->addChild (this); } /** \brief standard deconstructor \todo this deconstructor is not jet implemented - do it */ PNode::~PNode () { /* delete &this->children; delete &this->relCoordinate; delete &this->absCoordinate; delete &this->relDirection; delete &this->absDirection; */ this->parent = NULL; /* there is currently a problem with cleaning up - fix*/ } /** \brief deletes the hole pnode tree cleans up all pnodes */ void PNode::destroy () { PNode* pn = this->children->enumerate(); while( pn != NULL) { pn->destroy (); pn = this->children->nextElement(); } this->children->destroy (); } /** \brief get relative coordinates \returns relative coordinates to its parent */ Vector PNode::getRelCoor () { Vector r = this->relCoordinate; /* return a copy, so it can't be modified */ return r; } /** \brief set relative coordinates \param relative coordinates to its parent it is very importand, that you use this function, if you want to update the relCoordinates. If you don't use this, the PNode won't recognize, that something has changed and won't update the children Nodes. */ void PNode::setRelCoor (Vector* relCoord) { this->bRelCoorChanged = true; this->relCoordinate = *relCoord; } /** \brief get absolute coordinates \returns absolute coordinates from (0,0,0) */ Vector PNode::getAbsCoor () { return this->absCoordinate; } /** \brief get relative coordinates \returns relative coordinates to its parent it is very importand, that you use this function, if you want to update the absCoordinates. If you don't use this, the PNode won't recognize, that something has changed and won't update the children Nodes. */ void PNode::setAbsCoor (Vector* absCoord) { this->bAbsCoorChanged = true; this->absCoordinate = *absCoord; } /** \brief shift coordinate (abs and rel) \param shift vector this function shifts the current coordinates about the vector shift. this is usefull because from some place else you can: PNode* someNode = ...; Vector objectMovement = calculateShift(); someNode->shiftCoor(objectMovement); elsewhere you would have to: PNode* someNode = ...; Vector objectMovement = calculateShift(); Vector currentCoor = someNode->getRelCoor(); Vector newCoor = currentCoor + objectMovement; someNode->setRelCoor(newCoor); yea right... shorter... */ void PNode::shiftCoor (Vector* shift) { if( this->bAbsCoorChanged) { this->absCoordinate = this->absCoordinate + *shift; } else { this->relCoordinate = this->relCoordinate + *shift; this->bRelCoorChanged = true; } } /** \brief get relative direction \returns relative direction to its parent */ Quaternion PNode::getRelDir () { return this->relDirection; } /** \brief set relative direction \param relative direction to its parent it is very importand, that you use this function, if you want to update the relDirection. If you don't use this, the PNode won't recognize, that something has changed and won't update the children Nodes. */ void PNode::setRelDir (Quaternion* relDir) { this->bRelCoorChanged = true; this->relDirection = *relDir; } /** \brief gets the absolute direction (0,0,1) \returns absolute coordinates */ Quaternion PNode::getAbsDir () { return this->absDirection; } /** \brief sets the absolute direction (0,0,1) \param absolute coordinates it is very importand, that you use this function, if you want to update the absDirection. If you don't use this, the PNode won't recognize, that something has changed and won't update the children Nodes. */ void PNode::setAbsDir (Quaternion* absDir) { this->bAbsDirChanged = true; this->absDirection = *absDir; } /** \brief shift coordinate (abs and rel) \param shift vector this function shifts the current coordinates about the vector shift. this is usefull because from some place else you can: PNode* someNode = ...; Quaternion objectMovement = calculateShift(); someNode->shiftCoor(objectMovement); elsewhere you would have to: PNode* someNode = ...; Quaternion objectMovement = calculateShift(); Quaternion currentCoor = someNode->getRelCoor(); Quaternion newCoor = currentCoor + objectMovement; someNode->setRelCoor(newCoor); yea right... shorter... */ void PNode::shiftDir (Quaternion* shift) {} /** \brief adds a child and makes this node to a parent \param child reference use this to add a child to this node. */ void PNode::addChild (PNode* pNode) { this->addChild(pNode, DEFAULT_MODE); } /** \brief adds a child and makes this node to a parent \param child reference \param on which changes the child should also change ist state use this to add a child to this node. */ void PNode::addChild (PNode* pNode, parentingMode mode) { pNode->mode = mode; pNode->parent = this; this->children->add (pNode); } /** /brief removes a child from the node */ void PNode::removeChild (PNode* pNode) { this->children->remove (pNode); } /** \brief sets the parent of this PNode */ void PNode::setParent (PNode* parent) { this->parent = parent; } /** \brief set the mode of this parent manualy */ void PNode::setMode (parentingMode mode) { this->mode = mode; } /** \brief has to be called, if the parent coordinate has changed normaly this will be done by the parent itself automaticaly. If you call this, you will force an update of the coordinated of the node. */ void PNode::parentCoorChanged () { this->bRelCoorChanged = true; } /** \brief has to be called, if the parent direction has changed normaly this will be done by the parent itself automaticaly. If you call this, you will force an update of the direction of the node. */ void PNode::parentDirChanged () { this->bRelDirChanged = true; } /** \brief updates the absCoordinate/absDirection this is used to go through the parent-tree to update all the absolute coordinates and directions. this update should be done by the engine, so you don't have to worry, normaly... */ void PNode::update (float timeStamp) { printf ("PNode::update - %s - (%f, %f, %f)\n", this->objectName, this->absCoordinate.x, this->absCoordinate.y, this->absCoordinate.z); if( this->mode == MOVEMENT || this->mode == ALL) { if( this->bAbsCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/) { printf("PNode::update () - this->bAbsCoorChanged = true\n"); /* if you have set the absolute coordinates this overrides all other changes */ this->relCoordinate = this->absCoordinate - parent->getAbsCoor (); } else if( this->bRelCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/) { /*this is bad style... must be deleted later - just for testing*/ if( this->parent == NULL) { this->absCoordinate = this->relCoordinate; } else this->absCoordinate = parent->getAbsCoor () + this->relCoordinate; /* update the current absCoordinate */ } } if( this->mode == ROTATION && this->mode == ALL) { if( this->bAbsDirChanged /*&& this->timeStamp != DataTank::timeStamp*/) { /* if you have set the absolute coordinates this overrides all other changes */ this->relDirection = this->absDirection - parent->getAbsDir (); } else if( this->bRelDirChanged /*&& this->timeStamp != DataTank::timeStamp*/) { /* update the current absDirection - remember * means rotation around sth.*/ this->absDirection = parent->getAbsDir () * this->relDirection; } } // } PNode* pn = this->children->enumerate(); while( pn != NULL) { /* if this node has changed, make sure, that all children are updated also */ if( this->bRelCoorChanged || this->bAbsCoorChanged) pn->parentCoorChanged (); if( this->bRelDirChanged || this->bAbsDirChanged) pn->parentDirChanged (); pn->update(timeStamp); pn = this->children->nextElement(); } this->timeStamp = timeStamp; this->bRelCoorChanged = false; this->bAbsCoorChanged = false; this->bRelDirChanged = false; this->bAbsDirChanged = false; } /* \brief tick */ void PNode::processTick (float dt) { this->tick (dt); PNode* pn = this->children->enumerate(); while( pn != NULL) { pn->processTick (dt); pn = this->children->nextElement(); } } void PNode::tick (float dt) {} void PNode::debug() { printf("PNode::debug() - absCoord: (%f, %f, %f)\n", this->absCoordinate.x, this->absCoordinate.y, this->absCoordinate.z); } /* \brief set the name of the node for debug purposes realy usefull, not used to work properly */ void PNode::setName (char* newName) { this->objectName = newName; } /* \brief gets the name of the node */ char* PNode::getName () { return this->objectName; }