[CSM] Add camera API (#5609)

* [CSM] Add camera API
roper rebase & squash

* Address nerzhul's review
This commit is contained in:
bigfoot547 2017-05-05 15:07:36 -05:00 committed by Loïc Blot
parent e8b00fdf98
commit de028fc056
11 changed files with 314 additions and 70 deletions

@ -305,6 +305,7 @@ LOCAL_SRC_FILES += \
jni/src/script/cpp_api/s_server.cpp \ jni/src/script/cpp_api/s_server.cpp \
jni/src/script/lua_api/l_areastore.cpp \ jni/src/script/lua_api/l_areastore.cpp \
jni/src/script/lua_api/l_base.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_client.cpp \
jni/src/script/lua_api/l_craft.cpp \ jni/src/script/lua_api/l_craft.cpp \
jni/src/script/lua_api/l_env.cpp \ jni/src/script/lua_api/l_env.cpp \

@ -694,7 +694,7 @@ Call these functions only at load time!
* `minetest.get_wielded_item()` * `minetest.get_wielded_item()`
* Returns the itemstack the local player is holding * Returns the itemstack the local player is holding
* `minetest.localplayer` * `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 ### Client Environment
* `minetest.get_player_names()` * `minetest.get_player_names()`
@ -750,7 +750,7 @@ Call these functions only at load time!
* Encodes a string in base64. * Encodes a string in base64.
* `minetest.decode_base64(string)`: returns string * `minetest.decode_base64(string)`: returns string
* Decodes a string encoded in base64. * 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 * look up the translation of a string in the gettext message catalog
* `fgettext_ne(string, ...)` * `fgettext_ne(string, ...)`
* call minetest.gettext(string), replace "$1"..."$9" with the given * call minetest.gettext(string), replace "$1"..."$9" with the given
@ -762,7 +762,9 @@ Call these functions only at load time!
### UI ### UI
* `minetest.ui.minimap` * `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 * `minetest.show_formspec(formname, formspec)` : returns true on success
* Shows a formspec to the player * Shows a formspec to the player
* `minetest.display_chat_message(message)` returns true on success * `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) * `set_shape(shape)`: Sets the minimap shape. (0 = square, 1 = round)
* `get_shape()`: Gets 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 ### LocalPlayer
An interface to retrieve information about the player. The player is An interface to retrieve information about the player. The player is
not accessible until the client is fully done loading and therefore not accessible until the client is fully done loading and therefore
@ -844,16 +880,6 @@ Methods:
* returns last player speed * returns last player speed
* `get_breath()` * `get_breath()`
* returns the player's 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()` * `get_movement_acceleration()`
* returns acceleration of the player in different environments: * returns acceleration of the player in different environments:

@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/numeric.h" #include "util/numeric.h"
#include "constants.h" #include "constants.h"
#include "fontengine.h" #include "fontengine.h"
#include "script/scripting_client.h"
#define CAMERA_OFFSET_STEP 200 #define CAMERA_OFFSET_STEP 200
@ -125,6 +126,10 @@ bool Camera::successfullyCreated(std::string &error_message)
} else { } else {
error_message.clear(); error_message.clear();
} }
if (g_settings->getBool("enable_client_modding")) {
m_client->getScript()->on_camera_ready(this);
}
return error_message.empty(); return error_message.empty();
} }

@ -160,7 +160,13 @@ public:
else else
m_camera_mode = CAMERA_MODE_FIRST; 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 //read the current camera mode
inline CameraMode getCameraMode() inline CameraMode getCameraMode()
{ {

@ -29,4 +29,5 @@ set(client_SCRIPT_LUA_API_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_storage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_sound.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_sound.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_localplayer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_localplayer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_camera.cpp
PARENT_SCOPE) PARENT_SCOPE)

@ -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}
};

@ -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

@ -203,34 +203,6 @@ int LuaLocalPlayer::l_get_breath(lua_State *L)
return 1; 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) int LuaLocalPlayer::l_get_pos(lua_State *L)
{ {
LocalPlayer *player = getobject(L, 1); LocalPlayer *player = getobject(L, 1);
@ -239,22 +211,6 @@ int LuaLocalPlayer::l_get_pos(lua_State *L)
return 1; 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) int LuaLocalPlayer::l_get_movement_acceleration(lua_State *L)
{ {
LocalPlayer *player = getobject(L, 1); LocalPlayer *player = getobject(L, 1);
@ -393,12 +349,7 @@ const luaL_Reg LuaLocalPlayer::methods[] = {
luamethod(LuaLocalPlayer, get_last_look_vertical), luamethod(LuaLocalPlayer, get_last_look_vertical),
luamethod(LuaLocalPlayer, get_key_pressed), luamethod(LuaLocalPlayer, get_key_pressed),
luamethod(LuaLocalPlayer, get_breath), 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_pos),
luamethod(LuaLocalPlayer, get_eye_pos),
luamethod(LuaLocalPlayer, get_eye_offset),
luamethod(LuaLocalPlayer, get_movement_acceleration), luamethod(LuaLocalPlayer, get_movement_acceleration),
luamethod(LuaLocalPlayer, get_movement_speed), luamethod(LuaLocalPlayer, get_movement_speed),
luamethod(LuaLocalPlayer, get_movement), luamethod(LuaLocalPlayer, get_movement),

@ -59,15 +59,8 @@ private:
static int l_get_breath(lua_State *L); 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_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_acceleration(lua_State *L);
static int l_get_movement_speed(lua_State *L); static int l_get_movement_speed(lua_State *L);

@ -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_item.h"
#include "lua_api/l_nodemeta.h" #include "lua_api/l_nodemeta.h"
#include "lua_api/l_localplayer.h" #include "lua_api/l_localplayer.h"
#include "lua_api/l_camera.h"
ClientScripting::ClientScripting(Client *client): ClientScripting::ClientScripting(Client *client):
ScriptApiBase() ScriptApiBase()
@ -71,6 +72,7 @@ void ClientScripting::InitializeModApi(lua_State *L, int top)
LuaMinimap::Register(L); LuaMinimap::Register(L);
NodeMetaRef::RegisterClient(L); NodeMetaRef::RegisterClient(L);
LuaLocalPlayer::Register(L); LuaLocalPlayer::Register(L);
LuaCamera::Register(L);
} }
void ClientScripting::on_client_ready(LocalPlayer *localplayer) void ClientScripting::on_client_ready(LocalPlayer *localplayer)
@ -78,3 +80,8 @@ void ClientScripting::on_client_ready(LocalPlayer *localplayer)
lua_State *L = getStack(); lua_State *L = getStack();
LuaLocalPlayer::create(L, localplayer); LuaLocalPlayer::create(L, localplayer);
} }
void ClientScripting::on_camera_ready(Camera *camera)
{
LuaCamera::create(getStack(), camera);
}

@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class Client; class Client;
class LocalPlayer; class LocalPlayer;
class Camera;
class ClientScripting: class ClientScripting:
virtual public ScriptApiBase, virtual public ScriptApiBase,
public ScriptApiSecurity, public ScriptApiSecurity,
@ -36,6 +37,7 @@ class ClientScripting:
public: public:
ClientScripting(Client *client); ClientScripting(Client *client);
void on_client_ready(LocalPlayer *localplayer); void on_client_ready(LocalPlayer *localplayer);
void on_camera_ready(Camera *camera);
private: private:
virtual void InitializeModApi(lua_State *L, int top); virtual void InitializeModApi(lua_State *L, int top);