X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Flib%2Foo.qh;h=3708552d5968c5d5bcfb1c976bd56cae9779fa63;hb=8cbf0e84432e075e617f43c037c645ea9846eba0;hp=4615ea970cd7b64bb210f03ad2218f6b03cda8a4;hpb=118e6c304a242d2de95978fdbf593a62c9d86073;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/lib/oo.qh b/qcsrc/lib/oo.qh index 4615ea970c..3708552d59 100644 --- a/qcsrc/lib/oo.qh +++ b/qcsrc/lib/oo.qh @@ -4,15 +4,9 @@ #include "nil.qh" #include "static.qh" -#ifdef MENUQC - #define NULL (0, null_entity) -#else - #define NULL (0, world) -#endif - .vector origin; .bool pure_data; -/** @deprecated, use new_pure or NEW(class) */ +/** @deprecated use new_pure or NEW(class) */ #define make_pure(e) \ MACRO_BEGIN \ { \ @@ -49,10 +43,10 @@ entity __spawn(string _classname, string _sourceLoc, bool pure) if (pure) { make_pure(this); #ifdef CSQC - setorigin(this, '0 0 10000'); + setorigin(this, (world.mins + world.maxs) * 0.5); #endif #ifdef SVQC - setorigin(this, '0 0 -10000'); + setorigin(this, (world.mins + world.maxs) * 0.5); #endif } return this; @@ -63,7 +57,7 @@ entity __spawn(string _classname, string _sourceLoc, bool pure) #define EVAL_entityclass(...) __VA_ARGS__ #define entityclass_1(name) entityclass_2(name, Object) #ifndef QCC_SUPPORT_ENTITYCLASS - #define entityclass_2(name, base) typedef entity name + #define entityclass_2(name, base) USING(name, entity) #define class(name) #define _new(class, pure) __spawn( #class, __FILE__ ":" STR(__LINE__), pure) #else @@ -105,20 +99,38 @@ void clearentity(entity e) // Classes have a `spawn##cname(entity)` constructor // The parameter is used across [[accumulate]] functions +.bool transmute; + // Macros to hide this implementation detail: #ifdef __STDC__ #define NEW(cname, ...) \ OVERLOAD_(spawn##cname, new_pure(cname) P99_IF_EMPTY(__VA_ARGS__)()(, __VA_ARGS__)) + + #define _TRANSMUTE(cname, this, ...) \ + OVERLOAD_(spawn##cname, this P99_IF_EMPTY(__VA_ARGS__)()(, __VA_ARGS__)) + #define CONSTRUCT(cname, ...) \ OVERLOAD_(spawn##cname, this P99_IF_EMPTY(__VA_ARGS__)()(, __VA_ARGS__)) #else #define NEW(cname, ...) \ OVERLOAD(spawn##cname, new_pure(cname),##__VA_ARGS__) + #define _TRANSMUTE(cname, this, ...) \ + OVERLOAD(spawn##cname, this,##__VA_ARGS__) + #define CONSTRUCT(cname, ...) \ OVERLOAD(spawn##cname, this,##__VA_ARGS__) #endif +#define TRANSMUTE(cname, this, ...) MACRO_BEGIN \ + entity _e = (this); \ + if (_e.vtblbase != cname##_vtbl) { \ + _e.transmute = true; \ + _e.classname = #cname; \ + _TRANSMUTE(cname, _e, __VA_ARGS__); \ + } \ + MACRO_END + #define CONSTRUCTOR(cname, ...) \ cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__) \ { \ @@ -136,7 +148,7 @@ STATIC_INIT(RegisterClasses) } #define VTBL(cname, base) \ - INIT_STATIC(cname); \ + _INIT_STATIC(cname); \ entity cname##_vtbl; \ void cname##_vtbl_init() \ { \ @@ -149,30 +161,32 @@ STATIC_INIT(RegisterClasses) } \ ACCUMULATE_FUNCTION(RegisterClasses, cname##_vtbl_init) -#define INIT_STATIC(cname) [[accumulate]] void spawn##cname##_static(cname this) +#define _INIT_STATIC(cname) [[accumulate]] void spawn##cname##_static(cname this) #define INIT(cname) [[accumulate]] cname spawn##cname##_1(cname this) #define CLASS(cname, base) \ entityclass(cname, base); \ - class(cname).bool instanceOf##cname; \ + class(cname).bool instanceOf##cname; \ bool is_##cname(entity e) { return e.instanceOf##cname; } \ + void isnt_##cname(entity e) { eprint(e); } \ VTBL(cname, base) \ - INIT_STATIC(cname) \ - { \ - if (cname##_vtbl) \ - { \ + _INIT_STATIC(cname) \ + { \ + if (cname##_vtbl && !this.transmute)\ + { \ copyentity(cname##_vtbl, this); \ return; \ } \ spawn##base##_static(this); \ this.instanceOf##cname = true; \ } \ - INIT(cname) \ - { \ + INIT(cname) \ + { \ /* Only statically initialize the current class, it contains everything it inherits */ \ if (cname##_vtbl.vtblname == this.classname) \ - { \ + { \ spawn##cname##_static(this); \ + this.transmute = false; \ this.classname = #cname; \ this.vtblname = string_null; \ this.vtblbase = cname##_vtbl; \ @@ -189,7 +203,7 @@ STATIC_INIT(RegisterClasses) #define METHOD(cname, name, prototype) \ STATIC_METHOD(cname, name, prototype); \ class(cname) .prototype name; \ - INIT_STATIC(cname) \ + _INIT_STATIC(cname) \ { \ this.name = METHOD_REFERENCE(cname, name); \ } \ @@ -200,6 +214,7 @@ STATIC_INIT(RegisterClasses) METHOD(cname, dtor, void(cname this)) \ { \ METHOD_REFERENCE(cname, dtorimpl)(this); \ + this.instanceOf##cname = false; \ entity super = SUPER(cname); \ if (super != cname##_vtbl) super.dtor(this); \ } \ @@ -213,6 +228,16 @@ STATIC_INIT(RegisterClasses) this.name = val; \ } +#define STATIC_ATTRIB(cname, name, type, val) \ + type cname##_##name; \ + _INIT_STATIC(cname) \ + { \ + noref bool strzone; /* Error on strzone() calls. */ \ + cname##_##name = val; \ + } + +// cleanup potentially zoned strings from base classes + #define ATTRIB_STRZONE(cname, name, type, val) \ class(cname).type name; \ INIT(cname) \ @@ -222,6 +247,15 @@ STATIC_INIT(RegisterClasses) this.name = strzone(val); \ } +#define STATIC_ATTRIB_STRZONE(cname, name, type, val) \ + type cname##_##name; \ + _INIT_STATIC(cname) \ + { \ + if (cname##_##name) \ + strunzone(cname##_##name); \ + cname##_##name = val; \ + } + #define ATTRIBARRAY(cname, name, type, cnt) \ class(cname).type name[cnt];