Advertisement
jackd5011

ProcessingShapeModeler

Apr 26th, 2019
234
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.56 KB | None | 0 0
  1. /**
  2.  *    ProcessingShapeModeler by Jack Davenport
  3.  *    2019
  4.  */
  5.  
  6. ArrayList<PVector> positions = new ArrayList<PVector>();
  7. PImage backgroundImage;
  8.  
  9. // settings
  10. boolean joinWithFirst = true;
  11. boolean fillShape = true;
  12. boolean strokeShape = true;
  13. boolean outputTexCoords = true;
  14. float zoom = 1f;
  15. int selectedVertex = -1;
  16. boolean deleteFlag = false;
  17. boolean hideGui = false;
  18.  
  19. // pan vars
  20. float panX = 0f, panY = 0f;
  21. float offX = 0f, offY = 0f;
  22. boolean shiftPressed = false;
  23.  
  24. // handle vars
  25. boolean xHandled = false;
  26. boolean yHandled = false;
  27. float dmx, dmy, dpx, dpy;
  28.  
  29. void settings() {
  30.   size(1024, 640);
  31. }
  32.  
  33. void setup() {
  34. }
  35.  
  36. void draw() {
  37.   float oriX = width / 2 + panX;
  38.   float oriY = height / 2 + panY;
  39.  
  40.   // background colour
  41.   background(200);
  42.   pushMatrix();
  43.   {
  44.     translate(oriX, oriY);
  45.     scale(zoom);
  46.     if (backgroundImage != null) {
  47.       imageMode(CENTER);
  48.       image(backgroundImage, offX, offY);
  49.     }
  50.     strokeWeight(1/zoom);
  51.     stroke(150);
  52.     for (float x = -100f; x <= 100f; x += 10f) {
  53.       line(x, -100f, x, 100f);
  54.     }
  55.     for (float y = -100f; y <= 100f; y += 10f) {
  56.       line(-100f, y, 100f, y);
  57.     }
  58.   }
  59.   popMatrix();
  60.  
  61.   // draw shape
  62.   strokeWeight(1/zoom);
  63.   if (strokeShape) {
  64.     stroke(0);
  65.   } else {
  66.     noStroke();
  67.   }
  68.   if (fillShape) {
  69.     fill(128, 128, 128, 128);
  70.   } else {
  71.     noFill();
  72.   }
  73.  
  74.   if (!positions.isEmpty()) {
  75.     pushMatrix();
  76.     {
  77.       translate(oriX, oriY);
  78.       scale(zoom);
  79.  
  80.       // draw shapes
  81.       beginShape();
  82.       for (PVector pos : positions) {
  83.         vertex(pos.x, pos.y);
  84.       }
  85.       if (joinWithFirst) {
  86.         PVector first = positions.get(0);
  87.         vertex(first.x, first.y);
  88.       }
  89.       endShape();
  90.  
  91.       // show vertices
  92.       strokeWeight(6/zoom);
  93.       boolean flag = false;
  94.       for (int i = 0; i < positions.size(); i++) {
  95.         PVector pos = positions.get(i);
  96.         if (selectedVertex == i) {
  97.           stroke(255, 255, 0);
  98.         } else if (!flag && dist(oriX+pos.x*zoom, oriY+pos.y*zoom, mouseX, mouseY) < 6) {
  99.           stroke(0, 255, 0);
  100.           flag = true;
  101.         } else {
  102.           stroke(0);
  103.         }
  104.         point(pos.x, pos.y);
  105.       }
  106.     }
  107.     popMatrix();
  108.   }
  109.  
  110.   // show origin point
  111.   strokeWeight(5);
  112.   stroke(255, 0, 0);
  113.   point(oriX, oriY);
  114.  
  115.   // show position controls
  116.   if (selectedVertex != -1) {
  117.     PVector pos = positions.get(selectedVertex);
  118.     pushMatrix();
  119.     {
  120.       translate(oriX, oriY);
  121.       translate(pos.x*zoom, pos.y*zoom);
  122.       float mx = mouseX - (oriX + pos.x * zoom);
  123.       float my = mouseY - (oriY + pos.y * zoom);
  124.  
  125.       strokeWeight(1);
  126.       // x-axis
  127.       stroke(255, 0, 0);
  128.       fill(255, 0, 0);
  129.       if (xHandled || (mx > 40 && mx < 50 && my > -10 && my < 10)) {
  130.         stroke(255, 255, 0);
  131.         fill(255, 255, 0);
  132.       }
  133.       line(6, 0, 40, 0);
  134.       triangle(40, 10, 40, -10, 50, 0);
  135.       // y-axis
  136.       stroke(0, 255, 0);
  137.       fill(0, 255, 0);
  138.       if (yHandled || (mx > -10 && mx < 10 && my > 40 && my < 50)) {
  139.         stroke(255, 255, 0);
  140.         fill(255, 255, 0);
  141.       }
  142.       line(0, 6, 0, 40);
  143.       triangle(10, 40, -10, 40, 0, 50);
  144.     }
  145.     popMatrix();
  146.  
  147.     // do dragging
  148.     if (xHandled) {
  149.       float dx = mouseX - dmx;
  150.       pos.x = dpx + dx / zoom;
  151.     }
  152.     if (yHandled) {
  153.       float dy = mouseY - dmy;
  154.       pos.y = dpy + dy / zoom;
  155.     }
  156.   }
  157.  
  158.   // deletion
  159.   if (deleteFlag && selectedVertex != -1) {
  160.     positions.remove(selectedVertex);
  161.     selectedVertex = -1;
  162.     deleteFlag = false;
  163.   }
  164.  
  165.   // show gui
  166.   if (!hideGui) {
  167.     fill(0);
  168.     textSize(20);
  169.     textAlign(LEFT, TOP);
  170.     text("Vertex count: " + (positions.size() + (joinWithFirst && !positions.isEmpty() ? 1 : 0)), 10, 10);
  171.     text("Join with first vertex? " + (joinWithFirst ? "yes" : "no"), 10, 30);
  172.     text("Fill shape (editor only)? " + (fillShape ? "yes" : "no"), 10, 50);
  173.     text("Stroke shape (editor only)? " + (strokeShape ? "yes" : "no"), 10, 70);
  174.     if (backgroundImage != null) {
  175.       text("Output texture coordinates? " + (outputTexCoords ? "yes" : "no"), 10, 90);
  176.     }
  177.  
  178.     textAlign(LEFT, BOTTOM);
  179.     text("Controls", 10, height-250);
  180.     text("P: print shape to console (shift to save to file)", 10, height-230);
  181.     text("U: undo last vertex", 10, height-210);
  182.     text("J: toggle join with first", 10, height-190);
  183.     text("B: select background image", 10, height-170);
  184.     text("N: clear background image", 10, height-150);
  185.     text("F: toggle fill", 10, height-130);
  186.     text("S: toggle stroke", 10, height-110);
  187.     text("T: toggle output texture coordinates", 10, height-90);
  188.     text("H: hide/show GUI", 10, height-70);
  189.     text("Del/Backspace: Delete selected vertex", 10, height-50);
  190.     text("Arrow Keys: Pan camera", 10, height-30);
  191.     text("Shift + Arrow Keys: Pan texture", 10, height-10);
  192.   }
  193. }
  194.  
  195. void mousePressed() {
  196.   float oriX = width/2 + panX;
  197.   float oriY = height/2 + panY;
  198.   int idx = -1;
  199.   for (int i = 0; i < positions.size(); i++) {
  200.     PVector pos = positions.get(i);
  201.     if (dist(oriX+pos.x*zoom, oriY+pos.y*zoom, mouseX, mouseY) < 6) {
  202.       idx = i;
  203.       break;
  204.     }
  205.   }
  206.   if (idx != -1) {
  207.     selectedVertex = idx;
  208.     return;
  209.   }
  210.  
  211.   if (selectedVertex == -1) {
  212.     float relX = (mouseX - oriX) / zoom;
  213.     float relY = (mouseY - oriY) / zoom;
  214.     positions.add(0, new PVector(relX, relY));
  215.   } else {
  216.     PVector pos = positions.get(selectedVertex);
  217.     float mx = mouseX - (oriX + pos.x * zoom);
  218.     float my = mouseY - (oriY + pos.y * zoom);
  219.  
  220.     // x handle
  221.     if (mx > 40 && mx < 50 && my > -10 && my < 10) {
  222.       xHandled = true;
  223.       dmx = mouseX;
  224.       dmy = mouseY;
  225.       dpx = pos.x;
  226.       dpy = pos.y;
  227.     }
  228.     // y handle
  229.     else if (mx > -10 && mx < 10 && my > 40 && my < 50) {
  230.       yHandled = true;
  231.       dmx = mouseX;
  232.       dmy = mouseY;
  233.       dpx = pos.x;
  234.       dpy = pos.y;
  235.     } else {
  236.       selectedVertex = -1;
  237.     }
  238.   }
  239. }
  240.  
  241. void keyPressed() {
  242.   if (key == 'p') {
  243.     printShape(false);
  244.   } else if(key == 'P') {
  245.     printShape(true);
  246.   } else if (key == 'u' || key == 'U') {
  247.     if (positions.isEmpty()) {
  248.       return;
  249.     }
  250.     positions.remove(0);
  251.   } else if (key == 'j' || key == 'J') {
  252.     joinWithFirst = !joinWithFirst;
  253.   } else if (key == 'b' || key == 'B') {
  254.     selectInput("Select a background image", "onBackgroundSelected");
  255.   } else if (key == 'n' || key == 'N') {
  256.     backgroundImage = null;
  257.   } else if (key == 'f' || key == 'F') {
  258.     fillShape = !fillShape;
  259.   } else if (key == 's' || key == 'S') {
  260.     strokeShape = !strokeShape;
  261.   } else if (keyCode == BACKSPACE || keyCode == DELETE) {
  262.     if (selectedVertex != -1) {
  263.       deleteFlag = true;
  264.     }
  265.   } else if ((key == 't' || key == 'T') && backgroundImage != null) {
  266.     outputTexCoords = !outputTexCoords;
  267.   } else if (keyCode == LEFT) {
  268.     if (shiftPressed) offX += 2f;
  269.     else panX += 2f;
  270.   } else if (keyCode == RIGHT) {
  271.     if (shiftPressed) offX -= 2f;
  272.     else panX -= 2f;
  273.   } else if (keyCode == UP) {
  274.     if (shiftPressed) offY += 2f;
  275.     else panY += 2f;
  276.   } else if (keyCode == DOWN) {
  277.     if (shiftPressed) offY -= 2f;
  278.     else panY -= 2f;
  279.   } else if (keyCode == SHIFT) {
  280.     shiftPressed = true;
  281.   } else if(key == 'h' || key == 'H') {
  282.     hideGui = !hideGui;
  283.   }
  284. }
  285.  
  286. void keyReleased() {
  287.   if (keyCode == SHIFT) {
  288.     shiftPressed = false;
  289.   }
  290. }
  291.  
  292. void mouseWheel(MouseEvent e) {
  293.   zoom += (float)e.getCount() * 0.1f;
  294.   zoom  = min(max(zoom, 0.1f), 10f);
  295. }
  296.  
  297. void mouseReleased() {
  298.   if (xHandled) {
  299.     xHandled = false;
  300.   }
  301.   if (yHandled) {
  302.     yHandled = false;
  303.   }
  304. }
  305.  
  306. void printShape(boolean file) {
  307.   String out = "";
  308.   if (!positions.isEmpty()) {
  309.     boolean includeUVs = backgroundImage != null && outputTexCoords;
  310.     float texWidth = includeUVs ? backgroundImage.width * 0.5f : 0f;
  311.     float texHeight = includeUVs ? backgroundImage.height * 0.5f : 0f;
  312.     out += "/* -------- CREATED WITH ProcessingShapeModeler ------- */\n";
  313.     if (includeUVs) {
  314.       out += "/* WARNING: this shape uses textures, and requires P2D to render correctly! */\n";
  315.       out += "PImage tex = ... // provide your own image\n";
  316.     }
  317.     out += "PShape shape = createShape();\n";
  318.     out += "shape.beginShape();\n";
  319.     if (includeUVs) {
  320.       out += "shape.texture(tex);\n";
  321.       out += "shape.textureMode(NORMAL);\n";
  322.     }
  323.     for (PVector pos : positions) {
  324.       out += printVertex(pos, includeUVs, texWidth, texHeight);
  325.     }
  326.     if (joinWithFirst) {
  327.       out += printVertex(positions.get(0), includeUVs, texWidth, texHeight);
  328.     }
  329.     out += "shape.endShape();\n";
  330.   } else {
  331.     out += "/* ERROR: please create some vertices first! */\n";
  332.   }
  333.  
  334.   if(file) {
  335.     PrintWriter writer = createWriter("shape.pde");
  336.     writer.print(out);
  337.     writer.flush();
  338.     writer.close();
  339.     println("// saved to shape.pde");
  340.   } else {
  341.     println(out);
  342.   }
  343. }
  344.  
  345. String printVertex(PVector vector, boolean includeUVs, float texWidth, float texHeight) {
  346.   String out = "";
  347.   out += "shape.vertex(" + vector.x + ", " + vector.y;
  348.   if (includeUVs) {
  349.     float u = ((vector.x - offX) / texWidth) * 0.5f + 0.5f;
  350.     float v = ((vector.y - offY) / texHeight) * 0.5f + 0.5f;
  351.     out += ", " + u + ", " + v;
  352.   }
  353.   return out + ");\n";
  354. }
  355.  
  356. void onBackgroundSelected(File backgroundFile) {
  357.   try {
  358.     backgroundImage = loadImage(backgroundFile.getAbsolutePath());
  359.   }
  360.   catch(Exception e) {
  361.     println("ERROR: invalid background image file: " + backgroundFile.getAbsolutePath());
  362.     backgroundImage = null;
  363.   }
  364. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement