/////////////////////////////////////////////////////////////////////////////// // 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 ); } }
/////////////////////////////////////////////////////////////////////////////// // Callback for when a selection change has been completed by a user interaction. // Updates the scene selection to match that of the tree. // void SceneOutliner::OnSelectionChanged( wxTreeEvent& args ) { EDITOR_SCOPE_TIMER( ("") ); if ( m_CurrentScene && !m_IgnoreSelectionChange ) { OS_SceneNodeDumbPtr nodes; wxArrayTreeItemIds selections; const size_t numSelections = m_TreeCtrl->GetSelections( selections ); for ( size_t i = 0; i < numSelections; i++ ) { SceneOutlinerItemData* itemData = GetTreeItemData( selections[i] ); if ( itemData ) { SceneNode* node = Reflect::SafeCast<SceneNode>( itemData->GetObject() ); if ( node ) { nodes.Append( node ); } } } // Set the selection on the scene. Note, the second parameter is a delegate that // tells the scene selection event not to pass the event back to this class since // we have already updated ourselves. m_CurrentScene->Push( m_CurrentScene->GetSelection().SetItems( nodes, SelectionChangingSignature::Delegate (), SelectionChangedSignature::Delegate( this, &SceneOutliner::SelectionChanged ) ) ); } }
/////////////////////////////////////////////////////////////////////////////// // Callback for when a row's selectability checkbox is changed in the grid. // Changes the selectability member of the layer to match the row that was // changed. // void LayersPanel::LayerSelectableChanged( const GridRowChangeArgs& args ) { const tstring& name = m_Grid->GetRowName( args.m_RowNumber ); M_LayerDumbPtr::const_iterator layerItr = m_Layers.find( name ); if ( layerItr != m_Layers.end() ) { Layer* layer = layerItr->second; bool selectable = m_Grid->IsRowSelectableChecked( args.m_RowNumber ); layer->SetSelectable( selectable ); if (!selectable) { OS_SceneNodeDumbPtr newSelection; OS_SceneNodeDumbPtr selection = layer->GetOwner()->GetSelection().GetItems(); OS_SceneNodeDumbPtr::Iterator itr = selection.Begin(); OS_SceneNodeDumbPtr::Iterator end = selection.End(); for ( ; itr != end; ++itr ) { SceneNode* node = Reflect::SafeCast<SceneNode>( *itr ); if (!node || !layer->ContainsMember( node )) { newSelection.Append(*itr); } } if (newSelection.Size() != selection.Size()) { layer->GetOwner()->GetSelection().SetItems( newSelection ); } } layer->GetOwner()->Execute( false ); } else { Log::Error( TXT( "LayerSelectableChanged - layer named %s not found\n" ), name.c_str() ); HELIUM_BREAK(); } }
/////////////////////////////////////////////////////////////////////////////// // Called when the "Select Layer" button is clicked on the toolbar. Goes // through all the layers that are currently selected in this control and // adds them to the scene's selection list (implicity this is an undoable // operation). // void LayersPanel::OnSelectLayer( wxCommandEvent& event ) { if ( m_Scene ) { OS_SceneNodeDumbPtr newSelection; const std::set< uint32_t >& selection = m_Grid->GetSelectedRows(); std::set< uint32_t >::const_iterator rowItr = selection.begin(); std::set< uint32_t >::const_iterator rowEnd = selection.end(); for ( ; rowItr != rowEnd; ++rowItr ) { M_LayerDumbPtr::iterator layerItr = m_Layers.find( m_Grid->GetRowName( *rowItr ) ); HELIUM_ASSERT( layerItr != m_Layers.end() ); Layer* layer = layerItr->second; newSelection.Append( layer ); } m_Scene->Push( m_Scene->GetSelection().SetItems( newSelection ) ); m_Scene->Execute( false ); } }
void PropertiesManager::GenerateProperties( PropertiesThreadArgs& args ) { M_ElementByType currentElements; M_ElementsByType commonElements; M_InterpretersByType commonElementInterpreters; EnumerateElementArgs enumerateElementArgs( currentElements, commonElements, commonElementInterpreters ); OS_SceneNodeDumbPtr selection; for ( OrderedSet<SceneNodePtr>::Iterator itr = args.m_Selection.Begin(), end = args.m_Selection.End(); itr != end; ++itr ) { selection.Append( *itr ); } // // First Pass: // Iterates over selection, asking each to enumerate their attributes into temp members (current) // Then coallate those results into an intersection member (common) // HELIUM_ASSERT( !selection.Empty() ); // intersection support M_PanelCreators intersectingPanels = s_PanelCreators; // union support typedef std::map< tstring, OS_SceneNodeDumbPtr > M_UnionedSelections; M_UnionedSelections unionedSelections; M_PanelCreators unionedPanels; { SCENE_GRAPH_SCOPE_TIMER( ("Selection Processing") ); OS_SceneNodeDumbPtr::Iterator itr = selection.Begin(); OS_SceneNodeDumbPtr::Iterator end = selection.End(); for ( size_t index = 0; itr != end; ++itr, ++index ) { if ( *args.m_CurrentSelectionId != args.m_SelectionId ) { return; } currentElements.clear(); { SCENE_GRAPH_SCOPE_TIMER( ("Object Property Enumeration") ); (*itr)->ConnectProperties(enumerateElementArgs); } M_PanelCreators currentPanels; #ifdef SCENE_DEBUG_PROPERTIES_GENERATOR Log::Print("Object type %s:\n", (*itr)->GetClass()->m_Name.c_str() ); #endif { SCENE_GRAPH_SCOPE_TIMER( ("Object Panel Validation") ); M_PanelCreators::const_iterator itrPanel = args.m_Style == PropertiesStyles::Intersection ? intersectingPanels.begin() : s_PanelCreators.begin(); M_PanelCreators::const_iterator endPanel = args.m_Style == PropertiesStyles::Intersection ? intersectingPanels.end() : s_PanelCreators.end(); for ( ; itrPanel != endPanel; ++itrPanel) { if ( *args.m_CurrentSelectionId != args.m_SelectionId ) { return; } if ((*itr)->ValidatePanel(itrPanel->first)) { #ifdef SCENE_DEBUG_PROPERTIES_GENERATOR Log::Print(" accepts %s\n", itrPanel->first.c_str()); #endif switch (m_Style) { case PropertiesStyles::Intersection: { currentPanels.insert( *itrPanel ); break; } case PropertiesStyles::Union: { unionedPanels.insert( *itrPanel ); Helium::StdInsert<M_UnionedSelections>::Result inserted = unionedSelections.insert( M_UnionedSelections::value_type ( itrPanel->first, OS_SceneNodeDumbPtr () ) ); inserted.first->second.Append( *itr ); } } } else { #ifdef SCENE_DEBUG_PROPERTIES_GENERATOR Log::Print(" rejects %s\n", itrPanel->first.c_str()); #endif } } } #ifdef SCENE_DEBUG_PROPERTIES_GENERATOR Log::Print("\n"); #endif if ( m_Style == PropertiesStyles::Intersection ) { intersectingPanels = currentPanels; } if (currentElements.empty()) { commonElements.clear(); } else { SCENE_GRAPH_SCOPE_TIMER( ("Object Unique Reflect Property Culling") ); M_ElementsByType newCommonElements; if (index == 0) { M_ElementByType::const_iterator currentItr = currentElements.begin(); M_ElementByType::const_iterator currentEnd = currentElements.end(); for ( ; currentItr != currentEnd; ++currentItr ) { if ( *args.m_CurrentSelectionId != args.m_SelectionId ) { return; } // copy the shared list into the new shared map Helium::StdInsert<M_ElementsByType>::Result inserted = newCommonElements.insert(M_ElementsByType::value_type( currentItr->first, std::vector<Reflect::Object*> () )); // add this current element's instance to the new shared list inserted.first->second.push_back(currentItr->second); } } else { M_ElementsByType::const_iterator sharedItr = commonElements.begin(); M_ElementsByType::const_iterator sharedEnd = commonElements.end(); for ( ; sharedItr != sharedEnd; ++sharedItr ) { if ( *args.m_CurrentSelectionId != args.m_SelectionId ) { return; } M_ElementByType::const_iterator found = currentElements.find(sharedItr->first); // if we found a current element entry for this shared element if (found != currentElements.end()) { // copy the shared list into the new shared map Helium::StdInsert<M_ElementsByType>::Result inserted = newCommonElements.insert(M_ElementsByType::value_type( sharedItr->first, sharedItr->second )); // add this current element's instance to the new shared list inserted.first->second.push_back(found->second); } else { // there is NO instance of this element in the current instance, let it be culled from the shared list } } } commonElements = newCommonElements; } // we have eliminated all the shared types, abort if (intersectingPanels.empty() && commonElements.empty() ) { break; } } } // // Second Pass: // Create client-constructed attribute panels // Inspect::ContainerPtr container = new Inspect::Container (); { SCENE_GRAPH_SCOPE_TIMER( ("Static Panel Creation") ); M_PanelCreators::const_iterator itr = args.m_Style == PropertiesStyles::Intersection ? intersectingPanels.begin() : unionedPanels.begin(); M_PanelCreators::const_iterator end = args.m_Style == PropertiesStyles::Intersection ? intersectingPanels.end() : unionedPanels.end(); for ( ; itr != end; ++itr ) { if ( *args.m_CurrentSelectionId != args.m_SelectionId ) { return; } switch ( args.m_Style ) { case PropertiesStyles::Intersection: { m_Generator->Push( container ); itr->second.Invoke( CreatePanelArgs (m_Generator, selection) ); m_Generator->Pop( false ); break; } case PropertiesStyles::Union: { M_UnionedSelections::const_iterator found = unionedSelections.find( itr->first ); if (found != unionedSelections.end()) { // this connects the invocation with the validated selection m_Generator->Push( container ); itr->second.Invoke( CreatePanelArgs (m_Generator, found->second) ); m_Generator->Pop( false ); } else { // something is horribly horribly wrong HELIUM_BREAK(); } break; } } // if you hit then, then your custom panel creator needs work HELIUM_ASSERT(m_Generator->GetContainerStack().empty()); } } // // Third Pass: // Iterates over resultant map and causes interpretation to occur for each object in the list // { SCENE_GRAPH_SCOPE_TIMER( ("Reflect Interpret") ); M_ElementsByType::const_iterator itr = commonElements.begin(); M_ElementsByType::const_iterator end = commonElements.end(); for ( ; itr != end; ++itr ) { if ( *args.m_CurrentSelectionId != args.m_SelectionId ) { return; } Inspect::ReflectInterpreterPtr interpreter = m_Generator->CreateInterpreter<Inspect::ReflectInterpreter>( container ); interpreter->Interpret(itr->second, itr->first.m_IncludeFlags, itr->first.m_ExcludeFlags); Helium::StdInsert<M_InterpretersByType>::Result inserted = commonElementInterpreters.insert( M_InterpretersByType::value_type(itr->first, interpreter) ); } } class Presenter { public: Presenter( PropertiesManager* propertiesManager, uint32_t selectionId, const Inspect::V_Control& controls ) : m_PropertiesManager( propertiesManager ) , m_SelectionId( selectionId ) , m_Controls( controls ) { } void Finalize( Helium::Void ) { m_PropertiesManager->Present( m_SelectionId, m_Controls ); delete this; } private: PropertiesManager* m_PropertiesManager; uint32_t m_SelectionId; Inspect::V_Control m_Controls; }; // release ownership of the controls now we have passed them onto the main thread for // realization and presentation to the user, this will try and unrealize the controls // from a background thread, but that is okay since they haven't been realized yet :) Presenter* presenter = new Presenter ( this, args.m_SelectionId, container->ReleaseChildren() ); // will cause the main thread to realize and present the controls m_CommandQueue->Post( VoidSignature::Delegate( presenter, &Presenter::Finalize ) ); }
bool CurveEditTool::ValidateSelection( OS_SceneNodeDumbPtr& items ) { OS_SceneNodeDumbPtr result; OS_SceneNodeDumbPtr::Iterator itr = items.Begin(); OS_SceneNodeDumbPtr::Iterator end = items.End(); for( ; itr != end; ++itr ) { CurveControlPoint* p = Reflect::SafeCast<CurveControlPoint>( *itr ); if ( !p ) { continue; } bool appendPoint = true; if ( s_CurrentSelection ) { appendPoint = false; OS_SceneNodeDumbPtr::Iterator curveItr = m_SelectedCurves.Begin(); OS_SceneNodeDumbPtr::Iterator curveEnd = m_SelectedCurves.End(); for ( ; curveItr != curveEnd; ++curveItr ) { if ( p->GetParent() == *curveItr ) { appendPoint = true; break; } } } if ( appendPoint ) { result.Append( p ); } } items = result; if ( items.Empty() ) { OS_SceneNodeDumbPtr::Iterator itr = items.Begin(); OS_SceneNodeDumbPtr::Iterator end = items.End(); for( ; itr != end; ++itr ) { Curve* c = Reflect::SafeCast<Curve>( *itr ); if ( !c ) { continue; } result.Append( c ); break; } } items = result; return !items.Empty(); }
void CurveEditTool::KeyPress( const KeyboardInput& e ) { if ( !m_Scene->IsEditable() ) { return; } int32_t keyCode = e.GetKeyCode(); if ( keyCode == KeyCodes::Left || keyCode == KeyCodes::Up || keyCode == KeyCodes::Right || keyCode == KeyCodes::Down ) { OS_SceneNodeDumbPtr selection = m_Scene->GetSelection().GetItems(); if ( selection.Empty() ) { return; } CurveControlPoint* point = Reflect::SafeCast<CurveControlPoint>( selection.Front() ); if ( !point ) { return; } Curve* curve = Reflect::SafeCast<Curve>( point->GetParent() ); if ( !curve ) { return; } int32_t index = curve->GetIndexForControlPoint( point ); if ( index == -1 ) { return; } uint32_t countControlPoints = curve->GetNumberControlPoints(); if ( keyCode == KeyCodes::Left || keyCode == KeyCodes::Down ) { index--; index += countControlPoints; index %= countControlPoints; } else if ( keyCode == KeyCodes::Right || keyCode == KeyCodes::Up ) { index++; index %= countControlPoints; } point = curve->GetControlPointByIndex( index ); selection.Clear(); selection.Append( point ); m_Scene->GetSelection().SetItems( selection ); } Base::KeyPress( e ); }