commit dd3e6b65b537161abfb62188254d60dba5984f2c
Author: Captain <87000456+captain0xff@users.noreply.github.com>
Date:   Sat Mar 21 05:52:51 2026 +0530

    Gui: update CoinPtr to not use boost::intrusive_ptr (#28427)

diff --git src/Gui/View3DInventor.cpp src/Gui/View3DInventor.cpp
index 807432fb68..037380390b 100644
--- src/Gui/View3DInventor.cpp
+++ src/Gui/View3DInventor.cpp
@@ -597,7 +597,7 @@ bool View3DInventor::setCamera(const char* pCamera)
     }
 
     // this is to make sure to reliably delete the node
-    CoinPtr<SoNode> camPtr(Cam, true);
+    CoinPtr<SoNode> camPtr {Cam};
 
     // toggle between perspective and orthographic camera
     if (Cam->getTypeId() != CamViewer->getTypeId()) {
diff --git src/Gui/ViewProvider.h src/Gui/ViewProvider.h
index 2c4600cc80..7680d46f9f 100644
--- src/Gui/ViewProvider.h
+++ src/Gui/ViewProvider.h
@@ -86,26 +86,102 @@ enum ViewStatus
 };
 
 
+/** Convenience smart pointer to manage the lifetime of coin nodes.
+ *
+ * This class is copied from Inventor/misc/SoRefPtr.h and can be removed when the
+ * minimum supported coin version provides this header.
+ */
+template<typename T>
+class SoRefPtr
+{
+public:
+    SoRefPtr(void) noexcept
+        : ptr(NULL)
+    {}
+
+    explicit SoRefPtr(T* p)
+        : ptr(p)
+    {
+        if (this->ptr) {
+            this->ptr->ref();
+        }
+    }
+
+    SoRefPtr(const SoRefPtr& other)
+        : ptr(other.ptr)
+    {
+        if (this->ptr) {
+            this->ptr->ref();
+        }
+    }
+
+    SoRefPtr(SoRefPtr&& other) noexcept
+        : ptr(other.ptr)
+    {
+        other.ptr = NULL;
+    }
+
+    ~SoRefPtr(void)
+    {
+        if (this->ptr) {
+            this->ptr->unref();
+        }
+    }
+
+    SoRefPtr& operator=(SoRefPtr other) noexcept
+    {
+        this->swap(other);
+        return *this;
+    }
+
+    void reset(T* p = NULL)
+    {
+        SoRefPtr tmp(p);
+        this->swap(tmp);
+    }
+
+    T* get(void) const noexcept
+    {
+        return this->ptr;
+    }
+    T& operator*(void) const
+    {
+        return *this->ptr;
+    }
+    T* operator->(void) const noexcept
+    {
+        return this->ptr;
+    }
+    explicit operator bool(void) const noexcept
+    {
+        return this->ptr != NULL;
+    }
+
+    void swap(SoRefPtr& other) noexcept
+    {
+        using std::swap;
+        swap(this->ptr, other.ptr);
+    }
+
+private:
+    T* ptr;
+};
+
 /** Convenience smart pointer to wrap coin node.
  *
- * It is basically boost::intrusive plus implicit pointer conversion to save the
- * trouble of typing get() all the time.
+ * This class isn't merged with SoRefPtr because it can be removed in the future
  */
 template<class T>
-class CoinPtr: public boost::intrusive_ptr<T>
+class CoinPtr: public SoRefPtr<T>
 {
 public:
-    // Too bad, VC2013 does not support constructor inheritance
-    // using boost::intrusive_ptr<T>::intrusive_ptr;
-    using inherited = boost::intrusive_ptr<T>;
-    CoinPtr() = default;
-    CoinPtr(T* p, bool add_ref = true)
-        : inherited(p, add_ref)
-    {}
-    template<class Y>
-    CoinPtr(CoinPtr<Y> const& r)
-        : inherited(r)
-    {}
+    using SoRefPtr<T>::SoRefPtr;
+
+    CoinPtr& operator=(T* ptr)
+    {
+        SoRefPtr<T>::reset(ptr);
+        return *this;
+    }
 
     operator T*() const
     {
diff --git src/Gui/ViewProviderLink.cpp src/Gui/ViewProviderLink.cpp
index 269c21dd9a..398e7ff921 100644
--- src/Gui/ViewProviderLink.cpp
+++ src/Gui/ViewProviderLink.cpp
@@ -1644,7 +1644,7 @@ void LinkView::updateLink()
 bool LinkView::linkGetElementPicked(const SoPickedPoint* pp, std::string& subname) const
 {
     std::ostringstream ss;
-    CoinPtr<SoPath> path = pp->getPath();
+    CoinPtr<SoPath> path {pp->getPath()};
     if (!nodeArray.empty()) {
         auto idx = path->findNode(pcLinkRoot);
         if (idx < 0 || idx + 2 >= path->getLength()) {
