new input system WIP

This commit is contained in:
Mikulas Florek 2017-10-12 19:41:38 +02:00
parent bfbf0b11e5
commit 1e157ed0c9
11 changed files with 160 additions and 166 deletions

View file

@ -433,8 +433,9 @@ public:
GetCursorPos(&p);
ScreenToClient(m_hwnd, &p);
auto& input_system = m_engine->getInputSystem();
input_system.injectMouseXMove(float(raw->data.mouse.lLastX), (float)p.x);
input_system.injectMouseYMove(float(raw->data.mouse.lLastY), (float)p.y);
/*input_system.injectMouseXMove(float(raw->data.mouse.lLastX), (float)p.x);
input_system.injectMouseYMove(float(raw->data.mouse.lLastY), (float)p.y);*/
// TODO
}
}

View file

@ -2071,8 +2071,15 @@ public:
}
Vec2 getMouseMove() const override
{
return m_mouse_move;
}
void processSystemEvents()
{
m_mouse_move.set(0, 0);
SDL_Event event;
auto& io = ImGui::GetIO();
while (SDL_PollEvent(&event))
@ -2116,8 +2123,8 @@ public:
case SDL_MOUSEMOTION:
{
auto& input_system = m_editor->getEngine().getInputSystem();
input_system.injectMouseXMove(float(event.motion.xrel), float(event.motion.x));
input_system.injectMouseYMove(float(event.motion.yrel), float(event.motion.y));
input_system.setCursorPosition({(float)event.motion.x, (float)event.motion.y});
m_mouse_move += Vec2((float)event.motion.xrel, (float)event.motion.yrel);
if (SDL_GetRelativeMouseMode() == SDL_FALSE)
{
io.MousePos.x = (float)event.motion.x;
@ -2334,6 +2341,7 @@ public:
ProfilerUI* m_profiler_ui;
Settings m_settings;
Metadata m_metadata;
Vec2 m_mouse_move;
char m_template_name[100];
char m_open_filter[64];
char m_component_filter[32];

View file

@ -23,10 +23,11 @@ namespace Lumix
{
struct Action;
struct ComponentUID;
struct ResourceType;
struct Vec2;
class WorldEditor;
struct Action;
class LUMIX_EDITOR_API StudioApp
@ -115,6 +116,7 @@ public:
virtual DragData getDragData() = 0;
virtual void setFullscreen(bool fullscreen) = 0;
virtual bool makeFile(const char* path, const char* content) = 0;
virtual Vec2 getMouseMove() const = 0;
virtual ~StudioApp() {}
virtual void run() = 0;

View file

@ -767,19 +767,6 @@ public:
}
static float LUA_getInputActionValue(Engine* engine, u32 action)
{
auto v = engine->getInputSystem().getActionValue(action);
return v;
}
static void LUA_addInputAction(Engine* engine, u32 action, int type, int key, int controller_id)
{
engine->getInputSystem().addAction(action, InputSystem::InputType(type), key, controller_id);
}
static void LUA_setEntityPosition(Universe* univ, Entity entity, Vec3 pos) { univ->setPosition(entity, pos); }
static void LUA_unloadResource(EngineImpl* engine, int resource_idx) { engine->unloadLuaResource(resource_idx); }
static Universe* LUA_createUniverse(EngineImpl* engine) { return &engine->createUniverse(false); }
@ -944,7 +931,6 @@ public:
LuaWrapper::createSystemFunction(m_state, "Engine", #name, \
&LuaWrapper::wrap<decltype(&LUA_##name), LUA_##name>); \
REGISTER_FUNCTION(addInputAction);
REGISTER_FUNCTION(createComponent);
REGISTER_FUNCTION(createEntity);
REGISTER_FUNCTION(createUniverse);
@ -957,7 +943,6 @@ public:
REGISTER_FUNCTION(getEntityRotation);
REGISTER_FUNCTION(getEntityByName);
REGISTER_FUNCTION(getFirstEntity);
REGISTER_FUNCTION(getInputActionValue);
REGISTER_FUNCTION(getNextEntity);
REGISTER_FUNCTION(getScene);
REGISTER_FUNCTION(getSceneUniverse);
@ -985,16 +970,6 @@ public:
LuaWrapper::createSystemFunction(m_state, "Engine", "instantiatePrefab", &LUA_instantiatePrefab);
LuaWrapper::createSystemFunction(m_state, "Engine", "createEntityEx", &LUA_createEntityEx);
LuaWrapper::createSystemFunction(m_state, "Engine", "multVecQuat", &LUA_multVecQuat);
LuaWrapper::createSystemVariable(m_state, "Engine", "INPUT_TYPE_DOWN", InputSystem::DOWN);
LuaWrapper::createSystemVariable(m_state, "Engine", "INPUT_TYPE_PRESSED", InputSystem::PRESSED);
LuaWrapper::createSystemVariable(m_state, "Engine", "INPUT_TYPE_MOUSE_X", InputSystem::MOUSE_X);
LuaWrapper::createSystemVariable(m_state, "Engine", "INPUT_TYPE_MOUSE_Y", InputSystem::MOUSE_Y);
LuaWrapper::createSystemVariable(m_state, "Engine", "INPUT_TYPE_LTHUMB_X", InputSystem::LTHUMB_X);
LuaWrapper::createSystemVariable(m_state, "Engine", "INPUT_TYPE_LTHUMB_Y", InputSystem::LTHUMB_Y);
LuaWrapper::createSystemVariable(m_state, "Engine", "INPUT_TYPE_RTHUMB_X", InputSystem::RTHUMB_X);
LuaWrapper::createSystemVariable(m_state, "Engine", "INPUT_TYPE_RTHUMB_Y", InputSystem::RTHUMB_Y);
LuaWrapper::createSystemVariable(m_state, "Engine", "INPUT_TYPE_RTRIGGER", InputSystem::RTRIGGER);
LuaWrapper::createSystemVariable(m_state, "Engine", "INPUT_TYPE_LTRIGGER", InputSystem::LTRIGGER);
lua_newtable(m_state);
lua_pushvalue(m_state, -1);

View file

@ -7,50 +7,79 @@
namespace Lumix
{
struct IAllocator;
struct Vec2;
struct IAllocator;
struct Vec2;
class LUMIX_ENGINE_API InputSystem
{
public:
enum InputType
class LUMIX_ENGINE_API InputSystem
{
public:
struct Device
{
enum Type
{
PRESSED,
DOWN,
MOUSE_X,
MOUSE_Y,
LTHUMB_X,
LTHUMB_Y,
RTHUMB_X,
RTHUMB_Y,
RTRIGGER,
LTRIGGER
MOUSE,
KEYBOARD,
CONTROLLER
};
enum MouseButton
Type type;
};
struct ButtonEvent
{
u32 key_id;
float x_abs;
float y_abs;
enum
{
LEFT,
MIDDLE,
RIGHT
UP,
DOWN
} state;
};
struct AxisEvent
{
float x;
float y;
float x_abs;
float y_abs;
};
struct Event
{
enum Type : u32
{
BUTTON,
AXIS
};
public:
static InputSystem* create(IAllocator& allocator);
static void destroy(InputSystem& system);
Type type;
Device* device;
union EventData
{
ButtonEvent button;
AxisEvent axis;
} data;
};
virtual ~InputSystem() {}
virtual void enable(bool enabled) = 0;
virtual void update(float dt) = 0;
virtual float getActionValue(u32 action) = 0;
virtual void injectMouseXMove(float rel, float abs) = 0;
virtual void injectMouseYMove(float rel, float abs) = 0;
virtual float getMouseXMove() const = 0;
virtual float getMouseYMove() const = 0;
virtual bool isMouseDown(MouseButton button) = 0;
virtual Vec2 getMousePos() const = 0;
virtual void addAction(u32 action, InputType type, int key, int controller_id) = 0;
};
public:
static InputSystem* create(IAllocator& allocator);
static void destroy(InputSystem& system);
virtual ~InputSystem() {}
virtual void enable(bool enabled) = 0;
virtual void update(float dt) = 0;
virtual void injectEvent(const Event& event) = 0;
virtual int getEventsCount() const = 0;
virtual const Event* getEvents() const = 0;
virtual Device* getMouseDevice() = 0;
virtual Vec2 getCursorPosition() const = 0;
virtual void setCursorPosition(const Vec2& pos) = 0;
};
} // ~namespace Lumix
} // namespace Lumix

View file

@ -40,6 +40,7 @@ struct LUMIX_ENGINE_API Vec2
Vec2 operator *(const Vec2& v) const { return Vec2(x * v.x, y * v.y); }
Vec2 operator *(float f) const { return Vec2(x * f, y * f); }
Vec2 operator +(const Vec2& v) const { return Vec2(x + v.x, y + v.y); }
void operator +=(const Vec2& v) { x += v.x; y += v.y; }
Vec2 operator -(const Vec2& v) const { return Vec2(x - v.x, y - v.y); }
Vec2 operator -(float f) const { return Vec2(x - f, y - f); }
Vec2 normalized() const { return *this * (1 / length()); }

View file

@ -22,14 +22,13 @@ struct InputSystemImpl LUMIX_FINAL : public InputSystem
typedef decltype(XInputGetState)* XInputGetState_fn_ptr;
explicit InputSystemImpl(IAllocator& allocator)
: m_actions(allocator)
, m_allocator(allocator)
: m_allocator(allocator)
, m_events(m_allocator)
, m_is_enabled(false)
, m_mouse_rel_pos(0, 0)
, m_injected_mouse_rel_pos(0, 0)
, m_xinput_library(nullptr)
, m_xinput_get_state(nullptr)
{
m_mouse_device.type = Device::MOUSE;
m_last_checked_controller = 0;
for (int i = 0; i < lengthOf(m_xinput_connected); ++i)
{
@ -61,6 +60,7 @@ struct InputSystemImpl LUMIX_FINAL : public InputSystem
{
PROFILE_FUNCTION();
m_events.clear();
if (m_xinput_get_state)
{
for (int i = 0; i < XUSER_MAX_COUNT; ++i)
@ -73,34 +73,20 @@ struct InputSystemImpl LUMIX_FINAL : public InputSystem
}
m_last_checked_controller = (m_last_checked_controller + 1) % XUSER_MAX_COUNT;
}
m_mouse_rel_pos = m_injected_mouse_rel_pos;
m_injected_mouse_rel_pos = {0, 0};
}
void injectMouseXMove(float rel, float abs) override
void injectEvent(const Event& event) override
{
m_injected_mouse_rel_pos.x = rel;
m_mouse_pos.x = abs;
m_events.push(event);
}
void injectMouseYMove(float rel, float abs) override
{
m_injected_mouse_rel_pos.y = rel;
m_mouse_pos.y = abs;
}
void addAction(u32 action, InputType type, int key, int controller_id) override
{
InputSystemImpl::Action value;
value.key = key;
value.type = type;
value.controller_id = controller_id;
m_actions[action] = value;
}
int getEventsCount() const override { return m_events.size(); }
const Event* getEvents() const override { return m_events.empty() ? nullptr : &m_events[0]; }
Vec2 getCursorPosition() const override { return m_cursor_pos; }
void setCursorPosition(const Vec2& pos) override { m_cursor_pos = pos; }
static float deadZone(float value, float dead_zone)
{
@ -109,78 +95,17 @@ struct InputSystemImpl LUMIX_FINAL : public InputSystem
}
float getMouseXMove() const override { return m_mouse_rel_pos.x; }
float getMouseYMove() const override { return m_mouse_rel_pos.y; }
Vec2 getMousePos() const override { return m_mouse_pos; }
bool isMouseDown(MouseButton button) override
Device* getMouseDevice() override
{
switch (button)
{
case LEFT: return (GetAsyncKeyState(VK_LBUTTON) >> 8) != 0;
case RIGHT: return (GetAsyncKeyState(VK_RBUTTON) >> 8) != 0;
case MIDDLE: return (GetAsyncKeyState(VK_MBUTTON) >> 8) != 0;
}
return false;
}
float getActionValue(u32 action) override
{
if (!m_is_enabled) return 0;
InputSystemImpl::Action value;
if (m_actions.find(action, value))
{
switch (value.type)
{
case InputType::PRESSED: return (GetAsyncKeyState(value.key) >> 8) ? 1.0f : 0;
case InputType::DOWN:
if (value.controller_id < 0)
{
return GetAsyncKeyState(value.key) & 1 ? 1.0f : 0;
}
else
{
return m_xinput_states[value.controller_id].Gamepad.wButtons & value.key ? 1.0f : 0;
}
case InputType::MOUSE_X: return m_mouse_rel_pos.x;
case InputType::MOUSE_Y: return m_mouse_rel_pos.y;
};
if (!m_xinput_connected[value.controller_id]) return 0;
switch (value.type)
{
case InputType::LTHUMB_X:
return deadZone(m_xinput_states[value.controller_id].Gamepad.sThumbLX / 32767.0f, DEADZONE);
case InputType::LTHUMB_Y:
return deadZone(m_xinput_states[value.controller_id].Gamepad.sThumbLY / 32767.0f, DEADZONE);
case InputType::RTHUMB_X:
return deadZone(m_xinput_states[value.controller_id].Gamepad.sThumbRX / 32767.0f, DEADZONE);
case InputType::RTHUMB_Y:
return deadZone(m_xinput_states[value.controller_id].Gamepad.sThumbRY / 32767.0f, DEADZONE);
case InputType::RTRIGGER:
return deadZone(m_xinput_states[value.controller_id].Gamepad.bRightTrigger / 255.0f, DEADZONE);
case InputType::LTRIGGER:
return deadZone(m_xinput_states[value.controller_id].Gamepad.bLeftTrigger / 255.0f, DEADZONE);
default: ASSERT(false); break;
}
}
return 0;
return &m_mouse_device;
}
struct Action
{
InputSystem::InputType type;
int key;
int controller_id;
};
Device m_mouse_device;
IAllocator& m_allocator;
AssociativeArray<u32, Action> m_actions;
Vec2 m_injected_mouse_rel_pos;
Vec2 m_mouse_rel_pos;
Vec2 m_mouse_pos;
Array<Event> m_events;
bool m_is_enabled;
Vec2 m_cursor_pos;
HMODULE m_xinput_library;
XInputGetState_fn_ptr m_xinput_get_state;
XINPUT_STATE m_xinput_states[XUSER_MAX_COUNT];

View file

@ -238,8 +238,7 @@ struct GUISystemImpl LUMIX_FINAL : public GUISystem
float getMouseX() const
{
Vec2 mouse_pos = m_engine.getInputSystem().getMousePos() - m_interface->getPos();
return mouse_pos.x;
return ImGui::GetIO().MousePos.x - m_interface->getPos().x;
}
@ -251,18 +250,26 @@ struct GUISystemImpl LUMIX_FINAL : public GUISystem
float getMouseY() const
{
Vec2 mouse_pos = m_engine.getInputSystem().getMousePos() - m_interface->getPos();
return mouse_pos.y;
return ImGui::GetIO().MousePos.x - m_interface->getPos().x;
}
void update(float time_delta) override
{
beginGUI();
Vec2 mouse_pos = m_engine.getInputSystem().getMousePos() - m_interface->getPos();
InputSystem& input_system = m_engine.getInputSystem();
Vec2 mouse_pos = input_system.getCursorPosition() - m_interface->getPos();
auto& io = ImGui::GetIO();
io.MousePos = ImVec2(mouse_pos.x, mouse_pos.y);
io.MouseDown[0] = m_engine.getInputSystem().isMouseDown(InputSystem::LEFT);
const InputSystem::Event* events = input_system.getEvents();
for (int i = 0, c = input_system.getEventsCount(); i < c; ++i)
{
if (events[i].type == InputSystem::Event::BUTTON && events[i].device->type == InputSystem::Device::MOUSE && events[i].data.button.key_id == 0)
{
io.MouseDown[0] = events[i].data.button.state == InputSystem::ButtonEvent::DOWN;
}
}
endGUI();
}

View file

@ -321,6 +321,52 @@ void GameView::onWindowGUI()
PlatformInterface::clipCursor((int)pos.x, (int)pos.y, (int)m_size.x, (int)m_size.y);
}
if (m_is_mouse_captured && ImGui::IsItemHovered())
{
Vec2 delta = m_studio_app.getMouseMove();
InputSystem& input = m_editor.getEngine().getInputSystem();
ImVec2 rel_mp = ImGui::GetMousePos();
rel_mp.x -= m_pos.x;
rel_mp.y -= m_pos.y;
for (int i = 0; i < 3; ++i)
{
if (ImGui::IsMouseClicked(i))
{
InputSystem::Event event;
event.type = InputSystem::Event::BUTTON;
event.device = input.getMouseDevice();
event.data.button.key_id = i;
event.data.button.state = InputSystem::ButtonEvent::DOWN;
event.data.button.x_abs = rel_mp.x;
event.data.button.y_abs = rel_mp.y;
input.injectEvent(event);
}
else if (ImGui::IsMouseReleased(i))
{
InputSystem::Event event;
event.type = InputSystem::Event::BUTTON;
event.device = input.getMouseDevice();
event.data.button.key_id = i;
event.data.button.state = InputSystem::ButtonEvent::UP;
event.data.button.x_abs = rel_mp.x;
event.data.button.y_abs = rel_mp.y;
input.injectEvent(event);
}
}
if (delta.x != 0 || delta.y != 0)
{
InputSystem::Event event;
event.type = InputSystem::Event::AXIS;
event.device = input.getMouseDevice();
event.data.axis.x_abs = rel_mp.x;
event.data.axis.y_abs = rel_mp.y;
event.data.axis.x = delta.x;
event.data.axis.y = delta.y;
input.injectEvent(event);
}
}
if (ImGui::Checkbox("Pause", &m_paused))
{
m_editor.getEngine().pause(m_paused);
@ -354,6 +400,7 @@ void GameView::onWindowGUI()
m_pipeline->callLuaFunction("onGUI");
}
if (m_is_mouse_captured && (io.KeysDown[ImGui::GetKeyIndex(ImGuiKey_Escape)] || !m_editor.isGameMode()))
{
captureMouse(false);

View file

@ -535,7 +535,7 @@ struct ModelPlugin LUMIX_FINAL : public AssetBrowser::IPlugin
if (ImGui::IsItemHovered() && mouse_down)
{
auto& input = engine.getInputSystem();
auto delta = Vec2(input.getMouseXMove(), input.getMouseYMove());
auto delta = m_app.getMouseMove();
if (!m_is_mouse_captured)
{

View file

@ -419,8 +419,7 @@ void SceneView::onWindowGUI()
}
if (m_is_mouse_captured || ImGui::IsItemHovered())
{
auto& input = m_editor.getEngine().getInputSystem();
auto delta = Vec2(input.getMouseXMove(), input.getMouseYMove());
auto delta = m_app.getMouseMove();
if (delta.x != 0 || delta.y != 0)
{
m_editor.onMouseMove((int)rel_mp.x, (int)rel_mp.y, (int)delta.x, (int)delta.y);