← Back to team overview

kicad-developers team mailing list archive

Re: Zone keepouts within modules

 

I think I have it updated correctly now. There was a conflict in pcbnew/menubar_footprint_editor.cpp

See patch attached.

Simon


El 19/03/2018 a las 15:28, Jon Evans escribió:
Hi Simon,

Thanks for sharing your work! This sounds like a neat feature and I'd like to test it and give feedback. Unfortunately your patch does not apply against current master, and it looks like it is based on an old enough point that I couldn't fix the merge issues manually. Could you please rebase your patch against the latest master and re-send it?

Please note in case you haven't been following the developer list, we are in feature freeze for the 5.0 release and so we would only be able to merge new features like this once 6.0 development starts, so you'll likely need to rebase it once more before it can be merged at that point.

Thanks,
Jon

On Mon, Mar 19, 2018 at 8:02 AM, Simon Santesteban <tech@xxxxxxxxxxxx <mailto:tech@xxxxxxxxxxxx>> wrote:

    Hi everyone,

    I am a new developer in kicad community. I have been working on
    adding zones to modules, so I would like to share this work.
    Find attached a patch to have this functionality.

    Regards,

    Simon

    _______________________________________________
    Mailing list: https://launchpad.net/~kicad-developers
    <https://launchpad.net/%7Ekicad-developers>
    Post to     : kicad-developers@xxxxxxxxxxxxxxxxxxx
    <mailto:kicad-developers@xxxxxxxxxxxxxxxxxxx>
    Unsubscribe : https://launchpad.net/~kicad-developers
    <https://launchpad.net/%7Ekicad-developers>
    More help   : https://help.launchpad.net/ListHelp
    <https://help.launchpad.net/ListHelp>



From 94ab6176e8c1dd0314c054052463a46f5eb1ae19 Mon Sep 17 00:00:00 2001
From: embeblue <tech@xxxxxxxxxxxx>
Date: Mon, 19 Mar 2018 16:23:18 +0100
Subject: [PATCH] fix keepout area menu conflict
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.7.4"

This is a multi-part message in MIME format.
--------------2.7.4
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit

---
 pcbnew/board_commit.cpp                  |   4 +
 pcbnew/class_board.cpp                   |   6 ++
 pcbnew/class_board.h                     |  74 +++++++++++++
 pcbnew/class_module.cpp                  | 102 ++++++++++++++++++
 pcbnew/class_module.h                    |  45 ++++++++
 pcbnew/collectors.cpp                    |   2 +
 pcbnew/controle.cpp                      |   1 +
 pcbnew/drc.cpp                           |  24 ++---
 pcbnew/footprint_editor_onclick.cpp      |  91 +++++++++++++++-
 pcbnew/footprint_editor_utils.cpp        |   4 +
 pcbnew/kicad_clipboard.cpp               |   7 +-
 pcbnew/kicad_plugin.cpp                  |  21 +++-
 pcbnew/menubar_footprint_editor.cpp      |   7 +-
 pcbnew/pcb_parser.cpp                    |  23 +++-
 pcbnew/pcbnew_id.h                       |   1 +
 pcbnew/tool_footprint_editor.cpp         |   4 +
 pcbnew/tools/drawing_tool.cpp            |   8 +-
 pcbnew/tools/pcb_actions.cpp             |   1 +
 pcbnew/tools/pcbnew_control.cpp          |   5 +
 pcbnew/tools/selection_tool.cpp          |  11 ++
 pcbnew/tools/zone_create_helper.cpp      |   9 ++
 pcbnew/zone_filler.cpp                   |   5 +-
 pcbnew/zones_functions_for_undo_redo.cpp | 173 +++++++++++++++++++++++++++++++
 pcbnew/zones_functions_for_undo_redo.h   |  24 +++++
 24 files changed, 630 insertions(+), 22 deletions(-)


--------------2.7.4
Content-Type: text/x-patch; name="0001-fix-keepout-area-menu-conflict.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0001-fix-keepout-area-menu-conflict.patch"

diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp
index 57e0e68..fbbeeea 100644
--- a/pcbnew/board_commit.cpp
+++ b/pcbnew/board_commit.cpp
@@ -298,6 +298,10 @@ EDA_ITEM* BOARD_COMMIT::parentObject( EDA_ITEM* aItem ) const
         case PCB_MODULE_EDGE_T:
         case PCB_MODULE_TEXT_T:
             return aItem->GetParent();
+        case PCB_ZONE_AREA_T:
+			if(aItem->GetParent() && aItem->GetParent()->Type() == PCB_MODULE_T)
+				return aItem->GetParent();
+			// else do default
         default:
             return aItem;
     }
diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp
index c5486d8..3067f95 100644
--- a/pcbnew/class_board.cpp
+++ b/pcbnew/class_board.cpp
@@ -955,6 +955,12 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem )
                 break;
             }
         }
+        
+		// search inside modules
+		for( MODULE* module = m_Modules; module; module = module->Next() )
+        {
+			module->Remove(aBoardItem);
+		}
         break;
 
     case PCB_MODULE_T:
diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h
index 81a048e..22389cd 100644
--- a/pcbnew/class_board.h
+++ b/pcbnew/class_board.h
@@ -47,6 +47,8 @@
 
 #include <memory>
 
+#include <class_module.h>
+
 using std::unique_ptr;
 
 class PCB_BASE_FRAME;
@@ -1013,6 +1015,78 @@ public:
         return (int) m_ZoneDescriptorList.size();
     }
 
