pdlua graphics
===

pdlua's graphics allow you to draw basic vector graphics and receive mouse events on pure-data and plugdata. Drawing functions are prefixed with 'gfx.', and should only be called from within the "paint" function.

NOTE: The "paint" method (see below) is required by all pdlua objects which want to utilize the graphics interface. Defining it automatically puts the object into graphics mode in which all graphics routines work as described below.


Painting:
--------------
You can paint by defining the "paint" function, for example:

function yourclass:paint(g)
    g:set_color(250, 200, 240)
    g:fill_all()
end


Mouse Events:
--------------
You can receive mouse events by defining the "mouse_down", "mouse_up", "mouse_move" and "mouse_drag" functions. Both pass the x,y coordinates as arguments. For example:

function yourclass:mouse_down(x, y)
    pd.post(tostring(x))
    pd.post(tostring(y))
end


API overview
--------------

-- Callback functions you can define
pd:Class:mouse_down(x, y)                                      -- Mouse down callback, called when the mouse is clicked
pd:Class:mouse_up(x, y)                                        -- Mouse up callback, called when the mouse button is released
pd:Class:mouse_move(x, y)                                      -- Mouse move callback, called when the mouse is moved while not being down
pd:Class:mouse_drag(x, y)                                      -- Mouse drag callback, called when the mouse is moved while also being down


-- Functions you can call
pd:Class:repaint(layer)                                        -- Request a repaint for specified layer (or all layers if no parameter is set
                                                                  or if layer is 0). after this, the "paint" or "paint_layer_n" callback will occur

pd:Class:paint(g) / pd:Class:paint_layer_n(g)                  -- Paint callback, passes a graphics context object (commonly called g) for main
                                                                  layer or layer n (n > 1) that you can call these drawing functions on:

g:set_size(w, h)                                               -- Sets the size of the object
width, height = g:get_size(w, h)                               -- Gets the size of the object

g:set_color(r, g, b, a=1.0)                                    -- Sets the color for the next drawing operation

g:fill_ellipse(x, y, w, h)                                     -- Draws a filled ellipse at the specified position and size
g:stroke_ellipse(x, y, w, h, line_width)                       -- Draws the outline of an ellipse at the specified position and size

g:fill_rect(x, y, w, h)                                        -- Draws a filled rectangle at the specified position and size
g:stroke_rect(x, y, w, h, line_width)                          -- Draws the outline of a rectangle at the specified position and size

g:fill_rounded_rect(x, y, w, h, corner_radius)                 -- Draws a filled rounded rectangle at the specified position and size
g:stroke_rounded_rect(x, y, w, h, corner_radius, line_width)   -- Draws the outline of a rounded rectangle at the specified position and size

g:draw_line(x1, y1, x2, y2)                                    -- Draws a line between two points
g:draw_text(text, x, y, w, fontsize)                           -- Draws text at the specified position and size

g:fill_all()                                                   -- Fills the entire drawing area with the current color. Also will draw
                                                                  an object outline in the style of the host (ie. pure-data or plugdata)

g:translate(tx, ty)                                            -- Translates the coordinate system by the specified amounts
g:scale(sx, sy)                                                -- Scales the coordinate system by the specified factors. This will always happen after the translation
g:reset_transform()                                            -- Resets current scale and translation

p = Path(x, y)                                                 -- Initiates a new path at the specified point
p:line_to(x, y)                                                -- Adds a line segment to the path
p:quad_to(x1, y1, x2, y2)                                      -- Adds a quadratic Bezier curve to the path
p:cubic_to(x1, y1, x2, y2, x3, y)                              -- Adds a cubic Bezier curve to the path
p:close_path()                                                 -- Closes the path

g:stroke_path(p, line_width)                                   -- Draws the outline of the path with the specified line width
g:fill_path(p)                                                 -- Fills the current path


-- Audio callbacks
pd:Class:dsp(samplerate, blocksize, channel_counts)            -- Called when DSP is activated and whenever the DSP graph is updated
pd:Class:perform(in1, in2, ..., in_n)                          -- Called for every audio block, passing tables of samples per inlet and
                                                                  expecting tables of samples per outlet
pd:Class:signal_setmultiout(outlet_index, channel_count)       -- Used in dsp function to achieve multichannel output for specific outlets


-- Additional functions
expandedsymbol = pd:Class:canvas_realizedollar(s)              -- Expand dollar symbols in patch canvas context
pd:Class:set_args(args)                                        -- Set the object arguments to be saved in the patch file
args = pd:Class:get_args()                                     -- Get the object arguments


Basic example
---------------------

-- Create an object named "example"
local example = pd.Class:new():register("example")

function example:initialize(sel, atoms)
    self.inlets = 1
    self.circle_x = 10
    self.circle_y = 10

    return true
end

-- Receive mouse drag events
function example:mouse_drag(x, y)
    -- Set circle position
    self.circle_x = x - 15
    self.circle_y = y - 15

    -- Request a repaint
    self:repaint()
end

function example:paint(g)
    -- Fill background with color
    g:set_color(255, 0, 0, 1)
    g:fill_all()

    -- Draw an ellipse
    g:set_color(0, 255, 0, 1)
    g:fill_ellipse(self.circle_x, self.circle_y, 30, 30)
end
