"Fossies" - the Fresh Open Source Software archive

Member "graph/src/anitroll/atom.c" of archive pixcon-5.02.tar.gz:




#include <stdlib.h>
#include <string.h>

#include "quark.h"
#include "pstring.h"


/* *************************************************************
************************************************************* */
void eventtype::evaluate(int frameno, atom *source, dbl_llist_manager *hiearchy_manager) {

   vfile     *infile;                            // input file
   string_type token;
   string_type parent, object;                  // temp string
   int       number;                            // # of changes during an event
   int       j;                                 // loop vars
   float     temp;                              // temp array
   quark     *qtr;                              // quark pointer
   
   infile = (vfile *)global_resource_manager->find_resource_object(RESOURCE_SFILE, NULL, NULL);
   if (!infile->scan_data(efilename.string, EVENT_PATH.string)) {
      global_resource_manager->register_resource_object(RESOURCE_SFILE, infile);
      sprintf(perror_buffer, "Warning: can't access %s...\n", efilename.string);
      pprintf(perror_buffer);
      return;
   }

   infile->scan_token(&token);

   for (number=asc2int(token.string); number>0; number--) {
      infile->scan_token(&token);
      object.stringcpy(&token);                 // backup in case of quark name
      lower_case(token.string);

      if (!token.stringcmp("composite")) {     // the following event affects atom
         infile->scan_token(&token);
         lower_case(token.string);

         source->flags |= QUARK_FLAG_RECALC;

         if (!token.stringcmp("spline"))       // xyz dof change
            source->motion.read_spline(infile, timefactor, &token);
         else                                // quaternion dof
            source->motion.read_quaternion(infile, timefactor, &token);
      }

      else if (!token.stringcmp("move")) {       // change parent of a child
         infile->scan_token(&token);
         object.stringcpy(&token);
         infile->scan_token(&token);
         source->move_quark(object.string, token.string);
      }

      else if (!token.stringcmp("drop")) {     // make a child indep. object
         infile->scan_token(&token);
         source->drop_quark(frameno, token.string, hiearchy_manager, infile);
      }

      // absorb another object
      else if (!token.stringcmp("absorb")) {
         infile->scan_token(&token);
         object.stringcpy(&token);
         infile->scan_token(&token);
         if (!source->name.stringcmp(object.string))
            source->join_atom(object.string, token.string, hiearchy_manager);
      }

      else if (!token.stringcmp("take")) {// take child from object
         infile->scan_token(&token);
         object.stringcpy(&token);
         infile->scan_token(&token);
         parent.stringcpy(&token);
         infile->scan_token(&token);

         source->take_quark(object.string, parent.string, token.string, hiearchy_manager);
      }

      else if (!token.stringcmp("scale")) { // global scale of object
         infile->scan_token(&token);
         temp = (float)atof(token.string);
         infile->scan_token(&token);
         source->scale_quark(temp, token.string);
      }

      else {                     // child event
         qtr = source->find((quark *)NULL, object.string);
	    
         if (qtr)
            qtr->new_action(infile, timefactor, NULL);
         else {                          // cant find item, so junk event
            sprintf(perror_buffer, "Warning::ATOM... Can't find %s\n", object.string);
            pprintf(perror_buffer);
	       
            infile->scan_token(&token);
            lower_case(token.string);

            if (!token.stringcmp("spline") || !token.stringcmp("quaternion")) {
               infile->scan_token(&token);
               j = asc2int(token.string);
               infile->scan_token(&token);
               infile->scan_token(&token);
               infile->scan_token(&token);

               for (; j>-1; j--) {
                  infile->scan_token(&token);
                  infile->scan_token(&token);
                  infile->scan_token(&token);
               }

            }

         }

      }

   }

   global_resource_manager->register_resource_object(RESOURCE_SFILE, infile);
}


/* *************************************************************
************************************************************* */
void atom::render_object(engine *proc, quark *parent, frustum_type *frustum, unsigned int frustum_flag) {

   linktype *ptr;

   // cull node w/ view frustum
   if ((old_state.state_flags & STATE_MASK_TREE) == STATE_FLAG_TNONE)
      frustum_flag = 0;

   if (frustum_flag && (old_state.state_flags & STATE_MASK_TREE) == STATE_FLAG_TSPHERE && 
       query_frustum_clip(old_state.tree_radius, old_state.tree_center, frustum, &frustum_flag, frustum_fail_data))  {  
      flags &= ~QUARK_FLAG_VISIBLE;
      return;
   }

   flags |= QUARK_FLAG_VISIBLE;

   for (ptr=(linktype *)edge.head; ptr; ptr=(linktype *)ptr->next)
      ptr->link->render_object(proc, this, frustum, frustum_flag);
}


