added file location messeges & disabled handler that was crashing on reload or newfile
[blender-addons-contrib.git] / add_mesh_walls / Wallfactory.py
1 # ***** BEGIN GPL LICENSE BLOCK *****
2 #
3 # This program is free software; you may redistribute it, and/or
4 # modify it, under the terms of the GNU General Public License
5 # as published by the Free Software Foundation - either version 2
6 # of the License, or (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, write to:
15 #
16 #       the Free Software Foundation Inc.
17 #       51 Franklin Street, Fifth Floor
18 #       Boston, MA 02110-1301, USA
19 #
20 # or go online at: http://www.gnu.org/licenses/ to view license options.
21 #
22 # ***** END GPL LICENCE BLOCK *****
23
24 #
25 # This module contains the UI definition, display, and processing (create mesh)
26 # functions.
27 #
28 # The routines to generate the vertices for the wall are found in the "Blocks" module.
29 #
30
31
32 import bpy
33 import mathutils
34 from bpy.props import *
35 from add_mesh_walls.Blocks import *
36 #from add_mesh_walls.preset_utils import *
37
38
39 #
40 class add_mesh_wallb(bpy.types.Operator):
41     """Add a wall mesh"""
42     bl_idname = "mesh.wall_add"
43     bl_label = "Add A Masonry Wall"
44     bl_options = {'REGISTER', 'UNDO'} # removes object, does not reset to "last" modification.
45     bl_description = "adds a block wall"
46
47     # UI items - API for properties - User accessable variables... 
48 # not all options are via UI, and some operations just don't work yet.
49
50     # only create object when True
51     # False allows modifying several parameters without creating object
52     ConstructTog = BoolProperty(name="Construct",
53                                 description="Generate the object",
54                                 default = True)
55
56 # need to modify so radial makes a tower (normal); want "flat" setting to make disk (alternate)
57     # make the wall circular - if not sloped it's a flat disc
58     RadialTog = BoolProperty(name="Radial",
59                              description="Make masonry radial",
60                              default = False)
61
62     # curve the wall - if radial creates dome.
63     SlopeTog = BoolProperty(name="Curved",
64                             description="Make masonry sloped, or curved",
65                             default = False)
66
67 #need to review defaults and limits for all of these UI objects.
68
69     # wall area/size
70     WallStart = FloatProperty(name="Start",
71                               description="Left side, or start angle",
72                               default=-10.0, min=-100, max=100.0)
73     WallEnd = FloatProperty(name="End",
74                             description="Right side, or end angle",
75                             default=10.0, min=0.0, max=100.0)
76     WallBottom = FloatProperty(name="Bottom",
77                                description="Lower height or radius",
78                                default=0.0, min=-100, max=100)
79     WallTop = FloatProperty(name="Top",
80                             description="Upper height or radius",
81                             default=15.0, min=0.0, max=100.0)
82     EdgeOffset = FloatProperty(name="Edging",
83                                description="Block staggering on wall sides",
84                                default=0.6, min=0.0, max=100.0)
85
86     # block sizing
87     Width = FloatProperty(name="Width",
88                           description="Average width of each block",
89                           default=1.5, min=0.01, max=100.0)
90     WidthVariance = FloatProperty(name="Variance",
91                                   description="Random variance of block width",
92                                   default=0.5, min=0.0, max=100.0)
93     WidthMinimum = FloatProperty(name="Minimum",
94                                  description="Absolute minimum block width",
95                                  default=0.5, min=0.01, max=100.0)
96     Height = FloatProperty(name="Height",
97                            description="Average Height of each block",
98                            default=0.7, min=0.01, max=100.0)
99     HeightVariance = FloatProperty(name="Variance",
100                                    description="Random variance of block Height",
101                                    default=0.3, min=0.0, max=100.0)
102     HeightMinimum = FloatProperty(name="Minimum",
103                                   description="Absolute minimum block Height",
104                                   default=0.25, min=0.01, max=100.0)
105     Depth = FloatProperty(name="Depth",
106                           description="Average Depth of each block",
107                           default=2.0, min=0.01, max=100.0)
108     DepthVariance = FloatProperty(name="Variance",
109                                   description="Random variance of block Depth",
110                                   default=0.1, min=0.0, max=100.0)
111     DepthMinimum = FloatProperty(name="Minimum",
112                                  description="Absolute minimum block Depth",
113                                  default=1.0, min=0.01, max=100.0)
114     MergeBlock = BoolProperty(name="Merge Blocks",
115                               description="Make big blocks (merge closely adjoining blocks)",
116                               default = False)
117
118     # edging for blocks
119     Grout = FloatProperty(name="Thickness",
120                           description="Distance between blocks",
121                           default=0.1, min=-10.0, max=10.0)
122     GroutVariance = FloatProperty(name="Variance",
123                                   description="Random variance of block Grout",
124                                   default=0.03, min=0.0, max=100.0)
125     GroutDepth = FloatProperty(name="Depth",
126                           description="Grout Depth from the face of the blocks",
127                           default=0.1, min=0.0001, max=10.0)
128     GroutDepthVariance = FloatProperty(name="Variance",
129                                   description="Random variance of block Grout Depth",
130                                   default=0.03, min=0.0, max=100.0)
131     GroutEdge = BoolProperty(name="Edging",
132                              description="Grout perimiter",
133                              default = False)
134
135     #properties for openings
136     Opening1Tog = BoolProperty(name="Opening(s)",description="Make windows or doors", default = True)
137     Opening1Width = FloatProperty(name="Width",
138                                   description="The Width of opening 1",
139                                   default=2.5, min=0.01, max=100.0)
140     Opening1Height = FloatProperty(name="Height",
141                                    description="The Height of opening 1",
142                                    default=3.5, min=0.01, max=100.0)
143     Opening1X = FloatProperty(name="Indent",
144                               description="The x position or spacing of opening 1",
145                               default=5.0, min=-100, max=100.0)
146     Opening1Z = FloatProperty(name="Bottom",
147                               description="The z position of opening 1",
148                               default=5.0, min=-100, max=100.0)
149     Opening1Repeat = BoolProperty(name="Repeat",
150                                   description="make multiple openings, with spacing X1",
151                                   default=False)
152     Opening1TopArchTog = BoolProperty(name="Top Arch",
153                                       description="Add an arch to the top of opening 1",
154                                       default=True)
155     Opening1TopArch = FloatProperty(name="Curve",
156                                     description="Height of the arch on the top of the opening",
157                                     default=2.5, min=0.001, max=100.0)
158     Opening1TopArchThickness = FloatProperty(name="Thickness",
159                                              description="Thickness of the arch on the top of the opening",
160                                              default=0.75, min=0.001, max=100.0)
161     Opening1BtmArchTog = BoolProperty(name="Bottom Arch",
162                                       description="Add an arch to the bottom of opening 1",
163                                       default=False)
164     Opening1BtmArch = FloatProperty(name="Curve",
165                                     description="Height of the arch on the bottom of the opening",
166                                     default=1.0, min=0.01, max=100.0)
167     Opening1BtmArchThickness = FloatProperty(name="Thickness",
168                                              description="Thickness of the arch on the bottom of the opening",
169                                              default=0.5, min=0.01, max=100.0)
170     Opening1Bevel = FloatProperty(name="Bevel",
171                                              description="Angle block face",
172                                              default=0.25, min=-10.0, max=10.0)
173
174
175     # openings on top of wall.
176     CrenelTog = BoolProperty(name="Crenels",
177                              description="Make openings along top of wall",
178                              default = False)
179     CrenelXP = FloatProperty(name="Width %",
180                              description="Gap width in wall based % of wall width",
181                              default=0.25, min=0.10, max=1.0)
182     CrenelZP = FloatProperty(name="Height %",
183                              description="Crenel Height as % of wall height",
184                              default=0.10, min=0.10, max=1.0)
185
186
187     # narrow openings in wall.
188 #need to prevent overlap with arch openings - though inversion is an interesting effect.
189     SlotTog = BoolProperty(name="Slots",
190                            description="Make narrow openings in wall",
191                            default = False)
192     SlotRpt = BoolProperty(name="Repeat",
193                            description="Repeat slots along wall",
194                            default = False)
195     SlotWdg = BoolProperty(name="Wedged (n/a)",
196                            description="Bevel edges of slots",
197                            default = False)
198     SlotX = FloatProperty(name="Indent",
199                           description="The x position or spacing of slots",
200                           default=0.0, min=-100, max=100.0)
201     SlotGap = FloatProperty(name="Opening",
202                             description="The opening size of slots",
203                             default=0.5, min=0.10, max=100.0)
204     SlotV = BoolProperty(name="Vertical",
205                          description="Vertical slots",
206                          default = True)
207     SlotVH = FloatProperty(name="Height",
208                            description="Height of vertical slot",
209                            default=3.5, min=0.10, max=100.0)
210     SlotVBtm = FloatProperty(name="Bottom",
211                              description="Z position for slot",
212                              default=5.00, min=-100.0, max=100.0)
213     SlotH = BoolProperty(name="Horizontal",
214                          description="Horizontal slots",
215                          default = False)
216     SlotHW = FloatProperty(name="Width",
217                            description="Width of horizontal slot",
218                            default=2.5, min=0.10, max=100.0)
219 #this should offset from VBtm... maybe make a % like crenels?
220     SlotHBtm = FloatProperty(name="Bottom",
221                              description="Z position for horizontal slot",
222                              default=5.50, min=-100.0, max=100.0)
223
224
225     #properties for shelf (extend blocks in area)
226     ShelfTog = BoolProperty(name="Shelf",description="Add blocks in area by depth to make shelf/platform", default = False)
227     ShelfX = FloatProperty(name="Left",
228                               description="The x position of Shelf",
229                               default=-5.00, min=-100, max=100.0)
230     ShelfZ = FloatProperty(name="Bottom",
231                               description="The z position of Shelf",
232                               default=10.0, min=-100, max=100.0)
233     ShelfH = FloatProperty(name="Height",
234                                    description="The Height of Shelf area",
235                                    default=1.0, min=0.01, max=100.0)
236     ShelfW = FloatProperty(name="Width",
237                                   description="The Width of shelf area",
238                                   default=5.0, min=0.01, max=100.0)
239     ShelfD = FloatProperty(name="Depth",
240                           description="Depth of each block for shelf (from cursor + 1/2 wall depth)",
241                           default=2.0, min=0.01, max=100.0)
242     ShelfBack = BoolProperty(name="Backside",description="Shelf on backside of wall", default = False)
243
244
245     #properties for steps (extend blocks in area, progressive width)
246     StepTog = BoolProperty(name="Steps",description="Add blocks in area by depth with progressive width to make steps", default = False)
247     StepX = FloatProperty(name="Left",
248                               description="The x position of steps",
249                               default=-9.00, min=-100, max=100.0)
250     StepZ = FloatProperty(name="Bottom",
251                               description="The z position of steps",
252                               default=0.0, min=-100, max=100.0)
253     StepH = FloatProperty(name="Height",
254                                    description="The Height of step area",
255                                    default=10.0, min=0.01, max=100.0)
256     StepW = FloatProperty(name="Width",
257                                   description="The Width of step area",
258                                   default=8.0, min=0.01, max=100.0)
259     StepD = FloatProperty(name="Depth",
260                           description="Depth of each block for steps (from cursor + 1/2 wall depth)",
261                           default=1.0, min=0.01, max=100.0)
262     StepV = FloatProperty(name="Riser",
263                                   description="Height of each step",
264                                   default=0.70, min=0.01, max=100.0)
265     StepT = FloatProperty(name="Tread",
266                           description="Width of each step",
267                           default=1.0, min=0.01, max=100.0)
268     StepLeft = BoolProperty(name="High Left",description="Height left; else Height right", default = False)
269     StepOnly = BoolProperty(name="No Blocks",description="Steps only, no supporting blocks", default = False)
270     StepBack = BoolProperty(name="Backside",description="Steps on backside of wall", default = False)
271
272 ##
273 ##
274 #####
275 # Show the UI - expose the properties.
276 #####
277 ##
278 ##
279     # Display the toolbox options
280
281     def draw(self, context):
282
283         layout = self.layout
284
285         box = layout.box()
286         box.prop(self, 'ConstructTog')
287
288 # Wall area (size/position)
289         box = layout.box()
290         box.label(text='Wall Size (area)')
291         box.prop(self, 'WallStart')
292         box.prop(self, 'WallEnd')
293         box.prop(self, 'WallBottom')
294         box.prop(self, 'WallTop')
295         box.prop(self, 'EdgeOffset')
296
297 # Wall block sizing
298         box = layout.box()
299         box.label(text='Block Sizing')
300         box.prop(self, 'MergeBlock')
301 #add checkbox for "fixed" sizing (ignore variance) a.k.a. bricks.
302         box.prop(self, 'Width')
303         box.prop(self, 'WidthVariance')
304         box.prop(self, 'WidthMinimum')
305         box.prop(self, 'Height')
306         box.prop(self, 'HeightVariance')
307         box.prop(self, 'HeightMinimum')
308         box.prop(self, 'Depth')
309         box.prop(self, 'DepthVariance')
310         box.prop(self, 'DepthMinimum')
311
312 # grout settings
313         box = layout.box()
314         bl_label = "Grout"
315         box.label(text='Grout')
316         box.prop(self, 'Grout')
317         box.prop(self, 'GroutVariance')
318         box.prop(self, 'GroutDepth')
319         box.prop(self, 'GroutDepthVariance')
320 #               box.prop(self, 'GroutEdge')
321
322 # Wall shape modifiers
323         box = layout.box()
324         box.label(text='Wall Shape')
325         box.prop(self, 'RadialTog')
326         box.prop(self, 'SlopeTog')
327
328 # Openings (doors, windows; arched)
329         box = layout.box()
330         box.prop(self, 'Opening1Tog')
331         if self.properties.Opening1Tog:
332             box.prop(self, 'Opening1Width')
333             box.prop(self, 'Opening1Height')
334             box.prop(self, 'Opening1X')
335             box.prop(self, 'Opening1Z')
336             box.prop(self, 'Opening1Bevel')
337             box.prop(self, 'Opening1Repeat')
338             box.prop(self, 'Opening1TopArchTog')
339             box.prop(self, 'Opening1TopArch')
340             box.prop(self, 'Opening1TopArchThickness')
341             box.prop(self, 'Opening1BtmArchTog')
342             box.prop(self, 'Opening1BtmArch')
343             box.prop(self, 'Opening1BtmArchThickness')
344
345 # Slots (narrow openings)
346         box = layout.box()
347         box.prop(self, 'SlotTog')
348         if self.properties.SlotTog:
349 #               box.prop(self, 'SlotWdg')
350             box.prop(self, 'SlotX')
351             box.prop(self, 'SlotGap')
352             box.prop(self, 'SlotRpt')
353             box.prop(self, 'SlotV')
354             box.prop(self, 'SlotVH')
355             box.prop(self, 'SlotVBtm')
356             box.prop(self, 'SlotH')
357             box.prop(self, 'SlotHW')
358             box.prop(self, 'SlotHBtm')
359
360 # Crenels, gaps in top of wall
361         box = layout.box()
362         box.prop(self, 'CrenelTog')
363         if self.properties.CrenelTog:
364             box.prop(self, 'CrenelXP')
365             box.prop(self, 'CrenelZP')
366
367 # Shelfing (protrusions)
368         box = layout.box()
369         box.prop(self, 'ShelfTog')
370         if self.properties.ShelfTog:
371             box.prop(self, 'ShelfX')
372             box.prop(self, 'ShelfZ')
373             box.prop(self, 'ShelfH')
374             box.prop(self, 'ShelfW')
375             box.prop(self, 'ShelfD')
376             box.prop(self, 'ShelfBack')
377
378 # Steps
379         box = layout.box()
380         box.prop(self, 'StepTog')
381         if self.properties.StepTog:
382             box.prop(self, 'StepX')
383             box.prop(self, 'StepZ')
384             box.prop(self, 'StepH')
385             box.prop(self, 'StepW')
386             box.prop(self, 'StepD')
387             box.prop(self, 'StepV')
388             box.prop(self, 'StepT')
389             box.prop(self, 'StepLeft')
390             box.prop(self, 'StepOnly')
391             box.prop(self, 'StepBack')
392
393 ##
394 #####
395 # Respond to UI - get the properties set by user.
396 #####
397 ##
398     # Check and process UI settings to generate masonry
399
400     def execute(self, context):
401
402         global radialized
403         global slope
404         global openingSpecs
405         global bigBlock
406         global shelfExt
407         global stepMod
408         global stepLeft
409         global shelfBack
410         global stepOnly
411         global stepBack
412
413         # Create the wall when enabled (skip regen iterations when off)
414         if not self.properties.ConstructTog: return {'FINISHED'}
415
416         #enter the settings for the wall dimensions (area)
417 # start can't be zero - min/max don't matter [if max less than end] but zero don't workie.
418 # start can't exceed end.
419         if not self.properties.WallStart or self.properties.WallStart >= self.properties.WallEnd:
420             self.properties.WallStart = NOTZERO # Reset UI if input out of bounds...
421
422         dims['s'] = self.properties.WallStart
423         dims['e'] = self.properties.WallEnd
424         dims['b'] = self.properties.WallBottom
425         dims['t'] = self.properties.WallTop
426
427         settings['eoff'] = self.properties.EdgeOffset
428
429         #retrieve the settings for the wall block properties
430         settings['w'] = self.properties.Width
431         settings['wv'] = self.properties.WidthVariance
432         settings['wm'] = self.properties.WidthMinimum
433         if not radialized: settings['sdv'] = settings['w'] 
434         else: settings['sdv'] = 0.12
435
436         settings['h'] = self.properties.Height
437         settings['hv'] = self.properties.HeightVariance
438         settings['hm'] = self.properties.HeightMinimum
439
440         settings['d'] = self.properties.Depth
441         settings['dv'] = self.properties.DepthVariance
442         settings['dm'] = self.properties.DepthMinimum
443
444         if self.properties.MergeBlock:
445             bigBlock = 1
446         else: bigBlock = 0
447
448         settings['g'] = self.properties.Grout
449         settings['gv'] = self.properties.GroutVariance
450         settings['gd'] = self.properties.GroutDepth
451         settings['gdv'] = self.properties.GroutDepthVariance
452
453         if self.properties.GroutEdge: settings['ge'] = 1
454         else: settings['ge'] = 0
455
456         # set wall shape modifiers
457         if self.properties.RadialTog:
458             radialized = 1
459 #eliminate to allow user control for start/completion?
460             dims['s'] = 0.0 # complete radial
461             if dims['e'] > PI*2: dims['e'] = PI*2 # max end for circle
462             if dims['b'] < settings['g']: dims['b'] = settings['g'] # min bottom for grout extension
463         else: radialized = 0
464
465         if self.properties.SlopeTog: slope = 1
466         else: slope = 0
467
468
469         shelfExt = 0
470         shelfBack = 0
471
472         # Add shelf if enabled
473         if self.properties.ShelfTog:
474             shelfExt = 1
475             shelfSpecs['h'] = self.properties.ShelfH
476             shelfSpecs['w'] = self.properties.ShelfW
477             shelfSpecs['d'] = self.properties.ShelfD
478             shelfSpecs['x'] = self.properties.ShelfX
479             shelfSpecs['z'] = self.properties.ShelfZ
480
481             if self.properties.ShelfBack:
482                 shelfBack = 1
483
484
485         stepMod = 0
486         stepLeft = 0
487         stepOnly = 0
488         stepBack = 0
489
490         # Make steps if enabled
491         if self.properties.StepTog:
492             stepMod = 1
493             stepSpecs['x'] = self.properties.StepX
494             stepSpecs['z'] = self.properties.StepZ
495             stepSpecs['h'] = self.properties.StepH
496             stepSpecs['w'] = self.properties.StepW
497             stepSpecs['d'] = self.properties.StepD
498             stepSpecs['v'] = self.properties.StepV
499             stepSpecs['t'] = self.properties.StepT
500
501             if self.properties.StepLeft:
502                 stepLeft = 1
503
504             if self.properties.StepOnly:
505                 stepOnly = 1
506
507             if self.properties.StepBack:
508                 stepBack = 1
509
510
511         #enter the settings for the openings
512 #when openings overlap they create inverse stonework - interesting but not the desired effect :)
513 #if opening width == indent*2 the edge blocks fail (row of blocks cross opening) - bug.
514         openingSpecs = []
515         openingIdx = 0 # track opening array references for multiple uses
516
517         # general openings with arch options - can be windows or doors.
518         if self.properties.Opening1Tog:
519             # set defaults...
520             openingSpecs += [{'w':0.5, 'h':0.5, 'x':0.8, 'z':2.7, 'rp':1, 'b':0.0, 'v':0, 'vl':0, 't':0, 'tl':0}]
521
522             openingSpecs[openingIdx]['w'] = self.properties.Opening1Width
523             openingSpecs[openingIdx]['h'] = self.properties.Opening1Height
524             openingSpecs[openingIdx]['x'] = self.properties.Opening1X
525             openingSpecs[openingIdx]['z'] = self.properties.Opening1Z
526             openingSpecs[openingIdx]['rp'] = self.properties.Opening1Repeat
527
528             if self.properties.Opening1TopArchTog:
529                 openingSpecs[openingIdx]['v'] = self.properties.Opening1TopArch
530                 openingSpecs[openingIdx]['t'] = self.properties.Opening1TopArchThickness
531
532             if self.properties.Opening1BtmArchTog:
533                 openingSpecs[openingIdx]['vl'] = self.properties.Opening1BtmArch
534                 openingSpecs[openingIdx]['tl'] = self.properties.Opening1BtmArchThickness
535             
536             openingSpecs[openingIdx]['b'] = self.properties.Opening1Bevel
537
538             openingIdx += 1 # count window/door/arch openings
539
540         # Slots (narrow openings)
541         if self.properties.SlotTog:
542
543             if self.properties.SlotV: # vertical slots
544                 # set defaults...
545                 openingSpecs += [{'w':0.5, 'h':0.5, 'x':0.0, 'z':2.7, 'rp':0, 'b':0.0, 'v':0, 'vl':0, 't':0, 'tl':0}]
546
547                 openingSpecs[openingIdx]['w'] = self.properties.SlotGap
548                 openingSpecs[openingIdx]['h'] = self.properties.SlotVH
549                 openingSpecs[openingIdx]['x'] = self.properties.SlotX
550                 openingSpecs[openingIdx]['z'] = self.properties.SlotVBtm
551                 openingSpecs[openingIdx]['rp'] = self.properties.SlotRpt
552
553                 # make them pointy...
554                 openingSpecs[openingIdx]['v'] = self.properties.SlotGap
555                 openingSpecs[openingIdx]['t'] = self.properties.SlotGap/2
556                 openingSpecs[openingIdx]['vl'] = self.properties.SlotGap
557                 openingSpecs[openingIdx]['tl'] = self.properties.SlotGap/2
558
559                 openingIdx += 1 # count vertical slot openings
560
561 # need to handle overlap of H and V slots...
562
563             if self.properties.SlotH: # Horizontal slots
564                 # set defaults...
565                 openingSpecs += [{'w':0.5, 'h':0.5, 'x':0.0, 'z':2.7, 'rp':0, 'b':0.0, 'v':0, 'vl':0, 't':0, 'tl':0}]
566
567                 openingSpecs[openingIdx]['w'] = self.properties.SlotHW
568                 openingSpecs[openingIdx]['h'] = self.properties.SlotGap
569                 openingSpecs[openingIdx]['x'] = self.properties.SlotX
570                 openingSpecs[openingIdx]['z'] = self.properties.SlotHBtm
571 #horizontal repeat isn't same spacing as vertical...
572                 openingSpecs[openingIdx]['rp'] = self.properties.SlotRpt
573
574                 # make them pointy...
575 # want arc to go sideways... maybe wedge will be sufficient and can skip horiz arcs.
576 #                               openingSpecs[openingIdx]['v'] = self.properties.SlotGap
577 #                               openingSpecs[openingIdx]['t'] = self.properties.SlotGap/2
578 #                               openingSpecs[openingIdx]['vl'] = self.properties.SlotGap
579 #                               openingSpecs[openingIdx]['tl'] = self.properties.SlotGap/2
580
581                 openingIdx += 1 # count horizontal slot openings
582
583
584         # Crenellations (top row openings)
585         if self.properties.CrenelTog:
586
587 # add bottom arch option?
588 # perhaps a repeat toggle...
589 # if crenel opening overlaps with arch opening it fills with blocks...
590
591             # set defaults...
592             openingSpecs += [{'w':0.5, 'h':0.5, 'x':0.0, 'z':2.7, 'rp':1, 'b':0.0, 'v':0, 'vl':0, 't':0, 'tl':0}]
593
594             wallW = self.properties.WallEnd - self.properties.WallStart
595             crenelW = wallW*self.properties.CrenelXP # Width % opening.
596
597             wallH = self.properties.WallTop - self.properties.WallBottom
598             crenelH = wallH*self.properties.CrenelZP # % proportional height.
599
600             openingSpecs[openingIdx]['w'] = crenelW
601             openingSpecs[openingIdx]['h'] = crenelH
602
603             # calculate the spacing between openings.
604             # this isn't the absolute start (left), it's opening center offset relative to cursor (space between openings)...
605             openingSpecs[openingIdx]['x'] = crenelW*2-1 # assume standard spacing
606
607             if not radialized: # normal wall?
608                 # set indent 0 (center) if opening is 50% or more of wall width, no repeat.
609                 if crenelW*2 >= wallW:
610                     openingSpecs[openingIdx]['x'] = 0
611                     openingSpecs[openingIdx]['rp'] = 0
612
613             openingSpecs[openingIdx]['z'] = self.properties.WallTop - (crenelH/2) # set bottom of opening (center of hole)
614
615             openingIdx += 1 # count crenel openings
616
617         #
618         # Process the user settings to generate a wall
619         #
620         # generate the list of vertices for the wall...
621         verts_array, faces_array = createWall(radialized, slope, openingSpecs, bigBlock,
622                 shelfExt, shelfBack, stepMod, stepLeft, stepOnly, stepBack)
623
624         # Create new mesh
625         mesh = bpy.data.meshes.new("Wall")
626
627         # Make a mesh from a list of verts/edges/faces.
628         mesh.from_pydata(verts_array, [], faces_array)
629
630         scene = context.scene
631
632         # Deselect all objects.
633         bpy.ops.object.select_all(action='DESELECT')
634
635         mesh.update()
636
637         ob_new = bpy.data.objects.new("Wall", mesh)
638         scene.objects.link(ob_new)
639 # leave this out to prevent 'Tab key" going into edit mode :):):)
640 # Use rmb click to select and still modify.
641         scene.objects.active = ob_new
642         ob_new.select = True
643
644         ob_new.location = tuple(context.scene.cursor_location)
645         ob_new.rotation_quaternion = [1.0,0.0,0.0,0.0]
646
647         return {'FINISHED'}