]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/oo.qh
Merge branch 'master' into TimePath/vehicles_cleanup
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / oo.qh
1 #ifndef OO_H
2 #define OO_H
3
4 #include "registry.qh"
5
6 #ifdef MENUQC
7     #define NULL (null_entity)
8 #else
9     #define NULL (world)
10 #endif
11
12 .string classname;
13 /** Location entity was spawned from in source */
14 .string sourceLocFile;
15 .int sourceLocLine;
16 entity _spawn();
17 entity __spawn(string _classname, string _sourceFile, int _sourceLine) {
18     entity this = _spawn();
19     this.classname = _classname;
20     this.sourceLocFile = _sourceFile;
21     this.sourceLocLine = _sourceLine;
22     return this;
23 }
24
25
26
27 #define entityclass(...) OVERLOAD(entityclass, __VA_ARGS__)
28 #define entityclass_1(name) entityclass_2(name, Object)
29 #ifndef QCC_SUPPORT_ENTITYCLASS
30     #define entityclass_2(name, base) typedef entity name
31     #define class(name)
32     #define new(class) __spawn(#class, __FILE__, __LINE__)
33 #else
34     #define entityclass_2(name, base) entityclass name : base {}
35     #define class(name) [[class(name)]]
36     #define new(class) ((class) __spawn(#class, __FILE__, __LINE__))
37 #endif
38
39 // Classes have a `spawn##cname(entity)` constructor
40 // The parameter is used across [[accumulate]] functions
41
42 // Macro to hide this implementation detail
43 #define NEW(cname, ...) \
44     OVERLOAD(spawn##cname, new(cname), ##__VA_ARGS__)
45
46 #define CONSTRUCT(cname, ...) \
47     OVERLOAD(spawn##cname, this, ##__VA_ARGS__)
48
49 #define CONSTRUCTOR(cname, ...) \
50     cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__)
51
52 .string vtblname;
53 .entity vtblbase;
54
55 void RegisterClasses() { }
56 ACCUMULATE_FUNCTION(__static_init, RegisterClasses)
57
58 #define VTBL(cname, base) \
59     INIT_STATIC(cname); \
60     entity cname##_vtbl; \
61     void cname##_vtbl_init() { \
62         cname e = new(vtbl); \
63         spawn##cname##_static(e); \
64         e.vtblname = #cname; \
65         /* Top level objects refer to themselves */ \
66         e.vtblbase = base##_vtbl ? base##_vtbl : e; \
67         cname##_vtbl = e; \
68     } \
69     ACCUMULATE_FUNCTION(RegisterClasses, cname##_vtbl_init)
70
71 #define INIT_STATIC(cname) [[accumulate]] void spawn##cname##_static(cname this)
72 #define INIT(cname) [[accumulate]] cname spawn##cname##_1(cname this)
73
74 #define CLASS(cname, base)                  \
75     entityclass(cname, base);               \
76     class(cname) .bool instanceOf##cname;   \
77     VTBL(cname, base)                       \
78     INIT_STATIC(cname) {                    \
79         if (cname##_vtbl) {                 \
80             copyentity(cname##_vtbl, this); \
81             return;                         \
82         }                                   \
83         spawn##base##_static(this);         \
84         this.instanceOf##cname = true;      \
85     }                                       \
86     INIT(cname) {                           \
87         /* Only statically initialize the current class, it contains everything it inherits */ \
88         if (cname##_vtbl.vtblname == this.classname) { \
89             spawn##cname##_static(this);    \
90             this.classname = #cname;        \
91             this.vtblname = string_null;    \
92             this.vtblbase = cname##_vtbl;   \
93         }                                   \
94         spawn##base##_1(this);              \
95     }
96
97 #define METHOD(cname, name, prototype)      \
98     class(cname) .prototype name;           \
99     prototype cname##_##name;               \
100     INIT_STATIC(cname) { this.name = cname##_##name; } \
101     prototype cname##_##name
102
103 #define ATTRIB(cname, name, type, val)      \
104     class(cname) .type name;                \
105     INIT(cname) { this.name = val; }
106
107 #define ATTRIBARRAY(cname, name, type, cnt) \
108     class(cname) .type name[cnt];
109
110 #define ENDCLASS(cname) \
111     [[last]] INIT(cname) { return this; }
112
113 #define SUPER(cname) (cname##_vtbl.vtblbase)
114
115 #define spawn_static(this)
116 #define spawn_1(this)
117 #define _vtbl NULL
118 CLASS(Object, ); ENDCLASS(Object)
119 #undef spawn_static
120 #undef spawn_1
121 #undef _vtbl
122
123 #endif