TOOLS.C

Go to the documentation of this file.
00001 /* file  WTOOLS.C   Animator tools for Windows */
00002 
00003 #define MODULE_TOOLS 1
00004 
00005 #include "animate.h"
00006 
00007 static short PanTo(long *, long *, long);
00008 static void get_stage_actor_position(node *Np, long *x, long *y, long *z,
00009     long *xx, long *yy, long *zz);
00010 static void get_stage_actor_rotation(node *Np, double *theta,
00011        double *phi, double *alpha);
00012 static void get_stage_actor_expansion(node *Np, double *sx,
00013        double *sy, double *sz);
00014 
00015 static double lpa,lpp,lpt;
00016 static long lpx,lpy,lpz,lpxx,lpyy,lpzz;
00017 
00018 long GrabonX,GrabonY,GrabonZ,GrabDx,GrabDy,GrabDz;
00019 
00020 void ExecuteActorsMenu(HWND hWnd){
00021   long idata[12]={IDBM_MENU1_MO,
00022                   IDBM_MENU1_MF,
00023                   IDBM_MENU1_CA,
00024                   IDBM_MENU1_TA,
00025                   IDBM_MENU1_LI,
00026                   IDBM_MENU1_PA,
00027                   IDBM_MENU1_SK,
00028                   IDBM_MENU1_GR,
00029                   IDBM_MENU1_RO,
00030                   IDBM_MENU1_CS,
00031                   IDBM_MENU1_XI,
00032                   IDBM_MENU1_DR};
00033   long icommand[12]={
00034     IDM_ACTOR_QADD_MOD,
00035     IDM_ACTOR_QADD_MORPH,
00036     IDM_ACTOR_QADD_CAMERA,
00037     IDM_ACTOR_QADD_TARGET,
00038     IDM_ACTOR_QADD_LIGHT,
00039     IDM_ACTOR_QADD_PATH,
00040     IDM_ACTOR_QADD_SKY,
00041     IDM_ACTOR_QADD_GROUND,
00042     IDM_ACTOR_QADD_ROBOT,
00043     IDM_ACTOR_QADD_CSG,
00044     IDM_ACTOR_QADD_XIP,
00045     IDM_ACTOR_QADD_DIRECTOR};
00046   int i;
00047   POINT pt;
00048   HMENU hMenu=CreatePopupMenu();
00049   HBITMAP hBitmap[12];
00050   RECT rc;
00051   UINT align=TPM_LEFTALIGN;
00052   GetWindowRect(GetDlgItem(ghwndTools,7),&rc);
00053   if(bToolpannelLeft){pt.x=rc.right; align=TPM_LEFTALIGN; }
00054   else               {pt.x=rc.left;  align=TPM_RIGHTALIGN;}
00055   pt.y=rc.top; //  GetCursorPos(&pt);
00056   for(i=0;i<12;i++){
00057     hBitmap[i]=LoadBitmap(ghinst_main,MAKEINTRESOURCE(idata[i]));
00058     AppendMenu(hMenu,MF_ENABLED|MF_BITMAP,icommand[i],(LPCSTR)hBitmap[i]);
00059     if(i == 1 || i == 5 || i == 9)
00060       AppendMenu(hMenu,MF_SEPARATOR,0,NULL);
00061   }
00062   TrackPopupMenu(hMenu,align | TPM_LEFTBUTTON,
00063                         pt.x,pt.y,0,hWnd,NULL);
00064   DestroyMenu(hMenu);
00065   for(i=0;i<12;i++){
00066     if(hBitmap[i] != NULL)DeleteObject(hBitmap);
00067   }
00068   InvalidateRect(ghwndTools,NULL,FALSE);
00069 }
00070 
00071 void EngageTool(int newtool){
00072  int oldtool;
00073  oldtool=tool;
00074  if(tool != NOTOOL){
00075     DisengageTool();
00076  }
00077  TOOLCHANGED:
00078  if(newtool == NODETOOL){
00079    if(SelectedNode != NULL){
00080      if(SelectedNode->type == PATH){
00081        newtool=PATHEDITOR; goto TOOLCHANGED;
00082      }
00083      else if(SelectedNode->type == ROBOT){
00084        newtool=SKELETOR; goto TOOLCHANGED;
00085      }
00086    }
00087    if(tool == NOTOOL){
00088      tool=NODETOOL;
00089      SendPrgmMessage(IDS_NODESELECTOR1,1);
00090    }
00091  }
00092  else if(newtool == GRABBER){
00093    Save_UndoA();
00094    SendPrgmMessage(IDS_GRABBERTOOL,1);
00095    StageGrabOn();
00096    AugmentToolPannel(TRUE);
00097  }
00098  else if(newtool == ROTATOR){
00099    Save_UndoA();
00100    SendPrgmMessage(IDS_ROTATORTOOL,1);
00101    StageRotateOn();
00102    AugmentToolPannel(TRUE);
00103  }
00104  else if(newtool == SIZER){
00105    Save_UndoA();
00106    SendPrgmMessage(IDS_SIZERTOOL,1);
00107    StageSizeOn();
00108    AugmentToolPannel(TRUE);
00109  }
00110  else if(newtool == TRACKER){
00111    Save_UndoA();
00112    SendPrgmMessage(IDS_TRACKER,1);
00113    ShifterOn();
00114    if(tool == TRACKER)SetCursor(ghcurTracker);
00115  }
00116  else if(newtool == PATHEDITOR){
00117    Save_UndoA();
00118    SendPrgmMessage(IDS_PATHEDITORTOOL,1);
00119    EditPathOn();
00120    if(tool == PATHEDITOR)SetCursor(ghcurPathed);
00121  }
00122  else if(newtool == SKELETOR){
00123    Save_UndoA();
00124    SendPrgmMessage(IDS_SKELETORTOOL,1);
00125    SkeletorOn();
00126    if(tool == SKELETOR)SetCursor(ghcurSkeletor);
00127  }
00128  else if(newtool == PAN){
00129    SendPrgmMessage(IDS_PANTOOL,1);
00130    tool=newtool;
00131  }
00132  else if(newtool == INZOOM){
00133    SendPrgmMessage(IDS_INZOOMTOOL,1);
00134    tool=newtool;
00135  }
00136  if(newtool >= NTOOLS)newtool=NODETOOL;
00137  else if(tool != NOTOOL)SetCursor(ghcurTools[newtool]);
00138  InvalidateRect(ghwndTools,NULL,FALSE);
00139 }
00140 
00141 void DisengageTool(void){
00142  int otool;
00143  otool=tool;
00144  if(tool == GRABBER || tool == ROTATOR ||     // To switch out of internal
00145     tool == SIZER)AugmentToolPannel(FALSE);   // undo
00146  if     (tool == GRABBER)StageGrabOff(1);
00147  else if(tool == ROTATOR)RotateOff(1);
00148  else if(tool == SIZER)SizeOff(1);
00149  else if(tool == PAN || tool == INZOOM)tool=NOTOOL;
00150  else if(tool == TRACKER && subtool == SHIFTER)ShifterOff(1);
00151  else if(tool == TRACKER && subtool == ANGLER)AnglerOff(1);
00152  else if(tool == PATHEDITOR)EditPathOff(1);
00153  else if(tool == SKELETOR)SkeletorOff(1);
00154  else if(tool == NODETOOL)tool=NOTOOL;
00155  if(otool >= NTOOLS)otool=NODETOOL;
00156  InvalidateRect(ghwndTools,NULL,FALSE);
00157  SendPrgmMessage(IDS_SELECTTOOL,1);
00158  SetCursor(ghcurArrow);
00159 }
00160 
00161 object *PickNode(short type1, short type2){
00162  node *Np;
00163  object *Op;
00164  point  p,tp;
00165  short im,hx,vy;
00166  double dmin,phi,theta,alpha,sx,sy,sz,ima;
00167  Op=NULL;
00168  if((Np=FirstNp) == NULL)return NULL;
00169  else if(tool == PATHEDITOR && type1 != PATH){
00170     SendPrgmQuery(IDQ_INPATH,0);
00171     return NULL;
00172  }
00173  else if(tool == TRACKER && subtool == SHIFTER){
00174     SendPrgmQuery(IDQ_INSHIFTER,0);
00175     return NULL;
00176  }
00177  else if(tool == TRACKER && subtool == ANGLER){
00178     SendPrgmQuery(IDQ_INANGLER,0);
00179     return NULL;
00180  }
00181  if(SelectedNode == NULL)while(Np != NULL){
00182    if((Op=Np->fobj) != NULL)while(Op != NULL){
00183      if( CurrentFrame >= Op->firstframe && CurrentFrame <= Op->lastframe
00184          && (type1 == Op->type || type2 == Op->type))goto GOTIT;
00185      Op=Op->next;
00186    }
00187    Np=Np->next;
00188  }
00189  else{
00190   if((Np=SelectedNode->next) == NULL)Np=FirstNp;
00191   while(Np != SelectedNode){
00192     if((Op=Np->fobj) != NULL)while(Op != NULL){
00193       if( CurrentFrame >= Op->firstframe && CurrentFrame <= Op->lastframe
00194           && (type1 == Op->type || type2 == Op->type))goto GOTIT;
00195       Op=Op->next;
00196     }
00197     Np=Np->next;
00198     if(Np == NULL)Np=FirstNp;
00199   }
00200  }
00201  return NULL;
00202 GOTIT:
00203  if(Op != NULL && !(GetAsyncKeyState(VK_CONTROL) & 0x80000)){/* ctrl -  don't ON */
00204    GetTransform(0,CurrentFrame,1.0,
00205                 Np,Op,p,tp,&phi,&theta,&alpha,&sx,&sy,&sz,&im,&ima);
00206    if( ! in_stage_triview(p)){
00207      TVpointX = p[0]-TVsizeX/2;
00208      TVpointY = p[1]-TVsizeY/2;
00209      TVpointZ = p[2]-TVsizeZ/2;
00210    }
00211    GrabonX=NpointerX=p[0]; GrabDx=0;
00212    GrabonY=NpointerY=p[1]; GrabDy=0;
00213    GrabonZ=NpointerZ=p[2]; GrabDz=0;
00214    UpdateRuler(0);
00215  }
00216  SelectedNode=Np;
00217  if(tool == GRABBER)get_stage_actor_position(SelectedNode,
00218                     &lpx,&lpy,&lpz,&lpxx,&lpyy,&lpzz);
00219  if(tool == ROTATOR)get_stage_actor_rotation(SelectedNode,
00220                     &lpt,&lpp,&lpa);
00221  if(tool == SIZER)get_stage_actor_expansion(SelectedNode,
00222                     &lpt,&lpp,&lpa);
00223  if(tool == PATHEDITOR){
00224   SelectedPath=NULL; SelectedPathPoint=NULL;
00225  }
00226  UpdateSelectedActor(TRUE);
00227  if(tool == NODETOOL){
00228    EngageTool(NODETOOL);
00229    if(tool == NODETOOL)ReDrawStageDisplay(TRUE);
00230  }
00231  else
00232    ReDrawStageDisplay(TRUE);
00233  return Op;
00234 }
00235 
00236 int CheckClosestObject(int w,double *dmin,point vp,int hx,int vy,int r){
00237  int sho,svo;
00238  double d;
00239  GetWindowCoords(w,vp[0],vp[1],vp[2],&sho,&svo);
00240  if( (sho > hx-r) && (sho < hx+r)
00241   && (svo > vy-r) && (svo < vy+r)){
00242    d=(double)(vp[0]-NpointerX)*(double)(vp[0]-NpointerX)
00243     +(double)(vp[1]-NpointerY)*(double)(vp[1]-NpointerY)
00244     +(double)(vp[2]-NpointerZ)*(double)(vp[2]-NpointerZ);
00245    if(d < *dmin){
00246      *dmin=d;
00247      return 1;
00248    }
00249  }
00250  return 0;
00251 }
00252 
00253 BOOL PickClosestNode(int wid, int hx, int vy, BOOL pick_only){
00254  node *Np,*node_found=NULL;
00255  pathpoint *Pp;
00256  object *Op;
00257  point  ObjectOffset,vp,tp;
00258  short im;
00259  double dmin,dmin1,phi,theta,alpha,sx,sy,sz,ima;
00260  int type;
00261  dmin=(double)TVsizeX*(double)TVsizeX*(double)TVsizeZ;
00262  if((Np=FirstNp) == NULL)return FALSE;
00263  while(Np != NULL){
00264    if((Op=Np->fobj) != NULL)while(Op != NULL){
00265      if( CurrentFrame >= Op->firstframe && CurrentFrame <= Op->lastframe){
00266        GetTransform(0,CurrentFrame,1.0,
00267                     Np,Op,ObjectOffset,tp,&phi,&theta,&alpha,
00268                     &sx,&sy,&sz,&im,&ima);
00269        if(Op->type == PATH){
00270          Pp=Op->firstpathpoint; while(Pp != NULL){
00271            AddPoints(Pp->p,ObjectOffset,vp);
00272            dmin1=dmin;
00273            if(CheckClosestObject(wid,&dmin,vp,hx,vy,5) == 1){
00274              node_found=Np;
00275              if(node_found == SelectedNode)dmin=dmin1;
00276              break;
00277            }
00278            Pp=Pp->next;
00279          }
00280        }
00281        else if(Op->type == CAMERA){
00282          CopyPoint(ObjectOffset,vp);
00283          dmin1=dmin;
00284          if(CheckClosestObject(wid,&dmin,vp,hx,vy+8,12) == 1){
00285            node_found=Np;
00286            if(node_found == SelectedNode)dmin=dmin1;
00287          }
00288        }
00289        else if(Op->type == LIGHT){
00290          CopyPoint(ObjectOffset,vp);
00291          dmin1=dmin;
00292          if(CheckClosestObject(wid,&dmin,vp,hx-2,vy+8,10) == 1){
00293            node_found=Np;
00294            if(node_found == SelectedNode)dmin=dmin1;
00295          }
00296        }
00297        else if(Op->type == NORMAL || Op->type == ANIMOBJ){
00298          if(DrawStatus == 0 || Op->quick_only == 1)type=0;
00299          else if(DrawStatus == 3 || (DrawStatus == 2 && Np != SelectedNode)
00300                  || (DrawStatus == 1 && Np == SelectedNode))type=1;
00301          else type=0;
00302          dmin1=dmin;
00303          if(CheckBoundingObject(type,wid,hx,vy,Op,ObjectOffset,
00304             phi,theta,alpha,im,ima,sx,sy,sz,&dmin) == 1){
00305            node_found=Np;
00306            if(node_found == SelectedNode)dmin=dmin1;
00307          }
00308        }
00309        else if(Op->type == PARTICLE){
00310          dmin1=dmin;
00311          if(CheckBoundingObject(0,wid,hx,vy,Op,ObjectOffset,
00312             phi,theta,alpha,im,ima,sx,sy,sz,&dmin) == 1){
00313            node_found=Np;
00314            if(node_found == SelectedNode)dmin=dmin1;
00315          }
00316        }
00317        else{
00318          CopyPoint(ObjectOffset,vp);
00319          dmin1=dmin;
00320          if(CheckClosestObject(wid,&dmin,vp,hx,vy,5) == 1){
00321            node_found=Np;
00322            if(node_found == SelectedNode)dmin=dmin1;
00323          }
00324        }
00325      }
00326      Op=Op->next;
00327    }
00328    Np=Np->next;
00329  }
00330  if(node_found == NULL)return FALSE;
00331  if(node_found == SelectedNode)return TRUE;
00332  SelectedNode=node_found;
00333  UpdateSelectedActor(TRUE);
00334  if(tool == NODETOOL || tool == PATHEDITOR || tool == SKELETOR ||
00335     tool == TRACKER){
00336    if(tool == TRACKER)EngageTool(TRACKER);
00337    else               EngageTool(NODETOOL);
00338    if(tool == NODETOOL)ReDrawStageDisplay(TRUE);
00339    else if(pick_only)return TRUE;
00340    else              return FALSE;
00341  }
00342  else
00343    ReDrawStageDisplay(TRUE);
00344  return TRUE;
00345 }
00346 
00347 BOOL PickClosestPathPoint(int wid, int hx, int vy){
00348  node *Np,*node_found=NULL;
00349  pathpoint *Pp,*point_found=NULL;
00350  object *Op,*path_found=NULL;
00351  point  ObjectOffset,vp,tp;
00352  short im;
00353  double dmin,phi,theta,alpha,sx,sy,sz,ima;
00354  int type;
00355  dmin=(double)TVsizeX*(double)TVsizeX*(double)TVsizeZ;
00356  GrabonX=NpointerX; GrabonY=NpointerY; GrabonZ=NpointerZ;
00357  Np=FirstNp; while(Np != NULL){
00358    if((Op=Np->fobj) != NULL)while(Op != NULL){
00359      if(Op->type == PATH){
00360        if( CurrentFrame >= Op->firstframe && CurrentFrame <= Op->lastframe){
00361             GetTransform(0,CurrentFrame,1.0,
00362                          Np,Op,ObjectOffset,tp,&phi,&theta,&alpha,
00363                          &sx,&sy,&sz,&im,&ima);
00364          Pp=Op->firstpathpoint; while(Pp != NULL){
00365            AddPoints(Pp->p,ObjectOffset,vp);
00366            if(CheckClosestObject(wid,&dmin,vp,hx,vy,3) == 1){
00367              node_found=Np;
00368              path_found=Op;
00369              point_found=Pp;
00370            }
00371            Pp=Pp->next;
00372          }
00373        }
00374      }
00375      Op=Op->next;
00376    }
00377    Np=Np->next;
00378  }
00379  if(node_found == NULL){
00380    if(SelectedNode == NULL){
00381      SelectedPath=NULL;  SelectedPathPoint=NULL;
00382    }
00383    return FALSE;
00384  }
00385  if(node_found  == SelectedNode &&
00386     path_found  == SelectedPath &&
00387     point_found == SelectedPathPoint)return TRUE;
00388  if(node_found == SelectedNode){
00389    DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,EDITING);
00390    SelectedPath=path_found;
00391    SelectedPathPoint=point_found;
00392    DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,EDITING);
00393    return TRUE;
00394  }
00395  SelectedNode=node_found;
00396  SelectedPath=path_found;
00397  SelectedPathPoint=point_found;
00398  UpdateSelectedActor(TRUE);
00399  ReDrawStageDisplay(TRUE);
00400  return TRUE;
00401 }
00402 
00403 void SnapTo(short option){
00404  object *Op;
00405  pathpoint *Pp;
00406  point p,po;
00407  double zero=0.0,one=1.0,length_on_path;
00408  p[0]=po[0]=0; p[1]=po[1]=0; p[2]=po[2]=0;
00409  if(SelectedNode == NULL)return;
00410  GetOffsetPosition(SelectedNode,NULL,CurrentFrame,1.0,p);
00411  if(option > 0){ /* start/end of path */
00412    if(SelectedNode->type != PATH){
00413      SendPrgmQuery(IDQ_NOPATH,0);
00414      return;
00415    }
00416    if     (option == 1){
00417      Op=GetObjectAtFrame(SelectedNode,CurrentFrame);
00418      if(Op == NULL)return;
00419      if((Pp=Op->firstpathpoint) == NULL)return;
00420      CopyPoint(Pp->p,po);
00421    }
00422    else if(option == 2){
00423      Op=GetObjectAtFrame(SelectedNode,CurrentFrame);
00424      if(Op == NULL)return;
00425      if((Pp=Op->firstpathpoint) == NULL)return;
00426      while(Pp->next != NULL)Pp=Pp->next;
00427      CopyPoint(Pp->p,po);
00428    }
00429    else if(option == 3){
00430      if(tool != PATHEDITOR || SelectedPathPoint == NULL){
00431        SendPrgmQuery(IDQ_NOPATH,0);
00432        return;
00433      }
00434      if(SelectedPathPoint != NULL)CopyPoint(SelectedPathPoint->p,po);
00435    }
00436    AddPoints(p,po,p);
00437  }
00438  if( (p[0] > TVpointX && p[0] < TVpointX+TVsizeX)
00439   && (p[1] > TVpointY && p[1] < TVpointY+TVsizeY)
00440   && (p[2] > TVpointZ && p[2] < TVpointZ+TVsizeZ)){
00441     Draw3dCursor();
00442     NpointerX=p[0];
00443     NpointerY=p[1];
00444     NpointerZ=p[2];
00445     Draw3dCursor();
00446  }
00447  else{
00448    NpointerX=p[0];
00449    NpointerY=p[1];
00450    NpointerZ=p[2];
00451    TVpointX=NpointerX - TVsizeX/2;
00452    TVpointY=NpointerY - TVsizeY/2;
00453    TVpointZ=NpointerZ - TVsizeZ/2;
00454    ReDrawStageDisplay(TRUE);
00455   if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
00456   else UpdateGLview(TRUE);
00457  }
00458  if(coords_visible)UpdateRuler(0);
00459 }
00460 
00461 #define TIME_DELAY 30
00462 
00463 // move tool code
00464 
00465 static position *GrabIdentity;
00466 
00467 void EnterGrabMode(void){
00468  int i,ifd,ild;
00469  do_NOT_abort=YES;
00470  DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00471  /* now draw directly onto screen */
00472  if(View == TRIVIEW){ifd=0;ild=3;}
00473  else               {ifd=ActiveView; ild=ifd+1;}
00474  for(i=ifd;i<ild;i++)UpdateWindow(ghwnd_triview[i]);
00475  Draw3dCursor();
00476  DrawInvertNode(NULL,SelectedNode,SELECTED);
00477  Draw3dCursor();
00478  do_NOT_abort=NO;
00479 }
00480 
00481 void LeaveGrabMode(void){
00482  do_NOT_abort=YES;
00483  DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00484  do_NOT_abort=NO;
00485  if(ghwndOpenGLview != NULL)UpdateGLview(TRUE);
00486  else PerspectiveView(0,1);
00487 }
00488 
00489 position *IsValidPosition(void){
00490  position *Pp;
00491  if(SelectedNode == NULL)return NULL;
00492  Pp=SelectedNode->fpos; while(Pp != NULL){
00493    if(CurrentFrame >= Pp->firstframe && CurrentFrame <= Pp->lastframe){
00494      if(CurrentFrame == Pp->lastframe ||
00495         (Pp->type != TWEEN && Pp->type != SPLINE && Pp->type != FOLLOWAT)){
00496        return Pp;
00497      }
00498      return NULL;
00499    }
00500    Pp=Pp->next;
00501  }
00502  return NULL;
00503 }
00504 
00505 int StageGrabIdentify(void){ /* Button down */
00506  position *Pp;
00507  int id;
00508  GrabIdentity=NULL;
00509  if(SelectedNode == NULL)return 0;
00510  Pp=SelectedNode->fpos; while(Pp != NULL){
00511    if(CurrentFrame >= Pp->firstframe && CurrentFrame <= Pp->lastframe){
00512      if(CurrentFrame == Pp->lastframe ||
00513         (Pp->type != TWEEN && Pp->type != SPLINE && Pp->type != FOLLOWAT)){
00514        GrabIdentity=Pp;
00515        GrabonX=NpointerX; GrabonY=NpointerY; GrabonZ=NpointerZ;
00516        return 1;
00517      }
00518      if((id=SelectKeyMaker()) > 0){
00519        if     (id == 1)NextKey('N');
00520        else if(id == 2)MakeKey('P',CurrentFrame,SelectedNode);
00521        get_stage_actor_position(SelectedNode,&lpx,&lpy,&lpz,&lpxx,&lpyy,&lpzz);
00522      }
00523      return 0;
00524    }
00525    Pp=Pp->next;
00526  }
00527  MakeControl(SelectedNode,'P',ghwnd_main);
00528  return 0;
00529 }
00530 
00531 void SetNewPosition(long pX, long pY, long pZ, short abrel){
00532  position *Pp;
00533  if((Pp=GrabIdentity) != NULL){
00534    if(Pp->type == TWEEN  || Pp->type == SPLINE || Pp->type == FOLLOWAT){
00535      if(abrel){Pp->finish[0] =pX;   Pp->finish[1] =pY;  Pp->finish[2] =pZ; }
00536      else     {Pp->finish[0]+=pX;   Pp->finish[1]+=pY;  Pp->finish[2]+=pZ; }
00537    }
00538  }
00539  return;
00540 }
00541 
00542 void StageGrabOn(void){
00543  EDIT_ACTION=YES;
00544  tool=GRABBER;
00545  if(SelectedNode != NULL)get_stage_actor_position(SelectedNode,
00546    &lpx,&lpy,&lpz,&lpxx,&lpyy,&lpzz);
00547  ReDrawStageDisplay(TRUE);
00548 }
00549 
00550 void StageGrabOff(short redraw){
00551   tool=NOTOOL;
00552   if(redraw)ReDrawStageDisplay(TRUE);
00553 }
00554 
00555 void StageGrab(short where, short which){
00556   short id;
00557   int i,ifd,ild;
00558   if(View == TRIVIEW){ifd=0;ild=3;}
00559   else               {ifd=ActiveView; ild=ifd+1;}
00560   if(SelectedNode == NULL)return;
00561   if((GrabonX != NpointerX)||(GrabonY != NpointerY)||(GrabonZ != NpointerZ)
00562                            || (where == 1)){
00563     GrabDx=NpointerX-GrabonX;
00564     GrabDy=NpointerY-GrabonY;
00565     GrabDz=NpointerZ-GrabonZ;
00566     if(which)DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00567     else{
00568       Draw3dCursor();
00569       DrawInvertNode(NULL,SelectedNode,SELECTED);
00570     }
00571     if((where%2) == 1)SetNewPosition(NpointerX,NpointerY,NpointerZ,1);
00572     else              SetNewPosition(GrabDx,GrabDy,GrabDz,0); /* rel */
00573 
00574     if(where < 2){int flag=0,x,y;
00575       POINT pt;
00576       GetCursorPos(&pt);
00577       ScreenToClient(ghwnd_current,&pt);
00578       x=pt.x; y=pt.y;
00579       if     (x > WindowSizeX[ActiveView] - 4){
00580         flag=1;
00581         if(ActiveView == TRITOP  )Zoom(PANRIGHT,0);
00582         if(ActiveView == TRIFRONT)Zoom(PANRIGHT,0);
00583         if(ActiveView == TRIRIGHT)Zoom(PANFORWARD,0);
00584       }
00585       else if(x < 4){
00586         flag=1;
00587         if(ActiveView == TRITOP  )Zoom(PANLEFT,0);
00588         if(ActiveView == TRIFRONT)Zoom(PANLEFT,0);
00589         if(ActiveView == TRIRIGHT)Zoom(PANBACK,0);
00590       }
00591       else if(y < 4){
00592         flag=1;
00593         if(ActiveView == TRITOP  )Zoom(PANFORWARD,0);
00594         if(ActiveView == TRIFRONT)Zoom(PANUP,0);
00595         if(ActiveView == TRIRIGHT)Zoom(PANUP,0);
00596       }
00597       else if(y > WindowSizeY[ActiveView] - 4){
00598         flag=1;
00599         if(ActiveView == TRITOP  )Zoom(PANBACK,0);
00600         if(ActiveView == TRIFRONT)Zoom(PANDOWN,0);
00601         if(ActiveView == TRIRIGHT)Zoom(PANDOWN,0);
00602       }
00603       if(flag){
00604         GetWindowCoords(ActiveView,NpointerX,NpointerY,NpointerZ,&x,&y);
00605         pt.x=x; pt.y=y;
00606         ClientToScreen(ghwnd_current,&pt);
00607         SetCursorPos(pt.x,pt.y);
00608         ReDrawStageDisplay(FALSE);
00609         for(i=ifd;i<ild;i++)UpdateWindow(ghwnd_triview[i]);
00610         Draw3dCursor();
00611       }
00612     }
00613 
00614     if(which)DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00615     else{
00616       DrawInvertNode(NULL,SelectedNode,SELECTED);
00617       Draw3dCursor();
00618     }
00619     if(which)for(i=ifd;i<ild;i++)UpdateWindow(ghwnd_triview[i]);
00620     if(ghwndOpenGLview == NULL){
00621       PerspectiveView(View,0);
00622       UpdateWindow(ghwnd_view);
00623     }
00624     else UpdateGLview(FALSE);
00625     GrabonX=NpointerX;
00626     GrabonY=NpointerY;
00627     GrabonZ=NpointerZ;
00628   }
00629 }
00630 
00631 static void get_stage_actor_position(node *Np, long *x, long *y, long *z,
00632     long *xx, long *yy, long *zz){
00633  position *Pp;
00634  *x = *xx = NpointerX; *y = *yy = NpointerY; *z = *zz = NpointerZ;
00635  if((Pp=Np->fpos) != NULL){
00636    while(Pp != NULL){
00637      if(CurrentFrame == Pp->lastframe){
00638        *x=Pp->finish[0]; *y=Pp->finish[1]; *z=Pp->finish[2];
00639        return;
00640      }
00641      Pp=Pp->next;
00642    }
00643  }
00644  return;
00645 }
00646 
00647 void InstantStageGrab(void){
00648  node *Np;
00649  short id;
00650  position *Pp;
00651  double x,y,z;
00652  if((Np=SelectedNode) != NULL){
00653    if((Pp=Np->fpos) != NULL){
00654      while(Pp != NULL){
00655        if(CurrentFrame == Pp->lastframe){
00656          if(Pp->type == TWEEN  || Pp->type == SPLINE){
00657            x=(double)(Pp->finish[0]-lrulerx)/ruler;
00658            y=(double)(Pp->finish[1]-lrulery)/ruler;
00659            z=(double)(Pp->finish[2]-lrulerz)/ruler;
00660            if(fabs(x) > 999999 || fabs(y) > 999999 || fabs(z) > 999999){
00661              SendPrgmQuery(IDQ_COORDTOOBIG,0);
00662              return;
00663            }
00664            LoadString(ghinst_main,IDX_MISC_MOVETO,res_str,256);
00665            if(Read3Reals(res_str,&x,&y,&z,0) == OK){
00666              Pp->finish[0]=(long)(x*ruler)+lrulerx;
00667              Pp->finish[1]=(long)(y*ruler)+lrulery;
00668              Pp->finish[2]=(long)(z*ruler)+lrulerz;
00669              ReDrawStageDisplay(TRUE);
00670              if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
00671              else UpdateGLview(TRUE);
00672            }
00673          }
00674          else SendPrgmQuery(IDQ_ONLYTWEEN,0);
00675          return;
00676        }
00677        Pp=Pp->next;
00678      }
00679    }
00680    SendPrgmQuery(IDQ_ONLYKEYFRAME,0);
00681  }
00682  else SendPrgmQuery(IDQ_NOACTORSELECTED,0);
00683  return;
00684 }
00685 
00686 static short SetupActorTrack(node *Np);
00687 static short GetActorTrack(position *fp, position *lp, long nstart);
00688 static void FreeActorTrack(void);
00689 
00690 static int key_action_tool;
00691 
00697 typedef struct tagTRACKPOINT {
00698  struct Animator_POSITION *pp;
00699  point p;
00700  long  type;
00701 } TRACKPOINT;
00702 
00703 static TRACKPOINT *trackpoints=NULL;
00704 static long Ntrackpoints;
00705 
00706 void ShifterOn(void){
00707  node *Np;
00708  short id;
00709  position *Pp;
00710  double x,y,z;
00711  if(SelectedNode == NULL){
00712    SendPrgmQuery(IDQ_NOACTORSELECTED,0);
00713    return;
00714  }
00715  if(Nframes == 1){
00716    SendPrgmQuery(IDQ_MUSTEXCEED1FRAME,0);
00717    return;
00718  }
00719  key_action_tool=gToolFlags.flagT;
00720  if(!SetupActorTrack(SelectedNode))return;
00721  EDIT_ACTION=YES;
00722  tool=TRACKER;  subtool=SHIFTER;
00723  if(!IsWindow(ghwndDlgTools)){
00724    ghwndDlgTools=CreateDialog(ghinst_main,MAKEINTRESOURCE(DLG_TRACK_DIRECT),
00725                                  ghwnd_main,(DLGPROC)SplineTweenDlgProc);
00726    if(IsWindow(ghwndDlgTools))ShowWindow(ghwndDlgTools,SW_SHOW);
00727    SetFocus(ghwnd_main);
00728  }
00729  ReDrawStageDisplay(TRUE);
00730 }
00731 
00732 void ShifterOff(short redraw){
00733  FreeActorTrack();
00734  if(IsWindow(ghwndDlgTools)){
00735    DestroyWindow(ghwndDlgTools);
00736    ghwndDlgTools=NULL;
00737  }
00738  tool=NOTOOL;
00739  if(redraw)ReDrawStageDisplay(TRUE);
00740 }
00741 
00742 static int shiftkeyframe_id = -1;
00743 
00744 void ShiftKeyFrameDeactivate(void){
00745  shiftkeyframe_id = -1;
00746 }
00747 
00748 void ShiftKeyFrame(int x, int y){
00749  position *pp;
00750  int i,k,oldROP[3];
00751  long j,id,type;
00752  int sho,svo,ifd,ild;
00753  if((id = (long)shiftkeyframe_id) < 0)return;
00754  if(View == TRIVIEW){ifd=0;ild=3;}
00755  else               {ifd=ActiveView; ild=ifd+1;}
00756  for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
00757  DrawActorTrack(ghdc_triview_Bitmap,0);
00758  DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00759  if(trackpoints[id].pp != NULL){
00760    if(ActiveView == 0 || ActiveView == 1)trackpoints[id].pp->finish[0]=NpointerX;
00761    if(ActiveView == 0 || ActiveView == 2)trackpoints[id].pp->finish[1]=NpointerY;
00762    if(ActiveView == 1 || ActiveView == 2)trackpoints[id].pp->finish[2]=NpointerZ;
00763  }
00764  if(!GetActorTrack(SelectedNode->fpos,NULL,0))goto TOOL_ERROR;
00765  DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00766  DrawActorTrack(ghdc_triview_Bitmap,0);
00767  for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
00768  {int flag=0;
00769   if     (x > WindowSizeX[ActiveView] - 4){
00770     flag=1; SendMessage(ghwnd_main,WM_COMMAND,IDM_PAN_RIGHT,ActiveView);
00771   }
00772   else if(x < 4){
00773     flag=1; SendMessage(ghwnd_main,WM_COMMAND,IDM_PAN_LEFT,ActiveView);
00774   }
00775   else if(y < 4){
00776     flag=1; SendMessage(ghwnd_main,WM_COMMAND,IDM_PAN_UP,ActiveView);
00777   }
00778   else if(y > WindowSizeY[ActiveView] - 4){
00779     flag=1; SendMessage(ghwnd_main,WM_COMMAND,IDM_PAN_DOWN,ActiveView);
00780   }
00781   if(flag){
00782     POINT pt;
00783     GetWindowCoords(ActiveView,NpointerX,NpointerY,NpointerZ,&x,&y);
00784     pt.x=x; pt.y=y;
00785     ClientToScreen(ghwnd_current,&pt);
00786     SetCursorPos(pt.x,pt.y);
00787   }
00788  }
00789  for(k=ifd;k<ild;k++){
00790    InvalidateRect(ghwnd_triview[k],NULL,FALSE);
00791    UpdateWindow(ghwnd_triview[k]);
00792  }
00793  if(ghwndOpenGLview == NULL)PerspectiveView(0,0);
00794  else UpdateGLview(FALSE);
00795  return;
00796  TOOL_ERROR:
00797  ShifterOff(1);
00798  return;
00799 }
00800 
00801 int ShiftKeyFrameActivate(int x, int y){
00802  position *pp;
00803  int xo,i,k,space_exit=0,oldROP[3];
00804  long j,id,type;
00805  double d,dmin,drange;
00806  int sho,svo,ifd,ild;
00807  POINT pt;
00808  HCURSOR hSaveCursor;
00809  long evTime;
00810  if(trackpoints == NULL || SelectedNode == NULL)return 0;
00811  if(View == TRIVIEW){ifd=0;ild=3;}
00812  else               {ifd=ActiveView; ild=ifd+1;}
00813  id = -1; type=1;  shiftkeyframe_id = (int)id;
00814  LOOP:
00815  dmin=(double)TVsizeX*(double)TVsizeX;
00816  drange=dmin/32/32;
00817  for(j=0;j<Ntrackpoints;j++){
00818    if(trackpoints[j].type == type && in_stage_triview(trackpoints[j].p)){
00819      GetWindowCoords(ActiveView,trackpoints[j].p[0],
00820        trackpoints[j].p[1],trackpoints[j].p[2],&sho,&svo);
00821      if( (sho > x-4) && (sho < x+4) && (svo > y-4) && (svo < y+4)){
00822        d=(double)(trackpoints[j].p[0]-NpointerX)
00823         *(double)(trackpoints[j].p[0]-NpointerX)
00824         +(double)(trackpoints[j].p[1]-NpointerY)
00825         *(double)(trackpoints[j].p[1]-NpointerY)
00826         +(double)(trackpoints[j].p[2]-NpointerZ)
00827         *(double)(trackpoints[j].p[2]-NpointerZ);
00828        if(d < dmin){
00829          dmin=d;
00830          id=j;
00831        }
00832      }
00833    }
00834  }
00835  if(id < 0){
00836    if(type == 1)type=0;
00837    else  return 0;
00838    goto LOOP;
00839  }
00840  key_action_tool=gToolFlags.flagT;
00841  if(trackpoints[id].type == 0){ /* make a key frame */
00842    char ttt[64];
00843    LoadString(ghinst_main,IDX_MISC_CREATEKEY,res_str,256);
00844    LoadString(ghinst_main,IDX_MISC_CONFIRM,ttt,64);
00845    if(MessageBox(NULL,res_str,ttt,
00846       MB_YESNO|MB_ICONQUESTION|MB_TASKMODAL) != IDYES)return -1;
00847    for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
00848    DrawActorTrack(ghdc_triview_Bitmap,0);
00849    DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00850    trackpoints[id].pp->firstframe=id+2; /* because id starts at 0 */
00851    if(trackpoints[id].pp->last == NULL)j=id+1;
00852    else j=trackpoints[id].pp->last->lastframe+1;
00853    if((pp=CreatePosition(SelectedNode,j,id+1)) == NULL)goto TOOL_ERROR;
00854    UPDATETIMELINES(IDC_TIMEL_UPDATE)
00855    CopyPoint(trackpoints[id].p,pp->finish);
00856    pp->type=trackpoints[id].pp->type;
00857    if(!GetActorTrack(SelectedNode->fpos,NULL,0))goto TOOL_ERROR;
00858    DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00859    DrawActorTrack(ghdc_triview_Bitmap,0);
00860    for(k=ifd;k<ild;k++){
00861      oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
00862      InvalidateRect(ghwnd_triview[k],NULL,FALSE);
00863      UpdateWindow(ghwnd_triview[k]);
00864    }
00865    return -1;
00866  }
00867  else if(key_action_tool > 0){
00868    i=key_action_tool;
00869    pp=trackpoints[id].pp;
00870    while (GetAsyncKeyState(VK_LBUTTON) & 0x8000){;}
00871    if(i == 1){ /* time shift */
00872      GetCursorPos(&pt); xo=pt.x;
00873      evTime=GetTickCount()+TIME_DELAY;
00874      do {
00875        if(evTime > GetTickCount())continue;
00876        if(GetAsyncKeyState(VK_LBUTTON) & 0x8000)break;
00877        GetCursorPos(&pt); y=pt.x;
00878        x = y-xo; xo=y;
00879        if(x != 0){
00880          if(x > 0)y=max( 1,min( 45,x));
00881          else     y=min(-1,max(-45,x));
00882 /*         BKIN: */
00883          if(abs(y) > 5){
00884            for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
00885            DrawActorTrack(ghdc_triview_Bitmap,0);
00886            DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00887            if(pp->next != NULL){
00888              if(y < 0 && pp->lastframe > pp->firstframe){
00889                pp->lastframe--;
00890                pp->next->firstframe--;
00891              }
00892              else if(y > 0 && pp->next->firstframe < pp->next->lastframe){
00893                pp->lastframe++;
00894                pp->next->firstframe++;
00895              }
00896            }
00897            if(!GetActorTrack(SelectedNode->fpos,NULL,0))goto TOOL_ERROR;
00898            DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00899            DrawActorTrack(ghdc_triview_Bitmap,0);
00900            for(k=ifd;k<ild;k++){
00901              oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
00902              InvalidateRect(ghwnd_triview[k],NULL,FALSE);
00903              UpdateWindow(ghwnd_triview[k]);
00904            }
00905          }
00906          if(abs(y) < 50){ /* mouse in use do - pause */
00907            evTime=GetTickCount()+TIME_DELAY;
00908            while(GetTickCount() < TIME_DELAY){;}
00909            GetCursorPos(&pt); xo=pt.x;
00910          }
00911        }
00912 //       Get_Key(&key,&ekey);
00913 //       if(key == 0 && ekey == RIGHTARROW){y = -50; goto BKIN;}
00914 //       if(key == 0 && ekey == LEFTARROW) {y =  50; goto BKIN;}
00915 //       if(key == RETURN || key == SPACE)break;
00916        evTime=GetTickCount()+TIME_DELAY;
00917      }
00918      while(1);
00919    }
00920    else if(i == 2){ /* delete */
00921      if(pp->last == NULL || pp->next == NULL){
00922        SendPrgmQuery(IDQ_NOENDCHANGE,0);
00923        return -1;
00924      }
00925      for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
00926      DrawActorTrack(ghdc_triview_Bitmap,0);
00927      DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00928      i=pp->firstframe;
00929      pp=pp->next;
00930      DeletePosition(SelectedNode,i);
00931      UPDATETIMELINES(IDC_TIMEL_UPDATE)
00932      pp->firstframe=i;
00933      if(!GetActorTrack(SelectedNode->fpos,NULL,0))goto TOOL_ERROR;
00934      DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00935      DrawActorTrack(ghdc_triview_Bitmap,0);
00936      for(k=ifd;k<ild;k++){
00937        oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
00938        InvalidateRect(ghwnd_triview[k],NULL,FALSE);
00939        UpdateWindow(ghwnd_triview[k]);
00940      }
00941    }
00942    else if(i == 3){ /* change tension */
00943      GetCursorPos(&pt); xo=pt.x;
00944      evTime=GetTickCount()+TIME_DELAY;
00945      do {
00946        if(evTime > GetTickCount())continue;
00947        if(GetAsyncKeyState(VK_LBUTTON) & 0x8000)break;
00948        GetCursorPos(&pt); y=pt.x;
00949        x = y-xo; xo=y;
00950        if(x != 0){
00951          if(x > 0)y=max( 1,min( 50,x));
00952          else     y=min(-1,max(-50,x));
00953          d=1.0+(double)y/95.0;
00954          for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
00955          DrawActorTrack(ghdc_triview_Bitmap,0);
00956          DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00957          if((dmin=pp->tension_e * d) > 0.01 && dmin < 0.95)pp->tension_e=dmin;
00958          if(pp->next != NULL){
00959            if((dmin=pp->next->tension_s * d) > 0.01 && dmin < 0.95)
00960              pp->next->tension_s=dmin;
00961          }
00962          if(!GetActorTrack(SelectedNode->fpos,NULL,0))goto TOOL_ERROR;
00963          DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00964          DrawActorTrack(ghdc_triview_Bitmap,0);
00965          for(k=ifd;k<ild;k++){
00966            oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
00967            InvalidateRect(ghwnd_triview[k],NULL,FALSE);
00968            UpdateWindow(ghwnd_triview[k]);
00969          }
00970        }
00971 //       if(key == RETURN || key == SPACE)break;
00972        evTime=GetTickCount()+TIME_DELAY;
00973      }
00974      while(1);
00975    }
00976 //   SetCursor(hSaveCursor);
00977    while (GetAsyncKeyState(VK_LBUTTON) & 0x8000){;}
00978    if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
00979    else UpdateGLview(TRUE);
00980    return 0;
00981  }
00982  shiftkeyframe_id = (int)id;
00983  return 1;
00984  TOOL_ERROR:
00985  ShifterOff(1);
00986  return 0;
00987 }
00988 
00989 static short SetupActorTrack(node *Np){
00990  position *pp;
00991  if(Np == NULL)return 0;
00992  else if(Np->fpos == NULL){ /* create the time lines */
00993    if(CreatePosition(Np,1,1) == NULL)return 0;
00994    if(CreatePosition(Np,2,Nframes) == NULL)return 0;
00995    Np->fpos->type=SPLINE;
00996    Np->fpos->next->type=SPLINE;
00997    UPDATETIMELINES(IDC_TIMEL_UPDATE)
00998  }
00999  pp=Np->fpos;
01000  while(pp != NULL){
01001    if(!(pp->type == TWEEN || pp->type == SPLINE)){
01002      SendPrgmQuery(IDQ_ONLYTWEEN,0);
01003      return 0;
01004    }
01005    pp=pp->next;
01006  }
01007  if((trackpoints=(TRACKPOINT *)X__Malloc(Nframes*sizeof(TRACKPOINT))) == NULL){
01008    SendPrgmQuery(IDQ_NOMEM2,0);
01009    return 0;
01010  }
01011  if(!GetActorTrack(Np->fpos,NULL,0)){
01012    FreeActorTrack();
01013    return 0;
01014  }
01015  return 1;
01016 }
01017 
01018 static short GetActorTrack(position *fp, position *lp, long nstart){
01019  long i;
01020  double ratio,dr,kx[4],ky[4],kz[4],gs,ge;
01021  point dp,spl,spn;
01022  Ntrackpoints=nstart;
01023  while(fp != lp){
01024    dr=1.0/(double)(fp->lastframe+1 - fp->firstframe);
01025    for(i=fp->firstframe;i<=fp->lastframe;i++){
01026      if(fp->type == TWEEN){
01027        if((fp->last == NULL) || (fp->firstframe == fp->lastframe))
01028          CopyPoint(fp->finish,trackpoints[Ntrackpoints].p);
01029        else{
01030          ratio=(double)(i+1 - fp->firstframe)*dr;
01031          SubPoints(fp->finish,fp->last->finish,dp);
01032          ScalePoint(ratio,ratio,ratio,dp,dp);
01033          AddPoints(fp->last->finish,dp,trackpoints[Ntrackpoints].p);
01034          if(fp->last->lastframe != fp->firstframe-1){
01035            SendPrgmQuery(IDQ_NOGAPINTIMELINE,0);
01036            return 0;
01037          }
01038        }
01039      }
01040      else if(fp->type == SPLINE){
01041        if((fp->last == NULL) || (fp->firstframe == fp->lastframe))
01042          CopyPoint(fp->finish,trackpoints[Ntrackpoints].p);
01043        else{
01044          ratio=(double)(i+1 - fp->firstframe)*dr;
01045          if(fp->last->last != NULL){
01046            CopyPoint(fp->last->last->finish,spl);
01047          }
01048          else{
01049            SubPoints(fp->finish,fp->last->finish,dp);
01050            SubPoints(fp->last->finish,dp,spl);
01051          }
01052          if(fp->next != NULL){
01053            CopyPoint(fp->next->finish,spn);
01054          }
01055          else{
01056            SubPoints(fp->finish,fp->last->finish,dp);
01057            AddPoints(fp->finish,dp,spn);
01058          }
01059          gs=(double)(fp->finish[0]-spl[0])*fp->tension_s;
01060          ge=(double)(spn[0]-fp->last->finish[0])*fp->tension_e;
01061          SplinesG(kx,fp->last->finish[0],fp->finish[0],gs,ge);
01062 
01063          gs=(double)(fp->finish[1]-spl[1])*fp->tension_s;
01064          ge=(double)(spn[1]-fp->last->finish[1])*fp->tension_e;
01065          SplinesG(ky,fp->last->finish[1],fp->finish[1],gs,ge);
01066 
01067          gs=(double)(fp->finish[2]-spl[2])*fp->tension_s;
01068          ge=(double)(spn[2]-fp->last->finish[2])*fp->tension_e;
01069          SplinesG(kz,fp->last->finish[2],fp->finish[2],gs,ge);
01070 
01071          trackpoints[Ntrackpoints].p[0] = SplinesP(kx,ratio);
01072          trackpoints[Ntrackpoints].p[1] = SplinesP(ky,ratio);
01073          trackpoints[Ntrackpoints].p[2] = SplinesP(kz,ratio);
01074          /* extra bit here if needed in future */
01075        }
01076      }
01077      trackpoints[Ntrackpoints].pp=fp;
01078      if(i==fp->lastframe)trackpoints[Ntrackpoints].type=1;
01079      else                trackpoints[Ntrackpoints].type=0;
01080      Ntrackpoints++;
01081    }
01082    fp=fp->next;
01083  }
01084  return 1;
01085 }
01086 
01087 void DrawActorTrack(HDC hdc[],short mode){
01088  int i,sh,sv,shi[3],svi[3];
01089  long j;
01090  int ifd,ild;
01091  LOGPEN lopn;
01092  HPEN hOldPen[3];
01093  GetObject(ghSelectedPen,sizeof(LOGPEN),&lopn);
01094  if(View == TRIVIEW){ifd=0;ild=3;}
01095  else               {ifd=ActiveView; ild=ifd+1;}
01096  if(trackpoints == NULL)return;
01097  for(j=0;j<Ntrackpoints;j++){
01098    for(i=ifd;i<ild;i++){
01099      hOldPen[i]=SelectObject(hdc[i],ghInvertPen);
01100      if(j > 0){
01101        MoveToEx(hdc[i],shi[i],svi[i],NULL);
01102      }
01103      GetWindowCoords(i,
01104                      trackpoints[j].p[0],
01105                      trackpoints[j].p[1],
01106                      trackpoints[j].p[2],&shi[i],&svi[i]);
01107      if(j > 0){
01108        LineTo(hdc[i],shi[i],svi[i]);
01109      }
01110      if(!mode && trackpoints[j].type){
01111        SelectObject(hdc[i],ghSelectedPen);
01112        Rectangle(hdc[i],(int)shi[i]-2,(int)svi[i]-2,
01113                         (int)shi[i]+3,(int)svi[i]+3);
01114      }
01115      else if(shi[i] >= 0 && shi[i] < WindowSizeX[i] &&
01116              svi[i] >= 0 &&  svi[i] < WindowSizeY[i]){
01117        Rectangle(hdc[i],(int)shi[i]-1,(int)svi[i]-1,
01118                         (int)shi[i]+2,(int)svi[i]+2);
01119 //       X__SetPixel(hdc[i],shi[i],svi[i],lopn.lopnColor);
01120      }
01121      SelectObject(hdc[i],hOldPen[i]);
01122    }
01123  }
01124 }
01125 
01126 static void FreeActorTrack(void){
01127   if(trackpoints != NULL)X__Free(trackpoints);
01128   trackpoints=NULL;
01129 }
01130 // end move tool code
01131 
01132 // expand tool code
01133 
01134 void StageSizeOn(void){
01135  node *Np;
01136  size *Xp;
01137  double x,y,z;
01138  WORD res;
01139  EDIT_ACTION=YES;
01140  tool=SIZER;
01141  if(SelectedNode != NULL){
01142    get_stage_actor_expansion(SelectedNode,&lpt,&lpp,&lpa);
01143    if(!IsWindow(ghwndDlgTools)){
01144      if(SelectedNode->type != CAMERA){
01145        if(SelectedNode->type == LIGHT){
01146          gToolFlags.flagX=TRUE;
01147          gToolFlags.flagY=FALSE;
01148          gToolFlags.flagZ=TRUE;
01149          res=DLG_SIZERL;
01150        }
01151        else res=DLG_SIZER;
01152        ghwndDlgTools=CreateDialog(ghinst_main,MAKEINTRESOURCE(res),
01153                                   ghwnd_main,(DLGPROC)SizerToolDlgProc);
01154        if(IsWindow(ghwndDlgTools))ShowWindow(ghwndDlgTools,SW_SHOW);
01155        SetFocus(ghwnd_main);
01156      }
01157      else{
01158        gToolFlags.flagX=TRUE;
01159        gToolFlags.flagY=TRUE;
01160        gToolFlags.flagZ=FALSE;
01161      }
01162    }
01163  }
01164  ReDrawStageDisplay(TRUE);
01165 }
01166 
01167 void SizeOff(short redraw){
01168  tool=NOTOOL;
01169  if(IsWindow(ghwndDlgTools)){
01170    DestroyWindow(ghwndDlgTools);
01171    ghwndDlgTools=NULL;
01172  }
01173  if(redraw)ReDrawStageDisplay(TRUE);
01174 }
01175 
01176 static void ScalePath(short sor){
01177  object *Op;
01178  pathpoint *Ppp;
01179  int x,xo,MickeyX,I;
01180  POINT pt;
01181  long evTime;
01182  double scale_value,Sx,Sy,Sz,tro[4][4];
01183  if((Op=SelectedNode->fobj) != NULL)while(Op != NULL){
01184   if(CurrentFrame >= Op->firstframe || CurrentFrame <= Op->lastframe){
01185     GetCursorPos(&pt); xo=pt.x;
01186     evTime=GetTickCount()+TIME_DELAY;
01187     do {
01188      if(evTime > GetTickCount())continue;
01189      GetCursorPos(&pt); x=pt.x;
01190      MickeyX = x-xo; xo=x;
01191      if(MickeyX != 0){
01192       if(MickeyX > 0)I=max( 1,min( 50,MickeyX));
01193       else           I=min(-1,max(-50,MickeyX));
01194       DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01195       if(sor == 0){ /* change of scale */
01196         scale_value = 1.0 + (double)(I)/55.0; Sx=Sy=Sz=1.0;
01197         if(gToolFlags.flagX)Sx=scale_value;
01198         if(gToolFlags.flagY)Sy=scale_value;
01199         if(gToolFlags.flagZ)Sz=scale_value;
01200       }
01201       else{ /* a rotation about the origin */
01202         if     (gToolFlags.flagA == 2)roty(tro,-I*PIo180);
01203         else if(gToolFlags.flagA == 1)rotx(tro, I*PIo180);
01204         else  rotz(tro,I*PIo180);
01205       }
01206       if((Ppp=Op->firstpathpoint) != NULL){
01207         while(Ppp != NULL){
01208           if(sor == 0){
01209             Ppp->p[0] *= Sx; Ppp->p[1] *= Sy; Ppp->p[2] *= Sz;
01210           }
01211           else{
01212             m4by1(tro,(double)Ppp->p[0],(double)Ppp->p[1],(double)Ppp->p[2],
01213                   &Sx,&Sy,&Sz);
01214             Ppp->p[0] = (long)Sx; Ppp->p[1] = (long)Sy; Ppp->p[2] = (long)Sz;
01215           }
01216           Ppp=Ppp->next;
01217         }
01218       }
01219       DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01220       if(ghwndOpenGLview == NULL){
01221         PerspectiveView(View,0);
01222         UpdateWindow(ghwnd_view);
01223       }
01224       else UpdateGLview(FALSE);
01225       if(View == TRIVIEW){
01226         for(I=0;I<3;I++)UpdateWindow(ghwnd_triview[I]);
01227       }
01228       else UpdateWindow(ghwnd_current);
01229      }
01230      evTime=GetTickCount()+TIME_DELAY;
01231      {MSG msg;
01232        if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
01233          TranslateMessage(&msg);
01234          DispatchMessage(&msg);
01235        }
01236       }
01237     }
01238     while (GetAsyncKeyState(VK_LBUTTON) & 0x8000);
01239     Op->pathlength=PathLength(Op->firstpathpoint /* re-calculate the length */
01240                              ,Op->pathtype,Op->npathpoints);
01241     if(ghwndOpenGLview != NULL)UpdateGLview(TRUE);
01242     else PerspectiveView(0,1);
01243     return;
01244   }
01245   Op=Op->next;
01246  }
01247  return;
01248 }
01249 
01250 void Resize(void){
01251  size *Xp;
01252  int x,xo,MickeyX,I,id;
01253  double scale_value;
01254  POINT pt;
01255  long evTime;
01256  if(SelectedNode == NULL)return;
01257  if( !(SelectedNode->type == NORMAL || SelectedNode->type == GROUND   ||
01258        SelectedNode->type == PATH   || SelectedNode->type == ANIMOBJ  ||
01259        SelectedNode->type == CAMERA || SelectedNode->type == PARTICLE ||
01260        SelectedNode->type == ROBOT  || SelectedNode->type == LIGHT)){
01261     SendPrgmQuery(IDQ_NORESIZE,0);
01262     return;
01263  }
01264  if(SelectedNode->type == PATH){ScalePath(0); return;}
01265  else if((Xp=SelectedNode->fsiz) != NULL){
01266    while(Xp != NULL){
01267      if(CurrentFrame == Xp->lastframe){
01268        GetCursorPos(&pt); xo=pt.x;
01269        evTime=GetTickCount()+TIME_DELAY;
01270        do {
01271          if(evTime > GetTickCount())continue;
01272          GetCursorPos(&pt); x=pt.x;
01273          MickeyX = x-xo; xo=x;
01274          if(MickeyX != 0){
01275            if(MickeyX > 0)I=max( 1,min( 50,MickeyX));
01276            else           I=min(-1,max(-50,MickeyX));
01277            DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01278            scale_value = 1.0 + (double)(I)/55.0;
01279            if(gToolFlags.flagX)Xp->Sx *= scale_value;
01280            if(gToolFlags.flagY)Xp->Sy *= scale_value;
01281            if(SelectedNode->type == CAMERA){
01282              Xp->Sx = min(Xp->Sx,20);
01283              Xp->Sx = max(Xp->Sx,0.1);
01284              Xp->Sy = min(Xp->Sy,20);
01285              Xp->Sy = max(Xp->Sy,0.1);
01286            }
01287            else if(SelectedNode->type == LIGHT){
01288              Xp->Sx = min(Xp->Sx,150);
01289              Xp->Sx = max(Xp->Sx,1);
01290              if(gToolFlags.flagZ)Xp->Sz *= scale_value;
01291 //             Xp->Sy = min(Xp->Sy,150);
01292 //             Xp->Sy = max(Xp->Sy,1);
01293            }
01294            else{
01295              if(gToolFlags.flagZ)Xp->Sz *= scale_value;
01296            }
01297            DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01298            if(ghwndOpenGLview == NULL){
01299              PerspectiveView(View,0);
01300              UpdateWindow(ghwnd_view);
01301            }
01302            else UpdateGLview(FALSE);
01303            if(View == TRIVIEW){
01304              for(I=0;I<3;I++)UpdateWindow(ghwnd_triview[I]);
01305            }
01306            else UpdateWindow(ghwnd_current);
01307          }
01308          evTime=GetTickCount()+TIME_DELAY;
01309          {MSG msg;
01310           if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
01311             TranslateMessage(&msg);
01312             DispatchMessage(&msg);
01313           }
01314          }
01315        }
01316        while (GetAsyncKeyState(VK_LBUTTON) & 0x8000);
01317       if(ghwndOpenGLview != NULL)UpdateGLview(TRUE);
01318       else PerspectiveView(0,1);
01319       return;
01320      }
01321      Xp=Xp->next;
01322    }
01323    /* try to make key */
01324    Xp=SelectedNode->fsiz; while(Xp != NULL){
01325      if(CurrentFrame >= Xp->firstframe && CurrentFrame <= Xp->lastframe){
01326        if(CurrentFrame == Xp->lastframe)return;
01327        if((id=SelectKeyMaker()) > 0){
01328          if(id == 1){
01329            NextKey('N');
01330          }
01331          else if(id == 2){
01332            DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);    /* in case it doesn't come */
01333            MakeKey('Z',CurrentFrame,SelectedNode);                       /* back at the same place  */
01334            DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01335          }
01336        }
01337        return;
01338      }
01339      Xp=Xp->next;
01340    }
01341  }
01342  MakeControl(SelectedNode,'Z',ghwnd_main);
01343  return;
01344 }
01345 
01346 static void get_stage_actor_expansion(node *Np, double *sx,
01347        double *sy, double *sz){
01348  size *Xp;
01349  *sx=1.0; *sy=1.0; *sz=1.0;
01350  if((Xp=Np->fsiz) != NULL){
01351    while(Xp != NULL){
01352      if(CurrentFrame == Xp->lastframe){
01353        *sx=Xp->Sx; *sy=Xp->Sy; *sz=Xp->Sz;
01354        return;
01355      }
01356      Xp=Xp->next;
01357    }
01358  }
01359  return;
01360 }
01361 
01362 void InstantStageXpnd(void){
01363  node *Np;
01364  size *Xp;
01365  short id;
01366  double x,y,z;
01367  if((Np=SelectedNode) != NULL){
01368    if((Xp=Np->fsiz) != NULL){
01369      while(Xp != NULL){
01370        if(CurrentFrame == Xp->lastframe){
01371          x=Xp->Sx; y=Xp->Sy; z=Xp->Sz;
01372          LoadString(ghinst_main,IDX_MISC_SETSCALE,res_str,256);
01373          if(Read3Reals(res_str,&x,&y,&z,0) == OK){
01374            Xp->Sx=x; Xp->Sy=y; Xp->Sz=z;
01375            ReDrawStageDisplay(TRUE);
01376            if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
01377            else UpdateGLview(TRUE);
01378          }
01379          else SendPrgmQuery(IDQ_ONLYTWEEN,0);
01380          return;
01381        }
01382        Xp=Xp->next;
01383      }
01384    }
01385    SendPrgmQuery(IDQ_ONLYKEYFRAME,0);
01386  }
01387  else SendPrgmQuery(IDQ_NOACTORSELECTED,0);
01388  return;
01389 }
01390 // end expand tool code
01391 
01392 // rotate tool code
01393 
01394 void StageRotateOn(void){
01395  EDIT_ACTION=YES;
01396  tool=ROTATOR;
01397  if(SelectedNode != NULL)get_stage_actor_rotation(SelectedNode,
01398    &lpt,&lpp,&lpa);
01399 // if(!IsWindow(ghwndDlgTools)){
01400 //   ghwndDlgTools=CreateDialog(ghinst_main,MAKEINTRESOURCE(DLG_ROTATOR),
01401 //                                 ghwnd_main,(DLGPROC)RotatorToolDlgProc);
01402 //   if(IsWindow(ghwndDlgTools))ShowWindow(ghwndDlgTools,SW_SHOW);
01403 //   SetFocus(ghwnd_main);
01404 // }
01405  ReDrawStageDisplay(TRUE);
01406 }
01407 
01408 void RotateOff(long redraw){
01409  tool=NOTOOL;
01410  if(IsWindow(ghwndDlgTools)){
01411    DestroyWindow(ghwndDlgTools);
01412    ghwndDlgTools=NULL;
01413  }
01414  if(redraw)ReDrawStageDisplay(TRUE);
01415 }
01416 
01417 static void get_stage_actor_rotation(node *Np, double *theta,
01418        double *phi, double *alpha){
01419  align *Ap;
01420  *theta=0.0; *alpha=0.0; *phi=0.0;
01421  if((Ap=Np->fali) != NULL){
01422    while(Ap != NULL){
01423      if(CurrentFrame == Ap->lastframe){
01424        *alpha=Ap->alpha; *phi=Ap->phi; *theta=Ap->theta;
01425        return;
01426      }
01427      Ap=Ap->next;
01428    }
01429  }
01430  return;
01431 }
01432 
01433 void StageRotate(long window_id){
01434  align *Ap;
01435  int x,xo,MickeyX,I,id;
01436  POINT pt;
01437  long evTime;
01438  if(ActiveView == TRITOP  )gToolFlags.flagA = 0;
01439  if(ActiveView == TRIRIGHT)gToolFlags.flagA = 1;
01440  if(ActiveView == TRIFRONT)gToolFlags.flagA = 2;
01441  if(SelectedNode == NULL)return;
01442  if(SelectedNode->type == PATH){ScalePath(1); return;}
01443  else if((Ap=SelectedNode->fali) != NULL){
01444   while(Ap != NULL){
01445    if(CurrentFrame == Ap->lastframe){
01446     GetCursorPos(&pt); xo=pt.x;
01447     evTime=GetTickCount()+TIME_DELAY;
01448     do {
01449      if(evTime > GetTickCount())continue;
01450      GetCursorPos(&pt); x=pt.x;
01451      MickeyX = x-xo; xo=x;
01452      if(MickeyX != 0){
01453       if(MickeyX > 0)I=max( 1,min( 90,MickeyX));
01454       else           I=min(-1,max(-90,MickeyX));
01455       if((GetAsyncKeyState(VK_SHIFT) & 0x8000) == 0x8000){
01456         /* constrain 45 degrees */
01457         if(abs(I) < 22)I=0;
01458         else{
01459           if(I < 0)I = -45;
01460           else     I =  45;
01461         }
01462       }
01463       DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01464       if(gToolFlags.flagA == 2){ /* bank */
01465         Ap->theta -= I;if(Ap->theta> 180.0)Ap->theta= -360+Ap->theta;
01466       }
01467       else if(gToolFlags.flagA == 1 ||
01468              (GetAsyncKeyState(VK_CONTROL) & 0x8000)){ /* up/down */
01469         if(Ap->type == TWEEN || Ap->type == SPLINEA){
01470           Ap->alpha += I;if(Ap->alpha> 180.0)Ap->alpha= -360+Ap->alpha;
01471         }
01472       }
01473       else{   /* around and about rotation */
01474         if(Ap->type == TWEEN || Ap->type == SPLINEA){ /* not used for track, align, rotate */
01475           Ap->phi += I;if(Ap->phi> 180.0)Ap->phi= -360+Ap->phi;
01476         }
01477       }
01478       DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01479       if(ghwndOpenGLview == NULL){
01480         PerspectiveView(View,0);
01481         UpdateWindow(ghwnd_view);
01482       }
01483       else UpdateGLview(FALSE);
01484       if(View == ONEVIEW)UpdateWindow(ghwnd_current);
01485       else{
01486         for(I=0;I<3;I++)UpdateWindow(ghwnd_triview[I]);
01487       }
01488      }
01489      evTime=GetTickCount()+TIME_DELAY;
01490       {MSG msg;
01491        if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
01492          TranslateMessage(&msg);
01493          DispatchMessage(&msg);
01494        }
01495       }
01496     }
01497     while (GetAsyncKeyState(VK_LBUTTON) & 0x8000);
01498     if(ghwndOpenGLview != NULL)UpdateGLview(TRUE);
01499     else PerspectiveView(0,1);
01500     return;
01501    }
01502    Ap=Ap->next;
01503   }
01504   /* try to make key */
01505   Ap=SelectedNode->fali; while(Ap != NULL){
01506     if(CurrentFrame >= Ap->firstframe && CurrentFrame <= Ap->lastframe){
01507       if(CurrentFrame == Ap->lastframe)return;
01508       if((id=SelectKeyMaker()) > 0){
01509         if(id == 1){
01510           NextKey('N');
01511         }
01512         else if(id == 2){
01513           DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);    /* in case it doesn't come */
01514           MakeKey('A',CurrentFrame,SelectedNode);                       /* back at the same place  */
01515           DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01516         }
01517       }
01518       return;
01519     }
01520     Ap=Ap->next;
01521   }
01522  }
01523  MakeControl(SelectedNode,'A',ghwnd_main);
01524  return;
01525 }
01526 
01527 void StageStepRotate(int command){
01528  align *Ap;
01529  long axis,I;
01530  int id;
01531  axis=0;
01532  if(GetAsyncKeyState(VK_SHIFT) & 0x8000)I=5;
01533  else I=1;
01534  if(command == IDM_PAN_RIGHT){I =  I; axis=0;}
01535  if(command == IDM_PAN_LEFT) {I = -I; axis=0;}
01536  if(command == IDM_PAN_UP)   {I =  I; axis=1;}
01537  if(command == IDM_PAN_DOWN) {I = -I; axis=1;}
01538  if(command == IDM_ZOOM_IN)  {I =  I; axis=2;}   /* bank */
01539  if(command == IDM_ZOOM_OUT) {I = -I; axis=2;}   /* bank */
01540  if(SelectedNode == NULL)return;
01541  if(SelectedNode->type == PATH){return;}
01542  else if((Ap=SelectedNode->fali) != NULL){
01543   while(Ap != NULL){
01544    if(CurrentFrame == Ap->lastframe){
01545      DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01546      if(axis == 2){/* bank */
01547        Ap->theta -= I;if(Ap->theta> 180.0)Ap->theta= -360+Ap->theta;
01548      }
01549      else if(axis == 1){
01550        if(Ap->type == TWEEN || Ap->type == SPLINEA){
01551          Ap->alpha += I;if(Ap->alpha> 180.0)Ap->alpha= -360+Ap->alpha;
01552        }
01553      }
01554      else{   /* around and about rotation */
01555        if(Ap->type == TWEEN || Ap->type == SPLINEA){ /* not used for track, align, rotate */
01556          Ap->phi += I;if(Ap->phi> 180.0)Ap->phi= -360+Ap->phi;
01557        }
01558      }
01559      DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01560      if(ghwndOpenGLview == NULL)PerspectiveView(0,0);
01561      else UpdateGLview(FALSE);
01562      return;
01563    }
01564    Ap=Ap->next;
01565   }
01566   /* try to make key */
01567   Ap=SelectedNode->fali; while(Ap != NULL){
01568     if(CurrentFrame >= Ap->firstframe && CurrentFrame <= Ap->lastframe){
01569       if(CurrentFrame == Ap->lastframe)return;
01570       if((id=SelectKeyMaker()) > 0){
01571         if(id == 1){
01572           NextKey('N');
01573         }
01574         else if(id == 2){
01575           DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);    /* in case it doesn't come */
01576           MakeKey('A',CurrentFrame,SelectedNode);                       /* back at the same place  */
01577           DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01578         }
01579       }
01580       return;
01581     }
01582     Ap=Ap->next;
01583   }
01584  }
01585  MakeControl(SelectedNode,'A',ghwnd_main);
01586 }
01587 
01588 void InstantStageRotate(void){
01589  node *Np;
01590  align *Ap;
01591  short id;
01592  double x,y,z;
01593  if((Np=SelectedNode) != NULL){
01594    if((Ap=Np->fali) != NULL){
01595      while(Ap != NULL){
01596        if(CurrentFrame == Ap->lastframe){
01597          if(Ap->type == TWEEN || Ap->type == SPLINEA){
01598            x=Ap->phi; y=Ap->alpha; z=Ap->theta;
01599            LoadString(ghinst_main,IDX_MISC_SETROTATION,res_str,256);
01600            if(Read3Reals(res_str,&x,&y,&z,1) == OK){
01601              Ap->phi=x; Ap->alpha=y; Ap->theta=z;
01602              ReDrawStageDisplay(TRUE);
01603              if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
01604              else UpdateGLview(TRUE);
01605            }
01606          }
01607          else SendPrgmQuery(IDQ_ONLYTWEEN,0);
01608          return;
01609        }
01610        Ap=Ap->next;
01611      }
01612    }
01613    SendPrgmQuery(IDQ_ONLYKEYFRAME,0);
01614  }
01615  else SendPrgmQuery(IDQ_NOACTORSELECTED,0);
01616  return;
01617 }
01618 
01619 static short SetupActorAngles(node *Np);
01620 static short GetActorAngles(align *fa, align *la, long nstart);
01621 static void FreeActorAngles(void);
01622 
01628 typedef struct Animator_TRACKANGLE {
01629  struct Animator_ALIGN *ap;
01630  double alpha,theta,phi;
01631  long  type;
01632 } TRACKANGLE;
01633 
01634 static TRACKANGLE *trackangles=NULL;
01635 static long Ntrackangles;
01636 static align *SelectedActorRotation=NULL;
01637 
01638 static short SetupActorAngles(node *Np){
01639  align *ap;
01640  if(Np == NULL)return 0;
01641  else if(Np->fali == NULL){ /* create the time lines */
01642    if(CreateAlign(Np,1,1) == NULL)return 0;
01643    if(CreateAlign(Np,2,Nframes) == NULL)return 0;
01644    Np->fali->type=TWEEN;
01645    Np->fali->next->type=TWEEN;
01646    UPDATETIMELINES(IDC_TIMEL_UPDATE)
01647  }
01648  ap=Np->fali;
01649  while(ap != NULL){
01650    if(!(ap->type == TWEEN || ap->type == SPLINEA)){
01651      SendPrgmQuery(IDQ_ONLYTWEEN,0);
01652      return 0;
01653    }
01654    ap=ap->next;
01655  }
01656  if((trackangles=(TRACKANGLE *)X__Malloc(Nframes*sizeof(TRACKANGLE))) == NULL){
01657    SendPrgmQuery(IDQ_NOMEM2,0);
01658    return 0;
01659  }
01660  if(!GetActorAngles(Np->fali,NULL,0)){
01661    FreeActorAngles();
01662    return 0;
01663  }
01664  return 1;
01665 }
01666 
01667 static void FreeActorAngles(void){
01668   if(trackangles != NULL)X__Free(trackangles);
01669   trackangles=NULL;
01670 }
01671 
01672 static short GetActorAngles(align *fa, align *la, long nstart){
01673  long i,ddt;
01674  double ratio,dr,dp,kx[4],ky[4],kz[4],dpl,dpn;
01675  Ntrackangles=nstart;
01676  while(fa != la){
01677    dr=1.0/(double)(fa->lastframe+1 - fa->firstframe);
01678    for(i=fa->firstframe;i<=fa->lastframe;i++){
01679      if(fa->type == TWEEN){
01680        if((fa->last == NULL) || (fa->firstframe == fa->lastframe)){
01681           trackangles[Ntrackangles].phi=fa->phi;
01682           trackangles[Ntrackangles].theta=fa->theta;
01683           trackangles[Ntrackangles].alpha=fa->alpha;
01684        }
01685        else{
01686          ratio=(double)(i+1 - fa->firstframe)*dr;
01687          dp = fa->phi - fa->last->phi;
01688          if(dp < -180.0)dp += 360.0;
01689          if(dp >  180.0)dp -= 360.0;
01690          dp *= ratio;
01691          dp += fa->last->phi;
01692          if(dp < -180.0)dp += 360.0;
01693          if(dp >  180.0)dp -= 360.0;
01694          trackangles[Ntrackangles].phi = dp;
01695          dp = fa->theta - fa->last->theta;
01696          if(dp < -180.0)dp += 360.0;
01697          if(dp >  180.0)dp -= 360.0;
01698          dp *= ratio;
01699          dp += fa->last->theta;
01700          if(dp < -180.0)dp += 360.0;
01701          if(dp >  180.0)dp -= 360.0;
01702          trackangles[Ntrackangles].theta = dp;
01703          dp = fa->alpha - fa->last->alpha;
01704          if(dp < -180.0)dp += 360.0;
01705          if(dp >  180.0)dp -= 360.0;
01706          dp *= ratio;
01707          dp += fa->last->alpha;
01708          if(dp < -180.0)dp += 360.0;
01709          if(dp >  180.0)dp -= 360.0;
01710          trackangles[Ntrackangles].alpha = dp;
01711          if(fa->last->lastframe != fa->firstframe-1){
01712            SendPrgmQuery(IDQ_NOGAPINTIMELINE,0);
01713            return 0;
01714          }
01715        }
01716      }
01717      else if(fa->type == SPLINEA){
01718        if((fa->last == NULL) || (fa->firstframe == fa->lastframe)){
01719           trackangles[Ntrackangles].phi=fa->phi;
01720           trackangles[Ntrackangles].theta=fa->theta;
01721           trackangles[Ntrackangles].alpha=fa->alpha;
01722        }
01723        else{
01724          ratio=(double)(i+1 - fa->firstframe)*dr;
01725          dp = fa->phi - fa->last->phi;
01726          if(dp < -180.0)dp += 360.0;
01727          if(dp >  180.0)dp -= 360.0;
01728          if(fa->last->last == NULL)dpl=0.0;
01729          else{
01730            dpl = fa->last->phi - fa->last->last->phi;
01731            if(dpl < -180.0)dpl += 360.0;
01732            if(dpl >  180.0)dpl -= 360.0;
01733            ddt = fa->last->lastframe - fa->last->firstframe;
01734            if(ddt == 0)dpl=0.0; /* single frame  zero gradient */
01735          }
01736          if(fa->next == NULL)dpn=0.0;
01737          else{
01738            dpn = fa->next->phi - fa->phi;
01739            if(dpn < -180.0)dpn += 360.0;
01740            if(dpn >  180.0)dpn -= 360.0;
01741            ddt = fa->next->lastframe - fa->next->firstframe;
01742            if(ddt == 0)dpn=0.0;
01743          }
01744          dpl *= fa->tension_s; dpn *= fa->tension_e;
01745          SplinesG(kx,fa->last->phi,fa->last->phi+dp,dpl,dpn);
01746          dp=SplinesR(kx,ratio);
01747          if(dp < -180.0)dp += 360.0;
01748          if(dp >  180.0)dp -= 360.0;
01749          trackangles[Ntrackangles].phi = dp;
01750          dp = fa->theta - fa->last->theta;
01751          if(dp < -180.0)dp += 360.0;
01752          if(dp >  180.0)dp -= 360.0;
01753          if(fa->last->last == NULL)dpl=0.0;
01754          else{
01755            dpl = fa->last->theta - fa->last->last->theta;
01756            if(dpl < -180.0)dpl += 360.0;
01757            if(dpl >  180.0)dpl -= 360.0;
01758            ddt = fa->last->lastframe - fa->last->firstframe;
01759            if(ddt == 0)dpl=0.0;
01760          }
01761          if(fa->next == NULL)dpn=0.0;
01762          else{
01763            dpn = fa->next->theta - fa->theta;
01764            if(dpn < -180.0)dpn += 360.0;
01765            if(dpn >  180.0)dpn -= 360.0;
01766            ddt = fa->next->lastframe - fa->next->firstframe;
01767            if(ddt == 0)dpn=0.0;
01768          }
01769          dpl *= fa->tension_s; dpn *= fa->tension_e;
01770          SplinesG(kx,fa->last->theta,fa->last->theta+dp,dpl,dpn);
01771          dp=SplinesR(kx,ratio);
01772          if(dp < -180.0)dp += 360.0;
01773          if(dp >  180.0)dp -= 360.0;
01774          trackangles[Ntrackangles].theta = dp;
01775          dp = fa->alpha - fa->last->alpha;
01776          if(dp < -180.0)dp += 360.0;
01777          if(dp >  180.0)dp -= 360.0;
01778          if(fa->last->last == NULL)dpl=0.0;
01779          else{
01780            dpl = fa->last->alpha - fa->last->last->alpha;
01781            if(dpl < -180.0)dpl += 360.0;
01782            if(dpl >  180.0)dpl -= 360.0;
01783            ddt = fa->last->lastframe - fa->last->firstframe;
01784            if(ddt == 0)dpl=0.0;
01785          }
01786          if(fa->next == NULL)dpn=0.0;
01787          else{
01788            dpn = fa->next->alpha - fa->alpha;
01789            if(dpn < -180.0)dpn += 360.0;
01790            if(dpn >  180.0)dpn -= 360.0;
01791            ddt = fa->next->lastframe - fa->next->firstframe;
01792            if(ddt == 0)dpn=0.0;
01793          }
01794          dpl *= fa->tension_s; dpn *= fa->tension_e;
01795          SplinesG(kx,fa->last->alpha,fa->last->alpha+dp,dpl,dpn);
01796          dp=SplinesR(kx,ratio);
01797          if(dp < -180.0)dp += 360.0;
01798          if(dp >  180.0)dp -= 360.0;
01799          trackangles[Ntrackangles].alpha = dp;
01800        }
01801      }
01802      trackangles[Ntrackangles].ap=fa;
01803      if(i==fa->lastframe)trackangles[Ntrackangles].type=1;
01804      else                trackangles[Ntrackangles].type=0;
01805      Ntrackangles++;
01806    }
01807    fa=fa->next;
01808  }
01809  return 1;
01810 }
01811 
01812 void AnglerOn(void){
01813  node *Np;
01814  short id;
01815  position *Pp;
01816  double x,y,z;
01817  MessageBeep(MB_OK);
01818  return;
01819 #if 0
01820  SelectedActorRotation=NULL;
01821  if(SelectedNode == NULL){
01822    SendPrgmQuery(IDQ_NOACTORSELECTED,0);
01823    return;
01824  }
01825  if(Nframes == 1){
01826    SendPrgmQuery(IDQ_MUSTEXCEED1FRAME,0);
01827    return;
01828  }
01829  key_action_tool=gToolFlags.flagR;
01830  if(!SetupActorTrack(SelectedNode))return;
01831  if(!SetupActorAngles(SelectedNode)){
01832   FreeActorAngles(); return;
01833  }
01834  EDIT_ACTION=YES;
01835  tool=TRACKER; subtool=ANGLER;
01836  if(!IsWindow(ghwndDlgTools)){
01837    ghwndDlgTools=CreateDialog(ghinst_main,MAKEINTRESOURCE(DLG_DIRECT),
01838                                  ghwnd_main,(DLGPROC)DirectorToolDlgProc);
01839    if(IsWindow(ghwndDlgTools))ShowWindow(ghwndDlgTools,SW_SHOW);
01840    SetFocus(ghwnd_main);
01841  }
01842  ReDrawStageDisplay(TRUE);
01843 #endif
01844 }
01845 
01846 void AnglerOff(short redraw){
01847   SelectedActorRotation=NULL;
01848   FreeActorAngles();
01849   FreeActorTrack();
01850   if(IsWindow(ghwndDlgTools)){
01851     DestroyWindow(ghwndDlgTools);
01852     ghwndDlgTools=NULL;
01853   }
01854   tool=NOTOOL;
01855   if(redraw)ReDrawStageDisplay(TRUE);
01856 }
01857 
01858 void AngleKeyFrame(int x, int y){
01859  position *pp;
01860  align    *ap;
01861  int i,k,xo,oldROP[3];
01862  long j,id,type;
01863  double d,dmin,drange;
01864  int sho,svo,ifd,ild;
01865  POINT pt;
01866  HCURSOR hSaveCursor;
01867  long evTime;
01868  if(trackpoints == NULL || trackangles == NULL || SelectedNode == NULL)return;
01869  if(View == TRIVIEW){ifd=0;ild=3;}
01870  else               {ifd=ActiveView; ild=ifd+1;}
01871  if(grid_on){
01872    GetWindowCoords(ActiveView,NpointerX,NpointerY,NpointerZ,&x,&y);
01873  }
01874  id = -1; type=1;
01875  LOOP:
01876  dmin=(double)TVsizeX*(double)TVsizeX;
01877  drange=dmin/32/32;
01878  for(j=0;j<Ntrackpoints;j++){
01879    if(trackpoints[j].type == type && in_stage_triview(trackpoints[j].p)){
01880      GetWindowCoords(ActiveView,trackpoints[j].p[0],
01881        trackpoints[j].p[1],trackpoints[j].p[2],&sho,&svo);
01882      if( (sho > x-4) && (sho < x+4) && (svo > y-4) && (svo < y+4)){
01883        d=(double)(trackpoints[j].p[0]-NpointerX)
01884         *(double)(trackpoints[j].p[0]-NpointerX)
01885         +(double)(trackpoints[j].p[1]-NpointerY)
01886         *(double)(trackpoints[j].p[1]-NpointerY)
01887         +(double)(trackpoints[j].p[2]-NpointerZ)
01888         *(double)(trackpoints[j].p[2]-NpointerZ);
01889        if(d < dmin){
01890          dmin=d;
01891          id=j;
01892        }
01893      }
01894    }
01895  }
01896  if(id < 0){
01897    if(type == 1)type=0;
01898    else return;
01899    goto LOOP;
01900  }
01901  if(id >= Ntrackangles)return;
01902  key_action_tool=gToolFlags.flagR;
01903  if(trackangles[id].type == 0){ /* make a key frame */
01904    char ttt[64];
01905    LoadString(ghinst_main,IDX_MISC_CREATEKEY,res_str,256);
01906    LoadString(ghinst_main,IDX_MISC_CONFIRM,ttt,64);
01907    if(MessageBox(NULL,res_str,ttt,
01908       MB_YESNO|MB_ICONQUESTION|MB_TASKMODAL) != IDYES)return;
01909    for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
01910    DrawActorRotations(ghdc_triview_Bitmap,0);
01911    DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01912    trackangles[id].ap->firstframe=id+2; /* because id starts at 0 */
01913    if(trackangles[id].ap->last == NULL)j=id+1;
01914    else j=trackangles[id].ap->last->lastframe+1;
01915    if((ap=CreateAlign(SelectedNode,j,id+1)) == NULL)goto TOOL_ERROR;
01916    ap->alpha=trackangles[id].alpha;
01917    ap->theta=trackangles[id].theta;
01918    ap->phi  =trackangles[id].phi;
01919    ap->type=trackangles[id].ap->type;
01920    UPDATETIMELINES(IDC_TIMEL_UPDATE)
01921    if(!GetActorAngles(SelectedNode->fali,NULL,0))goto TOOL_ERROR;
01922    DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01923    DrawActorRotations(ghdc_triview_Bitmap,0);
01924    for(k=ifd;k<ild;k++){
01925      oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
01926      InvalidateRect(ghwnd_triview[k],NULL,FALSE);
01927      UpdateWindow(ghwnd_triview[k]);
01928    }
01929    if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
01930    else UpdateGLview(TRUE);
01931    return;
01932  }
01933  else if(key_action_tool > 0){
01934    i=key_action_tool;
01935    ap=trackangles[id].ap;
01936    while (GetAsyncKeyState(VK_LBUTTON) & 0x8000){;}
01937    if(i == 1){ /* time shift */
01938      GetCursorPos(&pt); xo=pt.x;
01939      evTime=GetTickCount()+TIME_DELAY;
01940      do {
01941        if(evTime > GetTickCount())continue;
01942        if(GetAsyncKeyState(VK_LBUTTON) & 0x8000)break;
01943        GetCursorPos(&pt); y=pt.x;
01944        x = y-xo; xo=y;
01945        if(x != 0){
01946          if(x > 0)y=max( 1,min( 45,x));
01947          else     y=min(-1,max(-45,x));
01948 /*         BKIN:  */
01949          if(abs(y) > 5){
01950            for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
01951            DrawActorRotations(ghdc_triview_Bitmap,0);
01952            DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01953            if(ap->next != NULL){
01954              if(y < 0 && ap->lastframe > ap->firstframe){
01955                ap->lastframe--;
01956                ap->next->firstframe--;
01957              }
01958              else if(y > 0 && ap->next->firstframe < ap->next->lastframe){
01959                ap->lastframe++;
01960                ap->next->firstframe++;
01961              }
01962            }
01963            if(!GetActorAngles(SelectedNode->fali,NULL,0))goto TOOL_ERROR;
01964            DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01965            DrawActorRotations(ghdc_triview_Bitmap,0);
01966            for(k=ifd;k<ild;k++){
01967              oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
01968              InvalidateRect(ghwnd_triview[k],NULL,FALSE);
01969              UpdateWindow(ghwnd_triview[k]);
01970            }
01971          }
01972          if(abs(y) < 50){ /* mouse in use do - pause */
01973            evTime=GetTickCount()+TIME_DELAY;
01974            while(GetTickCount() < TIME_DELAY){;}
01975            GetCursorPos(&pt); xo=pt.x;
01976          }
01977        }
01978        evTime=GetTickCount()+TIME_DELAY;
01979      }
01980      while(1);
01981    }
01982    else if(i == 2){ /* delete */
01983      if(ap->last == NULL || ap->next == NULL){
01984        SendPrgmQuery(IDQ_NOENDCHANGE,0);
01985        return;
01986      }
01987      for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
01988      DrawActorRotations(ghdc_triview_Bitmap,0);
01989      DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01990      i=ap->firstframe;
01991      ap=ap->next;
01992      DeleteAlign(SelectedNode,i);
01993      UPDATETIMELINES(IDC_TIMEL_UPDATE)
01994      ap->firstframe=i;
01995      if(!GetActorAngles(SelectedNode->fali,NULL,0))goto TOOL_ERROR;
01996      DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01997      DrawActorRotations(ghdc_triview_Bitmap,0);
01998      for(k=ifd;k<ild;k++){
01999        oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
02000        InvalidateRect(ghwnd_triview[k],NULL,FALSE);
02001        UpdateWindow(ghwnd_triview[k]);
02002      }
02003    }
02004    else if(i == 3){ /* change tension */
02005      for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
02006      DrawActorRotations(ghdc_triview_Bitmap,0);
02007      SelectedActorRotation=ap;
02008      DrawActorRotations(ghdc_triview_Bitmap,0);
02009      for(k=ifd;k<ild;k++){
02010        oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
02011        InvalidateRect(ghwnd_triview[k],NULL,FALSE);
02012        UpdateWindow(ghwnd_triview[k]);
02013      }
02014      GetCursorPos(&pt); xo=pt.x;
02015      evTime=GetTickCount()+TIME_DELAY;
02016      do {
02017        if(evTime > GetTickCount())continue;
02018        if(GetAsyncKeyState(VK_LBUTTON) & 0x8000)break;
02019        GetCursorPos(&pt); y=pt.x;
02020        x = y-xo; xo=y;
02021        if(x != 0){
02022          if(x > 0)y=max( 1,min( 50,x));
02023          else     y=min(-1,max(-50,x));
02024          d=1.0+(double)y/95.0;
02025          for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
02026          DrawActorRotations(ghdc_triview_Bitmap,0);
02027          DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
02028          if((dmin=ap->tension_e * d) > 0.01 && dmin < 1.95)ap->tension_e=dmin;
02029          if(ap->next != NULL){
02030            if((dmin=ap->next->tension_s * d) > 0.01 && dmin < 1.95)
02031              ap->next->tension_s=dmin;
02032          }
02033          if(!GetActorAngles(SelectedNode->fali,NULL,0))goto TOOL_ERROR;
02034          DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
02035          DrawActorRotations(ghdc_triview_Bitmap,0);
02036          for(k=ifd;k<ild;k++){
02037            oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
02038            InvalidateRect(ghwnd_triview[k],NULL,FALSE);
02039            UpdateWindow(ghwnd_triview[k]);
02040          }
02041        }
02042 //       if(key == RETURN || key == SPACE)break;
02043        evTime=GetTickCount()+TIME_DELAY;
02044      }
02045      while(1);
02046      for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
02047      DrawActorRotations(ghdc_triview_Bitmap,0);
02048      SelectedActorRotation=NULL;
02049      DrawActorRotations(ghdc_triview_Bitmap,0);
02050      for(k=ifd;k<ild;k++){
02051        oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
02052        InvalidateRect(ghwnd_triview[k],NULL,FALSE);
02053        UpdateWindow(ghwnd_triview[k]);
02054      }
02055    }
02056    while (GetAsyncKeyState(VK_LBUTTON) & 0x8000){;}
02057    if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
02058    else UpdateGLview(TRUE);
02059    return;
02060  }
02061  ap=trackangles[id].ap;  /* change angles of keyframes */
02062  for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
02063  DrawActorRotations(ghdc_triview_Bitmap,0);
02064  SelectedActorRotation=ap;
02065  DrawActorRotations(ghdc_triview_Bitmap,0);
02066  for(k=ifd;k<ild;k++){
02067    oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
02068    InvalidateRect(ghwnd_triview[k],NULL,FALSE);
02069    UpdateWindow(ghwnd_triview[k]);
02070  }
02071  while (GetAsyncKeyState(VK_LBUTTON) & 0x8000){;}
02072  GetCursorPos(&pt); xo=pt.x;
02073  evTime=GetTickCount()+TIME_DELAY;
02074  do {
02075    if(evTime > GetTickCount())continue;
02076    if(GetAsyncKeyState(VK_LBUTTON) & 0x8000)break;
02077    GetCursorPos(&pt); y=pt.x;
02078    x = y-xo; xo=y;
02079    if(x != 0){
02080      if(x > 0)y=max( 1,min( 45,x));
02081      else     y=min(-1,max(-45,x));
02082      for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
02083      DrawActorRotations(ghdc_triview_Bitmap,0);
02084      DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
02085      if(gToolFlags.flagA == 2 ||
02086         (GetAsyncKeyState(VK_SHIFT   ) & 0x8000)){ /* bank */
02087        ap->theta -= y;if(ap->theta > 180.0)ap->theta= -360+ap->theta;
02088      }
02089      else if(gToolFlags.flagA == 1 ||
02090              (GetAsyncKeyState(VK_CONTROL) & 0x8000)){ /* up/down */
02091        ap->alpha += y;if(ap->alpha > 180.0)ap->alpha= -360+ap->alpha;
02092      }
02093      else{   /* around and about rotation */
02094        ap->phi   += y;if(ap->phi > 180.0)ap->phi= -360+ap->phi;
02095      }
02096      if(!GetActorAngles(SelectedNode->fali,NULL,0))goto TOOL_ERROR;
02097      DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
02098      DrawActorRotations(ghdc_triview_Bitmap,0);
02099      for(k=ifd;k<ild;k++){
02100        oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
02101        InvalidateRect(ghwnd_triview[k],NULL,FALSE);
02102        UpdateWindow(ghwnd_triview[k]);
02103      }
02104    }
02105    evTime=GetTickCount()+TIME_DELAY;
02106  }
02107  while(1);
02108  for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
02109  DrawActorRotations(ghdc_triview_Bitmap,0);
02110  SelectedActorRotation=NULL;
02111  DrawActorRotations(ghdc_triview_Bitmap,0);
02112  for(k=ifd;k<ild;k++){
02113    oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
02114    InvalidateRect(ghwnd_triview[k],NULL,FALSE);
02115    UpdateWindow(ghwnd_triview[k]);
02116  }
02117  if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
02118  else UpdateGLview(TRUE);
02119  return;
02120  TOOL_ERROR:
02121  AnglerOff(1);
02122  return;
02123 }
02124 
02125 void DrawActorRotations(HDC hdc[], short mode){
02126  long j;
02127  DrawActorTrack(hdc,1);
02128  if(trackangles == NULL || trackpoints == NULL || Ntrackpoints != Ntrackangles)return;
02129  for(j=0;j<Ntrackangles;j++){
02130    if(trackangles[j].type)DrawArrow(hdc,trackpoints[j].p,
02131       trackangles[j].phi,
02132       trackangles[j].theta,
02133       trackangles[j].alpha,
02134       0,0.0,TVsizeX/24);
02135    else if(trackangles[j].ap == SelectedActorRotation ||
02136      (trackangles[j].ap->last != NULL &&
02137       trackangles[j].ap->last == SelectedActorRotation))
02138      DrawDirectionLine(hdc,trackpoints[j].p,
02139       trackangles[j].phi,
02140       trackangles[j].theta,
02141       trackangles[j].alpha,
02142       0,0.0,TVsizeX/36);
02143  }
02144 }
02145 
02146 void SwitchTrackerType(void){
02147  /* assume either in SHIFTER or ANGLER */
02148  int oldROP[3],k,ifd,ild;
02149  if(SelectedNode == NULL)return;
02150  if(View == TRIVIEW){ifd=0;ild=3;}
02151  else               {ifd=ActiveView; ild=ifd+1;}
02152  for(k=ifd;k<ild;k++)oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],R2_XORPEN);
02153  if(subtool == SHIFTER){
02154    DrawActorTrack(ghdc_triview_Bitmap,0);
02155    DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
02156    FreeActorTrack();
02157    subtool=ANGLER;
02158    SelectedActorRotation=NULL;
02159    key_action_tool=gToolFlags.flagR;
02160    SetupActorTrack(SelectedNode);
02161    SetupActorAngles(SelectedNode);
02162    DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
02163    DrawActorRotations(ghdc_triview_Bitmap,0);
02164  }
02165  else if(subtool == ANGLER){
02166    DrawActorRotations(ghdc_triview_Bitmap,0);
02167    DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
02168    SelectedActorRotation=NULL;
02169    FreeActorAngles();
02170    FreeActorTrack();
02171    subtool=SHIFTER;
02172    key_action_tool=gToolFlags.flagT;
02173    SetupActorTrack(SelectedNode);
02174    DrawNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
02175    DrawActorTrack(ghdc_triview_Bitmap,0);
02176  }
02177  for(k=ifd;k<ild;k++){
02178    oldROP[k]=SetROP2(ghdc_triview_Bitmap[k],oldROP[k]);
02179    InvalidateRect(ghwnd_triview[k],NULL,FALSE);
02180    UpdateWindow(ghwnd_triview[k]);
02181  }
02182 }
02183 // end rotate tool code
02184 
02185 void EditPathOn(void){
02186  object *Op;
02187  short im;
02188  double sx,sy,sz,ima,x,y,z;
02189  point tp;
02190  if(SelectedNode == NULL){
02191    SendPrgmQuery(IDQ_NOACTORSELECTED,0);
02192    return;
02193  }
02194  if(SelectedNode->type != PATH){
02195    SendPrgmQuery(IDQ_NOPATH,0);
02196    return;
02197  }
02198  EDIT_ACTION=YES;
02199  tool=PATHEDITOR;
02200  SelectedPath=NULL;
02201  SelectedPathPoint=NULL;
02202  ReDrawStageDisplay(TRUE);
02203  if(!IsWindow(ghwndDlgTools)){
02204    ghwndDlgTools=CreateDialog(ghinst_main,MAKEINTRESOURCE(DLG_PATHTOOL),
02205                               ghwnd_main,(DLGPROC)PathToolDlgProc);
02206    if(IsWindow(ghwndDlgTools))ShowWindow(ghwndDlgTools,SW_SHOW);
02207  }
02208 }
02209 
02210 void EditPathOff(short redraw){
02211  tool=NOTOOL;
02212  if(IsWindow(ghwndDlgTools)){
02213    DestroyWindow(ghwndDlgTools);
02214    ghwndDlgTools=NULL;
02215  }
02216  gToolFlags.flagP=0;
02217  if(SelectedPath != NULL)
02218     SelectedPath->pathlength=PathLength(
02219     SelectedPath->firstpathpoint,
02220     SelectedPath->pathtype,
02221     SelectedPath->npathpoints);
02222  SelectedPath=NULL;
02223  SelectedPathPoint=NULL;
02224  if(redraw)ReDrawStageDisplay(TRUE);
02225 }
02226 
02227 
02228 void AdjustPathTension(long window_id){
02229  pathpoint *pp;
02230  int x,y,xo,MickeyX,i,id;
02231  double d,dmin;
02232  POINT pt;
02233  long evTime;
02234  if(SelectedNode == NULL || SelectedPath == NULL ||
02235     (pp=SelectedPathPoint) == NULL)return;
02236  GetCursorPos(&pt); xo=pt.x;
02237  evTime=GetTickCount()+TIME_DELAY;
02238  do {
02239    if(evTime > GetTickCount())continue;
02240    GetCursorPos(&pt); y=pt.x;
02241    x = y-xo; xo=y;
02242    if(x != 0){
02243      if(x > 0)y=max( 1,min( 50,x));
02244      else     y=min(-1,max(-50,x));
02245      d=1.0+(double)y/95.0;
02246      DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,EDITING);
02247      if((dmin=pp->tension_p * d) > 0.01 && dmin < 0.95)pp->tension_p=dmin;
02248      if((dmin=pp->tension_n * d) > 0.01 && dmin < 0.95)pp->tension_n=dmin;
02249      DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,EDITING);
02250      if(View == ONEVIEW)UpdateWindow(ghwnd_current);
02251      else{
02252        for(i=0;i<3;i++)UpdateWindow(ghwnd_triview[i]);
02253      }
02254    }
02255    evTime=GetTickCount()+TIME_DELAY;
02256  }
02257  while(GetAsyncKeyState(VK_LBUTTON) & 0x8000);
02258  if(ghwndOpenGLview == NULL)PerspectiveView(View,1);
02259  else UpdateGLview(TRUE);
02260  return;
02261 }
02262 
02263 void EditPath(void){
02264  int i;
02265  if(gToolFlags.flagP == 3)return; /* tension    */
02266  if(gToolFlags.flagP != 0){       /* add/delete */
02267    DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,EDITING);
02268    SelectedPath=NULL; SelectedPathPoint=NULL;
02269    DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,EDITING);
02270    return;
02271  }
02272  if(SelectedNode == NULL || SelectedPath == NULL ||
02273     SelectedPathPoint == NULL)return;
02274  if((GrabonX != NpointerX)||(GrabonY != NpointerY)||(GrabonZ != NpointerZ)){
02275    DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,EDITING);
02276    SelectedPathPoint->p[0] += NpointerX-GrabonX;
02277    SelectedPathPoint->p[1] += NpointerY-GrabonY;
02278    SelectedPathPoint->p[2] += NpointerZ-GrabonZ;
02279    DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,EDITING);
02280    GrabonX=NpointerX;
02281    GrabonY=NpointerY;
02282    GrabonZ=NpointerZ;
02283    if(View == ONEVIEW)UpdateWindow(ghwnd_current);
02284    else{
02285      for(i=0;i<3;i++)UpdateWindow(ghwnd_triview[i]);
02286    }
02287  }
02288 }
02289 
02290 void AnimatorUndo(void){
02291  int id;
02292  if(tool == GRABBER && SelectedNode != NULL){
02293    DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
02294    NpointerX=lpxx;
02295    NpointerY=lpyy;
02296    NpointerZ=lpzz;
02297    GrabonX=NpointerX; GrabonY=NpointerY;  GrabonZ=NpointerZ;
02298    SetNewPosition(lpx,lpy,lpz,1);
02299    DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
02300    if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
02301    else UpdateGLview(TRUE);
02302  }
02303  else if(tool == ROTATOR && SelectedNode != NULL){
02304    align *Ap;
02305    if((Ap=SelectedNode->fali) != NULL){
02306      while(Ap != NULL){
02307        if(CurrentFrame == Ap->lastframe){
02308          DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
02309          Ap->phi=lpp; Ap->theta=lpt; Ap->alpha=lpa;
02310          DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
02311          if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
02312          else UpdateGLview(TRUE);
02313          break;
02314        }
02315        Ap=Ap->next;
02316      }
02317    }
02318  }
02319  else if(tool == SIZER && SelectedNode != NULL){
02320    size *Xp;
02321    if((Xp=SelectedNode->fsiz) != NULL){
02322      while(Xp != NULL){
02323        if(CurrentFrame == Xp->lastframe){
02324          DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
02325          Xp->Sx=lpt; Xp->Sy=lpp; Xp->Sz=lpa;
02326          DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
02327          if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
02328          else UpdateGLview(TRUE);
02329          break;
02330        }
02331        Xp=Xp->next;
02332      }
02333    }
02334  }
02335 }
02336 
02337 static int PanX,PanY,ZoomX,ZoomY,ZoomRX,ZoomRY;
02338 static BOOL ZoomInFlag=FALSE,PanMoveFlag=FALSE;
02339 static HDC hDCzoom;
02340 
02341 void PanToolUp(int x, int y, BOOL ctrl, BOOL shift, HWND hwnd){
02342  double zf=2.0;
02343  long a,b,c,d,e,f,stor;
02344  tool_down_flag=FALSE;
02345  tool_move_flag=FALSE;
02346  if(ZoomInFlag){
02347    Rectangle(hDCzoom,ZoomX,ZoomY,ZoomRX,ZoomRY);
02348    ReleaseDC(hwnd,hDCzoom);
02349    ZoomInFlag=FALSE;
02350    if(!ctrl)return;
02351    if(TVsizeX <= MINUNIT || TVsizeY <= MINUNIT || TVsizeZ <= MINUNIT){
02352      SendPrgmMessage(IDS_NOZOOMIN,1);
02353      MessageBeep(MB_OK);
02354      return;
02355    }
02356    if(ActiveView == TRITOP){
02357      stor=NpointerZ; NpointerZ=(TVpointZ+TVsizeZ/2);
02358    }
02359    else if(ActiveView == TRIFRONT){
02360      stor=NpointerY; NpointerY=(TVpointY+TVsizeY/2);
02361    }
02362    else{
02363      stor=NpointerX; NpointerX=(TVpointX+TVsizeX/2);
02364    }
02365    GetWorldCoords(ActiveView,&a,&b,&c,(ZoomX+ZoomRX)/2,(ZoomY+ZoomRY)/2);
02366    zf=(double)max(abs(ZoomX-ZoomRX),abs(ZoomY-ZoomRY))/
02367       (double)(max(WindowSizeX[ActiveView],WindowSizeY[ActiveView]));
02368    TVsizeX=(long)((double)TVsizeX*zf);
02369    TVsizeY=(long)((double)TVsizeY*zf);
02370    TVsizeZ=(long)((double)TVsizeZ*zf);
02371    WindowPixelSize=(double)TVsizeZ/(double)WindowSizeY[1];
02372    TVpointX=a-TVsizeX/2; TVcentreX=a;
02373    TVpointY=b-TVsizeY/2; TVcentreY=b;
02374    TVpointZ=c-TVsizeZ/2; TVcentreZ=c;
02375    if(ActiveView == TRITOP)NpointerZ=stor;
02376    else if(ActiveView == TRIFRONT)NpointerY=stor;
02377    else NpointerX=stor;
02378  }
02379  else if(ctrl){
02380    if(TVsizeX <= MINUNIT || TVsizeY <= MINUNIT || TVsizeZ <= MINUNIT){
02381      SendPrgmMessage(IDS_NOZOOMIN,1);
02382      MessageBeep(MB_OK);
02383    }
02384    else{
02385      if(ActiveView == TRITOP){
02386        stor=NpointerZ; NpointerZ=(TVpointZ+TVsizeZ/2);
02387      }
02388      else if(ActiveView == TRIFRONT){
02389        stor=NpointerY; NpointerY=(TVpointY+TVsizeY/2);
02390      }
02391      else{
02392        stor=NpointerX; NpointerX=(TVpointX+TVsizeX/2);
02393      }
02394      GetWorldCoords(ActiveView,&a,&b,&c,x,y);
02395      TVsizeX=(long)((double)TVsizeX/zf);
02396      TVsizeY=(long)((double)TVsizeY/zf);
02397      TVsizeZ=(long)((double)TVsizeZ/zf);
02398      WindowPixelSize=(double)TVsizeZ/(double)WindowSizeY[1];
02399      TVpointX=a-TVsizeX/2; TVcentreX=a;
02400      TVpointY=b-TVsizeY/2; TVcentreY=b;
02401      TVpointZ=c-TVsizeZ/2; TVcentreZ=c;
02402      if(ActiveView == TRITOP)NpointerZ=stor;
02403      else if(ActiveView == TRIFRONT)NpointerY=stor;
02404      else NpointerX=stor;
02405    }
02406  }
02407  else if(shift){
02408    if(TVsizeX >= MAXUNIT || TVsizeY >= MAXUNIT || TVsizeZ >= MAXUNIT){
02409      SendPrgmMessage(IDS_NOZOOMOUT,1);
02410      MessageBeep(MB_OK);
02411    }
02412    else{
02413      if(ActiveView == TRITOP){
02414        stor=NpointerZ; NpointerZ=(TVpointZ+TVsizeZ/2);
02415      }
02416      else if(ActiveView == TRIFRONT){
02417        stor=NpointerY; NpointerY=(TVpointY+TVsizeY/2);
02418      }
02419      else{
02420        stor=NpointerX; NpointerX=(TVpointX+TVsizeX/2);
02421      }
02422      GetWorldCoords(ActiveView,&a,&b,&c,x,y);
02423      TVsizeX=(long)((double)TVsizeX*zf);
02424      TVsizeY=(long)((double)TVsizeY*zf);
02425      TVsizeZ=(long)((double)TVsizeZ*zf);
02426      WindowPixelSize=(double)TVsizeZ/(double)WindowSizeY[1];
02427      TVpointX=a-TVsizeX/2; TVcentreX=a;
02428      TVpointY=b-TVsizeY/2; TVcentreY=b;
02429      TVpointZ=c-TVsizeZ/2; TVcentreZ=c;
02430      if(ActiveView == TRITOP)NpointerZ=stor;
02431      else if(ActiveView == TRIFRONT)NpointerY=stor;
02432      else NpointerX=stor;
02433    }
02434  }
02435  if(NpointerX < TVpointX)NpointerX=TVpointX+TVsizeX/2;
02436  if(NpointerX > TVpointX+TVsizeX)NpointerX=TVpointX+TVsizeX/2;
02437  if(NpointerY < TVpointY)NpointerY=TVpointY+TVsizeY/2;
02438  if(NpointerY > TVpointY+TVsizeY)NpointerY=TVpointY+TVsizeY/2;
02439  if(NpointerZ < TVpointZ)NpointerZ=TVpointZ+TVsizeZ/2;
02440  if(NpointerZ > TVpointZ+TVsizeZ)NpointerZ=TVpointZ+TVsizeZ/2;
02441  ReDrawStageDisplay(TRUE);
02442 }
02443 
02444 BOOL PanToolDown(int x, int y, BOOL ctrl, BOOL shift, HWND hwnd){
02445  PanX=x; PanY=y;
02446  ZoomInFlag=FALSE; PanMoveFlag=FALSE;
02447  ZoomX=x; ZoomY=y;
02448 // if(shift) Patblt
02449  tool_down_flag=TRUE;
02450  tool_move_flag=FALSE;
02451  return TRUE;
02452 }
02453 
02454 void PanToolMove(int x, int y, BOOL ctrl, BOOL shift,HWND hwnd){
02455  unsigned int SaveDrawStatus;
02456  long a,b,c,d,e,f,gqd;
02457  tool_down_flag=TRUE;
02458  tool_move_flag=TRUE;
02459  if(ctrl || ZoomInFlag){
02460    if(!ZoomInFlag && (abs(x-ZoomX) > 2 || abs(y-ZoomY) > 2)){
02461      ZoomInFlag=TRUE;
02462      hDCzoom=GetDC(hwnd);
02463      SelectObject(hDCzoom,GetStockObject(NULL_BRUSH));
02464      SelectObject(hDCzoom,ghSelectedPen);
02465      SetROP2(hDCzoom,R2_XORPEN);
02466 //     SelectPalette(hDCzoom,ghpaletteScreen,FALSE);
02467 //     RealizePalette(hDCzoom);
02468      Rectangle(hDCzoom,ZoomX,ZoomY,ZoomRX,ZoomRY);
02469    }
02470    if(ZoomInFlag){
02471      Rectangle(hDCzoom,ZoomX,ZoomY,ZoomRX,ZoomRY);
02472      ZoomRX=x; ZoomRY=y;
02473      Rectangle(hDCzoom,ZoomX,ZoomY,ZoomRX,ZoomRY);
02474    }
02475    return;
02476  }
02477  else if(shift)return;
02478  PanMoveFlag=TRUE;
02479  GetWorldCoords(ActiveView,&a,&b,&c,PanX,PanY);
02480  GetWorldCoords(ActiveView,&d,&e,&f,x,y);
02481  TVpointX += (a-d);
02482  TVpointY += (b-e);
02483  TVpointZ += (c-f);
02484  TVcentreX += (a-d);
02485  TVcentreY += (b-e);
02486  TVcentreZ += (c-f);
02487  PanX=x; PanY=y;
02488  SaveDrawStatus=DrawStatus;
02489  gqd=global_quickdraw;
02490  global_quickdraw=1;
02491  if(DrawStatus == 0)ReDrawStageDisplay(TRUE);
02492  else               ReDrawQuickDisplay(TRUE);
02493  UpdateWindow(ghwnd_current);
02494  global_quickdraw=gqd;
02495  DrawStatus=SaveDrawStatus;
02496 }
02497 
02498 void ZoomView(int x, int y){
02499  BOOL bRedraw=FALSE;
02500  unsigned int SaveDrawStatus;
02501  int xo;
02502  POINT pt;
02503  long gqd,evTime;
02504  double zf,dx,dy,dz;
02505  tool_down_flag=TRUE;
02506  tool_move_flag=TRUE;
02507  GetCursorPos(&pt); xo=pt.x;
02508  evTime=GetTickCount()+TIME_DELAY;
02509  do {
02510    if(evTime > GetTickCount())continue;
02511    if(!(GetAsyncKeyState(VK_LBUTTON) & 0x8000))break;
02512    GetCursorPos(&pt); y=pt.x;
02513    if(y < 1){
02514     x= 0; SetCursorPos(pt.x+20,pt.y); xo=pt.x+20;
02515    }
02516    else if(y > Xres-2){
02517     x= 0; SetCursorPos(pt.x-20,pt.y); xo=pt.x-20;
02518    }
02519    else{
02520      x = y-xo; xo=y;
02521    }
02522    if(x != 0){
02523      dx=(double)(NpointerX-TVpointX)/(double)TVsizeX;
02524      dy=(double)(NpointerY-TVpointY)/(double)TVsizeY;
02525      dz=(double)(NpointerZ-TVpointZ)/(double)TVsizeZ;
02526      if(x > 0){
02527        zf = 1.2+(x-20.0)*(5.0-1.2)/(400-20);
02528        zf = max(zf,1.2);
02529        zf = min(zf,5.0);
02530      }
02531      else{
02532        x = -x;
02533        zf = 0.888-(x-20)*(0.888-0.2)/(400-20);
02534        zf = min(zf,0.83333);
02535        zf = max(zf,0.2);
02536      }
02537      if(zf < 1.0 &&
02538         (TVsizeX >= MAXUNIT || TVsizeY >= MAXUNIT || TVsizeZ >= MAXUNIT)){
02539        MessageBeep(MB_OK);
02540      }
02541      else{
02542        TVsizeX=(long)((double)TVsizeX/zf);
02543        TVsizeY=(long)((double)TVsizeY/zf);
02544        TVsizeZ=(long)((double)TVsizeZ/zf);
02545        WindowPixelSize=(double)TVsizeZ/(double)WindowSizeY[1];
02546        TVpointX=NpointerX-(long)(dx*(double)TVsizeX); TVcentreX=TVpointX+TVsizeX/2;
02547        TVpointY=NpointerY-(long)(dy*(double)TVsizeY); TVcentreY=TVpointY+TVsizeY/2;
02548        TVpointZ=NpointerZ-(long)(dz*(double)TVsizeZ); TVcentreZ=TVpointZ+TVsizeZ/2;
02549        SaveDrawStatus=DrawStatus;
02550        gqd=global_quickdraw;
02551        global_quickdraw=1;
02552        if(DrawStatus == 0)ReDrawStageDisplay(TRUE);
02553        else               ReDrawQuickDisplay(TRUE);
02554        UpdateWindow(ghwnd_current);
02555        global_quickdraw=gqd;
02556        DrawStatus=SaveDrawStatus;
02557        bRedraw=TRUE;
02558      }
02559    }
02560    evTime=GetTickCount()+TIME_DELAY;
02561    {MSG msg;
02562     if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
02563       TranslateMessage(&msg);
02564       DispatchMessage(&msg);
02565     }
02566    }
02567  }
02568  while(1);
02569  tool_down_flag=FALSE;
02570  tool_move_flag=FALSE;
02571  if(bRedraw)ReDrawStageDisplay(TRUE);
02572  return;
02573 }
02574 
02575 static short PanTo(long *start, long *centre, long increment){
02576  long newpoint;
02577  newpoint = *start + increment;
02578  if(newpoint > MAXUNIT || newpoint < -MAXUNIT){
02579    SendPrgmQuery(IDQ_PANTOOFAR,0);
02580    return 0;
02581  }
02582  *start = newpoint;
02583  *centre = *centre + increment;
02584  return 1;
02585 }
02586 
02587 void Zoom2(double fraction){
02588  long what_shift,cx,cy,cz;
02589  double zf;
02590  short f;
02591  zf= (1.0+(double)fraction / 5.0);
02592  if(TVsizeX <= MINUNIT || TVsizeY <= MINUNIT || TVsizeZ <= MINUNIT){
02593     SendPrgmQuery(IDQ_NOZOOMIN,0);
02594     return;
02595  }
02596   if(TVsizeX >= MAXUNIT || TVsizeY >= MAXUNIT || TVsizeZ >= MAXUNIT){
02597     SendPrgmQuery(IDQ_NOZOOMOUT,0);
02598     return;
02599  }
02600  cx=TVpointX+TVsizeX/2; cy=TVpointY+TVsizeY/2; cz=TVpointZ+TVsizeZ/2;
02601  TVsizeX=(long)((double)TVsizeX/zf);
02602  TVsizeY=(long)((double)TVsizeY/zf);
02603  TVsizeZ=(long)((double)TVsizeZ/zf);
02604  WindowPixelSize=(double)TVsizeZ/(double)WindowSizeY[1];
02605  TVpointX=cx-TVsizeX/2;
02606  TVpointY=cy-TVsizeY/2;
02607  TVpointZ=cz-TVsizeZ/2;
02608  if(NpointerX < TVpointX)        NpointerX=TVpointX;
02609  if(NpointerX > TVpointX+TVsizeX)NpointerX=TVpointX+TVsizeX;
02610  if(NpointerY < TVpointY)        NpointerY=TVpointY;
02611  if(NpointerY > TVpointY+TVsizeY)NpointerY=TVpointY+TVsizeY;
02612  if(NpointerZ < TVpointZ)        NpointerZ=TVpointZ;
02613  if(NpointerZ > TVpointZ+TVsizeZ)NpointerZ=TVpointZ+TVsizeZ;
02614  ReDrawStageDisplay(TRUE);
02615 }
02616 
02617 void Zoom(int command, int redraw){
02618  long what_shift,cx,cy,cz;
02619  double zf;
02620  short f;
02621  if(command == ZOOMIN || command == ZOOMOUT){
02622    zf=1.2;
02623    if(GetAsyncKeyState(VK_SHIFT  ) & 0x8000)zf=1.5;
02624    if(GetAsyncKeyState(VK_CONTROL) & 0x8000)zf=2.0;
02625    if(GetAsyncKeyState(VK_MENU   ) & 0x8000)zf=4.0;
02626  }
02627  else{
02628    what_shift=TVsizeX/16;
02629    if(GetAsyncKeyState(VK_SHIFT  ) & 0x8000)what_shift=TVsizeX/2;
02630    if(GetAsyncKeyState(VK_CONTROL) & 0x8000)what_shift=TVsizeX;
02631    if(GetAsyncKeyState(VK_MENU   ) & 0x8000)what_shift=TVsizeX*1.5;
02632  }
02633  if(command == ZOOMIN){
02634   if(TVsizeX <= MINUNIT || TVsizeY <= MINUNIT || TVsizeZ <= MINUNIT){
02635     SendPrgmQuery(IDQ_NOZOOMIN,0);
02636     goto EXIT;
02637   }
02638   cx=TVpointX+TVsizeX/2; cy=TVpointY+TVsizeY/2; cz=TVpointZ+TVsizeZ/2;
02639   TVsizeX=(long)((double)TVsizeX/zf);
02640   TVsizeY=(long)((double)TVsizeY/zf);
02641   TVsizeZ=(long)((double)TVsizeZ/zf);
02642   WindowPixelSize=(double)TVsizeZ/(double)WindowSizeY[1];
02643   TVpointX=cx-TVsizeX/2;
02644   TVpointY=cy-TVsizeY/2;
02645   TVpointZ=cz-TVsizeZ/2;
02646  }
02647  else if(command == ZOOMOUT){
02648   if(TVsizeX >= MAXUNIT || TVsizeY >= MAXUNIT || TVsizeZ >= MAXUNIT){
02649     SendPrgmQuery(IDQ_NOZOOMOUT,0);
02650     goto EXIT;
02651   }
02652   cx=TVpointX+TVsizeX/2; cy=TVpointY+TVsizeY/2; cz=TVpointZ+TVsizeZ/2;
02653   TVsizeX=(long)((double)TVsizeX*zf);
02654   TVsizeY=(long)((double)TVsizeY*zf);
02655   TVsizeZ=(long)((double)TVsizeZ*zf);
02656   WindowPixelSize=(double)TVsizeZ/(double)WindowSizeY[1];
02657   TVpointX=cx-TVsizeX/2;
02658   TVpointY=cy-TVsizeY/2;
02659   TVpointZ=cz-TVsizeZ/2;
02660  }
02661  else if(command == RECENTRE){
02662   if(TVsizeX >= MAXUNIT || TVsizeY >= MAXUNIT || TVsizeZ >= MAXUNIT){
02663     goto EXIT;
02664   }
02665   TVpointX=NpointerX-TVsizeX/2; TVcentreX=NpointerX;
02666   TVpointY=NpointerY-TVsizeY/2; TVcentreY=NpointerY;
02667   TVpointZ=NpointerZ-TVsizeZ/2; TVcentreZ=NpointerZ;
02668  }
02669  else if(command == CENTREWORLD){
02670    point TVC,TVP,TVclipMin,TVclipMax;
02671    get_centre_stage(TVC,TVP,TVclipMin,TVclipMax);
02672    TVsizeX = 2*(TVC[0]-TVP[0]);
02673    TVsizeY = 2*(TVC[1]-TVP[1]);
02674    TVsizeZ = 2*(TVC[2]-TVP[2]);
02675    TVpointX=TVP[0]-TVsizeX/10;
02676    TVpointY=TVP[1]-TVsizeY/10;
02677    TVpointZ=TVP[2]-TVsizeZ/10;
02678    TVsizeX += TVsizeX/5; TVsizeY += TVsizeY/5; TVsizeZ += TVsizeZ/5;
02679    TVcentreX=NpointerX=TVC[0];
02680    TVcentreY=NpointerY=TVC[1];
02681    TVcentreZ=NpointerZ=TVC[2];
02682    GetTriview(FALSE);
02683  }
02684  else { /* pan commands */
02685    if(WindowBox_view == 1){
02686     if(command == PANFORWARD ||
02687        command == PANBACK    ||
02688        command == PANRIGHT   ||
02689        command == PANLEFT)what_shift *= -1.0;
02690    }
02691    if(command == PANFORWARD){if(!PanTo(&TVpointY,&TVcentreY,+what_shift))goto EXIT;} /* forward   */
02692    if(command == PANBACK   ){if(!PanTo(&TVpointY,&TVcentreY,-what_shift))goto EXIT;} /* backwards */
02693    if(command == PANRIGHT  ){if(!PanTo(&TVpointX,&TVcentreX,+what_shift))goto EXIT;} /* right     */
02694    if(command == PANLEFT   ){if(!PanTo(&TVpointX,&TVcentreX,-what_shift))goto EXIT;} /* left      */
02695    if(command == PANUP     ){if(!PanTo(&TVpointZ,&TVcentreZ,+what_shift))goto EXIT;} /* up        */
02696    if(command == PANDOWN   ){if(!PanTo(&TVpointZ,&TVcentreZ,-what_shift))goto EXIT;} /* down      */
02697  }
02698  if(NpointerX < TVpointX)        NpointerX=TVpointX;
02699  if(NpointerX > TVpointX+TVsizeX)NpointerX=TVpointX+TVsizeX;
02700  if(NpointerY < TVpointY)        NpointerY=TVpointY;
02701  if(NpointerY > TVpointY+TVsizeY)NpointerY=TVpointY+TVsizeY;
02702  if(NpointerZ < TVpointZ)        NpointerZ=TVpointZ;
02703  if(NpointerZ > TVpointZ+TVsizeZ)NpointerZ=TVpointZ+TVsizeZ;
02704  if(redraw)ReDrawStageDisplay(TRUE);
02705  EXIT:;
02706 }

Generated on Sun Apr 27 14:20:10 2014 for OpenFX by  doxygen 1.5.6