/* $NoKeywords: $ */ /* // // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert // McNeel & Associates. // // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF // MERCHANTABILITY ARE HEREBY DISCLAIMED. // // For complete openNURBS copyright information see . // //////////////////////////////////////////////////////////////// */ #if !defined(OPENNURBS_EXTENSIONS_INC_) #define OPENNURBS_EXTENSIONS_INC_ /* Description: The ONX_ErrorCounter is useful for counting errors that occur in a section of code. */ class ON_CLASS ONX_ErrorCounter { public: ONX_ErrorCounter() = default; ~ONX_ErrorCounter() = default; ONX_ErrorCounter(const ONX_ErrorCounter&) = default; ONX_ErrorCounter& operator=(const ONX_ErrorCounter&) = default; const ONX_ErrorCounter operator += (const ONX_ErrorCounter& rhs); const ONX_ErrorCounter operator + (const ONX_ErrorCounter& rhs); static const ONX_ErrorCounter Zero; /* Returns: Number of failures. */ unsigned int FailureCount() const; /* Returns: Number of errors. */ unsigned int ErrorCount() const; /* Returns: Number of warnings. */ unsigned int WarningCount() const; /* Returns: Number of failures, erros, and warnings. */ unsigned int TotalCount() const; /* Description: Adds one to the failure count. Returns: Number of failures including this one. */ unsigned int IncrementFailureCount(); /* Description: Adds one to the error count. Returns: Number of errors including this one. */ unsigned int IncrementErrorCount(); /* Description: Adds one to the warning count. Returns: Number of warnings including this one. */ unsigned int IncrementWarningCount(); /* Description: Saves the current value of ON_GetErrorCount() so future calls to ON_ERROR can be counted. */ void ClearLibraryErrors(); /* Description: Adds the number of calls to ON_ERROR since the last call to ClearLibraryErrors(), AddLibraryErrors(), ClearLibraryErrorsAndWarnings, or AddLibraryErrorsAndWarnings(). Returns: The number of errors added. */ unsigned int AddLibraryErrors(); /* Description: Saves the current value of ON_GetWarningCount() so future calls to ON_WARNING can be counted. */ void ClearLibraryWarnings(); /* Description: Adds the number of calls to ON_WARNING since the last call to ClearLibraryWarnings(), AddLibraryWarnings(), ClearLibraryErrorsAndWarnings(), or AddLibraryErrorsAndWarnings(). Returns: The number of warnings added. */ unsigned int AddLibraryWarnings(); /* Description: Calls ClearLibraryErrors() and ClearLibraryWarnings(). */ void ClearLibraryErrorsAndWarnings(); /* Description: Calls AddLibraryErrors() and AddLibraryWarnings(). Returns: The number of errors and warnings added. */ unsigned int AddLibraryErrorsAndWarnings(); void Dump(ON_TextLog& text_log) const; private: unsigned int m_failure_count = 0; unsigned int m_error_count = 0; unsigned int m_warning_count = 0; unsigned int m_state_bit_field = 0; unsigned int m_opennurbs_library_error_count = 0; unsigned int m_opennurbs_library_warning_count = 0; }; /* Description: Used to store user data information in an ONX_Model. */ class ON_CLASS ONX_Model_UserData { public: #if defined(OPENNURBS_EXPORTS) || defined(OPENNURBS_IMPORTS) // See comments at the top of opennurbs_extensions.cpp for details. // new/delete void* operator new(size_t); void operator delete(void*); // array new/delete void* operator new[] (size_t); void operator delete[] (void*); // in place new/delete void* operator new(size_t,void*); void operator delete(void*,void*); #endif ONX_Model_UserData() = default; ~ONX_Model_UserData() = default; ONX_Model_UserData(const ONX_Model_UserData&) = default; ONX_Model_UserData& operator=(const ONX_Model_UserData&) = default; void Dump( ON_TextLog& ) const; ON_UUID m_uuid = ON_nil_uuid; ON_3dmGoo m_goo; public: // 3dm version = 1,2,3,4,5,50,60,... unsigned int m_usertable_3dm_version = 0; // opennurbs_version = old yyyymmddn value or // a value from ON_VersionNumberConstruct(). unsigned int m_usertable_opennurbs_version = 0; }; #if defined(ON_DLL_TEMPLATE) ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; #endif /* Description: Pedegodgical example of all the things in an OpenNURBS 3dm archive. The openNURBS examples use ONX_Model to store the information read from 3dm archives. Please study example_read.cpp for details. */ class ON_CLASS ONX_Model { #if defined(OPENNURBS_EXPORTS) || defined(OPENNURBS_IMPORTS) // See comments at the top of opennurbs_extensions.cpp for details. public: // new/delete void* operator new(size_t); void operator delete(void*); // array new/delete void* operator new[] (size_t); void operator delete[] (void*); // in place new/delete void* operator new(size_t,void*); void operator delete(void*,void*); #endif public: ONX_Model(); virtual ~ONX_Model(); void Reset(); private: // prohibit use of copy construction and operator= ONX_Model(const ONX_Model&) = delete; ONX_Model& operator=(const ONX_Model&) = delete; public: /* Description: Reads an openNURBS archive and saves the information in this model Parameters: archive - [in] archive to read from table_filter - [in] If table_filter is zero, then everything in the archive is read. Otherwise the bits in table_filter identify what tables should be read. The bits are defined by the ON_BInaryArchive::table_type enum. model_object_type_filter - [in] If model_object_type_filter is not zero, then it is a bitfield filter made by bitwise oring ON::object_type values to select which types of objects will be read from the model object table. error_log - [out] any archive reading errors are logged here. Returns: true if archive is read with no error. False if errors occur. Error details are logged in error_log. If crc errors are in the archive, then ONX_Model::m_crc_error_count is set to the number of crc errors. Example: // for ASCII file names const char* sFileName = ....; FILE* fp = ON::OpenFile( sFileName, "rb"); // for UNICODE file names const wchar_t* wsFileName = ....; FILE* fp = ON::OpenFile( wsFileName, L"rb"); bool bModelRead = false; bool bModelIsValid = false; ON_TextLog error_log; ONX_Model model; if ( 0 != fp ) { ON_BinaryFile archive( ON::archive_mode::read3dm, fp ); bModelRead = model.Read( archive, error_log ); ON::CloseFile( fp ); } if ( bModelRead ) { bModelIsValid = model.Validate(error_log); } See Also: ONX_Model::IsValid ONX_Model::Write ONX_Model::m_crc_error_count */ bool Read( ON_BinaryArchive& archive, unsigned int table_filter, unsigned int model_object_type_filter, ON_TextLog* error_log ); bool Read( const char* filename, unsigned int table_filter, unsigned int model_object_type_filter, ON_TextLog* error_log ); bool Read( const wchar_t* filename, unsigned int table_filter, unsigned int model_object_type_filter, ON_TextLog* error_log ); bool Read( ON_BinaryArchive& archive, ON_TextLog* error_log = nullptr ); bool Read( const char* filename, ON_TextLog* error_log = nullptr ); bool Read( const wchar_t* filename, ON_TextLog* error_log = nullptr ); /* Description: Reads everything up to the object table. Parameters: archive - [in] archive to read from bManageComponents - [in] true: The ONX_Model destructor will delete the model components created by this function. false: The caller must delete the ON_ModelComponent components after the ONX_Model is destroyed. table_filter - [in] If table_filter is zero, then everything in the archive before the model object table is read. Otherwise the bits in table_filter identify what tables should be read. The bits are defined by the ON_BInaryArchive::table_type enum. error_log - [out] any archive reading errors are logged here. pass nullptr if you don't want to log errors Returns: If the input is valid and everything before the model object table is successfully read, then true is returned. Otherwise false is returned. Example: // for ASCII file names const char* sFileName = ....; FILE* fp = ON::OpenFile( sFileName, "rb"); // for UNICODE file names const wchar_t* wsFileName = ....; FILE* fp = ON::OpenFile( wsFileName, L"rb"); bool bModelRead = false; bool bModelIsValid = false; ON_TextLog error_log; if ( 0 != fp ) { ON_BinaryFile archive( ON::archive_mode::read3dm, fp ); ONX_Model model; // Read settings, layer information, and other tables // with information that is referenced by model object // attributes. bModelRead = model.IncrementalReadBegin( archive, error_log ); if ( bModelRead ) { object_filter = ON::mesh_object // read meshes | ON::curve_object // and curves ; for(;;) { // read the next model object ON_ModelGeometryComponent* pModelObject = model.IncrementalReadModelObject(object_filter,0); if ( 0 == pModelObject ) break; ... // work with this model object // done with this object. pModelObject = 0; model.m_object_table.Remove(); } } ON::CloseFile( fp ); } See Also: ONX_Model::IsValid ONX_Model::Write ONX_Model::m_crc_error_count */ bool IncrementalReadBegin( ON_BinaryArchive& archive, bool bManageComponents, unsigned int table_filter, ON_TextLog* error_log ); /* Description: Reads the next item in the model geometry table. Parameters: archive - [in] bManageModelGeometryComponent - [in] true: The ONX_Model destructor will delete the ON_ModelGeometryComponent components created by this function. false: The caller must delete the ON_ModelGeometryComponent components after the ONX_Model is destroyed. bManageGeometry - [in] true: The ON_ModelGeometryComponent destructor will delete the ON_Geometry classes created by this function. false: The caller must delete the ON_Geometry classes after the ONX_Model and ON_ModelGeometryComponent components are destroyed. bManageAttributes - [in] true: The ON_ModelGeometryComponent destructor will delete the ON_3dmObjectAttributes classes created by this function. false: The caller must delete the ON_3dmObjectAttributes classes after the ONX_Model and ON_ModelGeometryComponent components are destroyed. model_object_type_filter - [in] If model_object_type_filter is not zero, then it is a bitfield filter made by bitwise oring ON::object_type values to select which types of objects will be read from the model object table. model_geometry_reference - [out] A reference to an ON_ModelGeometryComponent. This referenced ON_ModelGeometryComponent component is also added to the ONX_Model. Call ONX_Model.RemoveComponent() if you want to discard it before continuing. Returns: True Succesful. If model_geometry_reference.IsEmpty() is true, then no more geometry objects are available and you should call IncrementalReadFinish(). False An error occured and reading should terminate. Remarks: You must call IncrementalReadBegin() before making any calls to IncrementalReadModelObject(). */ bool IncrementalReadModelGeometry( ON_BinaryArchive& archive, bool bManageModelGeometryComponent, bool bManageGeometry, bool bManageAttributes, unsigned int model_object_type_filter, ON_ModelComponentReference& model_geometry_reference ); /* Description: Reads everything up to the object table. Parameters: archive - [in] archive to read from bManageComponents - [in] true: The ONX_Model destructor will delete the model components created by this function. false: The caller must delete the ON_ModelComponent components after the ONX_Model is destroyed. table_filter - [in] If table_filter is zero, then everything in the archive before the model object table is read. Otherwise the bits in table_filter identify what tables should be read. The bits are defined by the ON_BInaryArchive::table_type enum. error_log - [out] any archive reading errors are logged here. pass nullptr if you don't want to log errors Returns: If the input is valid and everything before the model object table is successfully read, then true is returned. Otherwise false is returned. See Also: ONX_Model::IsValid ONX_Model::Write ONX_Model::m_crc_error_count */ bool IncrementalReadFinish( ON_BinaryArchive& archive, bool bManageComponents, unsigned int table_filter, ON_TextLog* error_log ); /* Description: Writes contents of this model to an openNURBS archive. Parameters: filename - [in] version - [in] Version of the openNURBS archive to write. 0 default value and suggested. When 0 is passed in, the value of ON_BinaryArchive::CurrentArchiveVersion() is used. 2, 3, 4, 50, 60, ... If you pass in a value < ON_BinaryArchive::CurrentArchiveVersion(), then some information in current data structures will not be saved in the 3dm archive. Rhino 2.x can read version 2 files. Rhino 3.x can read version 2 and 3 files. Rhino 4.x can read version 2, 3, and 4 files. Rhino 5.x can read version 2, 3, 4, 5, and 50 files. Rhino 6.x can read version 2, 3, 4, 5, 50, and 60 files. error_log - [out] any archive writing errors are logged here. Returns: True if archive is written with no error. False if errors occur. Error details are logged in error_log. */ bool Write( const char* filename, int version = 0, ON_TextLog* error_log = nullptr ) const; /* Description: Writes contents of this model to an openNURBS archive. Parameters: filename - [in] version - [in] Version of the openNURBS archive to write. 0 default value and suggested. When 0 is passed in, the value of ON_BinaryArchive::CurrentArchiveVersion() is used. 2, 3, 4, 50, 60, ... If you pass in a value < ON_BinaryArchive::CurrentArchiveVersion(), then some information in current data structures will not be saved in the 3dm archive. Rhino 2.x can read version 2 files. Rhino 3.x can read version 2 and 3 files. Rhino 4.x can read version 2, 3, and 4 files. Rhino 5.x can read version 2, 3, 4, 5, and 50 files. Rhino 6.x can read version 2, 3, 4, 5, 50, and 60 files. error_log - [out] any archive writing errors are logged here. Returns: True if archive is written with no error. False if errors occur. Error details are logged in error_log. */ bool Write( const wchar_t* filename, int version = 0, ON_TextLog* error_log = nullptr ) const; /* Description: Writes contents of this model to an openNURBS archive. Parameters: archive - [in] archive to write to You must call archive.SetArchiveFullPath(...) i order for file references to work correctly. version - [in] Version of the openNURBS archive to write. 0 default value and suggested. When 0 is passed in, the value of ON_BinaryArchive::CurrentArchiveVersion() is used. 2, 3, 4, 50, 60, ... If you pass in a value < ON_BinaryArchive::CurrentArchiveVersion(), then some information in current data structures will not be saved in the 3dm archive. Rhino 2.x can read version 2 files. Rhino 3.x can read version 2 and 3 files. Rhino 4.x can read version 2, 3, and 4 files. Rhino 5.x can read version 2, 3, 4, 5, and 50 files. Rhino 6.x can read version 2, 3, 4, 5, 50, and 60 files. error_log - [out] any archive writing errors are logged here. Returns: True if archive is written with no error. False if errors occur. Error details are logged in error_log. Example: model = ...; if ( model.IsValid( error_log ) ) { const wchar_t* wsFileName = ....; FILE* fp = ON::OpenFile( wsFileName, L"wb"); bool ok = false; if ( 0 != fp ) { const char* sStartSectionComment = "..."; int version = 5; // 2, 3, 4 or 5 are valid ON_BinaryFile archive( ON::archive_mode::write3dm, fp ); archive.SetArchiveFullPath(wsFileName); ok = model.write( archive, version, sStartSectionComment, error_log ); ON::CloseFile( fp ); } } */ bool Write( ON_BinaryArchive& archive, int version = 0, ON_TextLog* error_log = nullptr ) const; ///////////////////////////////////////////////////////////////////// // // BEGIN model definitions // // 3dm archive start section information int m_3dm_file_version = 0; unsigned int m_3dm_opennurbs_version = 0; ON__UINT64 m_3dm_file_byte_count = 0; ON_String m_sStartSectionComments; // Properties include revision history, notes, information about // the applicaton that created the file, and an optional preview image. ON_3dmProperties m_properties; // Settings include tolerance, and unit system, and defaults used // for creating views and objects. ON_3dmSettings m_settings; /* Description: A manifest of every model component in this ONX_Model. Remarks: Use the manifest to find model objects from a name, id or index. The manifest Id, Name, and Index values are values used in the model. These are assigned when a component is added to the ONX_Model. When possible the id and name are not changed. The manifest=model and original component values are different when: - The original component Id or Name was not set and a value was automatically assigned. - The original component Id or Name was not unique and was modified when the component was added to the model. - Generally the original component index differs from the manifest=model component index. The OriginalToModelMap() can be used to convert original component index and id to the manifest=model index and id. The ModelToOriginalMap() can be used to manifest=model index and id to the original component index and id. */ const ON_ComponentManifest& Manifest() const; /* Returns: A map from original component index and id to manifest=model index and id. Remarks: ON_ManifestMapItem Source = original component index and id. ON_ManifestMapItem Destination = model-manifest index and id. */ const ON_ManifestMap& OriginalToModelMap() const; /* Returns: A map from manifest=model index and id to original component index and id. Remarks: ON_ManifestMapItem Source = model-manifest index and id. ON_ManifestMapItem Destination = original component index and id. */ const ON_ManifestMap& ModelToOriginalMap() const; /* Description: This number changes every time the content of the ONX_Model is modified. */ ON__UINT64 ModelContentVersionNumber() const; /* Description: Add an copy of a model_compoent to this model. model_component - [in] A copy of model_component is added to this model. The index, id, and name of the copied component are set the the model values (Manifest() "Manifest" index, name, and id). bResolveIdAndNameConflicts - [in] If bResolveIdAndNameConflicts is false, then model_component.Id() must be non-nil and not used in this model and model_component.Name() must be correctly set. If bResolveIdAndNameConflicts is true, then id and name will be modified as needed in the model and manifest. Returns: A reference to the added model component. If the reference is empty (ON_ModelComponent::IsEmpty() is true) then the input was not valid. */ ON_ModelComponentReference AddModelComponent( const class ON_ModelComponent& model_component, bool bResolveIdAndNameConflicts ); ON_ModelComponentReference AddModelComponent( const class ON_ModelComponent& model_component ); ON_ModelComponentReference RemoveModelComponent( ON_ModelComponent::Type component_type, ON_UUID component_id ); /* Description: Easy way to add a layer to the model. Returns: If layer_name is valid, the layer's index (>=0) is returned. Otherwise, ON_UNSET_INT_INDEX is returned. */ int AddLayer( const wchar_t* layer_name, ON_Color layer_color ); /* Description: Easy way to add a default layer to the model. Properties: layer_name - [in] can be nullptr or empty. layer_color - [in] can be ON_Color::UnsetColor Returns: The default layer's index (>=0) is returned. */ int AddDefaultLayer( const wchar_t* layer_name, ON_Color layer_color ); /* Description: Easy way to add a default dimension style to the model. Parameters: dimension_style_name - [in] can be nullptr or empty length_unit_system - [in] If ON::LengthUnitSystem::Unset, then settings length unit system is used. tolerance - [in] If not > 0, then settings tolerance is used. Returns: The default dimension style's index (>=0) is returned. */ int AddDefaultDimensionStyle( const wchar_t* dimension_style_name, ON::LengthUnitSystem length_unit_system, double model_tolerance ); /* Description: Add a managed model component (ON_Layer, ON_DimStyle, ...) to this model. managed_model_component - [in] managed_model_component must be created by operator new and on the heap. It will be deleted when the model and last ON_ModelComponentReference are destroyed. bResolveIdAndNameConflicts - [in] If bResolveIdAndNameConflicts is false, then model_component.Id() must be non-nil and not used in this model and model_component.Name() must be correctly set. If bResolveIdAndNameConflicts is true, then id and name will be modified as needed in managed_model_component, the model, and the manifest. Returns: A reference to the added model component. If the reference is empty (ON_ModelComponent::IsEmpty() is true) then the input was not valid. */ ON_ModelComponentReference AddManagedModelComponent( class ON_ModelComponent* managed_model_component, bool bResolveIdAndNameConflicts ); ON_ModelComponentReference AddManagedModelComponent( class ON_ModelComponent* managed_model_component ); /* Description: Add a model component to this model and control how the model_component instance is managed. model_component - [in] An ON_ModelComponent created on the heap by calling new X where X is derived from ON_ModelComponent. bManagedComponent - [in] If bManagedComponent is true, then ~ONX_Model will delete the component. If bManagedComponent is false, then you are responsible for insuring the component exists past the desctruction of this ONX_Model. bResolveIdAndNameConflicts - [in] If bResolveIdAndNameConflicts is false, then model_component.Id() must be non-nil and not used in this model and model_component.Name() must be correctly set. If bResolveIdAndNameConflicts is true, then id and name will be modified as needed. bUpdateComponentIdentification - [in] The model_component Index(), Id(), and Name() values are set to match the ones used in the model (Manifest() "Manifest" values.) Returns: A reference to the added model component. If the reference is empty (ON_ModelComponentReference::IsEmpty() is true), then the input was not valid and the model component was not added. */ ON_ModelComponentReference AddModelComponentForExperts( class ON_ModelComponent* model_component, bool bManagedComponent, bool bResolveIdAndNameConflicts, bool bUpdateComponentIdentification ); /* Description: Add an copy of the model_geometry and attrbutes to this model. Parameters: geometry_object - [in] geometry_object must point to a geometric object (curve, surface, brep, mesh, points, ...), a render light, an annotation object, or a detail object. A copy of geometry_object is added to and managed by this model. attributes - [in] nullptr if not available. A copy of attributes is added to and managed by this model. bResolveIdAndNameConflicts - [in] If bResolveIdAndNameConflicts is false, then attributes must be nullptr or attributes->m_uid must be non-nil and not used in this model. If bResolveIdAndNameConflicts is true, then id will be modified as needed. Returns: A reference to the added model component. If the reference is empty (ON_ModelComponent::IsEmpty() is true) then the input was not valid. */ ON_ModelComponentReference AddModelGeometryComponent( const class ON_Object* geometry_object, const class ON_3dmObjectAttributes* attributes, bool bResolveIdAndNameConflicts ); ON_ModelComponentReference AddModelGeometryComponent( const class ON_Object* geometry_object, const class ON_3dmObjectAttributes* attributes ); /* Description: Add an copy of the model_geometry and attrbutes to this model. Parameters: managed_geometry_object - [in] managed_geometry_object must point to an instance geometric object (curve, surface, brep, mesh, points, ...), a render light, an annotation object, or a detail object created by operator new and on the heap. It will be deleted when the this ONX_Model and the last ON_ModelComponentReference are destroyed. managed_attributes - [in] managed_attributes should be nullptr or point to an instance created by operator new and on the heap. It will be deleted when the this ONX_Model and the last ON_ModelComponentReference are destroyed. bResolveIdAndNameConflicts - [in] If bResolveIdAndNameConflicts is false, then managed_attributes must be nullptr or managed_attributes->m_uuid must be non-nil and not used in this model. If bResolveIdAndNameConflicts is true, then id will be modified as needed. Returns: A reference to the added model component. If the reference is empty (ON_ModelComponent::IsEmpty() is true) then the input was not valid. */ ON_ModelComponentReference AddManagedModelGeometryComponent( class ON_Object* managed_geometry_object, class ON_3dmObjectAttributes* managed_attributes, bool bResolveIdAndNameConflicts ); ON_ModelComponentReference AddManagedModelGeometryComponent( class ON_Object* managed_geometry_object, class ON_3dmObjectAttributes* managed_attributes ); /* Description: Add geometry and attibutes to this model and control how the instances are managed. Parameters: bManageGeometry - [in] If true, geometry_object should point to an instance created by operator new and on the heap. It will be deleted when the this ONX_Model and the last ON_ModelComponentReference are destroyed. If false, the expert caller is carefully managing the instance and memory to insure model_geometry is a valid instance while this ONX_Model and any ON_ModelComponentReference are active. geometry_object - [in] geometry_object should point to a geometric object (curve, surface, brep, mesh, points, ...), a render light, an annotation object, or a detail object. bManageAttributes - [in] If true, attributes should be nullptr or point to an instance created by operator new and on the heap. It will be deleted when the this ONX_Model and the last ON_ModelComponentReference are destroyed. If false, the expert caller is carefully managing the instance and memory to insure attributes is a valid instance while this ONX_Model and and ON_ModelComponentReference are active. attributes - [in] nullptr if not avaiable. bResolveIdAndNameConflicts - [in] If bResolveIdAndNameConflicts is false, then attributes must be nullptr or attributes->m_uid must be non-nil and not used in this model. If bResolveIdAndNameConflicts is true, then id will be modified as needed. Returns: A reference to the added model component. If the reference is empty (ON_ModelComponent::IsEmpty() is true) then the input was not valid. */ ON_ModelComponentReference AddModelGeometryComponentForExperts( bool bManageGeometry, class ON_Object* geometry_object, bool bManageAttributes, class ON_3dmObjectAttributes* attributes, bool bResolveIdAndNameConflicts ); unsigned int ComponentIndexLimit( ON_ModelComponent::Type component_type ) const; /* Returns: Number of active and deleted components. Count does not include system components. */ unsigned int ActiveAndDeletedComponentCount( ON_ModelComponent::Type component_type ) const; /* Returns: Number of active components. Count does not include system components. */ unsigned int ActiveComponentCount( ON_ModelComponent::Type component_type ) const; /* Returns: Number of deleted components. */ unsigned int DeletedComponentCount( ON_ModelComponent::Type component_type ) const; ON_ModelComponentReference ComponentFromIndex( ON_ModelComponent::Type component_type, int component_model_index ) const; ON_ModelComponentReference ComponentFromUnsignedIndex( ON_ModelComponent::Type component_type, unsigned int component_model_index ) const; ON_ModelComponentReference ComponentFromId( ON_ModelComponent::Type component_type, ON_UUID component_model_id ) const; ON_ModelComponentReference ComponentFromName( ON_ModelComponent::Type component_type, ON_UUID component_parent_id, const wchar_t* component_model_name ) const; ON_ModelComponentReference ComponentFromNameHash( ON_ModelComponent::Type component_type, const ON_NameHash& component_model_name_hash ) const; /* Parameters: runtime_serial_number - [in] Value of ON_ModelComponent::RuntimeSerialNumber() to search for. Returns: If there is a model component with the specified runtime serial number, then a reference to that component is returned. Otherwise, ON_ModelComponentReference::Empty is returned. Remarks: ONX_Model::ComponentFromRuntimeSerialNumber() used to get a reference rather than a copy of the model's primary ON_ModelComponentReference. This is the function that must be used if a caller is going to use exclusive access funcitons like ON_ModelComponent* ON_ModelComponentReference::ExclusiveModelComponent() ON_3dmObjectAttributes* ON_ModelGeometryComponent::ExclusiveAttributes() ON_Geometry* ON_ModelGeometryComponent::ExclusiveGeometry() to modify content that is in the ONX_Model. The exclusive access functions will only return non-nullptr values when there are no external references to the model component. */ const ON_ModelComponentReference& ComponentFromRuntimeSerialNumber( ON__UINT64 runtime_serial_number ) const; /* Description: Get an image from its model index. Parameters: image_model_index - [in] Returns: An ON_ModelComponentReference to the image. Remarks: Model index and Manifest() manifest item index are the same. */ ON_ModelComponentReference ImageFromIndex( int image_model_index ) const; ON_ModelComponentReference ImageFromId( ON_UUID image_id ) const; ON_ModelComponentReference ImageFromFileFullPath( const wchar_t* image_file_full_path_name ) const; ON_ModelComponentReference ImageFromFileContent( const ON_ContentHash& image_file_content_hash ) const; ON_ModelComponentReference ImageFromFileReference( const ON_FileReference& file_reference ) const; /* Description: Get a line pattern from its model index. Parameters: line_pattern_model_index - [in] Returns: An ON_ModelComponentReference to the line pattern. Remarks: Model index and Manifest() manifest item index are the same. */ ON_ModelComponentReference LinePatternFromIndex( int line_pattern_model_index ) const; ON_ModelComponentReference LinePatternFromId( ON_UUID line_pattern_model_id ) const; ON_ModelComponentReference LinePatternFromName( const wchar_t* line_pattern_name ) const; ON_ModelComponentReference LinePatternFromNameHash( ON_NameHash line_pattern_model_name_hash ) const; /* Description: Get linetype from object attributes. Parameters: attributes - [in] object attributes. line_pattern - [out] linetype */ ON_ModelComponentReference LinePatternFromAttributes( const ON_3dmObjectAttributes& attributes ) const; ON_ModelComponentReference LinePatternFromLayerIndex( int layer_index ) const; /* Description: Get render material from object attributes. Parameters: attributes - [in] object attributes. material - [out] render material */ ON_ModelComponentReference RenderMaterialFromLayerIndex( int layer_index ) const; ON_ModelComponentReference RenderMaterialFromAttributes( const ON_3dmObjectAttributes& attributes ) const; ON_ModelComponentReference RenderMaterialFromIndex( int render_material_index ) const; ON_ModelComponentReference RenderMaterialFromId( ON_UUID render_material_id ) const; /* Description: Get a layer from its model index. Parameters: layer_model_index - [in] Returns: An ON_ModelComponentReference to the layer. Remarks: Model index and Manifest() manifest item index are the same. */ ON_ModelComponentReference LayerFromIndex( int layer_model_index ) const; ON_ModelComponentReference LayerFromId( ON_UUID layer_model_id ) const; ON_ModelComponentReference LayerFromName( ON_UUID layer_parent_id, const wchar_t* layer_name ) const; ON_ModelComponentReference LayerFromNameHash( const ON_NameHash& layer_model_name_hash ) const; ON_ModelComponentReference LayerFromAttributes( const ON_3dmObjectAttributes& attributes ) const; /* Description: Get a dimension style from its model index. Parameters: dimension_style_model_index - [in] Returns: An ON_ModelComponentReference to the dimension style. Remarks: Model index and Manifest() manifest item index are the same. */ ON_ModelComponentReference DimensionStyleFromIndex( int dimension_style_index ) const; ON_ModelComponentReference DimensionStyleFromId( ON_UUID dimension_styleid ) const; ON_ModelComponentReference DimensionStyleFromName( const wchar_t* dimension_style_name ) const; ON_ModelComponentReference DimensionStyleFromNameHash( ON_NameHash dimension_style_name_hash ) const; /* Returns: Id of the current dimension style or nil if the current style is not set or not in this model. */ ON_UUID CurrentDimensionStyleId() const; /* Parameters: dimension_style_id - [in] Id of a dimension style in this model, a system dimension style, or ON_nil_uuid. Returns: true if dimension_style_id is valid and is set. */ bool SetCurrentDimensionStyleId( ON_UUID dimension_style_id ); /* Returns: Current dimension style = DimensionStyleFromId(CurrentDimensionStyleId()) */ ON_ModelComponentReference CurrentDimensionStyle() const; /* Returns: A system dimension style that is the default for this model and is used when a referenced dimension style is missing from this model. */ ON_ModelComponentReference DefaultDimensionStyle() const; /* Parameters: font - [in] model_space_text_scale - [in] If model_space_text_scale > 0, then the DimScale() must be equal to model_space_text_scale. bIgnoreSystemDimStyles - [in] Returns: The first dimension style with the specified font. Remarks: dimension styles with a non-nil parent id are ignored. */ ON_ModelComponentReference FirstDimensionStyleFromFont( const ON_Font* font, double model_space_text_scale, bool bIgnoreSystemDimStyles ) const; /* Parameters: managed_font_serial_number - [in] model_space_text_scale - [in] If model_space_text_scale > 0, then the DimScale() must be equal to model_space_text_scale. bIgnoreSystemDimStyles - [in] Returns: The first dimension style with the specified font. Remarks: dimension styles with a non-nil parent id are ignored. */ ON_ModelComponentReference FirstDimensionStyleFromManagedFontSerialNumber( unsigned int managed_font_serial_number, double model_space_text_scale, bool bIgnoreSystemDimStyles ) const; /* Description: Find or create a dimension style with the specified font characteristics. */ ON_ModelComponentReference DimensionStyleWithFontCharacteristics( const ON_Font& font_characteristics, double model_space_text_scale ); /* Description: Find a model geometry component from Id Parameters: model_geometry_component_id - [in] Returns: If there is a model geometry component with the id, it is returned. Otherwise, ON_ModelComponentReference::Empty is returned. */ ON_ModelComponentReference ModelGeometryFromId( ON_UUID model_geometry_component_id ) const; /* Description: Find a model geometry component from Id Parameters: model_geometry_component_id - [in] Returns: If there is a model geometry component with the id, it is returned. Otherwise, ON_ModelGeometryComponent::Unset is returned. */ const ON_ModelGeometryComponent& ModelGeometryComponentFromId( ON_UUID model_geometry_component_id ) const; public: ON_SimpleArray m_userdata_table; private: ON_ModelComponentReference m_default_render_material = ON_ModelComponentReference::CreateConstantSystemComponentReference(ON_Material::Default); ON_ModelComponentReference m_default_line_pattern = ON_ModelComponentReference::CreateConstantSystemComponentReference(ON_Linetype::Continuous); ON_ModelComponentReference m_default_layer = ON_ModelComponentReference::CreateConstantSystemComponentReference(ON_Layer::Default); ON_ModelComponentReference m_default_text_style = ON_ModelComponentReference::CreateConstantSystemComponentReference(ON_TextStyle::Default); ON_ModelComponentReference m_default_dimension_style = ON_ModelComponentReference::CreateConstantSystemComponentReference(ON_DimStyle::Default); private: ON_ModelComponentReference Internal_AddModelComponent( ON_ModelComponent* model_component, ON_UUID id, ON_UUID name_parent_id, const ON_wString& name, bool bManagedComponent, bool bUpdateComponentIdentification ); private: // Content version is incremented every time the // contents of the ONX_Model are modified. ON__UINT64 m_model_content_version_number = 0; private: void Internal_IncrementModelContentVersionNumber(); private: // A manifest of everything in the model. Use the manifest to find // objects from a name, id or index. ON_ComponentManifest m_manifest; ON_ManifestMap m_original_to_manifest_map; ON_ManifestMap m_manifest_to_original_map; private: friend class ONX_ModelComponentIterator; class ONX_ModelComponentReferenceLink* Internal_ModelComponentLinkFromSerialNumber( ON__UINT64 model_component_runtime_serial_number ) const; class ONX_ModelComponentReferenceLink* Internal_AddModelComponentReference( ON_ModelComponentReference mcr ); void Internal_RemoveModelComponentReferenceLink( class ONX_ModelComponentReferenceLink* mcr_link ); // A map used to lookup by serial number. ON_SerialNumberMap m_mcr_sn_map; ON_FixedSizePool m_mcr_link_fsp; #pragma ON_PRAGMA_WARNING_PUSH #pragma ON_PRAGMA_WARNING_DISABLE_MSC( 4251 ) // C4251: ... needs to have dll-interface to be used by clients of class ... // This warning is not correct. // m_mcr_lists is private and all code that manages m_mcr_lists is explicitly implemented in the DLL. class ONX_ModelComponentList { public: ON_ModelComponent::Type m_component_type = ON_ModelComponent::Type::Unset; unsigned int m_count = 0; class ONX_ModelComponentReferenceLink* m_first_mcr_link = nullptr; class ONX_ModelComponentReferenceLink* m_last_mcr_link = nullptr; }; enum : unsigned int { ONX_MCR_LIST_COUNT = 16 }; ONX_ModelComponentList m_mcr_lists[ONX_MCR_LIST_COUNT]; const ONX_ModelComponentList& Internal_ComponentListConst(ON_ModelComponent::Type component_type) const; ONX_ModelComponentList& Internal_ComponentList(ON_ModelComponent::Type component_type); #pragma ON_PRAGMA_WARNING_POP public: bool ValdateComponentIdAndName( ON_ModelComponent::Type component_type, const ON_UUID& candidate_id, const ON_UUID& component_parent_id, const wchar_t* candidate_name, bool bResolveIdConflict, bool bResolveNameConflict, ON_UUID& model_id, ON_wString& model_name ) const; // // END model definitions // ///////////////////////////////////////////////////////////////////// public: /* Returns: Bounding box of every object in m_object_table[]. */ ON_BoundingBox ModelGeometryBoundingBox() const; /* Returns: Bounding box of every render light in m_light_table[]. */ ON_BoundingBox RenderLightBoundingBox() const; private: void Internal_ComponentTypeBoundingBox( const ON_ModelComponent::Type component_type, ON_BoundingBox& bbox ) const; public: /* Description: Get wireframe drawing color from object attributes. Parameters: attributes - [in] object attributes. Returns: Wireframe drawing color. */ ON_Color WireframeColorFromAttributes( const ON_3dmObjectAttributes& attributes ) const; /* Description: See if the instance reference iref refers to an instance definition. Parameters: iref - [in] idef_uuid - [in] id of idef we are looking for Returns: @untitled table 0 iref does not use idef 1 iref directly references idef >1 iref has a nested reference to idef (nesting depth returned) -1 iref.m_instance_definition_uuid is not valid -2 invalid idef found */ int UsesIDef( const ON_InstanceRef& iref, ON_UUID idef_uuid ) const; ///////////////////////////////////////////////////////////////////// // // BEGIN model document level user string tools // /* Description: Attach a user string to the document. Parameters: key - [in] id used to retrieve this string. string_value - [in] If nullptr, the string with this id will be removed. Returns: True if successful. */ bool SetDocumentUserString( const wchar_t* key, const wchar_t* string_value ); /* Description: Get user string from the document. Parameters: key - [in] id used to retrieve the string. string_value - [out] Returns: True if a string with id was found. */ bool GetDocumentUserString( const wchar_t* key, ON_wString& string_value ) const; /* Description: Get a list of all user strings in the document. Parameters: user_strings - [out] user strings are appended to this list. Returns: Number of elements appended to the user_strings list. */ int GetDocumentUserStrings( ON_ClassArray& user_strings ) const; // // END model document level user string tools // ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // // BEGIN model text dump tools // // text dump of entire model void Dump( ON_TextLog& ) const; // text dump of model properties and settings void DumpSummary( ON_TextLog& ) const; // text dump of user data table void DumpUserDataTable( ON_TextLog& ) const; void DumpComponentList( ON_ModelComponent::Type component_type, ON_TextLog& text_log ) const; /* Returns: A text dump of all component lists. */ void DumpComponentLists( ON_TextLog& text_log ) const; /* Returns: A SHA-1 hash of the model's content. If two models have identical content, then the have equal ContentHash() values. */ ON_SHA1_Hash ContentHash() const; public: private: void Internal_DumpSummary( ON_TextLog& dump, bool bInvariantContentOnly ) const; public: // // END model text dump tools // ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // // BEGIN Render Development Toolkit (RDK) information // // The following functions allow the developer access to the information saved per document or per-object in the 3dm file by the // RDK plug-in, built into Rhino. There are two parts to this information - the XML data that constitutes the information // about materials, textures and environments in addition to some of the document settings such as sun data, skylighting // ground plane and so on - and the embedded support files which are saved as byte-per-byte copies of the actual file data // for the original files. Typically, these embedded files will be textured used by materials, environments or decals. // Call this function to determine if RDK document information has been saved in this model and can be read using the GetRDKDocumentInfomation function. // Returns true if RDK document information is available. static bool IsRDKDocumentInformation(const ONX_Model_UserData& docud); // This function returns the entire XML associated with the RDK document data for this file. The XML will include details about // materials, textures and environments as well as sun, skylighting, ground plane and so on. // Returns true if RDK document information is available. static bool GetRDKDocumentInformation(const ONX_Model_UserData& docud,ON_wString& rdk_xml_document_data); // This function returns the embedded support files written with this document. The returned arrays will be empty if no support filers were saved. // Typically, these files will be used by materials and environments. Rhino unpacks these files into a folder with the suffix "embedded_files" next to the // 3dm file on disk. // This is only supported for Version 6 files onwards. // Returns true if embedded files were found. ON_DEPRECATED_MSG("This function is deprecated as it did not return the buffer sizes, making it useless") static bool GetRDKEmbeddedFiles(const ONX_Model_UserData& docud, ON_ClassArray& paths, ON_SimpleArray& embedded_files_as_buffers); // This function returns the embedded support files written with this document. The returned arrays will be empty if no support filers were saved. // Typically, these files will be used by materials and environments. Rhino unpacks these files into a folder with the suffix "embedded_files" next to the // 3dm file on disk. // This is only supported for Version 6 files onwards. // Returns true if embedded files were found. static bool GetRDKEmbeddedFiles(const ONX_Model_UserData& docud, ON_ClassArray& paths, ON_SimpleArray& embedded_files_as_buffers, ON_SimpleArray& buffer_sizes); // This function returns the paths of the embedded support files written with this document. The returned arrays will be empty if no support filers were saved. // This function is similar to GetRDKEmbeddedFiles, but is faster and uses less memory to return only the paths. Use the paths (exactly the strings returned from this function) to // extract the embedded files using GetRDKEmbeddedFile static bool GetRDKEmbeddedFilePaths(const ONX_Model_UserData& docud, ON_ClassArray& paths); // This function extracts one embedded file from the support files written with this document. Use the exact path as returned from GetRDKEmbeddedFilePaths static bool GetRDKEmbeddedFile(const ONX_Model_UserData& docud, const wchar_t* path, ON_SimpleArray& bytes); // Call this function to determine if RDK object information has saved in this model and can be read using the GetRDKObjectInformation function. // Returns true if RDK object information is available. static bool IsRDKObjectInformation(const ON_UserData& objectud); // This function returns the entire XML associated with the RDK object. The XML includes details about decals. // Returns true if RDK object information is available. static bool GetRDKObjectInformation(const ON_Object& object,ON_wString& rdk_xml_object_data); // // END Render Development Toolkit (RDK) information // ///////////////////////////////////////////////////////////////////// private: mutable ON_BoundingBox m_model_geometry_bbox = ON_BoundingBox::UnsetBoundingBox; mutable ON_BoundingBox m_render_light_bbox = ON_BoundingBox::UnsetBoundingBox; class ON_DocumentUserStringList* m_model_user_string_list = nullptr; }; class ON_CLASS ONX_ModelComponentIterator { public: ONX_ModelComponentIterator() = default; ~ONX_ModelComponentIterator() = default; ONX_ModelComponentIterator(const ONX_ModelComponentIterator&) = default; ONX_ModelComponentIterator& operator=(const ONX_ModelComponentIterator&) = default; ONX_ModelComponentIterator( const ONX_Model& model, ON_ModelComponent::Type component_type ); const ONX_Model* Model() const; ON_ModelComponentReference FirstComponentReference(); ON_ModelComponentReference LastComponentReference(); ON_ModelComponentReference CurrentComponentReference() const; ON_ModelComponentReference NextComponentReference(); ON_ModelComponentReference PreviousComponentReference(); ON_ModelComponentWeakReference FirstComponentWeakReference(); ON_ModelComponentWeakReference LastComponentWeakReference(); ON_ModelComponentWeakReference NextComponentWeakReference(); ON_ModelComponentWeakReference PreviousComponentWeakReference(); ON_ModelComponentWeakReference CurrentComponentWeakReference() const; // Use these with caution unless it is clear you are the only thread // with references to the model and the iterator. const ON_ModelComponent* FirstComponent(); const ON_ModelComponent* LastComponent(); const ON_ModelComponent* CurrentComponent() const; const ON_ModelComponent* NextComponent(); const ON_ModelComponent* PreviousComponent(); /* Returns: Number of active components in the current model. Remarks: If the model is modified during iteration, this value will changes. */ unsigned int ActiveComponentCount() const; private: const class ONX_Model::ONX_ModelComponentList* Internal_List() const; void Internal_SetLink(const class ONX_ModelComponentReferenceLink* link) const; void Internal_SetLink(ON__UINT64 model_component_sn) const; ON_ModelComponent::Type m_component_type = ON_ModelComponent::Type::Unset; const class ONX_Model* m_model = nullptr; mutable ON__UINT64 m_model_content_version = 0; mutable const class ONX_Model::ONX_ModelComponentList* m_list = nullptr; mutable const class ONX_ModelComponentReferenceLink* m_link = nullptr; mutable ON__UINT64 m_current_component_sn = 0; mutable ON__UINT64 m_next_component_sn = 0; mutable ON__UINT64 m_prev_component_sn = 0; // The current component is a weak ref so that a stand alone iterator cannot // keep the current element alive since iterations often involve deletion. // The iterators next/prev will still work as expected when the current element // is deleted. In particular, an iterator can be used to efficiently delete // portions of a model and have the deletion occur when many people // expect it to occur and not at a later time. This makes debugging // invalid deletions much easier. mutable ON_ModelComponentWeakReference m_current_component_weak_ref; }; class ON_CLASS ONX_ModelTest { public: ONX_ModelTest() = default; ~ONX_ModelTest() = default; ONX_ModelTest(const ONX_ModelTest&) = default; ONX_ModelTest& operator=(const ONX_ModelTest&) = default; static const ONX_ModelTest Unset; public: #pragma region // XXRH_C_SHARED_ENUM // [ONX_ModelTest::Type] [Rhino.Geometry.Something.Type] [nested:byte] /// /// ONX_ModelTest::Type identifies the type of file reading test to perform. /// enum class Type : unsigned char { Unset = 0, /// /// Read the source 3dm file. /// Read = 1, /// /// Read the source 3dm file and write one or two temporary 3dm files. The original /// source file is not modified. If the 3dm version of the source file /// is < ON_BinaryArchive::CurrentArchiveVersion(), then two temporary 3dm /// files are written, the first with 3dm version = ON_BinaryArchive::CurrentArchiveVersion()-10 /// and the second with 3dm version = ON_BinaryArchive::CurrentArchiveVersion(). /// For example, if Rhino 6 is the current version of Rhino and a file written /// by Rhino 5 is read, then both a temporary Rhino 5 and a temporary Rhino 6 3dm /// file are written. /// ReadWrite = 2, /// /// Perform the ReadWrite test and read the temporary files. /// ReadWriteRead = 3, /// /// Perform the ReadWriteRead test. If one of the temporary files has the same 3dm version /// as the original source file, verify that the ONX_Models created by reading the original /// 3dm file and the temporary 3dm file with the same version have identical values /// of ONX_Model::ContentHash(). /// ReadWriteReadCompare = 4 }; #pragma endregion static const char* TestTypeToString(ONX_ModelTest::Type test_type); static const wchar_t* TestTypeToWideString(ONX_ModelTest::Type test_type); #pragma region // XXRH_C_SHARED_ENUM // [ONX_ModelTest::Result] [Rhino.Geometry.Something.Result] [nested:byte] /// /// ONX_ModelTest::Result reports the result of a test. /// enum class Result : unsigned char { /// /// Test result is not set. /// Unset = 0, /// /// Test failed to complete. /// Fail = 1, /// /// Test was performed and completed, but at least one ON_ERROR occured. /// Errors = 2, /// /// Test was performed and completed, but at least one ON_WARNING occured. /// Warnings = 3, /// /// Test was performed and passed. /// Pass = 4, /// /// Test was not perfomed because the input did not satisfy prerequisites or an /// earlier test failed. /// For example, if a ONX_ModelReadTest::TestType::ReadWriteReadCompare /// test is requested and the source file is a Rhino 1 file, the compare /// test is skipped. /// For example, if a ONX_ModelReadTest::TestType::ReadWriteRead /// test is requested and the Write test failes, the second Read test is skipped. /// Skip = 5, }; #pragma endregion static const char* ResultToString(ONX_ModelTest::Result result); static const wchar_t* ResultToWideString(ONX_ModelTest::Result result); static ONX_ModelTest::Result WorstResult( ONX_ModelTest::Result a, ONX_ModelTest::Result b ); /* Parameters: error_count - [in] no_errors_result - [in] result to return when 0 = error_count.TotalCount(). */ static ONX_ModelTest::Result ResultFromErrorCounter( ONX_ErrorCounter error_count, ONX_ModelTest::Result no_errors_result ); /* Description: Test ONX_Model::Read() and ONX_Model::Write(). Parameters: file_path - [in] file path test_type - [in] test to perform. bKeepModels - [in] If true, then the ONX_Models created by reading 3dm archives are saved so the can be examined after the tests complete. text_log_file_path - [in] If not empty, the string to use for file_path in the output text_log. This is used to create logs on different computers that can be compared. text_log - [in] If text_log is not nullptr, then a summary of the test is sent to text_log. Returns: True if every test passed with no warnings or errors. False if a test failed or warnings or errors occured. */ bool ReadTest( const char* file_path, ONX_ModelTest::Type test_type, bool bKeepModels, const char* text_log_file_path, ON_TextLog* text_log ); /* Description: ONX_Model::ReadTest() can be used to test reading a specific file. Parameters: file_path - [in] file path test_type - [in] test to perform. bKeepModels - [in] If true, then the ONX_Models created by reading 3dm archives are saved so the can be examined after the tests complete. text_log_file_path - [in] If not empty, the string to use for file_path in the output text_log. This is used to create logs on different computers that can be compared. text_log - [in] If text_log is not nullptr, then a summary of the test is sent to text_log. Returns: True if every test passed with no warnings or errors. False if a test failed or warnings or errors occured. */ bool ReadTest( const wchar_t* file_path, ONX_ModelTest::Type test_type, bool bKeepModels, const wchar_t* text_log_file_path, ON_TextLog* text_log ); /* Description: ONX_Model::ReadTest() can be used to test reading a specific file. Parameters: fp - [in] fp pointer to a file opened with ON_FileStream::Opent(...,"rb"); test_type - [in] test to perform. bKeepModels - [in] If true, then the ONX_Models created by reading 3dm archives are saved so the can be examined after the tests complete. text_log_file_path - [in] If not empty, the string to use for file_path in the output text_log. This is used to create logs on different computers that can be compared. text_log - [in] If text_log is not nullptr, then a summary of the test is sent to text_log. Returns: True if every test passed with no warnings or errors. False if a test failed or warnings or errors occured. */ bool ReadTest( FILE* fp, ONX_ModelTest::Type test_type, bool bKeepModels, const wchar_t* text_log_file_path, ON_TextLog* text_log ); /* Description: ONX_Model::Test() can be used to test reading a specific file. Parameters: archive - [in] test_type - [in] test to perform. bKeepModels - [in] If true, then the ONX_Models created by reading 3dm archives are saved so the can be examined after the tests complete. text_log_file_path - [in] If not empty, the string to use for file_path in the output text_log. This is used to create logs on different computers that can be compared. text_log - [in] If text_log is not nullptr, then a summary of the test is sent to text_log. Returns: True if every test passed with no warnings or errors. False if a test failed or warnings or errors occured. */ bool ReadTest( ON_BinaryArchive& archive, ONX_ModelTest::Type test_type, bool bKeepModels, const wchar_t* text_log_file_path, ON_TextLog* text_log ); /* Description: Prints test results. */ void Dump(ON_TextLog& text_log) const; /* Description: Prints the model context to text_log. */ static bool DumpModel(const ONX_Model* model, ON_TextLog& text_log); /* Description: Prints the source model context to text file next to the source file with the file _ONX_ModelText_original_.txt appended to the source file name. Remark: Call after test is completed. */ bool DumpSourceModel() const; /* Description: Prints the source model context to text_log. Remark: Call after test is completed. */ bool DumpSourceModel(const wchar_t* text_file_full_path) const; /* Description: Prints the source model context to text_log. Remark: Call after test is completed. */ bool DumpSourceModel(ON_TextLog& text_log) const; /* Description: Prints the model obtained from the last read in the read-write-read test to with the file _ONX_ModelText_copy_.txt appended to the original source file name. Remark: Call after test is completed. */ bool DumpReadWriteReadModel() const; /* Description: Prints the model obtained from the last read in the read-write-read test to with the file _ONX_ModelText_copy_.txt appended to a text file with the specified name. Remark: Call after test is completed. */ bool DumpReadWriteReadModel(const wchar_t* text_file_full_path) const; /* Description: Prints the model obtained from the last read in the read-write-read test to with the file _ONX_ModelText_copy_.txt appended to the text_log. Remark: Call after test is completed. */ bool DumpReadWriteReadModel(ON_TextLog& text_log) const; private: void Internal_BeginTest(); void Internal_EndCurrentTest(); void Internal_BeginNextTest( ONX_ModelTest::Type test_type ); void Internal_ReadTest( ON_BinaryArchive& archive, ONX_ModelTest::Type test_type, bool bKeepModels, const wchar_t* text_log_file_path, ON_TextLog* text_log ); bool Internal_TallyTestResults(); public: // Test that was performed. ONX_ModelTest::Type TestType() const; /* Returns: The name of the source 3dm file. */ const ON_wString Source3dmFilePath() const; /* Returns: The string used in the output log to identify the source 3dm file. */ const ON_wString TextLogSource3dmFilePath() const; /* Returns: Version of the 3dm fie, 1,2,3,4,5,50,60,... */ unsigned int Source3dmFileVersion() const; /* Returns: Worst result for any test that was attempted. */ ONX_ModelTest::Result TestResult() const; /* Parameters: test_type - [in] Returns: Result of the test identified by the test_type parameter. */ ONX_ModelTest::Result TestResult( ONX_ModelTest::Type test_type ); static bool SkipCompare( unsigned int source_3dm_file_version ); /* Returns: Total number of failures, errors, and warnings for all tests that were performed. */ ONX_ErrorCounter ErrorCounter() const; /* Returns: Total number of failures, errors, and warnings for all tests that were performed. */ ONX_ErrorCounter ErrorCounter( ONX_ModelTest::Type test_type ) const; const ON_SHA1_Hash SourceModelHash(); const ON_SHA1_Hash ReadWriteReadModelHash(); /* Returns: nullptr if the test was run with bKeepModels=false or the source archive could not be read. Otherwise, a pointer to the source model. */ std::shared_ptr SourceModel() const; /* Returns: nullptr if the read write read test was not performed or was run with bKeepModels=false. Otherwise, a pointer to the result of the read write read test. */ std::shared_ptr ReadWriteReadModel() const; private: ONX_ModelTest::Type m_test_type = ONX_ModelTest::Type::Unset; ON_wString m_source_3dm_file_path; // if set, used when printing the name of m_source_3dm_file_path in the text // log so results from different computers can be compared. ON_wString m_text_log_3dm_file_path; unsigned int m_model_3dm_file_version[3]; unsigned int m_current_test_index = 0; ONX_ModelTest::Result m_test_result = ONX_ModelTest::Result::Unset; ONX_ModelTest::Result m_test_results[7] = {}; ONX_ErrorCounter m_error_count; ONX_ErrorCounter m_error_counts[7]; #pragma ON_PRAGMA_WARNING_PUSH #pragma ON_PRAGMA_WARNING_DISABLE_MSC( 4251 ) // C4251: ... : class 'std::shared_ptr' // needs to have dll-interface to be used by clients ... // m_model[] is private and all code that manages m_sp is explicitly implemented in the DLL. // m_model[0] = model from source file // m_model[1] = model[0] -> write to current 3dm version -> read into model[1] // m_model[2] = model[0] -> write to prev 3dm version -> read into model[2] std::shared_ptr m_model[3]; #pragma ON_PRAGMA_WARNING_POP // m_model_hash[i] = m_model[0].Hash() ON_SHA1_Hash m_model_hash[3]; }; #endif