📄 oasisscriptluainterpreter.cpp
字号:
/******************************************************************************
* This source file is part of Bad Camel Gaming
* Copyright (C) 2003 Zephie Greyvenstein
* See Readme.html for acknowledgements
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/******************************************************************************
* FILENAME : oasisScriptLuaInterpreter.cpp
* DESCRIPTION : The grunt of the lua language.
* AUTHOR : Gaw (garcia@cs.ttu.edu)
*****************************************************************************/
//only compile if Lua is included in the library
#ifdef HAS_LUA
#include <vector>
#include "oasisScriptInterpreter.h"
#include "oasisScriptSystem.h"
#include "oasisVector3.h"
#include "oasisQuaternion.h"
#include "oasisScriptLuaInterpreter.h"
#include "OgreLogManager.h"
extern int tolua_engine_open( lua_State * );
namespace Oasis {
scriptLuaInterpreter::scriptLuaInterpreter( )
: scriptInterpreter( ) {
luaInterpreter = lua_open( );
loadLibs( );
}
scriptLuaInterpreter::~scriptLuaInterpreter( ) {
lua_close( luaInterpreter );
}
bool scriptLuaInterpreter::executeScript( string &name ) {
scriptSystem::get( ).scriptLog( "Attempting to load " + name );
return !lua_dofile( luaInterpreter, name.c_str( ) );
}
void *scriptLuaInterpreter::executeString( string &name, uint8 &type ) {
int top = lua_gettop( luaInterpreter );
lua_dostring( luaInterpreter, name.c_str( ) );
//If anything in the size of the stack has changed, you have a return value
//note the above technique doesn't work because a sub-interpreter
//is started to evaluate the string.
if( lua_gettop( luaInterpreter ) - top )
return convertToC( ( void * ) NULL, type );
type = '0';
return ( void * ) NULL;
}
void scriptLuaInterpreter::reset( ) {
lua_close( luaInterpreter );
luaInterpreter = lua_open( );
loadLibs( );
}
//This function displays errors to the console.
int errorHandler( lua_State *L ) {
string error = lua_tostring( L, 1 );
scriptSystem::get( ).scriptLog( error );
return 1;
}
void scriptLuaInterpreter::loadLibs( ) {
lua_register( luaInterpreter, "_ALERT", ( lua_CFunction )&errorHandler );
lua_register( luaInterpreter, "_OUTPUT", ( lua_CFunction )&errorHandler );
luaopen_base( luaInterpreter );
luaopen_table( luaInterpreter );
luaopen_io( luaInterpreter );
luaopen_string( luaInterpreter );
luaopen_math( luaInterpreter );
luaopen_debug( luaInterpreter );
luaopen_loadlib( luaInterpreter );
tolua_engine_open( luaInterpreter );
}
void scriptLuaInterpreter::loadLibrary(
int ( *callback )( lua_State * ) ) {
callback( luaInterpreter );
}
void *scriptLuaInterpreter::convertFromC( void *cObject, uint8 type ) {
//conversion from and to the stack are intertwined, pushing it on
//now would only be error prone, this is done later. During callFunction
return cObject;
}
void scriptLuaInterpreter::_convertFromC( void *cObject, uint8 type ) {
int i;
//numbers
if( type == 'i' || type == 'd' )
lua_pushnumber( luaInterpreter, ( real ) *( int32 * ) cObject );
else if( type == 'r' || type == 'f' )
lua_pushnumber( luaInterpreter, *( real * ) cObject );
//bool
else if( type == 'b' )
lua_pushboolean( luaInterpreter, *( bool * ) cObject );
//vector
else if( type == 'v' ) {
lua_newtable( luaInterpreter );
lua_pushnumber( luaInterpreter, ( ( vector3 * ) cObject )->z );
lua_pushnumber( luaInterpreter, ( ( vector3 * ) cObject )->y );
lua_pushnumber( luaInterpreter, ( ( vector3 * ) cObject )->x );
for( i = 0; i < 3; i++ )
lua_rawseti( luaInterpreter, -( 4-i ), i+1 );
lua_pushstring( luaInterpreter, "n" );
lua_pushnumber( luaInterpreter, 3 );
lua_settable( luaInterpreter, -3 );
}
//quaternion
else if( type == 'q' ) {
lua_newtable( luaInterpreter );
lua_pushnumber( luaInterpreter, ( ( quaternion * ) cObject )->z );
lua_pushnumber( luaInterpreter, ( ( quaternion * ) cObject )->y );
lua_pushnumber( luaInterpreter, ( ( quaternion * ) cObject )->x );
lua_pushnumber( luaInterpreter, ( ( quaternion * ) cObject )->w );
for( i = 0; i<4; i++ )
lua_rawseti( luaInterpreter, -( 5-i ), i+1 );
lua_pushstring( luaInterpreter, "n" );
lua_pushnumber( luaInterpreter, 4 );
lua_settable( luaInterpreter, -3 );
}
//character
else if( type == 'c' ) {
char tmpstr[2];
tmpstr[0] = *( char * )cObject ;
tmpstr[1] = 0;
lua_pushstring( luaInterpreter, tmpstr );
}
else if( type == 's' )
lua_pushstring( luaInterpreter, ( char * ) cObject );
else
scriptSystem::get( ).scriptLog(
" Error, bad typed passed to callFunction->_convertFromC " );
}
void *scriptLuaInterpreter::convertToC( void *scriptObject, uint8 &type ) {
void *ret;
int index = lua_gettop( luaInterpreter );
int toptype = lua_type( luaInterpreter, index );
if ( toptype == LUA_TBOOLEAN ) {
ret = ( void * ) new bool( lua_toboolean( luaInterpreter, index ) );
type = 'b';
}
else if ( toptype == LUA_TNUMBER ) {
ret = ( void * ) new real( lua_tonumber( luaInterpreter, index ) );
type = 'r';
}
else if ( toptype == LUA_TSTRING ) {
ret = ( void * ) lua_tostring( luaInterpreter, index );
type = 's';
}
//We are only supporting vectors and quaternions,
//so the list must 1) be linear and 2) contain either
//3 or 4 elements of type real.
else if ( toptype == LUA_TTABLE ) {
std::vector < real > list;
int i = 1;
for( ; ; i++ ) {
//Get array entry 'index' and push result on stack
lua_rawgeti( luaInterpreter, index, i );
//nil signifies no other entries in array
//-1 means the top element in the stack.
if( lua_isnil( luaInterpreter, -1 )) break;
//PENDING: What happens when this isn't a number?
list.push_back( lua_tonumber( luaInterpreter, -1 ) );
lua_pop( luaInterpreter, 1 );
}
//clean up the nil element
lua_pop( luaInterpreter, 1 );
if( list.size() == 3 ) {
ret = ( void * ) new vector3( list[0], list[1], list[2] );
type = 'v';
}
else if( list.size() == 4 ) {
ret = ( void * ) new quaternion( list[0], list[1],
list[2], list[3] );
type = 'q';
}
//Should never be more than 4.
else {
ret = ( void * ) NULL;
type = '0';
}
}
//Let's support passing in the type 'quaternion' and 'vector3'
else if( toptype == LUA_TUSERDATA || toptype == LUA_TLIGHTUSERDATA ) {
lua_getmetatable( luaInterpreter, index );
//http://celestia.teyssier.org/lxr/source/src/celestia/celx.cpp
lua_rawget( luaInterpreter, LUA_REGISTRYINDEX );
//If the class isn't registered
if( lua_type( luaInterpreter, -1 ) != LUA_TSTRING ) {
lua_pop( luaInterpreter, 1 );
type = '0';
return ( void * ) NULL;
}
const char *name = lua_tostring( luaInterpreter, -1 );
lua_pop( luaInterpreter, 1 );
//invalid name
if( !name ) {
type = '0';
ret = ( void * ) NULL;
}
//vector3
else if(strcmp( name, "vector3" ) == 0) {
vector3 *flua = ( vector3 * )
lua_touserdata( luaInterpreter, index );
ret = new vector3( flua->x, flua->y, flua->z );
type = 'v';
}
//quaternion
else if(strcmp( name, "quaternion" ) == 0) {
quaternion *flua = ( quaternion * )
lua_touserdata( luaInterpreter, index );
ret = new quaternion( flua->w, flua->x, flua->y, flua->z );
type = 'q';
}
}
else {
ret = ( void * ) NULL;
type = '0';
}
return ret;
}
void *scriptLuaInterpreter::callFunction( string &name, string &types,
void **arguments,
uint8 &returntype ) {
int i;
int top = lua_gettop( luaInterpreter );
//Lookup our function in the globals table.
lua_pushstring( luaInterpreter, name.c_str( ) );
lua_gettable( luaInterpreter, LUA_GLOBALSINDEX );
//push the arguments on the stack.
//PENDING: Do these arguments get reversed?
for( i=0; i < types.length( ); i++ ) {
_convertFromC( arguments[i], types[i] );
}
lua_call( luaInterpreter, types.length(), 1 );
if( top < lua_gettop( luaInterpreter ) )
return convertToC( ( void * ) NULL, returntype );
else {
returntype = '0';
return ( void * ) NULL;
}
}
void scriptLuaInterpreter::freeVariable( void *script_var ) {
}
};
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -