unit DocumentFrameEvents;

interface
uses
  Windows,
  cBaseEvents,
  ks2DCOM_TLB,
  ks3DCOM_TLB,
  LTool3D,
  ksConstTLB,
  LDefin3D,
  ActiveX,
  Libtool,
  Opengl,
  LtDefine,
{$IFDEF __LIGHT_VERSION__}
  klAPI7;
{$ELSE}
  ksApi7;
{$ENDIF}

type

////////////////////////////////////////////////////////////////////////////////
// DocumentFrameEvent  -     
//
DocumentFrameEvent = class ( cBaseEvent, IDocumentFrameNotify )
public

  constructor Create( var frame : IDocumentFrame; _docRef : Reference ); overload;
  destructor  Destroy(); override;
  function    Advise(): boolean; override;

protected
  //    true   notifyType  
  function IsNotifyProcess(notifyType: SYSINT): WORDBOOL; virtual; stdcall;
  // frBeginPaint = 1   .
  function  BeginPaint(const paintObj: IUnknown): WordBool; virtual; stdcall;
  // frClosePaint = 2   .
  function  ClosePaint(const paintObj: IUnknown): WordBool; virtual; stdcall;
  // frMouseDown  = 3   .
  function  MouseDown(nButton: Smallint; nShiftState: Smallint; x: Integer; y: Integer): WordBool; virtual; stdcall;
  // frMouseUp = 4   .
  function  MouseUp(nButton: Smallint; nShiftState: Smallint; x: Integer; y: Integer): WordBool; virtual; stdcall;
  // frMouseDblClick = 5    .
  function  MouseDblClick(nButton: Smallint; nShiftState: Smallint; x: Integer; y: Integer): WordBool; virtual; stdcall;
  // frBeginPaintGL = 6      OpenGL.
  function  BeginPaintGL(drawMode: Integer): WordBool; virtual; stdcall;
  // frClosePaintGL = 7      OpenGL.
  function  ClosePaintGL(drawMode: Integer): WordBool; virtual; stdcall;
  // frAddGabarit = 8   .
  function  AddGabarit(const gabObj: IUnknown): WordBool; virtual; stdcall;
  // frActivate = 9  .
  function  Activate: WordBool; virtual; stdcall;
  // frDeactivate = 10  .
  function  Deactivate: WordBool; virtual; stdcall;
  // frCloseFrame = 11  .
  function  CloseFrame: WordBool; virtual; stdcall;
  // frMouseMove = 12  .
  function  MouseMove(nShiftState: Smallint; x: Integer; y: Integer): WordBool; virtual; stdcall;
  // frShowOcxTree = 13 \ 
  function  ShowOcxTree(const tree: IUnknown; show: WordBool): WordBool; virtual; stdcall;

end;

  function NewDocumentFrameEvent( var frame : IDocumentFrame; doc : reference; redrawType : Integer ) : DocumentFrameEvent;
  procedure RecursiveDraw( var pTopPart : IPart; var coll : IFeatureCollection );

implementation

var
  xMax : double = 0;
  frameEventRedrawType : integer;

constructor DocumentFrameEvent.Create( var frame : IDocumentFrame; _docRef : Reference );
var
  unk : IUnknown;
begin
  unk := frame As IUnknown;
  inherited CreateByObj( ntDocumentFrameNotify, unk, _docRef );
   m_params.pContainer := _docRef;
end;

destructor DocumentFrameEvent.Destroy();
begin
  inherited Destroy;
end;

//------------------------------------------------------------------------------
// Advise
//---
function DocumentFrameEvent.Advise() : boolean;
begin
  if not m_advise and ( m_params.ifType <> 0 ) then
    m_advise := boolean( ksConnectionAdvise( @m_params, PIUnknown(IDocumentFrameNotify(self)) ) );
	Result := m_advise;
end;

function DocumentFrameEvent.IsNotifyProcess( notifyType: SYSINT ) : WORDBOOL;
begin
  Result := ( notifyType >= frBeginPaint ) And ( notifyType <= frCloseFrame )
end;

// frBeginPaint = 1   .
function DocumentFrameEvent.BeginPaint(const paintObj: IUnknown): WordBool;
begin
  Result := true;
end;

