From 54a541f22c683c15fafbeb9d820def85c6701897 Mon Sep 17 00:00:00 2001 From: charras Date: Tue, 4 Aug 2009 18:21:32 +0000 Subject: [PATCH] fixed crashes in eeschema, modedit and 3D display --- 3d-viewer/3d_canvas.cpp | 46 +++++++++++----------------- 3d-viewer/3d_draw.cpp | 11 +++++++ 3d-viewer/3d_frame.cpp | 14 ++++----- eeschema/schematic_undo_redo.cpp | 18 +++++++++-- pcbnew/board_undo_redo.cpp | 3 ++ pcbnew/class_edge_mod.cpp | 3 +- pcbnew/class_module.cpp | 16 ++++++---- pcbnew/dialog_edit_module.cpp | 51 ++++++++++++++++++-------------- pcbnew/modedit.cpp | 1 - pcbnew/modedit_onclick.cpp | 18 ++++++----- pcbnew/modedit_undo_redo.cpp | 35 ++++++++++++++-------- 11 files changed, 126 insertions(+), 90 deletions(-) diff --git a/3d-viewer/3d_canvas.cpp b/3d-viewer/3d_canvas.cpp index 612679ee01..787c8258b9 100644 --- a/3d-viewer/3d_canvas.cpp +++ b/3d-viewer/3d_canvas.cpp @@ -491,17 +491,6 @@ void Pcb3D_GLCanvas::OnPaint( wxPaintEvent& event ) /*************************************************/ { wxPaintDC dc( this ); - - // Set the OpenGL viewport according to the client size of this canvas. - // This is done here rather than in a wxSizeEvent handler because our - // OpenGL rendering context (and thus viewport setting) is used with - // multiple canvases: If we updated the viewport in the wxSizeEvent - // handler, changing the size of one canvas causes a viewport setting that - // is wrong when next another canvas is repainted. - const wxSize ClientSize = GetClientSize(); - - glViewport( 0, 0, ClientSize.x, ClientSize.y ); - Redraw(); event.Skip(); } @@ -529,6 +518,24 @@ void Pcb3D_GLCanvas::InitGL() m_init = TRUE; g_Parm_3D_Visu.m_Zoom = 1.0; ZBottom = 1.0; ZTop = 10.0; + + glDisable( GL_CULL_FACE ); // show back faces + + glEnable( GL_DEPTH_TEST ); // Enable z-buferring + + glEnable( GL_LINE_SMOOTH ); + glEnable( GL_COLOR_MATERIAL ); + glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); + + /* speedups */ + glEnable( GL_DITHER ); + glShadeModel( GL_SMOOTH ); + glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST ); + glHint( GL_POLYGON_SMOOTH_HINT, GL_FASTEST ); + + /* blend */ + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); } /* set viewing projection */ @@ -558,23 +565,6 @@ void Pcb3D_GLCanvas::InitGL() SetLights(); - glDisable( GL_CULL_FACE ); // show back faces - - glEnable( GL_DEPTH_TEST ); // Enable z-buferring - - glEnable( GL_LINE_SMOOTH ); - glEnable( GL_COLOR_MATERIAL ); - glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); - - /* speedups */ - glEnable( GL_DITHER ); - glShadeModel( GL_SMOOTH ); - glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST ); - glHint( GL_POLYGON_SMOOTH_HINT, GL_FASTEST ); - - /* blend */ - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); } diff --git a/3d-viewer/3d_draw.cpp b/3d-viewer/3d_draw.cpp index 2fb66478dc..2e145e1340 100644 --- a/3d-viewer/3d_draw.cpp +++ b/3d-viewer/3d_draw.cpp @@ -49,6 +49,17 @@ void Pcb3D_GLCanvas::Redraw( bool finish ) #else SetCurrent( ); #endif + + // Set the OpenGL viewport according to the client size of this canvas. + // This is done here rather than in a wxSizeEvent handler because our + // OpenGL rendering context (and thus viewport setting) is used with + // multiple canvases: If we updated the viewport in the wxSizeEvent + // handler, changing the size of one canvas causes a viewport setting that + // is wrong when next another canvas is repainted. + const wxSize ClientSize = GetClientSize(); + // *MUST* be called after SetCurrent( ): + glViewport( 0, 0, ClientSize.x, ClientSize.y ); + InitGL(); glMatrixMode( GL_MODELVIEW ); /* position viewer */ diff --git a/3d-viewer/3d_frame.cpp b/3d-viewer/3d_frame.cpp index d520fc6d49..fcd48e6041 100644 --- a/3d-viewer/3d_frame.cpp +++ b/3d-viewer/3d_frame.cpp @@ -73,15 +73,11 @@ WinEDA3D_DrawFrame::WinEDA3D_DrawFrame( WinEDA_BasePcbFrame* parent, ReCreateMenuBar(); ReCreateHToolbar(); -// ReCreateAuxiliaryToolbar(); + // ReCreateAuxiliaryToolbar(); ReCreateVToolbar(); // Make a Pcb3D_GLCanvas - m_Canvas = new Pcb3D_GLCanvas( this ); - - /* init OpenGL once */ - m_Canvas->InitGL(); } @@ -204,8 +200,8 @@ void WinEDA3D_DrawFrame::Process_Zoom( wxCommandEvent& event ) return; } - m_Canvas->DisplayStatus(); m_Canvas->Refresh( FALSE ); + m_Canvas->DisplayStatus(); } @@ -337,8 +333,8 @@ void WinEDA3D_DrawFrame::Process_Special_Functions( wxCommandEvent& event ) return; } - m_Canvas->DisplayStatus(); m_Canvas->Refresh( true ); + m_Canvas->DisplayStatus(); } @@ -348,9 +344,9 @@ void WinEDA3D_DrawFrame::NewDisplay() { m_Canvas->ClearLists(); m_Canvas->CreateDrawGL_List(); - m_Canvas->InitGL(); - m_Canvas->DisplayStatus(); +// m_Canvas->InitGL(); m_Canvas->Refresh( true ); + m_Canvas->DisplayStatus(); } diff --git a/eeschema/schematic_undo_redo.cpp b/eeschema/schematic_undo_redo.cpp index 8cecd43fde..6c4c2107c0 100644 --- a/eeschema/schematic_undo_redo.cpp +++ b/eeschema/schematic_undo_redo.cpp @@ -208,12 +208,22 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( SCH_ITEM* aItem, * saved in Undo List (for Undo or Redo commands, saved wires will be exchanged with current wire list */ { + /* Does not save a null item. + * but if aCommandType == UR_WIRE_IMAGE, we must save null item. + * It happens for the first wire entered in schematic: + * To undo this first command, the previous state is a NULL item, + * and we accept this + */ + if( aItem == NULL && (aCommandType != UR_WIRE_IMAGE) ) // Nothing to save + return; + SCH_ITEM* CopyOfItem; PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST(); commandToUndo->m_TransformPoint = aTransformPoint; ITEM_PICKER itemWrapper( aItem, aCommandType ); - itemWrapper.m_PickedItemType = aItem->Type(); + if( aItem ) + itemWrapper.m_PickedItemType = aItem->Type(); switch( aCommandType ) { @@ -270,6 +280,8 @@ void WinEDA_SchematicFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii ); + if( item == NULL ) + continue; UndoRedoOpType command = aItemsList.GetPickedItemStatus( ii ); if( command == UR_UNSPECIFIED ) { @@ -332,8 +344,8 @@ void WinEDA_SchematicFrame::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bo { ITEM_PICKER itemWrapper = aList->GetItemWrapper( ii ); item = (SCH_ITEM*) itemWrapper.m_PickedItem; - wxASSERT( item ); - item->m_Flags = 0; + if ( item ) + item->m_Flags = 0; SCH_ITEM* image = (SCH_ITEM*) itemWrapper.m_Link; switch( itemWrapper.m_UndoRedoStatus ) { diff --git a/pcbnew/board_undo_redo.cpp b/pcbnew/board_undo_redo.cpp index 81ccbca810..d4792eac0b 100644 --- a/pcbnew/board_undo_redo.cpp +++ b/pcbnew/board_undo_redo.cpp @@ -313,6 +313,9 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( BOARD_ITEM* aItem, * */ { + if( aItem == NULL ) // Nothing to save + return; + BOARD_ITEM* CopyOfItem; PICKED_ITEMS_LIST* commandToUndo = new PICKED_ITEMS_LIST(); diff --git a/pcbnew/class_edge_mod.cpp b/pcbnew/class_edge_mod.cpp index d36afba2a8..feff9920b6 100644 --- a/pcbnew/class_edge_mod.cpp +++ b/pcbnew/class_edge_mod.cpp @@ -40,8 +40,9 @@ EDGE_MODULE::~EDGE_MODULE() /********************************************/ -void EDGE_MODULE:: Copy( EDGE_MODULE* source ) // copy structure +void EDGE_MODULE::Copy( EDGE_MODULE* source ) /********************************************/ +// copy structure { if( source == NULL ) return; diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index 2f93f7f2bd..163bc3b37a 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -39,12 +39,11 @@ MODULE::MODULE( BOARD* parent ) : m_LastEdit_Time = time( NULL ); m_Reference = new TEXTE_MODULE( this, TEXT_is_REFERENCE ); -// m_Reference->SetBack( this ); m_Value = new TEXTE_MODULE( this, TEXT_is_VALUE ); -// m_Value->SetBack( this ); - m_3D_Drawings.PushBack( new S3D_MASTER( this ) ); // Reserve one void 3D entry + // Reserve one void 3D entry, to avoid problems with void list + m_3D_Drawings.PushBack( new S3D_MASTER( this ) ); } @@ -139,7 +138,9 @@ void MODULE::Copy( MODULE* aModule ) } /* Copy auxiliary data: 3D_Drawings info */ - m_3D_Drawings.DeleteAll(); + m_3D_Drawings.DeleteAll(); + // Ensure there is one (or more) item in m_3D_Drawings + m_3D_Drawings.PushBack( new S3D_MASTER( this ) ); // push a void item for( S3D_MASTER* item = aModule->m_3D_Drawings; item; item = item->Next() ) { if ( item->m_Shape3DName.IsEmpty() ) // do not copy empty shapes. @@ -861,8 +862,11 @@ void MODULE::DisplayInfo( WinEDA_DrawFrame* frame ) Affiche_1_Parametre( frame, pos, _( "Module" ), m_LibRef, BLUE ); pos += 9; - Affiche_1_Parametre( frame, pos, _( "3D-Shape" ), - m_3D_Drawings->m_Shape3DName, RED ); + if( m_3D_Drawings != NULL ) + msg = m_3D_Drawings->m_Shape3DName; + else + msg = _("No 3D shape"); + Affiche_1_Parametre( frame, pos, _( "3D-Shape" ), msg, RED ); pos += 14; wxString doc = _( "Doc: " ) + m_Doc; diff --git a/pcbnew/dialog_edit_module.cpp b/pcbnew/dialog_edit_module.cpp index 3b14606c00..0d71ed63e1 100644 --- a/pcbnew/dialog_edit_module.cpp +++ b/pcbnew/dialog_edit_module.cpp @@ -108,14 +108,17 @@ void WinEDA_ModulePropertiesFrame::CreateControls() /* creation des autres formes 3D */ Panel3D_Ctrl* panel3D = m_Panel3D, * nextpanel3D; S3D_MASTER* draw3D = m_CurrentModule->m_3D_Drawings; - draw3D = (S3D_MASTER*) draw3D->Next(); - for( ; draw3D != NULL; draw3D = (S3D_MASTER*) draw3D->Next() ) + if( draw3D ) { - nextpanel3D = new Panel3D_Ctrl( this, m_NoteBook, -1, draw3D ); - m_NoteBook->AddPage( nextpanel3D, _( "3D settings" ), FALSE ); - panel3D->m_Pnext = nextpanel3D; - nextpanel3D->m_Pback = panel3D; - panel3D = nextpanel3D; + draw3D = (S3D_MASTER*) draw3D->Next(); + for( ; draw3D != NULL; draw3D = (S3D_MASTER*) draw3D->Next() ) + { + nextpanel3D = new Panel3D_Ctrl( this, m_NoteBook, -1, draw3D ); + m_NoteBook->AddPage( nextpanel3D, _( "3D settings" ), FALSE ); + panel3D->m_Pnext = nextpanel3D; + nextpanel3D->m_Pback = panel3D; + panel3D = nextpanel3D; + } } /* Creation des boutons de commande */ @@ -596,38 +599,42 @@ void WinEDA_ModulePropertiesFrame::OnOkClick( wxCommandEvent& event ) if( m_Keyword ) m_CurrentModule->m_KeyWord = m_Keyword->GetValue(); - /* Mise a jour des parametres 3D */ + /* Update 3D shape list */ Panel3D_Ctrl* panel3D = m_Panel3D; S3D_MASTER* draw3D = m_CurrentModule->m_3D_Drawings; - S3D_MASTER* nextdraw3D; for( ; panel3D != NULL; panel3D = panel3D->m_Pnext ) { - draw3D->m_Shape3DName = panel3D->m_3D_ShapeName->GetValue(); + wxString name3D = panel3D->m_3D_ShapeName->GetValue();; + if( name3D.IsEmpty() ) + continue; + if( draw3D == NULL ) + { + draw3D = new S3D_MASTER( draw3D ); + m_CurrentModule->m_3D_Drawings.Append( draw3D ); + } + + draw3D->m_Shape3DName = name3D; draw3D->m_MatScale = panel3D->m_3D_Scale->GetValue(); draw3D->m_MatRotation = panel3D->m_3D_Rotation->GetValue(); draw3D->m_MatPosition = panel3D->m_3D_Offset->GetValue(); - if( ( draw3D->m_Shape3DName.IsEmpty() ) - && (draw3D != m_CurrentModule->m_3D_Drawings) ) - continue; - - if( (draw3D->Next() == NULL) && panel3D->m_Pnext ) - { - nextdraw3D = new S3D_MASTER( draw3D ); - - // insert after draw3D, therefore pass ->Next() to insert before the next. - m_CurrentModule->m_3D_Drawings.Insert( nextdraw3D, draw3D->Next() ); - } draw3D = (S3D_MASTER*) draw3D->Next(); } + // Remove old extra 3D shapes + S3D_MASTER* nextdraw3D; for( ; draw3D != NULL; draw3D = nextdraw3D ) { nextdraw3D = (S3D_MASTER*) draw3D->Next(); - delete m_CurrentModule->m_3D_Drawings.Remove( draw3D ); } + // Fill shape list with one void entry, if no entry + if( m_CurrentModule->m_3D_Drawings == NULL ) + m_CurrentModule->m_3D_Drawings.PushBack( new S3D_MASTER( m_CurrentModule ) ); + + + m_CurrentModule->Set_Rectangle_Encadrement(); m_Parent->GetScreen()->SetModify(); diff --git a/pcbnew/modedit.cpp b/pcbnew/modedit.cpp index c9f789bcf5..364c0974a2 100644 --- a/pcbnew/modedit.cpp +++ b/pcbnew/modedit.cpp @@ -27,7 +27,6 @@ BOARD_ITEM* WinEDA_ModuleEditFrame::ModeditLocateAndDisplay( int aHotKeyCode ) if( GetBoard()->m_Modules == NULL ) return NULL; - GENERAL_COLLECTORS_GUIDE guide = GetCollectorsGuide(); // Assign to scanList the proper item types desired based on tool type diff --git a/pcbnew/modedit_onclick.cpp b/pcbnew/modedit_onclick.cpp index 18427f28e2..e7c62cb918 100644 --- a/pcbnew/modedit_onclick.cpp +++ b/pcbnew/modedit_onclick.cpp @@ -113,15 +113,17 @@ void WinEDA_ModuleEditFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos ) break; case ID_MODEDIT_DELETE_ITEM_BUTT: - if( !DrawStruct || (DrawStruct->m_Flags == 0) ) + if( DrawStruct && (DrawStruct->m_Flags != 0) ) // Item in edit, cannot delete it + break; + DrawStruct = ModeditLocateAndDisplay(); + if( DrawStruct == NULL || (DrawStruct->m_Flags != 0) ) + break; + if( DrawStruct->Type() != TYPE_MODULE) //GetBoard()->m_Modules ) // Cannot delete the module itself { - DrawStruct = ModeditLocateAndDisplay(); - if( DrawStruct && (DrawStruct->m_Flags == 0) ) - { - SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); - RemoveStruct( DrawStruct ); - SetCurItem( DrawStruct = NULL ); - } + SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); + RemoveStruct( DrawStruct ); + DrawStruct = NULL; + SetCurItem( NULL ); } break; diff --git a/pcbnew/modedit_undo_redo.cpp b/pcbnew/modedit_undo_redo.cpp index b08660f1c3..776e5e1755 100644 --- a/pcbnew/modedit_undo_redo.cpp +++ b/pcbnew/modedit_undo_redo.cpp @@ -56,14 +56,14 @@ void WinEDA_ModuleEditFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, UndoRedoOpType aTypeCommand, const wxPoint& aTransformPoint ) { - // Currently Unused in modedit + // Currently unused in modedit, because the module itself is saved for each change wxMessageBox( wxT( "SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList..) not yet in use" ) ); } -/*********************************************************/ +/********************************************************************************/ void WinEDA_ModuleEditFrame::GetComponentFromRedoList( wxCommandEvent& event ) -/*********************************************************/ +/********************************************************************************/ /* Redo the last edition: * - Place the current edited library component in undo list @@ -73,18 +73,24 @@ void WinEDA_ModuleEditFrame::GetComponentFromRedoList( wxCommandEvent& event ) if( GetScreen()->GetRedoCommandCount() <= 0 ) return; + // Save current module state in undo list PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST(); - ITEM_PICKER wrapper( GetBoard()->m_Modules.PopFront(), UR_MODEDIT ); + MODULE * module = GetBoard()->m_Modules.PopFront(); + ITEM_PICKER wrapper( module, UR_MODEDIT ); lastcmd->PushItem( wrapper ); GetScreen()->PushCommandToUndoList( lastcmd ); + // Retrieve last module state from undo list lastcmd = GetScreen()->PopCommandFromRedoList(); - wrapper = lastcmd->PopItem(); + module = (MODULE *)wrapper.m_PickedItem; + delete lastcmd; - GetBoard()->Add( (MODULE*) wrapper.m_PickedItem ); + if( module ) + GetBoard()->Add( module ); + + SetCurItem( NULL ); - SetCurItem( NULL );; GetScreen()->SetModify(); ReCreateHToolbar(); SetToolbars(); @@ -104,21 +110,26 @@ void WinEDA_ModuleEditFrame::GetComponentFromUndoList( wxCommandEvent& event ) if( GetScreen()->GetUndoCommandCount() <= 0 ) return; + // Save current module state in redo list PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST(); - ITEM_PICKER wrapper( GetBoard()->m_Modules.PopFront(), UR_MODEDIT ); + MODULE * module = GetBoard()->m_Modules.PopFront(); + ITEM_PICKER wrapper( module, UR_MODEDIT ); lastcmd->PushItem( wrapper ); GetScreen()->PushCommandToRedoList( lastcmd ); + // Retrieve last module state from undo list lastcmd = GetScreen()->PopCommandFromUndoList(); - wrapper = lastcmd->PopItem(); + module = (MODULE *)wrapper.m_PickedItem; + delete lastcmd; - if( wrapper.m_PickedItem ) - GetBoard()->Add( (MODULE*) wrapper.m_PickedItem, ADD_APPEND ); + if( module ) + GetBoard()->Add( module, ADD_APPEND ); + SetCurItem( NULL );; + GetScreen()->SetModify(); - SetCurItem( NULL );; ReCreateHToolbar(); SetToolbars(); DrawPanel->Refresh();