1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "nel/misc/path.h"
19 #include "nel/misc/file.h"
20 #include "nel/misc/common.h"
21 #include "nel/misc/algo.h"
25 using namespace NLMISC
;
28 // ***************************************************************************
29 void buildRaceAnimNames(std::vector
<string
> &raceAnimNames
, const std::string
&animName
)
31 if(animName
.compare(0, 3, "fy_")!=0)
33 nlwarning("ERROR: all .anim must begin with fy_");
37 raceAnimNames
.resize(4);
38 raceAnimNames
[0]= animName
;
39 raceAnimNames
[1]= animName
;
40 raceAnimNames
[2]= animName
;
41 raceAnimNames
[3]= animName
;
42 raceAnimNames
[0].replace(0, 3, "fy_");
43 raceAnimNames
[1].replace(0, 3, "ma_");
44 raceAnimNames
[2].replace(0, 3, "tr_");
45 raceAnimNames
[3].replace(0, 3, "zo_");
48 for(uint i
=0;i
<raceAnimNames
.size();i
++)
50 raceAnimNames
[i
]= string("\"") + raceAnimNames
[i
] + string("\"");
54 // ***************************************************************************
55 string::size_type
findAnimName(const string
&lineLwr
, const std::vector
<string
> &raceAnimNames
)
57 // line Must contains Name="filename", else CAN BE A LOAD CHAR ANIMATION!!!!
58 if(lineLwr
.find("name=\"filename\"")==string::npos
)
61 // in the animset, the original file can be a "tr_" ... Not necessarily a "fy_"
62 for(uint i
=0;i
<raceAnimNames
.size();i
++)
64 string::size_type pos
= lineLwr
.find(raceAnimNames
[i
]);
71 // ***************************************************************************
72 void appendRaceAnim(vector
<string
> &animSetText
, uint startBlock
, const vector
<string
> ©Text
, uint nameLineInBlock
, uint nameIndexInLine
, const string
&raceAnimName
)
75 animSetText
.insert(animSetText
.begin()+startBlock
, copyText
.size(), string());
78 for(uint i
=0;i
<copyText
.size();i
++)
80 string line
= copyText
[i
];
82 // If this is the line we have to change the anim name
83 if(i
==nameLineInBlock
)
84 line
.replace(nameIndexInLine
, raceAnimName
.size(), raceAnimName
);
86 // If this is the line we have to specify the race node
87 if(i
==copyText
.size()-2)
90 if(raceAnimName
.compare(1,3,"fy_")==0)
92 else if(raceAnimName
.compare(1,3,"ma_")==0)
94 else if(raceAnimName
.compare(1,3,"tr_")==0)
96 else if(raceAnimName
.compare(1,3,"zo_")==0)
100 nlwarning("ERROR: generated anim can be only fy_, ma_, zo_, tr_. Ask a coder");
103 line
=toString(" <ATOM Name=\"Race Restriction\" Value=\"%s\"/>", peopleEnum
.c_str());
107 animSetText
[startBlock
+i
]= line
;
111 // ***************************************************************************
112 void makeAnimByRace(const std::string
&animSetFile
, const std::vector
<string
> &animList
)
114 // *** Read the animset file.
116 iFile
.open(animSetFile
, true);
118 static vector
<string
> animSetText
;
123 iFile
.getline(tmp
, 50000);
124 animSetText
.push_back(tmp
);
129 bool someChangeDone
= false;
131 // *** For each possible anim
132 for(uint i
=0;i
<animList
.size();i
++)
134 // get the possible anim file name (lowered)
135 static vector
<string
> raceAnimNames
;
136 raceAnimNames
.clear();
137 buildRaceAnimNames(raceAnimNames
, toLower(CFile::getFilename(animList
[i
])));
139 // For each line of the animSet
140 uint lastStructLine
= 0;
141 bool raceRestrictionFound
= false;
142 for(uint j
=0;j
<animSetText
.size();)
144 string line
= animSetText
[j
];
145 string lineLwr
= toLower(line
);
147 // Find <LOG> TAg? => stop
148 if(line
.find("<LOG>")!=string::npos
)
151 // Find a STRUCT start?
152 if(line
.find("<STRUCT>")!=string::npos
)
155 raceRestrictionFound
= false;
158 // Find a RaceRestriction?
159 if( line
.find("Name=\"Race Restriction\"")!=string::npos
)
160 raceRestrictionFound
= true;
162 // Find the anim name?
163 string::size_type nameIndexInLine
= findAnimName(lineLwr
, raceAnimNames
);
164 if(nameIndexInLine
!=string::npos
)
166 // Find the enclosing struct
167 nlassert(lastStructLine
!=0);
168 uint startBlock
= lastStructLine
;
169 uint nameLineInBlock
= j
-startBlock
;
171 for(uint k
=j
+1;k
<animSetText
.size();k
++)
173 string line
= animSetText
[k
];
175 // Find a RaceRestriction?
176 if( line
.find("Name=\"Race Restriction\"")!=string::npos
)
177 raceRestrictionFound
= true;
180 if(line
.find("</STRUCT>")!=string::npos
)
182 // endBlock is exclusive
188 // if not found, abort
192 // if a raceRestriction has been found, no op (already done)
193 if(raceRestrictionFound
)
200 InfoLog
->displayRawNL("%s: Specifying %s by race",
201 CFile::getFilename(animSetFile
).c_str(),
202 CFile::getFilename(animList
[i
]).c_str());
204 // *** Start a copy paste ^^
206 static vector
<string
> copyText
;
208 for(uint k
=startBlock
;k
<endBlock
;k
++)
210 // add an empty line before </STRUCT>, for race selection node (filled later)
212 copyText
.push_back(string());
213 copyText
.push_back(animSetText
[k
]);
217 animSetText
.erase(animSetText
.begin()+startBlock
, animSetText
.begin()+endBlock
);
218 uint nextBlock
= startBlock
;
220 // Append for each race
221 for(uint k
=0;k
<raceAnimNames
.size();k
++)
223 appendRaceAnim(animSetText
, nextBlock
, copyText
, nameLineInBlock
, (uint
)nameIndexInLine
, raceAnimNames
[k
]);
224 // nextBlock is then shifted
225 nextBlock
+= (uint
)copyText
.size();
228 someChangeDone
= true;
230 // *** then let j point to next block
241 // *** Write the animset file.
245 oFile
.open(animSetFile
, false, true);
247 for(uint i
=0;i
<animSetText
.size();i
++)
249 string str
= animSetText
[i
];
251 oFile
.serialBuffer((uint8
*)str
.c_str(), (uint
)str
.size());
258 // ***************************************************************************
261 printf("Usage: make_anim_by_race new_anim_dir animset_dir");
266 // ***************************************************************************
267 int main(int argc
, char *argv
[])
269 NLMISC::createDebug();
271 // make_anim_by_race new_anim_dir animset_dir
274 string animDir
= argv
[1];
275 string animSetDir
= argv
[2];
277 // Get the list of .anim to make by race
278 vector
<string
> files
;
279 CPath::getPathContent(animDir
, false, false, true, files
);
281 vector
<string
> animList
;
282 InfoLog
->displayRawNL("");
283 InfoLog
->displayRawNL("********************");
284 InfoLog
->displayRawNL("**** .anim list ****");
285 InfoLog
->displayRawNL("********************");
286 for(uint i
=0;i
<files
.size();i
++)
288 if(testWildCard(files
[i
], "*.anim"))
290 animList
.push_back(files
[i
]);
291 InfoLog
->displayRawNL(animList
.back().c_str());
296 // Get the list of .animset to make by race
298 CPath::getPathContent(animSetDir
, true, false, true, files
);
299 vector
<string
> animSetList
;
300 InfoLog
->displayRawNL("");
301 InfoLog
->displayRawNL("*****************************");
302 InfoLog
->displayRawNL("**** .animation_set list ****");
303 InfoLog
->displayRawNL("*****************************");
304 for(uint i
=0;i
<files
.size();i
++)
306 if(testWildCard(files
[i
], "*.animation_set"))
308 animSetList
.push_back(files
[i
]);
309 InfoLog
->displayRawNL(animSetList
.back().c_str());
313 InfoLog
->displayRawNL("");
314 InfoLog
->displayRawNL("**************************");
315 InfoLog
->displayRawNL("**** Starting Process ****");
316 InfoLog
->displayRawNL("**************************");
317 // For each animset, test if can replace some anim
318 for(uint i
=0;i
<animSetList
.size();i
++)
320 makeAnimByRace(animSetList
[i
], animList
);