diff --git a/src/Mod/Part/App/AppPart.cpp b/src/Mod/Part/App/AppPart.cpp index 23ab086e84..cb5cf4a71c 100644 --- a/src/Mod/Part/App/AppPart.cpp +++ b/src/Mod/Part/App/AppPart.cpp @@ -498,6 +498,7 @@ PyMOD_INIT_FUNC(Part) Part::GeometryBoolExtension ::init(); Part::GeometryDoubleExtension ::init(); Part::GeometryMigrationExtension ::init(); + Part::GeometryMigrationPersistenceExtension ::init(); Part::Geometry ::init(); Part::GeomPoint ::init(); Part::GeomCurve ::init(); diff --git a/src/Mod/Part/App/GeometryMigrationExtension.cpp b/src/Mod/Part/App/GeometryMigrationExtension.cpp index e6f57a257f..2ecebe6298 100644 --- a/src/Mod/Part/App/GeometryMigrationExtension.cpp +++ b/src/Mod/Part/App/GeometryMigrationExtension.cpp @@ -29,14 +29,21 @@ using namespace Part; +TYPESYSTEM_SOURCE_ABSTRACT(Part::GeometryMigrationPersistenceExtension, Part::GeometryPersistenceExtension) + //---------- Geometry Extension TYPESYSTEM_SOURCE(Part::GeometryMigrationExtension,Part::GeometryExtension) -void GeometryMigrationExtension::copyAttributes(Part::GeometryExtension * cpy) const -{ + +void GeometryMigrationExtension::copyAttributes(Part::GeometryExtension *cpy) const { Part::GeometryExtension::copyAttributes(cpy); static_cast(cpy)->ConstructionState = this->ConstructionState; - static_cast(cpy)->GeometryMigrationFlags = this->GeometryMigrationFlags; + static_cast(cpy)->GeometryMigrationFlags = this->GeometryMigrationFlags; + + static_cast(cpy)->Id = this->Id; + static_cast(cpy)->Flags = this->Flags; + static_cast(cpy)->Ref = this->Ref; + static_cast(cpy)->RefIndex = this->RefIndex; } std::unique_ptr GeometryMigrationExtension::copy() const diff --git a/src/Mod/Part/App/GeometryMigrationExtension.h b/src/Mod/Part/App/GeometryMigrationExtension.h index 11f4fd0ef6..59375ee4f3 100644 --- a/src/Mod/Part/App/GeometryMigrationExtension.h +++ b/src/Mod/Part/App/GeometryMigrationExtension.h @@ -49,6 +49,8 @@ public: enum MigrationType { None = 0, Construction = 1, + GeometryId = 2, + ExternalReference = 3, NumMigrationType // Must be the last }; @@ -60,8 +62,32 @@ public: PyObject *getPyObject() override; - virtual bool getConstruction() const {return ConstructionState;} - virtual void setConstruction(bool construction) {ConstructionState = construction;} + virtual bool getConstruction() const { return ConstructionState; } + + virtual void setConstruction(bool construction) { + ConstructionState = construction; + setMigrationType(Construction); + } + + long getId() const { return Id; } + + void setId(long id) { + Id = id; + setMigrationType(GeometryId); + } + + const std::string &getRef() const { return Ref; } + + int getRefIndex() const { return RefIndex; } + + unsigned long getFlags() const { return Flags; } + + void setReference(const char *ref, int index, unsigned long flags) { + Ref = ref ? ref : ""; + RefIndex = index; + Flags = flags; + setMigrationType(ExternalReference); + } virtual bool testMigrationType(int flag) const { return GeometryMigrationFlags.test((size_t)(flag)); }; virtual void setMigrationType(int flag, bool v=true) { GeometryMigrationFlags.set((size_t)(flag), v); }; @@ -76,7 +102,21 @@ private: using MigrationTypeFlagType = std::bitset<32>; MigrationTypeFlagType GeometryMigrationFlags; bool ConstructionState{false}; + long Id = 0; + int RefIndex = -1; + unsigned long Flags = 0; + std::string Ref; +}; + +class PartExport GeometryMigrationPersistenceExtension : public Part::GeometryPersistenceExtension +{ + TYPESYSTEM_HEADER(); +public: + // Called to extend 'Geometry' XML tag with additional attributes (eg Id) + virtual void preSave(Base::Writer &/*writer*/) const {} + // Called to add additional tag after 'GeometryExtensions' XML elements (eg Construction flag) + virtual void postSave(Base::Writer &/*writer*/) const {} }; } //namespace Part diff --git a/src/Mod/Part/App/PartFeature.cpp b/src/Mod/Part/App/PartFeature.cpp index 60fad39631..0f2851bee6 100644 --- a/src/Mod/Part/App/PartFeature.cpp +++ b/src/Mod/Part/App/PartFeature.cpp @@ -148,8 +148,12 @@ std::pair Feature::getElementName(const char* name, if (!prop) { return App::GeoFeature::getElementName(name, type); } + return getExportElementName(prop->getShape(), name); +} - TopoShape shape = prop->getShape(); +std::pair Feature::getExportElementName(TopoShape shape, + const char* name) const +{ Data::MappedElement mapped = shape.getElementName(name); auto res = shape.shapeTypeAndIndex(mapped.index); static const int MinLowerTopoNames = 3; @@ -259,10 +263,10 @@ std::pair Feature::getElementName(const char* name, // disambiguation. auto it = std::find(ancestors.begin(), ancestors.end(), res.second); if (it == ancestors.end()) { - assert(0 && "ancestor not found"); // this shouldn't happened + assert(0 && "ancestor not found"); // this shouldn't happen } else { - op = Data::POSTFIX_TAG + std::to_string(it - ancestors.begin()); + op = Data::POSTFIX_INDEX + std::to_string(it - ancestors.begin()); } } @@ -284,10 +288,8 @@ std::pair Feature::getElementName(const char* name, } } } - return App::GeoFeature::_getElementName(name, mapped); } - - if (!res.second && mapped.name) { + else if (!res.second && mapped.name) { const char* dot = strchr(name, '.'); if (dot) { ++dot; @@ -350,7 +352,6 @@ std::pair Feature::getElementName(const char* name, if (ancestors.size() == 1) { idxName.setIndex(ancestors.front()); mapped.index = idxName; - return App::GeoFeature::_getElementName(name, mapped); } } } diff --git a/src/Mod/Part/App/PartFeature.h b/src/Mod/Part/App/PartFeature.h index 4387ccdd74..0288eded67 100644 --- a/src/Mod/Part/App/PartFeature.h +++ b/src/Mod/Part/App/PartFeature.h @@ -171,6 +171,17 @@ protected: void registerElementCache(const std::string &prefix, PropertyPartShape *prop); + /** Helper function to obtain mapped and indexed element name from a shape + * @params shape: source shape + * @param name: the input name, can be either mapped or indexed name + * @return Returns both the indexed and mapped name + * + * If the 'name' referencing a non-primary shape type, i.e. not + * Vertex/Edge/Face, this function will auto generate a name from primary + * sub-shapes. + */ + std::pair getExportElementName(TopoShape shape, const char *name) const; + /** * Build a history of changes * MakeShape: The operation that created the changes, e.g. BRepAlgoAPI_Common diff --git a/src/Mod/Sketcher/App/ExternalGeometryExtension.cpp b/src/Mod/Sketcher/App/ExternalGeometryExtension.cpp index cbc5eed357..44a0eaa9c7 100644 --- a/src/Mod/Sketcher/App/ExternalGeometryExtension.cpp +++ b/src/Mod/Sketcher/App/ExternalGeometryExtension.cpp @@ -36,13 +36,14 @@ using namespace Sketcher; constexpr std::array ExternalGeometryExtension::flag2str; -TYPESYSTEM_SOURCE(Sketcher::ExternalGeometryExtension, Part::GeometryPersistenceExtension) +TYPESYSTEM_SOURCE(Sketcher::ExternalGeometryExtension, Part::GeometryMigrationPersistenceExtension) void ExternalGeometryExtension::copyAttributes(Part::GeometryExtension* cpy) const { Part::GeometryPersistenceExtension::copyAttributes(cpy); static_cast(cpy)->Ref = this->Ref; + static_cast(cpy)->RefIndex = this->RefIndex; static_cast(cpy)->Flags = this->Flags; } @@ -50,15 +51,32 @@ void ExternalGeometryExtension::restoreAttributes(Base::XMLReader& reader) { Part::GeometryPersistenceExtension::restoreAttributes(reader); - Ref = reader.getAttribute("Ref"); - Flags = FlagType(reader.getAttribute("Flags")); + Ref = reader.getAttribute("Ref", ""); + RefIndex = reader.getAttributeAsInteger("RefIndex", "-1"); + Flags = FlagType(reader.getAttributeAsUnsigned("Flags", "0")); } void ExternalGeometryExtension::saveAttributes(Base::Writer& writer) const { Part::GeometryPersistenceExtension::saveAttributes(writer); + writer.Stream() << "\" Ref=\"" << Base::Persistence::encodeAttribute(Ref); + writer.Stream() << "\" Flags=\"" << Flags.to_ulong(); + if (RefIndex >= 0) { + writer.Stream() << "\" RefIndex=\"" << RefIndex; + } +} - writer.Stream() << "\" Ref=\"" << Ref << "\" Flags=\"" << Flags.to_string(); +void ExternalGeometryExtension::preSave(Base::Writer& writer) const +{ + if (Ref.size()) { + writer.Stream() << " ref=\"" << Base::Persistence::encodeAttribute(Ref) << "\""; + } + if (RefIndex >= 0) { + writer.Stream() << " refIndex=\"" << RefIndex << "\""; + } + if (Flags.any()) { + writer.Stream() << " flags=\"" << Flags.to_ulong() << "\""; + } } std::unique_ptr ExternalGeometryExtension::copy() const diff --git a/src/Mod/Sketcher/App/ExternalGeometryExtension.h b/src/Mod/Sketcher/App/ExternalGeometryExtension.h index 58a89cfc39..338d70f064 100644 --- a/src/Mod/Sketcher/App/ExternalGeometryExtension.h +++ b/src/Mod/Sketcher/App/ExternalGeometryExtension.h @@ -27,6 +27,7 @@ #include #include +#include #include @@ -40,18 +41,29 @@ public: // START_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder) // virtual bool testFlag(int flag) const = 0; + virtual void setFlag(int flag, bool v = true) = 0; + + virtual unsigned long getFlags() const = 0; + + virtual void setFlags(unsigned long flags) = 0; // END_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder) // virtual bool isClear() const = 0; + virtual size_t flagSize() const = 0; virtual const std::string& getRef() const = 0; + virtual void setRef(const std::string& ref) = 0; + + virtual int getRefIndex() const = 0; + + virtual void setRefIndex(int index) = 0; }; -class SketcherExport ExternalGeometryExtension: public Part::GeometryPersistenceExtension, +class SketcherExport ExternalGeometryExtension: public Part::GeometryMigrationPersistenceExtension, private ISketchExternalGeometryExtension { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -76,6 +88,7 @@ public: public: ExternalGeometryExtension() = default; + ~ExternalGeometryExtension() override = default; std::unique_ptr copy() const override; @@ -88,10 +101,21 @@ public: { return Flags.test((size_t)(flag)); } + void setFlag(int flag, bool v = true) override { Flags.set((size_t)(flag), v); } + + unsigned long getFlags() const override + { + return Flags.to_ulong(); + } + + void setFlags(unsigned long flags) override + { + Flags = flags; + } // END_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder) // @@ -99,6 +123,7 @@ public: { return Flags.none(); } + size_t flagSize() const override { return Flags.size(); @@ -108,18 +133,33 @@ public: { return Ref; } + void setRef(const std::string& ref) override { Ref = ref; } + int getRefIndex() const override + { + return RefIndex; + } + + void setRefIndex(int index) override + { + RefIndex = index; + } + static bool getFlagsFromName(std::string str, ExternalGeometryExtension::Flag& flag); protected: void copyAttributes(Part::GeometryExtension* cpy) const override; + void restoreAttributes(Base::XMLReader& reader) override; + void saveAttributes(Base::Writer& writer) const override; + void preSave(Base::Writer& writer) const override; + private: ExternalGeometryExtension(const ExternalGeometryExtension&) = default; @@ -128,6 +168,7 @@ private: // START_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder) // std::string Ref; + int RefIndex = -1; FlagType Flags; // END_CREDIT_BLOCK: Credit under LGPL for this block to Zheng, Lei (realthunder) // diff --git a/src/Mod/Sketcher/App/ExternalGeometryFacade.cpp b/src/Mod/Sketcher/App/ExternalGeometryFacade.cpp index 963bb4a165..6a4d249ba2 100644 --- a/src/Mod/Sketcher/App/ExternalGeometryFacade.cpp +++ b/src/Mod/Sketcher/App/ExternalGeometryFacade.cpp @@ -30,6 +30,7 @@ #include "ExternalGeometryFacade.h" #include "ExternalGeometryFacadePy.h" +FC_LOG_LEVEL_INIT("Sketch", true, true); using namespace Sketcher; @@ -160,6 +161,23 @@ void ExternalGeometryFacade::copyId(const Part::Geometry* src, Part::Geometry* d gfdst->setId(gfsrc->getId()); } +void ExternalGeometryFacade::copyFlags(const Part::Geometry* src, Part::Geometry* dst) +{ + auto gfsrc = ExternalGeometryFacade::getFacade(src); + auto gfdst = ExternalGeometryFacade::getFacade(dst); + gfdst->setFlags(gfsrc->getFlags()); +} + +void ExternalGeometryFacade::setRef(const std::string& ref) +{ + if (ref.empty() && getId() < 0) { + FC_ERR("Cannot set reference on root geometries"); + } + else { + getExternalGeoExt()->setRef(ref); + } +} + PyObject* ExternalGeometryFacade::getPyObject() { return new ExternalGeometryFacadePy(new ExternalGeometryFacade(this->Geo)); diff --git a/src/Mod/Sketcher/App/ExternalGeometryFacade.h b/src/Mod/Sketcher/App/ExternalGeometryFacade.h index bbcf464121..ac2c2b7dfd 100644 --- a/src/Mod/Sketcher/App/ExternalGeometryFacade.h +++ b/src/Mod/Sketcher/App/ExternalGeometryFacade.h @@ -68,6 +68,7 @@ public: // Factory methods public: // Utility methods static void ensureSketchGeometryExtensions(Part::Geometry* geometry); static void copyId(const Part::Geometry* src, Part::Geometry* dst); + static void copyFlags(const Part::Geometry* src, Part::Geometry* dst); public: void setGeometry(Part::Geometry* geometry); @@ -77,15 +78,27 @@ public: { return getExternalGeoExt()->testFlag(flag); } + void setFlag(int flag, bool v = true) override { getExternalGeoExt()->setFlag(flag, v); } + unsigned long getFlags() const override + { + return getExternalGeoExt()->getFlags(); + } + + void setFlags(unsigned long flags) override + { + getExternalGeoExt()->setFlags(flags); + } + bool isClear() const override { return getExternalGeoExt()->isClear(); } + size_t flagSize() const override { return getExternalGeoExt()->flagSize(); @@ -95,9 +108,17 @@ public: { return getExternalGeoExt()->getRef(); } - void setRef(const std::string& ref) override + + void setRef(const std::string& ref) override; + + int getRefIndex() const override { - getExternalGeoExt()->setRef(ref); + return getExternalGeoExt()->getRefIndex(); + } + + void setRefIndex(int index) override + { + getExternalGeoExt()->setRefIndex(index); } /** GeometryExtension Interface **/ diff --git a/src/Mod/Sketcher/App/GeometryFacade.cpp b/src/Mod/Sketcher/App/GeometryFacade.cpp index a2aa1dc14c..4dd4cf0577 100644 --- a/src/Mod/Sketcher/App/GeometryFacade.cpp +++ b/src/Mod/Sketcher/App/GeometryFacade.cpp @@ -146,6 +146,18 @@ void GeometryFacade::copyId(const Part::Geometry* src, Part::Geometry* dst) gfdst->setId(gfsrc->getId()); } +int GeometryFacade::getId(const Part::Geometry* geometry) +{ + auto gf = GeometryFacade::getFacade(geometry); + return gf->getId(); +} + +void GeometryFacade::setId(Part::Geometry* geometry, int id) +{ + auto gf = GeometryFacade::getFacade(geometry); + return gf->setId(id); +} + bool GeometryFacade::getConstruction(const Part::Geometry* geometry) { throwOnNullPtr(geometry); diff --git a/src/Mod/Sketcher/App/GeometryFacade.h b/src/Mod/Sketcher/App/GeometryFacade.h index a142806716..f3047ee24a 100644 --- a/src/Mod/Sketcher/App/GeometryFacade.h +++ b/src/Mod/Sketcher/App/GeometryFacade.h @@ -131,6 +131,8 @@ public: // Utility methods static InternalType::InternalType getInternalType(const Part::Geometry* geometry); static void setInternalType(Part::Geometry* geometry, InternalType::InternalType type); static bool getBlocked(const Part::Geometry* geometry); + static int getId(const Part::Geometry* geometry); + static void setId(Part::Geometry* geometry, int id); public: // Explicit deletion to show intent (not that it is needed) diff --git a/src/Mod/Sketcher/App/SketchGeometryExtension.cpp b/src/Mod/Sketcher/App/SketchGeometryExtension.cpp index 848d99bd53..4c2f224c72 100644 --- a/src/Mod/Sketcher/App/SketchGeometryExtension.cpp +++ b/src/Mod/Sketcher/App/SketchGeometryExtension.cpp @@ -93,6 +93,17 @@ void SketchGeometryExtension::saveAttributes(Base::Writer& writer) const << GeometryModeFlags.to_string() << "\" geometryLayer=\"" << GeometryLayer; } +void SketchGeometryExtension::preSave(Base::Writer& writer) const +{ + writer.Stream() << " id=\"" << Id << "\""; +} + +void SketchGeometryExtension::postSave(Base::Writer& writer) const +{ + writer.Stream() << writer.ind() << "\n"; +} + std::unique_ptr SketchGeometryExtension::copy() const { auto cpy = std::make_unique(); diff --git a/src/Mod/Sketcher/App/SketchGeometryExtension.h b/src/Mod/Sketcher/App/SketchGeometryExtension.h index d20564b544..588ee9fb2d 100644 --- a/src/Mod/Sketcher/App/SketchGeometryExtension.h +++ b/src/Mod/Sketcher/App/SketchGeometryExtension.h @@ -28,6 +28,7 @@ #include #include +#include #include @@ -84,7 +85,7 @@ public: virtual void setGeometryLayerId(int geolayer) = 0; }; -class SketcherExport SketchGeometryExtension: public Part::GeometryPersistenceExtension, +class SketcherExport SketchGeometryExtension: public Part::GeometryMigrationPersistenceExtension, private ISketchGeometryExtension { TYPESYSTEM_HEADER_WITH_OVERRIDE(); @@ -159,6 +160,8 @@ protected: void copyAttributes(Part::GeometryExtension* cpy) const override; void restoreAttributes(Base::XMLReader& reader) override; void saveAttributes(Base::Writer& writer) const override; + void preSave(Base::Writer& writer) const override; + void postSave(Base::Writer& writer) const override; private: SketchGeometryExtension(const SketchGeometryExtension&) = default;