1 // NeL - MMORPG Framework <https://wiki.ryzom.dev/>
2 // Copyright (C) 2015 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2016 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 // Author: Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
22 #include <nel/misc/types_nl.h>
23 #include "nel/pipeline/project_config.h"
33 #include <nel/misc/debug.h>
34 #include <nel/misc/path.h>
35 #include <nel/misc/config_file.h>
38 using namespace NLMISC
;
40 namespace NLPIPELINE
{
42 TPathString
CProjectConfig::s_AssetConfigPath
;
43 TPathString
CProjectConfig::s_ProjectConfigPath
;
44 std::vector
<NLMISC::CConfigFile
*> CProjectConfig::s_ConfigFiles
;
45 std::vector
<TPathString
> CProjectConfig::s_ConfigPaths
;
46 CProjectConfig
CProjectConfig::s_Instance
;
47 uint32
CProjectConfig::s_AssetConfigModification
;
48 uint32
CProjectConfig::s_ProjectConfigModification
;
49 CProjectConfig::Flags
CProjectConfig::s_InitFlags
= (CProjectConfig::Flags
)0;
50 std::string
CProjectConfig::s_ProjectName
;
52 static std::set
<TPathString
> s_SearchPaths
;
54 void CProjectConfig::cleanup()
56 for (std::vector
<NLMISC::CConfigFile
*>::iterator
it(s_ConfigFiles
.begin()), end(s_ConfigFiles
.end()); it
!= end
; ++it
)
58 s_ConfigFiles
.clear();
61 CProjectConfig::~CProjectConfig()
66 bool CProjectConfig::init(const std::string
&asset
, Flags flags
, bool partial
)
68 TPathString rootPath
= NLMISC::CPath::standardizePath(asset
, false);
69 TPathString configPath
= rootPath
+ "/nel.cfg";
70 while (!CFile::fileExists(configPath
))
72 std::string::size_type sep
= CFile::getLastSeparator(rootPath
);
73 if (sep
== string::npos
)
76 rootPath
= rootPath
.substr(0, sep
);
80 configPath
= rootPath
+ "/nel.cfg";
84 uint32 configFileModification
= CFile::getFileModificationDate(configPath
);
85 bool assetConfigSame
= configPath
== s_AssetConfigPath
&& s_AssetConfigModification
== configFileModification
&& s_InitFlags
== flags
;
87 std::vector
<TPathString
> configRootPaths
;
88 TPathString projectConfigPath
;
89 uint32 projectConfigModification
= 0;
90 std::string projectName
;
93 if (assetConfigSame
&& s_ProjectConfigPath
.empty())
94 return true; // Do not reload
98 if (assetConfigSame
&& !s_ProjectConfigPath
.empty() && CFile::fileExists(s_ProjectConfigPath
))
100 projectConfigModification
= CFile::getFileModificationDate(s_ProjectConfigPath
);
102 if (s_ProjectConfigModification
== projectConfigModification
)
103 return true; // Do not reload
106 // Search for project and load up all root paths
107 std::vector
<std::string
> files
;
108 CPath::getPathContent(CPath::getApplicationDirectory("NeL", true) + "/projects", false, false, true, files
);
109 for (std::vector
<std::string
>::iterator
it(files
.begin()), end(files
.end()); it
!= end
; ++it
)
111 const std::string
& file
= *it
;
112 if (file
.length() >= 4 && (file
.compare(file
.length() - 4, 4, ".cfg") == 0))
116 CConfigFile::CVar
&directories
= project
.getVar("Directories");
117 bool isProject
= false;
118 for (uint i
= 0; i
< directories
.size(); ++i
)
120 if (rootPath
== CPath::standardizePath(directories
.asString(i
), true))
128 projectConfigModification
= CFile::getFileModificationDate(file
);
129 projectConfigPath
= file
;
131 for (uint i
= 0; i
< directories
.size(); ++i
)
133 std::string dir
= CPath::standardizePath(directories
.asString(i
), true);
134 std::string cfgPath
= dir
+ "nel.cfg";
135 if (CFile::fileExists(cfgPath
))
136 configRootPaths
.push_back(dir
);
139 projectName
= project
.getVar("ProjectName").asString();
147 if (projectConfigPath
.empty())
149 projectName
= "NeL Project";
150 configRootPaths
.push_back(rootPath
);
151 projectConfigModification
= 0;
154 nldebug("Initializing project config '%s'", projectConfigPath
.empty() ? configPath
.c_str() : projectConfigPath
.c_str());
158 s_AssetConfigPath
= configPath
;
159 s_AssetConfigModification
= configFileModification
;
160 s_ProjectConfigPath
= projectConfigPath
;
161 s_ProjectConfigModification
= projectConfigModification
;
162 s_ProjectName
= projectName
;
163 s_ConfigPaths
= configRootPaths
;
165 std::map
<std::string
, CConfigFile
*> configFiles
;
166 for (std::vector
<TPathString
>::iterator
it(configRootPaths
.begin()), end(configRootPaths
.end()); it
!= end
; ++it
)
168 const std::string
&dir
= *it
;
169 const std::string
&cfgPath
= *it
+ "nel.cfg";
170 CConfigFile
*cfgFile
= new CConfigFile();
171 cfgFile
->load(cfgPath
);
172 std::string identifier
= cfgFile
->getVar("Identifier").asString();
173 if (configFiles
.find(identifier
) != configFiles
.end()) // Identifier already exists
177 // Replace config that was already added, asset root gets priority
178 std::vector
<NLMISC::CConfigFile
*>::iterator old
= std::find(s_ConfigFiles
.begin(), s_ConfigFiles
.end(), configFiles
[identifier
]);
179 uint idx
= old
- s_ConfigFiles
.begin();
180 s_ConfigFiles
.erase(old
);
181 s_ConfigPaths
.erase(s_ConfigPaths
.begin() + idx
);
185 // Skip, first listed config gets priority
186 s_ConfigPaths
.erase(s_ConfigPaths
.begin() + s_ConfigFiles
.size());
191 SetEnvironmentVariableA(identifier
.c_str(), dir
.c_str());
193 setenv(identifier
.c_str(), dir
.c_str(), 1);
195 configFiles
[identifier
] = cfgFile
;
196 s_ConfigFiles
.push_back(cfgFile
);
199 nlassert(s_ConfigFiles
.size() == s_ConfigPaths
.size());
201 if (flags
& DatabaseTextureSearchPaths
)
203 searchDirectories("DatabaseTextureSearchPaths");
209 void CProjectConfig::searchDirectories(const char *var
)
211 for (uint i
= 0; i
< s_ConfigFiles
.size(); ++i
)
213 CConfigFile
*cfg
= s_ConfigFiles
[i
];
214 const TPathString
&dir
= s_ConfigPaths
[i
];
215 CConfigFile::CVar
*paths
= cfg
->getVarPtr(var
);
218 for (uint i
= 0; i
< paths
->size(); i
++)
220 TPathString path
= paths
->asString(i
);
221 if (!CPath::isAbsolutePath(path
)) path
= dir
+ path
;
222 path
= CPath::standardizePath(path
);
223 if (s_SearchPaths
.find(path
) == s_SearchPaths
.end())
225 CPath::addSearchPath(path
);
226 s_SearchPaths
.insert(path
);
233 void CProjectConfig::release()
235 s_SearchPaths
.clear();
240 } /* namespace NLPIPELINE */