VTreeNode.cpp
Engine/source/Verve/Core/VTreeNode.cpp
Detailed Description
1 2//----------------------------------------------------------------------------- 3// Verve 4// Copyright (C) 2014 - Violent Tulip 5// 6// Permission is hereby granted, free of charge, to any person obtaining a copy 7// of this software and associated documentation files (the "Software"), to 8// deal in the Software without restriction, including without limitation the 9// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10// sell copies of the Software, and to permit persons to whom the Software is 11// furnished to do so, subject to the following conditions: 12// 13// The above copyright notice and this permission notice shall be included in 14// all copies or substantial portions of the Software. 15// 16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22// IN THE SOFTWARE. 23//----------------------------------------------------------------------------- 24#include "Verve/Core/VTreeNode.h" 25#include "console/simObject.h" 26#include "platform/platform.h" 27 28//----------------------------------------------------------------------------- 29 30VTreeNode::VTreeNode( void ) 31{ 32 mParentNode = NULL; 33 mChildNode = NULL; 34 mSiblingPrevNode = NULL; 35 mSiblingNextNode = NULL; 36} 37 38VTreeNode::~VTreeNode( void ) 39{ 40 // Delete Children. 41 clear(); 42 43 // Detach. 44 remove(); 45} 46 47//----------------------------------------------------------------------------- 48// 49// Reference Methods. 50// 51//----------------------------------------------------------------------------- 52 53//----------------------------------------------------------------------------- 54// 55// VTreeNode::clear(); 56// 57// Delete all child nodes. 58// 59//----------------------------------------------------------------------------- 60void VTreeNode::clear( void ) 61{ 62 if ( !mChildNode ) 63 { 64 return; 65 } 66 67 while ( mChildNode ) 68 { 69 // Fetch Child Node. 70 ITreeNode *node = mChildNode; 71 72 // Clear It. 73 node->clear(); 74 75 // Detach It. 76 node->remove(); 77 78 // Delete It. 79 SimObject *object = dynamic_cast<SimObject*>( node ); 80 if ( object ) 81 { 82 object->deleteObject(); 83 } 84 else 85 { 86 delete node; 87 } 88 } 89} 90 91//----------------------------------------------------------------------------- 92// 93// ITreeNode Methods. 94// 95//----------------------------------------------------------------------------- 96 97//----------------------------------------------------------------------------- 98// 99// VTreeNode::getRoot(); 100// 101// Returns the root object. 102// 103//----------------------------------------------------------------------------- 104ITreeNode *VTreeNode::getRoot( void ) 105{ 106 ITreeNode *parent = this; 107 while ( parent->mParentNode ) 108 { 109 parent = parent->mParentNode; 110 } 111 112 return parent; 113} 114 115//----------------------------------------------------------------------------- 116// 117// VTreeNode::getParent(); 118// 119// Returns the parent object. 120// 121//----------------------------------------------------------------------------- 122ITreeNode *VTreeNode::getParent( void ) 123{ 124 return mParentNode; 125} 126 127//----------------------------------------------------------------------------- 128// 129// VTreeNode::getChild(); 130// 131// Returns the first child object. 132// 133//----------------------------------------------------------------------------- 134ITreeNode *VTreeNode::getChild( void ) 135{ 136 return mChildNode; 137} 138 139//----------------------------------------------------------------------------- 140// 141// VTreeNode::getChild(); 142// 143// Returns the first child object. 144// 145//----------------------------------------------------------------------------- 146ITreeNode *VTreeNode::getLastChild( void ) 147{ 148 // Any Nodes? 149 if ( !mChildNode ) 150 { 151 // Null. 152 return NULL; 153 } 154 155 // Front Node. 156 ITreeNode *lastNode = mChildNode; 157 158 // Fetch Last Node. 159 while ( lastNode->mSiblingNextNode ) 160 { 161 lastNode = lastNode->mSiblingNextNode; 162 } 163 164 // Return. 165 return lastNode; 166} 167 168//----------------------------------------------------------------------------- 169// 170// VTreeNode::getPrevSibling(); 171// 172// Returns the previous object in the linked list. 173// 174//----------------------------------------------------------------------------- 175ITreeNode *VTreeNode::getPrevSibling( void ) 176{ 177 return mSiblingPrevNode; 178} 179 180//----------------------------------------------------------------------------- 181// 182// VTreeNode::getNextSibling(); 183// 184// Returns the next object in the linked list. 185// 186//----------------------------------------------------------------------------- 187ITreeNode *VTreeNode::getNextSibling( void ) 188{ 189 return mSiblingNextNode; 190} 191 192//----------------------------------------------------------------------------- 193// 194// VTreeNode::size(); 195// 196// Returns the number of child objects. Only includes top level. 197// 198//----------------------------------------------------------------------------- 199int VTreeNode::size( void ) 200{ 201 int size = 0; 202 203 ITreeNode *node = mChildNode; 204 while ( node ) 205 { 206 size++; 207 208 node = node->mSiblingNextNode; 209 } 210 211 return size; 212} 213 214//----------------------------------------------------------------------------- 215// 216// VTreeNode::at( pIndex ); 217// 218// Returns the object at the given index. 219// 220//----------------------------------------------------------------------------- 221ITreeNode *VTreeNode::at( const int pIndex ) 222{ 223 int index = 0; 224 225 ITreeNode *node = mChildNode; 226 while ( node ) 227 { 228 if ( index++ == pIndex ) 229 { 230 return node; 231 } 232 233 node = node->mSiblingNextNode; 234 } 235 236 return NULL; 237} 238 239//----------------------------------------------------------------------------- 240// 241// VTreeNode::getIndex(); 242// 243// Returns the index of the object in relation to the sibling nodes. 244// 245//----------------------------------------------------------------------------- 246int VTreeNode::getIndex( void ) 247{ 248 if ( !inTree() ) 249 { 250 // No Index. 251 return 0; 252 } 253 254 ITreeNode *walk = NULL; 255 if ( mParentNode ) 256 { 257 walk = mParentNode->mChildNode; 258 } 259 else 260 { 261 walk = this; 262 while ( walk->mSiblingPrevNode ) 263 { 264 // Walk Up. 265 walk = walk->mSiblingPrevNode; 266 } 267 } 268 269 for ( int i = 0; walk; walk = walk->mSiblingNextNode, i++ ) 270 { 271 if ( walk == this ) 272 { 273 return i; 274 } 275 } 276 277 AssertFatal( false, "VTreeNode::getIndex() - Node List Broken?" ); 278 279 return 0; 280} 281 282//----------------------------------------------------------------------------- 283// 284// VTreeNode::addTo( pNode ); 285// 286// Attach this node to the back of the target node. 287// 288//----------------------------------------------------------------------------- 289void VTreeNode::addTo( ITreeNode *pNode ) 290{ 291 if ( inTree() ) 292 { 293 // Already In Tree. 294 return; 295 } 296 297 // Set Parent. 298 mParentNode = pNode; 299 300 if ( !pNode->mChildNode ) 301 { 302 // Store Child Node. 303 pNode->mChildNode = this; 304 } 305 else 306 { 307 // Front Node. 308 ITreeNode *headNode = pNode->mChildNode; 309 310 // Fetch Head Node. 311 while ( headNode->mSiblingNextNode ) 312 { 313 headNode = headNode->mSiblingNextNode; 314 } 315 316 // Reference Next Node. 317 headNode->mSiblingNextNode = this; 318 319 // Reference Previous Node. 320 mSiblingPrevNode = headNode; 321 } 322 323 // Callback. 324 onAttach(); 325} 326 327//----------------------------------------------------------------------------- 328// 329// VTreeNode::addToFront( pNode ); 330// 331// Attach this node to the front of the target node. 332// 333//----------------------------------------------------------------------------- 334void VTreeNode::addToFront( ITreeNode *pNode ) 335{ 336 if ( inTree() ) 337 { 338 // Already In Tree. 339 return; 340 } 341 342 // Set Parent. 343 mParentNode = pNode; 344 345 if ( !pNode->mChildNode ) 346 { 347 // Store Child Node. 348 pNode->mChildNode = this; 349 } 350 else 351 { 352 // First Node. 353 ITreeNode *childNode = pNode->mChildNode; 354 355 // Reference Previous Node. 356 childNode->mSiblingPrevNode = this; 357 358 // Reference Next Node. 359 mSiblingNextNode = childNode; 360 361 // Store Child Node. 362 pNode->mChildNode = this; 363 } 364 365 // Callback. 366 onAttach(); 367} 368 369//----------------------------------------------------------------------------- 370// 371// VTreeNode::remove(); 372// 373// Detach this node from the current parent node. 374// 375//----------------------------------------------------------------------------- 376void VTreeNode::remove( void ) 377{ 378 if ( !inTree() ) 379 { 380 return; 381 } 382 383 // Callback. 384 onDetach(); 385 386 if ( mParentNode && mParentNode->mChildNode == this ) 387 { 388 // Update Parent Reference. 389 mParentNode->mChildNode = mSiblingNextNode; 390 } 391 392 if ( mSiblingNextNode ) 393 { 394 // Update Previous Node. 395 mSiblingNextNode->mSiblingPrevNode = mSiblingPrevNode; 396 } 397 398 if ( mSiblingPrevNode ) 399 { 400 // Update Next Node. 401 mSiblingPrevNode->mSiblingNextNode = mSiblingNextNode; 402 } 403 404 // Remove References. 405 mParentNode = mSiblingPrevNode = mSiblingNextNode = NULL; 406} 407 408//----------------------------------------------------------------------------- 409// 410// VTreeNode::moveTo( pNode ); 411// 412// Detach this node and attach it to the target node. 413// 414//----------------------------------------------------------------------------- 415void VTreeNode::moveTo( ITreeNode *pNode ) 416{ 417 if ( inTree() ) 418 { 419 // Remove from Tree. 420 remove(); 421 } 422 423 // Add to tree. 424 addTo( pNode ); 425} 426 427//----------------------------------------------------------------------------- 428// 429// VTreeNode::onAttach(); 430// 431// This method will be called when this node, or a parent node, is attached to 432// a node. 433// 434//----------------------------------------------------------------------------- 435void VTreeNode::onAttach( void ) 436{ 437 // Notify Children. 438 for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) 439 { 440 node->onAttach(); 441 } 442} 443 444//----------------------------------------------------------------------------- 445// 446// VTreeNode::onDetach(); 447// 448// This method will be called when this node, or a parent node, is detached. 449// 450//----------------------------------------------------------------------------- 451void VTreeNode::onDetach( void ) 452{ 453 // Notify Children. 454 for ( ITreeNode *node = mChildNode; node != NULL; node = node->mSiblingNextNode ) 455 { 456 node->onDetach(); 457 } 458} 459 460//----------------------------------------------------------------------------- 461// 462// VTreeNode::inTree(); 463// 464// Returns true if the node is the a member of a node tree. 465// 466//----------------------------------------------------------------------------- 467bool VTreeNode::inTree( void ) 468{ 469 return !( mParentNode == NULL && 470 mSiblingPrevNode == NULL && 471 mSiblingNextNode == NULL ); 472} 473