Exemplo n.º 1
0
///////////////////////////////////////////////////////////////////////////////
// Adds undoable commands to m_Scene's undo queue which will do one of two thing:
// 
// Either...
// 1. Adds the currently selected scene items to the currently highlighted
// layers.  Set addToLayer to true for this option.
// or...
// 2. Removes the currently selected scene items from the currently highlighted
// layers.  Set addToLayer to false for this option.
//
// If there are no selected items, or no selected layers, nothing happens.  It 
// is also safe to remove items from a layer even if they are not part of the
// layer (nothing happens), or add items to a layer that already belong to
// that layer (again, nothing happens).
// 
void LayersPanel::LayerSelectedItems( bool addToLayer )
{
    HELIUM_ASSERT( m_Scene );

    // Decide whether we are adding the selected scene items to the highlighted
    // layers, or removing the items from the layers.
    const DependencyCommand::DependencyAction action = addToLayer ? DependencyCommand::Connect : DependencyCommand::Disconnect;

    // If there are selected nodes in the scene, and selected rows in this control...
    const OS_SceneNodeDumbPtr& selectedNodes = m_Scene->GetSelection().GetItems();
    std::set< uint32_t > selectedRows = m_Grid->GetSelectedRows();
    if ( selectedNodes.Size() > 0 && selectedRows.size() > 0 )
    {
        //Log::Debug( "LayerSelectedItems\n" );
        Undo::BatchCommandPtr batch = new Undo::BatchCommand ();

        OS_SceneNodeDumbPtr::Iterator nodeItr = selectedNodes.Begin();
        OS_SceneNodeDumbPtr::Iterator nodeEnd = selectedNodes.End();
        std::set< uint32_t >::const_iterator rowItr;
        const std::set< uint32_t >::const_iterator rowEnd = selectedRows.end();
        const M_LayerDumbPtr::const_iterator layerEnd = m_Layers.end();

        // For each node in the scene's selection list...
        for ( ; nodeItr != nodeEnd; ++nodeItr )
        {
            // ensure that we are not trying to add one layer to another layer
            {
                Layer* layerTest = Reflect::SafeCast< Layer >( *nodeItr );
                if( layerTest )
                {
                    continue;
                }
            }

            //Check the current selection
            if( *nodeItr == NULL )
            {
                //Invalid or incompatible
                continue;
            }

            SceneNode* node = Reflect::SafeCast< SceneNode >( *nodeItr );
            if ( node )
            {
                // For each row that is highlighted...
                for ( rowItr = selectedRows.begin(); rowItr != rowEnd; ++rowItr )
                {
                    // Find the layer that goes with the highlighted row
                    M_LayerDumbPtr::iterator layerItr = m_Layers.find( m_Grid->GetRowName( *rowItr ) );
                    if ( layerItr != layerEnd )
                    {
                        // Check to see if the node is already in the current layer...
                        Layer* layer = layerItr->second;
                        S_SceneNodeSmartPtr::const_iterator foundDescendant = layer->GetDescendants().find( node );

                        // If the node is already in this layer, and we are suppose to be adding the node to the layer,
                        // just skip the command (doCommand = false).  If the node is not in this layer, and we are
                        // suppose to be removing the node from the layer, skip the command as well.  Otherwise, go 
                        // ahead and carry out the command (doCommand = true).
                        const bool doCommand = addToLayer ? ( foundDescendant == layer->GetDescendants().end() ) : ( foundDescendant != layer->GetDescendants().end() );
                        if ( doCommand )
                        {
                            // Finally make an undoable command to add/remove the node to/from the layer
                            batch->Push( new DependencyCommand( action, layer, node ) );
                            //Log::Debug( "\t\t%s node %s %s layer %s [row=%d]\n", addToLayer ? "Added" : "Removed", node->GetName().c_str(), addToLayer ? "to" : "from", layer->GetName().c_str(), *rowItr );
                        }
                        else
                        {
                            //Log::Debug( "\t\tNode %s was already a member of layer %s [row=%d]\n", node->GetName().c_str(), layer->GetName().c_str(), *rowItr );
                        }
                    }
                    else
                    {
                        // Something is wrong.  The rows that are selected in the grid do not correspond to
                        // items in our list of layers (m_Layers).  Somehow those lists got out of sync.
                        Log::Error( TXT( "Unable to add selection to layer [row=%d] because it doesn't exist\n" ), *rowItr );
                        HELIUM_BREAK();
                    }
                }
            }
        }

        //Log::Debug( "\n" );
        if( !batch->IsEmpty() )
        {
            m_Scene->Push( batch );
            m_Scene->Execute( false );
        }
    }
}