// frClosePaint = 2   .
function DocumentFrameEvent.ClosePaint(const paintObj: IUnknown): WordBool;
{var
  paintObject : IPaintObject;
  a11, a12, a13, a14, a21, a22, a23, a24 : Double;
  Xmm, Ymm, Zmm : Double;
  f             : OLE_HANDLE;
  _hWnd         : HWND;
  _hDC          : HDC;
  Xlp, Ylp      : Integer;
}
begin
{  paintObject := paintObj As IPaintObject;
  if paintObject <> nil then
  begin
    paintObject.GetTransformMatrix( a11, a12, a13, a14, a21, a22, a23, a24 );
//    Xlp := Round( Xmm * a11 + Ymm * a12 + Zmm * a13 + a14 );
//    Ylp := Round( Xmm * a21 + Ymm * a22 + Zmm * a23 + a24 );
    f := paintObject.GetHWND();
    _hWnd := f;
    _hDC  := GetDC(_hWnd);
    Xmm   := 50;
    Ymm   := 30;
    Zmm   := 10;
    Xlp   := Round(Xmm * a11 + Ymm * a12 + Zmm * a13 + a14);
    Ylp   := Round(Xmm * a21 + Ymm * a22 + Zmm * a23 + a24);
    MoveToEx( _hDC, Xlp, Ylp, nil );
    Xmm := xMax;
    Xlp := Round(Xmm * a11 + Ymm * a12 + Zmm * a13 + a14);

    LineTo( _hDC, Xlp, Ylp );
    ReleaseDC( _hWnd, _hDC );
  end;
}
  Result := true;
end;

// frMouseDown  = 3   .
function DocumentFrameEvent.MouseDown(nButton: Smallint; nShiftState: Smallint;
                                      x: Integer; y: Integer): WordBool;
begin
  Result := true;
end;

// frMouseUp = 4   .
function DocumentFrameEvent.MouseUp(nButton: Smallint; nShiftState: Smallint; x: Integer; y: Integer): WordBool;
begin
  Result := true;
end;

// frMouseDblClick = 5    .
function DocumentFrameEvent.MouseDblClick(nButton: Smallint; nShiftState: Smallint; x: Integer; y: Integer): WordBool;
begin
  Result := true;
end;

//-------------------------------------------------------------------------------
//  
// ---
procedure RedrawFace( var topPart: IPart; var nextPart : IPart; var fDef0 : IFaceDefinition );
var
  transform      : Boolean;
  i, j,
  pointsCount,
  trianglesCount,
  normalsCount,
  index         : Integer;
  points,
  indexes,
  normals        : OleVariant;
  tess           : ITessellation;
  x, y, z        : Double;
begin
  transform := ( topPart <> nil ) And ( topPart <> nextPart );
  if fDef0 <> nil then
  begin
    tess := ITessellation( fDef0.GetTessellation() );
    if tess <> nil then
    begin
      tess._Release();
      //     
      tess.GetFacetPoints( points, indexes );
      tess.GetFacetNormals( normals );
      if ( ( VarType( indexes ) = (VT_ARRAY Or VT_I4) )   And
           ( VarType( points  ) = (VT_ARRAY Or VT_R8) )   And
           ( VarType( normals ) = (VT_ARRAY Or VT_R8) ) ) then
      begin
        //           
        pointsCount    := ( VarArrayHighBound( points,  1 ) + 1 ) div 3;
        trianglesCount := ( VarArrayHighBound( indexes, 1 ) + 1 ) div 3;
        normalsCount   := ( VarArrayHighBound( normals, 1 ) + 1 ) div 3;
        if ( pointsCount > 0 ) And ( trianglesCount > 0 ) And ( normalsCount > 0 ) then
        begin
          //      
          j := 0;
          for i := 0 to trianglesCount -1 do
          begin
            glBegin( GL_TRIANGLES );
              index := indexes[j] * 3;
              x := points[index];
              inc( index );
              y := points[index];
              inc( index );
              z := points[index];
              if transform then
                //          
                topPart.TransformPoint( x, y, z, nextPart );
              glColor3d( 1.0, 0, 0.0 );
              glVertex3d( x, y, z );

              index := indexes[j] * 3;
              inc( j );
              x := normals[index];
              inc( index );
              y := normals[index];
              inc( index );
              z := normals[index];
              glNormal3d( x, y, z );

              index := indexes[j] * 3;
              x := points[index];
              inc( index );
              y := points[index];
              inc( index );
              z := points[index];
              if transform then
                //          
                topPart.TransformPoint( x, y, z, nextPart );
              glColor3d( 0.0, 1.0, 0 );
              glVertex3d( x, y, z );

              index := indexes[j] * 3;
              inc( j );
              x := normals[index];
              inc( index );
              y := normals[index];
              inc( index );
              z := normals[index];
              glNormal3d( x, y, z );

              index := indexes[j] * 3;
              x := points[index];
              inc( index );
              y := points[index];
              inc( index );
              z := points[index];
              if  transform then
                //          
                topPart.TransformPoint( x, y, z, nextPart );
              glColor3d( 0, 0.0, 1.0 );
              glVertex3d( x, y, z );

              index := indexes[j] * 3;
              inc( j );
              x := normals[index];
              inc( index );
              y := normals[index];
              inc( index );
              z := normals[index];
              glNormal3d( x, y, z );

            glEnd();
          end;
        end
      end
    end
  end
