Introduction
The overlay commands
Alpha blending
Using clips
Affine transformations
Cell view
The oplus package
Introduction
The overlay is a rectangular region of pixels that can be displayed
above the current layer. Lua scripts have total control of what the
overlay looks like and how the user interacts with it.
The Scripts/Lua folder supplied with Golly has a number of scripts
that illustrate how the overlay can be used:
- 3D.lua lets people explore
three-dimensional cellular automata.
- breakout.lua shows how to use
the overlay functions to create a working game.
- browse-patterns.lua browses
through patterns in a folder manually or automatically.
- hexgrid.lua creates a true
hexagonal grid for rules that use a hexagonal neighborhood.
- overlay-demo.lua demonstrates
how to use most of the overlay functions.
- pop-plot.lua displays a plot of
population versus time that can be saved as a PNG file.
To study how these scripts work, control-click or right-click on one of the
above links to open the script in your preferred text editor, then run the
script by clicking on the same link.
The overlay commands
The overlay is manipulated using two script commands called
overlay and ovtable.
The first, overlay, takes a single string parameter
that contains an overlay command followed by zero or more arguments separated by spaces.
Some overlay commands can also return a single string as their result.
The second, ovtable, takes a single table parameter
rather than a string and only supports a subset
of the overlay commands. It is typically faster to use ovtable than overlay.
The supported ovtable commands that return a result are get,
which returns individual values, and rgba, which returns
a table.
In all other ways ovtable is identical to the overlay command.
Here is an alphabetical list of all the valid overlay commands:
Here is an alphabetical list of the subset of overlay commands
supported by ovtable:
All of the drawing commands use the current render target.
This is initially the overlay but can be changed to a
clip with the target command.
The examples given below assume a script has started with these lines:
local g = golly()
local ov = g.overlay
local ovt = g.ovtable
blend i
Set alpha blending off (i = 0), full
(i = 1) or fast (i = 2) and return the previous blend state as a string ("0", "1" or "2").
The fast mode should only be used when the target pixels are opaque.
The commands affected by alpha blending are:
ellipse,
fill,
flood,
line,
lines,
load,
paste,
scale and
set.
Note that setting alpha blending to full or fast also forces ellipses and lines to be antialiased.
Example: local oldblend = ov("blend 1")
camera setting value(s)
Change a camera setting for the current cell view.
The valid camera settings and their allowed values are:
angle d | | –
set camera angle to d degrees where d is from 0.0 to 360.0 |
xy x y | | –
set camera pan position to x,y |
zoom z | | –
set camera zoom to z where z is from 0.0625 (-16x) to 32.0 |
Example: ov("camera angle 90")
Example: ov("camera xy -32 100")
Example: ov("camera zoom 3.5")
The cellview command initializes the
camera angle to 0 degrees, the x,y position to the centre of the view,
and the zoom value to 1.
celloption option value
Set a display option for the current cell view.
The valid options and their allowed values are:
depth d | | –
set layer depth to d where d is from 0.0 to 1.0 |
grid i | | –
set grid lines display on (i = 1) or off (i = 0) |
gridmajor g | | –
set grid lines major interval to g where g is an integer from 0 to 16 |
hex i | | –
set hex display on (i = 1) or off (i = 0) |
layers n | | –
set number of layers to n where n is an integer from 1 to 10 |
stars i | | –
set stars display on (i = 1) or off (i = 0) |
Example: ov("celloption depth 0.2")
Example: ov("celloption layers 6")
Example: ov("celloption hex 1")
Example: ov("celloption grid 1")
Example: ov("celloption gridmajor 8")
Example: ov("celloption stars 1")
The cellview command initializes the
depth to 0.05, the number of layers to 1, hex display to 0, grid to 0, gridmajor to 10 and stars to 0.
cellview x y wd ht
Create a cell view enclosed by the given rectangle
that can be drawn on the overlay.
The width and height must be from 16 to 4096 and a multiple of 16.
Example: ov("cellview -1024 -1024 2048 2048")
copy x y wd ht clipname
Copy the pixels in the given rectangle from the current render target into the named
clip for later use in a command like paste
or scale.
If the given width or height is less than 1 then it is treated as an inset from
the render target's current width or height (this makes it easy to copy the entire
render target with a command like "copy 0 0 0 0 all").
Any parts of the rectangle outside the render target are filled with transparent pixels.
The clip name can contain any characters except a space.
Example: ov("copy 0 0 100 200 tempbox")
create wd ht (clipname)
Create the overlay or if a clip name is specified create a new clip with the given
width and height. All pixels are initially transparent (their RGBA values are set to 0,0,0,0).
When creating the overlay the following are also set:
The initial RGBA values used by later drawing commands are set to 255,255,255,255 (opaque white).
The overlay's initial position is set to topleft,
the cursor is set to the standard arrow,
the transform values are set to 1,0,0,1 (identity) and alpha blending is off.
The initial font for drawing text is the default system font at a size of 10pt
(see the font command).
The text options are set to left alignment
(for multi-line text) and a transparent background.
The initial line width (used by the ellipse,
line and lines commands) is set to 1.
The render target is set to be the overlay.
Example: ov("create 400 300")
Example: ov("create 400 300 myclip")
Note that the when creating the overlay this command automatically ticks the
Show Overlay option to ensure the
overlay will be displayed when the viewport is updated (by calling g.update()
or the update command).
cursor name
Specify which cursor to use when the mouse moves over a
non-transparent pixel within the overlay. The valid cursor names are:
arrow | | – standard arrow |
cross | | – crosshairs |
current | | – Golly's current cursor (no change) |
hand | | – hand |
hidden | | – invisible cursor |
pencil | | – pencil |
pick | | – color picker |
wait | | – a lengthy task is in progress |
zoomin | | – magnifying glass with "+" |
zoomout | | – magnifying glass with "-" |
The previous cursor name is returned.
Example: local oldcursor = ov("cursor pencil")
delete (clipname)
Delete the overlay or if a clip name is specified delete the named clip.
When deleting the overlay this is equivalent to selecting
Delete Overlay from the Layer menu.
Note that it is an error to delete a clip that is the current render target.
Example: ov("delete")
Example: ov("delete myclip")
drawcells
Draw the cells from the current cell view onto the render target.
The cells will be drawn using the camera settings and colored using the current theme.
Further drawing commands can then be used to draw on top of the cell display. Pixels outside of the
current cell view are drawn in the current grid border color.
Example: ov("drawcells")
ellipse x y wd ht
Draw an ellipse inside the given rectangle using the current rgba values onto
the render target.
Any parts of the ellipse outside the render target are automatically clipped.
A width or height less than 1 is relative to the render target's width or height.
If the width equals the height (and both are positive) then the result is a circle.
If alpha blending is turned on then the edges of the ellipse are antialiased.
The lineoption width command determines the thickness
of the ellipse.
Example: ov("ellipse 10 10 60 40")
fill x y wd ht (...x y wd ht)
Fill the given rectangles in the render target with the current rgba values.
Any parts of the rectangles outside the render target are automatically clipped.
If no rectangle is given then the entire render target is filled.
A width or height less than 1 is relative to the render target's width or height,
so a command like ov("fill 1 1 -2 -2") would fill all of the render target
except for a 1 pixel border around the edges.
Example: ov("fill 10 10 30 50")
or
Example: ovt{"fill", 10, 10, 30, 50}
flood x y
Flood a connected region of pixels in the render target that match the given starting pixel
with the current rgba values.
Example: ov("flood 10 20")
font fontsize fontname
Set the font used by later text commands.
If the font name is not supplied then only the font size will be changed.
The valid font names are:
default | | – standard system font |
default-bold | | – bold system font |
default-italic | | – italic system font |
mono | | – mono-spaced font |
mono-bold | | – bold mono-spaced font |
mono-italic | | – italic mono-spaced font |
roman | | – roman font |
roman-bold | | – bold roman font |
roman-italic | | – italic roman font |
The previous font is returned as a string of the form "fontsize fontname".
Example: local oldfont = ov("font 15 roman-bold")
get x y
Return the RGBA values of the given pixel in the render target.
All values will be from 0 to 255.
For the string version the values are returned as a string of the form "red green blue alpha".
If the given pixel is outside the render target then "" is returned.
Example: local RGBA = ov("get 10 20")
For the table version the values are returned individually.
If the given pixel is outside the render target then -1 is returned for each component.
Example: local R, G, B, A = ovt{"get", 10, 20}
line x1 y1 x2 y2 (...xn yn)
Draw one or more connected lines of pixels between the supplied coordinates x1 y1 to xn yn
on the render target using the current rgba values.
Any pixels outside the render target edges are automatically clipped.
If alpha blending is turned on then the lines are antialiased.
The lineoption width command determines
the thickness of the lines.
Examples:
-- draw line from (10, 20) to (50, 60)
ov("line 10 20 50 60")
or
ovt{"line", 10, 20, 50, 60}
-- draw triangle with vertices at (0, 0), (100, 0) and (50, 100)
ov("line 0 0 100 0 50 100 0 0")
or
ovt{"line", 0, 0, 100, 0, 50, 100, 0, 0}
lines x1 y1 x2 y2 (...xn1 yn1 xn2 yn2)
Draw one or more separate lines of pixels between the supplied pairs of coordinates x1 y1 to x2 y2
on the render target using the current rgba values.
Any pixels outside the render target edges are automatically clipped.
If alpha blending is turned on then the lines are antialiased.
The lineoption width command determines
the thickness of the lines.
Examples:
-- draw line from (10, 20) to (50, 60)
ov("lines 10 20 50 60")
or
ovt{"lines", 10, 20, 50, 60}
-- draw line from (0, 0) to (100, 0) and another line from (50, 25) to (150, 25)
ov("lines 0 0 100 0 50 25 150 25")
or
ovt{"lines", 0, 0, 100, 0, 50, 25, 150, 25}
lineoption option value
Set an option used by the ellipse, line and lines commands.
There is currently one valid option:
width w | | –
set the line width to an integer from 1 to 10000.
|
The previous line width is returned as a string.
The create command initializes the line width to 1.
Example: local oldwidth = ov("lineoption width 3") |
load x y file
Load the given BMP/GIF/PNG/TIFF file into the render target at the given location.
Any pixels outside the render target edges are automatically clipped.
Return the total size of the image (including any clipped portions) as a
string of the form "width height". Note that it's sometimes desirable to call
this command twice: the 1st call can specify a location completely outside
the render target just to get the image's width and height; the 2nd call can then
use those values to do things like center the image within the render target.
Example: local wdht = ov("load 99999 99999 foo.png")
optimize clipname
Optimizes the named clip for improved paste performance when
using alpha blending.
Returns the bounding box of non-zero alpha pixels within the clip as a string
of the form "x y width height".
A clip that is modified after optimization must be optimized again before use to get the
performance benefit.
Especially effective for text rendering and used automatically by the
op.maketext function.
Example: local x, y, w, h = gp.split(ov("optimize textclip"))
paste x1 y1 (...xn yn) clipname
Paste the named clip (created by an earlier create, copy
or text command) into the render target at the given location(s).
Any pixels outside the render target edges are automatically clipped.
Examples:
-- paste the tempbox clip at (10, 20)
ov("paste 10 20 tempbox")
or
ovt{"paste", 10, 20, "tempbox"}
-- paste the tempbox clip at (10, 20), (100, 20) and (100, 50)
ov("paste 10 20 100 20 100 50 tempbox")
or
ovt{"paste", 10, 20, 100, 20, 100, 50, "tempbox"}
If multiple locations are given then the clip is drawn at the locations in the order specified.
position pos
Specify where the overlay is to be displayed within the current layer.
The valid positions are:
topleft | | – top left corner |
topright | | – top right corner |
bottomright | | – bottom right corner |
bottomleft | | – bottom left corner |
middle | | – middle of layer |
Example: ov("position middle")
replace red green blue alpha
Replace pixels with color red green blue alpha in the render target with the current
rgba values.
Returns the number of pixels replaced as a string.
Example:
-- replace opaque black pixels with semi-transparent blue pixels in clip named 'myclip'
local oldtarget = ov("target myclip")
ov("rgba 0 0 255 128")
local replaced = ov("replace 0 0 0 255")
ov("target "..oldtarget)
There are two special characters that can be used in the color specification for
more advanced matches: ! and *.
A color component may be specified as the wildcard * which means match any value for
that component.
Example:
-- replace any opaque pixel with opaque blue
ov(op.blue)
local replaced = ov("replace * * * 255")
If the match specification is prefixed with ! then pixels that don't match
the specification are replaced.
Example:
-- replace any pixel that isn't white with yellow
ov(op.yellow)
local replaced = ov("replace !255 255 255 255")
Alternatively if the alpha specification is prefixed with ! then pixels
that don't have the specified alpha value are replaced.
Example:
-- replace any non-opaque pixel with opaque blue
ov(op.blue)
local replaced = ov("replace * * * !255")
Normally when a match is found the clip pixel is replaced with the current
rgba values. This can be overridden by postfixing
one or more color components with r, g, b, a or #.
Each color component in the clip pixel can either be left unchanged
(in the case of #) or replaced with the specified color component from the clip pixel.
Examples:
-- make transparent pixels opaque (r g b 0 -> r g b 255)
ov("rgba 0 0 0 255")
local replaced = ov("replace *# *# *# 0")
-- swap the red and green components (r g b a -> g r b a)
local replaced = ov("replace *g *r *# *#")
-- set the pixels to opaque gray based on the alpha level (r g b a -> a a a 255)
ov("rgba 0 0 0 255")
local replaced = ov("replace *a *a *a *")
If the postfix character is followed by - then the component value is inverted.
Examples:
-- invert the r g b components but leave alpha unchanged (r g b a -> 255-r 255-g 255-b a)
local replaced = ov("replace *#- *#- *#- *#")
-- make transparent pixels opaque and vice versa (r g b a -> r g b 255-a)
local replaced = ov("replace *# *# *# *#-")
Color components can also be adjusted by using -- to decrement, ++ to increment,
-value to subtract a constant or +value to add a constant.
Component values are clamped to the range 0 to 255.
Examples:
-- increase the brightness of all pixels
local replaced = ov("replace *#+50 *#+50 *#+50 *#")
-- fade all pixels to black
while tonumber(ov("replace *#-- *#-- *#-- *#")) > 0 do
ov("update")
end
The postfixes can also be used without a target component. In which case the current
rgba values are adjusted.
Example:
-- replace green pixels with the current drawing color minus 32 alpha (0 255 0 255 -> 255 0 0 96)
ov("rgba 255 0 0 128")
local replaced = ov("replace 0 255 0 255-32")
resize wd ht (clipname)
Resize the overlay or if a clip name is specified resize the named clip.
The previous size is returned as a string of the form "width height".
This command is typically used if a window resize is detected and you
wish to keep the overlay covering all of the current layer.
Note that all pixels in the resized overlay/clip become transparent
(their RGBA values are reset to 0,0,0,0).
Example: local oldsize = ov("resize 1000 800")
Example: local oldsize = ov("resize 300 240 myclip")
rgba red green blue alpha
Set the current RGBA values used by later drawing commands
and return the old values. All values are from 0 to 255.
The commands that use the current RGBA values are:
ellipse,
fill,
flood,
line,
lines,
replace,
set and
text.
For the string version the values are returned as a string of the form "red green blue alpha".
Example: local oldrgba = ov("rgba 255 0 0 255")
For the table version the values are returned as a table of the form {"rgba", red, green, blue, alpha}.
Example: local oldrgba = ovt{"rgba", 255, 0, 0, 255}
save x y wd ht file
Save the pixels in the given rectangle of the render target in the given PNG file.
An error will occur if any part of the rectangle is outside the render target.
If the given width or height is less than 1 then it is treated as an inset from
the render target's current width or height (this makes it easy to save the entire
render target with a command like "save 0 0 0 0 overlay.png").
Example: ov("save 0 0 100 80 "..g.getdir("temp").."foo.png")
scale quality x y wd ht clipname
Paste the named clip into the current render target, scaling it so it fits into the
specified rectangle. Any pixels outside the render target edges are automatically clipped.
The given quality must be one of these strings:
best | | –
use a high quality, but slow, scaling algorithm
|
fast | | –
use a fast, but lower quality, scaling algorithm
|
Example: ov("scale best 10 10 100 200 image")
set x1 y1 (...xn yn)
Set the specified pixels in the render target to the current rgba values.
Pixels outside the render target are silently ignored.
Examples:
-- set pixel at (10, 20)
ov("set 10 20")
or
ovt{"set", 10, 20}
-- set pixels at (10, 20), (15, 25) and (16, 25)
ov("set 10 20 15 25 16 25")
or
ovt{"set", 10, 20, 15, 25, 16, 25}
target (clipname)
Set the render target to the named clip or to the overlay if no
clip is specified. All subsequent drawing commands will use the new render target.
Returns the previous target as a string (an empty string if it was the overlay).
It is an error to attempt to delete a clip while it is the
render target.
The commands that use the render target are:
copy (as the source),
drawcells,
ellipse,
fill,
flood,
get (as the source),
line,
lines,
load,
paste,
replace,
save (as the source),
scale and
set.
Example: local oldtarget = ov("target myclip")
text clipname one or more lines of text ...
Create a named clip containing the given text in the
current font (as set by the most recent font command).
Return the dimensions of the clip as a string of the form "width height descent".
The descent is the number of pixels under the baseline (useful if you want to
place text with different sized fonts on the same line).
The text's color depends on the most recent rgba command.
The text background color can be set with the textoption background
command. By default the text has a transparent background, so you'll probably need to set
blend to 1 before drawing the text with paste.
If you specify an opaque background then there's no need to turn on alpha blending
when doing the paste, so drawing such text will be significantly faster.
You can also specify the alignment of multi-line text with the
textoption align command.
Example: local dimens = ov("text tempclip First line.\nSecond line.")
textoption option value
Set a display option for the text command.
The valid options and their allowed values are:
align alignment | | –
set the alignment of multi-line text to left, right or center
|
background r g b a | | –
set the text background to the given RGBA values (all from 0 to 255)
|
The create command initializes the
text options to left alignment and a transparent background.
Both options return their previous setting as a string:
the returned alignment value will be "left", "right" or "center";
the returned background will be a string of the form "red green blue alpha".
Example: local oldalign = ov("textoption align right") |
Example: local oldbackground = ov("textoption background 255 0 0 255") |
theme r1 g1 b1 r2 g2 b2 r3 g3 b3 r4 g4 b4 r5 g5 b5 (alivea, deada, unoccupieda, bordera)
Define the color theme for drawing the current cell view.
Themes allow better visualization of patterns because they highlight history
and longevity of cells. The arguments define 5 colors:
r1 g1 b1 | | born | cell just born |
r2 g2 b2 | | alive | cell alive for at least 63 generations |
r3 g3 b3 | | died | cell just died |
r4 g4 b4 | | dead | cell dead for at least 63 generations |
r5 g5 b5 | | unoccupied | cell never occupied |
Example: ov("theme 0 255 255 255 255 255 0 0 255 0 0 47 0 0 0")
New cells are drawn in the born color (cyan 0 255 255).
If they stay alive they fade from the born color to the alive color
(white 255 255 255) over the next 63 generations. If the cell stays alive after that it remains
in the alive color. This provides a visual representation of cell longevity.
Cells are drawn in the died color (blue 0 0 255) when then they die.
If they stay dead they fade from the died color to the dead color
(dark blue 0 0 47) over the next 63 generations. If the cell stays dead after that it
remains in the dead color. This provides a visual representation of cell history.
Cells that have never been occupied are drawn in the unoccupied color (black 0 0 0).
Optionally you can specify the alpha values for the different cell types:
alivea | born to alive |
deada | died to dead |
unoccupieda | unoccupied |
bordera | border |
The border color RGB components are read from the View Preference
grid border color. If you don't want a border drawn around the cell view
then set bordera to 0 (transparent).
If you omit alpha values then they all default to 255 (opaque).
If no theme is specified then Golly's default colors for the pattern are used. If you want to switch
off the theme then use the command ov("theme -1").
There is a set of predefined themes in the oplus package using
which the example above would become: ov(op.theme1) or ov(op.themes[1]).
transform axx axy ayx ayy
Set the affine transformation values used by later
paste commands and return the old values as a string
of the form "axx axy ayx ayy".
Example: local oldt = ov("transform 0 -1 1 0")
update
Tell Golly to update the overlay without drawing the underlying layer.
This will be faster than calling g.update() but should only be used
in cases where the overlay covers the entire layer and all
pixels in the overlay are opaque.
Example: ov("update")
updatecells
Update the current cell view using the cells in
the current universe.
This command should typically be used every time the universe changes.
Example: ov("updatecells")
xy
Return the current mouse position within the overlay as a string
of the form "x y", or "" if the mouse is outside the overlay.
The x and y values are pixel coordinates.
The top left pixel in the overlay is "0 0"; x values increase
to the right and y values increase downwards.
Example: local mousepos = ov("xy")
Alpha blending
Alpha blending is a way of drawing translucent pixels on top of existing
pixels to get nicer looking results. When an overlay is created, alpha blending
is initially turned off. To turn it on a script needs to call "blend 1", for blending
with any target, or "blend 2", for faster blending when you know the target
pixels are opaque.
Consider this simple script which draws a translucent blue square on top
of a translucent red square (both on top of an opaque white background):
local g = golly()
local ov = g.overlay
ov("create 100 80")
ov("fill")
ov("blend 1")
ov("rgba 255 0 0 128")
ov("fill 10 10 50 50")
ov("rgba 0 0 255 128")
ov("fill 30 20 50 50")
|
|
|
blend 1 |
|
|
|
blend 0 |
|
The left image shows the resulting overlay. The right image shows
the overlay produced by the same script but with the "blend 1" line removed
(the grid lines are from the layer underneath the overlay).
Note that drawing with alpha blending on is significantly slower than drawing
with it off, so it's a good idea to only turn it on when necessary.
The overlay commands that can do alpha blending are:
ellipse,
fill,
flood,
line,
lines,
load,
paste,
scale,
set.
Using clips
Overlay scripts can use multiple "clipboards" called clips.
A clip is simply a chunk of memory containing a rectangular area of pixels.
Each clip has a unique name consisting of any characters except a space.
Clips can be created using three commands:
create, copy and text.
Clips can be the render target for any of the drawing commands.
The following script illustrates the use of clips. It creates a tiled
background pattern on which some translucent text is drawn.
The image on the right shows the resulting overlay.
local g = golly()
local ov = g.overlay
ov("create 199 177")
ov("rgba 255 255 0 255")
ov("fill")
-- create the tile
ov("rgba 0 0 0 255")
ov("line 10 0 0 20")
ov("line 10 0 20 20")
ov("line 0 20 20 20")
ov("rgba 200 200 255 255")
ov("flood 10 10")
ov("copy 0 0 21 21 mytile")
-- tile the overlay
for y = 0, 177, 21 do
for x = 0, 199, 21 do
ov("paste "..x.." "..y.." mytile")
end
end
-- create some translucent red text
ov("rgba 255 0 0 180")
ov("font 60 roman-bold")
ov("text mytext Golly")
ov("blend 1")
ov("paste 10 10 mytext")
|
|
|
Affine transformations
The transform command allows a limited set of
affine transformations, namely rotation by multiples of 90 degrees and
reflection about the x, y or diagonal axes. The following script shows
how text can be rotated or reflected. Instead of using explicit
transform commands it uses mnemonic synonyms
defined in the oplus package. The image on the right shows
the resulting overlay.
local g = golly()
local ov = g.overlay
local op = require "oplus"
ov("create 200 380")
ov("fill")
ov("blend 1")
ov("font 12 default-bold")
-- do rotations
ov("rgba 0 0 255 255")
ov("text temp ROTATE")
ov("set 100 100")
ov("paste 100 100 temp")
ov(op.rcw)
ov("paste 100 100 temp")
ov(op.racw)
ov("paste 100 100 temp")
ov(op.r180)
ov("paste 100 100 temp")
-- do reflections
ov("rgba 255 0 0 255")
ov(op.identity)
ov("text temp - REFLECT")
ov("set 100 270")
ov("paste 100 270 temp")
ov(op.flip_x)
ov("paste 100 270 temp")
ov(op.flip_y)
ov("paste 100 270 temp")
ov(op.swap_xy)
ov("paste 100 270 temp")
ov(op.swap_xy_flip)
ov("paste 100 270 temp")
|
|
|
Cell view
A cell view is a flexible way of displaying cells from the universe onto the overlay.
A number of steps are required:
-
Use the cellview command to specify the rectangle of cells
from the universe that you want to display.
-
Either use the current pattern colors or pick a theme with the
theme command.
-
Use the camera and celloption
commands to determine how you want to project the cells onto the overlay.
-
Whenever cells change in the universe you should use the
updatecells command to refresh the cell view.
-
To draw the cells onto the overlay use the drawcells command.
If the cells don't change and you want to change the camera or theme then just
use drawcells after the appropriate camera and theme commands.
Here is a simple example:
-- create an overlay the size of the current layer
local g = golly()
local ov = g.overlay
local viewwd, viewht = g.getview(g.getlayer())
ov("create "..viewwd.." "..viewht)
-- open example pattern
g.open(g.getdir("app").."Patterns/Life/Methuselahs/rabbits.lif")
-- create a cell view using a theme
ov("cellview -256 -256 512 512")
ov("theme 0 255 255 255 255 255 0 0 255 0 0 47 0 0 0")
-- set camera 14.5x zoom and 30 degree rotation
ov("camera zoom 14.5")
ov("camera angle 30")
ov("drawcells")
ov("update")
-- run for 1000 generations
for i = 1, 1000 do
g.run(1)
ov("updatecells")
ov("drawcells")
ov("update")
end
-- delete the overlay
ov("delete")
|
To see the above script in action, select and copy the lines to the
clipboard, then select Run Clipboard from the File menu.
The oplus package
The oplus package provides a high-level interface to the overlay commands
which implement
graphics,
text,
user interface and
utility
functions.
The package consists of a set of .lua files stored in the Scripts/Lua/oplus
directory. The following functions are available after a script calls
local op = require "oplus"
(see init.lua for
the implementation details).
Graphics commands
op.draw_line(x1, y1, x2, y2)
Draw a line from x1,y1 to x2,y2.
Example: op.draw_line(0, 0, 10, 10)
op.fill_ellipse(x, y, w, h, borderwd, fillrgba)
Draw an ellipse (or circle) inside the given rectangle.
If borderwd is greater than zero then an antialiased ellipse of the given thickness
is drawn using the current color.
If fillrgba is not an empty string then the ellipse is filled with the given color.
Example: op.fill_ellipse(200, 450, 140, 99, 2, "rgba 255 255 0 200")
op.fill_rect(x, y, wd, ht)
Draw a filled rectangle with its top left corner at x,y and of the given width and height.
Example: op.fill_rect(0, 0, 40, 30)
op.round_rect(x, y, w, h, radius, borderwd, fillrgba)
Draw a rounded rectangle where the given radius determines the curvature of each corner.
If borderwd is greater than zero then an antialiased border of the given thickness
is drawn using the current color.
If fillrgba is not an empty string then the rectangle is filled with the given color.
Example: op.round_rect(200, 300, 60, 30, 15, 0, "rgba 255 0 0 128")
Text commands
op.minbox(clipname, wd, ht)
Find the minimal bounding box of non-transparent pixels in the given clip.
This can be used to determine the real dimensions of some text.
If all pixels in the clip are transparent then the returned values are all zero.
Example: local minx, miny, minwd, minht = op.minbox("textclip", 80, 10)
op.maketext(text, clipname, color, shadowx, shadowy, shadowcolor)
A simpler and more powerful way of creating text that can then be drawn with pastetext.
Only the first argument, text, is required.
Example:
-- draw the string "Hello World" at 0, 0 on the current render target
op.maketext("Hello World")
op.pastetext(0, 0)
Usually the text clip is created using the current rgba values. This can be
overridden by specifying the color argument.
The text may also be given a shadow at a specific x, y pixel offset defined with the shadowx
and shadowy arguments. The shadow will be drawn in opaque black unless a different color is
specified with the shadowcol argument.
Example:
-- create a clip named "hello" with the text "Hello World" in blue with a yellow shadow offset by -1, -2 pixels.
local w, h = op.maketext("Hello World", "hello", op.blue, -1, -2, op.yellow)
The function returns the width and height of the created clip (including any shadow).
op.pastetext(x, y, transform, clipname)
Paste text onto the current render target. Only the first two arguments x, y are required. Returns the clip name.
Example:
-- paste a text clip at 0, 0 on the current render target
local textclip = op.pastetext(0, 0)
The transform argument can be used to specify an affine transformation. The clipname may
be used to specify a non-default clipname.
Example:
-- paste the clip named "hello" at 0, 0 and rotated clockwise on the current render target
op.pastetext(0, 0, op.rcw, "hello")
User interface commands
op.button(label, onclick)
Create and return a table representing a button.
The button width depends on the given label text.
If the op.process function detects a click in this
button then the given onclick function will be called.
Example: cancel_button = op.button("Cancel", g.exit)
The button will only appear after its show function is called.
Example: cancel_button.show(10, 10)
op.checkbox(label, labelrgba, onclick)
Create and return a table representing a check box.
The label text will be drawn using the given color to the right of a tickable button.
If the op.process function detects a click in this
check box (including the label) then the given onclick function will be called.
Example: line_box = op.checkbox("Show lines", op.black, toggle_lines)
The check box will only appear after its show function is called.
Example: line_box.show(10, 40, true)
op.radiobutton(label, labelrgba, onclick)
Create and return a table representing a radio button.
The label text will be drawn using the given color to the right of a radio button.
If the op.process function detects a click in this
radio button (including the label) then the given onclick function will be called.
Example:
draw_option = op.radiobutton("Draw", op.black, set_draw_mode)
select_option = op.radiobutton("Select", op.black, set_select_mode)
move_option = op.radiobutton("Move", op.black, set_move_mode)
The radio button will only appear after its show function is called.
Example:
draw_option.show(10, 40, mode == "draw")
select_option.show(10, 40, mode == "select")
move_option.show(10, 40, mode == "move")
op.slider(label, labelrgba, barwidth, minval, maxval, onclick)
Create and return a table representing a slider.
The label text will be drawn using the given color to the left of the slider's
horizontal bar. The bar width must be greater than 0.
The minimum and maximum values of the slider can be any integer values,
as long as minval is less than maxval.
If the op.process function detects a click in this slider,
and the slider value has changed, then the given onclick function will be called.
Example: red_slider = op.slider("Red:", op.black, 64, 0, 255, new_red)
The slider will only appear after its show function is called.
Example: red_slider.show(10, 70, 255)
op.menubar()
Create and return a table representing a menu bar.
You can then use its addmenu function to add menus to the menu bar,
then the additem function to append items to these menus.
If the op.process function detects a click in this menu bar
then it will track the mouse and call the specified callback function if a menu item
is selected.
Example:
mbar = op.menubar()
-- add some menus
mbar.addmenu("File")
mbar.addmenu("Edit")
-- add items to File menu
mbar.additem(1, "New Pattern", NewPattern)
mbar.additem(1, "Open Pattern...", OpenPattern)
mbar.additem(1, "Save Pattern...", SavePattern)
mbar.additem(1, "---", nil) -- separator
mbar.additem(1, "Exit", g.exit)
-- add items to Edit menu
mbar.additem(2, "Undo", Undo)
mbar.additem(2, "Redo", Redo)
The menu bar will appear when its show function is called.
Menu items can be enabled or disabled using the enableitem function,
and ticked or unticked using the tickitem function.
Example:
mbar.enableitem(2, 1, CanUndo())
mbar.enableitem(2, 2, CanRedo())
mbar.show(0, 0, 600, 30)
op.process(event)
Process the given event (normally the string returned by a
getevent command).
If it detects a click in a previously created button, check box or slider then
it will call the appropriate onclick function and return an empty string to
indicate the event was handled, otherwise it returns a copy of the given string
so the caller can process the event.
Example: local event = op.process( g.getevent() )
op.popupmenu()
Create and return a table representing a pop-up menu.
You can then use its additem function to append an item with a given label
and a callback function that will be called if the user selects the item.
Example:
editmenu = op.popupmenu()
editmenu.additem("Cut", CutSelection)
editmenu.additem("Copy", CopySelection)
editmenu.additem("Clear", ClearSelection)
editmenu.additem("---", nil)
editmenu.additem("Paste", PasteClipboard)
The pop-up menu will appear when its show function is called
(note that you need to pass in the overlay's width and height).
Example:
editmenu.setbgcolor("rgba 0 128 0 255") -- dark green background
editmenu.show(mousex, mousey, ovwd, ovht)
Utility commands
op.hexrule()
Return true if the current rule uses a hexagonal neighborhood.
Example: if op.hexrule() then do_hex_stuff() end
The oplus package also defines a number of synonyms for some
frequently used overlay commands.
Opaque colors:
op.white | | = "rgba 255 255 255 255" |
op.gray | | = "rgba 128 128 128 255" |
op.black | | = "rgba 0 0 0 255" |
op.red | | = "rgba 255 0 0 255" |
op.green | | = "rgba 0 255 0 255" |
op.blue | | = "rgba 0 0 255 255" |
op.cyan | | = "rgba 0 255 255 255" |
op.magenta | | = "rgba 255 0 255 255" |
op.yellow | | = "rgba 255 255 0 255" |
Affine transformations:
op.identity | | = "transform 1 0 0 1" |
op.flip | | = "transform -1 0 0 -1" |
op.flip_x | | = "transform -1 0 0 1" |
op.flip_y | | = "transform 1 0 0 -1" |
op.swap_xy | | = "transform 0 1 1 0" |
op.swap_xy_flip | | = "transform 0 -1 -1 0" |
op.rcw | | = "transform 0 -1 1 0" |
op.rccw | | = "transform 0 1 -1 0" |
op.racw | | = op.rccw |
op.r180 | | = op.flip |
Themes:
op.theme0 | | = "theme 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0" |
op.theme1 | | = "theme 0 255 255 255 255 255 0 0 255 0 0 47 0 0 0" |
op.theme2 | | = "theme 255 144 0 255 255 0 160 0 0 32 0 0 0 0 0" |
op.theme3 | | = "theme 0 255 255 255 255 255 0 128 0 0 24 0 0 0 0" |
op.theme4 | | = "theme 255 255 0 255 255 255 128 0 128 0 47 0 0 32 128" |
op.theme5 | | = "theme 176 176 176 255 255 255 104 104 104 16 16 16 0 0 0" |
op.theme6 | | = "theme 0 0 0 0 0 0 255 255 255 255 255 255 255 255 255" |
op.theme7 | | = "theme 0 0 255 0 0 0 0 255 255 240 240 240 255 255 255" |
op.theme8 | | = "theme 240 240 240 240 240 240 240 240 240 240 240 240 0 0 0" |
op.theme9 | | = "theme 240 240 240 240 240 240 160 0 0 160 0 0 0 0 0" |
You can also access the themes via an array: local mytheme = op.themes[2].
For a good example of how to use the oplus package,
see the 3D.lua script.