• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
WitchLord

AngelScript 1.9.0 WIP 4 (2004/08/31)

45 posts in this topic

Ok, I'll work on some way of defining the message format in as_config.h. Probably a simple printf() formatting string, with numbered arguments.

I'll also see if I can give better information on the exact token that causes the message. This can be either the length, or the exact token, or both.

Another thing I've been thinking on adding is a line offset when calling AddScriptSection(), this will allow you to offset the line numbers reported in error messages and exceptions thrown by the scripts. This would be used by those who, like abrken, add code before the actual script.

abrken:

Could you give me a little more detail on what you want? What do you mean with a trick to raise a warning?
0

Share this post


Link to post
Share on other sites
It's ok, i have raised a Warning like this :

int iWarning;
iWarning += 500;


That result in :

TheOtherCode (2, 1) : Info : Compiling void TheOtherCode()
TheOtherCode (11, 10) : Warning : 'iWarning' is not initialized.


0

Share this post


Link to post
Share on other sites
I've uploaded WIP 3 now.

This version adds dynamic binding of functions between modules, which allow functions to call into other modules.

The following code shows how the import can be done:


//
// Tests importing functions from other modules
//
// Test author: Andreas Jonsson
//

#include "angelscript.h"
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <string>

namespace TestImport
{

#define TESTNAME "TestImport"


static std::string output;

class COutStream : public asIOutputStream
{
public:
void Write(const char *text) { printf(text); /*output += text;*/ }
};


static const char *script1 =
"import void Test() from \"DynamicModule\"; \n"
"void main() \n"
"{ \n"
" Test(); \n"
"} \n";

static const char *script2 =
"void Test() \n"
"{ \n"
" number = 1234567890; \n"
"} \n";

bool Test()
{
bool fail = false;

int number = 0;

asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
engine->RegisterGlobalProperty("int number", &number);

COutStream out;
engine->AddScriptSection(0, TESTNAME ":1", script1, strlen(script1));
engine->Build(0, &out);

engine->AddScriptSection("DynamicModule", TESTNAME ":2", script2, strlen(script2));
engine->Build("DynamicModule", &out);

int module1 = engine->GetModuleID(0);

// Bind imported functions
int c = engine->GetImportedFunctionCount(0);
for( int n = 0; n < c; ++n )
{
char buffer[256];
engine->GetImportedFunctionDeclaration(module1 + n, buffer, 256);

// Get module name from where the function should be imported
const char *moduleName = engine->GetImportedFunctionSourceModule(module1 + n);

int funcID = engine->GetFunctionIDByDecl(moduleName, buffer);
engine->BindImportedFunction(module1 + n, funcID);
}

engine->ExecuteString(0, "main()", &out, 0);

engine->Release();

if( number != 1234567890 )
{
printf("%s: Failed to set the number as expected\n", TESTNAME);
fail = true;
}

// Success
return fail;
}

} // namespace



I'm however not satisfied with how the asIScriptEngine interface has become so bloated with the latest additions. I will therefore break out the module interface, which will make it easier to work with.

Regards,
Andreas Jönsson
0

Share this post


Link to post
Share on other sites
Quote:
Original post by WitchLord
I'm however not satisfied with how the asIScriptEngine interface has become so bloated with the latest additions. I will therefore break out the module interface, which will make it easier to work with.


What do you mean when you write this ?
1/ Do the syntax that is discribed in your code will change for the script (import ... from ...)
2/ Do the link between the modules will change for the C++ (loop GetImportedFunctionCount)
3/ Is this going to be an internal change that wont change anything from script to C++ interface.

Since I was waiting for dynamic binding of functions between modules, I can wait for another version if WIP 3 is just a primary approach.
0

Share this post


Link to post
Share on other sites
I see the reason for all this manual work (users might have special cases), but I don't think it's really needed.

I would preffer it to be more automated. Something like engine->BindImported("module") after all the modules that are needed are compiled.

Or with slightly more control: engine->BindImported("module", "ImportedName", "RealModuleName");

The completely manual approach can co-exist with this one, should application writers desire this.

Just offering my suggestions :).
0

Share this post


Link to post
Share on other sites
abrken:

I'll answer your last question first: This will change the library interface. Though the changes won't be that big that you can't start using WIP 3 already.

Currently the script syntax is:


import void Function(int param) from "module";
import void AnotherFunc() from "module";
import void OneMoreFunc() from "module";


I am playing with the thought of changing this to:


import from "module"
{
void Function(int param);
void AnotherFunc();
void OneMoreFunc();
}


