1from ctypes import * 2import sys 3import os 4import xml.etree.ElementTree as ET 5 6binaries = '../../../binaries' 7 8# Work out the platform-dependent library filename 9dll_filename = { 10 'posix': './libCollada_dbg.so', 11 'nt': 'Collada_dbg.dll', 12}[os.name] 13 14# The DLL may need other DLLs which are in its directory, so set the path to that 15# (Don't care about clobbering the old PATH - it doesn't have anything important) 16os.environ['PATH'] = '%s/system/' % binaries 17 18# Load the actual library 19library = cdll.LoadLibrary('%s/system/%s' % (binaries, dll_filename)) 20 21def log(severity, message): 22 print '[%s] %s' % (('INFO', 'WARNING', 'ERROR')[severity], message) 23 24clog = CFUNCTYPE(None, c_int, c_char_p)(log) 25 # (the CFUNCTYPE must not be GC'd, so try to keep a reference) 26library.set_logger(clog) 27skeleton_definitions = open('%s/data/tools/collada/skeletons.xml' % binaries).read() 28library.set_skeleton_definitions(skeleton_definitions, len(skeleton_definitions)) 29 30def _convert_dae(func, filename, expected_status=0): 31 output = [] 32 def cb(cbdata, str, len): 33 output.append(string_at(str, len)) 34 35 cbtype = CFUNCTYPE(None, POINTER(None), POINTER(c_char), c_uint) 36 status = func(filename, cbtype(cb), None) 37 assert(status == expected_status) 38 return ''.join(output) 39 40def convert_dae_to_pmd(*args, **kwargs): 41 return _convert_dae(library.convert_dae_to_pmd, *args, **kwargs) 42 43def convert_dae_to_psa(*args, **kwargs): 44 return _convert_dae(library.convert_dae_to_psa, *args, **kwargs) 45 46def clean_dir(path): 47 # Remove all files first 48 try: 49 for f in os.listdir(path): 50 os.remove(path+'/'+f) 51 os.rmdir(path) 52 except OSError: 53 pass # (ignore errors if files are in use) 54 # Make sure the directory exists 55 try: 56 os.makedirs(path) 57 except OSError: 58 pass # (ignore errors if it already exists) 59 60def create_actor(mesh, texture, anims, props_): 61 actor = ET.Element('actor', version='1') 62 ET.SubElement(actor, 'castshadow') 63 group = ET.SubElement(actor, 'group') 64 variant = ET.SubElement(group, 'variant', frequency='100', name='Base') 65 ET.SubElement(variant, 'mesh').text = mesh+'.pmd' 66 ET.SubElement(variant, 'texture').text = texture+'.dds' 67 68 animations = ET.SubElement(variant, 'animations') 69 for name, file in anims: 70 ET.SubElement(animations, 'animation', file=file+'.psa', name=name, speed='100') 71 72 props = ET.SubElement(variant, 'props') 73 for name, file in props_: 74 ET.SubElement(props, 'prop', actor=file+'.xml', attachpoint=name) 75 76 return ET.tostring(actor) 77 78def create_actor_static(mesh, texture): 79 actor = ET.Element('actor', version='1') 80 ET.SubElement(actor, 'castshadow') 81 group = ET.SubElement(actor, 'group') 82 variant = ET.SubElement(group, 'variant', frequency='100', name='Base') 83 ET.SubElement(variant, 'mesh').text = mesh+'.pmd' 84 ET.SubElement(variant, 'texture').text = texture+'.dds' 85 return ET.tostring(actor) 86 87################################ 88 89# Error handling 90 91if False: 92 convert_dae_to_pmd('This is not well-formed XML', expected_status=-2) 93 convert_dae_to_pmd('<html>This is not COLLADA</html>', expected_status=-2) 94 convert_dae_to_pmd('<COLLADA>This is still not valid COLLADA</COLLADA>', expected_status=-2) 95 96# Do some real conversions, so the output can be tested in the Actor Viewer 97 98test_data = binaries + '/data/tests/collada' 99test_mod = binaries + '/data/mods/_test.collada' 100 101clean_dir(test_mod + '/art/meshes') 102clean_dir(test_mod + '/art/actors') 103clean_dir(test_mod + '/art/animation') 104 105#for test_file in ['cube', 'jav2', 'jav2b', 'teapot_basic', 'teapot_skin', 'plane_skin', 'dude_skin', 'mergenonbone', 'densemesh']: 106#for test_file in ['teapot_basic', 'jav2b', 'jav2d']: 107for test_file in ['xsitest3c','xsitest3e','jav2d','jav2d2']: 108#for test_file in ['xsitest3']: 109#for test_file in []: 110 print "* Converting PMD %s" % (test_file) 111 112 input_filename = '%s/%s.dae' % (test_data, test_file) 113 output_filename = '%s/art/meshes/%s.pmd' % (test_mod, test_file) 114 115 input = open(input_filename).read() 116 output = convert_dae_to_pmd(input) 117 open(output_filename, 'wb').write(output) 118 119 xml = create_actor(test_file, 'male', [('Idle','dudeidle'),('Corpse','dudecorpse'),('attack1',test_file),('attack2','jav2d')], [('helmet','teapot_basic_static')]) 120 open('%s/art/actors/%s.xml' % (test_mod, test_file), 'w').write(xml) 121 122 xml = create_actor_static(test_file, 'male') 123 open('%s/art/actors/%s_static.xml' % (test_mod, test_file), 'w').write(xml) 124 125#for test_file in ['jav2','jav2b', 'jav2d']: 126for test_file in ['xsitest3c','xsitest3e','jav2d','jav2d2']: 127#for test_file in []: 128 print "* Converting PSA %s" % (test_file) 129 130 input_filename = '%s/%s.dae' % (test_data, test_file) 131 output_filename = '%s/art/animation/%s.psa' % (test_mod, test_file) 132 133 input = open(input_filename).read() 134 output = convert_dae_to_psa(input) 135 open(output_filename, 'wb').write(output) 136 137