feat: players interpolation & add hud.set_allow_pause(...)

This commit is contained in:
MihailRis 2025-01-17 01:44:46 +03:00
parent 036e13a2ca
commit 2fa71b3bf0
25 changed files with 232 additions and 41 deletions

View File

@ -19,7 +19,7 @@ function on_render()
return return
end end
local rx, ry, rz = player.get_rot(pid) local rx, ry, rz = player.get_rot(pid, true)
rig:set_matrix(headIndex, mat4.rotate({1, 0, 0}, ry)) rig:set_matrix(headIndex, mat4.rotate({1, 0, 0}, ry))
rig:set_matrix(bodyIndex, mat4.rotate({0, 1, 0}, rx)) rig:set_matrix(bodyIndex, mat4.rotate({0, 1, 0}, rx))

View File

@ -49,6 +49,7 @@ local Skeleton = {__index={
set_visible=function(self, i, b) return __skeleton.set_visible(self.eid, i, b) end, set_visible=function(self, i, b) return __skeleton.set_visible(self.eid, i, b) end,
get_color=function(self) return __skeleton.get_color(self.eid) end, get_color=function(self) return __skeleton.get_color(self.eid) end,
set_color=function(self, color) return __skeleton.set_color(self.eid, color) end, set_color=function(self, color) return __skeleton.set_color(self.eid, color) end,
set_interpolated=function(self, b) return __skeleton.set_interpolated(self.eid, b) end,
}} }}
local function new_Skeleton(eid) local function new_Skeleton(eid)

View File