+
+    /**
+     * Function GetAreaIncludingModules
+     * returns the Area (Zone Container) at a given index, including modules.
+     * @param index The array type index into a collection of ZONE_CONTAINER *.
+     * @return ZONE_CONTAINER* - a pointer to the Area or NULL if index out of range.
+     */
+    ZONE_CONTAINER* GetAreaIncludingModules( int index ) const
+    {
+        if( (unsigned) index < m_ZoneDescriptorList.size() )
+            return m_ZoneDescriptorList[index];
+
+		int count = (int) m_ZoneDescriptorList.size();
+		for( MODULE* module = m_Modules; module; module = module->Next() )
+        {
+			int n_mod = module->GetAreaCount();
+			
+			if(index < count + n_mod) {
+				// is inside this module
+				int idx = index - count;
+				return module->GetArea(idx);
+			}
+			count += n_mod;
+		}
+		
+        return NULL;
+    }
+
+    /**
+     * Function GetAreaIndexIncludingModules
+     * returns the Area Index  for the given Zone Container, including modules.
+     * @param  aArea :The ZONE_CONTAINER to find.
+     * @return an Area Index in m_ZoneDescriptorList or -1 if non found.
+     */
+    int GetAreaIndexIncludingModules( const ZONE_CONTAINER* aArea ) const
+    {
+        for( int ii = 0; ii < GetAreaCount(); ii++ )    // Search for aArea in list
+        {
+            if( aArea == GetArea( ii ) )                // Found !
+                return ii;
+        }
+
+		int count = GetAreaCount();
+		for( MODULE* module = m_Modules; module; module = module->Next() )
+        {
+			int n_mod = module->GetAreaCount();
+			int idx = module->GetAreaIndex(aArea);
+			
+			if(idx >= 0) {
+				return idx + count;
+			}
+			count += n_mod;
+		}
+        return -1;
+    }
+
+    /**
+     * Function GetAreaCountIncludingModules
+     * @return int - The number of Areas or ZONE_CONTAINER including modules.
+     */
+    int GetAreaCountIncludingModules() const
+    {
+        int ret = GetAreaCount();
+        
+        for( MODULE* module = m_Modules; module; module = module->Next() )
+        {
+			ret += module->GetAreaCount();
+		}
+        
+        return ret;
+    }
+	
     /* Functions used in test, merge and cut outlines */
 
     /**
diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp
index 515dcee..0509f38 100644
--- a/pcbnew/class_module.cpp
+++ b/pcbnew/class_module.cpp
@@ -78,6 +78,8 @@ MODULE::MODULE( BOARD* parent ) :
     m_Value = new TEXTE_MODULE( this, TEXTE_MODULE::TEXT_is_VALUE );
 
     m_3D_Drawings.clear();
+    
+    m_ZoneDescriptorList.clear();
 }
 
 
@@ -140,6 +142,15 @@ MODULE::MODULE( const MODULE& aModule ) :
 
     m_arflag = 0;
 
+	// Copy zones
+	m_ZoneDescriptorList.clear();
+	for( int ii = 0; ii < aModule.GetAreaCount(); ii++ )
+	{
+		ZONE_CONTAINER* zone = aModule.GetArea( ii );
+		ZONE_CONTAINER* zone_clone = new ZONE_CONTAINER(*zone);
+		Add(static_cast<BOARD_ITEM*>(zone_clone), ADD_APPEND );
+	}
+
     // Ensure auxiliary data is up to date
     CalculateBoundingBox();
 
@@ -150,6 +161,12 @@ MODULE::MODULE( const MODULE& aModule ) :
 
 MODULE::~MODULE()
 {
+	while( m_ZoneDescriptorList.size() )
+    {
+        ZONE_CONTAINER* area_to_remove = m_ZoneDescriptorList[0];
+        Delete( area_to_remove );
+    }
+    
     delete m_Reference;
     delete m_Value;
     delete m_initial_comments;
@@ -218,6 +235,15 @@ MODULE& MODULE::operator=( const MODULE& aOther )
     m_Doc         = aOther.m_Doc;
     m_KeyWord     = aOther.m_KeyWord;
 
+	// Copy zones
+	m_ZoneDescriptorList.clear();
+	for( int ii = 0; ii < aOther.GetAreaCount(); ii++ )
+	{
+		ZONE_CONTAINER* zone = aOther.GetArea( ii );
+		ZONE_CONTAINER* zone_clone = new ZONE_CONTAINER(*zone);
+		Add(static_cast<BOARD_ITEM*>(zone_clone), ADD_APPEND );
+	}
+
     // Ensure auxiliary data is up to date
     CalculateBoundingBox();
 
@@ -225,6 +251,16 @@ MODULE& MODULE::operator=( const MODULE& aOther )
 }
 
 
+void MODULE::DeleteZONEOutlines()
+{
+    // the vector does not know how to delete the ZONE Outlines, it holds
+    // pointers
+    for( unsigned i = 0; i<m_ZoneDescriptorList.size(); ++i )
+        delete m_ZoneDescriptorList[i];
+
+    m_ZoneDescriptorList.clear();
+}
+
 void MODULE::ClearAllNets()
 {
     // Force the ORPHANED dummy net info for all pads.
@@ -274,6 +310,11 @@ void MODULE::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
             m_Pads.PushFront( static_cast<D_PAD*>( aBoardItem ) );
         break;
 
+    // this one uses a vector 
+    case PCB_ZONE_AREA_T:
+			m_ZoneDescriptorList.push_back( (ZONE_CONTAINER*) aBoardItem );
+        break;
+        
     default:
     {
         wxString msg;
@@ -302,6 +343,11 @@ void MODULE::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
         static_cast<D_PAD*>( aBoardItem )->SetLocalCoord();
         break;
 
+	case PCB_ZONE_AREA_T:
+		//static_cast<ZONE_CONTAINER*>( aBoardItem )->SetLocalCoord();
+		// TODO : create setlocalcoord function
+        break;
+    
     default:
         // Huh? It should have been filtered out by the previous switch
         assert(false);
@@ -328,6 +374,18 @@ void MODULE::Remove( BOARD_ITEM* aBoardItem )
         m_Pads.Remove( static_cast<D_PAD*>( aBoardItem ) );
         break;
 
+    case PCB_ZONE_AREA_T:    // this one uses a vector 
+        // find the item in the vector, then delete then erase it.
+        for( unsigned i = 0; i<m_ZoneDescriptorList.size(); ++i )
+        {
+            if( m_ZoneDescriptorList[i] == (ZONE_CONTAINER*) aBoardItem )
+            {
+                m_ZoneDescriptorList.erase( m_ZoneDescriptorList.begin() + i );
+                break;
+            }
+        }
+        break;
+        
     default:
     {
         wxString msg;
@@ -870,6 +928,19 @@ SEARCH_RESULT MODULE::Visit( INSPECTOR inspector, void* testData, const KICAD_T
 
             break;
 
+        case PCB_ZONE_AREA_T:
+            // PCB_ZONE_AREA_T are in the m_ZoneDescriptorList std::vector
+            for( unsigned i = 0; i< m_ZoneDescriptorList.size(); ++i )
+            {
+                result = m_ZoneDescriptorList[i]->Visit( inspector, testData, p );
+
+                if( result == SEARCH_QUIT )
+                    break;
+            }
+
+            ++p;
+            break;
+
         default:
             done = true;
             break;
@@ -916,6 +987,15 @@ void MODULE::RunOnChildren( const std::function<void (BOARD_ITEM*)>& aFunction )
         for( BOARD_ITEM* drawing = m_Drawings; drawing; drawing = drawing->Next() )
             aFunction( drawing );
 
+    	// for each module, its zones
+		for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+		{
+			ZONE_CONTAINER* zone = this->GetArea( ii );
+
+		
+			aFunction( static_cast<BOARD_ITEM*>( zone ) );
+		}
+
         aFunction( static_cast<BOARD_ITEM*>( m_Reference ) );
         aFunction( static_cast<BOARD_ITEM*>( m_Value ) );
     }
@@ -1101,6 +1181,13 @@ void MODULE::Flip( const wxPoint& aCentre )
             break;
         }
     }
+    
+	for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+	{
+		ZONE_CONTAINER* zone = this->GetArea( ii );
+
+		zone->Flip( m_Pos );	
+	}
 
     CalculateBoundingBox();
 }
@@ -1143,6 +1230,14 @@ void MODULE::SetPosition( const wxPoint& newpos )
             break;
         }
     }
+    
+	for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+	{
+		ZONE_CONTAINER* zone = this->GetArea( ii );
+
+		zone->Move( delta );
+	}
+
 
     CalculateBoundingBox();
 }
@@ -1251,6 +1346,13 @@ void MODULE::SetOrientation( double newangle )
         }
     }
 
+	for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+	{
+		ZONE_CONTAINER* zone = this->GetArea( ii );
+
+		zone->Rotate( GetPosition(), angleChange );		
+	}
+    
     CalculateBoundingBox();
 }
 
diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h
index 8b82b69..d705b6d 100644
--- a/pcbnew/class_module.h
+++ b/pcbnew/class_module.h
@@ -48,6 +48,9 @@
 
 #include <functional>
 
+#include <class_zone.h>
+
+
 class LINE_READER;
 class EDA_3D_CANVAS;
 class EDA_DRAW_PANEL;
@@ -102,6 +105,8 @@ class MODULE_3D_SETTINGS
         wxString m_Filename;    ///< The 3D shape filename in 3D library
 };
 
+DECL_VEC_FOR_SWIG(ZONE_CONTAINERS, ZONE_CONTAINER*)
+
 class MODULE : public BOARD_ITEM_CONTAINER
 {
 public:
@@ -710,13 +715,53 @@ public:
      */
     bool BuildPolyCourtyard();
 
