'''Noesis import plugin. Written by Tsukihime''' from inc_noesis import * import noesis import rapi import os def registerNoesisTypes(): '''Register the plugin. Just change the Game name and extension.''' handle = noesis.register("Forsaken World", ".ski") noesis.setHandlerTypeCheck(handle, noepyCheckType) noesis.setHandlerLoadModel(handle, noepyLoadModel) return 1 def noepyCheckType(data): '''Verify that the format is supported by this plugin. Default yes''' if len(data) < 8: return 0 try: bs = NoeBitStream(data) idstring = noeStrFromBytes(bs.readBytes(8)) if idstring != "MOXBIKSA": return 0 return 1 except: return 0 def noepyLoadModel(data, mdlList): '''Build the model, set materials, bones, and animations. You do not need all of them as long as they are empty lists (they are by default)''' ctx = rapi.rpgCreateContext() parser = SanaeParser(data) parser.parse_file() mdl = rapi.rpgConstructModel() mdl.setModelMaterials(NoeModelMaterials(parser.texList, parser.matList)) mdl.setBones(parser.boneList) mdl.setAnims(parser.animList) mdlList.append(mdl) return 1 class SanaeParser(object): def __init__(self, data): '''Initialize some data. Refer to Sanae.py to see what is already initialized''' self.inFile = NoeBitStream(data) self.animList = [] self.texList = [] self.matList = [] self.boneList = [] def read_name(self, n=0): if n: string = self.inFile.readBytes(n) else: string = self.inFile.readBytes(self.inFile.readUInt()) try: return noeStrFromBytes(string) except: try: return noeStrFromBytes(string, 'gb2312') except: return "" def open_file(self, texName): dirpath = rapi.getDirForFilePath(rapi.getInputName()) try: f = open(texName, 'rb') return f except: try: f = open(dirpath + "textures\\" + texName, 'rb') return f except: print("failed to open texture: %s" %texName) def parse_textures(self, numTex): for i in range(numTex): texName = self.read_name() ext = texName[-4:] f = self.open_file(texName) if f: try: tex = rapi.loadTexByHandler(f.read(), ext) if tex is not None: tex.name = texName self.texList.append(tex) except: tex = NoeTexture("dummy", 0, 0, 0, 0) self.texList.append(tex) else: tex = NoeTexture("dummy", 0, 0, 0, 0) self.texList.append(tex) def parse_materials(self, numMat): for i in range(numMat): matHeader = self.read_name(11) self.inFile.read('16f') self.inFile.readFloat() self.inFile.readByte() def parse_vertices(self, numVerts, vertType): if vertType == 0: vertBuff = self.inFile.readBytes(48*numVerts) rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 48, 0) rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 48, 28) rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 48, 40) elif vertType == 1: vertBuff = self.inFile.readBytes(32*numVerts) rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 32, 0) rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 32, 12) rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 32, 24) def parse_faces(self, numIdx): return self.inFile.readBytes(numIdx*2) def create_material(self, matNum, texNum): matName = "material[%d]" %len(self.matList) texName = self.texList[texNum].name material = NoeMaterial(matName, texName) material.setDefaultBlend(0) self.matList.append(material) return matName def parse_meshes(self, numMesh, vertType): for i in range(numMesh): meshName = self.read_name() texNum, matNum = self.inFile.read('2l') if vertType == 1: self.inFile.readUInt() numVerts, numIdx = self.inFile.read('2L') matName = self.create_material(matNum, texNum) self.parse_vertices(numVerts, vertType) idxBuff = self.parse_faces(numIdx) rapi.rpgSetMaterial(matName) #rapi.rpgSetOption(noesis.RPGOPT_TRIWINDBACKWARD, 1) rapi.rpgCommitTriangles(idxBuff, noesis.RPGEODATA_USHORT, numIdx, noesis.RPGEO_TRIANGLE, 1) def parse_bones(self, numBones): for i in range(numBones): boneName = self.read_name() def parse_file(self): '''Main parser method''' idstring = self.inFile.readBytes(8) meshType = self.inFile.readUInt() numMesh1, numMesh2, unk1, unk2, numTex, numMat, numBones, unk3, \ typeMask = self.inFile.read('9L') self.inFile.seek(60, 1) self.parse_bones(numBones) self.parse_textures(numTex) self.parse_materials(numMat) if numMesh1: self.parse_meshes(numMesh1, 0) elif numMesh2: self.parse_meshes(numMesh2, 1)