Merge branch 'lua_versions' into main/rendor-staging
[ryzomcore.git] / ryzom / tools / make_anim_by_race / main.cpp
blobccc6fd9978e60aac2efd3ff54101f8c4f7072d3f
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
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/>.
21 #include "nel/misc/path.h"
22 #include "nel/misc/file.h"
23 #include "nel/misc/common.h"
24 #include "nel/misc/algo.h"
27 using namespace std;
28 using namespace NLMISC;
31 // ***************************************************************************
32 void buildRaceAnimNames(std::vector<string> &raceAnimNames, const std::string &animName)
34 if(animName.compare(0, 3, "fy_")!=0)
36 nlwarning("ERROR: all .anim must begin with fy_");
37 exit(-1);
40 raceAnimNames.resize(4);
41 raceAnimNames[0]= animName;
42 raceAnimNames[1]= animName;
43 raceAnimNames[2]= animName;
44 raceAnimNames[3]= animName;
45 raceAnimNames[0].replace(0, 3, "fy_");
46 raceAnimNames[1].replace(0, 3, "ma_");
47 raceAnimNames[2].replace(0, 3, "tr_");
48 raceAnimNames[3].replace(0, 3, "zo_");
50 // Force ""
51 for(uint i=0;i<raceAnimNames.size();i++)
53 raceAnimNames[i]= string("\"") + raceAnimNames[i] + string("\"");
57 // ***************************************************************************
58 string::size_type findAnimName(const string &lineLwr, const std::vector<string> &raceAnimNames)
60 // line Must contains Name="filename", else CAN BE A LOAD CHAR ANIMATION!!!!
61 if(lineLwr.find("name=\"filename\"")==string::npos)
62 return -1;
64 // in the animset, the original file can be a "tr_" ... Not necessarily a "fy_"
65 for(uint i=0;i<raceAnimNames.size();i++)
67 string::size_type pos= lineLwr.find(raceAnimNames[i]);
68 if(pos!=string::npos)
69 return pos;
71 return string::npos;
74 // ***************************************************************************
75 void appendRaceAnim(vector<string> &animSetText, uint startBlock, const vector<string> &copyText, uint nameLineInBlock, uint nameIndexInLine, const string &raceAnimName)
77 // add empty space
78 animSetText.insert(animSetText.begin()+startBlock, copyText.size(), string());
80 // Fill line by line
81 for(uint i=0;i<copyText.size();i++)
83 string line= copyText[i];
85 // If this is the line we have to change the anim name
86 if(i==nameLineInBlock)
87 line.replace(nameIndexInLine, raceAnimName.size(), raceAnimName);
89 // If this is the line we have to specify the race node
90 if(i==copyText.size()-2)
92 string peopleEnum;
93 if(raceAnimName.compare(1,3,"fy_")==0)
94 peopleEnum= "Fyros";
95 else if(raceAnimName.compare(1,3,"ma_")==0)
96 peopleEnum= "Matis";
97 else if(raceAnimName.compare(1,3,"tr_")==0)
98 peopleEnum= "Tryker";
99 else if(raceAnimName.compare(1,3,"zo_")==0)
100 peopleEnum= "Zorai";
101 else
103 nlwarning("ERROR: generated anim can be only fy_, ma_, zo_, tr_. Ask a coder");
104 exit(-1);
106 line=toString(" <ATOM Name=\"Race Restriction\" Value=\"%s\"/>", peopleEnum.c_str());
109 // copy
110 animSetText[startBlock+i]= line;
114 // ***************************************************************************
115 void makeAnimByRace(const std::string &animSetFile, const std::vector<string> &animList)
117 // *** Read the animset file.
118 CIFile iFile;
119 iFile.open(animSetFile, true);
120 // Read all text
121 static vector<string> animSetText;
122 animSetText.clear();
123 while(!iFile.eof())
125 char tmp[50000];
126 iFile.getline(tmp, 50000);
127 animSetText.push_back(tmp);
129 iFile.close();
132 bool someChangeDone= false;
134 // *** For each possible anim
135 for(uint i=0;i<animList.size();i++)
137 // get the possible anim file name (lowered)
138 static vector<string> raceAnimNames;
139 raceAnimNames.clear();
140 buildRaceAnimNames(raceAnimNames, toLowerAscii(CFile::getFilename(animList[i])));
142 // For each line of the animSet
143 uint lastStructLine= 0;
144 bool raceRestrictionFound= false;
145 for(uint j=0;j<animSetText.size();)
147 string line= animSetText[j];
148 string lineLwr= toLowerAscii(line);
150 // Find <LOG> TAg? => stop
151 if(line.find("<LOG>")!=string::npos)
152 break;
154 // Find a STRUCT start?
155 if(line.find("<STRUCT>")!=string::npos)
157 lastStructLine= j;
158 raceRestrictionFound= false;
161 // Find a RaceRestriction?
162 if( line.find("Name=\"Race Restriction\"")!=string::npos )
163 raceRestrictionFound= true;
165 // Find the anim name?
166 string::size_type nameIndexInLine= findAnimName(lineLwr, raceAnimNames);
167 if(nameIndexInLine!=string::npos)
169 // Find the enclosing struct
170 nlassert(lastStructLine!=0);
171 uint startBlock= lastStructLine;
172 uint nameLineInBlock= j-startBlock;
173 uint endBlock= 0;
174 for(uint k=j+1;k<animSetText.size();k++)
176 string line= animSetText[k];
178 // Find a RaceRestriction?
179 if( line.find("Name=\"Race Restriction\"")!=string::npos )
180 raceRestrictionFound= true;
182 // end of block?
183 if(line.find("</STRUCT>")!=string::npos)
185 // endBlock is exclusive
186 endBlock= k+1;
187 break;
191 // if not found, abort
192 if(endBlock==0)
193 break;
195 // if a raceRestriction has been found, no op (already done)
196 if(raceRestrictionFound)
198 j= endBlock;
200 else
202 // LOG
203 InfoLog->displayRawNL("%s: Specifying %s by race",
204 CFile::getFilename(animSetFile).c_str(),
205 CFile::getFilename(animList[i]).c_str());
207 // *** Start a copy paste ^^
208 // Copy
209 static vector<string> copyText;
210 copyText.clear();
211 for(uint k=startBlock;k<endBlock;k++)
213 // add an empty line before </STRUCT>, for race selection node (filled later)
214 if(k==endBlock-1)
215 copyText.push_back(string());
216 copyText.push_back(animSetText[k]);
219 // erase this part
220 animSetText.erase(animSetText.begin()+startBlock, animSetText.begin()+endBlock);
221 uint nextBlock= startBlock;
223 // Append for each race
224 for(uint k=0;k<raceAnimNames.size();k++)
226 appendRaceAnim(animSetText, nextBlock, copyText, nameLineInBlock, (uint)nameIndexInLine, raceAnimNames[k]);
227 // nextBlock is then shifted
228 nextBlock+= (uint)copyText.size();
231 someChangeDone= true;
233 // *** then let j point to next block
234 j= nextBlock;
237 else
239 j++;
244 // *** Write the animset file.
245 if(someChangeDone)
247 COFile oFile;
248 oFile.open(animSetFile, false, true);
249 // Write all text
250 for(uint i=0;i<animSetText.size();i++)
252 string str= animSetText[i];
253 str+= "\n";
254 oFile.serialBuffer((uint8*)str.c_str(), (uint)str.size());
261 // ***************************************************************************
262 int usage()
264 printf("Usage: make_anim_by_race new_anim_dir animset_dir");
265 return -1;
269 // ***************************************************************************
270 int main(int argc, char *argv[])
272 NLMISC::createDebug();
274 // make_anim_by_race new_anim_dir animset_dir
275 if(argc!=3)
276 return usage();
277 string animDir= argv[1];
278 string animSetDir= argv[2];
280 // Get the list of .anim to make by race
281 vector<string> files;
282 CPath::getPathContent(animDir, false, false, true, files);
283 // Filter .anim
284 vector<string> animList;
285 InfoLog->displayRawNL("");
286 InfoLog->displayRawNL("********************");
287 InfoLog->displayRawNL("**** .anim list ****");
288 InfoLog->displayRawNL("********************");
289 for(uint i=0;i<files.size();i++)
291 if(testWildCard(files[i], "*.anim"))
293 animList.push_back(files[i]);
294 InfoLog->displayRawNL(animList.back().c_str());
299 // Get the list of .animset to make by race
300 files.clear();
301 CPath::getPathContent(animSetDir, true, false, true, files);
302 vector<string> animSetList;
303 InfoLog->displayRawNL("");
304 InfoLog->displayRawNL("*****************************");
305 InfoLog->displayRawNL("**** .animation_set list ****");
306 InfoLog->displayRawNL("*****************************");
307 for(uint i=0;i<files.size();i++)
309 if(testWildCard(files[i], "*.animation_set"))
311 animSetList.push_back(files[i]);
312 InfoLog->displayRawNL(animSetList.back().c_str());
316 InfoLog->displayRawNL("");
317 InfoLog->displayRawNL("**************************");
318 InfoLog->displayRawNL("**** Starting Process ****");
319 InfoLog->displayRawNL("**************************");
320 // For each animset, test if can replace some anim
321 for(uint i=0;i<animSetList.size();i++)
323 makeAnimByRace(animSetList[i], animList);
326 return 0;