Merge remote-tracking branch 'remotes/origin/master' into TimePath/itemsys
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / oo.qh
1 #ifndef OO_H
2 #define OO_H
3
4 #ifdef MENUQC
5         #define NULL (null_entity)
6 #else
7         #define NULL (world)
8 #endif
9
10 .string classname;
11 .string vtblname;
12 .entity vtblbase;
13 entity spawnVtbl(entity this, entity base)
14 {
15         entity vtbl = spawn();
16         copyentity(this, vtbl);
17         vtbl.vtblname = vtbl.classname;
18         vtbl.classname = "vtbl";
19         vtbl.vtblbase = base ? base : vtbl; // Top level objects use vtbl as base
20         return vtbl;
21 }
22
23 entity Object_vtbl;
24 entity spawnObject(entity this, entity)
25 {
26         this = spawn();
27         this.classname = "Object";
28         if (!Object_vtbl) Object_vtbl = spawnVtbl(this, NULL);
29         return this;
30 }
31
32 // Classes have a `spawn##cname(entity, entity)` constructor
33 // The parameters are used as locals for [[accumulate]]
34
35 // Macro to hide this implementation detail
36 #define NEW(cname) (spawn##cname(NULL, NULL))
37
38 #define CLASS(cname, base)                                                      \
39 entity spawn##cname(entity this, entity basevtbl) {                             \
40     this = NEW(base); basevtbl = base##_vtbl;                                   \
41 }
42
43 #define METHOD(cname, name, prototype)                                          \
44 prototype cname##_##name;                                                       \
45 .prototype name;                                                                \
46 [[accumulate]] entity spawn##cname(entity this, entity basevtbl) {              \
47     this.name = cname##_##name;                                                 \
48 }
49
50 #define ATTRIB(cname, name, type, val)                                          \
51 .type name;                                                                     \
52 [[accumulate]] entity spawn##cname(entity this, entity basevtbl) {              \
53     this.name = val;                                                            \
54 }
55
56 #define ATTRIBARRAY(cname, name, type, cnt)                                     \
57 .type name[cnt];
58
59 #define ENDCLASS(cname)                                                         \
60 .bool instanceOf##cname;                                                        \
61 entity cname##_vtbl;                                                            \
62 [[accumulate]] [[last]] entity spawn##cname(entity this, entity basevtbl) {     \
63     this.instanceOf##cname = true;                                              \
64     this.classname = #cname;                                                    \
65     if (!cname##_vtbl) cname##_vtbl = spawnVtbl(this, basevtbl);                \
66     return this;                                                                \
67 }
68
69 #define SUPER(cname) (cname##_vtbl.vtblbase)
70
71 #endif