KEYFRAME.C

Go to the documentation of this file.
00001 /* file keyframe.c */
00002 
00003 // The functions in this file handles all the "keyframer" interactions
00004 // and quite a lot of its functions. Since the keyframer is used to
00005 // create time lines and keyframes quite a few of the main program's
00006 // commands call through to these functions.
00007 
00008 #define MODULE_SCRIPT 1
00009 
00010 #include "animate.h"
00011 #include "spin_dll.h"
00012 
00013 static short CreatePathObject(short action, node *Np, object *tempobj,
00014                        long firstframe, long lastframe);
00015 static short SetupTimeLineEndPoints(short current, short *ff, short *lf,
00016                                     short *type,short line, HWND parent);
00017 static void SetFollowAtOptions(position *, HWND);
00018 static short EditEndPoints(short type, object *vp, position *pp, align *ap);
00019 static void ChangeSizeEndPoints(node *Np, short frame, short code);
00020 static void ChangeAlignEndPoints(node *, short, short, HWND, int);
00021 static void ChangePositionEndPoints(node *, short, short, HWND ,int);
00022 static short EditObjectTimeline(node *Np, short frame, short code,
00023                                short in_script);
00024 static void CopyObject(node *Np, short firstframe, short lastframe);
00025 static void CutOutObject(node *Np, short frame);
00026 static void CutOutPosition(node *Np, short frame);
00027 static void CutOutAlign(node *Np, short frame);
00028 static node *LoadStandinModel(short *nmodels, char *title, char *command);
00029 static LRESULT CALLBACK TimelineEditorWndProc(HWND hwnd, UINT msg,
00030                             WPARAM wparam, LPARAM lparam );
00031 static LRESULT CALLBACK TimelineChildWndProc(HWND hwnd, UINT msg,
00032                             WPARAM wparam, LPARAM lparam );
00033 static LRESULT CALLBACK pTimeLineEditDlgProc(HWND hwnd, UINT msg,
00034                                       WPARAM wparam, LPARAM lparam);
00035 static LRESULT CALLBACK rTimeLineEditDlgProc(HWND hwnd, UINT msg,
00036                                           WPARAM wparam, LPARAM lparam);
00037 static LRESULT CALLBACK DlgCommandDlgProc(HWND hwnd, UINT msg,
00038                                           WPARAM wparam, LPARAM lparam);
00039 static LRESULT CALLBACK ReorderDlgProc(HWND hwnd, UINT msg,
00040                                        WPARAM wParam, LPARAM lParam);
00041 static int GetPresets(int nPresets);
00042 static BOOL BuildFromPreset(int action);
00043 static void FreePresets(void);
00044 
00045 static point Cube[8]={ UNIT, UNIT,-UNIT,
00046                       -UNIT, UNIT,-UNIT,
00047                       -UNIT,-UNIT,-UNIT,
00048                        UNIT,-UNIT,-UNIT,
00049                        UNIT, UNIT, UNIT,
00050                       -UNIT, UNIT, UNIT,
00051                       -UNIT,-UNIT, UNIT,
00052                        UNIT,-UNIT, UNIT};
00053 static point Disk[8]={ UNIT, UNIT,-UNIT/10,
00054                       -UNIT, UNIT,-UNIT/10,
00055                       -UNIT,-UNIT,-UNIT/10,
00056                        UNIT,-UNIT,-UNIT/10,
00057                        UNIT, UNIT, UNIT/10,
00058                       -UNIT, UNIT, UNIT/10,
00059                       -UNIT,-UNIT, UNIT/10,
00060                        UNIT,-UNIT, UNIT/10};
00061 
00062 // script part 1
00063 
00064 node *AddOnlyNewNode(HWND hWnd, long action){
00065  node   *Np;
00066  object *Op;
00067 #if __DEMO__
00068  if(Nnodes >= 10){
00069    MessageBox(NULL,"Only 10 actors allowed in demo","Demo",MB_OK);
00070    return NULL;
00071  }
00072 #endif
00073  if((Np=CreateNode()) != NULL){
00074    if(action < 0){
00075      EnableToolPannels(ALL_PANNELS,FALSE);
00076      action=(long)DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_ADDACTOR),hWnd,
00077        (DLGPROC)SelectActorDlgProc,(LPARAM)Np);
00078      EnableToolPannels(ALL_PANNELS,TRUE);
00079    }
00080    if(action == FAIL)strcpy(Np->actorname,"FAIL"); /* dumy text */
00081    if((action == GROUND && Nground > 0) ||
00082       (action == 7 && Nskys > 0) ||
00083       (action == 11 && Ndirectors > 0)
00084      ){
00085       SendPrgmQuery(IDQ_ONLYONEALLOWED,0);
00086       action = FAIL;
00087    }
00088    if(action == GROUND)Nground=1;
00089    if(action == 8)Nrobots++;
00090    if(action == 7)Nskys=1;   /* sky */
00091    if(action == 11)Ndirectors=1;
00092    if(action < 0){
00093      DeleteNode(Np);
00094      Np=NULL;
00095    }
00096    else if(action == 6)Np->type = PARTICLE;
00097    else if(action == 7)Np->type = SKY;
00098    else if(action == 8)Np->type = ROBOT;
00099    else if(action == 9){
00100      Np->type = CAMERA;
00101      if((Op=CreateCostume(Np,1,(short)Nframes)) == NULL){
00102        DeleteNode(Np);
00103        Np=NULL;
00104      }
00105      else{
00106        Ncameras++;
00107        Op->type=Np->type;
00108        Np->fobj->morph=NO;
00109      }
00110    }
00111    else if(action == 10)Np->type = IMAGEP;
00112    else if(action == 11)Np->type = DIRECTOR;
00113    else  Np->type = action;
00114  }
00115  return Np;
00116 }
00117 
00118 void AddQuickActor(long command){
00119   long action;
00120   node *local_node;
00121   Save_UndoA();
00122   if(command < 0){
00123    local_node=AddOnlyNewNode(ghwnd_main,-1);
00124   }
00125   else{
00126     action=NORMAL;
00127     switch (command){
00128      case IDM_ACTOR_QADD_MOD:      action=NORMAL;  break;
00129      case IDM_ACTOR_QADD_MORPH:    action=ANIMOBJ; break;
00130      case IDM_ACTOR_QADD_CAMERA:   action=9;       break;
00131      case IDM_ACTOR_QADD_TARGET:   action=TARGET;  break;
00132      case IDM_ACTOR_QADD_LIGHT:    action=LIGHT;   break;
00133      case IDM_ACTOR_QADD_PATH:     action=PATH;    break;
00134      case IDM_ACTOR_QADD_SKY:      action=7;       break;
00135      case IDM_ACTOR_QADD_GROUND:   action=GROUND;  break;
00136      case IDM_ACTOR_QADD_XIP:      action=10;      break;
00137      case IDM_ACTOR_QADD_ROBOT:    action=8;       break;
00138      case IDM_ACTOR_QADD_CSG:      action=6;       break;
00139      case IDM_ACTOR_QADD_DIRECTOR: action=11;      break;
00140     }
00141     local_node=AddOnlyNewNode(ghwnd_main,action);
00142     if(local_node != NULL){
00143       char tchBuf[64];
00144       long i,tc;
00145       strcpy(local_node->actorname,"Actor");
00146       if     (local_node->type == GROUND)
00147         sprintf(tchBuf,"%s",ObjectTypeList[3]);
00148       else if(local_node->type == SKY)
00149         sprintf(tchBuf,"%s",ObjectTypeList[7]);
00150       else if(local_node->type == DIRECTOR)
00151         sprintf(tchBuf,"%s",ObjectTypeList[11]);
00152       else{
00153         node *nnp;
00154         tc=1;
00155         nnp=FirstNp; while(nnp != NULL){
00156            if(local_node != nnp && local_node->type == nnp->type)tc++;
00157            nnp=nnp->next;
00158         }
00159         if     (local_node->type == NORMAL)i=0;
00160         else if(local_node->type == PATH)i=1;
00161         else if(local_node->type == TARGET)i=2;
00162         else if(local_node->type == LIGHT)i=4;
00163         else if(local_node->type == ANIMOBJ)i=5;
00164         else if(local_node->type == PARTICLE)i=6;
00165         else if(local_node->type == ROBOT)i=8;
00166         else if(local_node->type == CAMERA)i=9;
00167         else if(local_node->type == IMAGEP)i=10;
00168         sprintf(tchBuf,"%s%d",ObjectTypeList[i],tc);
00169       }
00170       strcpy(local_node->actorname,tchBuf);
00171     }
00172   }
00173   if(local_node != NULL){
00174     position *localpp;
00175     if(local_node->type != SKY &&
00176        local_node->type != IMAGEP &&
00177        local_node->type != DIRECTOR &&
00178       (localpp=CreatePosition(local_node,1,Nframes)) != NULL){
00179       localpp->type=SPLINE;
00180       localpp->finish[0]=NpointerX;
00181       localpp->finish[1]=NpointerY;
00182       localpp->finish[2]=NpointerZ;
00183       if(local_node->type != TARGET){
00184         CreateAlign(local_node,1,Nframes);
00185          CreateSize(local_node,1,Nframes);
00186       }
00187     }
00188     if(local_node->type != CAMERA){
00189       if(AddCostumeTimeLine(local_node) == FAIL){
00190         if(local_node->type == GROUND)Nground=0;
00191         if(local_node->type == SKY)Nskys=0;
00192         if(local_node->type == DIRECTOR)Ndirectors=0;
00193         if(local_node->type == ROBOT)Nrobots--;
00194         DeleteNode(local_node);
00195         local_node=NULL;
00196       }
00197     }
00198     if( local_node != NULL &&
00199        (local_node->type == CAMERA || local_node->type == LIGHT)){
00200       /* add target for lights and cameras */
00201       object *Op;
00202       CreateNode();
00203 //      strcpy(MainNp->actorname,"Target");
00204       sprintf(MainNp->actorname,"Target(%s)",local_node->actorname);
00205       MainNp->type=TARGET;
00206       Op=CreateCostume(MainNp,1,(short)Nframes);
00207       Op->type=MainNp->type;
00208       local_node->fali->type=TRACK;
00209       local_node->fali->topath=MainNp;
00210       localpp=CreatePosition(MainNp,1,Nframes);
00211       MainNp->fpos->finish[0]=local_node->fpos->finish[0];
00212       MainNp->fpos->finish[1]=local_node->fpos->finish[1]+TVsizeY/4;
00213       MainNp->fpos->finish[2]=local_node->fpos->finish[2]-TVsizeZ/4;
00214       MainNp->fpos->type=SPLINE;
00215     }
00216     ReDrawStageDisplay(TRUE);
00217     if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
00218     else UpdateGLview(TRUE);
00219     UPDATETIMELINES(IDC_TIMEL_UPDATE)
00220   }
00221 }
00222 
00223 
00224 short GetTimeGapAtFrame(node *Np, long frame,
00225                         short *start_gap, short *end_gap){
00226  object   *Op,*Op1=NULL;
00227  sky      *Sp,*Sp1=NULL;
00228  director *Dp,*Dp1=NULL;
00229  if(Np == NULL)return FAIL;
00230  if(Np->type == SKY){
00231    if((Sp=Np->fsky) != NULL)while(Sp != NULL){
00232      if(frame < Sp->firstframe){
00233        *end_gap=Sp->firstframe-1;
00234        if(Sp->last != NULL)*start_gap=Sp->last->lastframe+1;
00235        else                *start_gap=1;
00236        return OK;
00237      }
00238      Sp1=Sp;
00239      Sp=Sp->next;
00240    }
00241    *end_gap=Nframes;
00242    if(Sp1 != NULL)*start_gap=Sp1->lastframe+1;
00243    else           *start_gap=1;
00244    return OK;
00245  }
00246  else if(Np->type == DIRECTOR){
00247    if((Dp=Np->fdirector) != NULL)while(Dp != NULL){
00248      if(frame < Dp->firstframe){
00249        *end_gap=Dp->firstframe-1;
00250        if(Dp->last != NULL)*start_gap=Dp->last->lastframe+1;
00251        else                *start_gap=1;
00252        return OK;
00253      }
00254      Dp1=Dp;
00255      Dp=Dp->next;
00256    }
00257    *end_gap=Nframes;
00258    if(Dp1 != NULL)*start_gap=Dp1->lastframe+1;
00259    else           *start_gap=1;
00260    return OK;
00261  }
00262  else{
00263    if((Op=Np->fobj) != NULL)while(Op != NULL){
00264      if(frame < Op->firstframe){
00265        *end_gap=Op->firstframe-1;
00266        if(Op->last != NULL)*start_gap=Op->last->lastframe+1;
00267        else                *start_gap=1;
00268        return OK;
00269      }
00270      Op1=Op;
00271      Op=Op->next;
00272    }
00273    *end_gap=Nframes;
00274    if(Op1 != NULL)*start_gap=Op1->lastframe+1;
00275    else           *start_gap=1;
00276    return OK;
00277  }
00278  return FAIL;
00279 }
00280 
00281 object *GetObjectAtFrame(node *Np, long frame){
00282  object   *Op;
00283  sky      *Sp;
00284  director *Dp;
00285  if(Np != NULL){
00286    if(Np->type == SKY){
00287      if((Sp=Np->fsky) != NULL)while(Sp != NULL){
00288        if(frame >= Sp->firstframe && frame <= Sp->lastframe)
00289          return (object *)Sp;
00290        Sp=Sp->next;
00291      }
00292    }
00293    else if(Np->type == DIRECTOR){
00294      if((Dp=Np->fdirector) != NULL)while(Dp != NULL){
00295        if(frame >= Dp->firstframe && frame <= Dp->lastframe)
00296          return (object *)Dp;
00297        Dp=Dp->next;
00298      }
00299    }
00300    else{
00301      if((Op=Np->fobj) != NULL)while(Op != NULL){
00302        if(frame >= Op->firstframe && frame <= Op->lastframe)return Op;
00303        Op=Op->next;
00304      }
00305    }
00306  }
00307  return NULL;
00308 }
00309 
00310 void GetTimelinesAtFrame(node *Np, long frame, object **o,
00311                         position **p, align **a, size **s){
00312  object *Op;
00313  position *Pp;
00314  align *Ap;
00315  size *Sp;
00316  if(Np == NULL)return;
00317  if(Np->type == SKY)return;
00318  if((Op=Np->fobj) != NULL)while(Op != NULL){
00319    if(frame >= Op->firstframe && frame <= Op->lastframe){
00320      *o = Op; break;
00321    }
00322    Op=Op->next;
00323  }
00324  if((Pp=Np->fpos) != NULL)while(Pp != NULL){
00325    if(frame >= Pp->firstframe && frame <= Pp->lastframe){
00326      *p = Pp; break;
00327    }
00328    Pp=Pp->next;
00329  }
00330  if((Ap=Np->fali) != NULL)while(Ap != NULL){
00331    if(frame >= Ap->firstframe && frame <= Ap->lastframe){
00332      *a = Ap; break;
00333    }
00334    Ap=Ap->next;
00335  }
00336  if((Sp=Np->fsiz) != NULL)while(Sp != NULL){
00337    if(frame >= Sp->firstframe && frame <= Sp->lastframe){
00338      *s = Sp; break;
00339    }
00340    Sp=Sp->next;
00341  }
00342  return;
00343 }
00344 
00345 short AddCostumeTimeLine(node *Np){
00346   short ff,lf,retval=FAIL;
00347   point TVC,TVP,TVclipMin,TVclipMax;
00348   if(Np != NULL){
00349     if(GetObjectAtFrame(Np,CurrentFrame) == NULL){
00350       if(GetTimeGapAtFrame(Np,CurrentFrame,&ff,&lf) == OK){
00351         retval=(short)EditObject(Np,ff,lf,NO,NO);
00352         if(Preferences.autocentre  &&
00353            !(GetAsyncKeyState(VK_CONTROL) & 0x8000)){
00354           get_centre_stage(TVC,TVP,TVclipMin,TVclipMax);
00355           TVpointX=TVP[0]; TVpointY=TVP[1]; TVpointZ=TVP[2];
00356           TVsizeX=2*(TVC[0]-TVP[0]);
00357           TVsizeY=2*(TVC[1]-TVP[1]);
00358           TVsizeZ=2*(TVC[2]-TVP[2]);
00359           TVcentreX=NpointerX=TVC[0];
00360           TVcentreY=NpointerY=TVC[1];
00361           TVcentreZ=NpointerZ=TVC[2];
00362           GetTriview(FALSE);  /* this will adjust the TV size */
00363         }
00364         if(retval == OK){
00365           ReDrawStageDisplay(TRUE);
00366           if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
00367           else UpdateGLview(TRUE);
00368         }
00369         return retval;
00370       }
00371       else{
00372         SendPrgmQuery(IDQ_NOADDTIMELINE,0);
00373       }
00374     }
00375     else if(Np->type == SKY || Np->type == IMAGEP)
00376       retval=EditObject(Np,(short)CurrentFrame,(short)CurrentFrame,NO,NO);
00377     else {
00378       SendPrgmQuery(IDQ_COSTUMEEXISTS,0);
00379     }
00380   }
00381   return retval;
00382 }
00383 
00384 short EditObject(node *Np, short firstframe, short lastframe,
00385                  short in_script, short split){
00386   /* action > 0 then use this as preset if editing */
00387   sky      *tempsky;
00388   director *tempdirector;
00389   object   *tempobj;
00390   short action,type,i,n,retval=OK;
00391   HWND hwnd;
00392   struct NP {node *np; short ff,lf;} NP;
00393   struct NC {node *np; object *op,*tp; int d;} NC;
00394 
00395   if(in_script)hwnd=ghwndTimeline; else hwnd=ghwnd_main;
00396 
00397   if(Np->type == SKY){ /* edit SKY */
00398     tempsky = CreateSky(Np,firstframe,lastframe);
00399     if((tempsky == NULL) && fail_op == NO){
00400       NP.np=Np; NP.ff=firstframe; NP.lf=lastframe;
00401       action=(short)DialogBoxParam(ghinst_main,
00402                             MAKEINTRESOURCE(DLG_LINEOPT),hwnd,
00403                             (DLGPROC)ObjectTimelineDlgProc,(LPARAM)&NP);
00404       if(action == 0)DeleteSky(Np,firstframe);
00405       else if(action == 1){
00406         if((tempsky=Np->fsky) != NULL)while(tempsky != NULL){
00407           if(firstframe >= tempsky->firstframe &&
00408              firstframe <= tempsky->lastframe){
00409             EditSkyDialog(tempsky,in_script);
00410             break;
00411           }
00412           tempsky=tempsky->next;
00413         }
00414       }
00415     }
00416     else if(tempsky != NULL){ /* add a new sky */
00417       if(EditSkyDialog(tempsky,in_script) < 0){
00418         DeleteSky(Np,firstframe);
00419         retval=FAIL;
00420       }
00421     }
00422     fail_op=NO;
00423   }
00424 
00425   else if(Np->type == DIRECTOR){ /* edit DIRECTOR */
00426     tempdirector = CreateDirector(Np,firstframe,lastframe);
00427     if((tempdirector == NULL) && fail_op == NO){
00428       NP.np=Np; NP.ff=firstframe; NP.lf=lastframe;
00429       action=(short)DialogBoxParam(ghinst_main,
00430                             MAKEINTRESOURCE(DLG_LINEOPT),hwnd,
00431                             (DLGPROC)ObjectTimelineDlgProc,(LPARAM)&NP);
00432       if(action == 0)DeleteDirector(Np,firstframe);
00433       else if(action == 1){
00434         if((tempdirector=Np->fdirector) != NULL)while(tempdirector != NULL){
00435           if(firstframe >= tempdirector->firstframe &&
00436              firstframe <= tempdirector->lastframe){
00437             EditDirectorDialog(tempdirector,in_script);
00438             break;
00439           }
00440           tempdirector=tempdirector->next;
00441         }
00442       }
00443     }
00444     else if(tempdirector != NULL){ /* add a new director */
00445       if(EditDirectorDialog(tempdirector,in_script) < 0){
00446         DeleteDirector(Np,firstframe);
00447         retval=FAIL;
00448       }
00449     }
00450     fail_op=NO;
00451   }
00452 
00453   else if(Np->type != CAMERA){
00454     tempobj=CreateCostume(Np,firstframe,lastframe);
00455     if(fail_op == YES)fail_op=NO; /* creation failed no memory or overlap */
00456     else if((tempobj == NULL) && (firstframe == lastframe)){/* edit needed */
00457       NP.np=Np; NP.ff=firstframe; NP.lf=lastframe;
00458       if(Np->type == IMAGEP){ /* use a single dialog to get the action */
00459         action=EditObjectTimeline(Np,firstframe,0,in_script);
00460       }
00461       else /* use a general purpose action */
00462         action=(short)DialogBoxParam(ghinst_main,
00463                          MAKEINTRESOURCE(DLG_LINEOPT),hwnd,
00464                          (DLGPROC)ObjectTimelineDlgProc,(LPARAM)&NP);
00465       if     (action == 0)DeleteCostume(Np,firstframe);
00466       else if(action == 1){
00467         EditObjectTimeline(Np,firstframe,0,in_script);
00468       }
00469       else if(action == 3) /* delete bar and shift left */
00470         CutOutObject(Np,firstframe);
00471       else if(action == 4) /* copy to end of time bar */
00472         CopyObject(Np,firstframe,lastframe);
00473       else if(action == 5) /* export robot sequence  */
00474         ExportRobotSequence(Np);
00475       else if(action == 6) /* Set Robot To follow a Specific Path */
00476         SetRobotToWalkPath(Np);
00477     }
00478     else if(tempobj != NULL){/* add a new object */
00479      tempobj->type=Np->type;
00480      CheckRecursiveFollow(Np,firstframe,lastframe);
00481      if(Np->type == NORMAL || (Np->type == ANIMOBJ && tempobj->next != NULL)){
00482        if((i=SelectMorphFileName(gszSCEfile,gszSCEdir,"Select Model",
00483          "(*.MFX)|*.mfx|",hwnd)) > 0){
00484          strcpy(tempobj->name,gszSCEfile);
00485          if(i > 3){ /* used for default if previous then make morph */
00486            i=1; /* don't automatically morph in 95  */
00487          }
00488          tempobj->morph=(short)(i-1);
00489          if(tempobj->morph < 0){
00490            DeleteCostume(Np,firstframe);
00491            retval=FAIL;
00492          }
00493          else if(LoadMeshObject(tempobj->name,tempobj,YES,YES,NO) == FAIL){
00494            DeleteCostume(Np,firstframe);
00495            retval=FAIL;
00496          }
00497        }
00498        else{
00499          DeleteCostume(Np,firstframe);
00500          retval=FAIL;
00501        }
00502      }
00503      else if(Np->type == ANIMOBJ){
00504        DeleteCostume(Np,firstframe); /* this single object is of no use */
00505        LoadAnimObject(Np,firstframe,lastframe,hwnd);
00506      }
00507      else if(Np->type == GROUND){
00508        if(EditGroundDialog(tempobj,in_script) < 0){
00509          DeleteCostume(Np,firstframe);
00510          retval=FAIL;
00511        }
00512      }
00513      else if(Np->type == LIGHT){
00514        tempobj->colour[0]=255;  tempobj->colour[1]=255;
00515        tempobj->colour[2]=255;  tempobj->lighttype=SPHERE;
00516        if(EditLightDialog(tempobj,(int)in_script) < 0){
00517          DeleteCostume(Np,firstframe);
00518          retval=FAIL;
00519        }
00520      }
00521      else if(Np->type == PATH){
00522        action=(short)DialogBox(ghinst_main,
00523                           MAKEINTRESOURCE(DLG_PATHTYPE),
00524                           hwnd,(DLGPROC)PathSetDlgProc);
00525        strcpy(tempobj->name,"PATH1995"); /* used to recognise new paths */
00526        if(action < OPEN){
00527          DeleteCostume(Np,firstframe);
00528          retval=FAIL;
00529        }
00530        else  CreatePathObject(action,Np,tempobj,firstframe,lastframe);
00531      }
00532      else if(Np->type == PARTICLE){
00533        object temp_obj;
00534        tempobj->lighttype=0; tempobj->groundtype=0; tempobj->groundTemperature=10;
00535        tempobj->colour[0]=255; tempobj->colour[1]=255; tempobj->colour[2]=0;
00536        NC.op=tempobj;  NC.tp=&temp_obj; NC.np=Np;  NC.d=0;
00537        action=(short)DialogBoxParam(ghinst_main,
00538                           MAKEINTRESOURCE(DLG_PARTICLE),
00539                           hwnd,(DLGPROC)ParticleDlgProc,(LPARAM)&NC);
00540        if(action < 0 || action == 1){
00541          DeleteCostume(Np,firstframe);  /* escape pressed */
00542          retval=FAIL;
00543        }
00544        else{
00545          for(i=0;i<8;i++){
00546            if(tempobj->lighttype==DISK)CopyPoint(Disk[i],tempobj->outline[i]);
00547            else                        CopyPoint(Cube[i],tempobj->outline[i]);
00548          }
00549        }
00550      }
00551      else if(Np->type == TARGET){ ; }/* no need to load anything */
00552      else if(Np->type == IMAGEP){
00553        if(in_script)hwnd=ghwndTimeline; else hwnd=ghwnd_main;
00554        if((tempobj->xip=EditObjectImageProcess(hwnd,tempobj->xip)) == NULL){
00555          DeleteCostume(Np,firstframe);
00556          retval=FAIL;
00557        }
00558        tempobj->morph=1;
00559      }
00560      else if(Np->type == ROBOT){
00561        if(in_script)hwnd=ghwndTimeline; else hwnd=ghwnd_main;
00562        if(split && tempobj != NULL && tempobj->next != NULL){
00563          strcpy(gszSCEfile,tempobj->next->name);  /* make same name */
00564          strcpy(gszSCEdir,tempobj->next->name);
00565          *FileInPath(gszSCEdir) = '\0';
00566          if(!(GetAsyncKeyState(VK_CONTROL) & 0x8000)){n=1; goto DONT_GET_NEW;} // avoid asking for same costute unless control key is down
00567        }
00568        n=1;
00569        if((split && (SelectSfxFileName(0,gszSCEfile,gszSCEdir,IDX_MISC_SELECTROBOT,
00570           "(*.MFX)|*.mfx|",hwnd) == TRUE)) ||
00571          (n=SelectRobotFileName(gszSCEfile,gszSCEdir,IDX_MISC_SELECTROBOT,  // This is used for non split insertions - offers choice of how may instances
00572             "Skeleton or Sequences|*.mfx;*.rsq|"
00573             "(*.MFX)|*.mfx|"
00574             "(*.RSQ)|*.rsq|",hwnd)) != 0){
00575          DONT_GET_NEW:
00576          strcpy(tempobj->name,gszSCEfile);
00577          tempobj->morph=0;
00578          //if(tempobj->morph < 0){
00579          //  DeleteCostume(Np,firstframe);
00580          //  retval=FAIL;
00581          //}
00582          //else{
00583          { 
00584            if(n < 0){ //Load  robot sequence
00585              i=ImportRobotSequence(n*(-1),Np,gszRSQfile,firstframe,lastframe);
00586            }
00587            else if(n < 2){ // insert single instance or split existing timeline
00588              i=LoadMeshObject(tempobj->name,tempobj,YES,YES,YES);
00589            }
00590            else {  // insert multiple instance 
00591              long dura,step,lastf;
00592              //if(n > 1){char tt[256]; sprintf(tt,"Add %ld instances",n); MessageBox(NULL,tt,NULL,MB_OK);}
00593              dura=lastframe-firstframe+1;
00594              step=dura/n;
00595              if(step < 1)n=1;    // allow only one step
00596              DeleteCostume(Np,firstframe);  // get rid of temporary one first 
00597              for(i=0;i<n;i++){            // now add the multiples
00598                if(i == n-1)lastf=lastframe;
00599                else        lastf=firstframe+step-1;
00600                tempobj=CreateCostume(Np,firstframe,lastf);
00601                if(fail_op == YES){ i=OK; split=0; fail_op=NO; retval=FAIL; break;}
00602                strcpy(tempobj->name,gszSCEfile);
00603                tempobj->morph=0;
00604                if(LoadMeshObject(tempobj->name,tempobj,YES,YES,YES) == FAIL){
00605                  DeleteCostume(Np,firstframe);
00606                  i=OK; split=0; retval=FAIL;
00607                  break;
00608                }
00609                firstframe=lastf+1;
00610              }
00611            }
00612            if(i == FAIL){
00613              DeleteCostume(Np,firstframe);
00614              retval=FAIL;
00615            }
00616            else if(split){
00617              object *Opl,*Opn;
00618              if(tempobj != NULL && (Opl=tempobj->last) != NULL
00619                                 && (Opn=tempobj->next) != NULL){
00620                double mr;
00621                mr=(double)(Opn->lastframe - firstframe+1);
00622                mr=(double)(lastframe - firstframe+1)/mr;
00623                if((n=tempobj->nskeleton) == Opn->nskeleton &&
00624                   tempobj->skeleton != NULL && Opn->skeleton != NULL){
00625                  InterpolateRobot(mr,Opn,Opl);
00626                  for(i=0;i<n;i++){ /* Q is interpolated rotations */
00627                     c4to4((Opn->skeleton+i)->Q,(tempobj->skeleton+i)->R);
00628                  }
00629                }
00630              }
00631            }
00632          }
00633        }
00634        else{
00635          DeleteCostume(Np,firstframe);
00636          retval=FAIL;
00637        }
00638      } // end robot
00639     }
00640   }
00641   UpdateSelectedActor(FALSE);
00642   return retval;
00643 }
00644 
00645 static short CreatePathObject(short action, node *Np, object *tempobj,
00646                        long firstframe, long lastframe){
00647   int i;
00648   tempobj->firstpathpoint=CreateIPointPath(action,Np,(short)firstframe,
00649                  &(tempobj->pathtype),&(tempobj->npathpoints));
00650   if(tempobj->firstpathpoint != NULL){
00651     tempobj->origin[0]=0;   /* leave this alone no offset required */
00652     tempobj->origin[1]=0;   /* for paths !!!!!!!                   */
00653     tempobj->origin[2]=0;
00654     tempobj->pathlength=PathLength(tempobj->firstpathpoint
00655                                   ,tempobj->pathtype
00656                                   ,tempobj->npathpoints);
00657     i=tempobj->lastframe - tempobj->firstframe + 1;
00658     tempobj->v=ReTweenVelocity(tempobj,NULL,i,i,tempobj->pathlength,0);
00659     return 0;
00660   }
00661   DeleteCostume(Np,firstframe);
00662   return -1;
00663 }
00664 
00665 void MakeKey(char com, long frame, node *np){
00666   position *Pp,*tempPp;
00667   align    *Ap,*tempAp;
00668   size     *Xp,*tempXp;
00669   double ratio,sx,sy,sz,ddp,phi,theta,alpha,kx[4],ky[4],kz[4];
00670   point  Offset,dp,spl,spn;
00671   short  ff;
00672   if(np == NULL){
00673     SendPrgmQuery(IDQ_OLD1,0);
00674   }
00675   else if(com == 'P'){
00676     if((Pp=np->fpos) != NULL)while(Pp != NULL){
00677       if(frame >= Pp->firstframe && frame < Pp->lastframe){
00678         if((Pp->last == NULL) || (Pp->firstframe == Pp->lastframe))
00679           CopyPoint(Pp->finish,Offset);
00680         else{
00681           ratio=(double)(frame+1  - Pp->firstframe)
00682                /(double)(Pp->lastframe+1 - Pp->firstframe);
00683           if(Pp->type == TWEEN || Pp->type == FOLLOWAT){
00684             SubPoints(Pp->finish,Pp->last->finish,dp);
00685             ScalePoint(ratio,ratio,ratio,dp,dp);
00686             AddPoints(Pp->last->finish,dp,Offset);
00687           }
00688           else{
00689             if(Pp->last->last != NULL)CopyPoint(Pp->last->last->finish,spl);
00690             else{
00691               SubPoints(Pp->finish,Pp->last->finish,dp);
00692               SubPoints(Pp->last->finish,dp,spl);
00693             }
00694             if(Pp->next != NULL)CopyPoint(Pp->next->finish,spn);
00695             else{
00696               SubPoints(Pp->finish,Pp->last->finish,dp);
00697               AddPoints(Pp->finish,dp,spn);
00698             }
00699             SplinesK(kx,spl[0],Pp->last->finish[0],Pp->finish[0],spn[0]);
00700             SplinesK(ky,spl[1],Pp->last->finish[1],Pp->finish[1],spn[1]);
00701             SplinesK(kz,spl[2],Pp->last->finish[2],Pp->finish[2],spn[2]);
00702             Offset[0] = SplinesP(kx,ratio);
00703             Offset[1] = SplinesP(ky,ratio);
00704             Offset[2] = SplinesP(kz,ratio);
00705           }
00706         }
00707         ff=Pp->firstframe;
00708         Pp->firstframe=frame+1;
00709         tempPp=CreatePosition(np,ff,(short)frame);
00710         if(tempPp == NULL){  /* if not created put everything back */
00711           Pp->firstframe=ff;
00712           return;
00713         }
00714         tempPp->type = Pp->type;
00715         CopyPoint(Offset,tempPp->finish);
00716         tempPp->onpath=Pp->onpath;
00717         tempPp->tension_s=Pp->tension_s;
00718         tempPp->tension_e=Pp->tension_e;
00719         goto MADEKEY;
00720       }
00721       Pp=Pp->next;
00722     }
00723     SendPrgmQuery(IDQ_NOADDKEY,0);
00724   }
00725   else if(com == 'Z'){
00726     if((Xp=np->fsiz) != NULL)while(Xp != NULL){
00727       if(frame >= Xp->firstframe && frame < Xp->lastframe){
00728         if(Xp->last == NULL){
00729           sx=Xp->Sx; sy=Xp->Sy; sz=Xp->Sz;
00730         }
00731         else{
00732           ratio=(double)(frame+1  - Xp->firstframe)
00733                /(double)(Xp->lastframe+1 - Xp->firstframe);
00734           sx = (Xp->Sx - Xp->last->Sx)*ratio + Xp->last->Sx;
00735           sy = (Xp->Sy - Xp->last->Sy)*ratio + Xp->last->Sy;
00736           sz = (Xp->Sz - Xp->last->Sz)*ratio + Xp->last->Sz;
00737         }
00738         ff=Xp->firstframe;
00739         Xp->firstframe=frame+1;
00740         tempXp=CreateSize(np,ff,(short)frame);
00741         if(tempXp == NULL){  /* if not created put everything back */
00742           Xp->firstframe=ff;
00743           return;
00744         }
00745         tempXp->Sx=sx;
00746         tempXp->Sy=sy;
00747         tempXp->Sz=sz;
00748         if(tempXp->last != NULL)memcpy(&tempXp->camera_params,&(tempXp->last->camera_params),sizeof(cameraparam));
00749         goto MADEKEY;
00750       }
00751       Xp=Xp->next;
00752     }
00753     SendPrgmQuery(IDQ_NOADDKEY,0);
00754   }
00755   else if(com == 'A'){
00756     if((Ap=np->fali) != NULL)while(Ap != NULL){
00757       if(frame >= Ap->firstframe && frame < Ap->lastframe){
00758         if((Ap->last == NULL) || (Ap->firstframe == Ap->lastframe)){
00759           phi=Ap->phi;
00760           theta=Ap->theta;
00761           alpha=Ap->alpha;
00762         }
00763         else{
00764           ratio=(double)(frame+1  - Ap->firstframe)
00765                /(double)(Ap->lastframe+1 - Ap->firstframe);
00766           ddp = Ap->phi - Ap->last->phi;
00767           if(ddp < -180.0)ddp += 360.0;
00768           if(ddp >  180.0)ddp -= 360.0;
00769           ddp *= ratio;
00770           ddp += Ap->last->phi;
00771           if(ddp < -180.0)ddp += 360.0;
00772           if(ddp >  180.0)ddp -= 360.0;
00773           phi = ddp;
00774           ddp = Ap->theta - Ap->last->theta;
00775           if(ddp < -180.0)ddp += 360.0;
00776           if(ddp >  180.0)ddp -= 360.0;
00777           ddp *= ratio;
00778           ddp += Ap->last->theta;
00779           if(ddp < -180.0)ddp += 360.0;
00780           if(ddp >  180.0)ddp -= 360.0;
00781           theta = ddp;
00782           ddp = Ap->alpha - Ap->last->alpha;
00783           if(ddp < -180.0)ddp += 360.0;
00784           if(ddp >  180.0)ddp -= 360.0;
00785           ddp *= ratio;
00786           ddp += Ap->last->alpha;
00787           if(ddp < -180.0)ddp += 360.0;
00788           if(ddp >  180.0)ddp -= 360.0;
00789           alpha = ddp;
00790         }
00791         ff=Ap->firstframe;
00792         Ap->firstframe=frame+1;
00793         tempAp=CreateAlign(np,ff,(short)frame);
00794         if(tempAp == NULL){  /* if not created put everything back */
00795           Ap->firstframe=ff;
00796           return;
00797         }
00798         tempAp->type=Ap->type;
00799         tempAp->theta=theta;
00800         tempAp->phi=phi;
00801         tempAp->alpha=alpha;
00802         tempAp->im=Ap->im;     /* needs fixing if tweening   ??? */
00803         tempAp->ima=Ap->ima;
00804         tempAp->topath=Ap->topath;
00805         tempAp->tension_s=Ap->tension_s;
00806         tempAp->tension_e=Ap->tension_e;
00807         goto MADEKEY;
00808       }
00809       Ap=Ap->next;
00810     }
00811     SendPrgmQuery(IDQ_NOADDKEY,0);
00812   }
00813   return;
00814   MADEKEY:
00815   UPDATETIMELINES(IDC_TIMEL_UPDATE)
00816   UpdateSelectedActor(FALSE);
00817   return;
00818 }
00819 
00820 void NextKey(char com){
00821  object   *Op;
00822  position *Pp;
00823  align    *Ap;
00824  size     *Xp;
00825  if(com == 'N'){
00826    if(SelectedNode == NULL)goto KEY_ERR;
00827    if(tool == NOTOOL || tool == NODETOOL || tool == SKELETOR){
00828     if((Op=SelectedNode->fobj) != NULL)while(Op != NULL){
00829      if(CurrentFrame < Op->lastframe){
00830        CurrentFrame=Op->lastframe;
00831        goto GOTIT;
00832      }
00833      Op=Op->next;
00834     }
00835     goto KEY_ERR;
00836    }
00837    else if(tool == GRABBER || (tool == TRACKER && subtool == SHIFTER)){
00838     if((Pp=SelectedNode->fpos) != NULL)while(Pp != NULL){
00839      if(CurrentFrame < Pp->lastframe){
00840        CurrentFrame=Pp->lastframe;
00841        goto GOTIT;
00842      }
00843      Pp=Pp->next;
00844     }
00845     goto KEY_ERR;
00846    }
00847    else if(tool == ROTATOR || (tool == TRACKER && subtool == ANGLER)){
00848     if((Ap=SelectedNode->fali) != NULL)while(Ap != NULL){
00849      if(CurrentFrame < Ap->lastframe){
00850        CurrentFrame=Ap->lastframe;
00851        goto GOTIT;
00852      }
00853      Ap=Ap->next;
00854     }
00855     goto KEY_ERR;
00856    }
00857    else if(tool == SIZER){
00858     if((Xp=SelectedNode->fsiz) != NULL)while(Xp != NULL){
00859      if(CurrentFrame < Xp->lastframe){
00860        CurrentFrame=Xp->lastframe;
00861        goto GOTIT;
00862      }
00863      Xp=Xp->next;
00864     }
00865     goto KEY_ERR;
00866    }
00867    else goto KEY_ERR;
00868  }
00869  else if(com == 'L'){
00870    if(SelectedNode == NULL)goto KEY_ERR;
00871    if(tool == NOTOOL || tool == NODETOOL || tool == SKELETOR){
00872     if((Op=SelectedNode->fobj) != NULL)while(Op != NULL){
00873      if(CurrentFrame <= Op->lastframe){
00874        if(Op->last == NULL)goto KEY_ERR;
00875        CurrentFrame=Op->last->lastframe;
00876        goto GOTIT;
00877      }
00878      Op=Op->next;
00879     }
00880     goto KEY_ERR;
00881    }
00882    else if(tool == GRABBER || (tool == TRACKER && subtool == SHIFTER)){
00883     if((Pp=SelectedNode->fpos) != NULL)while(Pp != NULL){
00884      if(CurrentFrame <= Pp->lastframe){
00885        if(Pp->last == NULL)goto KEY_ERR;
00886        CurrentFrame=Pp->last->lastframe;
00887        goto GOTIT;
00888      }
00889      Pp=Pp->next;
00890     }
00891     goto KEY_ERR;
00892    }
00893    else if(tool == ROTATOR || (tool == TRACKER && subtool == ANGLER)){
00894     if((Ap=SelectedNode->fali) != NULL)while(Ap != NULL){
00895      if(CurrentFrame <= Ap->lastframe){
00896        if(Ap->last == NULL)goto KEY_ERR;
00897        CurrentFrame=Ap->last->lastframe;
00898        goto GOTIT;
00899      }
00900      Ap=Ap->next;
00901     }
00902     goto KEY_ERR;
00903    }
00904    else if(tool == SIZER){
00905     if((Xp=SelectedNode->fsiz) != NULL)while(Xp != NULL){
00906      if(CurrentFrame <= Xp->lastframe){
00907        if(Xp->last == NULL)goto KEY_ERR;
00908        CurrentFrame=Xp->last->lastframe;
00909        goto GOTIT;
00910      }
00911      Xp=Xp->next;
00912     }
00913     goto KEY_ERR;
00914    }
00915    else goto KEY_ERR;
00916  }
00917  goto KEY_ERR;
00918  GOTIT:
00919  ReDrawStageDisplay(TRUE);
00920  UpdateSelectedActor(FALSE);
00921  if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
00922  else UpdateGLview(TRUE);
00923 // SetScrollPos(ghwnd_xscl,SB_CTL,(int)CurrentFrame,TRUE);
00924  SendMessage(ghwnd_xscl,TBM_SETPOS,TRUE,(LPARAM)CurrentFrame);
00925  return;
00926  KEY_ERR:
00927  MessageBeep(MB_OK);
00928  //SendPrgmQuery(IDQ_NOKEYFOUND,0);
00929  return;
00930 }
00931 
00932 short MakeControl(node *Np, char typ, HWND parent){
00933 /* This function assummes that a time line does not exist at that frame */
00934  short code,nextf,lastf,type;
00935  position *Pp;
00936  align    *Ap;
00937  size     *Xp;
00938  nextf=Nframes;
00939  lastf=1;
00940  code=FAIL;
00941  if(typ == 'P'){
00942    if((Pp=Np->fpos) != NULL){
00943     if(Np->type == SKY || Np->type == IMAGEP)return OK;
00944      while(Pp != NULL){
00945        if(Pp->firstframe > CurrentFrame){
00946          nextf=Pp->firstframe-1;
00947          break;
00948        }
00949        lastf=Pp->lastframe+1;
00950        Pp=Pp->next;
00951      }
00952    }
00953    EditPosition(Np,lastf,nextf,0,parent); code=OK;
00954  }
00955  if(typ == 'A'){
00956   if(Np->type == PATH || Np->type == SKY || Np->type == TARGET ||
00957      Np->type == IMAGEP)return OK;
00958   if((Ap=Np->fali) != NULL){
00959      while(Ap != NULL){
00960        if(Ap->firstframe > CurrentFrame){
00961          nextf=Ap->firstframe-1;
00962          break;
00963        }
00964        lastf=Ap->lastframe+1;
00965        Ap=Ap->next;
00966      }
00967    }
00968    EditAlign(Np,lastf,nextf,0,parent); code=OK;
00969  }
00970  if(typ == 'Z'){
00971    if(Np->type == PATH || Np->type == SKY || Np->type == TARGET ||
00972       Np->type == IMAGEP)return OK;
00973    if((Xp=Np->fsiz) != NULL){
00974      while(Xp != NULL){
00975        if(Xp->firstframe > CurrentFrame){
00976          nextf=Xp->firstframe-1;
00977          break;
00978        }
00979        lastf=Xp->lastframe+1;
00980        Xp=Xp->next;
00981      }
00982    }
00983    EditSize(Np,lastf,nextf); code=OK;
00984  }
00985  if(code == FAIL){;}
00986  else{
00987   UPDATETIMELINES(IDC_TIMEL_UPDATE)
00988  }
00989  fail_op=NO;
00990  return code;
00991 }
00992 
00993 short CheckForControl(node *Np, char typ){
00994  position *Pp;
00995  align    *Ap;
00996  size     *Xp;
00997  if(typ == 'P'){
00998    if((Pp=Np->fpos) != NULL){
00999      while(Pp != NULL){
01000        if(Pp->firstframe <= CurrentFrame && Pp->lastframe >= CurrentFrame){
01001          return YES;
01002        }
01003        Pp=Pp->next;
01004      }
01005    }
01006  }
01007  if(typ == 'A'){
01008    if((Ap=Np->fali) != NULL){
01009      while(Ap != NULL){
01010        if(Ap->firstframe <= CurrentFrame && Ap->lastframe >= CurrentFrame){
01011          return YES;
01012        }
01013        Ap=Ap->next;
01014      }
01015    }
01016  }
01017  if(typ == 'Z'){
01018    if((Xp=Np->fsiz) != NULL){
01019      while(Xp != NULL){
01020        if(Xp->firstframe <= CurrentFrame && Xp->lastframe >= CurrentFrame){
01021          return YES;
01022        }
01023        Xp=Xp->next;
01024      }
01025    }
01026  }
01027  return NO;
01028 }
01029 
01030 void EditPosition(node *Np, short firstframe, short lastframe,
01031                   short type, HWND parent){
01032  position *tempposition;
01033  short action;
01034  double x,y,z;
01035  if(Np->type == SKY || Np->type == IMAGEP)return;
01036  tempposition = CreatePosition(Np,firstframe,lastframe);
01037  if(fail_op == YES)fail_op=NO; /* failed no memory or overlap do nothing*/
01038  else if(tempposition != NULL){
01039    tempposition->type=SPLINE;
01040    ChangePositionEndPoints(Np,firstframe,lastframe,parent,YES);
01041  }
01042  else if(firstframe == lastframe){
01043    ChangePositionEndPoints(Np,firstframe,firstframe,parent,NO);
01044  }
01045  UpdateSelectedActor(FALSE);
01046  return;
01047 }
01048 
01049 void EditAlign(node *Np, short firstframe, short lastframe,
01050                short type, HWND parent){
01051  align *tempalign;
01052  short action,dumyi1;
01053  double dr1,dr2,dr3,dr4;
01054  point dumypoint,dp1;
01055  if((Np->type == SKY) || (Np->type == TARGET) ||
01056     (Np->type == PATH)|| (Np->type == IMAGEP))return;
01057  tempalign = CreateAlign(Np,firstframe,lastframe);
01058  if(fail_op == YES)fail_op=NO;    /* failed no memory or overlap */
01059  else if(tempalign != NULL){
01060    ChangeAlignEndPoints(Np,firstframe,lastframe,parent,YES);
01061  }
01062  else if(firstframe == lastframe){
01063    ChangeAlignEndPoints(Np,firstframe,firstframe,parent,NO);
01064  }
01065  UpdateSelectedActor(FALSE);
01066  return;
01067 }
01068 
01069 void EditSize(node *Np, short firstframe, short lastframe){
01070  size *tempsize;
01071  char string[32];
01072  short action;
01073  double sx,sy,sz;
01074  if( (Np->type == SKY)  || (Np->type == TARGET)
01075   || (Np->type == PATH) || (Np->type == IMAGEP))return;
01076  tempsize = CreateSize(Np,firstframe,lastframe);
01077  if(fail_op == YES)fail_op=NO;
01078  else if((tempsize == NULL) && (firstframe == lastframe)){
01079    ChangeSizeEndPoints(Np,firstframe,0);/* edit etc */
01080  }
01081  else if(tempsize != NULL){
01082    sx=tempsize->Sx; sy=tempsize->Sy; sz=tempsize->Sz;
01083    if(Np->type == LIGHT){
01084      if(RequestEditLightSize(&sx,&sy,&sz,tempsize,0) < 0){
01085        DeleteSize(Np,firstframe);
01086        return;
01087      }
01088    }
01089    else if(Np->type == CAMERA){
01090      if(EditCameraSize(&sx,&sy,&sz,tempsize,0) < 0){
01091        DeleteSize(Np,firstframe);
01092        return;
01093      }
01094    }
01095    else{
01096      if(RequestEditSize(&sx,&sy,&sz,tempsize,0) < 0){
01097        DeleteSize(Np,firstframe);
01098        return;
01099      }
01100    }
01101    tempsize->Sx=sx; tempsize->Sy=sy; tempsize->Sz=sz;
01102  }
01103  UpdateSelectedActor(FALSE);
01104  return;
01105 }
01106 
01107 // script part 2
01108 
01109 static node *LoadStandinModel(short *, char *, char *);
01110 
01111 static void ChangeSizeEndPoints(node *Np, short frame, short code){
01112   size *tempsize;
01113   char string[24];
01114   short l,f,minf,maxf;
01115   double sx,sy,sz;
01116   int i;
01117   EDIT_ACTION=YES;
01118   if((tempsize = Np->fsiz) != NULL)while(tempsize != NULL){
01119     if(tempsize->firstframe <=frame && tempsize->lastframe >=frame){
01120       if(code == 0){
01121         sx=tempsize->Sx;  sy=tempsize->Sy;  sz=tempsize->Sz;
01122         if(Np->type == LIGHT){
01123           i=RequestEditLightSize(&sx,&sy,&sz,tempsize,1);
01124           if(i == OK){
01125             tempsize->Sx=sx;  tempsize->Sy=sy;  tempsize->Sz=sz;
01126           }
01127           else if(i == 2){
01128             DeleteSize(Np,frame);
01129           }
01130         }
01131         else if(Np->type == CAMERA){
01132           i=(int)EditCameraSize(&sx,&sy,&sz,tempsize,1);
01133           if(i == OK){
01134             tempsize->Sx=sx;  tempsize->Sy=sy;  tempsize->Sz=sz;
01135           }
01136           else if(i == 2){
01137             DeleteSize(Np,frame);
01138           }
01139         }
01140         else{
01141           i=(int)RequestEditSize(&sx,&sy,&sz,tempsize,1);
01142           if(i == OK){
01143             tempsize->Sx=sx;  tempsize->Sy=sy;  tempsize->Sz=sz;
01144           }
01145           else if(i == 2){
01146             DeleteSize(Np,frame);
01147           }
01148         }
01149       }
01150       break;
01151     }
01152     tempsize=tempsize->next;
01153   }
01154   else{
01155     SendPrgmQuery(IDQ_SYNTAXERROR,0);
01156   }
01157 }
01158 
01159 static void ChangeAlignEndPoints(node *Np, short ff, short lf,
01160                                  HWND parent,int new){
01161  int i;
01162  align *Op,Align;
01163  struct NP {node *np; align *ap; int new;} NP;
01164  if((Op=Np->fali) != NULL)while(Op != NULL){
01165   if(Op->firstframe <= ff && Op->lastframe >= lf){
01166     memcpy(&Align,Op,sizeof(align));
01167     NP.np=Np; NP.ap= &Align; NP.new=new;
01168     if((i=(int)DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_TLER),parent,
01169          (DLGPROC)rTimeLineEditDlgProc,(LPARAM)&NP)) >= 0){
01170       EDIT_ACTION=YES;
01171       if(i == 1)DeleteAlign(Np,lf);
01172       else if(i == 2)CutOutAlign(Np,lf);
01173       else memcpy(Op,&Align,sizeof(align));
01174     }
01175     else if(new == YES){
01176       DeleteAlign(Np,lf);
01177     }
01178     CheckRecursiveFollow(Np,Op->firstframe,Op->lastframe);
01179     return;
01180   }
01181   Op=Op->next;
01182  }
01183 }
01184 
01185 static void ChangePositionEndPoints(node *Np, short ff, short lf,
01186                                     HWND parent, int new){
01187  int i;
01188  position *Op,Position;
01189  struct NP {node *np; position *pp; int new;} NP;
01190  if((Op=Np->fpos) != NULL)while(Op != NULL){
01191   if(Op->firstframe <= ff && Op->lastframe >= lf){
01192     memcpy(&Position,Op,sizeof(position));
01193     NP.np=Np; NP.pp= &Position;  NP.new=new;
01194     if((i=(int)DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_TLEP),parent,
01195          (DLGPROC)pTimeLineEditDlgProc,(LPARAM)&NP)) >= 0){
01196       EDIT_ACTION=YES;
01197       if(i == 1)DeletePosition(Np,lf);
01198       else if(i == 2)CutOutPosition(Np,lf);
01199       else memcpy(Op,&Position,sizeof(position));
01200     }
01201     else if(new == YES){
01202       DeletePosition(Np,lf);
01203     }
01204     CheckRecursiveFollow(Np,Op->firstframe,Op->lastframe);
01205     return;
01206   }
01207   Op=Op->next;
01208  }
01209 }
01210 
01211 static short EditObjectTimeline(node *Np, short frame, short code,
01212                                short in_script){
01213  object *Op;
01214  char string[10];
01215  short f,l,minf,maxf,oldff,oldlf,action=-1,action1;
01216  double ref;
01217  HWND hwnd;
01218  EDIT_ACTION=YES;
01219  if(in_script)hwnd=ghwndTimeline; else hwnd=ghwnd_main;
01220  if((Op=Np->fobj) != NULL)while(Op != NULL){
01221   if(Op->firstframe <= frame && Op->lastframe >= frame){
01222    oldff=Op->firstframe; oldlf=Op->lastframe;
01223    if(Op->type == NORMAL || Op->type == ANIMOBJ){
01224      action=(short)DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_COSTUME),
01225                     hwnd,(DLGPROC)EditObjectDlgProc,(LPARAM)Op);
01226    }
01227    else if(Op->type == GROUND){
01228      if(EditGroundDialog(Op,YES) < 0){;}
01229    }
01230    else if(Op->type == LIGHT){
01231      if(EditLightDialog(Op,YES) < 0){;}
01232    }
01233    else if(Op->type == IMAGEP){
01234      action=(short)DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_COSTUMEXIP),
01235                     hwnd,(DLGPROC)EditObjectXipDlgProc,(LPARAM)Op);
01236    }
01237    else if(Op->type == PARTICLE){
01238      struct NC {node *np; object *op,*tp; int d;} NC;
01239      object temp_obj;
01240      NC.op=Op;  NC.tp=&temp_obj; NC.np=Np;  NC.d=1;
01241      action=(short)DialogBoxParam(ghinst_main,
01242                           MAKEINTRESOURCE(DLG_PARTICLE),
01243                           hwnd,(DLGPROC)ParticleDlgProc,(LPARAM)&NC);
01244      if(action == 1){
01245        DeleteCostume(Np,frame);
01246      }
01247    }
01248 //   else if(Op->type == PATH){
01249 //   }
01250    CheckRecursiveFollow(Np,Op->firstframe,Op->lastframe);
01251    return action;
01252   }
01253   Op=Op->next;
01254  }
01255  return action;
01256 }
01257 
01258 static void CopyObject(node *Np, short firstframe, short lastframe){
01259  object *Op,*tempobj,*lastobj;
01260  pathpoint *Ppp,*Qpp;
01261  short endframe,newstart,newend,i;
01262  long sks;
01263  lastobj=NULL;
01264  EDIT_ACTION=YES;
01265  if((Op=Np->fobj) != NULL)while(Op != NULL){lastobj=Op; Op=Op->next; }
01266  if(lastobj == NULL || lastobj->lastframe >= Nframes){
01267    SendPrgmQuery(IDQ_NOCOPYSPACE,0);
01268  }
01269  else if((Op=Np->fobj) != NULL){
01270    endframe=lastobj->lastframe;
01271    while(Op != NULL && Op->firstframe <= lastframe){
01272      if(Op->lastframe >= firstframe){
01273        newstart= endframe+1;
01274        newend  = newstart+(Op->lastframe-Op->firstframe);
01275        if(newend > Nframes)newend=Nframes;
01276        tempobj=CreateCostume(Np,newstart,newend);
01277        if(tempobj == NULL){
01278          SendPrgmQuery(IDQ_COPYFAIL,0);
01279          break;
01280        }
01281        strcpy(tempobj->name,Op->name);
01282        tempobj->morph=Op->morph;
01283        tempobj->morphNo=Op->morphNo;
01284        if(Op->effect != NULL){
01285          tempobj->effect=(char *)X__Malloc(strlen(Op->effect)+1);
01286          strncpy(tempobj->effect,Op->effect,strlen(Op->effect)+1);
01287        }
01288        if(Op->xip != NULL){
01289          tempobj->xip=(char *)X__Malloc(strlen(Op->xip)+1);
01290          strncpy(tempobj->xip,Op->xip,strlen(Op->xip)+1);
01291        }
01292        tempobj->hEffect=Op->hEffect;
01293        strcpy(tempobj->effectname,Op->effectname);
01294        tempobj->type=Op->type;
01295        tempobj->quick_only=Op->quick_only;
01296        tempobj->fileID=Op->fileID;
01297        tempobj->in_ram=Op->in_ram;
01298        tempobj->bWireframe=Op->bWireframe;
01299        tempobj->points=Op->points;
01300        tempobj->edges=Op->edges;
01301        tempobj->nedges=Op->nedges;
01302        tempobj->npoints=Op->npoints;
01303        tempobj->w_frame.Np=Op->w_frame.Np;
01304        tempobj->w_frame.Ne=Op->w_frame.Ne;
01305        tempobj->w_frame.p=Op->w_frame.p;
01306        tempobj->w_frame.e=Op->w_frame.e;
01307        tempobj->nNurbs=Op->nNurbs;
01308        tempobj->Nurbs=Op->Nurbs;
01309        tempobj->bIKchain=Op->bIKchain;
01310        if(Op->nskeleton > 0){
01311          sks=(long)(Op->nskeleton)*(long)sizeof(skel);
01312          if((tempobj->skeleton=(skel *)X__Malloc(sks)) != NULL){
01313            tempobj->nskeleton = Op->nskeleton;
01314            memcpy(tempobj->skeleton,Op->skeleton,sks);
01315          }
01316          else{
01317            tempobj->nskeleton=0;
01318          }
01319        }
01320        tempobj->skid=Op->skid;
01321        CopyPoint(Op->origin,tempobj->origin);
01322        CopyPoint(Op->offset,tempobj->offset);
01323        for(i=0;i<8;i++){
01324          CopyPoint(Op->outline[i],tempobj->outline[i]);
01325        }
01326        tempobj->groundtype=Op->groundtype;
01327        tempobj->groundTemperature=Op->groundTemperature;
01328        tempobj->lighttype=Op->lighttype;
01329        tempobj->light_intensity=Op->light_intensity;
01330        tempobj->depth_cue=Op->depth_cue;
01331        tempobj->depth_cue_c=Op->depth_cue_c;
01332        tempobj->depth_cue_l=Op->depth_cue_l;
01333        tempobj->depth_cue_q=Op->depth_cue_l;
01334        tempobj->self_shadow=Op->self_shadow;
01335        tempobj->cast_shadow=Op->cast_shadow;
01336        tempobj->show_shadow=Op->show_shadow;
01337        tempobj->colour[0]=Op->colour[0];
01338        tempobj->acolour[0]=Op->acolour[0];
01339        tempobj->colour[1]=Op->colour[1];
01340        tempobj->acolour[1]=Op->acolour[1];
01341        tempobj->colour[2]=Op->colour[2];
01342        tempobj->acolour[2]=Op->acolour[2];
01343        tempobj->pathtype=Op->pathtype;
01344        tempobj->npathpoints=Op->npathpoints;
01345        tempobj->pathlength=Op->pathlength;
01346        tempobj->gspec=Op->gspec;
01347        tempobj->gtran=Op->gtran;
01348        tempobj->grefl=Op->grefl;
01349        tempobj->gbump=Op->gbump;
01350        if(Op->npathpoints > 0)
01351        for(i=0,Ppp=NULL,Qpp=Op->firstpathpoint;i<Op->npathpoints;i++){
01352           if(((Ppp=AppendPathPoint(Ppp)) != NULL) && Qpp != NULL){
01353             if(i == 0)tempobj->firstpathpoint=Ppp;
01354             Ppp->status=Qpp->status;
01355             CopyPoint(Qpp->p,Ppp->p);
01356             Ppp->distance=Qpp->distance;
01357             Ppp->ptheta=Qpp->ptheta;
01358             Ppp->pfi=Qpp->pfi;
01359             Ppp->tension_n=Qpp->tension_n;
01360             Ppp->tension_p=Qpp->tension_p;
01361             Qpp=Qpp->next;
01362           }
01363        }
01364        tempobj->pec=NULL;
01365        tempobj->npec=0;
01366        if(Op->v != NULL){            /* copy the velocity specification */
01367          tempobj->v=ReTweenVelocity(Op,Op->v,
01368            (int)(Op->lastframe-Op->firstframe+1),
01369            (int)(tempobj->lastframe-tempobj->firstframe+1),
01370            Op->pathlength,1);
01371        }
01372        memcpy(&(tempobj->particles),&(Op->particles),sizeof(ParticleSystem));
01373        endframe=newend;
01374        CheckRecursiveFollow(Np,newstart,newend);
01375        if(newend == Nframes){
01376          SendPrgmQuery(IDQ_NOCOPYSPACE,0);
01377          break;
01378        }
01379      }
01380      Op=Op->next;
01381    }
01382  }
01383 }
01384 
01385 static void CutOutObject(node *Np, short frame){
01386  object *Op,*Op1;
01387  short ff,lf,df;
01388  EDIT_ACTION=YES;
01389  if((Op=Np->fobj) != NULL)while(Op != NULL){
01390   if((ff=Op->firstframe) <= frame && (lf=Op->lastframe) >= frame){
01391     df=Op->lastframe - Op->firstframe+1;
01392     Op1=Op->next;
01393     DeleteCostume(Np,frame);
01394     while(Op1 != NULL){
01395       Op1->firstframe -= df;
01396       Op1->lastframe  -= df;
01397       CheckRecursiveFollow(Np,Op1->firstframe,Op1->lastframe);
01398       Op1=Op1->next;
01399     }
01400     return;
01401   }
01402   Op=Op->next;
01403  }
01404 }
01405 
01406 static void CutOutPosition(node *Np, short frame){
01407  position *Op,*Op1;
01408  short ff,lf,df;
01409  EDIT_ACTION=YES;
01410  if((Op=Np->fpos) != NULL)while(Op != NULL){
01411   if((ff=Op->firstframe) <= frame && (lf=Op->lastframe) >= frame){
01412     df=Op->lastframe - Op->firstframe+1;
01413     Op1=Op->next;
01414     DeletePosition(Np,frame);
01415     while(Op1 != NULL){
01416       Op1->firstframe -= df;
01417       Op1->lastframe  -= df;
01418       CheckRecursiveFollow(Np,Op1->firstframe,Op1->lastframe);
01419       Op1=Op1->next;
01420     }
01421     return;
01422   }
01423   Op=Op->next;
01424  }
01425 }
01426 
01427 static void CutOutAlign(node *Np, short frame){
01428  align *Op,*Op1;
01429  short ff,lf,df;
01430  EDIT_ACTION=YES;
01431  if((Op=Np->fali) != NULL)while(Op != NULL){
01432   if((ff=Op->firstframe) <= frame && (lf=Op->lastframe) >= frame){
01433     df=Op->lastframe - Op->firstframe+1;
01434     Op1=Op->next;
01435     DeleteAlign(Np,frame);
01436     while(Op1 != NULL){
01437       Op1->firstframe -= df;
01438       Op1->lastframe  -= df;
01439       CheckRecursiveFollow(Np,Op1->firstframe,Op1->lastframe);
01440       Op1=Op1->next;
01441     }
01442     return;
01443   }
01444   Op=Op->next;
01445  }
01446 }
01447 
01448 static node *LoadStandinModel(short *nmodels, char *title, char *command){
01449  object *Op;
01450  if(CreateNode() == NULL)return NULL;
01451  sprintf(MainNp->actorname,"Model%d",(*nmodels+1));
01452  MainNp->type=NORMAL;
01453  if((Op=CreateCostume(MainNp,1,(short)Nframes)) == NULL || fail_op)goto ERRORS;
01454  Op->type=MainNp->type;
01455  if(SelectFileName(0,gszSCEfile,gszSCEdir,title,
01456                    "(*.MFX)|*.mfx|",ghwnd_main) == TRUE){
01457    strcpy(Op->name,gszSCEfile);
01458    Op->morph=NO;
01459    if(LoadMeshObject(gszSCEfile,Op,YES,YES,NO) == FAIL)
01460      DeleteCostume(MainNp,1);
01461  }
01462  else DeleteCostume(MainNp,1);
01463  (*nmodels)++;
01464  return MainNp;
01465  ERRORS:
01466  DeleteNode(MainNp);
01467  return NULL;
01468 }
01469 
01470 static BOOL CALLBACK FollowAtOptionsDlgProc(HWND hwnd,UINT msg,
01471                                  WPARAM wparam,LPARAM lparam){
01472  char str[32];
01473  position *pp;
01474  BOOL err;
01475  int i;
01476  switch( msg ) {
01477    case WM_PAINT:
01478      PaintDialogBackground(hwnd,ghinst_main);
01479      break;
01480    case WM_INITDIALOG:{
01481        SetWindowLong(hwnd,GWL_USERDATA,lparam);
01482        pp=(position *)lparam;
01483        if(pp->fx)SendDlgItemMessage(hwnd,DLG_FOLLOWAT_LR,BM_SETCHECK,1,0);
01484        if(pp->fy)SendDlgItemMessage(hwnd,DLG_FOLLOWAT_FB,BM_SETCHECK,1,0);
01485        if(pp->fz)SendDlgItemMessage(hwnd,DLG_FOLLOWAT_UD,BM_SETCHECK,1,0);
01486        CentreDialogOnCursor(hwnd);
01487      }
01488      return (TRUE);
01489    case WM_COMMAND:
01490       pp=(position *)GetWindowLong(hwnd,GWL_USERDATA);
01491       switch(LOWORD(wparam)){
01492         case DLG_FOLLOWAT_CANCEL:
01493           EndDialog(hwnd,FAIL);
01494           return(TRUE);
01495         case DLG_FOLLOWAT_OK:
01496           if(SendDlgItemMessage(hwnd,DLG_FOLLOWAT_LR,BM_GETCHECK,0,0))
01497              pp->fx=1; else pp->fx=0;
01498           if(SendDlgItemMessage(hwnd,DLG_FOLLOWAT_FB,BM_GETCHECK,0,0))
01499              pp->fy=1; else pp->fy=0;
01500           if(SendDlgItemMessage(hwnd,DLG_FOLLOWAT_UD,BM_GETCHECK,0,0))
01501              pp->fz=1; else pp->fz=0;
01502           EndDialog(hwnd,OK);
01503           return(TRUE);
01504         default:
01505           break;
01506       }
01507       break;
01508     default: break;
01509  }
01510  return(FALSE);
01511 }
01512 
01513 static void SetFollowAtOptions(position *Pp, HWND parent){
01514  int i;
01515  position pp;
01516  HWND original;
01517  memcpy(&pp,Pp,sizeof(position));
01518  original=GetActiveWindow();
01519  if((i=DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_FOLLOWAT),parent,
01520             (DLGPROC)FollowAtOptionsDlgProc,(LPARAM)&pp)) == OK){
01521    EDIT_ACTION=YES;
01522    memcpy(Pp,&pp,sizeof(position));
01523  }
01524  if(original != NULL)SetActiveWindow(original);
01525  return;
01526 }
01527 
01528 static LRESULT CALLBACK pTimeLineEditDlgProc(HWND hwnd, UINT msg,
01529                                           WPARAM wparam, LPARAM lparam){
01530  static position *dp;
01531  static node     *np;
01532  char title[128];
01533  struct NP {node *np; position *pp; int new;} *NP;
01534  node *OnPath;
01535  BOOL err,status;
01536  int i,TypeID[6]={DLG_TLEP_PT,DLG_TLEP_FOLLOW,DLG_TLEP_ST,
01537                  DLG_TLEP_FOFF,DLG_TLEP_FON,DLG_TLEP_FAT};
01538  int ff,lf;
01539  double x,y,z;
01540  switch( msg ) {
01541    case WM_PAINT:
01542      PaintDialogBackground(hwnd,ghinst_main);
01543      break;
01544    case WM_INITDIALOG:{
01545        EnableToolPannels(ALL_PANNELS,FALSE);
01546        NP=(struct NP *)lparam;
01547        dp=NP->pp; np=NP->np;
01548        sprintf(title,"Movement Timeline for %s Actor",NP->np->actorname);
01549        SendMessage(hwnd,WM_SETTEXT,0,(LPARAM)title);
01550        if(NP->new == YES){
01551          EnableWindow(GetDlgItem(hwnd,DLG_TLEP_DELETE),FALSE);
01552          EnableWindow(GetDlgItem(hwnd,DLG_TLEP_CUT),FALSE);
01553        }
01554        SetDlgItemInt(hwnd,DLG_TLEP_F,dp->firstframe,FALSE);
01555        SetDlgItemInt(hwnd,DLG_TLEP_L,dp->lastframe,FALSE);
01556        if(dp->last != NULL)ff=dp->last->lastframe+1;
01557        else                ff=1;
01558        if(dp->next != NULL)lf=dp->next->firstframe-1;
01559        else                lf=Nframes;
01560        SendDlgItemMessage(hwnd,DLG_TLEP_FS,SPNM_SETRANGE,0,
01561                           MAKELPARAM(ff,lf));
01562        SendDlgItemMessage(hwnd,DLG_TLEP_FS,SPNM_SETCRNTVALUE,
01563                           (WPARAM)dp->firstframe,0);
01564        SendDlgItemMessage(hwnd,DLG_TLEP_FS,SPNM_SETEDITCTRL,0,
01565                           (LPARAM)GetDlgItem(hwnd,DLG_TLEP_F));
01566        SendDlgItemMessage(hwnd,DLG_TLEP_LS,SPNM_SETRANGE,0,
01567                           MAKELPARAM(ff,lf));
01568        SendDlgItemMessage(hwnd,DLG_TLEP_LS,SPNM_SETCRNTVALUE,
01569                           (WPARAM)dp->lastframe,0);
01570        SendDlgItemMessage(hwnd,DLG_TLEP_LS,SPNM_SETEDITCTRL,0,
01571                           (LPARAM)GetDlgItem(hwnd,DLG_TLEP_L));
01572        SendDlgItemMessage(hwnd,TypeID[dp->type],BM_SETCHECK,TRUE,0);
01573        x = (double)(dp->finish[0]-lrulerx); x /= ruler;
01574        y = (double)(dp->finish[1]-lrulery); y /= ruler;
01575        z = (double)(dp->finish[2]-lrulerz); z /= ruler;
01576        sprintf(title,"%.2lf",x); SetDlgItemText(hwnd,DLG_TLEP_X,title);
01577        sprintf(title,"%.2lf",y); SetDlgItemText(hwnd,DLG_TLEP_Y,title);
01578        sprintf(title,"%.2lf",z); SetDlgItemText(hwnd,DLG_TLEP_Z,title);
01579        OnPath=dp->onpath;
01580        if(OnPath != NULL){
01581          SetDlgItemText(hwnd,DLG_TLEP_FOLLOWED,OnPath->actorname);
01582        }
01583        else{
01584          SetDlgItemText(hwnd,DLG_TLEP_FOLLOWED,"<None>");
01585        }
01586        if(OnPath == NULL)status=FALSE; else status=TRUE;
01587        EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FOLLOW),status);
01588        if(OnPath != NULL && OnPath->type == PATH)status=FALSE;
01589        EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FOFF),status);
01590        EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FON),status);
01591        EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FAT),status);
01592        if(dp->type == TWEEN || dp->type == SPLINE)
01593          status=FALSE; else status=TRUE;
01594        EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FOLLOWED),status);
01595        EnableWindow(GetDlgItem(hwnd,DLG_TLEP_X),!status);
01596        EnableWindow(GetDlgItem(hwnd,DLG_TLEP_Y),!status);
01597        EnableWindow(GetDlgItem(hwnd,DLG_TLEP_Z),!status);
01598        if(OnPath == NULL)status=TRUE;
01599        EnableWindow(GetDlgItem(hwnd,DLG_TLEP_SELECT),status);
01600        CentreDialogOnScreen(hwnd);
01601      }
01602      return (TRUE);
01603    case WM_DESTROY:
01604      EnableToolPannels(ALL_PANNELS,TRUE);
01605      break;
01606    case WM_COMMAND:
01607       /****************** NOTE: dont make radio buttons default *****************/
01608       if(dp == NULL)break;
01609       switch(LOWORD(wparam)){
01610         case DLG_TLEP_PT:      i=TWEEN;     goto PT1;
01611         case DLG_TLEP_ST:      i=SPLINE;    goto PT1;
01612         case DLG_TLEP_FOLLOW:  i=FOLLOW;    goto PT1;
01613         case DLG_TLEP_FOFF:    i=FOLLOWOFF; goto PT1;
01614         case DLG_TLEP_FON:     i=FOLLOWON;  goto PT1;
01615         case DLG_TLEP_FAT:     i=FOLLOWAT;
01616           PT1:
01617           dp->type=i;
01618           OnPath=dp->onpath;
01619           if(OnPath == NULL)status=FALSE; else status=TRUE;
01620           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FOLLOW),status);
01621           if(OnPath != NULL && OnPath->type == PATH)status=FALSE;
01622           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FOFF),status);
01623           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FON),status);
01624           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FAT),status);
01625           if(OnPath != NULL)
01626             SetDlgItemText(hwnd,DLG_TLEP_FOLLOWED,OnPath->actorname);
01627           else
01628             SetDlgItemText(hwnd,DLG_TLEP_FOLLOWED,"<None>");
01629           if(dp->type == TWEEN || dp->type == SPLINE)
01630             status=FALSE; else status=TRUE;
01631           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FOLLOWED),status);
01632           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_X),!status);
01633           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_Y),!status);
01634           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_Z),!status);
01635           if(OnPath == NULL)status=TRUE;
01636           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_SELECT),status);
01637           break;
01638         case DLG_TLEP_SELECT:
01639           if((OnPath=SelectNode(dp->pnodename,NO,hwnd)) != NULL){
01640             if(OnPath == np){
01641               MessageBox(hwnd,"Actor Cannot Follow Itself",NULL,MB_OK);
01642               break;
01643             }
01644             dp->onpath=OnPath;
01645             strcpy(dp->pnodename,OnPath->actorname);
01646           }
01647           OnPath=dp->onpath;
01648           if(OnPath == NULL)status=FALSE; else status=TRUE;
01649           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FOLLOW),status);
01650           if(OnPath != NULL && OnPath->type == PATH)status=FALSE;
01651           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FOFF),status);
01652           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FON),status);
01653           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FAT),status);
01654           if(OnPath != NULL)
01655             SetDlgItemText(hwnd,DLG_TLEP_FOLLOWED,OnPath->actorname);
01656           else
01657             SetDlgItemText(hwnd,DLG_TLEP_FOLLOWED,"<None>");
01658           if(dp->type == TWEEN || dp->type == SPLINE)
01659             status=FALSE; else status=TRUE;
01660           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_FOLLOWED),status);
01661           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_X),!status);
01662           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_Y),!status);
01663           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_Z),!status);
01664           if(OnPath == NULL)status=TRUE;
01665           EnableWindow(GetDlgItem(hwnd,DLG_TLEP_SELECT),status);
01666           break;
01667         case DLG_TLEP_COPY:
01668           if(dp->last != NULL){
01669             x = (double)(dp->last->finish[0]-lrulerx); x /= ruler;
01670             y = (double)(dp->last->finish[1]-lrulery); y /= ruler;
01671             z = (double)(dp->last->finish[2]-lrulerz); z /= ruler;
01672             sprintf(title,"%.2lf",x); SetDlgItemText(hwnd,DLG_TLEP_X,title);
01673             sprintf(title,"%.2lf",y); SetDlgItemText(hwnd,DLG_TLEP_Y,title);
01674             sprintf(title,"%.2lf",z); SetDlgItemText(hwnd,DLG_TLEP_Z,title);
01675           }
01676           break;
01677         case IDCANCEL:
01678         case DLG_TLEP_CANCEL:
01679           EndDialog(hwnd,-1);
01680           return(TRUE);
01681         case DLG_TLEP_DELETE:
01682           EndDialog(hwnd,1);
01683           return(TRUE);
01684         case DLG_TLEP_CUT:
01685           EndDialog(hwnd,2);
01686           return(TRUE);
01687         case IDOK:
01688         case DLG_TLEP_OK:
01689           if(dp->type == TWEEN || dp->type == SPLINE){
01690              dp->onpath=NULL; dp->pnodename[0]='\0';
01691           }
01692           if(dp->type == FOLLOWAT)SetFollowAtOptions(dp,hwnd);
01693           i=GetDlgItemInt(hwnd,DLG_TLEP_F,&err,FALSE);
01694           if(err)dp->firstframe=(short)i;
01695           if(dp->last != NULL && dp->firstframe <= dp->last->lastframe)
01696              dp->firstframe=dp->last->lastframe+1;
01697           if(dp->firstframe < 1)dp->firstframe=1;
01698           i=GetDlgItemInt(hwnd,DLG_TLEP_L,&err,FALSE);
01699           if(err)dp->lastframe=(short)i;
01700           if(dp->next != NULL && dp->lastframe >= dp->next->firstframe)
01701              dp->lastframe=dp->next->firstframe-1;
01702           if(dp->lastframe > Nframes)dp->lastframe=Nframes;
01703           if(dp->lastframe < dp->firstframe)dp->lastframe=dp->firstframe;
01704           if(GetDlgItemText(hwnd,DLG_TLEP_X,title,10) != 0){
01705              x=atof(title); x *= ruler; dp->finish[0]=lrulerx+(long)x;
01706           }
01707           if(GetDlgItemText(hwnd,DLG_TLEP_Y,title,10) != 0){
01708              y=atof(title); y *= ruler; dp->finish[1]=lrulery+(long)y;
01709           }
01710           if(GetDlgItemText(hwnd,DLG_TLEP_Z,title,10) != 0){
01711              z=atof(title); z *= ruler; dp->finish[2]=lrulerz+(long)z;
01712           }
01713           EndDialog(hwnd,0);
01714           return(TRUE);
01715         default:
01716           break;
01717       }
01718       break;
01719     default: break;
01720  }
01721  return(FALSE);
01722 }
01723 
01724 static LRESULT CALLBACK rTimeLineEditDlgProc(HWND hwnd, UINT msg,
01725                                           WPARAM wparam, LPARAM lparam){
01726  static align *dp;
01727  static node  *np;
01728  node *OnPath;
01729  BOOL err,status;
01730  char title[128];
01731  struct NP {node *np; align *ap; int new;} *NP;
01732  int i,TypeID[5]={DLG_TLER_PT,DLG_TLER_TOPATH,DLG_TLER_LOOKAT,
01733                   DLG_TLER_MIMIC,DLG_TLER_ST},
01734        InternalID[4]={DLG_TLER_NA,DLG_TLER_VA,DLG_TLER_SA,DLG_TLER_FA};
01735  int ff,lf;
01736  double a;
01737  switch( msg ) {
01738    case WM_PAINT:
01739      PaintDialogBackground(hwnd,ghinst_main);
01740      break;
01741    case WM_INITDIALOG:{
01742        dp=NULL;
01743        EnableToolPannels(ALL_PANNELS,FALSE);
01744        NP=(struct NP *)lparam;
01745        dp=NP->ap;
01746        np=NP->np;
01747        sprintf(title,"Rotation Timeline for %s Actor",NP->np->actorname);
01748        SendMessage(hwnd,WM_SETTEXT,0,(LPARAM)title);
01749        if(NP->new == YES){
01750          EnableWindow(GetDlgItem(hwnd,DLG_TLER_DELETE),FALSE);
01751          EnableWindow(GetDlgItem(hwnd,DLG_TLER_CUT),FALSE);
01752        }
01753        SetDlgItemInt(hwnd,DLG_TLER_F,dp->firstframe,FALSE);
01754        SetDlgItemInt(hwnd,DLG_TLER_L,dp->lastframe,FALSE);
01755        if(dp->last != NULL)ff=dp->last->lastframe+1;
01756        else                ff=1;
01757        if(dp->next != NULL)lf=dp->next->firstframe-1;
01758        else                lf=Nframes;
01759        SendDlgItemMessage(hwnd,DLG_TLER_FS,SPNM_SETRANGE,0,
01760                           MAKELPARAM(ff,lf));
01761        SendDlgItemMessage(hwnd,DLG_TLER_FS,SPNM_SETCRNTVALUE,
01762                           (WPARAM)dp->firstframe,0);
01763        SendDlgItemMessage(hwnd,DLG_TLER_FS,SPNM_SETEDITCTRL,0,
01764                           (LPARAM)GetDlgItem(hwnd,DLG_TLER_F));
01765        SendDlgItemMessage(hwnd,DLG_TLER_LS,SPNM_SETRANGE,0,
01766                           MAKELPARAM(ff,lf));
01767        SendDlgItemMessage(hwnd,DLG_TLER_LS,SPNM_SETCRNTVALUE,
01768                           (WPARAM)dp->lastframe,0);
01769        SendDlgItemMessage(hwnd,DLG_TLER_LS,SPNM_SETEDITCTRL,0,
01770                           (LPARAM)GetDlgItem(hwnd,DLG_TLER_L));
01771        SendDlgItemMessage(hwnd,TypeID[dp->type],BM_SETCHECK,TRUE,0);
01772        sprintf(title,"%.2lf",dp->theta);
01773        SetDlgItemText(hwnd,DLG_TLER_THETA,title);
01774        sprintf(title,"%.2lf",dp->alpha);
01775        SetDlgItemText(hwnd,DLG_TLER_ALPHA,title);
01776        sprintf(title,"%.2lf",dp->phi);
01777        SetDlgItemText(hwnd,DLG_TLER_PHI,title);
01778        OnPath=dp->topath;
01779        if(OnPath != NULL){
01780          SetDlgItemText(hwnd,DLG_TLER_FOLLOWED,OnPath->actorname);
01781        }
01782        else{
01783          SetDlgItemText(hwnd,DLG_TLER_FOLLOWED,"<None>");
01784        }
01785        if(OnPath == NULL)status=FALSE; else status=TRUE;
01786        EnableWindow(GetDlgItem(hwnd,DLG_TLER_LOOKAT),status);
01787        EnableWindow(GetDlgItem(hwnd,DLG_TLER_MIMIC),status);
01788        if(OnPath != NULL && OnPath->type != PATH)status=FALSE;
01789        EnableWindow(GetDlgItem(hwnd,DLG_TLER_TOPATH),status);
01790        if(dp->type == TWEEN || dp->type == SPLINEA)
01791          status=FALSE; else status=TRUE;
01792        EnableWindow(GetDlgItem(hwnd,DLG_TLER_FOLLOWED),status);
01793        EnableWindow(GetDlgItem(hwnd,DLG_TLER_THETA),!status);
01794        EnableWindow(GetDlgItem(hwnd,DLG_TLER_ALPHA),!status);
01795        EnableWindow(GetDlgItem(hwnd,DLG_TLER_PHI),!status);
01796        if(OnPath == NULL)status=TRUE;
01797        EnableWindow(GetDlgItem(hwnd,DLG_TLER_SELECT),status);
01798        if(NP->np->type == CAMERA || NP->np->type == GROUND){
01799          EnableWindow(GetDlgItem(hwnd,DLG_TLER_NA),FALSE);
01800          EnableWindow(GetDlgItem(hwnd,DLG_TLER_VA),FALSE);
01801          EnableWindow(GetDlgItem(hwnd,DLG_TLER_SA),FALSE);
01802          EnableWindow(GetDlgItem(hwnd,DLG_TLER_FA),FALSE);
01803          EnableWindow(GetDlgItem(hwnd,DLG_TLER_CLOCK),FALSE);
01804          EnableWindow(GetDlgItem(hwnd,DLG_TLER_ACLOCK),FALSE);
01805        }
01806        else{
01807          SendDlgItemMessage(hwnd,InternalID[dp->im],BM_SETCHECK,TRUE,0);
01808          if(dp->ima < 0.0)
01809               SendDlgItemMessage(hwnd,DLG_TLER_CLOCK,BM_SETCHECK,TRUE,0);
01810          else SendDlgItemMessage(hwnd,DLG_TLER_ACLOCK,BM_SETCHECK,TRUE,0);
01811        }
01812        CentreDialogOnScreen(hwnd);
01813      }
01814      return (TRUE);
01815    case WM_DESTROY:
01816      EnableToolPannels(ALL_PANNELS,TRUE);
01817      break;
01818    case WM_COMMAND:
01819       if(dp == NULL)break;
01820       switch(LOWORD(wparam)){
01821         case DLG_TLER_PT:      i=TWEEN;     goto PT1;
01822         case DLG_TLER_ST:      i=SPLINEA;   goto PT1;
01823         case DLG_TLER_TOPATH:  i=TOPATH;    goto PT1;
01824         case DLG_TLER_LOOKAT:  i=TRACK;     goto PT1;
01825         case DLG_TLER_MIMIC:   i=COPY;      goto PT1;
01826           PT1:
01827           dp->type=i;
01828           OnPath=dp->topath;
01829           if(OnPath == NULL)status=FALSE; else status=TRUE;
01830           EnableWindow(GetDlgItem(hwnd,DLG_TLER_LOOKAT),status);
01831           EnableWindow(GetDlgItem(hwnd,DLG_TLER_MIMIC),status);
01832           if(OnPath != NULL && OnPath->type != PATH)status=FALSE;
01833           EnableWindow(GetDlgItem(hwnd,DLG_TLER_TOPATH),status);
01834           if(OnPath != NULL)
01835             SetDlgItemText(hwnd,DLG_TLER_FOLLOWED,OnPath->actorname);
01836           else
01837             SetDlgItemText(hwnd,DLG_TLER_FOLLOWED,"<None>");
01838           if(dp->type == TWEEN || dp->type == SPLINEA)
01839             status=FALSE; else status=TRUE;
01840           EnableWindow(GetDlgItem(hwnd,DLG_TLER_FOLLOWED),status);
01841           EnableWindow(GetDlgItem(hwnd,DLG_TLER_THETA),!status);
01842           EnableWindow(GetDlgItem(hwnd,DLG_TLER_ALPHA),!status);
01843           EnableWindow(GetDlgItem(hwnd,DLG_TLER_PHI),!status);
01844           if(OnPath == NULL)status=TRUE;
01845           EnableWindow(GetDlgItem(hwnd,DLG_TLER_SELECT),status);
01846           break;
01847         case DLG_TLER_SELECT:
01848           if((OnPath=SelectNode(dp->anodename,NO,hwnd)) != NULL){
01849             if(OnPath == np){
01850               MessageBox(hwnd,"Actor Cannot Look at Itself",NULL,MB_OK);
01851               break;
01852             }
01853             dp->topath=OnPath;
01854             strcpy(dp->anodename,OnPath->actorname);
01855           }
01856           OnPath=dp->topath;
01857           if(OnPath == NULL)status=FALSE; else status=TRUE;
01858           EnableWindow(GetDlgItem(hwnd,DLG_TLER_LOOKAT),status);
01859           EnableWindow(GetDlgItem(hwnd,DLG_TLER_MIMIC),status);
01860           if(OnPath != NULL && OnPath->type != PATH)status=FALSE;
01861           EnableWindow(GetDlgItem(hwnd,DLG_TLER_TOPATH),status);
01862           if(OnPath != NULL)
01863             SetDlgItemText(hwnd,DLG_TLER_FOLLOWED,OnPath->actorname);
01864           else
01865             SetDlgItemText(hwnd,DLG_TLER_FOLLOWED,"<None>");
01866           if(dp->type == TWEEN || dp->type == SPLINEA)
01867             status=FALSE; else status=TRUE;
01868           EnableWindow(GetDlgItem(hwnd,DLG_TLER_FOLLOWED),status);
01869           EnableWindow(GetDlgItem(hwnd,DLG_TLER_THETA),!status);
01870           EnableWindow(GetDlgItem(hwnd,DLG_TLER_ALPHA),!status);
01871           EnableWindow(GetDlgItem(hwnd,DLG_TLER_PHI),!status);
01872           if(OnPath == NULL)status=TRUE;
01873           EnableWindow(GetDlgItem(hwnd,DLG_TLER_SELECT),status);
01874           break;
01875         case DLG_TLER_NA:  dp->im=0;  break;
01876         case DLG_TLER_VA:  dp->im=1;  break;
01877         case DLG_TLER_SA:  dp->im=2;  break;
01878         case DLG_TLER_FA:  dp->im=3;  break;
01879         case DLG_TLER_CLOCK:
01880           dp->ima = -1.0;
01881           break;
01882         case DLG_TLER_ACLOCK:
01883           dp->ima = 1.0;
01884           break;
01885         case DLG_TLER_COPY:
01886           if(dp->last != NULL){
01887             sprintf(title,"%.2lf",dp->last->theta);
01888             SetDlgItemText(hwnd,DLG_TLER_THETA,title);
01889             sprintf(title,"%.2lf",dp->last->alpha);
01890             SetDlgItemText(hwnd,DLG_TLER_ALPHA,title);
01891             sprintf(title,"%.2lf",dp->last->phi);
01892             SetDlgItemText(hwnd,DLG_TLER_PHI,title);
01893           }
01894           break;
01895         case IDCANCEL:
01896         case DLG_TLER_CANCEL:
01897           EndDialog(hwnd,-1);
01898           return(TRUE);
01899         case DLG_TLER_DELETE:
01900           EndDialog(hwnd,1);
01901           return(TRUE);
01902         case DLG_TLER_CUT:
01903           EndDialog(hwnd,2);
01904           return(TRUE);
01905         case IDOK:
01906         case DLG_TLER_OK:
01907           if(dp->type == TWEEN || dp->type == SPLINEA){
01908              dp->topath=NULL; dp->anodename[0]='\0';
01909           }
01910           i=GetDlgItemInt(hwnd,DLG_TLER_F,&err,FALSE);
01911           if(err)dp->firstframe=(short)i;
01912           if(dp->last != NULL && dp->firstframe <= dp->last->lastframe)
01913              dp->firstframe=dp->last->lastframe+1;
01914           if(dp->firstframe < 1)dp->firstframe=1;
01915           i=GetDlgItemInt(hwnd,DLG_TLER_L,&err,FALSE);
01916           if(err)dp->lastframe=(short)i;
01917           if(dp->next != NULL && dp->lastframe >= dp->next->firstframe)
01918              dp->lastframe=dp->next->firstframe-1;
01919           if(dp->lastframe > Nframes)dp->lastframe=Nframes;
01920           if(dp->lastframe < dp->firstframe)dp->lastframe=dp->firstframe;
01921           if(GetDlgItemText(hwnd,DLG_TLER_ALPHA,title,10) != 0){
01922              a=atof(title);
01923              if(a >= -360.0 && a <= 360.0)dp->alpha=a;
01924           }
01925           if(GetDlgItemText(hwnd,DLG_TLER_THETA,title,10) != 0){
01926              a=atof(title);
01927              if(a >= -360.0 && a <= 360.0)dp->theta=a;
01928           }
01929           if(GetDlgItemText(hwnd,DLG_TLER_PHI,title,10) != 0){
01930              a=atof(title);
01931              if(a >= -360.0 && a <= 360.0)dp->phi=a;
01932           }
01933           EndDialog(hwnd,0);
01934           return(TRUE);
01935         default:
01936           break;
01937       }
01938       break;
01939     default: break;
01940  }
01941  return(FALSE);
01942 }
01943 
01944 static LRESULT CALLBACK DlgCommandDlgProc(HWND hwnd, UINT msg,
01945                                           WPARAM wparam, LPARAM lparam){
01946  node *np;
01947  char title[128];
01948  switch( msg ) {
01949    case WM_PAINT:
01950      PaintDialogBackground(hwnd,ghinst_main);
01951      break;
01952    case WM_INITDIALOG:
01953      np=(node *)lparam;
01954      sprintf(title,"Edit: %s",np->actorname);
01955      SendMessage(hwnd,WM_SETTEXT,0,(LPARAM)title);
01956      CentreDialogOnScreen(hwnd);
01957      return (TRUE);
01958    case WM_DESTROY:
01959      break;
01960    case WM_COMMAND:
01961       switch(LOWORD(wparam)){
01962         case IDCANCEL:
01963           EndDialog(hwnd,-1);
01964           return(TRUE);
01965         case DLG_KEYF_COMMAND_DELETE:
01966           EndDialog(hwnd,IDM_TIMELINE_ACTOR_DELETE);
01967           return(TRUE);
01968         case DLG_KEYF_COMMAND_RENAME:
01969           EndDialog(hwnd,IDM_TIMELINE_ACTOR_RENAME);
01970           return(TRUE);
01971         case DLG_KEYF_COMMAND_INFO:
01972           EndDialog(hwnd,IDM_TIMELINE_ACTOR_INFO);
01973           return(TRUE);
01974         case DLG_KEYF_COMMAND_SAVEANI:
01975           EndDialog(hwnd,IDM_TIMELINE_ACTOR_SAVEANIOBJ);
01976           return(TRUE);
01977         default:
01978           break;
01979       }
01980       break;
01981     default: break;
01982  }
01983  return(FALSE);
01984 }
01985 
01986 #define  CYORDERDLGLINE 18          // Height of a line.
01987 static HWND hwndOrderDlg;           // Window handle of the Order/Group dlg.
01988 static HWND hwndOrderList;          // Window handle of the list box.
01989 static WNDPROC lpfnOldLBWndProc;    // Original list box window proc.
01990 static BOOL cSelItems=FALSE;
01991 
01992 static BOOL OrderDlgInsertHitTest(INT y,PINT piInsert){
01993  INT i;
01994  INT iPixel;
01995  INT iInsert;
01996  INT iLine;
01997  BOOL fInsertZone;
01998  if (!cSelItems) return FALSE;
01999  iPixel = y % CYORDERDLGLINE;
02000  if (iPixel < 3) {
02001    iLine = y / CYORDERDLGLINE;
02002    fInsertZone = TRUE;
02003  }
02004  else if (iPixel > CYORDERDLGLINE - 3) {
02005    iLine = (y / CYORDERDLGLINE) + 1;
02006    fInsertZone = TRUE;
02007  }
02008  else {
02009    fInsertZone = FALSE;
02010  }
02011  if (fInsertZone) {
02012    iInsert = iLine + (INT)SendMessage(hwndOrderList,
02013                           LB_GETTOPINDEX, 0, 0L);
02014    if (iInsert > Nnodes)fInsertZone = FALSE;
02015    else *piInsert = iInsert;
02016  }
02017  return fInsertZone;
02018 }
02019 
02020 static LRESULT CALLBACK OrderDlgLBWndProc(HWND hwnd,UINT msg,WPARAM wParam,
02021                                     LPARAM lParam){
02022  INT iInsert;
02023  int item;
02024  switch (msg) {
02025    case WM_SETCURSOR:
02026      if (LOWORD(lParam) == HTCLIENT)return TRUE;
02027      break;
02028     case WM_MOUSEMOVE:
02029      if (!(GetKeyState(VK_LBUTTON) & 0x8000) &&
02030            OrderDlgInsertHitTest(HIWORD(lParam), &iInsert))
02031        SetCursor(ghcurInsert);
02032      else
02033        SetCursor(ghcurArrow);
02034      break;
02035    case WM_LBUTTONDOWN:
02036      if(OrderDlgInsertHitTest(HIWORD(lParam), &iInsert)) {
02037        item=SendMessage(hwndOrderList,LB_GETCURSEL,0,0);
02038        if(item == 0 || iInsert == 0){
02039          SendPrgmQuery(IDQ_CAMERANOREORDER,0);
02040          SetFocus(hwnd);
02041        }
02042        else if(item != LB_ERR){
02043          char temp[64];
02044          cSelItems=FALSE;
02045          SendMessage(hwndOrderList,LB_GETTEXT,item,(LPARAM)temp);
02046          if(item > iInsert){
02047            SendMessage(hwndOrderList,LB_DELETESTRING,(WPARAM)item,0);
02048            SendMessage(hwndOrderList,LB_INSERTSTRING,(WPARAM)iInsert,(LPARAM)temp);
02049          }
02050          else if(item < iInsert){
02051            SendMessage(hwndOrderList,LB_INSERTSTRING,(WPARAM)iInsert,(LPARAM)temp);
02052            SendMessage(hwndOrderList,LB_DELETESTRING,(WPARAM)item,0);
02053          }
02054          if(iInsert != item){
02055            node *n_out=NULL,*n_in=NULL,*Np,*Lp;
02056            int i;
02057            Np=FirstNp; i=0; while(Np != NULL){
02058              if(i == item)  n_out=Np;
02059              if(i == iInsert)n_in=Np;
02060              Lp=Np;
02061              i++; Np=Np->next;
02062            }
02063            if(n_out != NULL){
02064              if(n_out->next != NULL)n_out->next->last = n_out->last;
02065              if(n_out->last != NULL)n_out->last->next = n_out->next;
02066              if(n_out == FirstNp)FirstNp=n_out->next;
02067              if(n_out == MainNp)MainNp=n_out->last;
02068              if(n_in != NULL){
02069                n_out->last=n_in->last;
02070                if(n_in->last != NULL)n_in->last->next=n_out;
02071                n_in->last=n_out;
02072                n_out->next=n_in;
02073                if(n_in == FirstNp)FirstNp=n_out;
02074              }
02075              else{ /* at end of list */
02076                if(Lp != MainNp)MessageBeep(MB_OK);
02077                n_out->next=NULL;
02078                n_out->last=Lp;
02079                Lp->next=n_out;
02080                MainNp=n_out;
02081              }
02082            }
02083          }
02084        }
02085        return FALSE;
02086      }
02087      break;
02088   }
02089   return CallWindowProc((WNDPROC)lpfnOldLBWndProc,hwnd,msg,wParam,lParam);
02090 }
02091 
02092 static void OrderDlgInit(HWND hwnd){
02093  int nItem;
02094  node *Np;
02095  hwndOrderDlg = hwnd;
02096  hwndOrderList = GetDlgItem(hwnd,DLG_REORDER_LIST);
02097  cSelItems=FALSE;
02098  Np=FirstNp; while(Np != NULL){
02099    nItem=SendMessage(hwndOrderList,LB_ADDSTRING,0,(LPARAM)Np->actorname);
02100    Np=Np->next;
02101  }
02102  lpfnOldLBWndProc = (WNDPROC)SetWindowLong(hwndOrderList,
02103                      GWL_WNDPROC, (DWORD)OrderDlgLBWndProc);
02104  CentreDialogOnScreen(hwnd);
02105 }
02106 
02107 static LRESULT CALLBACK ReorderDlgProc(HWND hwnd, UINT msg,
02108                                        WPARAM wParam, LPARAM lParam){
02109  switch (msg) {
02110    case WM_PAINT:
02111      PaintDialogBackground(hwnd,ghinst_main);
02112      break;
02113    case WM_INITDIALOG:
02114      OrderDlgInit(hwnd);
02115      return TRUE;
02116    case WM_MEASUREITEM:
02117      ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = CYORDERDLGLINE;
02118      return TRUE;
02119    case WM_DRAWITEM:{
02120        LPDRAWITEMSTRUCT lpdis=(LPDRAWITEMSTRUCT)lParam;
02121        TCHAR szItem[MAX_PATH];
02122        TEXTMETRIC tm;
02123        int y;
02124        if(lpdis->itemState & ODS_SELECTED) {
02125          SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
02126          SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
02127        }
02128        else {
02129          SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW));
02130          SetTextColor(lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
02131        }
02132        switch(lpdis->itemAction){
02133          case ODA_SELECT:
02134          case ODA_DRAWENTIRE:
02135            SendMessage(lpdis->hwndItem,LB_GETTEXT,lpdis->itemID,(LPARAM)szItem);
02136            GetTextMetrics(lpdis->hDC,&tm);
02137            y=(lpdis->rcItem.bottom+lpdis->rcItem.top-tm.tmHeight)/2;
02138            ExtTextOut(lpdis->hDC,6,y,
02139                     ETO_OPAQUE | ETO_CLIPPED, &lpdis->rcItem,
02140                     szItem, lstrlen(szItem), NULL);
02141          default:
02142            break;
02143        }
02144        if(lpdis->itemState & ODS_FOCUS)
02145          DrawFocusRect(lpdis->hDC, &lpdis->rcItem);
02146      }
02147      return TRUE;
02148    case WM_COMMAND:
02149      switch (LOWORD(wParam)) {
02150        case DLG_REORDER_LIST:
02151          switch (HIWORD(wParam)) {
02152            case LBN_SELCHANGE:
02153              cSelItems=TRUE;
02154              break;
02155          }
02156          break;
02157        case IDCANCEL:
02158        case IDOK:
02159          EndDialog(hwnd, LOWORD(wParam));
02160          break;
02161      }
02162      return TRUE;
02163    default:
02164      return FALSE;
02165  }
02166  return FALSE;
02167 }
02168 // script part 3
02169 
02170 #define UPDATETRIVIEW(x)           \
02171   if(ghwndTimeline != NULL){       \
02172     if(!IsZoomed(ghwndTimeline)){  \
02173       ReDrawStageDisplay(TRUE);    \
02174       if(ghwndOpenGLview == NULL)  \
02175         PerspectiveView(0,1);      \
02176       else UpdateGLview(TRUE);     \
02177     }                              \
02178   }
02179 
02180 #define BOUND(x,min,max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
02181 #define A_H 60
02182 #define F_W 10
02183 #define L_H 10
02184 #define WM_KEYFRAMEUPDATE (WM_USER+1)
02185 
02186 static void DoKeyFramerCommand(WPARAM wparam, int local_actor);
02187 
02188 static char  szTimelineChildClass[]="OFX:TimelineChildClass";
02189 static char  szTimelineClass[]="OFX:TimelineClass";
02190 static int TimelineStatusPartsList[3]={110,220,-1};
02191 static int FirstTime=TRUE,IndicatorVisible = NO,IndicatorActive=NO,
02192            IndicatedActor= -1, IndicatedFrame= -1, IndicatedLine= -1,
02193            ScrollingTimeLine=0,TimeLineUpdateFlag=0,TimeLineVisibleFlag=0,
02194            IndicatorsChanged=NO;
02195 static HBITMAP  hTimelineBitmap=NULL;
02196 static HWND     hwndTimelineInfo=NULL;
02197 static node     *IndicatedNode=NULL;
02198 static sky      *IndicatedSky=NULL;
02199 static director *IndicatedDirector=NULL;
02200 static object   *IndicatedObject=NULL;
02201 static position *IndicatedPosition=NULL;
02202 static align    *IndicatedAlign=NULL;
02203 static size     *IndicatedSize=NULL;
02204 static DWORD fdwStyleP = WS_POPUP | WS_CLIPSIBLINGS | WS_CAPTION |
02205                          WS_SYSMENU | WS_THICKFRAME |
02206                          WS_MAXIMIZEBOX | WS_MINIMIZEBOX |
02207                          !WS_VSCROLL | !WS_HSCROLL;
02208 static DWORD fdwStyleD = WS_CHILD | WS_CLIPSIBLINGS | !WS_CAPTION |
02209                          !WS_SYSMENU | !WS_THICKFRAME | !WS_MAXIMIZEBOX |
02210                          !WS_VSCROLL | !WS_HSCROLL | !WS_BORDER;
02211 static DWORD fdwStyleC = WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE;
02212 static int xScreen,yScreen,nXBorder,nXTitle,nYTitle;
02213 static POINT ptSize;
02214 static long NoldFrames= -1, NoldNodes = -1;
02215 static char *linetype[5]={NULL,NULL,NULL,NULL,NULL};
02216 
02217 static int ChangeIndicatedKeys(BOOL bEditKeyStart){
02218  int dn,fn,update=0;
02219 
02220  if(IndicatedObject != NULL){
02221    if(bEditKeyStart){ /* moving start of timeline */
02222      if(IndicatedObject->last == NULL)dn=1;
02223      else dn=IndicatedObject->last->firstframe+1;
02224      if(IndicatedFrame >= dn){
02225        if(IndicatedObject->next == NULL)dn=Nframes;
02226        else dn=IndicatedObject->next->firstframe-1;
02227        if(IndicatedFrame <= dn){
02228          IndicatedObject->firstframe=IndicatedFrame;
02229          if(IndicatedObject->firstframe > IndicatedObject->lastframe)
02230             IndicatedObject->firstframe=IndicatedObject->lastframe;
02231          if(IndicatedObject->last != NULL){
02232            if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
02233                  IndicatedObject->last->lastframe=min(IndicatedFrame-1,
02234                  IndicatedObject->last->lastframe);
02235            else IndicatedObject->last->lastframe=IndicatedFrame-1;
02236          }
02237        }
02238      }
02239    }
02240    else{  /* moving end of timeline */
02241      if(IndicatedObject->last == NULL)dn=1;
02242      else dn=IndicatedObject->last->lastframe+1;
02243      if(IndicatedFrame >= dn){
02244        if(IndicatedObject->next == NULL)dn=Nframes;
02245        else dn=IndicatedObject->next->lastframe-1;
02246        if(IndicatedFrame <= dn){
02247          IndicatedObject->lastframe=IndicatedFrame;
02248          if(IndicatedObject->firstframe > IndicatedObject->lastframe)
02249             IndicatedObject->firstframe=IndicatedObject->lastframe;
02250          if(IndicatedObject->next != NULL){
02251            if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
02252                  IndicatedObject->next->firstframe=max(IndicatedFrame+1,
02253                  IndicatedObject->next->firstframe);
02254            else IndicatedObject->next->firstframe=IndicatedFrame+1;
02255          }
02256        }
02257      }
02258    }
02259    update=1;
02260  }
02261 
02262  if(IndicatedSky != NULL){
02263    if(bEditKeyStart){ /* moving start of timeline */
02264      if(IndicatedSky->last == NULL)dn=1;
02265      else dn=IndicatedSky->last->firstframe+1;
02266      if(IndicatedFrame >= dn){
02267        if(IndicatedSky->next == NULL)dn=Nframes;
02268        else dn=IndicatedSky->next->firstframe-1;
02269        if(IndicatedFrame <= dn){
02270          IndicatedSky->firstframe=IndicatedFrame;
02271          if(IndicatedSky->firstframe > IndicatedSky->lastframe)
02272             IndicatedSky->firstframe=IndicatedSky->lastframe;
02273          if(IndicatedSky->last != NULL){
02274            if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
02275                  IndicatedSky->last->lastframe=min(IndicatedFrame-1,
02276                  IndicatedSky->last->lastframe);
02277            else IndicatedSky->last->lastframe=IndicatedFrame-1;
02278          }
02279        }
02280      }
02281    }
02282    else{
02283      if(IndicatedSky->last == NULL)dn=1;
02284      else dn=IndicatedSky->last->lastframe+1;
02285      if(IndicatedFrame >= dn){
02286        if(IndicatedSky->next == NULL)dn=Nframes;
02287        else dn=IndicatedSky->next->lastframe-1;
02288        if(IndicatedFrame <= dn){
02289          IndicatedSky->lastframe=IndicatedFrame;
02290          if(IndicatedSky->firstframe > IndicatedSky->lastframe)
02291             IndicatedSky->firstframe=IndicatedSky->lastframe;
02292          if(IndicatedSky->next != NULL){
02293            if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
02294                  IndicatedSky->next->firstframe=max(IndicatedFrame+1,
02295                  IndicatedSky->next->firstframe);
02296            else  IndicatedSky->next->firstframe=IndicatedFrame+1;
02297          }
02298        }
02299      }
02300    }
02301    update=1;
02302  }
02303 
02304  if(IndicatedDirector != NULL){
02305    if(bEditKeyStart){ /* moving start of timeline */
02306      if(IndicatedDirector->last == NULL)dn=1;
02307      else dn=IndicatedDirector->last->firstframe+1;
02308      if(IndicatedFrame >= dn){
02309        if(IndicatedDirector->next == NULL)dn=Nframes;
02310        else dn=IndicatedDirector->next->firstframe-1;
02311        if(IndicatedFrame <= dn){
02312          IndicatedDirector->firstframe=IndicatedFrame;
02313          if(IndicatedDirector->firstframe > IndicatedDirector->lastframe)
02314             IndicatedDirector->firstframe=IndicatedDirector->lastframe;
02315          if(IndicatedDirector->last != NULL){
02316            if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
02317                  IndicatedDirector->last->lastframe=min(IndicatedFrame-1,
02318                  IndicatedDirector->last->lastframe);
02319            else IndicatedDirector->last->lastframe=IndicatedFrame-1;
02320          }
02321        }
02322      }
02323    }
02324    else{
02325      if(IndicatedDirector->last == NULL)dn=1;
02326      else dn=IndicatedDirector->last->lastframe+1;
02327      if(IndicatedFrame >= dn){
02328        if(IndicatedDirector->next == NULL)dn=Nframes;
02329        else dn=IndicatedDirector->next->lastframe-1;
02330        if(IndicatedFrame <= dn){
02331          IndicatedDirector->lastframe=IndicatedFrame;
02332          if(IndicatedDirector->firstframe > IndicatedDirector->lastframe)
02333             IndicatedDirector->firstframe=IndicatedDirector->lastframe;
02334          if(IndicatedDirector->next != NULL){
02335            if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
02336                  IndicatedDirector->next->firstframe=max(IndicatedFrame+1,
02337                  IndicatedDirector->next->firstframe);
02338            else  IndicatedDirector->next->firstframe=IndicatedFrame+1;
02339          }
02340        }
02341      }
02342    }
02343    update=1;
02344  }
02345 
02346  if(IndicatedPosition != NULL){
02347    if(bEditKeyStart){ /* moving start of timeline */
02348      if(IndicatedPosition->last == NULL)dn=1;
02349      else dn=IndicatedPosition->last->firstframe+1;
02350      if(IndicatedFrame >= dn){
02351        if(IndicatedPosition->next == NULL)dn=Nframes;
02352        else dn=IndicatedPosition->next->firstframe-1;
02353        if(IndicatedFrame <= dn){
02354          IndicatedPosition->firstframe=IndicatedFrame;
02355          if(IndicatedPosition->firstframe > IndicatedPosition->lastframe)
02356             IndicatedPosition->firstframe=IndicatedPosition->lastframe;
02357          if(IndicatedPosition->last != NULL){
02358            if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
02359                  IndicatedPosition->last->lastframe=min(IndicatedFrame-1,
02360                  IndicatedPosition->last->lastframe);
02361            else IndicatedPosition->last->lastframe=IndicatedFrame-1;
02362          }
02363        }
02364      }
02365    }
02366    else{
02367      if(IndicatedPosition->last == NULL)dn=1;
02368      else dn=IndicatedPosition->last->lastframe+1;
02369      if(IndicatedFrame >= dn){
02370        if(IndicatedPosition->next == NULL)dn=Nframes;
02371        else  dn=IndicatedPosition->next->lastframe-1;
02372        if(IndicatedFrame <= dn){
02373          IndicatedPosition->lastframe=IndicatedFrame;
02374          if(IndicatedPosition->firstframe > IndicatedPosition->lastframe)
02375             IndicatedPosition->firstframe=IndicatedPosition->lastframe;
02376          if(IndicatedPosition->next != NULL){
02377            if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
02378                  IndicatedPosition->next->firstframe=max(IndicatedFrame+1,
02379                  IndicatedPosition->next->firstframe);
02380            else  IndicatedPosition->next->firstframe=IndicatedFrame+1;
02381          }
02382        }
02383      }
02384    }
02385    update=1;
02386  }
02387  if(IndicatedAlign != NULL){
02388    if(bEditKeyStart){ /* moving start of timeline */
02389      if(IndicatedAlign->last == NULL)dn=1;
02390      else dn=IndicatedAlign->last->firstframe+1;
02391      if(IndicatedFrame >= dn){
02392        if(IndicatedAlign->next == NULL)dn=Nframes;
02393        else dn=IndicatedAlign->next->firstframe-1;
02394        if(IndicatedFrame <= dn){
02395          IndicatedAlign->firstframe=IndicatedFrame;
02396          if(IndicatedAlign->firstframe > IndicatedAlign->lastframe)
02397             IndicatedAlign->firstframe=IndicatedAlign->lastframe;
02398          if(IndicatedAlign->last != NULL){
02399            if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
02400                  IndicatedAlign->last->lastframe=min(IndicatedFrame-1,
02401                  IndicatedAlign->last->lastframe);
02402            else IndicatedAlign->last->lastframe=IndicatedFrame-1;
02403          }
02404        }
02405      }
02406    }
02407    else{
02408      if(IndicatedAlign->last == NULL)dn=1;
02409      else dn=IndicatedAlign->last->lastframe+1;
02410      if(IndicatedFrame >= dn){
02411        if(IndicatedAlign->next == NULL)dn=Nframes;
02412        else dn=IndicatedAlign->next->lastframe-1;
02413        if(IndicatedFrame <= dn){
02414          IndicatedAlign->lastframe=IndicatedFrame;
02415          if(IndicatedAlign->firstframe > IndicatedAlign->lastframe)
02416             IndicatedAlign->firstframe=IndicatedAlign->lastframe;
02417          if(IndicatedAlign->next != NULL){
02418            if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
02419                  IndicatedAlign->next->firstframe=max(IndicatedFrame+1,
02420                  IndicatedAlign->next->firstframe);
02421            else  IndicatedAlign->next->firstframe=IndicatedFrame+1;
02422          }
02423        }
02424      }
02425    }
02426    update=1;
02427  }
02428  if(IndicatedSize != NULL){
02429    if(bEditKeyStart){ /* moving start of timeline */
02430      if(IndicatedSize->last == NULL)dn=1;
02431      else dn=IndicatedSize->last->firstframe+1;
02432      if(IndicatedFrame >= dn){
02433        if(IndicatedSize->next == NULL)dn=Nframes;
02434        else dn=IndicatedSize->next->firstframe-1;
02435        if(IndicatedFrame <= dn){
02436          IndicatedSize->firstframe=IndicatedFrame;
02437          if(IndicatedSize->firstframe > IndicatedSize->lastframe)
02438             IndicatedSize->firstframe=IndicatedSize->lastframe;
02439          if(IndicatedSize->last != NULL){
02440            if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
02441                  IndicatedSize->last->lastframe=min(IndicatedFrame-1,
02442                  IndicatedSize->last->lastframe);
02443            else IndicatedSize->last->lastframe=IndicatedFrame-1;
02444          }
02445        }
02446      }
02447    }
02448    else{
02449      if(IndicatedSize->last == NULL)dn=1;
02450      else dn=IndicatedSize->last->lastframe+1;
02451      if(IndicatedFrame >= dn){
02452        if(IndicatedSize->next == NULL)dn=Nframes;
02453        else dn=IndicatedSize->next->lastframe-1;
02454        if(IndicatedFrame <= dn){
02455          IndicatedSize->lastframe=IndicatedFrame;
02456          if(IndicatedSize->firstframe > IndicatedSize->lastframe)
02457           IndicatedSize->firstframe=IndicatedSize->lastframe;
02458          if(IndicatedSize->next != NULL){
02459            if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
02460                  IndicatedSize->next->firstframe = max(IndicatedFrame+1,
02461                  IndicatedSize->next->firstframe);
02462            else  IndicatedSize->next->firstframe=IndicatedFrame+1;
02463          }
02464        }
02465      }
02466    }
02467    update=1;
02468  }
02469  if(update)return 1;
02470  return 0;
02471 }
02472 
02473 void WaitForUp(void){
02474  MSG msg;
02475  POINT p;
02476  RECT  r;
02477  GetCursorPos(&p);
02478  r.top=p.y; r.left=p.x;
02479  r.bottom=p.y; r.right=p.x;
02480  ClipCursor(&r);
02481  while (1) {
02482    GetMessage(&msg,NULL,0,0);
02483    TranslateMessage(&msg);
02484      DispatchMessage(&msg);
02485    if(msg.message == WM_LBUTTONUP)break;
02486  }
02487 }
02488 
02489 static node *EditTimeLine(int actor, int frame, int line, BOOL *keystart){
02490  node     *Np;
02491  object   *Op,*Opp;
02492  sky      *Sp,*Spp;
02493  director *Dp,*Dpp;
02494  position *Pp,*Ppp;
02495  align    *Ap,*App;
02496  size     *Xp,*Xpp;
02497  int i,lf;
02498  short slf,sframe,type;
02499  EDIT_ACTION=YES;
02500  IndicatedSky=NULL;      IndicatedObject=NULL;
02501  IndicatedPosition=NULL; IndicatedAlign=NULL; IndicatedSize=NULL;
02502  IndicatedDirector=NULL;
02503  *keystart=FALSE;
02504  Np=FirstNp; if(actor > 1)for(i=1;i<actor;i++)Np=Np->next;
02505  if(Np == NULL)return NULL;
02506 
02507  if(line == 0 && Np->type == SKY){
02508   Sp=Np->fsky; Spp=Sp;
02509   while(Sp != NULL){
02510     Spp=Sp;
02511     if(Sp->firstframe > frame){
02512       if(Sp->last == NULL)lf=1;
02513       else                lf=Sp->last->lastframe+1;
02514       WaitForUp();
02515       EditObject(Np,(short)lf,(short)frame,YES,NO);
02516       UPDATETIMELINES(IDC_TIMEL_UPDATE)
02517       return NULL;
02518     }
02519     if(Sp->firstframe <= frame && Sp->lastframe >= frame){
02520       if(Sp->lastframe == frame){
02521         IndicatedSky=Sp;
02522         return Np;
02523       }
02524       else if(Sp->firstframe == frame){
02525         IndicatedSky=Sp;
02526         *keystart=TRUE;
02527         return Np;
02528       }
02529       else{
02530         WaitForUp();
02531         if(!(GetKeyState(VK_CONTROL) & 0x8000) &&
02532           SendPrgmQuery(IDQ_BREAKCHANNEL,1) == IDNO)return NULL;
02533         lf=Sp->firstframe;
02534         Sp->firstframe=frame+1;
02535         EditObject(Np,(short)lf,(short)frame,YES,YES);
02536         UPDATETIMELINES(IDC_TIMEL_UPDATE)
02537       }
02538       return NULL;
02539     }
02540     Sp=Sp->next;
02541   }
02542   if(Spp != NULL)lf=Spp->lastframe+1;
02543   else lf=1;
02544   WaitForUp();
02545   EditObject(Np,(short)lf,(short)frame,YES,NO);
02546   UPDATETIMELINES(IDC_TIMEL_UPDATE)
02547   return NULL;
02548  }
02549 
02550  else if(line == 0 && Np->type == DIRECTOR){
02551   Dp=Np->fdirector; Dpp=Dp;
02552   while(Dp != NULL){
02553     Dpp=Dp;
02554     if(Dp->firstframe > frame){
02555       if(Dp->last == NULL)lf=1;
02556       else                lf=Dp->last->lastframe+1;
02557       WaitForUp();
02558       EditObject(Np,(short)lf,(short)frame,YES,NO);
02559       UPDATETIMELINES(IDC_TIMEL_UPDATE)
02560       return NULL;
02561     }
02562     if(Dp->firstframe <= frame && Dp->lastframe >= frame){
02563       if(Dp->lastframe == frame){
02564         IndicatedDirector=Dp;
02565         return Np;
02566       }
02567       else if(Dp->firstframe == frame){
02568         IndicatedDirector=Dp;
02569         *keystart=TRUE;
02570         return Np;
02571       }
02572       else{
02573         WaitForUp();
02574         if(!(GetKeyState(VK_CONTROL) & 0x8000) &&
02575           SendPrgmQuery(IDQ_BREAKCHANNEL,1) == IDNO)return NULL;
02576         lf=Dp->firstframe;
02577         Dp->firstframe=frame+1;
02578         EditObject(Np,(short)lf,(short)frame,YES,YES);
02579         UPDATETIMELINES(IDC_TIMEL_UPDATE)
02580       }
02581       return NULL;
02582     }
02583     Dp=Dp->next;
02584   }
02585   if(Dpp != NULL)lf=Dpp->lastframe+1;
02586   else lf=1;
02587   WaitForUp();
02588   EditObject(Np,(short)lf,(short)frame,YES,NO);
02589   UPDATETIMELINES(IDC_TIMEL_UPDATE)
02590   return NULL;
02591  }
02592 
02593  else if (line == 0){
02594   if(Np->type == CAMERA)return NULL; //To allow Camera Timeline Editing MOD
02595   Op=Np->fobj; Opp=Op;
02596   while(Op != NULL){
02597     Opp=Op;
02598     if(Op->firstframe > frame){
02599       if(Op->last == NULL)lf=1;
02600       else                lf=Op->last->lastframe+1;
02601       WaitForUp();
02602       EditObject(Np,(short)lf,(short)frame,YES,NO);
02603       UPDATETIMELINES(IDC_TIMEL_UPDATE)
02604       UPDATETRIVIEW(0)
02605       return NULL;
02606     }
02607     if(Op->firstframe <= frame && Op->lastframe >= frame){
02608       if(Op->lastframe == frame){
02609         IndicatedObject=Op;
02610         return Np;
02611       }
02612       else if(Op->firstframe == frame){
02613         IndicatedObject=Op;
02614         *keystart=TRUE;
02615         return Np;
02616       }
02617       else{
02618         WaitForUp();
02619         if(!(GetKeyState(VK_CONTROL) & 0x8000) &&
02620           SendPrgmQuery(IDQ_BREAKCHANNEL,1) == IDNO)return NULL;
02621         lf=Op->firstframe;
02622         Op->firstframe=frame+1;
02623         if(Op->type == PATH){
02624            Op->v=ReTweenVelocity(Op,Op->v,
02625                                  Op->lastframe-lf+1,
02626                                  Op->lastframe-Op->firstframe+1,
02627                                  Op->pathlength,
02628                                  0);
02629         }
02630         EditObject(Np,(short)lf,(short)frame,YES,YES); // All objects
02631         UPDATETIMELINES(IDC_TIMEL_UPDATE)
02632         UPDATETRIVIEW(0)
02633       }
02634       return NULL;
02635     }
02636     Op=Op->next;
02637   }
02638   if(Opp != NULL)lf=Opp->lastframe+1;
02639   else lf=1;
02640   WaitForUp();
02641   EditObject(Np,(short)lf,(short)frame,YES,NO);
02642   UPDATETIMELINES(IDC_TIMEL_UPDATE)
02643   UPDATETRIVIEW(0)
02644   return NULL;
02645  }
02646  if(line == 1){
02647   if(Np->type == SKY || Np->type == IMAGEP || Np->type == DIRECTOR)return NULL;
02648   Pp=Np->fpos; Ppp=Pp;
02649   while(Pp != NULL){
02650     Ppp=Pp;
02651     if(Pp->firstframe > frame){
02652       if(Pp->last == NULL)lf=1;
02653       else                lf=Pp->last->lastframe+1;
02654       WaitForUp();
02655       type=0; slf=(short)lf; sframe=(short)frame;
02656       EditPosition(Np,slf,sframe,type,ghwndTimeline);
02657       UPDATETIMELINES(IDC_TIMEL_UPDATE)
02658       UPDATETRIVIEW(0)
02659       return NULL;
02660     }
02661     if(Pp->firstframe <= frame && Pp->lastframe >= frame){
02662       if(Pp->lastframe == frame){
02663         IndicatedPosition=Pp;
02664         return Np;
02665       }
02666       else if(Pp->firstframe == frame){
02667         IndicatedPosition=Pp;
02668         *keystart=TRUE;
02669         return Np;
02670       }
02671       else{
02672         WaitForUp();
02673         if(!(GetKeyState(VK_CONTROL) & 0x8000) &&
02674           SendPrgmQuery(IDQ_BREAKCHANNEL,1) == IDNO)return NULL;
02675         MakeKey('P',frame,Np);
02676         UPDATETRIVIEW(0)
02677       }
02678       return NULL;
02679     }
02680     Pp=Pp->next;
02681   }
02682   if(Ppp != NULL)lf=Ppp->lastframe+1;
02683   else lf=1;
02684   WaitForUp();
02685   type=0; slf=(short)lf; sframe=(short)frame;
02686   EditPosition(Np,slf,sframe,type,ghwndTimeline);
02687   UPDATETIMELINES(IDC_TIMEL_UPDATE)
02688   UPDATETRIVIEW(0)
02689   return NULL;
02690  }
02691  else if(line == 2){
02692   if(Np->type == SKY  || Np->type == TARGET || Np->type == DIRECTOR ||
02693      Np->type == PATH || Np->type == IMAGEP)return NULL;
02694   Ap=Np->fali; App=Ap;
02695   while(Ap != NULL){
02696     App=Ap;
02697     if(Ap->firstframe > frame){
02698       if(Ap->last == NULL)lf=1;
02699       else                lf=Ap->last->lastframe+1;
02700       WaitForUp();
02701       type=0; slf=(short)lf; sframe=(short)frame;
02702       EditAlign(Np,slf,sframe,type,ghwndTimeline);
02703       UPDATETIMELINES(IDC_TIMEL_UPDATE)
02704       UPDATETRIVIEW(0)
02705       return NULL;
02706     }
02707     if(Ap->firstframe <= frame && Ap->lastframe >= frame){
02708       if(Ap->lastframe == frame){
02709         IndicatedAlign=Ap;
02710         return Np;
02711       }
02712       else if(Ap->firstframe == frame){
02713         IndicatedAlign=Ap;
02714         *keystart=TRUE;
02715         return Np;
02716       }
02717       else{
02718         WaitForUp();
02719         if(!(GetKeyState(VK_CONTROL) & 0x8000) &&
02720           SendPrgmQuery(IDQ_BREAKCHANNEL,1) == IDNO)return NULL;
02721         MakeKey('A',frame,Np);
02722         UPDATETRIVIEW(0)
02723       }
02724       return NULL;
02725     }
02726     Ap=Ap->next;
02727   }
02728   if(App != NULL)lf=App->lastframe+1;
02729   else lf=1;
02730   WaitForUp();
02731   type=0; slf=(short)lf; sframe=(short)frame;
02732   EditAlign(Np,slf,sframe,type,ghwndTimeline);
02733   UPDATETIMELINES(IDC_TIMEL_UPDATE)
02734   UPDATETRIVIEW(0)
02735   return NULL;
02736  }
02737  else if(line == 3){
02738   if(Np->type == SKY  || Np->type == TARGET || Np->type == DIRECTOR ||
02739      Np->type == PATH || Np->type == IMAGEP)return NULL;
02740   Xp=Np->fsiz; Xpp=Xp;
02741   while(Xp != NULL){
02742     Xpp=Xp;
02743     if(Xp->firstframe > frame){
02744       if(Xp->last == NULL)lf=1;
02745       else                lf=Xp->last->lastframe+1;
02746       WaitForUp();
02747       EditSize(Np,(short)lf,(short)frame);
02748       UPDATETIMELINES(IDC_TIMEL_UPDATE)
02749       UPDATETRIVIEW(0)
02750       return NULL;
02751     }
02752     if(Xp->firstframe <= frame && Xp->lastframe >= frame){
02753       if(Xp->lastframe == frame){
02754         IndicatedSize=Xp;
02755         return Np;
02756       }
02757       else if(Xp->firstframe == frame){
02758         IndicatedSize=Xp;
02759         *keystart=TRUE;
02760         return Np;
02761       }
02762       else{
02763         WaitForUp();
02764         if(!(GetKeyState(VK_CONTROL) & 0x8000) &&
02765           SendPrgmQuery(IDQ_BREAKCHANNEL,1) == IDNO)return NULL;
02766         MakeKey('Z',frame,Np);
02767         UPDATETRIVIEW(0)
02768       }
02769       return NULL;
02770     }
02771     Xp=Xp->next;
02772   }
02773   if(Xpp != NULL)lf=Xpp->lastframe+1;
02774   else lf=1;
02775   WaitForUp();
02776   EditSize(Np,(short)lf,(short)frame);
02777   UPDATETIMELINES(IDC_TIMEL_UPDATE)
02778   UPDATETRIVIEW(0)
02779   return NULL;
02780  }
02781  return NULL;
02782 }
02783 
02784 static void GetRealClientRect(HWND hwnd, PRECT lprc){
02785  DWORD dwStyle;
02786  dwStyle = GetWindowLong(hwnd, GWL_STYLE);
02787  GetClientRect(hwnd,lprc);
02788  if (dwStyle & WS_HSCROLL)lprc->bottom += GetSystemMetrics(SM_CYHSCROLL);
02789  if (dwStyle & WS_VSCROLL)lprc->right  += GetSystemMetrics(SM_CXVSCROLL);
02790 }
02791 
02792 static void SetScrollRanges(HWND hwnd,int update){
02793  RECT rc;
02794  int iRangeH,iRangeV,i;
02795  static int iSem = 0;
02796  if(!iSem){
02797    iSem++;
02798    GetRealClientRect(hwnd,&rc);
02799    for(i = 0; i < 2; i++){
02800      iRangeV = ptSize.y - rc.bottom;
02801      iRangeH = ptSize.x - rc.right;
02802      iRangeV = (iRangeV/A_H+1)*A_H;
02803      iRangeH = (iRangeH/F_W+1)*F_W;
02804      if(iRangeH < 0)iRangeH = 0;
02805      if(keyframer_docked)iRangeH=max(iRangeH,F_W); /* to keep hor scroll */
02806      if(iRangeV < 0)iRangeV = 0;
02807      SetScrollRange(hwnd, SB_VERT, 0, iRangeV, TRUE);
02808      SetScrollRange(hwnd, SB_HORZ, 0, iRangeH, TRUE);
02809      GetClientRect(hwnd, &rc);
02810    }
02811    iSem--;
02812    if(update)InvalidateRect(hwnd,NULL,TRUE);
02813  }
02814 }
02815 
02816 static void GetIndicators(int x, int y, RECT rc,
02817                           int *frame, int *actor, int *line,
02818                           int *firstframe, int *firstactor,
02819                           int *lastframe, int *lastactor){
02820  int f,a,ff,aa;
02821  ff=GetScrollPos(ghwndTimelineChild,SB_HORZ);
02822  aa=GetScrollPos(ghwndTimelineChild,SB_VERT);
02823  f=x+ff;
02824  a=y+aa;
02825  *frame =(f/F_W)+1;
02826  *actor =(a/A_H)+1;
02827  *line  =(a-(a/A_H)*A_H)/L_H - 2;
02828  *lastframe=(ff+rc.right)/F_W+1;
02829  *lastactor=(aa+rc.bottom)/A_H+1;
02830  *firstframe=ff/F_W+1;
02831  *firstactor=aa/A_H+1;
02832 }
02833 
02834 static void UpdateIndicators(int frame, int actor, int line,
02835                              int firstframe, int lastframe){
02836  RECT rc,rcW;
02837  char str[128];
02838  if(frame < 0)strcpy(str," ");
02839  else{
02840    sprintf(str,"%s %ld ",linetype[4],frame);
02841  }
02842  if(IsWindow(hwndTimelineInfo))
02843    SendMessage(hwndTimelineInfo,SB_SETTEXT,(WPARAM)0,(LPARAM)str);
02844  else SendPrgmText(str);
02845  strcpy(str," ");
02846  if(frame >= 0 && line >= 0 && line <= 3 && actor <= Nnodes)strcpy(str,linetype[line]);
02847  if(IsWindow(hwndTimelineInfo))
02848    SendMessage(hwndTimelineInfo,SB_SETTEXT,(WPARAM)1,(LPARAM)str);
02849 }
02850 
02851 static void DrawHairs(HDC ihdc, HWND hwnd, int frame, int actor, int line){
02852  int x,y,f,a,oldROP;
02853  HDC hdc;
02854  RECT rc;
02855  HPEN holdpen;
02856  HBRUSH holdbrush;
02857  if(ihdc == NULL)hdc=GetDC(hwnd);
02858  else hdc=ihdc;
02859  holdpen=SelectObject(hdc,GetStockObject(WHITE_PEN));
02860  oldROP=SetROP2(hdc,R2_XORPEN);
02861  GetClientRect(hwnd,&rc);
02862  f=GetScrollPos(ghwndTimelineChild,SB_HORZ)/F_W+1;
02863  a=GetScrollPos(ghwndTimelineChild,SB_VERT)/A_H+1;
02864  x=(frame-f)*F_W+F_W/3;
02865  y=(actor-a)*A_H+20+line*10;
02866  MoveToEx(hdc,x,rc.top,NULL); LineTo(hdc,x,rc.bottom);
02867 #if 0
02868  if(line >= 0 && line <= 3 && frame <= Nframes){
02869    MoveToEx(hdc,x,rc.top,NULL); LineTo(hdc,x,y);
02870    holdbrush=SelectObject(hdc,GetStockObject(HOLLOW_BRUSH));
02871    Rectangle(hdc,x-5,y,x+5,y+9);
02872    MoveToEx(hdc,x,y+9,NULL); LineTo(hdc,x,rc.bottom);
02873    SelectObject(hdc,holdbrush);
02874  }
02875  else if(line == -1){
02876    MoveToEx(hdc,x-5,y+4,NULL); LineTo(hdc,x+6,y+4);
02877    MoveToEx(hdc,x-5,y-4,NULL); LineTo(hdc,x+6,y-4);
02878    MoveToEx(hdc,x,y-4,NULL); LineTo(hdc,x,y+5);
02879  }
02880  else {
02881    MoveToEx(hdc,x-5,y+4,NULL); LineTo(hdc,x+6,y+4);
02882    MoveToEx(hdc,x,rc.top,NULL); LineTo(hdc,x,rc.bottom);
02883  }
02884 #endif
02885  SetROP2(hdc,oldROP);
02886  SelectObject(hdc,holdpen);
02887  if(ihdc == NULL)ReleaseDC(hwnd,hdc);
02888 }
02889 
02890 static void DrawTime(HDC hdc,int o,int y,int x0,int x1,HPEN hp, HPEN hps){
02891  HPEN holdpen;
02892 // holdpen=SelectObject(hdc,hp);  // for single colour line
02893  holdpen=SelectObject(hdc,hps);
02894  MoveToEx(hdc,x0+1,y-3,NULL); LineTo(hdc,x0+1,y+3);
02895  MoveToEx(hdc,x0+1,y,NULL); LineTo(hdc,x1,y);
02896  y++;
02897  SelectObject(hdc,hps);
02898 // Ellipse(hdc,x1,y-4,x1+7,y+3);
02899  Rectangle(hdc,x1,y-4,x1+7,y+3);
02900  SelectObject(hdc,holdpen);
02901 }
02902 
02903 static void DrawFrameIndicators(HDC hdc,int x, int y, int ff, int lf){
02904  int i;
02905  char str[128];
02906  SelectObject(hdc,GetStockObject(BLACK_PEN));
02907  for(i=ff;i<lf;i++,x += F_W){
02908    if(x >= 55){
02909      if(i%10 == 0){
02910        sprintf(str,"%ld",i);
02911        TextOut(hdc,x-4,y,str,strlen(str));
02912      }
02913      else{
02914        if(i < 100)Ellipse(hdc,x+1,y+6,x+5,y+10);
02915        else if(i < 999 && i%10 > 1)Ellipse(hdc,x+1,y+6,x+5,y+10);
02916        else if(i%10 > 2)Ellipse(hdc,x+1,y+6,x+5,y+10);
02917      }
02918    }
02919  }
02920 }
02921 
02922 static void DrawPopupButton(HDC hDC,int x,int y){
02923  HBITMAP hbm,hbmOld;
02924  BITMAP bmp;
02925  HDC hMemDC;
02926  int cx,cy;
02927  hbm=LoadBitmap(ghinst_main,MAKEINTRESOURCE(IDBM_QT2));
02928  if(hbm != NULL){
02929    GetObject(hbm,sizeof(BITMAP),&bmp);
02930    cx = bmp.bmWidth;
02931    cy = bmp.bmHeight;
02932    hMemDC = CreateCompatibleDC(hDC);
02933    hbmOld = SelectObject(hMemDC,hbm);
02934    BitBlt(hDC,x,y+3,cx,cy,hMemDC,0,0,SRCAND);
02935    SelectObject(hMemDC,hbmOld);
02936    DeleteDC(hMemDC);
02937    DeleteObject(hbm);
02938  }
02939 }
02940 
02941 static void DrawActorNames(HWND hWnd, int fg, int ff, int lf){
02942  int a,na,ac=0;
02943  node *np;
02944  HDC hdc;
02945  RECT rc;
02946  hdc=GetDC(hWnd);
02947  GetClientRect(hWnd,&rc);
02948  SetBkMode(hdc,TRANSPARENT);
02949 // SelectObject(hdc,GetStockObject(LTGRAY_BRUSH));
02950  SelectObject(hdc,GetStockObject(GRAY_BRUSH));
02951 // SelectObject(hdc,GetStockObject(DKGRAY_BRUSH));
02952  SetTextColor(hdc,RGB(255,255,255));
02953  LoadString(ghinst_main,IDX_MISC_LANGUAGE,res_str,256);
02954  if(strcmp(res_str,"ENGLISH") == 0)
02955    SelectObject(hdc,GetStockObject(ANSI_VAR_FONT));
02956  a=GetScrollPos(ghwndTimelineChild,SB_VERT)/A_H+1;
02957  na=a+rc.bottom/A_H;
02958  if((np=FirstNp) != NULL)while(np != NULL){
02959    ac++;
02960    if(ac >= a && ac <= na){
02961      if(fg){
02962        DrawFrameIndicators(hdc,0,(ac-a)*A_H+7,ff,lf);
02963        TextOut(hdc,1,(ac-a)*A_H+7,np->actorname,min(strlen(np->actorname),8));
02964        SetTextColor(hdc,RGB(0,0,0));  // strange needed for SRCAND
02965        DrawPopupButton(hdc,45,(ac-a)*A_H+7);
02966        SetTextColor(hdc,RGB(255,255,255));
02967      }
02968 //     else PatBlt(hdc,1,(ac-a)*A_H+1,100,20,PATCOPY);
02969      else PatBlt(hdc,0,(ac-a)*A_H+6,rc.right,14,PATCOPY);
02970    }
02971    np=np->next;
02972  }
02973  ReleaseDC(hWnd,hdc);
02974 }
02975 
02976 static void DrawActorTime(HDC hdc, HPEN hp, HPEN *hps, RECT rc, int f, int a,
02977                           int na, int fa, node *np, int ac, int f_f, int l_f){
02978  int ff,lf;
02979  sky *sp;
02980  director *dp;
02981  object *op;
02982  position *pp;
02983  align *ap;
02984  size  *xp;
02985  HBRUSH hOldBrush;
02986  HPEN   hPen,hOldPen;
02987  SelectObject(hdc,GetStockObject(BLACK_PEN));
02988  hOldBrush=SelectObject(hdc,GetStockObject(NULL_BRUSH));
02989  lf=(Nframes-f+1)*F_W;
02990  MoveToEx(hdc,0,(ac-a)*A_H+24,NULL); LineTo(hdc,lf,(ac-a)*A_H+24);
02991  MoveToEx(hdc,0,(ac-a)*A_H+34,NULL); LineTo(hdc,lf,(ac-a)*A_H+34);
02992  MoveToEx(hdc,0,(ac-a)*A_H+44,NULL); LineTo(hdc,lf,(ac-a)*A_H+44);
02993  MoveToEx(hdc,0,(ac-a)*A_H+54,NULL); LineTo(hdc,lf,(ac-a)*A_H+54);
02994  if(!ScrollingTimeLine){
02995    LoadString(ghinst_main,IDX_MISC_LANGUAGE,res_str,256);
02996    if(strcmp(res_str,"ENGLISH") == 0)
02997      SelectObject(hdc,GetStockObject(ANSI_VAR_FONT));
02998    SetTextColor(hdc,RGB(255,255,255));
02999    DrawFrameIndicators(hdc,0,(ac-a)*A_H+7,f_f,l_f);
03000    TextOut(hdc,1,(ac-a)*A_H+7,np->actorname,min(strlen(np->actorname),8));
03001    SetTextColor(hdc,RGB(0,0,0));
03002    DrawPopupButton(hdc,45,(ac-a)*A_H+7);
03003  }
03004  SelectObject(hdc,GetStockObject(BLACK_BRUSH));
03005  if(np->type == SKY){
03006    if((sp=np->fsky) != NULL)while(sp != NULL){
03007      ff=sp->firstframe; lf=sp->lastframe;
03008      if( (ff >= f && ff <= fa) ||
03009          (lf >= f && lf <= fa) ||
03010          (ff <  f && lf >  fa) ){
03011        DrawTime(hdc,0,(ac-a)*A_H+24,(ff-f)*F_W,(lf-f)*F_W,hp,hps[0]);
03012      }
03013      sp=sp->next;
03014    }
03015  }
03016  else if(np->type == DIRECTOR){
03017    if((dp=np->fdirector) != NULL)while(dp != NULL){
03018      ff=dp->firstframe; lf=dp->lastframe;
03019      if( (ff >= f && ff <= fa) ||
03020          (lf >= f && lf <= fa) ||
03021          (ff <  f && lf >  fa) ){
03022        DrawTime(hdc,0,(ac-a)*A_H+24,(ff-f)*F_W,(lf-f)*F_W,hp,hps[0]);
03023      }
03024      dp=dp->next;
03025    }
03026  }
03027  else{
03028    if((op=np->fobj) != NULL)while(op != NULL){
03029      ff=op->firstframe; lf=op->lastframe;
03030      if( (ff >= f && ff <= fa) ||
03031          (lf >= f && lf <= fa) ||
03032          (ff <  f && lf >  fa) ){
03033        DrawTime(hdc,0,(ac-a)*A_H+24,(ff-f)*F_W,(lf-f)*F_W,hp,hps[0]);
03034      }
03035      op=op->next;
03036    }
03037  }
03038  if((pp=np->fpos) != NULL)while(pp != NULL){
03039    ff=pp->firstframe; lf=pp->lastframe;
03040    if( (ff >= f && ff <= fa) ||
03041        (lf >= f && lf <= fa) ||
03042        (ff <  f && lf >  fa) ){
03043      DrawTime(hdc,1,(ac-a)*A_H+34,(ff-f)*F_W,(lf-f)*F_W,hp,hps[1]);
03044    }
03045    pp=pp->next;
03046  }
03047  if((ap=np->fali) != NULL)while(ap != NULL){
03048    ff=ap->firstframe; lf=ap->lastframe;
03049    if( (ff >= f && ff <= fa) ||
03050        (lf >= f && lf <= fa) ||
03051        (ff <  f && lf >  fa) ){
03052      DrawTime(hdc,2,(ac-a)*A_H+44,(ff-f)*F_W,(lf-f)*F_W,hp,hps[2]);
03053    }
03054    ap=ap->next;
03055  }
03056  if((xp=np->fsiz) != NULL)while(xp != NULL){
03057    ff=xp->firstframe; lf=xp->lastframe;
03058    if( (ff >= f && ff <= fa) ||
03059        (lf >= f && lf <= fa) ||
03060        (ff <  f && lf >  fa) ){
03061      DrawTime(hdc,3,(ac-a)*A_H+54,(ff-f)*F_W,(lf-f)*F_W,hp,hps[3]);
03062    }
03063    xp=xp->next;
03064  }
03065  hPen=CreatePen(PS_SOLID,2,RGB(192,192,192));
03066  hOldPen=SelectObject(hdc,hPen);
03067  MoveToEx(hdc,0,(ac-a)*A_H+59,NULL); LineTo(hdc,rc.right,(ac-a)*A_H+59);
03068  SelectObject(hdc,hOldPen);
03069  DeleteObject(hPen);
03070  SelectObject(hdc,hOldBrush);
03071  return;
03072 }
03073 
03074 
03075 // script part 4
03076 
03077 static BOOL RegisterTimelineClass(HINSTANCE hInstance){
03078  WNDCLASS wc;
03079  /* main window */
03080  wc.lpszClassName = szTimelineClass;
03081  wc.style = 0;
03082  wc.lpfnWndProc = (WNDPROC)TimelineEditorWndProc;
03083  wc.cbClsExtra = 0;
03084  wc.cbWndExtra = 0;
03085  wc.hInstance = hInstance;
03086  wc.hIcon = LoadIcon(hInstance,"ANIMATORICON");
03087  wc.hCursor = LoadCursor(NULL,IDC_ARROW);
03088  wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
03089  if(keyframer_docked)wc.lpszMenuName = NULL;
03090  else                wc.lpszMenuName = MAKEINTRESOURCE(TIMELINE_MENU);
03091  if(!RegisterClass( &wc ))return FALSE;
03092  /* child window */
03093  wc.lpszClassName = szTimelineChildClass;
03094  wc.style = CS_DBLCLKS;
03095  wc.lpfnWndProc = (WNDPROC)TimelineChildWndProc;
03096  wc.cbClsExtra = 0;
03097  wc.cbWndExtra = 0;
03098  wc.hInstance = hInstance;
03099  wc.hIcon = NULL;
03100  wc.hCursor = LoadCursor(NULL,IDC_ARROW);
03101  wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
03102 // wc.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
03103  wc.lpszMenuName = NULL;
03104  if(!RegisterClass( &wc ))return FALSE;
03105  FirstTime=FALSE;
03106  return TRUE;
03107 }
03108 
03109 static LRESULT CALLBACK TimelineEditorWndProc(HWND hWnd, UINT msg,
03110                             WPARAM wparam, LPARAM lparam ){
03111  int i;
03112  RECT  rc;
03113  static RECT ClientClip;
03114  switch( msg ){
03115    case WM_DESTROY:{
03116        char str[64];
03117        if(hTimelineBitmap != NULL)DeleteObject(hTimelineBitmap);
03118        hTimelineBitmap=NULL;
03119        DestroyWindow(ghwndTimelineChild);
03120        if(IsZoomed(hWnd) || IsIconic(hWnd) || keyframer_docked > 0)break;
03121        GetWindowRect(hWnd,&rc);
03122        sprintf(str,"%ld %ld %ld %ld",rc.left,rc.top,
03123                rc.right-rc.left,rc.bottom-rc.top);
03124        if(Preferences.use_positions)
03125          WritePrivateProfileString("KEYFRAMER","POSITION",str,IniFilename);
03126        for(i=0;i<5;i++){
03127          X__Free(linetype[i]); linetype[i]=NULL;
03128        }
03129      }
03130      break;
03131    case WM_CREATE: {
03132        HMENU hmenu = GetSystemMenu(hWnd, FALSE);
03133        RemoveMenu(hmenu, 7, MF_BYPOSITION);
03134 //       RemoveMenu(hmenu, SC_MINIMIZE, MF_BYCOMMAND);
03135        RemoveMenu(hmenu, SC_TASKLIST, MF_BYCOMMAND);
03136        if(!keyframer_docked){
03137          hwndTimelineInfo=CreateWindowEx(0L,STATUSCLASSNAME,"",
03138            WS_CHILD | !WS_BORDER | WS_VISIBLE,
03139            0,0,0,0,
03140            hWnd,
03141            (HMENU)101,
03142            ghinst_main,
03143            NULL);
03144          SendMessage(hwndTimelineInfo,SB_SETPARTS,(WPARAM)3,
03145                      (LPARAM)TimelineStatusPartsList);
03146        }
03147        else hwndTimelineInfo=NULL;
03148        ghwndTimelineChild = CreateWindow(szTimelineChildClass," ",
03149                                          fdwStyleC,
03150                                          0,0,0,0,
03151                                          hWnd,
03152                                          (HMENU)102,
03153                                          ghinst_main,NULL);
03154        hTimelineBitmap=LoadBitmap(ghinst_main,MAKEINTRESOURCE(IDBM_TIMELINE));
03155      }
03156      break;
03157    case WM_PAINT: {
03158        HDC hdc;
03159        PAINTSTRUCT ps;
03160        hdc=BeginPaint(hWnd,&ps);
03161        if(keyframer_docked && hTimelineBitmap != NULL){
03162          HDC hMemDC;
03163          HBITMAP hbmOld;
03164          BITMAP bmp;
03165          hMemDC = CreateCompatibleDC(hdc);
03166          GetObject(hTimelineBitmap,sizeof(BITMAP),&bmp);
03167          hbmOld = SelectObject(hMemDC,hTimelineBitmap);
03168          BitBlt(hdc,0,0,bmp.bmWidth,bmp.bmHeight,hMemDC,0,0,SRCCOPY);
03169          SelectObject(hMemDC, hbmOld);
03170          DeleteDC(hMemDC);
03171        }
03172        EndPaint(hWnd,&ps);
03173      }
03174      break;
03175 //#if 0
03176    case WM_ACTIVATE:
03177        if(IndicatorVisible)DrawHairs(NULL,ghwndTimelineChild,
03178          IndicatedFrame,IndicatedActor,IndicatedLine);
03179        if(wparam)IndicatorActive=YES;
03180        else      IndicatorActive=NO;
03181        IndicatorVisible=NO;
03182       break;
03183 //#endif
03184    case WM_MOUSEMOVE:
03185    case WM_NCMOUSEMOVE:
03186      if(IndicatorVisible)DrawHairs(NULL,ghwndTimelineChild,
03187          IndicatedFrame,IndicatedActor,IndicatedLine);
03188      IndicatorVisible=NO;
03189      UpdateIndicators(-1,-1,-1,-1,-1);
03190      IndicatedFrame = -1; IndicatedActor = -1; IndicatedLine = -1;
03191      break;
03192    case WM_SIZE:{
03193        int yOff=0,xOff=0;
03194        if(keyframer_docked){
03195          yOff=1;
03196          xOff=56;
03197        }
03198        if(IsWindow(hwndTimelineInfo)){
03199          SendMessage(hwndTimelineInfo,msg,wparam,lparam);
03200          i=InfoWindowSize;
03201        }
03202        else i=0;
03203        MoveWindow(ghwndTimelineChild,xOff,yOff,
03204                   LOWORD(lparam)-xOff,
03205                   HIWORD(lparam)-i-yOff,TRUE);
03206      }
03207      break;
03208    case WM_SYSCOMMAND:
03209      switch(LOWORD(wparam & 0xfff0)){
03210        case SC_MINIMIZE:
03211          PostMessage(ghwnd_main,WM_COMMAND,IDM_FILE_KEYFRAMERDOCK,0);
03212          break;
03213        case SC_CLOSE:
03214          PostMessage(hWnd,WM_COMMAND,IDM_TIMELINE_HIDE,0);
03215          break;
03216        default:
03217          return( DefWindowProc( hWnd, msg, wparam, lparam ) );
03218          break;
03219      }
03220      break;
03221    case WM_COMMAND:{
03222      switch (LOWORD(wparam)){
03223         case IDM_TIMELINE_ACTOR_ADD:
03224           AddOnlyNewNode(hWnd,-1);
03225           UPDATETIMELINES(IDC_TIMEL_UPDATE)
03226           break;
03227         case IDM_TIMELINE_ACTOR_ORDER:
03228           DialogBox(ghinst_main,MAKEINTRESOURCE(DLG_REORDER),
03229                          ghwndTimeline,(DLGPROC)ReorderDlgProc);
03230           UPDATETIMELINES(IDC_TIMEL_UPDATE)
03231           break;
03232         case IDM_TIMELINE_ACTOR_DELETE:
03233         case IDM_TIMELINE_ACTOR_RENAME:
03234         case IDM_TIMELINE_ACTOR_INFO:
03235         case IDM_TIMELINE_ACTOR_SAVEANIOBJ:
03236           DoKeyFramerCommand(wparam,0);
03237           break;
03238         case IDM_TIMELINE_FRAMES:
03239           SendMessage(ghwnd_main,WM_COMMAND,IDM_FRAME_SETNUMBER,0);  
03240           break;
03241         case IDM_TIMELINE_INSERTFRAMES:
03242           SendMessage(ghwnd_main,WM_COMMAND,IDM_FRAME_INSERT,0);  
03243           break;
03244         case IDM_TIMELINE_DELETEFRAMES:
03245           SendMessage(ghwnd_main,WM_COMMAND,IDM_FRAME_DELETE,0);  
03246           break;
03247         case IDM_TIMELINE_HIDE:{
03248             char tt[128];
03249             ShowWindow(hWnd,SW_HIDE);
03250             TimeLineVisibleFlag=0;
03251             IndicatorVisible = NO;
03252             IndicatedActor= -1, IndicatedFrame= -1, IndicatedLine= -1;
03253             LoadString(ghinst_main,IDX_MISC_SKEYFRAMER,tt,128);
03254             ModifyMenu(GetMenu(ghwnd_main),IDM_FILE_KEYFRAMER,
03255                     MF_BYCOMMAND|MF_STRING,IDM_FILE_KEYFRAMER,tt);
03256           }
03257           break;
03258         case IDC_TIMEL_UPDATE:
03259           SendMessage(ghwndTimelineChild,WM_KEYFRAMEUPDATE,0,0);
03260           break;
03261         default: break;
03262      }
03263      break;
03264    }
03265    default:
03266      return( DefWindowProc( hWnd, msg, wparam, lparam ) );
03267  }
03268  return( 0L );
03269 }
03270 
03271 static LRESULT CALLBACK TimelineChildWndProc(HWND hWnd, UINT msg,
03272                             WPARAM wparam, LPARAM lparam ){
03273  int i,iPos,iMax,iMin,dn,lastframe,lastactor,firstframe,firstactor;
03274  RECT  rc;
03275  POINT pt;
03276  static BOOL bTrackMouse=FALSE,bClientArea=FALSE,bEditKey=FALSE,
03277              bEditKeyStart=FALSE;
03278  static RECT ClientClip;
03279  switch( msg ){
03280    case WM_PAINT: {
03281        HDC hdc;
03282        PAINTSTRUCT ps;
03283        node *np;
03284        HPEN hp,hps[4];
03285        int f,a,ac=0,na,fa;
03286        hdc=BeginPaint(hWnd,&ps);
03287        SetBkMode(hdc,TRANSPARENT);
03288        f=GetScrollPos(hWnd,SB_HORZ)/F_W+1;
03289        a=GetScrollPos(hWnd,SB_VERT)/A_H+1;
03290        hp=CreatePen(PS_SOLID,2,RGB(255,0,0));
03291 #if 0    // the original colours
03292        hps[0]=CreatePen(PS_SOLID,2,RGB(0,255,255));
03293        hps[1]=CreatePen(PS_SOLID,2,RGB(255,255,0));
03294        hps[2]=CreatePen(PS_SOLID,2,RGB(0,255,0));
03295        hps[3]=CreatePen(PS_SOLID,2,RGB(255,0,0));
03296 #endif
03297        hps[0]=CreatePen(PS_SOLID,2,RGB(145,255,94));
03298        hps[1]=CreatePen(PS_SOLID,2,RGB(0,255,255));
03299        hps[2]=CreatePen(PS_SOLID,2,RGB(255,255,0));
03300        hps[3]=CreatePen(PS_SOLID,2,RGB(255,96,0));
03301        na=a+ps.rcPaint.bottom/A_H; fa=f+ps.rcPaint.right/F_W;
03302        if((np=FirstNp) != NULL)while(np != NULL){
03303          ac++;
03304          if(ac >= a && ac <= na){
03305            GetClientRect(hWnd,&rc);
03306            GetIndicators(0,0,rc,&i,&i,&i,&firstframe,&i,&lastframe,&i);
03307            DrawActorTime(hdc,hp,hps,ps.rcPaint,f,a,na,fa,np,ac,
03308                          firstframe,lastframe);
03309          }
03310          np=np->next;
03311        }
03312        if(IndicatorVisible){
03313          DrawHairs(hdc,hWnd,IndicatedFrame,IndicatedActor,IndicatedLine);
03314          UpdateWindow(hWnd);
03315        }
03316        DeleteObject(hp);
03317        DeleteObject(hps[0]); DeleteObject(hps[1]);
03318        DeleteObject(hps[2]); DeleteObject(hps[3]);
03319        EndPaint(hWnd,&ps);
03320      }
03321      break;
03322    case WM_LBUTTONDBLCLK:
03323      if(bEditKey){
03324        Save_UndoA();
03325        if(IndicatedLine == 0)EditObject(IndicatedNode,
03326                                         (short)IndicatedFrame,
03327                                         (short)IndicatedFrame,
03328                                         YES,NO);
03329        if(IndicatedLine == 1)EditPosition(IndicatedNode,
03330                              (short)IndicatedFrame,
03331                              (short)IndicatedFrame,-1,ghwndTimeline);
03332        if(IndicatedLine == 2)EditAlign(IndicatedNode,
03333                              (short)IndicatedFrame,
03334                              (short)IndicatedFrame,-1,ghwndTimeline);
03335        if(IndicatedLine == 3)EditSize(IndicatedNode,
03336                              (short)IndicatedFrame,(short)IndicatedFrame);
03337        IndicatedNode=NULL;
03338        UPDATETIMELINES(IDC_TIMEL_UPDATE)
03339        UPDATETRIVIEW(0)
03340        bEditKey=0;
03341      }
03342      /* could add keyframe command here */
03343      break;
03344    case WM_LBUTTONDOWN:
03345      if(IndicatorActive == YES){
03346 //       SetCursor(ghcurCross); /* hide cursor */
03347        UpdateWindow(hWnd);
03348        if(!IndicatorVisible){
03349          GetClientRect(hWnd,&rc);
03350          GetIndicators((int)LOWORD(lparam),(int)HIWORD(lparam),rc,
03351                    &IndicatedFrame,&IndicatedActor,&IndicatedLine,
03352                    &firstframe,&firstactor,&lastframe,&lastactor);
03353          DrawHairs(NULL,hWnd,IndicatedFrame,IndicatedActor,IndicatedLine);
03354          UpdateWindow(hWnd);
03355          IndicatorVisible=YES;
03356        }
03357      }
03358      if(tool != NOTOOL){
03359        MessageBeep(MB_OK);
03360        break;
03361      }
03362      bEditKey=FALSE;
03363      if(IndicatedActor >  0 && IndicatedActor <= Nnodes  &&
03364         IndicatedFrame >  0 && IndicatedFrame <= Nframes &&
03365         IndicatedLine  >= 0 && IndicatedLine  <  4){
03366        int f,a;
03367        f=GetScrollPos(hWnd,SB_HORZ)/F_W;
03368        a=GetScrollPos(hWnd,SB_VERT)/A_H;
03369        SetCapture(hWnd);
03370        GetClientRect(hWnd,&rc);
03371        pt.x=0;
03372        pt.y=(IndicatedActor-1-a)*A_H+(IndicatedLine+2)*L_H;
03373        ClientClip.left=pt.x; ClientClip.top=pt.y;
03374        ClientToScreen(hWnd,&pt); rc.left=pt.x; rc.top=pt.y;
03375        pt.x=rc.right;  // pt.x=min(rc.right,(Nframes-f)*F_W);
03376        pt.y=min((IndicatedActor-1-a)*A_H+(IndicatedLine+3)*L_H,rc.bottom);
03377        ClientClip.right=pt.x; ClientClip.bottom=pt.y-1; //test
03378        ClientToScreen(hWnd,&pt); rc.right=pt.x; rc.bottom=pt.y;
03379        ClipCursor(&rc);
03380        bTrackMouse=TRUE;
03381        if((IndicatedNode=EditTimeLine(IndicatedActor,IndicatedFrame,
03382            IndicatedLine,&bEditKeyStart)) != NULL)bEditKey=TRUE;
03383      }
03384      else if((IndicatedLine == -1 || IndicatedLine == -2)
03385              && IndicatedActor <= Nnodes
03386              && LOWORD(lparam) < 55 && LOWORD(lparam) > 42){
03387        Save_UndoA();
03388        {
03389          POINT pt;
03390          HMENU hMenu=LoadMenu(ghinst_main,"KeyframerPopupMenu");
03391          node *local_node;
03392          if(hMenu == NULL)break;
03393          pt.x=LOWORD(lparam);
03394          pt.y=HIWORD(lparam);
03395          ClientToScreen(hWnd,&pt);
03396          local_node=FirstNp;
03397          if(IndicatedActor > 1)
03398            for(i=1;i<IndicatedActor;i++)local_node=local_node->next;
03399          if(local_node != NULL){
03400            if(local_node->type != NORMAL)
03401              EnableMenuItem(hMenu,IDM_TIMELINE_ACTOR_SAVEANIOBJ,MF_GRAYED);
03402            if(local_node->type == CAMERA ||
03403               local_node->type == DIRECTOR ||
03404               local_node->type == SKY)
03405              EnableMenuItem(hMenu,IDM_TIMELINE_ACTOR_INFO,MF_GRAYED);
03406          }
03407          TrackPopupMenu(GetSubMenu(hMenu,0),TPM_LEFTALIGN | TPM_LEFTBUTTON,
03408                         pt.x,pt.y,0,hWnd,NULL);
03409          DestroyMenu(hMenu);
03410        }
03411      }
03412      break;
03413    case WM_LBUTTONUP:
03414      if(IndicatorsChanged){
03415        IndicatorsChanged=NO;
03416        UPDATETRIVIEW(0)
03417        if(IndicatedNode != NULL){
03418          if(IndicatedObject != NULL && IndicatedObject->type == PATH){
03419            int dfn;
03420            dfn=IndicatedObject->lastframe - IndicatedObject->firstframe + 1;
03421            IndicatedObject->v=ReTweenVelocity(IndicatedObject,
03422                                               IndicatedObject->v,
03423                                               -1,dfn,
03424                                               IndicatedObject->pathlength,
03425                                               0);
03426          }
03427          CheckRecursiveFollow(IndicatedNode,1,(short)Nframes);
03428        }
03429      }
03430      if(bTrackMouse){
03431        bTrackMouse=FALSE;
03432        IndicatedSky=NULL;      IndicatedObject=NULL;
03433        IndicatedPosition=NULL; IndicatedAlign=NULL;
03434        IndicatedSize=NULL;     IndicatedDirector=NULL;
03435        ClipCursor(NULL);
03436        if(ScrollingTimeLine){
03437          if(IndicatorVisible)DrawHairs(NULL,hWnd,
03438                              IndicatedFrame,IndicatedActor,IndicatedLine);
03439          GetClientRect(hWnd,&rc);
03440          GetIndicators(0,0,rc,&i,&i,&i,&firstframe,&i,&lastframe,&i);
03441          DrawActorNames(hWnd,1,firstframe,lastframe);
03442          if(IndicatorVisible)DrawHairs(NULL,hWnd,
03443                              IndicatedFrame,IndicatedActor,IndicatedLine);
03444          ScrollingTimeLine=0;
03445        }
03446        ReleaseCapture();
03447      }
03448      break;
03449    case WM_MOUSEMOVE:
03450 //     if(IndicatorActive == YES)SetCursor(ghcurCross); /* hidden cursor */
03451      bClientArea=TRUE;
03452      GetClientRect(hWnd,&rc);
03453      i=IndicatedFrame;
03454      iMin=IndicatedLine; iMax=IndicatedActor;
03455      GetIndicators((int)LOWORD(lparam),(int)HIWORD(lparam),rc,
03456                    &IndicatedFrame,&IndicatedActor,&IndicatedLine,
03457                    &firstframe,&firstactor,&lastframe,&lastactor);
03458      if(IndicatorActive && (i != IndicatedFrame ||
03459                          iMax != IndicatedActor || iMin != IndicatedLine)){
03460        UpdateWindow(hWnd);
03461        if(IndicatorVisible)DrawHairs(NULL,hWnd,i,iMax,iMin);
03462        DrawHairs(NULL,hWnd,IndicatedFrame,IndicatedActor,IndicatedLine);
03463        IndicatorVisible=YES;
03464      }
03465      UpdateIndicators(IndicatedFrame,IndicatedActor,IndicatedLine,
03466                       firstframe,lastframe);
03467      if(i != IndicatedFrame){
03468        if(ChangeIndicatedKeys(bEditKeyStart)){
03469          IndicatorsChanged=YES;
03470          InvalidateRect(hWnd,&ClientClip,TRUE);
03471          UpdateWindow(hWnd);
03472        }
03473      }
03474      if(bTrackMouse && (IndicatedFrame >= lastframe-1 ||
03475                         IndicatedFrame == firstframe) ){
03476        GetScrollRange(hWnd, SB_HORZ, &iMin, &iMax);
03477        iPos = GetScrollPos(hWnd, SB_HORZ);
03478        if(IndicatedFrame >= lastframe-1)dn=  F_W;
03479        else                             dn= -F_W;
03480        if ((dn = BOUND (iPos + dn, iMin, iMax) - iPos) != 0) {
03481          if(IndicatorVisible)DrawHairs(NULL,hWnd,
03482            IndicatedFrame,IndicatedActor,IndicatedLine);
03483          DrawActorNames(hWnd,0,firstframe,lastframe);
03484          if(IndicatorVisible)DrawHairs(NULL,hWnd,
03485            IndicatedFrame,IndicatedActor,IndicatedLine);
03486          ScrollingTimeLine=1;
03487          ScrollWindow(hWnd, -dn, 0, NULL, NULL);
03488          SetScrollPos(hWnd, SB_HORZ, iPos + dn, TRUE);
03489          UpdateWindow(hWnd);
03490          GetCursorPos(&pt);
03491          if(IndicatedFrame >= lastframe-1)pt.x -= dn;
03492          else                             pt.x += (abs(dn));
03493          SetCursorPos(pt.x,pt.y);
03494        }
03495      }
03496      break;
03497    case WM_VSCROLL:
03498      GetScrollRange (hWnd, SB_VERT, &iMin, &iMax);
03499      iPos = GetScrollPos (hWnd, SB_VERT);
03500      GetClientRect (hWnd, &rc);
03501      switch (LOWORD(wparam)) {
03502        case SB_ENDSCROLL:
03503          dn=0;
03504          break;
03505        case SB_LINEDOWN:      dn =  A_H;                  break;
03506        case SB_LINEUP:        dn = -A_H;                  break;
03507        case SB_PAGEDOWN:      dn =  rc.bottom / 2  + A_H; break;
03508        case SB_PAGEUP:        dn = -rc.bottom / 2  - A_H; break;
03509        case SB_THUMBTRACK:
03510        case SB_THUMBPOSITION:
03511          dn = HIWORD(wparam)-iPos;
03512          break;
03513        default:               dn = 0;
03514      }
03515      /* Limit scrolling to current scroll range */
03516      dn=(dn/A_H)*A_H;
03517      if ((dn = BOUND (iPos + dn, iMin, iMax) - iPos) != 0) {
03518        ScrollWindow(hWnd, 0, -dn, NULL, NULL);
03519        SetScrollPos(hWnd, SB_VERT, iPos + dn, TRUE);
03520        IndicatedActor=(iPos+dn)/A_H+1;
03521      }
03522      break;
03523    case WM_HSCROLL:
03524      /* Calculate new horizontal scroll position */
03525      GetScrollRange(hWnd, SB_HORZ, &iMin, &iMax);
03526      iPos = GetScrollPos(hWnd, SB_HORZ);
03527      GetClientRect (hWnd, &rc);
03528      switch (LOWORD(wparam)) {
03529        case SB_ENDSCROLL:
03530          if(ScrollingTimeLine){
03531            ScrollingTimeLine=0;
03532            GetIndicators(0,0,rc,&i,&i,&i,&firstframe,&i,&lastframe,&i);
03533            DrawActorNames(hWnd,1,firstframe,lastframe);
03534          }
03535          dn=0;
03536          break;
03537        case SB_LINEDOWN:      dn =  F_W;             break;
03538        case SB_LINEUP:        dn = -F_W;             break;
03539        case SB_PAGEDOWN:      dn =  rc.right/5+F_W;  break;
03540        case SB_PAGEUP:        dn = -rc.right/5+F_W;  break;
03541        case SB_THUMBTRACK:
03542        case SB_THUMBPOSITION:
03543          dn = HIWORD(wparam) - iPos;
03544          break;
03545        default:               dn = 0;
03546      }
03547      /* Limit scrolling to current scroll range */
03548      dn=(dn/F_W)*F_W;
03549      if ((dn = BOUND (iPos + dn, iMin, iMax) - iPos) != 0) {
03550        ScrollingTimeLine=1;
03551        GetIndicators(0,0,rc,&i,&i,&i,&firstframe,&i,&lastframe,&i);
03552        DrawActorNames(hWnd,0,firstframe,lastframe);
03553        ScrollWindow(hWnd, -dn, 0, NULL, NULL);
03554        SetScrollPos(hWnd, SB_HORZ, iPos + dn, TRUE);
03555        iMin=(iPos+dn)/F_W+1;
03556        iMax=(iPos+dn+rc.right)/F_W+1;
03557        UpdateIndicators(iMin,-1,-1,iMin,iMax);
03558      }
03559      break;
03560    case WM_SIZE:
03561      SetScrollRanges(hWnd,1);
03562      break;
03563    case WM_NCMOUSEMOVE:{
03564        if(!bClientArea)break;
03565        bClientArea=FALSE;
03566        if(IndicatorVisible)DrawHairs(NULL,hWnd,
03567          IndicatedFrame,IndicatedActor,IndicatedLine);
03568        IndicatorVisible=NO;
03569        UpdateIndicators(-1,-1,-1,-1,-1);
03570        IndicatedFrame = -1; IndicatedActor = -1; IndicatedLine = -1;
03571      }
03572      break;
03573    case WM_KEYFRAMEUPDATE:
03574      if(!TimeLineVisibleFlag)TimeLineUpdateFlag=1;
03575      else{
03576        TimeLineUpdateFlag=0;
03577        if(Nframes != NoldFrames || NoldNodes != Nnodes){
03578          ptSize.x=Nframes*F_W;   ptSize.y=Nnodes*A_H;
03579          SetScrollRanges(hWnd,0);
03580          if(Nframes < NoldFrames){
03581            GetScrollRange(hWnd, SB_HORZ, &iMin, &iMax);
03582            SetScrollPos(hWnd,SB_HORZ,iMin,TRUE);
03583          }
03584          if(Nnodes  < NoldNodes){
03585            GetScrollRange(hWnd, SB_VERT, &iMin, &iMax);
03586            SetScrollPos(hWnd,SB_VERT,iMin,TRUE);
03587          }
03588          NoldFrames=Nframes; NoldNodes=Nnodes;
03589        }
03590        InvalidateRect(hWnd,NULL,TRUE);
03591        UpdateWindow(hWnd);
03592      }
03593      break;
03594    case WM_COMMAND:
03595      switch (LOWORD(wparam)){
03596         case IDM_TIMELINE_ACTOR_DELETE:
03597         case IDM_TIMELINE_ACTOR_RENAME:
03598         case IDM_TIMELINE_ACTOR_INFO:
03599         case IDM_TIMELINE_ACTOR_SAVEANIOBJ:
03600           DoKeyFramerCommand(wparam,IndicatedActor);
03601           break;
03602         default:
03603           break;
03604       }
03605    default:
03606      return( DefWindowProc( hWnd, msg, wparam, lparam ) );
03607  }
03608  return( 0L );
03609 }
03610 
03611 static void DoKeyFramerCommand(WPARAM wparam, int local_actor){
03612  int i,id;
03613  node *local_node,*temp_node;
03614  char local_nodename[128];
03615  if(local_actor == 0){
03616    if((local_node=SelectNode(local_nodename,YES,ghwndTimeline))
03617                               == NULL)return;
03618  }
03619  else {
03620    local_node=FirstNp;
03621    if(local_actor > 1)for(i=1;i<local_actor;i++)local_node=local_node->next;
03622    if(local_node == NULL)return;
03623 //   if((id=DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_KEYF_COMMAND),
03624 //       ghwndTimeline,(DLGPROC)DlgCommandDlgProc,(LPARAM)local_node)) < 0)
03625 //     return;
03626 //   wparam=id;
03627    strcpy(local_nodename,local_node->actorname);
03628  }
03629  switch (LOWORD(wparam)){
03630    case IDM_TIMELINE_ACTOR_DELETE:
03631      if(local_node->type == CAMERA){
03632        if(local_node == FirstNp){
03633          SendPrgmQuery(IDQ_CAMERANODELETE,0);
03634          break;
03635        }
03636        if(local_node == SelectedCamera)SelectedCamera=FirstNp;
03637        DeleteNode(local_node);
03638        SelectedNode=NULL;
03639        UpdateSelectedActor(FALSE);
03640        Ncameras--;
03641      }
03642      else {
03643        if(local_node->type == GROUND)Nground=0;
03644        if(local_node->type == SKY)Nskys=0;
03645        if(local_node->type == DIRECTOR)Ndirectors=0;
03646        if(local_node->type == ROBOT)Nrobots--;
03647        DeleteNode(local_node);
03648        SelectedNode=NULL;
03649        UpdateSelectedActor(FALSE);
03650      }
03651      UPDATETIMELINES(IDC_TIMEL_UPDATE)
03652      UPDATETRIVIEW(0)
03653      break;
03654    case IDM_TIMELINE_ACTOR_RENAME:
03655      LoadString(ghinst_main,IDX_MISC_RENAMEOBJECT,res_str,256);
03656      RequestCharString(64,local_node->actorname,res_str);
03657      UPDATETIMELINES(IDC_TIMEL_UPDATE)
03658      break;
03659    case IDM_TIMELINE_ACTOR_INFO:
03660      temp_node=SelectedNode;
03661      SelectedNode=local_node;
03662      SelectedInfo();
03663      SelectedNode=temp_node;
03664      break;
03665    case IDM_TIMELINE_ACTOR_SAVEANIOBJ:
03666      SaveAnimFile(local_node);
03667      break;
03668  }
03669 }
03670 
03671 void TimelineEditor(void){
03672  char str[64];
03673  char tt[128];
03674  int i,x,y,cx,cy,nf;
03675  if(FirstTime){
03676    if(!RegisterTimelineClass(ghinst_main))return;
03677    xScreen     = GetSystemMetrics(SM_CXSCREEN);
03678    yScreen     = GetSystemMetrics(SM_CYSCREEN);
03679    nXBorder    = (INT)GetSystemMetrics(SM_CXFRAME);
03680    nXTitle     = (INT)GetSystemMetrics(SM_CXSIZE);
03681    nYTitle     = (INT)GetSystemMetrics(SM_CYSIZE);
03682    x=0; y=nYTitle+GetSystemMetrics(SM_CYFRAME)+GetSystemMetrics(SM_CYMENU)
03683                  +GetSystemMetrics(SM_CYBORDER);
03684    if(Xres >= 800)nf=60; else nf=40;
03685    cx=(max(nf,Nframes))*F_W;   cy=(max(3,Nnodes))*A_H+25;
03686    GetPrivateProfileString("KEYFRAMER","POSITION","$$$",
03687                    str,sizeof(str),IniFilename);
03688    if(Preferences.use_positions && strncmp(str,"$$$",3) != 0){ /* if valid paramaters */
03689      int xx,yy,cxx,cyy;
03690      sscanf(str,"%ld %ld %ld %ld",&xx,&yy,&cxx,&cyy);
03691      if(xx < Xres-10 && yy < Yres-10){
03692        x=xx; y=yy;
03693        cx=cxx;
03694        cy=cyy;
03695      }
03696    }
03697    NoldFrames=Nframes; NoldNodes=Nnodes;
03698    for(i=0;i<5;i++)linetype[i]=X__Malloc(16);
03699    if(linetype[0] != NULL)LoadString(ghinst_main,IDX_MISC_LINE1,linetype[0],16);
03700    if(linetype[1] != NULL)LoadString(ghinst_main,IDX_MISC_LINE2,linetype[1],16);
03701    if(linetype[2] != NULL)LoadString(ghinst_main,IDX_MISC_LINE3,linetype[2],16);
03702    if(linetype[3] != NULL)LoadString(ghinst_main,IDX_MISC_LINE4,linetype[3],16);
03703    if(linetype[4] != NULL)LoadString(ghinst_main,IDX_MISC_LINE0,linetype[4],16);
03704    LoadString(ghinst_main,IDX_MISC_KEYFRAMER,str,64);
03705    if(keyframer_docked){
03706      RECT rc;
03707      GetClientRect(ghwnd_main,&rc);
03708      if((ghwndTimeline = CreateWindow(szTimelineClass,str,
03709         fdwStyleD,
03710         0,KeyframerYpos,
03711         rc.right,KeyframerSize,
03712         ghwnd_main,NULL,ghinst_main,NULL)) == NULL)return;
03713    }
03714    else{
03715      if((ghwndTimeline = CreateWindow(szTimelineClass,str,
03716         fdwStyleP,
03717         x,y,0,0,ghwnd_main,NULL,ghinst_main,NULL)) == NULL)return;
03718      SetWindowPos(ghwndTimeline,(HWND)NULL,0,0,
03719        min(Xres,cx),min(Yres-100,cy),SWP_NOMOVE | SWP_NOZORDER);
03720    }
03721    ShowWindow(ghwndTimeline,SW_SHOW);
03722    TimeLineVisibleFlag=1;
03723    LoadString(ghinst_main,IDX_MISC_HKEYFRAMER,tt,128);
03724    ModifyMenu(GetMenu(ghwnd_main),IDM_FILE_KEYFRAMER,
03725            MF_BYCOMMAND|MF_STRING,IDM_FILE_KEYFRAMER,tt);
03726    { int iMin,iMax;
03727      ptSize.x=Nframes*F_W;   ptSize.y=Nnodes*A_H;
03728      SetScrollRanges(ghwndTimelineChild,0);
03729      GetScrollRange(ghwndTimelineChild, SB_HORZ, &iMin, &iMax);
03730      SetScrollPos(ghwndTimelineChild,SB_HORZ,iMin,TRUE);
03731      GetScrollRange(ghwndTimelineChild, SB_VERT, &iMin, &iMax);
03732      SetScrollPos(ghwndTimelineChild,SB_VERT,iMin,TRUE);
03733      InvalidateRect(ghwndTimeline,NULL,TRUE);
03734      UpdateWindow(ghwndTimeline);
03735    }
03736    if(keyframer_docked)IndicatorActive=YES;
03737  }
03738  else{
03739    if(TimeLineVisibleFlag == 0){
03740      LoadString(ghinst_main,IDX_MISC_HKEYFRAMER,tt,128);
03741      ModifyMenu(GetMenu(ghwnd_main),IDM_FILE_KEYFRAMER,
03742              MF_BYCOMMAND|MF_STRING,IDM_FILE_KEYFRAMER,tt);
03743      ShowWindow(ghwndTimeline,SW_SHOW);
03744      TimeLineVisibleFlag=1;
03745      if(TimeLineUpdateFlag)UPDATETIMELINES(IDC_TIMEL_UPDATE)
03746    }
03747    else SendMessage(ghwndTimeline,WM_COMMAND,IDM_TIMELINE_HIDE,0);
03748  }
03749 }
03750 
03751 void DestroyTimelineEditor(void){
03752  if(FirstTime)return;
03753  DestroyWindow(ghwndTimeline);
03754  FirstTime=TRUE;
03755  ScrollingTimeLine=0;
03756  TimeLineUpdateFlag=0;
03757  TimeLineVisibleFlag=0;
03758  keyframer_docked_and_visible=0;
03759  IndicatorVisible = NO; IndicatorActive=NO; IndicatorsChanged=NO;
03760  IndicatedActor= -1; IndicatedFrame= -1; IndicatedLine= -1;
03761  UnregisterClass(szTimelineClass,ghinst_main);
03762  UnregisterClass(szTimelineChildClass,ghinst_main);
03763  ghwndTimeline=NULL;
03764  ghwndTimelineChild=NULL;
03765  hwndTimelineInfo=NULL;
03766  return;
03767 }
03768 
03769 void AutoUpdateKeyframerVpos(void){
03770  node *np;
03771  long c;
03772  if(!keyframer_docked_and_visible)return;
03773  if(SelectedNode == NULL)return;
03774  if(ghwndTimelineChild == NULL)return;
03775  if(!Preferences.auto_update_keyframer)return;
03776  c=0;
03777  if((np=FirstNp) != NULL)while(np != NULL){
03778    if(SelectedNode == np){
03779      SetScrollPos(ghwndTimelineChild,SB_VERT,c*A_H,TRUE);
03780      InvalidateRect(ghwndTimelineChild,NULL,TRUE);
03781 //     UpdateWindow(ghwndTimelineChild);
03782      return;
03783    }
03784    c++;
03785    np=np->next;
03786  }
03787  return;
03788 }
03789 // end script part4
03790 
03791 #define EXTEND 0
03792 #define CHOP   0
03793 #define SCALE  1
03794 #define BLANKS 2
03795 
03796 BOOL ActorNameExists(HWND parent,node *this_node,char *name){
03797  node *np;
03798  np=FirstNp; while(np != NULL){
03799    if(np != this_node){
03800      if(strcmpi(np->actorname,name) == 0){
03801        SendPrgmQuery(IDQ_ACTORNAMEEXISTS,0);
03802        return TRUE;
03803      }
03804    }
03805    np=np->next;
03806  }
03807  return FALSE;
03808 }
03809 
03810 void ShiftAllKeys(int allActors){
03811  int n;
03812  node     *Np,*Nstart;
03813  object   *Op,*Op1;
03814  sky      *Sp,*Sp1;
03815  director *Dp,*Dp1;
03816  position *Pp,*Pp1;
03817  align    *Ap,*Ap1;
03818  size     *Xp,*Xp1;
03819  if(allActors)Nstart=FirstNp;
03820  else         Nstart=SelectedNode;
03821  if(Nstart == NULL)return;
03822  n=DialogBox(ghinst_main,MAKEINTRESOURCE(DLG_SHIFTKEYS),
03823              ghwnd_main,(DLGPROC)ShiftKeysDlgProc);
03824  if(n == 0)return;
03825  if(n < -Nframes || n > Nframes){
03826    SendPrgmQuery(IDQ_TOOMANYFRAMES,0);
03827    return;
03828  }
03829  Save_UndoA();
03830  if((Np=Nstart) != NULL)while(Np != NULL){
03831    if(n > 0){ /* shifting later   */
03832      if(Np->type != CAMERA && (Op=Np->fobj) != NULL)while(Op != NULL){
03833        Op1=Op; Op=Op->next;
03834        if(Op1->firstframe+n > Nframes)DeleteCostume(Np,Op1->firstframe);
03835      }
03836      if((Sp=Np->fsky) != NULL)while(Sp != NULL){
03837        Sp1=Sp; Sp=Sp->next;
03838        if(Sp1->firstframe+n > Nframes)DeleteSky(Np,Sp1->firstframe);
03839      }
03840      if((Dp=Np->fdirector) != NULL)while(Dp != NULL){
03841        Dp1=Dp; Dp=Dp->next;
03842        if(Dp1->firstframe+n > Nframes)DeleteDirector(Np,Dp1->firstframe);
03843      }
03844      if((Pp=Np->fpos) != NULL)while(Pp != NULL){
03845        Pp1=Pp; Pp=Pp->next;
03846        if(Pp1->firstframe+n > Nframes)DeletePosition(Np,Pp1->firstframe);
03847      }
03848      if((Ap=Np->fali) != NULL)while(Ap != NULL){
03849        Ap1=Ap; Ap=Ap->next;
03850        if(Ap1->firstframe+n > Nframes)DeleteAlign(Np,Ap1->firstframe);
03851      }
03852      if((Xp=Np->fsiz) != NULL)while(Xp != NULL){
03853        Xp1=Xp; Xp=Xp->next;
03854        if(Xp1->firstframe+n > Nframes)DeleteSize(Np,Xp1->firstframe);
03855      }
03856    }
03857    else{      /* shifting earlier */
03858      if(Np->type != CAMERA && (Op=Np->fobj) != NULL)while(Op != NULL){
03859        Op1=Op; Op=Op->next;
03860        if(Op1->lastframe+n < 1)DeleteCostume(Np,Op1->firstframe);
03861      }
03862      if((Sp=Np->fsky) != NULL)while(Sp != NULL){
03863        Sp1=Sp; Sp=Sp->next;
03864        if(Sp1->lastframe+n < 1)DeleteSky(Np,Sp1->firstframe);
03865      }
03866      if((Dp=Np->fdirector) != NULL)while(Dp != NULL){
03867        Dp1=Dp; Dp=Dp->next;
03868        if(Dp1->lastframe+n < 1)DeleteDirector(Np,Dp1->firstframe);
03869      }
03870      if((Pp=Np->fpos) != NULL)while(Pp != NULL){
03871        Pp1=Pp; Pp=Pp->next;
03872        if(Pp1->lastframe+n < 1)DeletePosition(Np,Pp1->firstframe);
03873      }
03874      if((Ap=Np->fali) != NULL)while(Ap != NULL){
03875        Ap1=Ap; Ap=Ap->next;
03876        if(Ap1->lastframe+n < 1)DeleteAlign(Np,Ap1->firstframe);
03877      }
03878      if((Xp=Np->fsiz) != NULL)while(Xp != NULL){
03879        Xp1=Xp; Xp=Xp->next;
03880        if(Xp1->lastframe+n < 1)DeleteSize(Np,Xp1->firstframe);
03881      }
03882    }
03883    if(Np->type != CAMERA && (Op=Np->fobj) != NULL)while(Op != NULL){
03884      Op->firstframe += n; Op->lastframe += n;
03885      Op->firstframe=max(1,Op->firstframe);
03886      Op->lastframe=min(Nframes,Op->lastframe);
03887      Op=Op->next;
03888    }
03889    if((Sp=Np->fsky) != NULL)while(Sp != NULL){
03890      Sp->firstframe += n; Sp->lastframe += n;
03891      Sp->firstframe=max(1,Sp->firstframe);
03892      Sp->lastframe=min(Nframes,Sp->lastframe);
03893      Sp=Sp->next;
03894    }
03895    if((Dp=Np->fdirector) != NULL)while(Dp != NULL){
03896      Dp->firstframe += n; Dp->lastframe += n;
03897      Dp->firstframe=max(1,Dp->firstframe);
03898      Dp->lastframe=min(Nframes,Dp->lastframe);
03899      Dp=Dp->next;
03900    }
03901    if((Pp=Np->fpos) != NULL)while(Pp != NULL){
03902      Pp->firstframe += n; Pp->lastframe += n;
03903      Pp->firstframe=max(1,Pp->firstframe);
03904      Pp->lastframe=min(Nframes,Pp->lastframe);
03905      Pp=Pp->next;
03906    }
03907    if((Ap=Np->fali) != NULL)while(Ap != NULL){
03908      Ap->firstframe += n; Ap->lastframe += n;
03909      Ap->firstframe=max(1,Ap->firstframe);
03910      Ap->lastframe=min(Nframes,Ap->lastframe);
03911      Ap=Ap->next;
03912    }
03913    if((Xp=Np->fsiz) != NULL)while(Xp != NULL){
03914      Xp->firstframe += n; Xp->lastframe += n;
03915      Xp->firstframe=max(1,Xp->firstframe);
03916      Xp->lastframe=min(Nframes,Xp->lastframe);
03917      Xp=Xp->next;
03918    }
03919    if(!allActors)break; // only doing the selected actor
03920    Np=Np->next;
03921  }
03922  EDIT_ACTION=YES;
03923  UpdateSelectedActor(FALSE);
03924  UPDATETIMELINES(IDC_TIMEL_UPDATE)
03925  ReDrawStageDisplay(TRUE);
03926  if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
03927  else UpdateGLview(TRUE);
03928  return;
03929 }
03930 
03931 void ShiftSelectedPositionAllKeys(void){
03932  int n;
03933  node     *Np;
03934  position *Pp;
03935  double x=0.0,y=0.0,z=0.0;
03936  if((Np=SelectedNode)== NULL)return;
03937  LoadString(ghinst_main,IDX_MISC_MOVEBY,res_str,256);
03938  if(Read3Reals(res_str,&x,&y,&z,0) != OK)return;
03939  Save_UndoA();
03940  if((Pp=Np->fpos) != NULL)while(Pp != NULL){
03941    Pp->finish[0] += (long)(x*ruler)+lrulerx;
03942    Pp->finish[1] += (long)(y*ruler)+lrulery;
03943    Pp->finish[2] += (long)(z*ruler)+lrulerz;
03944    Pp=Pp->next;
03945  }
03946  EDIT_ACTION=YES;
03947  UpdateSelectedActor(FALSE);
03948  UPDATETIMELINES(IDC_TIMEL_UPDATE)
03949  ReDrawStageDisplay(TRUE);
03950  if(ghwndOpenGLview == NULL)PerspectiveView(0,1);
03951  else UpdateGLview(TRUE);
03952  return;
03953 }
03954 
03955 void SetNumberOfFrames(short query){
03956   char string[10];
03957   short number,appear,newappear,oldff,oldlf;
03958   int action;
03959   double   scale,dappear;
03960   node     *Np;
03961   object   *Op,*OpEnd;
03962   sky      *Sp,*SpEnd;
03963   director *Dp,*DpEnd;
03964   position *Pp,*PpEnd;
03965   align    *Ap,*ApEnd;
03966   size     *Xp,*XpEnd;
03967   HWND     hwnd;
03968   if(query < 0){
03969     number= -query;
03970     action=SCALE;
03971   }
03972   else if(query == 0){
03973     if((hwnd=GetActiveWindow()) != ghwndTimeline)hwnd=ghwnd_main;
03974     number=(short)DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_SETFRAMES),
03975            hwnd,(DLGPROC)SetFramesDlgProc,(LPARAM)&action);
03976     if(number < 1)return;
03977 #if __DEMO__
03978     if(number > 70){
03979       LoadString(ghinst_main,IDX_MISC_DEMO1,res_str,256);
03980       MessageBox(NULL,res_str,NULL,MB_OK);
03981       number=70;
03982     }
03983 #endif
03984     if(number < 0)return;
03985     if(number > 0  && number != Nframes){
03986       scale = (double)number/(double)Nframes;
03987     }
03988   }
03989   else{
03990     number=query;
03991     scale = (double)number/(double)Nframes;
03992     action=EXTEND;
03993   }
03994   EDIT_ACTION=YES;
03995   if((Np=FirstNp) != NULL)while(Np != NULL){
03996    OpEnd=NULL;
03997    if((Op=Np->fobj) != NULL)while(Op != NULL){OpEnd=Op;  Op=Op->next;}
03998    if(OpEnd != NULL && (action < BLANKS || Np->type == CAMERA)){
03999      if(action == SCALE){
04000        Op=Np->fobj;
04001        while(Op != NULL){
04002          oldff=Op->firstframe; oldlf=Op->lastframe;
04003          appear=Op->lastframe - Op->firstframe + 1 ;
04004          Op->firstframe = (Op->firstframe - 1) * scale + 1;
04005          newappear = (short)((double)appear * scale);
04006          Op->lastframe = Op->firstframe + newappear;
04007          if(Op->last != NULL){
04008            if(Op->last->lastframe >= Op->firstframe){
04009              Op->firstframe = Op->last->lastframe + 1;
04010              if(Op->lastframe < Op->firstframe)
04011                Op->lastframe = Op->firstframe;
04012            }
04013          }
04014          if(Op->type == PATH && Op->v != NULL){
04015            Op->v=ReTweenVelocity(Op,Op->v,
04016                (int)(oldlf-oldff+1),(int)(Op->lastframe-Op->firstframe+1),
04017                Op->pathlength,0);
04018          }
04019          Op=Op->next;
04020        }
04021      }
04022      if(number > OpEnd->lastframe && OpEnd->lastframe >= Nframes){
04023        oldff=OpEnd->firstframe; oldlf=OpEnd->lastframe;
04024        OpEnd->lastframe=number;
04025        if(OpEnd->type == PATH && OpEnd->v != NULL){
04026          OpEnd->v=ReTweenVelocity(OpEnd,OpEnd->v,
04027               (int)(oldlf-oldff+1),
04028               (int)(OpEnd->lastframe-OpEnd->firstframe+1),
04029               OpEnd->pathlength,0);
04030        }
04031      }
04032    }
04033    if(OpEnd != NULL)while(OpEnd != NULL){
04034      Op=OpEnd->last;
04035      if(OpEnd->firstframe > number)DeleteCostume(Np,OpEnd->firstframe);
04036      else if(OpEnd->lastframe > number){
04037        oldff=OpEnd->firstframe; oldlf=OpEnd->lastframe;
04038        OpEnd->lastframe=number;
04039        if(OpEnd->type == PATH && OpEnd->v != NULL){
04040          OpEnd->v=ReTweenVelocity(OpEnd,OpEnd->v,
04041               (int)(oldlf-oldff+1),
04042               (int)(OpEnd->lastframe-OpEnd->firstframe+1),
04043               OpEnd->pathlength,0);
04044          }
04045      }
04046      OpEnd=Op;
04047    }
04048    SpEnd=NULL;
04049    if((Sp=Np->fsky) != NULL)while(Sp != NULL){SpEnd=Sp;  Sp=Sp->next;}
04050    if(SpEnd != NULL && action < BLANKS){
04051      if(action == SCALE){
04052        Sp=Np->fsky;
04053        while(Sp != NULL){
04054          appear=Sp->lastframe - Sp->firstframe + 1 ;
04055          Sp->firstframe = (Sp->firstframe - 1) * scale + 1;
04056          newappear = (short)((double)appear * scale);
04057          Sp->lastframe = Sp->firstframe + newappear;
04058          if(Sp->last != NULL){
04059            if(Sp->last->lastframe >= Sp->firstframe){
04060              Sp->firstframe = Sp->last->lastframe + 1;
04061              if(Sp->lastframe < Sp->firstframe)
04062                Sp->lastframe = Sp->firstframe;
04063            }
04064          }
04065        Sp=Sp->next;}
04066      }
04067      if(number > SpEnd->lastframe && SpEnd->lastframe >= Nframes)
04068        SpEnd->lastframe=number;
04069    }
04070    if(SpEnd != NULL)while(SpEnd != NULL){Sp=SpEnd->last;
04071      if(SpEnd->firstframe > number)DeleteSky(Np,SpEnd->firstframe);
04072      else if(SpEnd->lastframe > number)SpEnd->lastframe=number;
04073    SpEnd=Sp;}
04074 
04075    DpEnd=NULL;
04076    if((Dp=Np->fdirector) != NULL)while(Dp != NULL){DpEnd=Dp;  Dp=Dp->next;}
04077    if(DpEnd != NULL && action < BLANKS){
04078      if(action == SCALE){
04079        Dp=Np->fdirector;
04080        while(Dp != NULL){
04081          appear=Dp->lastframe - Dp->firstframe + 1 ;
04082          Dp->firstframe = (Dp->firstframe - 1) * scale + 1;
04083          newappear = (short)((double)appear * scale);
04084          Dp->lastframe = Dp->firstframe + newappear;
04085          if(Dp->last != NULL){
04086            if(Dp->last->lastframe >= Dp->firstframe){
04087              Dp->firstframe = Dp->last->lastframe + 1;
04088              if(Dp->lastframe < Dp->firstframe)
04089                Dp->lastframe = Dp->firstframe;
04090            }
04091          }
04092        Dp=Dp->next;}
04093      }
04094      if(number > DpEnd->lastframe && DpEnd->lastframe >= Nframes)
04095        DpEnd->lastframe=number;
04096    }
04097    if(DpEnd != NULL)while(DpEnd != NULL){Dp=DpEnd->last;
04098      if(DpEnd->firstframe > number)DeleteDirector(Np,DpEnd->firstframe);
04099      else if(DpEnd->lastframe > number)DpEnd->lastframe=number;
04100    DpEnd=Dp;}
04101 
04102    PpEnd=NULL;
04103    if((Pp=Np->fpos) != NULL)while(Pp != NULL){PpEnd=Pp;  Pp=Pp->next;}
04104    if(PpEnd != NULL && action < BLANKS){
04105      if(action == SCALE){
04106        Pp=Np->fpos;
04107        while(Pp != NULL){
04108          appear=Pp->lastframe - Pp->firstframe + 1 ;
04109          Pp->firstframe = (Pp->firstframe - 1) * scale + 1;
04110          newappear = (short)((double)appear * scale);
04111          Pp->lastframe  =  Pp->firstframe + newappear;
04112          if(Pp->last != NULL){
04113            if(Pp->last->lastframe >= Pp->firstframe){
04114              Pp->firstframe = Pp->last->lastframe + 1;
04115              if(Pp->lastframe < Pp->firstframe)
04116                Pp->lastframe = Pp->firstframe;
04117            }
04118          }
04119        Pp=Pp->next;}
04120      }
04121      if(number > PpEnd->lastframe && PpEnd->lastframe >= Nframes)
04122        PpEnd->lastframe=number;
04123    }
04124    if(PpEnd != NULL)while(PpEnd != NULL){Pp=PpEnd->last;
04125      if(PpEnd->firstframe > number)DeletePosition(Np,PpEnd->firstframe);
04126      else if(PpEnd->lastframe > number)PpEnd->lastframe=number;
04127    PpEnd=Pp;}
04128    ApEnd=NULL;
04129    if((Ap=Np->fali) != NULL)while(Ap != NULL){ApEnd=Ap;  Ap=Ap->next;}
04130    if(ApEnd != NULL && action < BLANKS){
04131      if(action == SCALE){
04132        Ap=Np->fali;
04133        while(Ap != NULL){
04134          appear=Ap->lastframe - Ap->firstframe + 1 ;
04135          Ap->firstframe = (Ap->firstframe - 1) * scale + 1;
04136          newappear = (short)((double)appear * scale);
04137          Ap->lastframe  =  Ap->firstframe + newappear;
04138          if(Ap->last != NULL){
04139            if(Ap->last->lastframe >= Ap->firstframe){
04140              Ap->firstframe = Ap->last->lastframe + 1;
04141              if(Ap->lastframe < Ap->firstframe)
04142                Ap->lastframe = Ap->firstframe;
04143            }
04144          }
04145        Ap=Ap->next;}
04146      }
04147      if(number > ApEnd->lastframe && ApEnd->lastframe >= Nframes)
04148        ApEnd->lastframe=number;
04149    }
04150    if(ApEnd != NULL)while(ApEnd != NULL){Ap=ApEnd->last;
04151      if(ApEnd->firstframe > number)DeleteAlign(Np,ApEnd->firstframe);
04152      else if(ApEnd->lastframe > number)ApEnd->lastframe=number;
04153    ApEnd=Ap;}
04154    XpEnd=NULL;
04155    if((Xp=Np->fsiz) != NULL)while(Xp != NULL){XpEnd=Xp;  Xp=Xp->next;}
04156    if(XpEnd != NULL && action < BLANKS){
04157      if(action == SCALE){
04158        Xp=Np->fsiz;
04159        while(Xp != NULL){
04160          appear=Xp->lastframe - Xp->firstframe + 1 ;
04161          Xp->firstframe = (Xp->firstframe - 1) * scale + 1;
04162          newappear = (short)((double)appear * scale);
04163          Xp->lastframe  =  Xp->firstframe + newappear;
04164          if(Xp->last != NULL){
04165            if(Xp->last->lastframe >= Xp->firstframe){
04166              Xp->firstframe = Xp->last->lastframe + 1;
04167              if(Xp->lastframe < Xp->firstframe)
04168                Xp->lastframe = Xp->firstframe;
04169            }
04170          }
04171        Xp=Xp->next;}
04172      }
04173      if(number > XpEnd->lastframe && XpEnd->lastframe >= Nframes)
04174        XpEnd->lastframe=number;
04175    }
04176    if(XpEnd != NULL)while(XpEnd != NULL){Xp=XpEnd->last;
04177      if(XpEnd->firstframe > number)DeleteSize(Np,XpEnd->firstframe);
04178      else if(XpEnd->lastframe > number)XpEnd->lastframe=number;
04179    XpEnd=Xp;}
04180 
04181   Np=Np->next;}
04182   Nframes=number;
04183   UpdateSelectedActor(FALSE);
04184   EnableMenuItem(GetMenu(ghwnd_main),IDM_FRAME_RENDERNOW,MF_GRAYED);
04185 }
04186 
04187 BOOL InsertFrames(BOOL type, long inf, long cf, long nf){
04188  node     *Np;
04189  object   *Op;
04190  sky      *Sp;
04191  director *Dp;
04192  position *Pp;
04193  align    *Ap;
04194  size     *Xp;
04195  HWND     hwnd;
04196  long     oldff,oldlf;
04197  if(type == TRUE){ // use dialog to get number of frames to insert
04198    if((hwnd=GetActiveWindow()) != ghwndTimeline)hwnd=ghwnd_main;
04199    inf=(short)DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_INSERTFRAMES),
04200           hwnd,(DLGPROC)InsertFramesDlgProc,(LPARAM)&cf);
04201    if(inf < 1)return FALSE;
04202  }
04203 // {char cc[64]; sprintf(cc,"insert %ld  before %ld",inf,cf);
04204 // MessageBox(NULL,cc,NULL,MB_OK);}
04205  if(cf > Nframes || cf < 1)return FALSE;
04206  EDIT_ACTION=YES;
04207  if((Np=FirstNp) != NULL)while(Np != NULL){
04208    if((Op=Np->fobj) != NULL)while(Op != NULL){
04209      oldff=Op->firstframe; oldlf=Op->lastframe;
04210      if(oldff > cf || (Np->type != CAMERA && oldff == cf))Op->firstframe += inf;
04211      if(oldlf >= cf)Op->lastframe += inf;
04212      if(Op->type == PATH && Op->v != NULL && oldff < cf && oldlf > cf){
04213         Op->v=ReTweenVelocity(Op,Op->v,
04214                               (int)(oldlf-oldff+1),(int)(Op->lastframe-Op->firstframe+1),
04215                               Op->pathlength,0);
04216      }
04217      Op=Op->next;
04218    }
04219    if((Sp=Np->fsky) != NULL)while(Sp != NULL){
04220      oldff=Sp->firstframe; oldlf=Sp->lastframe;
04221      if(oldff >= cf)Sp->firstframe += inf;
04222      if(oldlf >= cf)Sp->lastframe += inf;
04223      Sp=Sp->next;
04224    }
04225    if((Dp=Np->fdirector) != NULL)while(Dp != NULL){
04226      oldff=Dp->firstframe; oldlf=Dp->lastframe;
04227      if(oldff >= cf)Dp->firstframe += inf;
04228      if(oldlf >= cf)Dp->lastframe += inf;
04229      Dp=Dp->next;
04230    }
04231    if((Pp=Np->fpos) != NULL)while(Pp != NULL){
04232      oldff=Pp->firstframe; oldlf=Pp->lastframe;
04233      if(oldff >= cf)Pp->firstframe += inf;
04234      if(oldlf >= cf)Pp->lastframe += inf;
04235      Pp=Pp->next;
04236    }
04237    if((Ap=Np->fali) != NULL)while(Ap != NULL){
04238      oldff=Ap->firstframe; oldlf=Ap->lastframe;
04239      if(oldff >= cf)Ap->firstframe += inf;
04240      if(oldlf >= cf)Ap->lastframe += inf;
04241      Ap=Ap->next;
04242    }
04243    if((Xp=Np->fsiz) != NULL)while(Xp != NULL){
04244      oldff=Xp->firstframe; oldlf=Xp->lastframe;
04245      if(oldff >= cf)Xp->firstframe += inf;
04246      if(oldlf >= cf)Xp->lastframe += inf;
04247      Xp=Xp->next;
04248    }
04249 
04250    Np=Np->next;
04251  }
04252  Nframes += inf;
04253  UpdateSelectedActor(FALSE);
04254  return TRUE;
04255 }
04256 
04257 BOOL DeleteRangeOfFrames(BOOL type, long inf, long cf, long nf){
04258  node     *Np;
04259  object   *Op,*OpNext;
04260  sky      *Sp,*SpNext;
04261  director *Dp,*DpNext;
04262  position *Pp,*PpNext;
04263  align    *Ap,*ApNext;
04264  size     *Xp,*XpNext;
04265  HWND     hwnd;
04266  long     ef,oldff,oldlf;
04267  if(type == TRUE){ // use dialog to get number of frames to insert
04268    if((hwnd=GetActiveWindow()) != ghwndTimeline)hwnd=ghwnd_main;
04269    inf=(short)DialogBoxParam(ghinst_main,MAKEINTRESOURCE(DLG_DELETEFRAMES),
04270           hwnd,(DLGPROC)DeleteFramesDlgProc,(LPARAM)&cf);
04271    if(inf < 1 || inf >= Nframes)return FALSE;
04272  }
04273  if(cf >= Nframes || cf < 1)return FALSE;
04274  EDIT_ACTION=YES;
04275  ef=cf+inf-1;
04276  if((Np=FirstNp) != NULL)while(Np != NULL){
04277    if((Op=Np->fobj) != NULL)while(Op != NULL){
04278      oldff=Op->firstframe; oldlf=Op->lastframe;
04279      if     (oldff > ef){Op->firstframe -= inf; Op->lastframe -= inf; Op=Op->next;}
04280      else if(oldlf < cf){Op=Op->next;}
04281      else if(oldff < cf && oldlf <= ef) {Op->lastframe = cf-1; Op=Op->next;}
04282      else if(oldff < cf && oldlf > ef)  {Op->lastframe -= inf; Op=Op->next;}
04283      else if(oldff <= ef && oldlf > ef) {Op->firstframe = cf; Op->lastframe -= inf; Op=Op->next;}
04284      else if(oldff >= cf && oldlf <= ef){
04285        OpNext=Op->next;
04286        DeleteCostume(Np,Op->firstframe);
04287        Op=OpNext;
04288      }
04289      else Op=Op->next;
04290    }
04291 
04292    if((Sp=Np->fsky) != NULL)while(Sp != NULL){
04293      oldff=Sp->firstframe; oldlf=Sp->lastframe;
04294      if     (oldff > ef){Sp->firstframe -= inf; Sp->lastframe -= inf; Sp=Sp->next;}
04295      else if(oldlf < cf){Sp=Sp->next;}
04296      else if(oldff < cf && oldlf <= ef) {Sp->lastframe = cf-1; Sp=Sp->next;}
04297      else if(oldff < cf && oldlf > ef)  {Sp->lastframe -= inf; Sp=Sp->next;}
04298      else if(oldff <= ef && oldlf > ef) {Sp->firstframe = cf; Sp->lastframe -= inf; Sp=Sp->next;}
04299      else if(oldff >= cf && oldlf <= ef){
04300        SpNext=Sp->next;
04301        DeleteSky(Np,Sp->firstframe);
04302        Sp=SpNext;
04303      }
04304      else Sp=Sp->next;
04305    }
04306 
04307    if((Dp=Np->fdirector) != NULL)while(Dp != NULL){
04308      oldff=Dp->firstframe; oldlf=Dp->lastframe;
04309      if     (oldff > ef){Dp->firstframe -= inf; Dp->lastframe -= inf; Dp=Dp->next;}
04310      else if(oldlf < cf){Dp=Dp->next;}
04311      else if(oldff < cf && oldlf <= ef) {Dp->lastframe = cf-1; Dp=Dp->next;}
04312      else if(oldff < cf && oldlf > ef)  {Dp->lastframe -= inf; Dp=Dp->next;}
04313      else if(oldff <= ef && oldlf > ef) {Dp->firstframe = cf; Dp->lastframe -= inf; Dp=Dp->next;}
04314      else if(oldff >= cf && oldlf <= ef){
04315        DpNext=Dp->next;
04316        DeleteDirector(Np,Dp->firstframe);
04317        Dp=DpNext;
04318      }
04319      else Dp=Dp->next;
04320    }
04321 
04322    if((Pp=Np->fpos) != NULL)while(Pp != NULL){
04323      oldff=Pp->firstframe; oldlf=Pp->lastframe;
04324      if     (oldff > ef){Pp->firstframe -= inf; Pp->lastframe -= inf; Pp=Pp->next;}
04325      else if(oldlf < cf){Pp=Pp->next;}
04326      else if(oldff < cf && oldlf <= ef) {Pp->lastframe = cf-1; Pp=Pp->next;}
04327      else if(oldff < cf && oldlf > ef)  {Pp->lastframe -= inf; Pp=Pp->next;}
04328      else if(oldff <= ef && oldlf > ef) {Pp->firstframe = cf; Pp->lastframe -= inf; Pp=Pp->next;}
04329      else if(oldff >= cf && oldlf <= ef){
04330        PpNext=Pp->next;
04331        DeletePosition(Np,Pp->firstframe);
04332        Pp=PpNext;
04333      }
04334      else Pp=Pp->next;
04335    }
04336 
04337    if((Ap=Np->fali) != NULL)while(Ap != NULL){
04338      oldff=Ap->firstframe; oldlf=Ap->lastframe;
04339      if     (oldff > ef){Ap->firstframe -= inf; Ap->lastframe -= inf; Ap=Ap->next;}
04340      else if(oldlf < cf){Ap=Ap->next;}
04341      else if(oldff < cf && oldlf <= ef) {Ap->lastframe = cf-1; Ap=Ap->next;}
04342      else if(oldff < cf && oldlf > ef)  {Ap->lastframe -= inf; Ap=Ap->next;}
04343      else if(oldff <= ef && oldlf > ef) {Ap->firstframe = cf; Ap->lastframe -= inf; Ap=Ap->next;}
04344      else if(oldff >= cf && oldlf <= ef){
04345        ApNext=Ap->next;
04346        DeleteAlign(Np,Ap->firstframe);
04347        Ap=ApNext;
04348      }
04349      else Ap=Ap->next;
04350    }
04351 
04352    if((Xp=Np->fsiz) != NULL)while(Xp != NULL){
04353      oldff=Xp->firstframe; oldlf=Xp->lastframe;
04354      if     (oldff > ef){Xp->firstframe -= inf; Xp->lastframe -= inf; Xp=Xp->next;}
04355      else if(oldlf < cf){Xp=Xp->next;}
04356      else if(oldff < cf && oldlf <= ef) {Xp->lastframe = cf-1; Xp=Xp->next;}
04357      else if(oldff < cf && oldlf > ef)  {Xp->lastframe -= inf; Xp=Xp->next;}
04358      else if(oldff <= ef && oldlf > ef) {Xp->firstframe = cf; Xp->lastframe -= inf; Xp=Xp->next;}
04359      else if(oldff >= cf && oldlf <= ef){
04360        XpNext=Xp->next;
04361        DeleteSize(Np,Xp->firstframe);
04362        Xp=XpNext;
04363      }
04364      else Xp=Xp->next;
04365    }
04366 
04367    Np=Np->next;
04368  }
04369  Nframes -= inf;
04370  UpdateSelectedActor(FALSE);
04371  return TRUE;
04372 }
04373 
04374 static int  nActionsList=0;
04375 static char *ActionsList[256],*ActionsText[256];
04376 
04377 short StartDefault(short what_function){
04378  int nPresets=7;
04379  short action,nfr,nmodels=0;
04380  node     *Np,*Np1,*lastNode,*pathNode;
04381  object   *Op,*Op1;
04382  sky      *Sp;
04383  position *Pp;
04384  align    *Ap,*Ap1;
04385  size     *Xp;
04386  char response[16];
04387  nPresets=GetPresets(nPresets);
04388  LoadString(ghinst_main,IDX_MISC_TEMPLATE,res_str,256);
04389  action=SelectScrolledItemList(nPresets,ActionsText,res_str,
04390                                TRUE,ghwnd_main);
04391  if(action < 0)goto FINISHED;
04392  if(action > 6){
04393    if(!BuildFromPreset(action))goto ERRORS;
04394    goto FINISHED;
04395  }
04396  if(Nskys == 0){
04397    if(CreateNode() != NULL){
04398      LoadString(ghinst_main,IDX_MISC_NAMESKY,res_str,256);
04399      strcpy(MainNp->actorname,res_str);
04400      MainNp->type=SKY;
04401      MainNp->fsky=NULL;
04402      Nskys=1;
04403    }
04404    else goto FINISHED;
04405  }
04406  if((Sp=CreateSky(MainNp,1,(short)Nframes)) == NULL || fail_op)goto ERRORS;
04407  Sp->type=SKYGRADED;
04408  Sp->colour[0]=0; Sp->colour[1]=255; Sp->colour[2]=255;
04409  Sp->zcolour[0]=0; Sp->zcolour[1]=0; Sp->zcolour[2]=255;
04410  if(CreatePosition(FirstNp,1,(short)Nframes) == NULL || fail_op)goto ERRORS;
04411  FirstNp->fpos->finish[0]=TVpointX+TVsizeX*2;
04412  FirstNp->fpos->finish[1]=TVpointY+TVsizeY*2;
04413  FirstNp->fpos->finish[2]=TVpointZ+TVsizeZ*2;
04414  FirstNp->fpos->type=SPLINE;
04415  if((Ap=CreateAlign(FirstNp,1,(short)Nframes)) == NULL || fail_op)goto ERRORS;
04416  if(CreateNode() == NULL)goto ERRORS;
04417  LoadString(ghinst_main,IDX_MISC_NAMETARGET,res_str,256);
04418  strcpy(MainNp->actorname,res_str);
04419  MainNp->type=TARGET;
04420  if((Op=CreateCostume(MainNp,1,(short)Nframes)) == NULL || fail_op)goto ERRORS;
04421  Op->type=MainNp->type;
04422  FirstNp->fali->type=TRACK; FirstNp->fali->topath=MainNp;
04423 // strange bug !!!  if((Pp=CreatePosition(MainNp,1,Nframes)) == NULL || fail_op)goto ERRORS;
04424 // anything will do
04425  if(action < 6){
04426    char ttt[64];
04427    LoadString(ghinst_main,IDX_MISC_SELECTMODEL,res_str,256);
04428    LoadString(ghinst_main,IDX_MISC_SELECT1,ttt,256);
04429    if((Np1=LoadStandinModel(&nmodels,res_str,ttt)) == NULL)
04430    goto ERRORS;
04431  }
04432  else if(action == 6){
04433    char ttt[64];
04434    LoadString(ghinst_main,IDX_MISC_MODELHEAD,res_str,256);
04435    LoadString(ghinst_main,IDX_MISC_MODELLOAD,ttt,256);
04436    if((Np1=LoadStandinModel(&nmodels,res_str,ttt))
04437           == NULL)goto ERRORS;
04438  }
04439  if(Np1->fobj != NULL){
04440    Op1=Np1->fobj;
04441    FirstNp->fpos->finish[0] += Op1->outline[2][0];
04442    FirstNp->fpos->finish[1] += Op1->outline[2][1];
04443    FirstNp->fpos->finish[2] += Op1->outline[2][2];
04444  }
04445  if(CreateNode() == NULL)goto ERRORS;
04446  LoadString(ghinst_main,IDX_MISC_NAMELIGHT,res_str,256);
04447  strcpy(MainNp->actorname,res_str);
04448  MainNp->type=LIGHT;
04449  if((Op=CreateCostume(MainNp,1,Nframes)) == NULL)goto ERRORS;
04450  Op->type=MainNp->type;
04451  Op->lighttype=SPHERE; Op->colour[0]=Op->colour[1]=Op->colour[2]=255;
04452  if((Pp=CreatePosition(MainNp,1,(short)Nframes)) == NULL || fail_op)goto ERRORS;
04453  Pp->finish[0]=FirstNp->fpos->finish[0]+TVsizeX/2;
04454  Pp->finish[1]=FirstNp->fpos->finish[1]+TVsizeY;
04455  Pp->finish[2]=FirstNp->fpos->finish[2]+TVsizeZ*2;
04456  Pp->type=SPLINE;
04457  if(action < 1)goto FINISHED;
04458  if(action == 1){
04459    if(CreateNode() == NULL)goto ERRORS;
04460    LoadString(ghinst_main,IDX_MISC_NAMEGROUND,res_str,256);
04461    strcpy(MainNp->actorname,res_str);
04462    MainNp->type=GROUND; Nground=1;
04463    if((Op=CreateCostume(MainNp,1,(short)Nframes)) == NULL)goto ERRORS;
04464    Op->type=MainNp->type;
04465    Op->groundtype=PLAIN;
04466    Op->groundTemperature=10;
04467    SetSfxColour(Op->colour,IDX_MISC_GROUND_COLOUR,ghwnd_main);
04468    if((Pp=CreatePosition(MainNp,1,Nframes)) == NULL || fail_op)goto ERRORS;
04469    Pp->finish[0]=0;
04470    Pp->finish[1]=0;
04471    Pp->finish[2]=TVpointZ;
04472    Pp->type=SPLINE;
04473    if((Xp=CreateSize(MainNp,1,Nframes)) == NULL || fail_op)goto ERRORS;
04474  }
04475  if(action > 1){
04476    char ttt[64];
04477    LoadString(ghinst_main,IDX_MISC_NUMFRAMES,res_str,256);
04478    LoadString(ghinst_main,IDX_MISC_FRAMES,ttt,64);
04479    nfr=RequestNumEntry(60,1,999,res_str,ttt);
04480 #if __DEMO__
04481    if(nfr > 70){
04482      LoadString(ghinst_main,IDX_MISC_DEMO1,res_str,256);
04483      MessageBox(NULL,res_str,NULL,MB_OK);
04484      nfr=70;
04485    }
04486 #endif
04487    if(nfr < 0)goto FINISHED;
04488    SetNumberOfFrames(nfr);
04489    if((Ap1=CreateAlign(Np1,1,Nframes)) == NULL || fail_op)goto ERRORS;
04490    if(action == 2){Ap1->im=1; Ap1->ima=1.0;}
04491  }
04492  if(action >= 3 && action <= 5){
04493    if(CreateNode() == NULL)goto ERRORS;
04494    LoadString(ghinst_main,IDX_MISC_NAMEPATH,res_str,256);
04495    strcpy(MainNp->actorname,res_str);
04496    MainNp->type=PATH;
04497    if((Op=CreateCostume(MainNp,1,Nframes)) == NULL)goto ERRORS;
04498    Op->type=MainNp->type;
04499    strcpy(Op->name,"PATH1995");
04500    if(CreatePathObject((short)(action-3),MainNp,Op,1,Nframes) < 0)goto ERRORS;
04501    if((Pp=CreatePosition(Np1,1,Nframes)) == NULL || fail_op)goto ERRORS;
04502    Pp->type=FOLLOW; Pp->onpath=MainNp;
04503    Ap1->type=TOPATH; Ap1->topath=MainNp;
04504  }
04505  else if(action == 6){ /* train so load the other models */
04506    if(CreateNode() == NULL)goto ERRORS;
04507    LoadString(ghinst_main,IDX_MISC_NAMEPATH,res_str,256);
04508    strcpy(MainNp->actorname,res_str);
04509    pathNode=MainNp;
04510    MainNp->type=PATH;
04511    if((Op=CreateCostume(MainNp,1,Nframes)) == NULL)goto ERRORS;
04512    Op->type=MainNp->type;
04513    strcpy(Op->name,"PATH1995");
04514    if(CreatePathObject(2,MainNp,Op,1,Nframes) < 0)goto ERRORS;
04515    if((Pp=CreatePosition(Np1,1,Nframes)) == NULL || fail_op)goto ERRORS;
04516    Pp->type=FOLLOW; Pp->onpath=pathNode;
04517    Ap1->type=TOPATH; Ap1->topath=pathNode;
04518    lastNode=Np1;
04519    while(1){
04520      char ttt[64];
04521      LoadString(ghinst_main,IDX_MISC_NEXTCANCEL,res_str,256);
04522      LoadString(ghinst_main,IDX_MISC_ADDNEXT,ttt,64);
04523      if((Np=LoadStandinModel(&nmodels,res_str,ttt))
04524            == NULL)goto ERRORS;
04525      if(Np->fobj == NULL){
04526        DeleteNode(Np);
04527        break;
04528      }
04529      if((Pp=CreatePosition(Np,1,Nframes)) == NULL || fail_op)goto ERRORS;
04530      Pp->type=FOLLOWON; Pp->onpath=lastNode;
04531      if((Ap=CreateAlign(Np,1,Nframes)) == NULL || fail_op)goto ERRORS;
04532      Ap->type=TOPATH; Ap->topath=pathNode;
04533      lastNode=Np;
04534    }
04535  }
04536  goto FINISHED;
04537  ERRORS:
04538  SendPrgmQuery(IDQ_OLD4,0);
04539  FINISHED:
04540  FreePresets();
04541  return 0;
04542 }
04543 
04544 static int GetPresets(int nPresets){
04545  int i;
04546  HANDLE h;
04547  FILE *ff;
04548  WIN32_FIND_DATA ffd,*lpffd;
04549  char str[255],title[64],tempstr[256];
04550  int PresetTypeListID[]={
04551    IDX_MISC_PRESET1,
04552    IDX_MISC_PRESET2,
04553    IDX_MISC_PRESET3,
04554    IDX_MISC_PRESET4,
04555    IDX_MISC_PRESET5,
04556    IDX_MISC_PRESET6,
04557    IDX_MISC_PRESET7
04558  };
04559  sprintf(str,"%s\\*.pfx",gszPSTdir);
04560  lpffd=&ffd;
04561  nActionsList=0;
04562  for(i=0;i<nPresets;i++){
04563    ActionsList[nActionsList]=(char *)X__Malloc(8*sizeof(char));
04564    if(ActionsList[nActionsList] != NULL)strcpy(ActionsList[nActionsList],"I");
04565    ActionsText[nActionsList]=(char *)X__Malloc(256*sizeof(char));
04566    if(ActionsText[nActionsList] != NULL){
04567      LoadString(ghinst_main,PresetTypeListID[nActionsList],tempstr,256);
04568      strcpy(ActionsText[nActionsList],tempstr);
04569    }
04570    nActionsList++;
04571  }
04572  if((h=FindFirstFile(str,lpffd)) != INVALID_HANDLE_VALUE){
04573    sprintf(str,"%s\\%s",gszPSTdir,lpffd->cFileName);
04574    ActionsList[nActionsList]=(char *)X__Malloc(256*sizeof(char));
04575    if(ActionsList[nActionsList] != NULL)strcpy(ActionsList[nActionsList],str);
04576    nActionsList++;
04577    while(FindNextFile(h,lpffd)){
04578      sprintf(str,"%s\\%s",gszPSTdir,lpffd->cFileName);
04579      ActionsList[nActionsList]=(char *)X__Malloc(256*sizeof(char));
04580      strcpy(ActionsList[nActionsList],str);
04581      nActionsList++;
04582    }
04583    if(GetLastError() != ERROR_NO_MORE_FILES){
04584      LoadString(ghinst_main,IDX_MISC_ERRORINNEXT,res_str,256);
04585      MessageBox(NULL,res_str,NULL,MB_OK);
04586    }
04587    if(!FindClose(h)){
04588      LoadString(ghinst_main,IDX_MISC_FILEERROR,res_str,256);
04589      MessageBox(NULL,res_str,NULL,MB_OK);
04590    }
04591    if(nActionsList > nPresets)for(i=nPresets;i<nActionsList;i++){
04592      if((ff=fopen(ActionsList[i],"r")) != NULL){
04593        fscanf(ff,"%[^\n]",title);
04594        ActionsText[i]=(char *)X__Malloc(256*sizeof(char));
04595        if(ActionsText[i] != NULL)
04596        strcpy(ActionsText[i],title);
04597        fclose(ff);
04598      }
04599    }
04600  }
04601  return nActionsList;
04602 }
04603 
04604 static void FreePresets(void){
04605  int i;
04606  if(nActionsList > 0){
04607    for(i=0;i<nActionsList;i++){
04608      if(ActionsList[i] != NULL)X__Free(ActionsList[i]);
04609      if(ActionsText[i] != NULL)X__Free(ActionsText[i]);
04610    }
04611    nActionsList=0;
04612  }
04613 }
04614 
04615 static BOOL BuildFromPreset(int action){
04616  BOOL status=FALSE;
04617  HMODULE hLib;
04618  FARPROC fpFun;
04619  ANI_STRUCTURE *Evs;
04620  BOOL (*fpFun1)(HWND, ANI_STRUCTURE *);
04621  int l;
04622  char fname[255];
04623  strcpy(fname,ActionsList[action]);
04624  l=strlen(fname);
04625  fname[l-1]='l'; fname[l-2]='l'; fname[l-3]='d';
04626  Evs=&AniStructure;
04627  if((hLib=LoadLibrary(fname)) != NULL){
04628    if((fpFun=GetProcAddress(hLib,"_ExternalPreset")) != NULL){
04629      fpFun1 = (void *)fpFun;
04630      status=(*fpFun1)(ghwnd_main,Evs);
04631    }
04632    else MessageBox(ghwnd_main,(LPCTSTR) "Failed function",(LPCTSTR)" ",
04633         MB_OK | MB_TASKMODAL );
04634    FreeLibrary(hLib);
04635  }
04636  else MessageBox(ghwnd_main,(LPCTSTR)fname,(LPCTSTR)"Failed to find DLL",
04637                 MB_OK | MB_TASKMODAL );
04638  return status;
04639 }

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