/* $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 . // //////////////////////////////////////////////////////////////// */ #include "opennurbs.h" #if !defined(ON_COMPILING_OPENNURBS) // This check is included in all opennurbs source .c and .cpp files to insure // ON_COMPILING_OPENNURBS is defined when opennurbs source is compiled. // When opennurbs source is being compiled, ON_COMPILING_OPENNURBS is defined // and the opennurbs .h files alter what is declared and how it is declared. #error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs #endif class ON_Value { public: // The VALUE_TYPE enum values must never be changed // because the values are used to determine the parameter // type during file reading. Additions can be made. enum VALUE_TYPE { no_value_type = 0, bool_value = 1, int_value = 2, double_value = 3, color_value = 4, point_value = 5, vector_value = 6, xform_value = 7, string_value = 8, objref_value = 9, geometry_value = 10, uuid_value = 11, point_on_object_value = 12, polyedge_value = 13, subd_edge_chain_value = 14, // each value type must have a case in ON_Value::CreateValue(). force_32bit_enum = 0xFFFFFFFF }; static ON_Value* CreateValue( int value_type ); void Report( ON_TextLog& text_log ) const; // The valid id is a nonzero integer the developer // assigns to this value. Developers are responsible // for ensuring the int m_value_id = -1; const VALUE_TYPE m_value_type; ON_Value(VALUE_TYPE); ON_Value(const ON_Value& src); virtual ~ON_Value(); virtual ON_Value* Duplicate() const=0; virtual int Count() const=0; virtual bool ReadHelper(ON_BinaryArchive& )=0; virtual bool WriteHelper(ON_BinaryArchive& ) const=0; virtual bool ReportHelper(ON_TextLog& ) const=0; virtual int GetBools( const bool*& ) const; virtual int GetInts( const int*& ) const; virtual int GetColors( const ON_Color*& ) const; virtual int GetDoubles( const double*& ) const; virtual int Get3dPoints( const ON_3dPoint*& ) const; virtual int Get3dVectors( const ON_3dVector*& ) const; virtual int GetXforms( const ON_Xform*& ) const; virtual int GetUuids( const ON_UUID*& ) const; virtual int GetObjRefs( ON_ClassArray& ) const; virtual int GetGeometryPointers( const ON_Geometry* const*& ) const; virtual int GetSubDEdgeChainPointers(const ON_SubDEdgeChain* const*&) const; virtual int GetStrings( ON_ClassArray& ) const; virtual int GetPolyEdgePointers(ON_ClassArray&) const; private: // no implementation ON_Value() = delete; ON_Value& operator=(const ON_Value&) = delete; }; ON_Value::ON_Value( ON_Value::VALUE_TYPE value_type ) : m_value_type(value_type) {} ON_Value::ON_Value(const ON_Value& src) : m_value_id(src.m_value_id) , m_value_type(src.m_value_type) {} ON_Value::~ON_Value() {} // base class virtuals do nothing. int ON_Value::GetBools( const bool*& ) const {return 0;} int ON_Value::GetInts( const int*& ) const {return 0;} int ON_Value::GetColors( const ON_Color*& ) const {return 0;} int ON_Value::GetDoubles( const double*& ) const {return 0;} int ON_Value::Get3dPoints( const ON_3dPoint*& ) const {return 0;} int ON_Value::Get3dVectors( const ON_3dVector*& ) const {return 0;} int ON_Value::GetXforms( const ON_Xform*& ) const {return 0;} int ON_Value::GetUuids( const ON_UUID*& ) const {return 0;} int ON_Value::GetObjRefs( ON_ClassArray& ) const {return 0;} int ON_Value::GetGeometryPointers( const ON_Geometry* const*& ) const {return 0;} int ON_Value::GetSubDEdgeChainPointers(const ON_SubDEdgeChain* const*&) const { return 0; } int ON_Value::GetStrings( ON_ClassArray& ) const {return 0;} int ON_Value::GetPolyEdgePointers(ON_ClassArray&) const { return 0; } class ON_DummyValue : public ON_Value { public: ON_DummyValue(); ~ON_DummyValue(); ON_Value* Duplicate() const; int Count() const; bool ReadHelper(ON_BinaryArchive& ); bool WriteHelper(ON_BinaryArchive& ) const; bool ReportHelper(ON_TextLog& ) const; }; ON_DummyValue::ON_DummyValue() : ON_Value(ON_Value::no_value_type) { } ON_DummyValue::~ON_DummyValue() { } ON_Value* ON_DummyValue::Duplicate() const {return 0;} int ON_DummyValue::Count() const {return 0;} bool ON_DummyValue::ReadHelper(ON_BinaryArchive& ) {return 0;} bool ON_DummyValue::WriteHelper(ON_BinaryArchive& ) const {return 0;} bool ON_DummyValue::ReportHelper(ON_TextLog& ) const {return 0;} /////////////////////////////////////////////////////////////////////// // // ON_BoolValue saves bool values in the ON_HistoryRecord::m_value[] array // class ON_BoolValue : public ON_Value { public: ON_BoolValue(); ~ON_BoolValue(); ON_SimpleArray m_value; // virtual class ON_Value* Duplicate() const; // virtual int Count() const; // virtual bool ReadHelper(ON_BinaryArchive& archive ); // virtual bool WriteHelper(ON_BinaryArchive& archive ) const; // virtual bool ReportHelper(ON_TextLog& text_log ) const; // virtual int GetBools( const bool*& b ) const; }; ON_BoolValue::ON_BoolValue() : ON_Value(ON_Value::bool_value) { } ON_BoolValue::~ON_BoolValue() { } // virtual class ON_Value* ON_BoolValue::Duplicate() const { return new ON_BoolValue(*this); } // virtual int ON_BoolValue::Count() const { return m_value.Count(); } // virtual bool ON_BoolValue::ReadHelper(ON_BinaryArchive& archive ) { return archive.ReadArray(m_value); } // virtual bool ON_BoolValue::WriteHelper(ON_BinaryArchive& archive ) const { return archive.WriteArray(m_value); } // virtual bool ON_BoolValue::ReportHelper(ON_TextLog& text_log ) const { int i, count = m_value.Count(); text_log.Print("bool value\n"); text_log.PushIndent(); for ( i = 0; i < count; i++ ) { text_log.Print(m_value[i]?"true":"false"); } text_log.PopIndent(); return true; } // virtual int ON_BoolValue::GetBools( const bool*& b ) const { b = m_value.Array(); return m_value.Count(); } /////////////////////////////////////////////////////////////////////// // // ON_IntValue saves int values in the ON_HistoryRecord::m_value[] array // class ON_IntValue : public ON_Value { public: ON_IntValue(); ~ON_IntValue(); ON_SimpleArray m_value; // virtual class ON_Value* Duplicate() const; // virtual int Count() const; // virtual bool ReadHelper(ON_BinaryArchive& archive ); // virtual bool WriteHelper(ON_BinaryArchive& archive ) const; // virtual bool ReportHelper(ON_TextLog& text_log ) const; // virtual int GetInts( const int*& b ) const; }; ON_IntValue::ON_IntValue() : ON_Value(ON_Value::int_value) { } ON_IntValue::~ON_IntValue() { } // virtual class ON_Value* ON_IntValue::Duplicate() const { return new ON_IntValue(*this); } // virtual int ON_IntValue::Count() const { return m_value.Count(); } // virtual bool ON_IntValue::ReadHelper(ON_BinaryArchive& archive ) { return archive.ReadArray(m_value); } // virtual bool ON_IntValue::WriteHelper(ON_BinaryArchive& archive ) const { return archive.WriteArray(m_value); } // virtual bool ON_IntValue::ReportHelper(ON_TextLog& text_log ) const { int i, count = m_value.Count(); text_log.Print("integer value\n"); text_log.PushIndent(); for ( i = 0; i < count; i++ ) { text_log.Print("%d",m_value[i]); } text_log.PopIndent(); return true; } // virtual int ON_IntValue::GetInts( const int*& b ) const { b = m_value.Array(); return m_value.Count(); } /////////////////////////////////////////////////////////////////////// // // ON_DoubleValue saves bool values in the ON_HistoryRecord::m_value[] array // class ON_DoubleValue : public ON_Value { public: ON_DoubleValue(); ~ON_DoubleValue(); ON_SimpleArray m_value; // virtual class ON_Value* Duplicate() const; // virtual int Count() const; // virtual bool ReadHelper(ON_BinaryArchive& archive ); // virtual bool WriteHelper(ON_BinaryArchive& archive ) const; // virtual bool ReportHelper(ON_TextLog& text_log ) const; // virtual int GetDoubles( const double*& a ) const; }; ON_DoubleValue::ON_DoubleValue() : ON_Value(ON_Value::double_value) { } ON_DoubleValue::~ON_DoubleValue() { } // virtual class ON_Value* ON_DoubleValue::Duplicate() const { return new ON_DoubleValue(*this); } // virtual int ON_DoubleValue::Count() const { return m_value.Count(); } // virtual bool ON_DoubleValue::ReadHelper(ON_BinaryArchive& archive ) { return archive.ReadArray(m_value); } // virtual bool ON_DoubleValue::WriteHelper(ON_BinaryArchive& archive ) const { return archive.WriteArray(m_value); } // virtual bool ON_DoubleValue::ReportHelper(ON_TextLog& text_log ) const { int i, count = m_value.Count(); text_log.Print("number value\n"); text_log.PushIndent(); for ( i = 0; i < count; i++ ) { text_log.Print(m_value[i]); } text_log.PopIndent(); return true; } // virtual int ON_DoubleValue::GetDoubles( const double*& a ) const { a = m_value.Array(); return m_value.Count(); } /////////////////////////////////////////////////////////////////////// // // ON_PointValue saves bool values in the ON_HistoryRecord::m_value[] array // class ON_PointValue : public ON_Value { public: ON_PointValue(); ~ON_PointValue(); ON_SimpleArray m_value; // virtual class ON_Value* Duplicate() const; // virtual int Count() const; // virtual bool ReadHelper(ON_BinaryArchive& archive ); // virtual bool WriteHelper(ON_BinaryArchive& archive ) const; // virtual bool ReportHelper(ON_TextLog& text_log ) const; // virtual int Get3dPoints( const ON_3dPoint*& a ) const; }; ON_PointValue::ON_PointValue() : ON_Value(ON_Value::point_value) { } ON_PointValue::~ON_PointValue() { } // virtual class ON_Value* ON_PointValue::Duplicate() const { return new ON_PointValue(*this); } // virtual int ON_PointValue::Count() const { return m_value.Count(); } // virtual bool ON_PointValue::ReadHelper(ON_BinaryArchive& archive ) { return archive.ReadArray(m_value); } // virtual bool ON_PointValue::WriteHelper(ON_BinaryArchive& archive ) const { return archive.WriteArray(m_value); } // virtual bool ON_PointValue::ReportHelper(ON_TextLog& text_log ) const { int i, count = m_value.Count(); text_log.Print("point value\n"); text_log.PushIndent(); for ( i = 0; i < count; i++ ) { text_log.Print(m_value[i]); } text_log.PopIndent(); return true; } // virtual int ON_PointValue::Get3dPoints( const ON_3dPoint*& a ) const { a = m_value.Array(); return m_value.Count(); } /////////////////////////////////////////////////////////////////////// // // ON_VectorValue saves bool values in the ON_HistoryRecord::m_value[] array // class ON_VectorValue : public ON_Value { public: ON_VectorValue(); ~ON_VectorValue(); ON_SimpleArray m_value; // virtual class ON_Value* Duplicate() const; // virtual int Count() const; // virtual bool ReadHelper(ON_BinaryArchive& archive ); // virtual bool WriteHelper(ON_BinaryArchive& archive ) const; // virtual bool ReportHelper(ON_TextLog& text_log ) const; // virtual int Get3dVectors( const ON_3dVector*& a ) const; }; ON_VectorValue::ON_VectorValue() : ON_Value(ON_Value::vector_value) { } ON_VectorValue::~ON_VectorValue() { } // virtual class ON_Value* ON_VectorValue::Duplicate() const { return new ON_VectorValue(*this); } // virtual int ON_VectorValue::Count() const { return m_value.Count(); } // virtual bool ON_VectorValue::ReadHelper(ON_BinaryArchive& archive ) { return archive.ReadArray(m_value); } // virtual bool ON_VectorValue::WriteHelper(ON_BinaryArchive& archive ) const { return archive.WriteArray(m_value); } // virtual bool ON_VectorValue::ReportHelper(ON_TextLog& text_log ) const { text_log.Print("vector value\n"); text_log.PushIndent(); int i, count = m_value.Count(); for ( i = 0; i < count; i++ ) { text_log.Print(m_value[i]); } text_log.PopIndent(); return true; } // virtual int ON_VectorValue::Get3dVectors( const ON_3dVector*& a ) const { a = m_value.Array(); return m_value.Count(); } /////////////////////////////////////////////////////////////////////// // // ON_XformValue saves bool values in the ON_HistoryRecord::m_value[] array // class ON_XformValue : public ON_Value { public: ON_XformValue(); ~ON_XformValue(); ON_SimpleArray m_value; // virtual class ON_Value* Duplicate() const; // virtual int Count() const; // virtual bool ReadHelper(ON_BinaryArchive& archive ); // virtual bool WriteHelper(ON_BinaryArchive& archive ) const; // virtual bool ReportHelper(ON_TextLog& text_log ) const; // virtual int GetXforms( const ON_Xform*& a ) const; }; ON_XformValue::ON_XformValue() : ON_Value(ON_Value::xform_value) { } ON_XformValue::~ON_XformValue() { } // virtual class ON_Value* ON_XformValue::Duplicate() const { return new ON_XformValue(*this); } // virtual int ON_XformValue::Count() const { return m_value.Count(); } // virtual bool ON_XformValue::ReadHelper(ON_BinaryArchive& archive ) { return archive.ReadArray(m_value); } // virtual bool ON_XformValue::WriteHelper(ON_BinaryArchive& archive ) const { return archive.WriteArray(m_value); } // virtual bool ON_XformValue::ReportHelper(ON_TextLog& text_log ) const { text_log.Print("xform value\n"); text_log.PushIndent(); int i, count = m_value.Count(); for ( i = 0; i < count; i++ ) { text_log.Print(m_value[i]); } text_log.PopIndent(); return true; } // virtual int ON_XformValue::GetXforms( const ON_Xform*& a ) const { a = m_value.Array(); return m_value.Count(); } /////////////////////////////////////////////////////////////////////// // // ON_ColorValue saves bool values in the ON_HistoryRecord::m_value[] array // class ON_ColorValue : public ON_Value { public: ON_ColorValue(); ~ON_ColorValue(); ON_SimpleArray m_value; // virtual class ON_Value* Duplicate() const; // virtual int Count() const; // virtual bool ReadHelper(ON_BinaryArchive& archive ); // virtual bool WriteHelper(ON_BinaryArchive& archive ) const; // virtual bool ReportHelper(ON_TextLog& text_log ) const; // virtual int GetColors( const ON_Color*& a ) const; }; ON_ColorValue::ON_ColorValue() : ON_Value(ON_Value::color_value) { } ON_ColorValue::~ON_ColorValue() { } // virtual class ON_Value* ON_ColorValue::Duplicate() const { return new ON_ColorValue(*this); } // virtual int ON_ColorValue::Count() const { return m_value.Count(); } // virtual bool ON_ColorValue::ReadHelper(ON_BinaryArchive& archive ) { return archive.ReadArray(m_value); } // virtual bool ON_ColorValue::WriteHelper(ON_BinaryArchive& archive ) const { return archive.WriteArray(m_value); } // virtual bool ON_ColorValue::ReportHelper(ON_TextLog& text_log ) const { ON_Color c; text_log.Print("color value\n"); text_log.PushIndent(); int i, count = m_value.Count(); for ( i = 0; i < count; i++ ) { c = m_value[i]; text_log.Print("rbg(%d,%d,%d)",c.Red(),c.Green(),c.Blue()); } text_log.PopIndent(); return true; } // virtual int ON_ColorValue::GetColors( const ON_Color*& a ) const { a = m_value.Array(); return m_value.Count(); } /////////////////////////////////////////////////////////////////////// // // ON_UuidValue saves bool values in the ON_HistoryRecord::m_value[] array // class ON_UuidValue : public ON_Value { public: ON_UuidValue(); ~ON_UuidValue(); ON_SimpleArray m_value; // virtual class ON_Value* Duplicate() const; // virtual int Count() const; // virtual bool ReadHelper(ON_BinaryArchive& archive ); // virtual bool WriteHelper(ON_BinaryArchive& archive ) const; // virtual bool ReportHelper(ON_TextLog& text_log ) const; // virtual int GetUuids( const ON_UUID*& a ) const; }; ON_UuidValue::ON_UuidValue() : ON_Value(ON_Value::uuid_value) { } ON_UuidValue::~ON_UuidValue() { } // virtual class ON_Value* ON_UuidValue::Duplicate() const { return new ON_UuidValue(*this); } // virtual int ON_UuidValue::Count() const { return m_value.Count(); } // virtual bool ON_UuidValue::ReadHelper(ON_BinaryArchive& archive ) { return archive.ReadArray(m_value); } // virtual bool ON_UuidValue::WriteHelper(ON_BinaryArchive& archive ) const { return archive.WriteArray(m_value); } // virtual bool ON_UuidValue::ReportHelper(ON_TextLog& text_log ) const { text_log.Print("uuid value\n"); text_log.PushIndent(); int i, count = m_value.Count(); for ( i = 0; i < count; i++ ) { text_log.Print(m_value[i]); } text_log.PopIndent(); return true; } // virtual int ON_UuidValue::GetUuids( const ON_UUID*& a ) const { a = m_value.Array(); return m_value.Count(); } /////////////////////////////////////////////////////////////////////// // // ON_StringValue saves string values in the ON_HistoryRecord::m_value[] array // class ON_StringValue : public ON_Value { public: ON_StringValue(); ~ON_StringValue(); ON_ClassArray m_value; // virtual class ON_Value* Duplicate() const; // virtual int Count() const; // virtual bool ReadHelper(ON_BinaryArchive& archive ); // virtual bool WriteHelper(ON_BinaryArchive& archive ) const; // virtual bool ReportHelper(ON_TextLog& text_log ) const; // virtual int GetStrings( ON_ClassArray& s ) const; }; ON_StringValue::ON_StringValue() : ON_Value(ON_Value::string_value) { } ON_StringValue::~ON_StringValue() { } // virtual class ON_Value* ON_StringValue::Duplicate() const { return new ON_StringValue(*this); } // virtual int ON_StringValue::Count() const { return m_value.Count(); } // virtual bool ON_StringValue::ReadHelper(ON_BinaryArchive& archive ) { return archive.ReadArray(m_value); } // virtual bool ON_StringValue::WriteHelper(ON_BinaryArchive& archive ) const { return archive.WriteArray(m_value); } // virtual bool ON_StringValue::ReportHelper(ON_TextLog& text_log ) const { text_log.Print("string value\n"); text_log.PushIndent(); int i, count = m_value.Count(); for ( i = 0; i < count; i++ ) { text_log.Print(m_value[i]); } text_log.PopIndent(); return true; } // virtual int ON_StringValue::GetStrings( ON_ClassArray& s ) const { s = m_value; return m_value.Count(); } /////////////////////////////////////////////////////////////////////// // // ON_ObjRefValue saves objref values in the ON_HistoryRecord::m_value[] array // class ON_ObjRefValue : public ON_Value { public: ON_ObjRefValue(); ~ON_ObjRefValue(); ON_ClassArray m_value; // virtual class ON_Value* Duplicate() const; // virtual int Count() const; // virtual bool ReadHelper(ON_BinaryArchive& archive ); // virtual bool WriteHelper(ON_BinaryArchive& archive ) const; // virtual bool ReportHelper(ON_TextLog& text_log ) const; // virtual int GetObjRefs( ON_ClassArray& oref ) const; }; ON_ObjRefValue::ON_ObjRefValue() : ON_Value(ON_Value::objref_value) { } ON_ObjRefValue::~ON_ObjRefValue() { } // virtual class ON_Value* ON_ObjRefValue::Duplicate() const { return new ON_ObjRefValue(*this); } // virtual int ON_ObjRefValue::Count() const { return m_value.Count(); } // virtual bool ON_ObjRefValue::ReadHelper(ON_BinaryArchive& archive ) { return archive.ReadArray(m_value); } // virtual bool ON_ObjRefValue::WriteHelper(ON_BinaryArchive& archive ) const { return archive.WriteArray(m_value); } // virtual bool ON_ObjRefValue::ReportHelper(ON_TextLog& text_log ) const { text_log.Print("objref value\n"); text_log.PushIndent(); int i, count = m_value.Count(); for ( i = 0; i < count; i++ ) { text_log.Print("object id: "); text_log.Print(m_value[i].m_uuid); text_log.Print("\n"); } text_log.PopIndent(); return true; } // virtual int ON_ObjRefValue::GetObjRefs( ON_ClassArray& s ) const { s = m_value; return m_value.Count(); } /////////////////////////////////////////////////////////////////////// // // ON_GeometryValue saves geometry values in the ON_HistoryRecord::m_value[] array // class ON_GeometryValue : public ON_Value { public: ON_GeometryValue(); ~ON_GeometryValue(); ON_GeometryValue(const ON_GeometryValue& src); ON_GeometryValue& operator=(const ON_GeometryValue& src); ON_SimpleArray m_value; // virtual class ON_Value* Duplicate() const; // virtual int Count() const; // virtual bool ReadHelper(ON_BinaryArchive& archive ); // virtual bool WriteHelper(ON_BinaryArchive& archive ) const; // virtual bool ReportHelper(ON_TextLog& text_log ) const; // virtual int GetGeometryPointers( const ON_Geometry* const*& ) const; }; ON_GeometryValue::ON_GeometryValue() : ON_Value(ON_Value::geometry_value) { } ON_GeometryValue::~ON_GeometryValue() { int i, count = m_value.Count(); for ( i = 0; i < count; i++ ) { ON_Geometry* p = m_value[i]; m_value[i] = 0; if (p) { delete p; } } } ON_GeometryValue::ON_GeometryValue(const ON_GeometryValue& src) : ON_Value(src) { *this = src; } ON_GeometryValue& ON_GeometryValue::operator=(const ON_GeometryValue& src) { if ( this != &src ) { int i, count = m_value.Count(); for ( i = 0; i < count; i++ ) { ON_Geometry* p = m_value[i]; m_value[i] = 0; if (p) { delete p; } } m_value.Destroy(); m_value_id = src.m_value_id; count = src.m_value.Count(); m_value.Reserve(count); for ( i = 0; i < count; i++ ) { const ON_Geometry* src_ptr = src.m_value[i]; if ( !src_ptr ) continue; ON_Geometry* ptr = src_ptr->Duplicate(); if ( ptr ) m_value.Append(ptr); } } return *this; } // virtual class ON_Value* ON_GeometryValue::Duplicate() const { return new ON_GeometryValue(*this); } // virtual int ON_GeometryValue::Count() const { return m_value.Count(); } // virtual bool ON_GeometryValue::ReadHelper(ON_BinaryArchive& archive ) { int i, count = m_value.Count(); for ( i = 0; i < count; i++ ) { delete m_value[i]; } m_value.SetCount(0); int major_version = 0; int minor_version = 0; bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version); if (!rc) return false; for(;;) { rc = archive.ReadInt(&count); if (!rc) break; m_value.Reserve(count); for( i = 0; i < count && rc; i++ ) { ON_Object* p=0; rc = archive.ReadObject(&p) > 0; if (rc) { ON_Geometry* g = ON_Geometry::Cast(p); if (g) { p = 0; m_value.Append(g); } } if ( p ) delete p; } if (!rc) break; break; } if ( !archive.EndRead3dmChunk() ) rc = false; return rc; } // virtual bool ON_GeometryValue::WriteHelper(ON_BinaryArchive& archive ) const { bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0); if (!rc) return false; for(;;) { rc = archive.WriteInt(m_value.Count()); if (!rc) break; int i, count = m_value.Count(); for( i = 0; i < count && rc; i++ ) { rc = archive.WriteObject(m_value[i]); } if (!rc) break; break; } if ( !archive.EndWrite3dmChunk() ) rc = false; return rc; } // virtual bool ON_GeometryValue::ReportHelper(ON_TextLog& text_log ) const { text_log.Print("geometry value\n"); text_log.PushIndent(); int i, count = m_value.Count(); for ( i = 0; i < count; i++ ) { const ON_Geometry* p = m_value[i]; if ( p ) p->Dump(text_log); } text_log.PopIndent(); return true; } // virtual int ON_GeometryValue::GetGeometryPointers( const ON_Geometry* const*&a ) const { a = m_value.Array(); return m_value.Count(); } /////////////////////////////////////////////////////////////////////// // // ON_PolyEdgeHistoryValue saves geometry values in the ON_HistoryRecord::m_value[] array // class ON_PolyEdgeHistoryValue : public ON_Value { public: ON_PolyEdgeHistoryValue(); ~ON_PolyEdgeHistoryValue(); ON_ClassArray m_value; // virtual class ON_Value* Duplicate() const; // virtual int Count() const; // virtual bool ReadHelper(ON_BinaryArchive& archive ); // virtual bool WriteHelper(ON_BinaryArchive& archive ) const; // virtual bool ReportHelper(ON_TextLog& text_log ) const; // virtual int GetPolyEdgePointers( ON_ClassArray& ) const; }; ON_PolyEdgeHistoryValue::ON_PolyEdgeHistoryValue() : ON_Value(ON_Value::polyedge_value) { } ON_PolyEdgeHistoryValue::~ON_PolyEdgeHistoryValue() { m_value.Destroy(); } //ON_PolyEdgeHistoryValue::ON_PolyEdgeHistoryValue(const ON_PolyEdgeHistoryValue& src) : ON_Value(src) //{ // *this = src; //} // //ON_PolyEdgeHistoryValue& ON_PolyEdgeHistoryValue::operator=(const ON_PolyEdgeHistoryValue& src) //{ // if ( this != &src ) // { // int i, count = m_value.Count(); // for ( i = 0; i < count; i++ ) // { // ON_Geometry* p = m_value[i]; // m_value[i] = 0; // if (p) // { // delete p; // } // } // m_value.Destroy(); // // m_value_id = src.m_value_id; // // count = src.m_value.Count(); // m_value.Reserve(count); // for ( i = 0; i < count; i++ ) // { // const ON_Geometry* src_ptr = src.m_value[i]; // if ( !src_ptr ) // continue; // ON_Geometry* ptr = src_ptr->Duplicate(); // if ( ptr ) // m_value.Append(ptr); // } // } // return *this; //} // virtual class ON_Value* ON_PolyEdgeHistoryValue::Duplicate() const { return new ON_PolyEdgeHistoryValue(*this); } // virtual int ON_PolyEdgeHistoryValue::Count() const { return m_value.Count(); } // virtual bool ON_PolyEdgeHistoryValue::ReadHelper(ON_BinaryArchive& archive ) { m_value.Destroy(); int major_version = 0; int minor_version = 0; bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version); if (!rc) return false; for(;;) { int count = 0; rc = archive.ReadInt(&count); if (!rc) break; m_value.Reserve(count); for( int i = 0; i < count && rc; i++ ) { if ( !m_value.AppendNew().Read(archive) ) { m_value.Destroy(); rc = false; break; } } if (!rc) break; break; } if ( !archive.EndRead3dmChunk() ) rc = false; return rc; } // virtual bool ON_PolyEdgeHistoryValue::WriteHelper(ON_BinaryArchive& archive ) const { bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0); if (!rc) return false; for(;;) { rc = archive.WriteInt(m_value.Count()); if (!rc) break; int i, count = m_value.Count(); for( i = 0; i < count && rc; i++ ) { rc = m_value[i].Write(archive); } if (!rc) break; break; } if ( !archive.EndWrite3dmChunk() ) rc = false; return rc; } // virtual bool ON_PolyEdgeHistoryValue::ReportHelper(ON_TextLog& text_log ) const { text_log.Print("polyedge value\n"); text_log.PushIndent(); int i, count = m_value.Count(); for ( i = 0; i < count; i++ ) { m_value[i].Dump(text_log); } text_log.PopIndent(); return true; } // virtual int ON_PolyEdgeHistoryValue::GetPolyEdgePointers( ON_ClassArray& a ) const { a = m_value; return m_value.Count(); } /////////////////////////////////////////////////////////////////////// // // ON_SubDEdgeChainHistoryValue saves geometry values in the ON_HistoryRecord::m_value[] array // class ON_SubDEdgeChainHistoryValue : public ON_Value { public: ON_SubDEdgeChainHistoryValue(); ~ON_SubDEdgeChainHistoryValue(); ON_SubDEdgeChainHistoryValue(const ON_SubDEdgeChainHistoryValue&); ON_SubDEdgeChainHistoryValue& operator=(const ON_SubDEdgeChainHistoryValue&); ON_SimpleArray m_value; class ON_Value* Duplicate() const override; int Count() const override; bool ReadHelper(ON_BinaryArchive& archive) override; bool WriteHelper(ON_BinaryArchive& archive) const override; bool ReportHelper(ON_TextLog& text_log) const override; int GetSubDEdgeChainPointers(const ON_SubDEdgeChain* const*&) const override; }; ON_SubDEdgeChainHistoryValue::ON_SubDEdgeChainHistoryValue() : ON_Value(ON_Value::subd_edge_chain_value) { } ON_SubDEdgeChainHistoryValue::~ON_SubDEdgeChainHistoryValue() { int i, count = m_value.Count(); for (i = 0; i < count; i++) { ON_SubDEdgeChain* p = m_value[i]; if (nullptr != p) { m_value[i] = nullptr; delete p; } } } ON_SubDEdgeChainHistoryValue::ON_SubDEdgeChainHistoryValue(const ON_SubDEdgeChainHistoryValue& src) : ON_Value(src) { *this = src; } ON_SubDEdgeChainHistoryValue& ON_SubDEdgeChainHistoryValue::operator=(const ON_SubDEdgeChainHistoryValue& src) { if (this != &src) { int i, count = m_value.Count(); for (i = 0; i < count; i++) { ON_SubDEdgeChain* p = m_value[i]; if (nullptr != p) { m_value[i] = nullptr; delete p; } } m_value.Destroy(); m_value_id = src.m_value_id; count = src.m_value.Count(); m_value.Reserve(count); for (i = 0; i < count; i++) { const ON_SubDEdgeChain* src_ptr = src.m_value[i]; if (!src_ptr) continue; ON_SubDEdgeChain* ptr = new ON_SubDEdgeChain(*src_ptr); if (ptr) m_value.Append(ptr); } } return *this; } // virtual class ON_Value* ON_SubDEdgeChainHistoryValue::Duplicate() const { return new ON_SubDEdgeChainHistoryValue(*this); } // virtual int ON_SubDEdgeChainHistoryValue::Count() const { return m_value.Count(); } // virtual bool ON_SubDEdgeChainHistoryValue::ReadHelper(ON_BinaryArchive& archive) { m_value.Destroy(); int chunk_version = 0; if (false == archive.BeginRead3dmAnonymousChunk(&chunk_version)) return false; bool rc = false; for (;;) { if (chunk_version < 1) break; int count = 0; if (false == archive.ReadInt(&count)) break; m_value.Reserve(count); for (int i = 0; i < count; i++) { ON_SubDEdgeChain* c = new ON_SubDEdgeChain(); if (false == c->Read(archive)) break; m_value.Append(c); } if (count == m_value.Count()) rc = true; else m_value.Destroy(); break; } if (!archive.EndRead3dmChunk()) rc = false; return rc; } // virtual bool ON_SubDEdgeChainHistoryValue::WriteHelper(ON_BinaryArchive& archive) const { if (false == archive.BeginWrite3dmAnonymousChunk(1)) return false; bool rc = false; for (;;) { int count = m_value.Count(); for (int i = 0; i < count; ++i) { if (nullptr == m_value[i]) count = 0; } if (false == archive.WriteInt(count)) break; rc = true; for (int i = 0; i < count && rc; i++) rc = m_value[i]->Write(archive); break; } if (!archive.EndWrite3dmChunk()) rc = false; return rc; } // virtual bool ON_SubDEdgeChainHistoryValue::ReportHelper(ON_TextLog& text_log) const { text_log.Print("SubD edge chain value\n"); text_log.PushIndent(); int i, count = m_value.Count(); for (i = 0; i < count; i++) { if( nullptr != m_value[i]) m_value[i]->Dump(text_log); } text_log.PopIndent(); return true; } // virtual int ON_SubDEdgeChainHistoryValue::GetSubDEdgeChainPointers(const ON_SubDEdgeChain* const*& a) const { a = m_value.Array(); return m_value.Count(); } /////////////////////////////////////////////////////////////////////// // // static ON_Value* ON_Value::CreateValue( int value_type ) { ON_Value* value = 0; switch((unsigned int)value_type) { case no_value_type: break; case bool_value: value = new ON_BoolValue(); break; case int_value: value = new ON_IntValue(); break; case double_value: value = new ON_DoubleValue(); break; case color_value: value = new ON_ColorValue(); break; case point_value: value = new ON_PointValue(); break; case vector_value: value = new ON_VectorValue(); break; case xform_value: value = new ON_XformValue(); break; case string_value: value = new ON_StringValue(); break; case objref_value: value = new ON_ObjRefValue(); break; case geometry_value: value = new ON_GeometryValue(); break; case uuid_value: value = new ON_UuidValue(); break; case point_on_object_value: //value = new ON_PointOnObjectValue(); break; case polyedge_value: value = new ON_PolyEdgeHistoryValue(); break; case subd_edge_chain_value: value = new ON_SubDEdgeChainHistoryValue(); break; case force_32bit_enum: break; default: break; } return value; } /////////////////////////////////////////////////////////////////////// // // ON_HistoryRecord implementation // ON_OBJECT_IMPLEMENT(ON_HistoryRecord,ON_ModelComponent,"ECD0FD2F-2088-49dc-9641-9CF7A28FFA6B"); ON_HistoryRecord::ON_HistoryRecord() ON_NOEXCEPT : ON_ModelComponent(ON_ModelComponent::Type::HistoryRecord) {} ON_HistoryRecord::~ON_HistoryRecord() { Internal_Destroy(); } ON_HistoryRecord::ON_HistoryRecord(const ON_HistoryRecord& src) : ON_ModelComponent(ON_ModelComponent::Type::HistoryRecord,src) { Internal_Copy(src); } ON_HistoryRecord& ON_HistoryRecord::operator=(const ON_HistoryRecord& src) { if ( this != &src && false == this->IsSystemComponent() ) { ON_ModelComponent::operator=(*this); Internal_Destroy(); ON_Object::operator=(src); Internal_Copy(src); } return *this; } void ON_HistoryRecord::Internal_Copy(const ON_HistoryRecord& src) { // input value of this->m_value[] is known to be empty m_command_id = src.m_command_id; m_version = src.m_version; m_record_type = src.m_record_type; m_descendants = src.m_descendants; m_antecedents = src.m_antecedents; m_bValuesSorted = true; m_bCopyOnReplaceObject = src.m_bCopyOnReplaceObject; const unsigned int count = src.m_value.UnsignedCount(); m_value.SetCapacity(count); const ON_Value* prev_v = 0; for (unsigned int i = 0; i < count; i++) { const ON_Value* src_v = src.m_value[i]; if (src_v) { ON_Value* v = src_v->Duplicate(); if (v) { m_value.Append(v); if (m_bValuesSorted && prev_v && prev_v->m_value_id > v->m_value_id) m_bValuesSorted = false; prev_v = v; } } } } bool ON_HistoryRecord::IsValid( ON_TextLog* text_log ) const { return true; } void ON_HistoryRecord::Internal_Destroy() { const unsigned int count = m_value.UnsignedCount(); for ( unsigned int i = 0; i < count; i++ ) { ON_Value* v = m_value[i]; if (nullptr != v) { m_value[i] = nullptr; delete v; } } m_value.Empty(); } ON_HistoryRecord::RECORD_TYPE ON_HistoryRecord::RecordType(int i) { switch (i) { case (int)ON_HistoryRecord::RECORD_TYPE::history_parameters: return ON_HistoryRecord::RECORD_TYPE::history_parameters; case (int)ON_HistoryRecord::RECORD_TYPE::feature_parameters: return ON_HistoryRecord::RECORD_TYPE::feature_parameters; } return ON_HistoryRecord::RECORD_TYPE::history_parameters; } bool ON_HistoryRecord::SetBoolValue( int value_id, bool b) { return ( 1 == SetBoolValues(value_id, 1, &b) ); } bool ON_HistoryRecord::SetIntValue( int value_id, int i) { return ( 1 == SetIntValues(value_id, 1, &i) ); } bool ON_HistoryRecord::SetDoubleValue( int value_id, double x) { return ( 1 == SetDoubleValues(value_id, 1, &x) ); } bool ON_HistoryRecord::SetPointValue( int value_id, ON_3dPoint p) { return ( 1 == SetPointValues(value_id, 1, &p) ); } bool ON_HistoryRecord::SetVectorValue( int value_id, ON_3dVector v) { return ( 1 == SetVectorValues(value_id, 1, &v) ); } bool ON_HistoryRecord::SetXformValue( int value_id, ON_Xform xform) { return ( 1 == SetXformValues(value_id, 1, &xform) ); } bool ON_HistoryRecord::SetColorValue( int value_id, ON_Color c) { return ( 1 == SetColorValues(value_id, 1, &c) ); } bool ON_HistoryRecord::SetObjRefValue( int value_id, const ON_ObjRef& oref) { return ( 1 == SetObjRefValues(value_id, 1, &oref) ); } bool ON_HistoryRecord::SetPointOnObjectValue( int value_id, const ON_ObjRef& oref, ON_3dPoint point ) { ON_ObjRef poo = oref; poo.m_point = point; return SetObjRefValue(value_id,poo); } bool ON_HistoryRecord::GetPointOnObjectValue( int value_id, ON_ObjRef& oref ) const { bool rc = GetObjRefValue(value_id,oref); return (rc && oref.m_point.IsValid()); } bool ON_HistoryRecord::SetGeometryValue( int value_id, ON_Geometry* g) { ON_SimpleArray a(1); a.Append(g); return SetGeometryValues(value_id, a); } bool ON_HistoryRecord::SetPolyEdgeValue( int value_id, const ON_PolyEdgeHistory& polyedge ) { return ( 1 == SetPolyEdgeValues(value_id, 1, &polyedge) ); } bool ON_HistoryRecord::SetUuidValue( int value_id, ON_UUID uuid ) { return ( 1 == SetUuidValues(value_id, 1, &uuid) ); } static int CompareValueIdHelper(const ON_Value* a, const ON_Value* b ) { if (!a) { return b ? -1 : 0; } if (!b) { return 1; } return (a->m_value_id - b->m_value_id); } static int CompareValueId( ON_Value * const * a, ON_Value * const * b ) { // handle NULLs in case somebody messes up the m_value[] array. if ( !a ) { return b ? -1 : 0; } if (!b) return 1; return CompareValueIdHelper(*a,*b); } ON_Value* ON_HistoryRecord::FindValueHelper( int value_id, int value_type, bool bCreateOne ) const { ON_HistoryRecord* vp = const_cast(this); if ( m_value.Count() > 0 ) { if ( !m_bValuesSorted ) { vp->m_value.QuickSort(CompareValueId); vp->m_bValuesSorted = true; } ON_DummyValue dummy_value; dummy_value.m_value_id = value_id; ON_Value* p = &dummy_value; int i = m_value.BinarySearch(&p,CompareValueId); if ( i >= 0 ) { // m_value[i]->m_value_id == value_id if ( value_type == ((int)m_value[i]->m_value_type) ) { // type matches return m_value[i]; } if ( bCreateOne ) { // type does not match - replace the existing one ON_Value* new_value = ON_Value::CreateValue(value_type); if ( new_value ) { new_value->m_value_id = value_id; delete m_value[i]; vp->m_value[i] = new_value; return new_value; } } } else if ( bCreateOne ) { // no value in m_value[] array with a matching value_id ON_Value* new_value = ON_Value::CreateValue(value_type); if ( new_value ) { new_value->m_value_id = value_id; if ( m_bValuesSorted && (*m_value.Last())->m_value_id > value_id ) vp->m_bValuesSorted = false; vp->m_value.Append(new_value); return new_value; } } } else if ( bCreateOne ) { ON_Value* new_value = ON_Value::CreateValue(value_type); if ( new_value ) { new_value->m_value_id = value_id; vp->m_bValuesSorted = true; vp->m_value.Append(new_value); return new_value; } } return 0; } bool ON_HistoryRecord::SetBoolValues( int value_id, int count, const bool* b) { ON_BoolValue* v = static_cast(FindValueHelper(value_id,ON_Value::bool_value,true)); if ( v ) { v->m_value.SetCount(0); v->m_value.SetCapacity(count); v->m_value.Append(count,b); } return (0 != v); } bool ON_HistoryRecord::SetIntValues( int value_id, int count, const int* i) { ON_IntValue* v = static_cast(FindValueHelper(value_id,ON_Value::int_value,true)); if ( v ) { v->m_value.SetCount(0); v->m_value.SetCapacity(count); v->m_value.Append(count,i); } return (0 != v); } bool ON_HistoryRecord::SetDoubleValues( int value_id, int count, const double* x) { ON_DoubleValue* v = static_cast(FindValueHelper(value_id,ON_Value::double_value,true)); if ( v ) { v->m_value.SetCount(0); v->m_value.SetCapacity(count); v->m_value.Append(count,x); } return (0 != v); } bool ON_HistoryRecord::SetPointValues( int value_id, int count, const ON_3dPoint* P) { ON_PointValue* v = static_cast(FindValueHelper(value_id,ON_Value::point_value,true)); if ( v ) { v->m_value.SetCount(0); v->m_value.SetCapacity(count); v->m_value.Append(count,P); } return (0 != v); } bool ON_HistoryRecord::SetVectorValues( int value_id, int count, const ON_3dVector* V) { ON_VectorValue* v = static_cast(FindValueHelper(value_id,ON_Value::vector_value,true)); if ( v ) { v->m_value.SetCount(0); v->m_value.SetCapacity(count); v->m_value.Append(count,V); } return (0 != v); } bool ON_HistoryRecord::SetXformValues( int value_id, int count, const ON_Xform* xform) { ON_XformValue* v = static_cast(FindValueHelper(value_id,ON_Value::xform_value,true)); if ( v ) { v->m_value.SetCount(0); v->m_value.SetCapacity(count); v->m_value.Append(count,xform); } return (0 != v); } bool ON_HistoryRecord::SetColorValues( int value_id, int count, const ON_Color* c) { ON_ColorValue* v = static_cast(FindValueHelper(value_id,ON_Value::color_value,true)); if ( v ) { v->m_value.SetCount(0); v->m_value.SetCapacity(count); v->m_value.Append(count,c); } return (0 != v); } bool ON_HistoryRecord::SetUuidValues( int value_id, int count, const ON_UUID* u ) { ON_UuidValue* v = static_cast(FindValueHelper(value_id,ON_Value::uuid_value,true)); if ( v ) { v->m_value.SetCount(0); v->m_value.SetCapacity(count); v->m_value.Append(count,u); } return (0 != v); } bool ON_HistoryRecord::SetStringValues( int value_id, int count, const wchar_t* const* s ) { ON_StringValue* v = static_cast(FindValueHelper(value_id,ON_Value::string_value,true)); if ( v ) { v->m_value.Destroy(); v->m_value.Reserve(count); int i; for( i = 0; i < count; i++ ) { v->m_value.AppendNew() = s[i]; } } return (0 != v); } bool ON_HistoryRecord::SetStringValues( int value_id, const ON_ClassArray& s ) { ON_StringValue* v = static_cast(FindValueHelper(value_id,ON_Value::string_value,true)); if ( v ) { v->m_value = s; } return (0 != v); } bool ON_HistoryRecord::SetStringValue( int value_id, const wchar_t* s ) { ON_StringValue* v = static_cast(FindValueHelper(value_id,ON_Value::string_value,true)); if ( v ) { v->m_value.Destroy(); v->m_value.AppendNew() = s; } return (0 != v); } bool ON_HistoryRecord::SetObjRefValues( int value_id, int count, const ON_ObjRef* oref) { ON_ObjRefValue* v = static_cast(FindValueHelper(value_id,ON_Value::objref_value,true)); if ( v ) { v->m_value.Destroy(); v->m_value.Reserve(count); if(count) { // 2019-01-23 - kike@mcneel.com // Objects in instance definitions can not be modified in that case // I add the root instance reference and all the instance definitions as 'antecedents' const bool idef_geometry = oref && (oref->m__iref.Count() > 0); for(int i = 0; i < count; i++) { // The call to DecrementProxyReferenceCount() is critical. // It makes sure there are no active runtime pointers // saved in the history record. If this call is not here, // you will eventually crash and history update will never // work right even when it doesn't crash. ON_ObjRef& vor = v->m_value.AppendNew(); vor = oref[i]; vor.DecrementProxyReferenceCount(); // Feb 12 2010 - Fixing bug in ExtrudeCrv history // and probably lots of other subtle history bugs. // History must lookup by UUID and not by runtime serial number. vor.m_runtime_sn = 0; // 2019-01-23 - kike@mcneel.com if(!idef_geometry) { ON_UUID object_id = v->m_value[i].m_uuid; if(!ON_UuidIsNil(object_id)) { m_antecedents.AddUuid(object_id); } } } // 2019-01-23 - kike@mcneel.com if(idef_geometry) { if(auto iref = oref->m__iref.Last()) m_antecedents.AddUuid(iref->m_iref_uuid); for(int r = 0; r < oref->m__iref.Count(); ++r) m_antecedents.AddUuid(oref->m__iref[r].m_idef_uuid); } } } return (0 != v); } bool ON_HistoryRecord::SetGeometryValues(int value_id, const ON_SimpleArray a) { ON_GeometryValue* v = static_cast(FindValueHelper(value_id, ON_Value::geometry_value, true)); if (v) { v->m_value = a; } return (0 != v); } bool ON_HistoryRecord::SetSubDEdgeChainValue(int value_id, const ON_SubDEdgeChain& edge_chain) { ON_SimpleArray a; a.Append(&edge_chain); return ON_HistoryRecord::SetSubDEdgeChainValues(value_id, a); } bool ON_HistoryRecord::SetSubDEdgeChainValues(int value_id, const ON_ClassArray& edge_chains) { const unsigned count = edge_chains.UnsignedCount(); ON_SimpleArray a(count); for (unsigned i = 0; i < count; ++i) a.Append(&edge_chains[i]); return ON_HistoryRecord::SetSubDEdgeChainValues(value_id, a); } bool ON_HistoryRecord::SetSubDEdgeChainValues(int value_id, const ON_SimpleArray& edge_chains) { // validate const unsigned count = edge_chains.UnsignedCount(); if (count <= 0) return false; for (unsigned i = 0; i < count; ++i) { const ON_SubDEdgeChain* c = edge_chains[i]; if (nullptr == c) return false; const ON_UUID parent_subd_id = c->PersistentSubDId(); if (ON_nil_uuid == parent_subd_id) return false; // a persistent id is reqiured so that update history can find the new subd and update the runtime ON_SubDEdgePtr values. if (c->EdgeCount() <= 0) return false; if (false == c->HasPersistentEdgeIds()) { c->SetPersistentEdgeIdsFromRuntimeEdgePtrs(); if (false == c->HasPersistentEdgeIds()) return false; } m_antecedents.AddUuid(parent_subd_id, true); } // copy edge chains and add ON_SubDEdgeChainHistoryValue* v = static_cast(FindValueHelper(value_id, ON_Value::subd_edge_chain_value, true)); if ( nullptr != v ) { v->m_value.Reserve(count); for (unsigned i = 0; i < count; ++i) v->m_value.Append(new ON_SubDEdgeChain(*edge_chains[i])); } return (nullptr != v); } bool ON_HistoryRecord::SetPolyEdgeValues( int value_id, int count, const ON_PolyEdgeHistory* a ) { ON_PolyEdgeHistoryValue* v = static_cast(FindValueHelper(value_id,ON_Value::polyedge_value,true)); if ( v ) { v->m_value.Destroy(); v->m_value.Append(count,a); for ( int i = 0; i < count; i++ ) { const ON_PolyEdgeHistory& pe_history = a[i]; for ( int j = 0; j < pe_history.m_segment.Count(); j++ ) { const ON_CurveProxyHistory& segment = pe_history.m_segment[j]; m_antecedents.AddUuid(segment.m_curve_ref.m_uuid); } } } return (0 != v); } bool ON_HistoryRecord::GetBoolValue( int value_id, bool* b ) const { bool rc = false; const ON_BoolValue* v = static_cast(FindValueHelper(value_id,ON_Value::bool_value,0)); if ( v && 1 == v->m_value.Count()) { *b = v->m_value[0]; rc = true; } return rc; } bool ON_HistoryRecord::GetIntValue( int value_id, int* i ) const { bool rc = false; const ON_IntValue* v = static_cast(FindValueHelper(value_id,ON_Value::int_value,0)); if ( v && 1 == v->m_value.Count()) { *i = v->m_value[0]; rc = true; } return rc; } bool ON_HistoryRecord::GetDoubleValue( int value_id, double* number ) const { bool rc = false; const ON_DoubleValue* v = static_cast(FindValueHelper(value_id,ON_Value::double_value,0)); if ( v && 1 == v->m_value.Count()) { *number = v->m_value[0]; rc = true; } return rc; } bool ON_HistoryRecord::GetPointValue( int value_id, ON_3dPoint& point ) const { bool rc = false; const ON_PointValue* v = static_cast(FindValueHelper(value_id,ON_Value::point_value,0)); if ( v && 1 == v->m_value.Count()) { point = v->m_value[0]; rc = true; } return rc; } bool ON_HistoryRecord::GetVectorValue( int value_id, ON_3dVector& vector ) const { bool rc = false; const ON_VectorValue* v = static_cast(FindValueHelper(value_id,ON_Value::vector_value,0)); if ( v && 1 == v->m_value.Count()) { vector = v->m_value[0]; rc = true; } return rc; } bool ON_HistoryRecord::GetXformValue( int value_id, ON_Xform& xform ) const { bool rc = false; const ON_XformValue* v = static_cast(FindValueHelper(value_id,ON_Value::xform_value,0)); if ( v && 1 == v->m_value.Count()) { xform = v->m_value[0]; rc = true; } return rc; } bool ON_HistoryRecord::GetColorValue( int value_id, ON_Color* color ) const { bool rc = false; const ON_ColorValue* v = static_cast(FindValueHelper(value_id,ON_Value::color_value,0)); if ( v && 1 == v->m_value.Count()) { *color = v->m_value[0]; rc = true; } return rc; } bool ON_HistoryRecord::GetObjRefValue( int value_id, ON_ObjRef& oref ) const { bool rc = false; const ON_ObjRefValue* v = static_cast(FindValueHelper(value_id,ON_Value::objref_value,0)); if ( v && 1 == v->m_value.Count()) { oref = v->m_value[0]; rc = true; } return rc; } bool ON_HistoryRecord::GetStringValue( int value_id, ON_wString& str ) const { bool rc = false; ON_StringValue* v = static_cast(FindValueHelper(value_id,ON_Value::string_value,0)); if ( v && 1 == v->m_value.Count()) { str = v->m_value[0]; rc = true; } return rc; } bool ON_HistoryRecord::GetGeometryValue( int value_id, const ON_Geometry*& g ) const { bool rc = false; g = 0; const ON_GeometryValue* v = static_cast(FindValueHelper(value_id,ON_Value::geometry_value,0)); if ( v && 1 == v->m_value.Count()) { g = v->m_value[0]; rc = true; } return rc; } bool ON_HistoryRecord::GetSubDEdgeChainValue(int value_id, const ON_SubDEdgeChain*& edge_chain) const { bool rc = false; edge_chain = 0; const ON_SubDEdgeChainHistoryValue* v = static_cast(FindValueHelper(value_id, ON_Value::subd_edge_chain_value, 0)); if (v && 1 == v->m_value.Count()) { edge_chain = v->m_value[0]; rc = true; } return rc; } bool ON_HistoryRecord::GetPolyEdgeValue( int value_id, const ON_PolyEdgeHistory*& polyedge ) const { bool rc = false; polyedge = 0; const ON_PolyEdgeHistoryValue* v = static_cast(FindValueHelper(value_id,ON_Value::polyedge_value,0)); if ( v && 1 == v->m_value.Count()) { polyedge = &v->m_value[0]; rc = true; } return rc; } bool ON_HistoryRecord::GetCurveValue( int value_id, const ON_Curve*& c ) const { c = 0; const ON_Geometry* g = 0; if (GetGeometryValue( value_id, g )) { c = ON_Curve::Cast(g); } return (0 != c); } bool ON_HistoryRecord::GetSurfaceValue( int value_id, const ON_Surface*& s ) const { s = 0; const ON_Geometry* g = 0; if (GetGeometryValue( value_id, g )) { s = ON_Surface::Cast(g); } return (0 != s); } bool ON_HistoryRecord::GetBrepValue( int value_id, const ON_Brep*& b ) const { b = 0; const ON_Geometry* g = 0; if (GetGeometryValue( value_id, g )) { b = ON_Brep::Cast(g); } return (0 != b); } bool ON_HistoryRecord::GetMeshValue( int value_id, const ON_Mesh*& m ) const { m = 0; const ON_Geometry* g = 0; if (GetGeometryValue( value_id, g )) { m = ON_Mesh::Cast(g); } return (0 != m); } bool ON_HistoryRecord::GetUuidValue( int value_id, ON_UUID* uuid ) const { bool rc = false; const ON_UuidValue* v = static_cast(FindValueHelper(value_id,ON_Value::uuid_value,0)); if ( v && 1 == v->m_value.Count()) { *uuid = v->m_value[0]; rc = true; } return rc; } int ON_HistoryRecord::GetBoolValues( int value_id, ON_SimpleArray& a ) const { a.SetCount(0); const ON_BoolValue* v = static_cast(FindValueHelper(value_id,ON_Value::bool_value,0)); if ( v ) { a = v->m_value; } return a.Count(); } int ON_HistoryRecord::GetStringValues( int value_id, ON_ClassArray& a ) const { a.SetCount(0); const ON_StringValue* v = static_cast(FindValueHelper(value_id,ON_Value::string_value,0)); if ( v ) { a = v->m_value; } return a.Count(); } int ON_HistoryRecord::GetIntValues( int value_id, ON_SimpleArray& a ) const { a.SetCount(0); const ON_IntValue* v = static_cast(FindValueHelper(value_id,ON_Value::int_value,0)); if ( v ) { a = v->m_value; } return a.Count(); } int ON_HistoryRecord::GetDoubleValues( int value_id, ON_SimpleArray& a) const { a.SetCount(0); const ON_DoubleValue* v = static_cast(FindValueHelper(value_id,ON_Value::double_value,0)); if ( v ) { a = v->m_value; } return a.Count(); } int ON_HistoryRecord::GetPointValues( int value_id, ON_SimpleArray& a ) const { a.SetCount(0); const ON_PointValue* v = static_cast(FindValueHelper(value_id,ON_Value::point_value,0)); if ( v ) { a = v->m_value; } return a.Count(); } int ON_HistoryRecord::GetVectorValues( int value_id, ON_SimpleArray& a ) const { a.SetCount(0); const ON_VectorValue* v = static_cast(FindValueHelper(value_id,ON_Value::vector_value,0)); if ( v ) { a = v->m_value; } return a.Count(); } int ON_HistoryRecord::GetXformValues( int value_id, ON_SimpleArray& a ) const { a.SetCount(0); const ON_XformValue* v = static_cast(FindValueHelper(value_id,ON_Value::xform_value,0)); if ( v ) { a = v->m_value; } return a.Count(); } int ON_HistoryRecord::GetColorValues( int value_id, ON_SimpleArray& a ) const { a.SetCount(0); const ON_ColorValue* v = static_cast(FindValueHelper(value_id,ON_Value::color_value,0)); if ( v ) { a = v->m_value; } return a.Count(); } int ON_HistoryRecord::GetObjRefValues( int value_id, ON_ClassArray& a ) const { a.SetCount(0); const ON_ObjRefValue* v = static_cast(FindValueHelper(value_id,ON_Value::objref_value,0)); if ( v ) { a = v->m_value; } return a.Count(); } int ON_HistoryRecord::GetGeometryValues( int value_id, ON_SimpleArray& a) const { a.SetCount(0); const ON_GeometryValue* v = static_cast(FindValueHelper(value_id,ON_Value::geometry_value,0)); if ( v ) { int i, count = v->m_value.Count(); a.Reserve(count); for ( i = 0; i < count; i++ ) a.Append(v->m_value[i]); } return a.Count(); } int ON_HistoryRecord::GetSubDEdgeChainValues(int value_id, ON_SimpleArray& a) const { a.SetCount(0); const ON_SubDEdgeChainHistoryValue* v = static_cast(FindValueHelper(value_id, ON_Value::subd_edge_chain_value, 0)); if (v) { int i, count = v->m_value.Count(); a.Reserve(count); for (i = 0; i < count; i++) a.Append(v->m_value[i]); } return a.Count(); } int ON_HistoryRecord::GetPolyEdgeValues( int value_id, ON_SimpleArray& a) const { a.SetCount(0); const ON_PolyEdgeHistoryValue* v = static_cast(FindValueHelper(value_id,ON_Value::polyedge_value,0)); if ( v ) { int i, count = v->m_value.Count(); a.Reserve(count); for ( i = 0; i < count; i++ ) a.Append(&v->m_value[i]); } return a.Count(); } int ON_HistoryRecord::GetUuidValues( int value_id, ON_SimpleArray& a) const { a.SetCount(0); const ON_UuidValue* v = static_cast(FindValueHelper(value_id,ON_Value::uuid_value,0)); if ( v ) { a = v->m_value; } return a.Count(); } bool ON_HistoryRecord::IsAntecedent( ON_UUID object_uuid ) const { return m_antecedents.FindUuid(object_uuid); } int ON_HistoryRecord::ValueReport( ON_TextLog& text_log ) const { int value_count = 0; int i, vi, count = m_value.Count(); // list values ON_SimpleArray vi_list(count); vi_list.SetCount(count); vi_list.Zero(); m_value.Sort( ON::sort_algorithm::quick_sort, vi_list.Array(), CompareValueId ); for ( i = 0; i < count; i++ ) { vi = vi_list[i]; const ON_Value* v = m_value[vi]; if (!v) continue; text_log.Print("Value ID %d:\n",v->m_value_id); text_log.PushIndent(); m_value[i]->ReportHelper(text_log); text_log.PopIndent(); value_count++; } return value_count; } void ON_HistoryRecord::Dump( ON_TextLog& text_log ) const { ON_ModelComponent::Dump(text_log); int i, count; ON_SimpleArray uuid_list; text_log.Print("Command ID: "); text_log.Print(m_command_id); text_log.Print("\n"); text_log.Print("Version %d\n",m_version); text_log.Print("Record ID: "); text_log.Print(Id()); text_log.Print("\n"); text_log.Print("Record type: %s\n", (m_record_type == ON_HistoryRecord::RECORD_TYPE::feature_parameters) ? "feature parameters" : "history parameters"); // list antededents uuid_list.SetCount(0); m_antecedents.GetUuids(uuid_list); count = uuid_list.Count(); if ( count <= 0 ) { text_log.Print("No antededents.\n"); } else { text_log.Print("Antededent ID:\n"); text_log.PushIndent(); for ( i = 0; i < count; i++ ) { text_log.Print(uuid_list[i]); text_log.Print("\n"); } text_log.PopIndent(); } // list descendants uuid_list.SetCount(0); m_descendants.GetUuids(uuid_list); count = uuid_list.Count(); if ( count <= 0 ) { text_log.Print("No descendants.\n"); } else { text_log.Print("Descendant ID:\n"); text_log.PushIndent(); for ( i = 0; i < count; i++ ) { text_log.Print(uuid_list[i]); text_log.Print("\n"); } text_log.PopIndent(); } text_log.Print("Values:\n"); text_log.PushIndent(); int value_count = ValueReport(text_log); if ( 0 == value_count ) text_log.Print("none\n"); text_log.PopIndent(); } void ON_HistoryRecord::DestroyValue( int value_id ) { if ( m_value.Count() > 0 ) { if ( !m_bValuesSorted ) { m_value.QuickSort(CompareValueId); m_bValuesSorted = true; } ON_DummyValue dummy_value; dummy_value.m_value_id = value_id; ON_Value* p = &dummy_value; int i = m_value.BinarySearch(&p,CompareValueId); if ( i >= 0 ) { ON_Value* v = m_value[i]; m_value.Remove(); delete v; } } } bool ON_HistoryRecord::Read(ON_BinaryArchive& archive) { return Internal_ReadV5(archive); } bool ON_HistoryRecord::Internal_ReadV5( ON_BinaryArchive& archive ) { *this = ON_HistoryRecord::Empty; // put entire history record in a chunk int major_version = 0; int minor_version = 0; bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version); if (!rc) return false; for(;;) { rc = (1 == major_version); if (!rc) break; ON_UUID record_id = ON_nil_uuid; rc = archive.ReadUuid(record_id); if(!rc) break; SetId(record_id); rc = archive.ReadInt(&m_version); if(!rc) break; rc = archive.ReadUuid(m_command_id); if(!rc) break; // 16 October 2012 Dale Lear // Fixing http://dev.mcneel.com/bugtrack/?q=101403 // Changing bSortDescendantsAferRead from true to false // per discussion in the bug report. const bool bSortDescendantsAferRead = false; rc = m_descendants.Read(archive,bSortDescendantsAferRead); if(!rc) break; rc = m_antecedents.Read(archive); if(!rc) break; // all values are in a chunk int mjvs=0,mnvs=0; int value_id0 = 0; rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&mjvs,&mnvs); if (rc) { rc = ( 1 == mjvs ); int i, count = 0; if (rc) rc = archive.ReadInt(&count); if (rc) m_value.Reserve(count); for ( i = 0; i < count && rc; i++ ) { int mjv=0,mnv=0; rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&mjv,&mnv); if ( !rc) break; for(;;) { rc = ( 1 == mjv); if (!rc) break; int value_type = ON_Value::no_value_type; rc = archive.ReadInt(&value_type); if (!rc) break; int value_id = 0; rc = archive.ReadInt(&value_id); if (!rc) break; ON_Value* value = ON_Value::CreateValue(value_type); if ( value ) { value->m_value_id = value_id; rc = value->ReadHelper(archive); if (!rc) { delete value; break; } m_value.Append(value); if ( value->m_value_id <= value_id0 ) m_bValuesSorted = false; else value_id0 = value->m_value_id; } break; } if (!archive.EndRead3dmChunk()) rc = false; } // end of all values if (!archive.EndRead3dmChunk()) rc = false; } if ( rc && minor_version >= 1 ) { // 1.1 fields added to opennurbs version 200603200 int rec_type = (int)ON_HistoryRecord::RECORD_TYPE::history_parameters; if (rc) rc = archive.ReadInt( &rec_type ); if (rc ) m_record_type = RecordType(rec_type); if (rc && minor_version >= 2) { archive.ReadBool(&m_bCopyOnReplaceObject); } } break; } // end of entire history record in a chunk if (!archive.EndRead3dmChunk()) rc = false; return rc; } bool ON_HistoryRecord::Write(ON_BinaryArchive& archive) const { return Internal_WriteV5(archive); } bool ON_HistoryRecord::Internal_WriteV5( ON_BinaryArchive& archive ) const { // 2015-06-01 Dale Lear // Save m_bCopyOnReplaceObject in the file in chunck version 1.2 const int minor_version = (archive.Archive3dmVersion() >= 60) ? 2 // V6 after 2015-06-01 or later file : 1; // V5 or earlier file bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,minor_version); if (!rc) return false; for(;;) { rc = archive.WriteUuid(Id()); if(!rc) break; rc = archive.WriteInt(m_version); if(!rc) break; rc = archive.WriteUuid(m_command_id); if(!rc) break; // 30 October 2012 Dale Lear // Fixing http://dev.mcneel.com/bugtrack/?q=101403 // Changing bSortDescendantsBeforeWrite from true to false // per discussion in the bug report. const bool bSortDescendantsBeforeWrite = false; rc = m_descendants.Write(archive,bSortDescendantsBeforeWrite); if(!rc) break; rc = m_antecedents.Write(archive); if(!rc) break; // wrap all values in a chunk rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0); if (rc) { // value count int i, count = m_value.Count(); rc = archive.WriteInt(count); for ( i = 0; i < count && rc; i++ ) { // put individual value in its own chunk rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0); if ( !rc) break; for(;;) { const ON_Value* value = m_value[i]; rc = archive.WriteInt(value ? value->m_value_type : ON_Value::no_value_type ); if (!rc) break; rc = archive.WriteInt(value ? value->m_value_id : 0 ); if (!rc) break; if ( value && value->m_value_type != ON_Value::no_value_type ) rc = value->WriteHelper(archive); if (!rc) break; break; } // end of individual value chunk if (!archive.EndWrite3dmChunk()) rc = false; } // end of all values chunk if ( !archive.EndWrite3dmChunk() ) rc = false; } // 1.1 fields added to opennurbs version 200603200 if (rc) { int i = (int)m_record_type; rc = archive.WriteInt(i); } if (rc && minor_version >= 2) { rc = archive.WriteBool(m_bCopyOnReplaceObject); } break; } if (!archive.EndWrite3dmChunk()) rc = false; return rc; } void ON_HistoryRecord::RemapObjectIds( const ON_SimpleArray& id_remap ) { if ( id_remap.Count() > 0 ) { int i, j; m_antecedents.RemapUuids(id_remap); m_descendants.RemapUuids(id_remap); for ( i = 0; i < m_value.Count(); i++ ) { ON_Value* v = m_value[i]; if ( v && ON_Value::objref_value == v->m_value_type ) { ON_ObjRefValue* objrev_v = static_cast(v); for ( j = 0; j < objrev_v->m_value.Count(); j++ ) { objrev_v->m_value[j].RemapObjectId(id_remap); } } // 24 May 2021, Mikko, RH-56171: // Some commands like Offset use an UUID list to map inputs and outputs. // Similar to remapping the objref ids, the uuid lists also need to be // updated to use new ids. // Other commands that currently use UUID lists are Divide, Slab, Ribbon, // FilletSrf, ChamferSrf, ArrayCrv, Hatch. else if (v && ON_Value::uuid_value == v->m_value_type) { ON_UuidValue* uuid_v = static_cast(v); for (j = 0; j < uuid_v->m_value.Count(); j++) { int index = id_remap.BinarySearch((const ON_UuidPair*)&uuid_v->m_value[j], ON_UuidPair::CompareFirstUuid); if (index >= 0) uuid_v->m_value[j] = id_remap[index].m_uuid[1]; } } } } } bool ON_HistoryRecord::CopyOnReplaceObject() const { return m_bCopyOnReplaceObject; } void ON_HistoryRecord::SetCopyOnReplaceObject( bool bCopyOnReplaceObject ) { m_bCopyOnReplaceObject = (bCopyOnReplaceObject) ? true : false; } ///////////////////////////////////////////////////////////////////////////////// // // ON_CurveProxyHistory // ON_CurveProxyHistory::ON_CurveProxyHistory() { } ON_CurveProxyHistory::~ON_CurveProxyHistory() { } void ON_CurveProxyHistory::Destroy() { m_curve_ref.Destroy(); m_bReversed = false; m_full_real_curve_domain = ON_Interval::EmptyInterval; m_sub_real_curve_domain = ON_Interval::EmptyInterval; m_proxy_curve_domain = ON_Interval::EmptyInterval; m_segment_edge_domain = ON_Interval::EmptyInterval; m_segment_trim_domain = ON_Interval::EmptyInterval; } bool ON_CurveProxyHistory::Write( ON_BinaryArchive& file ) const { if ( !file.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK,1,1) ) return false; bool rc = false; for(;;) { if ( !m_curve_ref.Write(file) ) break; if ( !file.WriteBool(m_bReversed) ) break; if ( !file.WriteInterval(m_full_real_curve_domain) ) break; if ( !file.WriteInterval(m_sub_real_curve_domain) ) break; if (!file.WriteInterval(m_proxy_curve_domain)) break; // Added in version 1,1 if (!file.WriteInterval(m_segment_edge_domain)) break; if (!file.WriteInterval(m_segment_trim_domain)) break; rc = true; break; } if ( !file.EndWrite3dmChunk() ) rc = false; return rc; } bool ON_CurveProxyHistory::Read( ON_BinaryArchive& file ) { int version_major = 0; int version_minor = 0; Destroy(); if ( !file.BeginRead3dmChunk( TCODE_ANONYMOUS_CHUNK,&version_major,&version_minor) ) return false; bool rc = false; for(;;) { if ( 1 != version_major ) break; if ( !m_curve_ref.Read(file) ) break; if ( !file.ReadBool(&m_bReversed) ) break; if ( !file.ReadInterval(m_full_real_curve_domain) ) break; if ( !file.ReadInterval(m_sub_real_curve_domain) ) break; if (!file.ReadInterval(m_proxy_curve_domain)) break; if (version_minor > 0) { if (!file.ReadInterval(m_segment_edge_domain)) break; if (!file.ReadInterval(m_segment_trim_domain)) break; } rc = true; break; } if ( !file.EndRead3dmChunk() ) rc = false; return rc; } void ON_CurveProxyHistory::Dump( ON_TextLog& ) const { } ///////////////////////////////////////////////////////////////////////////////// // // ON_PolyEdgeHistory // ON_PolyEdgeHistory::ON_PolyEdgeHistory() : m_evaluation_mode(0) { } ON_PolyEdgeHistory::~ON_PolyEdgeHistory() { } void ON_PolyEdgeHistory::Destroy() { m_segment.Destroy(); m_t.Destroy(); m_evaluation_mode = 0; } bool ON_PolyEdgeHistory::Write( ON_BinaryArchive& file ) const { int i; if ( !file.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK,1,0) ) return false; bool rc = false; for(;;) { if ( !file.WriteInt(m_segment.Count()) ) break; for ( i = 0; i < m_segment.Count(); i++ ) { if ( !m_segment[i].Write(file) ) break; } if ( i < m_segment.Count() ) break; if ( !file.WriteInt(m_t.Count()) ) break; if ( m_t.Count() > 0 ) { if ( !file.WriteDouble(m_t.Count(),m_t.Array()) ) break; } if ( !file.WriteInt(m_evaluation_mode) ) break; rc = true; break; } if ( !file.EndWrite3dmChunk() ) rc = false; return rc; } bool ON_PolyEdgeHistory::Read( ON_BinaryArchive& file ) { int count, i; int version_major = 0; int version_minor = 0; Destroy(); if ( !file.BeginRead3dmChunk( TCODE_ANONYMOUS_CHUNK,&version_major,&version_minor) ) return false; bool rc = false; for(;;) { if ( 1 != version_major ) break; count = 0; if ( !file.ReadInt(&count) ) break; m_segment.Reserve(count); for ( i = 0; i < count; i++ ) { if ( !m_segment.AppendNew().Read(file) ) break; } if ( i < count ) break; count = 0; if ( !file.ReadInt(&count) ) break; if ( count > 0 ) { m_t.Reserve(count); m_t.SetCount(count); if ( !file.ReadDouble(count,m_t.Array()) ) break; } if ( !file.ReadInt(&m_evaluation_mode) ) break; rc = true; break; } if ( !file.EndRead3dmChunk() ) rc = false; return rc; } void ON_PolyEdgeHistory::Dump( ON_TextLog& ) const { }