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