📄 oasisscriptsystem.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 : oasisScriptSystem.cpp
* DESCRIPTION : Scripting engine
* AUTHOR : Zephie Greyvenstein, Godot
****************************************************************************/
#include "oasisScriptSystem.h"
#include "oasisScriptInterpreter.h"
#include "oasisScriptCommon.h"
#include "oasisConsoleSystem.h"
#include "oasisVector3.h"
#include "oasisQuaternion.h"
#include "oasisAudible.h"
#include "oasisMovable.h"
#include "oasisPhysical.h"
#include "oasisSound.h"
#include "oasisPhysics.h"
#include "oasisPool.h"
#include "oasisVisible.h"
#include "oasisEntity.h"
#include "oasisColour.h"
#include "oasisScriptExtension.h"
#include "oasisRoot.h"
#include "OgreLogManager.h"
#include "OgreStringVector.h"
#include "OgreDataChunk.h"
//#include <stdio.h>
//#include <stdarg.h>
namespace Oasis {
template< > scriptSystem *singleton< scriptSystem >::singletonPtr = 0;
scriptSystem::scriptSystem( ) : system( "Script" ) {
/// TODO: InterpreterManager or not? _parseAllSources( ".scripts" );
loaded = LNONE;
specifics = NULL;
}
scriptSystem::~scriptSystem( ) {
if( loaded != LNONE && specifics )
delete specifics;
}
scriptSystem &scriptSystem::get( void ) {
return singleton< scriptSystem >::get( );
}
scriptSystem *scriptSystem::getPtr( void ) {
return singleton< scriptSystem >::getPtr( );
}
void scriptSystem::reset( void ) {
if( loaded == LNONE ) return;
specifics->reset( );
}
void scriptSystem::initLanguage( Language toinit ) {
int i = 0;
if( loaded != LNONE ) {
delete specifics;
specifics = NULL;
loaded = LNONE;
}
if( toinit == LLUA ) {
#ifndef HAS_LUA
scriptLog( "How are you going to use Lua scripts w/o Lua?" );
#endif
#ifdef HAS_LUA
specifics = new scriptLuaInterpreter( );
loaded = LLUA;
#endif
}
else if( toinit == LRUBY ) {
#ifndef HAS_RUBY
scriptLog( "How are you going to use Ruby scripts w/o Ruby?" );
#endif
#ifdef HAS_RUBY
specifics = new scriptRubyInterpreter( );
loaded = LRUBY;
#endif
}
else {
scriptLog( "Attemptimg to load script, but Language isn't defined." );
}
//Setup the extensions to any particular language
for( ; i < extensions.size( ) ; i++ )
extensions[i]->enableScripting( );
}
void scriptSystem::update( real time ) {
//PENDING: Do we even need this anymore?
}
void *scriptSystem::executeString(uint8 &type, const char *command, ... ) {
char buffer[4097];
void *retv;
if( loaded == LNONE || specifics == 0 ) return NULL;
va_list list;
va_start( list, command );
::vsnprintf( buffer, 4096, command, list );
string strcmd = buffer;
retv = specifics->executeString( strcmd, type );
va_end( list );
return retv;
}
void scriptSystem::executeScript( const string &name ) {
if( loaded == LNONE || specifics == 0 ) return;
uint8 i=0;
string strname;
if( loaded == LLUA )
strname = name + ".lua";
else if ( loaded == LRUBY )
strname = name + ".rb";
for( i=0; i<root::get().directories.size(); i++ ) {
string strbuf = root::get().directories[i] + strname;
scriptSystem::get().scriptLog( string( "Trying: " ) + strbuf );
if( specifics->executeScript( strbuf ) )
break;
}
if( i==root::get().directories.size() )
scriptSystem::get().scriptLog( string( "Couldn't find: " ) + strname );
}
void scriptSystem::scriptLog( const string &message ) {
Ogre::LogManager::getSingleton( ).logMessage( "SCRIPT: " + message );
//std::cout << " SCRIPT " + message << std::endl;
if ( consoleSystem::getPtr( ) ) {
consoleSystem::get( ).write( message );
}
}
void *scriptSystem::callFunction(uint8 &returntype,
string funct, char *types, ... ) {
uint16 i;
uint16 len = strlen( types );
va_list list;
string strtypes;
void *next_arg;
void ** input = ( void ** ) new ( void * )[len];
//This variable is going to store references to allocated memory
//for later deletion.
void ** input_cp = ( void ** ) new ( void * )[len];
void * retv;
if( loaded == LNONE || specifics == 0 ) return NULL;
va_start( list, types );
// populate the function's argument list
// Note that va_* only allows for integer types (whether pointers
// or just integer values), so we convert to/from.
for( i = 0;i < len; i++ ) {
if(types[i] == 'i') {
int16 *ni = new int16;
*ni = ( int16 ) va_arg( list, int32 );
next_arg = ( void * ) ni;
}
else if(types[i] == 'd') {
int32 *ni = new int32;
*ni = va_arg( list, int32 );
next_arg = ( void * ) ni;
}
else if(types[i] == 'c') {
uint8 *ni = new uint8;
*ni = ( uint8 ) va_arg( list, int32 );
next_arg = ( void * ) ni;
}
else if(types[i] == 'b') {
bool *ni = new bool;
*ni = ( bool ) va_arg( list, int32 );
next_arg = ( void * ) ni;
}
else if(types[i] == 's') {
char *ni,*cp;
ni = va_arg( list, char * );
cp = new char[ strlen( ni ) ];
strcpy( cp, ni );
next_arg = ( void * ) cp;
}
else if(types[i] == 'f' || types[i] == 'r' ) {
real *ni = new real;
*ni = va_arg( list, real );
next_arg = ( void * ) ni;
}
else if(types[i] == 'q') {
quaternion *ni, *cp;
ni = va_arg( list, quaternion * );
cp = new quaternion( ni->w, ni->x, ni->y, ni->z );
next_arg = ( void * ) cp;
}
else if(types[i] == 'v') {
vector3 *ni, *cp;
ni = va_arg( list, vector3 * );
cp = new vector3( ni->x, ni->y, ni->z );
next_arg = ( void * ) cp;
}
else {
scriptSystem::get().scriptLog( "Unknown type passed to callFunction!!" );
}
input[i]=specifics->convertFromC( next_arg, types[i] );
input_cp[i]=next_arg;
}
va_end( list );
// call the scripted function, capture the output, convert the output.
strtypes = types;
// call the function ( non-specific to scripting language :) )
retv = specifics->callFunction( funct, strtypes, input, returntype );
// free the variables/return the converted ouput
for( i = 0; i < len; i++ ) {
freeVariable( input_cp[i], types[i] );
specifics->freeVariable( input[i] );
}
return retv;
}
void scriptSystem::freeVariable( void * var, uint8 type )
{
if(type == 'i')
delete (int16 *) var;
else if(type == 'd')
delete (int32 *) var;
else if(type == 'c')
delete (uint8 *) var;
else if(type == 'b')
delete (bool *) var;
else if(type == 's')
delete (char *) var;
else if(type == 'f' || type == 'r' )
delete (real *) var;
else if(type == 'q')
delete (quaternion *) var;
else if(type == 'v')
delete (vector3 *) var;
else if(type == '0')
return;
//else
//scriptSystem::get().scriptLog( "Tried to delete unknown type." );
}
string scriptSystem::toString( void *var, uint8 type ) {
if(type == 'i' || type == 'd') {
char ret[32];
sprintf( ret, "%d", *( int32 * ) var );
return string( ret ) + string( " : type 'int'" );
}
else if(type == 'c') {
string ret = "0";
ret[0] = *( char * )var;
return ret + string( " : type 'char'" );
}
else if(type == 'b')
return ( *( bool * ) var ? "True" : "False" );
else if(type == 's')
return string( ( char * ) var + string( " : type 'string'" ) );
else if(type == 'f' || type == 'r' ) {
char ret[64];
sprintf( ret, "%f", *( real * ) var );
return string( ret ) + string( " : type 'real'" );
}
else if(type == 'q') {
char ret[256];
quaternion *val = ( quaternion * ) var;
sprintf( ret, "(w%f, x%f, y%f, z%f)", val->w, val->x,
val->y, val->z );
return string( ret ) + string( " : type 'quaternion'" );
}
else if(type == 'v') {
char ret[256];
vector3 *val = ( vector3 * ) var;
sprintf( ret, "(x%f, y%f, z%f)", val->x, val->y, val->z );
return string( ret ) + string( " : type 'vector3'" );
}
else if(type == '0')
return "Nil";
else {
/*string retv= " :Undefined";
retv[0]=type;*/
return "";
}
}
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -