more Input work
This commit is contained in:
parent
fe3763ed33
commit
73841ee041
@ -125,7 +125,7 @@ LuaValue LuaConverter<Json>::from(LuaEngine& engine, Json const& v) {
|
|||||||
} else if (v.isType(Json::Type::Int)) {
|
} else if (v.isType(Json::Type::Int)) {
|
||||||
return LuaInt(v.toInt());
|
return LuaInt(v.toInt());
|
||||||
} else if (v.isType(Json::Type::String)) {
|
} else if (v.isType(Json::Type::String)) {
|
||||||
return engine.createString(v.stringPtr()->utf8Ptr());
|
return engine.createString(*v.stringPtr());
|
||||||
} else {
|
} else {
|
||||||
return LuaDetail::jsonContainerToTable(engine, v);
|
return LuaDetail::jsonContainerToTable(engine, v);
|
||||||
}
|
}
|
||||||
@ -451,7 +451,10 @@ ByteArray LuaEngine::compile(ByteArray const& contents, String const& name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LuaString LuaEngine::createString(String const& str) {
|
LuaString LuaEngine::createString(String const& str) {
|
||||||
return createString(str.utf8Ptr());
|
lua_checkstack(m_state, 1);
|
||||||
|
|
||||||
|
lua_pushlstring(m_state, str.utf8Ptr(), str.utf8Size());
|
||||||
|
return LuaString(LuaDetail::LuaHandle(RefPtr<LuaEngine>(this), popHandle(m_state)));
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaString LuaEngine::createString(char const* str) {
|
LuaString LuaEngine::createString(char const* str) {
|
||||||
|
@ -1,9 +1,22 @@
|
|||||||
#include "StarInput.hpp"
|
#include "StarInput.hpp"
|
||||||
#include "StarAssets.hpp"
|
#include "StarAssets.hpp"
|
||||||
#include "StarRoot.hpp"
|
#include "StarRoot.hpp"
|
||||||
|
#include "StarJsonExtra.hpp"
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
|
const KeyMod KeyModOptional = KeyMod::Num | KeyMod::Caps | KeyMod::Scroll;
|
||||||
|
|
||||||
|
inline bool compareKeyModLenient(KeyMod input, KeyMod test) {
|
||||||
|
input |= KeyModOptional;
|
||||||
|
test |= KeyModOptional;
|
||||||
|
return (test & input) == test;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool compareKeyMod(KeyMod input, KeyMod test) {
|
||||||
|
return (input | (KeyModOptional & ~test)) == (test | KeyModOptional);
|
||||||
|
}
|
||||||
|
|
||||||
Json keyModsToJson(KeyMod mod) {
|
Json keyModsToJson(KeyMod mod) {
|
||||||
JsonArray array;
|
JsonArray array;
|
||||||
|
|
||||||
@ -49,11 +62,62 @@ size_t hash<InputVariant>::operator()(InputVariant const& v) const {
|
|||||||
return indexHash;
|
return indexHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Json Input::inputEventToJson(InputEvent const& input) {
|
||||||
|
String type;
|
||||||
|
Json data;
|
||||||
|
|
||||||
|
if (auto keyDown = input.ptr<KeyDownEvent>()) {
|
||||||
|
type = "KeyDown";
|
||||||
|
data = JsonObject{
|
||||||
|
{"key", KeyNames.getRight(keyDown->key)},
|
||||||
|
{"mods", keyModsToJson(keyDown->mods)}
|
||||||
|
};
|
||||||
|
} else if (auto keyUp = input.ptr<KeyUpEvent>()) {
|
||||||
|
type = "KeyUp";
|
||||||
|
data = JsonObject{
|
||||||
|
{"key", KeyNames.getRight(keyUp->key)}
|
||||||
|
};
|
||||||
|
} else if (auto mouseDown = input.ptr<MouseButtonDownEvent>()) {
|
||||||
|
type = "MouseButtonDown";
|
||||||
|
data = JsonObject{
|
||||||
|
{"mouseButton", MouseButtonNames.getRight(mouseDown->mouseButton)},
|
||||||
|
{"mousePosition", jsonFromVec2I(mouseDown->mousePosition)}
|
||||||
|
};
|
||||||
|
} else if (auto mouseUp = input.ptr<MouseButtonUpEvent>()) {
|
||||||
|
type = "MouseButtonUp";
|
||||||
|
data = JsonObject{
|
||||||
|
{"mouseButton", MouseButtonNames.getRight(mouseUp->mouseButton)},
|
||||||
|
{"mousePosition", jsonFromVec2I(mouseUp->mousePosition)}
|
||||||
|
};
|
||||||
|
} else if (auto mouseWheel = input.ptr<MouseWheelEvent>()) {
|
||||||
|
type = "MouseWheel";
|
||||||
|
data = JsonObject{
|
||||||
|
{"mouseWheel", MouseWheelNames.getRight(mouseWheel->mouseWheel)},
|
||||||
|
{"mousePosition", jsonFromVec2I(mouseWheel->mousePosition)}
|
||||||
|
};
|
||||||
|
} else if (auto mouseMove = input.ptr<MouseMoveEvent>()) {
|
||||||
|
type = "MouseMove";
|
||||||
|
data = JsonObject{
|
||||||
|
{"mouseMove", jsonFromVec2I(mouseMove->mouseMove)},
|
||||||
|
{"mousePosition", jsonFromVec2I(mouseMove->mousePosition)}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
return JsonObject{
|
||||||
|
{"type", type},
|
||||||
|
{"data", data}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
Input::Bind Input::bindFromJson(Json const& json) {
|
Input::Bind Input::bindFromJson(Json const& json) {
|
||||||
Bind bind;
|
Bind bind;
|
||||||
|
|
||||||
String type = json.getString("type");
|
String type = json.getString("type");
|
||||||
Json value = json.get("value");
|
Json value = json.get("value", {});
|
||||||
|
|
||||||
if (type == "key") {
|
if (type == "key") {
|
||||||
KeyBind keyBind;
|
KeyBind keyBind;
|
||||||
@ -117,8 +181,8 @@ Input::BindEntry::BindEntry(String entryId, Json const& config, BindCategory con
|
|||||||
|
|
||||||
Input::BindCategory::BindCategory(String categoryId, Json const& categoryConfig) {
|
Input::BindCategory::BindCategory(String categoryId, Json const& categoryConfig) {
|
||||||
id = move(categoryId);
|
id = move(categoryId);
|
||||||
name = config.getString("name", id);
|
|
||||||
config = categoryConfig;
|
config = categoryConfig;
|
||||||
|
name = config.getString("name", id);
|
||||||
|
|
||||||
ConfigurationPtr userConfig = Root::singletonPtr()->configuration();
|
ConfigurationPtr userConfig = Root::singletonPtr()->configuration();
|
||||||
auto userBindings = userConfig->get("modBindings");
|
auto userBindings = userConfig->get("modBindings");
|
||||||
@ -142,6 +206,20 @@ Input::BindCategory::BindCategory(String categoryId, Json const& categoryConfig)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Input::BindEntry*> Input::filterBindEntries(List<Input::BindRef> const& binds, KeyMod mods) const {
|
||||||
|
uint8_t maxPriority = 0;
|
||||||
|
List<BindEntry*> result{};
|
||||||
|
for (const BindRef& bind : binds) {
|
||||||
|
if (bind.priority < maxPriority)
|
||||||
|
break;
|
||||||
|
else if (compareKeyModLenient(mods, bind.mods)) {
|
||||||
|
maxPriority = bind.priority;
|
||||||
|
result.emplace_back(bind.entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Input* Input::s_singleton;
|
Input* Input::s_singleton;
|
||||||
|
|
||||||
Input* Input::singletonPtr() {
|
Input* Input::singletonPtr() {
|
||||||
@ -174,15 +252,34 @@ Input::~Input() {
|
|||||||
s_singleton = nullptr;
|
s_singleton = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<std::pair<InputEvent, bool>> const& Input::inputEventsThisFrame() const {
|
||||||
|
return m_inputEvents;
|
||||||
|
}
|
||||||
|
|
||||||
void Input::reset() {
|
void Input::reset() {
|
||||||
|
m_inputEvents.resize(0); // keeps reserved memory
|
||||||
m_inputStates.clear();
|
m_inputStates.clear();
|
||||||
m_bindStates.clear();
|
m_bindStates.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Input::update() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Input::handleInput(InputEvent const& input, bool gameProcessed) {
|
||||||
|
m_inputEvents.emplace_back(input, gameProcessed);
|
||||||
|
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Input::rebuildMappings() {
|
||||||
|
m_bindMappings.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void Input::reload() {
|
void Input::reload() {
|
||||||
reset();
|
reset();
|
||||||
m_bindCategories.clear();
|
m_bindCategories.clear();
|
||||||
m_inputsToBinds.clear();
|
|
||||||
|
|
||||||
auto assets = Root::singleton().assets();
|
auto assets = Root::singleton().assets();
|
||||||
|
|
||||||
@ -202,6 +299,8 @@ void Input::reload() {
|
|||||||
count += pair.second.entries.size();
|
count += pair.second.entries.size();
|
||||||
|
|
||||||
Logger::info("Binds: Loaded {} bind{}", count, count == 1 ? "" : "s");
|
Logger::info("Binds: Loaded {} bind{}", count, count == 1 ? "" : "s");
|
||||||
|
|
||||||
|
rebuildMappings();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -20,6 +20,9 @@ namespace Star {
|
|||||||
|
|
||||||
class Input {
|
class Input {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
static Json inputEventToJson(InputEvent const& event);
|
||||||
|
|
||||||
struct KeyBind {
|
struct KeyBind {
|
||||||
Key key = Key::Zero;
|
Key key = Key::Zero;
|
||||||
KeyMod mods = KeyMod::NoMod;
|
KeyMod mods = KeyMod::NoMod;
|
||||||
@ -124,29 +127,39 @@ namespace Star {
|
|||||||
Input(Input const&) = delete;
|
Input(Input const&) = delete;
|
||||||
Input& operator=(Input const&) = delete;
|
Input& operator=(Input const&) = delete;
|
||||||
|
|
||||||
// Clears input state. Should be done at the end of the client loop.
|
List<std::pair<InputEvent, bool>> const& inputEventsThisFrame() const;
|
||||||
|
|
||||||
|
// Clears input state. Should be done at the very start or end of the client loop.
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
void update();
|
||||||
|
|
||||||
// Handles an input event.
|
// Handles an input event.
|
||||||
bool handleInput(InputEvent const& event);
|
bool handleInput(InputEvent const& input, bool gameProcessed);
|
||||||
|
|
||||||
|
void rebuildMappings();
|
||||||
|
|
||||||
// Loads input categories and their binds from Assets.
|
// Loads input categories and their binds from Assets.
|
||||||
void reload();
|
void reload();
|
||||||
private:
|
private:
|
||||||
|
List<BindEntry*> filterBindEntries(List<BindRef> const& binds, KeyMod mods) const;
|
||||||
|
|
||||||
static Input* s_singleton;
|
static Input* s_singleton;
|
||||||
|
|
||||||
// Regenerated on reload.
|
// Regenerated on reload.
|
||||||
StringMap<BindCategory> m_bindCategories;
|
StringMap<BindCategory> m_bindCategories;
|
||||||
// Contains raw pointers to bind entries in categories, so also regenerated on reload.
|
// Contains raw pointers to bind entries in categories, so also regenerated on reload.
|
||||||
HashMap<InputVariant, List<BindRef>> m_inputsToBinds;
|
HashMap<InputVariant, List<BindRef>> m_bindMappings;
|
||||||
|
|
||||||
ListenerPtr m_rootReloadListener;
|
ListenerPtr m_rootReloadListener;
|
||||||
|
|
||||||
// Per-frame input state maps.
|
// Per-frame input event storage for Lua.
|
||||||
|
List<std::pair<InputEvent, bool>> m_inputEvents;
|
||||||
|
|
||||||
//Raw input state
|
// Per-frame input state maps.
|
||||||
|
//Input states
|
||||||
HashMap<InputVariant, InputState> m_inputStates;
|
HashMap<InputVariant, InputState> m_inputStates;
|
||||||
//Bind input state
|
//Bind states
|
||||||
HashMap<BindEntry*, InputState> m_bindStates;
|
HashMap<BindEntry*, InputState> m_bindStates;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,9 @@ LuaCallbacks LuaBindings::makePlayerCallbacks(Player* player) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
callbacks.registerCallback("name", [player]() { return player->name(); });
|
||||||
|
callbacks.registerCallback("setName", [player](String const& name) { player->setName(name); });
|
||||||
|
|
||||||
callbacks.registerCallback("species", [player]() { return player->species(); });
|
callbacks.registerCallback("species", [player]() { return player->species(); });
|
||||||
callbacks.registerCallback("setSpecies", [player](String const& species) { player->setSpecies(species); });
|
callbacks.registerCallback("setSpecies", [player](String const& species) { player->setSpecies(species); });
|
||||||
|
|
||||||
@ -101,8 +104,6 @@ LuaCallbacks LuaBindings::makePlayerCallbacks(Player* player) {
|
|||||||
player->setPersonality(parsePersonality(newPersonality, personalityConfig));
|
player->setPersonality(parsePersonality(newPersonality, personalityConfig));
|
||||||
});
|
});
|
||||||
|
|
||||||
void setPersonality(Personality const& personality);
|
|
||||||
|
|
||||||
callbacks.registerCallback("id", [player]() { return player->entityId(); });
|
callbacks.registerCallback("id", [player]() { return player->entityId(); });
|
||||||
callbacks.registerCallback("uniqueId", [player]() { return player->uniqueId(); });
|
callbacks.registerCallback("uniqueId", [player]() { return player->uniqueId(); });
|
||||||
callbacks.registerCallback("isAdmin", [player]() { return player->isAdmin(); });
|
callbacks.registerCallback("isAdmin", [player]() { return player->isAdmin(); });
|
||||||
|
@ -30,6 +30,8 @@ LuaCallbacks LuaBindings::makeRootCallbacks() {
|
|||||||
|
|
||||||
auto root = Root::singletonPtr();
|
auto root = Root::singletonPtr();
|
||||||
|
|
||||||
|
callbacks.registerCallbackWithSignature<StringList, String>("assetsByExtension", bind(RootCallbacks::assetsByExtension, root, _1));
|
||||||
|
callbacks.registerCallbackWithSignature<String, String>("assetData", bind(RootCallbacks::assetData, root, _1));
|
||||||
callbacks.registerCallbackWithSignature<Json, String>("assetJson", bind(RootCallbacks::assetJson, root, _1));
|
callbacks.registerCallbackWithSignature<Json, String>("assetJson", bind(RootCallbacks::assetJson, root, _1));
|
||||||
callbacks.registerCallbackWithSignature<Json, String, Json>("makeCurrentVersionedJson", bind(RootCallbacks::makeCurrentVersionedJson, root, _1, _2));
|
callbacks.registerCallbackWithSignature<Json, String, Json>("makeCurrentVersionedJson", bind(RootCallbacks::makeCurrentVersionedJson, root, _1, _2));
|
||||||
callbacks.registerCallbackWithSignature<Json, Json, String>("loadVersionedJson", bind(RootCallbacks::loadVersionedJson, root, _1, _2));
|
callbacks.registerCallbackWithSignature<Json, Json, String>("loadVersionedJson", bind(RootCallbacks::loadVersionedJson, root, _1, _2));
|
||||||
@ -170,6 +172,15 @@ LuaCallbacks LuaBindings::makeRootCallbacks() {
|
|||||||
return callbacks;
|
return callbacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringList LuaBindings::RootCallbacks::assetsByExtension(Root* root, String const& extension) {
|
||||||
|
return root->assets()->scanExtension(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
String LuaBindings::RootCallbacks::assetData(Root* root, String const& path) {
|
||||||
|
auto bytes = root->assets()->bytes(path);
|
||||||
|
return String(bytes->ptr(), bytes->size());
|
||||||
|
}
|
||||||
|
|
||||||
Json LuaBindings::RootCallbacks::assetJson(Root* root, String const& path) {
|
Json LuaBindings::RootCallbacks::assetJson(Root* root, String const& path) {
|
||||||
return root->assets()->json(path);
|
return root->assets()->json(path);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ namespace LuaBindings {
|
|||||||
LuaCallbacks makeRootCallbacks();
|
LuaCallbacks makeRootCallbacks();
|
||||||
|
|
||||||
namespace RootCallbacks {
|
namespace RootCallbacks {
|
||||||
|
StringList assetsByExtension(Root* root, String const& extension);
|
||||||
|
String assetData(Root* root, String const& path);
|
||||||
Json assetJson(Root* root, String const& path);
|
Json assetJson(Root* root, String const& path);
|
||||||
Json makeCurrentVersionedJson(Root* root, String const& identifier, Json const& content);
|
Json makeCurrentVersionedJson(Root* root, String const& identifier, Json const& content);
|
||||||
Json loadVersionedJson(Root* root, Json const& versionedJson, String const& expectedIdentifier);
|
Json loadVersionedJson(Root* root, Json const& versionedJson, String const& expectedIdentifier);
|
||||||
|
Loading…
Reference in New Issue
Block a user