Pipmak Game Engine Wiki
Status: Alpha
Brought to you by:
cwalther
For the moment, I'm just going to paste in Christian's email. Hopefully more notes and documentation can be added later.--Rivenwanderer 04:51, 2 November 2008 (UTC)
rivenwanderer wrote: > I'm not that familiar with Pipmak's source code, nor with Lua in general. > However, I'd like to add the option to specify handle locations in terms of the > center of the rectangle (with perhaps parameters name [caz, cel] or something > similar). Internally, this could hopefully just be mapped back to the regular > representation (az=caz-w/2, el=cel+h/2) in a seamless way so that the rest of > the treatment of handles would be unaffected. Sounds like a good idea - and it's even something you can add without having to recompile Pipmak. I agree with your suggestion, caz/cel would just override az/el when specified. For flat nodes, I'd add cx/cy that override x/y. > Can anyone point me at the portion of the source where this could be > accomplished? Short answer: defaults.lua, function pipmak_internal.handle(handle) (line 521 in my development version). The defaults.lua file is at resources/resources/defaults.lua in the source code (if you want to compile from source), in Pipmak.app/Contents/Resources/resources/defaults.lua on Mac OS, or at resources/defaults.lua in the file "Pipmak Resources", which is a ZIP archive, on Windows and Linux. Long answer: Pipmak can be divided into a "Lua side" and a "C side". Reading project Lua files obviously belongs to the Lua side, but the Lua side extends futher into Pipmak's innards in that things that Lua is good at, like handling of dynamic lists, strings, and tables, are done in Lua. The Lua side is entirely implemented in the mentioned defaults.lua file (that you can modify in a released binary version, without having to compile the C side or even needing an SVN checkout or a source release). All the rest, like the whole rendering and event handling, is done in C. The interface between the Lua side and the C side consists of functions callable from Lua but implemented in C, mostly in file pipmakLuaLib.c, and C objects (structs) wrapped as Lua "userdata" objects (images and sounds are examples of such objects). Other objects have representations on both the Lua side and the C side, such as nodes. The Lua representation (that the project author interacts with) in that case is an ordinary Lua table, with a metatable assigned that gives the object its methods. Projects are supposed to treat these tables as opaque objects, only using their methods or pipmak functions to interact with them, but the contents of the table are plainly accessible for those who want to take a look. The C representation of the object is a C struct that is never directly touched by the project's Lua code. The two representations refer to each other, and each only contains as much information as the respective side needs (they largely overlap, but neither is a subset of the other). Handles, in particular, are handled entirely on the Lua side, they have no C representation (hit testing is done by event handling branching out from the C side to the Lua side by calling function pipmak_internal.getcontrol_flat() or ..._pano()). Their Lua representation, incidentally, is directly the table a node.lua file uses to describe the handle, and the "handle" function that interprets it mostly consists of argument validation (and conversion of the simplified "target/effect" syntax for navigation controls to the generic syntax). Recall that a node.lua statement like "handle { target = 15 }", while conceptually a declarative statement, is technically a Lua function call - function "handle" is called with a new table (that maps the string "target" to the number 15) as a single argument. There is no parser for node.lua syntax built into Pipmak, reading a node.lua file means running it. That's the powerful concept that makes it effortless (from the point of view of me, the Pipmak developer) to support things like making the image of a patch not constant, but dependent on game state (or even much more complex things like Andrea's Autocubic system). Loading a node from a node.lua file works roughly as follows: On the C side, the C representation of the node object is created and a few of its most important fields are filled in. Then the Lua representation is created (still on the C side, by Lua C API calls), the two representations are cross-referenced, and then handed over to the Lua side by calling function pipmak_internal.loadnode() (defined in defaults.lua). That function initializes more fields in the Lua table representation of the node object and then executes node.lua. Node.lua calls back to functions like "handle". These functions are only assigned to these short names during execution of node.lua and unassigned afterwards (to stop people from trying to call them at other times than node loading, which would make a mess). Their permanent definitions live under the same names in the pipmak_internal table, i.e. pipmak_internal.handle() etc. These functions fill more values into the Lua representation of the node object. When control returns from the Lua side to the C side after the end of pipmak_internal.loadnode(), the C representation of the node is fully initialized by reading out some of the contents of the Lua representation and storing them in the C struct. (Disclaimer: This is all written mostly from memory and may contain small inaccuracies.) > In general, is there any documentation of the overall structure of Pipmak's architecture? There isn't, as far as I'm aware. I hope what I wrote above helps to some extent. You're welcome to put it onto the wiki and augment it by your own observations. If you have more questions, please come back and ask. I can show you an implementation of your proposed "handle center" feature if you like, that's a matter of a few minutes, but maybe you want to have a try yourself first. When you examine pipmak_internal.handle(), there's one potentially confusing expression that jumps at me right now: the line "if math.mod(node.type, 2) == 1" should be read as "if this node is flat". It has historically happened that the node types for flat nodes (slides, panels) are odd, while panoramic node types (cubic, equirectangular) are even (equirectangular is currently only used for hotspot maps, not for nodes). -Christian