#include "stdafx.h"

#ifdef STRICT							// Already defined by stdafx,
#undef STRICT							// so we avoid warning linking msg
#endif
#ifdef _MBCS							// The same as above
#undef _MBCS
#endif


#include "LegMirrorPanel.h"


#pragma pack(push,8)
#include "..\\MaxControls\\IKSlaveClipObject.h"

#include <IKCTRL.h>
#include <IKCTRL.h>
#pragma pack(pop)

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

void LegMirrorPanel::DoMirror()
{
    
    
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
    HINSTANCE loc_hInstance = AfxGetResourceHandle ();
    
    PlaceZeroKeys(m_ip->GetRootNode());
    MirrorAnimation(m_ip->GetRootNode());
    SwapExpressions(m_ip->GetRootNode());
    
    m_ip->ForceCompleteRedraw();
    
}


void LegMirrorPanel::MirrorExpControl(ExprControl *expc)
{
    int i,slot;
    TSTR nname;
    INode *nde,*tnde;
    Control *cpt;
    
    for(i=0;i<expc->getVarCount(VECTOR_EXPR);i++)
    {
        slot=expc->vVars[i].refID;
        expc->refTab[slot].client->NotifyDependents(FOREVER,(PartID)&nname,REFMSG_GET_NODE_NAME);
        
        
        nde=m_ip->GetINodeByName(nname);
        tnde=FindCorespondingNode(nde);
        
        if(tnde!=NULL)
        {
            int sanim;
            CString conname(expc->refTab[slot].client->SubAnimName(expc->vVars[i].subNum));	
            cpt=GetControlByName(tnde->GetTMController(),conname,&sanim);
            ASSERT(cpt);
            expc->assignController(VECTOR_EXPR,i,cpt,sanim);
        }
        
    }	
    
    for(i=0;i<expc->getVarCount(SCALAR_VAR);i++)
    {
        slot=expc->sVars[i].refID;
        expc->refTab[slot].client->NotifyDependents(FOREVER,(PartID)&nname,REFMSG_GET_NODE_NAME);
        
        nde=m_ip->GetINodeByName(nname);
        tnde=FindCorespondingNode(nde);
        if(tnde!=NULL)
        {
            int sanim;
            CString conname(expc->refTab[slot].client->SubAnimName(expc->sVars[i].subNum));	
            cpt=GetControlByName(tnde->GetTMController(),conname,&sanim);
            ASSERT(cpt);
            expc->assignController(SCALAR_EXPR,i,cpt,sanim);
        }
        
    }
    
}

void LegMirrorPanel::SwapAnimations(INode *nde1,INode *nde2)
{
    
    Control *tcon;
    
    
    ExpControlDep d1,d2;
    //	INode *tnd;
    /*	
    GetExpDeps(nde1,&d1);
    GetExpDeps(nde2,&d2);
    
      for(int i=0;i<6;i++)
      {
      if(d1.ndes[i]) 
      {   
      tnd=FindCorespondingNode(d1.ndes[i]);
      if(tnd) d1.ndes[i]=tnd;
      }
      
        if(d2.ndes[i]) 
        {   
        tnd=FindCorespondingNode(d2.ndes[i]);
        if(tnd) d2.ndes[i]=tnd;
        }
        
          }
          
    */
    
    tcon=(Control *)nde1->GetTMController()->Clone();
    nde1->SetTMController(nde2->GetTMController());
    nde2->SetTMController(tcon);
    /*
    AssignExpressions(nde2,&d1);
    AssignExpressions(nde1,&d2);
    */
}

