////////////////////////////////////////////////////////////////////////////////
//
// step3D2.cpp -   
// 
// 1.                                               - CreateDocument3D 
// 2.                                            - DocIterator 
// 3.                                   - UseEntityCollection 
// 4.  /                                   - GetSetPartName 
// 5.                       - FixAndStandartComponent 
// 6.                       - GetSetColorProperty 
// 7.                       - GetSetArrayVariable 
// 8.                 - GetSetPlacmentComponent 
// 9.    ksEntity    
//                                      - GetSetEntity 
// 10.                                                   - CreateSketch 
// 11.   (   )    
//      ksEntityCollection( IEntityCollection )             - GetArraySketch 
// 12.            - GetSetUserParamComponent 
//
////////////////////////////////////////////////////////////////////////////////
#ifndef VCL_H
#include <vcl.h>
#endif

#ifndef __WINDOWS_
#include <windows.h>
#endif

#ifndef __STDIO_H
#include <stdio.h>
#endif

#ifndef  __MATH_H
#include <math.h>
#endif

#pragma hdrstop

#include <objbase.h>
#include <initguid.h>

#ifndef __STEP3D2_RH
#include "step3D2.rh"
#endif

#ifndef __STEP3D2_H
#include "step3D2.h"
#endif

#include "ksConstants.h"

#if !defined(_IFUNC)
# define _IFUNC STDMETHODCALLTYPE
#endif

HINSTANCE _hinst;

//------------------------------------------------------------------------------
//    
// ---
LPTSTR _LoadStr( int id )
{ 
  static char buf[512]; 
  //       
  ksConvertLangStrEx( _hinst, id, buf, 512 );
  return buf;
}


//-------------------------------------------------------------------------------
//   
// ---
extern "C" unsigned int far __export __pascal LibraryId()
{
	return IDR_LIBID;
}


//-------------------------------------------------------------------------------
//   
// ---
void CreateDocument3D();
void DocIterator();
void UseEntityCollection();
void GetSetPartName( LPDOCUMENT3D pDocument3d );
void FixAndStandartComponent( LPDOCUMENT3D pDocument3d );
void GetSetColorProperty( LPDOCUMENT3D pDocument3d );
void GetSetArrayVariable( LPDOCUMENT3D pDocument3d  );
void GetSetPlacmentComponent( LPDOCUMENT3D pDocument3d );
void GetSetEntity( LPDOCUMENT3D pDocument3d );
void CreateSketch( LPDOCUMENT3D pDocument3d );
void GetArraySketch( LPDOCUMENT3D pDocument3d );
void GetSetUserParamComponent( LPDOCUMENT3D pDocument3d  );


//-------------------------------------------------------------------------------
//   
// ---
extern "C" void far __export __pascal LibraryEntry( unsigned int comm )
{
  switch ( comm )
  {
    case 10 :  CreateDocument3D();     break;  //  
    case 11 :  DocIterator();          break;  //   
    case 12 :  UseEntityCollection();  break;  //   
    default :
    {
      IUEnv <IDocument3D> document3d( ksGetActive3dDocument() ); //       
      if ( document3d  )
      {
        switch ( comm )
        {
          case 1  : GetSetPartName( document3d.GetI() );           break; // /  
          case 2  : FixAndStandartComponent( document3d.GetI() );  break; //     
          case 3  : GetSetColorProperty( document3d.GetI() );      break; //      
          case 4  : GetSetArrayVariable( document3d.GetI() );      break; //      
          case 5  : GetSetPlacmentComponent( document3d.GetI() );  break; //        
          case 6  : GetSetEntity( document3d.GetI() );             break; //   ksEntity        
          case 7  : CreateSketch( document3d.GetI() );             break; //  
          case 8  : GetArraySketch( document3d.GetI() );           break; //   (   )     ksEntityCollection( IEntityCollection )
          case 9  : GetSetUserParamComponent( document3d.GetI() ); break; //       
        }
      }
      else
      {
        Error( _LoadStr( STR_3DDOCERROR ) ); //       3D-
      }
      if ( ReturnResult() == etError10 ) // !  
        ResultNULL(); //  
    }    
  }
}


