Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/ps/scripting/JSInterface_Hotkey.cpp
Show All 18 Lines | |||||
#include "JSInterface_Hotkey.h" | #include "JSInterface_Hotkey.h" | ||||
#include "lib/external_libraries/libsdl.h" | #include "lib/external_libraries/libsdl.h" | ||||
#include "ps/CLogger.h" | #include "ps/CLogger.h" | ||||
#include "ps/ConfigDB.h" | #include "ps/ConfigDB.h" | ||||
#include "ps/Hotkey.h" | #include "ps/Hotkey.h" | ||||
#include "ps/KeyName.h" | #include "ps/KeyName.h" | ||||
#include "scriptinterface/FunctionWrapper.h" | |||||
#include "scriptinterface/ScriptConversions.h" | #include "scriptinterface/ScriptConversions.h" | ||||
#include <unordered_map> | #include <unordered_map> | ||||
#include <vector> | #include <vector> | ||||
#include <set> | #include <set> | ||||
/** | /** | ||||
* Convert an unordered map to a JS object, mapping keys to values. | * Convert an unordered map to a JS object, mapping keys to values. | ||||
Show All 26 Lines | |||||
} | } | ||||
template<> | template<> | ||||
void ScriptInterface::ToJSVal<std::unordered_map<std::string, std::string>>(const ScriptRequest& rq, JS::MutableHandleValue ret, const std::unordered_map<std::string, std::string>& val) | void ScriptInterface::ToJSVal<std::unordered_map<std::string, std::string>>(const ScriptRequest& rq, JS::MutableHandleValue ret, const std::unordered_map<std::string, std::string>& val) | ||||
{ | { | ||||
ToJSVal_unordered_map(rq, ret, val); | ToJSVal_unordered_map(rq, ret, val); | ||||
} | } | ||||
namespace | |||||
{ | |||||
/** | /** | ||||
* @return a (js) object mapping hotkey name (from cfg files) to a list ofscancode names | * @return a (js) object mapping hotkey name (from cfg files) to a list ofscancode names | ||||
*/ | */ | ||||
JS::Value GetHotkeyMap(ScriptInterface::CmptPrivate* pCmptPrivate) | JS::Value GetHotkeyMap(const ScriptRequest& rq) | ||||
{ | { | ||||
ScriptRequest rq(*pCmptPrivate->pScriptInterface); | |||||
JS::RootedValue hotkeyMap(rq.cx); | JS::RootedValue hotkeyMap(rq.cx); | ||||
std::unordered_map<std::string, std::vector<std::vector<std::string>>> hotkeys; | std::unordered_map<std::string, std::vector<std::vector<std::string>>> hotkeys; | ||||
for (const std::pair<const SDL_Scancode_, KeyMapping>& key : g_HotkeyMap) | for (const std::pair<const SDL_Scancode_, KeyMapping>& key : g_HotkeyMap) | ||||
for (const SHotkeyMapping& mapping : key.second) | for (const SHotkeyMapping& mapping : key.second) | ||||
{ | { | ||||
std::vector<std::string> keymap; | std::vector<std::string> keymap; | ||||
if (key.first != UNUSED_HOTKEY_CODE) | if (key.first != UNUSED_HOTKEY_CODE) | ||||
keymap.push_back(FindScancodeName(static_cast<SDL_Scancode>(key.first))); | keymap.push_back(FindScancodeName(static_cast<SDL_Scancode>(key.first))); | ||||
for (const SKey& secondary_key : mapping.requires) | for (const SKey& secondary_key : mapping.requires) | ||||
keymap.push_back(FindScancodeName(static_cast<SDL_Scancode>(secondary_key.code))); | keymap.push_back(FindScancodeName(static_cast<SDL_Scancode>(secondary_key.code))); | ||||
// If keymap is empty (== unused) or size 1, push the combination. | // If keymap is empty (== unused) or size 1, push the combination. | ||||
// Otherwise, all permutations of the combination will exist, so pick one using an arbitrary order. | // Otherwise, all permutations of the combination will exist, so pick one using an arbitrary order. | ||||
if (keymap.size() < 2 || keymap[0] < keymap[1]) | if (keymap.size() < 2 || keymap[0] < keymap[1]) | ||||
hotkeys[mapping.name].emplace_back(keymap); | hotkeys[mapping.name].emplace_back(keymap); | ||||
} | } | ||||
pCmptPrivate->pScriptInterface->ToJSVal(rq, &hotkeyMap, hotkeys); | ScriptInterface::ToJSVal(rq, &hotkeyMap, hotkeys); | ||||
return hotkeyMap; | return hotkeyMap; | ||||
} | } | ||||
/** | /** | ||||
* @return a (js) object mapping scancode names to their locale-dependent name. | * @return a (js) object mapping scancode names to their locale-dependent name. | ||||
*/ | */ | ||||
JS::Value GetScancodeKeyNames(ScriptInterface::CmptPrivate* pCmptPrivate) | JS::Value GetScancodeKeyNames(const ScriptRequest& rq) | ||||
{ | { | ||||
ScriptRequest rq(*pCmptPrivate->pScriptInterface); | |||||
JS::RootedValue obj(rq.cx); | JS::RootedValue obj(rq.cx); | ||||
std::unordered_map<std::string, std::string> map; | std::unordered_map<std::string, std::string> map; | ||||
// Get the name of all scancodes. | // Get the name of all scancodes. | ||||
// This is slightly wasteful but should be fine overall, they are dense. | // This is slightly wasteful but should be fine overall, they are dense. | ||||
for (int i = 0; i < MOUSE_LAST; ++i) | for (int i = 0; i < MOUSE_LAST; ++i) | ||||
map[FindScancodeName(static_cast<SDL_Scancode>(i))] = FindKeyName(static_cast<SDL_Scancode>(i)); | map[FindScancodeName(static_cast<SDL_Scancode>(i))] = FindKeyName(static_cast<SDL_Scancode>(i)); | ||||
pCmptPrivate->pScriptInterface->ToJSVal(rq, &obj, map); | ScriptInterface::ToJSVal(rq, &obj, map); | ||||
return obj; | return obj; | ||||
} | } | ||||
void ReloadHotkeys(ScriptInterface::CmptPrivate* UNUSED(pCmptPrivate)) | void ReloadHotkeys() | ||||
{ | { | ||||
UnloadHotkeys(); | UnloadHotkeys(); | ||||
LoadHotkeys(g_ConfigDB); | LoadHotkeys(g_ConfigDB); | ||||
} | } | ||||
JS::Value GetConflicts(ScriptInterface::CmptPrivate* pCmptPrivate, JS::HandleValue combination) | JS::Value GetConflicts(const ScriptRequest& rq, JS::HandleValue combination) | ||||
{ | { | ||||
ScriptInterface* scriptInterface = pCmptPrivate->pScriptInterface; | |||||
ScriptRequest rq(*scriptInterface); | |||||
std::vector<std::string> keys; | std::vector<std::string> keys; | ||||
if (!scriptInterface->FromJSVal(rq, combination, keys)) | if (!ScriptInterface::FromJSVal(rq, combination, keys)) | ||||
{ | { | ||||
LOGERROR("Invalid hotkey combination"); | LOGERROR("Invalid hotkey combination"); | ||||
return JS::NullValue(); | return JS::NullValue(); | ||||
} | } | ||||
if (keys.empty()) | if (keys.empty()) | ||||
return JS::NullValue(); | return JS::NullValue(); | ||||
Show All 19 Lines | for (const SHotkeyMapping& keymap : it->second) | ||||
std::set<SKey> match(keymap.requires.begin(), keymap.requires.end()); | std::set<SKey> match(keymap.requires.begin(), keymap.requires.end()); | ||||
if (codes == match) | if (codes == match) | ||||
conflicts.emplace_back(keymap.name); | conflicts.emplace_back(keymap.name); | ||||
} | } | ||||
if (conflicts.empty()) | if (conflicts.empty()) | ||||
return JS::NullValue(); | return JS::NullValue(); | ||||
JS::RootedValue ret(rq.cx); | JS::RootedValue ret(rq.cx); | ||||
scriptInterface->ToJSVal(rq, &ret, conflicts); | ScriptInterface::ToJSVal(rq, &ret, conflicts); | ||||
return ret; | return ret; | ||||
} | } | ||||
} | |||||
void JSI_Hotkey::RegisterScriptFunctions(const ScriptInterface& scriptInterface) | void JSI_Hotkey::RegisterScriptFunctions(const ScriptRequest& rq) | ||||
{ | { | ||||
scriptInterface.RegisterFunction<JS::Value, &GetHotkeyMap>("GetHotkeyMap"); | ScriptFunction::Register<&GetHotkeyMap>(rq, "GetHotkeyMap"); | ||||
scriptInterface.RegisterFunction<JS::Value, &GetScancodeKeyNames>("GetScancodeKeyNames"); | ScriptFunction::Register<&GetScancodeKeyNames>(rq, "GetScancodeKeyNames"); | ||||
scriptInterface.RegisterFunction<void, &ReloadHotkeys>("ReloadHotkeys"); | ScriptFunction::Register<&ReloadHotkeys>(rq, "ReloadHotkeys"); | ||||
scriptInterface.RegisterFunction<JS::Value, JS::HandleValue, &GetConflicts>("GetConflicts"); | ScriptFunction::Register<&GetConflicts>(rq, "GetConflicts"); | ||||
} | } |
Wildfire Games · Phabricator