void GD_EXTENSION_API SetAttributeString(const gd::String &refname, const gd::String &property, const gd::String &value, RuntimeScene &scene) { TiXmlNode *refNode = RefManager::Get(&scene)->GetRef(refname); if(refNode) { TiXmlElement *refEle = refNode->ToElement(); if(refEle) { refEle->SetAttribute(property.c_str(), value.c_str()); } } }
void GD_EXTENSION_API SetText(const gd::String &refName, const gd::String &text, RuntimeScene &scene) { TiXmlNode *refNode = RefManager::Get(&scene)->GetRef(refName); if(refNode) { refNode->SetValue(text.c_str()); } }
void GD_API WriteStringInFile( const gd::String & filename, const gd::String & group, const gd::String & str ) { std::shared_ptr<XmlFile> file = XmlFilesManager::GetFile(filename); TiXmlHandle hdl( &file->GetTinyXmlDocument() ); //D�coupage des groupes istringstream groupsStr( group.Raw() ); std::string gstr; vector < gd::String > groups; while ( std::getline( groupsStr, gstr, '/' ) ) { groups.push_back(gd::String::FromUTF8(gstr)); } groups.erase(std::remove_if(groups.begin(), groups.end(), StringEmpty()), groups.end()); if ( groups.empty() ) return; //Insertion de la d�claration TiXmlDeclaration decl( "1.0", "ISO-8859-1", "" ); if ( hdl.FirstChildElement().Element() != NULL ) { //Il y a d�j� un noeud, on v�rifie que c'est pas une d�claration if ( hdl.FirstChild().ToNode()->ToDeclaration() == NULL ) file->GetTinyXmlDocument().InsertBeforeChild(hdl.FirstChildElement().Element(), decl); } else file->GetTinyXmlDocument().InsertEndChild(decl); //Il n'y a rien, on peut ins�rer notre d�claration //Cr�ation si besoin est de la racine if ( hdl.FirstChildElement(groups.at(0).c_str()).Element() == NULL ) { TiXmlElement root(groups.at(0).c_str()); file->GetTinyXmlDocument().InsertEndChild(root); } //A chaque fois, on v�rifie si le groupe voulu existe, si non on le cr��, //et on se d�place dedans. for (std::size_t i =0;i<groups.size();i++) { if ( hdl.FirstChildElement(groups.at(i).c_str()).Element() == NULL ) { TiXmlElement le_nouveau (groups.at(i).c_str()); hdl.Element()->InsertEndChild(le_nouveau); } hdl = hdl.FirstChildElement(groups.at(i).c_str()); } //Ecriture dans le groupe if ( hdl.Element() != NULL ) hdl.Element()->SetAttribute("texte", str.c_str()); return; }
void ExtensionsLoader::ExtensionsLoadingDone(const gd::String & directory) { gd::String suffix = ""; #if defined(WINDOWS) suffix += "w"; #endif #if defined(GD_IDE_ONLY) suffix += "e"; #endif #if defined(LINUX) || defined (MACOS) //List all extensions loaded struct dirent *lecture; DIR *rep; rep = opendir( directory.c_str() ); int l = 0; if ( rep == NULL ) { cout << "Unable to open Extensions ("<< directory <<") directory." << endl; return; } std::vector<gd::String> librariesLoaded; while ( (lecture = readdir( rep )) ) { gd::String lec = lecture->d_name; if ( lec != "." && lec != ".." && lec.find(".xgd"+suffix, lec.length()-4-suffix.length()) != string::npos) { librariesLoaded.push_back(directory+"/"+lec); l++; } } closedir( rep ); //Libraries are loaded using dlopen(.., RTLD_LAZY|RTLD_LOCAL) meaning that their symbols are not available for other libraries //nor for LLVM/Clang. We then reload set them as global to make their symbols available for LLVM/Clang. We couldn't mark them //as global when loading them as every extension use the same "CreateGDExtension" symbol. //SetLibraryGlobal is also setting RTLD_NOW to ensure that all symbols are resolved: Otherwise, we can get weird //"symbol lookup error" even if the symbols exist in the extensions! for (std::size_t i = 0;i<librariesLoaded.size();++i) SetLibraryGlobal(librariesLoaded[i].c_str()); #else //Nothing to do on Windows. #endif }
gd::String GD_EXTENSION_API GetAttributeString(const gd::String &refname, const gd::String &property, RuntimeScene &scene) { TiXmlNode *refNode = RefManager::Get(&scene)->GetRef(refname); if(refNode) { TiXmlElement *refEle = refNode->ToElement(); if(refEle) { gd::String attributeStr = refEle->Attribute(property.c_str()); return attributeStr; } else { return ""; } } else { return ""; } }
double GD_EXTENSION_API GetAttributeNumber(const gd::String &refname, const gd::String &property, RuntimeScene &scene) { TiXmlNode *refNode = RefManager::Get(&scene)->GetRef(refname); if(refNode) { TiXmlElement *refEle = refNode->ToElement(); if(refEle) { double attributeDouble = 0; refEle->QueryDoubleAttribute(property.c_str(), &attributeDouble); return attributeDouble; } else { return 0; } } else { return 0; } }
void ExtensionsLoader::LoadAllExtensions(const gd::String & directory, gd::Platform & platform, bool forgiving) { std::cout << "Loading extensions for " << platform.GetName() << "... "; gd::String suffix = ""; #if defined(WINDOWS) suffix += "w"; #endif #if defined(GD_IDE_ONLY) suffix += "e"; #endif #if defined(__GNUC__) //For compilers with posix support struct dirent *lecture; DIR *rep; rep = opendir( directory.c_str() ); int l = 0; if ( rep == NULL ) { cout << "Unable to open Extensions ("<< directory <<") directory." << endl; return; } std::vector<gd::String> librariesLoaded; while ( (lecture = readdir( rep )) ) { gd::String lec = lecture->d_name; //Load all extensions, except the legacy ones finishing by *Automatism.xgd* from GD3.x if ( lec != "." && lec != ".." && lec.find(".xgd"+suffix, lec.length()-4-suffix.length()) != string::npos && lec.find("Automatism.xgd"+suffix) == string::npos) { //Use a log file, in IDE only #if defined(GD_IDE_ONLY) && !defined(GD_NO_WX_GUI) { wxFile errorDetectFile(wxFileName::GetTempDir()+"/ExtensionBeingLoaded.log", wxFile::write); errorDetectFile.Write(directory+"/"+lec); } #endif LoadExtension(directory+"/"+lec, platform, forgiving); //Everything is ok : Delete the log file #if defined(GD_IDE_ONLY) && !defined(GD_NO_WX_GUI) wxRemoveFile(wxFileName::GetTempDir()+"/ExtensionBeingLoaded.log"); #endif librariesLoaded.push_back(directory+"/"+lec); l++; } } closedir( rep ); #elif defined(_MSC_VER) WIN32_FIND_DATA f; gd::String dirPart = "/*.xgd"; gd::String dirComplete = directory + dirPart + suffix; HANDLE h = FindFirstFile(dirComplete.c_str(), &f); if(h != INVALID_HANDLE_VALUE) { do { //Use a log file, in IDE only #if defined(GD_IDE_ONLY) && !defined(GD_NO_WX_GUI) { wxFile errorDetectFile(wxFileName::GetTempDir()+"/ExtensionBeingLoaded.log", wxFile::write); errorDetectFile.Write(f.cFileName); } #endif LoadExtension(f.cFileName, platform, forgiving); //Everything is ok : Delete the log file #if defined(GD_IDE_ONLY) && !defined(GD_NO_WX_GUI) wxRemoveFile(wxFileName::GetTempDir()+"/ExtensionBeingLoaded.log"); #endif } while(FindNextFile(h, &f)); } #else #warning Compiler not supported (but might support one style of directory listing, update defines if necessary) for dynamic libraries loading #endif std::cout << " done. " << std::endl; }
void ExtensionsLoader::LoadExtension(const gd::String & fullpath, gd::Platform & platform, bool forgiving) { if ( platform.GetExtensionCreateFunctionName().empty() ) { cout << "Unable to load extension " << fullpath << ":" << endl; cout << "The plaftorm does not support extensions creation." << endl; return; } Handle extensionHdl = OpenLibrary(fullpath.c_str()); if (extensionHdl == NULL) { gd::String error = DynamicLibraryLastError(); cout << "Unable to load extension " << fullpath << "." << endl; cout << "Error returned : \"" << error << "\"" << endl; #if defined(GD_IDE_ONLY) && !defined(GD_NO_WX_GUI) wxString userMsg = _("Extension ")+ fullpath + _(" could not be loaded.\nContact the developer for more informations.\n\nDetailed log:\n") + error; wxMessageBox(userMsg, _("Extension not compatible"), wxOK | wxICON_EXCLAMATION); #endif return; } createExtension create_extension = (createExtension)GetSymbol(extensionHdl, platform.GetExtensionCreateFunctionName().c_str()); if (create_extension == NULL) { if (!forgiving) { cout << "Unable to load extension " << fullpath << " (Creation function symbol not found)." << endl; #if defined(GD_IDE_ONLY) && !defined(GD_NO_WX_GUI) wxString userMsg = _("Extension ")+ fullpath + _(" could not be loaded.\nContact the developer for more informations." ); wxMessageBox(userMsg, _("Extension not compatible"), wxOK | wxICON_EXCLAMATION); #endif } CloseLibrary(extensionHdl); return; } #if defined(GD_IDE_ONLY) && !defined(GD_NO_WX_GUI) gd::LocaleManager::Get()->AddCatalog(wxFileName(fullpath).GetName()); //In editor, load catalog associated with extension, if any. #endif gd::PlatformExtension * extensionPtr = create_extension(); gd::String error; //Perform safety check about the compilation if ( !extensionPtr->compilationInfo.informationCompleted ) error += "Compilation information not filled.\n"; #if defined(GD_IDE_ONLY) else if ( extensionPtr->compilationInfo.runtimeOnly ) error += "Extension compiled for runtime only.\n"; #if !defined(GD_NO_WX_GUI) else if ( extensionPtr->compilationInfo.wxWidgetsMajorVersion != wxMAJOR_VERSION || extensionPtr->compilationInfo.wxWidgetsMinorVersion != wxMINOR_VERSION || extensionPtr->compilationInfo.wxWidgetsReleaseNumber != wxRELEASE_NUMBER || extensionPtr->compilationInfo.wxWidgetsSubReleaseNumber != wxSUBRELEASE_NUMBER ) error += "Not the same wxWidgets version.\n"; #endif #endif #if defined(__GNUC__) else if ( extensionPtr->compilationInfo.gccMajorVersion != __GNUC__ || extensionPtr->compilationInfo.gccMinorVersion != __GNUC_MINOR__ ) error += "Not the same GNU Compiler version.\n"; #endif else if ( extensionPtr->compilationInfo.sfmlMajorVersion != 2 || extensionPtr->compilationInfo.sfmlMinorVersion != 0 ) error += "Not the same SFML version.\n"; else if ( extensionPtr->compilationInfo.gdCoreVersion != GDCore_RC_FILEVERSION_STRING) error += "Not the same GDevelop Core version.\n(Extension is using "+extensionPtr->compilationInfo.gdCoreVersion+", GDevelop is using "+GDCore_RC_FILEVERSION_STRING+")\n"; else if ( extensionPtr->compilationInfo.sizeOfpInt != sizeof(int*)) error += "Not the same architecture.\n(Extension sizeof(int*) is "+gd::String::From(extensionPtr->compilationInfo.sizeOfpInt)+", GDevelop sizeof(int*) is "+gd::String::From(sizeof(int*))+")\n"; if ( !error.empty() ) { char beep = 7; cout << "-- WARNING ! --" << beep << endl; cout << "Bad extension " + fullpath + " loaded :\n" + error; cout << "---------------" << endl; #if defined(RELEASE)//Load extension despite errors in non release build //Destroy the extension class THEN unload the library from memory delete extensionPtr; CloseLibrary(extensionHdl); #endif #if defined(GD_IDE_ONLY) && !defined(GD_NO_WX_GUI) && defined(RELEASE) //Show errors in IDE only wxString userMsg = _("Extension ") + fullpath + _(" has errors :\n") + error + _("\nThe extension was not loaded. Contact the developer to get more information." ); wxMessageBox(userMsg, _("Extension not compatible"), wxOK | wxICON_EXCLAMATION); #endif #if defined(RELEASE)//Load extension despite errors in non release build return; #endif } std::shared_ptr<gd::PlatformExtension> extension(extensionPtr); platform.AddExtension(extension); return; }
void GD_EXTENSION_API NextSibling(const gd::String &futureRefName, const gd::String &baseRefName, const gd::String &tagName, RuntimeScene &scene) { if(!RefManager::Get(&scene)->GetRef(baseRefName)) return; RefManager::Get(&scene)->SetRef(futureRefName, tagName == "" ? RefManager::Get(&scene)->GetRef(baseRefName)->NextSibling() : RefManager::Get(&scene)->GetRef(baseRefName)->NextSibling(tagName.c_str())); }