/* 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 \param absCoordinate the Absolute coordinate of the Object \param parent The parent-node of this node. */ 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 relCoord 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; } /** \param absCoord set absolute coordinate 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 relDir 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 absDir 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... \todo implement this */ void PNode::shiftDir (Quaternion* shift) {} /** \brief adds a child and makes this node to a parent \param pNode 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 pNode child reference \param mode 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 \param pNode the child to remove from this pNode. */ void PNode::removeChild (PNode* pNode) { this->children->remove (pNode); } /** \brief sets the parent of this PNode \param parent the Parent to set */ void PNode::setParent (PNode* parent) { this->parent = parent; } /** \brief set the mode of this parent manualy \param mode the mode of the bind-type. */ 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 \param timeStamp The timestanp used for to look if calculations should be done 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 \param dt time to tick */ void PNode::processTick (float dt) { this->tick (dt); PNode* pn = this->children->enumerate(); while( pn != NULL) { pn->processTick (dt); pn = this->children->nextElement(); } } /** \param dt time to tick */ void PNode::tick (float dt) {} /** \brief displays some information about this pNode */ 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; }