diff options
Diffstat (limited to '')
| -rw-r--r-- | src/world.cpp | 73 |
1 files changed, 41 insertions, 32 deletions
diff --git a/src/world.cpp b/src/world.cpp index 897ad0a..a2e65cc 100644 --- a/src/world.cpp +++ b/src/world.cpp | |||
| @@ -1015,20 +1015,19 @@ void *world_find_material(const char *name) { | |||
| 1015 | using GetFn = void *(*)(void *, unsigned short); | 1015 | using GetFn = void *(*)(void *, unsigned short); |
| 1016 | using CountFn = int (*)(void *); | 1016 | using CountFn = int (*)(void *); |
| 1017 | using NameFn = const char *(*)(void *); | 1017 | using NameFn = const char *(*)(void *); |
| 1018 | using FindFn = void *(*)(void *, const char *, const char *, bool, | ||
| 1019 | const char *); | ||
| 1018 | FirstFn first = (FirstFn)vfunc<FirstFn>(ms, 73); | 1020 | FirstFn first = (FirstFn)vfunc<FirstFn>(ms, 73); |
| 1019 | NextFn next = (NextFn)vfunc<NextFn>(ms, 74); | 1021 | NextFn next = (NextFn)vfunc<NextFn>(ms, 74); |
| 1020 | InvalidFn invalid = (InvalidFn)vfunc<InvalidFn>(ms, 75); | 1022 | InvalidFn invalid = (InvalidFn)vfunc<InvalidFn>(ms, 75); |
| 1021 | GetFn get = (GetFn)vfunc<GetFn>(ms, 76); | 1023 | GetFn get = (GetFn)vfunc<GetFn>(ms, 76); |
| 1022 | CountFn count = (CountFn)vfunc<CountFn>(ms, 77); | 1024 | CountFn count = (CountFn)vfunc<CountFn>(ms, 77); |
| 1023 | const char *candidates[] = {name, | 1025 | static const char *groups[] = {"Model textures", "Other textures", nullptr}; |
| 1024 | "models/debug/debugwhite2", | 1026 | |
| 1025 | "models/debug/debugwhite3", | 1027 | auto walk = [&](const char *want) -> void * { |
| 1026 | "vgui/white", | 1028 | int total = count ? count(ms) : 0; |
| 1027 | "debug/debugtranslucentsinglecolor", | 1029 | if (total <= 0 || total >= 200000) |
| 1028 | "debug/debugwireframevertexcolorignorez", | 1030 | return nullptr; |
| 1029 | nullptr}; | ||
| 1030 | int total = count ? count(ms) : 0; | ||
| 1031 | if (total > 0 && total < 200000) { | ||
| 1032 | unsigned short h = first(ms); | 1031 | unsigned short h = first(ms); |
| 1033 | unsigned short inv = invalid(ms); | 1032 | unsigned short inv = invalid(ms); |
| 1034 | for (int i = 0; i < total && h != inv; i++) { | 1033 | for (int i = 0; i < total && h != inv; i++) { |
| @@ -1036,38 +1035,48 @@ void *world_find_material(const char *name) { | |||
| 1036 | if (mat) { | 1035 | if (mat) { |
| 1037 | NameFn mat_name = (NameFn)vfunc<NameFn>(mat, 0); | 1036 | NameFn mat_name = (NameFn)vfunc<NameFn>(mat, 0); |
| 1038 | const char *n = mat_name(mat); | 1037 | const char *n = mat_name(mat); |
| 1039 | if (n) { | 1038 | if (n && strcmp(n, want) == 0) |
| 1040 | for (int c = 0; candidates[c]; c++) | 1039 | return mat; |
| 1041 | if (strcmp(n, candidates[c]) == 0) { | ||
| 1042 | logf("chams: material %s = %p", n, mat); | ||
| 1043 | return mat; | ||
| 1044 | } | ||
| 1045 | } | ||
| 1046 | } | 1040 | } |
| 1047 | h = next(ms, h); | 1041 | h = next(ms, h); |
| 1048 | } | 1042 | } |
| 1049 | } | 1043 | return nullptr; |
| 1050 | // Not resident yet: let the material system load it. | 1044 | }; |
| 1051 | using FindFn = void *(*)(void *, const char *, const char *, bool, | 1045 | auto find = [&](const char *want) -> void * { |
| 1052 | const char *); | ||
| 1053 | static const char *groups[] = {"Model textures", "Other textures", nullptr}; | ||
| 1054 | for (int c = 0; candidates[c]; c++) { | ||
| 1055 | for (int g = 0; groups[g]; g++) { | 1046 | for (int g = 0; groups[g]; g++) { |
| 1056 | void *mat = vfunc<FindFn>(ms, 71)(ms, candidates[c], groups[g], false, | 1047 | void *mat = vfunc<FindFn>(ms, 71)(ms, want, groups[g], false, nullptr); |
| 1057 | nullptr); | ||
| 1058 | if (!mat) | 1048 | if (!mat) |
| 1059 | continue; | 1049 | continue; |
| 1060 | NameFn mat_name = (NameFn)vfunc<NameFn>(mat, 0); | 1050 | NameFn mat_name = (NameFn)vfunc<NameFn>(mat, 0); |
| 1061 | const char *n = mat_name(mat); | 1051 | const char *n = mat_name(mat); |
| 1062 | if (!n) | 1052 | if (n && strcmp(n, want) == 0) |
| 1063 | continue; | 1053 | return mat; |
| 1064 | for (int k = 0; candidates[k]; k++) { | 1054 | } |
| 1065 | if (strcmp(n, candidates[k]) == 0) { | 1055 | return nullptr; |
| 1066 | logf("chams: material %s = %p (FindMaterial)", n, mat); | 1056 | }; |
| 1067 | return mat; | 1057 | |
| 1068 | } | 1058 | // First the exact style requested (resident or loaded on demand), then only |
| 1069 | } | 1059 | // the basic white fallbacks. Returning vgui/white before trying the exact |
| 1060 | // name made every style look identical. | ||
| 1061 | void *mat = walk(name); | ||
| 1062 | if (!mat) | ||
| 1063 | mat = find(name); | ||
| 1064 | if (mat) { | ||
| 1065 | logf("chams: material %s = %p", name, mat); | ||
| 1066 | return mat; | ||
| 1067 | } | ||
| 1068 | static const char *fallbacks[] = {"models/debug/debugwhite", "vgui/white", | ||
| 1069 | nullptr}; | ||
| 1070 | for (int i = 0; fallbacks[i]; i++) { | ||
| 1071 | mat = walk(fallbacks[i]); | ||
| 1072 | if (!mat) | ||
| 1073 | mat = find(fallbacks[i]); | ||
| 1074 | if (mat) { | ||
| 1075 | logf("chams: material %s (fallback for %s) = %p", fallbacks[i], name, | ||
| 1076 | mat); | ||
| 1077 | return mat; | ||
| 1070 | } | 1078 | } |
| 1071 | } | 1079 | } |
| 1080 | logf("chams: material %s not found", name); | ||
| 1072 | return nullptr; | 1081 | return nullptr; |
| 1073 | } | 1082 | } |
