added file location messeges & disabled handler that was crashing on reload or newfile
[blender-addons-contrib.git] / add_mesh_stairs / tread.py
1 # Stairbuilder - Tread generation
2 #
3 # Generates treads for stair generation.
4 #   Stair Type (typ):
5 #       - id1 = Freestanding staircase
6 #       - id2 = Housed-open staircase
7 #       - id3 = Box staircase
8 #       - id4 = Circular staircase
9 #   Tread Type (typ_t):
10 #       - tId1 = Classic
11 #       - tId2 = Basic Steel
12 #       - tId3 = Bar 1
13 #       - tId4 = Bar 2
14 #       - tId5 = Bar 3
15
16 # Paul "BrikBot" Marshall
17 # Created: September 19, 2011
18 # Last Modified: January 26, 2012
19 # Homepage (blog): http://post.darkarsenic.com/
20 #                       //blog.darkarsenic.com/
21 #
22 # Coded in IDLE, tested in Blender 2.61.
23 # Search for "@todo" to quickly find sections that need work.
24 #
25 # ##### BEGIN GPL LICENSE BLOCK #####
26 #
27 #  Stairbuilder is for quick stair generation.
28 #  Copyright (C) 2011  Paul Marshall
29 #
30 #  This program is free software: you can redistribute it and/or modify
31 #  it under the terms of the GNU General Public License as published by
32 #  the Free Software Foundation, either version 3 of the License, or
33 #  (at your option) any later version.
34 #
35 #  This program is distributed in the hope that it will be useful,
36 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
37 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38 #  GNU General Public License for more details.
39 #
40 #  You should have received a copy of the GNU General Public License
41 #  along with this program.  If not, see <http://www.gnu.org/licenses/>.
42 #
43 # ##### END GPL LICENSE BLOCK #####
44
45 import mathutils
46 from copy import copy
47 from math import radians, sqrt
48 from mathutils import Matrix, Vector
49
50 class Treads:
51     def __init__(self,G,typ,typ_t,run,w,h,d,r,toe,o,n,tk,sec,sp,sn,deg=4):
52         self.G = G #General
53         self.typ = typ #Stair type
54         self.typ_t = typ_t #Tread type
55         self.run = run #Stair run.  Degrees if self.typ == "id4"
56         self.w=w #tread width.  Is outer radius if self.typ == "id4"
57         self.h=h #tread height
58         self.d=d #tread run.  Ignore for now if self.typ == "id4"
59         self.r=r #tread rise
60         self.t=toe #tread nosing
61         self.o=o #tread side overhang.  Is inner radius if self.typ == "id4"
62         self.n=n #number of treads
63         self.tk=tk #thickness of tread metal
64         self.sec=sec #metal sections for tread
65         if sec != 1 and typ_t not in ["tId4", "tId5"]:
66             self.sp=((d+toe)*(sp/100))/(sec-1) #spacing between sections (% of depth)
67         elif typ_t in ["tId4", "tId5"]:
68             self.sp=sp/100 #keep % value
69         else:
70             self.sp=0
71         self.sn=sn #number of cross sections
72         self.deg = deg #number of section per "slice".  Only applys if self.typ == "id4"
73         self.tId2_faces = [[0,1,2,3],[0,3,4,5],[4,5,6,7],[6,7,8,9],[8,9,10,11],
74                            [12,13,14,15],[12,15,16,17],[16,17,18,19],
75                            [18,19,20,21],[20,21,22,23],[0,1,13,12],[1,2,14,13],
76                            [2,3,15,14],[3,4,16,15],[4,7,19,16],[7,8,20,19],
77                            [8,11,23,20],[11,10,22,23],[10,9,21,22],[9,6,18,21],
78                            [6,5,17,18],[5,0,12,17]]
79         self.out_faces = [[0,2,3,1],[0,2,10,8],[9,11,3,1],[9,11,10,8],
80                           [2,6,7,3],[2,6,14,10],[11,15,7,3],[11,15,14,10],
81                           [0,4,5,1],[0,4,12,8],[9,13,5,1],[9,13,12,8],
82                           [4,6,7,5],[4,6,14,12],[13,15,14,12],[13,15,7,5]]
83         self.Create()
84
85     def Create(self):
86         # Setup the coordinates:
87         coords = []
88         coords2 = []
89         coords3 = []
90         cross = 0
91         cW = 0
92         depth = 0
93         offset = 0
94         height = 0
95         if self.typ in ["id1", "id2", "id3"]:
96             if self.typ_t == "tId1":
97                 coords.append(Vector([-self.t,-self.o,0]))
98                 coords.append(Vector([self.d,-self.o,0]))
99                 coords.append(Vector([-self.t,self.w + self.o,0]))
100                 coords.append(Vector([self.d,self.w + self.o,0]))
101                 for i in range(4):
102                     coords.append(coords[i]+Vector([0,0,-self.h]))
103
104             elif self.typ_t == "tId2":
105                 depth = (self.d + self.t - (self.sec - 1) * self.sp) / self.sec
106                 inset = depth / 4
107                 tDepth = depth - self.t
108                 coords.append(Vector([-self.t, -self.o, -self.h]))                          #0
109                 coords.append(Vector([inset - self.t, -self.o, -self.h]))           #1
110                 coords.append(Vector([inset - self.t, -self.o, -self.h + self.tk])) #2
111                 coords.append(Vector([self.tk - self.t, -self.o, -self.h + self.tk]))       #3
112                 coords.append(Vector([self.tk - self.t, -self.o, -self.tk]))                #4
113                 coords.append(Vector([-self.t, -self.o, 0]))                                #5
114                 coords.append(Vector([tDepth, -self.o, 0]))                                 #6
115                 coords.append(Vector([tDepth - self.tk, -self.o, -self.tk]))                #7
116                 coords.append(Vector([tDepth - self.tk, -self.o, self.tk - self.h]))        #8
117                 coords.append(Vector([tDepth, -self.o, -self.h]))                           #9
118                 coords.append(Vector([tDepth - inset, -self.o, -self.h]))           #10
119                 coords.append(Vector([tDepth - inset, -self.o, -self.h + self.tk])) #11
120                 for i in range(12):
121                     coords.append(coords[i] + Vector([0, self.w + (2 * self.o), 0]))
122             
123             elif self.typ_t in ["tId3", "tId4", "tId5"]:
124                 # Frame:
125                 coords.append(Vector([-self.t,-self.o,-self.h]))
126                 coords.append(Vector([self.d,-self.o,-self.h]))
127                 coords.append(Vector([-self.t,-self.o,0]))
128                 coords.append(Vector([self.d,-self.o,0]))
129                 for i in range(4):
130                     if (i % 2) == 0:
131                         coords.append(coords[i] + Vector([self.tk,self.tk,0]))
132                     else:
133                         coords.append(coords[i] + Vector([-self.tk,self.tk,0]))
134                 for i in range(4):
135                     coords.append(coords[i] + Vector([0,self.w + self.o,0]))
136                 for i in range(4):
137                     coords.append(coords[i + 4] + Vector([0,self.w + self.o - (2 * self.tk),0]))
138
139                 # Tread sections:
140                 if self.typ_t == "tId3":
141                     offset = (self.tk * sqrt(2)) / 2
142                     topset = self.h - offset
143                     self.sp = ((self.d + self.t - (2 * self.tk)) - (offset * (self.sec) + topset)) / (self.sec + 1)
144                     baseX = -self.t + self.sp + self.tk
145                     coords2.append(Vector([baseX, self.tk - self.o, offset - self.h]))
146                     coords2.append(Vector([baseX + offset, self.tk - self.o, -self.h]))
147                     for i in range(2):
148                         coords2.append(coords2[i] + Vector([topset, 0, topset]))
149                     for i in range(4):
150                         coords2.append(coords2[i] + Vector([0, (self.w + self.o) - (2 * self.tk), 0]))
151                 elif self.typ_t in ["tId4", "tId5"]:
152                     offset = ((self.run + self.t) * self.sp) / (self.sec + 1)
153                     topset = (((self.run + self.t) * (1 - self.sp)) - (2 * self.tk)) / self.sec
154                     baseX = -self.t + self.tk + offset
155                     baseY = self.w + self.o - 2 * self.tk
156                     coords2.append(Vector([baseX, -self.o + self.tk, -self.h / 2]))
157                     coords2.append(Vector([baseX + topset, -self.o + self.tk, -self.h / 2]))
158                     coords2.append(Vector([baseX, -self.o + self.tk, 0]))
159                     coords2.append(Vector([baseX + topset, -self.o + self.tk, 0]))
160                     for i in range(4):
161                         coords2.append(coords2[i] + Vector([0, baseY, 0]))
162
163                 # Tread cross-sections:
164                 if self.typ_t in ["tId3", "tId4"]:
165                     cW = self.tk
166                     cross = (self.w + (2 * self.o) - (self.sn + 2) * self.tk) / (self.sn + 1)
167                 else: # tId5
168                     spacing = self.sp ** (1 / 4)
169                     cross = ((2*self.o + self.w) * spacing) / (self.sn + 1)
170                     cW = (-2*self.tk + (2*self.o + self.w) * (1 - spacing)) / self.sn
171                     self.sp = topset
172                     height = -self.h / 2
173                 baseY = -self.o + self.tk + cross
174                 coords3.append(Vector([-self.t + self.tk, baseY, -self.h]))
175                 coords3.append(Vector([self.d - self.tk, baseY, -self.h]))
176                 coords3.append(Vector([-self.t + self.tk, baseY, height]))
177                 coords3.append(Vector([self.d - self.tk, baseY, height]))
178                 for i in range(4):
179                     coords3.append(coords3[i] + Vector([0, cW, 0]))
180
181             # Make the treads:
182             for i in range(self.n):
183                 if self.typ_t == "tId1":
184                     self.G.Make_mesh(coords,self.G.faces,'treads')
185                 elif self.typ_t == "tId2":
186                     temp = []
187                     for j in coords:
188                         temp.append(copy(j))
189                     for j in range(self.sec):
190                         self.G.Make_mesh(temp, self.tId2_faces, 'treads')
191                         for k in temp:
192                             k += Vector([depth + self.sp, 0, 0])
193                 elif self.typ_t in ["tId3", "tId4", "tId5"]:
194                     self.G.Make_mesh(coords,self.out_faces,'treads')
195                     temp = []
196                     for j in coords2:
197                         temp.append(copy(j))
198                     for j in range(self.sec):
199                         self.G.Make_mesh(temp,self.G.faces,'bars')
200                         for k in temp:
201                             k += Vector([offset + self.sp, 0, 0])
202                     for j in coords2:
203                         j += Vector([self.d, 0, self.r])
204                     temp = []
205                     for j in coords3:
206                         temp.append(copy(j))
207                     for j in range(self.sn):
208                         self.G.Make_mesh(temp,self.G.faces,'crosses')
209                         for k in temp:
210                             k += Vector([0, cW + cross, 0])
211                     for j in coords3:
212                         j += Vector([self.d, 0, self.r])
213                 for j in coords:
214                     j += Vector([self.d,0,self.r])
215         # Circular staircase:
216         elif self.typ in ["id4"]:
217             start = [Vector([0, -self.o, 0]), Vector([0, -self.o, -self.h]),
218                      Vector([0, -self.w, 0]), Vector([0, -self.w, -self.h])]
219             self.d = radians(self.run) / self.n
220             for i in range(self.n):
221                 coords = []
222                 # Base faces.  Should be able to append more sections:
223                 tId4_faces = [[0, 1, 3, 2]]
224                 t_inner = Matrix.Rotation((-self.t / self.o) + (self.d * i), 3, 'Z')
225                 coords.append((t_inner * start[0]) + Vector([0, 0, self.r * i]))
226                 coords.append((t_inner * start[1]) + Vector([0, 0, self.r * i]))
227                 t_outer = Matrix.Rotation((-self.t / self.w) + (self.d * i), 3, 'Z')
228                 coords.append((t_outer * start[2]) + Vector([0, 0, self.r * i]))
229                 coords.append((t_outer * start[3]) + Vector([0, 0, self.r * i]))
230                 k = 0
231                 for j in range(self.deg + 1):
232                     k = (j * 4) + 4
233                     tId4_faces.append([k, k - 4, k - 3, k + 1])
234                     tId4_faces.append([k - 2, k - 1, k + 3, k + 2])
235                     tId4_faces.append([k + 1, k - 3, k - 1, k + 3])
236                     tId4_faces.append([k, k - 4, k - 2, k + 2])
237                     rot = Matrix.Rotation(((self.d * j) / self.deg) + (self.d * i), 3, 'Z')
238                     for v in start:
239                         coords.append((rot * v) + Vector([0, 0, self.r * i]))
240                 tId4_faces.append([k, k + 1, k + 3, k + 2])
241                 self.G.Make_mesh(coords, tId4_faces, 'treads')
242         return