// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz // http://chaosforge.org/ // // This file is part of NV Libraries. // For conditions of distribution and use, see copyright notice in nv.hh #include "nv/object.hh" #include "nv/root.hh" #include "nv/types.hh" #include "nv/lua/lua_state.hh" #include "nv/uid.hh" using namespace nv; object::object() : m_root( nullptr ), m_id(), m_name(), m_uid(0), m_lua_index(-2), m_parent( nullptr ), m_children(), m_child_count(0) { } object::object( root* aroot, const string& aid ) : m_root( aroot ), m_id(aid), m_name(), m_uid( 0 ), m_lua_index(-2), m_parent( nullptr ), m_children(), m_child_count(0) { if ( m_root ) { uid_store* store = get_root()->get_uid_store(); lua::state* state = get_root()->get_lua_state(); if (store) { m_uid = store->insert( this ); } if (state) { m_lua_index = state->register_object( this ); } } } void object::add_child( object* child ) { if (child) { if (child->m_parent) { child->detach(); } child->m_parent = this; m_children.push_back( child ); m_child_count++; m_root->child_added( child ); } } void object::remove_child( object* child ) { if ( child->m_parent != this ) { return; // signal error? } list::iterator it = std::find( m_children.begin(), m_children.end(), child ); if ( it != m_children.end() ) { (*it)->m_parent = nullptr; m_children.erase(it); m_root->child_removed( child ); } } void object::detach() { if (m_parent) { m_parent->remove_child( this ); } } void object::change_parent( object* new_parent ) { if (m_parent) detach(); if (new_parent) new_parent->add_child( this ); } void object::destroy_children() { while ( !m_children.empty() ) { delete m_children.front(); } } object::~object() { if ( m_lua_index != lua::ref_none ) { lua::state* state = get_root()->get_lua_state(); state->unregister_object( this ); } if ( m_uid != 0 && m_root ) { uid_store* store = get_root()->get_uid_store(); if (store) store->remove( m_uid ); } detach(); destroy_children(); } object* object::find( object* child, bool recursive /*= false */ ) { list::iterator it = std::find( m_children.begin(), m_children.end(), child ); if ( it != m_children.end() ) { return *it; } if ( recursive ) { for ( object* i : m_children ) { object* r = i->find( child, recursive ); if (r) return r; } } return nullptr; } object* object::find( uid child, bool recursive /*= false */ ) { for ( object* i : m_children ) { if (i->m_uid == child) return i; } if ( recursive ) { for ( object* i : m_children ) { object* r = i->find( child, recursive ); if (r) return r; } } return nullptr; } object* object::find( string child, bool recursive /*= false */ ) { for ( object* i : m_children ) { if (i->m_id == child) return i; } if ( recursive ) { for ( object* i : m_children ) { object* r = i->find( child, recursive ); if (r) return r; } } return nullptr; } bool object::move_to_top( object* child ) { list::iterator it = std::find( m_children.begin(), m_children.end(), child ); if ( it != m_children.end() ) { m_children.erase( it ); m_children.push_back( child ); return true; } return false; } bool object::move_to_bottom( object* child ) { list::iterator it = std::find( m_children.begin(), m_children.end(), child ); if ( it != m_children.end() ) { m_children.erase( it ); m_children.push_front( child ); return true; } return false; } void object::register_type( type_database* db ) { type_field fields[] = { type_field("id", &object::m_id), type_field("uid", &object::m_uid).flag( TF_READONLY ), type_field("lua_index", &object::m_lua_index).flag( TF_READONLY | TF_NOSERIALIZE ), type_field("parent", &object::m_parent).flag( TF_READONLY | TF_NOSERIALIZE ), type_field("child_count", &object::m_child_count).flag( TF_READONLY ), type_field("children" , &object::m_children).flag( TF_READONLY ), }; db->create_type("object").fields(fields); }