Пример #1
0
 def tgi(self, pattern='tgi', order='<'):
     pattern = pattern.lower()
     self.verify_tgi(pattern)
     key = ResourceKey()
     for f in pattern:
         if f == 't': key.t = self.u32(order)
         elif f == 'g': key.g = self.u32(order)
         elif f == 'i': key.i = self.u64(order)
     return key
Пример #2
0
 def __init__(self, key):
     self.version = self.VERSION.DEFAULT
     self.rig = ExternalResource(ResourceKey())
     self.unknown = 1.0
     self.reserved = [0] * self.RESERVED_COUNT
     self.bone_weights = []
     RCOL.__init__(self, key)
Пример #3
0
 def __init__(self, key=None, stream=None):
     self.version = self.VERSION.DEFAULT
     self.bounds = BoundingBox()
     self.flags = 0x00000000
     self.routing_footprint = ExternalResource(ResourceKey())
     self.entries = []
     RCOL.__init__(self, key, stream)
Пример #4
0
 def __init__(self, package):
     """
     """
     self.offset = 0
     self.file_size = 0
     self.mem_size = 0
     self.compressed = False
     self.unknown = 1
     self.key = ResourceKey()
     self.delete_pending = False
     self.source = package
     self.name = ''
Пример #5
0
 def __init__(self, key=None):
     RCOL.__init__(self, key)
     self.version = 0
     self.indices = []
     self.vertices = []
     self.shader = None
     self.material = MaterialBlock()
     self.merge_group = 0
     self.skin_controller = ExternalResource(
         ResourceKey(BodySkinController.ID))
     self.sort_order = 0
     self.vertex_format = self.VertexFormat()
     self.bones = []
Пример #6
0
    def create_key(cls, name):
        assert len(name) > 4
        s = name.split('_', 1)
        assert len(s[0]) >= 1

        flags = {
            'b': 0x01,
            'p': 0x02,
            'c': 0x03,
            't': 0x04,
            'h': 0x05,
            'e': 0x06,
            'ad': 0x08,
            'cd': 0x09,
            'al': 0x0A,
            'ac': 0x0D,
            'cc': 0x0E,
            'ah': 0x10,
            'ch': 0x11,
            'ab': 0x12,
            'ar': 0x13
        }

        generic_name = name
        generic_actor_types = {'a', 'o'}

        def get_generic_actor_type(s):
            return 'o' if s == 'o' else 'a'

        actors = s[0].split('2', 1)
        mask = 0
        xAge = 0
        yAge = 0
        if actors[0] in flags:
            xAge = flags[actors[0]]
        if len(actors) > 1:
            if not actors[0] in generic_actor_types or not actors[
                    1] in generic_actor_types:
                if actors[1] in flags:
                    yAge = flags[actors[1]]
                generic_name = '%s2%s_%s' % (get_generic_actor_type(
                    actors[0]), get_generic_actor_type(actors[1]), s[1])
                mask = 0x8000 | xAge << 8 | yAge
        elif not actors[0] in generic_actor_types:
            generic_name = 'a_' + s[1]
            mask = 0x8000 | xAge << 8
        instance = FNV64.hash(generic_name)
        instance &= 0x7FFFFFFFFFFFFFFF
        instance ^= mask << 48
        group = 0x48000000 if xAge > 0x06 or yAge > 0x06 else 0
        return ResourceKey(cls.ID, group, instance)
Пример #7
0
 def parse_value(value_string, resources):
     items = []
     strings = value_string.split(',')
     for string in strings:
         if string[:4] == 'key:':
             keyVals = string[4:].split(':')
             key = ResourceKey(int(keyVals[0], 16), int(keyVals[1], 16),
                               int(keyVals[2], 16))
             items.append(key)
         elif string in ('true', 'false'):
             items.append(string == 'true')
         else:
             items.append(string)
     return items if len(items) > 1 else items[0]
Пример #8
0
 def __init__(self, filename=None):
     """
     """
     self.stream = None
     self.filename = os.path.abspath(filename)
     if filename:
         self.stream = io.open(self.filename, 'rb')
     self.entries = []
     self.header = self.Header()
     self.index_flags = 0
     self.static_key = ResourceKey()
     self.__name_map = None
     self.__loaded_resources = {}
     self.__pending_deletes = {}
     self.cache = False
     self.load()