+	void DeleteZONEOutlines();
+
     virtual void SwapData( BOARD_ITEM* aImage ) override;
 
+    ZONE_CONTAINERS& Zones() { return m_ZoneDescriptorList; }
+    
+    ZONE_CONTAINER* GetArea( int index ) const
+    {
+        if( (unsigned) index < m_ZoneDescriptorList.size() )
+            return m_ZoneDescriptorList[index];
+
+        return NULL;
+    }
+
+    /**
+     * Function GetAreaIndex
+     * returns the Area Index  for the given Zone Container.
+     * @param  aArea :The ZONE_CONTAINER to find.
+     * @return an Area Index in m_ZoneDescriptorList or -1 if non found.
+     */
+    int GetAreaIndex( const ZONE_CONTAINER* aArea ) const
+    {
+        for( int ii = 0; ii < GetAreaCount(); ii++ )    // Search for aArea in list
+        {
+            if( aArea == GetArea( ii ) )                // Found !
+                return ii;
+        }
+
+        return -1;
+    }
+
+    /**
+     * Function GetAreaCount
+     * @return int - The number of Areas or ZONE_CONTAINER.
+     */
+    int GetAreaCount() const
+    {
+        return (int) m_ZoneDescriptorList.size();
+    }
+
 #if defined(DEBUG)
     virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
 #endif
 
 private:
+    ZONE_CONTAINERS         m_ZoneDescriptorList;
+
     DLIST<D_PAD> m_Pads;                ///< Linked list of pads.
     DLIST<BOARD_ITEM> m_Drawings;       ///< Linked list of graphical items.
     std::list<MODULE_3D_SETTINGS> m_3D_Drawings;  ///< Linked list of 3D models.
diff --git a/pcbnew/collectors.cpp b/pcbnew/collectors.cpp
index 2219886..141cff5 100644
--- a/pcbnew/collectors.cpp
+++ b/pcbnew/collectors.cpp
@@ -115,6 +115,7 @@ const KICAD_T GENERAL_COLLECTOR::ModulesAndTheirItems[] = {
     PCB_MODULE_EDGE_T,
     PCB_PAD_T,
     PCB_MODULE_T,
+    PCB_ZONE_AREA_T,
     EOT
 };
 
@@ -123,6 +124,7 @@ const KICAD_T GENERAL_COLLECTOR::ModuleItems[] = {
     PCB_MODULE_TEXT_T,
     PCB_MODULE_EDGE_T,
     PCB_PAD_T,
+    PCB_ZONE_AREA_T,
     EOT
 };
 
diff --git a/pcbnew/controle.cpp b/pcbnew/controle.cpp
index 8ae024a..9e5e617 100644
--- a/pcbnew/controle.cpp
+++ b/pcbnew/controle.cpp
@@ -143,6 +143,7 @@ BOARD_ITEM* PCB_BASE_FRAME::PcbGeneralLocateAndDisplay( int aHotKeyCode )
 
         case ID_PCB_ZONES_BUTT:
         case ID_PCB_KEEPOUT_AREA_BUTT:
+        case ID_MODEDIT_KEEPOUT_AREA_TOOL:
             scanList = GENERAL_COLLECTOR::Zones;
             break;
 
diff --git a/pcbnew/drc.cpp b/pcbnew/drc.cpp
index f66e39c..0aa9a4b 100644
--- a/pcbnew/drc.cpp
+++ b/pcbnew/drc.cpp
@@ -190,9 +190,9 @@ int DRC::TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers )
     int nerrors = 0;
 
     // iterate through all areas
