From 31f3c445209dc86c91b81a803d7ae7f94a88a5ad Mon Sep 17 00:00:00 2001
From: Jon Evans <jon@craftyjon.com>
Date: Sat, 29 Mar 2025 16:47:13 -0400
Subject: [PATCH] API: Clear footprint caches when making changes

---
 pcbnew/api/api_handler_pcb.cpp | 10 ++++++++++
 pcbnew/footprint.cpp           | 11 +++++++++++
 pcbnew/footprint.h             |  3 +++
 3 files changed, 24 insertions(+)

diff --git a/pcbnew/api/api_handler_pcb.cpp b/pcbnew/api/api_handler_pcb.cpp
index 6af7e6668f..4e44b49b91 100644
--- a/pcbnew/api/api_handler_pcb.cpp
+++ b/pcbnew/api/api_handler_pcb.cpp
@@ -478,6 +478,16 @@ HANDLER_RESULT<ItemRequestStatus> API_HANDLER_PCB::handleCreateUpdateItemsIntern
         {
             BOARD_ITEM* boardItem = *optItem;
             commit->Modify( boardItem );
+
+            // Normally this is done by the footprint methods SetPosition, SetOrientation, etc
+            // Since the API is just using the assignment operator, we need to wipe out all the
+            // caches so that they will be rebuilt with any changes to the geometry made by the API
+            if( boardItem->Type() == PCB_FOOTPRINT_T )
+            {
+                auto boardFp = static_cast<FOOTPRINT*>( boardItem );
+                boardFp->InvalidateGeometryCaches();
+            }
+
             boardItem->CopyFrom( item.get() );
             boardItem->Serialize( newItem );
         }
diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp
index 3a88b4e86d..5ffb2a9245 100644
--- a/pcbnew/footprint.cpp
+++ b/pcbnew/footprint.cpp
@@ -955,6 +955,17 @@ void FOOTPRINT::CopyFrom( const BOARD_ITEM* aOther )
 }
 
 
+void FOOTPRINT::InvalidateGeometryCaches()
+{
+    m_boundingBoxCacheTimeStamp = 0;
+    m_textExcludedBBoxCacheTimeStamp = 0;
+    m_hullCacheTimeStamp = 0;
+
+    m_courtyard_cache_back_hash.Clear();
+    m_courtyard_cache_front_hash.Clear();
+}
+
+
 bool FOOTPRINT::IsConflicting() const
 {
     return HasFlag( COURTYARD_CONFLICT );
diff --git a/pcbnew/footprint.h b/pcbnew/footprint.h
index 529a44e024..44b74f7183 100644
--- a/pcbnew/footprint.h
+++ b/pcbnew/footprint.h
@@ -145,6 +145,9 @@ public:
         return aItem && aItem->Type() == PCB_FOOTPRINT_T;
     }
 
+    /// Resets the caches for this footprint, for example if it was modified via the API
+    void InvalidateGeometryCaches();
+
     LSET GetPrivateLayers() const { return m_privateLayers; }
     void SetPrivateLayers( const LSET& aLayers ) { m_privateLayers = aLayers; }