/** * @brief * Loads a resource which type has to be evaluated internally */ bool Application::LoadResource(const String &sFilename, const String &sType) { bool bResult = false; // Error by default // Clear the scene, after calling this method the scene is empty ClearScene(); // Destroy the currently used script DestroyScript(); // Backup the filename of the current resource m_sResourceFilename = sFilename; // Is there anything to load in? if (sFilename.GetLength()) { { // Make the directory of the scene to load in to the current directory // Ok, the next thing is tricky, and every solution will end up in being a hack due to lack of information. // Within materials, meshes etc. there are usually relative paths provided, no absolute (not just true for PixelLight file formats). // Further, those paths are usually relative to a project root resulting e.g. within a default directory layout like // - Root // - Data // - Meshes // - Materials // For "normal" projects this is no issue because everything is usually relative to the root project directory... // ... but this viewer must be able to pick out e.g. a mesh out of nowhere and must still be able to locate the required // other resources like materials. So, in here, we can only work with heuristics... this can and will of course go from // time to time horribly wrong... // First try: Find the first "Data" occurrence with the given filename and hope that it's the project root directory // Get filename as clean URL Url cUrl = Url(sFilename); cUrl.Collapse(); // Get the first part of the path, and then look for "Data" uint32 nPathPos = 0; String sPart = cUrl.GetFirstPath(nPathPos); while (sPart != "Data" && sPart.GetLength()) sPart = cUrl.GetNextPath(nPathPos); if (sPart == "Data") { // Set the base directory of the application SetBaseDirectory(cUrl.GetRoot() + cUrl.GetPath().GetSubstring(0, nPathPos - 5)); // -5 = Remove "Data/" } else { // Second try: Cut of "/Data/Scenes/" and hope that it's the project root directory. // If it's not there, take the directory the given resource is in. // Validate path const String sDirectory = cUrl.CutFilename(); // Search for "/Data/Scenes/" and get the prefix of that, in case it's not there just use directly the scene directory const int nIndex = sDirectory.IndexOf("/Data/Scenes/"); // Set the base directory of the application SetBaseDirectory("file://" + ((nIndex >= 0) ? sDirectory.GetSubstring(0, nIndex) : sDirectory) + '/'); } }
Url Url::ResolveReference(const Url& ref) const { if (ref.IsAbsolute()) return ref; Url url; url.SetScheme(m_strScheme); url.SetUser(m_strUserName); url.SetPassword(m_strPassword); url.SetHost(m_strHost); url.SetPort(m_iPort); url.SetRawQuery(ref.GetRawQuery()); url.SetFragment(ref.GetFragment()); auto pathDirList = base::strings::Split(m_strPath, "/"); auto relDirList = base::strings::Split(ref.GetPath(), "/"); std::stack<std::string> pathDirStack; for (auto v : pathDirList) { if (v.empty()) continue; pathDirStack.push(v); } for (auto v : relDirList) { if (v.empty() || "." == v) continue; if (".." == v) { if (!pathDirStack.empty()) pathDirStack.pop(); } else pathDirStack.push(v); } if (pathDirStack.empty()) url.SetPath("/"); else { std::string strPath; while (!pathDirStack.empty()) { strPath = pathDirStack.top() + "/" + strPath; pathDirStack.pop(); } url.SetPath("/" + strPath); } return url; }