pub.lua

BlitzMax Forums/BlitzMax Module Tweaks/pub.lua

Rozek(Posted 2006) [#1]
Hello!

Since I'm using Lua a lot from within BlitzMax (and currently constructing Lua interfaces for many of the BlitzMax modules), I just wanted to let you know that I've considerably modified and extended the axe.lua module (yielding a "pub.lua" module not to break other code which still uses axe.lua)

The main idea was to support the official Lua API as completely as possible.

You are free to use it - and probably replace axe.lua with it if you find that useful.

As I'm still new to BlitzMax, it's the .bmx file which is available for download only. For the time being, you'll have to build the module yourself (unless somebody instructs me how to deploy the module (cross-platform) over the BlitzMax servers)

I've tested pub.lua under WinXP and MacOSX, but not Linux (yet)

The .bmx file is available under

http://www.Andreas-Rozek.de/BlitzMax/lua.bmx

Any feedback (positive or negative) is welcome.


Dreamora(Posted 2006) [#2]
LUA was originally pub and then moved to AXE.
Reason is, it is not officially supported and only official BRL supported modules should reside within BRL and PUB modservers. Simply reason is: without framework anything from BRL and PUB is automatically imported thus 3rd party definitely shouldn't be in PUB.


Rozek(Posted 2006) [#3]
Oops,

so I did the worst I could do...Well, anyway, as it's not automatically synchronized, it's probably not dangerous in the moment.

Should any "experimental" module go to AXE? Or is there another namespace for experimental modules?


Dreamora(Posted 2006) [#4]
AXE is skidracers modserver
For your own experiments you can simply create a new one.
You can have an "unlimited" amount of mod/someFolder.mod/yourmod.mod folders


Diordna(Posted 2006) [#5]
What's better about this one than axe.lua?


Gabriel(Posted 2006) [#6]
Is there any documentation, or perhaps a few simple samples? I'd like to get into scripting, but I don't have a clue where to start.


skidracer(Posted 2006) [#7]
Yes, lua core has links to the lua manuals, and lua script engine includes a small example, use program->document modules if you can't see them in the navbar under help->modules.

luascript is kindof out of date, the correct way to initialize the engine is to call luaL_openlibs(state) which will call the other lua_open functions itself.


Gabriel(Posted 2006) [#8]
I guess I'm not really sure where everything fits in. There's axe.lua ( core ) and there's pub.lua ( core ) and there's also axe.luascript, do I need both Lua and LuaScript, or are they just different implementations of the same functionality?

I'm ok from the LUA side, it's just figuring out where all the different modules fit in, how they're different, which I need, whether one is more powerful or another is easier to use.


skidracer(Posted 2006) [#9]
pub.lua???

axe.luascript is a "friendly" wrapper for axe.lua which is the raw lua library.


Gabriel(Posted 2006) [#10]
That'd be the one that Rozek made, as a modification of Noel's modification of.. I get lost after that. It's a modification of Axe.Lua anyway. It's considerably modified and extended apparently.


Rozek(Posted 2007) [#11]
Hello!

Sorry for the long "silence" - I've been occupied by other activities for quite a while...

Back to BlitzMAX/MaxGUI and Lua: the main idea of my extensions to the axe.lua interface was to add as many of the missing Lua API calls as possible.

You now get almost any API call you can find in the official Lua 5.1.1 documentation.

The very few missing ones have not been implemented due to variable argument lists (I don't know how to describe them in BlitzMAX) and some callback functions. Everything else should be there.

The link can be found a few posts upwards in this thread. As I don't yet know where to send my code for an official inclusion into the BlitzMAX environment I just publish it privately.

Concerning examples etc.: I'm currently writing Lua interfaces to a majority of BlitzMAX/MaxGUI functions in order to create a (rather) complete runtime environment for Lua scripts.

As a result, you may write your applications in Lua and use BlitzMAX/MaxGUI as a multi-platform runtime environment.

BlitzMAX/MaxGUI interfaces and Lua examples should be ready by the beginning of February 2007.


skidracer(Posted 2007) [#12]
As I don't yet know where to send my code for an official inclusion into the BlitzMAX environment I just publish it privately.


Hi Rozek, please send to to me in future any modifications (email in profile) I'll try and update axe.lua with your latest version today.

Your current project sounds really interesting!


Gabriel(Posted 2007) [#13]

Concerning examples etc.: I'm currently writing Lua interfaces to a majority of BlitzMAX/MaxGUI functions in order to create a (rather) complete runtime environment for Lua scripts.

As a result, you may write your applications in Lua and use BlitzMAX/MaxGUI as a multi-platform runtime environment.

BlitzMAX/MaxGUI interfaces and Lua examples should be ready by the beginning of February 2007.


This sounds great. It would ( presumably ) give us a good basis to learn how to do the same for own modules?


Barbapapa(Posted 2007) [#14]
Any news about Lua? I am missing some official statements.


skidracer(Posted 2007) [#15]
Oops, axe.lua may have reverted back to earlier version, try another syncmods (windows) for version 1.22 which has additional stuff by Andreas Rozek added.


Barbapapa(Posted 2007) [#16]
ahh, I thought so, cool will do. What about axe.LuaScript, is this depreciated? I lost several hours with axe.Luascript trying to execute a lua file with a simple print statement until I realized that I had written it with a capital P(rint) instead of print ;) bad me...


Rozek(Posted 2007) [#17]
Hello!

Just to keep you informed: due to several other activities (and an "influenza"), my work on the Lua interfaces has been delayed a bit. But I'm still working on them trying to release the stuff before end of march.

Sorry for the delay...


Barbapapa(Posted 2007) [#18]
Influenza? You too? seems half Germany has been contaminated 8-]
What are your future additions to LUA btw?


Rozek(Posted 2007) [#19]
Indeed, it seems to have begun in the south and then expanded to the north - but it's over now

Concerning my planned extensions: first, I'll provide LUA interfaces for many (probably most or even all) BlitzMAX functions - letting Lua programmers use the functionality provided by BlitzMAX modules in their programs. The emphasis is on "functions" as I won't provide any interface for any BlitzMAX (user defined) type. This is not really a problem as - luckily - the modules always provide functions which take such an object as their first parameter (very similar to the Lua approach) I'm currently implementing the last number of modules, thus, you may expect a first release within the next week.

If that approach turns out to be useful and stable, I'll implement Lua "classes" and "objects" as loose counterparts of BlitzMAX types in order to simplify programming.

My primary intent is to provide a "framework" for cross-platform graphical user interfaces scripted in Lua - with additional file system and networking support.


Gabriel(Posted 2007) [#20]
Sounds great, looking forward to it.


Rozek(Posted 2007) [#21]
Just to keep you informed:

the interfaces have been coded - I'm testing now. For those, who can't wait for the first "official" release I could provide the current code "as-is" (but keep in mind: I expect numerous errors and might even have to change some of my methods to interface Lua and BlitzMAX)

However, my first experiments with MaxGUI from Lua already look very promising...


Rozek(Posted 2007) [#22]
what I forgot:

if everything works well, I plan to release the interfaces within a week from now - hopefully together with some Lua "classes", which make scripting a lot easier, and together with several examples.


Rozek(Posted 2007) [#23]
Just to give you a *very* first impression:

this is the screenshot of a *very first* programming example - together with the code used to produce it.



blitzmax.import(brl.event);
blitzmax.import(brl.eventqueue);
blitzmax.import(brl.maxgui);
blitzmax.import(brl.pixmap);

--------------------------------------------------------------------------------
-- loadGuiFont                    Platform-independent "loadGuiFont" function --
--------------------------------------------------------------------------------

  function loadGuiFont(FontName, FontSize, isBold, isItalic, isUnderlined)
    if (blitzmax.Platform ~= "Win32") then
      FontSize = math.floor(FontSize * 1.32);
    end;
    return brl.maxgui.loadGuiFont(FontName, FontSize, isBold, isItalic, isUnderlined);
  end;

--******************************************************************************
--*                                                                            *
--*                                Main Program                                *
--*                                                                            *
--******************************************************************************

--**** provide a few application-specific definitions ****

  local Title    = "MaxGUI_00";
  local Subtitle = "very first experiments with MaxGUI and Lua";

--**** load some application-specific images ****

  local Icon = loadPixmap("Lua-Logo.png");
--  Icon = maskPixmap(Icon, 212,208,200);    -- does not work
  if (Icon == nil) then error("unable to load 'Lua-Logo.png'"); end;

  local sunkenLine = loadPixmap("sunkenLine.png");
  if (sunkenLine == nil) then error("unable to load 'sunkenLine.png'"); end;

--**** load any application-specific fonts ****

  local TitleFont    = loadGuiFont("Arial", 12, true, true, false);
  local SubtitleFont = loadGuiFont("Arial",  9, true, false,false);
  local TextFont     = loadGuiFont("Arial",  8, false,false,false);
  local BoldFont     = loadGuiFont("Arial",  8, true, false,false);
  if (TitleFont == nil) or (SubtitleFont == nil) or (TextFont == nil) or (BoldFont == nil) then
    error("unable to load all requested fonts");
  end;

--**** setup the application window ****

  local Window = createWindow(Title.." - "..Subtitle, 20,20, 320,240, nil,
    WINDOW_TITLEBAR + WINDOW_RESIZABLE + WINDOW_CLIENTCOORDS); -- + WINDOW_STATUS);
    setMinWindowSize(Window, 320,240);

    local IconView = createPanel(2,4, 32,32, Window);
      setPanelPixmap (IconView, Icon, PANELPIXMAP_CENTER);
      setGadgetLayout(IconView, EDGE_ALIGNED,0,EDGE_ALIGNED,0);
    local TitleLabel = createLabel(Title, 36,2, 282,18, Window, LABEL_RIGHT);
      setGadgetFont  (TitleLabel,TitleFont);
      setGadgetLayout(TitleLabel, 0,EDGE_ALIGNED,EDGE_ALIGNED,0);
    local SubtitleLabel = createLabel(Subtitle, 36,22, 282,16, Window, LABEL_RIGHT);
      setGadgetFont  (SubtitleLabel,SubtitleFont);
      setGadgetLayout(SubtitleLabel, 0,EDGE_ALIGNED,EDGE_ALIGNED,0);
    local UpperSeparator = createPanel(2,40, 316,2, Window);
      setPanelPixmap (UpperSeparator, sunkenLine, PANELPIXMAP_TILE);
      setGadgetLayout(UpperSeparator, EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,0);
    local ClientArea = createTextArea(2,44, 316,174, Window, TEXTAREA_READONLY);
      setGadgetLayout(ClientArea, EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED);
      setGadgetColor (ClientArea, 128,128,128, true)
    local LowerSeparator = createPanel(2,220, 316,2, Window);
      setPanelPixmap (LowerSeparator, sunkenLine, PANELPIXMAP_TILE);
      setGadgetLayout(LowerSeparator, EDGE_ALIGNED,EDGE_ALIGNED,0,EDGE_ALIGNED);
    local Statusbar = createLabel("(no special action required)", 2,224, 316,18, Window);
      setGadgetFont  (Statusbar,TextFont);
      setGadgetLayout(Statusbar, EDGE_ALIGNED,EDGE_ALIGNED,0,EDGE_ALIGNED);
--  setStatusText(Window, "(no special action required)");
  showGadget(Window);

--**** handle any incoming events... ****

  while true do
    waitEvent();
    if (EventId() == EVENT_WINDOWCLOSE) then break; end;
  end;



Rozek(Posted 2007) [#24]
Just another screenshot - TextAreas seem to work...




Barbapapa(Posted 2007) [#25]
I'll try to describe it in many words: wonderfull!


Rozek(Posted 2007) [#26]
Just to keep you informed:

here is a very first screenshot of the MaxGUI_01 application shown above - running under MacOSX!



It does not yet look nice (the classical font problems together with some ".bmp" display issues) - but I'll work on it in order to let you really write cross-platform Lua programs!

--EDIT: the snapshot has changed since this posting has been issued, the initial font and BMP probems are thus no longer visible. In fact, the MacOSX version is now the best-looking one!

Hmmm, now (I think) I'll also have to try all that stuff under Linux ;-)


Rozek(Posted 2007) [#27]
Et voilą,

here it is - the *very* first screenshot of MaxGUI_00 under Linux (unfortunately, MaxGUI_01 just crashes)



From what you can see in the screenshot, the Linux version still needs a lot of fine tuning! (sigh)


Rozek(Posted 2007) [#28]
Apart from the screenshots:

I've meanwhile also added an interface for MiniB3D and am now "objectifying" all interfaces such that you can use "objects" and "methods" under Lua rather than having to deal with the BlitzMax functions (and object "handles") yourself. The resulting (Lua) code will become much smaller and easier to handle.

Additionally, I'll try to hide some of the cross-platform issues inside these "objects"

Stay tuned!


Rozek(Posted 2007) [#29]
Just to keep you informed:

a few days ago, I discovered LogicGUI (a visual form editor for MaxGUI) which writes BlitzMax code in a form, which may easily be converted into Lua. I wrote a (quick-and-dirty) converter which gives you a Lua basis, which may then be extended with proper event handling.

Here is a screenshot of another little program, which I "hacked together" in a few minutes in the context of another Forum thread:



The corresponding source code as produced by the converter (and after editing the Windows-specific file paths, though):


I'll now try to test all MaxGUI gadgets and then release my BlitzMax runtime environment for Lua - together with LogicGUI (which is *not* part of my environment!) and my converter you will then already be able to construct simple Lua applications with a graphical user interface...


Rozek(Posted 2007) [#30]
Just for your information:

the author's modified version of axe.lua now also contains some documentation (see this thread)


Gabriel(Posted 2007) [#31]
Is there a bare bones example of using Lua from BlitzMax ( rather than BlitzMax from Lua ) around anywhere? I think there used to be a couple of tutorials on the Wiki, but that seems to be down at the moment. I was pretty sure that initial function was to call Lua_Open() but I can't even find a function with that name in this module any more, so I'm thinking my memory might be tricking me.


Rozek(Posted 2007) [#32]
Good morning!

There are just a few minutes left before I'll have to wake up my family - let's see, how much I'll be able to write down:
    local LuaState:byte ptr = luaL_newstate()

creates a new variale which contains the full state of a Lua VM - you could also say, it starts the Lua interpreter.
    luaL_openlibs(LuaState)

opens and initializes the standard Lua libraries - which is what you usually want. You should really be a Lua expert if you plan to do without them.
  lua_register(LuaState, "luaname",  BMXName)

registers a BlitzMax function (called "BMXName") with the name "luaname" under Lua.
  function BMXName:int (LuaState:Byte Ptr)
    ...
    return 0 ' number of values returned to Lua
  end function

This is the frame of a BlitzMax function which may be invoked from within Lua - I don't want to talk about stack handling here right now (no time in the moment)
    lua_pushstring(LuaState, "BMXString")
    lua_setglobal (LuaState, "luaglobal")

defines a global Lua variable (called luaglobal) which contains a string (namely "BMXString") - this is just to give you at least one example of how to use the stack-based Lua API functions.
    local Result:int = luaL_loadString(LuaState,LuaScript)
    if (Result <> 0) then
      ' ERROR!!!
      lua_close(LuaState)                                  ' just to be complete
      end
    end if

loads and compiles a (BlitzMax) string containing a LuaScript. The result (of compilation) is left on the (Lua) stack.
    lua_getfield(LuaState, LUA_GLOBALSINDEX, "debug")       ' get global "debug"
    lua_getfield(LuaState, -1,           "traceback")    ' get "debug.traceback"
    lua_remove  (LuaState, -2)                 ' remove "debug" table from stack

    Result = lua_pcall(LuaState,1,-1,-1)' use "debug.traceback" as error handler
    if (Result <> 0) then
      ' ERROR
      lua_close(LuaState)                                  ' just to be complete
      end
    end if

actually evaluates the previously loaded script. The initially mentioned Lua commands just prepare for proper error messages should the Lua script fail.
    lua_close(LuaState)                                    ' just to be complete

terminates the Lua interpreter and invalidates the Lua state variable.

Let that be enough for now - I could sit down and write a "Lua from within BlitzMAX" tutorial, but not in the moment (please wait two weeks, I really want to finish my BlitzMax interface for Lua first)

So far for now (family is waiting)


Ratchet(Posted 2007) [#33]
Hi,
if you're making a BMX-LUA interface you should make it in "Lua-Style". What I mean is: All Lua functions are sorted by catergory. Every category has a own table including the functions. For exsample

s = string.gsub(str, "^%l", string.upper)
math.abs(-100)


That's why I love Lua. Everything is logical sorted. Please, do not mess up Lua and store your functions into tables. Something like

gui.waitevent()


This would be more clearer.


Rozek(Posted 2007) [#34]
;-)

This has already done: all BlitzMAX functions are in tables named after their modules, e.g.
  brl.eventqueue.waitEvent();

This makes it easy for BlitzMAX programmers to become familiar with the Lua interface. If you don't like the table prefix, you may "import" a (BlitzMAX module) table, making all its functions global (as shown in the above example)...

Additionally, I also have Lua "objects", which are loosely modelled after their BlitzMax counterparts and provide object-based access to BlitzMax functions. The GUI part, however, already has automatic layouting capabilities and an interface similar to that of TkLua.


Ratchet(Posted 2007) [#35]
*Thumbs up*


Gabriel(Posted 2007) [#36]
Thanks heaps for the tutorial, Rozek. That was more than enough to get me started. I've read the two online books and I've ordered a paper book, but it was just the starting point that was giving me trouble ( I think I was reading a tutorial which covered Lua 4.0 which didn't help ) and I think I'll be fine now that I've got your explanations and examples.


Rozek(Posted 2007) [#37]
Gabriel,

as usual: as soon as one has understood the underlying concept, everything else becomes quite simple (provided that it has been designed in a systematic way)

Good luck for your work!


Gabriel(Posted 2007) [#38]
Hi Andreas,

I'm having some problems with Lua_ToInteger when sending a number from Lua to BMax. I get a completely incorrect number ( it's 14344644 or something ) when I send a number. If I use Lua_ToNumber() I get the correct number, and if use Lua_ToString() I get the right number ( albeit, as a string ) but Lua_ToInteger returns the wrong value. Any ideas why?

EDIT: I'm looking at the source, and perhaps I'm reading it wrong, but it seems that this function in C++ is actually returning a 32bit number, not a 64bit number. Could this be the problem? I tried recompiling it with an int instead but it just returned 0 instead of the correct number, so either there's more to it than that or I'm barking up the wrong tree entirely here.


Rozek(Posted 2007) [#39]
Gabriel,

I'll check that. Right now, I have only 15 minutes left before waking up my family. Thus, I may only be able to work on your problem in a few hours (after having returned from the kindergarden)

Update: I had a few minutes and found that it is indeed the discrepancy between int and long which causes that problem. I'll correct this in approx. 2 hours

By the way, I just looked into my code and found, that I always use lua_tonumber and then convert the result into an int within BlitzMAX myself. Main reason for that detour is the possibility of range checking prior to the type conversion...

However, lua_tointeger (et al.) has to behave properly as well, of course


Gabriel(Posted 2007) [#40]
Thanks Andreas. Using Lua_ToNumber and converting to an int seems like a good idea actually. Lua_ToInteger seems to be a relatively recent addition to Lua ( I noticed for example that they have not implemented a matching Lua_IsInteger ) so quite possibly Lua_ToNumber and then a typecast ( referred to as coersion, in Lua, I believe ) to int is the recommended way to go. It works fine for what I'm doing right now anyway. Thanks again.


Rozek(Posted 2007) [#41]
Gabriel,

I've corrected the bug you've found and published the new version of axe.lua (see the corresponding thread, I think it's time to close this one ;-) )