// pre 

package actor;

import render.*;
import render.Geometry;
import render.Matrix;

/**
 * $Id: WorldState.java,v 1.9 2004/03/03 22:13:36 robbins Exp $
 */
public class WorldState
{
  private int top = 0;
  private Matrix[] matrix;
  private Geometry root;
  
  // Interface should be implemented by RenderJPanel, RenderApplet, etc.
  protected RenderableContext context;   
  
  // Static singleton instance               
  private static WorldState instance;

  /** Static singleton constructor            */
  public static WorldState getInstance(RenderableContext context) 
  {
    if (instance == null) {
      synchronized(WorldState.class) {
        if (instance == null)
          instance = new WorldState(context);
      }
    }
    return instance;
  }
  
  
  private WorldState(RenderableContext context) 
  {
    this.context = context;
    this.root = context.getWorldGeometry();
    this.matrix = context.getMatrix();
  }
  
  public Matrix getTopMatrix() { 
    return matrix[top]; 
  }

  /**
   Pops the top matrix from the stack.
   */
  public void pop() {
    top--;
  }

  /**
   Pushes a copy of the top matrix onto the stack.
   */
  public void push() {
    matrix[top + 1].copy(matrix[top]);
    top++;
  }

  /**
   Rotates the top matrix around the X axis by angle t (radians).<p>
   @param t angle in radians
   */
  public void rotateX(double t) {
    getTopMatrix().rotateX(t);
  }

  /**
   Rotates the top matrix around the Y axis by angle t (radians).<p>
   @param t angle in radians
   */
  public void rotateY(double t) {
    getTopMatrix().rotateY(t);
  }

  /**
   Rotates the top matrix around the Z axis by angle t (radians).<p>       
   @param t angle in radians
   */
  public void rotateZ(double t) {
    getTopMatrix().rotateZ(t);
  }

  /**
   Scales the top matrix by x, y, z in their respective dimensions.<p>
   @param x x scale factor
   @param y y scale factor
   @param z z scale factor
   */
  public void scale(double x, double y, double z) {
    getTopMatrix().scale(x, y, z);
  }
  
  public void scale(Point3D pt) {
    scale(pt.x, pt.y, pt.z);
  }
  
  public void scale(double d) {
    scale(d, d, d);
  }

  /**
   Applies the top transformation matrix to {@link Geometry} s.<p>
   @param s Geometry object
   */
  public void transform(Geometry s) {
    s.setMatrix(getTopMatrix());
  }

  /**
   * Translates the top matrix by Point3D p
   * @param p
   */
  public void translate(Point3D p)
  {
    translate(p.x, p.y, p.z);
  }
  
  /** 
   Translates the top matrix by vector v.<p>
   @param v an array of three doubles representing translations 
   in the x,y,z directions.
   */
  public void translate(double v[]) {
    translate(v[0], v[1], v[2]);
  }

  /**
   Translates the top matrix by x, y, z.<p>
   @param x - translation in the x direction.
   @param y - translation in the y direction.
   @param z - translation in the z direction.
   */
  public void translate(double x, double y, double z) {
    getTopMatrix().translate(x, y, z);
  }

  public Geometry getRoot()
  {
    return root;
  }

  public void setRoot(Geometry root)
  {
    this.root = root;
  }

  public double getTime()
  {
    return context.getCurrentTime();
  }

}// end