]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/lib/deglobalization.qh
declare vars explicitly
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / deglobalization.qh
1 #include "lib/float.qh"
2 #include "lib/misc.qh"
3 #include "lib/static.qh"
4 #include "lib/vector.qh"
5
6 // These macros wrap functions which use globals so mutation only occurs inside them and is not visible from outside.
7 // Functions for which all usages are replaced with these macros can be hidden by #defines inside our `*defs.qh` files
8 // to prevent anyone from using them accidentally in the future
9
10 // TODO stuff in the engine that uses the v_forward/v_right/v_up globals and is not wrapped yet:
11 //  - RF_USEAXIS, addentities, predraw,
12 //    - CL_GetEntityMatrix (in engine but is called from other functions so transitively any of them can use the globals - e.g. V_CalcRefdef, maybe others)
13 //    - however RF_USEAXIS is only used if MF_ROTATE is used which is only set in one place
14 //  - e.camera_transform / CL_VM_TransformView (in engine)
15 //    - this is the only used function that both sets and gets the globals (aim does too but isn't used in our code)
16
17 // convenience for deglobalization code - don't use these just to hide that globals are still used
18 #define CLEAR_V_GLOBALS() v_forward = VEC_NAN; v_right = VEC_NAN; v_up = VEC_NAN
19 #define GET_V_GLOBALS(forward, right, up) forward = v_forward; right = v_right; up = v_up
20 #define SET_V_GLOBALS(forward, right, up) v_forward = forward; v_right = right; v_up = up
21
22 #ifdef GAMEQC
23 STATIC_INIT(globals) {
24         // set to NaN to more easily detect uninitialized use
25         // TODO when all functions are wrapped and the raw functions are not used anymore,
26         // uncomment the defines in *progs.qh files that hide the raw functions
27         // and assert that the global vectors are NaN before calling the raw functions here
28         // to make sure nobody (even builtins) is accidentally using them - NaN is the most likely value to expose remaining usages
29
30         CLEAR_V_GLOBALS();
31 }
32 #endif
33
34 /// Same as the `makevectors` builtin but uses the provided locals instead of the `v_*` globals.
35 /// Always use this instead of raw `makevectors` to make the data flow clear.
36 /// Note that you might prefer `FIXED_MAKE_VECTORS` for new code.
37 #define MAKE_VECTORS(angles, forward, right, up) MACRO_BEGIN \
38         _makevectors_hidden(angles); \
39         GET_V_GLOBALS(forward, right, up); \
40         CLEAR_V_GLOBALS(); \
41 MACRO_END
42
43 /// Returns all 4 vectors by assigning to them (instead of returning a value) for consistency (and sanity)
44 #define SKEL_GET_BONE_ABS(skel, bonenum, forward, right, up, origin) MACRO_BEGIN \
45         origin = _skel_get_boneabs_hidden(skel, bonenum) \
46         GET_V_GLOBALS(forward, right, up); \
47         CLEAR_V_GLOBALS(); \
48 MACRO_END
49
50 #define SKEL_SET_BONE(skel, bonenum, org, forward, right, up) MACRO_BEGIN \
51         SET_V_GLOBALS(forward, right, up); \
52         _skel_set_bone_hidden(skel, bonenum, org); \
53         CLEAR_V_GLOBALS(); \
54 MACRO_END
55
56 #define ADD_DYNAMIC_LIGHT(org, radius, lightcolours, forward, right, up) MACRO_BEGIN \
57         SET_V_GLOBALS(forward, right, up); \
58         _adddynamiclight_hidden(org, radius, lightcolours); \
59         CLEAR_V_GLOBALS(); \
60 MACRO_END
61
62 #define VECTOR_VECTORS(forward_in, forward, right, up) MACRO_BEGIN \
63         _vectorvectors_hidden(forward_in); \
64         GET_V_GLOBALS(forward, right, up); \
65         CLEAR_V_GLOBALS(); \
66 MACRO_END
67
68 /// Note that this only avoids the v_* globals, not the gettaginfo_* ones
69 #define GET_TAG_INFO(ent, tagindex, forward, right, up, origin) MACRO_BEGIN \
70         origin = _gettaginfo_hidden(ent, tagindex); \
71         GET_V_GLOBALS(forward, right, up); \
72         CLEAR_V_GLOBALS(); \
73 MACRO_END