Added script files
This commit is contained in:
49
src/scriptengine/README.txt
Normal file
49
src/scriptengine/README.txt
Normal file
@@ -0,0 +1,49 @@
|
||||
This is currently only a tiny prototype to get an idea of what the scripting engine can do/ check it's performance.
|
||||
TODO:
|
||||
set up a build target for angelscript
|
||||
get file manager support for loading scripts
|
||||
move scripts to stk-data, etc.
|
||||
|
||||
|
||||
Steps to get this working.
|
||||
1)get AngelScript SDK 2.28.1
|
||||
|
||||
http://www.angelcode.com/angelscript/downloads.html
|
||||
|
||||
2)Build the AngelScript library
|
||||
IF LINUX{
|
||||
|
||||
Build AngelScript by going to
|
||||
|
||||
cd ANGELSCRIPT_DIR\sdk\angelscript\projects\gnuc
|
||||
make
|
||||
|
||||
==> angelscript.a
|
||||
}
|
||||
|
||||
IF WINDOWS{
|
||||
|
||||
Load the VS Project, Build the .lib
|
||||
|
||||
==>angelscriptd.lib
|
||||
}
|
||||
|
||||
Copy the generated library file (.a or .lib) to stk-code/dependencies/lib
|
||||
Comment/Uncomment the lines in CMakeLists in stk-code as necessary (for Linux/Windows)
|
||||
|
||||
Build the game.
|
||||
Test by changing the strings in stk-code/src/tracks/
|
||||
|
||||
|
||||
|
||||
Steps for creating new scripts/ actions
|
||||
Add an action trigger to the relevant track (Either add it on blender and export it / set it up in scene.xml)
|
||||
Create a new script with the defined action scene.xml for the action trigger created. (For example, for tutorial_bananas =>
|
||||
|
||||
<object type="action-trigger" action="tutorial_bananas" distance="7.0" xyz="67.90 0.86 99.49" hpr="0.0 -0.0 0.0" scale="7.00 7.00 7.00"/>
|
||||
|
||||
action is "tutorial_bananas"
|
||||
so the script it calls is, stk/stk-code/scriptengine/tutorial_bananas.as
|
||||
|
||||
Make sure the method onTrigger() is defined. Check tutorial_bananas.as for more details
|
||||
|
||||
1808
src/scriptengine/angelscript.bak
Normal file
1808
src/scriptengine/angelscript.bak
Normal file
File diff suppressed because it is too large
Load Diff
1809
src/scriptengine/angelscript.h
Normal file
1809
src/scriptengine/angelscript.h
Normal file
File diff suppressed because it is too large
Load Diff
336
src/scriptengine/script_engine.cpp
Normal file
336
src/scriptengine/script_engine.cpp
Normal file
@@ -0,0 +1,336 @@
|
||||
|
||||
#include <iostream> // cout
|
||||
#include <assert.h> // assert()
|
||||
#include <string.h> // strstr()
|
||||
#include "states_screens/dialogs/tutorial_message_dialog.hpp"
|
||||
#ifdef _LINUX_
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
//#include <conio.h> // kbhit(), getch()
|
||||
//#include <windows.h> // timeGetTime()
|
||||
#endif
|
||||
|
||||
#include "angelscript.h"
|
||||
#include "script_engine.hpp"
|
||||
#include "scriptstdstring.h"
|
||||
|
||||
#define UINT unsigned int
|
||||
typedef unsigned int DWORD;
|
||||
|
||||
using namespace irr;
|
||||
|
||||
// Linux does have a getch() function in the curses library, but it doesn't
|
||||
// work like it does on DOS. So this does the same thing, with out the need
|
||||
// of the curses library.
|
||||
/*int getch()
|
||||
{
|
||||
struct termios oldt, newt;
|
||||
int ch;
|
||||
|
||||
tcgetattr(STDIN_FILENO, &oldt);
|
||||
newt = oldt;
|
||||
newt.c_lflag &= ~( ICANON | ECHO );
|
||||
tcsetattr( STDIN_FILENO, TCSANOW, &newt );
|
||||
|
||||
ch = getchar();
|
||||
|
||||
tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
|
||||
return ch;
|
||||
}
|
||||
*/
|
||||
//#endif
|
||||
|
||||
// Function prototypes
|
||||
int RunApplication(std::string);
|
||||
void ConfigureEngine(asIScriptEngine *engine);
|
||||
int CompileScript(asIScriptEngine *engine,std::string scriptName);
|
||||
void PrintString(std::string &str);
|
||||
void PrintString_Generic(asIScriptGeneric *gen);
|
||||
//void timeGetTime_Generic(asIScriptGeneric *gen);
|
||||
//void LineCallback(asIScriptContext *ctx, DWORD *timeOut);
|
||||
|
||||
ScriptEngineOne::ScriptEngineOne(){
|
||||
|
||||
}
|
||||
|
||||
// Displays the message specified in displayMessage( string message ) within the script
|
||||
void dispmsg(asIScriptGeneric *gen){
|
||||
std::string *input = (std::string*)gen->GetArgAddress(0);
|
||||
irr::core::stringw msgtodisp;
|
||||
irr::core::stringw out = irr::core::stringw((*input).c_str()); //irr::core::stringw supported by message dialogs
|
||||
new TutorialMessageDialog((out),true);
|
||||
}
|
||||
|
||||
std::string ScriptEngineOne::doit(std::string scriptName)
|
||||
{
|
||||
//displaymsg();
|
||||
fprintf(stderr, "inside engine");
|
||||
RunApplication(scriptName);
|
||||
|
||||
// Wait until the user presses a key
|
||||
//std::cout << std::endl << "Press any key to quit." << std::endl;
|
||||
//while(!getch());
|
||||
|
||||
return "wot";
|
||||
}
|
||||
void MessageCallback(const asSMessageInfo *msg, void *param)
|
||||
{
|
||||
const char *type = "ERR ";
|
||||
if( msg->type == asMSGTYPE_WARNING )
|
||||
type = "WARN";
|
||||
else if( msg->type == asMSGTYPE_INFORMATION )
|
||||
type = "INFO";
|
||||
|
||||
printf("%s (%d, %d) : %s : %s\n", msg->section, msg->row, msg->col, type, msg->message);
|
||||
}
|
||||
|
||||
|
||||
int RunApplication(std::string scriptName)
|
||||
{
|
||||
int r;
|
||||
std::cout<<scriptName;
|
||||
// Create the script engine
|
||||
asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
|
||||
if( engine == 0 )
|
||||
{
|
||||
std::cout << "Failed to create script engine." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// The script compiler will write any compiler messages to the callback.
|
||||
//engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL);
|
||||
|
||||
// Configure the script engine with all the functions,
|
||||
// and variables that the script should be able to use.
|
||||
ConfigureEngine(engine);
|
||||
|
||||
// Compile the script code
|
||||
r = CompileScript(engine,scriptName);
|
||||
if( r < 0 )
|
||||
{
|
||||
engine->Release();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Create a context that will execute the script.
|
||||
asIScriptContext *ctx = engine->CreateContext();
|
||||
if( ctx == 0 )
|
||||
{
|
||||
std::cout << "Failed to create the context." << std::endl;
|
||||
engine->Release();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// We don't want to allow the script to hang the application, e.g. with an
|
||||
// infinite loop, so we'll use the line callback function to set a timeout
|
||||
// that will abort the script after a certain time. Before executing the
|
||||
// script the timeOut variable will be set to the time when the script must
|
||||
// stop executing.
|
||||
//DWORD timeOut;
|
||||
//r = ctx->SetLineCallback(asFUNCTION(LineCallback), &timeOut, asCALL_CDECL);
|
||||
if( r < 0 )
|
||||
{
|
||||
std::cout << "Failed to set the line callback function." << std::endl;
|
||||
ctx->Release();
|
||||
engine->Release();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Find the function for the function we want to execute.
|
||||
//This is how you call a normal function with arguments
|
||||
//asIScriptFunction *func = engine->GetModule(0)->GetFunctionByDecl("void onTrigger(float, float)");
|
||||
asIScriptFunction *func = engine->GetModule(0)->GetFunctionByDecl("void onTrigger()");
|
||||
if( func == 0 )
|
||||
{
|
||||
std::cout << "The function 'float calc(float, float)' was not found." << std::endl;
|
||||
ctx->Release();
|
||||
engine->Release();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Prepare the script context with the function we wish to execute. Prepare()
|
||||
// must be called on the context before each new script function that will be
|
||||
// executed. Note, that if you intend to execute the same function several
|
||||
// times, it might be a good idea to store the function returned by
|
||||
// GetFunctionByDecl(), so that this relatively slow call can be skipped.
|
||||
r = ctx->Prepare(func);
|
||||
if( r < 0 )
|
||||
{
|
||||
std::cout << "Failed to prepare the context." << std::endl;
|
||||
ctx->Release();
|
||||
engine->Release();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Now we need to pass the parameters to the script function.
|
||||
//ctx->SetArgFloat(0, 3.14159265359f);
|
||||
//ctx->SetArgFloat(1, 2.71828182846f);
|
||||
|
||||
|
||||
// Execute the function
|
||||
std::cout << "Executing the script." << std::endl;
|
||||
std::cout << "---" << std::endl;
|
||||
r = ctx->Execute();
|
||||
std::cout << "---" << std::endl;
|
||||
if( r != asEXECUTION_FINISHED )
|
||||
{
|
||||
// The execution didn't finish as we had planned. Determine why.
|
||||
if( r == asEXECUTION_ABORTED )
|
||||
std::cout << "The script was aborted before it could finish. Probably it timed out." << std::endl;
|
||||
else if( r == asEXECUTION_EXCEPTION )
|
||||
{
|
||||
std::cout << "The script ended with an exception." << std::endl;
|
||||
|
||||
// Write some information about the script exception
|
||||
asIScriptFunction *func = ctx->GetExceptionFunction();
|
||||
std::cout << "func: " << func->GetDeclaration() << std::endl;
|
||||
std::cout << "modl: " << func->GetModuleName() << std::endl;
|
||||
std::cout << "sect: " << func->GetScriptSectionName() << std::endl;
|
||||
std::cout << "line: " << ctx->GetExceptionLineNumber() << std::endl;
|
||||
std::cout << "desc: " << ctx->GetExceptionString() << std::endl;
|
||||
}
|
||||
else
|
||||
std::cout << "The script ended for some unforeseen reason (" << r << ")." << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Retrieve the return value from the context
|
||||
//float returnValue = ctx->GetReturnFloat();
|
||||
//std::cout << "The script function returned: " << returnValue << std::endl;
|
||||
}
|
||||
|
||||
// We must release the contexts when no longer using them
|
||||
ctx->Release();
|
||||
|
||||
// Release the engine
|
||||
engine->Release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
void ConfigureEngine(asIScriptEngine *engine)
|
||||
{
|
||||
int r;
|
||||
|
||||
// Register the script string type
|
||||
// Look at the implementation for this function for more information
|
||||
// on how to register a custom string type, and other object types.
|
||||
RegisterStdString(engine);
|
||||
|
||||
if( !strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
|
||||
{
|
||||
// Register the functions that the scripts will be allowed to use.
|
||||
// Note how the return code is validated with an assert(). This helps
|
||||
// us discover where a problem occurs, and doesn't pollute the code
|
||||
// with a lot of if's. If an error occurs in release mode it will
|
||||
// be caught when a script is being built, so it is not necessary
|
||||
// to do the verification here as well.
|
||||
r = engine->RegisterGlobalFunction("void Print(string &in)", asFUNCTION(PrintString), asCALL_CDECL); assert( r >= 0 );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Notice how the registration is almost identical to the above.
|
||||
r = engine->RegisterGlobalFunction("void Print(string &in)", asFUNCTION(PrintString_Generic), asCALL_GENERIC); assert( r >= 0 );
|
||||
|
||||
}
|
||||
r = engine->RegisterGlobalFunction("void displayMessage(string &in)", asFUNCTION(dispmsg), asCALL_GENERIC); assert(r>=0);
|
||||
|
||||
// It is possible to register the functions, properties, and types in
|
||||
// configuration groups as well. When compiling the scripts it then
|
||||
// be defined which configuration groups should be available for that
|
||||
// script. If necessary a configuration group can also be removed from
|
||||
// the engine, so that the engine configuration could be changed
|
||||
// without having to recompile all the scripts.
|
||||
}
|
||||
|
||||
int CompileScript(asIScriptEngine *engine, std::string scriptName)
|
||||
{
|
||||
int r;
|
||||
|
||||
// We will load the script from a file on the disk.
|
||||
std::string load_dir = "D:\\Github\\stk\\stk-code\\src\\scriptengine\\";
|
||||
//std::string load_dir = "D:\\Github\\stk\\stk-code\\src\\scriptengine\\";
|
||||
load_dir += scriptName + ".as";
|
||||
FILE *f = fopen(load_dir.c_str(), "rb");
|
||||
//FILE *f = fopen("D:\\Uni Torrents\\angelscript_2.28.1\\sdk\\samples\\tutorial\\bin\\script.as", "rb");
|
||||
//FILE *f = fopen("//media//New Volume//Uni Torrents//angelscript_2.28.1//sdk//samples//tutorial//bin//script.as", "rb");
|
||||
if( f == 0 )
|
||||
{
|
||||
std::cout << "Failed to open the script file 'script.as'." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Determine the size of the file
|
||||
fseek(f, 0, SEEK_END);
|
||||
int len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
// On Win32 it is possible to do the following instead
|
||||
// int len = _filelength(_fileno(f));
|
||||
|
||||
// Read the entire file
|
||||
std::string script;
|
||||
script.resize(len);
|
||||
int c = fread(&script[0], len, 1, f);
|
||||
fclose(f);
|
||||
if( c == 0 )
|
||||
{
|
||||
std::cout << "Failed to load script file." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
//std::cout<<script<<std::endl;
|
||||
//script = "float calc(float a, float b){ return 23;}//asfafagadbsgsgsbfdxhbdhdhdfhdfbdfbdbfg";
|
||||
//len = script.size();
|
||||
// Add the script sections that will be compiled into executable code.
|
||||
// If we want to combine more than one file into the same script, then
|
||||
// we can call AddScriptSection() several times for the same module and
|
||||
// the script engine will treat them all as if they were one. The script
|
||||
// section name, will allow us to localize any errors in the script code.
|
||||
asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
|
||||
r = mod->AddScriptSection("script", &script[0], len);
|
||||
if( r < 0 )
|
||||
{
|
||||
std::cout << "AddScriptSection() failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Compile the script. If there are any compiler messages they will
|
||||
// be written to the message stream that we set right after creating the
|
||||
// script engine. If there are no errors, and no warnings, nothing will
|
||||
// be written to the stream.
|
||||
r = mod->Build();
|
||||
if( r < 0 )
|
||||
{
|
||||
std::cout << "Build() failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// The engine doesn't keep a copy of the script sections after Build() has
|
||||
// returned. So if the script needs to be recompiled, then all the script
|
||||
// sections must be added again.
|
||||
|
||||
// If we want to have several scripts executing at different times but
|
||||
// that have no direct relation with each other, then we can compile them
|
||||
// into separate script modules. Each module use their own namespace and
|
||||
// scope, so function names, and global variables will not conflict with
|
||||
// each other.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Function implementation with native calling convention
|
||||
void PrintString(std::string &str)
|
||||
{
|
||||
std::cout << str;
|
||||
}
|
||||
|
||||
// Function implementation with generic script interface
|
||||
void PrintString_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
std::string *str = (std::string*)gen->GetArgAddress(0);
|
||||
std::cout << *str;
|
||||
}
|
||||
47
src/scriptengine/script_engine.hpp
Normal file
47
src/scriptengine/script_engine.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2009-2013 Joerg Henrichs
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_SCRIPT_ENGINE_ONE_HPP
|
||||
#define HEADER_SCRIPT_ENGINE_ONE_HPP
|
||||
|
||||
#include<string>
|
||||
|
||||
class TrackObjectPresentation;
|
||||
|
||||
class ScriptEngineOne
|
||||
{
|
||||
public:
|
||||
|
||||
ScriptEngineOne();
|
||||
// ~ScriptEngine();
|
||||
void displayMessage();
|
||||
|
||||
int five(){
|
||||
return 5;
|
||||
}
|
||||
std::string doit(std::string scriptName);
|
||||
std::string getout(){
|
||||
return outval;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string outval;
|
||||
}; // class ScriptEngine
|
||||
#endif
|
||||
|
||||
1869
src/scriptengine/scriptarray.cpp
Normal file
1869
src/scriptengine/scriptarray.cpp
Normal file
File diff suppressed because it is too large
Load Diff
106
src/scriptengine/scriptarray.h
Normal file
106
src/scriptengine/scriptarray.h
Normal file
@@ -0,0 +1,106 @@
|
||||
#ifndef SCRIPTARRAY_H
|
||||
#define SCRIPTARRAY_H
|
||||
|
||||
#ifndef ANGELSCRIPT_H
|
||||
// Avoid having to inform include path if header is already include before
|
||||
#include "angelscript.h"
|
||||
#endif
|
||||
|
||||
// Sometimes it may be desired to use the same method names as used by C++ STL.
|
||||
// This may for example reduce time when converting code from script to C++ or
|
||||
// back.
|
||||
//
|
||||
// 0 = off
|
||||
// 1 = on
|
||||
|
||||
#ifndef AS_USE_STLNAMES
|
||||
#define AS_USE_STLNAMES 0
|
||||
#endif
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
struct SArrayBuffer;
|
||||
struct SArrayCache;
|
||||
|
||||
class CScriptArray
|
||||
{
|
||||
public:
|
||||
CScriptArray(asIObjectType *ot, void *initBuf); // Called from script when initialized with list
|
||||
CScriptArray(asUINT length, asIObjectType *ot);
|
||||
CScriptArray(asUINT length, void *defVal, asIObjectType *ot);
|
||||
CScriptArray(const CScriptArray &other);
|
||||
virtual ~CScriptArray();
|
||||
|
||||
void AddRef() const;
|
||||
void Release() const;
|
||||
|
||||
// Type information
|
||||
asIObjectType *GetArrayObjectType() const;
|
||||
int GetArrayTypeId() const;
|
||||
int GetElementTypeId() const;
|
||||
|
||||
void Reserve(asUINT maxElements);
|
||||
void Resize(asUINT numElements);
|
||||
asUINT GetSize() const;
|
||||
bool IsEmpty() const;
|
||||
|
||||
// Get a pointer to an element. Returns 0 if out of bounds
|
||||
void *At(asUINT index);
|
||||
const void *At(asUINT index) const;
|
||||
|
||||
// Set value of an element
|
||||
void SetValue(asUINT index, void *value);
|
||||
|
||||
CScriptArray &operator=(const CScriptArray&);
|
||||
bool operator==(const CScriptArray &) const;
|
||||
|
||||
void InsertAt(asUINT index, void *value);
|
||||
void RemoveAt(asUINT index);
|
||||
void InsertLast(void *value);
|
||||
void RemoveLast();
|
||||
void SortAsc();
|
||||
void SortDesc();
|
||||
void SortAsc(asUINT startAt, asUINT count);
|
||||
void SortDesc(asUINT startAt, asUINT count);
|
||||
void Sort(asUINT startAt, asUINT count, bool asc);
|
||||
void Reverse();
|
||||
int Find(void *value) const;
|
||||
int Find(asUINT startAt, void *value) const;
|
||||
int FindByRef(void *ref) const;
|
||||
int FindByRef(asUINT startAt, void *ref) const;
|
||||
|
||||
// GC methods
|
||||
int GetRefCount();
|
||||
void SetFlag();
|
||||
bool GetFlag();
|
||||
void EnumReferences(asIScriptEngine *engine);
|
||||
void ReleaseAllHandles(asIScriptEngine *engine);
|
||||
|
||||
protected:
|
||||
mutable int refCount;
|
||||
mutable bool gcFlag;
|
||||
asIObjectType *objType;
|
||||
SArrayBuffer *buffer;
|
||||
int elementSize;
|
||||
int subTypeId;
|
||||
|
||||
bool Less(const void *a, const void *b, bool asc, asIScriptContext *ctx, SArrayCache *cache);
|
||||
void *GetArrayItemPointer(int index);
|
||||
void *GetDataPointer(void *buffer);
|
||||
void Copy(void *dst, void *src);
|
||||
void Precache();
|
||||
bool CheckMaxSize(asUINT numElements);
|
||||
void Resize(int delta, asUINT at);
|
||||
void CreateBuffer(SArrayBuffer **buf, asUINT numElements);
|
||||
void DeleteBuffer(SArrayBuffer *buf);
|
||||
void CopyBuffer(SArrayBuffer *dst, SArrayBuffer *src);
|
||||
void Construct(SArrayBuffer *buf, asUINT start, asUINT end);
|
||||
void Destruct(SArrayBuffer *buf, asUINT start, asUINT end);
|
||||
bool Equals(const void *a, const void *b, asIScriptContext *ctx, SArrayCache *cache) const;
|
||||
};
|
||||
|
||||
void RegisterScriptArray(asIScriptEngine *engine, bool defaultArray);
|
||||
|
||||
END_AS_NAMESPACE
|
||||
|
||||
#endif
|
||||
1050
src/scriptengine/scriptstdstring.cpp
Normal file
1050
src/scriptengine/scriptstdstring.cpp
Normal file
File diff suppressed because it is too large
Load Diff
53
src/scriptengine/scriptstdstring.h
Normal file
53
src/scriptengine/scriptstdstring.h
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// Script std::string
|
||||
//
|
||||
// This function registers the std::string type with AngelScript to be used as the default string type.
|
||||
//
|
||||
// The string type is registered as a value type, thus may have performance issues if a lot of
|
||||
// string operations are performed in the script. However, for relatively few operations, this should
|
||||
// not cause any problem for most applications.
|
||||
//
|
||||
|
||||
#ifndef SCRIPTSTDSTRING_H
|
||||
#define SCRIPTSTDSTRING_H
|
||||
|
||||
#ifndef ANGELSCRIPT_H
|
||||
// Avoid having to inform include path if header is already include before
|
||||
#include "angelscript.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
//---------------------------
|
||||
// Compilation settings
|
||||
//
|
||||
|
||||
// The use of the string pool can improve performance quite drastically
|
||||
// for scripts that work with a lot of literal string constants.
|
||||
//
|
||||
// 1 = on
|
||||
// 0 = off
|
||||
|
||||
#ifndef AS_USE_STRINGPOOL
|
||||
#define AS_USE_STRINGPOOL 1
|
||||
#endif
|
||||
|
||||
// Sometimes it may be desired to use the same method names as used by C++ STL.
|
||||
// This may for example reduce time when converting code from script to C++ or
|
||||
// back.
|
||||
//
|
||||
// 0 = off
|
||||
// 1 = on
|
||||
|
||||
#ifndef AS_USE_STLNAMES
|
||||
#define AS_USE_STLNAMES 0
|
||||
#endif
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
void RegisterStdString(asIScriptEngine *engine);
|
||||
void RegisterStdStringUtils(asIScriptEngine *engine);
|
||||
|
||||
END_AS_NAMESPACE
|
||||
|
||||
#endif
|
||||
129
src/scriptengine/scriptstdstring_utils.cpp
Normal file
129
src/scriptengine/scriptstdstring_utils.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
#include <assert.h>
|
||||
#include "scriptstdstring.h"
|
||||
#include "scriptarray.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
// This function takes an input string and splits it into parts by looking
|
||||
// for a specified delimiter. Example:
|
||||
//
|
||||
// string str = "A|B||D";
|
||||
// array<string>@ array = str.split("|");
|
||||
//
|
||||
// The resulting array has the following elements:
|
||||
//
|
||||
// {"A", "B", "", "D"}
|
||||
//
|
||||
// AngelScript signature:
|
||||
// array<string>@ string::split(const string &in delim) const
|
||||
static CScriptArray *StringSplit(const string &delim, const string &str)
|
||||
{
|
||||
// Obtain a pointer to the engine
|
||||
asIScriptContext *ctx = asGetActiveContext();
|
||||
asIScriptEngine *engine = ctx->GetEngine();
|
||||
|
||||
// TODO: This should only be done once
|
||||
// TODO: This assumes that CScriptArray was already registered
|
||||
asIObjectType *arrayType = engine->GetObjectTypeById(engine->GetTypeIdByDecl("array<string>"));
|
||||
|
||||
// Create the array object
|
||||
CScriptArray *array = new CScriptArray(0, arrayType);
|
||||
|
||||
// Find the existence of the delimiter in the input string
|
||||
int pos = 0, prev = 0, count = 0;
|
||||
while( (pos = (int)str.find(delim, prev)) != (int)string::npos )
|
||||
{
|
||||
// Add the part to the array
|
||||
array->Resize(array->GetSize()+1);
|
||||
((string*)array->At(count))->assign(&str[prev], pos-prev);
|
||||
|
||||
// Find the next part
|
||||
count++;
|
||||
prev = pos + (int)delim.length();
|
||||
}
|
||||
|
||||
// Add the remaining part
|
||||
array->Resize(array->GetSize()+1);
|
||||
((string*)array->At(count))->assign(&str[prev]);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
static void StringSplit_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
// Get the arguments
|
||||
string *str = (string*)gen->GetObject();
|
||||
string *delim = *(string**)gen->GetAddressOfArg(0);
|
||||
|
||||
// Return the array by handle
|
||||
*(CScriptArray**)gen->GetAddressOfReturnLocation() = StringSplit(*delim, *str);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This function takes as input an array of string handles as well as a
|
||||
// delimiter and concatenates the array elements into one delimited string.
|
||||
// Example:
|
||||
//
|
||||
// array<string> array = {"A", "B", "", "D"};
|
||||
// string str = join(array, "|");
|
||||
//
|
||||
// The resulting string is:
|
||||
//
|
||||
// "A|B||D"
|
||||
//
|
||||
// AngelScript signature:
|
||||
// string join(const array<string> &in array, const string &in delim)
|
||||
static string StringJoin(const CScriptArray &array, const string &delim)
|
||||
{
|
||||
// Create the new string
|
||||
string str = "";
|
||||
if( array.GetSize() )
|
||||
{
|
||||
int n;
|
||||
for( n = 0; n < (int)array.GetSize() - 1; n++ )
|
||||
{
|
||||
str += *(string*)array.At(n);
|
||||
str += delim;
|
||||
}
|
||||
|
||||
// Add the last part
|
||||
str += *(string*)array.At(n);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static void StringJoin_Generic(asIScriptGeneric *gen)
|
||||
{
|
||||
// Get the arguments
|
||||
CScriptArray *array = *(CScriptArray**)gen->GetAddressOfArg(0);
|
||||
string *delim = *(string**)gen->GetAddressOfArg(1);
|
||||
|
||||
// Return the string
|
||||
new(gen->GetAddressOfReturnLocation()) string(StringJoin(*array, *delim));
|
||||
}
|
||||
|
||||
// This is where the utility functions are registered.
|
||||
// The string type must have been registered first.
|
||||
void RegisterStdStringUtils(asIScriptEngine *engine)
|
||||
{
|
||||
int r;
|
||||
|
||||
if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
|
||||
{
|
||||
r = engine->RegisterObjectMethod("string", "array<string>@ split(const string &in) const", asFUNCTION(StringSplit_Generic), asCALL_GENERIC); assert(r >= 0);
|
||||
r = engine->RegisterGlobalFunction("string join(const array<string> &in, const string &in)", asFUNCTION(StringJoin_Generic), asCALL_GENERIC); assert(r >= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = engine->RegisterObjectMethod("string", "array<string>@ split(const string &in) const", asFUNCTION(StringSplit), asCALL_CDECL_OBJLAST); assert(r >= 0);
|
||||
r = engine->RegisterGlobalFunction("string join(const array<string> &in, const string &in)", asFUNCTION(StringJoin), asCALL_CDECL); assert(r >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
END_AS_NAMESPACE
|
||||
4
src/scriptengine/tutorial_bananas.as
Normal file
4
src/scriptengine/tutorial_bananas.as
Normal file
@@ -0,0 +1,4 @@
|
||||
void onTrigger()
|
||||
{
|
||||
displayMessage("Bananas! Bananas! Everywhere!");
|
||||
}
|
||||
Reference in New Issue
Block a user