Ejemplo n.º 1
0
///////////////////////////////////////////////////////////////////////////////
// Called when the "Select Layer Members" button is clicked on the toolbar.
//
void LayersPanel::OnSelectLayerMembers( wxCommandEvent& event )
{
    if ( m_Scene )
    {
        OS_SceneNodeDumbPtr newSelection;
        M_LayerDumbPtr::const_iterator layerItr = m_Layers.begin();
        M_LayerDumbPtr::const_iterator layerEnd = m_Layers.end();
        for ( ; layerItr != layerEnd; ++layerItr )
        {
            Layer* layer = layerItr->second;
            if ( m_Grid->IsSelected( layer->GetName() ) )
            {
                S_SceneNodeSmartPtr::const_iterator dependItr = layer->GetDescendants().begin();
                S_SceneNodeSmartPtr::const_iterator dependEnd = layer->GetDescendants().end();
                for ( ; dependItr != dependEnd; ++dependItr )
                {
                    newSelection.Append( *dependItr );
                }
            }
        }

        m_Scene->Push( m_Scene->GetSelection().SetItems( newSelection ) );
        m_Scene->Execute( false );
    }
}
Ejemplo n.º 2
0
void LayersPanel::DeleteSelectedLayers()
{
    // If anything selected in the grid
    if ( m_Scene && m_Grid->IsAnythingSelected() )
    {
        LayerSelectedItems( false );

        // Begin undo batch
        BatchUndoCommandPtr batch = new BatchUndoCommand ();

        // Get an ordered list of the selected rows, and traverse the list in reverse order.
        // This makes sure that removing an item doesn't change the row number of another
        // item that will be removed later in the loop.  If we don't do this, we run the
        // risk of invalidating the selection array as we iterate over it.
        const std::set< uint32_t >& selection = m_Grid->GetSelectedRows();
        std::set< uint32_t >::const_reverse_iterator rowItr = selection.rbegin();
        std::set< uint32_t >::const_reverse_iterator rowEnd = selection.rend();
        for ( ; rowItr != rowEnd; ++rowItr )
        {
            M_LayerDumbPtr::iterator layerItr = m_Layers.find( m_Grid->GetRowName( *rowItr ) );
            HELIUM_ASSERT( layerItr != m_Layers.end() );
            // NOTE: m_Layers is changing as we iterate over the selection (items are being
            // removed via callbacks), so don't hold on to any iterators that point into the list.
            // Recalculate m_Layers.end() each time through the loop.
            if ( layerItr != m_Layers.end() )
            {
                Layer* layer = layerItr->second;

                // If the layer that we are about to delete is in the scene's selection list,
                // we had better just clear out the selection list (otherwise the attribute
                // editor will still be showing a layer that is no longer in the scene).  This
                // has to be done before actually deleting the layer.
                if ( m_Scene->GetSelection().Contains( layer ) )
                {
                    batch->Push( m_Scene->GetSelection().Clear() );
                }

                // If the layer has any members, we should remove them before removing the layer,
                // otherwise if those members are deleted, they will be pointing to an invalid
                // layer that will eventually be Disconnected.
                S_SceneNodeSmartPtr descendents = layer->GetDescendants();
                for ( S_SceneNodeSmartPtr::iterator itr = descendents.begin(), end = descendents.end(); itr != end; ++itr )
                {
                    batch->Push( new DependencyCommand( DependencyCommand::Disconnect, layer, *itr ) );
                }

                // Push the command to delete the layer
                batch->Push( new SceneNodeExistenceCommand( ExistenceActions::Remove, m_Scene, layer ) );
            }
        }

        // End undo batch
        m_Scene->Push( batch );

        m_Scene->Execute( false );
    }
}
Ejemplo n.º 3
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_ObjectDumbPtr& selectedNodes = m_Scene->GetSelection().GetItems();
    std::set< uint32_t > selectedRows = m_Grid->GetSelectedRows();
    if ( selectedNodes.Size() > 0 && selectedRows.size() > 0 )
    {
        //Log::Debug( "LayerSelectedItems\n" );
        BatchUndoCommandPtr batch = new BatchUndoCommand ();

        OS_ObjectDumbPtr::Iterator nodeItr = selectedNodes.Begin();
        OS_ObjectDumbPtr::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 );
        }
    }
}