/* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "stdafx.h" #include "scenenodegroups.h" #include "Event.h" #include "MemCell.h" namespace scene { node_groups Groups; // requests creation of a new node group. returns: handle to the group scene::group_handle node_groups::create() { m_activegroup.push( create_handle() ); return handle(); } // indicates creation of current group ended. returns: handle to the parent group or null_handle if group stack is empty scene::group_handle node_groups::close() { if( false == m_activegroup.empty() ) { auto const closinggroup { m_activegroup.top() }; m_activegroup.pop(); // if the completed group holds only one item and there's no chance more items will be added, disband it if( ( true == m_activegroup.empty() ) || ( m_activegroup.top() != closinggroup ) ) { auto lookup { m_groupmap.find( closinggroup ) }; if( ( lookup != m_groupmap.end() ) && ( ( lookup->second.nodes.size() + lookup->second.events.size() ) <= 1 ) ) { erase( lookup ); } } } return handle(); } // returns current active group, or null_handle if group stack is empty group_handle node_groups::handle() const { return ( m_activegroup.empty() ? null_handle : m_activegroup.top() ); } // places provided node in specified group void node_groups::insert( scene::group_handle const Group, scene::basic_node *Node ) { // TBD, TODO: automatically unregister the node from its current group? Node->group( Group ); if( Group == null_handle ) { return; } auto &nodesequence { m_groupmap[ Group ].nodes }; if( std::find( std::begin( nodesequence ), std::end( nodesequence ), Node ) == std::end( nodesequence ) ) { // don't add the same node twice nodesequence.emplace_back( Node ); } } // places provided event in specified group void node_groups::insert( scene::group_handle const Group, basic_event *Event ) { // TBD, TODO: automatically unregister the event from its current group? Event->group( Group ); if( Group == null_handle ) { return; } auto &eventsequence { m_groupmap[ Group ].events }; if( std::find( std::begin( eventsequence ), std::end( eventsequence ), Event ) == std::end( eventsequence ) ) { // don't add the same node twice eventsequence.emplace_back( Event ); } } // sends basic content of the class in legacy (text) format to provided stream void node_groups::export_as_text( std::ostream &Output ) const { for( auto const &group : m_groupmap ) { Output << "group\n"; for( auto *node : group.second.nodes ) { // HACK: auto-generated memory cells aren't exported, so we check for this // TODO: is_exportable as basic_node method if( ( typeid( *node ) == typeid( TMemCell ) ) && ( false == static_cast( node )->is_exportable ) ) { continue; } node->export_as_text( Output ); } for( auto *event : group.second.events ) { event->export_as_text( Output ); } Output << "endgroup\n"; } } // removes specified group from the group list and group information from the group's nodes void node_groups::erase( group_map::const_iterator Group ) { for( auto *node : Group->second.nodes ) { node->group( null_handle ); } for( auto *event : Group->second.events ) { event->group( null_handle ); } m_groupmap.erase( Group ); } // creates handle for a new group group_handle node_groups::create_handle() { // NOTE: for simplification nested group structure are flattened return( m_activegroup.empty() ? m_groupmap.size() + 1 : // new group isn't created until node registration m_activegroup.top() ); } } // scene //---------------------------------------------------------------------------