end;


//-------------------------------------------------------------------------------
//  
// ---
procedure RedrawFaceByEntity( var topPart: IPart; var nextPart : IPart; var face : IEntity );
var
  fDef0          : IFaceDefinition;
  pUnk           : IUnknown;
begin
  if ( face <> nil ) And ( face.IsCreated() <> 0 ) then
  begin
    pUnk := IUnknown( face.GetDefinition() );
    fDef0 := pUnk As IFaceDefinition;
    if fDef0 <> nil then
    begin
      fDef0._Release();
      RedrawFace( topPart, nextPart, fDef0 );
    end
  end
end;

//-------------------------------------------------------------------------------
//  
// ---
procedure RedrawFaces( var topPart: IPart; var nextPart : IPart; var faces : IEntityCollection );
var
  facesCount, ie : Integer;
  face           : IEntity;
begin
  facesCount := faces.GetCount();
  for ie := 0 to facesCount - 1 do
  begin
    face := IEntity( faces.GetByIndex(ie) );
    face._Release();
    RedrawFaceByEntity( topPart, nextPart, face );
  end
end;

//-------------------------------------------------------------------------------
//  
// ---
procedure RedrawFacesByFaceCollection( var topPart: IPart; var nextPart : IPart; var faces : IFaceCollection );
var
  facesCount, ie : Integer;
  face           : IFaceDefinition;
begin
  facesCount := faces.GetCount();
  for ie := 0 to facesCount - 1 do
  begin
    face := IFaceDefinition( faces.GetByIndex(ie) );
    face._Release();
    RedrawFace( topPart, nextPart, face );
  end
end;

//-------------------------------------------------------------------------------
//
// ---
procedure RedrawModelFaces( var topPart : IPart; var nextPart : IPart );
var
  faces       : IEntityCollection;
  partFeature,
  nextFeature : IFeature;
  featureColl : IFeatureCollection;
  i, count    : Integer;
  bodyColl    : IBodyCollection;
  faceColl    : IFaceCollection;
  body        : IBody;
begin
  if ( nextPart <> nil ) And ( nextPart.IsDetail()   <> 0 )
                         And ( nextPart.GetHidden()   = 0 )
                         And ( nextPart.GetExcluded() = 0 ) then
  begin
    case frameEventRedrawType of

      0 : //    
        begin
          faces := IEntityCollection( nextPart.EntityCollection(o3d_face) );
          if ( faces <> nil ) then
          begin
            faces._Release();
            RedrawFaces( topPart, nextPart, faces );
          end
        end;

      1 : //    
        begin
          partFeature := IFeature( nextPart.GetFeature() );
          if partFeature <> nil then
          begin
            //    
            featureColl := IFeatureCollection( partFeature.SubFeatureCollection( 0,  //    
                                                                                 1 ) );
            if ( featureColl <> nil ) then
            begin
              featureColl._Release;
              count := featureColl.GetCount();
              for i := 0 to count - 1 do
              begin
                nextFeature := IFeature( featureColl.GetByIndex(i) );
                nextFeature._Release;
                faces := IEntityCollection( nextFeature.EntityCollection(o3d_face) );
                if ( faces <> nil ) then
                begin
                  faces._Release;
                  RedrawFaces( topPart, nextPart, faces );
                end
              end;
            end;
          end
        end;

      2 : //      
        begin
          bodyColl := IBodyCollection( nextPart.BodyCollection() );
          if ( bodyColl <> nil ) then
          begin
            bodyColl._Release;
            count := bodyColl.GetCount();
            for i := 0 to count - 1 do
            begin
              body := IBody( bodyColl.GetByIndex(i) );
              if ( body <> nil ) then
              begin
                body._Release;
                faceColl := IFaceCollection( body.FaceCollection() );
                if ( faceColl <> nil ) then
                begin
                  faceColl._Release;
                  RedrawFacesByFaceCollection( topPart, nextPart, faceColl );
                end
              end;
            end
          end
        end;
      3 : //      
        begin
          body :=  IBody( nextPart.GetMainBody() );
          if ( body <> nil ) then
          begin
            faceColl := IFaceCollection( body.FaceCollection() );
            if ( faceColl <> nil ) then
            begin
              faceColl._Release;
              RedrawFacesByFaceCollection( topPart, nextPart, faceColl );
            end;
          end;
        end;
    end;
  end
