mirror of
https://github.com/Awakenchan/LanternEngine.git
synced 2026-11-10 01:11:45 -10:00
232 lines
9.7 KiB
C++
232 lines
9.7 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
#include "../gpu/shim/input/bindings.h"
|
|
#include "../gpu/shim/input/mouse_turn.h"
|
|
#include "../gpu/shim/input/pad.h"
|
|
#include <SDL3/SDL.h>
|
|
#include <cassert>
|
|
#include <chrono>
|
|
#include <cmath>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <string>
|
|
#include <thread>
|
|
|
|
void host_log(const char*, ...) {}
|
|
std::uint32_t menu_confirm_button() { return PadBits::kCross; }
|
|
std::uint32_t menu_back_button() { return PadBits::kCircle; }
|
|
|
|
namespace {
|
|
struct Keyboard {
|
|
bool keys[SDL_SCANCODE_COUNT] = {};
|
|
bool held[kBindCount] = {};
|
|
Keyboard& Down(SDL_Scancode sc, bool down = true) {
|
|
keys[sc] = down;
|
|
host_bindings_keys_held(keys, SDL_SCANCODE_COUNT, held);
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
PadState Pad(std::initializer_list<int> actions, bool strong = false) {
|
|
bool held[kBindCount] = {};
|
|
for (int a : actions) held[a] = true;
|
|
PadState pad;
|
|
host_bindings_apply(held, strong, pad);
|
|
return pad;
|
|
}
|
|
|
|
std::string Described(int action) {
|
|
char text[160];
|
|
host_binding_describe(action, text, sizeof text);
|
|
return text;
|
|
}
|
|
|
|
void Defaults() {
|
|
host_bindings_load_defaults();
|
|
assert(host_binding_key(kBindMoveF) == SDL_SCANCODE_W && host_binding_key(kBindWalk) == SDL_SCANCODE_LALT);
|
|
assert(host_binding_key(kBindAttack) == 0 && host_binding_mouse(kBindAttack) == 1);
|
|
assert(host_binding_ini_value(kBindAttack) == "Mouse1");
|
|
assert(host_binding_ini_value(kBindTransform) == "C, Mouse2");
|
|
assert(Described(kBindTransform) == "C / Middle Button");
|
|
assert(Described(kBindDebugMenu) == "` (backtick)");
|
|
assert(std::string(host_binding_info(kBindRoll).key) == "roll" && host_binding_info(kBindRoll).button == PadBits::kCircle);
|
|
}
|
|
|
|
void Movement() {
|
|
host_bindings_load_defaults();
|
|
PadState p = Pad({kBindMoveF});
|
|
assert(p.lx == kStickRest && p.ly == kStickLow);
|
|
p = Pad({kBindMoveF, kBindMoveR});
|
|
assert(p.lx == kStickHigh && p.ly == kStickLow);
|
|
|
|
const PadState straight = Pad({kBindMoveF, kBindWalk}), diagonal = Pad({kBindMoveF, kBindMoveR, kBindWalk});
|
|
const float reach = float(kStickRest - straight.ly);
|
|
assert(reach > 60 && reach < 90);
|
|
assert(std::abs(std::hypot(float(diagonal.lx) - kStickRest, float(diagonal.ly) - kStickRest) - reach) <= 1.5f);
|
|
|
|
Keyboard k;
|
|
k.Down(SDL_SCANCODE_W).Down(SDL_SCANCODE_S);
|
|
assert(!k.held[kBindMoveF] && !k.held[kBindMoveB]);
|
|
k.Down(SDL_SCANCODE_S, false);
|
|
assert(k.held[kBindMoveF]);
|
|
}
|
|
|
|
void Buttons() {
|
|
host_bindings_load_defaults();
|
|
PadState p = Pad({kBindAttack}, true);
|
|
assert(p.buttons == PadBits::kR2 && p.r2 == 255);
|
|
p = Pad({kBindFirearm});
|
|
assert(p.buttons == PadBits::kL2 && p.l2 == 255);
|
|
p = Pad({kBindConfirm, kBindBack});
|
|
assert(p.buttons == (PadBits::kCross | PadBits::kCircle));
|
|
p = Pad({kBindLookL, kBindLookD});
|
|
assert(p.rx == kStickLow && p.ry == kStickHigh);
|
|
|
|
p = Pad({kBindGestures, kBindEffects});
|
|
assert(p.buttons == PadBits::kTouchPad && p.touch_count == 2);
|
|
assert(p.touch[0].x < kTouchWidth / 2 && p.touch[1].x > kTouchWidth / 2 && p.touch[0].id == p.touch[1].id);
|
|
p = Pad({kBindDebugMenu});
|
|
assert(p.buttons == 0);
|
|
}
|
|
|
|
void IniValues() {
|
|
host_bindings_load_defaults();
|
|
assert(host_bindings_parse("attack", "E, Mouse2"));
|
|
assert(host_binding_key(kBindAttack) == SDL_SCANCODE_E && host_binding_mouse(kBindAttack) == 2);
|
|
assert(host_binding_ini_value(kBindAttack) == "E, Mouse2");
|
|
assert(host_bindings_parse("use_item", "F, Shift+E, Ctrl+Mouse4"));
|
|
assert(host_binding_ini_value(kBindUseItem) == "F, Shift+E, Ctrl+Mouse4");
|
|
assert(Described(kBindUseItem) == "F / Shift+E / Ctrl+Button 4");
|
|
assert(host_bindings_parse("lock_on", " \"control+alt+Q\" , WheelDown "));
|
|
assert(host_binding_ini_value(kBindLockOn) == "Ctrl+Alt+Q, WheelDown");
|
|
|
|
assert(host_bindings_parse("interact", "E, NoSuchKey, Mouse5"));
|
|
assert(host_binding_ini_value(kBindInteract) == "E, Mouse5");
|
|
assert(host_bindings_parse("blood_vial", "R, 1, 2, 3, 4, 5"));
|
|
assert(host_binding_ini_value(kBindBloodVial) == "R, 1, 2, 3");
|
|
assert(host_bindings_parse("gestures", "none") && host_binding_ini_value(kBindGestures) == "none");
|
|
assert(Described(kBindGestures) == "Unbound");
|
|
|
|
assert(host_bindings_parse("dpad_down", "Z") && host_binding_key(kBindSwitchItem) == SDL_SCANCODE_Z);
|
|
assert(!host_bindings_parse("jump", "Space"));
|
|
}
|
|
|
|
void Modifiers() {
|
|
host_bindings_load_defaults();
|
|
assert(host_bindings_parse("use_item", "F, Shift+E, Ctrl+Mouse4"));
|
|
assert(host_bindings_parse("interact", "E, Mouse5"));
|
|
Keyboard k;
|
|
k.Down(SDL_SCANCODE_E);
|
|
assert(k.held[kBindInteract] && !k.held[kBindUseItem]);
|
|
k.Down(SDL_SCANCODE_LSHIFT);
|
|
assert(!k.held[kBindInteract] && k.held[kBindUseItem] && k.held[kBindStrongMod]);
|
|
k.Down(SDL_SCANCODE_E, false).Down(SDL_SCANCODE_LSHIFT, false).Down(SDL_SCANCODE_RCTRL);
|
|
bool mouse[kBindCount];
|
|
host_bindings_mouse_held(1u << 3, mouse);
|
|
assert(mouse[kBindUseItem]);
|
|
k.Down(SDL_SCANCODE_RCTRL, false);
|
|
host_bindings_mouse_held(1u << 3, mouse);
|
|
assert(!mouse[kBindUseItem]);
|
|
|
|
assert(host_bindings_parse("walk", "Mouse5"));
|
|
host_bindings_mouse_held(1u << 4, mouse);
|
|
k.Down(SDL_SCANCODE_W);
|
|
assert(k.held[kBindWalk]);
|
|
host_bindings_mouse_held(0, mouse);
|
|
k.Down(SDL_SCANCODE_W);
|
|
assert(!k.held[kBindWalk]);
|
|
}
|
|
|
|
void Rebinding() {
|
|
host_bindings_load_defaults();
|
|
const std::uint64_t serial = host_bindings_serial();
|
|
|
|
host_bind_capture_begin(kBindAttack);
|
|
assert(host_bind_capturing() == kBindAttack && host_bind_capture_blocking());
|
|
assert(host_bind_capture_key(SDL_SCANCODE_F));
|
|
assert(host_bind_capturing() < 0 && host_bind_capture_take_done() == kBindAttack && host_bind_capture_take_done() < 0);
|
|
assert(host_binding_key(kBindAttack) == SDL_SCANCODE_F && host_binding_key(kBindUseItem) == 0);
|
|
assert(host_binding_mouse(kBindAttack) == 1 && host_bindings_serial() != serial);
|
|
|
|
assert(host_bind_capture_blocking());
|
|
host_bind_capture_note_held(true);
|
|
assert(host_bind_capture_blocking());
|
|
host_bind_capture_note_held(false);
|
|
assert(!host_bind_capture_blocking());
|
|
|
|
host_bind_capture_begin(kBindAttack);
|
|
host_bind_capture_key(SDL_SCANCODE_ESCAPE);
|
|
assert(host_binding_ini_value(kBindAttack) == "F, Mouse1");
|
|
host_bind_capture_note_held(false);
|
|
host_bind_capture_begin(kBindAttack);
|
|
host_bind_capture_key(SDL_SCANCODE_DELETE);
|
|
assert(host_binding_ini_value(kBindAttack) == "none");
|
|
host_bind_capture_note_held(false);
|
|
assert(host_bindings_parse("attack", "F, Mouse1"));
|
|
host_binding_clear(kBindAttack);
|
|
assert(host_binding_ini_value(kBindAttack) == "none");
|
|
|
|
host_bind_capture_begin(kBindLockOn);
|
|
assert(host_bind_capture_key(SDL_SCANCODE_LSHIFT, SDL_KMOD_LSHIFT) && host_bind_capturing() == kBindLockOn);
|
|
assert(!host_bind_capture_key_up(SDL_SCANCODE_Q));
|
|
assert(host_bind_capture_key(SDL_SCANCODE_Q, SDL_KMOD_LSHIFT) && host_bind_capturing() < 0);
|
|
assert(host_binding_ini_value(kBindLockOn) == "Shift+Q");
|
|
host_bind_capture_note_held(false);
|
|
host_bind_capture_begin(kBindLockOn);
|
|
host_bind_capture_key(SDL_SCANCODE_RSHIFT, SDL_KMOD_RSHIFT);
|
|
assert(host_bind_capture_key_up(SDL_SCANCODE_RSHIFT) && host_binding_ini_value(kBindLockOn) == "Right Shift");
|
|
host_bind_capture_note_held(false);
|
|
|
|
assert(!host_bind_capture_key(SDL_SCANCODE_K) && !host_bind_capture_mouse(1));
|
|
|
|
host_bind_capture_begin(kBindInteract);
|
|
assert(host_bind_capture_mouse(2) && host_bind_capturing() == kBindInteract);
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(320));
|
|
assert(host_bind_capture_mouse(2) && host_bind_capturing() < 0);
|
|
assert(host_binding_ini_value(kBindInteract) == "E, Mouse2" && host_binding_ini_value(kBindTransform) == "C");
|
|
host_bind_capture_note_held(false);
|
|
|
|
host_bind_note_clear_key();
|
|
assert(host_bind_take_clear_key() && !host_bind_take_clear_key());
|
|
host_bindings_load_defaults();
|
|
}
|
|
|
|
void MouseCameraTurn() {
|
|
using MouseTurn::DegreesPerCount;
|
|
assert(std::abs(DegreesPerCount(5) - 0.25f) < 1e-6f && std::abs(DegreesPerCount(0) - 0.1f) < 1e-6f);
|
|
assert(std::abs(DegreesPerCount(-1) - 0.08f) < 1e-6f && std::abs(DegreesPerCount(20) - 0.7f) < 1e-6f);
|
|
assert(DegreesPerCount(99) == DegreesPerCount(20) && DegreesPerCount(-99) == DegreesPerCount(-10));
|
|
assert(DegreesPerCount(-10) > 0 && DegreesPerCount(-10) < DegreesPerCount(-9));
|
|
|
|
const MouseTurn::Settings s{DegreesPerCount(5), false, false};
|
|
const auto turned = [&](int updates) {
|
|
float pitch = 0, yaw = 0;
|
|
for (int i = 0; i < updates; ++i) MouseTurn::Turn(120.0f / updates, 60.0f / updates, s, pitch, yaw, -1, 1);
|
|
return std::pair{pitch, yaw};
|
|
};
|
|
const auto a = turned(30), b = turned(60), c = turned(90);
|
|
assert(std::abs(a.first - b.first) < 1e-5f && std::abs(a.second - c.second) < 1e-5f);
|
|
assert(std::abs(a.second - 120 * 0.25f * 0.0174532924f) < 1e-5f && a.first > 0);
|
|
float pitch = 0, yaw = 0;
|
|
assert(!MouseTurn::Turn(0, 0, s, pitch, yaw, -1, 1) && pitch == 0 && yaw == 0);
|
|
const MouseTurn::Settings inverted{DegreesPerCount(5), true, true};
|
|
assert(MouseTurn::Turn(10, 10, inverted, pitch, yaw, -1, 1) && pitch < 0 && yaw < 0);
|
|
|
|
MouseTurn::Turn(10000, 10000, s, pitch, yaw, -0.5f, 0.5f);
|
|
assert(pitch == 0.5f && yaw >= -3.1416f && yaw <= 3.1416f);
|
|
MouseTurn::Turn(0, -10000, s, pitch, yaw, -0.5f, 0.5f);
|
|
assert(pitch == -0.5f);
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
Defaults();
|
|
Movement();
|
|
Buttons();
|
|
IniValues();
|
|
Modifiers();
|
|
Rebinding();
|
|
MouseCameraTurn();
|
|
std::puts("PC input: PASS (defaults, movement and walking, buttons and touchpad, lantern.ini values, modifiers, "
|
|
"rebinding, the mouse camera's turn)");
|
|
}
|