Added GPLv3 headers all over the place.
[fail.git] / lua-modules / shared / fail.lua
blob2b282ce33b04e3ad6fedebf3cfbb2b1e701abbec
1 --[[
2 Fail game engine
3 Copyright 2007 Antoine Chavasse <a.chavasse@gmail.com>
5 This file is part of Fail.
7 Fail is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 3
9 as published by the Free Software Foundation.
11 Fail is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 --]]
19 module( "fail", package.seeall )
21 function class( template )
23 -- Extract the information we need to setup the class from the
24 -- template.
25 superclass = template.superclass
26 ctor = template[1]
28 template.superclass = nil
29 template[1] = nil
31 -- Instance meta table
32 instancemeta = { _flNonNative = true }
34 -- We can't just point the table on itself here,
35 -- because then when we reach the native class up in
36 -- the hierarchy, we no longer have the instance table
37 -- that contains a field pointing to the C++ wrapper, but
38 -- one of the classdef table.
39 -- So we try to rawget up the hierarchy until we hit a native
40 -- table, and then we just get the key from the wrapped C++
41 -- object in _flNativeInstance.
42 function instancemeta.__index( table, key )
44 local v = rawget( table, key )
45 if v ~= nil then return v end
47 t = getmetatable( table )
48 while( rawget( t, "_flNonNative" ) ) do
49 local v = rawget( t, key )
50 if v ~= nil then return v end
51 t = getmetatable( t )
52 end
54 return table._flNativeInstance[key]
56 end
58 -- set up superclass' (if any) instance meta table to be the meta table
59 -- of instancemeta.
60 -- Also copy the __newindex meta method, so we can write to attributes
61 -- inherited from native classes.
62 if( superclass ) then
63 instancemeta.__newindex = superclass._flMetatable.__newindex
64 setmetatable( instancemeta, superclass._flMetatable )
65 end
67 --
68 -- The class table will be returned and stored globally as
69 -- modulename.classname.
71 -- It contains:
72 -- * a field called _flMetatable, which is the metatable used
73 -- of instances of this class
74 -- * a function called init, that construct this class's part of the
75 -- provided instance table (and call this class' ctor).
76 -- This is called by sub classes' constructors.
77 -- * a metatable that define a __call function that allows the
78 -- creation of a new instance of this class by writing
79 -- instance = someclass( params )
80 -- Its metatable also defines a __newindex function that
81 -- allow to add things to the instance metatable, so member functions
82 -- can then be defined with "function MyClass:func() bla bla end".
84 -- Native classes also define all these things and thus can
85 -- be subclassed (for those that allows it) and instanciated
86 -- the same way.
87 -- This allows to write drop in C++ replacements of existing lua classes
88 -- if it turns out they need to be rewritten for performance reasons,
89 -- provided the lua class(es) to be replaced inherit directly from a native
90 -- class, as a lua class can inherit from a C++ class but not the other way around.
91 classtable = { _flMetatable = instancemeta }
93 function classtable:init( obj, ... )
94 -- Copy the keys from the template into the instance,
95 -- then call the ctor
96 for k,v in pairs( template ) do
97 obj[k] = v
98 end
100 ctor( obj, ... )
103 -- Metatable for the class table.
104 classmeta = {}
106 function classmeta.__newindex( table, key, value )
107 rawset( instancemeta, key, value)
110 -- The wrapper ctor that will be called by the user to instantiate the class.
111 -- It is not returned directly as a function, because we want the global class
112 -- definition to be a table so we can get things like the correpsonding
113 -- instance metatable from it for inheritance purpose, and the init function.
114 -- Note that native classes also expose their instance metatables the same way.
115 function classmeta.__call( func, ... )
116 obj = {}
118 for k,v in pairs( template ) do
119 obj[k] = v
122 setmetatable( obj, instancemeta )
123 ctor( obj, ... )
124 return obj
127 setmetatable( classtable, classmeta )
128 return classtable