//-------------------------------------------------------------------------------
//   3D
// ---
void CreateDocument3D()
{
  //       
  LPDOCUMENT3D pDocument3d = ksGet3dDocument();
  if ( pDocument3d ) 
  {
    if ( pDocument3d->Create( false,   //     ( TRUE -  , FALSE -   )
                              true ) ) //   ( TRUE - , FALSE -  ) 
    {
      pDocument3d->SetAuthor( WideString( "" ) );                //  
      pDocument3d->SetComment( WideString( "  3D" ) ); //   
      pDocument3d->SetFileName( WideString( "C:\\Example.m3d" ) );    //   
      pDocument3d->UpdateDocumentParam();                                           //   
      pDocument3d->Save();                                                          //  
      Message( "    " );
      pDocument3d->SaveAs( WideString( "C:\\Example2.m3d" ) );        //     

      char buf[255];
      
      //  
      String author = pDocument3d->GetAuthor();
      sprintf( buf, " : %s", author );
      Message( buf );
      
      //   
      String comment = pDocument3d->GetComment();
      sprintf( buf, "  : %s", comment );
      Message( buf );
      
      //  
      String fileName = pDocument3d->GetFileName();
      sprintf( buf, " : %s", fileName );
      Message( buf );

      pDocument3d->Close(); //  
    }
  }
}


//-------------------------------------------------------------------------------
//        
// ---
void DocIterator()
{
  //       
  reference rArDocFileName = CreateArray( CHAR_STR_ARR, 0 );
  
  if ( ksChoiceFiles( "*.m3d", " ( *.m3d )|*.m3d| ( *.a3d )|*a3d|  ( *.* )|*.*|", rArDocFileName, 1 ) )
  {
    char buf[255];
    
    //     
    int docCount = GetArrayCount( rArDocFileName );
    for ( int i = 0; i < docCount; i++ ) 
    {
      if ( GetArrayItem( rArDocFileName, i, buf, 255 ) ) 
      {
        //       
        LPDOCUMENT3D pDocument3d = ksGet3dDocument();
        if ( pDocument3d )
          //    - (    )
          pDocument3d->Open( WideString( buf ), //    
                             false );           //    
                                                // ( TRUE   , FALSE -   )
        pDocument3d->Release(); //  , AddRef   
      }
    }

    //        
    sprintf( buf, " %d ", docCount );
    Message( buf );
    
    //   3D 
    reference rIterator = CreateIterator( D3_DOCUMENT_OBJ, 0 );
    if ( rIterator ) 
    { 
      reference rDocument = MoveIterator( rIterator, 'F' ); //     
      while ( rDocument > 0 )
      {
        LPDOCUMENT3D pDocument3d = ksGet3dDocumentFromReference( rDocument );
        if ( pDocument3d ) 
        {
          //  
          String author = pDocument3d->GetAuthor();
          sprintf( buf, " : %s", author );
          Message( buf );
      
          //   
          String comment = pDocument3d->GetComment();
          sprintf( buf, "  : %s", comment );
          Message( buf );
      
          //  
          String fileName = pDocument3d->GetFileName();
          sprintf( buf, " : %s", fileName );
          Message( buf );
          
          //  
          sprintf( buf, " : %s", pDocument3d->IsDetail() ? "" : "" );
          Message( buf );
            
          pDocument3d->Release(); //  , AddRef   
          
        }
        rDocument = MoveIterator( rIterator, 'N' ); //     
      } 
      DeleteIterator( rIterator ); //  
    }
  }
}