-    for( int ia = 0; ia < board->GetAreaCount(); ia++ )
+    for( int ia = 0; ia < board->GetAreaCountIncludingModules(); ia++ )
     {
-        ZONE_CONTAINER* zoneRef = board->GetArea( ia );
+		ZONE_CONTAINER* zoneRef = board->GetAreaIncludingModules( ia );
         SHAPE_POLY_SET refSmoothedPoly;
 
         zoneRef->BuildSmoothedPoly( refSmoothedPoly );
@@ -204,9 +204,9 @@ int DRC::TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers )
         if( aZone && ( aZone != zoneRef) )
             continue;
 
-        for( int ia2 = 0; ia2 < board->GetAreaCount(); ia2++ )
+        for( int ia2 = 0; ia2 < board->GetAreaCountIncludingModules(); ia2++ )
         {
-            ZONE_CONTAINER* zoneToTest = board->GetArea( ia2 );
+            ZONE_CONTAINER* zoneToTest = board->GetAreaIncludingModules( ia2 );
             SHAPE_POLY_SET testSmoothedPoly;
 
             zoneToTest->BuildSmoothedPoly( testSmoothedPoly );
@@ -762,9 +762,9 @@ void DRC::testZones()
     // In recent Pcbnew versions, the netcode is always >= 0, but an internal net name
     // is stored, and initialized from the file or the zone properties editor.
     // if it differs from the net name from net code, there is a DRC issue
-    for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
+    for( int ii = 0; ii < m_pcb->GetAreaCountIncludingModules(); ii++ )
     {
-        ZONE_CONTAINER* test_area = m_pcb->GetArea( ii );
+		ZONE_CONTAINER* test_area = m_pcb->GetAreaIncludingModules( ii );
 
         if( !test_area->IsOnCopperLayer() )
             continue;
@@ -792,10 +792,10 @@ void DRC::testZones()
 
 void DRC::testKeepoutAreas()
 {
-    // Test keepout areas for vias, tracks and pads inside keepout areas
-    for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
+    // Test keepout areas for vias, tracks and pads inside keepout areas, including modules'
+    for( int ii = 0; ii < m_pcb->GetAreaCountIncludingModules(); ii++ )
     {
-        ZONE_CONTAINER* area = m_pcb->GetArea( ii );
+		ZONE_CONTAINER* area = m_pcb->GetAreaIncludingModules( ii );
 
         if( !area->GetIsKeepout() )
         {
@@ -970,10 +970,10 @@ void DRC::testTexts()
 
 bool DRC::doTrackKeepoutDrc( TRACK* aRefSeg )
 {
-    // Test keepout areas for vias, tracks and pads inside keepout areas
-    for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
+    // Test keepout areas for vias, tracks and pads inside keepout areas, including modules'
+    for( int ii = 0; ii < m_pcb->GetAreaCountIncludingModules(); ii++ )
     {
-        ZONE_CONTAINER* area = m_pcb->GetArea( ii );
+		ZONE_CONTAINER* area = m_pcb->GetAreaIncludingModules( ii );
 
         if( !area->GetIsKeepout() )
             continue;
diff --git a/pcbnew/footprint_editor_onclick.cpp b/pcbnew/footprint_editor_onclick.cpp
index 333d9cb..3518052 100644
--- a/pcbnew/footprint_editor_onclick.cpp
+++ b/pcbnew/footprint_editor_onclick.cpp
@@ -44,6 +44,12 @@
 #include <dialog_edit_footprint_for_fp_editor.h>
 #include <menus_helpers.h>
 
+#include <zones_functions_for_undo_redo.h>
+#include <board_commit.h>
+#include <zone_filler.h>
+
+static PICKED_ITEMS_LIST s_PickedList;              // a picked list to save zones for undo/redo command
+static PICKED_ITEMS_LIST s_AuxiliaryList;           // a picked list to store zones that are deleted or added when combined
 
 void FOOTPRINT_EDIT_FRAME::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
 {
@@ -522,7 +528,6 @@ void FOOTPRINT_EDIT_FRAME::OnLeftDClick( wxDC* DC, const wxPoint& MousePos )
     }
 }
 
-
 void FOOTPRINT_EDIT_FRAME::OnEditItemRequest( wxDC* aDC, BOARD_ITEM* aItem )
 {
     switch( aItem->Type() )
@@ -553,6 +558,90 @@ void FOOTPRINT_EDIT_FRAME::OnEditItemRequest( wxDC* aDC, BOARD_ITEM* aItem )
         m_canvas->Refresh();
         break;
 
+	case PCB_ZONE_AREA_T:
+		{
+			ZONE_EDIT_T     edited;
+			ZONE_SETTINGS   zoneInfo = GetZoneSettings();
+
+			BOARD_COMMIT commit( this );
+			m_canvas->SetIgnoreMouseEvents( true );
+
+			ZONE_CONTAINER* aZone = static_cast<ZONE_CONTAINER*> ( aItem );
+			wxDC* DC = aDC;
+			
+			MODULE* parentModule = static_cast<MODULE*> ( aZone->GetParent() );
+			
+			if( !parentModule ) {
+				return;
+			}
+			
+			// Save initial zones configuration, for undo/redo, before adding new zone
+			// note the net name and the layer can be changed, so we must save all zones
+			s_AuxiliaryList.ClearListAndDeleteItems();
+			s_PickedList.ClearListAndDeleteItems();
+			SaveCopyOfZones( s_PickedList, parentModule, -1, UNDEFINED_LAYER );
+
+			if( aZone->GetIsKeepout() )
+			{
+				// edit a keepout area on a copper layer
+				zoneInfo << *aZone;
+				edited = InvokeKeepoutAreaEditor( this, &zoneInfo );
+			}
+			else if( IsCopperLayer( aZone->GetLayer() ) )
+			{
+				// edit a zone on a copper layer
+
+				zoneInfo << *aZone;
+
+				edited = InvokeCopperZonesEditor( this, &zoneInfo );
+			}
+			else
+			{
+				edited = InvokeNonCopperZonesEditor( this, aZone, &zoneInfo );
+			}
+
+			m_canvas->MoveCursorToCrossHair();
+			m_canvas->SetIgnoreMouseEvents( false );
+
+			if( edited == ZONE_ABORT )
+			{
+				s_AuxiliaryList.ClearListAndDeleteItems();
+				s_PickedList.ClearListAndDeleteItems();
+				return;
+			}
+
+			if( edited == ZONE_EXPORT_VALUES )
+			{
+				UpdateCopyOfZonesList( s_PickedList, s_AuxiliaryList, parentModule );
+				commit.Stage( s_PickedList );
+				commit.Push( _( "Modify zone properties" ) );
+				s_PickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items
+				return;
+			}
+
+			wxBusyCursor dummy;
+
+			// Undraw old zone outlines
+			for( int ii = 0; ii < parentModule->GetAreaCount(); ii++ )
+			{
+				ZONE_CONTAINER* edge_zone = parentModule->GetArea( ii );
+				edge_zone->Draw( m_canvas, DC, GR_XOR );
+
+				if( IsGalCanvasActive() )
+				{
+					GetGalCanvas()->GetView()->Update( edge_zone );
+				}
+			}
+
+			zoneInfo.ExportSetting( *aZone );
+
+			commit.Stage( s_PickedList );
+			commit.Push( _( "Modify zone properties" ) );
+
+			s_PickedList.ClearItemsList();  // s_ItemsListPicker is no longer owner of picked items
+		}
+        break;
+
     default:
         break;
     }
diff --git a/pcbnew/footprint_editor_utils.cpp b/pcbnew/footprint_editor_utils.cpp
index 7bc0c80..7be4d7c 100644
--- a/pcbnew/footprint_editor_utils.cpp
+++ b/pcbnew/footprint_editor_utils.cpp
@@ -959,6 +959,10 @@ void FOOTPRINT_EDIT_FRAME::OnVerticalToolbar( wxCommandEvent& aEvent )
         SetToolID( id, wxCURSOR_PENCIL, _( "Set grid origin" ) );
         break;
 
+    case ID_MODEDIT_KEEPOUT_AREA_TOOL:
+        SetToolID( id, wxCURSOR_PENCIL, _( "Add keepout" ) );
+        break;
+
     case ID_MODEDIT_PAD_TOOL:
         if( GetBoard()->m_Modules )
         {
diff --git a/pcbnew/kicad_clipboard.cpp b/pcbnew/kicad_clipboard.cpp
index 9b8c2f0..19d2da6 100644
--- a/pcbnew/kicad_clipboard.cpp
+++ b/pcbnew/kicad_clipboard.cpp
@@ -78,10 +78,13 @@ void CLIPBOARD_IO::SaveSelection( const SELECTION& aSelected )
     bool onlyModuleParts = true;
     for( const auto i : aSelected )
     {
-        // check if it not one of the module primitives
+        // check if it not one of the module primitives               
         if( ( i->Type() != PCB_MODULE_EDGE_T ) &&
                 ( i->Type() != PCB_MODULE_TEXT_T ) &&
-                ( i->Type() != PCB_PAD_T ) )
+                ( i->Type() != PCB_PAD_T ) &&
+                !( (i->Type() == PCB_ZONE_AREA_T ) && 
+					(i->GetParent()) && 
+					(i->GetParent()->Type() == PCB_MODULE_T) ) )
         {
             onlyModuleParts = false;
             continue;
diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp
index eef47d7..c83d1a9 100644
--- a/pcbnew/kicad_plugin.cpp
+++ b/pcbnew/kicad_plugin.cpp
@@ -1161,7 +1161,14 @@ void PCB_IO::format( MODULE* aModule, int aNestLevel ) const
         }
         ++bs3D;
     }
-
+    
+    // save zones
+	for( int ii = 0; ii < aModule->GetAreaCount(); ii++ )
+	{
+		ZONE_CONTAINER* zone = aModule->GetArea( ii );
+		format( zone, aNestLevel+1 );
+	};
+		
     m_out->Print( aNestLevel, ")\n" );
 }
 
@@ -1183,6 +1190,11 @@ void PCB_IO::formatLayers( LSET aLayerMask, int aNestLevel ) const
     static const LSET mask(  2, B_Mask,     F_Mask );
     static const LSET crt_yd(2, B_CrtYd,    F_CrtYd );
     static const LSET fab(   2, B_Fab,      F_Fab );
+    static const LSET inner(   30,
+		In1_Cu, In2_Cu, In3_Cu, In4_Cu, In5_Cu, In6_Cu, In7_Cu, In8_Cu, In9_Cu, In10_Cu,
+		In11_Cu, In12_Cu, In13_Cu, In14_Cu, In15_Cu, In16_Cu, In17_Cu, In18_Cu, In19_Cu, In20_Cu,
+		In21_Cu, In22_Cu, In23_Cu, In24_Cu, In25_Cu, In26_Cu, In27_Cu, In28_Cu, In29_Cu, In30_Cu
+	);
 
     LSET cu_mask = cu_all;
 
@@ -1238,6 +1250,13 @@ void PCB_IO::formatLayers( LSET aLayerMask, int aNestLevel ) const
         aLayerMask &= ~fab;
     }
 
+    if( ( aLayerMask & inner ) == inner )
+    {
+        output += " In*.Cu";
+        aLayerMask &= ~inner;
+    }
+
+
     // output any individual layers not handled in wildcard combos above
 
     if( m_board )
diff --git a/pcbnew/menubar_footprint_editor.cpp b/pcbnew/menubar_footprint_editor.cpp
index 17d8dae..1ae64a5 100644
--- a/pcbnew/menubar_footprint_editor.cpp
+++ b/pcbnew/menubar_footprint_editor.cpp
@@ -360,6 +360,12 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar()
 
     placeMenu->AppendSeparator();
 
+	// Keepout Area
+    AddMenuItem( placeMenu, ID_MODEDIT_KEEPOUT_AREA_TOOL,
+                 _( "&Keepout Area" ), _( "Add keepout areas" ), KiBitmap( add_keepout_area_xpm ) );
+
+    placeMenu->AppendSeparator();
+
     // Text
     AddMenuItem( placeMenu, ID_MODEDIT_TEXT_TOOL,
                  _( "&Text" ), _( "Add graphic text" ),
@@ -428,7 +434,6 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar()
                  _( "Choose and delete a footprint from the active library" ),
                  KiBitmap( delete_xpm ) );
 
-
     //----- Preferences menu -----------------
     wxMenu* prefs_menu = new wxMenu;
 
diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp
index 1de9777..1aade08 100644
--- a/pcbnew/pcb_parser.cpp
+++ b/pcbnew/pcb_parser.cpp
@@ -79,6 +79,11 @@ void PCB_PARSER::init()
     m_layerMasks[ "*.SilkS" ]   = LSET( 2, B_SilkS, F_SilkS );
     m_layerMasks[ "*.Fab" ]     = LSET( 2, B_Fab,   F_Fab );
     m_layerMasks[ "*.CrtYd" ]   = LSET( 2, B_CrtYd, F_CrtYd );
+    m_layerMasks[ "In*.Cu" ]   = LSET( 30,
+		In1_Cu, In2_Cu, In3_Cu, In4_Cu, In5_Cu, In6_Cu, In7_Cu, In8_Cu, In9_Cu, In10_Cu,
+		In11_Cu, In12_Cu, In13_Cu, In14_Cu, In15_Cu, In16_Cu, In17_Cu, In18_Cu, In19_Cu, In20_Cu,
+		In21_Cu, In22_Cu, In23_Cu, In24_Cu, In25_Cu, In26_Cu, In27_Cu, In28_Cu, In29_Cu, In30_Cu
+	);
 
     // This is for the first pretty & *.kicad_pcb formats, which had
     // Inner1_Cu - Inner14_Cu with the numbering sequence
@@ -2009,6 +2014,10 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
             module->Add3DModel( parse3DModel() );
             break;
 
+        case T_zone:
+			module->Add( parseZONE_CONTAINER(), ADD_APPEND );
+            break;
+
         default:
             Expecting( "locked, placed, tedit, tstamp, at, descr, tags, path, "
                        "autoplace_cost90, autoplace_cost180, solder_mask_margin, "
@@ -2834,7 +2843,19 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER()
     // bigger scope since each filled_polygon is concatenated in here
     SHAPE_POLY_SET pts;
 
-    std::unique_ptr< ZONE_CONTAINER > zone( new ZONE_CONTAINER( m_board ) );
+	std::unique_ptr< ZONE_CONTAINER > zone;
+	if(m_board != nullptr)
+	{
+		zone = std::unique_ptr< ZONE_CONTAINER > ( new ZONE_CONTAINER( m_board ) );
+	}else {
+		std::unique_ptr<BOARD> aBoard( new BOARD( ) );
+		//zone = std::unique_ptr< ZONE_CONTAINER > ( new ZONE_CONTAINER( nullptr ) );
+		//aBoard.get()->GetZoneSettings().ExportSetting( *(zone.get()) );
+		//aBoard->GetZoneSettings().ExportSetting( *zone );
+		
+		zone = std::unique_ptr< ZONE_CONTAINER > ( new ZONE_CONTAINER( aBoard.get() ) );
+		zone->SetParent( nullptr );
+	}
 
     zone->SetPriority( 0 );
 
diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h
index 86fc676..3db49d8 100644
--- a/pcbnew/pcbnew_id.h
+++ b/pcbnew/pcbnew_id.h
@@ -339,6 +339,7 @@ enum pcbnew_ids
 
     // Module editor right vertical tool bar commands.
     ID_MODEDIT_PAD_TOOL,
+    ID_MODEDIT_KEEPOUT_AREA_TOOL,
     ID_MODEDIT_LINE_TOOL,
     ID_MODEDIT_CIRCLE_TOOL,
     ID_MODEDIT_ARC_TOOL,
diff --git a/pcbnew/tool_footprint_editor.cpp b/pcbnew/tool_footprint_editor.cpp
index c8498be..5b0b30a 100644
--- a/pcbnew/tool_footprint_editor.cpp
+++ b/pcbnew/tool_footprint_editor.cpp
@@ -164,6 +164,10 @@ void FOOTPRINT_EDIT_FRAME::ReCreateVToolbar()
     m_drawToolBar->AddTool( ID_MODEDIT_PAD_TOOL, wxEmptyString, KiScaledBitmap( pad_xpm, this ),
                             _( "Add pad" ), wxITEM_CHECK );
 
+    m_drawToolBar->AddTool( ID_MODEDIT_KEEPOUT_AREA_TOOL, wxEmptyString,
+                            KiScaledBitmap( add_keepout_area_xpm, this ),
+                            _( "Add keepout areas" ), wxITEM_CHECK );
+
     KiScaledSeparator( m_drawToolBar, this );
     m_drawToolBar->AddTool( ID_MODEDIT_LINE_TOOL, wxEmptyString, KiScaledBitmap( add_graphical_segments_xpm, this ),
                             _( "Add graphic line" ), wxITEM_CHECK );
diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp
index f085ce9..55fadc8 100644
--- a/pcbnew/tools/drawing_tool.cpp
+++ b/pcbnew/tools/drawing_tool.cpp
@@ -644,7 +644,13 @@ int DRAWING_TOOL::DrawZoneKeepout( const TOOL_EVENT& aEvent )
 {
     SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::KEEPOUT );
 
-    m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add keepout" ) );
+	if( m_editModules )
+	{
+		m_frame->SetToolID( ID_MODEDIT_KEEPOUT_AREA_TOOL, wxCURSOR_PENCIL, _( "Add keepout" ) );
+	} else
+	{
+		m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add keepout" ) );
+	}
 
     return drawZone( true, ZONE_MODE::ADD );
 }
diff --git a/pcbnew/tools/pcb_actions.cpp b/pcbnew/tools/pcb_actions.cpp
index 2569bc3..6ac54a4 100644
--- a/pcbnew/tools/pcb_actions.cpp
+++ b/pcbnew/tools/pcb_actions.cpp
@@ -61,6 +61,7 @@ OPT<TOOL_EVENT> PCB_ACTIONS::TranslateLegacyId( int aId )
     case ID_PCB_DRAW_VIA_BUTT:
         return PCB_ACTIONS::drawVia.MakeEvent();
 
+    case ID_MODEDIT_KEEPOUT_AREA_TOOL:
     case ID_PCB_KEEPOUT_AREA_BUTT:
         return PCB_ACTIONS::drawZoneKeepout.MakeEvent();
 
diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp
index ea7a892..320094d 100644
--- a/pcbnew/tools/pcbnew_control.cpp
+++ b/pcbnew/tools/pcbnew_control.cpp
@@ -889,6 +889,11 @@ int PCBNEW_CONTROL::PasteItemsFromClipboard( const TOOL_EVENT& aEvent )
                     item->SetParent ( board()->m_Modules.GetFirst() );
                     items.push_back( item );
                 }
+                for( auto zone : mod->Zones() )
+				{
+					zone->SetParent ( board()->m_Modules.GetFirst() );
+					items.push_back( zone );
+				}
             }
             else
             {
diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp
index fe66646..83575f3 100644
--- a/pcbnew/tools/selection_tool.cpp
+++ b/pcbnew/tools/selection_tool.cpp
@@ -1535,6 +1535,17 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
         {
             auto* zone = static_cast<const ZONE_CONTAINER*>( aItem );
 
+			//check if zone has a parent of type module
+			if( zone && zone->GetParent() && (zone->GetParent()->Type() == PCB_MODULE_T) )
+			{
+				// only if not editing module
+				if(m_frame->IsType(FRAME_PCB_MODULE_EDITOR) == false)
+				{
+					return false;
+				}	
+				
+			}
+			
             if( zone && zone->GetIsKeepout() )
             {
                 auto zoneLayers = zone->GetLayerSet().Seq();
diff --git a/pcbnew/tools/zone_create_helper.cpp b/pcbnew/tools/zone_create_helper.cpp
index 933a56a..b1e3f02 100644
--- a/pcbnew/tools/zone_create_helper.cpp
+++ b/pcbnew/tools/zone_create_helper.cpp
@@ -92,6 +92,15 @@ std::unique_ptr<ZONE_CONTAINER> ZONE_CREATE_HELPER::createNewZone( bool aKeepout
 
     // Apply the selected settings
     zoneInfo.ExportSetting( *newZone );
+    
+    if(frame.IsType(FRAME_PCB_MODULE_EDITOR)) {
+		for( auto module : board.Modules() )
+		{
+			newZone->SetParent(module);
+			break;
+		}
+		
+	}
 
     return newZone;
 }
diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp
index 32a98fd..a66f03e 100644
--- a/pcbnew/zone_filler.cpp
+++ b/pcbnew/zone_filler.cpp
@@ -551,10 +551,9 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone,
         }
     }
 
-    // Add zones outlines having an higher priority and keepout
-    for( int ii = 0; ii < m_board->GetAreaCount(); ii++ )
+    for( int ii = 0; ii < m_board->GetAreaCountIncludingModules(); ii++ )
     {
-        ZONE_CONTAINER* zone = m_board->GetArea( ii );
+        ZONE_CONTAINER* zone = m_board->GetAreaIncludingModules( ii );
 
         // If the zones share no common layers
         if( !aZone->CommonLayerExists( zone->GetLayerSet() ) )
diff --git a/pcbnew/zones_functions_for_undo_redo.cpp b/pcbnew/zones_functions_for_undo_redo.cpp
index 97b02cb..9322f96 100644
--- a/pcbnew/zones_functions_for_undo_redo.cpp
+++ b/pcbnew/zones_functions_for_undo_redo.cpp
@@ -162,6 +162,33 @@ int SaveCopyOfZones( PICKED_ITEMS_LIST& aPickList, BOARD* aPcb, int aNetCode, LA
     return copyCount;
 }
 
+/**
+ * Function SaveCopyOfZones
+ * creates a copy of zones in a module having a given netcode on a given layer,
+ * and fill a pick list with pickers to handle these copies
+ * the UndoRedo status is set to UR_CHANGED for all items in list
+ * Later, UpdateCopyOfZonesList will change and update these pickers after a zone edition
+ * @param aPickList = the pick list
+ * @param aModule = the Module
+ * @param aNetCode = the reference netcode. if aNetCode < 0 all netcodes are used
+ * @param aLayer = the layer of zones. if aLayer < 0, all layers are used
+ * @return the count of saved copies
+ */
+int SaveCopyOfZones( PICKED_ITEMS_LIST& aPickList, MODULE* aModule, int aNetCode, LAYER_NUM aLayer )
+{
+    int copyCount = 0;
+
+	MODULE* moduleDup = new MODULE( *aModule );
+	moduleDup->SetParent ( aModule->GetParent () );
+	ITEM_PICKER picker( aModule, UR_CHANGED );
+	picker.SetLink( moduleDup );
+	aPickList.PushItem( picker );
+	copyCount++;	
+
+    return copyCount;
+}
+
+
 
 /**
  * Function UpdateCopyOfZonesList
@@ -307,3 +334,149 @@ void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList,
     wxASSERT_MSG( aAuxiliaryList.GetCount() == 0,
                   wxT( "UpdateCopyOfZonesList() error: aAuxiliaryList not empty." ) );
 }
+
+/**
+ * Function UpdateCopyOfZonesList
+ * check a pick list to remove zones identical to their copies in a module
+ * and set the type of operation in picker (UR_DELETED, UR_CHANGED)
+ * if an item is deleted, the initial values are retrievered,
+ * because they can have changed in edition
+ * @param aPickList = the main pick list
+ * @param aAuxiliaryList = the list of deleted or added (new created) items after calculations
+ * @param aModule = the Module
+ *
+ * aAuxiliaryList is a list of pickers updated by zone algorithms:
+ *  This list contains zones which were added or deleted during the zones combine process
+ * aPickList :is a list of zones that can be modified (changed or deleted, or not modified)
+ *  Typically, this is the list of existing zones on the layer of the edited zone,
+ *  before any change.
+ *  >> if the picked zone is not changed, it is removed from list
+ *  >> if the picked zone was deleted (i.e. not found in board list), the picker is modified:
+ *          its status becomes UR_DELETED
+ *          the aAuxiliaryList corresponding picker is removed (if not found : set an error)
+ *  >> if the picked zone was flagged as UR_NEW, and was after deleted ,
+ *  perhaps combined with an other zone  (i.e. not found in board list):
+ *          the picker is removed
+ *          the zone itself if really deleted
+ *          the aAuxiliaryList corresponding picker is removed (if not found : set an error)
+ * After aPickList is cleaned, the aAuxiliaryList is read
+ *  All pickers flagged UR_NEW are moved to aPickList
+ * (the corresponding zones are zone that were created by the zone normalize and combine process,
+ * mainly when adding cutout areas, or creating self intersecting contours)
+ *  All pickers flagged UR_DELETED are removed, and the coresponding zones actually deleted
+ * (the corresponding zones are new zone that were created by the zone normalize process,
+ * when creating self intersecting contours, and after combined with an existing zone.
+ * At the end of the update process the aAuxiliaryList must be void,
+ *  because all pickers created by the combine process
+ *  must have been removed (removed for new and deleted zones, or moved in aPickList.)
+ * If not an error is set.
+ */
+void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList,
+                            PICKED_ITEMS_LIST& aAuxiliaryList,
+                            MODULE*             aModule )
+{
+    for( unsigned kk = 0; kk < aPickList.GetCount(); kk++ )
+    {
+        UNDO_REDO_T  status = aPickList.GetPickedItemStatus( kk );
+
+        ZONE_CONTAINER* ref = (ZONE_CONTAINER*) aPickList.GetPickedItem( kk );
+
+        for( unsigned ii = 0; ; ii++ )  // analyse the main picked list
+        {
+            ZONE_CONTAINER* zone = aModule->GetArea( ii );
+
+            if( zone == NULL )
+            {
+                /* End of list: the stored item is not found:
+                 * it must be in aDeletedList:
+                 * search it and restore initial values
+                 * or
+                 * if flagged UR_NEW: remove it definitively
+                 */
+                if( status == UR_NEW )
+                {
+                    delete ref;
+                    ref = NULL;
+                    aPickList.RemovePicker( kk );
+                    kk--;
+                }
+                else
+                {
+                    ZONE_CONTAINER* zcopy = (ZONE_CONTAINER*) aPickList.GetPickedItemLink( kk );
+                    aPickList.SetPickedItemStatus( UR_DELETED, kk );
+
+                    wxASSERT_MSG( zcopy != NULL,
+                                  wxT( "UpdateCopyOfZonesList() error: link = NULL" ) );
+
+                    *ref = *zcopy;
+
+                    // the copy was deleted; the link does not exists now.
+                    aPickList.SetPickedItemLink( NULL, kk );
+                    delete zcopy;
+                }
+
+                // Remove this item from aAuxiliaryList, mainly for tests purpose
+                bool notfound = true;
+
+                for( unsigned nn = 0; nn < aAuxiliaryList.GetCount(); nn++ )
+                {
+                    if( ref != NULL && aAuxiliaryList.GetPickedItem( nn ) == ref )
+                    {
+                        aAuxiliaryList.RemovePicker( nn );
+                        notfound = false;
+                        break;
+                    }
+                }
+
+                if( notfound )  // happens when the new zone overlaps an existing zone
+                                // and these zones are combined
+                {
+                    DBG( printf(
+                        "UpdateCopyOfZonesList(): item not found in aAuxiliaryList,"
+                        "combined with an other zone\n" ) );
+                }
+                break;
+            }
+
+            if( zone == ref )      // picked zone found
+            {
+                if( aPickList.GetPickedItemStatus( kk ) != UR_NEW )
+                {
+                    ZONE_CONTAINER* zcopy = (ZONE_CONTAINER*) aPickList.GetPickedItemLink( kk );
+
+                    if( zone->IsSame( *zcopy ) )    // Remove picked, because no changes
+                    {
+                        delete zcopy;               // Delete copy
+                        aPickList.RemovePicker( kk );
+                        kk--;
+                    }
+                }
+
+                break;
+            }
+        }
+    }
+
+    // Add new zones in main pick list, and remove pickers from Auxiliary List
+    for( unsigned ii = 0; ii < aAuxiliaryList.GetCount(); )
+    {
+        if( aAuxiliaryList.GetPickedItemStatus( ii ) == UR_NEW )
+        {
+            ITEM_PICKER picker = aAuxiliaryList.GetItemWrapper( ii );
+            aPickList.PushItem( picker );
+            aAuxiliaryList.RemovePicker( ii );
+        }
+        else if( aAuxiliaryList.GetPickedItemStatus( ii ) == UR_DELETED )
+        {
+            delete aAuxiliaryList.GetPickedItemLink( ii );
+            aAuxiliaryList.RemovePicker( ii );
+        }
+        else
+            ii++;
+    }
+
+    // Should not occur:
+    wxASSERT_MSG( aAuxiliaryList.GetCount() == 0,
+                  wxT( "UpdateCopyOfZonesList() error: aAuxiliaryList not empty." ) );
+}
+
diff --git a/pcbnew/zones_functions_for_undo_redo.h b/pcbnew/zones_functions_for_undo_redo.h
index a5260a3..c420dde 100644
--- a/pcbnew/zones_functions_for_undo_redo.h
+++ b/pcbnew/zones_functions_for_undo_redo.h
@@ -58,6 +58,17 @@
  */
 int SaveCopyOfZones(PICKED_ITEMS_LIST & aPickList, BOARD* aPcb, int aNetCode, LAYER_NUM aLayer );
 
+/**
+ * Function SaveCopyOfZones
+ * creates a copy of zones in a module having a given netcode on a given layer,
+ * and fill a pick list with pickers to handle these copies
+ * @param aPickList = the pick list
+ * @param aModule = the Module
+ * @param aNetCode = the reference netcode. if aNetCode < 0 all netcodes are used
+ * @param aLayer = the layer of zones. if aLayer < 0, all layers are used
+ * @return the count of saved copies
+ */
+int SaveCopyOfZones( PICKED_ITEMS_LIST& aPickList, MODULE* aModule, int aNetCode, LAYER_NUM aLayer );
 
 /**
  * Function UpdateCopyOfZonesList
@@ -69,4 +80,17 @@ int SaveCopyOfZones(PICKED_ITEMS_LIST & aPickList, BOARD* aPcb, int aNetCode, LA
  */
 void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList, PICKED_ITEMS_LIST& aAuxiliaryList, BOARD* aPcb );
 
+
+/**
+ * Function UpdateCopyOfZonesList
+ * check a pick list to remove zones identical to their copies in a module
+ * and set the type of operation in picker (UR_DELETED, UR_CHANGED)
+ * @param aPickList = the main pick list
+ * @param aAuxiliaryList = the list of deleted or added (new created) items after calculations
+ * @param aModule = the Module
+ */
+void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList,
+                            PICKED_ITEMS_LIST& aAuxiliaryList,
+                            MODULE*             aModule );
+
 #endif      // ZONES_FUNCTIONS_TO_UNDO_REDO_H

--------------2.7.4--



Follow ups

References