void LegMirrorPanel::SwapProperties(INode *nde1,INode *nde2)
{
    
    IKClipObject *cobj;
    IKSlaveClipObject *jtmp;
    
    
    cobj=nde1->GetTMController()->CopyIKParams(COPYPASTE_IKROT);
    
    if(cobj && cobj->ClassID()==IKSLAVE_CLASSID)
    {
        
        float mins[6],maxs[6];
        
        jtmp=(IKSlaveClipObject *)cobj;
        
        mins[4]=jtmp->min[4];
        maxs[4]=jtmp->max[4];
        mins[5]=jtmp->min[5];
        maxs[5]=jtmp->max[5];
        
        
        cobj=nde2->GetTMController()->CopyIKParams(COPYPASTE_IKROT);
        jtmp=(IKSlaveClipObject *)cobj;
        
        jtmp->min[4]=-jtmp->min[4];
        jtmp->max[4]=-jtmp->max[4];
        jtmp->min[5]=-jtmp->min[5];
        jtmp->max[5]=-jtmp->max[5];
        
        
        nde1->GetTMController()->PasteIKParams(cobj,COPYPASTE_IKROT);
        
        
        
        jtmp->min[4]=-mins[4];
        jtmp->max[4]=-maxs[4];
        jtmp->min[5]=-mins[5];
        jtmp->max[5]=-maxs[5];
        
        
        nde2->GetTMController()->PasteIKParams(cobj,COPYPASTE_IKROT);
        
    }
    
    
}

void LegMirrorPanel::SwapRotations(INode *nde1,INode *nde2)
{
    
    Control *tcon;
    
    ExpControlDep d1,d2;
    //	INode *tnd;
    /*	
    GetExpDeps(nde1,&d1);
    GetExpDeps(nde2,&d2);
    
      for(int i=0;i<6;i++)
      {
      if(d1.ndes[i]) 
      {   
      tnd=FindCorespondingNode(d1.ndes[i]);
      if(tnd) d1.ndes[i]=tnd;
      }
      
        if(d2.ndes[i]) 
        {   
        tnd=FindCorespondingNode(d2.ndes[i]);
        if(tnd) d2.ndes[i]=tnd;
        }
        
          }
    */	
    if(!nde1->GetTMController()->GetRotationController()) return;
    tcon=(Control *)nde1->GetTMController()->GetRotationController()->Clone();
    
    nde1->GetTMController()->SetRotationController(nde2->GetTMController()->GetRotationController());
    nde2->GetTMController()->SetRotationController(tcon);
    /*	
    AssignExpressions(nde2,&d1);
    AssignExpressions(nde1,&d2);
    */
}

void LegMirrorPanel::MirrorNode(INode *nde)
{
    CString str(nde->GetName());
    
    if( IsJoint(str) || IsHandle(str) )
    {   
        Control *tm_con,*pos_con,*rot_con,*xp_con,*yp_con,*zp_con,*xr_con,*yr_con,*zr_con;
        IKeyControl *ikc;
        
        tm_con = nde->GetTMController();
        if(tm_con!=NULL)
        {
            pos_con = tm_con->GetPositionController();
            rot_con = tm_con->GetRotationController();
            
            if(rot_con)
            {
                ikc = GetKeyControlInterface(rot_con);
                if(ikc)
                {
                    NegateKey(ikc,rot_con->ClassID());
                }
                
                xr_con=rot_con->GetXController();
                if(xr_con!=NULL)
                {
                }
                
                yr_con=rot_con->GetYController();
                if(yr_con!=NULL)
                {
                    ikc = GetKeyControlInterface(yr_con);
                    if(ikc)
                    {
                        NegateKey(ikc,yr_con->ClassID());
                    }
                    
                }
                
                zr_con=rot_con->GetZController();
                if(zr_con!=NULL)
                {
                    ikc = GetKeyControlInterface(zr_con);
                    if(ikc)
                    {
                        NegateKey(ikc,zr_con->ClassID());
                    }
                    
                }
            }
            
            
            if( !IsJoint(str) || ( IsJoint(str) && TellSide(nde)==ISNEITHER ) )
                if(pos_con)
                {
                    ikc = GetKeyControlInterface(pos_con);
                    if(ikc)
                    {
                        NegateKey(ikc,pos_con->ClassID());
                    }
                    
                    xp_con=pos_con->GetXController();
                    if(xp_con!=NULL)
                    {
                        ikc = GetKeyControlInterface(xp_con);
                        if(ikc)
                        {
                            NegateKey(ikc,xp_con->ClassID());
                        }
                    }
                    
                    yp_con=pos_con->GetYController();
                    if(yp_con!=NULL)
                    {
                    }
                    
                    zp_con=pos_con->GetZController();
                    if(zp_con!=NULL)
                    {
                    }
                }
                
        }
    }			  					  
}

