characterDollUtilities.py (12903B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\charactercreator\client\characterDollUtilities.py 2 from __future__ import print_function 3 import charactercreator.const as ccConst 4 from eve.common.script.paperDoll.paperDollDefinitions import BODY_CATEGORIES, GENDER, HAIR_CATEGORIES, SEPERATOR_CHAR 5 from utillib import KeyVal 6 7 class CharacterDollUtilities: 8 9 def __init__(self): 10 self.modifierLocationsByName = {} 11 self.modifierLocationsByKey = {} 12 self.assetsToIDs = {'male': None, 13 'female': None} 14 15 def GetNewCharacterMetadata(self, genderID, bloodlineID): 16 return KeyVal(genderID=genderID, bloodlineID=bloodlineID, types={}, typeColors={}, typeWeights={}, typeSpecularity={}, hairDarkness=0.0) 17 18 def RemoveFromCharacterMetadata(self, metadata, category): 19 if category in metadata.types: 20 metadata.types.pop(category, None) 21 metadata.typeColors.pop(category, None) 22 metadata.typeSpecularity.pop(category, None) 23 metadata.typeWeights.pop(category, None) 24 25 def SetColorSpecularityByCategory(self, doll, category, specularity, doUpdate = True, metadata = None): 26 modifier = self.GetModifierByCategory(doll, category) 27 if modifier: 28 metadata.typeSpecularity[category] = specularity 29 m1 = 1.0 + 0.4 * specularity 30 s1 = 0.5 + 0.3 * specularity 31 s2 = 0.5 - 0.2 * specularity 32 modifier.SetColorVariationSpecularity([(s1, 33 s1, 34 s1, 35 m1), (s2, 36 s2, 37 s2, 38 1.0), (0.5, 0.5, 0.5, 1.0)]) 39 40 def GetModifierByCategory(self, doll, category, getAll = False): 41 modifiers = self.GetModifiersByCategory(doll, category) 42 if not modifiers: 43 return None 44 elif getAll: 45 return modifiers 46 else: 47 if category == HAIR_CATEGORIES.BEARD: 48 for modifier in modifiers: 49 if modifier.name != 'stubble': 50 return modifier 51 52 return modifiers[0] 53 54 def GetModifiersByCategory(self, doll, category): 55 ret = [] 56 mods = doll.buildDataManager.GetModifiersAsList(includeFuture=True) 57 for m in mods: 58 resPath = m.GetResPath() 59 resPathSplit = resPath.split('/') 60 categSplit = category.split('/') 61 match = True 62 for i, each in enumerate(categSplit): 63 if not (len(resPathSplit) > i and resPathSplit[i] == each): 64 match = False 65 break 66 67 if match: 68 ret.append(m) 69 70 return ret 71 72 def ApplyTypeToDoll(self, itemType, weight = 1.0, doUpdate = True, rawColorVariation = None, metadata = None, factory = None, doll = None): 73 assetTypeID = None 74 if itemType is None: 75 return 76 import eve.client.script.ui.login.charcreation.ccUtil as ccUtil 77 self.PopulateModifierLocationDicts() 78 genderID = metadata.genderID 79 if type(itemType) is not tuple: 80 charGender = ccUtil.GenderIDToPaperDollGender(genderID) 81 itemTypeData = factory.GetItemType(itemType, gender=charGender) 82 if itemTypeData is None: 83 itemTypeLower = itemType.lower() 84 if BODY_CATEGORIES.TOPINNER in itemTypeLower: 85 self.ApplyItemToDoll(BODY_CATEGORIES.TOPINNER, None, removeFirst=True, doUpdate=False, doll=doll, metadata=metadata, factory=factory) 86 elif BODY_CATEGORIES.BOTTOMINNER in itemTypeLower: 87 self.ApplyItemToDoll(BODY_CATEGORIES.BOTTOMINNER, None, removeFirst=True, doUpdate=False, doll=doll, metadata=metadata, factory=factory) 88 else: 89 print("Item type file is missing, can't be loaded %s" % str(itemType)) 90 return 91 assetID, assetTypeID = self.GetAssetAndTypeIDsFromPath(charGender, itemType) 92 itemType = (assetID, itemTypeData[:3], assetTypeID) 93 category = self.GetCategoryFromResPath(itemType[1][0]) 94 modifierLocationKey = self.modifierLocationsByName.get(category, None) 95 toRemove = [] 96 for otherCategory, otherResourceID in metadata.types.iteritems(): 97 if otherResourceID is None: 98 continue 99 otherResource = cfg.paperdollResources.Get(otherResourceID) 100 if otherResource.typeID is None: 101 continue 102 if otherResource.clothingRemovesCategory == modifierLocationKey: 103 toRemove.append(otherCategory) 104 105 for itemToRemove in toRemove: 106 self.ApplyItemToDoll(itemToRemove, None, removeFirst=True, doUpdate=False) 107 108 activeMod = self.GetModifierByCategory(doll, category) 109 if activeMod: 110 doll.RemoveResource(activeMod.GetResPath(), factory) 111 modifier = doll.AddItemType(factory, itemType[1], weight, rawColorVariation) 112 metadata.types[category] = itemType[0] 113 myTypeID = itemType[2] 114 if myTypeID: 115 removesCategory = cfg.paperdollResources.Get(itemType[0]).clothingRemovesCategory 116 if removesCategory: 117 modifierLocationName = self.modifierLocationsByKey[int(removesCategory)] 118 self.ApplyItemToDoll(modifierLocationName, None, removeFirst=True, doUpdate=False, doll=doll, metadata=metadata, factory=factory) 119 if ccUtil.HasUserDefinedWeight(category): 120 metadata.typeWeights[category] = weight 121 if category in (ccConst.hair, ccConst.beard, ccConst.eyebrows) and assetTypeID is None: 122 self.SynchronizeHairColors(metadata, doll) 123 return modifier 124 125 def PopulateModifierLocationDicts(self, force = False): 126 if not force and len(self.modifierLocationsByKey) > 0: 127 return 128 self.modifierLocationsByName = {} 129 self.modifierLocationsByKey = {} 130 for row in cfg.paperdollModifierLocations: 131 self.modifierLocationsByKey[row.modifierLocationID] = row.modifierKey 132 self.modifierLocationsByName[row.modifierKey] = row.modifierLocationID 133 134 def ApplyItemToDoll(self, category, name, removeFirst = False, variation = None, doUpdate = True, doll = None, metadata = None, factory = None): 135 modifier = None 136 modifierFoundForVariationSwitch = False 137 if name and variation: 138 modifier = self.GetModifierByCategory(doll, category) 139 if modifier and modifier.name.split(SEPERATOR_CHAR)[-1] == name: 140 modifier.SetVariation(variation) 141 modifierFoundForVariationSwitch = True 142 if not modifierFoundForVariationSwitch: 143 if removeFirst: 144 if name: 145 modifier = self.GetModifierByCategory(doll, category) 146 if modifier: 147 self.RemoveFromCharacterMetadata(metadata, category) 148 doll.RemoveResource(modifier.respath, factory) 149 else: 150 modifiers = self.GetModifierByCategory(doll, category, getAll=True) 151 if modifiers: 152 self.RemoveFromCharacterMetadata(metadata, category) 153 for modifier in modifiers: 154 doll.RemoveResource(modifier.respath, factory) 155 156 if name: 157 modifier = doll.AddResource(category + '/' + name, 1.0, factory, variation=variation) 158 elif not removeFirst: 159 modifier = self.GetModifierByCategory(doll, category) 160 if modifier: 161 self.RemoveFromCharacterMetadata(metadata, category) 162 doll.RemoveResource(modifier.GetResPath(), factory) 163 return modifier 164 165 def SynchronizeHairColors(self, metadata, doll): 166 import geo2 167 hairData = self.GetModifierByCategory(doll, ccConst.hair) 168 if hairData is not None: 169 colorizeData = hairData.colorizeData 170 orgA, orgB, orgC = colorizeData 171 newA = geo2.Vector(*orgA) 172 lowA = newA * 0.2 173 newA = geo2.Vec4Lerp(lowA, newA, metadata.hairDarkness) 174 adjustedColor = (newA, orgB, orgC) 175 for hairModifier in (ccConst.beard, ccConst.eyebrows): 176 if hairModifier == ccConst.beard: 177 hms = self.GetModifierByCategory(doll, hairModifier, getAll=True) 178 else: 179 hms = [self.GetModifierByCategory(doll, hairModifier)] 180 if hms is None: 181 continue 182 for hm in hms: 183 if hm: 184 hm.colorizeData = adjustedColor 185 hm.pattern = hairData.pattern 186 hm.patternData = hairData.patternData 187 hm.specularColorData = hairData.specularColorData 188 hm.SetColorVariation('none') 189 190 def SetColorValueByCategory(self, doll, metadata, category, colorVar1, colorVar2, doUpdate = True): 191 if colorVar1 is None: 192 return 193 color1Value, color1Name, color2Name, variation = self.GetColorsToUse(colorVar1, colorVar2) 194 modifier = self.GetModifierByCategory(doll, category) 195 if not modifier: 196 return 197 if color1Value: 198 metadata.typeColors[category] = (color1Name, None) 199 modifier.SetColorizeData(color1Value) 200 elif colorVar2 is not None: 201 metadata.typeColors[category] = (color1Name, color2Name) 202 modifier.SetColorVariationDirectly(variation) 203 else: 204 metadata.typeColors[category] = (color1Name, None) 205 modifier.SetColorVariationDirectly(variation) 206 if category == ccConst.hair: 207 self.SynchronizeHairColors(metadata, doll) 208 209 def GetColorsToUse(self, colorVar1, colorVar2, *args): 210 if colorVar1 is None: 211 return (None, None, None, None) 212 if len(colorVar1) == 3: 213 colorVar1 = (colorVar1[0], colorVar1[2]) 214 if colorVar2 is not None and len(colorVar2) == 3: 215 colorVar2 = (colorVar2[0], colorVar2[2]) 216 color1Name, color1Value = colorVar1 217 import types 218 if type(color1Value) == types.TupleType: 219 return (color1Value, 220 color1Name, 221 None, 222 None) 223 elif colorVar2 is not None: 224 color2Name, color2Value = colorVar2 225 variation = {} 226 if color1Value: 227 if color2Value and 'colors' in color1Value: 228 variation['colors'] = [color1Value['colors'][0], color2Value['colors'][1], color2Value['colors'][2]] 229 if 'pattern' in color1Value: 230 variation['pattern'] = color1Value['pattern'] 231 if color2Value and 'patternColors' in color1Value: 232 variation['patternColors'] = [color1Value['patternColors'][0], color2Value['patternColors'][1], color2Value['patternColors'][2]] 233 if 'patternColors' in color1Value: 234 variation['patternColors'] = color1Value['patternColors'] 235 if color2Value and 'specularColors' in color1Value: 236 variation['specularColors'] = [color1Value['specularColors'][0], color2Value['specularColors'][1], color2Value['specularColors'][2]] 237 return (None, 238 color1Name, 239 color2Name, 240 variation) 241 else: 242 return (None, 243 color1Name, 244 None, 245 color1Value) 246 247 def GetAssetAndTypeIDsFromPath(self, gender, assetPath): 248 if self.assetsToIDs[gender] is None: 249 self.assetsToIDs[gender] = {} 250 for row in cfg.paperdollResources: 251 if row.resGender == (gender == GENDER.MALE): 252 self.assetsToIDs[gender][self.GetRelativePath(row.resPath).lower()] = (row.paperdollResourceID, row.typeID) 253 254 assetPath = self.GetRelativePath(assetPath).lower() 255 if assetPath in self.assetsToIDs[gender]: 256 return self.assetsToIDs[gender][assetPath] 257 else: 258 return (None, None) 259 260 def GetRelativePath(self, resPath): 261 if resPath.lower().startswith('res:'): 262 for chopPart in ['Modular/Female/', 263 'Modular/Male/', 264 'Female/Paperdoll/', 265 'Male/Paperdoll/', 266 'modular/female/', 267 'modular/male/', 268 'female/paperdoll/', 269 'male/paperdoll/']: 270 startPos = resPath.find(chopPart) 271 if startPos != -1: 272 chopTo = len(chopPart) + startPos 273 resPath = resPath[chopTo:] 274 275 return resPath 276 277 def GetCategoryFromResPath(self, resPath): 278 parts = resPath.split('/') 279 return '/'.join(parts[:-1])