//-------------------------------------------------------------------------------
//   
// ---
void UseEntityCollection()
{
  LPDOCUMENT3D pDocument3d = ksGetActive3dDocument(); //       
  if ( pDocument3d )
  {
    //           ( pNew_Part -  ,
    // pEdit_Part -  , pTop_Part -   )    
    IUEnv <IPart> part( pDocument3d->GetPart( pTop_Part ) );
    if ( part )
    {
      char buf[255];
            
      //          -   
      IUEnv <IEntityCollection> entityCollection( part->EntityCollection( o3d_face ) );
      if ( entityCollection )
      {
        int countAllFace  = entityCollection->GetCount(); //   
        int countPlane = 0;                               //   
        int countCone  = 0;                               //   
        for ( int i = 0; i < countAllFace; i++ ) 
        {
          IUEnv <IEntity> entityFace( entityCollection->GetByIndex( i ) ); //  
          IUEnv <IColorParam> colorParam( entityFace->ColorParam() );       //  
          
          //        
          LPUNKNOWN pDefinitionFace = entityFace->GetDefinition();
          if ( pDefinitionFace )
          {
            //   
            IUPTR( FaceDefinition ) faceDefinition( pDefinitionFace );
            if ( faceDefinition ) 
            {
              if ( faceDefinition->IsCone() ||    //   
                   faceDefinition->IsCylinder() ) //  
              {
                colorParam->SetColor( RGB( 255, 255, 0 ) );
                countCone++; //    
              }
      
              if ( faceDefinition->IsPlanar() ) //   
              {
                colorParam->SetColor( RGB( 0, 255, 255 ) );
                countPlane++; //    
              }
              entityFace->Update(); //   
            }
          }
          pDefinitionFace->Release(); //  , AddRef   
        }

        if ( countAllFace == 0 )
          Message( "    " );
        else 
        {
          sprintf( buf, " %i   %i  ", countCone, countPlane );
          Message( buf );
        }
      } 
      
      //          -   
      IUEnv <IEntityCollection> entityCollection2( part->EntityCollection( o3d_edge ) );
      if ( entityCollection2 )
      {
        int countAllEdge     = entityCollection2->GetCount(); //   
        int countRectilinear = 0;                             //   
        int countCurvilinear = 0;                             //   
        for ( int i = 0; i < countAllEdge; i++ ) 
        {
          IUEnv <IEntity> entityEdge( entityCollection->GetByIndex( i ) ); //  
          
          //        
          LPUNKNOWN pDefinitionEdge = entityEdge ? entityEdge->GetDefinition() : NULL;
          if ( pDefinitionEdge )
          {
            //   
            IUPTR( EdgeDefinition ) edgeDefinition( pDefinitionEdge );
            if ( edgeDefinition ) 
            {
              if ( edgeDefinition->IsStraight() )
                countRectilinear++; //   
              else
                countCurvilinear++; //   
            }
            pDefinitionEdge->Release(); //  , AddRef   
          }
        }
        
        if ( countAllEdge == 0 )
          Message( "    " );
        else 
        {
          sprintf( buf, " %i   %i  ", countRectilinear, countCurvilinear );
          Message( buf );
        }
      }    
    }
  }
}


//-------------------------------------------------------------------------------
// /       
// ---
void GetSetPartName( LPDOCUMENT3D pDocument3d ) 
{
  //           ( pNew_Part -  ,
  // pEdit_Part -  , pTop_Part -   )    
  IUEnv <IPart> part( pDocument3d->GetPart( pTop_Part ) );
  if ( part )
  {
    char buf[255];
   
    //        
    String name = part->GetName();
    sprintf( buf, "  %s", name );
    Message( buf );
   
    //        
    part->SetName( WideString( "  " ) );
    part->Update(); //   
  }
}


//-------------------------------------------------------------------------------
//     
// ---
void FixAndStandartComponent( LPDOCUMENT3D pDocument3d ) 
{
  if ( pDocument3d->IsDetail() ) // ,    
  {
    Error( "    " );
    return;
  }
  
  //           ( pNew_Part -  ,
  // pEdit_Part -  , pTop_Part -   )    
  IUEnv <IPart> part( pDocument3d->GetPart( 0 ) ); //    
  if ( part )
  {
    //     (   ,      )
    int fixedComponent = part->GetFixedComponent();
    Message( fixedComponent ? " " : "  " );
    
    //     (     )
    int standardComponent = part->GetStandardComponent();
    Message( standardComponent ? " " : " " );
    
    //     (   ,      )
    part->SetFixedComponent( !fixedComponent );    
    //     (     )
    part->SetStandardComponent( !standardComponent );
  }
}