void LegMirrorPanel::MirrorAnimation(INode *nde)
{
    LRFLAG flg;
    flg=TellSide(nde);
    CString str(nde->GetName());
    
    if(flg==ISLEFT) //only swap lefts to avoid double swaps
    {
        INode *tnde;
        
        tnde=FindCorespondingNode(nde);
        if(tnde!=NULL)
        {
            if(!str.Left(8).CompareNoCase("HANDLE_L") )
            {
                if(IsReversable(tnde))				//if the corespondant really exists and can be reversed
                {
                    MirrorNode(tnde);
                    MirrorNode(nde);
                    SwapAnimations(tnde,nde);
                }
            }
            else
                if(IsJoint(str))
                {
                    MirrorNode(tnde);
                    MirrorNode(nde);
                    SwapRotations(tnde,nde);
                    if(!str.CompareNoCase("joint_luleg") ) SwapProperties(tnde,nde);
                }
        }
    }
    else							//if it has no correspondant just mirror it
        if(flg==ISNEITHER) //only swap lefts to avoid double swaps
            if(IsReversable(nde))			
            {
                MirrorNode(nde);
            }
            
            for(int i=0;i<nde->NumberOfChildren();i++)
            {
                MirrorAnimation(nde->GetChildNode(i));
            }
}

void LegMirrorPanel::SwapExpressions(INode *nde)
{
    
    for(int i=0;i<nde->NumberOfChildren();i++)
    {
        SwapExpressions(nde->GetChildNode(i));
    }
    
    CString str(nde->GetName());
    
    
    if(TellSide(nde)==ISNEITHER) return;
    
    
    Control *tm_con,*pos_con,*rot_con,*xp_con,*yp_con,*zp_con,*xr_con,*yr_con,*zr_con;
    
    tm_con = nde->GetTMController();
    if(tm_con!=NULL)
    {
        pos_con = tm_con->GetPositionController();
        rot_con = tm_con->GetRotationController();
        
        if(rot_con)
        {
            if(!GetKeyControlInterface(rot_con) 
                && IsExprControl(rot_con)&& 
                HasCircularReference(nde,(ExprControl *)rot_con))
            {
                MirrorExpControl((ExprControl *)rot_con);
            }
            
            
            xr_con=rot_con->GetXController();
            if(xr_con!=NULL)
            {
                if(!GetKeyControlInterface(xr_con) &&
                    IsExprControl(xr_con) && 
                    HasCircularReference(nde,(ExprControl *)xr_con))
                {
                    MirrorExpControl((ExprControl *)xr_con);
                }
            }
            
            yr_con=rot_con->GetYController();
            if(yr_con!=NULL)
            {
                if(!GetKeyControlInterface(yr_con) 
                    && IsExprControl(yr_con)&& 
                    HasCircularReference(nde,(ExprControl *)yr_con))
                {
                    MirrorExpControl((ExprControl *)yr_con);
                }
            }
            
            zr_con=rot_con->GetZController();
            if(zr_con!=NULL)
            {
                if(!GetKeyControlInterface(zr_con) 
                    && IsExprControl(zr_con)&& 
                    HasCircularReference(nde,(ExprControl *)zr_con))
                {
                    MirrorExpControl((ExprControl *)zr_con);
                }
            }
        }
        
        
        if(!IsJoint(str))
            if(pos_con)
            {
                if(!GetKeyControlInterface(pos_con)  
                    && IsExprControl(pos_con)&& 
                    HasCircularReference(nde,(ExprControl *)pos_con))
                {
                    MirrorExpControl((ExprControl *)pos_con);
                }
                
                xp_con=pos_con->GetXController();
                if(xp_con!=NULL)
                {
                    if(!GetKeyControlInterface(xp_con)  
                        && IsExprControl(xp_con)&& 
                        HasCircularReference(nde,(ExprControl *)xp_con))
                    {
                        MirrorExpControl((ExprControl *)xp_con);
                    }
                }
                
                yp_con=pos_con->GetYController();
                if(yp_con!=NULL)
                {
                    if(!GetKeyControlInterface(yp_con)  
                        && IsExprControl(yp_con)&& 
                        HasCircularReference(nde,(ExprControl *)yp_con))
                    {
                        MirrorExpControl((ExprControl *)yp_con);
                    }
                }
                
                zp_con=pos_con->GetZController();
                if(zp_con!=NULL)
                {
                    if(!GetKeyControlInterface(zp_con)  
                        && IsExprControl(zp_con)&& 
                        HasCircularReference(nde,(ExprControl *)zp_con))
                    {
                        MirrorExpControl((ExprControl *)zp_con);
                    }
                }
                
            }
            
    }
    
}