Пример #9
0
 def load(self):
     if not self.stream:
         return
     s = StreamReader(self.stream)
     self.entries = []
     self.header.read(self.stream)
     self.stream.seek(self.header.index_offset, SEEK_SET)
     self.index_flags = s.u32()
     if Flag.is_set(self.index_flags, self.INDEX_FLAG.TYPE):
         self.static_key.t = s.u32()
     if Flag.is_set(self.index_flags, self.INDEX_FLAG.GROUP):
         self.static_key.g = s.u32()
     if Flag.is_set(self.index_flags, self.INDEX_FLAG.INSTANCE_HI):
         self.static_key.i = s.u32() << 32
     if Flag.is_set(self.index_flags, self.INDEX_FLAG.INSTANCE_LO):
         self.static_key.i |= s.u32()
     for i in range(self.header.index_entry_count):
         index = self.IndexEntry(self)
         index.key = ResourceKey()
         if Flag.is_set(self.index_flags, self.INDEX_FLAG.TYPE):
             index.key.t = self.static_key.t
         else:
             index.key.t = s.u32()
         if Flag.is_set(self.index_flags, self.INDEX_FLAG.GROUP):
             index.key.g = self.static_key.g
         else:
             index.key.g = s.u32()
         if Flag.is_set(self.index_flags, self.INDEX_FLAG.INSTANCE_HI):
             instance_hi = self.static_key.i >> 32
         else:
             instance_hi = s.u32()
         if Flag.is_set(self.index_flags, self.INDEX_FLAG.INSTANCE_LO):
             instance_lo = self.static_key.i & 0xFFFFFFFF
         else:
             instance_lo = s.u32()
         index.key.i = (instance_hi << 32) + instance_lo
         index.offset = s.u32()
         index.file_size = s.u32() & 0x0FFFFFFF
         index.mem_size = s.u32()
         flag = s.u16()
         index.compressed = flag == 0xFFFF
         index.unknown = s.u16()
         self.entries.append(index)
     nmap = self.name_map
     for entry in self.entries:
         entry.name = nmap[entry.key.i]
     print("Done.")
Пример #10
0
 def write_rcol(self, stream, rcol):
     self.write_tag(stream)
     s = StreamWriter(stream)
     s.u32(self.version)
     tgi = TGIList()
     tgi.begin_write(stream)
     s.u8(len(self.entries))
     for entry in self.entries:
         s.u8(entry.TYPE)
         entry.write(stream, tgi)
     s.u8(2)
     self.bounds.write(stream)
     s.u32(self.flags)
     if self.routing_footprint.key != ResourceKey():
         s.u8(1)
         s.tgi(self.routing_footprint.key, 'TGI')
     else: s.u8(0)
     tgi.end_write(stream)
Пример #11
0
def load_object(objd, package):
    print('Loading object!')
    assert isinstance(objd, BuildBuyProduct)
    vpxy = first(package.find_all_type(VisualProxy.ID)).fetch(VisualProxy)

    armature_rig = None
    rig = package.find_key(
        first(
            vpxy.entries, lambda e: isinstance(e, VisualProxy.MiscEntry) and e.
            resource.key.t == SkeletonRig.ID).resource.key)
    if rig:
        try:
            rig = rig.fetch(SkeletonRig)
            armature_rig = load_rig(rig)
        except:
            print('Unable to load rig, please patch your game...')
    if not armature_rig:
        print('No rig found')
        armature_rig = create_marker_node(objd.resource_name, True)

    print('Loading Model...')
    modl = package.find_key(
        first(
            vpxy.entries, lambda e: isinstance(e, VisualProxy.MiscEntry) and e.
            resource.key.t == Model.ID).resource.key).fetch(Model)

    if any(objd.presets):
        preset = objd.presets[0]
    else:
        preset = package.find_key(
            ResourceKey(t=PackedPreset.ID, g=1, i=modl.key.i))
        if preset:
            preset = preset.fetch(PackedPreset)
        else:
            preset = Preset()
    ml = MaterialLoader(package, preset)

    load_model(package, modl, armature_rig, ml)

    return armature_rig
Пример #12
0
 def __init__(self):
     self.name = ""
     self.resource = ExternalResource(ResourceKey())
     self.values = {}
     self.patterns = []
     self.variable = None
Пример #13
0
 def __init__(self, stream=None, resources=None, parent=None):
     self.index = 0
     self.resource = ExternalResource(ResourceKey())
     VisualProxy.Entry.__init__(self, stream, resources)