//-------------------------------------------------------------------------------
// /   
// ---
void GetSetColorProperty( LPDOCUMENT3D pDocument3d ) 
{
  //           ( pNew_Part -  ,
  // pEdit_Part -  , pTop_Part -   )    
  IUEnv <IPart> part( pDocument3d->GetPart( pTop_Part ) );
  if ( part )
  {
    char buf[255];

    //    
    //   
    IUEnv <IColorParam> colorParam( part->ColorParam() );
    if ( colorParam ) 
    {
      sprintf( buf, " = %d,   = %g,\n = %g,  = %g,\n = %g,  = %g,\n = %g", 
               colorParam->GetColor(), colorParam->GetAmbient(), 
               colorParam->GetDiffuse(), colorParam->GetSpecularity(), 
               colorParam->GetShininess(), colorParam->GetTransparency(), 
               colorParam->GetEmission() );
      Message( buf );
      
      //    
      colorParam->SetColor( 5421504 );
      colorParam->SetTransparency( 0.5 );
      colorParam->SetAmbient( 0.1 );
      colorParam->SetDiffuse( 0.1 );
      
      part->Update(); //   
      
      sprintf( buf, " = %d,   = %g,\n = %g,  = %g,\n = %g,  = %g,\n = %g", 
               colorParam->GetColor(), colorParam->GetAmbient(), 
               colorParam->GetDiffuse(), colorParam->GetSpecularity(), 
               colorParam->GetShininess(), colorParam->GetTransparency(), 
               colorParam->GetEmission() );
      Message( buf );
    }
    
    //  
    COLORREF color;      // 
    double ambient,      //  
           diffuse,      // 
           specularity,  //   
           shininess,    // 
           transparency, // 
           emission;     //   
    
    //        
    part->GetAdvancedColor( &color, &ambient, &diffuse, &specularity, &shininess, &transparency, &emission );
    sprintf( buf, " = %d,   = %g,\n = %g,  = %g,\n = %g,  = %g,\n = %g", 
             color, ambient, 
             diffuse, specularity, 
             shininess, transparency, 
             emission );
    Message( buf );
    
    //    
    color = 9421504; 
    transparency = 0.5; 
    ambient = 0.1; 
    diffuse = 0.1;
    
    //       
    part->SetAdvancedColor( color, ambient, diffuse, specularity, shininess, transparency, emission );
   
    part->Update(); //   
    
    //        
    part->GetAdvancedColor( &color, &ambient, &diffuse, &specularity, &shininess, &transparency, &emission );
    sprintf( buf, " = %d,   = %g,\n = %g,  = %g,\n = %g,  = %g,\n = %g", 
             color, ambient, 
             diffuse, specularity, 
             shininess, transparency, 
             emission );
    Message( buf );
  }
}


//-------------------------------------------------------------------------------
// /   
// ---
void GetSetArrayVariable( LPDOCUMENT3D pDocument3d ) 
{
  if ( pDocument3d->IsDetail() ) // ,    
  {
    Error( "    " );
    return;
  }
  
  //           ( pNew_Part -  ,
  // pEdit_Part -  , pTop_Part -   )    
  IUEnv <IPart> part( pDocument3d->GetPart( 0 ) ); //    
  if ( part )
  {  
    //     
    IUEnv <IVariableCollection> variableCollection( part->VariableCollection() );
    if ( variableCollection ) 
    {
      //     
      int count = variableCollection->GetCount();
      for ( int i = 0; i < count; i++ ) 
      {
        //  
        IUEnv <IVariable> variable( variableCollection->GetByIndex( i ) );
        if ( variable ) 
        {
          if ( i == 0 ) 
          {
            //   
            variable->SetNote( WideString( " " ) );
            double d = 0;
            //   
            ReadDouble( " ", 10, 0, 100, &d );
            //    
            variable->SetValue( d );
          }
        
          char buf[255];
          String name = variable->GetName(); //  
          String note = variable->GetNote(); //  
          sprintf( buf, "  : %d\n  : %s\n  : %g\n : %s",
                   i, name, variable->GetValue(), note );
          Message( buf );
        }
      }
      //         
      part->RebuildModel();
    }
  }
}


//-------------------------------------------------------------------------------
//        
// ---
void GetSetPlacmentComponent( LPDOCUMENT3D pDocument3d ) 
{
  if ( pDocument3d->IsDetail() ) // ,    
  {
    Error( "    " );
    return;
  }
  
  //           ( pNew_Part -  ,
  // pEdit_Part -  , pTop_Part -   )    
  IUEnv <IPart> part( pDocument3d->GetPart( 0 ) ); //    
  if ( part )
  {  
    IUEnv <IPlacement> placement( part->GetPlacement() ); //      
    if ( placement ) 
    {
      double x, y, z;  
      placement->GetOrigin( &x, &y, &z ); //      
      
      char buf[255];
      sprintf( buf, "x = %g\ny = %g\nz = %g", x, y, z );
      Message( buf );
      
      placement->SetOrigin( 20, 20, 20 ); //      
      
      part->SetPlacement( placement.GetI() ); //    
      part->UpdatePlacement(); //   ,   SetPlacement
      part->Update(); //    (   ) 
    }
  }
}


