diff options
Diffstat (limited to '')
| -rw-r--r-- | src/studio.cpp | 65 |
1 files changed, 50 insertions, 15 deletions
diff --git a/src/studio.cpp b/src/studio.cpp index 1ca8ad7..44d1bb4 100644 --- a/src/studio.cpp +++ b/src/studio.cpp | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <cstdio> | 19 | #include <cstdio> |
| 20 | #include <cstring> | 20 | #include <cstring> |
| 21 | #include <dlfcn.h> | 21 | #include <dlfcn.h> |
| 22 | #include <time.h> | ||
| 22 | 23 | ||
| 23 | namespace { | 24 | namespace { |
| 24 | 25 | ||
| @@ -196,34 +197,37 @@ using ForceOverrideFn = void (*)(void *, void *, int); | |||
| 196 | void *g_modelrender = nullptr; | 197 | void *g_modelrender = nullptr; |
| 197 | ModelExecFn g_orig_model_exec = nullptr; | 198 | ModelExecFn g_orig_model_exec = nullptr; |
| 198 | ForceOverrideFn g_force_override = nullptr; | 199 | ForceOverrideFn g_force_override = nullptr; |
| 199 | void *g_chams_mat = nullptr; | 200 | void *g_style_mats[6] = {}; |
| 200 | int g_chams_mat_idx = -1; | 201 | |
| 202 | void *viewmodel_material(); | ||
| 201 | 203 | ||
| 202 | const char *chams_material_name(int idx) { | 204 | const char *chams_material_name(int idx) { |
| 203 | (void)idx; | 205 | switch (idx) { |
| 204 | // Only this debug material is reliably resident in the base game; the other | 206 | case 1: return "debug/debugwireframe"; |
| 205 | // debug VMTs are not loaded and FindMaterial does not make them available. | 207 | case 2: return "debug/additivevertexcolorvertexalpha"; |
| 206 | // Visual styles are applied as material flags instead. | 208 | case 3: return "debug/debugtranslucentsinglecolor"; |
| 207 | return "debug/debugtranslucentsinglecolor"; | 209 | case 4: return "debug/debugtranslucentvertexcolor"; |
| 210 | case 5: return "debug/debugmrmfullbright2"; | ||
| 211 | default: return "models/debug/debugwhite"; | ||
| 212 | } | ||
| 208 | } | 213 | } |
| 209 | 214 | ||
| 210 | void *chams_material() { | 215 | void *chams_material() { |
| 211 | int idx = g_chams_mat_index; | 216 | int idx = g_chams_mat_index; |
| 212 | if (idx < 0) idx = 0; | 217 | if (idx < 0) idx = 0; |
| 213 | if (idx > 5) idx = 5; | 218 | if (idx > 5) idx = 5; |
| 214 | if (g_chams_mat && g_chams_mat_idx == idx) | 219 | if (g_style_mats[idx]) |
| 215 | return g_chams_mat; | 220 | return g_style_mats[idx]; |
| 216 | g_chams_mat = world_find_material(chams_material_name(idx)); | 221 | if (g_style_mats[3]) |
| 217 | if (!g_chams_mat) | 222 | return g_style_mats[3]; |
| 218 | g_chams_mat = world_find_material("debug/debugtranslucentsinglecolor"); | 223 | return viewmodel_material(); |
| 219 | g_chams_mat_idx = idx; | ||
| 220 | logf("chams: style %d -> %p", idx, g_chams_mat); | ||
| 221 | return g_chams_mat; | ||
| 222 | } | 224 | } |
| 223 | 225 | ||
| 224 | // Viewmodels need a model shader; the VGUI white materials used by some | 226 | // Viewmodels need a model shader; the VGUI white materials used by some |
| 225 | // styles do not draw skinned models and make the hands/weapon disappear. | 227 | // styles do not draw skinned models and make the hands/weapon disappear. |
| 226 | void *viewmodel_material() { | 228 | void *viewmodel_material() { |
| 229 | if (g_style_mats[3]) | ||
| 230 | return g_style_mats[3]; | ||
| 227 | static void *mat = nullptr; | 231 | static void *mat = nullptr; |
| 228 | if (!mat) | 232 | if (!mat) |
| 229 | mat = world_find_material("debug/debugtranslucentsinglecolor"); | 233 | mat = world_find_material("debug/debugtranslucentsinglecolor"); |
| @@ -307,6 +311,37 @@ void hkdModelExecute(void *self, const void *state, const void *info, | |||
| 307 | 311 | ||
| 308 | } // namespace | 312 | } // namespace |
| 309 | 313 | ||
| 314 | static double chams_now() { | ||
| 315 | timespec ts; | ||
| 316 | clock_gettime(CLOCK_MONOTONIC, &ts); | ||
| 317 | return (double)ts.tv_sec + (double)ts.tv_nsec * 1e-9; | ||
| 318 | } | ||
| 319 | |||
| 320 | // Called from outer_draw (outside the model draw) so FindMaterial can load | ||
| 321 | // the style VMTs. The render hook only reads the cached pointers. | ||
| 322 | void chams_preload() { | ||
| 323 | static double last = 0.0; | ||
| 324 | static bool probed = false; | ||
| 325 | double now = chams_now(); | ||
| 326 | if (now - last < 1.5) | ||
| 327 | return; | ||
| 328 | last = now; | ||
| 329 | if (!probed) { | ||
| 330 | probed = true; | ||
| 331 | void *probe = world_find_material("vgui/white"); | ||
| 332 | logf("chams: probe vgui/white = %p", probe); | ||
| 333 | } | ||
| 334 | for (int i = 0; i < 6; i++) { | ||
| 335 | if (g_style_mats[i]) | ||
| 336 | continue; | ||
| 337 | void *m = world_find_material(chams_material_name(i)); | ||
| 338 | if (m) { | ||
| 339 | g_style_mats[i] = m; | ||
| 340 | logf("chams: preloaded style %d %s = %p", i, chams_material_name(i), m); | ||
| 341 | } | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 310 | void chams_init() { | 345 | void chams_init() { |
| 311 | if (g_modelrender || !g_iface.modelrender) { | 346 | if (g_modelrender || !g_iface.modelrender) { |
| 312 | if (!g_iface.modelrender) | 347 | if (!g_iface.modelrender) |
