Jump to content

  • Log In with Google      Sign In   
  • Create Account

Andreas Jonsson

Member Since 26 Mar 2000
Offline Last Active Yesterday, 06:03 PM

#5268242 Accessing an object managed by the engine through a global variable

Posted by Andreas Jonsson on 28 December 2015 - 06:43 PM

What about setting the value of the global parameter through GetAddressOfGlobalVar() like I showed you above? Is that okay? And is the global variable still allowed to be a handle even though the object type is not garbage collected?


Yes. This is the correct way of doing it.


asOBJ_NOCOUNT just means that the type doesn't rely on reference counting for controlling the lifetime of the objects, it doesn't mean that the types cannot be references through handles (which in this case behave pretty much the same way as ordinary pointers in C++).


Had the type been reference counted, you would still use GetAddressOfGlobalVar() to set the value, but you would have to take care to call Release on the previous object and AddRef on the new object when changing the address.

#5268202 Accessing an object managed by the engine through a global variable

Posted by Andreas Jonsson on 28 December 2015 - 10:42 AM

What you've done is perfectly fine if you trust the script writers not to do something unexpected with the ScriptComponent reference. For example, if the script store a reference to the ScriptComponent in some other variable for use at a later time. That might end up causing crashes due to dangling pointers if the script tries to access the object after it has been destroyed in the game engine. 


If you do not trust the script writers, e.g. if you plan to allow end users to write their own scripts, then you may want to use a little more secure way of managing your pointers, e.g. add proper reference counting in the objects to make sure they aren't destroyed while there are still active references to them, and probably also use weak-references to avoid keeping objects alive longer than necessary.

#5265294 Array doesn't properly document find and findByRef

Posted by Andreas Jonsson on 07 December 2015 - 11:53 AM

Thanks. I'll make the necessary adjustments.

#5264130 Support for unicode identifiers

Posted by Andreas Jonsson on 29 November 2015 - 12:13 PM

Having the tokenizer call a callback for every identifier would probably impact the compiler performance quite a bit for everyone, even those who would not use the callback.  


Instead I suggest you modify the CScriptBuilder add-on to translate special identifiers to keywords before passing the script to the compiler. The CScriptBuilder already has logic for doing a pre-compile pass on the code script and change some things, so it should be quite easy for you to implement that on your own.


Alternatively you can customize the asCTokenizer to translate the special identifiers for you.

#5260114 Support for unicode identifiers

Posted by Andreas Jonsson on 02 November 2015 - 08:20 AM

I've implemented support for this in revision 2248.


You turn on the support for unicode in identifiers with engine->SetEngineProperty(asEP_ALLOW_UNICODE_IDENTIFIERS, true);




#5259346 Factory Functions

Posted by Andreas Jonsson on 27 October 2015 - 07:04 PM

instance = *((asIscriptObject**)asEngine->CreateScriptObject(ctrl->type));


This should be instance = (asIScriptObject*)asEngine->CreateScriptObject(ctrl->type);



instance->AddRef(); // this throws a null pointer error and crashes the program


This shouldn't be done. The pointer returned by CreateScriptObject already has one reference counted for, which is owned by the application that called CreateScriptObject. When you are done with the object you should call instance->Release() to free the memory.



On a side note, i would like the CGameObj  @self; link to be seamless, would it be better to define this inside the game code as a base class rather than using a interface.


I didn't quite understand your question. Do you want that the script writer doesn't have to declare CGameObj @self in the script class? If so, yes you can have the application implement a base class that all scripts controllers must inherit from instead of the controller interface.

#5259204 Factory Functions

Posted by Andreas Jonsson on 26 October 2015 - 04:16 PM

If the class doesn't define any constructor at all, then it will get a default constructor. asIScriptEngine::CreateScriptObject can be used to create instances of classes that have default constructors (or you can manually call the default factory). The application can then call the Start method on the class that the user defined.


When deserializing a script object you should preferably use the method asIScriptEngine::CreateUninitializedScriptObject. The method will basically just allocate the necessary memory, but will not call any of the class' constructors. Once created the application should enumerate the properties of the object and set the value of each of them to whatever was serialized before.

#5257715 Patch proposal for scriptany add-on issue

Posted by Andreas Jonsson on 17 October 2015 - 03:35 PM

I've fixed this in revision 2243.




#5252806 object function and variable list

Posted by Andreas Jonsson on 17 September 2015 - 08:54 PM

You'd use the asIObjectType interface to inspect the declaration of object properties, and asIScriptObject to get/set the values of the object properties.


