#include "ScriptHeadersExporter.hpp" #include #include static bool replace(std::string& str, const std::string& from, const std::string& to) { size_t start_pos = str.find(from); if (start_pos == std::string::npos) return false; str.replace(start_pos, from.length(), to); return true; } static void PrintObjectTypeDef(asITypeInfo* type, const std::filesystem::path& dir) { auto name = std::string(type->GetName()); if (name == "string" || name == "array") return; std::fstream fs; fs.open((dir / name).concat(".astypedef"), std::fstream::out); if ((type->GetFlags() & asOBJ_VALUE) != 0 && (type->GetFlags() & asOBJ_ASHANDLE) == 0) { fs << "valuetype"; } else { fs << "type"; } fs << " " << type->GetName(); if ((type->GetFlags() & asOBJ_TEMPLATE) != 0) { fs << "<"; for (asUINT i = 0; i < type->GetSubTypeCount(); ++i) { if (i != 0) { fs << ", "; } fs << type->GetSubType(i)->GetName(); } fs << ">"; } fs << " {" << std::endl; auto behaviourCount = type->GetBehaviourCount(); for (asUINT j = 0; j < behaviourCount; j++) { if (name == "ref") break; if (name == "dictionaryValue") break; asEBehaviours behaviourType; auto behaviour = type->GetBehaviourByIndex(j, &behaviourType); if (behaviourType > 4) { continue; } auto decl = std::string(behaviour->GetDeclaration(false, false, true)); if (behaviourType == asBEHAVE_CONSTRUCT || behaviourType == asBEHAVE_FACTORY) { replace(decl, type->GetName(), "void f"); } if (behaviourType == asBEHAVE_DESTRUCT) { replace(decl, std::string("~") + type->GetName(), "void f"); } if (behaviourType == asBEHAVE_LIST_CONSTRUCT || behaviourType == asBEHAVE_LIST_FACTORY) { replace(decl, "$list", "f"); } fs << " behave " << behaviourType << " " << decl << ";" << std::endl; } auto propertyCount = type->GetMethodCount(); for (asUINT j = 0; j < propertyCount; j++) { auto method = type->GetMethodByIndex(j); if (method->IsProperty()) { auto name = std::string(method->GetName()); auto decl = std::string(method->GetDeclaration(false, true, false)); auto realName = name.substr(4); replace(decl, name, realName); replace(decl, "() const", " { get const; }"); replace(decl, "()", " { get; }"); fs << " " << decl << ";" << std::endl; } else { auto name = std::string(method->GetName()); auto decl = std::string(method->GetDeclaration(false, true, true)); replace(decl, "&in", " &in"); replace(decl, "&out", " &out"); replace(decl, "ref", "ref@"); fs << " " << decl << ";" << std::endl; } } fs << "}" << std::endl; fs.close(); } static void PrintScriptObject(asITypeInfo* type, const std::filesystem::path& dir) { auto name = std::string(type->GetName()); if (name == "string" || name == "array" || name == "ref") return; std::fstream fs; fs.open((dir / name).concat(".as"), std::fstream::out); auto isAbstract = (type->GetFlags() & asEObjTypeFlags::asOBJ_ABSTRACT) != 0; fs << "shared "; if (isAbstract) fs << "abstract class "; else fs << "interface "; fs << type->GetName() << " {" << std::endl; auto propertyCount = type->GetMethodCount(); for (asUINT j = 0; j < propertyCount; j++) { auto method = type->GetMethodByIndex(j); if (method->IsProperty()) { auto name = std::string(method->GetName()); auto decl = std::string(method->GetDeclaration(false, true, false)); auto realName = name.substr(4); replace(decl, name, realName); replace(decl, "() const", " { get const; }"); replace(decl, "()", " { get; }"); fs << "\t" << decl << std::endl; } else { auto name = std::string(method->GetName()); if (name == "opAssign") continue; if (name == "GetOwner") { fs << "\tref@ __owner;" << std::endl << std::endl; } auto decl = std::string(method->GetDeclaration(false, true, true)); replace(decl, "&in", " &in"); replace(decl, "&out", " &out"); replace(decl, "ref", "ref@"); fs << "\t" << decl; if (isAbstract) { if (method->GetReturnTypeId() == 0) { fs << "{};" << std::endl; } else { if (name == "GetOwner") { fs << "{ return __owner; };" << std::endl; } else if (method->GetReturnTypeId() == asTYPEID_BOOL) { fs << "{ return false; };" << std::endl; } else { fs << "{ return 0; };" << std::endl; } } } else fs << ";" << std::endl; } } fs << "}" << std::endl; fs.close(); } void ScriptHeadersExporter::Export(const std::string& outPath) { auto resolver = new AngelScriptResolver(); resolver->Initialize(nullptr); resolver->FinalizeModule(); auto module = resolver->GetMainModule(); auto engine = module->GetEngine(); auto typesCount = engine->GetObjectTypeCount(); std::filesystem::path dir(outPath); for (asUINT i = 0; i < typesCount; i++) { auto type = engine->GetObjectTypeByIndex(i); if ((type->GetTypeId() & asTYPEID_SCRIPTOBJECT) != 0) { PrintScriptObject(type, dir); } else { PrintObjectTypeDef(type, dir); } } auto moduleTypesCount = module->GetObjectTypeCount(); for (asUINT i = 0; i < moduleTypesCount; i++) { auto type = module->GetObjectTypeByIndex(i); if ((type->GetTypeId() & asTYPEID_SCRIPTOBJECT) != 0) { PrintScriptObject(type, dir); } else { PrintObjectTypeDef(type, dir); } } auto enumCount = engine->GetEnumCount(); for (asUINT i = 0; i < enumCount; i++) { auto en = engine->GetEnumByIndex(i); auto name = en->GetName(); std::fstream fs; fs.open((dir / name).concat(".astypedef"), std::fstream::out); fs << "enum " << en->GetName() << " {" << std::endl; auto valueCount = en->GetEnumValueCount(); for (asUINT j = 0; j < valueCount; j++) { int val; auto name = en->GetEnumValueByIndex(j, &val); fs << "\t" << name << " = " << val << "," << std::endl; } fs << "}" << std::endl; fs.close(); } auto globalFuncs = engine->GetGlobalFunctionCount(); if (globalFuncs > 0) { std::fstream fs; fs.open((dir / "globals").concat(".astypedef"), std::fstream::out); for (asUINT i = 0; i < globalFuncs; ++i) { auto func = engine->GetGlobalFunctionByIndex(i); fs << "func " << func->GetDeclaration(false, false, true) << ";" << std::endl; } } }