189 | function PlayerStyle:loadConfigurationXML(xmlFilename) |
190 | local xmlFile = XMLFile.load("player", xmlFilename) |
191 | if xmlFile == nil then |
192 | Logging.error("Player config does not exist at %s. Loading default instead", xmlFilename) |
193 | |
194 | xmlFilename = "dataS/character/humans/player/player01.xml" |
195 | xmlFile = XMLFile.load("player", xmlFilename) |
196 | if xmlFile == nil then |
197 | Logging.fatal("Default player config does not exist at %s", xmlFilename) |
198 | end |
199 | end |
200 | |
201 | -- Used for moving from 1 config to another |
202 | local restoreSelection = nil |
203 | |
204 | self.xmlFilename = xmlFilename |
205 | local rootKey = "player.character.playerStyle" |
206 | |
207 | self.filename = xmlFile:getString("player.filename") |
208 | self.atlasFilename = xmlFile:getString("player.character.playerStyle#atlas") |
209 | |
210 | self.skeletonRootIndex = xmlFile:getInt("player.character.thirdPerson#skeleton") or 0 |
211 | |
212 | -- Attach points |
213 | self.attachPoints = {} |
214 | xmlFile:iterate(rootKey .. ".attachPoints.attachPoint", function(_, key) |
215 | local name = xmlFile:getString(key .. "#name") |
216 | local node = self:parseIndex(xmlFile:getString(key .. "#node")) |
217 | self.attachPoints[name] = node |
218 | end) |
219 | |
220 | -- Faces |
221 | if self.faceConfig.selection ~= 0 and self.faceConfig.items[self.faceConfig.selection] ~= nil then |
222 | restoreSelection = self.faceConfig.items[self.faceConfig.selection].name |
223 | end |
224 | self.faceConfig.items = {} |
225 | self.facesByName = {} |
226 | xmlFile:iterate(rootKey .. ".faces.face", function(_, key) |
227 | local index = xmlFile:getString(key .. "#node") |
228 | local name = xmlFile:getString(key .. "#name") |
229 | local skinColor = string.getVectorN(xmlFile:getString(key .. "#skinColor"), 3) |
230 | local uvSlot = xmlFile:getInt(key .. "#uvSlot") |
231 | local filename = xmlFile:getString(key .. "#filename") |
232 | |
233 | local attachPoint = xmlFile:getString(key .. "#attachPoint") or "" |
234 | local attachNode = self.attachPoints[attachPoint] |
235 | if attachNode == nil then |
236 | Logging.xmlError(xmlFile, "Attach point with name '%s' does not exist for %s", attachPoint, name) |
237 | return |
238 | end |
239 | |
240 | table.insert(self.faceConfig.items, { |
241 | index = index, |
242 | name = name, |
243 | skinColor = skinColor, |
244 | uvSlot = uvSlot, |
245 | numColors = 0, |
246 | filename = filename, |
247 | attachNode = attachNode, |
248 | }) |
249 | |
250 | if self.facesByName[name] ~= nil then |
251 | Logging.devError("Wardrobe face name '%s' already used", name) |
252 | end |
253 | |
254 | self.facesByName[name] = #self.faceConfig.items |
255 | |
256 | if name == restoreSelection then |
257 | self.faceConfig.selection = #self.faceConfig.items |
258 | end |
259 | end) |
260 | |
261 | self.faceNeutralDiffuseColor = string.getVectorN(xmlFile:getString(rootKey .. ".faces#neutralDiffuse"), 3) |
262 | |
263 | -- Nude body parts |
264 | self.bodyParts = {} |
265 | self.bodyPartIndexByName = {} |
266 | xmlFile:iterate(rootKey .. ".bodyParts.bodyPart", function(_, key) |
267 | local index = self:parseIndex(xmlFile:getString(key .. "#node")) |
268 | local name = xmlFile:getString(key .. "#name") |
269 | |
270 | table.insert(self.bodyParts, {index = index, name = name}) |
271 | |
272 | if self.bodyPartIndexByName[name] ~= nil then |
273 | Logging.devError("Wardrobe body part name '%s' already used", name) |
274 | end |
275 | self.bodyPartIndexByName[name] = #self.bodyParts |
276 | end) |
277 | |
278 | self:loadColors(xmlFile, rootKey .. ".colors.hair.color", "hairColors") |
279 | self:loadColors(xmlFile, rootKey .. ".colors.clothing.color", "defaultClothingColors") |
280 | |
281 | local topsByName = self:loadClothing(xmlFile, rootKey .. ".tops", "top", "topConfig", true) |
282 | local bottomsByName = self:loadClothing(xmlFile, rootKey .. ".bottoms", "bottom", "bottomConfig", true) |
283 | local footwearByName = self:loadClothing(xmlFile, rootKey .. ".footwear", "footwear", "footwearConfig", true) |
284 | local glovesByName = self:loadClothing(xmlFile, rootKey .. ".gloves", "glove", "glovesConfig", true) |
285 | local glassesByName = self:loadClothing(xmlFile, rootKey .. ".glasses", "glasses", "glassesConfig") |
286 | local onepiecesByName = self:loadClothing(xmlFile, rootKey .. ".onepieces", "onepiece", "onepieceConfig", true) |
287 | local facegearByName = self:loadClothing(xmlFile, rootKey .. ".facegear", "facegear", "facegearConfig", true, false, true) |
288 | local headgearByName = self:loadClothing(xmlFile, rootKey .. ".headgear", "headgear", "headgearConfig", true, false, false, true) |
289 | self:loadClothing(xmlFile, rootKey .. ".hairStyles", "hairStyle", "hairStyleConfig", true, true, nil, nil, true) |
290 | self:loadClothing(xmlFile, rootKey .. ".beards", "beard", "beardConfig", true, true, true) |
291 | self:loadClothing(xmlFile, rootKey .. ".mustaches", "mustache", "mustacheConfig", true, true, true) |
292 | |
293 | -- Presets |
294 | self.presets = {} |
295 | local presetByName = {} |
296 | xmlFile:iterate(rootKey .. ".presets.preset", function(index, key) |
297 | local text = xmlFile:getString(key .. "#text") |
298 | local name = xmlFile:getString(key .. "#name") |
299 | local brand |
300 | local brandName = xmlFile:getString(key .. "#brand") |
301 | if brandName ~= nil then |
302 | if g_brandManager ~= nil then |
303 | brand = g_brandManager:getBrandByName(brandName) |
304 | if brand ~= nil then |
305 | brandName = nil |
306 | end |
307 | end |
308 | end |
309 | |
310 | if presetByName[name] ~= nil then |
311 | Logging.devError("Wardrobe preset name '%s' already used", name) |
312 | end |
313 | |
314 | local preset = { |
315 | name = name, |
316 | text = text, |
317 | uvSlot = xmlFile:getInt(key .. "#uvSlot"), |
318 | brand = brand, |
319 | brandName = brandName, |
320 | extraContentId = xmlFile:getString(key .. "#extraContentId"), |
321 | isSelectable = xmlFile:getBool(key .. "#isSelectable", true) |
322 | } |
323 | presetByName[name] = preset |
324 | |
325 | local function getOrNul(list, itemKey) |
326 | if itemKey == nil then |
327 | return nil |
328 | end |
329 | if list[itemKey] ~= nil then |
330 | return list[itemKey] |
331 | end |
332 | |
333 | for _, face in ipairs(self.faceConfig.items) do |
334 | local item = list[itemKey .. "_" .. face.name] |
335 | if item ~= nil then |
336 | return item |
337 | end |
338 | end |
339 | |
340 | return 0 |
341 | end |
342 | |
343 | local faceName = xmlFile:getString(key .. ".face#name") |
344 | if faceName ~= nil then |
345 | preset.face = self.facesByName[faceName] |
346 | end |
347 | |
348 | preset.top = getOrNul(topsByName, xmlFile:getString(key .. ".top#name")) |
349 | preset.bottom = getOrNul(bottomsByName, xmlFile:getString(key .. ".bottom#name")) |
350 | preset.onepiece = getOrNul(onepiecesByName, xmlFile:getString(key .. ".onepiece#name")) |
351 | preset.glasses = getOrNul(glassesByName, xmlFile:getString(key .. ".glasses#name")) |
352 | preset.gloves = getOrNul(glovesByName, xmlFile:getString(key .. ".gloves#name")) |
353 | preset.headgear = getOrNul(headgearByName, xmlFile:getString(key .. ".headgear#name")) |
354 | preset.footwear = getOrNul(footwearByName, xmlFile:getString(key .. ".footwear#name")) |
355 | preset.facegear = getOrNul(facegearByName, xmlFile:getString(key .. ".facegear#name")) |
356 | |
357 | table.insert(self.presets, preset) |
358 | end) |
359 | |
360 | self.isConfigurationLoaded = true |
361 | |
362 | xmlFile:delete() |
363 | end |
55 | function PlayerStyle.new(customMt) |
56 | local self = setmetatable({}, customMt or PlayerStyle_mt) |
57 | |
58 | local function createConfig(name, setter, listMappingGetter, colorSetter) |
59 | self[name] = { |
60 | items = {}, |
61 | selection = 0, |
62 | setter = setter, |
63 | listMappingGetter = listMappingGetter, |
64 | color = 1, |
65 | colorSetter = colorSetter, |
66 | } |
67 | end |
68 | |
69 | createConfig("beardConfig", self.setBeard, self.getPossibleBeards, self.setHairItemColor) |
70 | createConfig("bottomConfig", self.setBottom, self.getPossibleBottoms, self.setItemColor) |
71 | createConfig("faceConfig", self.setFace, self.getPossibleFaces, self.setItemColor) |
72 | createConfig("footwearConfig", self.setFootwear, self.getPossibleFootwear, self.setItemColor) |
73 | createConfig("glassesConfig", self.setGlasses, self.getPossibleGlasses, self.setItemColor) |
74 | createConfig("glovesConfig", self.setGloves, self.getPossibleGloves, self.setItemColor) |
75 | createConfig("hairStyleConfig", self.setHairStyle, self.getPossibleHairStyles, self.setHairItemColor) |
76 | createConfig("headgearConfig", self.setHeadgear, self.getPossibleHeadgear, self.setItemColor) |
77 | createConfig("mustacheConfig", self.setMustache, self.getPossibleMustaches, self.setHairItemColor) |
78 | createConfig("onepieceConfig", self.setOnepiece, self.getPossibleOnepieces, self.setItemColor) |
79 | createConfig("topConfig", self.setTop, self.getPossibleTops, self.setItemColor) |
80 | createConfig("facegearConfig", self.setFacegear) |
81 | |
82 | -- Unify hair colors |
83 | self.beardConfig.color = self.hairStyleConfig.color |
84 | self.mustacheConfig.color = self.hairStyleConfig.color |
85 | |
86 | self.faceConfig.selection = 1 |
87 | self.hairStyleConfig.selection = 2 |
88 | |
89 | self.disabledOptionsForSelection = {} |
90 | |
91 | self.presets = {} |
92 | |
93 | self.isConfigurationLoaded = false |
94 | |
95 | return self |
96 | end |