skip to Main Content

I wrote a script with a dialog with custom round buttons (something like the official adobe ones).
Being ignorant of mathematics, I drew the button with straight lines, like this:

    ButtonPanel ();
    function ButtonPanel () {
        var Panel = new Window ("dialog");
        Panel.text = "Panel";
        var Button = Panel.add ("button");
        Button.text = "Exit";
        Button.preferredSize.width = 170;
        Button.onClick = function () {
                Panel.close ();
            }
        Draw (Button);
        Panel.show ();
        function Draw (Obj) {
            if (Obj.type == "button") {
                Obj.graphics.foregroundColor = Obj.graphics.newPen (Obj.graphics.PenType.SOLID_COLOR, [1, 1, 1], 1);
                Obj.graphics.font = ScriptUI.newFont (Obj.graphics.font.name, "Bold", Obj.graphics.font.size);
                Obj.onDraw = function (Event) {
                    with (Obj) {
                        graphics.drawOSControl ();
                        graphics.newPath ();
                        graphics.moveTo ((size[0] / 340) * 25, (size[1] / 50) * 0);
                        graphics.lineTo ((size[0] / 340) * 17.73, (size[1] / 50) * 1.06);
                        graphics.lineTo ((size[0] / 340) * 11.98, (size[1] / 50) * 3.65);
                        graphics.lineTo ((size[0] / 340) * 7.32, (size[1] / 50) * 7.32);
                        graphics.lineTo ((size[0] / 340) * 3.65, (size[1] / 50) * 11.98);
                        graphics.lineTo ((size[0] / 340) * 1.06, (size[1] / 50) * 17.73);
                        graphics.lineTo ((size[0] / 340) * 0, (size[1] / 50) * 25);
                        graphics.lineTo ((size[0] / 340) * 1.06, (size[1] / 50) * 32.26);
                        graphics.lineTo ((size[0] / 340) * 3.65, (size[1] / 50) * 38.02);
                        graphics.lineTo ((size[0] / 340) * 7.32, (size[1] / 50) * 42.68);
                        graphics.lineTo ((size[0] / 340) * 11.98, (size[1] / 50) * 46.35);
                        graphics.lineTo ((size[0] / 340) * 17.73, (size[1] / 50) * 48.93);
                        graphics.lineTo ((size[0] / 340) * 25, (size[1] / 50) * 50);
                        graphics.lineTo ((size[0] / 340) * 315, (size[1] / 50) * 50);
                        graphics.lineTo ((size[0] / 340) * 322.25, (size[1] / 50) * 48.93);
                        graphics.lineTo ((size[0] / 340) * 328, (size[1] / 50) * 46.35);
                        graphics.lineTo ((size[0] / 340) * 332.66, (size[1] / 50) * 42.68);
                        graphics.lineTo ((size[0] / 340) * 336.34, (size[1] / 50) * 38.02);
                        graphics.lineTo ((size[0] / 340) * 338.92, (size[1] / 50) * 32.26);
                        graphics.lineTo ((size[0] / 340) * 340, (size[1] / 50) * 25);
                        graphics.lineTo ((size[0] / 340) * 338.92, (size[1] / 50) * 17.73);
                        graphics.lineTo ((size[0] / 340) * 336.34, (size[1] / 50) * 11.98);
                        graphics.lineTo ((size[0] / 340) * 332.66, (size[1] / 50) * 7.32);
                        graphics.lineTo ((size[0] / 340) * 328, (size[1] / 50) * 3.65);
                        graphics.lineTo ((size[0] / 340) * 322.25, (size[1] / 50) * 1.06);
                        graphics.lineTo ((size[0] / 340) * 315, (size[1] / 50) * 0);
                        graphics.lineTo ((size[0] / 340) * 25, (size[1] / 50) * 0);
                        graphics.closePath ();
                        graphics.fillPath (graphics.newBrush (graphics.BrushType.SOLID_COLOR, [1, 0, 0]));
                        graphics.closePath ();
                        if (text) {
                            graphics.drawString (text, (graphics.newPen (graphics.PenType.SOLID_COLOR, [1, 1, 1], 1)), (size[0] - graphics.measureString (text, graphics.font, size[0])[0]) / 2, (size[1] - graphics.measureString (text, graphics.font, size[1])[1]) / 2, graphics.font);
                            }
                        if (Event.mouseOver) {
                            graphics.fillPath (graphics.newBrush (graphics.BrushType.SOLID_COLOR, [1, 1, 1]));
                            if (text) {
                                graphics.drawString (text, (graphics.newPen (graphics.PenType.SOLID_COLOR, [1, 0, 0], 1)), (size[0] - graphics.measureString (text, graphics.font, size[0])[0]) / 2, (size[1] - graphics.measureString (text, graphics.font, size[1])[1]) / 2, graphics.font);
                                }
                            }
                        }
                    }
                }
            }
        }

However I have seen on this site that it is possible to draw the various shapes with a geometric formulas.
Does anyone know how the half circles on the sides of the button could be drawn with "geometric calculations"?


UPDATE

