import glob import os try: from xml.etree.cElementTree import parse except ImportError: from elementtree.ElementTree import parse import files import shader class MissingNode(object): def __init__(self): self.text = None def get(self, name): return None class GameDataTagDef(object): def __init__(self): self.multi = False self.opt = False self.type = None self.default = None class GameDataNode(object): def __init__(self): self.dict = {} def __setitem__(self, name, val): self.dict[name] = val def __getitem__(self, name): return self.dict[name]._value def __getattr__(self, name): if name == 'dict': raise AttributeError, name try: return self.dict[name] except KeyError: if name == '_value': return None raise AttributeError, name def __setattr__(self, name, val): if name == 'dict': return object.__setattr__(self, name, val) try: self.dict[name] = val except KeyError: object.__setattr__(self, name, val) def add_multi(self, key, value): if not self.dict.has_key(key): self.dict[key] = [] self.dict[key].append(value) def add_single(self, key, value): self.dict[key] = value def __repr__(self): return """""" % (self.dict['_name'],) def has_key(self, key): return self.dict.has_key(key) class XMLGameDataReader(object): def __init__(self, bin, xml): self._bin = bin self._xml = xml self._tree = self.construct() self._name = xml.tag def value_as_type(self, value, type): if type == 'string': return value elif type == 'bool': if value and value[0].lower() in ('y', 't', '1'): return True else: return False elif type == 'int': return int(value) elif type == 'float': return float(value) elif type == 'csvarray': # csvarrays are always ints... return [int(x.strip()) for x in value.split(',')] else: raise TypeError, type def create_datatag_def(self, tag): d = GameDataTagDef() if tag.get('multiple') != None and tag.get('multiple')[0].lower() == 'y': d.multi = True if tag.get('optional') != None and tag.get('optional')[0].lower() == 'y': d.opt = True if tag.get('data') != None: d.type = tag.get('data') if tag.get('default') != None: d.default = self.value_as_type(tag.get('default'), d.type) d.opt = True return d def create_attribute_def(self, tag): return self.create_datatag_def(tag) def construct_node(self, bin, xml): node = GameDataNode() value = None if bin.tag == 'datatag': df = self.create_datatag_def(bin) if df.type: value = xml.text if type(xml) == MissingNode and df.opt: value = df.default elif type(xml) == MissingNode: raise ValueError, "Missing value for mandatory tag %s" % (bin.get('name'),) elif df.type == 'bool': # tag exists, and since it is a bool, that means it's True value = True else: value = self.value_as_type(value, df.type) node['_value'] = value elif bin.tag == 'attribute': df = self.create_attribute_def(bin) if df.type: value = xml.get(bin.get('name')) if value == None and df.opt: value = df.default elif not value: raise ValueError, "Missing value for mandatory tag %s" % (bin.get('name'),) else: value = self.value_as_type(value, df.type) node['_value'] = value node['_def'] = df node['_name'] = bin.get('name') return node def construct_recurse(self, bin, xml): xmldict = {} tagdict = {} attrdict = {} if bin.tag == 'xml_binary_packing': node = GameDataNode() else: node = self.construct_node(bin, xml) for child in bin.getchildren(): if child.tag == 'datatag': tagdict[child.get('name')] = child elif child.tag == 'attribute': attrdict[child.get('name')] = child else: raise ValueError xmlattrdict = {} for k, v in xml.items(): if not k in attrdict: raise ValueError, "Key %s not a valid attribute: %s" % (k, attrdict.keys()) continue binchild = attrdict[k] xmlchild = xml xmlattrdict[k] = 0 subnode = self.construct_node(binchild, xml) if subnode._def.multi: node.add_multi(k, subnode) else: node.add_single(k, subnode) xmltagdict = {} for child in xml.getchildren(): if not child.tag in tagdict: raise ValueError continue binchild = tagdict[child.tag] xmlchild = child xmltagdict[child.tag] = 0 subnode = self.construct_recurse(binchild, xmlchild) if subnode._def.multi: node.add_multi(child.tag, subnode) else: node.add_single(child.tag, subnode) missing = MissingNode() for k in tagdict.keys(): if not k in xmltagdict: # Missing datatag subnode = self.construct_node(tagdict[k], missing) if not subnode._def.multi: node.add_single(k, subnode) else: node.add_single(k, []) for k in attrdict.keys(): if not k in xmlattrdict: # Missing attribute subnode = self.construct_node(attrdict[k], missing) if not subnode._def.multi: node.add_single(k, subnode) else: node.add_single(k, []) return node def construct(self): rootname = self._bin.get('name') assert rootname == self._xml.tag return self.construct_recurse(self._bin, self._xml) def __getattr__(self, name): if name == 'tree': raise AttributeError, name return self._tree.__getattr__(name) def __getitem__(self, name): return self._tree.__getitem__(name) def load_xml_files(binfile, xmlfile): bintree = parse(binfile).getroot() xmltree = parse(xmlfile).getroot() return XMLGameDataReader(bintree, xmltree) def load_gamedata(): bins = glob.glob(files.mgr.path("xml/def", "*.xml")) xmls = glob.glob(files.mgr.path("xml", "*.xml")) binfns = [os.path.split(x)[1] for x in bins] xmlfns = [os.path.split(x)[1] for x in xmls] ffns = [] for bfn in binfns: if bfn in xmlfns: ffns.append(bfn) dataobjs = {} for fn in ffns: print fn #DELME binfile = files.mgr.path("xml/def", fn) xmlfile = files.mgr.path("xml", fn) dataobj = load_xml_files(binfile, xmlfile) dataobjs[dataobj._name] = dataobj shader.mgr.load_shaders(dataobjs['shaders']) return dataobjs