The serializer add-on may be of help getting your save system working. 


You may also find the article on Reflection of interest.




#5252703 *.fnt files and Game Maker Studio

Posted by Andreas Jonsson on 17 September 2015 - 12:04 PM

xadvance is how much the cursor should be advanced after rendering the character before rendering the next character. It is unrelated to the xoffset, x and width values. Note, that kerning pairs alter this value for specific combinations of characters as determined by the font designer.


xoffset and yoffset are the offsets from the current position where the character quad should be rendered. xoffset is usually near 0, unless the character is designed to have an overlap with previous character (negative xoffset) or have extra spacing between previous character (positive xoffset). As yoffset is the distance from the top of the line to the top of the quad, it will have a higher value for smaller characters, e.g. capital A (id 65) has a small yoffset, and small a (id 97) has a larger yoffset, underline _ (id 95) has an even larger yoffset.


width and height give the size of the quad that should be rendered.


x and y show the position in the texture where the character should be copied from when rendering it.




I'm not sure what format and layout that Game Maker requires for its bitmap fonts, so I can't say what you need to do to transform the BMFont format into the Game Maker format.


I think you would benefit from taking a look at how fonts are actually rendered directly from the BMFont format. Take a look at the various tutorials and resouces that I link to from my site. Hopefully by seeing the code it will be easier for you to figure what needs to be done to transform the format.

#5252593 *.fnt files and Game Maker Studio

Posted by Andreas Jonsson on 16 September 2015 - 08:37 PM

I didn't even know of the Littera web app, much less that it exported fonts in the same format that I came up with for BMFont long back. biggrin.png


I'll gladly link to your project for converting the png+fnt BMFont format into the Game Maker format from my site. I'm sure others will be interested in using it too.

#5250697 How is cast<T>() registered?

Posted by Andreas Jonsson on 05 September 2015 - 10:22 AM

cast<T>() is not registered. This is a built-in function, and serves the same purpose as dynamic_cast<T>() in C++.


You can implement the opImplConv overload in the typeof<T>() class to allow it to be implicitly converted to the Type object.


You may want to take a look at this post. cvet has already implemented and shared code that does exactly what you want.

#5250338 Would this be misuse of aslScriptContext::Suspend()?

Posted by Andreas Jonsson on 02 September 2015 - 04:48 PM

A) This is a perfectly valid use case. Using this script engine like this can be thought of a form of coroutine. Just remember that it is currently not possible to serialize a context's state, so if you plan on allowing the user to save the game in the middle of a playthrough with coroutines still running you'll face trouble.


B) You'll probably be fine with 50 something contexts. Expect each context to take up a few KB of memory. If you're targeting platforms with limited amount of memory you can tweak the amount of memory that is allocated for the callstack in the contexts by setting the engine property asEP_MAX_STACK_SIZE.


C) Take a look at the code for the ExecuteString helper function. It is a good place to start, but you'll likely want to make some adaptions to suite your own specific needs. For example, resuming the context after it has been suspended. By default the function doesn't support resuming, since it discards the script code before returning.


D) Yes, PushState/PopState can be used to call the different script. Though, obviously you cannot resume the original script before the called script finishes if you do.




#5250195 Implicit parameter to factory function?

Posted by Andreas Jonsson on 01 September 2015 - 06:45 PM

You could implement the factory function for the object as a functor, and register it with the calling convention asCALL_THISCALL_ASGLOBAL. The functor object can then hold the value that you wish to pass to the object constructor.


class MyFunctor
Object *Factory() { return new Object(value); };
int value;
MyFunctor *factoryFunctor = new MyFunctor;
factoryFunctor->value = 42; // change this whenever you want a different value for the Object constructor
engine->RegisterObjectBehaviour("Object", asBEHAVE_FACTORY, "Object @f()", asMETHOD(MyFunctor, Factory), asCALL_THISCALL_ASGLOBAL, factoryFunctor);

#5249739 AngelScript 2.30.2 is out

Posted by Andreas Jonsson on 30 August 2015 - 12:07 PM

With this version I've spent most of the time on optimizations. Specifically the time for loading pre-compiled byte code has improved significantly for applications that exposes a large interface to the scripts. There are some run-time optimizations too, but those are probably only noticeable in very specific cases.


Besides the optimizations I've implemented support for anonymous functions, a.k.a. lambdas, in the script language. The anonymous functions are so far just global functions declared locally in the expression that needs them, but I'll continue to expand on the usefulness of them for future releases.