/*
cylinder
  
Scriptographer 2.0 script
2006-11-23
2008-03-26 modified to work with Sg 2.0.025
2008-03-27 minor modification for dialog
2008-04-01  minor fix on myDialog_getValues

Scriptographer is a plugin for Adobe Illustrator(TM)
created by Juerg Lehni
http://www.scriptographer.com/

This script was written by SATO Hiroyuki
http://park12.wakwak.com/~shp/lc/et/en_sg.html
*/

var hlen = 4*(Math.sqrt(2)-1)/3;
var mpi = Math.PI;
var hpi = Math.PI / 2;
var wpi = Math.PI * 2;

var r, h, m, interval, jitter, lastPnt;
var g_myDialog;
// ----------------------------------------------
function onInit() {
  r = 5; // radius
  h = 18; // height
  interval = h*0.75;
  jitter = h;
  m = r*2;
  // show dialog at start
  onOptions();
}
// ----------------------------------------------
function mm2pt(n){  return n * 2.83464567;  }
// ----------------------------------------------
function onOptions(){
  
  // "interval" and "jitter" are specified as the percentage for
  // the greater one of m (diameter) and h (height).
  
  if(g_myDialog){
    g_myDialog.dialog.destroy();
    g_myDialog = null;
  }
  
  g_myDialog = myDialog("cylinder:",[
    {description:"diameter",     value:m},
    {description:"height",       value:h},
    {description:"interval (%)", value:interval/Math.max(m,h)*100},
    {description:"jitter (%)",   value:jitter/Math.max(m,h)*100}]);
}
// ---------------------
function getValuesFromDialog(){
  var opt = myDialog_getValues();
  if(opt != null){
    if(opt[0]<=0 || opt[1]<=0 || opt[2]<=0 || opt[3]<=0){
      Dialog.alert("please input a positive number");
      return false;
    }
    m = opt[0];
    r = m/2;
    h = opt[1];
    interval = opt[2]*Math.max(m,h)/100;
    jitter = opt[3]*Math.max(m,h)/100;
    return true;
  }
  return false;
}
// ----------------------------------------------
function onMouseDown(event){
  with(activeDocument.activeLayer){
    if(locked || hidden){
      Dialog.alert("please unlock and show the active layer");
      return; }
  }
  // get values from dialog
  var chk = getValuesFromDialog();
  if(!chk){ return; }
  
  lastPnt = event.point;
  drawCylinder(r,h, lastPnt);
}
// ----------------------------------------------
function onMouseDrag(event){
  if(!lastPnt || event.point.isClose(lastPnt, interval) ) return;
  var jv = event.point.subtract(lastPnt).normalize().rotate(hpi);
  lastPnt = event.point;
  drawCylinder(r,h, lastPnt.add(jv.multiply((Math.random()-0.5)*jitter)));
}
// ----------------------------------------------
function onMouseUp(){
  lastPnt = null;
}
// ----------------------------------------------
function drawCylinder(r, h, pnt){

  var tv = (Math.random()*0.8+0.1)*hpi;

  var v = new Point(1,0);

  var pi = make_a_path(1, new GrayColor(0));
  pi.closed = true;
//  pi.style.stroke.join = 1;
  var gr = new Group();
  gr.appendChild(pi);
  var seg = pi.segments;
  seg.addAll([
    new Segment(v.rotate(hpi).multiply(r).multiply(1,Math.sin(tv)),
                v.multiply(r*hlen), v.multiply(-r*hlen)),
    new Segment(v.rotate(mpi).multiply(r),
                v.rotate(hpi).multiply(r*hlen).multiply(1,Math.sin(tv)),
                new Point(0,0))
    ]);
  seg.addAll([
    new Segment(seg[1].point.add(0,-h*Math.cos(tv)),
                new Point(0,0),
                seg[1].handleIn.multiply(-1)),
    new Segment(seg[0].point.add(0,-h*Math.cos(tv)-r*2*Math.sin(tv)),
                seg[0].handleOut, seg[0].handleIn)
    ]);
  seg.addAll([
    new Segment(seg[2].point.add(r*2,0),
                seg[2].handleOut, new Point(0,0)),
    new Segment(seg[1].point.add(r*2,0),
                new Point(0,0), seg[1].handleIn)
    ]);

  pi = make_a_path(0.5, null);
  var seg2 = pi.segments; gr.appendChild(pi);
  seg2.addAll([
    new Segment(seg[1].point, new Point(0,0), seg[2].handleOut),
    new Segment(new Point(0,-seg[0].point.y),
                seg[0].handleOut, seg[0].handleIn),
    new Segment(seg[5].point, seg[4].handleIn, new Point(0,0))
    ]);

  gr.translate(0,h*Math.cos(tv)/2);
  gr.rotate( Math.random()*wpi );
  gr.translate(pnt);
}
// ----------------------------------------------
function make_a_path(w,c){
  var pi = new Path();
  pi.closed = false;
  with(pi.style){
    stroke.color = new GrayColor(1);
    stroke.width = w;
    fill.color = c;
  }
  return pi;
}


// ==================================================================
// function for floating dialog
function myDialog(title, elems){
  this.dialog = new FloatingDialog(FloatingDialog.OPTION_TABBED);
  this.dialog.title = title
  this.textedits = [];
  this.max_caption_width = 0;

  // parts --------------------------------------
  this.addStatic = function(elem, left, top){
    var st = new Static(this.dialog);
    st.setText(elem["description"]);
    st.setSize(st.bestSize);
    st.setPosition(left, top);
    if(st.size.width > this.max_caption_width){
      this.max_caption_width = st.size.width;
    }
  }

  this.addTextEdit = function(elem, size, left, top){
    var te = new TextEdit(this.dialog, { units:TextValueItem.UNITS_NO });
    te.setText(elem["value"]);
    te.setSize(size);
    te.setPosition(left, top);
    this.textedits.push(te);
  }

  // layout --------------------------------------
  // constants
  var vertical_interval = 24;
  var caption_and_textedit_interval = 4;
  var margin = 10;
  var left = margin;
  
  var textedit_size = new Size(50, 20);
  var button_size = new Size(50, 20);
  
  // ------------------------
  for(var i=0; i<elems.length; i++){
    this.addStatic(elems[i], left, vertical_interval * i + margin);
  }
  left += this.max_caption_width + caption_and_textedit_interval;
  for(var i=0; i<elems.length; i++){
    this.addTextEdit(elems[i], textedit_size, left,
                     vertical_interval * i + margin - 2);
  }
  
  var button_height = 0;
  
  this.dialog.setSize(left + textedit_size.width + margin*2,
                      vertical_interval * elems.length + margin*2
                      + button_height);
  return this;
}
// ------------------------------------
function myDialog_getValues(){
  var ar = [];
  var txt;
  for(var i=0; i<g_myDialog.textedits.length; i++){
    txt = g_myDialog.textedits[i].stringValue;
    try{
      ar.push(eval(txt) - 0);
    }catch(e){
      Dialog.alert(e);
      return null;
    }
  }
  return ar;
}
// ==================================================================