/* *************************************************************
************************************************************* */
void atom::new_action(vfile *infile, float  timefactor, char *buffer) {
}


/* *************************************************************
************************************************************* */
int atom::query_whatwasi(int type) {

   return (atom::query_whatami() == type) ? 1 : quark::query_whatwasi(type);
}


/* *************************************************************
   This is the destructor for this class
************************************************************* */
int atom::parse(vfile *infile, string_type *token) {

   if (!quark::parse(infile, token))
      read_event(infile, token, 0);

   return 1;
}


/* *************************************************************
   Read in an object's data
************************************************************* */
int atom::read_data(char *filename) {

   vfile *infile;
   string_type token;
   
   infile = (vfile *)global_resource_manager->find_resource_object(RESOURCE_SFILE, NULL, NULL);
   if (!infile->scan_data(filename, ATOM_PATH.string)) {
      global_resource_manager->register_resource_object(RESOURCE_SFILE, infile);
      return 0;
   }

   name.stringcpy(filename);

   while (read_quark(infile, &token, 0));

   global_resource_manager->register_resource_object(RESOURCE_SFILE, infile);
   return 1;
}


/* *************************************************************
************************************************************* */
basic_event *atom::read_event(vfile *infile, string_type *token, int frame_offset) {

   eventtype *ptr;
   basic_event *qtr;

   ptr = new eventtype;

   infile->scan_token(token);
   ptr->event = asc2int(token->string) + frame_offset;

   // "event_mult"
   infile->scan_token(token);
   infile->scan_token(token);
   ptr->timefactor = (float)atof(token->string);

   // "event"
   infile->scan_token(token);
   infile->scan_token(&ptr->efilename);

   for (qtr = (basic_event *)event_manager.head; qtr && qtr->event < ptr->event; qtr = (basic_event *)qtr->next);
   
   if (qtr)
      event_manager.insert(ptr, qtr);
   else
      event_manager.append(ptr, NULL);
   
   return ptr;
}


/* *************************************************************
   This function implements new events
************************************************************* */
void atom::new_action(int frameno, dbl_llist_manager *hiearchy_manager) {

   basic_event *ptr;                            // event pointer
   
   for (ptr=(basic_event *)event_manager.head; ptr && frameno >= ptr->event; ptr = (basic_event *)event_manager.head) {
      ptr->evaluate(frameno, this, hiearchy_manager);
      event_manager.remove(ptr);
      delete ptr;
   }
      
}


/* ********************************************************
******************************************************** */
int atom::scale_quark(float s, char *part) {

   quark *target, *parent;
   
   target = find(NULL, part, &parent);

   if (target) {
      target->apply_scale(s); 
      return 1;
   }
   	 
   sprintf(perror_buffer, "Could not scale %s\n", part);
   pprintf(perror_buffer);
   return 0;
}


/* ********************************************************
   This function changes the parent of a child - moves it w/in its own atom tree
******************************************************** */
int atom::move_quark(char *child, char *parent) {

   quark *ptr;                         // temp pointers
   quark *old_parent = NULL;           // temp pointer
   quark *new_parent;
   
   // find "child" and make sure not to assign a child to a node in the child's tree
   ptr = find(NULL, child, &old_parent);

   if (!ptr || ptr->find(NULL, parent)) {
      sprintf(perror_buffer, "Could not move %s to %s\n", child, parent);
      pprintf(perror_buffer);
      return 0;
   }

   // find new parent
   new_parent = !strcmp(parent, TOKEN_NULL_STR) ? this : find(NULL, parent);
   
   if (!new_parent) {
      sprintf(perror_buffer, "Could not move %s to %s\n", child, parent);
      pprintf(perror_buffer);
      return 0;
   }
   
   if (old_parent) {
      old_parent->remove_link(ptr);
      ptr->remove_link(old_parent);
   }
   
   else
      remove_link(ptr);
      

   ptr->create_link(new_parent);
   new_parent->create_link(ptr);

   return 1;
}


