VTreeNode.cpp

Engine/source/Verve/Core/VTreeNode.cpp

More...

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