21 |
|
|
22 |
# TODO |
# TODO |
23 |
# * Convert writer to use xml.sax.writer.PrettyPrinter |
# * Convert writer to use xml.sax.writer.PrettyPrinter |
24 |
|
# -> There doesn't seem to be a way to set output charset |
25 |
|
# -> Not exactly pretty either |
26 |
# * Add save feedback |
# * Add save feedback |
27 |
# * Add more GUI controls |
# * Add more GUI controls |
28 |
|
|
29 |
__author__ = "Chong Kai Xiong" |
__author__ = "Chong Kai Xiong" |
30 |
__version__ = "0.1" |
__version__ = "0.2" |
31 |
__email__ = "descender@phreaker.net" |
__email__ = "descender@phreaker.net" |
32 |
__url__ = "http://www.nongnu.org/usata" |
__url__ = "http://www.nongnu.org/usata" |
33 |
|
|
34 |
import Blender |
import Blender |
35 |
|
import xml.sax.writer |
36 |
|
import gettext |
37 |
|
|
38 |
from Blender.BGL import * |
from Blender.BGL import * |
39 |
from xml.sax.xmlreader import AttributesImpl |
from Blender import Registry |
|
from xml.sax.saxutils import XMLGenerator |
|
40 |
|
|
41 |
|
# i18n |
42 |
|
|
43 |
|
I18N_DOMAIN = "blender-usata-export" |
44 |
|
|
45 |
# event numbers |
# event numbers |
46 |
|
|
47 |
EV_NONE = 0 |
EVENT_NONE = 0 |
48 |
EV_SAVE = 100 |
EVENT_SAVE = 100 |
49 |
EV_QUIT = 101 |
EVENT_QUIT = 101 |
50 |
|
EVENT_FILENAME = 102 |
51 |
|
|
52 |
|
_ = gettext.gettext |
53 |
|
|
54 |
output_name = Blender.Draw.Create("untitled.xml") |
class XmlWriter(xml.sax.writer.PrettyPrinter): |
55 |
output_charset = 'utf-8' |
def __init__(self, fp): |
56 |
|
xml.sax.writer.PrettyPrinter.__init__(self, fp) |
57 |
|
|
58 |
fp_format = '%.8f' |
def characters(self, data, start = 0, length = -1): |
59 |
|
if length < 0: |
60 |
|
length = len(data) - start |
61 |
|
xml.sax.writer.PrettyPrinter.characters(self, data, start, length) |
62 |
|
|
63 |
class XmlExporter: |
class XmlExporter(object): |
64 |
|
|
65 |
def __init__(self, filename): |
def __init__(self, filename, charset, fp_format): |
66 |
self.filename = filename |
self.filename = filename |
67 |
|
self.charset = charset |
68 |
|
self.fp_format = fp_format |
69 |
|
|
70 |
self.file = None |
self.file = None |
71 |
self.writer = None |
self.writer = None |
72 |
|
|
74 |
self.writer.startElement("vertex", {}) |
self.writer.startElement("vertex", {}) |
75 |
|
|
76 |
self.writer.startElement("position", |
self.writer.startElement("position", |
77 |
{"x": fp_format % vertex.co[0], |
{"x": self.fp_format % vertex.co[0], |
78 |
"y": fp_format % vertex.co[1], |
"y": self.fp_format % vertex.co[1], |
79 |
"z": fp_format % vertex.co[2]} |
"z": self.fp_format % vertex.co[2]} |
80 |
) |
) |
81 |
self.writer.endElement("position") |
self.writer.endElement("position") |
82 |
|
|
83 |
self.writer.startElement("texture", |
self.writer.startElement("texture", |
84 |
{"u": fp_format % vertex.uvco[0], |
{"u": self.fp_format % vertex.uvco[0], |
85 |
"v": fp_format % vertex.uvco[1]} |
"v": self.fp_format % vertex.uvco[1]} |
86 |
) |
) |
87 |
self.writer.endElement("texture") |
self.writer.endElement("texture") |
88 |
|
|
89 |
self.writer.startElement("normal", |
self.writer.startElement("normal", |
90 |
{"x": fp_format % vertex.no[0], |
{"x": self.fp_format % vertex.no[0], |
91 |
"y": fp_format % vertex.no[1], |
"y": self.fp_format % vertex.no[1], |
92 |
"z": fp_format % vertex.no[2]} |
"z": self.fp_format % vertex.no[2]} |
93 |
) |
) |
94 |
self.writer.endElement("normal") |
self.writer.endElement("normal") |
95 |
|
|
144 |
self.writer.endElement("name") |
self.writer.endElement("name") |
145 |
|
|
146 |
self.writer.startElement("position", |
self.writer.startElement("position", |
147 |
{"x": fp_format % camera_obj.loc[0], |
{"x": self.fp_format % camera_obj.loc[0], |
148 |
"y": fp_format % camera_obj.loc[1], |
"y": self.fp_format % camera_obj.loc[1], |
149 |
"z": fp_format % camera_obj.loc[2]} |
"z": self.fp_format % camera_obj.loc[2]} |
150 |
) |
) |
151 |
self.writer.endElement("position") |
self.writer.endElement("position") |
152 |
|
|
153 |
self.writer.startElement("lens", {}) |
self.writer.startElement("lens", {}) |
154 |
self.writer.characters(fp_format % camera.getLens()) |
self.writer.characters(self.fp_format % camera.getLens()) |
155 |
self.writer.endElement("lens") |
self.writer.endElement("lens") |
156 |
|
|
157 |
self.writer.startElement("near", {}) |
self.writer.startElement("near", {}) |
158 |
self.writer.characters(fp_format % camera.getClipStart()) |
self.writer.characters(self.fp_format % camera.getClipStart()) |
159 |
self.writer.endElement("near") |
self.writer.endElement("near") |
160 |
|
|
161 |
self.writer.startElement("far", {}) |
self.writer.startElement("far", {}) |
162 |
self.writer.characters(fp_format % camera.getClipEnd()) |
self.writer.characters(self.fp_format % camera.getClipEnd()) |
163 |
self.writer.endElement("far") |
self.writer.endElement("far") |
164 |
|
|
165 |
self.writer.endElement("camera") |
self.writer.endElement("camera") |
185 |
self.writer.startElement("scene", {}) |
self.writer.startElement("scene", {}) |
186 |
|
|
187 |
# write all cameras |
# write all cameras |
188 |
|
for camera in Blender.Camera.Get(): |
|
print "Writing cameras..." |
|
|
|
|
|
cameras = Blender.Camera.Get() |
|
|
|
|
|
print "..." |
|
|
|
|
|
for camera in cameras: |
|
189 |
self.write_camera(camera) |
self.write_camera(camera) |
190 |
|
|
191 |
# write mesh objects |
# write mesh objects |
192 |
|
for object in Blender.Object.Get(): |
|
print "Writing objects..." |
|
|
|
|
|
objects = Blender.Object.Get() |
|
|
|
|
|
for object in objects: |
|
193 |
# check if object is a mesh |
# check if object is a mesh |
194 |
|
|
195 |
mesh = Blender.NMesh.GetRaw(object.name) |
mesh = Blender.NMesh.GetRaw(object.name) |
201 |
self.writer.endElement("scene") |
self.writer.endElement("scene") |
202 |
|
|
203 |
def write(self): |
def write(self): |
204 |
print "Writing...", self.filename |
print "Writing to file (%s)..." % self.filename |
205 |
|
|
206 |
self.file = open(self.filename, "wt") |
self.file = open(self.filename, "wt") |
207 |
self.writer = XMLGenerator(self.file, output_charset) |
self.writer = XmlWriter(self.file) |
208 |
|
|
209 |
self.writer.startDocument() |
self.writer.startDocument() |
210 |
self.write_scene() |
self.write_scene() |
212 |
|
|
213 |
self.file.close() |
self.file.close() |
214 |
|
|
215 |
|
class GUIControl(object): |
216 |
|
def __init__(self): |
217 |
def Draw(): |
self.load_settings() |
218 |
global output_name |
|
219 |
|
def load_settings(self): |
220 |
# clear window |
self.settings = Registry.GetKey('Usata') |
221 |
glClearColor(0.6, 0.6, 0.65, 1.0) |
|
222 |
glClear(GL_COLOR_BUFFER_BIT) |
if not self.settings: |
223 |
|
self.settings = {} |
224 |
# draw title |
|
225 |
glColor3f(0.0, 0.0, 0.0) |
self.settings.setdefault('filename', 'untitled.xml') |
226 |
glRasterPos2i(50, 500) |
self.settings.setdefault('charset', 'UTF-8') |
227 |
Blender.Draw.Text("Blender XML file exporter") |
self.settings.setdefault('float-format', "%.8f") |
228 |
|
|
229 |
# filename entry button |
def save_settings(self): |
230 |
output_name = Blender.Draw.String("File: ", EV_NONE, |
Registry.SetKey('Usata', self.settings) |
231 |
50, 400, 400, 20, |
|
232 |
output_name.val, 255, |
def export(self): |
233 |
"filename") |
print "Exporting scene..." |
234 |
|
exporter = XmlExporter(self.settings['filename'], |
235 |
# save button |
self.settings['charset'], |
236 |
Blender.Draw.Button("Save", EV_SAVE, 50, 350, 50, 20, |
self.settings['float-format']) |
237 |
"save file") |
exporter.write() |
238 |
|
|
239 |
# quit button |
def draw(self): |
240 |
Blender.Draw.Button("Quit", EV_QUIT, 110, 350, 50, 20, |
# clear window |
241 |
"exit script") |
glClearColor(0.6, 0.6, 0.65, 1.0) |
242 |
|
glClear(GL_COLOR_BUFFER_BIT) |
243 |
|
|
244 |
def handle_widget_event(event): |
# draw title |
245 |
if event == EV_SAVE: |
glColor3f(0.0, 0.0, 0.0) |
246 |
export_scene() |
glRasterPos2i(50, 500) |
247 |
elif event == EV_QUIT: |
Blender.Draw.Text(_("Usata XML file exporter")) |
248 |
Blender.Draw.Exit() |
|
249 |
|
# filename entry button |
250 |
|
self.output_name = Blender.Draw.String(_("File: "), EVENT_FILENAME, |
251 |
def export_scene(): |
50, 400, 400, 20, |
252 |
print "Exporting scene..." |
self.settings['filename'], 255, |
253 |
exporter = XmlExporter(output_name.val) |
"Output filename") |
254 |
exporter.write() |
|
255 |
|
# save button |
256 |
|
Blender.Draw.Button(_("Save"), EVENT_SAVE, 50, 350, 50, 20, |
257 |
|
"save file") |
258 |
|
|
259 |
|
# quit button |
260 |
|
Blender.Draw.Button(_("Quit"), EVENT_QUIT, 110, 350, 50, 20, |
261 |
|
"exit script") |
262 |
|
|
263 |
|
def run(self): |
264 |
|
Blender.Draw.Register(self.draw, None, self.handle_event) |
265 |
|
|
266 |
|
def handle_event(self, event): |
267 |
|
if event == EVENT_FILENAME: |
268 |
|
self.settings['filename'] = self.output_name.val |
269 |
|
|
270 |
|
elif event == EVENT_SAVE: |
271 |
|
self.export() |
272 |
|
|
273 |
|
elif event == EVENT_QUIT: |
274 |
|
self.save_settings() |
275 |
|
Blender.Draw.Exit() |
276 |
|
|
277 |
|
def setup_i18n(): |
278 |
|
gettext.bindtextdomain(I18N_DOMAIN) |
279 |
|
#gettext.bind_textdomain_codeset(I18N_DOMAIN, 'UTF-8') # Python 2.4 |
280 |
|
gettext.textdomain(I18N_DOMAIN) |
281 |
|
|
282 |
def main(): |
def main(): |
283 |
Blender.Draw.Register(Draw, None, handle_widget_event) |
setup_i18n() |
284 |
|
gui = GUIControl() |
285 |
|
gui.run() |
286 |
|
|
287 |
if __name__ == "__main__": |
if __name__ == "__main__": |
288 |
main() |
main() |