Пример #14
0
def load_caspart(caspart,
                 package,
                 armature_rig,
                 morphs=False,
                 expressions=False):
    print('Loading CASPart %s...' % caspart.resource_name)
    bgeo = {}
    preset = None
    loaded_morphs = []

    # Loads a BlendGeometry and add it to the dictionary.  If a key was already loaded, skip it.  Either key or index must be specified.
    # If a name is provided, it will be used, otherwise it will default to the package name or the instance id
    def load_bgeo(key=None, name=None, index=None):
        if index:
            assert isinstance(index, Package.IndexEntry)
            key = index.key
        print('Loading %s %s' % (key, index))
        if not key.i:
            print(
                'Skipping invalid BlendGeometry %s:  Instance must not be 0.' %
                key)
            return
        if key in loaded_morphs:
            print('Skipping BlendGeometry %s: Already loaded.' % key)
            return
        try:
            if not index:
                if key.t == BlendData.ID:
                    blend_data = package.find_key(key).fetch(BlendData)
                    assert isinstance(blend_data, BlendData)
                    key = blend_data.blend_geometry.key
                index = package.find_key(key)
            if not index:
                print(
                    'Skipping BlendGeometry %s: Resource not found in package'
                    % key)
                return

            assert isinstance(index, Package.IndexEntry)
            resource = index.fetch(BlendGeometry)
            assert isinstance(resource, BlendGeometry)
            if not name:
                name = resource.resource_name
            if not name:
                name = '%16X' % key.i
            bgeo[name] = resource
            loaded_morphs.append(key)

        except Exception as ex:
            print('Skipping BlendGeometry %s: Error loading' % key)
            print(ex)
            pass
        pass

    # Maps blend LOD vertex by it's id
    def map_blend_vertex(blend_lod):
        bvmap = {}
        for v in blend_lod.vertices:
            bvmap[v.id] = v
        return bvmap

    # Adds a bone to the skeleton
    def create_armature_bone(bone_name, parent_bone=None, min_bone=.001):
        set_context('EDIT', armature_rig)
        armature_bone = find_bone(armature_rig.data.edit_bones, bone_name)
        if not armature_bone:
            armature_bone = armature_rig.data.edit_bones.new(bone_name)
            armature_bone.use_connect = False
            armature_bone.tail = [0, min_bone, 0]
        if parent_bone:
            armature_bone.parent = armature_rig.data.edit_bones[parent_bone]
        set_context('POSE', armature_rig)
        return armature_bone

    if caspart:
        print('CASP found...')
        preset = package.find_key(
            ResourceKey(t=PackedPreset.ID, g=caspart.key.g, i=caspart.key.i))
        if preset:
            preset = preset.fetch(PackedPreset)
        elif any(caspart.presets):
            preset = caspart.presets[0]
        part_name = caspart.part_name
        assert isinstance(caspart, CASPart)
        vpxy = package.get_resource(key=caspart.sources[0].key,
                                    wrapper=VisualProxy)

        # Load standard morphs if specified with user friendly name
        if morphs:
            if caspart.blend_fat.key.i:
                load_bgeo(name='Fat', key=caspart.blend_fat.key)
            if caspart.blend_fit.key.i:
                load_bgeo(name='Fit', key=caspart.blend_fit.key)
            if caspart.blend_thin.key.i:
                load_bgeo(name='Thin', key=caspart.blend_thin.key)
            if caspart.blend_special.key.i:
                load_bgeo(name='Pregnant', key=caspart.blend_special.key)

    else:
        print('No CASP found, defaulting to first VPXY')
        vpxy = first(package.find_all_type(VisualProxy.ID))
        if vpxy:
            vpxy = vpxy.fetch(VisualProxy)
        assert isinstance(vpxy, VisualProxy)
        part_name = vpxy.resource_name

    print('Loading morphs...')
    for bgeo_index in package.find_all_type(BlendGeometry.ID):
        try:
            load_bgeo(index=bgeo_index)
        except Exception as ex:
            print("Unable to load morph %s" % bgeo_index)
            print(ex)
    if not preset:
        preset = Preset()
    ml = MaterialLoader(package, preset)
    lod_hi = first(vpxy.entries, lambda e: e.TYPE == VisualProxy.LodEntry.TYPE)
    assert isinstance(lod_hi, VisualProxy.LodEntry)

    # Arrange morph data for processing
    blend_vertex_lod_map = {}
    for blend_name in bgeo:
        cur_bgeo = bgeo[blend_name]
        for blend in cur_bgeo.blends:
            blend_vertex_lod_map[blend_name] = map_blend_vertex(
                blend.lods[lod_hi.index])

    # Load face morphs for animal meshes.  Loads any BodyGeometry matching the name 'Expression' as a morph
    if expressions:
        driver_root = 'b__DRIVERS__'
        create_armature_bone(driver_root)
        print('creating root: %s' % driver_root)
        for index in package.find_all_type(BodyGeometry.ID):
            assert isinstance(index, Package.IndexEntry)
            geom = index.fetch(BodyGeometry)
            assert isinstance(geom, BodyGeometry)
            if not 'Expressions' in geom.resource_name:
                continue
            blend_name = geom.resource_name[17:-2]
            create_armature_bone(blend_name, parent_bone=driver_root)
            blend_vertex_lod_map[blend_name] = map_blend_vertex(geom)
    meshes = []
    for lod_sub_index, geom in enumerate(
            package.find_key(item.key).fetch(BodyGeometry)
            for item in lod_hi.resources):
        material = ml.generate('%s_%i' % (part_name, lod_sub_index),
                               geom.material)
        meshes.append(
            load_geom(part_name + '_' + str(lod_sub_index), geom,
                      blend_vertex_lod_map, armature_rig, material))
    return meshes