int LegMirrorPanel::NegateKey(IKeyControl *ikc,Class_ID id)
{
    int key_number,MaxKeys;
    MaxKeys=ikc->GetNumKeys();
    
    for(key_number=0;key_number<MaxKeys;key_number++)
    {
        if (id == Class_ID(LININTERP_FLOAT_CLASS_ID,0))
        {
            ILinFloatKey key;
            ikc->GetKey(key_number, &key);
            key.val=key.val*-1;
            ikc->SetKey(key_number, &key);
        }
        else if (id == Class_ID(HYBRIDINTERP_FLOAT_CLASS_ID,0))
        {
            IBezFloatKey key;
            ikc->GetKey(key_number, &key);
            key.val*=-1;
            key.intan*=-1;
            key.outtan*=-1;
            ikc->SetKey(key_number, &key);
        }
        else if (id == Class_ID(TCBINTERP_FLOAT_CLASS_ID,0))
        {	
            ITCBFloatKey key;
            ikc->GetKey(key_number, &key);
            key.val*=-1;
            ikc->SetKey(key_number, &key);
        }	
        else if (id == Class_ID(LININTERP_POSITION_CLASS_ID,0))
        {
            ILinPoint3Key key;
            ikc->GetKey(key_number, &key);
            key.val.x*=-1;
            key.val.y*=-1;
            key.val.z*=-1;
            ikc->SetKey(key_number, &key);
        }
        else if (id == Class_ID(HYBRIDINTERP_POSITION_CLASS_ID,0))
        {
            IBezPoint3Key key;
            ikc->GetKey(key_number, &key);
            key.val.x*=-1;
            key.intan.x*=-1;
            key.outtan.x*=-1;
            key.val.y*=-1;
            key.intan.y*=-1;
            key.outtan.y*=-1;
            key.val.z*=-1;
            key.intan.z*=-1;
            key.outtan.z*=-1;
            ikc->SetKey(key_number, &key);
        }
        else if (id == Class_ID(TCBINTERP_POSITION_CLASS_ID,0))
        {
            ITCBPoint3Key key;
            ikc->GetKey(key_number, &key);
            key.val.x*=-1;
            key.val.y*=-1;
            key.val.z*=-1;
            ikc->SetKey(key_number, &key);
        }
        else if (id == Class_ID(LININTERP_ROTATION_CLASS_ID,0))
        {
            ILinRotKey key;
            ikc->GetKey(key_number, &key);
            key.val.w*=-1;
            ikc->SetKey(key_number, &key);
        }
        else if (id == Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID,0))
        {
            IBezQuatKey key;
            ikc->GetKey(key_number, &key);
            key.val.w*=-1;
            ikc->SetKey(key_number, &key);
        }
        else if (id == Class_ID(TCBINTERP_ROTATION_CLASS_ID,0))
        {
            ITCBRotKey key;
            ikc->GetKey(key_number, &key);
            key.val.angle*=-1;
            ikc->SetKey(key_number, &key);
        }
        else if (id == Class_ID(HYBRIDINTERP_POINT3_CLASS_ID,0))
        {
            IBezPoint3Key key;
            ikc->GetKey(key_number, &key);
            key.val.x*=-1;
            key.val.y*=-1;
            key.val.z*=-1;
            ikc->SetKey(key_number, &key);
        }
        else if (id == Class_ID(TCBINTERP_POINT3_CLASS_ID,0))
        {
            ITCBPoint3Key key;
            ikc->GetKey(key_number, &key);
            key.val.x*=-1;
            key.val.y*=-1;
            key.val.z*=-1;
            ikc->SetKey(key_number, &key);
        }
    }			// end of for i				
    
    return MaxKeys;
}

