#pragma ident "@(#)attrib.c 1.1 97/10/31 SMI"

/*
 * attrib.c
 *
 *	@(#)attrib.c 1.1 96/06/17 21:54:22
 *
 * Copyright (c) 1996, Sun Microsystems Computer Company, Mountain View, CA
 *
 *			All Rights Reserved
 *
 *	This is a program for manipulating 3D objects.  It is currently being
 *	developed by Mike M. Chow and Scott R. Nelson. 
 *
 *      This module contains methods for attributes.
 */

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#include <GL/gl.h>
#include "types.h"
#include "attrib.h"
#include "zdebug.h"
#include "utils.h"

/* 
 * Attributes
 * ===========
 * 
 * Each scene graph nodes contains an attribute field that specifies
 * colors, rendering modes (wire, solids, etc.), blending functions, and
 * OpenGL attributes. During traversal of scene at the drawing stage,
 * each visited node's attribute is pushed on an attribute stack (see
 * below).  When the node is done, its attribute is poped from the stack
 * and the original attribute is restored.
 * 
 * The main advantage of attribute stack is to allow material and
 * rendering modes to be inherited from the parent node (such as the car
 * body) to its children (such as wheels and car's doors).  This way, the
 * user need only specify the color of the parent once and all of
 * children will inherit the same color.
 */



/*
 * attribNew
 *
 *      Return a new, uninitialized attribute struct.
 */

Attrib *
attribNew()
{
  Attrib *attrib;

  attrib = (Attrib *) malloc(sizeof(Attrib));

  /* For the time being, we also set the attrib values by default.
   *  It should be done in attribCreat, ideally.
   */
  attrib->antialiasMode = ANTI_LINE_MODE;
  attrib->blendSrc = GL_SRC_ALPHA;
  attrib->blendDest = GL_ONE_MINUS_SRC_ALPHA;
  attrib->drawingMode = SOLIDMODE;
  attrib->pointSize = 1.0;
  attrib->lineWidth = 1.0;
  attrib->frontSurf = NULL;
  attrib->backSurf = NULL;
  return attrib;
}  /* End of attribNew*/
       



/*
 * attribCreate
 *
 *     Creates an initialized attribute struct.
 */

Attrib *
attribCreate()
{
    Attrib * attrib;
    
    attrib = attribNew();
    attrib->frontSurf = surfCreateDefault();
    attrib->masks = 0;
    attrib->antialiasMode = ANTI_LINE_MODE;
    return attrib;
}  /* End of attribCreate */




/*
 * attribDestroy
 *
 *      Free up attrib.
 */

void
attribDestroy(Attrib *attrib)
{
  surfDestroy(attrib->frontSurf);
  free(attrib);
}  /* End of attribDestroy */




/*
 * attribPrint
 *
 *      This is used by Scene Graph Writer to output attribute info 
 * to file.  This is useful for debugging too.
 */

void 
attribPrint(FILE *fp, int indent, Attrib *attrib)
{
  if (attrib->masks == 0)
    return;
  spaces(fp, indent);
  fprintf(fp, "Attrib {\n");
  spaces(fp, indent+2);
  fprintf(fp, "masks %d\n", attrib->masks);
  
  spaces(fp, indent+2);
  fprintf(fp, "frontSurf \n");
  surfPrint(fp, indent + 2, attrib->frontSurf);
  spaces(fp, indent);
  fprintf(fp, "}\n");
}  /* End of attribPrint */

    
/*
 * attribCopy
 *
 *     Copies attribute struct.
 */

void
attribCopy(Attrib *dest, Attrib *src)
{
  dest->masks = src->masks;
  surfCopy(dest->frontSurf, src->frontSurf);
  dest->blendSrc = src->blendSrc;
  dest->blendDest = src->blendDest;
  dest->drawingMode = src->drawingMode;
}  /* End of attribCopy */



/*
 * attribPush      
 *
 *      Pushes a new attribute on the attribute stack.
 */

void
attribPush()
{
  Stack *stack;
#if 0
  stack = &UserState.attribStack;
  zdo6 fprintf(stderr, "push on stack pos:%d\n", stack->top);
  if (stack->top >= MAX_ATTRIB_STACK_DEPTH){
    fprintf(stderr, "Warning: Max attrib stack is reached! Not pushing new attributes.");
    return;
  }

  stack->item[stack->top++] = UserState.currentAttrib;
#endif
}  /* End of attribPush */



/*
 * attribPop
 *
 *      Pops off the top most attribute from the attrib stack.
 */

void
attribPop()
{
  Stack *stack;
#if 0
  stack = &UserState.attribStack;
  if (stack->top == -1){
    fprintf(stderr, "Error: Trying to pop an empty attrib stack!\n");
    return;
  }
  stack->top--;
  zdo6 fprintf(stderr, "pop off stack pos:%d\n", stack->top);
  UserState.currentAttrib = stack->item[stack->top];
#endif
}   /* End of attribPop */

 /* End of attrib.c */
    
