]> git.mxchange.org Git - flightgear.git/blob - utils/Modeller/uv_export_svg.py
initial commit for a python based terrasync client
[flightgear.git] / utils / Modeller / uv_export_svg.py
1 #!BPY
2
3 # """
4 # Name: 'UV: Export to SVG'
5 # Blender: 245
6 # Group: 'Image'
7 # Tooltip: 'Export selected objects to SVG file'
8 # """
9
10 __author__ = "Melchior FRANZ < mfranz # aon : at >"
11 __url__ = ["http://www.flightgear.org/", "http://cvs.flightgear.org/viewvc/source/utils/Modeller/uv_export_svg.py"]
12 __version__ = "0.1"
13 __bpydoc__ = """\
14 Saves the UV mappings of all selected objects to an SVG file. The uv_import_svg.py
15 script can be used to re-import such a file. Each object and each group of adjacent
16 faces therein will be made a separate SVG group.
17 """
18
19 #--------------------------------------------------------------------------------
20 # Copyright (C) 2008  Melchior FRANZ  < mfranz # aon : at >
21 #
22 # This program is free software; you can redistribute it and/or
23 # modify it under the terms of the GNU General Public License as
24 # published by the Free Software Foundation; either version 2 of the
25 # License, or (at your option) any later version.
26 #
27 # This program is distributed in the hope that it will be useful, but
28 # WITHOUT ANY WARRANTY; without even the implied warranty of
29 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
30 # General Public License for more details.
31 #
32 # You should have received a copy of the GNU General Public License
33 # along with this program; if not, write to the Free Software
34 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
35 #--------------------------------------------------------------------------------
36
37
38 FILL_COLOR = None  # 'yellow' or '#ffa000' e.g. for uni-color, None for random color
39 ID_SEPARATOR = '_.:._'
40
41
42 import Blender, BPyMessages, sys, random
43
44
45 class Abort(Exception):
46         def __init__(self, msg):
47                 self.msg = msg
48
49
50 class UVFaceGroups:
51         def __init__(self, mesh):
52                 faces = dict([(f.index, f) for f in mesh.faces])
53                 self.groups = []
54                 while faces:
55                         self.groups.append(self.adjacent(faces))
56
57         def __len__(self):
58                 return len(self.groups)
59
60         def __iter__(self):
61                 return self.groups.__iter__()
62
63         def adjacent(self, faces):
64                 uvcoords = {}
65                 face = faces.popitem()[1]
66                 group = [face]
67                 for c in face.uv:
68                         uvcoords[tuple(c)] = True
69
70                 while True:
71                         found = []
72                         for face in faces.itervalues():
73                                 for c in face.uv:
74                                         if tuple(c) in uvcoords:
75                                                 for c in face.uv:
76                                                         uvcoords[tuple(c)] = True
77                                                 found.append(face)
78                                                 break
79                         if not found:
80                                 return group
81                         for face in found:
82                                 group.append(face)
83                                 del faces[face.index]
84
85
86 def stringcolor(string):
87         random.seed(hash(string))
88         c = [random.randint(220, 255), random.randint(120, 240), random.randint(120, 240)]
89         random.shuffle(c)
90         return "#%02x%02x%02x" % tuple(c)
91
92
93 def write_svg(path):
94         size = Blender.Draw.PupMenu("Image size%t|128|256|512|1024|2048|4096|8192")
95         if size < 0:
96                 raise Abort('no image size chosen')
97         size = 1 << (size + 6)
98
99         svg = open(path, "w")
100         svg.write('<?xml version="1.0" standalone="no"?>\n')
101         svg.write('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n\n')
102         svg.write('<svg width="%spx" height="%spx" viewBox="0 0 %d %d" xmlns="http://www.w3.org/2000/svg"' \
103                         ' version="1.1" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">\n'
104                         % (size, size, size, size))
105         svg.write("\t<desc>uv_export_svg.py: %s</desc>\n" % path);
106         svg.write('\t<rect x="0" y="0" width="%d" height="%d" fill="none" stroke="blue" stroke-width="%f"/>\n'
107                         % (size, size, 1.0))
108
109         objects = {}
110         for o in Blender.Scene.GetCurrent().objects.selected:
111                 if o.type != "Mesh":
112                         continue
113
114                 mesh = o.getData(mesh = 1)
115                 if mesh.faceUV:
116                         objects[mesh.name] = (o.name, mesh)
117
118         for meshname, v in objects.iteritems():
119                 objname, mesh = v
120                 color = FILL_COLOR or stringcolor(meshname)
121
122                 svg.write('\t<g style="fill:%s; stroke:black stroke-width:1px" inkscape:label="%s" ' \
123                                 'id="%s">\n' % (color, objname, objname))
124
125                 facegroups = UVFaceGroups(mesh)
126                 for faces in facegroups:
127                         indent = '\t\t'
128                         if len(facegroups) > 1:
129                                 svg.write('\t\t<g>\n')
130                                 indent = '\t\t\t'
131                         for f in faces:
132                                 svg.write('%s<polygon id="%s%s%d" points="' % (indent, meshname, ID_SEPARATOR, f.index))
133                                 for p in f.uv:
134                                         svg.write('%.8f,%.8f ' % (p[0] * size, size - p[1] * size))
135                                 svg.write('"/>\n')
136                         if len(facegroups) > 1:
137                                 svg.write('\t\t</g>\n')
138
139                 svg.write("\t</g>\n")
140
141         svg.write('</svg>\n')
142         svg.close()
143
144
145 def export(path):
146         if not BPyMessages.Warning_SaveOver(path):
147                 return
148
149         editmode = Blender.Window.EditMode()
150         if editmode:
151                 Blender.Window.EditMode(0)
152
153         try:
154                 write_svg(path)
155                 Blender.Registry.SetKey("UVImportExportSVG", { "path" : path }, False)
156
157         except Abort, e:
158                 print "Error:", e.msg, "  -> aborting ...\n"
159                 Blender.Draw.PupMenu("Error%t|" + e.msg)
160
161         if editmode:
162                 Blender.Window.EditMode(1)
163
164
165 registry = Blender.Registry.GetKey("UVImportExportSVG", False)
166 if registry and "path" in registry:
167         path = registry["path"]
168 else:
169         active = Blender.Scene.GetCurrent().objects.active
170         basename = Blender.sys.basename(Blender.sys.splitext(Blender.Get("filename"))[0])
171         path = basename + "-" + active.name + ".svg"
172
173 Blender.Window.FileSelector(export, "Export to SVG", path)
174