From de028fc056b26e03ee00324888f870f64e28c756 Mon Sep 17 00:00:00 2001 From: bigfoot547 Date: Fri, 5 May 2017 15:07:36 -0500 Subject: [PATCH] [CSM] Add camera API (#5609) * [CSM] Add camera API roper rebase & squash * Address nerzhul's review --- build/android/jni/Android.mk | 1 + doc/client_lua_api.md | 52 +++++-- src/camera.cpp | 5 + src/camera.h | 8 +- src/script/lua_api/CMakeLists.txt | 1 + src/script/lua_api/l_camera.cpp | 206 +++++++++++++++++++++++++++ src/script/lua_api/l_camera.h | 46 ++++++ src/script/lua_api/l_localplayer.cpp | 49 ------- src/script/lua_api/l_localplayer.h | 7 - src/script/scripting_client.cpp | 7 + src/script/scripting_client.h | 2 + 11 files changed, 314 insertions(+), 70 deletions(-) create mode 100644 src/script/lua_api/l_camera.cpp create mode 100644 src/script/lua_api/l_camera.h diff --git a/build/android/jni/Android.mk b/build/android/jni/Android.mk index 6525942bd..d4a8d988f 100644 --- a/build/android/jni/Android.mk +++ b/build/android/jni/Android.mk @@ -305,6 +305,7 @@ LOCAL_SRC_FILES += \ jni/src/script/cpp_api/s_server.cpp \ jni/src/script/lua_api/l_areastore.cpp \ jni/src/script/lua_api/l_base.cpp \ + jni/src/script/lua_api/l_camera.cpp \ jni/src/script/lua_api/l_client.cpp \ jni/src/script/lua_api/l_craft.cpp \ jni/src/script/lua_api/l_env.cpp \ diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index b76a406ea..a4293500f 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -694,7 +694,7 @@ Call these functions only at load time! * `minetest.get_wielded_item()` * Returns the itemstack the local player is holding * `minetest.localplayer` - * Reference to the LocalPlayer object. See `LocalPlayer` class reference for methods. + * Reference to the LocalPlayer object. See [`LocalPlayer`](#localplayer) class reference for methods. ### Client Environment * `minetest.get_player_names()` @@ -750,7 +750,7 @@ Call these functions only at load time! * Encodes a string in base64. * `minetest.decode_base64(string)`: returns string * Decodes a string encoded in base64. -* `minetest.gettext(string) : returns string +* `minetest.gettext(string)` : returns string * look up the translation of a string in the gettext message catalog * `fgettext_ne(string, ...)` * call minetest.gettext(string), replace "$1"..."$9" with the given @@ -762,7 +762,9 @@ Call these functions only at load time! ### UI * `minetest.ui.minimap` - * Reference to the minimap object. See `Minimap` class reference for methods. + * Reference to the minimap object. See [`Minimap`](#minimap) class reference for methods. +* `minetest.camera` + * Reference to the camera object. See [`Camera`](#camera) class reference for methods. * `minetest.show_formspec(formname, formspec)` : returns true on success * Shows a formspec to the player * `minetest.display_chat_message(message)` returns true on success @@ -785,6 +787,40 @@ An interface to manipulate minimap on client UI * `set_shape(shape)`: Sets the minimap shape. (0 = square, 1 = round) * `get_shape()`: Gets the minimap shape. (0 = square, 1 = round) +### Camera +An interface to get or set information about the camera and cameranode. +Please do not try to access the reference until the camera is initialized, otherwise the reference will be nil. + +#### Methods +* `set_camera_mode(mode)` + * Pass `0` for first-person, `1` for third person, and `2` for third person front +* `get_camera_mode()` + * Returns with same syntax as above +* `get_fov()` + * Returns: + +```lua + { + x = number, + y = number, + max = number, + actual = number + } +``` + +* `get_pos()` + * Returns position of camera with view bobbing +* `get_offset()` + * Returns eye offset vector +* `get_look_dir()` + * Returns eye direction unit vector +* `get_look_vertical()` + * Returns pitch in radians +* `get_look_horizontal()` + * Returns yaw in radians +* `get_aspect_ratio()` + * Returns aspect ratio of screen + ### LocalPlayer An interface to retrieve information about the player. The player is not accessible until the client is fully done loading and therefore @@ -844,16 +880,6 @@ Methods: * returns last player speed * `get_breath()` * returns the player's breath -* `get_look_dir()` - * returns look direction vector -* `get_look_horizontal()` - * returns look horizontal angle -* `get_look_vertical()` - * returns look vertical angle -* `get_eye_pos()` - * returns the player's eye position -* `get_eye_offset()` - * returns the player's eye shift vector * `get_movement_acceleration()` * returns acceleration of the player in different environments: diff --git a/src/camera.cpp b/src/camera.cpp index b119bbfbb..949494b00 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/numeric.h" #include "constants.h" #include "fontengine.h" +#include "script/scripting_client.h" #define CAMERA_OFFSET_STEP 200 @@ -125,6 +126,10 @@ bool Camera::successfullyCreated(std::string &error_message) } else { error_message.clear(); } + + if (g_settings->getBool("enable_client_modding")) { + m_client->getScript()->on_camera_ready(this); + } return error_message.empty(); } diff --git a/src/camera.h b/src/camera.h index e4c1d0b25..ca2e4ddcc 100644 --- a/src/camera.h +++ b/src/camera.h @@ -160,7 +160,13 @@ public: else m_camera_mode = CAMERA_MODE_FIRST; } - + + // Set the current camera mode + inline void setCameraMode(CameraMode mode) + { + m_camera_mode = mode; + } + //read the current camera mode inline CameraMode getCameraMode() { diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt index b03e94a09..1a78580e6 100644 --- a/src/script/lua_api/CMakeLists.txt +++ b/src/script/lua_api/CMakeLists.txt @@ -29,4 +29,5 @@ set(client_SCRIPT_LUA_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_sound.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_localplayer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_camera.cpp PARENT_SCOPE) diff --git a/src/script/lua_api/l_camera.cpp b/src/script/lua_api/l_camera.cpp new file mode 100644 index 000000000..e6229ffe8 --- /dev/null +++ b/src/script/lua_api/l_camera.cpp @@ -0,0 +1,206 @@ +#include "script/common/c_converter.h" +#include "l_camera.h" +#include "l_internal.h" +#include "content_cao.h" +#include "camera.h" + +LuaCamera::LuaCamera(Camera *m) +{ + m_camera = m; +} + +void LuaCamera::create(lua_State *L, Camera *m) +{ + LuaCamera *o = new LuaCamera(m); + *(void **) (lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + + int camera_object = lua_gettop(L); + + lua_getglobal(L, "core"); + luaL_checktype(L, -1, LUA_TTABLE); + int coretable = lua_gettop(L); + + lua_pushvalue(L, camera_object); + lua_setfield(L, coretable, "camera"); +} + +int LuaCamera::l_set_camera_mode(lua_State *L) +{ + Camera *camera = getobject(L, 1); + GenericCAO *playercao = getClient(L)->getEnv().getLocalPlayer()->getCAO(); + if (!camera) + return 0; + sanity_check(playercao); + if (!lua_isnumber(L, 2)) + return 0; + + camera->setCameraMode((CameraMode)((int)lua_tonumber(L, 2))); + playercao->setVisible(camera->getCameraMode() > CAMERA_MODE_FIRST); + playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST); + return 0; +} + +int LuaCamera::l_get_camera_mode(lua_State *L) +{ + Camera *camera = getobject(L, 1); + if (!camera) + return 0; + + lua_pushnumber(L, (int)camera->getCameraMode()); + + return 1; +} + +int LuaCamera::l_get_fov(lua_State *L) +{ + Camera *camera = getobject(L, 1); + if (!camera) + return 0; + + lua_newtable(L); + lua_pushnumber(L, camera->getFovX() * core::DEGTORAD); + lua_setfield(L, -2, "x"); + lua_pushnumber(L, camera->getFovY() * core::DEGTORAD); + lua_setfield(L, -2, "y"); + lua_pushnumber(L, camera->getCameraNode()->getFOV() * core::RADTODEG); + lua_setfield(L, -2, "actual"); + lua_pushnumber(L, camera->getFovMax() * core::RADTODEG); + lua_setfield(L, -2, "max"); + return 1; +} + +int LuaCamera::l_get_pos(lua_State *L) +{ + Camera *camera = getobject(L, 1); + if (!camera) + return 0; + + push_v3f(L, camera->getPosition()); + return 1; +} + +int LuaCamera::l_get_offset(lua_State *L) +{ + Camera *camera = getobject(L, 1); + if (!camera) + return 0; + + push_v3s16(L, camera->getOffset()); + return 1; +} + +int LuaCamera::l_get_look_dir(lua_State *L) +{ + LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer(); + sanity_check(player); + + float pitch = -1.0 * player->getPitch() * core::DEGTORAD; + float yaw = (player->getYaw() + 90.) * core::DEGTORAD; + v3f v(cos(pitch) * cos(yaw), sin(pitch), cos(pitch) * sin(yaw)); + + push_v3f(L, v); + return 1; +} + +int LuaCamera::l_get_look_horizontal(lua_State *L) +{ + LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer(); + sanity_check(player); + + lua_pushnumber(L, (player->getYaw() + 90.) * core::DEGTORAD); + return 1; +} + +int LuaCamera::l_get_look_vertical(lua_State *L) +{ + LocalPlayer *player = getClient(L)->getEnv().getLocalPlayer(); + sanity_check(player); + + lua_pushnumber(L, -1.0 * player->getPitch() * core::DEGTORAD); + return 1; +} + +int LuaCamera::l_get_aspect_ratio(lua_State *L) +{ + Camera *camera = getobject(L, 1); + if (!camera) + return 0; + + lua_pushnumber(L, camera->getCameraNode()->getAspectRatio()); + return 1; +} + +LuaCamera *LuaCamera::checkobject(lua_State *L, int narg) +{ + luaL_checktype(L, narg, LUA_TUSERDATA); + + void *ud = luaL_checkudata(L, narg, className); + if (!ud) + luaL_typerror(L, narg, className); + + return *(LuaCamera **) ud; +} + +Camera *LuaCamera::getobject(LuaCamera *ref) +{ + return ref->m_camera; +} + +Camera *LuaCamera::getobject(lua_State *L, int narg) +{ + LuaCamera *ref = checkobject(L, narg); + assert(ref); + Camera *camera = getobject(ref); + if (!camera) + return NULL; + return camera; +} + +int LuaCamera::gc_object(lua_State *L) +{ + LuaCamera *o = *(LuaCamera **) (lua_touserdata(L, 1)); + delete o; + return 0; +} + +void LuaCamera::Register(lua_State *L) +{ + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pop(L, 1); + + luaL_openlib(L, 0, methods, 0); + lua_pop(L, 1); +} + +const char LuaCamera::className[] = "Camera"; +const luaL_reg LuaCamera::methods[] = { + luamethod(LuaCamera, set_camera_mode), + luamethod(LuaCamera, get_camera_mode), + luamethod(LuaCamera, get_fov), + luamethod(LuaCamera, get_pos), + luamethod(LuaCamera, get_offset), + luamethod(LuaCamera, get_look_dir), + luamethod(LuaCamera, get_look_vertical), + luamethod(LuaCamera, get_look_horizontal), + luamethod(LuaCamera, get_aspect_ratio), + + {0, 0} +}; diff --git a/src/script/lua_api/l_camera.h b/src/script/lua_api/l_camera.h new file mode 100644 index 000000000..82ab6a47f --- /dev/null +++ b/src/script/lua_api/l_camera.h @@ -0,0 +1,46 @@ +#ifndef L_CAMERA_H +#define L_CAMERA_H + +#include "l_base.h" + +class Camera; + +class LuaCamera : public ModApiBase { +private: + + static const char className[]; + static const luaL_Reg methods[]; + + // garbage collector + static int gc_object(lua_State *L); + + static int l_set_camera_mode(lua_State *L); + static int l_get_camera_mode(lua_State *L); + + static int l_get_fov(lua_State *L); + + static int l_get_pos(lua_State *L); + static int l_get_offset(lua_State *L); + static int l_get_look_dir(lua_State *L); + static int l_get_look_vertical(lua_State *L); + static int l_get_look_horizontal(lua_State *L); + static int l_get_aspect_ratio(lua_State *L); + + Camera *m_camera; + +public: + + LuaCamera(Camera *m); + ~LuaCamera() {} + + static void create(lua_State *L, Camera *m); + + static LuaCamera *checkobject(lua_State *L, int narg); + static Camera *getobject(LuaCamera *ref); + static Camera *getobject(lua_State *L, int narg); + + static void Register(lua_State *L); + +}; + +#endif // L_CAMERA_H diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp index 177df55f3..7ec4eaa62 100644 --- a/src/script/lua_api/l_localplayer.cpp +++ b/src/script/lua_api/l_localplayer.cpp @@ -203,34 +203,6 @@ int LuaLocalPlayer::l_get_breath(lua_State *L) return 1; } -int LuaLocalPlayer::l_get_look_dir(lua_State *L) -{ - LocalPlayer *player = getobject(L, 1); - - float pitch = -1.0 * player->getPitch() * core::DEGTORAD; - float yaw = (player->getYaw() + 90.) * core::DEGTORAD; - v3f v(cos(pitch) * cos(yaw), sin(pitch), cos(pitch) * sin(yaw)); - - push_v3f(L, v); - return 1; -} - -int LuaLocalPlayer::l_get_look_horizontal(lua_State *L) -{ - LocalPlayer *player = getobject(L, 1); - - lua_pushnumber(L, (player->getYaw() + 90.) * core::DEGTORAD); - return 1; -} - -int LuaLocalPlayer::l_get_look_vertical(lua_State *L) -{ - LocalPlayer *player = getobject(L, 1); - - lua_pushnumber(L, -1.0 * player->getPitch() * core::DEGTORAD); - return 1; -} - int LuaLocalPlayer::l_get_pos(lua_State *L) { LocalPlayer *player = getobject(L, 1); @@ -239,22 +211,6 @@ int LuaLocalPlayer::l_get_pos(lua_State *L) return 1; } -int LuaLocalPlayer::l_get_eye_pos(lua_State *L) -{ - LocalPlayer *player = getobject(L, 1); - - push_v3f(L, player->getEyePosition()); - return 1; -} - -int LuaLocalPlayer::l_get_eye_offset(lua_State *L) -{ - LocalPlayer *player = getobject(L, 1); - - push_v3f(L, player->getEyeOffset()); - return 1; -} - int LuaLocalPlayer::l_get_movement_acceleration(lua_State *L) { LocalPlayer *player = getobject(L, 1); @@ -393,12 +349,7 @@ const luaL_Reg LuaLocalPlayer::methods[] = { luamethod(LuaLocalPlayer, get_last_look_vertical), luamethod(LuaLocalPlayer, get_key_pressed), luamethod(LuaLocalPlayer, get_breath), - luamethod(LuaLocalPlayer, get_look_dir), - luamethod(LuaLocalPlayer, get_look_horizontal), - luamethod(LuaLocalPlayer, get_look_vertical), luamethod(LuaLocalPlayer, get_pos), - luamethod(LuaLocalPlayer, get_eye_pos), - luamethod(LuaLocalPlayer, get_eye_offset), luamethod(LuaLocalPlayer, get_movement_acceleration), luamethod(LuaLocalPlayer, get_movement_speed), luamethod(LuaLocalPlayer, get_movement), diff --git a/src/script/lua_api/l_localplayer.h b/src/script/lua_api/l_localplayer.h index 6ec3f4c09..e56ec808f 100644 --- a/src/script/lua_api/l_localplayer.h +++ b/src/script/lua_api/l_localplayer.h @@ -59,15 +59,8 @@ private: static int l_get_breath(lua_State *L); - static int l_get_look_dir(lua_State *L); - static int l_get_look_horizontal(lua_State *L); - static int l_get_look_vertical(lua_State *L); - static int l_get_pos(lua_State *L); - static int l_get_eye_pos(lua_State *L); - static int l_get_eye_offset(lua_State *L); - static int l_get_movement_acceleration(lua_State *L); static int l_get_movement_speed(lua_State *L); diff --git a/src/script/scripting_client.cpp b/src/script/scripting_client.cpp index 8ff5abcc4..b5a5085be 100644 --- a/src/script/scripting_client.cpp +++ b/src/script/scripting_client.cpp @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_item.h" #include "lua_api/l_nodemeta.h" #include "lua_api/l_localplayer.h" +#include "lua_api/l_camera.h" ClientScripting::ClientScripting(Client *client): ScriptApiBase() @@ -71,6 +72,7 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) LuaMinimap::Register(L); NodeMetaRef::RegisterClient(L); LuaLocalPlayer::Register(L); + LuaCamera::Register(L); } void ClientScripting::on_client_ready(LocalPlayer *localplayer) @@ -78,3 +80,8 @@ void ClientScripting::on_client_ready(LocalPlayer *localplayer) lua_State *L = getStack(); LuaLocalPlayer::create(L, localplayer); } + +void ClientScripting::on_camera_ready(Camera *camera) +{ + LuaCamera::create(getStack(), camera); +} diff --git a/src/script/scripting_client.h b/src/script/scripting_client.h index b3451e409..c13fde607 100644 --- a/src/script/scripting_client.h +++ b/src/script/scripting_client.h @@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., class Client; class LocalPlayer; +class Camera; class ClientScripting: virtual public ScriptApiBase, public ScriptApiSecurity, @@ -36,6 +37,7 @@ class ClientScripting: public: ClientScripting(Client *client); void on_client_ready(LocalPlayer *localplayer); + void on_camera_ready(Camera *camera); private: virtual void InitializeModApi(lua_State *L, int top);