After messing with the stib’s code and the linked site’s one, I came up with this final script:

    ButtonPanel ();
    function ButtonPanel () {
        var Panel = new Window ("dialog");
        Panel.text = "Panel";
        var Button = Panel.add ("button");
        Button.text = "Exit";
        Button.preferredSize.width = 170;
        Button.onClick = function () {
                Panel.close ();
            }
        Draw (Button);
        Panel.show ();
        function Draw (Obj) {
            if (Obj.type == "button") {
                Obj.graphics.foregroundColor = Obj.graphics.newPen (Obj.graphics.PenType.SOLID_COLOR, [1, 1, 1], 1);
                Obj.graphics.font = ScriptUI.newFont (Obj.graphics.font.name, "Bold", Obj.graphics.font.size);
                Obj.onDraw = function (Event) {
                    with (Obj) {
                        graphics.drawOSControl ();
                        graphics.newPath ();
                        graphics.moveTo (12.5, 0);
                        for (var i = 0; i < Math.PI; i += Math.PI / 100) {
                            graphics.lineTo ((-12.5 * Math.sin (i)) + 12.5, (-12.5 * Math.cos (i)) + 12.5);
                            }
                            graphics.lineTo (157.5, 25);
                        for (var i = 0; i < Math.PI; i += Math.PI / 100) {
                            graphics.lineTo ((12.5 * Math.sin (i)) + 157.5, (12.5 * Math.cos (i)) + 12.5);
                            }
                        graphics.lineTo (12.5, 0);
                        graphics.closePath ();
                        graphics.fillPath (graphics.newBrush (graphics.BrushType.SOLID_COLOR, [1, 0, 0]));
                        if (text) {
                            graphics.drawString (text, (graphics.newPen (graphics.PenType.SOLID_COLOR, [1, 1, 1], 1)), (size[0] - graphics.measureString (text, graphics.font, size[0])[0]) / 2, (size[1] - graphics.measureString (text, graphics.font, size[1])[1]) / 2, graphics.font);
                            }
                        if (Event.mouseOver) {
                            graphics.fillPath (graphics.newBrush (graphics.BrushType.SOLID_COLOR, [1, 1, 1]));
                            if (text) {
                                graphics.drawString (text, (graphics.newPen (graphics.PenType.SOLID_COLOR, [1, 0, 0], 1)), (size[0] - graphics.measureString (text, graphics.font, size[0])[0]) / 2, (size[1] - graphics.measureString (text, graphics.font, size[1])[1]) / 2, graphics.font);
                                }
                            }
                        }
                    }
                }
            }
        }

2

Answers


  1. Oof. You know that loops are a thing right?

    The site you link to is just using straight lines but is generating each segment using the formula for the various curves. The formula for a point on the circumference of a circle given the angle θ from the x axis to the point, and the radius r is [ cos(θ), sin(θ) ] * r. You can decide how many segments you want in the half circle and make a loop to call that formula that many times.

        function halfCircle(
            radius, //radius of the half circle
            segStart, //coordinates of the start of the segment
            angleStart, // angle of the start of the segment from the positive x axis
            numSegments //how many segments to draw
        ){
    
            var circle = {
                x: function(i, r){ return Math.cos(i) * r},
                y: function(i, r){ return Math.cos(i) * r}
            }
    
            var g = this.graphics;
            g.newPath();
            g.moveTo(segStart);
    
            var increment = Math.pi / numSegments; //Pi in radians is 180°
            var offset = angleStart * Math.pi / 180;
            for (var i = 0; i < numSegments; i++){
                g.lineTo(
                    circle.x(i * increment + offset, radius) + segStart, 
                    circle.y(i * increment + offset, radius) + segStart
                );
            }
        }
    
        halfCircle(340, [123,456], 123, 45);
    
    Login or Signup to reply.
  2. If you look at the values of size[0] which is 170 and size[1], which is 25 you can rewrite the semi circle code with the exact values:

    graphics.lineTo ((size[0] / 340) * 17.73, (size[1] / 50) * 1.06);
    graphics.lineTo ((size[0] / 340) * 11.98, (size[1] / 50) * 3.65);
    graphics.lineTo ((size[0] / 340) * 7.32, (size[1] / 50) * 7.32);
    graphics.lineTo ((size[0] / 340) * 3.65, (size[1] / 50) * 11.98);
    graphics.lineTo ((size[0] / 340) * 1.06, (size[1] / 50) * 17.73);
    graphics.lineTo ((size[0] / 340) * 0, (size[1] / 50) * 25);
    graphics.lineTo ((size[0] / 340) * 1.06, (size[1] / 50) * 32.26);
    graphics.lineTo ((size[0] / 340) * 3.65, (size[1] / 50) * 38.02);
    graphics.lineTo ((size[0] / 340) * 7.32, (size[1] / 50) * 42.68);
    graphics.lineTo ((size[0] / 340) * 11.98, (size[1] / 50) * 46.35);
    graphics.lineTo ((size[0] / 340) * 17.73, (size[1] / 50) * 48.93);
    

    or simply

    graphics.lineTo (8.865, 0.53);
    graphics.lineTo (5.99, 1.825);
    graphics.lineTo (3.66, 3.66);
    graphics.lineTo (1.825, 5.99);
    graphics.lineTo (0.53, 8.865);
    graphics.lineTo (0, 12.5);
    graphics.lineTo (0.53, 8.865);
    graphics.lineTo (1.825, 5.99);
    graphics.lineTo (3.66, 3.66);
    graphics.lineTo (5.99, 1.825);
    graphics.lineTo (8.865, 0.53);
    

    So it’s now simply a matter of substituting the x an y values with [ cos(θ), sin(θ) ] * r as stib has shown you in his much better (and quicker) answer.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search