Line 1: |
Line 1: |
| Note: Neither the ''io'' nor ''os'' libraries are present for the TI-Nspire, which seems to be running a light version of Lua 5.1.4. | | Note: Neither the ''io'' nor ''os'' libraries are present for the TI-Nspire, which seems to be running a light version of Lua 5.1.4. |
| | | |
− | == Standard Library == | + | == Standard Library == |
| | | |
| ( This has been taken from [http://www.wowwiki.com/Lua_functions a WoWWiki page] - See the full, official documentation [http://www.lua.org/manual/5.1/manual.html here] ) | | ( This has been taken from [http://www.wowwiki.com/Lua_functions a WoWWiki page] - See the full, official documentation [http://www.lua.org/manual/5.1/manual.html here] ) |
Line 20: |
Line 20: |
| *'''[[xpcall]]'''(func, err) - Returns a boolean indicating successful execution of func and calls err on failure, additionally returning func's or err's results. | | *'''[[xpcall]]'''(func, err) - Returns a boolean indicating successful execution of func and calls err on failure, additionally returning func's or err's results. |
| | | |
− | == Concepts and Basics == | + | == Concepts and Basics == |
| | | |
| This part will explain you how the Lua actually works inside the OS and help you to figure out what you're doing when you write a script for the TI-Nspire. Before reading this, you have to know all about the Lua basics. | | This part will explain you how the Lua actually works inside the OS and help you to figure out what you're doing when you write a script for the TI-Nspire. Before reading this, you have to know all about the Lua basics. |
Line 35: |
Line 35: |
| *... | | *... |
| *Link events (pseudo code) | | *Link events (pseudo code) |
− | <div dir="ltr" class="mw-geshi" style="text-align: left;"><div class="lua source-lua"><pre class="de1"> <span class="kw1">while</span><span class="br0">(</span>Exit<span class="br0">)</span> <span class="co1">------- Some OS routines here</span> <span class="co1">---- Begin of Event link</span> buffer:captureDataFromKeyPad<span class="br0">(</span><span class="br0">)</span> <span class="co1">-- (N) some underground routines to catch events</span> <span class="kw1">if</span> buffer.charInput ~<span class="sy0">=</span> <span class="st0">""</span> <span class="kw1">then</span> <span class="co1">-- (N)</span> <span class="kw3">on.charIn</span><span class="br0">(</span>buffer.charInput<span class="br0">)</span> buffer.charInput<span class="sy0">=</span> <span class="st0">""</span> <span class="co1">-- (N)</span> <span class="kw1">end</span> <span class="kw1">if</span> buffer.arrowKey ~<span class="sy0">=</span> <span class="st0">""</span> <span class="kw1">then</span> <span class="co1">-- (N)</span> <span class="kw3">on.arrowKey</span><span class="br0">(</span>buffer.arrowKey<span class="br0">)</span> buffer.arrowKey <span class="sy0">=</span> <span class="st0">""</span> <span class="co1">-- (N)</span> <span class="kw1">end</span> <span class="co1">----- etc ... </span> <span class="kw1">if</span> platform.window.isInvalidate <span class="kw1">then</span> platform.gc<span class="br0">(</span><span class="br0">)</span>:purge<span class="br0">(</span><span class="br0">)</span> <span class="co1">-- (N) Empty buffer before starting to draw</span> <span class="kw3">on.paint</span><span class="br0">(</span>platform.gc<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> <span class="co1">-- save all the things we have to draw</span> platform:paint<span class="br0">(</span><span class="br0">)</span> <span class="co1">-- (N) draw all those things</span> platform.window.isInvalidate <span class="sy0">=</span> <span class="kw1">false</span> <span class="co1">-- say that the window has been drawn</span> <span class="kw1">end</span> <span class="co1">----- End of Event link</span> <span class="kw1">end</span></pre></div></div> | + | <div dir="ltr" class="mw-geshi" style="text-align: left;"><div class="lua source-lua"><pre class="de1"><span class="Apple-style-span" style="font-family: sans-serif; line-height: 19px; white-space: normal; font-size: 13px; ">''while(Exit) |
− | ''Note : the (N) commented line only indicates the meaning of the routine. Those functions don't really exist.'' | + | ------- Some OS routines here |
− | | + | |
| + | ---- Begin of Event link |
| + | buffer:captureDataFromKeyPad() -- (N) some underground routines to catch events |
| + | if buffer.charInput ~= "" then -- (N) |
| + | on.charIn(buffer.charInput) |
| + | buffer.charInput= "" -- (N) |
| + | end |
| + | if buffer.arrowKey ~= "" then -- (N) |
| + | on.arrowKey(buffer.arrowKey) |
| + | buffer.arrowKey = "" -- (N) |
| + | end |
| + | ----- etc ... |
| + | if platform.window.isInvalidate then |
| + | platform.gc():purge() -- (N) Empty buffer before starting to draw |
| + | on.paint(platform.gc()) -- save all the things we have to draw |
| + | platform:paint() -- (N) draw all those things |
| + | platform.window.isInvalidate = false -- say that the window has been drawn |
| + | end |
| + | ----- End of Event link |
| + | end'' |
| + | ''Note : the (N) commented line only indicates the meaning of the routine. Those functions don't really exist. |
| + | '' |
| + | </span></pre></div></div> |
| Now we can understand how everything is linked, just by a main loop. This helps you to understand that you don't have to code a loop yourself, because the screen wouldn't be refreshed. This also helps to see when the screen gets refreshed. In other words, we cannot use niether '''gc''' nor '''platform.gc()''' (which are the same) in order to draw somthing on the screen if we are outside of '''on.paint()''' (except if your outside function is called within on.paint() ). This also means that we don't need to pass '''gc''' as parameter, because we can rather use '''platform.gc()''' for any functions called within on.paint(). This is exactly what [https://github.com/adriweb/BetterLuaAPI-for-TI-Nspire/blob/master/BetterLuaAPI.lua the BetterLuaAPI library for Nspire] does. | | Now we can understand how everything is linked, just by a main loop. This helps you to understand that you don't have to code a loop yourself, because the screen wouldn't be refreshed. This also helps to see when the screen gets refreshed. In other words, we cannot use niether '''gc''' nor '''platform.gc()''' (which are the same) in order to draw somthing on the screen if we are outside of '''on.paint()''' (except if your outside function is called within on.paint() ). This also means that we don't need to pass '''gc''' as parameter, because we can rather use '''platform.gc()''' for any functions called within on.paint(). This is exactly what [https://github.com/adriweb/BetterLuaAPI-for-TI-Nspire/blob/master/BetterLuaAPI.lua the BetterLuaAPI library for Nspire] does. |
| | | |
| Here is an example of a simple Lua program that displays a message only when a key is pressed (and let the screen blank otherwise). | | Here is an example of a simple Lua program that displays a message only when a key is pressed (and let the screen blank otherwise). |
− | <div dir="ltr" class="mw-geshi" style="text-align: left;"><div class="lua source-lua"><pre class="de1"> <span class="kw1">function</span> <span class="kw3">on.paint</span><span class="br0">(</span>gc<span class="br0">)</span> <span class="kw1">if</span> message <span class="kw1">then</span> <span class="kw2">gc:setFont</span><span class="br0">(</span><span class="st0">"sansserif"</span>, <span class="st0">"r"</span>, <span class="nu0">10</span><span class="br0">)</span> <span class="co1">-- initialize font drawing</span> <span class="kw2">gc:drawString</span><span class="br0">(</span>message, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="st0">"top"</span><span class="br0">)</span> <span class="co1">-- display the message at (0, 0) coordinates</span> message <span class="sy0">=</span> <span class="kw1">nil</span> <span class="co1">-- erase the message</span> <span class="kw2">timer.start</span><span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span> <span class="co1">-- start a timer to exit on.paint() but keep in mind that we have to redraw the screen</span> <span class="kw1">end</span> <span class="kw1">end</span> <span class="kw1">function</span> <span class="kw3">on.timer</span><span class="br0">(</span><span class="br0">)</span> <span class="kw2">timer.stop</span><span class="br0">(</span><span class="br0">)</span> <span class="kw2">platform.window:invalidate<span class="br0">(</span><span class="br0">)</span></span> <span class="kw1">end</span> <span class="kw1">function</span> <span class="kw3">on.charIn</span><span class="br0">(</span>ch<span class="br0">)</span> message <span class="sy0">=</span> <span class="st0">"Hello World !"</span> <span class="co1">-- store a message</span> <span class="kw2">platform.window:invalidate<span class="br0">(</span><span class="br0">)</span></span> <span class="co1">-- force display</span> <span class="kw1">end</span></pre></div></div> | + | <div dir="ltr" class="mw-geshi" style="text-align: left;"><div class="lua source-lua"><pre class="de1"> function on.paint(gc) |
| + | if message then |
| + | gc:setFont("sansserif", "r", 10) -- initialize font drawing |
| + | gc:drawString(message, 0, 0, "top") -- display the message at (0, 0) coordinates |
| + | message = nil -- erase the message |
| + | timer.start(1) -- start a timer to exit on.paint() but keep in mind that we have to redraw the screen |
| + | end |
| + | end |
| + | |
| + | function on.timer() |
| + | timer.stop() |
| + | platform.window:invalidate() |
| + | end |
| + | |
| + | function on.charIn(ch) |
| + | message = "Hello World !" -- store a message |
| + | platform.window:invalidate() -- force display |
| + | end</pre></div></div> |
| When you open the document, the script is read once. It initializes and overwrites all the functions and globals with the ones you defined. Thus, '''message''' is nil. Once the '''on.paint()''' event is called, '''message''' is nil, thus, nothing is done. When you press a key that calls '''on.charIn()''' (see below for more information), '''message''' is now "Hello World" and we tell the '''platform''' that the screen has to be refreshed. Then, '''on.paint()''' is called again, '''message''' is not nil then we display it, erase '''message''' and launch a timer. Why is that ? Because if we call '''platform.window:invalidate()''' right there, we won't refresh the screen. Why again ? Just look at the pseudo-code above. We set the window as drawn after each call of on.paint(). Thus a timer is necessary to manually recall '''on.paint()''' and exit the '''on.paint()''' function to draw the screen. When the timer is ended, '''on.timer()''' is called and we refresh the screen. The screen is then redrawn but there is nothing to draw because '''message''' is nil. Thus, the graphic context lets the screen blank. | | When you open the document, the script is read once. It initializes and overwrites all the functions and globals with the ones you defined. Thus, '''message''' is nil. Once the '''on.paint()''' event is called, '''message''' is nil, thus, nothing is done. When you press a key that calls '''on.charIn()''' (see below for more information), '''message''' is now "Hello World" and we tell the '''platform''' that the screen has to be refreshed. Then, '''on.paint()''' is called again, '''message''' is not nil then we display it, erase '''message''' and launch a timer. Why is that ? Because if we call '''platform.window:invalidate()''' right there, we won't refresh the screen. Why again ? Just look at the pseudo-code above. We set the window as drawn after each call of on.paint(). Thus a timer is necessary to manually recall '''on.paint()''' and exit the '''on.paint()''' function to draw the screen. When the timer is ended, '''on.timer()''' is called and we refresh the screen. The screen is then redrawn but there is nothing to draw because '''message''' is nil. Thus, the graphic context lets the screen blank. |
| | | |
− | == gc (as in Graphics Context) == | + | == gc (as in Graphics Context) == |
| | | |
| Note: You need to add “gc:” before each of these commands in order to use them. ex. '''gc:setAlpha(...)'''. You can also call gc like this : '''platform.gc():setAlpha(...)'''. Then you can use the gc library in a function where gc is not passed as an argument. but this function *has* to be called within '''on.paint(gc)''' | | Note: You need to add “gc:” before each of these commands in order to use them. ex. '''gc:setAlpha(...)'''. You can also call gc like this : '''platform.gc():setAlpha(...)'''. Then you can use the gc library in a function where gc is not passed as an argument. but this function *has* to be called within '''on.paint(gc)''' |
Line 56: |
Line 95: |
| *'''[[gc:drawLine]]'''(xstart, ystart, xend, yend) Draws a line starting at the point (xstart,ystart) and ending at the point (xend, yend) | | *'''[[gc:drawLine]]'''(xstart, ystart, xend, yend) Draws a line starting at the point (xstart,ystart) and ending at the point (xend, yend) |
| *'''[[gc:drawPolyLine]]'''(int list1 [,int list2, .., int listN]) Draws a shape from a list contaning successively the x and y coordinates of each point the line have to draw. | | *'''[[gc:drawPolyLine]]'''(int list1 [,int list2, .., int listN]) Draws a shape from a list contaning successively the x and y coordinates of each point the line have to draw. |
− |
| |
− | For example
| |
− | <div dir="ltr" class="mw-geshi" style="text-align: left;"><div class="lua source-lua"><pre class="de1"> drawPolyLine<span class="br0">(</span><span class="br0">{</span><span class="nu0">0</span>,<span class="nu0">0</span>, <span class="nu0">0</span>,<span class="nu0">100</span>, <span class="nu0">100</span>,<span class="nu0">100</span>, <span class="nu0">100</span>,<span class="nu0">0</span>, <span class="nu0">0</span>,<span class="nu0">0</span><span class="br0">}</span><span class="br0">)</span></pre></div></div>
| |
− | and
| |
− | <div dir="ltr" class="mw-geshi" style="text-align: left;"><div class="lua source-lua"><pre class="de1"> drawRect<span class="br0">(</span><span class="nu0">0</span>,<span class="nu0">0</span>,<span class="nu0">100</span>,<span class="nu0">100</span><span class="br0">)</span></pre></div></div>
| |
− | do the same. If there are multiple argument (which can be 4 elements list to represent lines), each list has to contain an even number of element.
| |
| | | |
| *'''[[gc:drawRect]]'''(x, y, xwidth, yheight) Draws a rectangle at (x,y) with the “x” side being “xwidth” long and the “y” side being “yheight” long | | *'''[[gc:drawRect]]'''(x, y, xwidth, yheight) Draws a rectangle at (x,y) with the “x” side being “xwidth” long and the “y” side being “yheight” long |
Line 92: |
Line 125: |
| *'''[[platform.isColorDisplay()]]''' Returns ''true'' if the unit the code is being run on has a color display (-> Nspire CX), and ''false'' otherwise. | | *'''[[platform.isColorDisplay()]]''' Returns ''true'' if the unit the code is being run on has a color display (-> Nspire CX), and ''false'' otherwise. |
| | | |
− | == cursor == | + | == cursor == |
| | | |
| *'''[[cursor.hide]]'''() - hides the cursor (mouse pointer) | | *'''[[cursor.hide]]'''() - hides the cursor (mouse pointer) |
Line 98: |
Line 131: |
| *'''[[cursor.show]]'''() - Shows the cursor on screen | | *'''[[cursor.show]]'''() - Shows the cursor on screen |
| | | |
− | == document == | + | == document == |
| | | |
| *'''[[document.markChanged]]'''() - Flag the document as "changed" so the user has to save it after using it. | | *'''[[document.markChanged]]'''() - Flag the document as "changed" so the user has to save it after using it. |
| | | |
− | == clipboard == | + | == clipboard == |
| | | |
| *'''[[clipboard.addText]]'''() | | *'''[[clipboard.addText]]'''() |
| *'''[[clipboard.getText]]'''() | | *'''[[clipboard.getText]]'''() |
| | | |
− | == locale == | + | == locale == |
| | | |
| *'''[[locale.name]]'''() - Returns the current language the calculator is set in, formatted as ISO-639 (i.e : "fr", "en", "it" ...). | | *'''[[locale.name]]'''() - Returns the current language the calculator is set in, formatted as ISO-639 (i.e : "fr", "en", "it" ...). |
| | | |
− | == image == | + | == image == |
| | | |
− | *'''[[image.copy]]'''(image, width, height) - returns a new Image which has a new scale. Width is the final width, Heigth, the final height of the image. | + | *'''[[image.copy]]'''(image, width, height) - returns a new Image which has a new scale. Width is the final width, Heigth, the final height of the image. |
| *'''[[image.height]]'''(image) - returns the height of the image given in parameter | | *'''[[image.height]]'''(image) - returns the height of the image given in parameter |
− | *'''[[image.new]]'''(string) - Creates a new image from the string given in parameter (see TI.Image). Call it with <tt>img = image.new("...")</tt> | + | *'''[[image.new]]'''(string) - Creates a new image from the string given in parameter (see TI.Image). |
| *'''[[image.width]]'''(image) - returns the width of the image given in parameter | | *'''[[image.width]]'''(image) - returns the width of the image given in parameter |
| | | |
− | == timer == | + | == timer == |
| | | |
| *'''[[timer.getMilliSecCounter]]'''() - Returns the amount of milliseconds elapsed since last calculator reboot. (in TI's Computer software, returns an absolute negative time) | | *'''[[timer.getMilliSecCounter]]'''() - Returns the amount of milliseconds elapsed since last calculator reboot. (in TI's Computer software, returns an absolute negative time) |
Line 124: |
Line 157: |
| *'''[[timer.stop]]'''() - Stops a timer | | *'''[[timer.stop]]'''() - Stops a timer |
| | | |
− | == toolpalette == | + | == toolpalette == |
| | | |
| *'''[[toolpalette.enable]]'''(string) | | *'''[[toolpalette.enable]]'''(string) |
Line 132: |
Line 165: |
| *'''[[toolpalette.register]]'''(table) | | *'''[[toolpalette.register]]'''(table) |
| | | |
− | == var == | + | == var == |
| | | |
| *'''[[var.list]]'''() - returns a list of all the variables in the entire Activity | | *'''[[var.list]]'''() - returns a list of all the variables in the entire Activity |
Line 141: |
Line 174: |
| *'''[[var.unmonitor]]'''() - ? | | *'''[[var.unmonitor]]'''() - ? |
| | | |
− | == Events == | + | == Events == |
| | | |
| *'''[[on.paint]]'''(gc) is called when the GUI is painted. 'gc' is the Graphics Context (see above) | | *'''[[on.paint]]'''(gc) is called when the GUI is painted. 'gc' is the Graphics Context (see above) |
| *'''[[on.resize]]'''() is called when the window is rezised | | *'''[[on.resize]]'''() is called when the window is rezised |
| *'''[[on.timer]]'''() is called when the timer has been finished. Here an example of using timer to play an animation : | | *'''[[on.timer]]'''() is called when the timer has been finished. Here an example of using timer to play an animation : |
− | <div dir="ltr" class="mw-geshi" style="text-align: left;"><div class="lua source-lua"><pre class="de1"> x <span class="sy0">=</span> <span class="nu0">1</span> animating <span class="sy0">=</span> <span class="kw1">false</span> <span class="kw1">function</span> <span class="kw3">on.paint</span><span class="br0">(</span>gc<span class="br0">)</span> <span class="kw2">gc:setFont</span><span class="br0">(</span><span class="st0">"sansserif"</span>, <span class="st0">"r"</span>, <span class="nu0">10</span><span class="br0">)</span> <span class="kw2">gc:drawString</span><span class="br0">(</span><span class="kw1">tostring</span><span class="br0">(</span>x<span class="br0">)</span>, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="st0">"top"</span><span class="br0">)</span> <span class="kw1">if</span> animating <span class="kw1">then</span> x <span class="sy0">=</span> x + <span class="nu0">1</span> <span class="kw2">timer.start</span><span class="br0">(</span><span class="nu0">0.5</span><span class="br0">)</span> <span class="kw1">end</span> <span class="kw1">end</span> <span class="kw1">function</span> <span class="kw3">on.charIn</span><span class="br0">(</span>ch<span class="br0">)</span> animating <span class="sy0">=</span> <span class="kw1">not</span> animating <span class="co1">-- switch state</span> <span class="kw2">platform.window:invalidate<span class="br0">(</span><span class="br0">)</span></span> <span class="co1">-- recall graph engine</span> <span class="kw1">end</span> <span class="kw1">function</span> <span class="kw3">on.timer</span><span class="br0">(</span><span class="br0">)</span> <span class="kw2">timer.stop</span><span class="br0">(</span><span class="br0">)</span> <span class="kw2">platform.window:invalidate<span class="br0">(</span><span class="br0">)</span></span> <span class="co1">-- recall graph engine</span> <span class="kw1">end</span></pre></div></div> | + | <div dir="ltr" class="mw-geshi" style="text-align: left;"><div class="lua source-lua"><pre class="de1"> x = 1 |
| + | animating = false |
| + | function on.paint(gc) |
| + | gc:setFont("sansserif", "r", 10) |
| + | gc:drawString(tostring(x), 0, 0, "top") |
| + | if animating then |
| + | x = x + 1 |
| + | timer.start(0.5) |
| + | end |
| + | end |
| + | |
| + | function on.charIn(ch) |
| + | animating = not animating -- switch state |
| + | platform.window:invalidate() -- recall graph engine |
| + | end |
| + | |
| + | function on.timer() |
| + | timer.stop() |
| + | platform.window:invalidate() -- recall graph engine |
| + | end |
| + | </pre></div></div> |
| ---- | | ---- |
| | | |
Line 173: |
Line 226: |
| *'''[[on.help]]'''() is called when the combo-key '''Ctrl H''' is pressed. | | *'''[[on.help]]'''() is called when the combo-key '''Ctrl H''' is pressed. |
| | | |
− | *'''[[on.charIn]]'''(string) is called when the Nspire detects a non arrow key being pressed. ch is the character it detect. If you want to auto start an event in the file linked to key r(like a reset) put on.charIn(“r”) where you want. This Lua program lets you display the value of a valid non arrow key : | + | *'''[[on.charIn]]'''(string) is called when the Nspire detects a non arrow key being pressed. ch is the character it detect. If you want to auto start an event in the file linked to key r(like a reset) put on.charIn(“r”) where you want. |
− | <div dir="ltr" class="mw-geshi" style="text-align: left;"><div class="lua source-lua"><pre class="de1"> c <span class="sy0">=</span> <span class="st0">""</span> <span class="kw1">function</span> <span class="kw3">on.charIn</span><span class="br0">(</span>ch<span class="br0">)</span> c <span class="sy0">=</span> ch <span class="kw2">platform.window:invalidate<span class="br0">(</span><span class="br0">)</span></span> <span class="co1">-- we force the screen draw</span> <span class="kw1">end</span> <span class="kw1">function</span> <span class="kw3">on.paint</span><span class="br0">(</span>gc<span class="br0">)</span> <span class="kw2">gc:setFont</span><span class="br0">(</span>“sansserif”, <span class="st0">"r"</span>, <span class="nu0">10</span><span class="br0">)</span> <span class="kw2">gc:drawString</span><span class="br0">(</span>c, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="st0">"top"</span><span class="br0">)</span> <span class="kw1">end</span></pre></div></div>
| |
− | ----
| |
| | | |
| *'''[[on.blink]]'''() ? is called when the focus is lost on the page (like launching the document, changing page etc...) | | *'''[[on.blink]]'''() ? is called when the focus is lost on the page (like launching the document, changing page etc...) |
Line 206: |
Line 257: |
| ---- | | ---- |
| | | |
− | == D2Editor == | + | == D2Editor == |
| | | |
| *'''[[D2Editor.newRichText]]'''() creates a new RichText object (default values : x, y, width, height = 0) | | *'''[[D2Editor.newRichText]]'''() creates a new RichText object (default values : x, y, width, height = 0) |
Line 217: |
Line 268: |
| | | |
| Example of a valid function using the D2Editor | | Example of a valid function using the D2Editor |
− | <div dir="ltr" class="mw-geshi" style="text-align: left;"><div class="lua source-lua"><pre class="de1"> <span class="kw1">function</span> createRichTextBox box <span class="sy0">=</span> <span class="kw2">D2Editor.newRichText</span><span class="br0">(</span><span class="br0">)</span> box:move<span class="br0">(</span><span class="nu0">50</span>, <span class="nu0">50</span><span class="br0">)</span> box:resize<span class="br0">(</span><span class="nu0">50</span>, <span class="nu0">50</span><span class="br0">)</span> box:setText<span class="br0">(</span><span class="st0">"Hello World !"</span><span class="br0">)</span> <span class="kw1">end</span></pre></div></div> | + | <div dir="ltr" class="mw-geshi" style="text-align: left;"><div class="lua source-lua"><pre class="de1"> function createRichTextBox |
− | == External Links == | + | box = D2Editor.newRichText() |
| + | box:move(50, 50) |
| + | box:resize(50, 50) |
| + | box:setText("Hello World !") |
| + | end</pre></div></div> |
| + | == External Links == |
| | | |
| An interesting page about LUA code optimization, that can be really useful, especially for calculators : [http://trac.caspring.org/wiki/LuaPerformance Lua Performance] | | An interesting page about LUA code optimization, that can be really useful, especially for calculators : [http://trac.caspring.org/wiki/LuaPerformance Lua Performance] |
| | | |
− | == Online Demo == | + | == Online Demo == |
| | | |
| [[Document Player]] | | [[Document Player]] |