🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Template containers angelscript addon library release!

Started by
48 comments, last by Wracky 7 years, 8 months ago
This page of the manual answers some of your questions regarding using custom c++ types as keys of containers: manual link

The script:


unordered_map<Vector2i,string> spacehash;

should compile if you register a template specialization of the aatc hashing function as described at the bottom of that manual page. The manual page also tells you that the "Vector2i" type should have an equals operator. Spacehashes for everyone.

The test application's script has some examples of how to declare required methods for script objects to be used in containers, including operator< for set/map and hash for unordered set/map.
Found here: "aatc/test/bin/script/basics.as" bottom of the file

class Material{
  string name;
  int id;

  Material(){}
  Material(string _name,int _id){
    name = _name;
    id = _id;
  }
  ~Material(){}


  bool opEquals(Material &in other){return (name == other.name);}
  int opCmp(Material &in other){
    if(name == other.name){return 0;}
    if(name < other.name){return -1;}else{return 1;}
  }
  uint64 hash(){return aatc_Hashfunc_djb2(name);}
};

With those functions, the Material class is able to be used in all containers as a key or value.

it.current_key();

vs

it.key

Where key and value are actually properties returning references

I was under the impression that accessing iterators had to be done with functions in the current version of angelscript. I should make the names of current_x() configurable so that you could name them shorter if you like.

foreach macro

Macro looks legit, but I don't think the scriptbuilder addon's preprocessor supports macros. Ofcourse you can use your own preprocessor for scripts.

Advertisement

The script:


unordered_map<Vector2i,string> spacehash;

should compile if you register a template specialization of the aatc hashing function as described at the bottom of that manual page. The manual page also tells you that the "Vector2i" type should have an equals operator. Spacehashes for everyone.

But the doc says:

map and unordered_map are not available because they take 2 template parameters and that would require partial template specialization which angelscript probably doesnt support.

So I thought it was not possible, and I didn't found aatc_register_container_tempspec_unordered_map. Or maybe I'm not doing it right?

map and unordered_map are not available because they take 2 template parameters

Means you can't make a template specialization of the entire container. Making a tempspec of the container is supposed to give you slightly more speed because it won't have to worry about the contained types in runtime. You can still use your c++ class with the actual angelscript template type container by registering that hash functor template specialization for your c++ vector class. Looks all the same in script in the end, just 1% slower.

edit: just found out that you need something more.

Got a space hash unordered_map working with my own c++ vec3 as the key, but it needs more than just the hash functor tempspec.

Because unordered_map is always an actual angelscript template object, it treats your c++ vector type as a script object.

So you also need to tell your angelscript engine that your c++ vector class has a hashing function with RegisterObjectMethod.

I got it working with code like this:

edit3: these fucking code boxes keep on exploding


//you need to include aatc_common.hpp instead of just aatc.hpp for the hashing templates
#include "aatc_common.hpp"


template<> class aatc_functor_hash<myVec3>{
  public:
  aatc_hash_type operator()(const myVec3& a) const{
    return (a.x * 73856093) ^ (a.y * 19349663) ^ (a.z * 83492791);
  }
};

void Register_All_My_Things(engine){
  ...
  ...
  engine->RegisterObjectType("myVec3", sizeof(myVec3), asOBJ_VALUE ...);
  ...
  engine->RegisterObjectMethod("myVec3", "bool opEquals(const myVec3 &in) const", ...);
  ...
  //this line is new stuff
  //engine->RegisterObjectMethod("myVec3", "uint64 hash()", asFUNCTION(aatc_func_hash_value<myVec3>), asCALL_CDECL_OBJLAST);
  //edit2: use this instead, for automated hash result typenames
  aatc_Register_aatc_func_hash_value<myVec3>(engine, "myVec3");
  ...
  ...
  aatc_RegisterAllContainers(engine);
}

I just now implemented "aatc_func_hash_value" which is a templated function to wrap a templated functor (...) for this purpose, because angelscript don't want to register no functors. You'll have to grab a new version from the old link, only "aatc_common.hpp" has changed.

edit2: more changes!