//-------------------------------------------------------------------------------
//   ksEntity        
// ---
void GetSetEntity( LPDOCUMENT3D pDocument3d ) 
{
  //           ( pNew_Part -  ,
  // pEdit_Part -  , pTop_Part -   )    
  IUEnv <IPart> part( pDocument3d->GetPart( pTop_Part ) ); 
  if ( part )
  {  
    IUEnv <IEntity> entityPlane( part->GetDefaultEntity( o3d_planeXOY ) ); //     ,
                                                                           //     -  XOY
    if ( entityPlane ) 
    {
      char buf[255];
      String name = entityPlane->GetName(); //    
      sprintf( buf, " : %s", name );
      Message( buf );

      entityPlane->SetName( WideString( "Plane" ) ); //      
      entityPlane->Update(); //    (   )
    }
  }
}


//-------------------------------------------------------------------------------
//  
// ---
void CreateSketch( LPDOCUMENT3D pDocument3d )
{
  //           ( pNew_Part -  ,
  // pEdit_Part -  , pTop_Part -   )    
  IUEnv <IPart> part( pDocument3d->GetPart( pTop_Part ) ); 
  if ( part )
  {  
    //   
    IUEnv <IEntity> entitySketch( part->NewEntity( o3d_sketch ) );
    if ( entitySketch )
    {
      //        
      LPUNKNOWN pDefinitionSketch = entitySketch->GetDefinition();
      if ( pDefinitionSketch )
      {
        //   
        IUPTR( SketchDefinition ) sketchDefinition( pDefinitionSketch );
        if ( sketchDefinition )
        {
          //     XOY
          IUEnv <IEntity> basePlane( part->GetDefaultEntity( o3d_planeXOY ) );
 
          //   
          sketchDefinition->SetPlane( basePlane.GetI() ); //   XOY   
          sketchDefinition->SetAngle( 45 );               //   
 
          //  
          entitySketch->Create();

          //     
          if ( sketchDefinition->BeginEdit() )
          {
            //    - 
            LineSeg(  50,  50, -50,  50, 1 );
            LineSeg(  50, -50, -50, -50, 1 );
            LineSeg(  50, -50,  50,  50, 1 );
            LineSeg( -50, -50, -50,  50, 1 );
            //     
            sketchDefinition->EndEdit();
          }  
        }
      }
    }
  }
}


//-------------------------------------------------------------------------------
//    (  )     IEntityCollection
// ---
void GetArraySketch( LPDOCUMENT3D pDocument3d ) 
{
  //           ( pNew_Part -  ,
  // pEdit_Part -  , pTop_Part -   )    
  IUEnv <IPart> part( pDocument3d->GetPart( pTop_Part ) ); 
  if ( part )
  {  
    //          -   
    IUEnv <IEntityCollection> entityCollection( part->EntityCollection( o3d_sketch ) ); 
    if ( entityCollection ) 
    {
      //     
      int count = entityCollection->GetCount();
      for ( int i = 0; i < count; i++ ) 
      {
        IUEnv <IEntity> currentEntity( entityCollection->GetByIndex( i ) ); //  
        char buf[255];
        String name = currentEntity->GetName(); //  
        sprintf( buf, " : %s", name );
        Message( buf );
      }
    }
  }
}


//-------------------------------------------------------------------------------
//       
// ---
void GetSetUserParamComponent( LPDOCUMENT3D pDocument3d  ) 
{
  if ( pDocument3d->IsDetail() ) // ,    
  {
    Error( "    " );
    return;
  }
  
  //           ( pNew_Part -  ,
  // pEdit_Part -  , pTop_Part -   )    
  IUEnv <IPart> part( pDocument3d->GetPart( 0 ) ); //    
  if ( part )
  {    
    //  
    struct UserParam 
    {
      double d1;
      double d2;
      int    i1;
      int    i2;
    } param;
    
    param.d1 = 12.12;
    param.d2 = 21.21;
    param.i1 = 666;
    param.i2 = 999;

    //   ,  
    part->SetUserParam( &param, sizeof( param ), 0, 0, -1 );
    part->Update(); //    (   ) 

    char buf[255];
    sprintf( buf, "   %d", part->GetUserParamSize() ); //   
    Message( buf );

    part->GetUserParam( &param, sizeof( param ) ); //   ,   
    sprintf( buf, "  \nd1 = %g\nd2 = %g\ni1 = %d\ni2 = %d",
             param.d1, param.d2, param.i1, param.i2 );
    Message( buf ); 
  }
} 