]> git.mxchange.org Git - flightgear.git/blob - utils/Modeller/uv_pack.py
Add a generic binary protocol configuration file analyser that outputs the relevant...
[flightgear.git] / utils / Modeller / uv_pack.py
1 #!BPY
2
3 # """
4 # Name: 'Pack selected objects on a square'
5 # Blender: 245
6 # Group: 'UV'
7 # Tooltip: 'Pack UV maps of all selected objects onto an empty square texture'
8 # """
9
10 __author__ = "Melchior FRANZ < mfranz # aon : at >"
11 __url__ = "http://members.aon.at/mfranz/flightgear/"
12 __version__ = "0.1"
13 __bpydoc__ = """\
14 Script for mapping multiple objects onto one square texture.
15
16 Usage:
17 (1) create new square texture in the UV editor
18 (2) map all objects individually, choosing the most appropriate technique
19 (3) scale each of the mappings to the appropriate size, relative to the
20     other object mappings
21 (4) select all objects and switch to edit mode (consider to use
22     Select->Linked->Material or similar methods)
23 (5) start this script with UVs->Scripts->Pack objects on a square
24
25     [now the texture image will first be erased, then colored rectangles
26     will appear for each object]
27
28 (6) rescale and/or remap objects that you aren't happy with (the
29     relative size of a mapping will be kept)
30
31     [continue with (5) until you like the result]
32
33 (7) export UV layout to SVG (UVs->Scripts->Save UV Face Layout)
34 """
35
36
37 #--------------------------------------------------------------------------------
38 # Copyright (C) 2008  Melchior FRANZ  < mfranz # aon : at >
39 #
40 # This program is free software; you can redistribute it and/or
41 # modify it under the terms of the GNU General Public License as
42 # published by the Free Software Foundation; either version 2 of the
43 # License, or (at your option) any later version.
44 #
45 # This program is distributed in the hope that it will be useful, but
46 # WITHOUT ANY WARRANTY; without even the implied warranty of
47 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
48 # General Public License for more details.
49 #
50 # You should have received a copy of the GNU General Public License
51 # along with this program; if not, write to the Free Software
52 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
53 #--------------------------------------------------------------------------------
54
55
56 MARGIN = 10 # px
57 GAP = 10    # px
58
59
60 import Blender
61 from random import randint as rand
62
63
64 class Abort(Exception):
65         def __init__(self, msg):
66                 self.msg = msg
67
68
69 def pack():
70         image = Blender.Image.GetCurrent()
71         if not image:
72                 raise Abort('No texture image selected')
73
74         imgwidth, imgheight = image.getSize()
75         if imgwidth != imgheight:
76                 Blender.Draw.PupMenu("Warning%t|Image isn't a square!")
77         gap = (float(GAP) / imgwidth, float(GAP) / imgheight)
78         margin = (float(MARGIN) / imgwidth - gap[0] * 0.5, float(MARGIN) / imgheight - gap[1] * 0.5)
79
80         def drawrect(x0, y0, x1, y1, color = (255, 255, 255, 255)):
81                 x0 *= imgwidth
82                 x1 *= imgwidth
83                 y0 *= imgheight
84                 y1 *= imgheight
85                 for u in range(int(x0 + 0.5), int(x1 - 0.5)):
86                         for v in range(int(y0 + 0.5), int(y1 - 0.5)):
87                                 image.setPixelI(u, v, color)
88
89
90         boxes = []
91         unique_meshes = {}
92
93         BIG = 1<<30
94         Blender.Window.DrawProgressBar(0.0, "packing")
95         for o in Blender.Scene.GetCurrent().objects.selected:
96                 if o.type != "Mesh":
97                         continue
98
99                 mesh = o.getData(mesh = 1)
100                 if not mesh.faceUV:
101                         continue
102                 if mesh.name in unique_meshes:
103                         #print "dropping duplicate mesh", mesh.name, "of object", o.name
104                         continue
105                 unique_meshes[mesh.name] = True
106
107                 print "\tobject '%s'" % o.name
108                 xmin = ymin = BIG
109                 xmax = ymax = -BIG
110                 for f in mesh.faces:
111                         for p in f.uv:
112                                 xmin = min(xmin, p[0])
113                                 xmax = max(xmax, p[0])
114                                 ymin = min(ymin, p[1])
115                                 ymax = max(ymax, p[1])
116
117                 width = xmax - xmin
118                 height = ymax - ymin
119                 boxes.append([0, 0, width + gap[0], height + gap[1], xmin, ymin, mesh])
120
121         if not boxes:
122                 raise Abort('No mesh objects selected')
123
124
125         boxwidth, boxheight = Blender.Geometry.BoxPack2D(boxes)
126         boxmax = max(boxwidth, boxheight)
127         xscale = (1.0 - 2.0 * margin[0]) / boxmax
128         yscale = (1.0 - 2.0 * margin[1]) / boxmax
129
130         image.reload()
131         #drawrect(0, 0, 1, 1) # erase texture
132
133         for i, box in enumerate(boxes):
134                 Blender.Window.DrawProgressBar(float(i) * len(boxes), "Drawing")
135                 xmin = ymin = BIG
136                 xmax = ymax = -BIG
137                 for f in box[6].faces:
138                         for p in f.uv:
139                                 p[0] = (p[0] - box[4] + box[0] + gap[0] * 0.5 + margin[0]) * xscale
140                                 p[1] = (p[1] - box[5] + box[1] + gap[1] * 0.5 + margin[1]) * yscale
141
142                                 xmin = min(xmin, p[0])
143                                 xmax = max(xmax, p[0])
144                                 ymin = min(ymin, p[1])
145                                 ymax = max(ymax, p[1])
146
147                 drawrect(xmin, ymin, xmax, ymax, (rand(128, 255), rand(128, 255), rand(128, 255), 255))
148                 box[6].update()
149
150         Blender.Window.RedrawAll()
151         Blender.Window.DrawProgressBar(1.0, "Finished")
152
153
154
155 editmode = Blender.Window.EditMode()
156 if editmode:
157         Blender.Window.EditMode(0)
158 Blender.Window.WaitCursor(1)
159
160 try:
161         print "box packing ..."
162         pack()
163         print "done\n"
164 except Abort, e:
165         print "Error:", e.msg, "  -> aborting ...\n"
166         Blender.Draw.PupMenu("Error%t|" + e.msg)
167
168 Blender.Window.WaitCursor(0)
169 if editmode:
170         Blender.Window.EditMode(1)
171
172