]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/oo.qh
Cleanup OO macros
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / oo.qh
index 63b17089e48c0a8d080e30b797f46b689fd4385f..b2b8b0ad29305ef962c5c01c270d5628c10fb095 100644 (file)
@@ -1,71 +1,99 @@
 #ifndef OO_H
 #define OO_H
 
+#include "registry.qh"
+
 #ifdef MENUQC
-       #define NULL (null_entity)
+    #define NULL (null_entity)
 #else
-       #define NULL (world)
+    #define NULL (world)
 #endif
 
 .string classname;
-.string vtblname;
-.entity vtblbase;
-entity spawnVtbl(entity this, entity base)
-{
-       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;
+/** Location entity was spawned from in source */
+.string sourceLocFile;
+.int sourceLocLine;
+entity _spawn();
+entity __spawn(string _classname, string _sourceFile, int _sourceLine) {
+    entity this = _spawn();
+    this.classname = _classname;
+    this.sourceLocFile = _sourceFile;
+    this.sourceLocLine = _sourceLine;
+    return this;
 }
 
-entity Object_vtbl;
-entity spawnObject(entity this, entity)
-{
-       this = spawn();
-       this.classname = "Object";
-       if (!Object_vtbl) Object_vtbl = spawnVtbl(this, NULL);
-       return this;
-}
+#define entityclass(...) OVERLOAD(entityclass, __VA_ARGS__)
+#define entityclass_1(name) entityclass_2(name, Object)
+#ifndef QCC_SUPPORT_ENTITYCLASS
+    #define entityclass_2(name, base) typedef entity name
+    #define class(name)
+    #define new(class) __spawn(#class, __FILE__, __LINE__)
+#else
+    #define entityclass_2(name, base) entityclass name : base {}
+    #define class(name) [[class(name)]]
+    #define new(class) ((class) __spawn(#class, __FILE__, __LINE__))
+#endif
 
-// Classes have a `spawn##cname(entity, entity)` constructor
-// The parameters are used as locals for [[accumulate]]
+// Classes have a `spawn##cname(entity)` constructor
+// The parameter is used across [[accumulate]] functions
 
 // Macro to hide this implementation detail
-#define NEW(cname) (spawn##cname(NULL, NULL))
+#define NEW(cname) (spawn##cname(new(cname)))
 
-#define CLASS(cname, base)                                                     \
-entity spawn##cname(entity this, entity basevtbl) {                            \
-    this = NEW(base); basevtbl = base##_vtbl;                                  \
-}
+.string vtblname;
+.entity vtblbase;
 
-#define METHOD(cname, name, prototype)                                         \
-prototype cname##_##name;                                                      \
-.prototype name;                                                               \
-[[accumulate]] entity spawn##cname(entity this, entity basevtbl) {             \
-    this.name = cname##_##name;                                                \
-}
+#define VTBL(cname, base) \
+    entity cname##_vtbl; \
+    STATIC_INIT(cname##_vtbl) { \
+        entity e = NEW(cname); \
+        e.vtblname = #cname; \
+        e.classname = "vtbl"; \
+        /* Top level objects refer to themselves */ \
+        e.vtblbase = base ? base : e; \
+        cname##_vtbl = e; \
+    }
 
-#define ATTRIB(cname, name, type, val)                                         \
-.type name;                                                                    \
-[[accumulate]] entity spawn##cname(entity this, entity basevtbl) {             \
-    this.name = val;                                                           \
-}
+#define INIT_STATIC(cname) [[accumulate]] entity spawn##cname(entity this)
+#define INIT(cname) [[accumulate]] void spawn##cname##_init(entity this)
 
-#define ATTRIBARRAY(cname, name, type, cnt)                                    \
-.type name[cnt];
-
-#define ENDCLASS(cname)                                                        \
-.bool instanceOf##cname;                                                       \
-entity cname##_vtbl;                                                           \
-[[accumulate]] [[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 CLASS(cname, base)                  \
+    entityclass(cname, base);               \
+    class(cname) .bool instanceOf##cname;   \
+    INIT(cname) { }                         \
+    INIT_STATIC(cname);                     \
+    VTBL(cname, base##_vtbl)                \
+    INIT_STATIC(cname) {                    \
+        if (cname##_vtbl) {                 \
+            copyentity(cname##_vtbl, this); \
+            spawn##cname##_init(this);      \
+            return this;                    \
+        }                                   \
+        spawn##base(this);                  \
+        this.instanceOf##cname = true;      \
+    }
+
+#define METHOD(cname, name, prototype)      \
+    class(cname) .prototype name;           \
+    prototype cname##_##name;               \
+    INIT_STATIC(cname) { this.name = cname##_##name; }
+
+#define ATTRIB(cname, name, type, val)      \
+    class(cname) .type name;                \
+    INIT(cname) { this.name = val; }
+
+#define ATTRIBARRAY(cname, name, type, cnt) \
+    class(cname) .type name[cnt];
+
+#define ENDCLASS(cname) \
+    [[last]] INIT_STATIC(cname) { return this; }
 
 #define SUPER(cname) (cname##_vtbl.vtblbase)
 
+#define spawnNULL(e)
+#define NULL_vtbl NULL
+
+CLASS(Object, NULL)
+ENDCLASS(Object)
+
 #endif