end;


//-------------------------------------------------------------------------------
//    
// ---
procedure RecursiveDrawOnFeature( var pTopPart : IPart; var nextFeature : IFeature );
var
  unkObj, unkDef : IUnknown;
  pPart, parent  : IPart;
  featColl       : IFeatureCollection;
  entityColl     : IEntityCollection;
  entity         : IEntity;
  count, i       : Integer;
  pFace          : IFaceDefinition;
begin
  if ( pTopPart <> nil ) And ( nextFeature <> nil ) then
  begin
    unkObj := IUnknown( nextFeature.GetObject() );
    if unkObj <> nil then
      unkObj._Release;
    case nextFeature.GetType() of
      o3d_part:
      begin
        pPart :=  unkObj As IPart;
        if ( pPart <> nil ) And ( pPart.IsDetail() <> 0 ) then
          RedrawModelFaces( pTopPart, pPart )
        else
        begin
          //    
          featColl := IFeatureCollection( nextFeature.SubFeatureCollection(  0     //    
                                                                           , 1) ); //   
          if featColl <> nil then
          begin
            featColl._Release;
            RecursiveDraw( pTopPart, featColl ); //     
          end;
        end;
      end;

      o3d_entity:
      begin
        entity := unkObj As IEntity;
        if ( entity <> nil ) and ( frameEventredrawType = 1 ) then
        begin
          if ( entity.GetExcluded() = 0 ) And
             ( entity.GetHidden()   = 0 ) then
          begin
            //               
            //      
            parent := IPart( entity.GetParent() );
            if ( parent <> nil ) then
            begin
              parent._Release;
              if parent.IsDetail() = 0 then
              begin
                entityColl := IEntityCollection( nextFeature.EntityCollection(o3d_face) );
                if ( entityColl <> nil ) then
                begin
                  entityColl._Release;
                  count := entityColl.GetCount;
                  for i := 0 to count - 1 do
                  begin
                    //       
                    entity := IEntity( entityColl.GetByIndex(i) );
                    if ( entity <> nil ) then
                    begin
                      entity._Release;
                      parent := IPart( entity.GetParent() );
                      if ( parent <> nil ) then
                      begin
                        unkDef := IUnknown( entity.GetDefinition() );
                        if ( unkDef <> nil ) then
                        begin
                          unkDef._Release;
                          pFace  := unkDef As IFaceDefinition;
                          if ( pFace <> nil ) then
                          begin
                            RedrawFace( pTopPart, parent, pFace );
                          end
                        end;
                      end;
                    end;
                  end;
                end
              end;
            end
          end
        end;
        featColl := IFeatureCollection( nextFeature.SubFeatureCollection( 0, 1 ) );
        if featColl <> nil then
        begin
          featColl._Release;
          RecursiveDraw( pTopPart, featColl );
        end
      end;

      o3d_unknown:
      begin
        //    SubFeatureCollection
        featColl := IFeatureCollection( nextFeature.SubFeatureCollection( 0, 0 ) );
        if featColl <> nil then
        begin
          featColl._Release();
          RecursiveDraw( pTopPart, featColl );
        end;
      end
    end
  end
