// This ULP creates 2 layers (100=tStkDoc and 101=bStkDoc) and draws all parts
// which begin with the prefix 'X' (in my drawings used for connectors) in the
// new created layers. Top mounted parts are drawn on the layer 100 and bottom
// mounted parts respectively parts with the value "BOTTOM" are drawn on the
// layer 101. Afterwards each pin is commented with its signal name. The output
// is written to "DocStk.scr".


string prefix = "X";	// Connector prefix;
int t_ratio = 10;	// Standard ratio to use
int t_size = 12700;	// Standard text size to use

int g_width = 0, g_ratio = 10, g_size = 12700;

void PrintText(real angle, int mirror, int ratio, int size, string value, int x, int y)
{
  if (g_size != size)
  {
    g_size = size;
    printf("CHANGE SIZE %f;\n", u2mm(size));
  }
  if (g_ratio != ratio)
  {
    g_ratio = ratio;
    printf("CHANGE RATIO %d;\n", ratio);
  }
  printf("TEXT '%s' R%d (%f %f);\n", value, int(angle), u2mm(x), u2mm(y));
  if (mirror)
  {
    printf("MIRROR (%f %f);\n", u2mm(x), u2mm(y));
  }
}

output("DocStk.scr")
{
  board(B)
  {
    printf("GRID mm 0.635;\n");
    printf("CHANGE WIDTH %f;\n", u2mm(g_width));
    printf("CHANGE RATIO %d;\n", g_ratio);
    printf("CHANGE SIZE %f;\n", u2mm(g_size));
    printf("LAYER 100 tStkDoc;\n");
    printf("LAYER 101 bStkDoc;\n");
    B.elements(E)
    {
      int minx, miny, maxx, maxy;
      int aminx, aminy, amaxx, amaxy;
      int angle = 0;
      int nr = 0;

      if (strstr(E.name, prefix) == 0)
      {
        E.package.wires(W)
        {
          if (nr)
          {
            aminx = min(aminx, W.x1);
            aminy = min(aminy, W.y1);
            amaxx = max(amaxx, W.x1);
            amaxy = max(amaxy, W.y1);
            aminx = min(aminx, W.x2);
            aminy = min(aminy, W.y2);
            amaxx = max(amaxx, W.x2);
            amaxy = max(amaxy, W.y2);
          }
          else
          {
            aminx = amaxx = W.x1;
            aminy = amaxy = W.y1;
            aminx = min(aminx, W.x2);
            aminy = min(aminy, W.y2);
            amaxx = max(amaxx, W.x2);
            amaxy = max(amaxy, W.y2);
          }
          nr++;
        }
        nr = 0;
        E.package.contacts(C)
        {
          if (nr)
          {
            minx = min(minx, C.pad.x);
            miny = min(miny, C.pad.y);
            maxx = max(maxx, C.pad.x);
            maxy = max(maxy, C.pad.y);
          }
          else
          {
            minx = maxx = C.pad.x;
            miny = maxy = C.pad.y;
          }
          nr++;
        }
        if (minx < aminx)
        {
          aminx = minx;
        }
        if (maxx > amaxx)
        {
          amaxx = maxx;
        }
        if (miny < aminy)
        {
          aminy = miny;
        }
        if (maxy > amaxy)
        {
          amaxy = maxy;
        }
      }
      if (nr)
      {
        int midx, midy;
        
        midx = (minx + maxx) / 2;
        midy = (miny + maxy) / 2;
        if ((strupr(E.value) == "BOTTOM") || (E.mirror))
        {
          printf("LAYER bStkDoc;\n");
        }
        else
        {
          printf("LAYER tStkDoc;\n");
        }
        if (maxx - minx > maxy - miny)
        {
          angle = 90;
        }
        E.texts(T)
        {
          PrintText(T.angle, T.mirror, T.ratio, T.size, T.value, T.x, T.y);
        }
        E.package.wires(W)
        {
          if (g_width != W.width)
          {
            g_width = W.width;
            printf("CHANGE WIDTH %f;\n", u2mm(W.width));
          }
          printf("WIRE (%f %f) (%f %f);\n", u2mm(W.x1), u2mm(W.y1), u2mm(W.x2), u2mm(W.y2));
        }
        E.package.texts(T)
        {
          PrintText(T.angle, T.mirror, T.ratio, T.size, T.value, T.x, T.y);
        }
        E.package.arcs(A)
        {
          if (g_width != A.width)
          {
            g_width = A.width;
            printf("CHANGE WIDTH %f;\n", u2mm(A.width));
          }
          printf("ARC CCW (%f %f) (%f %f) (%f %f);\n",
                  u2mm(A.x1), u2mm(A.y1),
                  u2mm(2 * A.xc - A.x1), u2mm(2 * A.yc - A.y1),
                  u2mm(A.x2), u2mm(A.y2));
        }
        E.package.contacts(C)
        {
          if (C.pad)
          {
            printf("CIRCLE (%f %f) (%f %f);\n",
                   u2mm(C.pad.x), u2mm(C.pad.y),
                   u2mm(C.pad.x + C.pad.diameter / 2), u2mm(C.pad.y));
            if (angle)
            {
              if (C.pad.y > midy)
              {
                PrintText(90, 0, t_ratio, t_size, C.signal, C.pad.x + C.pad.diameter / 2, amaxy + 2 * C.pad.diameter);
              }
              else
              {
                PrintText(270, 0, t_ratio, t_size, C.signal, C.pad.x - C.pad.diameter / 2, aminy - 2 * C.pad.diameter);
              }
            }
            else
            {
              if (C.pad.x > midx)
              {
                PrintText(0, 0, t_ratio, t_size, C.signal, amaxx + 2 * C.pad.diameter, C.pad.y - C.pad.diameter / 2);
              }
              else
              {
                PrintText(180, 0, t_ratio, t_size, C.signal, aminx - 2 * C.pad.diameter, C.pad.y + C.pad.diameter / 2);
              }
            }
          }
        }
      }
    }
  }
}
