diff options
Diffstat (limited to '')
| -rw-r--r-- | src/world.cpp | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/world.cpp b/src/world.cpp index 2fa1fc4..ab0c134 100644 --- a/src/world.cpp +++ b/src/world.cpp | |||
| @@ -999,3 +999,50 @@ void skybox_update() { | |||
| 999 | g_sky_retry_at = now + 1.0; | 999 | g_sky_retry_at = now + 1.0; |
| 1000 | } | 1000 | } |
| 1001 | } | 1001 | } |
| 1002 | |||
| 1003 | // Find a loaded material by its full name (e.g. "models/debug/debugwhite"). | ||
| 1004 | // Used by chams; walks the material list like the tint code and falls back to | ||
| 1005 | // FindMaterial if the material is not currently resident. | ||
| 1006 | void *world_find_material(const char *name) { | ||
| 1007 | if (!name || !*name) | ||
| 1008 | return nullptr; | ||
| 1009 | void *ms = material_system(); | ||
| 1010 | if (!ms) | ||
| 1011 | return nullptr; | ||
| 1012 | using FirstFn = unsigned short (*)(void *); | ||
| 1013 | using NextFn = unsigned short (*)(void *, unsigned short); | ||
| 1014 | using InvalidFn = unsigned short (*)(void *); | ||
| 1015 | using GetFn = void *(*)(void *, unsigned short); | ||
| 1016 | using CountFn = int (*)(void *); | ||
| 1017 | using NameFn = const char *(*)(void *); | ||
| 1018 | FirstFn first = (FirstFn)vfunc<FirstFn>(ms, 73); | ||
| 1019 | NextFn next = (NextFn)vfunc<NextFn>(ms, 74); | ||
| 1020 | InvalidFn invalid = (InvalidFn)vfunc<InvalidFn>(ms, 75); | ||
| 1021 | GetFn get = (GetFn)vfunc<GetFn>(ms, 76); | ||
| 1022 | CountFn count = (CountFn)vfunc<CountFn>(ms, 77); | ||
| 1023 | int total = count ? count(ms) : 0; | ||
| 1024 | if (total > 0 && total < 200000) { | ||
| 1025 | unsigned short h = first(ms); | ||
| 1026 | unsigned short inv = invalid(ms); | ||
| 1027 | for (int i = 0; i < total && h != inv; i++) { | ||
| 1028 | void *mat = get(ms, h); | ||
| 1029 | if (mat) { | ||
| 1030 | NameFn mat_name = (NameFn)vfunc<NameFn>(mat, 0); | ||
| 1031 | const char *n = mat_name(mat); | ||
| 1032 | if (n && strcmp(n, name) == 0) | ||
| 1033 | return mat; | ||
| 1034 | } | ||
| 1035 | h = next(ms, h); | ||
| 1036 | } | ||
| 1037 | } | ||
| 1038 | // Not resident yet: let the material system load it. FindMaterial is slot | ||
| 1039 | // 71 (IsMaterialLoaded is 72, FirstMaterial 73). | ||
| 1040 | using FindFn = void *(*)(void *, const char *, const char *, bool, | ||
| 1041 | const char *); | ||
| 1042 | void *mat = vfunc<FindFn>(ms, 71)(ms, name, "Model textures", false, nullptr); | ||
| 1043 | if (!mat) | ||
| 1044 | return nullptr; | ||
| 1045 | NameFn mat_name = (NameFn)vfunc<NameFn>(mat, 0); | ||
| 1046 | const char *n = mat_name(mat); | ||
| 1047 | return (n && strcmp(n, name) == 0) ? mat : nullptr; | ||
| 1048 | } | ||
