#ifndef ASLSP_NATIVE_TYPEDEFRESULT_HPP #define ASLSP_NATIVE_TYPEDEFRESULT_HPP #include #include #include #include #include #include namespace ASTypeDefParser { class TypeDefResult { struct Type { Type(std::string objectType, std::string classDef, std::string className, int flags, std::vector definitions, std::vector> behaviours) : ClassDef(std::move(classDef)), ClassName(std::move(className)), Definitions(std::move(definitions)), Flags(flags), ObjectType(std::move(objectType)), Behaviours(behaviours) {} std::string ObjectType; std::string ClassDef; std::string ClassName; long Flags; std::vector Definitions; std::vector> Behaviours; }; struct Enum { Enum(std::string name, std::vector> values) : Name(std::move(name)), Values(std::move(values)) {} std::string Name; std::vector> Values; }; std::vector _types; std::vector _enums; std::vector _functions; public: void StoreType(const std::string& objType, const std::string& classDef, const std::string& className, long flags, const std::vector& definitions, const std::vector>& behaviours) { _types.emplace_back(objType, classDef, className, flags, definitions, behaviours); } void StoreEnum(const std::string& name, const std::vector>& values) { _enums.emplace_back(name, values); } void StoreFunc(const std::string& function) { _functions.push_back(function); } void Clear() { _types.clear(); _enums.clear(); _functions.clear(); } void RegisterTypes(asIScriptEngine* engine) { for (auto& t : _types) { try { auto size = 0; if (t.ObjectType == "valuetype") { size = 1; } engine->RegisterObjectType(t.ClassDef.c_str(), size, t.Flags); } catch (std::exception&) { } } for (auto& t : _enums) { try { engine->RegisterEnum(t.Name.c_str()); } catch (std::exception&) { } } } private: // As opposed to normal functions, behaviours can be called from the builder. If we pass a default value, // this causes a segfault. As such, we have an empty function for them. static void BehaviourPlaceHolder(void*){} static void RegisterTypeImplementation(asIScriptEngine* engine, Type& t) { for (auto& def : t.Definitions) { auto i = engine->RegisterObjectMethod(t.ClassName.c_str(), def.c_str(), {}, asCALL_THISCALL); if (i < 0) { return; } } for (auto& def : t.Behaviours) { auto call = asCALL_CDECL; if (std::get<0>(def) == 0 || std::get<0>(def) == 2) { call = asCALL_CDECL_OBJLAST; } auto i = engine->RegisterObjectBehaviour(t.ClassName.c_str(), static_cast(std::get<0>(def)), std::get<1>(def).c_str(), asFUNCTION(BehaviourPlaceHolder), call); if (i < 0) { return; } } } public: void RegisterImplementation(asIScriptEngine* engine) { for (auto& t : _types) { if ((t.Flags & asOBJ_TEMPLATE) == 0) { continue; } RegisterTypeImplementation(engine, t); } for (auto& t : _types) { if ((t.Flags & asOBJ_TEMPLATE) != 0) { continue; } RegisterTypeImplementation(engine, t); } for (auto& t : _enums) { for (auto& v : t.Values) { engine->RegisterEnumValue(t.Name.c_str(), std::get<0>(v).c_str(), std::get<1>(v)); } } for (auto& f : _functions) { if (engine->GetGlobalFunctionByDecl(f.c_str()) != nullptr) { continue; } engine->RegisterGlobalFunction(f.c_str(), {}, asCALL_CDECL); } } }; } #endif // ASLSP_NATIVE_TYPEDEFRESULT_HPP