But that's not really the important change. I might even use both ways.

What I noticed when doing the tests for importing functions is that there can be a slight confusion between imported function IDs and script function IDs. The current loop for binding functions will change a little, but not that much that you can't start using WIP 3 already.

The code will probably end up something like this:


asIScriptModule *module = engine->GetModule(0);

// Bind imported functions
int c = module->GetImportedFunctionCount();
for( int n = 0; n < c; ++n )
{
char buffer[256];
module->GetImportedFunctionDeclaration(n, buffer, 256);

// Get module name from where the function should be imported
const char *moduleName = module->GetImportedFunctionSourceModule(n);

asIScriptModule *otherModule = engine->GetModule(moduleName);
asFUNCID funcID = otherModule->GetFunctionIDByDecl(buffer);
module->BindImportedFunction(n, funcID);
}



Basically, most of the functions that require a module name or module index will be moved into the module interface. There will be one more interface to keep track of but I think the interfaces will be more easy to understand and use.

Gyrbo:

I've had the same thoughts, and I just might go ahead and do something like that.

0

Share this post


Link to post
Share on other sites
If anyone has any suggestion for how to improve the dynamic binding of modules now is the time to tell me. Give WIP 3 a try and give me your feedback.

Thanks.
0

Share this post


Link to post
Share on other sites
WIP3 is not as easy to integrate as others ... acString changed to asString need extra work !
0

Share this post


Link to post
Share on other sites
Yes, I decided to include acCString and acCArray as integrated parts of the library, which meant changing the name of them to follow the naming standard of the library.

Are you using acCString/acCArray outside the library?

0

Share this post


Link to post
Share on other sites
Did you try to compile AngelScrit as Debug ?

Try it and you get compil error in as_bytecode.cpp.

This is what I was meaning in : it's not so easy ...


