X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Foo.qh;h=b2b8b0ad29305ef962c5c01c270d5628c10fb095;hb=08fe11af2394bba3cbeae74370269d6c63840969;hp=63b17089e48c0a8d080e30b797f46b689fd4385f;hpb=fcf4579b494a225ae17c64ccb3acf802c841245c;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/oo.qh b/qcsrc/common/oo.qh index 63b17089e..b2b8b0ad2 100644 --- a/qcsrc/common/oo.qh +++ b/qcsrc/common/oo.qh @@ -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