Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormeta-androcto <meta.androcto1@gmail.com>2016-06-13 17:33:52 +0300
committermeta-androcto <meta.androcto1@gmail.com>2016-06-13 17:33:52 +0300
commit75fb4e0a91d46bb8695579b6a780d2c9a9aef624 (patch)
treef57f3e6187a2fd2f32362410466c7e2593e6186b
parenteedce73b26ad84af51b8582a93efe7539b6310ce (diff)
fix merge error reported in irc: add blocks file & correct references
-rw-r--r--add_mesh_extra_objects/Blocks.py1683
-rw-r--r--add_mesh_extra_objects/Wallfactory.py2
-rw-r--r--add_mesh_extra_objects/__init__.py3
3 files changed, 1686 insertions, 2 deletions
diff --git a/add_mesh_extra_objects/Blocks.py b/add_mesh_extra_objects/Blocks.py
new file mode 100644
index 00000000..36ef5c0f
--- /dev/null
+++ b/add_mesh_extra_objects/Blocks.py
@@ -0,0 +1,1683 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you may redistribute it, and/or
+# modify it, under the terms of the GNU General Public License
+# as published by the Free Software Foundation - either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, write to:
+#
+# the Free Software Foundation Inc.
+# 51 Franklin Street, Fifth Floor
+# Boston, MA 02110-1301, USA
+#
+# or go online at: http://www.gnu.org/licenses/ to view license options.
+#
+# ***** END GPL LICENCE BLOCK *****
+
+
+##
+#
+# Module notes:
+#
+# Grout needs to be implemented.
+# consider removing wedge crit for small "c" and "cl" values
+# wrap around for openings on radial stonework?
+# auto-clip wall edge to SMALL for radial and domes.
+# unregister doesn't release all references.
+# repeat for opening doesn't distribute evenly when radialized - see wrap around
+# note above.
+# if opening width == indent*2 the edge blocks fail (row of blocks cross opening).
+# if openings overlap fills inverse with blocks - see h/v slots.
+# Negative grout width creates a pair of phantom blocks, seperated by grout
+# width, inside the edges.
+# if block width variance is 0, and edging is on, right edge blocks create a "vertical seam".
+#
+##
+
+# <pep8-80 compliant>
+
+import bpy, time, math
+from random import random
+from math import fmod, sqrt, sin, cos, atan
+
+#A few constants
+SMALL = 0.000000000001
+NOTZERO = 0.01 # for values that must be != 0; see UI options/variables -
+# sort of a bug to be fixed.
+PI = math.pi
+
+#global variables
+
+#General masonry Settings
+settings = {'w': 1.2, 'wv': 0.3, 'h': .6, 'hv': 0.3, 'd': 0.3, 'dv': 0.1,
+ 'g': 0.1, 'gv': 0.07, 'gd': 0.01, 'gdv': 0.0, 'b': 0, 'bv': 0,
+ 'f': 0.0, 'fv': 0.0, 't': 0.0, 'sdv': 0.1, 'hwt': 0.5, 'aln':0,
+ 'wm': 0.8, 'hm': 0.3, 'dm':0.1,
+ 'woff':0.0, 'woffv':0.0, 'eoff':0.3, 'eoffv':0.0, 'rwhl':1,
+ 'hb':0, 'ht':0, 'ge':0, 'physics':0}
+# 'w':width 'wv':widthVariation
+# 'h':height 'hv':heightVariation
+# 'd':depth 'dv':depthVariation
+# 'g':grout 'gv':groutVariation 'gd':groutDepth 'gdv':groutDepthVariation
+# 'b':bevel 'bv':bevelVariation
+# 'f':flawSize 'fv':flawSizeVariation 'ff':flawFraction
+# 't':taper
+# 'sdv':subdivision(distance or angle)
+# 'hwt':row height effect on block widths in the row (0=no effect,
+# 1=1:1 relationship, negative values allowed, 0.5 works well)
+# 'aln':alignment(0=none, 1=rows w/features, 2=features w/rows)
+# (currently un-used)
+# 'wm':width minimum 'hm':height minimum 'dm':depth minimum
+# 'woff':row start offset(fraction of width)
+# 'woffv':width offset variation(fraction of width)
+# 'eoff':edge offset 'eoffv':edge offset variation
+# 'rwhl':row height lock(1 is all blocks in row have same height)
+# 'hb':bottom row height 'ht': top row height 'ge': grout the edges
+# 'physics': set up for physics
+
+# dims = area of wall (face)
+dims = {'s':0, 'e':PI*3/2, 'b':0.1, 't':12.3} # radial
+# 's':start x or theta 'e':end x or theta 'b':bottom z or r 't':top z or r
+# 'w' = e-s and h = t-b; calculated to optimize for various operations/usages
+#dims = {'s':-12, 'e':15, 'w':27, 'b':-15., 't':15., 'h':30}
+#dims = {'s':-bayDim/2, 'e':bayDim/2, 'b':-5., 't':10.} # bay settings?
+
+radialized = 0 # Radiating from one point - round/disc; instead of square
+slope = 0 # Warp/slope; curved over like a vaulted tunnel
+# 'bigblock': merge adjacent blocks into single large blocks
+bigBlock = 0 # Merge blocks
+
+# Gaps in blocks for various apertures.
+#openingSpecs = []
+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}]
+# 'w': opening width, 'h': opening height,
+# 'x': horizontal position, 'z': vertical position,
+# 'rp': make multiple openings, with a spacing of x,
+# 'b': bevel the opening, inside only, like an arrow slit.
+# 'v': height of the top arch, 'vl':height of the bottom arch,
+# 't': thickness of the top arch, 'tl': thickness of the bottom arch
+
+# Add blocks to make platforms.
+shelfExt = 0
+#shelfSpecs = []
+shelfSpecs = {'w':0.5, 'h':0.5, 'd': 0.3, 'x':0.8, 'z':2.7}
+# 'w': block width, 'h': block height, 'd': block depth (shelf size; offset from wall)
+# 'x': horizontal start position, 'z': vertical start position
+
+# Add blocks to make steps.
+stepMod = 0
+stepSpecs = {'x':0.0, 'z':-10, 'w':10.0, 'h':10.0,
+ 'v':0.7, 't':1.0, 'd':1.0 }
+# 'x': horizontal start position, 'z': vertical start position,
+# 'w': step area width, 'h': step area height,
+# 'v': riser height, 't': tread width, 'd': block depth (step size; offset from wall)
+
+
+ #easier way to get to the random function
+def rnd(): return random()
+
+ #random number from -0.5 to 0.5
+def rndc(): return (random() - 0.5)
+
+ #random number from -1.0 to 1.0
+def rndd(): return (random() - 0.5)*2.0
+
+
+#Opening Test suite
+#opening test function
+
+def test(TestN = 13):
+ dims = {'s':-29., 'e':29., 'b':-6., 't':TestN*7.5}
+ openingSpecs = []
+ for i in range(TestN):
+ x = (random() - 0.5) * 6
+ z = i*7.5
+ v = .2 + i*(3./TestN)
+ vl = 3.2 - i*(3./TestN)
+ t = 0.3 + random()
+ tl = 0.3 + random()
+ rn = random()*2
+ openingSpecs += [{'w':3.1 + rn, 'h':0.3 + rn, 'x':float(x),
+ 'z':float(z), 'rp':0, 'b':0.,
+ 'v':float(v), 'vl':float(vl),
+ 't':float(t), 'tl':float(tl)}]
+ return dims, openingSpecs
+
+#dims, openingSpecs = test(15)
+
+
+#For filling a linear space with divisions
+def fill(left, right, avedst, mindst=0.0, dev=0.0, pad=(0.0,0.0), num=0,
+ center=0):
+ __doc__ = """\
+ Fills a linear range with points and returns an ordered list of those points
+ including the end points.
+
+ left: the lower boundary
+ right: the upper boundary
+ avedst: the average distance between points
+ mindst: the minimum distance between points
+ dev: the maximum random deviation from avedst
+ pad: tends to move the points near the bounds right (positive) or
+ left (negative).
+ element 0 pads the lower bounds, element 1 pads the upper bounds
+ num: substitutes a numerical limit for the right limit. fill will then make
+ a num+1 element list
+ center: flag to center the elements in the range, 0 == disabled
+ """
+
+ poslist = [left]
+ curpos = left+pad[0]
+
+ # Set offset by average spacing, then add blocks (fall through);
+ # if not at right edge.
+ if center:
+ curpos += ((right-left-mindst*2)%avedst)/2+mindst
+ if curpos-poslist[-1]<mindst: curpos = poslist[-1]+mindst+rnd()*dev/2
+
+ # clip to right edge.
+ if (right-curpos<mindst) or (right-curpos< mindst-pad[1]):
+ poslist.append(right)
+ return poslist
+
+ else: poslist.append(curpos)
+
+ #unused... for now.
+ if num:
+ idx = len(poslist)
+
+ while idx<num+1:
+ curpos += avedst+rndd()*dev
+ if curpos-poslist[-1]<mindst:
+ curpos = poslist[-1]+mindst+rnd()*dev/2
+ poslist.append(curpos)
+ idx += 1
+
+ return poslist
+
+ # make block edges
+ else:
+ while True: # loop for blocks
+ curpos += avedst+rndd()*dev
+ if curpos-poslist[-1]<mindst:
+ curpos = poslist[-1]+mindst+rnd()*dev/2
+ # close off edges at limit
+ if (right-curpos<mindst) or (right-curpos< mindst-pad[1]):
+ poslist.append(right)
+ return poslist
+
+ else: poslist.append(curpos)
+
+
+#For generating block geometry
+def MakeABlock(bounds, segsize, vll=0, Offsets=None, FaceExclude=[],
+ bevel=0, xBevScl=1):
+ __doc__ = """\
+ MakeABlock returns lists of points and faces to be made into a square
+ cornered block, subdivided along the length, with optional bevels.
+ bounds: a list of boundary positions:
+ 0:left, 1:right, 2:bottom, 3:top, 4:back, 5:front
+ segsize: the maximum size before lengthwise subdivision occurs
+ vll: the number of vertexes already in the mesh. len(mesh.verts) should
+ give this number.
+ Offsets: list of coordinate delta values.
+ Offsets are lists, [x,y,z] in
+ [
+ 0:left_bottom_back,
+ 1:left_bottom_front,
+ 2:left_top_back,
+ 3:left_top_front,
+ 4:right_bottom_back,
+ 5:right_bottom_front,
+ 6:right_top_back,
+ 7:right_top_front,
+ ]
+ FaceExclude: list of faces to exclude from the faces list. see bounds above for indices
+ xBevScl: how much to divide the end (+- x axis) bevel dimensions. Set to current average radius to compensate for angular distortion on curved blocks
+ """
+
+ slices = fill(bounds[0], bounds[1], segsize, segsize, center=1)
+ points = []
+ faces = []
+
+ if Offsets == None:
+ points.append([slices[0],bounds[4],bounds[2]])
+ points.append([slices[0],bounds[5],bounds[2]])
+ points.append([slices[0],bounds[5],bounds[3]])
+ points.append([slices[0],bounds[4],bounds[3]])
+
+ for x in slices[1:-1]:
+ points.append([x,bounds[4],bounds[2]])
+ points.append([x,bounds[5],bounds[2]])
+ points.append([x,bounds[5],bounds[3]])
+ points.append([x,bounds[4],bounds[3]])
+
+ points.append([slices[-1],bounds[4],bounds[2]])
+ points.append([slices[-1],bounds[5],bounds[2]])
+ points.append([slices[-1],bounds[5],bounds[3]])
+ points.append([slices[-1],bounds[4],bounds[3]])
+
+ else:
+ points.append([slices[0]+Offsets[0][0],bounds[4]+Offsets[0][1],bounds[2]+Offsets[0][2]])
+ points.append([slices[0]+Offsets[1][0],bounds[5]+Offsets[1][1],bounds[2]+Offsets[1][2]])
+ points.append([slices[0]+Offsets[3][0],bounds[5]+Offsets[3][1],bounds[3]+Offsets[3][2]])
+ points.append([slices[0]+Offsets[2][0],bounds[4]+Offsets[2][1],bounds[3]+Offsets[2][2]])
+
+ for x in slices[1:-1]:
+ xwt = (x-bounds[0])/(bounds[1]-bounds[0])
+ points.append([x+Offsets[0][0]*(1-xwt)+Offsets[4][0]*xwt,bounds[4]+Offsets[0][1]*(1-xwt)+Offsets[4][1]*xwt,bounds[2]+Offsets[0][2]*(1-xwt)+Offsets[4][2]*xwt])
+ points.append([x+Offsets[1][0]*(1-xwt)+Offsets[5][0]*xwt,bounds[5]+Offsets[1][1]*(1-xwt)+Offsets[5][1]*xwt,bounds[2]+Offsets[1][2]*(1-xwt)+Offsets[5][2]*xwt])
+ points.append([x+Offsets[3][0]*(1-xwt)+Offsets[7][0]*xwt,bounds[5]+Offsets[3][1]*(1-xwt)+Offsets[7][1]*xwt,bounds[3]+Offsets[3][2]*(1-xwt)+Offsets[7][2]*xwt])
+ points.append([x+Offsets[2][0]*(1-xwt)+Offsets[6][0]*xwt,bounds[4]+Offsets[2][1]*(1-xwt)+Offsets[6][1]*xwt,bounds[3]+Offsets[2][2]*(1-xwt)+Offsets[6][2]*xwt])
+
+ points.append([slices[-1]+Offsets[4][0],bounds[4]+Offsets[4][1],bounds[2]+Offsets[4][2]])
+ points.append([slices[-1]+Offsets[5][0],bounds[5]+Offsets[5][1],bounds[2]+Offsets[5][2]])
+ points.append([slices[-1]+Offsets[7][0],bounds[5]+Offsets[7][1],bounds[3]+Offsets[7][2]])
+ points.append([slices[-1]+Offsets[6][0],bounds[4]+Offsets[6][1],bounds[3]+Offsets[6][2]])
+
+ faces.append([vll,vll+3,vll+2,vll+1])
+
+ for x in range(len(slices)-1):
+ faces.append([vll,vll+1,vll+5,vll+4])
+ vll+=1
+ faces.append([vll,vll+1,vll+5,vll+4])
+ vll+=1
+ faces.append([vll,vll+1,vll+5,vll+4])
+ vll+=1
+ faces.append([vll,vll-3,vll+1,vll+4])
+ vll+=1
+
+ faces.append([vll,vll+1,vll+2,vll+3])
+
+ return points, faces
+#
+#
+#
+
+#For generating Keystone Geometry
+def MakeAKeystone(xpos, width, zpos, ztop, zbtm, thick, bevel, vll=0, FaceExclude=[], xBevScl=1):
+ __doc__ = """\
+ MakeAKeystone returns lists of points and faces to be made into a square cornered keystone, with optional bevels.
+ xpos: x position of the centerline
+ width: x width of the keystone at the widest point (discounting bevels)
+ zpos: z position of the widest point
+ ztop: distance from zpos to the top
+ zbtm: distance from zpos to the bottom
+ thick: thickness
+ bevel: the amount to raise the back vertex to account for arch beveling
+ vll: the number of vertexes already in the mesh. len(mesh.verts) should give this number
+ faceExclude: list of faces to exclude from the faces list. 0:left, 1:right, 2:bottom, 3:top, 4:back, 5:front
+ xBevScl: how much to divide the end (+- x axis) bevel dimensions. Set to current average radius to compensate for angular distortion on curved blocks
+ """
+
+ points = []
+ faces = []
+ faceinclude = [1 for x in range(6)]
+ for x in FaceExclude: faceinclude[x]=0
+ Top = zpos + ztop
+ Btm = zpos - zbtm
+ Wid = width/2.
+ Thk = thick/2.
+
+ # The front top point
+ points.append([xpos, Thk, Top])
+ # The front left point
+ points.append([xpos-Wid, Thk, zpos])
+ # The front bottom point
+ points.append([xpos, Thk, Btm])
+ # The front right point
+ points.append([xpos+Wid, Thk, zpos])
+
+ MirrorPoints = []
+ for i in points:
+ MirrorPoints.append([i[0],-i[1],i[2]])
+ points += MirrorPoints
+ points[6][2] += bevel
+
+ faces.append([3,2,1,0])
+ faces.append([4,5,6,7])
+ faces.append([4,7,3,0])
+ faces.append([5,4,0,1])
+ faces.append([6,5,1,2])
+ faces.append([7,6,2,3])
+ # Offset the vertex numbers by the number of verticies already in the list
+ for i in range(len(faces)):
+ for j in range(len(faces[i])): faces[i][j] += vll
+
+ return points, faces
+
+
+#for finding line/circle intercepts
+def circ(offs=0.,r=1.):
+ __doc__ = """\
+ offs is the distance perpendicular to the line to the center of the circle
+ r is the radius of the circle
+ circ returns the distance paralell to the line to the center of the circle at the intercept.
+ """
+ offs = abs(offs)
+ if offs > r: return None
+ elif offs == r: return 0.
+ else: return sqrt(r**2 - offs**2)
+
+
+#class openings in the wall
+class opening:
+ __doc__ = """\
+ This is the class for holding the data for the openings in the wall.
+ It has methods for returning the edges of the opening for any given position value,
+ as well as bevel settings and top and bottom positions.
+ It stores the 'style' of the opening, and all other pertinent information.
+ """
+ # x = 0. # x position of the opening
+ # z = 0. # x position of the opening
+ # w = 0. # width of the opening
+ # h = 0. # height of the opening
+ r = 0 # top radius of the arch (derived from 'v')
+ rl = 0 # lower radius of the arch (derived from 'vl')
+ rt = 0 # top arch thickness
+ rtl = 0# lower arch thickness
+ ts = 0 # Opening side thickness, if greater than average width, replaces it.
+ c = 0 # top arch corner position (for low arches), distance from the top of the straight sides
+ cl = 0 # lower arch corner position (for low arches), distance from the top of the straight sides
+ # form = 0 # arch type (unused for now)
+ # b = 0. # back face bevel distance, like an arrow slit
+ v = 0. # top arch height
+ vl = 0.# lower arch height
+ # variable "s" is used for "side" in the "edge" function.
+ # it is a signed int, multiplied by the width to get + or - of the center
+
+ def btm(self):
+ if self.vl <= self.w/2 : return self.z-self.h/2-self.vl-self.rtl
+ else: return self.z - sqrt((self.rl+self.rtl)**2 - (self.rl - self.w/2 )**2) - self.h/2
+
+
+ def top(self):
+ if self.v <= self.w/2 : return self.z+self.h/2+self.v+self.rt
+ else: return sqrt((self.r+self.rt)**2 - (self.r - self.w/2 )**2) + self.z + self.h/2
+
+
+ #crits returns the critical split points, or discontinuities, used for making rows
+ def crits(self):
+ critlist = []
+ if self.vl>0: # for lower arch
+ # add the top point if it is pointed
+ #if self.vl >= self.w/2.: critlist.append(self.btm())
+ if self.vl < self.w/2.:#else: for low arches, with wedge blocks under them
+ #critlist.append(self.btm())
+ critlist.append(self.z-self.h/2 - self.cl)
+
+ if self.h>0: # if it has a height, append points at the top and bottom of the main square section
+ critlist += [self.z-self.h/2,self.z+self.h/2]
+ else: # otherwise, append just one in the center
+ critlist.append(self.z)
+
+ if self.v>0: # for the upper arch
+ if self.v < self.w/2.: # add the splits for the upper wedge blocks, if needed
+ critlist.append(self.z+self.h/2 + self.c)
+ #critlist.append(self.top())
+ #otherwise just add the top point, if it is pointed
+ #else: critlist.append(self.top())
+
+ return critlist
+
+
+ # get the side position of the opening.
+ # ht is the z position; s is the side: 1 for right, -1 for left
+ # if the height passed is above or below the opening, return None
+ #
+ def edgeS(self, ht, s):
+ # set the row radius: 1 for standard wall (flat)
+ if radialized:
+ if slope: r1 = abs(dims['t']*sin(ht*PI/(dims['t']*2)))
+ else: r1 = abs(ht)
+ else: r1 = 1
+
+ #Go through all the options, and return the correct value
+ if ht < self.btm(): #too low
+ return None
+ elif ht > self.top(): #too high
+ return None
+
+ # Check for circ returning None - prevent TypeError (script failure) with float.
+
+ # in this range, pass the lower arch info
+ elif ht <= self.z-self.h/2-self.cl:
+ if self.vl > self.w/2:
+ circVal = circ(ht-self.z+self.h/2,self.rl+self.rtl)
+ if circVal == None:
+ return None
+ else: return self.x + s*(self.w/2.-self.rl+circVal)/r1
+ else:
+ circVal = circ(ht-self.z+self.h/2+self.vl-self.rl,self.rl+self.rtl)
+ if circVal == None:
+ return None
+ else: return self.x + s*circVal/r1
+
+ #in this range, pass the top arch info
+ elif ht >= self.z+self.h/2+self.c:
+ if self.v > self.w/2:
+ circVal = circ(ht-self.z-self.h/2,self.r+self.rt)
+ if circVal == None:
+ return None
+ else: return self.x + s*(self.w/2.-self.r+circVal)/r1
+ else:
+ circVal = circ(ht-(self.z+self.h/2+self.v-self.r),self.r+self.rt)
+ if circVal == None:
+ return None
+ else: return self.x + s*circVal/r1
+
+ #in this range pass the lower corner edge info
+ elif ht <= self.z-self.h/2:
+ d = sqrt(self.rtl**2 - self.cl**2)
+ if self.cl > self.rtl/sqrt(2.): return self.x + s*(self.w/2 + (self.z - self.h/2 - ht)*d/self.cl)/r1
+ else: return self.x + s*( self.w/2 + d )/r1
+
+ #in this range pass the upper corner edge info
+ elif ht >= self.z+self.h/2:
+ d = sqrt(self.rt**2 - self.c**2)
+ if self.c > self.rt/sqrt(2.): return self.x + s*(self.w/2 + (ht - self.z - self.h/2 )*d/self.c)/r1
+ else: return self.x + s*( self.w/2 + d )/r1
+
+ #in this range, pass the middle info (straight sides)
+ else: return self.x + s*self.w/2/r1
+
+
+ # get the top or bottom of the opening
+ # ht is the x position; s is the side: 1 for top, -1 for bottom
+ #
+ def edgeV(self, ht, s):
+ dist = abs(self.x-ht)
+ def radialAdjust(dist, sideVal):
+ """take the distance and adjust for radial geometry, return dist.
+ """
+ if radialized:
+ if slope:
+ dist = dist * abs(dims['t']*sin(sideVal*PI/(dims['t']*2)))
+ else:
+ dist = dist * sideVal
+ return dist
+
+ if s > 0 :#and (dist <= self.edgeS(self.z+self.h/2+self.c,1)-self.x): #check top down
+ #hack for radialized masonry, import approx Z instead of self.top()
+ dist = radialAdjust(dist, self.top())
+
+ #no arch on top, flat
+ if not self.r: return self.z+self.h/2
+
+ #pointed arch on top
+ elif self.v > self.w/2:
+ circVal = circ(dist-self.w/2+self.r,self.r+self.rt)
+ if circVal == None:
+ return None
+ else: return self.z+self.h/2+circVal
+
+ #domed arch on top
+ else:
+ circVal = circ(dist,self.r+self.rt)
+ if circVal == None:
+ return None
+ else: return self.z+self.h/2+self.v-self.r+circVal
+
+ else:#and (dist <= self.edgeS(self.z-self.h/2-self.cl,1)-self.x): #check bottom up
+ #hack for radialized masonry, import approx Z instead of self.top()
+ dist = radialAdjust(dist, self.btm())
+
+ #no arch on bottom
+ if not self.rl: return self.z-self.h/2
+
+ #pointed arch on bottom
+ elif self.vl > self.w/2:
+ circVal = circ(dist-self.w/2+self.rl,self.rl+self.rtl)
+ if circVal == None:
+ return None
+ else: return self.z-self.h/2-circVal
+
+ #old conditional? if (dist-self.w/2+self.rl)<=(self.rl+self.rtl):
+ #domed arch on bottom
+ else:
+ circVal = circ(dist,self.rl+self.rtl) # dist-self.w/2+self.rl
+ if circVal == None:
+ return None
+ else: return self.z-self.h/2-self.vl+self.rl-circVal
+
+ # and this never happens - but, leave it as failsafe :)
+ print("got all the way out of the edgeV! Not good!")
+ print("opening x = ", self.x, ", opening z = ", self.z)
+ return 0.0
+ #
+ def edgeBev(self, ht):
+ if ht > (self.z + self.h/2): return 0.0
+ if ht < (self.z - self.h/2): return 0.0
+ if radialized:
+ if slope: r1 = abs(dims['t']*sin(ht*PI/(dims['t']*2)))
+ else: r1 = abs(ht)
+ else: r1 = 1
+ bevel = self.b / r1
+ return bevel
+#
+##
+#
+
+ def __init__(self, xpos, zpos, width, height, archHeight=0, archThk=0,
+ archHeightLower=0, archThkLower=0, bevel=0, edgeThk=0):
+ self.x = float(xpos)
+ self.z = float(zpos)
+ self.w = float(width)
+ self.h = float(height)
+ self.rt = archThk
+ self.rtl = archThkLower
+ self.v = archHeight
+ self.vl = archHeightLower
+ if self.w <= 0: self.w = SMALL
+
+ #find the upper arch radius
+ if archHeight >= width/2:
+ # just one arch, low long
+ self.r = (self.v**2)/self.w + self.w/4
+ elif archHeight <= 0:
+ # No arches
+ self.r = 0
+ self.v = 0
+ else:
+ # Two arches
+ self.r = (self.w**2)/(8*self.v) + self.v/2.
+ self.c = self.rt*cos(atan(self.w/(2*(self.r-self.v))))
+
+ #find the lower arch radius
+ if archHeightLower >= width/2:
+ self.rl = (self.vl**2)/self.w + self.w/4
+ elif archHeightLower <= 0:
+ self.rl = 0
+ self.vl = 0
+ else:
+ self.rl = (self.w**2)/(8*self.vl) + self.vl/2.
+ self.cl = self.rtl*cos(atan(self.w/(2*(self.rl-self.vl))))
+
+ #self.form = something?
+ self.b = float(bevel)
+ self.ts = edgeThk
+#
+#
+
+#class for the whole wall boundaries; a sub-class of "opening"
+class OpeningInv(opening):
+ #this is supposed to switch the sides of the opening
+ #so the wall will properly enclose the whole wall.
+ #We'll see if it works.
+
+ def edgeS(self, ht, s):
+ return opening.edgeS(self, ht, -s)
+
+ def edgeV(self, ht, s):
+ return opening.edgeV(self, ht, -s)
+
+#class rows in the wall
+class rowOb:
+ __doc__ = """\
+ This is the class for holding the data for individual rows of blocks.
+ each row is required to have some edge blocks, and can also have
+ intermediate sections of "normal" blocks.
+ """
+
+ #z = 0.
+ #h = 0.
+ radius = 1
+ EdgeOffset = 0.
+# BlocksEdge = []
+# RowSegments = []
+# BlocksNorm = []
+
+ def FillBlocks(self):
+ # Set the radius variable, in the case of radial geometry
+ if radialized:
+ if slope: self.radius = dims['t']*(sin(self.z*PI/(dims['t']*2)))
+ else: self.radius = self.z
+
+ #initialize internal variables from global settings
+
+ SetH = settings['h']
+ SetHwt = settings['hwt']
+ SetWid = settings['w']
+ SetWidMin = settings['wm']
+ SetWidVar = settings['wv']
+ SetGrt = settings['g']
+ SetGrtVar = settings['gv']
+ SetRowHeightLink = settings['rwhl']
+ SetDepth = settings['d']
+ SetDepthVar = settings['dv']
+
+ #height weight, used for making shorter rows have narrower blocks, and vice-versa
+ hwt = ((self.h/SetH-1)*SetHwt+1)
+
+ # set variables for persistent values: loop optimization, readability, single ref for changes.
+
+ avgDist = hwt*SetWid/self.radius
+ minDist = SetWidMin/self.radius
+ deviation = hwt*SetWidVar/self.radius
+ grtOffset = SetGrt/(2*self.radius)
+
+ # init loop variables that may change...
+
+ grt = (SetGrt + rndc()*SetGrtVar)/(self.radius)
+ ThisBlockHeight = self.h+rndc()*(1-SetRowHeightLink)*SetGrtVar
+ ThisBlockDepth = rndd()*SetDepthVar+SetDepth
+
+ for segment in self.RowSegments:
+ divs = fill(segment[0]+grtOffset, segment[1]-grtOffset, avgDist, minDist, deviation)
+
+ #loop through the divisions, adding blocks for each one
+ for i in range(len(divs)-1):
+ ThisBlockx = (divs[i]+divs[i+1])/2
+ ThisBlockw = divs[i+1]-divs[i]-grt
+
+ self.BlocksNorm.append([ThisBlockx, self.z, ThisBlockw, ThisBlockHeight, ThisBlockDepth, None])
+
+ if SetDepthVar: # vary depth
+ ThisBlockDepth = rndd()*SetDepthVar+SetDepth
+
+ if SetGrtVar: # vary grout
+ grt = (SetGrt + rndc()*SetGrtVar)/(self.radius)
+ ThisBlockHeight = self.h+rndc()*(1-SetRowHeightLink)*SetGrtVar
+
+
+ def __init__(self,centerheight,rowheight,edgeoffset = 0.):
+ self.z = float(centerheight)
+ self.h = float(rowheight)
+ self.EdgeOffset = float(edgeoffset)
+
+#THIS INITILIZATION IS IMPORTANT! OTHERWISE ALL OBJECTS WILL HAVE THE SAME LISTS!
+ self.BlocksEdge = []
+ self.RowSegments = []
+ self.BlocksNorm = []
+
+#
+def arch(ra,rt,x,z, archStart, archEnd, bevel, bevAngle, vll):
+ __doc__ = """\
+ Makes a list of faces and vertexes for arches.
+ ra: the radius of the arch, to the center of the bricks
+ rt: the thickness of the arch
+ x: x center location of the circular arc, as if the arch opening were centered on x = 0
+ z: z center location of the arch
+ anglebeg: start angle of the arch, in radians, from vertical?
+ angleend: end angle of the arch, in radians, from vertical?
+ bevel: how much to bevel the inside of the arch.
+ vll: how long is the vertex list already?
+ """
+ avlist = []
+ aflist = []
+
+ #initialize internal variables for global settings
+#overkill?
+ SetH = settings['h']
+ SetHwt = settings['hwt']
+ SetWid = settings['w']
+ SetWidMin = settings['wm']
+ SetWidVar = settings['wv']
+ SetGrt = settings['g']
+ SetGrtVar = settings['gv']
+ SetRowHeightLink = settings['rwhl']
+ SetDepth = settings['d']
+ SetDepthVar = settings['dv']
+
+ # Init loop variables
+
+ def bevelEdgeOffset(offsets, bevel, side):
+ """
+ Take the block offsets and modify it for the correct bevel.
+
+ offsets = the offset list. See MakeABlock
+ bevel = how much to offset the edge
+ side = -1 for left (right side), 1 for right (left side)
+ """
+ left = (0,2,3)
+ right = (4,6,7)
+ if side == 1: pointsToAffect = right
+ else: pointsToAffect = left
+ for num in pointsToAffect:
+ offsets[num] = offsets[num][:]
+ offsets[num][0] += -bevel * side
+
+ ArchInner = ra-rt/2
+ ArchOuter = ra+rt/2-SetGrt + rndc()*SetGrtVar
+
+ DepthBack = -SetDepth/2-rndc()*SetDepthVar
+ DepthFront = SetDepth/2+rndc()*SetDepthVar
+
+ if radialized: subdivision = settings['sdv']
+ else: subdivision = 0.12
+
+ grt = (SetGrt + rndc()*SetGrtVar)/(2*ra) # init grout offset for loop
+ # set up the offsets, it will be the same for every block
+ offsets = ([[0]*2 + [bevel]] + [[0]*3]*3)*2
+
+ #make the divisions in the "length" of the arch
+ divs = fill(archStart, archEnd, settings['w']/ra, settings['wm']/ra, settings['wv']/ra)
+
+ for i in range(len(divs)-1):
+ if i == 0:
+ ThisOffset = offsets[:]
+ bevelEdgeOffset(ThisOffset, bevAngle, -1)
+ elif i == len(divs)-2:
+ ThisOffset = offsets[:]
+ bevelEdgeOffset(ThisOffset, bevAngle, 1)
+ else:
+ ThisOffset = offsets
+
+ geom = MakeABlock([divs[i]+grt, divs[i+1]-grt, ArchInner, ArchOuter, DepthBack, DepthFront],
+ subdivision, len(avlist) + vll, ThisOffset, [], None, ra)
+
+ avlist += geom[0]
+ aflist += geom[1]
+
+ if SetDepthVar: # vary depth
+ DepthBack = -SetDepth/2-rndc()*SetDepthVar
+ DepthFront = SetDepth/2+rndc()*SetDepthVar
+
+ if SetGrtVar: # vary grout
+ grt = (settings['g'] + rndc()*SetGrtVar)/(2*ra)
+ ArchOuter = ra+rt/2-SetGrt + rndc()*SetGrtVar
+
+ for i,vert in enumerate(avlist):
+ v0 = vert[2]*sin(vert[0]) + x
+ v1 = vert[1]
+ v2 = vert[2]*cos(vert[0]) + z
+
+ if radialized==1:
+ if slope==1: r1 = dims['t']*(sin(v2*PI/(dims['t']*2)))
+ else: r1 = v2
+ v0 = v0/r1
+
+ avlist[i] = [v0,v1,v2]
+
+ return (avlist,aflist)
+
+#
+def sketch():
+ __doc__ = """\
+ The 'sketch' function creates a list of openings from the general specifications passed to it.
+ It takes curved and domed walls into account, placing the openings at the appropriate angular locations
+ """
+ boundlist = []
+ for x in openingSpecs:
+ if x['rp']:
+ if radialized: r1 = x['z']
+ else: r1 = 1
+
+ if x['x'] > (x['w'] + settings['wm']):spacing = x['x']/r1
+ else: spacing = (x['w'] + settings['wm'])/r1
+
+ minspacing = (x['w'] + settings['wm'])/r1
+
+ divs = fill(dims['s'],dims['e'],spacing,minspacing,center=1)
+
+ for posidx in range(len(divs)-2):
+ boundlist.append(opening(divs[posidx+1],x['z'],x['w'],x['h'],x['v'],x['t'],x['vl'],x['tl'],x['b']))
+
+ else: boundlist.append(opening(x['x'],x['z'],x['w'],x['h'],x['v'],x['t'],x['vl'],x['tl'],x['b']))
+ #check for overlaping edges?
+
+ return boundlist
+
+
+def wedgeBlocks(row, opening, leftPos, rightPos, edgeBinary, r1):
+ __doc__ = """\
+ Makes wedge blocks for the left and right sides, depending
+ example:
+ wedgeBlocks(row, LeftWedgeEdge, LNerEdge, LEB, r1)
+ wedgeBlocks(row, RNerEdge, RightWedgeEdge, REB, r1)
+ """
+ wedgeEdges = fill(leftPos, rightPos, settings['w']/r1, settings['wm']/r1,
+ settings['wv']/r1)
+
+ for i in range(len(wedgeEdges)-1):
+ x = (wedgeEdges[i+1] + wedgeEdges[i])/2
+ grt = (settings['g'] + rndd()*settings['gv'])/r1
+ w = wedgeEdges[i+1] - wedgeEdges[i] - grt
+
+ ThisBlockDepth = rndd()*settings['dv']+settings['d']
+
+#edgeV may return "None" - causing TypeError for math op.
+#use 0 until wedgeBlocks operation worked out
+ edgeVal = opening.edgeV(x-w/2,edgeBinary)
+ if edgeVal == None: edgeVal = 0.0
+
+ LeftVertOffset = -( row.z - (row.h/2)*edgeBinary - edgeVal )
+
+#edgeV may return "None" - causing TypeError for math op.
+#use 0 until wedgeBlocks operation worked out
+ edgeVal = opening.edgeV(x+w/2,edgeBinary)
+ if edgeVal == None: edgeVal = 0.0
+
+ RightVertOffset = -( row.z - (row.h/2)*edgeBinary - edgeVal )
+
+ #Wedges are on top = off, blank, off, blank
+ #Wedges are on btm = blank, off, blank, off
+ ThisBlockOffsets = [[0,0,LeftVertOffset]]*2 + [[0]*3]*2 + [[0,0,RightVertOffset]]*2
+
+ # Instert or append "blank" for top or bottom wedges.
+ if edgeBinary == 1: ThisBlockOffsets = ThisBlockOffsets + [[0]*3]*2
+ else: ThisBlockOffsets = [[0]*3]*2 + ThisBlockOffsets
+
+ row.BlocksEdge.append([x,row.z,w,row.h,ThisBlockDepth,ThisBlockOffsets])
+
+ return None
+
+def bevelBlockOffsets(offsets, bevel, side):
+ """
+ Take the block offsets and modify it for the correct bevel.
+
+ offsets = the offset list. See MakeABlock
+ bevel = how much to offset the edge
+ side = -1 for left (right side), 1 for right (left side)
+ """
+# left = (4,6)
+# right = (0,2)
+ if side == 1: pointsToAffect = (0,2) # right
+ else: pointsToAffect = (4,6) # left
+ for num in pointsToAffect:
+ offsets[num] = offsets[num][:]
+ offsets[num][0] += bevel * side
+
+def rowProcessing(row, Thesketch, WallBoundaries):
+ __doc__ = """\
+ Take row and opening data and process a single row, adding edge and fill blocks to the row data.
+ """
+ #set end blocks
+ #check for openings, record top and bottom of row for right and left of each
+ #if both top and bottom intersect create blocks on each edge, appropriate to the size of the overlap
+ #if only one side intersects, run fill to get edge positions, but this should never happen
+ #
+
+ if radialized:#this checks for radial stonework, and sets the row radius if required
+ if slope: r1 = abs(dims['t']*sin(row.z*PI/(dims['t']*2)))
+ else: r1 = abs(row.z)
+ else: r1 = 1
+
+ # set the edge grout thickness, especially with radial stonework in mind
+ edgrt = settings['ge']*(settings['g']/2 + rndc()*settings['gv'])/(2*r1)
+
+ # Sets up a list of intersections of top of row with openings,
+ #from left to right [left edge of opening, right edge of opening, etc...]
+ #initially just the left and right edge of the wall
+ edgetop = [[dims['s']+row.EdgeOffset/r1+edgrt,WallBoundaries], [dims['e']+row.EdgeOffset/r1-edgrt,WallBoundaries]]
+ # Same as edgetop, but for the bottms of the rows
+ edgebtm = [[dims['s']+row.EdgeOffset/r1+edgrt,WallBoundaries], [dims['e']+row.EdgeOffset/r1-edgrt,WallBoundaries]]
+
+ # set up some useful values for the top and bottom of the rows.
+ rowTop = row.z+row.h/2
+ rowBtm = row.z-row.h/2
+
+ for hole in Thesketch:
+ #check the top and bottom of the row, looking at the opening from the right
+ e = [hole.edgeS(rowTop, -1), hole.edgeS(rowBtm, -1)]
+
+ # If either one hit the opening, make split points for the left side of the opening.
+ if e[0] or e[1]:
+ e += [hole.edgeS(rowTop, 1), hole.edgeS(rowBtm, 1)]
+
+ # If one of them missed for some reason, set that value to
+ # the middle of the opening.
+ for i,pos in enumerate(e):
+ if pos == None: e[i] = hole.x
+
+ # add the intersects to the list of edge points
+ edgetop.append([e[0],hole])
+ edgetop.append([e[2],hole])
+ edgebtm.append([e[1],hole])
+ edgebtm.append([e[3],hole])
+
+ # We want to make the walls in order, so sort the intersects.
+ # This is where you would want to remove edge points that are out of order
+ # so that you don't get the "oddity where overlapping openings create blocks inversely" problem
+ edgetop.sort()
+ edgebtm.sort()
+
+ #these two loops trim the edges to the limits of the wall. This way openings extending outside the wall don't enlarge the wall.
+ while True:
+ try:
+ if (edgetop[-1][0] > dims['e']+row.EdgeOffset/r1) or (edgebtm[-1][0] > dims['e']+row.EdgeOffset/r1):
+ edgetop[-2:] = []
+ edgebtm[-2:] = []
+ else: break
+ except IndexError: break
+ #still trimming the edges...
+ while True:
+ try:
+ if (edgetop[0][0] < dims['s']+row.EdgeOffset/r1) or (edgebtm[0][0] < dims['s']+row.EdgeOffset/r1):
+ edgetop[:2] = []
+ edgebtm[:2] = []
+ else: break
+ except IndexError: break
+
+ #make those edge blocks and rows! Wooo!
+ #This loop goes through each section, (a pair of points in edgetop)
+ #and places the edge blocks and inbetween normal block zones into the row object
+ for OpnSplitNo in range(int(len(edgetop)/2)):
+ #left edge is edge<x>[2*OpnSplitNo], right edge edgex[2*OpnSplitNo+1]
+ leftEdgeIndex = 2*OpnSplitNo
+ rightEdgeIndex = 2*OpnSplitNo + 1
+ # get the openings, to save time and confusion
+ leftOpening = edgetop[leftEdgeIndex][1]
+ rightOpening = edgetop[rightEdgeIndex][1]
+ #find the difference between the edge top and bottom on both sides
+ LTop = edgetop[leftEdgeIndex][0]
+ LBtm = edgebtm[leftEdgeIndex][0]
+ RTop = edgetop[rightEdgeIndex][0]
+ RBtm = edgebtm[rightEdgeIndex][0]
+ LDiff = LBtm-LTop
+ RDiff = RTop-RBtm
+
+ #which is furthur out on each side, top or bottom?
+ if LDiff > 0:
+ LFarEdge = LTop #The furthest edge left
+ LNerEdge = LBtm #the nearer edge left
+ LEB = 1 #Left Edge Boolean, set to 1 if furthest edge is top, -1 if it is bottom
+ else:
+ LFarEdge = LBtm
+ LNerEdge = LTop
+ LEB = -1
+
+ if RDiff > 0:
+ RFarEdge = RTop #The furthest edge right
+ RNerEdge = RBtm #the nearer edge right
+ REB = 1 #Right Edge Boolean, set to 1 if furthest edge is top, -1 if it is bottom
+
+ else:
+ RFarEdge = RBtm #The furthest edge right
+ RNerEdge = RTop
+ REB = -1 #Right Edge Boolean, set to 1 if furthest edge is top, -1 if it is bottom
+
+ #The space between the closest edges of the openings in this section of the row
+ InnerDiff = RNerEdge - LNerEdge
+ #The mid point between the nearest edges
+ InnerMid = (RNerEdge + LNerEdge)/2
+
+ #maximum distance to span with one block
+ MaxWid = (settings['w']+settings['wv'])/r1
+ AveWid = settings['w']
+ MinWid = settings['wm']
+
+ #check the left and right sides for wedge blocks
+ #Check and run the left edge first
+ #find the edge of the correct side, offset for minimum block height. The LEB decides top or bottom
+ ZPositionCheck = row.z + (row.h/2-settings['hm'])*LEB
+#edgeS may return "None"
+ LeftWedgeEdge = leftOpening.edgeS(ZPositionCheck,1)
+
+ if (abs(LDiff) > AveWid) or (not LeftWedgeEdge):
+ #make wedge blocks
+ if not LeftWedgeEdge: LeftWedgeEdge = leftOpening.x
+ wedgeBlocks(row, leftOpening, LeftWedgeEdge, LNerEdge, LEB, r1)
+ #set the near and far edge settings to vertical, so the other edge blocks don't interfere
+ LFarEdge , LTop , LBtm = LNerEdge, LNerEdge, LNerEdge
+ LDiff = 0
+
+ #Now do the wedge blocks for the right, same drill... repeated code?
+ #find the edge of the correct side, offset for minimum block height. The REB decides top or bottom
+ ZPositionCheck = row.z + (row.h/2-settings['hm'])*REB
+#edgeS may return "None"
+ RightWedgeEdge = rightOpening.edgeS(ZPositionCheck,-1)
+ if (abs(RDiff) > AveWid) or (not RightWedgeEdge):
+ #make wedge blocks
+ if not RightWedgeEdge: RightWedgeEdge = rightOpening.x
+ wedgeBlocks(row, rightOpening, RNerEdge, RightWedgeEdge, REB, r1)
+ #set the near and far edge settings to vertical, so the other edge blocks don't interfere
+ RFarEdge , RTop , RBtm = RNerEdge, RNerEdge, RNerEdge
+ RDiff = 0
+
+ #Check to see if the edges are close enough toegther to warrant a single block filling it
+ if (InnerDiff < MaxWid):
+ #if this is true, then this row is just one block!
+ x = (LNerEdge + RNerEdge)/2.
+ w = InnerDiff
+ ThisBlockDepth = rndd()*settings['dv']+settings['d']
+ BtmOff = LBtm - LNerEdge
+ TopOff = LTop - LNerEdge
+ ThisBlockOffsets = [[BtmOff,0,0]]*2 + [[TopOff,0,0]]*2
+ BtmOff = RBtm - RNerEdge
+ TopOff = RTop - RNerEdge
+ ThisBlockOffsets += [[BtmOff,0,0]]*2 + [[TopOff,0,0]]*2
+ bevel = leftOpening.edgeBev(rowTop)
+ bevelBlockOffsets(ThisBlockOffsets, bevel, 1)
+ bevel = rightOpening.edgeBev(rowTop)
+ bevelBlockOffsets(ThisBlockOffsets, bevel, -1)
+ row.BlocksEdge.append([x,row.z,w,row.h,ThisBlockDepth,ThisBlockOffsets])
+ continue
+
+ # it's not one block, must be two or more
+ # set up the offsets for the left
+ BtmOff = LBtm - LNerEdge
+ TopOff = LTop - LNerEdge
+ leftOffsets = [[BtmOff,0,0]]*2 + [[TopOff,0,0]]*2 + [[0]*3]*4
+ bevelL = leftOpening.edgeBev(rowTop)
+ bevelBlockOffsets(leftOffsets, bevelL, 1)
+ # and now for the right
+ BtmOff = RBtm - RNerEdge
+ TopOff = RTop - RNerEdge
+ rightOffsets = [[0]*3]*4 + [[BtmOff,0,0]]*2 + [[TopOff,0,0]]*2
+ bevelR = rightOpening.edgeBev(rowTop)
+ bevelBlockOffsets(rightOffsets, bevelR, -1)
+ # check to see if it is only two blocks
+ if (InnerDiff < MaxWid*2):
+ #this row is just two blocks! Left block, then right block
+ #div is the x position of the dividing point between the two bricks
+ div = InnerMid + (rndd()*settings['wv'])/r1
+ #set the grout distance, since we need grout seperation between the blocks
+ grt = (settings['g'] + rndc()*settings['gv'])/r1
+ #set the x position and width for the left block
+ x = (div + LNerEdge)/2 - grt/4
+ w = (div - LNerEdge) - grt/2
+ ThisBlockDepth = rndd()*settings['dv']+settings['d']
+ #For reference: EdgeBlocks = [[x,z,w,h,d,[corner offset matrix]],[etc.]]
+ row.BlocksEdge.append([x,row.z,w,row.h,ThisBlockDepth,leftOffsets])
+ #Initialize for the block on the right side
+ x = (div + RNerEdge)/2 + grt/4
+ w = (RNerEdge - div) - grt/2
+ ThisBlockDepth = rndd()*settings['dv']+settings['d']
+ row.BlocksEdge.append([x,row.z,w,row.h,ThisBlockDepth,rightOffsets])
+ continue
+
+ #program should only get here if there are more than two blocks in the row, and no wedge blocks
+
+ #make Left edge block
+ #set the grout
+ grt = (settings['g'] + rndc()*settings['gv'])/r1
+ #set the x position and width for the left block
+ widOptions = [settings['w'], bevelL + settings['wm'], leftOpening.ts]
+ baseWid = max(widOptions)
+ w = (rndd()*settings['wv']+baseWid+row.EdgeOffset)
+ widOptions[0] = settings['wm']
+ widOptions[2] = w
+ w = max(widOptions) / r1 - grt
+ x = w/2 + LNerEdge + grt/2
+ BlockRowL = x + w/2
+ ThisBlockDepth = rndd()*settings['dv']+settings['d']
+ row.BlocksEdge.append([x,row.z,w,row.h,ThisBlockDepth,leftOffsets])
+
+ #make Right edge block
+ #set the grout
+ grt = (settings['g'] + rndc()*settings['gv'])/r1
+ #set the x position and width for the left block
+ widOptions = [settings['w'], bevelR + settings['wm'], rightOpening.ts]
+ baseWid = max(widOptions)
+ w = (rndd()*settings['wv']+baseWid+row.EdgeOffset)
+ widOptions[0] = settings['wm']
+ widOptions[2] = w
+ w = max(widOptions) / r1 - grt
+ x = RNerEdge - w/2 - grt/2
+ BlockRowR = x - w/2
+ ThisBlockDepth = rndd()*settings['dv']+settings['d']
+ row.BlocksEdge.append([x,row.z,w,row.h,ThisBlockDepth,rightOffsets])
+
+ row.RowSegments.append([BlockRowL,BlockRowR])
+ return None
+
+
+def plan(Thesketch, oldrows = 0):
+ __doc__ = """\
+ The 'plan' function takes the data generated by the sketch function and the global settings
+ and creates a list of blocks.
+ It passes out a list of row heights, edge positions, edge blocks, and rows of blocks.
+ """
+ # if we were passed a list of rows already, use those; else make a list.
+ if oldrows: rows = oldrows
+ else:
+ #rows holds the important information common to all rows
+ #rows = [list of row objects]
+ rows = []
+
+ #splits are places where we NEED a row division, to accomidate openings
+ #add a split for the bottom row
+ splits = [dims['b']+settings['hb']]
+
+ #add a split for each critical point on each opening
+ for hole in Thesketch: splits += hole.crits()
+
+ #and, a split for the top row
+ splits.append(dims['t']-settings['ht'])
+ splits.sort()
+
+ #divs are the normal old row divisions, add them between the top and bottom split
+ divs = fill(splits[0],splits[-1],settings['h'],settings['hm']+settings['g'],settings['hv'])[1:-1]
+
+ #remove the divisions that are too close to the splits, so we don't get tiny thin rows
+ for i in range(len(divs)-1,-1,-1):
+ for j in range(len(splits)):
+ diff = abs(divs[i] - splits[j])
+ #(settings['hm']+settings['g']) is the old minimum value
+ if diff < (settings['h']-settings['hv']+settings['g']):
+ del(divs[i])
+ break
+
+ #now merge the divs and splits lists
+ divs += splits
+
+ #add bottom and/or top points, if bottom and/or top row heights are more than zero
+ if settings['hb']>0: divs.insert(0,dims['b'])
+ if settings['ht']>0: divs.append(dims['t'])
+
+ divs.sort()
+
+ #trim the rows to the bottom and top of the wall
+ if divs[0] < dims['b']: divs[:1] = []
+ if divs[-1] > dims['t']: divs[-1:] = []
+
+ #now, make the data for each row
+ #rows = [[center height,row height,edge offset],[etc.]]
+
+ divCount = len(divs)-1 # number of divs to check
+ divCheck = 0 # current div entry
+
+ while divCheck < divCount:
+ RowZ = (divs[divCheck]+divs[divCheck+1])/2
+ RowHeight = divs[divCheck+1]-divs[divCheck]-settings['g']+rndc()*settings['rwhl']*settings['gv']
+ EdgeOffset = settings['eoff']*(fmod(divCheck,2)-0.5)+settings['eoffv']*rndd()
+
+ # if row height is too shallow: delete next div entry, decrement total, and recheck current entry.
+ if RowHeight < settings['hm']:
+ del(divs[divCheck+1])
+ divCount -= 1 # Adjust count for removed div entry.
+ continue
+
+ rows.append(rowOb(RowZ, RowHeight, EdgeOffset))
+
+ divCheck += 1 # on to next div entry
+
+ #set up a special opening object to handle the edges of the wall
+ x = (dims['s'] + dims['e'])/2
+ z = (dims['t'] + dims['b'])/2
+ w = (dims['e'] - dims['s'])
+ h = (dims['t'] - dims['b'])
+ WallBoundaries = OpeningInv(x,z,w,h)
+
+ #Go over each row in the list, set up edge blocks and block sections
+ for rownum in range(len(rows)):
+ rowProcessing(rows[rownum], Thesketch, WallBoundaries)
+
+ #now return the things everyone needs
+ #return [rows,edgeBlocks,blockRows,Asketch]
+ return [rows,Thesketch]
+
+
+def archGeneration(hole, vlist, flist, sideSign):
+ __doc__ = """\
+ Makes arches for the top and bottom, depending on sideSign
+ example, Lower arch:
+ archGeneration(hole, vlist, flist, -1)
+ example, Upper arch:
+ archGeneration(hole, vlist, flist, 1)
+ hole is the opening object that the arch is for
+ add the verticies to vlist
+ add the faces to flist
+ sideSign is + or - 1, for the top or bottom arch. Other values may cause errors.
+ """
+
+ # working arrays for vectors and faces
+ avlist = []
+ aflist = []
+
+ # Top (1) or bottom (-1)
+ if sideSign == -1:
+ r = hole.rl #radius of the arch
+ rt = hole.rtl #thickness of the arch (stone height)
+ v = hole.vl #height of the arch
+ c = hole.cl
+ else:
+ r = hole.r #radius of the arch
+ rt = hole.rt #thickness of the arch (stone height)
+ v = hole.v #height of the arch
+ c = hole.c
+
+ ra = r + rt/2 #average radius of the arch
+ x = hole.x
+ w = hole.w
+ h = hole.h
+ z = hole.z
+ bev = hole.b
+ sideSignInv = -sideSign
+
+ if v > w/2: #two arcs, to make a pointed arch
+ # positioning
+ zpos = z + (h/2)*sideSign
+ xoffset = r - w/2
+ #left side top, right side bottom
+ #angles reference straight up, and are in radians
+ bevRad = r + bev
+ bevHt = sqrt(bevRad**2 - (bevRad - (w/2 + bev))**2)
+ midHalfAngle = atan(v/(r-w/2))
+ midHalfAngleBevel = atan(bevHt/(r-w/2))
+ bevelAngle = midHalfAngle - midHalfAngleBevel
+ anglebeg = (PI/2)*(sideSignInv)
+ angleend = (PI/2)*(sideSignInv) + midHalfAngle
+
+ avlist,aflist = arch(ra,rt,(xoffset)*(sideSign),zpos,anglebeg,angleend,bev,bevelAngle,len(vlist))
+
+ for i,vert in enumerate(avlist): avlist[i] = [vert[0]+hole.x,vert[1],vert[2]]
+ vlist += avlist
+ flist += aflist
+
+ #right side top, left side bottom
+
+ #angles reference straight up, and are in radians
+ anglebeg = (PI/2)*(sideSign) - midHalfAngle
+ angleend = (PI/2)*(sideSign)
+
+ avlist,aflist = arch(ra,rt,(xoffset)*(sideSignInv),zpos,anglebeg,angleend,bev,bevelAngle,len(vlist))
+
+ for i,vert in enumerate(avlist): avlist[i] = [vert[0]+hole.x,vert[1],vert[2]]
+
+ vlist += avlist
+ flist += aflist
+
+ #keystone
+ Dpth = settings['d']+rndc()*settings['dv']
+ Grout = settings['g'] + rndc()*settings['gv']
+ angleBevel = (PI/2)*(sideSign) - midHalfAngle
+ Wdth = (rt - Grout - bev) * 2 * sin(angleBevel) * sideSign #note, sin may be negative
+ MidZ = ((sideSign)*(bevHt + h/2.0) + z) + (rt - Grout - bev) * cos(angleBevel) #note, cos may come out negative too
+ nearCorner = sideSign*(MidZ - z) - v - h/2
+
+ if sideSign == 1:
+ TopHt = hole.top() - MidZ - Grout
+ BtmHt = nearCorner
+ else:
+ BtmHt = - (hole.btm() - MidZ) - Grout
+ TopHt = nearCorner
+
+ # set the amout to bevel the keystone
+ keystoneBevel = (bevHt - v)*sideSign
+ if Wdth >= settings['hm']:
+ avlist,aflist = MakeAKeystone(x, Wdth, MidZ, TopHt, BtmHt, Dpth, keystoneBevel, len(vlist))
+
+ if radialized:
+ for i,vert in enumerate(avlist):
+ if slope: r1 = dims['t']*sin(vert[2]*PI/(dims['t']*2))
+ else: r1 = vert[2]
+ avlist[i] = [((vert[0]-hole.x)/r1)+hole.x,vert[1],vert[2]]
+
+ vlist += avlist
+ flist += aflist
+# remove "debug note" once bevel is finalized.
+ else: print("keystone was too narrow - " + str(Wdth))
+
+ else: # only one arc - curve not peak.
+#bottom (sideSign -1) arch has poorly sized blocks...
+
+ zpos = z + (sideSign * (h/2 + v - r)) # single arc positioning
+
+ #angles reference straight up, and are in radians
+ if sideSign == -1: angleOffset = PI
+ else: angleOffset = 0.0
+
+ if v < w/2:
+ halfangle = atan(w/(2*(r-v)))
+
+ anglebeg = angleOffset - halfangle
+ angleend = angleOffset + halfangle
+ else:
+ anglebeg = angleOffset - PI/2
+ angleend = angleOffset + PI/2
+
+ avlist,aflist = arch(ra,rt,0,zpos,anglebeg,angleend,bev,0.0,len(vlist))
+
+ for i,vert in enumerate(avlist): avlist[i] = [vert[0]+x,vert[1],vert[2]]
+
+ vlist += avlist
+ flist += aflist
+
+ #Make the Side Stones
+ grt = (settings['g'] + rndc()*settings['gv'])
+ width = sqrt(rt**2 - c**2) - grt
+
+ if c > settings['hm'] + grt and c < width + grt:
+ if radialized: subdivision = settings['sdv'] * (zpos + (h/2)*sideSign)
+ else: subdivision = settings['sdv']
+
+ #set the height of the block, it should be as high as the max corner position, minus grout
+ height = c - grt*(0.5 + c/(width + grt))
+
+ #the vertical offset for the short side of the block
+ voff = sideSign * (settings['hm'] - height)
+ xstart = w/2
+ zstart = z + sideSign * (h/2 + grt/2)
+ woffset = width*(settings['hm'] + grt/2)/(c - grt/2)
+ depth = rndd()*settings['dv']+settings['d']
+
+ if sideSign == 1:
+ offsets = [[0]*3]*6 + [[0]*2 + [voff]]*2
+ topSide = zstart+height
+ btmSide = zstart
+ else:
+ offsets = [[0]*3]*4 + [[0]*2 + [voff]]*2 + [[0]*3]*2
+ topSide = zstart
+ btmSide = zstart-height
+ # Do some stuff to incorporate bev here
+ bevelBlockOffsets(offsets, bev, -1)
+
+ avlist,aflist = MakeABlock([x-xstart-width, x-xstart- woffset, btmSide, topSide, -depth/2, depth/2], subdivision, len(vlist), Offsets=offsets, xBevScl=1)
+
+# top didn't use radialized in prev version; just noting for clarity - may need to revise for "sideSign == 1"
+ if radialized:
+ for i,vert in enumerate(avlist): avlist[i] = [((vert[0]-x)/vert[2])+x,vert[1],vert[2]]
+
+ vlist += avlist
+ flist += aflist
+
+# keep sizing same - neat arches = master masons :)
+# grt = (settings['g'] + rndc()*settings['gv'])
+# height = c - grt*(0.5 + c/(width + grt))
+# if grout varies may as well change width too... width = sqrt(rt**2 - c**2) - grt
+# voff = sideSign * (settings['hm'] - height)
+# woffset = width*(settings['hm'] + grt/2)/(c - grt/2)
+
+ if sideSign == 1:
+ offsets = [[0]*3]*2 + [[0]*2 + [voff]]*2 + [[0]*3]*4
+ topSide = zstart+height
+ btmSide = zstart
+ else:
+ offsets = [[0]*2 + [voff]]*2 + [[0]*3]*6
+ topSide = zstart
+ btmSide = zstart-height
+ # Do some stuff to incorporate bev here
+ bevelBlockOffsets(offsets, bev, 1)
+
+ avlist,aflist = MakeABlock([x+xstart+woffset, x+xstart+width, btmSide, topSide, -depth/2, depth/2], subdivision, len(vlist), Offsets=offsets, xBevScl=1)
+
+# top didn't use radialized in prev version; just noting for clarity - may need to revise for "sideSign == 1"
+ if radialized:
+ for i,vert in enumerate(avlist): avlist[i] = [((vert[0]-x)/vert[2])+x,vert[1],vert[2]]
+
+ vlist += avlist
+ flist += aflist
+ return None
+
+
+def build(Aplan):
+ __doc__ = """\
+ Build creates the geometry for the wall, based on the
+ "Aplan" object from the "plan" function. If physics is
+ enabled, then it make a number of individual blocks with
+ physics interaction enabled. Otherwise it creates
+ geometry for the blocks, arches, etc. of the wall.
+ """
+
+ vlist = []
+ flist = []
+ rows = Aplan[0]
+
+#dead code...
+ #Physics setup is horribly broken. Revisit when new API is in place.
+ '''if False: #settings['physics']:
+ geom = MakeABlock([-0.5,0.5,-0.5,0.5,-0.5,0.5], 3, 0, None,[], 3*settings['b']/(settings['w'] + settings['h'] + settings['d']))
+ blockmesh = Blender.Mesh.New('block')
+ vlist += geom[0]
+ flist += geom[1]
+ blockmesh.verts.extend(vlist)
+ blockmesh.faces.extend(flist)
+
+ for block in Aplan[1]:
+ x,z,w,h,d = block[:5]
+ block = scn.objects.new(blockmesh, 'block')
+ block.loc = [x, 0, z]
+ block.size = [w,d,h]
+ block.rbFlags = Blender.Object.RBFlags['BOUNDS'] | Blender.Object.RBFlags['ACTOR'] | Blender.Object.RBFlags['DYNAMIC'] | Blender.Object.RBFlags['RIGIDBODY']
+ block.rbShapeBoundType = Blender.Object.RBShapes['BOX']
+
+
+ for row in Aplan[2]:#row=[xstart,xend,z,h]
+ #currently, radial geometry is disabled for physics blocks setup
+ if radialized:
+ if slope: r1 = dims['t']*sin(row[2]*PI/(dims['t']*2))
+ else: r1 = row[2]
+
+ else: r1 = 1
+
+ divs = fill(row[0], row[1], settings['w'], settings['wm'], settings['wv'])
+ for i in range(len(divs)-1):
+ block = scn.objects.new(blockmesh, 'block')
+ block.loc = [(divs[i]+divs[i+1])/2, 0, row[2]]
+ block.size = [(divs[i + 1] - divs[i]) - settings['g'], (settings['d'] + rndd()*settings['dv'])*(1-settings['t']*((row[3]-dims['b'])/(dims['t'] - dims['b']))), row[3]]
+ block.rbFlags = Blender.Object.RBFlags['BOUNDS'] | Blender.Object.RBFlags['ACTOR'] | Blender.Object.RBFlags['DYNAMIC'] | Blender.Object.RBFlags['RIGIDBODY']
+ block.rbShapeBoundType = Blender.Object.RBShapes['BOX']
+
+ return None'''
+#end dead code...
+
+ # all the edge blocks, redacted
+ #AllBlocks = [[x,z,w,h,d,[corner offset matrix]],[etc.]]
+
+ #loop through each row, adding the normal old blocks
+ for rowidx in range(len(rows)):#row = row object
+ rows[rowidx].FillBlocks()
+
+ AllBlocks = []
+
+ # If the wall is set to merge blocks, check all the blocks to see if you can merge any
+#seems to only merge vertical, should do horizontal too
+ if bigBlock:
+ for rowidx in range(len(rows)-1):
+ if radialized:
+ if slope: r1 = dims['t']*sin(abs(rows[rowidx].z)*PI/(dims['t']*2))
+ else: r1 = abs(rows[rowidx].z)
+ else: r1 = 1
+
+ Tollerance = settings['g']/r1
+ idxThis = len(rows[rowidx].BlocksNorm[:]) - 1
+ idxThat = len(rows[rowidx+1].BlocksNorm[:]) - 1
+
+ while True:
+ # end loop when either array idx wraps
+ if idxThis < 0 or idxThat < 0: break
+
+ blockThis = rows[rowidx].BlocksNorm[idxThis]
+ blockThat = rows[rowidx+1].BlocksNorm[idxThat]
+
+#seems to only merge vertical, should do horizontal too...
+ cx, cz, cw, ch, cd = blockThis[:5]
+ ox, oz, ow, oh, od = blockThat[:5]
+
+ if (abs(cw - ow) < Tollerance) and (abs(cx - ox) < Tollerance) :
+ if cw > ow: BlockW = ow
+ else: BlockW = cw
+
+ AllBlocks.append([(cx+ox)/2,(cz+oz+(oh-ch)/2)/2,BlockW,abs(cz-oz)+(ch+oh)/2,(cd+od)/2,None])
+
+ rows[rowidx].BlocksNorm.pop(idxThis)
+ rows[rowidx+1].BlocksNorm.pop(idxThat)
+ idxThis -= 1
+ idxThat -= 1
+
+ elif cx > ox: idxThis -= 1
+ else: idxThat -= 1
+
+ #
+ #
+ # Add blocks to create a "shelf/platform".
+ # Does not account for openings (crosses gaps - which is a good thing)
+ if shelfExt:
+ SetGrtOff = settings['g']/2 # half grout for block size modifier
+
+ # Use wall block settings for shelf
+ SetBW = settings['w']
+ SetBWVar = settings['wv']
+ SetBWMin = settings['wm']
+ SetBH = settings['h']
+
+ # Shelf area settings
+ ShelfLft = shelfSpecs['x']
+ ShelfBtm = shelfSpecs['z']
+ ShelfEnd = ShelfLft + shelfSpecs['w']
+ ShelfTop = ShelfBtm + shelfSpecs['h']
+ ShelfThk = shelfSpecs['d'] * 2 # use double-depth due to offsets to position at cursor.
+
+ # Use "corners" to adjust position so not centered on depth.
+ # Facing shelf, at cursor (middle of wall blocks) - this way no gaps between platform and wall face due to wall block depth.
+ wallDepth = settings['d']/2 # offset by wall depth so step depth matches UI setting :)
+ if shelfBack: # place blocks on backside of wall
+ ShelfOffsets = [[0,ShelfThk/2,0],[0,wallDepth,0],[0,ShelfThk/2,0],[0,wallDepth,0],[0,ShelfThk/2,0],[0,wallDepth,0],[0,ShelfThk/2,0],[0,wallDepth,0]]
+ else:
+ ShelfOffsets = [[0,-wallDepth,0],[0,-ShelfThk/2,0],[0,-wallDepth,0],[0,-ShelfThk/2,0],[0,-wallDepth,0],[0,-ShelfThk/2,0],[0,-wallDepth,0],[0,-ShelfThk/2,0]]
+
+ # Add blocks for each "shelf row" in area
+ while ShelfBtm < ShelfTop:
+
+ # Make blocks for each row - based on rowOb::fillblocks
+ # Does not vary grout.
+ divs = fill(ShelfLft, ShelfEnd, SetBW, SetBWMin, SetBWVar)
+
+ #loop through the row divisions, adding blocks for each one
+ for i in range(len(divs)-1):
+ ThisBlockx = (divs[i]+divs[i+1])/2
+ ThisBlockw = divs[i+1]-divs[i]-SetGrtOff
+
+ AllBlocks.append([ThisBlockx, ShelfBtm, ThisBlockw, SetBH, ShelfThk, ShelfOffsets])
+
+ ShelfBtm += SetBH + SetGrtOff # moving up to next row...
+ #
+ #
+ # Add blocks to create "steps".
+ # Does not account for openings (crosses gaps - which is a good thing)
+ if stepMod:
+ SetGrtOff = settings['g']/2 # half grout for block size modifier
+
+ # Vary block width by wall block variations.
+ SetWidVar = settings['wv']
+ SetWidMin = settings['wm']
+
+ StepXMod = stepSpecs['t'] # width of step/tread, also sets basic block size.
+ StepZMod = stepSpecs['v']
+
+ StepLft = stepSpecs['x']
+ StepRt = stepSpecs['x'] + stepSpecs['w']
+ StepBtm = stepSpecs['z'] + StepZMod/2 # Start offset for centered blocks
+ StepWide = stepSpecs['w']
+ StepTop = StepBtm + stepSpecs['h']
+ StepThk = stepSpecs['d'] * 2 # use double-depth due to offsets to position at cursor.
+
+ # Use "corners" to adjust steps so not centered on depth.
+ # Facing steps, at cursor (middle of wall blocks) - this way no gaps between steps and wall face due to wall block depth.
+ # Also, will work fine as stand-alone if not used with wall (try block depth 0 and see what happens).
+ wallDepth = settings['d']/2 # offset by wall depth so step depth matches UI setting :)
+ if stepBack: # place blocks on backside of wall
+ StepOffsets = [[0,StepThk/2,0],[0,wallDepth,0],[0,StepThk/2,0],[0,wallDepth,0],[0,StepThk/2,0],[0,wallDepth,0],[0,StepThk/2,0],[0,wallDepth,0]]
+ else:
+ StepOffsets = [[0,-wallDepth,0],[0,-StepThk/2,0],[0,-wallDepth,0],[0,-StepThk/2,0],[0,-wallDepth,0],[0,-StepThk/2,0],[0,-wallDepth,0],[0,-StepThk/2,0]]
+
+ # Add steps for each "step row" in area (neg width is interesting but prevented)
+ while StepBtm < StepTop and StepWide > 0:
+
+ # Make blocks for each step row - based on rowOb::fillblocks
+ # Does not vary grout.
+
+ if stepOnly: # "cantilevered steps"
+ if stepLeft:
+ stepStart = StepRt - StepXMod
+ else:
+ stepStart = StepLft
+
+ AllBlocks.append([stepStart, StepBtm, StepXMod, StepZMod, StepThk, StepOffsets])
+ else:
+ divs = fill(StepLft, StepRt, StepXMod, SetWidMin, SetWidVar)
+
+ #loop through the row divisions, adding blocks for each one
+ for i in range(len(divs)-1):
+ ThisBlockx = (divs[i]+divs[i+1])/2
+ ThisBlockw = divs[i+1]-divs[i]-SetGrtOff
+
+ AllBlocks.append([ThisBlockx, StepBtm, ThisBlockw, StepZMod, StepThk, StepOffsets])
+
+ StepBtm += StepZMod + SetGrtOff # moving up to next row...
+ StepWide -= StepXMod # reduce step width
+
+ # adjust side limit depending on direction of steps
+ if stepLeft:
+ StepRt -= StepXMod # move in from right
+ else:
+ StepLft += StepXMod # move in from left
+
+
+ #Copy all the blocks out of the rows
+ for row in rows:
+ AllBlocks += row.BlocksEdge
+ AllBlocks += row.BlocksNorm
+
+ #This loop makes individual blocks for each block specified in the plan
+ for block in AllBlocks:
+ x,z,w,h,d,corners = block
+ if radialized:
+ if slope: r1 = dims['t']*sin(z*PI/(dims['t']*2))
+ else: r1 = z
+ else: r1 = 1
+
+ geom = MakeABlock([x-w/2, x+w/2, z-h/2, z+h/2, -d/2, d/2], settings['sdv'], len(vlist), corners, None, settings['b']+rndd()*settings['bv'], r1)
+ vlist += geom[0]
+ flist += geom[1]
+
+
+ # This loop makes Arches for every opening specified in the plan.
+ for hole in Aplan[1]:
+ # lower arch stones
+ if hole.vl > 0 and hole.rtl > (settings['g'] + settings['hm']):#make lower arch blocks
+ archGeneration(hole, vlist, flist, -1)
+
+ #top arch stones
+ if hole.v > 0 and hole.rt > (settings['g'] + settings['hm']):#make upper arch blocks
+ archGeneration(hole, vlist, flist, 1)
+ #
+
+ #Warp all the points for domed stonework
+ if slope:
+ for i,vert in enumerate(vlist):
+ vlist[i] = [vert[0],(dims['t']+vert[1])*cos(vert[2]*PI/(2*dims['t'])),(dims['t']+vert[1])*sin(vert[2]*PI/(2*dims['t']))]
+
+ #Warp all the points for radial stonework
+ if radialized:
+ for i,vert in enumerate(vlist):
+ vlist[i] = [vert[2]*cos(vert[0]),vert[2]*sin(vert[0]),vert[1]]
+
+ return vlist, flist
+
+
+#The main function
+def createWall(radial, curve, openings, mergeBlox, shelf, shelfSide,
+ steps, stepDir, stepBare, stepSide):
+ __doc__ = """\
+ Call all the funcitons you need to make a wall, return the verts and faces.
+ """
+ global radialized
+ global slope
+ global openingSpecs
+ global bigBlock
+ global shelfExt
+ global stepMod
+ global stepLeft
+ global shelfBack
+ global stepOnly
+ global stepBack
+
+ # set all the working variables from passed parameters
+
+ radialized = radial
+ slope = curve
+ openingSpecs = openings
+ bigBlock = mergeBlox
+ shelfExt = shelf
+ stepMod = steps
+ stepLeft = stepDir
+ shelfBack = shelfSide
+ stepOnly = stepBare
+ stepBack = stepSide
+
+ asketch = sketch()
+ aplan = plan(asketch, 0)
+
+ return build(aplan)
+
diff --git a/add_mesh_extra_objects/Wallfactory.py b/add_mesh_extra_objects/Wallfactory.py
index 8c7fb935..cd432a52 100644
--- a/add_mesh_extra_objects/Wallfactory.py
+++ b/add_mesh_extra_objects/Wallfactory.py
@@ -32,7 +32,7 @@
import bpy
import mathutils
from bpy.props import *
-from add_mesh_building_objects.Blocks import *
+from add_mesh_extra_objects.Blocks import *
#from add_mesh_walls.preset_utils import *
diff --git a/add_mesh_extra_objects/__init__.py b/add_mesh_extra_objects/__init__.py
index 98dc1e0c..069a959c 100644
--- a/add_mesh_extra_objects/__init__.py
+++ b/add_mesh_extra_objects/__init__.py
@@ -62,6 +62,7 @@ if "bpy" in locals():
importlib.reload(mesh_discombobulator)
importlib.reload(add_mesh_beam_builder)
importlib.reload(Wallfactory)
+ importlib.reload(Blocks)
else:
from . import add_mesh_star
from . import add_mesh_twisted_torus
@@ -83,7 +84,7 @@ else:
from . import mesh_discombobulator
from . import add_mesh_beam_builder
from . import Wallfactory
-
+ from . import Blocks
import bpy