|
30 | 30 | //-----------------------------------------------------------------------------
|
31 | 31 | // Includes.
|
32 | 32 | //-----------------------------------------------------------------------------
|
| 33 | +// C++ |
| 34 | +#include <unordered_map> |
| 35 | +#include <vector> |
| 36 | + |
33 | 37 | #include "convar.h"
|
| 38 | + |
34 | 39 | #include "utilities/sp_util.h"
|
| 40 | +#include "modules/listeners/listeners_manager.h" |
| 41 | + |
| 42 | + |
| 43 | +//----------------------------------------------------------------------------- |
| 44 | +// Global ConVar changed callback mapping. |
| 45 | +//----------------------------------------------------------------------------- |
| 46 | +typedef std::vector<object> ChangedCallbacks; |
| 47 | +typedef std::unordered_map<std::string, ChangedCallbacks> ConVarMap; |
| 48 | +ConVarMap g_ConVarMap; |
35 | 49 |
|
36 | 50 |
|
37 | 51 | //-----------------------------------------------------------------------------
|
@@ -117,6 +131,88 @@ class ConVarExt
|
117 | 131 | pConVar->m_nFlags &= ~FCVAR_NOTIFY;
|
118 | 132 | g_pCVar->CallGlobalChangeCallbacks(pConVar, pConVar->GetString(), pConVar->GetFloat());
|
119 | 133 | }
|
| 134 | + |
| 135 | + static void ChangedCallback(IConVar* var, const char* pOldValue, float flOldValue) |
| 136 | + { |
| 137 | + ConVarMap::iterator map_it = g_ConVarMap.find(var->GetName()); |
| 138 | + if (map_it == g_ConVarMap.end()) |
| 139 | + return; |
| 140 | + |
| 141 | + ConVar* pConVar = static_cast<ConVar*>(var); |
| 142 | + |
| 143 | + ChangedCallbacks& callables = map_it->second; |
| 144 | + for (ChangedCallbacks::iterator it = callables.begin(); it != callables.end(); ++it) |
| 145 | + { |
| 146 | + BEGIN_BOOST_PY() |
| 147 | + (*it)(ptr(pConVar), pOldValue, pConVar->GetString()); |
| 148 | + END_BOOST_PY_NORET() |
| 149 | + } |
| 150 | + } |
| 151 | + |
| 152 | + static void AddChangedCallback(ConVar* pConVar, PyObject* pCallable) |
| 153 | + { |
| 154 | + // Get the object instance of the callable |
| 155 | + object oCallable = object(handle<>(borrowed(pCallable))); |
| 156 | + |
| 157 | + ChangedCallbacks& callables = g_ConVarMap[pConVar->GetName()]; |
| 158 | + if (!callables.size()) |
| 159 | + { |
| 160 | + if (!installed) |
| 161 | + { |
| 162 | + g_pCVar->InstallGlobalChangeCallback(ChangedCallback); |
| 163 | + installed = true; |
| 164 | + } |
| 165 | + } |
| 166 | + else |
| 167 | + { |
| 168 | + for (ChangedCallbacks::iterator it = callables.begin(); it != callables.end(); ++it) |
| 169 | + { |
| 170 | + if (is_same_func(oCallable, *it)) |
| 171 | + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Callback already registered.") |
| 172 | + } |
| 173 | + } |
| 174 | + |
| 175 | + callables.push_back(oCallable); |
| 176 | + } |
| 177 | + |
| 178 | + static void RemoveChangedCallback(ConVar* pConVar, PyObject* pCallable) |
| 179 | + { |
| 180 | + ConVarMap::iterator map_it = g_ConVarMap.find(pConVar->GetName()); |
| 181 | + if (map_it == g_ConVarMap.end()) |
| 182 | + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Callback not registered.") |
| 183 | + |
| 184 | + // Get the object instance of the callable |
| 185 | + object oCallable = object(handle<>(borrowed(pCallable))); |
| 186 | + |
| 187 | + ChangedCallbacks& callables = map_it->second; |
| 188 | + for (ChangedCallbacks::iterator it = callables.begin();;) |
| 189 | + { |
| 190 | + if(it == callables.end()) |
| 191 | + BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Callback not registered.") |
| 192 | + |
| 193 | + if (is_same_func(oCallable, *it)) |
| 194 | + { |
| 195 | + callables.erase(it); |
| 196 | + break; |
| 197 | + } |
| 198 | + else |
| 199 | + { |
| 200 | + ++it; |
| 201 | + } |
| 202 | + } |
| 203 | + |
| 204 | + if (!callables.size()) |
| 205 | + { |
| 206 | + g_ConVarMap.erase(map_it); |
| 207 | + if (!g_ConVarMap.size()) |
| 208 | + { |
| 209 | + g_pCVar->RemoveGlobalChangeCallback(ChangedCallback); |
| 210 | + installed = false; |
| 211 | + } |
| 212 | + } |
| 213 | + } |
| 214 | + |
| 215 | + static bool installed; |
120 | 216 | };
|
121 | 217 |
|
122 | 218 |
|
|
0 commit comments