/* Copyright (C) 2001-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.ui.*;
import artofillusion.object.Mesh.*;
import buoy.event.*;
import java.awt.*;
import java.text.*;
import java.util.Vector;

/** ThickenMeshTool is an EditingTool used for making pieces of TriangleMeshes thicker
    or thinner. */

public class ThickenMeshTool extends EditingTool
{
  private Point clickPoint;
  private Vec3 norm[], baseVertPos[];
  private UndoRecord undo;

  private static Image icon, selectedIcon;

  public ThickenMeshTool(EditingWindow fr)
  {
    super(fr);
    icon = loadImage("outsetPoints.gif");
    selectedIcon = loadImage("selected/outsetPoints.gif");
  }

  public void activate()
  {
    super.activate();

    MeshViewer view = ((MeshEditorWindow) theFrame).getCurrentView();
    int selected[] = view.getSelectionDistance();
    for (int i = 0; i < selected.length; i++)
      if (selected[i] == 0)
	{
	  theWindow.setHelpText(Translate.text("thickenMeshTool.helpText"));
	  return;
	}
    theWindow.setHelpText(Translate.text("thickenMeshTool.errorText"));
  }

  public Image getIcon()
  {
    return icon;
  }

  public Image getSelectedIcon()
  {
    return selectedIcon;
  }

  public String getToolTipText()
  {
    return Translate.text("thickenMeshTool.tipText");
  }

  public void mousePressed(WidgetMouseEvent e, ViewerCanvas view)
  {
    Mesh mesh = (Mesh) ((MeshViewer) view).getObject().object;
    MeshVertex v[] = mesh.getVertices();
    
    clickPoint = e.getPoint();
    norm = mesh.getNormals();
    baseVertPos = mesh.getVertexPositions();
  }
  
  public void mouseDragged(WidgetMouseEvent e, ViewerCanvas view)
  {
    Mesh mesh = (Mesh) ((MeshViewer) view).getObject().object;
    MeshVertex vert[] = mesh.getVertices();
    Camera cam = view.getCamera();
    Point dragPoint = e.getPoint();
    int i, size = MeshViewer.HANDLE_SIZE, selectDist[] = ((MeshViewer) view).getSelectionDistance();
    double distance;
    Vec3 v[];
    Vec2 p;

    if (undo == null)
      undo = new UndoRecord(theWindow, false, UndoRecord.COPY_VERTEX_POSITIONS, new Object [] {mesh, mesh.getVertexPositions()});
    distance = 0.01*(clickPoint.y - dragPoint.y);
    v = findNewPositions(mesh, baseVertPos, (MeshViewer) view, distance);
    mesh.setVertexPositions(v);
    ((ObjectViewer) view).objectChanged();
    theWindow.updateImage();
    NumberFormat format = NumberFormat.getNumberInstance();
    format.setMaximumFractionDigits(2);
    if (distance < 0.0)
      theWindow.setHelpText(Translate.text("thickenMeshTool.dragText.inward", format.format(-distance)));
    else
      theWindow.setHelpText(Translate.text("thickenMeshTool.dragText.outward", format.format(distance)));
  }

  public void mouseReleased(WidgetMouseEvent e, ViewerCanvas view)
  {
    Object3D meshobj = ((MeshViewer) view).getObject().object;
    Mesh mesh = (Mesh) meshobj;
    MeshVertex vert[] = mesh.getVertices();
    Camera cam = view.getCamera();
    Point dragPoint = e.getPoint();
    int i;
    double distance;
    Vec3 v[];

    if (undo != null)
      {
        theWindow.setUndoRecord(undo);
        distance = 0.01*(clickPoint.y - dragPoint.y);
	v = findNewPositions(mesh, baseVertPos, (MeshViewer) view, distance);
	mesh.setVertexPositions(v);
      }
    meshobj.informChanged(this, ModelEvent.CHANGEDUR_OBJECTEDITOR);
    theWindow.setHelpText(Translate.text("thickenMeshTool.helpText"));
    norm = null;
    undo = null;
    baseVertPos = null;
  }
  
  /* Find the new positions of the vertices . */

  Vec3 [] findNewPositions(Mesh mesh, Vec3 vert[], MeshViewer view, double distance)
  {
    Vec3 v[] = new Vec3 [vert.length];
    int selected[] = view.getSelectionDistance();
    
    for (int i = 0; i < v.length; i++)
      {
	if (selected[i] == 0)
	  v[i] = norm[i].times(distance);
	else
	  v[i] = new Vec3();
      }
    ((MeshEditorWindow) theFrame).adjustDeltas(v);
    for (int i = 0; i < vert.length; i++)
      v[i].add(vert[i]);
    return v;
  }
}