void asCByteCode::DebugOutput(const char *name)
{
#ifdef AS_DEBUG

mkdir("AS_DEBUG");

acCString str = "AS_DEBUG\\";


Also, I'm working with source control, witch mean changing files, and it takes some times too !

And finaly, no I'm not using acStrings !

Ooops, Yes finaly I was using acString !

Oooops 2, I must write some wrapper code to pure virtual methods added to asIScriptEngine !
0

Share this post


Link to post
Share on other sites
Hi everyone

This might sound a little stupid, but why do we need to bind modules manually?

Wouldn't it be much easyer if we just define that modules from which we use functions must be previously declared?

In the importing module we could write

BModule::trackEntity(e);

and the engines build method tries to bind the function automatically.

In case we need late binding (if we have circular dependencies) we still could do the binding by hand (although the engine could do this too by keeping track of what was bound and what is still unbound and checking for unbound functions after a new module is included), but this should not be the regular case.

Now, there are probably some good reasons why we need to do this by hand. I'm not familiar with the internals of AngelScript so forgive me if this really sounds like a silly thing to do.

Regards,
Tom

0

Share this post


Link to post
Share on other sites
abrken:

Ooops from me too [wink]. I haven't compiled with the AS_DEBUG flag in quite some time. I'll do that to check the code.

You are doing some heavy integration with the library. It's only expected that you are going to have more work to do with each version.

zola:

I chose not to require the modules to be compiled in a specific order because it makes it easier to use. With the import statement a module can be correctly compiled even if the other module doesn't exist yet. You can even execute the code, but if an imported function is called before being bound you'll get a script exception.

I also wanted to allow rebinding afterwards, so that the imported functions could be exchanged at runtime, possibly even by a function called from the script itself.

Another reason why I didn't want to make it automatic is that I want to allow an application to have control over which functions that are bound. It might be that an application don't want to allow binding of all script functions, in which case it must verify what functions the script is trying to bind.

If I didn't have the above requirements I could have used automatic binding. However, I will probably do what Gyrbo suggested and provide a method that automatically binds all imported functions after compilation, which is probably what most want to do anyway.

0

Share this post


Link to post
Share on other sites
After giving it a try I've decided not to create the separate module interface.

It got more awkward to work with the engine when using a separate interface. It became necessary to explicitly create the modules, and then keep track of references, etc. It was good that there was less parameters to pass with each call, but the negative impact outweighed the good ones.

I will still do some changes to the interface, but they will be minor and mostly cosmetic, e.g. using a struct for function IDs instead of just an integer (for compile time verification).

Just thought I'd let you know...
0

Share this post


Link to post
Share on other sites
After having integrated WIP3 I get returned to WIP2 !

My program that was working suddenly get troubles on string destructors (std::string integrated).

Sad to say that I can't reproduce the bug in a code snippset, so I have decided to continue working with WIP2.

When I get time I'll try to understand what's going on with ~string, at the time it re-work perfectly with WIP2 !
0

Share this post


Link to post
Share on other sites
I don't know either what's wrong. I have a test case in the framework that uses std::string and it works perfectly.

That said Lennart Denninger discovered yesterday a bug when doing multiple assignments in one statement:

a = b = c;

If a, b, and c are registered objects with the assignment behaviour then they won't be assigned correctly.

I've already fixed this problem in WIP4, and I'll show you how to fix it here as well:

In the file as_scriptengine.cpp:

Method RegisterObjectBehaviour():

Add this code:


if( !isGlobal )
func.objectType = type.extendedType;


after this part (aprox. 70 lines into the function):


r = bld.ParseFunctionDeclaration(decl, &func);
if( r < 0 )
return ConfigError(asINVALID_DECLARATION);


Method AddBehaviourFunction():

Add this code:


f->objectType = func.objectType;


after this part (aprox. 10 lines into the function):


asCScriptFunction *f = new asCScriptFunction;


[Edited by - WitchLord on August 31, 2004 8:44:03 AM]
0

Share this post


Link to post
Share on other sites
I've uploaded the latest work in progress.


  • Removed GetModuleID()
  • Added GetModuleIndex(), and GetModuleNameFromIndex()
  • Changed the interface for import functions, to work with module name and imported function index, instead of a single function ID. This was done to prevent confusion between functionID and imported function indices.
  • Added GetFunctionIDByIndex() and GetGlobalVarIDByIndex()
  • bug fix: Multiple assignments in the same statement didn't work for objects. Introduced in 1.9.0 (thanks Lennart Denninger)
  • Added functions for automatically binding all functions imported in a module. New error code asCANT_BIND_ALL_FUNCTIONS
  • Added the lineOffset parameter to AddScriptSection()
  • bug fix: Saving and loading byte code is actually working now. Introduced in 1.9.0


As I mentioned earlier the changes aren't quite so drastic as I had planned.

The new method BindAllFunctions() can be used to automatically bind all imported functions after the modules have been built.

I will probably only do a few minor corrections here and there before releasing 1.9.0 as beta.

0

Share this post


Link to post
Share on other sites
Yes !

I have downloaded WIP4 and everything is working like in WIP2 now !
Thank's for wathever you did to the WIP3 code !

Also I did test imported function and it's great ! (except that it took me some times to understand how BindAllImportedFunctions was working !)

I've got one question :
Why does the import statement MUST be outside a function ? (of course I ask you this because inserting an import statement in a function raised me a compile error !).

Again, great job, great thank you.



0

Share this post


Link to post
Share on other sites
I'm glad that WIP4 is working ok.

I'll update the manual when I release version 1.9.0 as beta. It ought to explain everything about importing functions. [smile]

The import statement must be global because AngelScript doesn't understand nested functions. After the function has been declared with the import statement, the compiler will treat it just like any other function.
0

Share this post


Link to post
Share on other sites
I'm having trouble with the asFUNCTIONP/PR macros. Each of the asMETHODP/PR versions work fine, but I can't seem to get the asFUNCTIONP/PR macros to work on overloaded functions (or on a non-overloaded functions for that matter).


pEngine->RegisterGlobalFunction("void ReadFile(const string& filename, string& buffer)", asFUNCTIONP(ReadFile, (const string&, string&)), asCALL_CDECL);

d:\Code\Rpg_test\asExtensions.cpp(174): error C2664: 'asFunctionPtr' : cannot convert parameter 1 from 'void (__cdecl *)(const std::string &,std::string &)' to 'asFUNCTION_t'

// ...

pEngine->RegisterGlobalFunction("Command& CMD(string scr, string fmt)", asFUNCTIONPR(CMD, (string,string), CCommand&), asCALL_CDECL);

d:\Code\Rpg_test\asExtensions.cpp(171): error C2664: 'asFunctionPtr' : cannot convert parameter 1 from 'CCommand &(__cdecl *)(std::string,std::string)' to 'asFUNCTION_t'


0

Share this post


Link to post
Share on other sites
I gave it a try, and found out that the macro needs one more cast to void(*)() in order to work.

The fix is to change the macros in angelscript.h to the following:

#define asFUNCTIONP(f,p) asFunctionPtr((void (*)())((void (*)p)(f)))
#define asFUNCTIONPR(f,p,r) asFunctionPtr((void (*)())((r (*)p)(f)))

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0