365 lines
11 KiB
C++
365 lines
11 KiB
C++
#include "binds.h"
|
|
#include "constants.h"
|
|
#include "main/references.h"
|
|
#include "main/initialization.h"
|
|
#include "scripts/manager.h"
|
|
#include "files.h"
|
|
#include <string>
|
|
#include "main/logging.h"
|
|
|
|
namespace scripts {
|
|
|
|
struct ScriptedKeybind : profile::Keybind {
|
|
scripts::Manager* manager;
|
|
asIScriptFunction* func;
|
|
|
|
ScriptedKeybind(scripts::Manager* man, asIScriptFunction* Func)
|
|
: manager(man), func(Func) {
|
|
}
|
|
|
|
void call(bool pressed) {
|
|
if(func) {
|
|
Call cl = manager->call(func);
|
|
cl.push(pressed);
|
|
cl.call();
|
|
}
|
|
}
|
|
};
|
|
|
|
static void cb_keybind(profile::BindGroup* grp, const std::string& name, const std::string& str) {
|
|
std::string decl("void ");
|
|
decl += str;
|
|
decl += "(bool)";
|
|
|
|
asIScriptContext* ctx = asGetActiveContext();
|
|
asIScriptFunction* func = ctx->GetFunction();
|
|
|
|
const char* module = func->GetModuleName();
|
|
|
|
Manager* manager = scripts::getActiveManager();
|
|
asIScriptFunction* scrFunc = manager->getFunction(module, decl.c_str());
|
|
|
|
if(scrFunc) {
|
|
grp->addBind(name, new ScriptedKeybind(manager, scrFunc));
|
|
}
|
|
else {
|
|
error("Could not locate function '%s::%s'", module, decl.c_str());
|
|
}
|
|
}
|
|
|
|
static void cb_keybind_id(profile::BindGroup* grp, unsigned id, const std::string& str) {
|
|
std::string decl("void ");
|
|
decl += str;
|
|
decl += "(bool)";
|
|
|
|
asIScriptContext* ctx = asGetActiveContext();
|
|
asIScriptFunction* func = ctx->GetFunction();
|
|
|
|
const char* module = func->GetModuleName();
|
|
|
|
Manager* manager = scripts::getActiveManager();
|
|
asIScriptFunction* scrFunc = manager->getFunction(module, decl.c_str());
|
|
|
|
if(scrFunc) {
|
|
grp->addBind(id, new ScriptedKeybind(manager, scrFunc));
|
|
}
|
|
else {
|
|
error("Could not locate function '%s::%s'", module, decl.c_str());
|
|
}
|
|
}
|
|
|
|
static void cb_save_kb() {
|
|
std::string bindFile = path_join(devices.mods.getProfile("settings"), "keybinds.txt");
|
|
devices.keybinds.saveBinds(bindFile);
|
|
}
|
|
|
|
static void cb_set_kb(profile::BindGroup* grp, int key, unsigned id) {
|
|
grp->setBind(key, id);
|
|
}
|
|
|
|
static void cb_clear_kb(profile::BindGroup* grp, int key) {
|
|
grp->clearBind(key);
|
|
}
|
|
|
|
static void cb_clear_kb_bind(profile::BindGroup* grp, unsigned id) {
|
|
grp->clearBinds(id);
|
|
}
|
|
|
|
static void cb_setdef_kb(profile::BindGroup* grp, unsigned id) {
|
|
grp->setDefaultBinds(id);
|
|
}
|
|
|
|
static void cb_setdef_kb_all(profile::BindGroup* grp) {
|
|
grp->setDefaultBinds();
|
|
}
|
|
|
|
static unsigned cb_defcount(profile::BindGroup* grp, unsigned id) {
|
|
return grp->getDefaultCount(id);
|
|
}
|
|
|
|
static int cb_defkey(profile::BindGroup* grp, unsigned id, unsigned index) {
|
|
return grp->getDefaultKey(id, index);
|
|
}
|
|
|
|
static unsigned cb_curcount(profile::BindGroup* grp, unsigned id) {
|
|
return grp->getBindCount(id);
|
|
}
|
|
|
|
static int cb_curkey(profile::BindGroup* grp, unsigned id, unsigned index) {
|
|
return grp->getBindKey(id, index);
|
|
}
|
|
|
|
static unsigned cb_count(profile::BindGroup* grp) {
|
|
return grp->descriptors.size();
|
|
}
|
|
|
|
static std::string cb_name(profile::BindGroup* grp, unsigned id) {
|
|
if(id >= grp->descriptors.size()) {
|
|
scripts::throwException("Keybind id out of bounds.");
|
|
return "";
|
|
}
|
|
|
|
return grp->descriptors[id].name;
|
|
}
|
|
|
|
static unsigned cb_group_cnt() {
|
|
return devices.keybinds.groups.size();
|
|
}
|
|
|
|
static int cb_getbind(profile::BindGroup* grp, int key) {
|
|
return grp->getBindID(key);
|
|
}
|
|
|
|
static profile::BindGroup* cb_group(unsigned i) {
|
|
if(i >= devices.keybinds.groups.size()) {
|
|
scripts::throwException("Group index out of bounds.");
|
|
return 0;
|
|
}
|
|
|
|
return devices.keybinds.groups[i];
|
|
}
|
|
|
|
static int mod_key(int key) {
|
|
int mod_key = key;
|
|
if(mod_key >= 'A' && mod_key <= 'Z')
|
|
mod_key += 'a'-'A';
|
|
if(devices.driver->ctrlKey)
|
|
mod_key |= profile::Mod_Ctrl;
|
|
if(devices.driver->altKey)
|
|
mod_key |= profile::Mod_Alt;
|
|
if(devices.driver->shiftKey)
|
|
mod_key |= profile::Mod_Shift;
|
|
return mod_key;
|
|
}
|
|
|
|
#define stAccess(type) \
|
|
void setSetting_ ## type (const std::string& name, type value) { \
|
|
auto* v = devices.settings.mod.getSetting(name);\
|
|
if(!v)\
|
|
v = devices.settings.engine.getSetting(name);\
|
|
if(!v) {\
|
|
scripts::throwException("Invalid setting name.");\
|
|
return;\
|
|
}\
|
|
*v = value;\
|
|
}\
|
|
type getSetting_ ## type (const std::string& name) { \
|
|
auto* v = devices.settings.mod.getSetting(name);\
|
|
if(!v)\
|
|
v = devices.settings.engine.getSetting(name);\
|
|
if(!v) {\
|
|
scripts::throwException("Invalid setting name.");\
|
|
return 0;\
|
|
}\
|
|
return *v;\
|
|
}\
|
|
|
|
stAccess(int);
|
|
stAccess(double);
|
|
stAccess(bool);
|
|
|
|
#define stMinMax(type, v_min, v_max) \
|
|
type getSetting_min_ ##type (const std::string& name) { \
|
|
auto* v = devices.settings.mod.getSetting(name);\
|
|
if(!v)\
|
|
v = devices.settings.engine.getSetting(name);\
|
|
if(!v) {\
|
|
scripts::throwException("Invalid setting name.");\
|
|
return 0;\
|
|
}\
|
|
return v->v_min;\
|
|
}\
|
|
type getSetting_max_ ##type (const std::string& name) { \
|
|
auto* v = devices.settings.mod.getSetting(name);\
|
|
if(!v)\
|
|
v = devices.settings.engine.getSetting(name);\
|
|
if(!v) {\
|
|
scripts::throwException("Invalid setting name.");\
|
|
return 0;\
|
|
}\
|
|
return v->v_max;\
|
|
}\
|
|
|
|
stMinMax(int, num_min, num_max);
|
|
stMinMax(double, flt_min, flt_max);
|
|
|
|
void setSetting_str(const std::string& name, const std::string& value) {
|
|
auto* v = devices.settings.mod.getSetting(name);
|
|
if(!v)
|
|
v = devices.settings.engine.getSetting(name);
|
|
if(!v) {
|
|
scripts::throwException("Invalid setting name.");
|
|
return;
|
|
}
|
|
v->setString(value);
|
|
}
|
|
|
|
const std::string errstr("ERR");
|
|
const std::string& getSetting_str(const std::string& name) {
|
|
auto* v = devices.settings.mod.getSetting(name);
|
|
if(!v)
|
|
v = devices.settings.engine.getSetting(name);
|
|
if(!v) {
|
|
scripts::throwException("Invalid setting name.");
|
|
return errstr;
|
|
}
|
|
std::string* str = v->getString();
|
|
if(!str) {
|
|
scripts::throwException("Setting is not a string setting.");
|
|
return errstr;
|
|
}
|
|
return *str;
|
|
}
|
|
|
|
void applySettings() {
|
|
if(game_running && devices.scripts.client) {
|
|
scripts::MultiCall cl = devices.scripts.client->call(SC_settings_changed);
|
|
cl.call();
|
|
}
|
|
else if(devices.scripts.menu) {
|
|
scripts::MultiCall cl = devices.scripts.menu->call(SC_settings_changed);
|
|
cl.call();
|
|
}
|
|
}
|
|
|
|
void saveSettings() {
|
|
devices.settings.engine.saveSettings(path_join(getProfileRoot(), "settings.txt"));
|
|
devices.settings.mod.saveSettings(path_join(devices.mods.getProfile("settings"), "settings.txt"));
|
|
}
|
|
|
|
void RegisterProfileBinds() {
|
|
//Bind dynamic enum for registered keybinds
|
|
EnumBind kb("Keybind");
|
|
kb["KB_NONE"] = -1;
|
|
foreach(it, devices.keybinds.groups) {
|
|
profile::BindGroup* grp = *it;
|
|
for(unsigned i = 0; i < grp->descriptors.size(); ++i) {
|
|
auto& bind = grp->descriptors[i];
|
|
kb[std::string("KB_")+bind.name] = i;
|
|
}
|
|
}
|
|
|
|
kb["MASK_CTRL"] = profile::Mod_Ctrl;
|
|
kb["MASK_ALT"] = profile::Mod_Alt;
|
|
kb["MASK_SHIFT"] = profile::Mod_Shift;
|
|
|
|
ClassBind grp("KeybindGroup", asOBJ_REF | asOBJ_NOCOUNT, 0);
|
|
grp.addMember("string name", offsetof(profile::BindGroup, name));
|
|
grp.addExternMethod("void addBind(const string &in, const string &in)", asFUNCTION(cb_keybind));
|
|
grp.addExternMethod("void addBind(Keybind, const string &in)", asFUNCTION(cb_keybind_id));
|
|
|
|
grp.addExternMethod("uint getBindCount()", asFUNCTION(cb_count));
|
|
grp.addExternMethod("string getBindName(uint index)", asFUNCTION(cb_name));
|
|
|
|
grp.addExternMethod("void setBind(int key, Keybind bind)", asFUNCTION(cb_set_kb));
|
|
grp.addExternMethod("void clearBin(int key)", asFUNCTION(cb_clear_kb));
|
|
grp.addExternMethod("void clearBinds(Keybind bind)", asFUNCTION(cb_clear_kb_bind));
|
|
|
|
grp.addExternMethod("void setDefaultBinds(Keybind bind)", asFUNCTION(cb_setdef_kb));
|
|
grp.addExternMethod("void setDefaultBinds()", asFUNCTION(cb_setdef_kb_all));
|
|
|
|
grp.addExternMethod("uint getDefaultKeyCount(Keybind bind)", asFUNCTION(cb_defcount));
|
|
grp.addExternMethod("int getDefaultKey(Keybind bind, uint index)", asFUNCTION(cb_defkey));
|
|
|
|
grp.addExternMethod("uint getCurrentKeyCount(Keybind bind)", asFUNCTION(cb_curcount));
|
|
grp.addExternMethod("int getCurrentKey(Keybind bind, uint index)", asFUNCTION(cb_curkey));
|
|
|
|
grp.addExternMethod("Keybind getBind(int key)", asFUNCTION(cb_getbind));
|
|
|
|
bind("int getKey(string key)", asFUNCTION(profile::getKey));
|
|
bind("string getKeyName(int key)", asFUNCTION(profile::getKeyName));
|
|
|
|
bind("int getKeyFromDisplayName(string key)", asFUNCTION(profile::getKeyFromDisplayName));
|
|
bind("string getKeyDisplayName(int key)", asFUNCTION(profile::getKeyDisplayName));
|
|
|
|
bind("void saveKeybinds()", asFUNCTION(cb_save_kb));
|
|
|
|
bind("KeybindGroup@ get_keybindGroup(uint index)", asFUNCTION(cb_group));
|
|
bind("uint get_keybindGroupCount()", asFUNCTION(cb_group_cnt));
|
|
bind("int modifyKey(int key)", asFUNCTION(mod_key));
|
|
|
|
{
|
|
Namespace ns("keybinds");
|
|
foreach(it, devices.keybinds.groups)
|
|
bindGlobal(format("::KeybindGroup $1", (*it)->name).c_str(), *it);
|
|
}
|
|
|
|
//Settings
|
|
bind("void setSettingInt(const string &in, int)", asFUNCTION(setSetting_int));
|
|
bind("void setSettingBool(const string &in, bool)", asFUNCTION(setSetting_bool));
|
|
bind("void setSettingDouble(const string &in, double)", asFUNCTION(setSetting_double));
|
|
bind("void setSettingStr(const string &in, const string &in)", asFUNCTION(setSetting_str));
|
|
|
|
bind("int getSettingInt(const string &in)", asFUNCTION(getSetting_int));
|
|
bind("bool getSettingBool(const string &in)", asFUNCTION(getSetting_bool));
|
|
bind("double getSettingDouble(const string &in)", asFUNCTION(getSetting_double));
|
|
bind("const string& getSettingStr(const string &in)", asFUNCTION(getSetting_str));
|
|
|
|
bind("int getSettingMaxInt(const string &in)", asFUNCTION(getSetting_max_int));
|
|
bind("int getSettingMinInt(const string &in)", asFUNCTION(getSetting_min_int));
|
|
bind("double getSettingMaxDouble(const string &in)", asFUNCTION(getSetting_max_double));
|
|
bind("double getSettingMinDouble(const string &in)", asFUNCTION(getSetting_min_double));
|
|
|
|
bind("void saveSettings()", asFUNCTION(saveSettings));
|
|
bind("void applySettings()", asFUNCTION(applySettings));
|
|
|
|
auto bindSetting = [](NamedGeneric& set) {
|
|
switch(set.type) {
|
|
case GT_Bool:
|
|
bindGlobal((std::string("bool ")+set.name).c_str(), &set.check);
|
|
break;
|
|
case GT_Integer:
|
|
bindGlobal((std::string("int ")+set.name).c_str(), &set.num);
|
|
break;
|
|
case GT_Double:
|
|
bindGlobal((std::string("double ")+set.name).c_str(), &set.flt);
|
|
break;
|
|
case GT_String:
|
|
bindGlobal((std::string("string ")+set.name).c_str(), set.str);
|
|
break;
|
|
case GT_Enum: {
|
|
std::string ename = set.name;
|
|
ename += "_OPTION";
|
|
|
|
EnumBind bnd(ename.c_str());
|
|
for(unsigned i = 0; i < set.values->size(); ++i)
|
|
bnd[(*set.values)[i]] = i;
|
|
|
|
bindGlobal(("::"+ename+" "+set.name).c_str(), &set.value);
|
|
} break;
|
|
}
|
|
};
|
|
|
|
{ Namespace ns("settings");
|
|
|
|
//Bind settings to global variables
|
|
foreach(it, devices.settings.engine.settings)
|
|
bindSetting((*it->second));
|
|
|
|
foreach(it, devices.settings.mod.settings)
|
|
bindSetting((*it->second));
|
|
}
|
|
}
|
|
|
|
};
|