home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / crend5 / statmach.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-28  |  23.8 KB  |  1,021 lines

  1. /* threaded state machine animation system */
  2.  
  3. /* Written by Dave Stampe Oct. 1992 */
  4.  
  5. /* Copyright 1992 by Dave Stampe and Bernie Roehl.
  6.      May be freely used to write software for release into the public domain;
  7.      all commercial endeavours MUST contact Bernie Roehl and Dave Stampe
  8.      for permission to incorporate any part of this software into their
  9.      products!
  10.  
  11.      ATTRIBUTION:  If you use any part of this source code or the libraries
  12.      in your projects, you must give attribution to REND386, Dave Stampe,
  13.      and Bernie Roehl in your documentation, source code, and at startup
  14.      of your program.  Let's keep the freeware ball rolling!
  15.  */
  16.  
  17. #pragma inline
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>      /* malloc() */
  21. #include <conio.h>      /* kbhit() */
  22. #include <string.h>
  23.  
  24. #include "rend386.h"  /* for current_time() */
  25. #include "intmath.h"
  26. #include "userint.h"
  27.  
  28. extern void connect_body(VIEW *v, SEGMENT *s);
  29. extern void disconnect_body(VIEW *v);
  30.  
  31. /* from world.c */
  32.  
  33. typedef struct _name NAMEREF;
  34.  
  35. struct _name {
  36.     char *name;
  37.     void *value;
  38.     NAMEREF *next;
  39. };
  40.  
  41. extern NAMEREF *add_name(NAMEREF **list, char *name, void *value);
  42. extern void del_namelist(NAMEREF *list);
  43. extern void *find_name(NAMEREF *list, char *name);
  44. extern SEGMENT *find_seg(char *name);
  45.  
  46. extern int flymode;
  47.  
  48. #define FREE     0      /* state (instruction) type */
  49. #define STEP     1
  50. #define MOVETO   2
  51. #define POSTEST  3
  52. #define ROTTEST  4
  53. #define SET      5
  54. #define SENSOR   6
  55. #define SELECTED 7
  56. #define TIMER    8
  57. #define GRAVITY  9
  58. #define POSLIMIT 10
  59. #define ROTLIMIT 11
  60. #define USEREP   12
  61. #define ABSTEP   13
  62. #define ATTACH   14
  63. #define POPTEXT  15
  64.  
  65. #define DONTCARE 0x80000000L    /* value for sets and tests */
  66.  
  67. #define SAME     0              /* status of timer and gravity */
  68. #define CHANGED  1
  69. #define EXPIRED  2
  70.  
  71. typedef struct _state {
  72.             int type;               /* type of operation       */
  73.             int status;             /* marks timer, gravity    */
  74.             struct _state *next;    /* next operation in state */
  75.             int tst1v, tst1i;       /* evaluation tests        */
  76.             int tst2v, tst2i;
  77.             struct _state *sstate;  /* "set" assignments, next state */
  78.             int set1v, set1i;
  79.             int set2v, set2i;
  80.             int set3v, set3i;
  81.             struct _state *rstate;  /* "reset" same    */
  82.             int rst1v, rst1i;
  83.             int rst2v, rst2i;
  84.             int rst3v, rst3i;
  85.             SEGMENT *seg;           /* segment to use  */
  86.             long x1, y1, z1;        /* numerical arg's */
  87.             long x2, y2, z2;        /* 1 = po's'n 2 = rotate */
  88.             long x3, y3, z3;        /* 3 = gravity accel */
  89.             unsigned xo1, yo1, zo1; /* underflows */
  90.             unsigned xo2, yo2, zo2;
  91.             struct _state *ulist;   /* list of seg's moved */
  92.             } STATE;
  93.  
  94. typedef struct _ani {
  95.          struct _ani *next;       /* next animation task      */
  96.          long last_time;          /* last time run            */
  97.          long period;             /* delay between runs       */
  98.          STATE *lstate;           /* set if state has changed */
  99.          STATE *state;            /* current state in machine */
  100.         } ANIMATION;
  101.  
  102. static ANIMATION *anilist = NULL;
  103. static ANIMATION *cur_ani = NULL;
  104. static STATE *cur_state   = NULL;
  105. static STATE *update_list = NULL;
  106. static STATE *update_end  = NULL;
  107.  
  108. NAMEREF *statelist  = NULL;
  109. NAMEREF *varlist    = NULL;
  110.  
  111. #define VARIABLES 200
  112. static int vars[VARIABLES];
  113. static int varcount = 0;
  114.  
  115. extern NAMEREF *figurelist;
  116. extern NAMEREF *fixedolist;
  117. extern SEGMENT *body_seg, *head_seg, *wrist_seg;
  118.  
  119. static long ctime;
  120.  
  121. void create_default_segs()
  122. {
  123.  body_seg  = new_seg(NULL);
  124.  head_seg  = new_seg(NULL);
  125.  wrist_seg = new_seg(NULL);
  126.  
  127.  add_name(&figurelist, "user_body", body_seg);
  128.  add_name(&figurelist, "user_head", head_seg);
  129.  add_name(&figurelist, "user_hand", wrist_seg);
  130. }
  131.  
  132. static void dump_states(void)    /* remove states in preparation for new animation */
  133. {
  134.  del_namelist(statelist);
  135.  statelist = NULL;
  136. }
  137.  
  138.  
  139. static int varindex(char *name)     /* return index of variable, or allocate new */
  140. {
  141.  void *v;
  142.  
  143.  if ((v = find_name(varlist, name))!=NULL)
  144.     {
  145.      return (int)v;
  146.     }
  147.  else
  148.     {
  149.      if (varcount == VARIABLES-1) return 0;
  150.      else
  151.         {
  152.          varcount++;
  153.          v = (void *) varcount;
  154.          if (add_name(&varlist, name, v)) return varcount;
  155.          else return 0;
  156.         }
  157.     }
  158. }
  159.  
  160.  
  161. static STATE * stateptr(char *name)   /* return adr. of state, or allocate new */
  162. {
  163.  STATE *v;
  164.  
  165.  if ((v = find_name(statelist, name))!=NULL)
  166.     {
  167.      return v;
  168.     }
  169.  else
  170.     {
  171.      v = (STATE *) malloc(sizeof(STATE));
  172.      if (v == NULL) return NULL;
  173.      else
  174.         {                   /* mark as usable as first command in state */
  175.          v->type = FREE;
  176.          if (add_name(&statelist, name, v)) return v;
  177.          else return NULL;
  178.         }
  179.     }
  180. }
  181.  
  182.  
  183. static char ps[] = " ,\t\n";
  184. static char st[] = "%s";
  185.  
  186. void parse_ani()
  187. {
  188.  float period = 10;
  189.  ANIMATION *ani, *a;
  190.  
  191.  dump_states();
  192.  period = atof(strtok(NULL,ps));
  193.  ani = (ANIMATION *)malloc(sizeof(ANIMATION));
  194.  if (ani == NULL)
  195.     {
  196.      cur_ani = NULL;
  197.      return;
  198.     }
  199.  ani->period = 180.0/period;
  200.  ani->last_time = -10000000L;            /* set to run immediately */
  201.  ani->lstate = NULL;
  202.  ani->state = NULL;
  203.  
  204.  ani->next = NULL;                 /* put it at end of list  */
  205.  if (anilist == NULL) anilist = ani;
  206.  else
  207.     {
  208.      for(a = anilist;a->next;a=a->next);
  209.      a->next = ani;
  210.     }
  211.  cur_ani = ani;
  212. }
  213.  
  214.  
  215. void parse_state()
  216. {
  217.  char name[40];
  218.  sscanf(strtok(NULL,ps),st, name);
  219.  cur_state = stateptr(name);             /* get new/old state adr.     */
  220.  if (cur_ani == NULL) return;               /* sequence error!            */
  221.  if (cur_ani->state == NULL)
  222.         cur_ani->state = cur_state;          /* set initial state if first */
  223. }
  224.  
  225.  
  226. static STATE *new_state(void)
  227. {
  228.  STATE *s;
  229.  
  230.  if (cur_state == NULL) return NULL;
  231.  if (cur_state->type == FREE) return cur_state;
  232.  else
  233.     {
  234.      s = (STATE *)malloc(sizeof(STATE));
  235.      if (s == NULL)
  236.         {
  237.          cur_state = NULL;
  238.          return NULL;
  239.         }
  240.      s->type = FREE;
  241.     }
  242.  return s;
  243. }
  244.  
  245.  
  246. static void parse_var(char *c, int *v, int *i)
  247. {
  248.  char *cc;
  249.  
  250.  *i = *v = 0;
  251.  if ((cc = strchr(c, '=')) == NULL) return;
  252.  *cc++ = 0;
  253.  *i = varindex(c);
  254.  *v = atoi(cc);
  255. }
  256.  
  257.  
  258. static STATE *parse_as(char *c, int *v, int *i)
  259. {
  260.  char *cc;
  261.  
  262.  *i = *v = 0;
  263.  if (!strcmpi(c, "EXIT"))     /* keyword "exit" */
  264.   {
  265.    *v = -1;
  266.    *i = -1;
  267.    return NULL;
  268.   }
  269.  if ((cc = strchr(c, '=')) == NULL) return NULL;
  270.  *cc++ = 0;
  271.  if (strcmpi(c, "STATE"))
  272.   {
  273.    *v = atoi(cc);
  274.    *i = varindex(c);
  275.    return NULL;
  276.   }
  277.  else
  278.   {
  279.    *v = *i = 0;
  280.    return stateptr(cc);
  281.   }
  282. }
  283.  
  284.  
  285. static char *parse_assgn(char *ci, STATE *s, int set)
  286. {
  287.  int v1, v2, v3, i1, i2, i3;
  288.  STATE *ss, *sp = NULL;
  289.  char *c, *r;
  290.  
  291.  if (set)
  292.     {
  293.      s->set1i = s->set2i = s->set3i = 0;
  294.      s->sstate = NULL;
  295.     }
  296.  else
  297.     {
  298.      s->rst1i = s->rst2i = s->rst3i = 0;
  299.      s->rstate = NULL;
  300.     }
  301.  
  302.  if ((c = strchr(ci,'[')) == NULL) return ci;   /* verify arguments   */
  303.  if ((r = strchr(c, ']')) == NULL) return ci;   /* trim off enclosure */
  304.  c++;  *r++ = 0;
  305.  
  306.  if ((ss = parse_as(strtok(c, " ,\t"),    &v1, &i1)) != NULL) sp = ss; ;
  307.  if ((ss = parse_as(strtok(NULL, " ,\t"), &v2, &i2)) != NULL) sp = ss; ;
  308.  if ((ss = parse_as(strtok(NULL, " ,\t"), &v3, &i3)) != NULL) sp = ss; ;
  309.  if (set)
  310.     {
  311.      s->set1v = v1;
  312.      s->set2v = v2;
  313.      s->set3v = v3;
  314.      s->set1i = i1;
  315.      s->set2i = i2;
  316.      s->set3i = i3;
  317.      s->sstate = sp;
  318.     }
  319.  else
  320.     {
  321.      s->rst1v = v1;
  322.      s->rst2v = v2;
  323.      s->rst3v = v3;
  324.      s->rst1i = i1;
  325.      s->rst2i = i2;
  326.      s->rst3i = i3;
  327.      s->rstate = sp;
  328.     }
  329.  return r;
  330. }
  331.  
  332.  
  333. static long getarg(char *ci, float scale, long x)
  334. {
  335.  char *c;
  336.  double f;
  337.  
  338.  c = strtok(ci, " \t\n,");
  339.  if (c == NULL || !sscanf(c, "%lf", &f) ) return x;
  340.  return (long) (scale * f);
  341. }
  342.  
  343.  
  344.  
  345. static void parse_rest(char *ci, STATE *s)
  346. {
  347.  char cmd[40]="", var[40]="", segn[40]="";
  348.  char *c, *cc, *cr;
  349.  SEGMENT *sp;
  350.  long jx, jy, jz;
  351.  
  352.  sscanf(ci, "%[^([\n]", cmd);   /* get segment and command */
  353.  if (strchr(cmd,'='))
  354.     {
  355.      c = strchr(cmd, '=');        /* split */
  356.      *c++ = 0;
  357.      sscanf(cmd, "%s", segn);      /* strip off whitespace */
  358.      sscanf(c,"%s", var);
  359.      sp = find_seg(segn);          /* find segment if any  */
  360.      if (!stricmp(var,"SELECTED"))
  361.         {
  362.          if (sp != NULL) sp = seg_get_object(sp);
  363.          else sp = find_name(fixedolist, segn);
  364. #ifdef USED_TO_BE
  365.          else sp = find_name(&fixedolist, segn);
  366. #endif
  367.          if (sp == NULL) return;
  368.         }
  369.      else
  370.         {
  371.          if (sp == NULL) return;
  372.          full_update_segment(find_root_segment(sp));    /* make sure root is current!    */
  373.          seg_getjointang(sp, &jx, &jy, &jz); /* and cached angle */
  374.         }
  375.      s->seg = sp;
  376.  
  377.      if (stricmp(var,"SET"))
  378.         {
  379.          if ((c = strchr(ci,'(')) == NULL) return;   /* verify arguments */
  380.          if ((cr = strchr(ci,')')) == NULL) return;
  381.          c++; *cr++ = 0;
  382.         }
  383.      else cr = strchr(ci,'[');
  384.  
  385.      if (!stricmp(var, "MOVETO"))
  386.         {
  387.          s->x1 = getarg(c,    1, DONTCARE);
  388.          s->y1 = getarg(NULL, 1, DONTCARE);
  389.          s->z1 = getarg(NULL, 1, DONTCARE);
  390.          s->x2 = getarg(NULL, 65536, DONTCARE);
  391.          s->y2 = getarg(NULL, 65536, DONTCARE);
  392.          s->z2 = getarg(NULL, 65536, DONTCARE);
  393.          parse_assgn(cr, s, 1);
  394.          s->type = MOVETO;
  395.         }
  396.      else if (!stricmp(var, "USEREP"))
  397.         {
  398.          OBJECT *o;
  399.          if ((o = seg_get_object(sp)) == NULL) return;
  400.          s->seg = o;
  401.          s->x1 = getarg(c, 1, 0) - 1;
  402.          parse_assgn(cr, s, 1);
  403.          s->type = USEREP;
  404.         }
  405.      else if (!stricmp(var, "ATTACH"))
  406.         {
  407.          if (sp == NULL) return;
  408.          s->x1 = getarg(c, 1, 1);
  409.          parse_assgn(cr, s, 1);
  410.          s->type = ATTACH;
  411.         }
  412.      else if (!stricmp(var, "STEP"))
  413.         {
  414.          s->x1 = getarg(c,    256, 0);
  415.          s->y1 = getarg(NULL, 256, 0);
  416.          s->z1 = getarg(NULL, 256, 0);
  417.          s->x2 = getarg(NULL, 65536, 0);
  418.          s->y2 = getarg(NULL, 65536, 0);
  419.          s->z2 = getarg(NULL, 65536, 0);
  420.          s->xo1 = s->yo1 = s->zo1 = 0;
  421.          parse_assgn(cr, s, 1);
  422.          s->type = STEP;
  423.         }
  424.      else if (!stricmp(var, "ABSTEP"))
  425.         {
  426.          s->x1 = getarg(c,    256, 0);
  427.          s->y1 = getarg(NULL, 256, 0);
  428.          s->z1 = getarg(NULL, 256, 0);
  429.          s->x2 = getarg(NULL, 65536, 0);
  430.          s->y2 = getarg(NULL, 65536, 0);
  431.          s->z2 = getarg(NULL, 65536, 0);
  432.          s->xo1 = s->yo1 = s->zo1 = 0;
  433.          parse_assgn(cr, s, 1);
  434.          s->type = ABSTEP;
  435.         }
  436.      else if (!stricmp(var, "GRAVITY"))
  437.         {
  438.          s->x2 = getarg(c,    256, 0);         /* initial */
  439.          s->y2 = getarg(NULL, 256, 0);
  440.          s->z2 = getarg(NULL, 256, 0);
  441.          s->x3 = getarg(NULL, 65536, 0);    /* accel */
  442.          s->y3 = getarg(NULL, 65536, 0);
  443.          s->z3 = getarg(NULL, 65536, 0);
  444.          s->xo1 = s->yo1 = s->zo1 = 0;
  445.          s->xo2 = s->yo2 = s->zo2 = 0;
  446.          parse_assgn(cr, s, 1);
  447.          s->type = GRAVITY;
  448.         }
  449.      else if (!stricmp(var, "POSTEST"))
  450.         {
  451.          s->x1 = getarg(c,    1, -1000000000L);
  452.          s->y1 = getarg(NULL, 1, -1000000000L);
  453.          s->z1 = getarg(NULL, 1, -1000000000L);
  454.          s->x2 = getarg(NULL, 1,  1000000000L);
  455.          s->y2 = getarg(NULL, 1,  1000000000L);
  456.          s->z2 = getarg(NULL, 1,  1000000000L);
  457.          cr = parse_assgn(cr, s, 1);
  458.          parse_assgn(cr, s, 0);
  459.          s->type = POSTEST;
  460.         }
  461.      else if (!stricmp(var, "ROTTEST"))
  462.         {
  463.          s->x1 = getarg(c,    65536, DONTCARE);
  464.          s->y1 = getarg(NULL, 65536, DONTCARE);
  465.          s->z1 = getarg(NULL, 65536, DONTCARE);
  466.          s->x2 = getarg(NULL, 65536, DONTCARE);
  467.          s->y2 = getarg(NULL, 65536, DONTCARE);
  468.          s->z2 = getarg(NULL, 65536, DONTCARE);
  469.          cr = parse_assgn(cr, s, 1);
  470.          parse_assgn(cr, s, 0);
  471.          s->type = ROTTEST;
  472.         }
  473.      else if (!stricmp(var, "POSLIMIT"))
  474.         {
  475.          s->x1 = getarg(c,    1, DONTCARE);
  476.          s->y1 = getarg(NULL, 1, DONTCARE);
  477.          s->z1 = getarg(NULL, 1, DONTCARE);
  478.          s->x2 = getarg(NULL, 1, DONTCARE);
  479.          s->y2 = getarg(NULL, 1, DONTCARE);
  480.          s->z2 = getarg(NULL, 1, DONTCARE);
  481.          cr = parse_assgn(cr, s, 1);
  482.          parse_assgn(cr, s, 0);
  483.          s->type = POSLIMIT;
  484.         }
  485.      else if (!stricmp(var, "ROTLIMIT"))
  486.         {
  487.          s->x1 = getarg(c,    65536, DONTCARE);
  488.          s->y1 = getarg(NULL, 65536, DONTCARE);
  489.          s->z1 = getarg(NULL, 65536, DONTCARE);
  490.          s->x2 = getarg(NULL, 65536, DONTCARE);
  491.          s->y2 = getarg(NULL, 65536, DONTCARE);
  492.          s->z2 = getarg(NULL, 65536, DONTCARE);
  493.          cr = parse_assgn(cr, s, 1);
  494.          parse_assgn(cr, s, 0);
  495.          s->type = ROTLIMIT;
  496.         }
  497.          else if (!stricmp(var, "SELECTED"))
  498.             {
  499.              s->x1 = getarg(c,    1, 0);
  500.              cr = parse_assgn(cr, s, 1);
  501.              parse_assgn(cr, s, 0);
  502.              s->type = SELECTED;
  503.             }
  504.      else return;
  505.     }
  506.  else
  507.     {
  508.      sscanf(cmd,"%s", var);
  509.      if (!stricmp(var, "SET"))
  510.         {
  511.          parse_assgn(ci, s, 1);
  512.          s->type = SET;
  513.         }
  514.      else
  515.         {
  516.          if ((c=strchr(ci,'('))==NULL) return;   /* verify arguments */
  517.          if ((cr=strchr(c,')'))==NULL) return;
  518.          c++;
  519.          *cr++ = 0;
  520.          if (!stricmp(var, "SENSOR"))
  521.             {
  522.              s->x1 = getarg(c,    1, -1000000000L);
  523.              s->y1 = getarg(NULL, 1, -1000000000L);
  524.              s->z1 = getarg(NULL, 1, -1000000000L);
  525.              s->x2 = getarg(NULL, 1,  1000000000L);
  526.              s->y2 = getarg(NULL, 1,  1000000000L);
  527.              s->z2 = getarg(NULL, 1,  1000000000L);
  528.              cr = parse_assgn(cr, s, 1);
  529.              parse_assgn(cr, s, 0);
  530.              s->type = SENSOR;
  531.             }
  532.      else if (!stricmp(var, "POPTEXT"))
  533.         {
  534.          s->x1 = getarg(c, 180, 90);
  535.          cr = parse_assgn(cr, s, 1);
  536.          c = strtok(cr, "#\n");
  537.          if (!c) return;
  538.          s->seg = strdup(c);
  539.          s->type = POPTEXT;
  540.         }
  541.          else if (!stricmp(var, "TIMER"))
  542.             {
  543.              s->x1 = getarg(c, 180, 0L);
  544.              s->y1 = DONTCARE;
  545.              cr = parse_assgn(cr, s, 1);
  546.              parse_assgn(cr, s, 0);
  547.              s->type = TIMER;
  548.             }
  549.          else return;
  550.         }
  551.     }
  552.  s->next = NULL;                 /* put it at end of list  */
  553.  s->status = 1;                  /* force a restart        */
  554.  if (cur_state==s) return;
  555.  cur_state->next = s;
  556.  cur_state = s;
  557. }
  558.  
  559.  
  560. void parse_if()
  561. {
  562.  STATE *s;
  563.  char *c, *r;
  564.  
  565.  if ((s = new_state()) == NULL) return;
  566.  c = strtok(NULL,"\n");
  567.  if ((c = strchr(c,'(')) == NULL) return;   /* verify conditional terminators */
  568.  if ((r = strchr(c,')')) == NULL) return;
  569.  *r++ = 0;                            /* trim length */
  570.  parse_var(strtok(c+1," \t\n,"),   &(s->tst1v), &(s->tst1i) );
  571.  parse_var(strtok(NULL, " \t\n,"), &(s->tst2v), &(s->tst2i) );
  572.  parse_rest(r, s);
  573. }
  574.  
  575.  
  576. void parse_do()
  577. {
  578.  STATE *s;
  579.  
  580.  if ((s = new_state()) == NULL) return;
  581.  s->tst1i = 0;
  582.  parse_rest(strtok(NULL,"\n"), s);
  583. }
  584.  
  585.  
  586. /********************* EXECUTE *******************/
  587.  
  588. static long elapsed = 0;
  589. extern int redraw;
  590. extern VIEW *current_view;
  591.  
  592. static void exec_state(STATE *s)
  593. {
  594.  STATE *old_state = s;
  595.  int changed = (s==cur_ani->lstate) ? 0 : 1 ;
  596.  long x, y, z, rx, ry, rz;
  597.  long nx, ny, nz, nrx, nry, nrz;
  598.  int seg_changed = 0;
  599.  long tps = 180L;
  600.  int endstate = 0;
  601.  
  602.  cur_state = s;
  603.  while((cur_ani->state==old_state) && s)
  604.     {
  605.    if (s->type == FREE) goto next_state;
  606.    if (changed) s->status |= CHANGED;
  607.    if (s->type == TIMER && changed) s->y1 = DONTCARE;   /* reset on entry */
  608.    if(s->type == GRAVITY && changed)
  609.     {
  610.      s->x1 = s->x2;
  611.      s->y1 = s->y2;
  612.      s->z1 = s->z2;
  613.      s->xo1 = s->yo1 = s->zo1 = 0;
  614.      s->xo2 = s->yo2 = s->zo2 = 0;
  615.     }
  616.    if (s->tst1i)
  617.     {
  618.      if (vars[s->tst1i] != s->tst1v) goto next_state;
  619.      if (s->tst2i)
  620.       {
  621.        if (vars[s->tst2i] != s->tst2v) goto next_state;
  622.       }
  623.     }
  624.    switch(s->type)
  625.         {
  626.      case SET: goto set;
  627.  
  628.          case SELECTED:
  629.              if (get_obj_flags(s->seg) & OBJ_HIGHLIGHTED)
  630.                 {
  631.                  if (s->x1) unhighlight_obj(s->seg);
  632.                  goto reset;
  633.                 }
  634.        else goto set;
  635.  
  636.      case USEREP:
  637.       {
  638.        if (s->x1 < 0) unlock_rep(s->seg);
  639.        else lock_rep(s->seg, s->x1);
  640.        redraw++;
  641.        goto set;
  642.       }
  643.  
  644.      case ATTACH:
  645.       {
  646.        if (s->x1 == 0)
  647.     {
  648.      disconnect_body(current_view);
  649.      if (!flymode)
  650.       {
  651.        current_view->roll = 0;
  652.       }
  653.     }
  654.        else connect_body(current_view, s->seg);
  655.        goto set;
  656.       }
  657.  
  658.      case POPTEXT:
  659.       {
  660.        long t;
  661.        if (s->seg) popmsg(s->seg);
  662.        t = current_time()+s->x1;
  663.        while(current_time() < t) if (kbhit()) break;
  664.        while(kbhit()) getkey();
  665.        redraw++;
  666.        goto set;
  667.       }
  668.  
  669.      case SENSOR:
  670.       {
  671.        extern VIEW real_view;
  672.        long x,y,z;
  673.        real_viewpoint(&real_view, &x, &y, &z);
  674.        if (s->x1 > x) goto set;
  675.        if (s->x2 < x) goto set;
  676.        if (s->y1 > y) goto set;
  677.        if (s->y2 < y) goto set;
  678.        if (s->z1 > z) goto set;
  679.        if (s->z2 < z) goto set;
  680.        goto reset;
  681.       }
  682.      case POSTEST:
  683.       {
  684.        seg_getposxyz(s->seg, &x, &y, &z);
  685.        if (s->x1 > x) goto set;
  686.        if (s->x2 < x) goto set;
  687.        if (s->y1 > y) goto set;
  688.        if (s->y2 < y) goto set;
  689.              if (s->z1 > z) goto set;
  690.        if (s->z2 < z) goto set;
  691.        goto reset;
  692.       }
  693.          case ROTTEST:
  694.       {
  695.        seg_getrxyz(s->seg, &x, &y, &z);
  696.        if (s->x1 != DONTCARE && s->x1>x) goto set;
  697.        if (s->x2 != DONTCARE && s->x2<x) goto set;
  698.        if (s->y1 != DONTCARE && s->y1>y) goto set;
  699.        if (s->y2 != DONTCARE && s->y2<y) goto set;
  700.              if (s->z1 != DONTCARE && s->z1 > z) goto set;
  701.        if(s->z2 != DONTCARE && s->z2 < z) goto set;
  702.        goto reset;
  703.       }
  704.      case POSLIMIT:
  705.       {
  706.        seg_getjointxyz(s->seg, &x, &y, &z);
  707.        if (s->x1 != DONTCARE && s->x1 > x) { x = s->x1; goto rstp; }
  708.        if (s->x2 != DONTCARE && s->x2 < x) { x = s->x2; goto rstp; }
  709.        if (s->y1 != DONTCARE && s->y1 > y) { y = s->y1; goto rstp; }
  710.        if (s->y2 != DONTCARE && s->y2 < y) { y = s->y2; goto rstp; }
  711.        if (s->z1 != DONTCARE && s->z1 > z) { z = s->z1; goto rstp; }
  712.        if (s->z2 != DONTCARE && s->z2 < z) { z = s->z2; goto rstp; }
  713.        goto reset;
  714.    rstp:
  715.        seg_changed++;
  716.        abs_move_segment(s->seg, x, y, z);
  717.        goto move_seg;
  718.       }
  719.      case ROTLIMIT:
  720.       {
  721.              seg_getrxyz(s->seg, &x, &y, &z);
  722.        if (s->x1 != DONTCARE && s->x1 > x) { x = s->x1; goto rstr; }
  723.        if (s->x2 != DONTCARE && s->x2 < x) { x = s->x2; goto rstr; }
  724.        if (s->y1 != DONTCARE && s->y1 > y) { y = s->y1; goto rstr; }
  725.        if (s->y2 != DONTCARE && s->y2 < y) { y = s->y2; goto rstr; }
  726.              if (s->z1 != DONTCARE && s->z1 > z) { z = s->z1; goto rstr; }
  727.        if (s->z2 != DONTCARE && s->z2 < z) { z = s->z2; goto rstr; }
  728.        goto reset;
  729.    rstr:
  730.        seg_changed++;
  731.        abs_rot_segment(s->seg, x, y, z, RYXZ);
  732.              goto move_seg;
  733.       }
  734.          case MOVETO:
  735.             {
  736.        seg_getjointxyz(s->seg, &x, &y, &z);
  737.        seg_getrxyz(s->seg, &rx, &ry, &rz);
  738.        nx = x; ny = y; nz = z;
  739.        nrx = rx; nry = ry; nrz = rz;
  740.        if (s->x1 != DONTCARE){ nx = s->x1; s->xo1 = 0; }   /* set pos'n, zero underflow */
  741.        if (s->y1 != DONTCARE){ ny = s->y1; s->yo1 = 0; }
  742.        if (s->z1 != DONTCARE){ nz = s->z1; s->zo1 = 0; }
  743.        if (s->x2 != DONTCARE) nrx = s->x2;
  744.        if (s->y2 != DONTCARE) nry = s->y2;
  745.        if (s->z2 != DONTCARE) nrz = s->z2;
  746.        if (x != nx || y != ny || z != nz)
  747.     {
  748.      seg_changed++;
  749.      abs_move_segment(s->seg, nx, ny, nz);
  750.     }
  751.        if (rx != nrx || ry != nry || rz != nrz)
  752.     {
  753.      seg_changed++;
  754.      abs_rot_segment(s->seg, nrx, nry, nrz, RYXZ);
  755.     }
  756.        if (seg_changed) goto move_seg; else goto set;
  757.       }
  758.          case ABSTEP:
  759.              tps = elapsed;
  760.          case STEP:
  761.             {
  762.              seg_getrxyz(s->seg, &rx, &ry, &rz);
  763.              nrx = rx; nry = ry; nrz = rz;
  764.              asm {
  765.             .386
  766.             les        bx,DWORD PTR s
  767.             mov        eax,es:[bx].(STATE)x2
  768.             imul    DWORD PTR elapsed
  769.             idiv     DWORD PTR tps
  770.             add        eax,nrx
  771.             cmp        eax,-360*65536
  772.             jg        nccx
  773.             add        eax,360*65536
  774.          }
  775. nccx:  asm {
  776.             cmp        eax,360*65536
  777.             jl        nchx
  778.             sub        eax,360*65536
  779.          }
  780. nchx:  asm {
  781.             mov        nrx,eax
  782.  
  783.             mov        eax,es:[bx].(STATE)y2
  784.             imul    DWORD PTR elapsed
  785.             idiv     DWORD PTR tps
  786.             add        eax,nry
  787.             cmp        eax,-360*65536
  788.             jg        nccy
  789.             add        eax,360*65536
  790.          }
  791. nccy:  asm {
  792.             cmp        eax,360*65536
  793.             jl        nchy
  794.             sub        eax,360*65536
  795.          }
  796. nchy:  asm {
  797.             mov        nry,eax
  798.  
  799.             mov        eax,es:[bx].(STATE)z2
  800.             imul    DWORD PTR elapsed
  801.             idiv     DWORD PTR tps
  802.             add        eax,nrz
  803.             cmp        eax,-360*65536
  804.             jg        nccz
  805.             sub        eax,-360*65536
  806.          }
  807. nccz:  asm {
  808.             cmp        eax,360*65536
  809.             jl        nchz
  810.             sub        eax,360*65536
  811.          }
  812. nchz:  asm {
  813.             mov        nrz,eax
  814.          }
  815.  
  816.              if (rx != nrx || ry != nry || rz != nrz)
  817.     {
  818.      seg_changed++;
  819.      abs_rot_segment(s->seg, nrx, nry, nrz, RYXZ);
  820.     }
  821.  
  822. do_posstep:
  823.     seg_getjointxyz(s->seg, &x, &y, &z);
  824.     nx = x; ny = y; nz = z;
  825.     if (s->x1 != 0)
  826.      {
  827.         asm {
  828.         les    bx,DWORD PTR s
  829.         mov    eax,es:[bx].(STATE)x1
  830.         imul    DWORD PTR elapsed
  831.         idiv     DWORD PTR tps
  832.         mov    dl,es:[bx].(STATE)xo1
  833.         mov    dh,al
  834.         sar    eax,8
  835.         add     dl,dh
  836.         adc    nx,eax
  837.         mov    es:[bx].(STATE)xo1,dl
  838.           }
  839.      }
  840.     if (s->y1 != 0)
  841.      {
  842.       asm {
  843.         les    bx,DWORD PTR s
  844.         mov    eax,es:[bx].(STATE)y1
  845.         imul    DWORD PTR elapsed
  846.         idiv     DWORD PTR tps
  847.         mov    dl,es:[bx].(STATE)yo1
  848.         mov    dh,al
  849.         sar    eax,8
  850.         add     dl,dh
  851.         adc    ny,eax
  852.         mov    es:[bx].(STATE)yo1,dl
  853.           }
  854.      }
  855.     if (s->z1 != 0)
  856.      {
  857.       asm {
  858.         les    bx,DWORD PTR s
  859.         mov    eax,es:[bx].(STATE)z1
  860.         imul    DWORD PTR elapsed
  861.         idiv     DWORD PTR tps
  862.         mov    dl,es:[bx].(STATE)zo1
  863.         mov    dh,al
  864.         sar    eax,8
  865.         add     dl,dh
  866.         adc    nz,eax
  867.         mov    es:[bx].(STATE)zo1,dl
  868.           }
  869.      }
  870.     if (x != nx || y != ny || z != nz)
  871.      {
  872.       seg_changed++;
  873.       abs_move_segment(s->seg, nx, ny, nz);
  874.      }
  875.     if (seg_changed) goto move_seg; else goto set;
  876.        }
  877.  
  878.       case GRAVITY:
  879.        {
  880.     if (s->x3 != 0)
  881.      {
  882.       asm {
  883.         les    bx,DWORD PTR s
  884.         mov    eax,es:[bx].(STATE)x3
  885.         imul    DWORD PTR elapsed
  886.         idiv     DWORD PTR tps
  887.         mov    dl,al
  888.         sar    eax,8
  889.         add     dl,es:[bx].(STATE)xo2
  890.         adc    es:[bx].(STATE)x1,eax
  891.         mov    es:[bx].(STATE)xo2,dl
  892.                 }
  893.      }
  894.     if (s->y3 != 0)
  895.      {
  896.       asm {
  897.         mov    eax,es:[bx].(STATE)y3
  898.         imul    DWORD PTR elapsed
  899.         idiv     DWORD PTR tps
  900.         mov    dl,al
  901.         sar    eax,8
  902.         add     dl,es:[bx].(STATE)yo2
  903.         adc    es:[bx].(STATE)y1,eax
  904.         mov    es:[bx].(STATE)yo2,dl
  905.           }
  906.      }
  907.     if (s->z3 != 0)
  908.      {
  909.       asm {
  910.         mov    eax,es:[bx].(STATE)z3
  911.         imul    DWORD PTR elapsed
  912.         idiv     DWORD PTR tps
  913.         mov    dl,al
  914.         sar    eax,8
  915.         add     dl,es:[bx].(STATE)zo2
  916.         adc    es:[bx].(STATE)z1,eax
  917.         mov    es:[bx].(STATE)zo2,dl
  918.           }
  919.      }
  920.     goto do_posstep;        /* now treat as normal motion */
  921.        }
  922.  
  923.       case TIMER:
  924.              {
  925.     if (s->y1 == DONTCARE) s->y1 = ctime+s->x1;
  926.     if (s->y1 < ctime)
  927.             goto reset;
  928.     else goto set;
  929.              }
  930.  
  931.  reset:
  932.     if (s->rst1i > 0) vars[s->rst1i] = s->rst1v;   /* do all setup stuff  */
  933.         else if (s->rst1i < 0) endstate++;
  934.     if (s->rst2i > 0) vars[s->rst2i] = s->rst2v;
  935.     else if (s->rst2i < 0) endstate++;
  936.     if (s->rst3i > 0) vars[s->rst3i] = s->rst3v;
  937.     else if (s->rst3i < 0) endstate++;
  938.     if (s->rstate)
  939.      {
  940.       cur_ani->state = s->rstate;
  941.       goto newstate;
  942.      }
  943.     break;
  944.  move_seg:
  945.        {
  946.     SEGMENT *r = get_root_segment(s->seg);
  947.     seg_set_flags(r, seg_get_flags(r)|16);  /* mark seg root to be moved */
  948.     s->ulist = NULL;                        /* put on move list */
  949.     if (update_list == NULL)  update_list = update_end = s;
  950.     else
  951.      {
  952.         update_end->ulist = s;
  953.         update_end = s;
  954.      }
  955.        }
  956.  set:
  957.     if (s->set1i > 0) vars[s->set1i] = s->set1v;
  958.     else if (s->set1i < 0) endstate++;
  959.     if (s->set2i > 0) vars[s->set2i] = s->set2v;
  960.     else if (s->set2i < 0) endstate++;
  961.     if (s->set3i > 0) vars[s->set3i] = s->set3v;
  962.     else if (s->set3i < 0) endstate++;
  963.     if (s->sstate)
  964.      {
  965.       cur_ani->state = s->sstate;
  966.         goto newstate;
  967.      }
  968.     break;
  969.     default: break;
  970.        }
  971. next_state:
  972.       if (endstate) s = NULL;
  973.       else s = s->next;
  974.      }
  975. newstate:
  976.  cur_ani->lstate = old_state;
  977. }
  978.  
  979.  
  980.  
  981. void do_animations()
  982. {
  983.  SEGMENT *s;
  984.  unsigned flags;
  985.  ANIMATION *ani = anilist;
  986.  ctime = current_time();
  987.  update_list = NULL;
  988.  
  989.  while(ani)
  990.     {
  991.      if (ani->last_time < ctime)       /* time to animate? */
  992.         {
  993.          elapsed = ctime+ani->period-ani->last_time;
  994.          if (elapsed > 300) elapsed = 300;
  995.          ani->last_time = ctime+ani->period;
  996.          cur_ani = ani;
  997.          exec_state(ani->state);
  998.         }
  999.      ani = ani->next;
  1000.     }
  1001.  
  1002.  while(update_list)                        /* process all root segments */
  1003.     {
  1004.      s = get_root_segment(update_list->seg); /* first check if done yet */
  1005.      flags = seg_get_flags(s);
  1006.      if (flags & 16)
  1007.         {
  1008.          seg_set_flags(s, flags&(~16));        /* clear flag, update */
  1009.          update_segment(s);
  1010.          redraw |= 0x4000;
  1011.         }
  1012.      update_list = update_list->ulist;
  1013.     }
  1014. }
  1015.  
  1016.  
  1017.  
  1018.  
  1019.  
  1020.  
  1021.