1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
6 // McNeel & Associates.
7 //
8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
10 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
11 //
12 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
13 //
14 ////////////////////////////////////////////////////////////////
15 */
16 
17 #include "opennurbs.h"
18 
19 #define ON_BOZO_VACCINE_11EE2C1FF90D4C6AA7CDEC8532E1E32D
20 #define ON_BOZO_VACCINE_F42D967121EB46929B9ABC3507FF28F5
21 
22 ON_OBJECT_IMPLEMENT( ON_InstanceDefinition, ON_Geometry, "26F8BFF6-2618-417f-A158-153D64A94989" );
23 
ON_InstanceDefinition()24 ON_InstanceDefinition::ON_InstanceDefinition()
25 {
26   m_uuid = ON_nil_uuid;
27   m_idef_update_type = ON_InstanceDefinition::static_def;
28   m_idef_update_depth = 0;
29   m_us.m_unit_system = ON::no_unit_system;
30   m_us.m_custom_unit_scale = 0.0;
31   m_us.m_custom_unit_name.Destroy();
32   m_source_bRelativePath = false;
33   m_reserved1 = 0;
34   m_idef_layer_style = 0;
35   m_reserved2[0] = 0;
36   m_reserved2[1] = 0;
37 }
38 
~ON_InstanceDefinition()39 ON_InstanceDefinition::~ON_InstanceDefinition()
40 {
41 }
42 
43 
Dump(ON_TextLog & text_log) const44 void ON_InstanceDefinition::Dump( ON_TextLog& text_log ) const
45 {
46   const wchar_t* wsIDefName = m_name;
47   if ( 0 == wsIDefName )
48     wsIDefName = L"";
49   text_log.Print("Name: \"%ls\"\n",wsIDefName);
50 
51 
52   text_log.Print("Type: ");
53   switch(m_idef_update_type)
54   {
55   case ON_InstanceDefinition::static_def:
56     text_log.Print("embedded.");
57     break;
58   case ON_InstanceDefinition::embedded_def:
59     if ( m_source_archive.Length() > 0 )
60       text_log.Print("OBSOLETE embedded_def with non-empty source archive - should be linked_and_embedded_def.");
61     else
62       text_log.Print("OBSOLETE embedded_def with empty source archive - should be static_def.");
63     break;
64   case ON_InstanceDefinition::linked_and_embedded_def:
65     text_log.Print("embedded and linked - definition from source archive.");
66     break;
67   case ON_InstanceDefinition::linked_def:
68     text_log.Print("linked - definition from source archive.");
69     break;
70   default:
71     text_log.Print("not valid");
72     break;
73   }
74   text_log.Print("\n");
75 
76 
77   text_log.Print("Id: "); text_log.Print(m_uuid); text_log.Print("\n");
78 
79   const wchar_t* wsDescription = m_description;
80   if ( 0 != wsDescription && 0 != wsDescription[0])
81     text_log.Print("Description: \"%ls\"\n",wsDescription);
82 
83   const wchar_t* wsURL = m_url;
84   if ( 0 != wsURL && 0 != wsURL[0])
85     text_log.Print("URL: \"%ls\"\n",wsURL);
86 
87   const wchar_t* wsTag = m_url_tag;
88   if ( 0 != wsTag && 0 != wsTag[0])
89     text_log.Print("URL tag: \"%ls\"\n",wsTag);
90 
91   m_us.Dump(text_log);
92 
93   const wchar_t* wsSourceArchive = SourceArchive();
94   text_log.Print("Source archive: ");
95   if ( 0 == wsSourceArchive || 0 == wsSourceArchive[0] )
96   {
97     text_log.Print("none.\n");
98   }
99   else
100   {
101     bool bRel = m_source_bRelativePath;
102     text_log.Print("\"%ls\" (%s)\n",wsSourceArchive,bRel?"relative":"absolute");
103 
104     text_log.PushIndent();
105     ON_wString str;
106     bRel = false;
107     if ( GetAlternateSourceArchivePath(str,bRel) )
108     {
109       const wchar_t* wsAlternateArchive = str;
110       if ( 0 == wsAlternateArchive || 0 == wsAlternateArchive[0] )
111         wsAlternateArchive = L"";
112       text_log.Print("Alternate archive: \"%ls\" (%s)\n",wsAlternateArchive,bRel?"relative":"absolute");
113     }
114 
115     text_log.Print("Update depth: %d\n",m_idef_update_type);
116 
117     text_log.Print("Archive ");
118     m_source_archive_checksum.Dump(text_log);
119     text_log.PopIndent();
120   }
121 
122   const int id_count = m_object_uuid.Count();
123   text_log.Print("Contains: %d objects\n",id_count);
124 
125   if ( id_count > 0 )
126   {
127     text_log.PushIndent();
128 
129     text_log.Print(m_object_uuid[0]);
130     text_log.Print("\n");
131 
132     if ( id_count > 4 )
133     {
134       text_log.Print("...\n");
135     }
136     else
137     {
138       for ( int i = 1; i < id_count; i++ )
139       {
140         text_log.Print(m_object_uuid[i]);
141         text_log.Print("\n");
142       }
143     }
144 
145     text_log.PopIndent();
146   }
147 
148   m_bbox.Dump(text_log);
149 }
150 
IsValid(ON_TextLog * text_log) const151 ON_BOOL32 ON_InstanceDefinition::IsValid( ON_TextLog* text_log ) const
152 {
153   if ( 0 == ON_UuidCompare( m_uuid, ON_nil_uuid) )
154   {
155     if (text_log)
156     {
157       text_log->Print("ON_InstanceDefinition has nil uuid.\n");
158     }
159     return false;
160   }
161   if ( !m_bbox.IsValid() )
162   {
163     if (text_log)
164     {
165       text_log->Print("ON_InstanceDefinition has invalid bounding box.\n");
166     }
167     return false;
168   }
169 
170   switch( m_idef_update_type)
171   {
172     case static_def:
173       // no source archive information should be present
174       if ( m_source_archive.Length() > 0 )
175       {
176         if (text_log)
177         {
178           text_log->Print("ON_InstanceDefinition is static but m_source_archive is not empty.\n");
179         }
180         return false;
181       }
182       if ( m_source_archive_checksum.IsSet() )
183       {
184         if (text_log)
185         {
186           text_log->Print("ON_InstanceDefinition is static but m_source_archive_checksum is set.\n");
187         }
188         return false;
189       }
190 
191       if ( 0 != m_idef_layer_style )
192       {
193         if (text_log)
194         {
195           text_log->Print("ON_InstanceDefinition is static but m_idef_layer_style is not zero.\n");
196         }
197         return false;
198       }
199       break;
200 
201     case embedded_def: // embedded_def is obsolete -
202       if ( text_log )
203       {
204         text_log->Print("ON_InstanceDefinition.m_idef_update_type = obsolete \"embedded_idef\". Use \"static_def\" or \"linked_and_embedded_def\".\n");
205       }
206       return false;
207       break;
208 
209     case linked_and_embedded_def:
210     case linked_def:
211       // source archive information is required
212       if( m_source_archive.IsEmpty())
213       {
214         if (text_log)
215         {
216           text_log->Print("ON_InstanceDefinition is linked or embedded but m_source_archive is empty.\n");
217         }
218         return false;
219       }
220       if( !m_source_archive_checksum.IsSet())
221       {
222         if (text_log)
223         {
224           text_log->Print("ON_InstanceDefinition is linked or embedded but m_source_archive_checksum is zero.\n");
225         }
226         return false;
227       }
228 
229       if ( linked_def == m_idef_update_type )
230       {
231         if ( 1 != m_idef_layer_style && 2 != m_idef_layer_style )
232         {
233           if (text_log)
234           {
235             text_log->Print("ON_InstanceDefinition is linked_def but m_idef_layer_style is not 1 or 2.\n");
236           }
237           return false;
238         }
239       }
240       else
241       {
242         if ( 0 != m_idef_layer_style )
243         {
244           if (text_log)
245           {
246             text_log->Print("ON_InstanceDefinition is linked_and_embedded_def but m_idef_layer_style is not zero.\n");
247           }
248           return false;
249         }
250       }
251 
252       break;
253 
254     default:
255       if ( text_log )
256       {
257         text_log->Print("ON_InstanceDefinition.m_idef_update_type value is invalid.\n");
258       }
259       return false;
260       break;
261   }
262 
263   // TODO
264   return true;
265 }
266 
267 
SizeOf() const268 unsigned int ON_InstanceDefinition::SizeOf() const
269 {
270   unsigned int sz = sizeof(*this) - sizeof(ON_Geometry);
271   sz += ON_Geometry::SizeOf();
272   sz += this->m_object_uuid.SizeOfArray();
273   sz += this->m_name.SizeOf();
274   sz += this->m_description.SizeOf();
275   sz += this->m_url.SizeOf();
276   sz += this->m_url_tag.SizeOf();
277   sz += this->m_source_archive.SizeOf();
278   return sz;
279 }
280 
281 
Write(ON_BinaryArchive & binary_archive) const282 ON_BOOL32 ON_InstanceDefinition::Write(
283        ON_BinaryArchive& binary_archive
284      ) const
285 {
286   bool rc = binary_archive.Write3dmChunkVersion(1,6);
287 
288   // version 1.0 fields
289   if ( rc )
290     rc = binary_archive.WriteUuid( m_uuid );
291   if ( rc )
292   {
293     if (    binary_archive.Archive3dmVersion() >= 4
294          && ON_InstanceDefinition::linked_def == m_idef_update_type )
295     {
296       // linked instance definition geometry is never in the file
297       ON_SimpleArray<ON_UUID> empty_uuid_list;
298       rc = binary_archive.WriteArray( empty_uuid_list );
299     }
300     else
301     {
302       rc = binary_archive.WriteArray( m_object_uuid );
303     }
304   }
305   if ( rc )
306     rc = binary_archive.WriteString( m_name );
307   if ( rc )
308     rc = binary_archive.WriteString( m_description );
309   if ( rc )
310     rc = binary_archive.WriteString( m_url );
311   if ( rc )
312     rc = binary_archive.WriteString( m_url_tag );
313   if ( rc )
314     rc = binary_archive.WriteBoundingBox( m_bbox );
315 
316   // m_idef_update_type was an unsigned int and got changed to an enum.  Read and write
317   // as an unsigned int to support backwards compatibility
318   const unsigned int idef_update_type = (unsigned int)this->IdefUpdateType();
319   if ( rc )
320     rc = binary_archive.WriteInt( idef_update_type );
321   if ( rc )
322   {
323     // 7 February 2012
324     //   Purge source archive information from static_defs
325     if ( ON_InstanceDefinition::static_def == idef_update_type )
326     {
327       ON_wString empty_string;
328       rc = binary_archive.WriteString( empty_string );
329     }
330     else
331       rc = binary_archive.WriteString( m_source_archive );
332   }
333 
334   // version 1.1 fields
335   if (rc)
336   {
337     // 7 February 2012
338     //   Purge source archive information from static_defs
339     if ( ON_InstanceDefinition::static_def == idef_update_type )
340       ON_CheckSum::UnsetCheckSum.Write(binary_archive);
341     else
342       rc = m_source_archive_checksum.Write( binary_archive );
343   }
344 
345   // version 1.2 fields
346   if (rc)
347     rc = binary_archive.WriteInt( m_us.m_unit_system );
348 
349   // version 1.3 fields - added 6 March 2006
350   if (rc)
351     rc = binary_archive.WriteDouble( m_us.m_custom_unit_scale );
352 
353   if ( rc )
354   {
355     bool b = (ON_InstanceDefinition::static_def == idef_update_type)
356            ? false
357            : m_source_bRelativePath;
358     rc = binary_archive.WriteBool( b );
359   }
360 
361   // version 1.4 fields
362   if (rc)
363     rc = m_us.Write(binary_archive);
364 
365   // version 1.5 fields
366   if (rc)
367     rc = binary_archive.WriteInt(m_idef_update_depth);
368 
369   // version 1.6 fields ( added 14 February 2012 )
370   if (rc)
371     rc = binary_archive.WriteInt(  m_idef_layer_style );
372 
373   return rc;
374 }
375 
IdefUpdateType() const376 ON_InstanceDefinition::IDEF_UPDATE_TYPE ON_InstanceDefinition::IdefUpdateType() const
377 {
378   if ( ON_InstanceDefinition::embedded_def == m_idef_update_type )
379   {
380     ON_ERROR("Using obsolete ON_InstanceDefinition::embedded_def value - fix code.");
381     const_cast< ON_InstanceDefinition* >(this)->m_idef_update_type
382                                   = ( m_source_archive.Length() > 0 )
383                                   ? ON_InstanceDefinition::linked_and_embedded_def
384                                   : ON_InstanceDefinition::static_def;
385   }
386   return m_idef_update_type;
387 }
388 
IdefUpdateType(int i)389 ON_InstanceDefinition::IDEF_UPDATE_TYPE ON_InstanceDefinition::IdefUpdateType(int i)
390 {
391   IDEF_UPDATE_TYPE t;
392   switch(i)
393   {
394   case ON_InstanceDefinition::static_def:
395     t = ON_InstanceDefinition::static_def;
396     break;
397   case ON_InstanceDefinition::embedded_def:
398     t = ON_InstanceDefinition::embedded_def;
399     break;
400   case ON_InstanceDefinition::linked_and_embedded_def:
401     t = ON_InstanceDefinition::linked_and_embedded_def;
402     break;
403   case ON_InstanceDefinition::linked_def:
404     t = ON_InstanceDefinition::linked_def;
405     break;
406   default:
407     t = ON_InstanceDefinition::static_def;
408     break;
409   }
410   return t;
411 }
412 
413 
Read(ON_BinaryArchive & binary_archive)414 ON_BOOL32 ON_InstanceDefinition::Read(
415        ON_BinaryArchive& binary_archive
416      )
417 {
418   int major_version = 0;
419   int minor_version = 0;
420 
421   m_idef_layer_style = 0;
422 
423   m_us.m_custom_unit_scale = 0.0;
424   m_us.m_custom_unit_name.Destroy();
425   m_us.m_unit_system = ON::no_unit_system;
426   m_source_bRelativePath = false;
427   m_source_archive.Destroy();
428 
429   bool rc = binary_archive.Read3dmChunkVersion(&major_version,&minor_version);
430   if ( rc )
431   {
432     if ( major_version != 1 )
433       rc = false;
434     // version 1.0 fields
435     if ( rc )
436       rc = binary_archive.ReadUuid( m_uuid );
437     if ( rc )
438       rc = binary_archive.ReadArray( m_object_uuid );
439     if ( rc )
440       rc = binary_archive.ReadString( m_name );
441     if ( rc )
442       rc = binary_archive.ReadString( m_description );
443     if ( rc )
444       rc = binary_archive.ReadString( m_url );
445     if ( rc )
446       rc = binary_archive.ReadString( m_url_tag );
447     if ( rc )
448       rc = binary_archive.ReadBoundingBox( m_bbox );
449     // m_idef_update_type was an unsigned int and got changed to an enum.  Read and write
450     // as an unsigned int to support backwards compatibility
451     unsigned int source = m_idef_update_type;
452     if ( rc )
453       rc = binary_archive.ReadInt( &source );
454     if( rc)
455       m_idef_update_type = ON_InstanceDefinition::IdefUpdateType(source);
456     if ( rc )
457       rc = binary_archive.ReadString( m_source_archive );
458 
459     // version 1.1 fields
460     if ( minor_version >= 1 )
461     {
462       if ( rc )
463         rc = m_source_archive_checksum.Read( binary_archive );
464     }
465 
466     // version 1.2 fields
467     if ( minor_version >= 2 )
468     {
469       int us = ON::no_unit_system;
470       if ( rc )
471         rc = binary_archive.ReadInt( &us );
472       m_us.m_unit_system = ON::UnitSystem(us);
473       if ( ON::custom_unit_system != m_us.m_unit_system && ON::no_unit_system != m_us.m_unit_system )
474       {
475         m_us.m_custom_unit_scale = ON::UnitScale( m_us.m_unit_system, ON::meters );
476       }
477       else
478       {
479         m_us.m_custom_unit_scale = 0.0;
480       }
481 
482       if ( minor_version >= 3 )
483       {
484         // version 1.3 fields - added 6 March 2006
485         //int us = ON::no_unit_system;
486         if ( rc )
487           rc = binary_archive.ReadDouble( &m_us.m_custom_unit_scale );
488         if ( rc )
489           rc = binary_archive.ReadBool( &m_source_bRelativePath );
490         if ( rc && minor_version >= 4 )
491         {
492           rc = m_us.Read(binary_archive);
493           if (rc && minor_version >= 5 )
494           {
495             rc = binary_archive.ReadInt(&m_idef_update_depth);
496 
497             if ( rc && minor_version >= 6 )
498             {
499               unsigned int i = 0;
500               rc = binary_archive.ReadInt(&i);
501               if ( i && i > 0 && i < 256 )
502                 m_idef_layer_style = (unsigned char)i;
503             }
504           }
505         }
506       }
507     }
508 
509     if ( ON_InstanceDefinition::embedded_def == m_idef_update_type )
510     {
511       // 7 February 2012
512       //   "embedded_def" is obsolete.
513       if (m_source_archive.Length() > 0 )
514         m_idef_update_type = ON_InstanceDefinition::linked_and_embedded_def;
515       else
516         DestroySourceArchive(); // convert to static
517     }
518 
519     if ( ON_InstanceDefinition::linked_def == m_idef_update_type )
520     {
521       if ( m_idef_layer_style < 1 || m_idef_layer_style > 2 )
522       {
523         // The goal of the next if/else clause is for Rhino users
524         // to see what they saw when they created the file.
525         if ( binary_archive.Archive3dmVersion() < 50 )
526         {
527           // V4 linked blocks and early V5 linked blocks treated
528           // layers and materials the way newer "active" idefs work,
529           // so when I read an archive with version < 50, the
530           // default will be 1 for "active".
531           m_idef_layer_style = 1;
532         }
533         else
534         {
535           // The more recent V5 linked blocks treated layers and materials
536           // the way "reference" style idefs work, so when I read an
537           // archive with version >= 50 (meaning recent V5), the default
538           // will be 2 for "reference".
539           m_idef_layer_style = 2;
540         }
541       }
542     }
543     else
544     {
545       m_idef_layer_style= 0;
546     }
547   }
548   return rc;
549 }
550 
ObjectType() const551 ON::object_type ON_InstanceDefinition::ObjectType() const
552 {
553   return ON::instance_definition;
554 }
555 
556 
557 // virtual ON_Geometry overrides
Dimension() const558 int ON_InstanceDefinition::Dimension() const
559 {
560   return 3;
561 }
562 
GetBBox(double * boxmin,double * boxmax,ON_BOOL32 bGrowBox) const563 ON_BOOL32 ON_InstanceDefinition::GetBBox(
564        double* boxmin,
565        double* boxmax,
566        ON_BOOL32 bGrowBox
567        ) const
568 {
569   if ( boxmin )
570   {
571     boxmin[0] = m_bbox.m_min.x;
572     boxmin[1] = m_bbox.m_min.y;
573     boxmin[2] = m_bbox.m_min.z;
574   }
575   if ( boxmax )
576   {
577     boxmax[0] = m_bbox.m_max.x;
578     boxmax[1] = m_bbox.m_max.y;
579     boxmax[2] = m_bbox.m_max.z;
580   }
581   return m_bbox.IsValid();
582 }
583 
Transform(const ON_Xform & xform)584 ON_BOOL32 ON_InstanceDefinition::Transform(
585        const ON_Xform& xform
586        )
587 {
588   // instance DEFs cannot be transformed
589   return false;
590 }
591 
Name() const592 const wchar_t* ON_InstanceDefinition::Name() const
593 {
594   return m_name;
595 }
596 
SetName(const wchar_t * name)597 void ON_InstanceDefinition::SetName( const wchar_t* name )
598 {
599   ON_wString s(name);
600   s.TrimLeftAndRight();
601   if ( s.IsEmpty() )
602     m_name.Destroy();
603   else
604     m_name = s;
605 }
606 
607 
URL() const608 const wchar_t* ON_InstanceDefinition::URL() const
609 {
610   return m_url;
611 }
612 
SetURL(const wchar_t * url)613 void ON_InstanceDefinition::SetURL( const wchar_t* url )
614 {
615   ON_wString s(url);
616   s.TrimLeftAndRight();
617   if ( s.IsEmpty() )
618     m_url.Destroy();
619   else
620     m_url = s;
621 }
622 
URL_Tag() const623 const wchar_t* ON_InstanceDefinition::URL_Tag() const
624 {
625   return m_url_tag;
626 }
627 
SetURL_Tag(const wchar_t * url_tag)628 void ON_InstanceDefinition::SetURL_Tag( const wchar_t* url_tag )
629 {
630   ON_wString s(url_tag);
631   s.TrimLeftAndRight();
632   if ( s.IsEmpty() )
633     m_url_tag.Destroy();
634   else
635     m_url_tag = s;
636 }
637 
Uuid() const638 ON_UUID ON_InstanceDefinition::Uuid() const
639 {
640   return m_uuid;
641 }
642 
SetUuid(ON_UUID uuid)643 void ON_InstanceDefinition::SetUuid( ON_UUID uuid )
644 {
645   m_uuid = uuid;
646 }
647 
Description() const648 const wchar_t* ON_InstanceDefinition::Description() const
649 {
650   return m_description;
651 }
652 
SetDescription(const wchar_t * description)653 void ON_InstanceDefinition::SetDescription( const wchar_t* description )
654 {
655   ON_wString s(description);
656   s.TrimLeftAndRight();
657   if ( s.IsEmpty() )
658     m_description.Destroy();
659   else
660     m_description = s;
661 }
662 
SetBoundingBox(ON_BoundingBox bbox)663 void ON_InstanceDefinition::SetBoundingBox( ON_BoundingBox bbox )
664 {
665   m_bbox = bbox;
666 }
667 
SetSourceArchive(const wchar_t * source_archive,ON_CheckSum checksum,ON_InstanceDefinition::IDEF_UPDATE_TYPE idef_update_type)668 void ON_InstanceDefinition::SetSourceArchive(
669         const wchar_t* source_archive,
670         ON_CheckSum checksum,
671         ON_InstanceDefinition::IDEF_UPDATE_TYPE idef_update_type
672         )
673 {
674   ON_wString s(source_archive);
675   s.TrimLeftAndRight();
676   if ( s.IsEmpty() )
677   {
678     DestroySourceArchive();
679   }
680   else
681   {
682     SetAlternateSourceArchivePath(0,false);
683     m_source_archive = s;
684     m_source_bRelativePath = false;
685     m_source_archive_checksum = checksum;
686     m_idef_update_type = ON_InstanceDefinition::IdefUpdateType(idef_update_type);
687     if ( ON_InstanceDefinition::linked_def != m_idef_update_type )
688     {
689       m_idef_layer_style = 0;
690     }
691   }
692 }
693 
DestroySourceArchive()694 void ON_InstanceDefinition::DestroySourceArchive()
695 {
696   m_source_archive.Destroy();
697   m_source_archive_checksum.Zero();
698   m_source_bRelativePath = false;
699   m_idef_update_type = ON_InstanceDefinition::static_def;
700   m_idef_layer_style = 0;
701   m_idef_update_depth = 0;
702   SetAlternateSourceArchivePath(0,false);
703 }
704 
SourceArchive() const705 const wchar_t* ON_InstanceDefinition::SourceArchive() const
706 {
707   return m_source_archive;
708 }
709 
SourceArchiveCheckSum() const710 ON_CheckSum ON_InstanceDefinition::SourceArchiveCheckSum() const
711 {
712   return m_source_archive_checksum;
713 }
714 
UnitSystem() const715 const ON_UnitSystem& ON_InstanceDefinition::UnitSystem() const
716 {
717   return m_us;
718 }
719 
SetUnitSystem(ON::unit_system us)720 void ON_InstanceDefinition::SetUnitSystem( ON::unit_system us )
721 {
722   // make sure we are not getting garbage cast as an ON::unit_system
723   if ( us == ON::UnitSystem(us) )
724   {
725     m_us.m_unit_system = us;
726     if ( ON::custom_unit_system != m_us.m_unit_system )
727     {
728       m_us.m_custom_unit_scale = ( ON::no_unit_system == m_us.m_unit_system )
729                                ? 0.0
730                                : ON::UnitScale(ON::meters,m_us.m_unit_system);
731     }
732   }
733 }
734 
SetUnitSystem(const ON_UnitSystem & us)735 void ON_InstanceDefinition::SetUnitSystem( const ON_UnitSystem& us )
736 {
737   // make sure we are not getting garbage cast as an ON::unit_system
738   if ( us.IsValid() )
739   {
740     m_us = us;
741     if ( ON::custom_unit_system != m_us.m_unit_system )
742     {
743       m_us.m_custom_unit_scale = ( ON::no_unit_system == m_us.m_unit_system )
744                                ? 0.0
745                                : ON::UnitScale(ON::meters,m_us.m_unit_system);
746     }
747   }
748 }
749 
750 ON_OBJECT_IMPLEMENT( ON_InstanceRef, ON_Geometry, "F9CFB638-B9D4-4340-87E3-C56E7865D96A" );
751 
752 const double ON_InstanceRef::m_singular_xform_tol = 1.0e-6;
753 
ON_InstanceRef()754 ON_InstanceRef::ON_InstanceRef()
755 {
756   m_instance_definition_uuid = ON_nil_uuid;
757   m_xform.Identity();
758 }
759 
IsValid(ON_TextLog * text_log) const760 ON_BOOL32 ON_InstanceRef::IsValid( ON_TextLog* text_log ) const
761 {
762   if ( 0 == ON_UuidCompare( m_instance_definition_uuid, ON_nil_uuid) )
763   {
764     if ( text_log )
765       text_log->Print("ON_InstanceRef has nil m_instance_definition_uuid.\n");
766     return false;
767   }
768 
769   ON_Xform tmp = m_xform.Inverse()*m_xform;
770   if ( !tmp.IsIdentity( ON_InstanceRef::m_singular_xform_tol ) )
771   {
772     if ( text_log )
773       text_log->Print("ON_InstanceRef has singular m_xform.\n");
774     return false;
775   }
776   return true;
777 }
778 
Write(ON_BinaryArchive & binary_archive) const779 ON_BOOL32 ON_InstanceRef::Write(
780        ON_BinaryArchive& binary_archive
781      ) const
782 {
783   bool rc = binary_archive.Write3dmChunkVersion(1,0);
784   if ( rc )
785     rc = binary_archive.WriteUuid( m_instance_definition_uuid );
786   if ( rc )
787     rc = binary_archive.WriteXform( m_xform );
788   if ( rc )
789     rc = binary_archive.WriteBoundingBox( m_bbox );
790   return rc;
791 }
792 
Read(ON_BinaryArchive & binary_archive)793 ON_BOOL32 ON_InstanceRef::Read(
794        ON_BinaryArchive& binary_archive
795      )
796 {
797   int major_version = 0;
798   int minor_version = 0;
799   bool rc = binary_archive.Read3dmChunkVersion(&major_version,&minor_version);
800   if ( rc )
801   {
802     if ( major_version != 1 )
803       rc = false;
804     if (rc )
805       rc = binary_archive.ReadUuid( m_instance_definition_uuid );
806     if ( rc )
807       rc = binary_archive.ReadXform( m_xform );
808     if ( rc )
809       rc = binary_archive.ReadBoundingBox( m_bbox );
810   }
811   return rc;
812 }
813 
ObjectType() const814 ON::object_type ON_InstanceRef::ObjectType() const
815 {
816   return ON::instance_reference;
817 }
818 
819 
820 // virtual ON_Geometry overrides
Dimension() const821 int ON_InstanceRef::Dimension() const
822 {
823   return 3;
824 }
825 
GetBBox(double * boxmin,double * boxmax,ON_BOOL32 bGrowBox) const826 ON_BOOL32 ON_InstanceRef::GetBBox(
827        double* boxmin,
828        double* boxmax,
829        ON_BOOL32 bGrowBox
830        ) const
831 {
832   if ( !boxmin || !boxmax )
833   {
834     bGrowBox = false;
835   }
836   else if ( bGrowBox )
837   {
838     bGrowBox = ON_BoundingBox(ON_3dPoint(boxmin),ON_3dPoint(boxmax)).IsValid();
839   }
840 
841   if( m_bbox.IsValid() )
842   {
843     if( bGrowBox )
844     {
845       if( boxmin[0] > m_bbox.m_min.x ) boxmin[0] = m_bbox.m_min.x;
846       if( boxmin[1] > m_bbox.m_min.y ) boxmin[1] = m_bbox.m_min.y;
847       if( boxmin[2] > m_bbox.m_min.z ) boxmin[2] = m_bbox.m_min.z;
848 
849       if( boxmax[0] < m_bbox.m_max.x ) boxmax[0] = m_bbox.m_max.x;
850       if( boxmax[1] < m_bbox.m_max.y ) boxmax[1] = m_bbox.m_max.y;
851       if( boxmax[2] < m_bbox.m_max.z ) boxmax[2] = m_bbox.m_max.z;
852     }
853     else
854     {
855       if( boxmin )
856       {
857         boxmin[0] = m_bbox.m_min.x;
858         boxmin[1] = m_bbox.m_min.y;
859         boxmin[2] = m_bbox.m_min.z;
860       }
861       if( boxmax )
862       {
863         boxmax[0] = m_bbox.m_max.x;
864         boxmax[1] = m_bbox.m_max.y;
865         boxmax[2] = m_bbox.m_max.z;
866       }
867       bGrowBox = true;
868     }
869   }
870 
871   return bGrowBox;
872 }
873 
Transform(const ON_Xform & xform)874 ON_BOOL32 ON_InstanceRef::Transform(
875        const ON_Xform& xform
876        )
877 {
878   ON_Geometry::Transform(xform);
879   m_xform = xform*m_xform;
880   m_bbox.Transform(xform);
881   return true;
882 }
883 
IsDeformable() const884 bool ON_InstanceRef::IsDeformable() const
885 {
886   // 25 Feb 2006 Dale Lear - this seems wrong to me.
887   return true;
888 }
889 
MakeDeformable()890 bool ON_InstanceRef::MakeDeformable()
891 {
892   // 25 Feb 2006 Dale Lear - this seems wrong to me.
893   return true;
894 }
895 
896 
897 class /*NEVER EXPORT THIS CLASS DEFINITION*/ ON__IDefLayerSettingsUserData : public ON_UserData
898 {
899 #if !defined(ON_BOZO_VACCINE_11EE2C1FF90D4C6AA7CDEC8532E1E32D)
900 #error Never copy this class definition or put this definition in a header file!
901 #endif
902   ON_OBJECT_DECLARE(ON__IDefLayerSettingsUserData);
903 
904 public:
905   ON__IDefLayerSettingsUserData();
906   ~ON__IDefLayerSettingsUserData();
907   // default copy constructor and operator= work fine.
908 
909   ON__IDefLayerSettingsUserData(const ON__IDefLayerSettingsUserData& src);
910   ON__IDefLayerSettingsUserData& operator=(const ON__IDefLayerSettingsUserData& src);
911 
912 
913   static ON__IDefLayerSettingsUserData* FindOrCreate(const ON_InstanceDefinition& idef,bool bCreate);
914 
915 private:
CreateHelper()916   void CreateHelper()
917   {
918     m_layers.Destroy();
919     m_idef_layer_table_parent_layer = 0;
920   }
921 
CopyHelper(const ON__IDefLayerSettingsUserData & src)922   void CopyHelper(const ON__IDefLayerSettingsUserData& src)
923   {
924     m_layers.Reserve(src.m_layers.Count());
925     for ( int i = 0; i < src.m_layers.Count(); i++ )
926     {
927       const ON_Layer* src_layer = src.m_layers[i];
928       if ( 0 != src_layer )
929       {
930         m_layers.Append( new ON_Layer( *src_layer ) );
931       }
932     }
933 
934     if ( 0 != src.m_idef_layer_table_parent_layer )
935     {
936       m_idef_layer_table_parent_layer = new ON_Layer( *src.m_idef_layer_table_parent_layer );
937     }
938 
939     m_runtime_layer_id_map = src.m_runtime_layer_id_map;
940     m_runtime_layer_id_map.ImproveSearchSpeed();
941   }
942 
DestroyHelper()943   void DestroyHelper()
944   {
945     for ( int i = 0; i < m_layers.Count(); i++ )
946     {
947       delete m_layers[i];
948       m_layers[i] = 0;
949     }
950     m_layers.Destroy();
951     if ( 0 != m_idef_layer_table_parent_layer )
952     {
953       delete m_idef_layer_table_parent_layer;
954       m_idef_layer_table_parent_layer = 0;
955     }
956     m_runtime_layer_id_map.Empty();
957   }
958 
959 public:
960   // virtual ON_Object override
961   ON_BOOL32 IsValid( ON_TextLog* text_log = NULL ) const;
962   // virtual ON_Object override
963   unsigned int SizeOf() const;
964   // virtual ON_Object override
965   ON__UINT32 DataCRC(ON__UINT32 current_remainder) const;
966   // virtual ON_Object override
967   ON_BOOL32 Write(ON_BinaryArchive& binary_archive) const;
968   // virtual ON_Object override
969   ON_BOOL32 Read(ON_BinaryArchive& binary_archive);
970   // virtual ON_UserData override
971   ON_BOOL32 Archive() const;
972   // virtual ON_UserData override
973   ON_BOOL32 GetDescription( ON_wString& description );
974 
975 public:
976   // m_layers[] satisfies
977   //  * has no null members
978   //  * is always sorted by layer id
979   //  * has no duplicate layer ids
980   //  * has no nil layer ids
981   //  * the m_layer_id and m_parent_layer_id
982   //    values are from the linked file.
983   ON_SimpleArray<ON_Layer*> m_layers;
984 
985   // Settings for the layer that is the
986   // parent of the layers in the linked
987   // files layer table.  This layer is
988   // not in the linked file and is not
989   // saved in the layer table of file containing
990   // the idef.  If null, it is created
991   ON_Layer* m_idef_layer_table_parent_layer;
992 
993   // When a linked idef is inserted and a layer id
994   // collision occures, the runtime id of the layer
995   // has to be changed. This list keeps track of the
996   // changes so we can determine which runtime layer
997   // correspondes to a layer in m_layers[].
998   // The first index id in the pair is the runtime
999   // id and the second id in the pair is the m_layer[]
1000   // id.
1001   ON_UuidPairList m_runtime_layer_id_map;
1002 };
1003 
1004 #undef ON_BOZO_VACCINE_11EE2C1FF90D4C6AA7CDEC8532E1E32D
1005 
1006 ON_OBJECT_IMPLEMENT(ON__IDefLayerSettingsUserData,ON_UserData,"11EE2C1F-F90D-4C6A-A7CD-EC8532E1E32D");
1007 
FindOrCreate(const ON_InstanceDefinition & idef,bool bCreate)1008 ON__IDefLayerSettingsUserData* ON__IDefLayerSettingsUserData::FindOrCreate(const ON_InstanceDefinition& idef,bool bCreate)
1009 {
1010   ON__IDefLayerSettingsUserData* ud = ON__IDefLayerSettingsUserData::Cast(idef.GetUserData(ON__IDefLayerSettingsUserData::m_ON__IDefLayerSettingsUserData_class_id.Uuid()));
1011   if ( !ud && bCreate )
1012   {
1013     ud = new ON__IDefLayerSettingsUserData();
1014     const_cast<ON_InstanceDefinition&>(idef).AttachUserData(ud);
1015   }
1016   return ud;
1017 }
1018 
ON__IDefLayerSettingsUserData()1019 ON__IDefLayerSettingsUserData::ON__IDefLayerSettingsUserData()
1020 {
1021   m_userdata_uuid = ON__IDefLayerSettingsUserData::m_ON__IDefLayerSettingsUserData_class_id.Uuid();
1022   m_application_uuid = ON_opennurbs5_id;
1023   m_userdata_copycount = 1;
1024   CreateHelper();
1025 }
1026 
~ON__IDefLayerSettingsUserData()1027 ON__IDefLayerSettingsUserData::~ON__IDefLayerSettingsUserData()
1028 {
1029   DestroyHelper();
1030 }
1031 
ON__IDefLayerSettingsUserData(const ON__IDefLayerSettingsUserData & src)1032 ON__IDefLayerSettingsUserData::ON__IDefLayerSettingsUserData(const ON__IDefLayerSettingsUserData& src)
1033 : ON_UserData(src)
1034 {
1035   m_userdata_uuid = ON__IDefLayerSettingsUserData::m_ON__IDefLayerSettingsUserData_class_id.Uuid();
1036   m_application_uuid = ON_opennurbs5_id;
1037   CreateHelper();
1038   CopyHelper(src);
1039 }
1040 
operator =(const ON__IDefLayerSettingsUserData & src)1041 ON__IDefLayerSettingsUserData& ON__IDefLayerSettingsUserData::operator=(const ON__IDefLayerSettingsUserData& src)
1042 {
1043   if ( this != &src )
1044   {
1045     DestroyHelper();
1046     ON_UserData::operator=(src);
1047     CopyHelper(src);
1048   }
1049   return *this;
1050 }
1051 
1052 // virtual ON_Object override
IsValid(ON_TextLog * text_log) const1053 ON_BOOL32 ON__IDefLayerSettingsUserData::IsValid( ON_TextLog* text_log ) const
1054 {
1055   return true;
1056 }
1057 
1058 // virtual ON_Object override
SizeOf() const1059 unsigned int ON__IDefLayerSettingsUserData::SizeOf() const
1060 {
1061   return (unsigned int)(sizeof(*this));
1062 }
1063 
1064 // virtual ON_Object override
DataCRC(ON__UINT32 current_remainder) const1065 ON__UINT32 ON__IDefLayerSettingsUserData::DataCRC(ON__UINT32 current_remainder) const
1066 {
1067   ON__UINT32 crc = current_remainder;
1068   for ( int i = 0; i < m_layers.Count(); i++ )
1069     crc = m_layers.DataCRC(crc);
1070   return crc;
1071 }
1072 
1073 // virtual ON_Object override
Write(ON_BinaryArchive & binary_archive) const1074 ON_BOOL32 ON__IDefLayerSettingsUserData::Write(ON_BinaryArchive& binary_archive) const
1075 {
1076   bool rc = binary_archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,1);
1077   if ( !rc )
1078     return false;
1079 
1080   rc = false;
1081   for(;;)
1082   {
1083     if ( !binary_archive.WriteArray(m_layers.Count(),m_layers.Array()) )
1084       break;
1085 
1086     // added in version 1.1 chunks
1087     bool bHaveParentLayer = ( 0 != m_idef_layer_table_parent_layer );
1088     if ( !binary_archive.WriteBool(bHaveParentLayer) )
1089       break;
1090 
1091     if ( bHaveParentLayer )
1092     {
1093       if ( !binary_archive.WriteObject(m_idef_layer_table_parent_layer) )
1094         break;
1095     }
1096 
1097     rc = true;
1098     break;
1099   }
1100 
1101   if ( !binary_archive.EndWrite3dmChunk() )
1102     rc = false;
1103 
1104   return rc;
1105 }
1106 
1107 // virtual ON_Object override
Read(ON_BinaryArchive & binary_archive)1108 ON_BOOL32 ON__IDefLayerSettingsUserData::Read(ON_BinaryArchive& binary_archive)
1109 {
1110   DestroyHelper();
1111 
1112   int major_version = 0;
1113   int minor_version = 0;
1114   bool rc = binary_archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
1115   if ( !rc )
1116     return false;
1117 
1118   rc = false;
1119   while ( 1 == major_version )
1120   {
1121     if ( !binary_archive.ReadArray(m_layers) )
1122       break;
1123 
1124     if ( minor_version <= 0 )
1125     {
1126       rc = true;
1127       break;
1128     }
1129 
1130     // added in version 1.1 chunks
1131     bool bHaveParentLayer = false;
1132     if ( !binary_archive.ReadBool(&bHaveParentLayer) )
1133       break;
1134 
1135     if ( bHaveParentLayer )
1136     {
1137       ON_Object* p = 0;
1138       if ( !binary_archive.ReadObject(&p) || 0 == p )
1139       {
1140         if (p)
1141         {
1142           delete p;
1143           break;
1144         }
1145       }
1146 
1147       m_idef_layer_table_parent_layer = ON_Layer::Cast(p);
1148       if ( 0 == m_idef_layer_table_parent_layer )
1149       {
1150         delete p;
1151         break;
1152       }
1153     }
1154 
1155     rc = true;
1156     break;
1157   }
1158 
1159   if ( !binary_archive.EndRead3dmChunk() )
1160     rc = false;
1161 
1162   return rc;
1163 }
1164 
1165 // virtual ON_UserData override
Archive() const1166 ON_BOOL32 ON__IDefLayerSettingsUserData::Archive() const
1167 {
1168   // don't save empty settings
1169   return m_layers.Count() > 0;
1170 }
1171 
1172 // virtual ON_UserData override
GetDescription(ON_wString & description)1173 ON_BOOL32 ON__IDefLayerSettingsUserData::GetDescription( ON_wString& description )
1174 {
1175   description = L"Linked Instance Definition Layer Settings";
1176   return true;
1177 }
1178 
1179 
1180 
HasLinkedIdefLayerSettings() const1181 bool ON_InstanceDefinition::HasLinkedIdefLayerSettings() const
1182 {
1183   const ON__IDefLayerSettingsUserData* ud = ON__IDefLayerSettingsUserData::FindOrCreate(*this,false);
1184   return ud ? (ud->m_layers.Count() > 0) : false;
1185 }
1186 
1187 ///////*
1188 //////Description:
1189 //////  Get layer settings for the context where the idef
1190 //////  is being used.
1191 //////Parameters:
1192 //////  layer_settings - [out]
1193 //////    Each layer has the settings from the linked reference file
1194 //////    and layer.GetSavedSettings() reports any changes for the
1195 //////    corresponding layers in the current context.
1196 //////*/
1197 //////void GetLinkedIdefLayerSettings( class ON_ObjectArray<ON_Layer>& layer_settings ) const;
1198 //////
1199 ///////*
1200 //////Description:
1201 //////  Get the most recently read layer settings from the reference file.
1202 //////Parameters:
1203 //////  layer_settings - [out]
1204 //////    The pointers in this array point memory managed by this
1205 //////    instance definition and may be deleted by other
1206 //////    ON_InstanceDefinition layer settings tools. Use the
1207 //////    returned information immediately or copy it to memory
1208 //////    you are managing.
1209 //////*/
1210 //////void GetLinkedIdefLayerReferenceSettings( class ON_SimpleArray<const ON_Layer*>& layer_settings ) const;
1211 //////
1212 //////
1213 //////void ON_InstanceDefinition::GetLinkedIdefLayerReferenceSettings( class ON_SimpleArray<const ON_Layer*>& layer_settings ) const
1214 //////{
1215 //////  const ON__IDefLayerSettingsUserData* ud = ON__IDefLayerSettingsUserData::LayerSettings(*this,false);
1216 //////  const int count = 0 != ud ? ud->m_layers.Count() : 0;
1217 //////  if ( count > 0 )
1218 //////  {
1219 //////    layer_settings.Reserve(count);
1220 //////    for ( int i = 0; i < count; i++ )
1221 //////    {
1222 //////      if ( 0 != ud->m_layers[i] )
1223 //////        layer_settings.Append(ud->m_layers[i]);
1224 //////    }
1225 //////  }
1226 //////  else
1227 //////  {
1228 //////    layer_settings.SetCount(0);
1229 //////  }
1230 //////}
1231 //////
1232 //////void ON_InstanceDefinition::GetLinkedIdefLayerSettings( class ON_ObjectArray<ON_Layer>& layer_settings ) const
1233 //////{
1234 //////  layer_settings.SetCount(0);
1235 //////
1236 //////  // Get the layers with settings from the referenced file.
1237 //////  ON_SimpleArray<const ON_Layer*> layers;
1238 //////  GetLinkedIdefLayerReferenceSettings(layers);
1239 //////
1240 //////  // Update those settings with any modifications made in the idef's current context.
1241 //////  layer_settings.Reserve(layers.Count());
1242 //////  unsigned int settings;
1243 //////  for ( int i = 0; i < layers.Count(); i++ )
1244 //////  {
1245 //////    if ( 0 != layers[i] )
1246 //////    {
1247 //////      ON_Layer& layer = layer_settings.AppendNew();
1248 //////      layer = *layers[i];
1249 //////      settings = 0;
1250 //////      layer.GetSavedSettings(layer,settings);
1251 //////    }
1252 //////  }
1253 //////}
1254 
compareLayerPtrId(const void * A,const void * B)1255 static int compareLayerPtrId(const void* A, const void*B)
1256 {
1257   if ( 0 == A )
1258   {
1259     return 0 == B ? 0 : -1;
1260   }
1261   if ( 0 == B )
1262   {
1263     return 1;
1264   }
1265 
1266   const ON_Layer* a = (0!=A) ? ( *((ON_Layer**)A) ) : 0;
1267   const ON_Layer* b = (0!=B) ? ( *((ON_Layer**)B) ) : 0;
1268   if ( 0 == a )
1269   {
1270     return (0 == b) ? 0 : -1;
1271   }
1272   if ( 0 == b )
1273   {
1274     return 1;
1275   }
1276 
1277   // NOTE WELL:
1278   //   Compare only m_layer_id.  Other values may differ and
1279   //   adding compares to them will break the code that uses
1280   //   this function.
1281   return ON_UuidCompare(a->m_layer_id,b->m_layer_id);
1282 }
1283 
compareUuidIndexId(const void * a,const void * b)1284 static int compareUuidIndexId(const void* a, const void* b)
1285 {
1286   return ON_UuidIndex::CompareId((const ON_UuidIndex*)a,(const ON_UuidIndex*)b);
1287 }
1288 
UpdateLinkedIdefReferenceFileLayerRuntimeId(const ON_UuidPairList & id_map)1289 void ON_InstanceDefinition::UpdateLinkedIdefReferenceFileLayerRuntimeId( const ON_UuidPairList& id_map )
1290 {
1291   ON__IDefLayerSettingsUserData* ud = ON__IDefLayerSettingsUserData::FindOrCreate(*this,false);
1292   if ( 0 == ud || ud->m_layers.Count() <= 0 )
1293     return;
1294   ud->m_runtime_layer_id_map = id_map;
1295   ud->m_runtime_layer_id_map.ImproveSearchSpeed();
1296 }
1297 
UpdateLinkedIdefParentLayerSettings(const ON_Layer * linked_idef_parent_layer)1298 void ON_InstanceDefinition::UpdateLinkedIdefParentLayerSettings( const ON_Layer* linked_idef_parent_layer )
1299 {
1300   bool bCreate = ( 0 != linked_idef_parent_layer );
1301   ON__IDefLayerSettingsUserData* ud = ON__IDefLayerSettingsUserData::FindOrCreate(*this,bCreate);
1302   if ( 0 != ud && ud->m_idef_layer_table_parent_layer != linked_idef_parent_layer )
1303   {
1304     if ( ud->m_idef_layer_table_parent_layer )
1305     {
1306       delete ud->m_idef_layer_table_parent_layer;
1307       ud->m_idef_layer_table_parent_layer = 0;
1308     }
1309     if ( 0 != linked_idef_parent_layer )
1310     {
1311       ud->m_idef_layer_table_parent_layer = new ON_Layer( *linked_idef_parent_layer );
1312     }
1313   }
1314 }
1315 
LinkedIdefParentLayerSettings() const1316 const ON_Layer* ON_InstanceDefinition::LinkedIdefParentLayerSettings() const
1317 {
1318   ON__IDefLayerSettingsUserData* ud = ON__IDefLayerSettingsUserData::FindOrCreate(*this,false);
1319   return (0 != ud) ? ud->m_idef_layer_table_parent_layer : 0;
1320 }
1321 
UpdateLinkedIdefReferenceFileLayerSettings(unsigned int layer_count,ON_Layer ** layer_settings)1322 void ON_InstanceDefinition::UpdateLinkedIdefReferenceFileLayerSettings( unsigned int layer_count, ON_Layer** layer_settings )
1323 {
1324   ON__IDefLayerSettingsUserData* ud;
1325 
1326   if ( layer_count <= 0 || 0 == layer_settings )
1327   {
1328     // delete linked idef layer settings
1329     ud = ON__IDefLayerSettingsUserData::FindOrCreate(*this,false);
1330     if ( 0 != ud )
1331       delete ud;
1332     return;
1333   }
1334 
1335   // Create an index_map[] into the layer_settings[] array that is sorted
1336   // by layer_settings[]->m_layer_id
1337   ON_Workspace ws;
1338   int* index_map = (int*)ws.GetMemory(layer_count*sizeof(index_map[0]));
1339   ON_Sort(ON::quick_sort,index_map,layer_settings,layer_count,sizeof(layer_settings[0]),compareLayerPtrId);
1340 
1341   // Use index_map[] to get a unique list of layers with valid ids
1342   ON_UuidIndex* iddex = (ON_UuidIndex*)ws.GetMemory(layer_count*sizeof(iddex[0]));
1343   unsigned int iddex_count = 0;
1344   unsigned int i;
1345   ON_Layer* layer;
1346   for ( i = 0; i < layer_count; i++ )
1347   {
1348     layer = layer_settings[index_map[i]];
1349     if ( 0 == layer )
1350       continue;
1351     layer->SaveSettings(0,false); // remove any saved settings on input layers
1352     if ( ON_UuidIsNil(layer->m_layer_id) )
1353       continue;
1354     if ( iddex_count > 0 && iddex[iddex_count-1].m_id == layer->m_layer_id )
1355       continue;
1356     iddex[iddex_count].m_i = index_map[i];
1357     iddex[iddex_count].m_id = layer->m_layer_id;
1358     iddex_count++;
1359   }
1360 
1361   if ( iddex_count <= 0 )
1362   {
1363     // delete settings
1364     UpdateLinkedIdefReferenceFileLayerSettings(0,0);
1365     return;
1366   }
1367 
1368   // Create or get user data where the saved layer settings
1369   // are stored.
1370   ud = ON__IDefLayerSettingsUserData::FindOrCreate(*this,true);
1371   if ( 0 == ud )
1372     return;
1373 
1374   // Go through the saved settings that were previously
1375   // on this idef apply those settings to the layer_settings[]
1376   // list. Then delete the information from ud->m_layers[].
1377   ON_UuidIndex idx;
1378   idx.m_i = 0;
1379   unsigned int settings;
1380   for ( i = 0; i < ud->m_layers.UnsignedCount(); i++ )
1381   {
1382     if ( 0 == ud->m_layers[i] )
1383       continue;
1384     layer = ud->m_layers[i];
1385     ud->m_layers[i] = 0;
1386     for(;;)
1387     {
1388       settings = layer->SavedSettings();
1389       if ( 0 == settings )
1390         break; // no settings were modified
1391       idx.m_id = layer->m_layer_id;
1392       const ON_UuidIndex* idx0 = (const ON_UuidIndex*)bsearch(&idx,iddex,iddex_count,sizeof(iddex[0]),compareUuidIndexId);
1393       if ( 0 == idx0)
1394         break; // this layer is not in the current layer_settings[] list
1395       layer_settings[idx0->m_i]->SaveSettings(settings,false); // saves the layer settings found in linked file
1396       layer_settings[idx0->m_i]->Set(settings,*layer);   // applies modifications found on idef
1397       break;
1398     }
1399     delete layer;
1400   }
1401 
1402   // Save a copy of this information on the user data
1403   // so it will persist in the file containing the idef.
1404   ud->m_layers.SetCount(0);
1405   ud->m_layers.Reserve(iddex_count);
1406   for ( i = 0; i < iddex_count; i++ )
1407   {
1408     layer = new ON_Layer( *layer_settings[iddex[i].m_i] );
1409     ud->m_layers.Append(layer);
1410   }
1411 }
1412 
1413 
1414 
UpdateLinkedIdefLayerSettings(unsigned int layer_count,const ON_Layer * const * layer_settings)1415 void ON_InstanceDefinition::UpdateLinkedIdefLayerSettings( unsigned int layer_count, const ON_Layer*const* layer_settings )
1416 {
1417   if ( layer_count <= 0 || 0 == layer_settings )
1418   {
1419     // delete linked idef layer settings
1420     UpdateLinkedIdefReferenceFileLayerSettings(0,0);
1421     return;
1422   }
1423 
1424   // Get layer information (saved on this idef) from the linked file
1425   ON__IDefLayerSettingsUserData* ud = ON__IDefLayerSettingsUserData::FindOrCreate(*this,false);
1426   if ( 0 == ud )
1427     return;
1428   if ( ud->m_layers.Count() <= 0 )
1429   {
1430     delete ud;
1431     return;
1432   }
1433 
1434   // Apply any saved settings
1435   ON_Layer** ud_layers = ud->m_layers.Array();
1436   size_t ud_layers_count = ud->m_layers.Count();
1437   ON_Layer layerId;
1438   const ON_Layer* layerPtrId = &layerId;
1439   for ( unsigned int i = 0; i < layer_count; i++ )
1440   {
1441     const ON_Layer* layer1 = layer_settings[i];
1442     if ( !ud->m_runtime_layer_id_map.FindId1(layer1->m_layer_id,&layerId.m_layer_id) )
1443       layerId.m_layer_id = layer1->m_layer_id;
1444     ON_Layer** pp = (ON_Layer**)bsearch(&layerPtrId,ud_layers,ud_layers_count,sizeof(ud_layers[0]),compareLayerPtrId);
1445     ON_Layer* layer0 = (0 != pp) ? *pp : 0;
1446     if ( 0 == layer0 )
1447       continue;
1448     unsigned int settings0 = layer0->SavedSettings();
1449     unsigned int settings1 = ON_Layer::Differences(*layer0,*layer1);
1450     // settings0 = settings changes
1451     // new_settings = settings changed since we opened the model
1452     unsigned int new_settings = (settings1 ^ (settings0 & settings1));
1453     if ( 0 != new_settings )
1454       layer0->SaveSettings( new_settings, true );
1455     layer0->Set((settings0|settings1),*layer1);
1456   }
1457 }
1458 
1459 
1460 
1461 ///////////////////////////////////////////////////////////////////
1462 
1463 
1464 class /*NEVER EXPORT THIS CLASS DEFINITION*/ ON__IDefAlternativePathUserData : public ON_UserData
1465 {
1466 #if !defined(ON_BOZO_VACCINE_F42D967121EB46929B9ABC3507FF28F5)
1467 #error Never copy this class definition or put this definition in a header file!
1468 #endif
1469   ON_OBJECT_DECLARE(ON__IDefAlternativePathUserData);
1470 
1471 public:
1472   ON__IDefAlternativePathUserData();
1473   ~ON__IDefAlternativePathUserData();
1474   // default copy constructor and operator= work fine.
1475 
1476   ON__IDefAlternativePathUserData(const ON__IDefAlternativePathUserData& src);
1477   ON__IDefAlternativePathUserData& operator=(const ON__IDefAlternativePathUserData& src);
1478 
1479 
1480   static ON__IDefAlternativePathUserData* FindOrCreate(const ON_InstanceDefinition& idef,bool bCreate);
1481 
1482 private:
CreateHelper()1483   void CreateHelper()
1484   {
1485     m_alternate_path.Destroy();
1486     m_bRelativePath = false;
1487   }
1488 
CopyHelper(const ON__IDefAlternativePathUserData & src)1489   void CopyHelper(const ON__IDefAlternativePathUserData& src)
1490   {
1491     m_alternate_path = src.m_alternate_path;
1492     m_bRelativePath = src.m_bRelativePath;
1493   }
1494 
DestroyHelper()1495   void DestroyHelper()
1496   {
1497     m_alternate_path.Destroy();
1498     m_bRelativePath = false;
1499   }
1500 
1501 public:
1502   // virtual ON_Object override
1503   ON_BOOL32 IsValid( ON_TextLog* text_log = NULL ) const;
1504   // virtual ON_Object override
1505   unsigned int SizeOf() const;
1506   // virtual ON_Object override
1507   ON__UINT32 DataCRC(ON__UINT32 current_remainder) const;
1508   // virtual ON_Object override
1509   ON_BOOL32 Write(ON_BinaryArchive& binary_archive) const;
1510   // virtual ON_Object override
1511   ON_BOOL32 Read(ON_BinaryArchive& binary_archive);
1512   // virtual ON_UserData override
1513   ON_BOOL32 Archive() const;
1514   // virtual ON_UserData override
1515   ON_BOOL32 GetDescription( ON_wString& description );
1516 
1517 public:
1518   ON_wString m_alternate_path;
1519   bool m_bRelativePath;
1520 };
1521 
1522 #undef ON_BOZO_VACCINE_F42D967121EB46929B9ABC3507FF28F5
1523 
1524 ON_OBJECT_IMPLEMENT(ON__IDefAlternativePathUserData,ON_UserData,"F42D9671-21EB-4692-9B9A-BC3507FF28F5");
1525 
FindOrCreate(const ON_InstanceDefinition & idef,bool bCreate)1526 ON__IDefAlternativePathUserData* ON__IDefAlternativePathUserData::FindOrCreate(const ON_InstanceDefinition& idef,bool bCreate)
1527 {
1528   ON__IDefAlternativePathUserData* ud = ON__IDefAlternativePathUserData::Cast(idef.GetUserData(ON__IDefAlternativePathUserData::m_ON__IDefAlternativePathUserData_class_id.Uuid()));
1529   if ( !ud && bCreate )
1530   {
1531     ud = new ON__IDefAlternativePathUserData();
1532     const_cast<ON_InstanceDefinition&>(idef).AttachUserData(ud);
1533   }
1534   return ud;
1535 }
1536 
ON__IDefAlternativePathUserData()1537 ON__IDefAlternativePathUserData::ON__IDefAlternativePathUserData()
1538 {
1539   m_userdata_uuid = ON__IDefAlternativePathUserData::m_ON__IDefAlternativePathUserData_class_id.Uuid();
1540   m_application_uuid = ON_opennurbs5_id;
1541   m_userdata_copycount = 1;
1542   CreateHelper();
1543 }
1544 
~ON__IDefAlternativePathUserData()1545 ON__IDefAlternativePathUserData::~ON__IDefAlternativePathUserData()
1546 {
1547   DestroyHelper();
1548 }
1549 
ON__IDefAlternativePathUserData(const ON__IDefAlternativePathUserData & src)1550 ON__IDefAlternativePathUserData::ON__IDefAlternativePathUserData(const ON__IDefAlternativePathUserData& src)
1551 : ON_UserData(src)
1552 {
1553   m_userdata_uuid = ON__IDefAlternativePathUserData::m_ON__IDefAlternativePathUserData_class_id.Uuid();
1554   m_application_uuid = ON_opennurbs5_id;
1555   CreateHelper();
1556   CopyHelper(src);
1557 }
1558 
operator =(const ON__IDefAlternativePathUserData & src)1559 ON__IDefAlternativePathUserData& ON__IDefAlternativePathUserData::operator=(const ON__IDefAlternativePathUserData& src)
1560 {
1561   if ( this != &src )
1562   {
1563     DestroyHelper();
1564     ON_UserData::operator=(src);
1565     CopyHelper(src);
1566   }
1567   return *this;
1568 }
1569 
1570 // virtual ON_Object override
IsValid(ON_TextLog * text_log) const1571 ON_BOOL32 ON__IDefAlternativePathUserData::IsValid( ON_TextLog* text_log ) const
1572 {
1573   return !m_alternate_path.IsEmpty();
1574 }
1575 
1576 // virtual ON_Object override
SizeOf() const1577 unsigned int ON__IDefAlternativePathUserData::SizeOf() const
1578 {
1579   return (unsigned int)(sizeof(*this) + m_alternate_path.SizeOf());
1580 }
1581 
1582 // virtual ON_Object override
DataCRC(ON__UINT32 current_remainder) const1583 ON__UINT32 ON__IDefAlternativePathUserData::DataCRC(ON__UINT32 current_remainder) const
1584 {
1585   ON__UINT32 crc = ON_CRC32(current_remainder,sizeof(m_bRelativePath),&m_bRelativePath);
1586   crc = m_alternate_path.DataCRC(crc);
1587   return crc;
1588 }
1589 
1590 // virtual ON_Object override
Write(ON_BinaryArchive & binary_archive) const1591 ON_BOOL32 ON__IDefAlternativePathUserData::Write(ON_BinaryArchive& binary_archive) const
1592 {
1593   bool rc = binary_archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
1594   if ( !rc )
1595     return false;
1596 
1597   rc = false;
1598   for(;;)
1599   {
1600     if ( !binary_archive.WriteString(m_alternate_path) )
1601       break;
1602     if ( !binary_archive.WriteBool(m_bRelativePath) )
1603       break;
1604     rc = true;
1605     break;
1606   }
1607 
1608   if ( !binary_archive.EndWrite3dmChunk() )
1609     rc = false;
1610 
1611   return rc;
1612 }
1613 
1614 // virtual ON_Object override
Read(ON_BinaryArchive & binary_archive)1615 ON_BOOL32 ON__IDefAlternativePathUserData::Read(ON_BinaryArchive& binary_archive)
1616 {
1617   DestroyHelper();
1618 
1619   int major_version = 0;
1620   int minor_version = 0;
1621   bool rc = binary_archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
1622   if ( !rc )
1623     return false;
1624 
1625   rc = false;
1626   while ( 1 == major_version )
1627   {
1628     if ( !binary_archive.ReadString(m_alternate_path) )
1629       break;
1630     if ( !binary_archive.ReadBool(&m_bRelativePath) )
1631       break;
1632     rc = true;
1633     break;
1634   }
1635 
1636   if ( !binary_archive.EndRead3dmChunk() )
1637     rc = false;
1638 
1639   return rc;
1640 }
1641 
1642 // virtual ON_UserData override
Archive() const1643 ON_BOOL32 ON__IDefAlternativePathUserData::Archive() const
1644 {
1645   // don't save empty settings
1646   return !m_alternate_path.IsEmpty();
1647 }
1648 
1649 // virtual ON_UserData override
GetDescription(ON_wString & description)1650 ON_BOOL32 ON__IDefAlternativePathUserData::GetDescription( ON_wString& description )
1651 {
1652   description = L"Linked Instance Definition Alternate Path";
1653   return true;
1654 }
1655 
1656 
SetAlternateSourceArchivePath(const wchar_t * alternate_source_archive_path,bool bRelativePath)1657 void ON_InstanceDefinition::SetAlternateSourceArchivePath(
1658       const wchar_t* alternate_source_archive_path,
1659       bool bRelativePath
1660       )
1661 {
1662   ON_wString s;
1663   if ( 0 != alternate_source_archive_path )
1664   {
1665     s = alternate_source_archive_path;
1666     s.TrimLeftAndRight();
1667     alternate_source_archive_path = s;
1668     if ( 0 != alternate_source_archive_path && 0 == alternate_source_archive_path[0] )
1669       alternate_source_archive_path = 0;
1670   }
1671   ON__IDefAlternativePathUserData* ud = ON__IDefAlternativePathUserData::FindOrCreate(*this,0!=alternate_source_archive_path);
1672   if ( 0 != ud )
1673   {
1674     if ( 0 == alternate_source_archive_path )
1675       delete ud;
1676     else
1677     {
1678       ud->m_alternate_path = alternate_source_archive_path;
1679       ud->m_bRelativePath = bRelativePath;
1680     }
1681   }
1682 }
1683 
GetAlternateSourceArchivePath(ON_wString & alternate_source_archive_path,bool & bRelativePath) const1684 bool ON_InstanceDefinition::GetAlternateSourceArchivePath(
1685       ON_wString& alternate_source_archive_path,
1686       bool& bRelativePath
1687       ) const
1688 {
1689   const ON__IDefAlternativePathUserData* ud = ON__IDefAlternativePathUserData::FindOrCreate(*this,false);
1690   const wchar_t* s = (0 != ud) ? ((const wchar_t*)ud->m_alternate_path) : 0;
1691   if ( 0 != s && 0 != s[0] )
1692   {
1693     alternate_source_archive_path = s;
1694     bRelativePath = ud->m_bRelativePath;
1695   }
1696   else
1697   {
1698     alternate_source_archive_path.Destroy();
1699     bRelativePath = false;
1700   }
1701   return !alternate_source_archive_path.IsEmpty();
1702 }
1703