void LegMirrorPanel::GetExpDeps(INode *nde,ExpControlDep *dep)
{
    
    Control *tm_con,*pos_con,*rot_con,*xp_con,*yp_con,*zp_con,*xr_con,*yr_con,*zr_con;
    dep->Clear();
    
    tm_con = nde->GetTMController();
    if(tm_con!=NULL)
    {
        pos_con = tm_con->GetPositionController();
        rot_con = tm_con->GetRotationController();
        
        if(rot_con)
        {
            if(!GetKeyControlInterface(rot_con) &&
                IsExprControl(rot_con) )
            {
                dep->ndes[0]=GetDepNode((ExprControl *)rot_con);
            }
            
            xr_con=rot_con->GetXController();
            if(xr_con!=NULL)
            {
                if(!GetKeyControlInterface(xr_con) &&
                    IsExprControl(xr_con) )
                {
                    dep->ndes[0]=GetDepNode((ExprControl *)xr_con);
                }
            }
            
            yr_con=rot_con->GetYController();
            if(yr_con!=NULL)
            {
                if(!GetKeyControlInterface(yr_con) 
                    && IsExprControl(yr_con))
                {
                    dep->ndes[1]=GetDepNode((ExprControl *)yr_con);
                }
            }
            
            zr_con=rot_con->GetZController();
            if(zr_con!=NULL)
            {
                if(!GetKeyControlInterface(zr_con) 
                    && IsExprControl(zr_con))
                {
                    dep->ndes[2]=GetDepNode((ExprControl *)zr_con);
                }
            }
        }
        
        
        if(pos_con)
        {
            if(!GetKeyControlInterface(pos_con)  
                && IsExprControl(pos_con))
            {
                dep->ndes[3]=GetDepNode((ExprControl *)pos_con);
            }
            
            xp_con=pos_con->GetXController();
            if(xp_con!=NULL)
            {
                if(!GetKeyControlInterface(xp_con)  
                    && IsExprControl(xp_con))
                {
                    dep->ndes[3]=GetDepNode((ExprControl *)xp_con);
                }
            }
            
            yp_con=pos_con->GetYController();
            if(yp_con!=NULL)
            {
                if(!GetKeyControlInterface(yp_con)  
                    && IsExprControl(yp_con))
                {
                    dep->ndes[4]=GetDepNode((ExprControl *)yp_con);
                }
            }
            
            zp_con=pos_con->GetZController();
            if(zp_con!=NULL)
            {
                if(!GetKeyControlInterface(zp_con)  
                    && IsExprControl(zp_con))
                {
                    dep->ndes[5]=GetDepNode((ExprControl *)zp_con);
                }
            }
        }
        
    }
    
}

INode *LegMirrorPanel::GetDepNode(ExprControl *expc)
{
    int i,slot;
    TSTR nname;
    
    for(i=0;i<expc->getVarCount(VECTOR_EXPR);i++)
    {
        slot=expc->vVars[i].refID;
        expc->refTab[slot].client->NotifyDependents(FOREVER,(PartID)&nname,REFMSG_GET_NODE_NAME);
        return m_ip->GetINodeByName(nname);
    }	
    
    for(i=0;i<expc->getVarCount(SCALAR_VAR);i++)
    {
        slot=expc->sVars[i].refID;
        expc->refTab[slot].client->NotifyDependents(FOREVER,(PartID)&nname,REFMSG_GET_NODE_NAME);
        return m_ip->GetINodeByName(nname);
    }
    
    return NULL;
}

