/* Copyright (C) 1999-2004 by Peter Eastman

   This program is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
   Foundation; either version 2 of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful, but WITHOUT ANY 
   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
   PARTICULAR PURPOSE.  See the GNU General Public License for more details. */

package artofillusion;

import artofillusion.math.*;
import artofillusion.object.*;
import artofillusion.view.*;
import buoy.event.*;
import buoy.widget.*;
import java.awt.*;

/** The ObjectPreviewCanvas class displays a single object which the user can move and rotate, but
    not edit. */

public class ObjectPreviewCanvas extends ObjectViewer
{
  private boolean sizeSet;

  static final RGBColor surfaceRGB = new RGBColor(0.8f, 0.8f, 1.0f);
  static final Color surfaceColor = new Color(0.8f, 0.8f, 1.0f);

  /** Create an ObjectPreviewCanvas for previewing a particular object. */

  public ObjectPreviewCanvas(ObjectInfo obj)
  {
    this(obj, new RowContainer());
  }

  /** Create an ObjectPreviewCanvas for previewing a particular object.  The controls for setting scale,
      projection, and view direction will be add to the Panel. */

  public ObjectPreviewCanvas(ObjectInfo obj, RowContainer p)
  {
    super(obj, p);
    setTool(new RotateViewTool(null));
    setMetaTool(new MoveViewTool(null));
    int mode = lastRenderMode;
    setRenderMode(RENDER_SMOOTH);
    lastRenderMode = mode;
    hideBackfaces = false;
  }

  /** Draw the object. */

  protected void drawObject(Graphics g)
  {
    RenderingMesh mesh;
    
    if (theObject == null)
      return;
    if (!sizeSet)
    {
      // When the canvas first comes up, calculate an initial scale that allows the entire object to be seen.
      
      Rectangle dim = getBounds();
      Vec3 objSize = theObject.getBounds().getSize();
      double scale = 0.8*Math.min(dim.width, dim.height)/Math.max(Math.max(objSize.x, objSize.y), objSize.z);
      setScale(scale);
      theCamera.setScreenParams(0, scale, dim.width, dim.height);
      sizeSet = true;
    }
    if (renderMode == RENDER_WIREFRAME)
    {
      g.setColor(surfaceColor);
      Object3D.draw(g, theCamera, objInfo.getWireframePreview(), objInfo.getBounds());
    }
    else if (renderMode == RENDER_TRANSPARENT)
    {
      mesh = objInfo.getPreviewMesh();
      if (mesh != null)
        renderMeshTransparent(mesh, theCamera, theCamera.getViewToWorld().timesDirection(Vec3.vz()), surfaceRGB, null);
    }
    else
    {
      mesh = objInfo.getPreviewMesh();
      Vec3 viewDir = theCamera.getViewToWorld().timesDirection(Vec3.vz());
      VertexShader shader;
      if (renderMode == RENDER_FLAT)
        shader = new FlatVertexShader(mesh, surfaceRGB, viewDir);
      else if (renderMode == RENDER_SMOOTH)
        shader = new SmoothVertexShader(mesh, surfaceRGB, viewDir);
      else
        shader = new TexturedVertexShader(mesh, theObject, 0.0, viewDir).optimize();
      renderMesh(mesh, shader, theCamera, theObject.isClosed(), null);
    }
/*    else if (renderMode == RENDER_FLAT)
    } */
  }

  /** When the user presses the mouse, forward events to the current tool. */

  protected void mousePressed(WidgetMouseEvent e)
  {
    requestFocus();
    sentClick = true;
    activeTool = currentTool;
    if (metaTool != null && e.isMetaDown())
      activeTool = metaTool;
    activeTool.mousePressed(e, this);
  }

  protected void mouseReleased(WidgetMouseEvent e)
  {
    if (sentClick)
      activeTool.mouseReleased(e, this);
  }
}