mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-20 15:04:54 +02:00
With the cursor out of the window ImGui has no place for it, and the ray under it came out as NaN: the zoom put the camera there for good and the next look at the ground under the cursor aborted. The wheel is left alone then, and the ground isn't asked for a point which isn't one. The self-test gets leave, the cursor taken out of the window.
252 lines
6.3 KiB
C++
252 lines
6.3 KiB
C++
/*
|
|
This Source Code Form is subject to the
|
|
terms of the Mozilla Public License, v.
|
|
2.0. If a copy of the MPL was not
|
|
distributed with this file, You can
|
|
obtain one at
|
|
http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "application/scriptedinput.h"
|
|
|
|
#include "application/application.h"
|
|
#include "application/uilayer.h"
|
|
#include "utilities/Globals.h"
|
|
#include "utilities/Logs.h"
|
|
#include "utilities/utilities.h"
|
|
#include "editor/editorFormat.hpp"
|
|
#include "imgui/imgui.h"
|
|
|
|
#include <cctype>
|
|
#include <cstdlib>
|
|
#include <fstream>
|
|
#include <map>
|
|
|
|
namespace
|
|
{
|
|
|
|
int key_named(std::string const &Name)
|
|
{
|
|
static std::map<std::string, int> const names{{"ctrl", GLFW_KEY_LEFT_CONTROL}, {"shift", GLFW_KEY_LEFT_SHIFT}, {"alt", GLFW_KEY_LEFT_ALT}, {"esc", GLFW_KEY_ESCAPE}, {"enter", GLFW_KEY_ENTER}, {"backspace", GLFW_KEY_BACKSPACE},
|
|
{"del", GLFW_KEY_DELETE}, {"space", GLFW_KEY_SPACE}, {"tab", GLFW_KEY_TAB}};
|
|
if (auto const found{names.find(Name)}; found != names.end())
|
|
return found->second;
|
|
if (Name.size() == 1 && std::isalpha(static_cast<unsigned char>(Name[0])))
|
|
return GLFW_KEY_A + (std::toupper(static_cast<unsigned char>(Name[0])) - 'A');
|
|
if (Name.size() == 1 && std::isdigit(static_cast<unsigned char>(Name[0])))
|
|
return GLFW_KEY_0 + (Name[0] - '0');
|
|
if (Name.size() > 1 && (Name[0] == 'f' || Name[0] == 'F') && std::isdigit(static_cast<unsigned char>(Name[1])))
|
|
return GLFW_KEY_F1 + std::stoi(Name.substr(1)) - 1;
|
|
return GLFW_KEY_UNKNOWN;
|
|
}
|
|
|
|
int modifier_of(int const Key)
|
|
{
|
|
return Key == GLFW_KEY_LEFT_CONTROL ? GLFW_MOD_CONTROL : Key == GLFW_KEY_LEFT_SHIFT ? GLFW_MOD_SHIFT : Key == GLFW_KEY_LEFT_ALT ? GLFW_MOD_ALT : 0;
|
|
}
|
|
|
|
void modifiers(int const Mods)
|
|
{
|
|
auto &io{ImGui::GetIO()};
|
|
io.AddKeyEvent(ImGuiMod_Ctrl, (Mods & GLFW_MOD_CONTROL) != 0);
|
|
io.AddKeyEvent(ImGuiMod_Shift, (Mods & GLFW_MOD_SHIFT) != 0);
|
|
io.AddKeyEvent(ImGuiMod_Alt, (Mods & GLFW_MOD_ALT) != 0);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void scripted_input::queue(std::function<void()> Event)
|
|
{
|
|
s_driving = true;
|
|
m_events.emplace_back(std::move(Event));
|
|
}
|
|
|
|
void scripted_input::deliver()
|
|
{
|
|
auto const events{std::move(m_events)};
|
|
m_events.clear();
|
|
for (auto const &event : events)
|
|
event();
|
|
}
|
|
|
|
void scripted_input::mouse_to(glm::dvec2 const &Screen)
|
|
{
|
|
bool const entered{m_mouse.has_value()};
|
|
m_mouse = Screen;
|
|
queue([Screen, entered]() {
|
|
if (false == entered)
|
|
ui_layer::cursor_enter_callback(1);
|
|
ui_layer::cursor_pos_callback(Screen.x, Screen.y);
|
|
Global.cursor_pos = glm::ivec2(Screen);
|
|
Application.on_cursor_pos(Screen.x, Screen.y);
|
|
});
|
|
}
|
|
|
|
bool scripted_input::dispatch(std::string const &Command, std::istringstream &Words)
|
|
{
|
|
if (Command == "mouse")
|
|
{
|
|
glm::dvec2 screen{0.0};
|
|
Words >> screen.x >> screen.y;
|
|
mouse_to(screen);
|
|
WriteLog(format("SELFTEST mouse %.0f %.0f", screen.x, screen.y));
|
|
return true;
|
|
}
|
|
if (Command == "leave")
|
|
{
|
|
m_mouse.reset();
|
|
queue([]() { ui_layer::cursor_enter_callback(0); });
|
|
WriteLog("SELFTEST leave");
|
|
return true;
|
|
}
|
|
if (Command == "button")
|
|
{
|
|
std::string which;
|
|
std::string action;
|
|
Words >> which >> action;
|
|
auto const button{which == "right" ? GLFW_MOUSE_BUTTON_RIGHT : which == "middle" ? GLFW_MOUSE_BUTTON_MIDDLE : GLFW_MOUSE_BUTTON_LEFT};
|
|
auto const state{action == "release" ? GLFW_RELEASE : GLFW_PRESS};
|
|
queue([button, state, mods = m_mods]() {
|
|
Application.on_mouse_button(button, state, mods);
|
|
modifiers(mods);
|
|
});
|
|
return true;
|
|
}
|
|
if (Command == "wheel")
|
|
{
|
|
double offset{0.0};
|
|
Words >> offset;
|
|
queue([offset, mods = m_mods]() {
|
|
Application.on_scroll(0.0, offset);
|
|
modifiers(mods);
|
|
});
|
|
return true;
|
|
}
|
|
if (Command == "press" || Command == "release" || Command == "tap")
|
|
{
|
|
std::string name;
|
|
Words >> name;
|
|
auto const key{key_named(name)};
|
|
if (key == GLFW_KEY_UNKNOWN)
|
|
{
|
|
WriteLog("SELFTEST " + Command + ": unknown key " + name);
|
|
return true;
|
|
}
|
|
if (Command != "release")
|
|
{
|
|
m_mods |= modifier_of(key);
|
|
queue([key, mods = m_mods]() {
|
|
Application.on_key(key, 0, GLFW_PRESS, mods);
|
|
modifiers(mods);
|
|
});
|
|
}
|
|
if (Command != "press")
|
|
{
|
|
m_mods &= ~modifier_of(key);
|
|
queue([key, mods = m_mods]() {
|
|
Application.on_key(key, 0, GLFW_RELEASE, mods);
|
|
modifiers(mods);
|
|
});
|
|
}
|
|
return true;
|
|
}
|
|
if (Command == "type")
|
|
{
|
|
std::string text;
|
|
std::getline(Words >> std::ws, text);
|
|
for (std::size_t index = 0; index < text.size();)
|
|
{
|
|
auto const lead{static_cast<unsigned char>(text[index])};
|
|
auto const extra{lead >= 0xF0 ? 3 : lead >= 0xE0 ? 2 : lead >= 0xC0 ? 1 : 0};
|
|
unsigned int code{extra == 0 ? lead : lead & (0x3Fu >> extra)};
|
|
for (int k = 1; k <= extra && index + k < text.size(); ++k)
|
|
code = (code << 6) | (static_cast<unsigned char>(text[index + k]) & 0x3Fu);
|
|
queue([code]() { Application.on_char(code); });
|
|
index += extra + 1;
|
|
}
|
|
return true;
|
|
}
|
|
if (Command == "softcursor")
|
|
{
|
|
int on{1};
|
|
Words >> on;
|
|
ImGui::GetIO().MouseDrawCursor = on != 0;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void input_script::step()
|
|
{
|
|
if (false == m_loaded)
|
|
{
|
|
m_loaded = true;
|
|
auto const *file{std::getenv(m_variable)};
|
|
if (file == nullptr)
|
|
return;
|
|
std::ifstream stream(file);
|
|
std::string line;
|
|
while (std::getline(stream, line))
|
|
if (false == line.empty() && line.front() != '#')
|
|
m_lines.push_back(line);
|
|
WriteLog("SELFTEST: " + std::to_string(m_lines.size()) + " steps from " + file);
|
|
}
|
|
if (m_wait > 0)
|
|
{
|
|
--m_wait;
|
|
return;
|
|
}
|
|
while (m_next < m_lines.size())
|
|
{
|
|
std::istringstream words(m_lines[m_next++]);
|
|
std::string command;
|
|
words >> command;
|
|
if (command == "wait")
|
|
{
|
|
words >> m_wait;
|
|
return;
|
|
}
|
|
if (command == "screenshot")
|
|
{
|
|
Application.queue_screenshot();
|
|
m_wait = 3;
|
|
return;
|
|
}
|
|
if (command == "log")
|
|
{
|
|
std::string text;
|
|
std::getline(words >> std::ws, text);
|
|
WriteLog("SELFTEST " + text);
|
|
continue;
|
|
}
|
|
if (command == "editorscript")
|
|
{
|
|
std::string file;
|
|
words >> file;
|
|
#ifdef _WIN32
|
|
_putenv_s("EU07_EDITOR_SELFTEST", file.c_str());
|
|
#else
|
|
setenv("EU07_EDITOR_SELFTEST", file.c_str(), 1);
|
|
#endif
|
|
WriteLog("SELFTEST editor script " + file);
|
|
continue;
|
|
}
|
|
if (command == "quit")
|
|
{
|
|
if (false == m_quitting)
|
|
{
|
|
WriteLog("SELFTEST done");
|
|
m_quitting = true;
|
|
m_wait = 30;
|
|
--m_next;
|
|
return;
|
|
}
|
|
Application.queue_quit(true);
|
|
return;
|
|
}
|
|
if (false == m_input.dispatch(command, words))
|
|
WriteLog("SELFTEST unknown command " + command);
|
|
}
|
|
}
|