]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/menu/oo/base.qh
Explain `CLASS` and `NEW` macros
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / oo / base.qh
index 55af8adb84cfa4ddbba23e7eb60f4089be48a557..5c74f0d6dffaca4a914b2ea2aedeceb5d7d4ef6b 100644 (file)
@@ -1,31 +1,71 @@
 #ifndef BASE_H
 #define BASE_H
 
+#include "../../common/util.qh"
+#include "../../dpdefs/keycodes.qh"
+
+#define NULL (null_entity)
+#define world NULL
+
 .string classname;
-entity Object_vtbl;
 .string vtblname;
 .entity vtblbase;
-// THIS LINE INTENTIONALLY LEFT BLANK
-entity spawnVtbl(entity e, entity b)
+entity spawnVtbl(entity this, entity base)
 {
-       entity v;
-       v = spawn();
-       copyentity(e, v);
-       v.vtblname = v.classname;
-       v.classname = "vtbl";
-       if(b)
-               v.vtblbase = b;
-       else
-               v.vtblbase = v;
-       return v;
+       entity vtbl = spawn();
+       copyentity(this, vtbl);
+       vtbl.vtblname = vtbl.classname;
+       vtbl.classname = "vtbl";
+       vtbl.vtblbase = base ? base : vtbl; // Top level objects use vtbl as base
+       return vtbl;
 }
-entity spawnObject()
+
+entity Object_vtbl;
+entity spawnObject(entity this, entity)
 {
-       entity e;
-       e = spawn();
-       e.classname = "Object";
-       if(!Object_vtbl)
-               Object_vtbl = spawnVtbl(e, null_entity);
-       return e;
+       this = spawn();
+       this.classname = "Object";
+       if (!Object_vtbl) Object_vtbl = spawnVtbl(this, null_entity);
+       return this;
+}
+
+// Classes have a `spawn##cname(entity, entity)` constructor
+// The parameters are used as locals for [[accumulate]]
+
+// Macro to hide this implementation detail
+#define NEW(cname) (spawn##cname(null_entity, null_entity))
+
+#define CLASS(cname, base)                                          \
+entity spawn##cname(entity this, entity basevtbl) {                 \
+    this = NEW(base); basevtbl = base##_vtbl;                       \
 }
-#endif
+
+#define METHOD(cname, name, prototype)                              \
+prototype cname##_##name;                                           \
+.prototype name;                                                    \
+[[accumulate]] entity spawn##cname(entity this, entity basevtbl) {  \
+    this.name = cname##_##name;                                     \
+}
+
+#define ATTRIB(cname, name, type, val)                              \
+.type name;                                                         \
+[[accumulate]] entity spawn##cname(entity this, entity basevtbl) {  \
+    this.name = val;                                                \
+}
+
+#define ATTRIBARRAY(cname, name, type, cnt)                         \
+.type name[cnt];
+
+#define ENDCLASS(cname)                                             \
+.bool instanceOf##cname;                                            \
+entity cname##_vtbl;                                                \
+[[last]] entity spawn##cname(entity this, entity basevtbl) {        \
+    this.instanceOf##cname = true;                                  \
+    this.classname = #cname;                                        \
+    if (!cname##_vtbl) cname##_vtbl = spawnVtbl(this, basevtbl);    \
+    return this;                                                    \
+}
+
+#define SUPER(cname) (cname##_vtbl.vtblbase)
+
+#endif
\ No newline at end of file