@ -223,7 +223,8 @@ void Hud::cleanup() {
} }
void Hud::processInput(bool visible) { void Hud::processInput(bool visible) {
if (!Window::isFocused() && !pause && !isInventoryOpen()) { auto menu = gui.getMenu();
if (!Window::isFocused() && !menu->hasOpenPage() && !isInventoryOpen()) {
setPause(true); setPause(true);
} }
if (!pause && visible && Events::jactive(BIND_HUD_INVENTORY)) { if (!pause && visible && Events::jactive(BIND_HUD_INVENTORY)) {
@ -318,14 +319,13 @@ void Hud::update(bool visible) {
if (!visible && inventoryOpen) { if (!visible && inventoryOpen) {
closeInventory(); closeInventory();
} }
if (pause && menu->getCurrent().panel == nullptr) { if (pause && !menu->hasOpenPage()) {
setPause(false); setPause(false);
} }
if (!gui.isFocusCaught()) { if (!gui.isFocusCaught()) {
processInput(visible); processInput(visible);
} }
if ((pause || inventoryOpen) == Events::_cursor_locked) { if ((menu->hasOpenPage() || inventoryOpen) == Events::isCursorLocked()) {
Events::toggleCursor(); Events::toggleCursor();
} }
@ -590,7 +590,9 @@ void Hud::draw(const DrawContext& ctx){
const Viewport& viewport = ctx.getViewport(); const Viewport& viewport = ctx.getViewport();
const uint width = viewport.getWidth(); const uint width = viewport.getWidth();
const uint height = viewport.getHeight(); const uint height = viewport.getHeight();
auto menu = gui.getMenu();
darkOverlay->setVisible(menu->hasOpenPage());
updateElementsPosition(viewport); updateElementsPosition(viewport);
uicamera->setFov(height); uicamera->setFov(height);
@ -676,19 +678,20 @@ void Hud::setPause(bool pause) {
if (this->pause == pause) { if (this->pause == pause) {
return; return;
} }
this->pause = pause; if (allowPause) {
this->pause = pause;
}
if (inventoryOpen) { if (inventoryOpen) {
closeInventory(); closeInventory();
} }
const auto& menu = gui.getMenu(); const auto& menu = gui.getMenu();
if (pause) { if (menu->hasOpenPage()) {
menu->setPage("pause");
} else {
menu->reset(); menu->reset();
} else {
menu->setPage("pause");
} }
darkOverlay->setVisible(pause);
menu->setVisible(pause); menu->setVisible(pause);
} }
@ -721,3 +724,12 @@ void Hud::setDebugCheats(bool flag) {
debugPanel->setZIndex(2); debugPanel->setZIndex(2);
gui.add(debugPanel); gui.add(debugPanel);
} }
void Hud::setAllowPause(bool flag) {
if (pause) {
auto menu = gui.getMenu();
setPause(false);
menu->setPage("pause", true);
}
allowPause = flag;
}

View File

@ -113,6 +113,8 @@ class Hud : public util::ObjectsKeeper {
bool showContentPanel = true; bool showContentPanel = true;
/// @brief Provide cheat controllers to the debug panel /// @brief Provide cheat controllers to the debug panel
bool allowDebugCheats = true; bool allowDebugCheats = true;
/// @brief Allow actual pause
bool allowPause = true;
bool debug = false; bool debug = false;
/// @brief UI element will be dynamicly positioned near to inventory or in screen center /// @brief UI element will be dynamicly positioned near to inventory or in screen center
std::shared_ptr<gui::UINode> secondUI; std::shared_ptr<gui::UINode> secondUI;
@ -206,6 +208,8 @@ public:
void setDebugCheats(bool flag); void setDebugCheats(bool flag);
void setAllowPause(bool flag);
static bool showGeneratorMinimap; static bool showGeneratorMinimap;
/// @brief Runtime updating debug visualization texture /// @brief Runtime updating debug visualization texture

View File

@ -168,8 +168,9 @@ void LevelScreen::updateHotkeys() {
void LevelScreen::update(float delta) { void LevelScreen::update(float delta) {
gui::GUI* gui = engine.getGUI(); gui::GUI* gui = engine.getGUI();
auto menu = gui->getMenu();
bool inputLocked = hud->isPause() || bool inputLocked = menu->hasOpenPage() ||
hud->isInventoryOpen() || hud->isInventoryOpen() ||
gui->isFocusCaught(); gui->isFocusCaught();
if (!gui->isFocusCaught()) { if (!gui->isFocusCaught()) {

View File

@ -12,6 +12,7 @@
#include "window/Camera.hpp" #include "window/Camera.hpp"
#include "objects/Player.hpp" #include "objects/Player.hpp"
#include "objects/Players.hpp" #include "objects/Players.hpp"
#include "objects/Entities.hpp"
#include "logic/LevelController.hpp" #include "logic/LevelController.hpp"
#include "util/stringutil.hpp" #include "util/stringutil.hpp"
#include "engine/Engine.hpp" #include "engine/Engine.hpp"
@ -159,7 +160,11 @@ void Decorator::update(float delta, const Camera& camera) {
renderer.texts->remove(textsIter->second); renderer.texts->remove(textsIter->second);
textsIter = playerTexts.erase(textsIter); textsIter = playerTexts.erase(textsIter);
} else { } else {
note->setPosition(player->getPosition() + glm::vec3(0, 1, 0)); glm::vec3 position = player->getPosition();
if (auto entity = level.entities->get(player->getEntity())) {
position = entity->getInterpolatedPosition();
}
note->setPosition(position + glm::vec3(0, 1, 0));
++textsIter; ++textsIter;
} }
} }

View File

@ -274,8 +274,9 @@ void WorldRenderer::renderHands(
glm::mat4(1.0f), -glm::pi<float>() * 0.5f, glm::vec3(0, 1, 0) glm::mat4(1.0f), -glm::pi<float>() * 0.5f, glm::vec3(0, 1, 0)
); );
prevRotation = rotation; prevRotation = rotation;
glm::vec3 cameraRotation = player.getRotation();
auto offset = -(camera.position - player.getPosition()); auto offset = -(camera.position - player.getPosition());
float angle = glm::radians(player.rotation.x - 90); float angle = glm::radians(cameraRotation.x - 90);
float cos = glm::cos(angle); float cos = glm::cos(angle);
float sin = glm::sin(angle); float sin = glm::sin(angle);

View File

@ -166,7 +166,7 @@ void GUI::actFocused() {
focus->keyPressed(key); focus->keyPressed(key);
} }
if (!Events::_cursor_locked) { if (!Events::isCursorLocked()) {
if (Events::clicked(mousecode::BUTTON_1) && if (Events::clicked(mousecode::BUTTON_1) &&
(Events::jclicked(mousecode::BUTTON_1) || Events::delta.x || Events::delta.y)) (Events::jclicked(mousecode::BUTTON_1) || Events::delta.x || Events::delta.y))
{ {
@ -189,7 +189,7 @@ void GUI::act(float delta, const Viewport& vp) {
auto prevfocus = focus; auto prevfocus = focus;
updateTooltip(delta); updateTooltip(delta);
if (!Events::_cursor_locked) { if (!Events::isCursorLocked()) {
actMouse(delta); actMouse(delta);
} else { } else {
if (hover) { if (hover) {

View File

@ -91,6 +91,10 @@ Page& Menu::getCurrent() {
return current; return current;
} }
bool Menu::hasOpenPage() const {
return current.panel != nullptr;
}
void Menu::clearHistory() { void Menu::clearHistory() {
pageStack = std::stack<Page>(); pageStack = std::stack<Page>();
} }

View File

@ -64,5 +64,7 @@ namespace gui {
/// @brief Get current page /// @brief Get current page
Page& getCurrent(); Page& getCurrent();
bool hasOpenPage() const;
}; };
} }

View File

@ -73,6 +73,7 @@ void LevelController::update(float delta, bool pause) {
if (player->isSuspended()) { if (player->isSuspended()) {
continue; continue;
} }
player->rotationInterpolation.updateTimer(delta);
player->updateEntity(); player->updateEntity();
glm::vec3 position = player->getPosition(); glm::vec3 position = player->getPosition();
player->chunks->configure( player->chunks->configure(

View File

@ -54,7 +54,7 @@ void CameraControl::refresh() {
} }
void CameraControl::updateMouse(PlayerInput& input) { void CameraControl::updateMouse(PlayerInput& input) {
glm::vec3& rotation = player.rotation; glm::vec3 rotation = player.getRotation();
float sensitivity = float sensitivity =
(input.zoom ? settings.sensitivity.get() / 4.f (input.zoom ? settings.sensitivity.get() / 4.f
@ -75,6 +75,8 @@ void CameraControl::updateMouse(PlayerInput& input) {
rotation.x += 360.f; rotation.x += 360.f;
} }
player.setRotation(rotation);
camera->rotation = glm::mat4(1.0f); camera->rotation = glm::mat4(1.0f);
camera->rotate( camera->rotate(
glm::radians(rotation.y), glm::radians(rotation.y),

View File

@ -130,6 +130,22 @@ static int l_set_color(lua::State* L) {
return 0; return 0;
} }
static int l_is_interpolated(lua::State* L) {
if (auto entity = get_entity(L, 1)) {
auto& skeleton = entity->getSkeleton();
return lua::pushboolean(L, skeleton.interpolation.isEnabled());
}
return 0;
}
static int l_set_interpolated(lua::State* L) {
if (auto entity = get_entity(L, 1)) {
auto& skeleton = entity->getSkeleton();
skeleton.interpolation.setEnabled(lua::toboolean(L, 2));
}
return 0;
}
const luaL_Reg skeletonlib[] = { const luaL_Reg skeletonlib[] = {
{"get_model", lua::wrap<l_get_model>}, {"get_model", lua::wrap<l_get_model>},
{"set_model", lua::wrap<l_set_model>}, {"set_model", lua::wrap<l_set_model>},
@ -142,4 +158,6 @@ const luaL_Reg skeletonlib[] = {
{"set_visible", lua::wrap<l_set_visible>}, {"set_visible", lua::wrap<l_set_visible>},
{"get_color", lua::wrap<l_get_color>}, {"get_color", lua::wrap<l_get_color>},
{"set_color", lua::wrap<l_set_color>}, {"set_color", lua::wrap<l_set_color>},
{"is_interpolated", lua::wrap<l_is_interpolated>},
{"set_interpolated", lua::wrap<l_set_interpolated>},
{NULL, NULL}}; {NULL, NULL}};

View File

@ -170,6 +170,11 @@ static int l_set_debug_cheats(lua::State* L) {
return 0; return 0;
} }
static int l_set_allow_pause(lua::State* L) {
hud->setAllowPause(lua::toboolean(L, 1));
return 0;
}
const luaL_Reg hudlib[] = { const luaL_Reg hudlib[] = {
{"open_inventory", lua::wrap<l_open_inventory>}, {"open_inventory", lua::wrap<l_open_inventory>},
{"close_inventory", lua::wrap<l_close_inventory>}, {"close_inventory", lua::wrap<l_close_inventory>},
@ -187,5 +192,6 @@ const luaL_Reg hudlib[] = {
{"_is_content_access", lua::wrap<l_is_content_access>}, {"_is_content_access", lua::wrap<l_is_content_access>},
{"_set_content_access", lua::wrap<l_set_content_access>}, {"_set_content_access", lua::wrap<l_set_content_access>},
{"_set_debug_cheats", lua::wrap<l_set_debug_cheats>}, {"_set_debug_cheats", lua::wrap<l_set_debug_cheats>},
{"set_allow_pause", lua::wrap<l_set_allow_pause>},
{NULL, NULL} {NULL, NULL}
}; };

View File

@ -61,7 +61,7 @@ static int l_set_vel(lua::State* L) {
static int l_get_rot(lua::State* L) { static int l_get_rot(lua::State* L) {
if (auto player = get_player(L, 1)) { if (auto player = get_player(L, 1)) {
return lua::pushvec_stack(L, player->rotation); return lua::pushvec_stack(L, player->getRotation(lua::toboolean(L, 2)));
} }
return 0; return 0;
} }
@ -71,7 +71,7 @@ static int l_set_rot(lua::State* L) {
if (!player) { if (!player) {
return 0; return 0;
} }
glm::vec3& rotation = player->rotation; glm::vec3 rotation = player->getRotation();
auto x = lua::tonumber(L, 2); auto x = lua::tonumber(L, 2);
auto y = lua::tonumber(L, 3); auto y = lua::tonumber(L, 3);
@ -82,6 +82,7 @@ static int l_set_rot(lua::State* L) {
rotation.x = x; rotation.x = x;
rotation.y = y; rotation.y = y;
rotation.z = z; rotation.z = z;
player->setRotation(rotation);
return 0; return 0;
} }

View File

@ -38,6 +38,18 @@ void Transform::refresh() {
dirty = false; dirty = false;
} }
void Entity::setInterpolatedPosition(const glm::vec3& position) {
getSkeleton().interpolation.refresh(position);
}
glm::vec3 Entity::getInterpolatedPosition() const {
const auto& skeleton = getSkeleton();
if (skeleton.interpolation.isEnabled()) {
return skeleton.interpolation.getCurrent();
}
return getTransform().pos;
}
void Entity::destroy() { void Entity::destroy() {
if (isValid()) { if (isValid()) {
entities.despawn(id); entities.despawn(id);
@ -561,11 +573,14 @@ void Entities::render(
if (transform.dirty) { if (transform.dirty) {
transform.refresh(); transform.refresh();
} }
if (skeleton.interpolation.isEnabled()) {
skeleton.interpolation.updateTimer(delta);
}
const auto& pos = transform.pos; const auto& pos = transform.pos;
const auto& size = transform.size; const auto& size = transform.size;
if (!frustum || frustum->isBoxVisible(pos - size, pos + size)) { if (!frustum || frustum->isBoxVisible(pos - size, pos + size)) {
const auto* rigConfig = skeleton.config; const auto* rigConfig = skeleton.config;
rigConfig->render(assets, batch, skeleton, transform.combined); rigConfig->render(assets, batch, skeleton, transform.combined, pos);
} }
} }
} }

View File

@ -170,6 +170,10 @@ public:
registry.get<EntityId>(entity).player = id; registry.get<EntityId>(entity).player = id;
} }
void setInterpolatedPosition(const glm::vec3& position);
glm::vec3 getInterpolatedPosition() const;
void destroy(); void destroy();
}; };

View File

@ -181,6 +181,7 @@ void Player::teleport(glm::vec3 position) {
if (auto entity = level.entities->get(eid)) { if (auto entity = level.entities->get(eid)) {
entity->getRigidbody().hitbox.position = position; entity->getRigidbody().hitbox.position = position;
entity->getTransform().setPos(position); entity->getTransform().setPos(position);
entity->setInterpolatedPosition(position);
} }
} }
@ -296,6 +297,18 @@ glm::vec3 Player::getSpawnPoint() const {
return spawnpoint; return spawnpoint;
} }
glm::vec3 Player::getRotation(bool interpolated) const {
if (interpolated) {
return rotationInterpolation.getCurrent();
}
return rotation;
}
void Player::setRotation(const glm::vec3& rotation) {
this->rotation = rotation;
rotationInterpolation.refresh(rotation);
}
dv::value Player::serialize() const { dv::value Player::serialize() const {
auto root = dv::object(); auto root = dv::object();

View File

@ -7,6 +7,7 @@
#include "interfaces/Serializable.hpp" #include "interfaces/Serializable.hpp"
#include "settings.hpp" #include "settings.hpp"
#include "voxels/voxel.hpp" #include "voxels/voxel.hpp"
#include "util/Interpolation.hpp"
class Chunks; class Chunks;
class Camera; class Camera;
@ -55,11 +56,15 @@ class Player : public Serializable {
bool loadingChunks = true; bool loadingChunks = true;
entityid_t eid; entityid_t eid;
entityid_t selectedEid = 0; entityid_t selectedEid = 0;
glm::vec3 rotation {};
public: public:
util::VecInterpolation<3, float, true> rotationInterpolation {true};
std::unique_ptr<Chunks> chunks; std::unique_ptr<Chunks> chunks;
std::shared_ptr<Camera> fpCamera, spCamera, tpCamera; std::shared_ptr<Camera> fpCamera, spCamera, tpCamera;
std::shared_ptr<Camera> currentCamera; std::shared_ptr<Camera> currentCamera;
glm::vec3 rotation {};
CursorSelection selection {}; CursorSelection selection {};
Player( Player(
@ -123,6 +128,9 @@ public:
void setSpawnPoint(glm::vec3 point); void setSpawnPoint(glm::vec3 point);
glm::vec3 getSpawnPoint() const; glm::vec3 getSpawnPoint() const;
glm::vec3 getRotation(bool interpolated=false) const;
void setRotation(const glm::vec3& rotation);
dv::value serialize() const override; dv::value serialize() const override;
void deserialize(const dv::value& src) override; void deserialize(const dv::value& src) override;

View File

@ -6,9 +6,8 @@
#include "graphics/commons/Model.hpp" #include "graphics/commons/Model.hpp"
#include "graphics/render/ModelBatch.hpp" #include "graphics/render/ModelBatch.hpp"
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/ext/matrix_transform.hpp> #include <glm/ext/matrix_transform.hpp>
#include <glm/gtx/norm.hpp> #include <glm/gtx/matrix_decompose.hpp>
using namespace rigging; using namespace rigging;
@ -69,7 +68,7 @@ SkeletonConfig::SkeletonConfig(
} }
size_t SkeletonConfig::update( size_t SkeletonConfig::update(
size_t index, Skeleton& skeleton, Bone* node, glm::mat4 matrix size_t index, Skeleton& skeleton, Bone* node, const glm::mat4& matrix
) const { ) const {
auto boneMatrix = skeleton.pose.matrices[index]; auto boneMatrix = skeleton.pose.matrices[index];
auto boneOffset = node->getOffset(); auto boneOffset = node->getOffset();
@ -90,17 +89,32 @@ size_t SkeletonConfig::update(
return count; return count;
} }
void SkeletonConfig::update(Skeleton& skeleton, glm::mat4 matrix) const { void SkeletonConfig::update(
update(0, skeleton, root.get(), matrix); Skeleton& skeleton, const glm::mat4& matrix, const glm::vec3& position
) const {
if (skeleton.interpolation.isEnabled()) {
const auto& interpolation = skeleton.interpolation;
glm::vec3 scale, translation, skew;
glm::quat rotation;
glm::vec4 perspective;
glm::decompose(matrix, scale, rotation, translation, skew, perspective);
auto delta = interpolation.getCurrent() - position;
auto interpolatedMatrix = glm::translate(matrix, delta);
update(0, skeleton, root.get(), interpolatedMatrix);
} else {
update(0, skeleton, root.get(), matrix);
}
} }
void SkeletonConfig::render( void SkeletonConfig::render(
const Assets& assets, const Assets& assets,
ModelBatch& batch, ModelBatch& batch,
Skeleton& skeleton, Skeleton& skeleton,
const glm::mat4& matrix const glm::mat4& matrix,
const glm::vec3& position
) const { ) const {
update(skeleton, matrix); update(skeleton, matrix, position);
if (!skeleton.visible) { if (!skeleton.visible) {
return; return;

View File

@ -1,12 +1,15 @@
#pragma once #pragma once
#include <glm/glm.hpp> #define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/norm.hpp>
#include <memory> #include <memory>
#include <string> #include <string>
#include <cmath>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "typedefs.hpp" #include "typedefs.hpp"
#include "util/Interpolation.hpp"
class Assets; class Assets;
class ModelBatch; class ModelBatch;
@ -83,6 +86,8 @@ namespace rigging {
bool visible; bool visible;
glm::vec3 tint {1.0f, 1.0f, 1.0f}; glm::vec3 tint {1.0f, 1.0f, 1.0f};
util::VecInterpolation<3, float> interpolation {false};
Skeleton(const SkeletonConfig* config); Skeleton(const SkeletonConfig* config);
}; };
@ -100,7 +105,7 @@ namespace rigging {
std::vector<Bone*> nodes; std::vector<Bone*> nodes;
size_t update( size_t update(
size_t index, Skeleton& skeleton, Bone* node, glm::mat4 matrix size_t index, Skeleton& skeleton, Bone* node, const glm::mat4& matrix
) const; ) const;
public: public:
SkeletonConfig( SkeletonConfig(
@ -109,12 +114,18 @@ namespace rigging {
size_t nodesCount size_t nodesCount
); );
void update(Skeleton& skeleton, glm::mat4 matrix) const; void update(
Skeleton& skeleton,
const glm::mat4& matrix,
const glm::vec3& position
) const;
void render( void render(
const Assets& assets, const Assets& assets,
ModelBatch& batch, ModelBatch& batch,
Skeleton& skeleton, Skeleton& skeleton,
const glm::mat4& matrix const glm::mat4& matrix,
const glm::vec3& position
) const; ) const;
Skeleton instance() const { Skeleton instance() const {

View File

@ -0,0 +1,60 @@
#pragma once
#include <limits>
#include <glm/glm.hpp>
namespace util {
template<int N, typename T, bool angular=false>
class VecInterpolation {
bool enabled;
glm::vec<N, T> prevPos {std::numeric_limits<T>::quiet_NaN()};
glm::vec<N, T> nextPos {};
T refreshInterval = 0.0;
T timer = 0.0;
T intervalUpdateFactor = 0.1;
public:
VecInterpolation(bool enabled) : enabled(enabled) {}
void refresh(const glm::vec<N, T>& position) {
auto current = getCurrent();
prevPos = current;
nextPos = position;
refreshInterval = timer * intervalUpdateFactor +
refreshInterval * (1.0 - intervalUpdateFactor);
timer = 0.0;
if constexpr (angular) {
for (int i = 0; i < N; i++) {
T diff = nextPos[i] - prevPos[i];
if (glm::abs(diff) > 180.0f) {
nextPos[i] += (diff > 0.0f ? -360.0f : 360.0f);
}
}
}
}
void updateTimer(T delta) {
timer += delta;
}
glm::vec<N, T> getCurrent() const {
if (refreshInterval < 0.001 || std::isnan(prevPos.x)) {
return nextPos;
}
T t = timer / refreshInterval;
return nextPos * t + prevPos * (1.0f - t);
}
T getRefreshInterval() const {
return refreshInterval;
}
bool isEnabled() const {
return enabled;
}
void setEnabled(bool enabled) {
this->enabled = enabled;
}
};
}

View File

@ -18,8 +18,8 @@ uint Events::currentFrame = 0;
int Events::scroll = 0; int Events::scroll = 0;
glm::vec2 Events::delta = {}; glm::vec2 Events::delta = {};
glm::vec2 Events::cursor = {}; glm::vec2 Events::cursor = {};
bool Events::cursor_drag = false; bool Events::cursorDrag = false;
bool Events::_cursor_locked = false; bool Events::cursorLocked = false;
std::vector<uint> Events::codepoints; std::vector<uint> Events::codepoints;
std::vector<keycode> Events::pressedKeys; std::vector<keycode> Events::pressedKeys;
std::unordered_map<std::string, Binding> Events::bindings; std::unordered_map<std::string, Binding> Events::bindings;
@ -61,10 +61,10 @@ bool Events::jclicked(int button) {
} }
void Events::toggleCursor() { void Events::toggleCursor() {
cursor_drag = false; cursorDrag = false;
_cursor_locked = !_cursor_locked; cursorLocked = !cursorLocked;
Window::setCursorMode( Window::setCursorMode(
_cursor_locked ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL cursorLocked ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL
); );
} }
@ -170,11 +170,11 @@ void Events::setButton(int button, bool b) {
} }
void Events::setPosition(float xpos, float ypos) { void Events::setPosition(float xpos, float ypos) {
if (Events::cursor_drag) { if (Events::cursorDrag) {
Events::delta.x += xpos - Events::cursor.x; Events::delta.x += xpos - Events::cursor.x;
Events::delta.y += ypos - Events::cursor.y; Events::delta.y += ypos - Events::cursor.y;
} else { } else {
Events::cursor_drag = true; Events::cursorDrag = true;
} }
Events::cursor.x = xpos; Events::cursor.x = xpos;
Events::cursor.y = ypos; Events::cursor.y = ypos;
@ -249,3 +249,7 @@ void Events::enableBindings() {
binding.enable = true; binding.enable = true;
} }
} }
bool Events::isCursorLocked() {
return cursorLocked;
}

View File

@ -19,12 +19,12 @@ class Events {
static bool keys[KEYS_BUFFER_SIZE]; static bool keys[KEYS_BUFFER_SIZE];
static uint frames[KEYS_BUFFER_SIZE]; static uint frames[KEYS_BUFFER_SIZE];
static uint currentFrame; static uint currentFrame;
static bool cursor_drag; static bool cursorDrag;
static bool cursorLocked;
public: public:
static int scroll; static int scroll;
static glm::vec2 delta; static glm::vec2 delta;
static glm::vec2 cursor; static glm::vec2 cursor;
static bool _cursor_locked;
static std::vector<uint> codepoints; static std::vector<uint> codepoints;
static std::vector<keycode> pressedKeys; static std::vector<keycode> pressedKeys;
static std::unordered_map<std::string, Binding> bindings; static std::unordered_map<std::string, Binding> bindings;
@ -65,4 +65,6 @@ public:
BindType bindType BindType bindType
); );
static void enableBindings(); static void enableBindings();
static bool isCursorLocked();
}; };

View File

@ -389,7 +389,9 @@ void Window::toggleFullscreen() {
GLFWmonitor* monitor = glfwGetPrimaryMonitor(); GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor); const GLFWvidmode* mode = glfwGetVideoMode(monitor);
if (Events::_cursor_locked) Events::toggleCursor(); if (Events::isCursorLocked()){
Events::toggleCursor();
}
if (fullscreen) { if (fullscreen) {
glfwGetWindowPos(window, &posX, &posY); glfwGetWindowPos(window, &posX, &posY);