end;


//-------------------------------------------------------------------------------
//   
// ---
procedure RecursiveDraw( var pTopPart : IPart; var coll : IFeatureCollection );
var
  i, count    : integer;
  nextFeature : IFeature;
begin
  if coll <> nil then
  begin
    count := coll.GetCount();
    for i := 0 to count - 1 do
    begin
      nextFeature := IFeature( coll.GetByIndex(i) );
      if ( nextFeature <> nil ) then
      begin
        nextFeature._Release();
        if nextFeature.GetExcluded() = 0  then
          RecursiveDrawOnFeature( pTopPart, nextFeature );
      end
    end
  end
end;


// frBeginPaintGL = 6      OpenGL.
function DocumentFrameEvent.BeginPaintGL(drawMode: Integer): WordBool;
var
  doc3D       : IDocument3D;
  pTopPart    : IPart;
  partFeature : IFeature;
begin
  Result := true;
  if drawMode = vm_Shaded then
  begin
    doc3D := IDocument3D( ksGetActive3dDocument() );
    if ( doc3D <> nil ) then
    begin
      doc3D._Release;
      //   
      glPushAttrib( GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );

      glClearColor( 1.0, 1.0, 1.0, 1.0 );
      glClear( GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT );
      glDisable( GL_LIGHTING );
      glEnable( GL_DEPTH_TEST );
      pTopPart := IPart( doc3D.GetPart(pTop_Part) );
      if pTopPart <> nil then
      begin
        pTopPart._Release;
        if doc3D.IsDetail() <> 0 then
          RedrawModelFaces( pTopPart, pTopPart )            //   
        else
        begin
          partFeature := IFeature( pTopPart.GetFeature() );
          if ( partFeature <> nil ) then
          begin
            partFeature._Release;
            RecursiveDrawOnFeature( pTopPart, partFeature );
          end
        end
      end;
      doc3D := nil;
      Result:= false;
      glEnable( GL_LIGHTING );
      
      //   
      glPopAttrib();
    end;
  end
end;

// frClosePaintGL = 7      OpenGL.
function DocumentFrameEvent.ClosePaintGL(drawMode: Integer): WordBool;
begin
  Result := true;
end;

// frAddGabarit = 8   .
function DocumentFrameEvent.AddGabarit(const gabObj: IUnknown): WordBool;
  var
    gabaritObject : IGabaritObject;
    x1, y1, z1    : Double;
    x2, y2, z2    : Double;
begin
  gabaritObject := gabObj As IGabaritObject;
  Result := true;
  if gabaritObject <> nil then
  begin
    Result := gabaritObject.GetCurrentGabarit( 0,  x1, y1, z1, x2, y2, z2 );
    if Result then
    begin
      x2   := x2 + 1000;
      xMax := x2;
      Result := gabaritObject.AddGabarit( x1, y1, z1, x2, y2, z2 );
    end
  end
end;

// frActivate = 9  .
function DocumentFrameEvent.Activate: WordBool;
begin
  Result := true;
end;

// frDeactivate = 10  .
function DocumentFrameEvent.Deactivate: WordBool;
begin
  Result := true;
end;

// frCloseFrame = 11  .
function DocumentFrameEvent.CloseFrame: WordBool;
begin
  Unadvise;
  Result := true;
end;

  // frMouseMove = 12  .
function  DocumentFrameEvent.MouseMove(nShiftState: Smallint; x: Integer; y: Integer): WordBool;
begin
  Result := true;
end;

// frShowOcxTree = 13 \ 
function DocumentFrameEvent.ShowOcxTree(const tree: IUnknown; show: WordBool): WordBool; stdcall;
begin
  Result := true;
end;

function NewDocumentFrameEvent(  var frame : IDocumentFrame; doc : reference; redrawType : Integer ) : DocumentFrameEvent;
var
  unk : IUnknown;
begin
  Result := nil;
  if doc <> 0 then begin
    unk := frame As IUnknown;
		if cBaseEvent.FindEvents( ntDocumentFrameNotify, 0, -1, unk ) = nil then begin
			Result := DocumentFrameEvent.Create( frame, doc );
			if not Result.Advise() then begin
        Result.Free;
				Result := nil;
			end
		end;
    frameEventRedrawType := redrawType;
	end
end;

end.
