Changes between Initial Version and Version 1 of UserGuide/Lua


Ignore:
Timestamp:
Oct 8, 2016, 12:35:20 PM (8 years ago)
Author:
pulkomandy
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • UserGuide/Lua

    v1 v1  
     1= Introduction =
     2
     3Grafx2 offers a lot of features, but sometimes you need something really
     4particular, and it's not there. That's why we added the brush factory, it allows you to generate or modify a brush using a lua script.
     5It has been expanded to allow changing the image and palette.
     6So you can extend Grafx2 capabilities with almost no limit!
     7
     8We are looking forward to your scripts, please send us them so we can share them
     9in the next version of GrafX2!
     10
     11= How does it work =
     12
     13Using the brush factory is quite simple : just right click the 'brush effects' button to open it.
     14It's a small window allowing you to select the script you want to run.
     15Once you press the run button, the script is executed and generates something.
     16If it's a brush, you can paste it like any other brush. If it's a picture, you should see it.
     17If you create your own scripts and place them in _<program directory>/scripts_ they will appear in the list. Scripts are reloaded from disk when you run them, so you can edit them in a text editor and test them without leaving Grafx2.
     18
     19= Available scripts =
     20
     21Before you start working on your own script, you may want to have a look at the existing ones. Maybe one of them already does what you need. If you make your own script, you may want to send it to the developpers so other users can enjoy it too. It's possible to go quite far with scripts and do complicated things, from palette manipulation to animating a sprite sheet.
     22
     23See the LuaScript list.
     24
     25= API Reference =
     26
     27Here is a list of things you get in lua. If you think we should add more, let us know !
     28
     29== Conventions ==
     30On this page we use the following conventions :
     31 * x : horizontal position
     32 * y : vertical position
     33 * c : color index
     34 * w : width
     35 * h : height
     36 * r : red
     37 * g : green
     38 * b : blue
     39
     40Note this is just for the examples below. You are free to name your variables the way you want.
     41
     42== Functions ==
     43=== Drawing ===
     44This is as simple as it gets. You can just render some things to the brush or to the current layer.
     45
     46 * {{{putbrushpixel(x, y, c)}}} set the color of pixel at coords (x, y) in the brush to c.
     47
     48 * {{{putpicturepixel(x, y, c)}}} set the color of pixel at coords (x, y) in the picture to c.
     49
     50  * {{{putsparepicturepixel(x, y, c)}}} set the color of pixel at coords (x, y) in the spare picture to c.
     51
     52
     53 * {{{drawline(x1,y1,x2,y2,c)}}} draws a line in the picture.
     54
     55 * {{{drawfilledrect(x1,y1,x2,y2,c)}}} draws a filled rectangle in the picture.
     56
     57 * {{{drawcircle(x1,y1,r,c)}}} draws a circle in the picture. _r_ is radius in pixels.
     58
     59 * {{{drawdisk(x1,y1,r,c)}}} draws a filled circle in the picture. _r_ is radius in pixels.
     60
     61 * {{{clearpicture(c)}}} clears picture with color c.
     62
     63Drawing out of bounds has no effect.
     64
     65=== Reading pixels ===
     66These allows you to read existing data, for example to filter it, do batch color replacing, or any other distorsion you could come up with.
     67
     68 * {{{getbrushpixel(x, y)}}} returns the color of pixel at coords (x, y) in the brush.
     69
     70 * {{{getbrushbackuppixel(x, y)}}} returns the color of pixel at coords (x, y) in the backup brush, before any of your changes.
     71
     72 * {{{getpicturepixel(x, y)}}} returns the color of pixel at coords (x, y) in the picture. If there are several layers visible,this will pick "the color that you see".
     73
     74 * {{{getlayerpixel(x, y)}}} returns the color of pixel at coords (x, y) in the current layer of the picture.
     75
     76 * {{{getbackuppixel(x, y)}}} returns the color of pixel at coords (x, y) in the backup screen, that is, the picture before your script started to run.
     77
     78 * {{{getsparelayerpixel(x, y)}}} returns the color of pixel at coords (x, y) in the current layer of the spare picture.
     79
     80 * {{{getsparepicturepixel(x, y)}}} returns the color of pixel at coords (x, y) in the spare picture. If there are several layers visible, this will pick "the color that you see".
     81
     82
     83Reading out of the brush will return the BackGround color, ie. the one that marks transparent pixels in the brush.
     84
     85Reading out of the picture will return the Transparent color.
     86
     87=== Changing sizes ===
     88Note the resize occurs immediately. If you need the original dimensions, to read from the backup, you should query them before the resize and keep them in Lua variables.
     89
     90 * {{{getbrushsize()}}} returns the brush size (w, h).
     91
     92 * {{{setbrushsize(w, h)}}} sets the brush size. The new brush is initially filled with transparent pixels.
     93
     94 * {{{getpicturesize()}}} returns the picture size (w, h).
     95
     96 * {{{setpicturesize(w, h)}}} sets the picture size. All layers are clipped accordingly. If you have made changes on the picture, you should call finalizepicture() first.
     97
     98 * {{{getsparepicturesize()}}} returns the spare image's size (w, h).
     99
     100 * {{{setsparepicturesize(w, h)}}} sets the spare picture size. All layers are clipped accordingly. If you have made changes on the picture, *you don't need to call finalizepicture()* first, this function does it by itself.
     101
     102
     103=== Palette and colors ===
     104 * {{{getforecolor()}}} returns the Foreground pen color (0-255).
     105
     106 * {{{getbackcolor()}}} returns the Background pen color (0-255).
     107
     108 * {{{gettranscolor()}}} returns the picture's transparent color (0-255) for layers and GIF transparency.
     109
     110 * {{{setforecolor(c)}}} sets the Foreground pen color (0-255).
     111
     112 * {{{setbackcolor(c)}}} sets the Background pen color (0-255).
     113
     114 * {{{setcolor(c,r,g,b)}}} set color index c in palette to (r,g,b)
     115
     116 * {{{getcolor(c)}}} returns the (r, g, b) value of color at index c.
     117
     118 * {{{matchcolor(r,g,b)}}} return the index of the nearest color available in the palette.
     119 * {{{matchcolor2(r,g,b)}}} return the index of the nearest color available in the palette.
     120
     121 * {{{getbackupcolor(c)}}} returns the (r, g, b) value of color at index c, from the original palette (before any changes done by your script).
     122
     123 * {{{getsparecolor(c)}}} returns the (r, g, b) value of color at index c, from the spare's palette.
     124
     125 * {{{getsparetranscolor()}}} returns the spare picture's transparent color (0-255) for layers and GIF transparency.
     126
     127All of r,g,b and c are normally in the range 0 to 255. For c, if you provide a number outside of this range, it will roll over : for example 300 becomes 45 and -2 becomes 254. Color components r,g and b, however, are clipped to the lower or upper limit.
     128
     129You can get infos on the palette for selecting your colors when drawing, or you can create scripts that just build a full palette from 2 or 3 colors.
     130
     131=== Windows ===
     132
     133 * {{{inputbox(window_title,label_1,initial_value_1,min_1,max_1,digits_1,...)}}} Opens a window that asks the user for one or several setting values. The control only accepts values between the min and max that you provide, and you can specify how many decimal places of precision it should have with {{{digits}}}. You can ask for more than one value by adding arguments: label_2, initial_value_2, min_2, max_2, digits_2 etc, with a limit of 9 settings. This function returns one value to tell if the user accepted or cancelled (true or false), and one additional return value by setting. Example:
     134{{{
     135ok, w, h = inputbox("Modify brush size",
     136  "Width",     w, 1,100,0,
     137  "Height",    h, 1,100,0
     138);
     139}}}
     140   * If min and max are 0 and 1, and digits is 0, it will show a checkbox. Ex:
     141{{{
     142ok, xflip, yflip = inputbox("Transformation",
     143  "X-Flip",    0, 0, 1,0,
     144  "Y-Flip",    0, 0, 1,0
     145);
     146}}}
     147   * If min and max are 0 and 1, and digits is negative, it will show a radio button. Radio buttons with the same number of "digits" are grouped together. Ex:
     148{{{
     149ok, a, b ,c, d = inputbox("Your choice",
     150  "A",    1, 0, 1,-1,
     151  "B",    0, 0, 1,-1,
     152  "C",    0, 0, 1,-1,
     153  "D",    0, 0, 1,-1
     154);
     155}}}
     156   * If min and max are 0, the entry is just a label, the user can't input anything on this line.
     157
     158 * {{{selectbox(caption,label_1,callback_1,label_2,callback_2)}}} Opens a window where the user has to click on one of the buttons. You provide the button labels, and Grafx2 executes the associated callback, which must be a function : a pre-defined function (don't type the parentheses after function name) or an anonymous function that you build on the spot. The user can press Esc to cancel. Example:
     159{{{
     160selectbox("Menu",
     161  "Sub-menu 1", sub_menu1_func,
     162  "Sub-menu 2", sub_menu2_func,
     163  "Say hello", function() messagebox("Hello"); end
     164);
     165}}}
     166 * {{{messagebox(message)}}} or {{{messagebox(window_title,message)}}} Displays a multiline message. It performs word-wrapping automatically, but you can also include character \n in message to force some carriage-returns. If you need variables in the message, use Lua's concatenation operator .. (two dots) to assemble the message string.
     167
     168=== Interactivity ===
     169
     170 * {{{wait(t)}}} Forces a delay, in seconds (floating values are accepted, rounded to 0.01s). During this time, mouse can move, and if color cycling is active, you'll see it updated. If you use a delay of zero, the program only updates the mouse position and immediately continues. For safety, you can't request a delay of more than 10 seconds.
     171
     172 * {{{waitbreak(t)}}} Forces a delay, in seconds. Similar to {{{wait()}}}, except that it returns early with a value of 1 if the user presses ESC, otherwise 0 when the wait is over. {{{waitbreak(0)}}} is very useful, it will only update mouse position (and color cycling if it's active) and return 1 if ESC has been pressed since last call.
     173
     174 * {{{moved, key, mx, my, mb, px, py = waitinput(t)}}} Waits for user input. _moved_ is 1 if the mouse cursor moved, _key_ is set when the user pressed a key, _mx_ and _my_ are the upadated mouse coordinates on screen, and _mb_ is the mouse buttons state, ie 1 while left mouse button is pressed, and 2 while right mouse button is pressed. _px_ and _py_ are the mouse coordinates in the picture space.
     175
     176 * {{{updatescreen()}}} Redraws the picture on the screen.
     177
     178 * {{{statusmessage(message)}}} Prints the given message in the status bar. Use this when your script is doing long calculations, so the user knows what is going on. Note the message is reset by waitbreak(), so usually you have to display it again before each call to updatescreen.
     179
     180=== Others ===
     181
     182 * {{{finalizepicture()}}} ends your modifications in picture history. The current state of the image (and palette) becomes the "backup", for all functions that read backup state. This can be called multiple times in a script, but remember the history size may be limited. Don't use all of it.
     183
     184 * {{{(name, path) = getfilename()}}} returns the picture name and the path where it is saved. This is useful for saving data related to the picture near to it, and finding it back later (or exporting it for other uses)
     185
     186 * {{{selectlayer(1)}}} select the layer or anim frame to use for pixel access in the main page. If the layer doesn't exist, it throws an error. There is no way to create a layer yet.
     187
     188 * {{{run(scriptname)}}} calls another script. This is a lot like Lua's built-in {{{dofile()}}}, but supports directories, and especially relative paths: The called script will update its current directory before running, and pop back to the original script's directory afterwards. The path uses a common format for all OSes: ".." is understood as the parent directory, and "/" acts a directory separator. This will help write scripts that run equally well on Linux, Windows, and Amiga-based OSes.
     189{{{
     190run("../libs/dawnbringer_lib.lua")
     191}}}
     192
     193= Sample script =
     194
     195Here is a very small sample script that generate a diagonal gradient.
     196
     197{{{
     198-- get the size of the brush
     199w, h = getbrushsize()
     200
     201-- Iterate over each pixel
     202for x = 0, w - 1, 1 do
     203        for y = 0, h - 1, 1 do
     204                -- Send the color for this pixel
     205                putbrushpixel(x, y, (x+y)%256);
     206        end
     207end
     208}}}
     209
     210= Known bugs and limitations =
     211 * The inputbox is limited. If you have needs that it can't meet, please contact us, we'll see if there is a way to improve it.
     212
     213= More reading =
     214Lua is a well known programming language.
     215Here are some pages from the internet you may want to look at for more information :
     216 * http://lua-users.org/wiki/MathLibraryTutorial Stuff about math.
     217 * http://lua-users.org/wiki/LuaDirectory The Lua wiki with a lot of pointers to informations.
     218 * http://code.google.com/p/grafx2/source/browse/#svn/trunk/share/grafx2/scripts The subversion holds a set of scripts you may use as a base for yours. You can send us your scripts if you want them to be added to the list.
     219
     220= Additional stuff =
     221
     222It is possible to extend the lua functions with your own ones. There are some examples on how to do that in the 'libs' directory in the link mentioned above.
     223
     224So far this includes :
     225 * Memory.lua : persistent on-disk storage for your scripts. Use this for storing your own settings or other data.
     226
     227We welcome any additions you want to make to this set of functions. If something proves too slow when done in lua, we may provide a faster C version, with the same interface whenever possible. This way all scripts can share the enhancements.