]> git.mxchange.org Git - flightgear.git/blob - utils/Modeller/uv_export_svg.py
- improve Blender registry handling
[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://members.aon.at/mfranz/flightgear/"
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 FILL_COLOR = ''  # 'yellow' or '#ffa000' e.g. for uni-color, empty string for random color
20 ID_SEPARATOR = '_.._'
21
22
23 import Blender, BPyMessages, sys, random
24
25
26 class Abort(Exception):
27         def __init__(self, msg):
28                 self.msg = msg
29
30
31 class UVFaceGroups:
32         def __init__(self, mesh):
33                 faces = dict([(f.index, f) for f in mesh.faces])
34                 self.groups = []
35                 while faces:
36                         self.groups.append(self.adjacent(faces))
37
38         def __len__(self):
39                 return len(self.groups)
40
41         def __iter__(self):
42                 return self.groups.__iter__()
43
44         def adjacent(self, faces):
45                 uvcoords = {}
46                 face = faces.popitem()[1]
47                 group = [face]
48                 for c in face.uv:
49                         uvcoords[(c[0], c[1])] = True
50
51                 while True:
52                         found = []
53                         for face in faces.itervalues():
54                                 for c in face.uv:
55                                         if (c[0], c[1]) in uvcoords:
56                                                 for c in face.uv:
57                                                         uvcoords[(c[0], c[1])] = True
58                                                 found.append(face)
59                                                 break
60                         if not found:
61                                 return group
62                         for face in found:
63                                 group.append(face)
64                                 del faces[face.index]
65
66
67 def hashcolor(name):
68         random.seed(hash(name))
69         c = [random.randint(220, 255), random.randint(120, 220), random.randint(120, 220)]
70         random.shuffle(c)
71         return "#%02x%02x%02x" % (c[0], c[1], c[2])
72
73
74 def write_svg(path):
75         size = Blender.Draw.PupMenu("Image size%t|128|256|512|1024|2048|4096|8192")
76         if size < 0:
77                 raise Abort('no image size chosen')
78         size = 1 << (size + 6)
79
80         print "exporting to '%s' (size %d) ... " % (path, size),
81         svg = open(path, "w")
82         svg.write('<?xml version="1.0" standalone="no"?>\n')
83         svg.write('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n\n')
84         svg.write('<svg width="%spx" height="%spx" viewBox="0 0 %d %d" xmlns="http://www.w3.org/2000/svg"' \
85                         ' version="1.1" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">\n'
86                         % (size, size, size, size))
87         svg.write("\t<desc>uv_export_svg.py: %s</desc>\n" % path);
88         svg.write('\t<rect x="0" y="0" width="%d" height="%d" fill="none" stroke="blue" stroke-width="%f"/>\n'
89                         % (size, size, 1.0))
90
91         objects = {}
92         for o in Blender.Scene.GetCurrent().objects.selected:
93                 if o.type != "Mesh":
94                         continue
95
96                 mesh = o.getData(mesh = 1)
97                 if mesh.faceUV:
98                         objects[mesh.name] = (o.name, mesh)
99
100         for meshname, v in objects.iteritems():
101                 objname, mesh = v
102                 color = FILL_COLOR or hashcolor(meshname)
103
104                 svg.write('\t<g style="fill:%s; stroke:black stroke-width:1px" inkscape:label="%s" ' \
105                                 'id="%s">\n' % (color, objname, objname))
106
107                 facegroups = UVFaceGroups(mesh)
108                 for faces in facegroups:
109                         indent = '\t\t'
110                         if len(facegroups) > 1:
111                                 svg.write('\t\t<g>\n')
112                                 indent = '\t\t\t'
113                         for f in faces:
114                                 svg.write('%s<polygon id="%s%s%d" points="' % (indent, meshname, ID_SEPARATOR, f.index))
115                                 for p in f.uv:
116                                         svg.write('%.8f,%.8f ' % (p[0] * size, size - p[1] * size))
117                                 svg.write('"/>\n')
118                         if len(facegroups) > 1:
119                                 svg.write('\t\t</g>\n')
120
121                 svg.write("\t</g>\n")
122
123         svg.write('</svg>\n')
124         svg.close()
125         print "done."
126
127
128 def export(path):
129         if not BPyMessages.Warning_SaveOver(path):
130                 return
131
132         editmode = Blender.Window.EditMode()
133         if editmode:
134                 Blender.Window.EditMode(0)
135
136         try:
137                 write_svg(path)
138                 Blender.Registry.SetKey("UVImportExportSVG", { "path" : path }, False)
139
140         except Abort, e:
141                 print "Error:", e.msg, "  -> aborting ...\n"
142                 Blender.Draw.PupMenu("Error%t|" + e.msg)
143
144         if editmode:
145                 Blender.Window.EditMode(1)
146
147
148 registry = Blender.Registry.GetKey("UVImportExportSVG", False)
149 if registry and "path" in registry:
150         path = registry["path"]
151 else:
152         active = Blender.Scene.GetCurrent().objects.active
153         basename = Blender.sys.basename(Blender.sys.splitext(Blender.Get("filename"))[0])
154         path = basename + "-" + active.name + ".svg"
155
156 Blender.Window.FileSelector(export, "Export to SVG", path)
157