Skip to content

Commit 8060a89

Browse files
committed
Merge branch 'CameraSetYawCrash' into 'master'
Prevent hard freeze when camera receives invalid inputs from Lua Closes #8503 See merge request OpenMW/openmw!4681
2 parents 8a10de5 + d2f1eef commit 8060a89

File tree

3 files changed

+61
-11
lines changed

3 files changed

+61
-11
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@
234234
Bug #8445: Launcher crashes on exit when cell name loading thread is still running
235235
Bug #8462: Crashes when resizing the window on macOS
236236
Bug #8465: Blue screen w/ antialiasing and post-processing on macOS
237+
Bug #8503: Camera does not handle NaN gracefully
237238
Feature #1415: Infinite fall failsafe
238239
Feature #2566: Handle NAM9 records for manual cell references
239240
Feature #3501: OpenMW-CS: Instance Editing - Shortcuts for axial locking

apps/openmw/mwlua/camerabindings.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <components/lua/luastate.hpp>
44
#include <components/lua/utilpackage.hpp>
5+
#include <components/misc/finitenumbers.hpp>
56
#include <components/settings/values.hpp>
67

78
#include "../mwbase/environment.hpp"
@@ -11,11 +12,12 @@
1112

1213
namespace MWLua
1314
{
14-
1515
using CameraMode = MWRender::Camera::Mode;
1616

1717
sol::table initCameraPackage(sol::state_view lua)
1818
{
19+
using FiniteFloat = Misc::FiniteFloat;
20+
1921
MWRender::Camera* camera = MWBase::Environment::get().getWorld()->getCamera();
2022
MWRender::RenderingManager* renderingManager = MWBase::Environment::get().getWorld()->getRenderingManager();
2123

@@ -49,34 +51,35 @@ namespace MWLua
4951
api["getRoll"] = [camera]() { return -camera->getRoll(); };
5052

5153
api["setStaticPosition"] = [camera](const osg::Vec3f& pos) { camera->setStaticPosition(pos); };
52-
api["setPitch"] = [camera](float v) {
54+
api["setPitch"] = [camera](const FiniteFloat v) {
5355
camera->setPitch(-v, true);
5456
if (camera->getMode() == CameraMode::ThirdPerson)
5557
camera->calculateDeferredRotation();
5658
};
57-
api["setYaw"] = [camera](float v) {
59+
api["setYaw"] = [camera](const FiniteFloat v) {
5860
camera->setYaw(-v, true);
5961
if (camera->getMode() == CameraMode::ThirdPerson)
6062
camera->calculateDeferredRotation();
6163
};
62-
api["setRoll"] = [camera](float v) { camera->setRoll(-v); };
63-
api["setExtraPitch"] = [camera](float v) { camera->setExtraPitch(-v); };
64-
api["setExtraYaw"] = [camera](float v) { camera->setExtraYaw(-v); };
65-
api["setExtraRoll"] = [camera](float v) { camera->setExtraRoll(-v); };
64+
api["setRoll"] = [camera](const FiniteFloat v) { camera->setRoll(-v); };
65+
api["setExtraPitch"] = [camera](const FiniteFloat v) { camera->setExtraPitch(-v); };
66+
api["setExtraYaw"] = [camera](const FiniteFloat v) { camera->setExtraYaw(-v); };
67+
api["setExtraRoll"] = [camera](const FiniteFloat v) { camera->setExtraRoll(-v); };
6668
api["getExtraPitch"] = [camera]() { return -camera->getExtraPitch(); };
6769
api["getExtraYaw"] = [camera]() { return -camera->getExtraYaw(); };
6870
api["getExtraRoll"] = [camera]() { return -camera->getExtraRoll(); };
6971

7072
api["getThirdPersonDistance"] = [camera]() { return camera->getCameraDistance(); };
71-
api["setPreferredThirdPersonDistance"] = [camera](float v) { camera->setPreferredCameraDistance(v); };
73+
api["setPreferredThirdPersonDistance"]
74+
= [camera](const FiniteFloat v) { camera->setPreferredCameraDistance(v); };
7275

7376
api["getFirstPersonOffset"] = [camera]() { return camera->getFirstPersonOffset(); };
7477
api["setFirstPersonOffset"] = [camera](const osg::Vec3f& v) { camera->setFirstPersonOffset(v); };
7578

7679
api["getFocalPreferredOffset"] = [camera]() -> osg::Vec2f { return camera->getFocalPointTargetOffset(); };
7780
api["setFocalPreferredOffset"] = [camera](const osg::Vec2f& v) { camera->setFocalPointTargetOffset(v); };
7881
api["getFocalTransitionSpeed"] = [camera]() { return camera->getFocalPointTransitionSpeed(); };
79-
api["setFocalTransitionSpeed"] = [camera](float v) { camera->setFocalPointTransitionSpeed(v); };
82+
api["setFocalTransitionSpeed"] = [camera](const FiniteFloat v) { camera->setFocalPointTransitionSpeed(v); };
8083
api["instantTransition"] = [camera]() { camera->instantTransition(); };
8184

8285
api["getCollisionType"] = [camera]() { return camera->getCollisionType(); };
@@ -86,11 +89,12 @@ namespace MWLua
8689
api["getFieldOfView"]
8790
= [renderingManager]() { return osg::DegreesToRadians(renderingManager->getFieldOfView()); };
8891
api["setFieldOfView"]
89-
= [renderingManager](float v) { renderingManager->setFieldOfView(osg::RadiansToDegrees(v)); };
92+
= [renderingManager](const FiniteFloat v) { renderingManager->setFieldOfView(osg::RadiansToDegrees(v)); };
9093

9194
api["getBaseViewDistance"] = [] { return Settings::camera().mViewingDistance.get(); };
9295
api["getViewDistance"] = [renderingManager]() { return renderingManager->getViewDistance(); };
93-
api["setViewDistance"] = [renderingManager](float d) { renderingManager->setViewDistance(d, true); };
96+
api["setViewDistance"]
97+
= [renderingManager](const FiniteFloat d) { renderingManager->setViewDistance(d, true); };
9498

9599
api["getViewTransform"] = [camera]() { return LuaUtil::TransformM{ camera->getViewMatrix() }; };
96100

components/misc/finitenumbers.hpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#ifndef OPENMW_COMPONENTS_MISC_FINITENUMBERS_HPP
2+
#define OPENMW_COMPONENTS_MISC_FINITENUMBERS_HPP
3+
4+
#include <components/lua/luastate.hpp>
5+
6+
#include <cmath>
7+
#include <stdexcept>
8+
9+
namespace Misc
10+
{
11+
struct FiniteFloat
12+
{
13+
float mValue;
14+
FiniteFloat(float v)
15+
{
16+
if (!std::isfinite(v))
17+
throw std::invalid_argument("Value must be a finite number");
18+
mValue = v;
19+
}
20+
operator float() const { return mValue; }
21+
};
22+
}
23+
24+
namespace sol
25+
{
26+
using FiniteFloat = Misc::FiniteFloat;
27+
28+
template <typename Handler>
29+
bool sol_lua_check(
30+
sol::types<FiniteFloat>, lua_State* L, int index, Handler&& handler, sol::stack::record& tracking)
31+
{
32+
bool success = sol::stack::check<float>(L, lua_absindex(L, index), handler);
33+
tracking.use(1);
34+
return success;
35+
}
36+
37+
static FiniteFloat sol_lua_get(sol::types<FiniteFloat>, lua_State* L, int index, sol::stack::record& tracking)
38+
{
39+
float val = sol::stack::get<float>(L, lua_absindex(L, index));
40+
tracking.use(1);
41+
return FiniteFloat(val);
42+
}
43+
}
44+
45+
#endif

0 commit comments

Comments
 (0)