void LegMirrorPanel::AssignExpressions(INode *nde,ExpControlDep *dep)
{
    
    Control *tm_con,*pos_con,*rot_con,*xp_con,*yp_con,*zp_con,*xr_con,*yr_con,*zr_con;
    
    tm_con = nde->GetTMController();
    if(tm_con!=NULL)
    {
        pos_con = tm_con->GetPositionController();
        rot_con = tm_con->GetRotationController();
        
        if(rot_con)
        {
            if(!GetKeyControlInterface(rot_con) &&
                IsExprControl(rot_con) )
            {
                AssignExpCtrl((ExprControl *)rot_con,dep->ndes[0]);
            }
            
            xr_con=rot_con->GetXController();
            if(xr_con!=NULL)
            {
                if(!GetKeyControlInterface(xr_con) &&
                    IsExprControl(xr_con) )
                {
                    AssignExpCtrl((ExprControl *)xr_con,dep->ndes[0]);
                }
            }
            
            yr_con=rot_con->GetYController();
            if(yr_con!=NULL)
            {
                if(!GetKeyControlInterface(yr_con) 
                    && IsExprControl(yr_con))
                {
                    AssignExpCtrl((ExprControl *)yr_con,dep->ndes[1]);
                }
            }
            
            zr_con=rot_con->GetZController();
            if(zr_con!=NULL)
            {
                if(!GetKeyControlInterface(zr_con) 
                    && IsExprControl(zr_con))
                {
                    AssignExpCtrl((ExprControl *)zr_con,dep->ndes[2]);
                }
            }
        }
        
        
        if(pos_con)
        {
            if(!GetKeyControlInterface(pos_con)  
                && IsExprControl(pos_con))
            {
                AssignExpCtrl((ExprControl *)pos_con,dep->ndes[3]);
            }
            
            xp_con=pos_con->GetXController();
            if(xp_con!=NULL)
            {
                if(!GetKeyControlInterface(xp_con)  
                    && IsExprControl(xp_con))
                {
                    AssignExpCtrl((ExprControl *)xp_con,dep->ndes[3]);
                }
            }
            
            yp_con=pos_con->GetYController();
            if(yp_con!=NULL)
            {
                if(!GetKeyControlInterface(yp_con)  
                    && IsExprControl(yp_con))
                {
                    AssignExpCtrl((ExprControl *)yp_con,dep->ndes[4]);
                }
            }
            
            zp_con=pos_con->GetZController();
            if(zp_con!=NULL)
            {
                if(!GetKeyControlInterface(zp_con)  
                    && IsExprControl(zp_con))
                {
                    AssignExpCtrl((ExprControl *)zp_con,dep->ndes[5]);
                }
            }
        }
        
    }
    
}

void LegMirrorPanel::AssignExpCtrl(ExprControl *expc,INode *tnde)
{
    
    
    int i,slot;
    int sanim;
    TSTR nname;
    Control *cpt;
    CString str(tnde->GetName());    //debug
    
    for(i=0;i<expc->getVarCount(VECTOR_EXPR);i++)
    {
        slot=expc->vVars[i].refID;
        CString conname(expc->refTab[slot].client->SubAnimName(expc->vVars[i].subNum));	
        cpt=GetControlByName(tnde->GetTMController(),conname,&sanim);
        ASSERT(cpt);
        expc->assignController(VECTOR_EXPR,i,cpt,sanim);
    }	
    
    for(i=0;i<expc->getVarCount(SCALAR_VAR);i++)
    {
        slot=expc->sVars[i].refID;
        CString conname(expc->refTab[slot].client->SubAnimName(expc->sVars[i].subNum));	
        cpt=GetControlByName(tnde->GetTMController(),conname,&sanim);
        ASSERT(cpt);
        expc->assignController(SCALAR_EXPR,i,cpt,sanim);
    }
    
    
}