Пример #15
0
    def commit(self):
        """
        """
        tmp_filename = tempfile.mktemp()
        tmp_stream = io.open(tmp_filename, 'wb')

        s = StreamWriter(tmp_stream)
        self.header.index_entry_count = len(self.entries)

        pkg_stream = None
        if self.stream:
            pkg_stream = self.stream
        elif exists(self.filename):
            pkg_stream = io.open(self.filename, 'rb')

        #skip over header
        tmp_stream.seek(self.Header.SIZE, SEEK_SET)

        # Write data, update header and index
        self.index_flags = 0
        self.static_key = ResourceKey()
        if any(self.entries):
            self.index_flags = self.INDEX_FLAG.TYPE | self.INDEX_FLAG.GROUP
            static_key = None
            for index in self.entries:
                if index.delete_pending:
                    self.entries.remove(index)
                    continue
                data = None
                if index.key in self.__loaded_resources:
                    index.compressed = False
                    wrapper = self.__loaded_resources[index.key]
                    with BytesIO() as wrapper_stream:
                        wrapper.write(wrapper_stream)
                        wrapper_stream.seek(0, SEEK_SET)
                        data = wrapper_stream.read(-1)
                    index.file_size = len(data)
                    index.mem_size = index.file_size
                elif isinstance(pkg_stream, io.FileIO):
                    pkg_stream.seek(index.offset)
                    data = pkg_stream.read(index.mem_size)
                else:
                    continue
#                if static_key == None: static_key = index.key.clone()
#                if not index.key.t == static_key.t:
#                    static_key.t = 0
#                    self.index_flags = Flag.unset(self.index_flags, self.INDEX_FLAG.TYPE)
#                if not index.key.g == static_key.g:
#                    static_key.g = 0
#                    self.index_flags = Flag.unset(self.index_flags, self.INDEX_FLAG.GROUP)
                index.offset = tmp_stream.tell()
                tmp_stream.write(data)
            if self.index_flags: self.static_key = static_key

        # Write index table
        self.header.index_offset = tmp_stream.tell()
        s.u32(0)
        #        if Flag.is_set(self.index_flags, self.INDEX_FLAG.TYPE):
        #            s.u32(self.static_key.t)
        #        if Flag.is_set(self.index_flags, self.INDEX_FLAG.GROUP):
        #            s.u32(self.static_key.g)
        for index in self.entries:
            #            if not Flag.is_set(self.index_flags, self.INDEX_FLAG.TYPE):
            #                s.u32(index.key.t)
            #            if not Flag.is_set(self.index_flags, self.INDEX_FLAG.GROUP):
            #                s.u32(index.key.g)
            s.u32(index.key.t)
            s.u32(index.key.g)
            instance_hi = index.key.i >> 32
            instance_lo = index.key.i & 0xFFFFFFFF
            s.u32(instance_hi)
            s.u32(instance_lo)
            s.u32(index.offset)
            s.u32(index.file_size | 0x80000000)
            s.u32(index.mem_size)
            s.u16(0 if not index.compressed else 0xFFFF)
            s.u16(index.unknown)
        end = tmp_stream.tell()
        self.header.index_size = end - self.header.index_offset

        # Go back and write header
        tmp_stream.seek(0, SEEK_SET)
        self.header.write(tmp_stream)
        if pkg_stream:
            pkg_stream.close()
            os.unlink(self.filename)

        tmp_stream.close()
        shutil.move(tmp_filename, self.filename)