/* ********************************************************
   This function makes a child an independent object
******************************************************** */
int atom::drop_quark(int frameno, char *child, dbl_llist_manager *hiearchy_manager, vfile *infile) {

   atom_list_type *tree;
   atom      *atr;                              // new object
   quark     *old_child;                        // child to drop
   quark     *old_parent = (quark *)NULL;       // parent of child
   string_type token;                  // temp string
   linktype  *ptr;

   old_child = find(NULL, child, &old_parent);

   if (!old_child) {  // cant find child....
      infile->scan_token(&token);
      infile->scan_token(&token);
      infile->scan_token(&token);

      do {
         if (!infile->scan_token(&token) || token.string[0] == '}')
            break;
      } while (1);

      return 0;
   }

   if (!old_parent) {  // since root node is to be dropped, reuse old atom
      event_manager.dest();
      atr = this;
   }

   else {
      old_parent->remove_link(old_child);
      old_child->remove_link(old_parent);

      // make new object
      hiearchy_manager->append(tree = new atom_list_type, NULL);
      tree->htree = atr = new atom;
      atr->edge.insert(ptr = new linktype, NULL);
      ptr->link = old_child;
   }

   // read object events
   infile->scan_token(&token);
   atr->name.stringcpy(&token);
   infile->scan_token(&token); // "{"

   do {
      if (!infile->scan_token(&token) || token.string[0] == '}')
         break;

      atr->read_event(infile, &token, frameno);
   } while (1);

   // update object
   atr->new_action(frameno, hiearchy_manager);

   return 1;
}


/* ********************************************************
   This function takes another object, and makes it
   a part of it.

   NOTE: events from one does not transfer over to the new object
******************************************************** */
int atom::join_atom(char *part, char *parent, dbl_llist_manager *hiearchy_manager) {

   atom     *btr;                       // atom pointers
   quark    *ptr;                       // quark pointers
   string_type token;
   quark    *qtr;
   linktype *rtr;
   atom_list_type *tree;

   token.stringcpy(parent);
   lower_case(token.string);

   // move to a child
   if (token.stringcmp("link")) {
      ptr = find((quark *)NULL, parent);
      if (!ptr)
         return 0;
   }

   // coexists w/ current children
   else 
      ptr = this;

   for (tree = (atom_list_type *)hiearchy_manager->head; tree && tree->htree->name.stringcmp(part); tree = (atom_list_type *)tree->next);

   if (!tree)
      return 0;

   // remove atom from the master list
   hiearchy_manager->remove(tree);
   btr = tree->htree;
   tree->htree = NULL;
   delete tree;

   for (rtr = (linktype *)btr->edge.head; rtr; rtr = (linktype *)rtr->next) {
      qtr = rtr->link;
      rtr->link = NULL;

      ptr->create_link(qtr);
      qtr->create_link(ptr);
   }
   
   // delete old atom
   delete btr;

   return 1;
}


/* ********************************************************
   This function takes part of another object, and makes it
   a part of itself
******************************************************** */
int atom::take_quark(char *dest, char *parent, char *part, dbl_llist_manager *hiearchy_manager) {

   atom_list_type *atr;               // target pointer
   quark *child, *new_parent;         // quark pointers
   quark *old_parent = NULL;          // quark pointer

   for (atr = (atom_list_type *)hiearchy_manager->head; atr && atr->htree->name.stringcmp(parent); atr=(atom_list_type *)atr->next);

   if (!atr || !(child = atr->htree->find(NULL, part, &old_parent))) {
      sprintf(perror_buffer, "Could not take %s from %s to %s\n", part, parent, dest);
      pprintf(perror_buffer);
      return 0;
   }

   new_parent = !strcmp(dest, TOKEN_NULL_STR) ? this : find(NULL, dest);
   
   if (!new_parent) {
      sprintf(perror_buffer, "Could not take %s from %s to %s\n", part, parent, dest);
      pprintf(perror_buffer);
      return 0;
   }

   if (old_parent) {
      old_parent->remove_link(child);
      child->remove_link(old_parent);
   }

   else {
      atr->htree->remove_link(child);

      // wipe out empty node
      if (!atr->htree->edge.head) {
         hiearchy_manager->remove(atr);
         delete atr;
      }

   }
   
   new_parent->create_link(child);
   child->create_link(new_parent);

   return 1;
}