int ObjectMotion()

in layer1/PyMOLObject.cpp [231:549]


int ObjectMotion(CObject * I, int action, int first,
               int last, float power, float bias,
               int simple, float linear, int wrap,
               int hand, int window, int cycles, int state, int quiet)
{
  PyMOLGlobals *G = I->G;
  if(I->type == cObjectGroup) { /* propagate */
    return ExecutiveGroupMotion(G,I,action,first,last, power,bias,simple,linear,
                                wrap,hand,window,cycles,state,quiet);
  } else {
    
    int frame;
    int nFrame = MovieGetLength(I->G);

    if(wrap<0) {
      wrap = SettingGet_b(I->G,NULL, I->Setting, cSetting_movie_loop);
    }

    if(nFrame < 0)
      nFrame = -nFrame;

    if(!I->ViewElem) {
      I->ViewElem = VLACalloc(CViewElem, 0);
    }
    
    if((action == 7) || (action == 8)) { /* toggle */
      frame = first;
      if(first < 0)
        frame = SceneGetFrame(G);
      VLACheck(I->ViewElem, CViewElem, frame);
      if(action == 7) {
        if(I->ViewElem[frame].specification_level>1) {
          action = 1;
        } else {
          action = 0;
        }
      } else if(action == 8) {
        if(I->ViewElem[frame].specification_level>1) {
          int frame;
          action = 3;
          for(frame=0;frame<nFrame;frame++) {
            if(I->ViewElem[frame].specification_level==1) {
              action = 6;
              break;
            }
          }
        }
        else if(I->ViewElem[frame].specification_level>0) {
          action = 6;
        } else {
          action = 3;
        }
      }
    }

    if(action == 4) {   /* smooth */
      int save_last = last;
      if(first < 0)
        first = 0;
      
      if(last < 0) {
        last = nFrame;
      }
      if(last >= nFrame) {
        last = nFrame - 1;
      }
      if(first <= last) {
        int a;
        VLACheck(I->ViewElem, CViewElem, last);
          for(a = 0; a < cycles; a++) {
            ViewElemSmooth(I->ViewElem + first, I->ViewElem + last, window, wrap);
          }
      }
      if(SettingGet_b(I->G, NULL, I->Setting, cSetting_movie_auto_interpolate)){
        action = 3; /* reinterpolate */
        last = save_last;
      }
    }
    switch (action) {
    case 0:                      /* store */
      if(!I->TTTFlag) {
        float mn[3], mx[3], orig[3];
        if(ExecutiveGetExtent(G, I->Name, mn, mx, true, -1, true)) {
          average3f(mn, mx, orig);
          ObjectSetTTTOrigin(I, orig);
        } else {
          initializeTTT44f(I->TTT);
          I->TTTFlag = true;
        }
      }
      if(I->ViewElem && I->TTTFlag) {
        if(first < 0)
          first = SceneGetFrame(G);
        if(last < 0)
          last = first;
        {
          int state_tmp=0, state_flag = false;
          if(state>=0) {
            state_tmp = state;
            state_flag = true;
          } else if(SettingGetIfDefined_i(G, I->Setting, cSetting_state, &state_tmp)) {
            state_flag = true;
            state_tmp--;
          }
        
          for(frame = first; frame <= last; frame++) {
            if((frame >= 0) && (frame < nFrame)) {
              VLACheck(I->ViewElem, CViewElem, frame);
              if(!quiet) {
                PRINTFB(G, FB_Object, FB_Details)
                  " ObjectMotion: Setting frame %d.\n", frame + 1 ENDFB(G);
              }
              TTTToViewElem(I->TTT, I->ViewElem + frame);

              if(state_flag) {
                I->ViewElem[frame].state_flag = state_flag;
                I->ViewElem[frame].state = state_tmp;
              }

              if(power!=0.0F) {
                I->ViewElem[frame].power_flag = true;
                I->ViewElem[frame].power = power;
              }

              if(bias > 0.0F) {
                I->ViewElem[frame].bias_flag = true;
                I->ViewElem[frame].bias = bias;
              }

              I->ViewElem[frame].specification_level = 2;
            }

          }
        }
      }
      break;
    case 1:                      /* clear */
      if(I->ViewElem) {
        if(first < 0)
          first = SceneGetFrame(G);
        if(last < 0)
          last = first;
        for(frame = first; frame <= last; frame++) {
          if((frame >= 0) && (frame < nFrame)) {
            VLACheck(I->ViewElem, CViewElem, frame);
            ViewElemArrayPurge(G, I->ViewElem + frame, 1);
            UtilZeroMem((void *) (I->ViewElem + frame), sizeof(CViewElem));
          }
        }
      }
      break;
    case 2:                      /* interpolate & reinterpolate */
    case 3:
      {
        CViewElem *first_view = NULL, *last_view = NULL;
        int view_found = false;

        if(first < 0)
          first = 0;
        if(first > nFrame) {
          first = nFrame - 1;
        }

        if(last < 0) {
          last = nFrame;
          if(last) {
            if(!wrap)
              last--;
            else {
              int frame = 0;
              VLACheck(I->ViewElem, CViewElem, last);
              for(frame = 0; frame < last; frame++) {
                if(I->ViewElem[frame].specification_level > 1) {
                  last += frame;
                  break;
                }
              }
            }
          }
        } else {
          if(last >= nFrame) {
            last = nFrame;
            if(last && !wrap)
              last--;
          }
        }

        VLACheck(I->ViewElem, CViewElem, last);

        if(wrap && (last >= nFrame)) {
          /* if we're interpolating beyond the last frame, then wrap by
             copying early frames to last frames */
          int a;
          for(a = nFrame; a <= last; a++) {
            ViewElemCopy(G, I->ViewElem + a - nFrame, I->ViewElem + a);
          }
        } else if(!wrap) { 
          /* if we're not wrapping, then make sure we nuke any stray / old
             interpolated frames */
          frame = nFrame - 1;
          while(frame>=0) {
            if(I->ViewElem[frame].specification_level > 1) 
              break;
            else
              UtilZeroMem((void *) (I->ViewElem + frame), sizeof(CViewElem));
            frame--;
          }
        }
        VLACheck(I->ViewElem, CViewElem, last);
        if(!quiet) {
          if(action == 2) {
            if(last == nFrame) {
              PRINTFB(G, FB_Object, FB_Details)
                " ObjectMotion: interpolating unspecified frames %d to %d (wrapping).\n",
                first + 1, last ENDFB(G);
            } else {
              PRINTFB(G, FB_Object, FB_Details)
                " ObjectMotion: interpolating unspecified frames %d to %d.\n", first + 1,
                last + 1 ENDFB(G);
            }
          } else {
            if(last == nFrame) {
              PRINTFB(G, FB_Object, FB_Details)
                " ObjectMotion: reinterpolating all frames %d to %d (wrapping).\n", first + 1,
                last ENDFB(G);
            } else {
              PRINTFB(G, FB_Object, FB_Details)
                " ObjectMotion: reinterpolating all frames %d to %d.\n", first + 1, last + 1
                ENDFB(G);
            }
          }
        }
        for(frame = first; frame <= last; frame++) {
          if(!first_view) {
            if(I->ViewElem[frame].specification_level == 2) {     /* specified */
              first_view = I->ViewElem + frame;
              view_found = true;
            }
          } else {
            CViewElem *view;
            int interpolate_flag = false;
            if(I->ViewElem[frame].specification_level == 2) {     /* specified */
              last_view = I->ViewElem + frame;
              if(action == 2) {   /* interpolate */
                for(view = first_view + 1; view < last_view; view++) {
                  if(!view->specification_level)
                    interpolate_flag = true;
                }
              } else {
                interpolate_flag = true;
              }
              if(interpolate_flag) {
                ViewElemInterpolate(G, first_view, last_view,
                                    power, bias, simple, linear, hand, 0.0F);
              }
              first_view = last_view;
              last_view = NULL;
            }
          }
        }

        if(first_view) {
          if(wrap && (last >= nFrame)) {
            /* if we're interpolating beyond the last frame, then wrap by
               copying the last frames back over the early frames */
            int a;
            for(a = nFrame; a <= last; a++) {
              ViewElemCopy(G, I->ViewElem + a, I->ViewElem + a - nFrame);
            }
          }
        }

        if((!view_found) && (last>=first) && (first>=0) && (last<=nFrame)) {
          UtilZeroMem(I->ViewElem + first, sizeof(CViewElem) * (1 + (last-first)));
        }

        if(last >= nFrame) {   /* now erase temporary views */
          ViewElemArrayPurge(G, I->ViewElem + nFrame, (1 + last - nFrame));
          UtilZeroMem((void *) (I->ViewElem + nFrame),
                      sizeof(CViewElem) * (1 + last - nFrame));
        }
      }
      break;
    case 5:                      /* reset */
      if(I->ViewElem) {
        VLAFreeP(I->ViewElem);
      }
      I->ViewElem = VLACalloc(CViewElem, 0);
      break;
    case 6:                      /* uninterpolate */
      if(I->ViewElem) {
        if(first < 0)
          first = 0;
        if(last < 0) {
          last = nFrame - 1;
        }
        for(frame = first; frame <= last; frame++) {
          if((frame >= 0) && (frame <= last)) {
            VLACheck(I->ViewElem, CViewElem, frame);
            if(I->ViewElem[frame].specification_level < 2) {
              ViewElemArrayPurge(G, I->ViewElem + frame, 1);
              UtilZeroMem((void *) (I->ViewElem + frame), sizeof(CViewElem));
            }
          }
        }
      }
      break;
    case 9:
      if(I->ViewElem) {
        VLAFreeP(I->ViewElem);
      }
      break;
    }
    if(I->ViewElem) {
      VLASize(I->ViewElem,CViewElem,nFrame);
    }
  }
  return 1;
}