aatc_config.hpp now has settings for hash return type bitness. Previously it assumed std::size_t and unsigned int 64 to be the same, which might have caused explosions in 32 bit projects. The settings are set automatically, but you can change them manually if you like.

aatc_Register_aatc_func_hash_value<myVec3>(engine, "myVec3"); implemented. It will take care of using the correct types when registering hash functions for your c++ classes.

"it.current_value()" and friends can now have their names configured in aatc_config.hpp

line = #define aatc_name_script_iterator_method_current_value "current_value"


I was under the impression that accessing iterators had to be done with functions in the current version of angelscript. I should make the names of current_x() configurable so that you could name them shorter if you like.

How about using virtual property accessors? I.e. name them get_key() and get_value()/set_value().

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Newest version of the experimental-auto-iterators branch now supports virtual property accessors!

New hot syntax:


for(auto it = myvec.begin();it++;){
  MyPrint("current value = " + it.value);
}

Iterators of map / uo_map obviously have "value" and "key" virtual properties.

Iterators can still be accessed with the old "current()", "current_key()" and "current_value()" and you might want to, because property accessors don't seem to support compound assignment operators (+= , *= etc) and functions returning references do.

All the new names can be set in the config.

Iterators can still be accessed with the old "current()", "current_key()" and "current_value()" and you might want to, because property accessors don't seem to support compound assignment operators (+= , *= etc) and functions returning references do.

That's weird... AngelScript properties (fields hidden by a get/set, to be clear^^) are defined just like methods with C++ functions, I wonder why they would behave differently?

I'm going to implement hash stuff with your new version soon smile.png

EDIT:

Additionnal question:

Are we forced to register hash functions before registering the containers?

I'm asking this because in my engine, I load modules as shared libraries on runtime that register stuff, but I registered the containers first because they're part of the Core.

--

The next thing I'm going to work being mighty hot-reload, how AATC behaves with the Serializer add-on?

Any actual template specializations of containers ("aatc_register_container_tempspec_X<>();") and whatever functor template specializations they need will have to come before registering the containers to script, because of c++ template things. AATC containers that are not specialized can store objects of any script created class or c++ class registered to the as engine, those classes can ofcourse be declared before or after aatc.

About the serializer addon:

The serializer addon requires c++ glue code to serialize a c++ class and the current version of AATC provides none of that.

The manual page for the serializer doesn't say anything about templates and how they should be registered for use with it, which leads me to believe it probably doesn't support them at all. If it does I will try to add support for the serializer.

In order to know how to serialize the AATC containers (or any other registered type) the application has to provide an implementation of the CUserType with the logic for the serialization. The manual page shows how it is done for the script array add-on. It would probably be very similar for the AATC containers.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

I've been trying to get the serialization working and guess what: as template problems. The serializer doesn't seem to care about template specializations at all.

vector<T> is a template
vector<string> is a template specialization

serializer->AddUserType(new aatc_serializer_usertype_container_vector_template(), "vector");
serializer->AddUserType(new aatc_serializer_usertype_container_vector_tempspec_string(), "vector<string>");

My test script has 1 'vector<string>' global thats supposed to get serialized.

If I compile with both of the above lines, 'aatc_serializer_usertype_container_vector_template' usertype will be used, which is wrong.

If I comment out the first line, I get this error 'Cannot restore type 'vector'' , the serializer refuses to use the 'aatc_serializer_usertype_container_vector_tempspec_string' usertype for 'vector<string>'.

Also, the serializer docs are a little old:


new CSerializedValue(...)

uses 4 parameters in the docs even though a new one has been added in the middle: 'const std::string& namespace'


CSerializedValue->Restore(...)

uses 1 parameter in the docs. A second parameter has been added: 'int refTypeId' , who knows how that is supposed to be used.

Thanks. I'll review and update the manual.

As the user type are registered by name and not declaration, you need to use the same CUserType for both the non-specialized template and the specialized template. The CUserType implementation has to determine if the object is the generic container type or a template specialization by for example checking the subtype, and knowing for which subtypes the container has been specialized.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement