NLA SoC: Adding some files that seem to have been missed during some merges. Hopefull...
authorJoshua Leung <aligorith@gmail.com>
Thu, 2 Jul 2009 02:53:18 +0000 (02:53 +0000)
committerJoshua Leung <aligorith@gmail.com>
Thu, 2 Jul 2009 02:53:18 +0000 (02:53 +0000)
15 files changed:
release/scripts/animation_clean.py [new file with mode: 0644]
release/scripts/image_2d_cutout.py [new file with mode: 0644]
release/scripts/object_active_to_other.py [new file with mode: 0644]
release/scripts/scripttemplate_gamelogic_module.py [new file with mode: 0644]
release/scripts/textplugin_convert_ge.py [new file with mode: 0644]
release/scripts/wizard_bolt_factory.py [new file with mode: 0644]
release/scripts/wizard_landscape_ant.py [new file with mode: 0644]
release/ui/space_sequencer.py [new file with mode: 0644]
source/gameengine/Converter/BL_ModifierDeformer.cpp [new file with mode: 0644]
source/gameengine/Converter/BL_ModifierDeformer.h [new file with mode: 0644]
source/gameengine/Ketsji/KX_PythonSeq.cpp [new file with mode: 0644]
source/gameengine/Ketsji/KX_PythonSeq.h [new file with mode: 0644]
source/gameengine/PyDoc/API_intro.py [new file with mode: 0644]
source/gameengine/SceneGraph/SG_DList.h [new file with mode: 0644]
source/gameengine/SceneGraph/SG_QList.h [new file with mode: 0644]

diff --git a/release/scripts/animation_clean.py b/release/scripts/animation_clean.py
new file mode 100644 (file)
index 0000000..fc44f26
--- /dev/null
@@ -0,0 +1,192 @@
+#!BPY
+
+"""
+Name: 'Clean Animation Curves'
+Blender: 249
+Group: 'Animation'
+Tooltip: 'Remove unused keyframes for ipo curves'
+"""
+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Copyright (C) 2008-2009: Blender Foundation
+#
+# This program is free software; you can 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,
+# --------------------------------------------------------------------------
+
+import bpy
+from Blender import IpoCurve, Draw, Window
+
+def clean_ipos(ipos):
+       eul = 0.001
+
+       def isflat(vec):
+               prev_y = vec[0][1]
+               mid_y = vec[1][1]
+               next_y = vec[2][1]
+               
+               # flat status for prev and next
+               return abs(mid_y-prev_y) < eul, abs(mid_y-next_y) < eul
+               
+               
+                       
+       X=0
+       Y=1
+       PREV=0
+       MID=1
+       NEXT=2
+
+       LEFT = 0
+       RIGHT = 1
+
+       TOT = 0
+       TOTBEZ = 0
+       # for ipo in bpy.data.ipos:
+       for ipo in ipos:
+               if ipo.lib: 
+                       continue
+               # print ipo
+               for icu in ipo:
+                       interp = icu.interpolation
+                       extend = icu.extend 
+                       
+                       bezierPoints = icu.bezierPoints
+                       bezierVecs = [bez.vec for bez in bezierPoints]
+                       
+                       l = len(bezierPoints)
+                       
+                       TOTBEZ += l
+                       
+                       # our aim is to simplify this ipo as much as possible!
+                       if interp == IpoCurve.InterpTypes.BEZIER or interp == interp == IpoCurve.InterpTypes.LINEAR:
+                               #print "Not yet supported"
+                               
+                               if interp == IpoCurve.InterpTypes.BEZIER:
+                                       flats = [isflat(bez) for bez in bezierVecs]
+                               else:
+                                       # A bit of a waste but fake the locations for these so they will always be flats
+                                       # IS better then too much duplicate code.
+                                       flats = [(True, True)] * l
+                                       for v in bezierVecs:
+                                               v[PREV][Y] = v[NEXT][Y] = v[MID][Y]
+                                       
+                               
+                               # remove middle points
+                               if l>2:
+                                       done_nothing = False
+                                       
+                                       while not done_nothing and len(bezierVecs) > 2:
+                                               done_nothing = True
+                                               i = l-2
+                                       
+                                               while i > 0:
+                                                       #print i
+                                                       #print i, len(bezierVecs)
+                                                       if flats[i]==(True,True)  and  flats[i-1][RIGHT]  and  flats[i+1][LEFT]:
+                                                       
+                                                               if abs(bezierVecs[i][MID][Y] - bezierVecs[i-1][MID][Y]) < eul   and   abs(bezierVecs[i][MID][Y] - bezierVecs[i+1][MID][Y]) < eul:
+                                                                       done_nothing = False
+                                                                       
+                                                                       del flats[i]
+                                                                       del bezierVecs[i]
+                                                                       icu.delBezier(i)
+                                                                       TOT += 1
+                                                                       l-=1
+                                                       i-=1
+                               
+                               # remove endpoints
+                               if extend == IpoCurve.ExtendTypes.CONST and len(bezierVecs) > 1:
+                                       #print l, len(bezierVecs)
+                                       # start
+                                       
+                                       while l > 2 and (flats[0][RIGHT]  and  flats[1][LEFT] and (abs(bezierVecs[0][MID][Y] - bezierVecs[1][MID][Y]) < eul)):
+                                               print "\tremoving 1 point from start of the curve"
+                                               del flats[0]
+                                               del bezierVecs[0]
+                                               icu.delBezier(0)
+                                               TOT += 1
+                                               l-=1
+                                       
+                                       
+                                       # End 
+                                       while l > 2 and flats[-2][RIGHT]  and  flats[-1][LEFT] and (abs(bezierVecs[-2][MID][Y] - bezierVecs[-1][MID][Y]) < eul):
+                                               print "\tremoving 1 point from end of the curve", l
+                                               del flats[l-1]
+                                               del bezierVecs[l-1]
+                                               icu.delBezier(l-1)
+                                               TOT += 1
+                                               l-=1
+                                               
+                               
+                                               
+                               if l==2:
+                                       if isflat( bezierVecs[0] )[RIGHT] and isflat( bezierVecs[1] )[LEFT] and abs(bezierVecs[0][MID][Y] - bezierVecs[1][MID][Y]) < eul:
+                                               # remove the second point
+                                               print "\tremoving 1 point from 2 point bez curve"
+                                               # remove the second point
+                                               del flats[1]
+                                               del bezierVecs[1]
+                                               icu.delBezier(1)
+                                               TOT+=1
+                                               l-=1
+                                               
+                               # Change to linear for faster evaluation
+                               '''
+                               if l==1:
+                                       print 'Linear'
+                                       icu.interpolation = IpoCurve.InterpTypes.LINEAR
+                               '''
+                               
+               
+                       
+                       
+                       if interp== IpoCurve.InterpTypes.CONST:
+                               print "Not yet supported"
+                               
+       print 'total', TOT, TOTBEZ
+       return TOT, TOTBEZ
+
+def main():
+       ret = Draw.PupMenu('Clean Selected Objects Ipos%t|Object IPO%x1|Object Action%x2|%l|All IPOs (be careful!)%x3')
+       
+       sce = bpy.data.scenes.active
+       ipos = []
+       
+       if ret == 3:
+               ipos.extend(list(bpy.data.ipos))
+       else:
+               for ob in sce.objects.context:
+                       if ret == 1:
+                               ipo = ob.ipo
+                               if ipo:
+                                       ipos.append(ipo)
+                       
+                       elif ret == 2:
+                               action = ob.action
+                               if action:
+                                       ipos.extend([ipo for ipo in action.getAllChannelIpos().values() if ipo])
+               
+                       
+       
+       if not ipos:
+               Draw.PupMenu('Error%t|No ipos found')
+       else:
+               total_removed, total = clean_ipos(ipos)
+               Draw.PupMenu('Done!%t|Removed ' + str(total_removed) + ' of ' + str(total) + ' points')
+       
+       Window.RedrawAll()
+       
+
+if __name__ == '__main__':
+       main()
diff --git a/release/scripts/image_2d_cutout.py b/release/scripts/image_2d_cutout.py
new file mode 100644 (file)
index 0000000..16d0805
--- /dev/null
@@ -0,0 +1,559 @@
+#!BPY
+
+"""
+Name: '2D Cutout Image Importer'
+Blender: 249
+Group: 'Image'
+Tooltip: 'Batch UV Map images to Planes'
+"""
+
+__author__ = "Kevin Morgan (forTe)"
+__url__ = ("Home page, http://gamulabs.freepgs.com")
+__version__ = "1.2.1"
+__bpydoc__ = """\
+This Script will take an image and
+UV map it to a plane sharing the same width to height ratio as the image.
+Import options allow for the image to be a still or sequence type image
+<br><br>
+Imports can be single images or whole directories of images depending on the chosen
+option.
+"""
+
+####################################################
+#Copyright (C) 2008: Kevin Morgan
+####################################################
+#-------------GPL LICENSE BLOCK-------------
+#This program is free software: you can redistribute it and/or modify
+#it under the terms of the GNU General Public License as published by
+#the Free Software Foundation, either version 3 of the License, or
+#(at your option) any later version.
+#
+#This program is distributed in the hopes 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, see <http://www.gnu.org/licenses>.
+####################################################
+####################################################
+#V1.0
+#Basic Functionality
+#Published June 28, 2007
+####################################################
+#V1.1
+#Added Support for enabling viewport transparency
+#Added more options to the UI for materials
+#Added Proportionality code (Pixels per unit)
+#Added GPL License Block
+#Published June 29, 2007
+####################################################
+#V1.2
+#Added Support for Copying Existing Materials
+#Import Images as Sequences
+#Refreshed GUI - now with more clutter :(
+#Miscellaneous and Housekeeping
+#Published June 16, 2008
+####################################################
+#V1.2.1
+#Added Extend Texture Mode option at request of a user
+#Published September 24, 2008
+####################################################
+
+import Blender
+from Blender import BGL, Draw, Image, Mesh, Material, Texture, Window
+from Blender.Mathutils import *
+import bpy
+
+# Global Constants
+DIR = 0
+SINGLE = 1
+CUROFFS = 0
+
+# GUI CONSTANTS
+NO_EVT = 0
+SINGLE_IMG = 1
+DIRECTORY_IMG = 2
+CLR_PATH = 3
+CHG_EXT = 4
+EXIT = 5
+DO_SCRIPT = 6
+
+VERSIONSTRING = '1.2.1'
+
+# Note the two parameter dicts could be combined, I just, liked them seperate...
+# GUI Buttons Dict
+GUIPARAMS = {
+       'Path': Draw.Create(''),
+       'ImageExt': Draw.Create(''),
+       'Seq': Draw.Create(0),
+       'PackImage': Draw.Create(0),
+       'PPU': Draw.Create(50),
+       'VPTransp': Draw.Create(1),
+       'XOff': Draw.Create(0.0),
+       'YOff': Draw.Create(0.0),
+       'ZOff': Draw.Create(0.0),
+       'CopyMat': Draw.Create(0),
+       'MatId': Draw.Create(0),
+       'MatCol': Draw.Create(1.0, 0.0, 0.0),
+       'Ref': Draw.Create(0.8),
+       'Spec': Draw.Create(0.5),
+       'Hard': Draw.Create(50),
+       'Alpha': Draw.Create(1.0),
+       'ZTransp': Draw.Create(1),
+       'Shadeless': Draw.Create(0),
+       'TexChan': Draw.Create(1),
+       'MPTCol': Draw.Create(1),
+       'MPTAlpha': Draw.Create(1),
+       'UseAlpha': Draw.Create(1),
+       'CalcAlpha': Draw.Create(0),
+       'ExtendMode': Draw.Create(0),
+       'AutoRefresh': Draw.Create(0),
+       'Cyclic': Draw.Create(0),
+       'Frames': Draw.Create(100),
+       'Offs': Draw.Create(0),
+       'StartFr': Draw.Create(1),
+       'RedrawImp': Draw.Create(0)
+}
+
+# Script Execution Paramaters
+PARAMS = {
+       'ImagePaths': [],                                                                       # Path to images to import
+       'ImportType': SINGLE,                                                   # Import a Directory or a Single Image?
+       'ImageProp': Image.Sources.STILL,       # What sources for the image, still or sequence
+       'PackImage': 0,                                                                                 # Pack the Image(s)?
+       'PPU': 20,                                                                                                      # Pixels Per Blender Unit
+       'MakeTransp': 1,                                                                                # Make face transparent in viewport
+       
+       'NewMat': 1,                                                                                            # If true make a new material, otherwise duplicate an existing one, replacing appropriate attributes
+       'MaterialId': 0,                                                                                # ID to take from the Materials list upon copy
+       'Materials': None,                                                                      # Materials in Scene
+       'MatProps': {'Col': [1.0, 0.0, 0.0], 'Shadeless': 1, 'Ref': 0.5, 'Spec': 0.5, 'Hard': 200, 'Alpha': 1.0, 'ZTransp': 1},
+       
+       'TexProps': {'UseAlpha': 1, 'CalcAlpha': 0, 'ExtendMode': 0}, # Texture Properties
+       'TexChannel': 0,                                                                                # Texture Channel
+       'TexMapTo': {'Col': 1, 'Alpha': 1}, # Map to Col and/or Alpha
+       'SeqProps': {'AutoRefresh': 0, 'Cyclic': 0, 'Frames': 100, 'Offs': 0, 'StartFr': 1},
+       'ObOffset': Vector(1, 0, 0)                             # Offset by this vector upon creation for multifile import
+}
+
+# Get the Active Scene, of course
+scn = bpy.data.scenes.active
+
+##########################################
+# MAIN SCRIPT FUNCTIONS
+##########################################
+
+def imgImport(imgPath):
+       global CUROFFS, PARAMS
+       ######################################
+       # Load the image
+       ######################################
+       try:
+               img = Image.Load(imgPath)
+               imgDimensions = img.getSize() # do this to ensure the data is available
+       except:
+               Blender.Draw.PupMenu('Error%t|Unsupported image format for "'+ imgPath.split('\\')[-1].split('/')[-1] +'"')
+               return          
+       
+       if PARAMS['PackImage']:
+               img.pack()
+       name = Blender.sys.makename(imgPath, strip = 1)
+       
+       ######################################
+       # Construct the mesh
+       ######################################
+       
+       me = Mesh.New(name)
+       
+       # Calculate Dimensions from Image Size
+       dim = [float(i)/PARAMS['PPU'] for i in imgDimensions]
+       v = [[dim[0], dim[1], 0], [-dim[0], dim[1], 0], [-dim[0], -dim[1], 0], [dim[0], -dim[1], 0]]
+       me.verts.extend(v)
+       me.faces.extend([0, 1, 2, 3])
+       
+       me.faces[0].image = img
+       me.faces[0].uv = [Vector(1.0, 1.0), Vector(0.0, 1.0), Vector(0.0, 0.0), Vector(1.0, 0.0)]
+       
+       if PARAMS['MakeTransp']:
+               me.faces[0].transp = Mesh.FaceTranspModes.ALPHA
+       
+       ######################################
+       # Modify the Material
+       ######################################
+       
+       mat = None
+       if not PARAMS['NewMat']:
+               mat = PARAMS['Materials'][PARAMS['MaterialId']].__copy__()
+               mat.setName(name)
+       else:
+               mat = Material.New(name)
+               properties = PARAMS['MatProps']
+               mat.setRGBCol(properties['Col'])
+               mat.setRef(properties['Ref'])
+               mat.setSpec(properties['Spec'])
+               mat.setHardness(properties['Hard'])
+               mat.setAlpha(properties['Alpha'])
+               
+               if properties['Shadeless']:
+                       mat.mode |= Material.Modes.SHADELESS
+               if properties['ZTransp']:
+                       mat.mode |= Material.Modes.ZTRANSP
+       
+       properties = PARAMS['TexProps']
+               
+       tex = Texture.New(name)
+       tex.setType('Image')
+       tex.setImage(img)
+       if properties['UseAlpha']:
+               tex.useAlpha = Texture.ImageFlags.USEALPHA
+                       
+       if properties['CalcAlpha']:
+               tex.calcAlpha = Texture.ImageFlags.CALCALPHA
+               
+       if properties['ExtendMode']:
+               tex.setExtend('Extend')
+               
+       if PARAMS['ImageProp'] == Image.Sources.SEQUENCE:
+               properties = PARAMS['SeqProps']
+               
+               img.source = PARAMS['ImageProp'] # Needs to be done here, otherwise an error with earlier getSize()
+               
+               tex.animStart = properties['StartFr']
+               tex.animOffset = properties['Offs']
+               tex.animFrames = properties['Frames']
+               tex.autoRefresh = properties['AutoRefresh']
+               tex.cyclic = properties['Cyclic']
+                       
+       texMapSetters = Texture.TexCo.UV
+       
+       # PARAMS['TexMapTo']['Col'] (and alpha) will either be 0 or 1 because its from a toggle, otherwise this line doesn't work
+       texChanSetters = Texture.MapTo.COL * PARAMS['TexMapTo']['Col'] | Texture.MapTo.ALPHA * PARAMS['TexMapTo']['Alpha']
+       
+       mat.setTexture(PARAMS['TexChannel'], tex, texMapSetters, texChanSetters)
+       me.materials += [mat]
+       
+       ######################################
+       # Object Construction
+       ######################################
+       
+       ob = scn.objects.new(me, name)
+       p = Vector(ob.getLocation()) # Should be the origin, but just to be safe, get it
+       ob.setLocation((CUROFFS * PARAMS['ObOffset']) + p)
+               
+       return
+
+def translateParams():
+       # Translates (or assigns for the most part) GUI values to those that can be read by the
+       # Import Function
+       
+       global GUIPARAMS, PARAMS
+       
+       if GUIPARAMS['Seq'].val and PARAMS['ImportType'] != DIR:
+               PARAMS['ImageProp'] = Image.Sources.SEQUENCE
+       
+       PARAMS['PackImage'] = GUIPARAMS['PackImage'].val
+       PARAMS['PPU'] = GUIPARAMS['PPU'].val
+       PARAMS['MakeTransp'] = GUIPARAMS['VPTransp'].val
+       PARAMS['ObOffset'] = Vector(GUIPARAMS['XOff'].val, GUIPARAMS['YOff'].val, GUIPARAMS['ZOff'].val)
+       
+       PARAMS['NewMat'] = not GUIPARAMS['CopyMat'].val
+       PARAMS['MaterialId'] = GUIPARAMS['MatId'].val
+       PARAMS['MatProps']['Col'] = list(GUIPARAMS['MatCol'].val)
+       PARAMS['MatProps']['Ref'] = GUIPARAMS['Ref'].val
+       PARAMS['MatProps']['Spec'] = GUIPARAMS['Spec'].val
+       PARAMS['MatProps']['Hard'] = GUIPARAMS['Hard'].val
+       PARAMS['MatProps']['Alpha'] = GUIPARAMS['Alpha'].val
+       PARAMS['MatProps']['ZTransp'] = GUIPARAMS['ZTransp'].val
+       PARAMS['MatProps']['Shadeless'] = GUIPARAMS['Shadeless'].val
+       
+       PARAMS['TexChannel'] = GUIPARAMS['TexChan'].val - 1 #Channels are 0-9, but GUI shows 1-10
+       PARAMS['TexProps']['UseAlpha'] = GUIPARAMS['UseAlpha'].val
+       PARAMS['TexProps']['CalcAlpha'] = GUIPARAMS['CalcAlpha'].val
+       PARAMS['TexProps']['ExtendMode'] = GUIPARAMS['ExtendMode'].val
+       PARAMS['TexMapTo']['Col'] = GUIPARAMS['MPTCol'].val
+       PARAMS['TexMapTo']['Alpha'] = GUIPARAMS['MPTAlpha'].val
+       
+       PARAMS['SeqProps']['AutoRefresh'] = GUIPARAMS['AutoRefresh'].val
+       PARAMS['SeqProps']['Cyclic'] = GUIPARAMS['Cyclic'].val
+       PARAMS['SeqProps']['Frames'] = GUIPARAMS['Frames'].val
+       PARAMS['SeqProps']['Offs'] = GUIPARAMS['Offs'].val
+       PARAMS['SeqProps']['StartFr'] = GUIPARAMS['StartFr'].val
+       return
+       
+def doScript():
+       # Main script Function
+       # Consists of choosing between 2 loops, one with a redraw, one without, see comments for why
+       
+       global CUROFFS
+       
+       translateParams()
+       
+       total = len(PARAMS['ImagePaths'])
+       broken = 0
+       
+       if GUIPARAMS['RedrawImp'].val: # Reduces the need to compare on every go through the loop
+               for i, path in enumerate(PARAMS['ImagePaths']):
+                       CUROFFS = i # Could be passed to the import Function, but I chose a global instead
+                       Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total))            
+                       imgImport(path)         
+                       Blender.Redraw()                
+                       if Blender.Get('version') >= 246:
+                               if Window.TestBreak():
+                                       broken = 1
+                                       break
+       else:
+               for i, path in enumerate(PARAMS['ImagePaths']):
+                       CUROFFS = i
+                       Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total))
+                       imgImport(path)
+                       if Blender.Get('version') >= 246:
+                               if Window.TestBreak():
+                                       broken = 1
+                                       break
+                               
+       if broken:
+               Window.DrawProgressBar(1.0, "Script Execution Aborted")
+       else:
+               Window.DrawProgressBar(1.0, "Finished Importing")
+               
+       Blender.Redraw() # Force a refresh, since the user may have chosen to not refresh as they go along
+       
+       return
+
+##########################################
+# PATH SETTERS AND CHANGERS
+##########################################
+
+def setSinglePath(filename):
+       global GUIPARAMS, PARAMS
+       GUIPARAMS['Path'].val = filename
+       PARAMS['ImagePaths'] = [filename]
+       return
+
+def setDirPath(filename):
+       global GUIPARAMS, PARAMS
+       
+       try:
+               import os
+       except:
+               Draw.PupMenu('Full install of python required to be able to set Directory Paths')
+               Draw.Exit()
+               return
+       
+       path = os.path.dirname(filename) # Blender.sys.dirname fails on '/'
+       GUIPARAMS['Path'].val = path
+       
+       ext_lower = GUIPARAMS['ImageExt'].val.lower()
+       for f in os.listdir(path):
+               if f.lower().endswith(ext_lower):
+                       PARAMS['ImagePaths'].append(os.path.join(path, f))
+       
+       return
+
+def changeExtension():
+       global GUIPARAMS, PARAMS
+       
+       if PARAMS['ImportType'] == SINGLE:
+               return
+       
+       try:
+               import os
+       except:
+               Draw.PupMenu('Full install of python required to be able to set Directory Paths')
+               Draw.Exit()
+               return
+               
+       PARAMS['ImagePaths'] = []
+       
+       ext_lower = GUIPARAMS['ImageExt'].val.lower()
+       for f in os.listdir(GUIPARAMS['Path'].val):
+               if f.lower().endswith(ext_lower):
+                       PARAMS['ImagePaths'].append(os.path.join(GUIPARAMS['Path'].val, f))
+                       
+       return
+
+##########################################
+# INTERFACE FUNCTIONS
+##########################################
+def compileMaterialList():
+       # Pretty straight forward, just grabs the materials in the blend file and constructs
+       # an appropriate string for use as a menu
+       
+       mats = [mat for mat in bpy.data.materials]
+       PARAMS['Materials'] = mats
+       title = 'Materials%t|'
+       menStrs = [mat.name + '%x' + str(i) + '|' for i, mat in enumerate(mats)]
+       return title + ''.join(menStrs)
+
+def event(evt, val):
+       # Disabled, since Esc is often used from the file browser
+       #if evt == Draw.ESCKEY:
+       #       Draw.Exit()
+               
+       return
+
+def bevent(evt):
+       global GUIPARAMS, PARAMS
+       
+       if evt == NO_EVT:
+               Draw.Redraw()
+       
+       elif evt == SINGLE_IMG:
+               Window.FileSelector(setSinglePath, 'Image', Blender.sys.expandpath('//'))
+               Draw.Redraw()
+               PARAMS['ImportType'] = SINGLE
+       
+       elif evt == DIRECTORY_IMG:
+               Window.FileSelector(setDirPath, 'Directory', Blender.sys.expandpath('//'))
+               Draw.Redraw()
+               PARAMS['ImportType'] = DIR
+               
+       elif evt == CLR_PATH:
+               GUIPARAMS['Path'].val = ''
+               PARAMS['ImagePaths'] = []
+               GUIPARAMS['ImageExt'].val = ''
+               Draw.Redraw()
+               
+       elif evt == CHG_EXT:
+               changeExtension()
+               Draw.Redraw()
+               
+       elif evt == EXIT:
+               Draw.Exit()
+               
+       elif evt == DO_SCRIPT:
+               doScript()
+               
+       else:
+               print "ERROR: UNEXPECTED BUTTON EVENT"
+                       
+       return
+
+# GUI Colors ######
+ScreenColor = [0.7, 0.7, 0.7]
+BackgroundColor = [0.8, 0.8, 0.8]
+TitleBG = [0.6, 0.6, 0.6]
+TitleCol = [1.0, 1.0, 1.0]
+ErrCol = [1.0, 0.0, 0.0]
+TextCol = [0.4, 0.4, 0.5]
+###################
+
+def GUI():
+       global GUIPARAMS, PARAMS
+       
+       BGL.glClearColor(*(ScreenColor + [1.0]))
+       BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
+       
+       minx = 5
+       maxx = 500
+       miny = 5
+       maxy = 450
+       
+       lineheight = 24
+       buPad = 5 # Generic Button Padding, most buttons should have 24-19 (or 5) px space around them
+       
+       lP = 5 # Left Padding
+       rP = 5 # Right Padding
+       
+       # Draw Background Box
+       BGL.glColor3f(*BackgroundColor)
+       BGL.glRecti(minx, miny, maxx, maxy)
+       
+       # Draw Title
+       BGL.glColor3f(*TitleBG)
+       BGL.glRecti(minx, maxy - (lineheight), maxx, maxy)
+       BGL.glColor3f(*TitleCol)
+       
+       title = "2D Cutout Image Importer v" + VERSIONSTRING
+       BGL.glRasterPos2i(minx + lP, maxy - 15)
+       Draw.Text(title, 'large')
+       
+       Draw.PushButton('Exit', EXIT, maxx-50-rP, maxy - lineheight + 2, 50, 19, "Exit Script")
+               
+       # Path Buttons
+       if GUIPARAMS['Path'].val == '':
+               Draw.PushButton('Single Image', SINGLE_IMG, minx + lP, maxy - (2*lineheight), 150, 19, "Select a Single Image to Import")
+               Draw.PushButton('Directory', DIRECTORY_IMG, minx + lP + 150, maxy - (2*lineheight), 150, 19, "Select a Directory of Images to Import")
+               
+       else:
+               Draw.PushButton('Clear', CLR_PATH, minx+lP, maxy - (2*lineheight), 50, 19, "Clear Path and Change Import Options")
+
+       GUIPARAMS['Path'] = Draw.String('Path: ', NO_EVT, minx + lP, maxy - (3*lineheight), (maxx-minx-lP-rP), 19, GUIPARAMS['Path'].val, 399, 'Path to Import From')
+       if PARAMS['ImportType'] == DIR:
+               GUIPARAMS['ImageExt'] = Draw.String('Image Ext: ', CHG_EXT, minx + lP, maxy - (4*lineheight), 110, 19,  GUIPARAMS['ImageExt'].val, 6, 'Image extension for batch directory importing (case insensitive)')
+       GUIPARAMS['PackImage'] = Draw.Toggle('Pack', NO_EVT, maxx - rP - 50, maxy - (4*lineheight), 50, 19, GUIPARAMS['PackImage'].val, 'Pack Image(s) into .Blend File')
+       
+       # Geometry and Viewport Options
+       BGL.glColor3f(*TextCol)
+       BGL.glRecti(minx+lP, maxy - (5*lineheight), maxx-rP, maxy - (5*lineheight) + 1)
+       BGL.glRasterPos2i(minx + lP, maxy-(5*lineheight) + 3)
+       Draw.Text('Geometry and Display Options', 'small')
+       
+       GUIPARAMS['PPU'] = Draw.Slider('Pixels Per Unit: ', NO_EVT, minx + lP, maxy - (6*lineheight), (maxx-minx)/2 - lP, 19, GUIPARAMS['PPU'].val, 1, 5000, 0, 'Set the Number of Pixels Per Blender Unit to preserve Image Size Relations') 
+       GUIPARAMS['VPTransp'] = Draw.Toggle('Viewport Transparency', NO_EVT, minx + lP, maxy - (8*lineheight),  (maxx-minx)/2 - lP, 2*lineheight - buPad, GUIPARAMS['VPTransp'].val, 'Display Alpha Transparency in the Viewport')
+
+       GUIPARAMS['XOff'] = Draw.Slider('Offs X: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (6*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['XOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the X-Direction if Importing Multiple Images')
+       GUIPARAMS['YOff'] = Draw.Slider('Offs Y: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (7*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['YOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the Y-Direction if Importing Multiple Images')
+       GUIPARAMS['ZOff'] = Draw.Slider('Offs Z: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (8*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['ZOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the Z-Direction if Importing Multiple Images')
+
+       # Material and Texture Options
+       BGL.glColor3f(*TextCol)
+       BGL.glRecti(minx+lP, maxy - (9*lineheight), maxx-rP, maxy - (9*lineheight) + 1)
+       BGL.glRasterPos2i(minx + lP, maxy-(9*lineheight) + 3)
+       Draw.Text('Material and Texture Options', 'small')
+       
+       half = (maxx-minx-lP-rP)/2
+       GUIPARAMS['CopyMat'] = Draw.Toggle('Copy Existing Material', NO_EVT, minx + lP, maxy-(10*lineheight), half, 19, GUIPARAMS['CopyMat'].val, 'Copy an Existing Material')
+       if GUIPARAMS['CopyMat'].val:
+               menStr = compileMaterialList()
+               GUIPARAMS['MatId'] = Draw.Menu(menStr, NO_EVT, minx + lP, maxy - (11*lineheight), half, 19, GUIPARAMS['MatId'].val, 'Material to Copy Settings From') 
+       else:
+               GUIPARAMS['MatCol'] = Draw.ColorPicker(NO_EVT, minx+lP, maxy - (13*lineheight), 40, (3*lineheight) - buPad, GUIPARAMS['MatCol'].val, 'Color of Newly Created Material')
+               GUIPARAMS['Ref'] = Draw.Slider('Ref: ', NO_EVT, minx +lP+45, maxy - (11*lineheight), half-45, 19, GUIPARAMS['Ref'].val, 0.0, 1.0, 0, 'Set the Ref Value for Created Materials')
+               GUIPARAMS['Spec'] = Draw.Slider('Spec: ', NO_EVT, minx +lP+45, maxy - (12*lineheight), half-45, 19, GUIPARAMS['Spec'].val, 0.0, 2.0, 0, 'Set the Spec Value for Created Materials')
+               GUIPARAMS['Hard'] = Draw.Slider('Hard: ', NO_EVT, minx +lP+45, maxy - (13*lineheight), half-45, 19, GUIPARAMS['Hard'].val, 1, 500, 0, 'Set the Hardness Value for Created Materials')
+               GUIPARAMS['Alpha'] = Draw.Slider('A: ', NO_EVT, minx +lP, maxy - (14*lineheight), half, 19, GUIPARAMS['Alpha'].val, 0.0, 1.0, 0, 'Set the Alpha Value for Created Materials')
+               
+               GUIPARAMS['ZTransp'] = Draw.Toggle('ZTransparency', NO_EVT, minx + lP, maxy - (15*lineheight), half, 19, GUIPARAMS['ZTransp'].val, 'Enable ZTransparency')
+               GUIPARAMS['Shadeless'] = Draw.Toggle('Shadeless', NO_EVT, minx + lP, maxy - (16*lineheight), half, 19, GUIPARAMS['Shadeless'].val, 'Enable Shadeless')
+
+       GUIPARAMS['TexChan'] = Draw.Number('Texture Channel: ', NO_EVT, minx + lP+ half + buPad, maxy - (10*lineheight), half-rP, 19, GUIPARAMS['TexChan'].val, 1, 10, 'Texture Channel for Image Texture')
+       
+       GUIPARAMS['MPTCol'] = Draw.Toggle('Color', NO_EVT, minx + lP + half + buPad, maxy - (11*lineheight), half/2, 19, GUIPARAMS['MPTCol'].val, 'Map To Color Channel')
+       GUIPARAMS['MPTAlpha'] = Draw.Toggle('Alpha', NO_EVT, minx + lP + int((1.5)*half) + buPad, maxy - (11*lineheight), half/2 - rP, 19, GUIPARAMS['MPTAlpha'].val, 'Map To Alpha Channel')
+       
+       third = int((maxx-minx-lP-rP)/6)
+       GUIPARAMS['UseAlpha'] = Draw.Toggle('Use Alpha', NO_EVT, minx + lP + half + buPad, maxy - (12*lineheight), third, 19, GUIPARAMS['UseAlpha'].val, "Use the Images' Alpha Values")
+       GUIPARAMS['CalcAlpha'] = Draw.Toggle('Calc Alpha', NO_EVT, minx + lP + half + third + buPad, maxy - (12*lineheight), third, 19, GUIPARAMS['CalcAlpha'].val, "Calculate Images' Alpha Values")
+       GUIPARAMS['ExtendMode'] = Draw.Toggle('Extend', NO_EVT, minx+lP+half+third+third+buPad, maxy - (12*lineheight), third-3, 19, GUIPARAMS['ExtendMode'].val, "Use Extend texture mode. If deselected, Repeat is used")
+       GUIPARAMS['Seq'] = Draw.Toggle('Sequence', NO_EVT, minx + lP + half + buPad, maxy - (13*lineheight), half-rP, 19, GUIPARAMS['Seq'].val, 'Set the Image(s) to use a Sequence instead of a Still')
+       
+       if GUIPARAMS['Seq'].val and not PARAMS['ImportType'] == DIR:
+               GUIPARAMS['AutoRefresh'] = Draw.Toggle('Auto Refresh', NO_EVT, minx + lP + half + buPad, maxy - (14*lineheight), half/2, 19, GUIPARAMS['AutoRefresh'].val, 'Use Auto Refresh')
+               GUIPARAMS['Cyclic'] = Draw.Toggle('Cyclic', NO_EVT, minx + lP + half + buPad + half/2, maxy - (14*lineheight), half/2 - rP, 19, GUIPARAMS['Cyclic'].val, 'Repeat Frames Cyclically`')
+
+               GUIPARAMS['Frames'] = Draw.Number('Frames: ', NO_EVT, minx +lP + half + buPad, maxy - (15*lineheight), half - rP, 19, GUIPARAMS['Frames'].val, 1, 30000, 'Sets the Number of Images of a Movie to Use')
+               GUIPARAMS['Offs'] = Draw.Number('Offs: ', NO_EVT, minx +lP + half + buPad, maxy - (16*lineheight), half/2, 19, GUIPARAMS['Offs'].val, -30000, 30000, 'Offsets the Number of the Frame to use in the Animation')
+               GUIPARAMS['StartFr'] = Draw.Number('StartFr: ', NO_EVT, minx +lP + half + buPad + half/2, maxy - (16*lineheight), half/2 - rP, 19, GUIPARAMS['StartFr'].val, 1, 30000, 'Sets the Global Starting Frame of the Movie')
+       elif GUIPARAMS['Seq'].val and PARAMS['ImportType'] == DIR:
+               BGL.glColor3f(*ErrCol)
+               BGL.glRasterPos2i(minx + lP + half + buPad + 7, maxy-(14 * lineheight) + 5)
+               Draw.Text('Sequence only available for Single Image Import', 'small')
+               
+       # Import Options
+       BGL.glColor3f(*TextCol)
+       BGL.glRecti(minx+lP, maxy - (17*lineheight), maxx-rP, maxy - (17*lineheight) + 1)
+       BGL.glRasterPos2i(minx + lP, maxy-(17*lineheight) + 3)
+       Draw.Text('Import', 'small')
+
+       if GUIPARAMS['Path'].val and GUIPARAMS['ImageExt'].val or GUIPARAMS['Path'].val and PARAMS['ImportType'] == SINGLE:
+               Draw.PushButton('Import', DO_SCRIPT, minx + lP, maxy - (18*lineheight), 75, 19, "Import Image(s)")
+       else:
+               BGL.glColor3f(*ErrCol)
+               BGL.glRasterPos2i(minx+lP, maxy - (18*lineheight) + 5)
+               Draw.Text('A path and image type must be specified to import images')
+               
+       GUIPARAMS['RedrawImp'] = Draw.Toggle('Redraw During Import', NO_EVT, maxx - rP - 150, maxy - (18*lineheight), 150, 19, GUIPARAMS['RedrawImp'].val, 'Redraw the View as Images Import')
+
+Draw.Register(GUI, event, bevent)
\ No newline at end of file
diff --git a/release/scripts/object_active_to_other.py b/release/scripts/object_active_to_other.py
new file mode 100644 (file)
index 0000000..131d1f6
--- /dev/null
@@ -0,0 +1,58 @@
+#!BPY
+"""
+Name: 'Copy Active to Selected'
+Blender: 249
+Group: 'Object'
+Tooltip: 'For every selected object, copy the active to their loc/size/rot'
+"""
+
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Script copyright (C) Campbell Barton
+#
+# This program is free software; you can 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+# --------------------------------------------------------------------------
+
+
+from Blender import Window, sys, Draw
+import bpy
+
+def my_object_util(sce):
+       ob_act = sce.objects.active
+       
+       if not ob_act:
+               Draw.PupMenu('Error%t|No active object selected')
+               return
+       
+       mats = [ob.matrixWorld for ob in sce.objects.context if ob != ob_act]
+       
+       for m in mats:
+               ob_copy = ob_act.copy()
+               sce.objects.link(ob_copy)
+               ob_copy.setMatrix(m)
+               ob_copy.Layers = ob.Layers
+               
+
+def main():
+       sce = bpy.data.scenes.active
+       
+       Window.WaitCursor(1)
+       my_object_util(sce)
+       Window.WaitCursor(0)
+
+if __name__ == '__main__':
+       main()
diff --git a/release/scripts/scripttemplate_gamelogic_module.py b/release/scripts/scripttemplate_gamelogic_module.py
new file mode 100644 (file)
index 0000000..2ef4950
--- /dev/null
@@ -0,0 +1,45 @@
+#!BPY
+"""
+Name: 'GameLogic Module'
+Blender: 249
+Group: 'ScriptTemplate'
+Tooltip: 'Basic template for new game logic modules'
+"""
+
+from Blender import Window
+import bpy
+
+script_data = \
+'''
+# This module can be accessed by a python controller with
+# its execution method set to 'Module'
+# * Set the module string to "gamelogic_module.main" (without quotes)
+# * When renaming the script it MUST have a .py extension
+# * External text modules are supported as long as they are at
+#   the same location as the blendfile or one of its libraries.
+
+import GameLogic
+
+# variables defined here will only be set once when the
+# module is first imported. Set object spesific vars
+# inside the function if you intend to use the module
+# with multiple objects.
+
+def main(cont):
+       own = cont.owner
+       
+       sens = cont.sensors['mySensor']
+       actu = cont.actuators['myActuator']
+       
+       if sens.positive:
+               cont.activate(actu)
+       else:
+               cont.deactivate(actu)
+
+# dont call main(GameLogic.getCurrentController()), the py controller will
+'''
+
+new_text = bpy.data.texts.new('gamelogic_module.py')
+new_text.write(script_data)
+bpy.data.texts.active = new_text
+Window.RedrawAll()
diff --git a/release/scripts/textplugin_convert_ge.py b/release/scripts/textplugin_convert_ge.py
new file mode 100644 (file)
index 0000000..f3b44cd
--- /dev/null
@@ -0,0 +1,863 @@
+#!BPY
+"""
+Name: 'Convert BGE 2.49'
+Blender: 246
+Group: 'TextPlugin'
+Shortcut: ''
+Tooltip: 'Attemps to update deprecated usage of game engine API.'
+"""
+
+#
+# Copyright 2009 Alex Fraser <alex@phatcore.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+#
+# This script updates game engine scripts that were designed for pre-2.49
+# versions of Blender to run with the new API. Deprecated function calls are
+# listed in attributeRenameDict. This script searches for instances of the keys
+# in a target script and re-writes them.
+#
+# Some deprecated functions are complicated to re-write. The most common
+# conversions have been implemented, but some have not. Running this will reduce
+# the number of deprecation warnings in your scripts, but may not eliminate them
+# entirely.
+#
+# NOTE: The conversion is not guaranteed to be perfect. It is strongly
+# recommended that you review all changes after running this script.
+#
+# TODO: The following attributes are either ambiguous or need special processing
+# to handle parameters. Deprecated attributes that map to multiple target
+# attributes will require a refactor of the main conversion loop in the
+# convert248to249 function: currently, it doesn't allow any conversion to
+# advance the row index by more than one.
+#
+# getLinearVelocity  (KX_SCA_AddObjectActuator, KX_ObjectActuator)
+#                    Conflicts with KX_GameObject.
+#                    Maps to multiple attributes.
+# setLinearVelocity  (KX_SCA_AddObjectActuator, KX_ObjectActuator)
+#                    Conflicts with KX_GameObject.
+#                    Maps to multiple attributes.
+# getAngularVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator)
+#                    Conflicts with KX_GameObject.
+#                    Maps to multiple attributes.
+# setAngularVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator)
+#                    Conflicts with KX_GameObject.
+#                    Maps to multiple attributes.
+# setAction          (BL_ShapeActionActuator, BL_ActionActuator)
+#                    `reset' argument has no conversion target.
+# set                (KX_VisibilityActuator, KX_IpoActuator)
+#                    Different numbers of arguments.
+#                    Arguments map to multiple attributes.
+# getIndex           (SCA_JoystickSensor)
+#                    Incompatible values: Old = 1-based index; new = 0-based.
+# getMesh            (KX_SCA_ReplaceMeshActuator)
+#                    Return types differ. Need to call object.name.
+# getObject          (KX_SCA_AddObjectActuator, KX_CameraActuator,
+#                     KX_TrackToActuator, KX_ParentActuator)
+#                    Default return type differs between classes.
+# setIndex           (SCA_JoystickSensor)
+#                    Incompatible values: Old = 1-based index; new = 0-based.
+# setObject          (KX_SCA_AddObjectActuator, KX_CameraActuator,
+#                     KX_TrackToActuator, KX_ParentActuator)
+#                    Incompatible types: Old = KX_GameObject or String; new =
+#                    KX_GameObject.
+# setOperation       (KX_SCA_DynamicActuator, KX_StateActuator)
+#                    Ambiguous: different target names.
+# getDRot            (KX_ObjectActuator)
+#                    Maps to multiple attributes.
+# setDRot            (KX_ObjectActuator)
+#                    Arguments map to multiple attributes.
+# getDLoc            (KX_ObjectActuator)
+#                    Maps to multiple attributes.
+# setDLoc            (KX_ObjectActuator)
+#                    Arguments map to multiple attributes.
+# getTorque          (KX_ObjectActuator)
+#                    Maps to multiple attributes.
+# setTorque          (KX_ObjectActuator)
+#                    Arguments map to multiple attributes.
+# getForce           (KX_ObjectActuator)
+#                    Maps to multiple attributes.
+# setForce           (KX_ObjectActuator)
+#                    Arguments map to multiple attributes.
+# position           (KX_GameObject)
+#                    Conflicts with KX_SoundActuator.
+# orientation        (KX_GameObject)
+#                    Conflicts with KX_SoundActuator.
+#
+
+import string
+import re
+
+COMMENTCHAR = '#'
+
+class ParseError(Exception): pass
+class ConversionError(Exception): pass
+
+def findBalancedParens(lines, row, col, openChar = '(', closeChar = ')'):
+       """Finds a balanced pair of parentheses, searching from lines[row][col].
+       The opening parenthesis must be on the starting line.
+       
+       Returns two tuples containing the row and column of the opening paren, and
+       the row and column of the matching paren.
+       
+       Throws a ParseError if the first character is not openChar, or if a matching
+       paren cannot be found."""
+       
+       #
+       # Find the opening coordinates.
+       #
+       oRow = row
+       oCol = col
+       line = lines[oRow]
+       while oCol < len(line):
+               if line[oCol] == openChar:
+                       break
+               elif line[oCol] == COMMENTCHAR:
+                       break
+               oCol = oCol + 1
+       
+       if oCol >= len(line) or line[oCol] != openChar or not re.match(r'^\s*$', line[col:oCol]):
+               raise ParseError, "Can't find opening parenthesis. '%s'" % openChar
+       
+       #
+       # Find the closing coordinates.
+       #
+       eRow = oRow
+       eCol = oCol + 1
+       level = 1
+       while eRow < len(lines) and level > 0:
+               line = lines[eRow]
+               while eCol < len(line) and level > 0:
+                       c = line[eCol]
+                       if c == openChar:
+                               # Found a nested paren.
+                               level = level + 1
+                       elif c == closeChar:
+                               # Exiting one level of nesting.
+                               level = level - 1
+                               if level == 0:
+                                       # Back to top level!
+                                       return (oRow, oCol), (eRow, eCol)
+                       elif c == COMMENTCHAR:
+                               # Comment. Skip the rest of the line.
+                               break
+                       eCol = eCol + 1
+               eRow = eRow + 1
+               eCol = 0
+       raise ParseError, "Couldn't find closing parenthesis."
+
+def findLastAssignment(lines, row, attrName):
+       """Finds the most recent assignment of `attrName' before `row'. Returns
+       everything after the '=' sign or None, if there was no match."""
+       contRegex = re.compile(r'[^#]*?' +      # Don't search in comments.
+                              attrName  +
+                              r'\s*=\s*(.*)')  # Assignment
+       
+       cRow = row - 1
+       while cRow >= 0:
+               match = contRegex.search(lines[cRow])
+               if match:
+                       return match.group(1)
+               cRow = cRow - 1
+       return None
+
+def replaceSubstr(s, start, end, newSubStr):
+       """Replace the contents of `s' between `start' and `end' with
+       `newSubStr'."""
+       return s[:start] + newSubStr + s[end:]
+
+def replaceNextParens(lines, row, colStart, newOpenChar, newCloseChar,
+                      oldOpenChar = '(', oldCloseChar = ')'):
+       """Replace the next set of parentheses with different characters. The
+       opening parenthesis must be located on line `row', and on or after
+       `colStart'. The closing parenthesis may be on the same line or any following
+       line. The strings are edited in-place.
+       
+       Throws a ParseError if the set of parentheses can't be found. In this case,
+       the strings in `lines' will be untouched."""
+       try:
+               pOpen, pClose = findBalancedParens(lines, row, colStart, oldOpenChar,
+                                                  oldCloseChar)
+       except ParseError:
+               raise
+       
+       # Replacement may change string length. Replace closing paren first.
+       r, c = pClose
+       lines[r] = replaceSubstr(lines[r], c, c + 1, newCloseChar)
+       # Replace opening paren.
+       r, c = pOpen
+       lines[r] = replaceSubstr(lines[r], c, c + 1, newOpenChar)
+
+def replaceSimpleGetter(lines, row, colStart, colEnd, newName):
+       """Replace a call to a simple getter function with a reference to a
+       property, e.g. foo.getBar() -> foo.bar
+       
+       The function identifier being replaced must be on line `row' and
+       between `colStart' and `colEnd'. The opening parenthesis must follow
+       immediately (whitespace is allowed). The closing parenthesis may be on the
+       same or following lines.
+       
+       Throws a ConversionError if the parentheses can't be found. In this case
+       the content of `lines' will be untouched."""
+       try:
+               replaceNextParens(lines, row, colEnd, newOpenChar = '', newCloseChar = '')
+       except ParseError:
+               raise ConversionError, ("Deprecated function reference.")
+       
+       lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName)
+
+def replaceSimpleSetter(lines, row, colStart, colEnd, newName):
+       """Replace a call to a simple setter function with a reference to a
+       property, e.g. foo.setBar(baz) -> foo.bar = baz
+       
+       The function identifier being replaced must be on line `row' and
+       between `colStart' and `colEnd'. The opening parenthesis must follow
+       immediately (whitespace is allowed). The closing parenthesis may be on the
+       same or following lines.
+       
+       Throws a ConversionError if the parentheses can't be found. In this case
+       the content of `lines' will be untouched."""
+       try:
+               replaceNextParens(lines, row, colEnd, newOpenChar = '', newCloseChar = '')
+       except ParseError:
+               raise ConversionError, ("Deprecated function reference.")
+       
+       lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName + ' = ')
+
+def replaceArgsWithListSetter(lines, row, colStart, colEnd, newName):
+       """Replace a call to a multi-agument setter function with a reference to a
+       list property, e.g. foo.setBar(baz, bazZ) -> foo.bar = [baz, bazZ]
+       
+       The function identifier being replaced must be on line `row' and
+       between `colStart' and `colEnd'. The opening parenthesis must follow
+       immediately (whitespace is allowed). The closing parenthesis may be on the
+       same or following lines.
+       
+       Throws a ConversionError if the parentheses can't be found. In this case
+       the content of `lines' will be untouched."""
+       try:
+               replaceNextParens(lines, row, colEnd, newOpenChar = '[', newCloseChar = ']')
+       except ParseError:
+               raise ConversionError, ("Deprecated function reference.")
+       
+       lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName + ' = ')
+       
+
+def replaceKeyedGetter(lines, row, colStart, colEnd, newName):
+       """Replace a call to a keyed getter function with a reference to a
+       property, e.g. foo.getBar(baz) -> foo.bar[baz]
+       
+       The function identifier being replaced must be on line `row' and
+       between `colStart' and `colEnd'. The opening parenthesis must follow
+       immediately (whitespace is allowed). The closing parenthesis may be on the
+       same or following lines.
+       
+       Throws a ConversionError if the parentheses can't be found. In this case
+       the content of `lines' will be untouched."""
+       try:
+               replaceNextParens(lines, row, colEnd, newOpenChar = '[', newCloseChar = ']')
+       except ParseError:
+               raise ConversionError, ("Deprecated function reference.")
+       
+       lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName)
+def replaceGetXYPosition(lines, row, colStart, colEnd, axis):
+       '''SCA_MouseSensor.getXPosition; SCA_MouseSensor.getYPosition.
+       This is like a keyed getter, but the key is embedded in the attribute
+       name.
+       
+       Throws a ConversionError if the parentheses can't be found. In this case
+       the content of `lines' will be untouched.'''
+       try:
+               (openRow, openCol), (closeRow, closeCol) = findBalancedParens(lines,
+                       row, colEnd)
+       except ParseError:
+               raise ConversionError, "Deprecated function reference."
+       if closeRow != row:
+               raise ConversionError, "Can't modify multiple lines."
+       
+       lines[row] = replaceSubstr(lines[row], openCol, closeCol + 1,
+               "[%s]" % axis)
+       
+       lines[row] = replaceSubstr(lines[row], colStart, colEnd, 'position')
+
+def replaceRename(lines, row, colStart, colEnd, newName):
+       """Replace an identifier with another, e.g.
+       foo.getBar() -> foo.getBaz()
+       foo.bar -> foo.baz
+       
+       The identifier being replaced must be on line `row' and between `colStart'
+       and `colEnd'."""
+       lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName)
+
+def replaceAddActiveActuator(lines, row, colStart, colEnd, closure):
+       '''Extra work needs to be done here to find out the name of the controller,
+       and whether the actuator should be activated or deactivated.
+       
+       Throws a ConversionError if the actuator, controller or condition can't be
+       found. In this case the content of `lines' will be untouched.'''
+       try:
+               (openRow, openCol), (closeRow, closeCol) = findBalancedParens(lines, row, colEnd)
+       except ParseError:
+               ConversionError, "Can't find arguments."
+       
+       if closeRow != openRow:
+               raise ConversionError, ("Can't perform conversion: arguments span multiple lines.")
+       
+       args = lines[row][openCol + 1:closeCol]
+       match = re.search(r'([a-zA-Z_]\w*)'       # Actuator identifier
+                         r',\s*'
+                         r'([0-9a-zA-Z_]\w*)',      # Condition (boolean)
+                                         args)
+       if not match:
+               raise ConversionError, "Can't find arguments."
+       
+       actuator = match.group(1)
+       condition = match.group(2)
+       controller = None
+       
+       assn = findLastAssignment(lines, row, actuator)
+       if assn:
+               match = re.search(r'([a-zA-Z_]\w*)'           # Controller identifier
+                                 r'\s*\.\s*'                 # Dot
+                                 r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier
+                                 assn)
+               if match:
+                       controller = match.group(1)
+       
+       if not controller:
+               raise ConversionError, "Can't find actuator's controller."
+       
+       gameLogicStart = lines[row].rfind("GameLogic", 0, colStart)
+       if gameLogicStart < 0:
+               raise ConversionError, "Can't find GameLogic identifier."
+       
+       newExpr = None
+       if condition in ['1', 'True']:
+               newExpr = "%s.activate(%s)" % (controller, actuator)
+       elif condition in ['0', 'False']:
+               newExpr = "%s.deactivate(%s)" % (controller, actuator)
+       else:
+               newExpr = "(lambda: %s and (%s.activate(%s) or True) or %s.deactivate(%s))()" % (
+                               condition, controller, actuator, controller, actuator)
+       lines[row] = replaceSubstr(lines[row], gameLogicStart, closeCol + 1, newExpr)
+
+def getObject(line, attributeStart):
+       '''Get the object that an attribute belongs to. `attributeStart' is the
+       index of the first character of the attribute name in the string `line'.
+       Returns: the identifier preceding `attributeStart', or None if one can't be
+       found.'''
+       match = re.search(r'([a-zA-Z_]\w*)\s*\.\s*$', line[0:attributeStart])
+       if not match:
+               return None
+       return match.group(1)
+
+def replaceGetActuator(lines, row, colStart, colEnd, closure):
+       '''getActuator is ambiguous: it could belong to SCA_IController or 
+       SCA_ActuatorSensor. Try to resolve and then convert.
+       
+       Raises a ConversionError if the parentheses can't be found, or if the
+       ambiguity can't be resolved.'''
+       # Get the name of the object this attribute is attached to.
+       obName = getObject(lines[row], colStart)
+       if obName:
+               # Try to find out whether the object is a controller.
+               assn = findLastAssignment(lines, row, obName)
+               if assn and re.search(r'GameLogic\s*\.\s*getCurrentController', assn):
+                       # It is (probably) a controller!
+                       replaceKeyedGetter(lines, row, colStart, colEnd, 'actuators')
+                       return
+       
+       raise ConversionError, "Ambiguous: addActiveActuator -> actuators[key] (SCA_IController) or actuator (SCA_ActuatorSensor)."
+
+def replaceSetOrientation(lines, row, colStart, colEnd, closure):
+       '''setOrientation is ambiguous: it could belong to KX_SoundActuator or 
+       KX_GameObject. Try to resolve and then convert. If the type can't be
+       determined, it is assumed to be a KX_GameObject. Currently, only the
+       conversion for KX_GameObject is implemented.
+       
+       Raises a ConversionError if the parentheses can't be found, or if the
+       object is found to be a KX_SoundActuator.'''
+       # Get the name of the object this attribute is attached to.
+       obName = getObject(lines[row], colStart)
+       if obName:
+               # Try to find out whether the object is an actuator.
+               assn = findLastAssignment(lines, row, obName)
+               if assn:
+                       match = re.search(r'([a-zA-Z_]\w*)'           # Controller identifier
+                                                       r'\s*\.\s*'                 # Dot
+                                                       r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier
+                                                       assn)
+                       if match:
+                               # It's probably a KX_SoundActuator.
+                               raise ConversionError, "Not implemented: Can't convert arguments to matrix."
+       
+       # It's probably a KX_GameObject.
+       replaceSimpleSetter(lines, row, colStart, colEnd, 'localOrientation')
+
+def replaceSetPosition(lines, row, colStart, colEnd, closure):
+       '''setPosition is ambiguous: it could belong to KX_SoundActuator or 
+       KX_GameObject. Try to resolve and then convert. If the type can't be
+       determined, it is assumed to be a KX_GameObject.
+       
+       Raises a ConversionError if the parentheses can't be found.'''
+       # Get the name of the object this attribute is attached to.
+       obName = getObject(lines[row], colStart)
+       if obName:
+               # Try to find out whether the object is an actuator.
+               assn = findLastAssignment(lines, row, obName)
+               if assn:
+                       match = re.search(r'([a-zA-Z_]\w*)'           # Controller identifier
+                                                       r'\s*\.\s*'                 # Dot
+                                                       r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier
+                                                       assn)
+                       if match:
+                               # It's probably a KX_SoundActuator.
+                               replaceSimpleSetter(lines, row, colStart, colEnd, 'position')
+       
+       # It's probably a KX_GameObject.
+       replaceSimpleSetter(lines, row, colStart, colEnd, 'localPosition')
+
+def replaceSplitProperty(lines, row, colStart, colEnd, (newGetter, newSetter)):
+       '''Some property attributes behave differently when being written to or read
+       from. Try to determine the operation, and replace accordingly. E.G.
+       o.position = foo -> o.localPosition = foo   # set
+       foo = o.position -> foo = o.worldPosition   # get
+
+       This implementation can not handle cases where the object is returned from
+       a function, e.g.
+       foo = bar.getObject().position # Error!
+
+       Raises a ConversionError if the operation can't be determined, or if the
+       object is returned from a function.'''
+       assnRegex = re.compile(r'(=\s*)?' # Getter
+                                                       r'[a-zA-Z_]\w*' # Object identifier
+                                                       r'\.([a-zA-Z_][a-zA-Z0-9_.]*)+' # Trailing attributes
+                                                       r'(\s*=)?') # Setter
+       match = assnRegex.search(lines[row])
+       
+       if not match:
+               raise ConversionError, "Can't determine operation (getting or setting)."
+
+       setting = False
+       getting = False
+       if match.group(1):
+                       getting = True
+       if match.group(3):
+                       setting = True
+       if (getting and setting) or ((not getting) and (not setting)):
+                       raise ConversionError, "Can't determine operation (getting or setting)."
+
+       if getting:
+                       replaceRename(lines, row, colStart, colEnd, newGetter)
+       else:
+                       replaceRename(lines, row, colStart, colEnd, newSetter)
+
+def notImplemented(lines, row, colStart, colEnd, classNames):
+       message = "Conversion not implemented. See documentation for " +\
+                 string.join(classNames, ', ')
+       raise ConversionError, message
+
+#
+# Deprecated attribute information. The format is:
+# deprecatedAttributeName: (conversionFunction, closure)
+# Usually the closure will be the name of the superceding attribute.
+#
+# Since each deprecated attribute can appear in this dictionary only once, it is
+# the conversion function's responsibility to resolve ambiguity.
+#
+attributeRenameDict = {
+ # Special cases
+ 'addActiveActuator': (replaceAddActiveActuator, None), # 
+ 'getActuator': (replaceGetActuator, None), # SCA_IController, SCA_ActuatorSensor
+ 'getXPosition': (replaceGetXYPosition, '0'), # SCA_MouseSensor
+ 'getYPosition': (replaceGetXYPosition, '1'), # SCA_MouseSensor
+ 'setOrientation': (replaceSetOrientation, None), # KX_GameObject, KX_SoundActuator
+ 'setPosition': (replaceSetPosition, None), # KX_GameObject, KX_SoundActuator
+
+ # Keyed getters/setters
+ 'getSensor': (replaceKeyedGetter, 'sensors'), # SCA_IController
+
+ # Multi-arg -> List setter
+ 'setAxis': (replaceArgsWithListSetter, 'axis'), # SCA_JoystickSensor
+ 'setForceLimitX': (replaceArgsWithListSetter, 'forceLimitX'), # KX_ObjectActuator
+ 'setForceLimitY': (replaceArgsWithListSetter, 'forceLimitY'), # KX_ObjectActuator
+ 'setForceLimitZ': (replaceArgsWithListSetter, 'forceLimitZ'), # KX_ObjectActuator
+ 'setHat': (replaceArgsWithListSetter, 'hat'), # SCA_JoystickSensor
+ 'setPID': (replaceArgsWithListSetter, 'pid'), # KX_ObjectActuator
+ 'setVelocity': (replaceArgsWithListSetter, 'velocity'), # KX_SoundActuator
+
+ # Straight rename
+ 'getButtonValue': (replaceRename, 'getButtonActiveList'), # SCA_JoystickSensor
+
+ # Split properties
+ 'scaling': (replaceSplitProperty, ('worldScaling', 'localScaling')), # KX_GameObject
+
+ # Simple getters/setters
+ 'getSensors': (replaceSimpleGetter, 'sensors'), # SCA_IController
+ 'getActuators': (replaceSimpleGetter, 'actuators'), # SCA_IController
+ 'enableViewport': (replaceSimpleSetter, 'useViewport'), # KX_Camera
+ 'getAction': (replaceSimpleGetter, 'action'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getAxis': (replaceSimpleGetter, 'axis'), # SCA_JoystickSensor
+ 'getAxisValue': (replaceSimpleGetter, 'axisValues'), # SCA_JoystickSensor
+ 'getBlendin': (replaceSimpleGetter, 'blendIn'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getBodies': (replaceSimpleGetter, 'bodies'), # KX_NetworkMessageSensor
+ 'getButton': (replaceSimpleGetter, 'button'), # SCA_JoystickSensor
+ 'getCamera': (replaceSimpleGetter, 'camera'), # KX_SceneActuator
+ 'getConeOrigin': (replaceSimpleGetter, 'coneOrigin'), # KX_RadarSensor
+ 'getConeTarget': (replaceSimpleGetter, 'coneTarget'), # KX_RadarSensor
+ 'getContinue': (replaceSimpleGetter, 'useContinue'), # BL_ActionActuator
+ 'getCurrentlyPressedKeys': (replaceSimpleGetter, 'events'), # SCA_KeyboardSensor
+ 'getDamping': (replaceSimpleGetter, 'damping'), # KX_ObjectActuator
+ 'getDelay': (replaceSimpleGetter, 'delay'), # SCA_DelaySensor
+ 'getDistribution': (replaceSimpleGetter, 'distribution'), # SCA_RandomActuator
+ 'getDuration': (replaceSimpleGetter, 'duration'), # SCA_DelaySensor
+ 'getEnd': (replaceSimpleGetter, 'frameEnd'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
+ 'getExecutePriority': (replaceSimpleGetter, 'executePriority'), # SCA_ILogicBrick
+ 'getFile': (replaceSimpleGetter, 'fileName'), # KX_GameActuator
+ 'getFilename': (replaceSimpleGetter, 'fileName'), # KX_SoundActuator
+ 'getForceIpoActsLocal': (replaceSimpleGetter, 'useIpoLocal'), # KX_IpoActuator
+ 'getForceLimitX': (replaceSimpleGetter, 'forceLimitX'), # KX_ObjectActuator
+ 'getForceLimitY': (replaceSimpleGetter, 'forceLimitY'), # KX_ObjectActuator
+ 'getForceLimitZ': (replaceSimpleGetter, 'forceLimitZ'), # KX_ObjectActuator
+ 'getFrame': (replaceSimpleGetter, 'frame'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getFrameMessageCount': (replaceSimpleGetter, 'frameMessageCount'), # KX_NetworkMessageSensor
+ 'getFrameProperty': (replaceSimpleGetter, 'framePropName'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getFrequency': (replaceSimpleGetter, 'frequency'), # SCA_ISensor
+ 'getGain': (replaceSimpleGetter, 'volume'), # KX_SoundActuator, KX_CDActuator
+ 'getHat': (replaceSimpleGetter, 'hat'), # SCA_JoystickSensor
+ 'getHeight': (replaceSimpleGetter, 'height'), # KX_CameraActuator
+ 'getHitNormal': (replaceSimpleGetter, 'hitNormal'), # KX_MouseFocusSensor, KX_RaySensor
+ 'getHitObject': (replaceSimpleGetter, 'hitObject'), # KX_MouseFocusSensor, KX_RaySensor, KX_TouchSensor
+ 'getHitObjectList': (replaceSimpleGetter, 'hitObjectList'), # KX_TouchSensor
+ 'getHitPosition': (replaceSimpleGetter, 'hitPosition'), # KX_MouseFocusSensor, KX_RaySensor
+ 'getHold1': (replaceSimpleGetter, 'hold1'), # SCA_KeyboardSensor
+ 'getHold2': (replaceSimpleGetter, 'hold2'), # SCA_KeyboardSensor
+ 'getInvert': (replaceSimpleGetter, 'invert'), # SCA_ISensor
+ 'getIpoAdd': (replaceSimpleGetter, 'useIpoAdd'), # KX_IpoActuator
+ 'getIpoAsForce': (replaceSimpleGetter, 'useIpoAsForce'), # KX_IpoActuator
+ 'getKey': (replaceSimpleGetter, 'key'), # SCA_KeyboardSensor
+ 'getLastCreatedObject': (replaceSimpleGetter, 'objectLastCreated'), # KX_SCA_AddObjectActuator
+ 'getLevel': (replaceSimpleGetter, 'level'), # SCA_ISensor
+ 'getLightList': (replaceSimpleGetter, 'lights'), # KX_Scene
+ 'getLooping': (replaceSimpleGetter, 'looping'), # KX_SoundActuator
+ 'getMass': (replaceSimpleGetter, 'mass'), # KX_GameObject
+ 'getMax': (replaceSimpleGetter, 'max'), # KX_CameraActuator
+ 'getMin': (replaceSimpleGetter, 'min'), # KX_CameraActuator
+ 'getName': (replaceSimpleGetter, 'name'), # KX_Scene
+ 'getNumAxes': (replaceSimpleGetter, 'numAxis'), # SCA_JoystickSensor
+ 'getNumButtons': (replaceSimpleGetter, 'numButtons'), # SCA_JoystickSensor
+ 'getNumHats': (replaceSimpleGetter, 'numHats'), # SCA_JoystickSensor
+ 'getObjectList': (replaceSimpleGetter, 'objects'), # KX_Scene
+ 'getOperation': (replaceSimpleGetter, 'mode'), # KX_SCA_DynamicActuator
+ 'getOrientation': (replaceSimpleGetter, 'worldOrientation'), # KX_GameObject
+ 'getOwner': (replaceSimpleGetter, 'owner'), # SCA_ILogicBrick
+ 'getPara1': (replaceSimpleGetter, 'para1'), # SCA_RandomActuator
+ 'getPara2': (replaceSimpleGetter, 'para2'), # SCA_RandomActuator
+ 'getParent': (replaceSimpleGetter, 'parent'), # KX_GameObject
+ 'getPID': (replaceSimpleGetter, 'pid'), # KX_ObjectActuator
+ 'getPitch': (replaceSimpleGetter, 'pitch'), # KX_SoundActuator
+ 'getPosition': (replaceSimpleGetter, 'worldPosition'), # KX_GameObject
+ 'getPressedKeys': (replaceSimpleGetter, 'events'), # SCA_KeyboardSensor
+ 'getPriority': (replaceSimpleGetter, 'priority'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getProjectionMatrix': (replaceSimpleGetter, 'projection_matrix'), # KX_Camera
+ 'getProperty': (replaceSimpleGetter, 'propName'), # SCA_PropertySensor, SCA_RandomActuator, SCA_PropertyActuator
+ 'getRayDirection': (replaceSimpleGetter, 'rayDirection'), # KX_MouseFocusSensor, KX_RaySensor
+ 'getRaySource': (replaceSimpleGetter, 'raySource'), # KX_MouseFocusSensor
+ 'getRayTarget': (replaceSimpleGetter, 'rayTarget'), # KX_MouseFocusSensor
+ 'getRepeat': (replaceSimpleGetter, 'repeat'), # SCA_DelaySensor
+ 'getRollOffFactor': (replaceSimpleGetter, 'rollOffFactor'), # KX_SoundActuator
+ 'getScene': (replaceSimpleGetter, 'scene'), # KX_SceneActuator
+ 'getScript': (replaceSimpleGetter, 'script'), # SCA_PythonController
+ 'getSeed': (replaceSimpleGetter, 'seed'), # SCA_RandomActuator
+ 'getStart': (replaceSimpleGetter, 'frameStart'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
+ 'getState': (replaceSimpleGetter, 'state'), # SCA_IController, KX_GameObject
+ 'getSubject': (replaceSimpleGetter, 'subject'), # KX_NetworkMessageSensor
+ 'getSubjects': (replaceSimpleGetter, 'subjects'), # KX_NetworkMessageSensor
+ 'getThreshold': (replaceSimpleGetter, 'threshold'), # SCA_JoystickSensor
+ 'getTime': (replaceSimpleGetter, 'time'), # KX_SCA_AddObjectActuator, KX_TrackToActuator
+ 'getTouchMaterial': (replaceSimpleGetter, 'useMaterial'), # KX_TouchSensor
+ 'getType': (replaceSimpleGetter, 'mode'), # SCA_PropertySensor
+ 'getUse3D': (replaceSimpleGetter, 'use3D'), # KX_TrackToActuator
+ 'getUseNegPulseMode': (replaceSimpleGetter, 'useNegPulseMode'), # SCA_ISensor
+ 'getUsePosPulseMode': (replaceSimpleGetter, 'usePosPulseMode'), # SCA_ISensor
+ 'getUseRestart': (replaceSimpleGetter, 'useRestart'), # KX_SceneActuator
+ 'getValue': (replaceSimpleGetter, 'value'), # SCA_PropertySensor, SCA_PropertyActuator
+ 'getVisible': (replaceSimpleGetter, 'visible'), # KX_GameObject
+ 'getXY': (replaceSimpleGetter, 'useXY'), # KX_CameraActuator
+ 'isConnected': (replaceSimpleGetter, 'connected'), # SCA_JoystickSensor
+ 'isPositive': (replaceSimpleGetter, 'positive'), # SCA_ISensor
+ 'isTriggered': (replaceSimpleGetter, 'triggered'), # SCA_ISensor
+ 'setActuator': (replaceSimpleSetter, 'actuator'), # SCA_ActuatorSensor
+ 'setBlendin': (replaceSimpleSetter, 'blendIn'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setBlendtime': (replaceSimpleSetter, 'blendTime'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setBodyType': (replaceSimpleSetter, 'usePropBody'), # KX_NetworkMessageActuator
+ 'setBody': (replaceSimpleSetter, 'body'), # KX_NetworkMessageActuator
+ 'setButton': (replaceSimpleSetter, 'button'), # SCA_JoystickSensor
+ 'setCamera': (replaceSimpleSetter, 'camera'), # KX_SceneActuator
+ 'setContinue': (replaceSimpleSetter, 'useContinue'), # BL_ActionActuator
+ 'setDamping': (replaceSimpleSetter, 'damping'), # KX_ObjectActuator
+ 'setDelay': (replaceSimpleSetter, 'delay'), # SCA_DelaySensor
+ 'setDuration': (replaceSimpleSetter, 'duration'), # SCA_DelaySensor
+ 'setEnd': (replaceSimpleSetter, 'frameEnd'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
+ 'setExecutePriority': (replaceSimpleSetter, 'executePriority'), # SCA_ILogicBrick
+ 'setFile': (replaceSimpleSetter, 'fileName'), # KX_GameActuator
+ 'setFilename': (replaceSimpleSetter, 'fileName'), # KX_SoundActuator
+ 'setForceIpoActsLocal': (replaceSimpleSetter, 'useIpoLocal'), # KX_IpoActuator
+ 'setFrame': (replaceSimpleSetter, 'frame'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setFrameProperty': (replaceSimpleSetter, 'framePropName'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setFrequency': (replaceSimpleSetter, 'frequency'), # SCA_ISensor
+ 'setGain': (replaceSimpleSetter, 'volume'), # KX_SoundActuator, KX_CDActuator
+ 'setHeight': (replaceSimpleSetter, 'height'), # KX_CameraActuator
+ 'setHold1': (replaceSimpleSetter, 'hold1'), # SCA_KeyboardSensor
+ 'setHold2': (replaceSimpleSetter, 'hold2'), # SCA_KeyboardSensor
+ 'setInvert': (replaceSimpleSetter, 'invert'), # SCA_ISensor
+ 'setIpoAdd': (replaceSimpleSetter, 'useIpoAdd'), # KX_IpoActuator
+ 'setIpoAsForce': (replaceSimpleSetter, 'useIpoAsForce'), # KX_IpoActuator
+ 'setKey': (replaceSimpleSetter, 'key'), # SCA_KeyboardSensor
+ 'setLevel': (replaceSimpleSetter, 'level'), # SCA_ISensor
+ 'setLooping': (replaceSimpleSetter, 'looping'), # KX_SoundActuator
+ 'setMask': (replaceSimpleSetter, 'mask'), # KX_StateActuator
+ 'setMax': (replaceSimpleSetter, 'max'), # KX_CameraActuator
+ 'setMesh': (replaceSimpleSetter, 'mesh'), # KX_SCA_ReplaceMeshActuator
+ 'setMin': (replaceSimpleSetter, 'min'), # KX_CameraActuator
+ 'setPitch': (replaceSimpleSetter, 'pitch'), # KX_SoundActuator
+ 'setPriority': (replaceSimpleSetter, 'priority'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setProjectionMatrix': (replaceSimpleSetter, 'projection_matrix'), # KX_Camera
+ 'setProperty': (replaceSimpleSetter, 'propName'), # KX_IpoActuator, SCA_PropertySensor, SCA_RandomActuator, SCA_PropertyActuator
+ 'setRepeat': (replaceSimpleSetter, 'repeat'), # SCA_DelaySensor
+ 'setRollOffFactor': (replaceSimpleSetter, 'rollOffFactor'), # KX_SoundActuator
+ 'setScene': (replaceSimpleSetter, 'scene'), # KX_SceneActuator
+ 'setScript': (replaceSimpleSetter, 'script'), # SCA_PythonController
+ 'setSeed': (replaceSimpleSetter, 'seed'), # SCA_RandomActuator
+ 'setStart': (replaceSimpleSetter, 'frameStart'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
+ 'setState': (replaceSimpleSetter, 'state'), # KX_GameObject
+ 'setSubject': (replaceSimpleSetter, 'subject'), # KX_NetworkMessageActuator
+ 'setSubjectFilterText': (replaceSimpleSetter, 'subject'), # KX_NetworkMessageSensor
+ 'setThreshold': (replaceSimpleSetter, 'threshold'), # SCA_JoystickSensor
+ 'setTime': (replaceSimpleSetter, 'time'), # KX_SCA_AddObjectActuator, KX_TrackToActuator
+ 'setToPropName': (replaceSimpleSetter, 'propName'), # KX_NetworkMessageActuator
+ 'setType': (replaceSimpleSetter, 'mode'), # SCA_PropertySensor
+ 'setUse3D': (replaceSimpleSetter, 'use3D'), # KX_TrackToActuator
+ 'setUseNegPulseMode': (replaceSimpleSetter, 'useNegPulseMode'), # SCA_ISensor
+ 'setUsePosPulseMode': (replaceSimpleSetter, 'usePosPulseMode'), # SCA_ISensor
+ 'setUseRestart': (replaceSimpleSetter, 'useRestart'), # KX_SceneActuator
+ 'setValue': (replaceSimpleSetter, 'value'), # SCA_PropertySensor, SCA_PropertyActuator
+ 'setXY': (replaceSimpleSetter, 'useXY'), # KX_CameraActuator
+
+ # Unimplemented!
+ 'getLinearVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
+ 'setLinearVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
+ 'getAngularVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
+ 'setAngularVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
+ 'setAction': (notImplemented, ['BL_ShapeActionActuator', 'BL_ActionActuator']),
+ 'set': (notImplemented, ['KX_VisibilityActuator', 'KX_IpoActuator']),
+ 'getIndex': (notImplemented, ['SCA_JoystickSensor']),
+ 'getMesh': (notImplemented, ['KX_SCA_ReplaceMeshActuator']),
+ 'getObject': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_CameraActuator', 'KX_TrackToActuator', 'KX_ParentActuator']),
+ 'setIndex': (notImplemented, ['SCA_JoystickSensor']),
+ 'setObject': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_CameraActuator', 'KX_TrackToActuator', 'KX_ParentActuator']),
+ 'setOperation': (notImplemented, ['KX_SCA_DynamicActuator', 'KX_StateActuator']),
+ 'position': (notImplemented, ['KX_GameObject', 'KX_SoundActuator']),
+ 'orientation': (notImplemented, ['KX_GameObject', 'KX_SoundActuator']),
+ 'getDRot': (notImplemented, ['KX_ObjectActuator']),
+ 'setDRot': (notImplemented, ['KX_ObjectActuator']),
+ 'getDLoc': (notImplemented, ['KX_ObjectActuator']),
+ 'setDLoc': (notImplemented, ['KX_ObjectActuator']),
+ 'getTorque': (notImplemented, ['KX_ObjectActuator']),
+ 'getTorque': (notImplemented, ['KX_ObjectActuator']),
+ 'getForce': (notImplemented, ['KX_ObjectActuator']),
+ 'setForce': (notImplemented, ['KX_ObjectActuator']),
+}
+
+def convert248to249(lines, log = True, logErrors = True, fileName = None):
+       # Regular expression for finding attributes. For the string 'a.b', this
+       # returns three groups: ['a.b', 'a.', 'b']. The last is the attribute name.
+       attrRegex = re.compile(r'\.\s*'           # Dot
+                              r'([a-zA-Z_]\w*)') # Identifier
+       
+       fileIdStr = ""
+       if fileName:
+               fileIdStr = fileName + ": "
+       row = 0
+       col = 0
+       nconverted = 0
+       nerrors = 0
+       while row < len(lines):
+               originalLine = lines[row]
+               changed = False
+               while col < len(lines[row]):
+                       # Don't search past comment. We have to check each iteration
+                       # because the line contents may have changed.
+                       commentStart = lines[row].find('#', col)
+                       if commentStart < 0:
+                               commentStart = len(lines[row])
+                       
+                       # Search for an attribute identifier.
+                       match = attrRegex.search(lines[row], col, commentStart)
+                       if not match:
+                               break
+                       
+                       attrName = match.group(1)
+                       if attributeRenameDict.has_key(attrName):
+                               # name is deprecated.
+                               func, closure = attributeRenameDict[attrName]
+                               try:
+                                       # Convert!
+                                       func(lines, row, match.start(1), match.end(1), closure)
+                               except ConversionError as e:
+                                       # Insert a comment saying the conversion failed.
+                                       print "ERROR: %sline %d, %s: %s\n" % (
+                                               fileIdStr, row + 1, attrName, e)
+                                       if logErrors:
+                                               lines.insert(row,
+                                                                       "##248## ERROR: %s: %s\n" %
+                                                                       (attrName, e))
+                                               row = row + 1
+                                       nerrors = nerrors + 1
+                               else:
+                                       changed = True
+                                       nconverted = nconverted + 1
+                       # Search the rest of this line.
+                       col = match.start(1)
+               
+               if changed and log:
+                       # Insert a comment to showing difference in lines.
+                       if originalLine[-1] != '\n':
+                               originalLine = originalLine + '\n'
+                       lines.insert(row, "##248##%s" % originalLine)
+                       row = row + 1
+               
+               row = row + 1
+               col = 0
+       return nconverted, nerrors
+
+def usage():
+       print "Usage: blender248to249.py [options] <infile> [outfile]"
+       print "Options:"
+       print "\t--nolog         Don't include old lines as comments."
+       print "\t--quieterrors   Don't insert errors as comments."
+
+def runAsConsoleScript():
+       '''Called when being run as a console script.'''
+       try:
+               opts, args = getopt.getopt(sys.argv[1:], "", ["nolog", "quieterrors"])
+       except getopt.GetoptError, err:
+               # print help information and exit:
+               print str(err)
+               usage()
+               sys.exit(2)
+       
+       log = True
+       logErrors = True
+       for o, a in opts:
+               if o == "--nolog":
+                       log = False
+               elif o == "--quieterrors":
+                       logErrors = False
+       
+       try:
+               inpath = args.pop(0)
+       except IndexError:
+               usage()
+               sys.exit(2)
+       try:
+               outpath = args.pop(0)
+       except IndexError:
+               outpath = inpath
+       
+       infile = io.FileIO(inpath, 'r')
+       # arbitrary file size of around 100kB
+       lines = infile.readlines(100000)
+       infile.close()
+
+       nconverted, nerrors = convert248to249(lines, log, logErrors)
+       
+       outfile = io.FileIO(outpath, 'w')
+       outfile.writelines(lines)
+       outfile.close()
+       print "Conversion finished. Modified %d attributes." % nconverted
+       print "There were %d errors." % nerrors
+       print "Please review all the changes."
+
+def runAsTextPlugin():
+       '''Called when run as a text plugin.'''
+       
+       import Blender
+       from Blender import Window, sys, Draw
+       import BPyTextPlugin, bpy
+       
+       message = ("Convert Game Engine script from 4.48 API to 2.49 API%t|"
+                  "Run on active script only%x1|"
+                  "Run on ALL text buffers%x2")
+       convertAllBuffers = Draw.PupMenu(message) == 2
+       
+       Window.WaitCursor(1)
+       try:
+               nconverted = 0
+               nerrors = 0
+               
+               if convertAllBuffers:
+                       texts = bpy.data.texts
+               else:
+                       if not bpy.data.texts.active:
+                               Draw.PupMenu("No active buffer.")
+                               return
+                       texts = [bpy.data.texts.active]
+               
+               Blender.SaveUndoState('Convert BGE 2.49')
+
+               for txt in texts:
+                       bufName = txt.name
+                       if txt.lib:
+                               bufName = txt.lib + '/' + bufName
+                       lines = txt.asLines()
+                       for i in range(0, len(lines)):
+                               if not lines[i].endswith('\n'):
+                                       lines[i] = lines[i] + '\n'
+                       
+                       nc, ne = convert248to249(lines, fileName = bufName)
+                       nconverted = nconverted + nc
+                       nerrors = nerrors + ne
+                       txt.clear()
+                       for line in lines:
+                               txt.write(line)
+       
+       finally:
+               Window.WaitCursor(0)
+               
+               message = "Converted %d attributes." % nconverted
+               if nerrors == 1:
+                       message = message + " There was 1 error (see console)."
+               if nerrors > 1:
+                       message = message + " There were %d errors (see console)." % nerrors
+               message = message + "|Please review all the changes."
+               Draw.PupMenu(message)
+
+def main():
+       try:
+               import Blender
+       except ImportError:
+               runAsConsoleScript()
+       else:
+               runAsTextPlugin()
+
+# This lets you import the script without running it
+if __name__ == "__main__":
+       import sys
+       import getopt
+       import io
+       main()
diff --git a/release/scripts/wizard_bolt_factory.py b/release/scripts/wizard_bolt_factory.py
new file mode 100644 (file)
index 0000000..6a280ec
--- /dev/null
@@ -0,0 +1,2804 @@
+#!BPY
+# -*- coding: latin-1 -*-
+"""
+Name: 'Bolt Factory'
+Blender: 248
+Group: 'Wizards'
+Tooltip: 'Create models of various types of screw fasteners.'
+"""
+
+__author__ = " Aaron Keith (Spudmn) "
+__version__ = "2.00 2009/05/22"
+__url__ = ["Author's site,http://sourceforge.net/projects/boltfactory/", "Blender,http://wiki.blender.org/index.php/Extensions:Py/Scripts/Manual/Misc/Bolt_Factory"]
+__bpydoc__ = """\
+Bolt_Factory.py 
+
+Bolt Factory is a Python script for Blender 3D.
+
+The script allows the user to create models of various types of screw fasteners.
+
+For best results set the material to smooth and apply a Edge Split modifier
+with default settings.
+
+
+History:
+
+V2.00 22/05/09 by Aaron Keith
+
+- Better error checking.
+- Lock Nut and Hex Nut meshes added.
+- Pre-sets for common metric bolts and nuts.
+- Improved GUI.
+- Meshes scaled to a smaller size
+- Fixed bug when using crest and root percent other than 10%
+- Can now create meshes in Edit Mode.  This will add to the 
+  current mesh and align with the current view.
+
+V1.00 01/04/08 by Aaron Keith
+
+- This version is very much a work in progress.
+- This is my first attempt to program in Python.  This version is
+  unpolished and doesn't do much error checking.  Therefore 
+  if the user sets strange variable the model created will be 
+  as equally strange.
+
+- To Do:
+- Better error checking.
+- More Head and Bit types. 
+- Better documentation.
+
+
+"""
+
+# -------------------------------------------------------------------------- 
+# Bolt_Factory.py 
+# -------------------------------------------------------------------------- 
+# ***** BEGIN GPL LICENSE BLOCK ***** 
+# 
+# Copyright (C) 2009: Aaron Keith
+# 
+# This program is free software; you can 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
+# 
+# ***** END GPL LICENCE BLOCK ***** 
+# -------------------------------------------------------------------------- 
+
+
+
+
+import Blender
+from Blender import Draw, BGL,Mesh
+from Blender import *
+from math import *
+from Blender import Mathutils
+from Blender.Mathutils import *
+
+
+#Global_Scale = 0.001    #1 blender unit = X mm
+Global_Scale = 0.1    #1 blender unit = X mm
+#Global_Scale = 1.0    #1 blender unit = X mm
+Global_NutRad = 0.0
+MAX_INPUT_NUMBER = 50
+
+No_Event,On_Preset_Click,On_Apply_Click,On_Create_Click,On_Hex_Click, On_Cap_Click,On_Dome_Click,On_Pan_Click,On_Bit_None_Click,On_Bit_Allen_Click,On_Bit_Philips_Click,On_Exit_Click,On_Model_Bolt_Click,On_Model_Nut_Click,On_Hex_Nut_Click,On_Lock_Nut_Click,On_Test_Click = range(17)  # this is like a ENUM
+
+
+Head_Type={'HEX' : [Draw.Create(1),On_Hex_Click,""],
+           'CAP' : [Draw.Create(0),On_Cap_Click,""],
+           'DOME': [Draw.Create(0),On_Dome_Click,""],
+           'PAN' : [Draw.Create(0),On_Pan_Click,""]}
+
+
+Bit_Type={'NONE' : [Draw.Create(1),On_Bit_None_Click,""],
+           'ALLEN' : [Draw.Create(0),On_Bit_Allen_Click,""],
+           'PHILLIPS': [Draw.Create(0),On_Bit_Philips_Click,""]}
+
+Model_Type={'BOLT' : [Draw.Create(1),On_Model_Bolt_Click,"Bolt Settings"],
+           'NUT' : [Draw.Create(0),On_Model_Nut_Click,"Nut Settings"]}
+
+Nut_Type={'HEX' : [Draw.Create(1),On_Hex_Nut_Click,""],
+           'LOCK' : [Draw.Create(0),On_Lock_Nut_Click,""]}
+
+
+Phillips_Bit_Depth = Draw.Create(3.27)
+Philips_Bit_Dia = Draw.Create(5.20)
+
+Allen_Bit_Depth = Draw.Create(4.0)
+Allen_Bit_Flat_Distance = Draw.Create(6.0)
+
+Hex_Head_Height = Draw.Create(5.3)
+Hex_Head_Flat_Distance = Draw.Create(13.0)
+
+Cap_Head_Dia = Draw.Create(13.5)
+Cap_Head_Height = Draw.Create(8.0)
+
+Dome_Head_Dia = Draw.Create(16.0)
+
+Pan_Head_Dia = Draw.Create(16.0)
+
+Shank_Dia = Draw.Create(8.0)
+Shank_Length = Draw.Create(0.0)
+
+Thread_Length = Draw.Create(16.0)
+Major_Dia = Draw.Create(8.0)
+Minor_Dia = Draw.Create(6.917)
+Pitch = Draw.Create(1.0)
+Crest_Percent = Draw.Create(10)
+Root_Percent = Draw.Create(10)
+
+Hex_Nut_Height = Draw.Create(8.0)
+Hex_Nut_Flat_Distance = Draw.Create(13.0)
+
+Preset_Menu = Draw.Create(5)
+
+
+##########################################################################################
+##########################################################################################
+##                    Miscellaneous Utilities
+##########################################################################################
+##########################################################################################
+
+# Returns a list of verts rotated by the given matrix. Used by SpinDup
+def Rot_Mesh(verts,matrix):
+    return [list(Vector(v) * matrix) for v in verts]
+
+# Returns a list of faces that has there index incremented by offset 
+def Copy_Faces(faces,offset):        
+    ret = []
+    for f in faces:
+        fsub = []
+        for i in range(len(f)):
+            fsub.append(f[i]+ offset)
+        ret.append(fsub)
+    return ret
+
+
+# Much like Blenders built in SpinDup.
+def SpinDup(VERTS,FACES,DEGREE,DIVISIONS,AXIS):
+    verts=[]
+    faces=[]
+    
+    if DIVISIONS == 0:
+       DIVISIONS = 1  
+  
+    step = DEGREE/DIVISIONS # set step so pieces * step = degrees in arc
+    
+    for i in xrange(int(DIVISIONS)):
+        rotmat = Mathutils.RotationMatrix(step*i, 4, AXIS) # 4x4 rotation matrix, 30d about the x axis.
+        Rot = Rot_Mesh(VERTS,rotmat)
+        faces.extend(Copy_Faces(FACES,len(verts)))    
+        verts.extend(Rot)
+    return verts,faces
+
+
+# Returns a list of verts that have been moved up the z axis by DISTANCE
+def Move_Verts_Up_Z(VERTS,DISTANCE):
+    return [[v[0],v[1],v[2]+DISTANCE] for v in VERTS]
+
+
+# Returns a list of verts and faces that has been mirrored in the AXIS 
+def Mirror_Verts_Faces(VERTS,FACES,AXIS,FLIP_POINT =0):
+    ret_vert = []
+    ret_face = []
+    offset = len(VERTS)    
+    if AXIS == 'y':
+        for v in VERTS:
+            Delta = v[0] - FLIP_POINT
+            ret_vert.append([FLIP_POINT-Delta,v[1],v[2]]) 
+    if AXIS == 'x':
+        for v in VERTS:
+            Delta = v[1] - FLIP_POINT
+            ret_vert.append([v[0],FLIP_POINT-Delta,v[2]]) 
+    if AXIS == 'z':
+        for v in VERTS:
+            Delta = v[2] - FLIP_POINT
+            ret_vert.append([v[0],v[1],FLIP_POINT-Delta]) 
+            
+    for f in FACES:
+        fsub = []
+        for i in range(len(f)):
+            fsub.append(f[i]+ offset)
+        fsub.reverse() # flip the order to make norm point out
+        ret_face.append(fsub)
+            
+    return ret_vert,ret_face
+
+
+
+# Returns a list of faces that 
+# make up an array of 4 point polygon. 
+def Build_Face_List_Quads(OFFSET,COLUM,ROW,FLIP = 0):
+    Ret =[]
+    RowStart = 0;
+    for j in range(ROW):
+        for i in range(COLUM):
+            Res1 = RowStart + i;
+            Res2 = RowStart + i + (COLUM +1)
+            Res3 = RowStart + i + (COLUM +1) +1
+            Res4 = RowStart+i+1
+            if FLIP:
+                Ret.append([OFFSET+Res1,OFFSET+Res2,OFFSET+Res3,OFFSET+Res4])
+            else:
+                Ret.append([OFFSET+Res4,OFFSET+Res3,OFFSET+Res2,OFFSET+Res1])
+        RowStart += COLUM+1
+    return Ret
+
+
+# Returns a list of faces that makes up a fill pattern for a 
+# circle
+def Fill_Ring_Face(OFFSET,NUM,FACE_DOWN = 0):
+    Ret =[]
+    Face = [1,2,0]
+    TempFace = [0,0,0]
+    A = 0
+    B = 1
+    C = 2
+    if NUM < 3:
+        return None
+    for i in range(NUM-2):
+        if (i%2):
+            TempFace[0] = Face[C];
+            TempFace[1] = Face[C] + 1;
+            TempFace[2] = Face[B];
+            if FACE_DOWN:
+                Ret.append([OFFSET+Face[2],OFFSET+Face[1],OFFSET+Face[0]])
+            else:
+                Ret.append([OFFSET+Face[0],OFFSET+Face[1],OFFSET+Face[2]])
+        else:
+            TempFace[0] =Face[C];
+            if Face[C] == 0:
+                TempFace[1] = NUM-1; 
+            else:
+                TempFace[1] = Face[C] - 1;
+            TempFace[2] = Face[B];
+            if FACE_DOWN:
+                Ret.append([OFFSET+Face[0],OFFSET+Face[1],OFFSET+Face[2]])
+            else:
+                Ret.append([OFFSET+Face[2],OFFSET+Face[1],OFFSET+Face[0]])
+        
+        Face[0] = TempFace[0]
+        Face[1] = TempFace[1]
+        Face[2] = TempFace[2]
+    return Ret
+    
+
+##########################################################################################
+##########################################################################################
+##                    Converter Functions For Bolt Factory 
+##########################################################################################
+##########################################################################################
+
+
+def Flat_To_Radius(FLAT):
+    h = (float(FLAT)/2)/cos(radians(30))
+    return h
+
+def Get_Phillips_Bit_Height(Bit_Dia):
+    Flat_Width_half = (Bit_Dia*(0.5/1.82))/2.0
+    Bit_Rad = Bit_Dia / 2.0
+    x = Bit_Rad - Flat_Width_half
+    y = tan(radians(60))*x
+    return y 
+
+##########################################################################################
+##########################################################################################
+##                    Error Checking
+##########################################################################################
+##########################################################################################
+
+
+def Error_Check():
+
+    #global Phillips_Bit_Depth 
+    #global Philips_Bit_Dia 
+
+    #global Allen_Bit_Depth 
+    #global Allen_Bit_Flat_Distance 
+
+    #global Hex_Head_Height 
+    #global Hex_Head_Flat_Distance 
+
+    #global Cap_Head_Dia 
+    #global Cap_Head_Height 
+    
+
+    #global Dome_Head_Dia 
+
+    #global Pan_Head_Dia 
+
+    #global Shank_Dia 
+    #global Shank_Length 
+
+    global Thread_Length
+    global Major_Dia 
+    global Minor_Dia 
+    global Pitch 
+    global Hex_Nut_Flat_Distance
+    global Model_Type
+    #global Crest_Percent 
+    #global Root_Percent 
+
+    Error_Result = 0
+    
+    if Minor_Dia.val >= Major_Dia.val:
+        error_txt = "Error%t|Major Dia must be larger than Minor Dia"
+        Blender.Draw.PupMenu(error_txt)
+        print error_txt
+        Error_Result = TRUE  
+
+    elif (Model_Type['BOLT'][0].val) and ((Pitch.val*7.0) > Thread_Length.val):
+        error_txt =  "Error%t|Thread length must be at least 7 times the Pitch"
+        Blender.Draw.PupMenu(error_txt)
+        print error_txt
+        Error_Result = TRUE  
+    
+    elif (Model_Type['NUT'][0].val) and (Hex_Nut_Flat_Distance.val < Major_Dia.val):
+        error_txt =  "Error%t|Nut Flat Distance must be greater than Major Dia"
+        Blender.Draw.PupMenu(error_txt)
+        print error_txt
+        Error_Result = TRUE  
+    
+    elif (Model_Type['NUT'][0].val) and ((Pitch.val * 2.5 )> Hex_Nut_Height.val):
+        error_txt =  "Error%t|Nut Height must be greater than 2.5 * Pitch"
+        Blender.Draw.PupMenu(error_txt)
+        print error_txt
+        Error_Result = TRUE  
+
+    elif (Model_Type['BOLT'][0].val):
+        Check_Head_Height = None
+        Check_Bit_Height = None
+        if (Bit_Type['ALLEN'][0].val):
+            Check_Bit_Height = Allen_Bit_Depth.val
+        if (Bit_Type['PHILLIPS'][0].val):
+            Check_Bit_Height = Phillips_Bit_Depth.val
+        if (Head_Type['HEX'][0].val):
+            Check_Head_Height = Hex_Head_Height.val
+        if (Head_Type['CAP'][0].val):
+            Check_Head_Height = Cap_Head_Height.val
+        
+        if Check_Head_Height != None and Check_Bit_Height != None :
+            if Check_Bit_Height  > Check_Head_Height:
+                error_txt =  "Error%t|Bit Depth must not be greater that Head Height"
+                Blender.Draw.PupMenu(error_txt)
+                print error_txt
+                Error_Result = TRUE
+    
+    
+    return Error_Result 
+
+
+
+##########################################################################################
+##########################################################################################
+##                    Create Allen Bit
+##########################################################################################
+##########################################################################################
+
+
+def Allen_Fill(OFFSET,FLIP= 0):
+    faces = []
+    Lookup = [[19,1,0],
+              [19,2,1],
+              [19,3,2],
+              [19,20,3],
+              [20,4,3],
+              [20,5,4],
+              [20,6,5],
+              [20,7,6],
+              [20,8,7],
+              [20,9,8],
+              
+              [20,21,9],
+              
+              [21,10,9],
+              [21,11,10],
+              [21,12,11],
+              [21,13,12],
+              [21,14,13],
+              [21,15,14],
+              
+              [21,22,15],
+              [22,16,15],
+              [22,17,16],
+              [22,18,17]
+              ]
+    for i in Lookup:
+        if FLIP:
+            faces.append([OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
+        else:
+            faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2]])
+            
+    return faces
+
+def Allen_Bit_Dia(FLAT_DISTANCE):
+    Flat_Radius = (float(FLAT_DISTANCE)/2.0)/cos(radians(30))
+    return (Flat_Radius * 1.05) * 2.0
+    
+def Allen_Bit_Dia_To_Flat(DIA):
+    Flat_Radius = (DIA/2.0)/1.05
+    return (Flat_Radius * cos (radians(30)))* 2.0
+    
+    
+
+def Create_Allen_Bit(FLAT_DISTANCE,HEIGHT):
+    Div = 36
+    verts = []
+    faces = []
+    
+    Flat_Radius = (float(FLAT_DISTANCE)/2.0)/cos(radians(30))
+    OUTTER_RADIUS = Flat_Radius * 1.05
+    Outter_Radius_Height = Flat_Radius * (0.1/5.77)
+    FaceStart_Outside = len(verts)
+    Deg_Step = 360.0 /float(Div)
+    
+    for i in range((Div/2)+1):    # only do half and mirror later
+        x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+        y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+        verts.append([x,y,0])
+    
+    FaceStart_Inside = len(verts)
+        
+    Deg_Step = 360.0 /float(6) 
+    for i in range((6/2)+1): 
+        x = sin(radians(i*Deg_Step))* Flat_Radius
+        y = cos(radians(i*Deg_Step))* Flat_Radius
+        verts.append([x,y,0-Outter_Radius_Height])     
+     
+    faces.extend(Allen_Fill(FaceStart_Outside,0))
+    
+    
+    FaceStart_Bottom = len(verts)
+    
+    Deg_Step = 360.0 /float(6) 
+    for i in range((6/2)+1): 
+        x = sin(radians(i*Deg_Step))* Flat_Radius
+        y = cos(radians(i*Deg_Step))* Flat_Radius
+        verts.append([x,y,0-HEIGHT])     
+        
+    faces.extend(Build_Face_List_Quads(FaceStart_Inside,3,1,TRUE))
+    faces.extend(Fill_Ring_Face(FaceStart_Bottom,4))
+    
+    
+    M_Verts,M_Faces = Mirror_Verts_Faces(verts,faces,'y')
+    verts.extend(M_Verts)
+    faces.extend(M_Faces)
+    
+    return verts,faces,OUTTER_RADIUS * 2.0
+
+
+##########################################################################################
+##########################################################################################
+##                    Create Phillips Bit
+##########################################################################################
+##########################################################################################
+
+
+def Phillips_Fill(OFFSET,FLIP= 0):
+    faces = []
+    Lookup = [[0,1,10],
+              [1,11,10],
+              [1,2,11],
+              [2,12,11],
+              
+              [2,3,12],
+              [3,4,12],
+              [4,5,12],
+              [5,6,12],
+              [6,7,12],
+              
+              [7,13,12],
+              [7,8,13],
+              [8,14,13],
+              [8,9,14],
+              
+              
+              [10,11,16,15],
+              [11,12,16],
+              [12,13,16],
+              [13,14,17,16],
+              [15,16,17,18]
+              
+              
+              ]
+    for i in Lookup:
+        if FLIP:
+            if len(i) == 3:
+                faces.append([OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
+            else:    
+                faces.append([OFFSET+i[3],OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]])
+        else:
+            if len(i) == 3:
+                faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2]])
+            else:
+                faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2],OFFSET+i[3]])
+    return faces
+
+
+
+def Create_Phillips_Bit(FLAT_DIA,FLAT_WIDTH,HEIGHT):
+    Div = 36
+    verts = []
+    faces = []
+    
+    FLAT_RADIUS = FLAT_DIA * 0.5
+    OUTTER_RADIUS = FLAT_RADIUS * 1.05
+    
+    Flat_Half = float(FLAT_WIDTH)/2.0
+        
+    FaceStart_Outside = len(verts)
+    Deg_Step = 360.0 /float(Div)
+    for i in range((Div/4)+1):    # only do half and mirror later
+        x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+        y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+        verts.append([x,y,0])
+    
+        
+    FaceStart_Inside = len(verts)
+    verts.append([0,FLAT_RADIUS,0]) #10
+    verts.append([Flat_Half,FLAT_RADIUS,0]) #11
+    verts.append([Flat_Half,Flat_Half,0])     #12
+    verts.append([FLAT_RADIUS,Flat_Half,0])    #13
+    verts.append([FLAT_RADIUS,0,0])            #14
+
+    verts.append([0,Flat_Half,0-HEIGHT])        #15
+    verts.append([Flat_Half,Flat_Half,0-HEIGHT])    #16
+    verts.append([Flat_Half,0,0-HEIGHT])            #17
+    
+    verts.append([0,0,0-HEIGHT])            #18
+    
+    faces.extend(Phillips_Fill(FaceStart_Outside,TRUE))
+
+    Spin_Verts,Spin_Face = SpinDup(verts,faces,360,4,'z')
+   
+    return Spin_Verts,Spin_Face,OUTTER_RADIUS * 2
+    
+
+##########################################################################################
+##########################################################################################
+##                    Create Head Types
+##########################################################################################
+##########################################################################################
+
+def Max_Pan_Bit_Dia(HEAD_DIA):
+    HEAD_RADIUS = HEAD_DIA * 0.5
+    XRad = HEAD_RADIUS * 1.976
+    return (sin(radians(10))*XRad) * 2.0
+
+
+def Create_Pan_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2,FACE_OFFSET):
+
+    DIV = 36
+    HOLE_RADIUS = HOLE_DIA * 0.5
+    HEAD_RADIUS = HEAD_DIA * 0.5
+    SHANK_RADIUS = SHANK_DIA * 0.5
+
+    verts = []
+    faces = []
+    Row = 0
+    BEVEL = HEIGHT * 0.01
+    #Dome_Rad =  HEAD_RADIUS * (1.0/1.75)
+    
+    Dome_Rad = HEAD_RADIUS * 1.12
+    RAD_Offset = HEAD_RADIUS * 0.96
+    OtherRad = HEAD_RADIUS * 0.16
+    OtherRad_X_Offset = HEAD_RADIUS * 0.84
+    OtherRad_Z_Offset = HEAD_RADIUS * 0.504
+    XRad = HEAD_RADIUS * 1.976
+    ZRad = HEAD_RADIUS * 1.768
+    EndRad = HEAD_RADIUS * 0.284
+    EndZOffset = HEAD_RADIUS * 0.432
+    HEIGHT = HEAD_RADIUS * 0.59
+    
+#    Dome_Rad =  5.6
+#    RAD_Offset = 4.9
+#    OtherRad = 0.8
+#    OtherRad_X_Offset = 4.2
+#    OtherRad_Z_Offset = 2.52
+#    XRad = 9.88
+#    ZRad = 8.84
+#    EndRad = 1.42
+#    EndZOffset = 2.16
+#    HEIGHT = 2.95
+    
+    FaceStart = FACE_OFFSET
+
+    z = cos(radians(10))*ZRad
+    verts.append([HOLE_RADIUS,0.0,(0.0-ZRad)+z])
+    Start_Height = 0 - ((0.0-ZRad)+z)
+    Row += 1
+
+    #for i in range(0,30,10):  was 0 to 30 more work needed to make this look good.
+    for i in range(10,30,10):
+        x = sin(radians(i))*XRad
+        z = cos(radians(i))*ZRad
+        verts.append([x,0.0,(0.0-ZRad)+z])
+        Row += 1
+
+    for i in range(20,140,10):
+        x = sin(radians(i))*EndRad
+        z = cos(radians(i))*EndRad
+        if ((0.0 - EndZOffset)+z) < (0.0-HEIGHT):
+            verts.append([(HEAD_RADIUS -EndRad)+x,0.0,0.0 - HEIGHT])
+        else:
+            verts.append([(HEAD_RADIUS -EndRad)+x,0.0,(0.0 - EndZOffset)+z])
+        Row += 1
+        
+        
+    verts.append([SHANK_RADIUS,0.0,(0.0-HEIGHT)])
+    Row += 1
+    
+    verts.append([SHANK_RADIUS,0.0,(0.0-HEIGHT)-Start_Height])
+    Row += 1
+
+
+    sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
+    sVerts.extend(verts)        #add the start verts to the Spin verts to complete the loop
+    
+    faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
+
+    Global_Head_Height = HEIGHT ;
+
+    
+    return Move_Verts_Up_Z(sVerts,Start_Height),faces,HEIGHT
+
+
+
+def Create_Dome_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2,FACE_OFFSET):
+    DIV = 36
+    HOLE_RADIUS = HOLE_DIA * 0.5
+    HEAD_RADIUS = HEAD_DIA * 0.5
+    SHANK_RADIUS = SHANK_DIA * 0.5
+    
+    verts = []
+    faces = []
+    Row = 0
+    BEVEL = HEIGHT * 0.01
+    #Dome_Rad =  HEAD_RADIUS * (1.0/1.75)
+    
+    Dome_Rad =  HEAD_RADIUS * 1.12
+    #Head_Height = HEAD_RADIUS * 0.78
+    RAD_Offset = HEAD_RADIUS * 0.98
+    Dome_Height = HEAD_RADIUS * 0.64
+    OtherRad = HEAD_RADIUS * 0.16
+    OtherRad_X_Offset = HEAD_RADIUS * 0.84
+    OtherRad_Z_Offset = HEAD_RADIUS * 0.504
+    
+    
+#    Dome_Rad =  5.6
+#    RAD_Offset = 4.9
+#    Dome_Height = 3.2
+#    OtherRad = 0.8
+#    OtherRad_X_Offset = 4.2
+#    OtherRad_Z_Offset = 2.52
+#    
+    
+    FaceStart = FACE_OFFSET
+    
+    verts.append([HOLE_RADIUS,0.0,0.0])
+    Row += 1
+
+
+    for i in range(0,60,10):
+        x = sin(radians(i))*Dome_Rad
+        z = cos(radians(i))*Dome_Rad
+        if ((0.0-RAD_Offset)+z) <= 0:
+            verts.append([x,0.0,(0.0-RAD_Offset)+z])
+            Row += 1
+
+
+    for i in range(60,160,10):
+        x = sin(radians(i))*OtherRad
+        z = cos(radians(i))*OtherRad
+        z = (0.0-OtherRad_Z_Offset)+z
+        if z < (0.0-Dome_Height):
+            z = (0.0-Dome_Height)
+        verts.append([OtherRad_X_Offset+x,0.0,z])
+        Row += 1
+        
+    verts.append([SHANK_RADIUS,0.0,(0.0-Dome_Height)])
+    Row += 1
+
+
+    sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
+    sVerts.extend(verts)        #add the start verts to the Spin verts to complete the loop
+    
+    faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
+
+    return sVerts,faces,Dome_Height
+
+
+
+def Create_Cap_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2):
+    DIV = 36
+    
+    HOLE_RADIUS = HOLE_DIA * 0.5
+    HEAD_RADIUS = HEAD_DIA * 0.5
+    SHANK_RADIUS = SHANK_DIA * 0.5
+    
+    verts = []
+    faces = []
+    Row = 0
+    BEVEL = HEIGHT * 0.01
+    
+    
+    FaceStart = len(verts)
+
+    verts.append([HOLE_RADIUS,0.0,0.0])
+    Row += 1
+
+    #rad
+    
+    for i in range(0,100,10):
+        x = sin(radians(i))*RAD1
+        z = cos(radians(i))*RAD1
+        verts.append([(HEAD_RADIUS-RAD1)+x,0.0,(0.0-RAD1)+z])
+        Row += 1
+    
+    
+    verts.append([HEAD_RADIUS,0.0,0.0-HEIGHT+BEVEL])
+    Row += 1
+
+    verts.append([HEAD_RADIUS-BEVEL,0.0,0.0-HEIGHT])
+    Row += 1
+
+    #rad2
+   
+    for i in range(0,100,10):
+        x = sin(radians(i))*RAD2
+        z = cos(radians(i))*RAD2
+        verts.append([(SHANK_RADIUS+RAD2)-x,0.0,(0.0-HEIGHT-RAD2)+z])
+        Row += 1
+    
+
+    sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
+    sVerts.extend(verts)        #add the start verts to the Spin verts to complete the loop
+    
+
+    faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
+    
+    return sVerts,faces,HEIGHT+RAD2
+
+
+
+def Create_Hex_Head(FLAT,HOLE_DIA,SHANK_DIA,HEIGHT):
+    
+    verts = []
+    faces = []
+    HOLE_RADIUS = HOLE_DIA * 0.5
+    Half_Flat = FLAT/2
+    TopBevelRadius = Half_Flat - (Half_Flat* (0.05/8))
+    Undercut_Height = (Half_Flat* (0.05/8))
+    Shank_Bevel = (Half_Flat* (0.05/8)) 
+    Flat_Height = HEIGHT - Undercut_Height - Shank_Bevel
+    #Undercut_Height = 5
+    SHANK_RADIUS = SHANK_DIA/2
+    Row = 0;
+
+    verts.append([0.0,0.0,0.0])
+    
+    
+    FaceStart = len(verts)
+    #inner hole
+    
+    x = sin(radians(0))*HOLE_RADIUS
+    y = cos(radians(0))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/6))*HOLE_RADIUS
+    y = cos(radians(60/6))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/3))*HOLE_RADIUS
+    y = cos(radians(60/3))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/2))*HOLE_RADIUS
+    y = cos(radians(60/2))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    Row += 1
+    
+    #bevel
+    
+    x = sin(radians(0))*TopBevelRadius
+    y = cos(radians(0))*TopBevelRadius
+    vec1 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/6))*TopBevelRadius
+    y = cos(radians(60/6))*TopBevelRadius
+    vec2 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/3))*TopBevelRadius
+    y = cos(radians(60/3))*TopBevelRadius
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/2))*TopBevelRadius
+    y = cos(radians(60/2))*TopBevelRadius
+    vec4 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    Row += 1
+    
+    #Flats
+    
+    x = tan(radians(0))*Half_Flat
+    dvec = vec1 - Mathutils.Vector([x,Half_Flat,0.0])
+    verts.append([x,Half_Flat,-dvec.length])
+    
+    
+    x = tan(radians(60/6))*Half_Flat
+    dvec = vec2 - Mathutils.Vector([x,Half_Flat,0.0])
+    verts.append([x,Half_Flat,-dvec.length])
+    
+
+    x = tan(radians(60/3))*Half_Flat
+    dvec = vec3 - Mathutils.Vector([x,Half_Flat,0.0])
+    Lowest_Point = -dvec.length
+    verts.append([x,Half_Flat,-dvec.length])
+    
+
+    x = tan(radians(60/2))*Half_Flat
+    dvec = vec4 - Mathutils.Vector([x,Half_Flat,0.0])
+    Lowest_Point = -dvec.length
+    verts.append([x,Half_Flat,-dvec.length])
+    Row += 1
+    
+    #down Bits Tri
+    x = tan(radians(0))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+    
+    x = tan(radians(60/6))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+
+    x = tan(radians(60/3))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+    
+    x = tan(radians(60/2))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+    Row += 1
+
+    #down Bits
+    
+    x = tan(radians(0))*Half_Flat
+    verts.append([x,Half_Flat,-Flat_Height])
+    
+    x = tan(radians(60/6))*Half_Flat
+    verts.append([x,Half_Flat,-Flat_Height])
+
+    x = tan(radians(60/3))*Half_Flat
+    verts.append([x,Half_Flat,-Flat_Height])
+    
+    x = tan(radians(60/2))*Half_Flat
+    verts.append([x,Half_Flat,-Flat_Height])
+    Row += 1
+    
+    
+    #under cut 
+       
+    x = sin(radians(0))*Half_Flat
+    y = cos(radians(0))*Half_Flat
+    vec1 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height])
+    
+    x = sin(radians(60/6))*Half_Flat
+    y = cos(radians(60/6))*Half_Flat
+    vec2 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height])
+    
+    x = sin(radians(60/3))*Half_Flat
+    y = cos(radians(60/3))*Half_Flat
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height])
+    
+    x = sin(radians(60/2))*Half_Flat
+    y = cos(radians(60/2))*Half_Flat
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height])
+    Row += 1
+    
+    #under cut down bit
+    x = sin(radians(0))*Half_Flat
+    y = cos(radians(0))*Half_Flat
+    vec1 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    
+    x = sin(radians(60/6))*Half_Flat
+    y = cos(radians(60/6))*Half_Flat
+    vec2 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    
+    x = sin(radians(60/3))*Half_Flat
+    y = cos(radians(60/3))*Half_Flat
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    
+    x = sin(radians(60/2))*Half_Flat
+    y = cos(radians(60/2))*Half_Flat
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    Row += 1
+    
+    #under cut to Shank BEVEAL
+    x = sin(radians(0))*(SHANK_RADIUS+Shank_Bevel)
+    y = cos(radians(0))*(SHANK_RADIUS+Shank_Bevel)
+    vec1 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    
+    x = sin(radians(60/6))*(SHANK_RADIUS+Shank_Bevel)
+    y = cos(radians(60/6))*(SHANK_RADIUS+Shank_Bevel)
+    vec2 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    
+    x = sin(radians(60/3))*(SHANK_RADIUS+Shank_Bevel)
+    y = cos(radians(60/3))*(SHANK_RADIUS+Shank_Bevel)
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    
+    x = sin(radians(60/2))*(SHANK_RADIUS+Shank_Bevel)
+    y = cos(radians(60/2))*(SHANK_RADIUS+Shank_Bevel)
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height])
+    Row += 1
+    
+    #under cut to Shank BEVEAL
+    x = sin(radians(0))*SHANK_RADIUS
+    y = cos(radians(0))*SHANK_RADIUS
+    vec1 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
+    
+    x = sin(radians(60/6))*SHANK_RADIUS
+    y = cos(radians(60/6))*SHANK_RADIUS
+    vec2 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
+    
+    x = sin(radians(60/3))*SHANK_RADIUS
+    y = cos(radians(60/3))*SHANK_RADIUS
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
+    
+    x = sin(radians(60/2))*SHANK_RADIUS
+    y = cos(radians(60/2))*SHANK_RADIUS
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel])
+    Row += 1
+    
+    
+    #Global_Head_Height = 0 - (-HEIGHT-0.1)
+    faces.extend(Build_Face_List_Quads(FaceStart,3,Row - 1))
+       
+    
+    Mirror_Verts,Mirror_Faces = Mirror_Verts_Faces(verts,faces,'y')
+    verts.extend(Mirror_Verts)
+    faces.extend(Mirror_Faces)
+    
+    Spin_Verts,Spin_Faces = SpinDup(verts,faces,360,6,'z')
+    
+    return Spin_Verts,Spin_Faces,0 - (-HEIGHT)
+   
+    
+##########################################################################################
+##########################################################################################
+##                    Create Bolt
+##########################################################################################
+##########################################################################################
+
+
+
+def MakeBolt():
+    global Phillips_Bit_Depth 
+    global Philips_Bit_Dia 
+
+    global Allen_Bit_Depth 
+    global Allen_Bit_Flat_Distance 
+
+    global Hex_Head_Height 
+    global Hex_Head_Flat_Distance 
+
+    global Cap_Head_Dia 
+    global Cap_Head_Height 
+    
+
+    global Dome_Head_Dia 
+
+    global Pan_Head_Dia 
+
+    global Shank_Dia 
+    global Shank_Length 
+
+    global Thread_Length
+    global Major_Dia 
+    global Minor_Dia 
+    global Pitch 
+    global Crest_Percent 
+    global Root_Percent 
+    
+    verts = []
+    faces = []
+    Bit_Verts = []
+    Bit_Faces = []
+    Bit_Dia = 0.001
+    Head_Verts = []
+    Head_Faces= []
+    Head_Height = 0.0
+    ReSized_Allen_Bit_Flat_Distance = Allen_Bit_Flat_Distance.val  # set default  
+   
+    
+    Head_Height = Hex_Head_Height.val # will be changed by the Head Functions
+    
+    if Bit_Type['ALLEN'][0].val and Head_Type['PAN'][0].val:
+        #need to size Allen bit if it is too big.
+        if  Allen_Bit_Dia(Allen_Bit_Flat_Distance.val) > Max_Pan_Bit_Dia(Pan_Head_Dia.val):
+            ReSized_Allen_Bit_Flat_Distance = Allen_Bit_Dia_To_Flat(Max_Pan_Bit_Dia(Pan_Head_Dia.val)) * 1.05
+            print "Resized Allen Bit Flat Distance to ",ReSized_Allen_Bit_Flat_Distance 
+    #bit Mesh
+    if Bit_Type['ALLEN'][0].val:
+        Bit_Verts,Bit_Faces,Bit_Dia = Create_Allen_Bit(ReSized_Allen_Bit_Flat_Distance,Allen_Bit_Depth.val)
+    
+    if Bit_Type['PHILLIPS'][0].val:
+        Bit_Verts,Bit_Faces,Bit_Dia = Create_Phillips_Bit(Philips_Bit_Dia.val,Philips_Bit_Dia.val*(0.5/1.82),Phillips_Bit_Depth.val)
+   
+        
+    #Head Mesh
+    if Head_Type['HEX'][0].val:  
+        Head_Verts,Head_Faces,Head_Height = Create_Hex_Head(Hex_Head_Flat_Distance.val,Bit_Dia,Shank_Dia.val,Hex_Head_Height.val)
+
+    elif Head_Type['CAP'][0].val:  
+        Head_Verts,Head_Faces,Head_Height = Create_Cap_Head(Bit_Dia,Cap_Head_Dia.val,Shank_Dia.val,Cap_Head_Height.val,Cap_Head_Dia.val*(1.0/19.0),Cap_Head_Dia.val*(1.0/19.0))
+        
+    elif Head_Type['DOME'][0].val:  
+        Head_Verts,Head_Faces,Head_Height = Create_Dome_Head(Bit_Dia,Dome_Head_Dia.val,Shank_Dia.val,Hex_Head_Height.val,1,1,0)
+    
+    elif Head_Type['PAN'][0].val:  
+        Head_Verts,Head_Faces,Head_Height = Create_Pan_Head(Bit_Dia,Pan_Head_Dia.val,Shank_Dia.val,Hex_Head_Height.val,1,1,0)
+
+
+    Face_Start = len(verts)
+    verts.extend(Move_Verts_Up_Z(Bit_Verts,Head_Height))
+    faces.extend(Copy_Faces(Bit_Faces,Face_Start))
+
+    Face_Start = len(verts)
+    verts.extend(Move_Verts_Up_Z(Head_Verts,Head_Height))
+    faces.extend(Copy_Faces(Head_Faces,Face_Start))
+
+    Face_Start = len(verts)
+    Thread_Verts,Thread_Faces,Thread_Height = Create_External_Thread(Shank_Dia.val,Shank_Length.val,Minor_Dia.val,Major_Dia.val,Pitch.val,Thread_Length.val,Crest_Percent.val,Root_Percent.val)
+
+    verts.extend(Move_Verts_Up_Z(Thread_Verts,00))
+    faces.extend(Copy_Faces(Thread_Faces,Face_Start))
+    
+    return Move_Verts_Up_Z(verts,Thread_Height),faces
+
+
+
+
+
+
+
+##########################################################################################
+##########################################################################################
+##                    Create Internal Thread
+##########################################################################################
+##########################################################################################
+
+
+def Create_Internal_Thread_Start_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
+    
+    
+    Ret_Row = 0;
+    
+    Height_Offset = Height_Offset + PITCH  #Move the offset up so that the verts start at 
+                                           #at the correct place  (Height_Start)
+    
+    Half_Pitch = float(PITCH)/2
+    Height_Start = Height_Offset - PITCH 
+    Height_Step = float(PITCH)/float(DIV)
+    Deg_Step = 360.0 /float(DIV)
+    
+    Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
+    Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
+    Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
+    
+
+    Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
+    for j in range(1):
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z])
+        Height_Offset -= Crest_Height
+        Ret_Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z ])
+        Height_Offset -= Crest_to_Root_Height
+        Ret_Row += 1
+    
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            if j == 0:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+            verts.append([x,y,z ])
+        Height_Offset -= Root_Height
+        Ret_Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+
+            if j == 0:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+            verts.append([x,y,z ])
+        Height_Offset -= Root_to_Crest_Height
+        Ret_Row += 1
+   
+    return Ret_Row,Height_Offset
+
+
+def Create_Internal_Thread_End_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
+    
+    
+    Ret_Row = 0;
+    
+    Half_Pitch = float(PITCH)/2
+    #Height_End = Height_Offset - PITCH - PITCH - PITCH- PITCH - PITCH- PITCH
+    Height_End = Height_Offset - PITCH 
+    #Height_End = -2.1
+    Height_Step = float(PITCH)/float(DIV)
+    Deg_Step = 360.0 /float(DIV)
+    
+    Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
+    Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
+    Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
+   
+    
+
+    Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
+    
+    Num = 0
+    
+    for j in range(2):
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z < Height_End:
+                z = Height_End
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z])
+        Height_Offset -= Crest_Height
+        Ret_Row += 1
+    
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z < Height_End:
+                z = Height_End
+            
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z ])
+        Height_Offset -= Crest_to_Root_Height
+        Ret_Row += 1
+    
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z < Height_End:
+                z = Height_End
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            if j == Num:
+                x = sin(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
+                y = cos(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
+            if j > Num:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS)
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS )
+                
+            verts.append([x,y,z ])
+        Height_Offset -= Root_Height
+        Ret_Row += 1
+    
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z < Height_End:
+                z = Height_End
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+
+            if j == Num:
+                x = sin(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
+                y = cos(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank))
+            if j > Num:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS )
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS )
+                
+            verts.append([x,y,z ])
+        Height_Offset -= Root_to_Crest_Height
+        Ret_Row += 1
+
+       
+    return Ret_Row,Height_End  # send back Height End as this is the lowest point
+
+
+def Create_Internal_Thread(INNER_DIA,OUTTER_DIA,PITCH,HEIGHT,CREST_PERCENT,ROOT_PERCENT,INTERNAL = 1):
+    verts = []
+    faces = []
+    
+    DIV = 36
+    
+    INNER_RADIUS = INNER_DIA/2
+    OUTTER_RADIUS = OUTTER_DIA/2
+    
+    Half_Pitch = float(PITCH)/2
+    Deg_Step = 360.0 /float(DIV)
+    Height_Step = float(PITCH)/float(DIV)
+            
+    Num = int(round((HEIGHT- PITCH)/PITCH))  # less one pitch for the start and end that is 1/2 pitch high    
+    
+    Col = 0
+    Row = 0
+    
+    
+    Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
+    Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
+    Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
+    
+    Height_Offset = 0
+    FaceStart = len(verts)
+    
+    Row_Inc,Height_Offset = Create_Internal_Thread_Start_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset)
+    Row += Row_Inc
+    
+    for j in range(Num):
+        
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,Height_Offset - (Height_Step*i) ])
+        Height_Offset -= Crest_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,Height_Offset - (Height_Step*i) ])
+        Height_Offset -= Crest_to_Root_Height
+        Row += 1
+    
+        
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            verts.append([x,y,Height_Offset - (Height_Step*i) ])
+        Height_Offset -= Root_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            verts.append([x,y,Height_Offset - (Height_Step*i) ])
+        Height_Offset -= Root_to_Crest_Height
+        Row += 1
+    
+
+    Row_Inc,Height_Offset = Create_Internal_Thread_End_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset)
+    Row += Row_Inc
+    
+    faces.extend(Build_Face_List_Quads(FaceStart,DIV,Row -1,INTERNAL))
+    
+    return verts,faces,0 - Height_Offset
+
+
+
+##########################################################################################
+##########################################################################################
+##                    Create External Thread
+##########################################################################################
+##########################################################################################
+
+
+
+def Thread_Start3(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset):
+    
+    
+    Ret_Row = 0;
+    
+    Half_Pitch = float(PITCH)/2
+    Height_Start = Height_Offset - PITCH
+    Height_Step = float(PITCH)/float(DIV)
+    Deg_Step = 360.0 /float(DIV)
+    
+    Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
+    Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
+    Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
+   
+#theard start
+
+    Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
+    for j in range(4):
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z])
+        Height_Offset -= Crest_Height
+        Ret_Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z ])
+        Height_Offset -= Crest_to_Root_Height
+        Ret_Row += 1
+    
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            if j == 0:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+            verts.append([x,y,z ])
+        Height_Offset -= Root_Height
+        Ret_Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+
+            if j == 0:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+            verts.append([x,y,z ])
+        Height_Offset -= Root_to_Crest_Height
+        Ret_Row += 1
+   
+    return Ret_Row,Height_Offset
+
+
+def Create_Shank_Verts(START_DIA,OUTTER_DIA,LENGTH,Z_LOCATION = 0):
+
+    verts = []
+    DIV = 36
+    
+    START_RADIUS = START_DIA/2
+    OUTTER_RADIUS = OUTTER_DIA/2
+    
+    Opp = abs(START_RADIUS - OUTTER_RADIUS)
+    Taper_Lentgh = Opp/tan(radians(31));
+    
+    if Taper_Lentgh > LENGTH:
+        Taper_Lentgh = 0
+    
+    Stright_Length = LENGTH - Taper_Lentgh
+    
+    Deg_Step = 360.0 /float(DIV)
+    
+    Row = 0
+    
+    Lowest_Z_Vert = 0;    
+    
+    Height_Offset = Z_LOCATION
+
+
+        #ring
+    for i in range(DIV+1): 
+        x = sin(radians(i*Deg_Step))*START_RADIUS
+        y = cos(radians(i*Deg_Step))*START_RADIUS
+        z =  Height_Offset - 0
+        verts.append([x,y,z])
+        Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Height_Offset -= Stright_Length
+    Row += 1
+
+    for i in range(DIV+1): 
+        x = sin(radians(i*Deg_Step))*START_RADIUS
+        y = cos(radians(i*Deg_Step))*START_RADIUS
+        z =  Height_Offset - 0
+        verts.append([x,y,z])
+        Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Height_Offset -= Taper_Lentgh
+    Row += 1
+
+
+    return verts,Row,Height_Offset
+
+
+def Create_Thread_Start_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
+    
+    verts = []
+    DIV = 36
+    
+    INNER_RADIUS = INNER_DIA/2
+    OUTTER_RADIUS = OUTTER_DIA/2
+    
+    Half_Pitch = float(PITCH)/2
+    Deg_Step = 360.0 /float(DIV)
+    Height_Step = float(PITCH)/float(DIV)
+
+    Row = 0
+    
+    Lowest_Z_Vert = 0;    
+    
+    Height_Offset = Z_LOCATION
+        
+    Height_Start = Height_Offset 
+    
+    Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
+    Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
+    Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
+
+    Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV)
+    
+    Height_Offset = Z_LOCATION + PITCH 
+    Cut_off = Z_LOCATION
+  
+    
+    for j in range(1):
+        
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            z = Height_Offset - (Height_Step*i)
+            if z > Cut_off : z = Cut_off
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            z = Height_Offset - (Height_Step*i)
+            if z > Cut_off : z = Cut_off
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_to_Root_Height
+        Row += 1
+        
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            z = Height_Offset - (Height_Step*i)
+            if z > Cut_off : z = Cut_off 
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            z = Height_Offset - (Height_Step*i)
+            if z > Cut_off : z = Cut_off 
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_to_Crest_Height
+        Row += 1
+    
+    
+    for j in range(2):
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            verts.append([x,y,z ])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_to_Root_Height
+        Row += 1
+    
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            if j == 0:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+            verts.append([x,y,z ])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i) 
+            if z > Height_Start:
+                z = Height_Start
+            
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+
+            if j == 0:
+                x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+                y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank))
+            verts.append([x,y,z ])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_to_Crest_Height
+        Row += 1
+        
+   
+    return verts,Row,Height_Offset
+
+
+
+def Create_Thread_Verts(INNER_DIA,OUTTER_DIA,PITCH,HEIGHT,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
+    verts = []
+        
+    DIV = 36
+    
+    INNER_RADIUS = INNER_DIA/2
+    OUTTER_RADIUS = OUTTER_DIA/2
+    
+    Half_Pitch = float(PITCH)/2
+    Deg_Step = 360.0 /float(DIV)
+    Height_Step = float(PITCH)/float(DIV)
+
+    NUM_OF_START_THREADS = 4.0
+    NUM_OF_END_THREADS = 3.0
+    Num = int((HEIGHT- ((NUM_OF_START_THREADS*PITCH) + (NUM_OF_END_THREADS*PITCH) ))/PITCH)
+    Row = 0
+    
+
+    Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
+    Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
+    Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
+
+
+    Height_Offset = Z_LOCATION
+    
+    Lowest_Z_Vert = 0;
+    FaceStart = len(verts)
+    
+    
+    for j in range(Num):
+        
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            z = Height_Offset - (Height_Step*i) 
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*OUTTER_RADIUS
+            y = cos(radians(i*Deg_Step))*OUTTER_RADIUS
+            z = Height_Offset - (Height_Step*i)
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_to_Root_Height
+        Row += 1
+    
+        
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            z = Height_Offset - (Height_Step*i) 
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            x = sin(radians(i*Deg_Step))*INNER_RADIUS
+            y = cos(radians(i*Deg_Step))*INNER_RADIUS
+            z = Height_Offset - (Height_Step*i) 
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_to_Crest_Height
+        Row += 1
+    
+    return verts,Row,Height_Offset
+
+
+
+def Create_Thread_End_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0):
+    verts = []
+        
+    DIV = 36
+
+    INNER_RADIUS = INNER_DIA/2
+    OUTTER_RADIUS = OUTTER_DIA/2
+    
+    Half_Pitch = float(PITCH)/2
+    Deg_Step = 360.0 /float(DIV)
+    Height_Step = float(PITCH)/float(DIV)
+
+    Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100)
+    Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100)
+    Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0
+       
+    Col = 0
+    Row = 0
+    
+    Height_Offset = Z_LOCATION 
+    
+    Tapper_Height_Start = Height_Offset - PITCH - PITCH 
+    
+    Max_Height = Tapper_Height_Start - PITCH 
+    
+    Lowest_Z_Vert = 0;
+    
+    FaceStart = len(verts)
+    for j in range(4):
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i)
+            z = max(z,Max_Height)
+            Tapper_Radius = OUTTER_RADIUS
+            if z < Tapper_Height_Start:
+                Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
+
+            x = sin(radians(i*Deg_Step))*(Tapper_Radius)
+            y = cos(radians(i*Deg_Step))*(Tapper_Radius)
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i)
+            z = max(z,Max_Height)
+            Tapper_Radius = OUTTER_RADIUS
+            if z < Tapper_Height_Start:
+                Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
+
+            x = sin(radians(i*Deg_Step))*(Tapper_Radius)
+            y = cos(radians(i*Deg_Step))*(Tapper_Radius)
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Crest_to_Root_Height
+        Row += 1
+    
+        
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i)
+            z = max(z,Max_Height)
+            Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
+            if Tapper_Radius > INNER_RADIUS:
+               Tapper_Radius = INNER_RADIUS
+            
+            x = sin(radians(i*Deg_Step))*(Tapper_Radius)
+            y = cos(radians(i*Deg_Step))*(Tapper_Radius)
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_Height
+        Row += 1
+    
+        for i in range(DIV+1):
+            z = Height_Offset - (Height_Step*i)
+            z = max(z,Max_Height)
+            Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z)
+            if Tapper_Radius > INNER_RADIUS:
+               Tapper_Radius = INNER_RADIUS
+            
+            x = sin(radians(i*Deg_Step))*(Tapper_Radius)
+            y = cos(radians(i*Deg_Step))*(Tapper_Radius)
+            verts.append([x,y,z])
+            Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Height_Offset -= Root_to_Crest_Height
+        Row += 1
+    
+    return verts,Row,Height_Offset,Lowest_Z_Vert
+
+
+
+
+def Create_External_Thread(SHANK_DIA,SHANK_LENGTH,INNER_DIA,OUTTER_DIA,PITCH,LENGTH,CREST_PERCENT,ROOT_PERCENT):
+    
+    verts = []
+    faces = []
+
+    DIV = 36
+    
+    Total_Row = 0
+    Thread_Len = 0;
+    
+    Face_Start = len(verts)
+    Offset = 0.0;
+    
+                                             
+    Shank_Verts,Shank_Row,Offset = Create_Shank_Verts(SHANK_DIA,OUTTER_DIA,SHANK_LENGTH,Offset)
+    Total_Row += Shank_Row
+
+    Thread_Start_Verts,Thread_Start_Row,Offset = Create_Thread_Start_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Offset)
+    Total_Row += Thread_Start_Row
+    
+    
+    Thread_Verts,Thread_Row,Offset = Create_Thread_Verts(INNER_DIA,OUTTER_DIA,PITCH,LENGTH,CREST_PERCENT,ROOT_PERCENT,Offset)
+    Total_Row += Thread_Row
+    
+    
+    Thread_End_Verts,Thread_End_Row,Offset,Lowest_Z_Vert = Create_Thread_End_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Offset )
+    Total_Row += Thread_End_Row       
+    
+    
+    verts.extend(Shank_Verts)
+    verts.extend(Thread_Start_Verts)
+    verts.extend(Thread_Verts)
+    verts.extend(Thread_End_Verts)
+    
+    faces.extend(Build_Face_List_Quads(Face_Start,DIV,Total_Row -1,0))
+    faces.extend(Fill_Ring_Face(len(verts)-DIV,DIV,1))
+    
+    return verts,faces,0.0 - Lowest_Z_Vert
+
+##########################################################################################
+##########################################################################################
+##                    Create Nut
+##########################################################################################
+##########################################################################################
+
+
+def add_Hex_Nut(FLAT,HOLE_DIA,HEIGHT):
+    global Global_Head_Height
+    global Global_NutRad
+    
+    verts = []
+    faces = []
+    HOLE_RADIUS = HOLE_DIA * 0.5
+    Half_Flat = FLAT/2
+    Half_Height = HEIGHT/2
+    TopBevelRadius = Half_Flat - 0.05
+    
+    Global_NutRad =  TopBevelRadius
+    
+    Row = 0;
+    Lowest_Z_Vert = 0.0;
+
+    verts.append([0.0,0.0,0.0])
+    
+    
+    FaceStart = len(verts)
+    #inner hole
+    
+    x = sin(radians(0))*HOLE_RADIUS
+    y = cos(radians(0))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/6))*HOLE_RADIUS
+    y = cos(radians(60/6))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/3))*HOLE_RADIUS
+    y = cos(radians(60/3))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/2))*HOLE_RADIUS
+    y = cos(radians(60/2))*HOLE_RADIUS
+    verts.append([x,y,0.0])
+    Row += 1
+    
+    #bevel
+    
+    x = sin(radians(0))*TopBevelRadius
+    y = cos(radians(0))*TopBevelRadius
+    vec1 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/6))*TopBevelRadius
+    y = cos(radians(60/6))*TopBevelRadius
+    vec2 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/3))*TopBevelRadius
+    y = cos(radians(60/3))*TopBevelRadius
+    vec3 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    
+    
+    x = sin(radians(60/2))*TopBevelRadius
+    y = cos(radians(60/2))*TopBevelRadius
+    vec4 = Mathutils.Vector([x,y,0.0])
+    verts.append([x,y,0.0])
+    Row += 1
+    
+    #Flats
+    
+    x = tan(radians(0))*Half_Flat
+    dvec = vec1 - Mathutils.Vector([x,Half_Flat,0.0])
+    verts.append([x,Half_Flat,-dvec.length])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
+    
+    
+    x = tan(radians(60/6))*Half_Flat
+    dvec = vec2 - Mathutils.Vector([x,Half_Flat,0.0])
+    verts.append([x,Half_Flat,-dvec.length])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
+    
+
+    x = tan(radians(60/3))*Half_Flat
+    dvec = vec3 - Mathutils.Vector([x,Half_Flat,0.0])
+    Lowest_Point = -dvec.length
+    verts.append([x,Half_Flat,-dvec.length])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
+
+    x = tan(radians(60/2))*Half_Flat
+    dvec = vec4 - Mathutils.Vector([x,Half_Flat,0.0])
+    Lowest_Point = -dvec.length
+    verts.append([x,Half_Flat,-dvec.length])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length)
+    Row += 1
+    
+    #down Bits Tri
+    x = tan(radians(0))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+    
+    
+    x = tan(radians(60/6))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+
+    x = tan(radians(60/3))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+    
+    x = tan(radians(60/2))*Half_Flat
+    verts.append([x,Half_Flat,Lowest_Point])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,Lowest_Point)
+    Row += 1
+
+    #down Bits
+    
+    x = tan(radians(0))*Half_Flat
+    verts.append([x,Half_Flat,-Half_Height])
+    
+    x = tan(radians(60/6))*Half_Flat
+    verts.append([x,Half_Flat,-Half_Height])
+
+    x = tan(radians(60/3))*Half_Flat
+    verts.append([x,Half_Flat,-Half_Height])
+    
+    x = tan(radians(60/2))*Half_Flat
+    verts.append([x,Half_Flat,-Half_Height])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,-Half_Height)
+    Row += 1
+
+    
+    
+    
+    faces.extend(Build_Face_List_Quads(FaceStart,3,Row - 1))
+
+
+    Global_Head_Height = HEIGHT
+    
+    Tvert,tface = Mirror_Verts_Faces(verts,faces,'z',Lowest_Z_Vert)
+    verts.extend(Tvert)
+    faces.extend(tface)
+           
+    
+    Tvert,tface = Mirror_Verts_Faces(verts,faces,'y')
+    verts.extend(Tvert)
+    faces.extend(tface)
+    
+    S_verts,S_faces = SpinDup(verts,faces,360,6,'z')
+    return S_verts,S_faces,TopBevelRadius
+
+
+def add_Nylon_Head(OUTSIDE_RADIUS,Z_LOCATION = 0):
+    DIV = 36
+    verts = []
+    faces = []
+    Row = 0
+
+    INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.25/4.75))
+    EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75))
+    RAD1 = (OUTSIDE_RADIUS * (0.5/4.75))
+    OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75))
+    
+    
+    FaceStart = len(verts)
+
+    Start_Height = 0 - 3
+    Height_Offset = Z_LOCATION
+    Lowest_Z_Vert = 0
+    
+    x = INNER_HOLE
+    z = (Height_Offset - OVER_ALL_HEIGTH) + EDGE_THICKNESS
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    x = INNER_HOLE
+    z = (Height_Offset - OVER_ALL_HEIGTH)
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    
+    for i in range(180,80,-10):
+        x = sin(radians(i))*RAD1
+        z = cos(radians(i))*RAD1
+        verts.append([(OUTSIDE_RADIUS-RAD1)+x,0.0,((Height_Offset - OVER_ALL_HEIGTH)+RAD1)+z])
+        Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+        Row += 1
+    
+    
+    x = OUTSIDE_RADIUS - 0
+    z = Height_Offset 
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+
+    sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
+    sVerts.extend(verts)        #add the start verts to the Spin verts to complete the loop
+    
+    faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
+
+    return Move_Verts_Up_Z(sVerts,0),faces,Lowest_Z_Vert
+
+
+
+def add_Nylon_Part(OUTSIDE_RADIUS,Z_LOCATION = 0):
+    DIV = 36
+    verts = []
+    faces = []
+    Row = 0
+
+    INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.5/4.75))
+    EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75))
+    RAD1 = (OUTSIDE_RADIUS * (0.5/4.75))
+    OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75))
+    PART_THICKNESS = OVER_ALL_HEIGTH - EDGE_THICKNESS
+    PART_INNER_HOLE = (OUTSIDE_RADIUS * (2.5/4.75))
+    
+    FaceStart = len(verts)
+
+    Start_Height = 0 - 3
+    Height_Offset = Z_LOCATION
+    Lowest_Z_Vert = 0
+    
+
+    x = INNER_HOLE + EDGE_THICKNESS
+    z = Height_Offset 
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    x = PART_INNER_HOLE
+    z = Height_Offset
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    x = PART_INNER_HOLE
+    z = Height_Offset - PART_THICKNESS
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+    
+    x = INNER_HOLE + EDGE_THICKNESS
+    z = Height_Offset - PART_THICKNESS
+    verts.append([x,0.0,z])
+    Lowest_Z_Vert = min(Lowest_Z_Vert,z)
+    Row += 1
+
+
+    sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z')
+    sVerts.extend(verts)  #add the start verts to the Spin verts to complete the loop
+    
+    faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV))
+
+    return sVerts,faces,0 - Lowest_Z_Vert
+
+
+
+def Nut_Mesh():
+
+    verts = []
+    faces = []
+    Head_Verts = []
+    Head_Faces= []
+
+    Face_Start = len(verts)
+    Thread_Verts,Thread_Faces,New_Nut_Height = Create_Internal_Thread(Minor_Dia.val,Major_Dia.val,Pitch.val,Hex_Nut_Height.val,Crest_Percent.val,Root_Percent.val,1)
+    verts.extend(Thread_Verts)
+    faces.extend(Copy_Faces(Thread_Faces,Face_Start))
+    
+    Face_Start = len(verts)
+    Head_Verts,Head_Faces,Lock_Nut_Rad = add_Hex_Nut(Hex_Nut_Flat_Distance.val,Major_Dia.val,New_Nut_Height)
+    verts.extend((Head_Verts))
+    faces.extend(Copy_Faces(Head_Faces,Face_Start))
+    
+    LowZ = 0 - New_Nut_Height
+    
+    if Nut_Type['LOCK'][0].val:
+        Face_Start = len(verts)
+        Nylon_Head_Verts,Nylon_Head_faces,LowZ = add_Nylon_Head(Lock_Nut_Rad,0-New_Nut_Height)    
+        verts.extend((Nylon_Head_Verts))
+        faces.extend(Copy_Faces(Nylon_Head_faces,Face_Start))
+    
+        Face_Start = len(verts)
+        Nylon_Verts,Nylon_faces,Temp_LowZ = add_Nylon_Part(Lock_Nut_Rad,0-New_Nut_Height)    
+        verts.extend((Nylon_Verts))
+        faces.extend(Copy_Faces(Nylon_faces,Face_Start))
+    
+
+    return Move_Verts_Up_Z(verts,0 - LowZ),faces
+
+
+
+##################################################################################################
+
+
+def Create_Nut():
+
+    verts = []
+    faces = []
+    
+  
+    if Error_Check() :
+        return
+
+    
+    verts, faces = Nut_Mesh()
+    Add_Mesh_To_Scene('Nut', verts, faces)
+    
+
+##################################################################################################
+
+
+def Create_Bolt():
+    verts = []
+    faces = []
+    
+  
+    if Error_Check() :
+        return
+    
+    verts, faces = MakeBolt()
+    Add_Mesh_To_Scene('Bolt', verts, faces)
+
+
+
+def Remove_Doubles_From_Mesh(verts,faces):
+    Ret_verts = []
+    Ret_faces = []
+    
+    is_editmode = Window.EditMode() # Store edit mode state
+    if is_editmode: Window.EditMode(0) # Python must get a mesh in object mode.
+    
+    Temp_mesh = Mesh.New('MeshTemp')          # create a new mesh
+
+    Temp_mesh.verts.extend(verts)          # add vertices to mesh
+    Temp_mesh.faces.extend(faces)           # add faces to the mesh (also adds edges)
+    
+    scn = Scene.GetCurrent()          # link object to current scene
+    Temp_Object = scn.objects.new(Temp_mesh, 'ObjectTemp')
+
+    Temp_mesh.remDoubles(0.010)
+    Temp_mesh.transform(Mathutils.Matrix([Global_Scale,0,0,0], [0,Global_Scale,0,0], [0,0,Global_Scale,0], [0,0,0, Global_Scale]))
+    Ret_verts[:] = [v.co for v in Temp_mesh.verts]
+    Ret_faces[:] = [ [v.index for v in f] for f in Temp_mesh.faces]
+
+    #delete temp mesh
+    scn.objects.unlink(Temp_Object)
+    scn.update(0)
+    
+    if is_editmode: Window.EditMode(1)
+    return Ret_verts,Ret_faces
+
+
+
+def Add_Mesh_To_Scene(name, verts, faces):
+    scn = Scene.GetCurrent()
+    if scn.lib: return
+    ob_act = scn.objects.active
+
+    is_editmode = Window.EditMode()
+
+    cursor = Window.GetCursorPos()
+    quat = None
+    
+    if is_editmode or Blender.Get('add_view_align'): # Aligning seems odd for editmode, but blender does it, oh well
+        try:    quat = Blender.Mathutils.Quaternion(Window.GetViewQuat())
+        except:    pass
+    
+
+    # Exist editmode for non mesh types
+    if ob_act and ob_act.type != 'Mesh' and is_editmode:
+        EditMode(0)
+   
+    # We are in mesh editmode
+    if Window.EditMode():
+        me = ob_act.getData(mesh=1)
+        
+        if me.multires:
+            error_txt = 'Error%t|Unable to complete action with multires enabled'
+            Blender.Draw.PupMenu(error_txt)
+            print error_txt
+            return
+        
+        #Don't want to remove doubles and scale the existing
+        # mesh so we need to get the verts and the faces from
+        # a mesh that has been scaled. 
+        verts,faces = Remove_Doubles_From_Mesh(verts, faces)
+                
+        # Add to existing mesh
+        # must exit editmode to modify mesh
+        Window.EditMode(0)
+        
+        me.sel = False
+        
+        vert_offset = len(me.verts)
+        face_offset = len(me.faces)
+        
+        
+        # transform the verts
+        txmat = Blender.Mathutils.TranslationMatrix(Blender.Mathutils.Vector(cursor))
+        if quat:
+            mat = quat.toMatrix()
+            mat.invert()
+            mat.resize4x4()
+            txmat = mat * txmat
+        
+        txmat = txmat * ob_act.matrixWorld.copy().invert()
+        
+        
+        me.verts.extend(verts)
+        # Transform the verts by the cursor and view rotation
+        me.transform(txmat, selected_only=True)
+        
+        if vert_offset:
+            me.faces.extend([[i+vert_offset for i in f] for f in faces])
+        else:
+            # Mesh with no data, unlikely
+            me.faces.extend(faces)        
+    else:
+        
+        # Object mode add new
+        me = Mesh.New(name)
+        me.verts.extend(verts)
+        me.faces.extend(faces)
+        
+        
+        me.sel = True
+        
+        # Object creation and location
+        scn.objects.selected = []
+        ob_act = scn.objects.new(me, name)
+        
+        me.remDoubles(0.010)
+        me.transform(Mathutils.Matrix([Global_Scale,0,0,0], [0,Global_Scale,0,0], [0,0,Global_Scale,0], [0,0,0, Global_Scale]))
+
+        scn.objects.active = ob_act
+        
+        if quat:
+            mat = quat.toMatrix()
+            mat.invert()
+            mat.resize4x4()
+            ob_act.setMatrix(mat)
+        
+        ob_act.loc = cursor
+    
+    me.calcNormals()
+    
+    if is_editmode or Blender.Get('add_editmode'):
+        Window.EditMode(1)
+        
+    Blender.Redraw(-1)#Redraw all
+
+##################################################################################################
+    
+    
+
+def Load_Preset():
+
+    global Preset_Menu
+    global Shank_Dia
+    global Shank_Length
+    global Thread_Length
+    global Major_Dia 
+    global Minor_Dia
+    global Pitch 
+    global Crest_Percent 
+    global Root_Percent 
+    global Allen_Bit_Flat_Distance
+    global Allen_Bit_Depth
+    global Head_Height
+    global Hex_Head_Flat_Distance 
+    global Head_Dia 
+    global Dome_Head_Dia
+    global Pan_Head_Dia 
+    global Philips_Bit_Dia 
+    global Phillips_Bit_Depth 
+    global Cap_Head_Height
+
+    global Hex_Nut_Height
+    global Hex_Nut_Flat_Distance
+
+
+    if Preset_Menu.val == 1 : #M3
+        Shank_Dia.val = 3.0
+        #Pitch.val = 0.5    #Coarse
+        Pitch.val = 0.35  #Fine
+        Crest_Percent.val = 10
+        Root_Percent.val = 10 
+        Major_Dia.val = 3.0
+        Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+        Hex_Head_Flat_Distance.val = 5.5
+        Hex_Head_Height.val = 2.0
+        Cap_Head_Dia.val = 5.5
+        Cap_Head_Height.val = 3.0
+        Allen_Bit_Flat_Distance.val = 2.5
+        Allen_Bit_Depth.val = 1.5
+        Pan_Head_Dia.val = 5.6
+        Dome_Head_Dia.val = 5.6
+        Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+        Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+        Hex_Nut_Height.val = 2.4
+        Hex_Nut_Flat_Distance.val = 5.5
+        Thread_Length.val = 6
+        Shank_Length.val = 0.0
+        
+    
+    if Preset_Menu.val == 2 : #M4
+        Shank_Dia.val = 4.0
+        #Pitch.val = 0.7    #Coarse
+        Pitch.val = 0.5  #Fine
+        Crest_Percent.val = 10
+        Root_Percent.val = 10 
+        Major_Dia.val = 4.0
+        Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+        Hex_Head_Flat_Distance.val = 7.0
+        Hex_Head_Height.val = 2.8
+        Cap_Head_Dia.val = 7.0
+        Cap_Head_Height.val = 4.0
+        Allen_Bit_Flat_Distance.val = 3.0
+        Allen_Bit_Depth.val = 2.0
+        Pan_Head_Dia.val = 8.0
+        Dome_Head_Dia.val = 8.0
+        Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+        Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+        Hex_Nut_Height.val = 3.2
+        Hex_Nut_Flat_Distance.val = 7.0
+        Thread_Length.val = 8
+        Shank_Length.val = 0.0
+        
+        
+    if Preset_Menu.val == 3 : #M5
+        Shank_Dia.val = 5.0
+        #Pitch.val = 0.8 #Coarse
+        Pitch.val = 0.5  #Fine
+        Crest_Percent.val = 10
+        Root_Percent.val = 10 
+        Major_Dia.val = 5.0
+        Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+        Hex_Head_Flat_Distance.val = 8.0
+        Hex_Head_Height.val = 3.5
+        Cap_Head_Dia.val = 8.5
+        Cap_Head_Height.val = 5.0
+        Allen_Bit_Flat_Distance.val = 4.0
+        Allen_Bit_Depth.val = 2.5
+        Pan_Head_Dia.val = 9.5
+        Dome_Head_Dia.val = 9.5
+        Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+        Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+        Hex_Nut_Height.val = 4.0
+        Hex_Nut_Flat_Distance.val = 8.0
+        Thread_Length.val = 10
+        Shank_Length.val = 0.0
+        
+        
+    if Preset_Menu.val == 4 : #M6
+        Shank_Dia.val = 6.0
+        #Pitch.val = 1.0 #Coarse
+        Pitch.val = 0.75  #Fine
+        Crest_Percent.val = 10
+        Root_Percent.val = 10
+        Major_Dia.val = 6.0
+        Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+        Hex_Head_Flat_Distance.val = 10.0
+        Hex_Head_Height.val = 4.0
+        Cap_Head_Dia.val = 10.0
+        Cap_Head_Height.val = 6.0
+        Allen_Bit_Flat_Distance.val = 5.0
+        Allen_Bit_Depth.val = 3.0
+        Pan_Head_Dia.val = 12.0
+        Dome_Head_Dia.val = 12.0
+        Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+        Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+        Hex_Nut_Height.val = 5.0
+        Hex_Nut_Flat_Distance.val = 10.0
+        Thread_Length.val = 12
+        Shank_Length.val = 0.0
+        
+        
+    if Preset_Menu.val == 5 : #M8
+        Shank_Dia.val = 8.0
+        #Pitch.val = 1.25 #Coarse
+        Pitch.val = 1.00  #Fine
+        Crest_Percent.val = 10
+        Root_Percent.val = 10
+        Major_Dia.val = 8.0
+        Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+        Hex_Head_Flat_Distance.val = 13.0
+        Hex_Head_Height.val = 5.3
+        Cap_Head_Dia.val = 13.5
+        Cap_Head_Height.val = 8.0
+        Allen_Bit_Flat_Distance.val = 6.0
+        Allen_Bit_Depth.val = 4.0
+        Pan_Head_Dia.val = 16.0
+        Dome_Head_Dia.val = 16.0
+        Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+        Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+        Hex_Nut_Height.val = 6.5
+        Hex_Nut_Flat_Distance.val = 13.0
+        Thread_Length.val = 16
+        Shank_Length.val = 0.0
+    
+    if Preset_Menu.val == 6 : #M10
+        Shank_Dia.val = 10.0
+        #Pitch.val = 1.5 #Coarse
+        Pitch.val = 1.25  #Fine
+        Crest_Percent.val = 10
+        Root_Percent.val = 10
+        Major_Dia.val = 10.0
+        Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+        Hex_Head_Flat_Distance.val = 17.0
+        Hex_Head_Height.val = 6.4
+        Cap_Head_Dia.val = 16.0
+        Cap_Head_Height.val = 10.0
+        Allen_Bit_Flat_Distance.val = 8.0
+        Allen_Bit_Depth.val = 5.0
+        Pan_Head_Dia.val = 20.0
+        Dome_Head_Dia.val = 20.0
+        Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+        Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+        Hex_Nut_Height.val = 8.0
+        Hex_Nut_Flat_Distance.val = 17.0
+        Thread_Length.val = 20
+        Shank_Length.val = 0.0
+    
+    
+    if Preset_Menu.val == 7 : #M12
+        #Pitch.val = 1.75 #Coarse
+        Pitch.val = 1.50  #Fine
+        Crest_Percent.val = 10
+        Root_Percent.val = 10
+        Major_Dia.val = 12.0
+        Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val)
+        Hex_Head_Flat_Distance.val = 19.0
+        Hex_Head_Height.val = 7.5
+        Cap_Head_Dia.val = 18.5
+        Cap_Head_Height.val = 12.0
+        Allen_Bit_Flat_Distance.val = 10.0
+        Allen_Bit_Depth.val = 6.0
+        Pan_Head_Dia.val = 24.0
+        Dome_Head_Dia.val = 24.0
+        Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6)
+        Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val)
+        Hex_Nut_Height.val = 10.0
+        Hex_Nut_Flat_Distance.val = 19.0
+        Shank_Dia.val = 12.0
+        Shank_Length.val = 33.0
+        Thread_Length.val = 32.0
+        
+##############################################################################################
+
+def Test():
+    verts = []
+    faces = []
+   
+    if Error_Check() :
+        return
+    
+    verts, faces = MakeBolt()
+    
+    Add_Mesh_To_Scene("TestBolt", verts,faces)
+
+    Window.Redraw(-1)
+
+
+
+
+def event(evt, val):    # the function to handle input events
+
+  if evt == Draw.ESCKEY:
+    Draw.Exit()                 # exit when user presses ESC
+    return
+
+
+def button_event(evt):  # the function to handle Draw Button events
+
+    if evt == On_Exit_Click:
+        Draw.Exit()                 # exit when user presses ESC
+        return
+
+    if evt == On_Test_Click:
+        Test()
+        Draw.Redraw(1)
+    
+    if evt == On_Preset_Click:
+        Load_Preset()
+        Draw.Redraw(1)
+
+    if evt == On_Create_Click:
+        if Model_Type['BOLT'][0].val:
+            Create_Bolt()
+        if Model_Type['NUT'][0].val:
+            Create_Nut()
+        Draw.Redraw(1)
+    
+    elif (evt in [On_Hex_Click, On_Cap_Click,On_Dome_Click,On_Pan_Click]):
+        for k in Head_Type.iterkeys():
+            if Head_Type[k][1]!=evt:
+                Head_Type[k][0].val=0
+            else:
+                Head_Type[k][0].val=1    
+        Draw.Redraw(1)
+    
+    elif (evt in [On_Bit_None_Click,On_Bit_Allen_Click,On_Bit_Philips_Click]):
+        for k in Bit_Type.iterkeys():
+            if Bit_Type[k][1]!=evt:
+                Bit_Type[k][0].val=0
+            else:
+                Bit_Type[k][0].val=1
+        Draw.Redraw(1)
+
+    elif (evt in [On_Model_Bolt_Click,On_Model_Nut_Click]):
+        for k in Model_Type.iterkeys():
+            if Model_Type[k][1]!=evt:
+                Model_Type[k][0].val=0
+            else:
+                Model_Type[k][0].val=1
+        Draw.Redraw(1)
+
+    elif (evt in [On_Hex_Nut_Click,On_Lock_Nut_Click]):
+        for k in Nut_Type.iterkeys():
+            if Nut_Type[k][1]!=evt:
+                Nut_Type[k][0].val=0
+            else:
+                Nut_Type[k][0].val=1
+        Draw.Redraw(1)
+    
+#####################################################################################
+      
+
+def Draw_Border(X1,Y1,X2,Y2): # X1,Y1 = Top Left X2,Y2 = Bottom Right
+    INDENT = 3
+    
+    BGL.glColor3f(1.0,1.0,1.0)
+    BGL.glBegin(BGL.GL_LINES)                
+    BGL.glVertex2i(X1+INDENT,Y1-INDENT)     #top line
+    BGL.glVertex2i(X2-INDENT,Y1-INDENT)
+    
+    BGL.glVertex2i(X1+INDENT,Y1-INDENT)     #left line
+    BGL.glVertex2i(X1+INDENT,Y2+INDENT)
+    BGL.glEnd()
+
+    BGL.glColor3f(0.5,0.5,0.5)
+    BGL.glBegin(BGL.GL_LINES)                
+    BGL.glVertex2i(X2-INDENT,Y1-INDENT)     #Right line
+    BGL.glVertex2i(X2-INDENT,Y2+INDENT)
+    
+    BGL.glVertex2i(X1+INDENT,Y2+INDENT)     #bottom line
+    BGL.glVertex2i(X2-INDENT,Y2+INDENT)
+    BGL.glEnd()
+    
+    
+
+
+def Create_Tab(X1,Y1,X2,Y2,Title,Buttons): # X1,Y1 = Top Left X2,Y2 = Bottom Right
+
+    BIT_BUTTON_WIDTH = 55
+    BIT_BUTTON_HEIGHT = 18
+    TITLE_HEIGHT = 15
+    INDENT = 6
+    BUTTON_GAP = 4
+
+    BGL.glColor3f(0.75, 0.75, 0.75)
+    BGL.glRecti(X1,Y1,X2,Y2)
+    
+    Draw_Border(X1,Y1,X2,Y2);
+    
+    BGL.glColor3f(0.0,0.0,0.0)
+    BGL.glRasterPos2d(X1+INDENT,Y1 - TITLE_HEIGHT)
+    Draw.Text(Title)
+    
+    Button_X = X1 + INDENT
+    Button_Y = Y1 - TITLE_HEIGHT - BIT_BUTTON_HEIGHT - 8
+    
+    #Nut_Number_X = Nut_Button_X
+    #Nut_Number_Y = Nut_Button_Y - 25
+    if (Buttons != 0):
+        key= Buttons.keys()
+        for k in key:
+            Buttons[k][0]= Draw.Toggle(k,Buttons[k][1],Button_X,Button_Y, BIT_BUTTON_WIDTH,BIT_BUTTON_HEIGHT,Buttons[k][0].val,Buttons[k][2])
+            Button_X += BIT_BUTTON_WIDTH + BUTTON_GAP    
+    
+    
+    
+def Dispaly_Title_Bar(Y_POS,CONTROL_HEIGHT):
+    CONTROL_WIDTH = 250
+    Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS -CONTROL_HEIGHT,"Bolt Factory V2.00",Model_Type)
+    
+    
+      
+def Dispaly_Preset_Tab(Y_POS,CONTROL_HEIGHT):
+    CONTROL_WIDTH = 250
+    BUTTON_Y_OFFSET = 40
+    
+    Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Preset",0)
+    
+    name = "M3%x1|M4%x2|M5%x3|M6%x4|M8%x5|M10%x6|M12%x7"
+    
+    global Preset_Menu
+    Preset_Menu = Draw.Menu(name,No_Event,9,Y_POS-BUTTON_Y_OFFSET,50,18, Preset_Menu.val, "Predefined metric screw sizes.")
+    Draw.Button("Apply",On_Preset_Click,150,Y_POS-BUTTON_Y_OFFSET,55,18,"Apply the preset screw sizes.")
+    
+
+def Dispaly_Bit_Tab(Y_POS,CONTROL_HEIGHT):  
+    
+    CONTROL_WIDTH = 250
+    NUMBER_HEIGHT = 18
+    NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
+
+    Bit_Number_X = 3+3+3
+    Bit_Number_Y = Y_POS - 64
+        
+    Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Bit Type",Bit_Type)
+    
+    if Bit_Type['NONE'][0].val:
+        DoNothing = 1;
+        
+    elif Bit_Type['ALLEN'][0].val:
+        global Allen_Bit_Depth
+        Allen_Bit_Depth = Draw.Number('Bit Depth: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Allen_Bit_Depth.val, 0,100, '')
+        Bit_Number_Y -= NUMBER_HEIGHT
+        global Allen_Bit_Flat_Distance
+        Allen_Bit_Flat_Distance = Draw.Number('Flat Dist: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH,NUMBER_HEIGHT,Allen_Bit_Flat_Distance.val, 0,100, '')
+        Bit_Number_Y -= NUMBER_HEIGHT
+
+    elif Bit_Type['PHILLIPS'][0].val:
+        global Phillips_Bit_Depth
+        Phillips_Bit_Depth = Draw.Number('Bit Depth: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Phillips_Bit_Depth.val, 0,100, '')
+        Bit_Number_Y -= NUMBER_HEIGHT
+        global Philips_Bit_Dia
+        Philips_Bit_Dia = Draw.Number('Bit Dia: ',No_Event,Bit_Number_X,Bit_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Philips_Bit_Dia.val, 0,100, '')
+        Bit_Number_Y -= NUMBER_HEIGHT
+
+
+
+def Dispaly_Shank_Tab(Y_POS,CONTROL_HEIGHT):  
+    
+    CONTROL_WIDTH = 250
+    NUMBER_HEIGHT = 18
+    NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
+
+    Number_X = 3+3+3
+    Number_Y_Pos = Y_POS - 40
+        
+    Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Shank",0)
+  
+    global Shank_Length 
+    Shank_Length = Draw.Number('Shank Length: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Shank_Length.val, 0,MAX_INPUT_NUMBER, 'some text tip')
+    Number_Y_Pos -= NUMBER_HEIGHT
+  
+    global Shank_Dia 
+    Shank_Dia = Draw.Number('Shank Dia: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Shank_Dia.val, 0,MAX_INPUT_NUMBER, 'some text tip')
+    Number_Y_Pos -= NUMBER_HEIGHT
+  
+    
+
+def Dispaly_Thread_Tab(Y_POS,CONTROL_HEIGHT):  
+    
+    CONTROL_WIDTH = 250
+    NUMBER_HEIGHT = 18
+    NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
+    
+
+    Number_X = 3+3+3
+    Number_Y_Pos = Y_POS - 40
+            
+    Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Thread",0)
+    
+    global Thread_Length
+    if Model_Type['BOLT'][0].val:
+        Thread_Length = Draw.Number('Thread Length: ',No_Event, Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Thread_Length.val, 0,MAX_INPUT_NUMBER, '')
+    Number_Y_Pos -= NUMBER_HEIGHT
+  
+    global Major_Dia
+    Major_Dia = Draw.Number('Major Dia: ',No_Event,Number_X,Number_Y_Pos, NUMBER_WIDTH,NUMBER_HEIGHT, Major_Dia.val, 0,MAX_INPUT_NUMBER, '')
+    Number_Y_Pos -= NUMBER_HEIGHT
+  
+    global Minor_Dia
+    Minor_Dia = Draw.Number('Minor Dia: ',No_Event,Number_X,Number_Y_Pos, NUMBER_WIDTH,NUMBER_HEIGHT, Minor_Dia.val, 0,MAX_INPUT_NUMBER, '')
+    Number_Y_Pos -= NUMBER_HEIGHT
+  
+    global Pitch
+    Pitch = Draw.Number('Pitch: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Pitch.val, 0.1,7.0, '')
+    Number_Y_Pos -= NUMBER_HEIGHT
+    
+    global Crest_Percent
+    Crest_Percent = Draw.Number('Crest %: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT,Crest_Percent.val, 1,90, '')
+    Number_Y_Pos -= NUMBER_HEIGHT
+  
+    global Root_Percent
+    Root_Percent = Draw.Number('Root %: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT,Root_Percent.val, 1,90, '')
+    Number_Y_Pos -= NUMBER_HEIGHT
+  
+
+    
+    
+def Dispaly_Head_Tab(Y_POS,CONTROL_HEIGHT):  
+    
+    CONTROL_WIDTH = 250
+    NUMBER_HEIGHT = 18
+    NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
+
+    Head_Number_X = 3+3+3
+    Head_Number_Y = Y_POS - 64
+        
+    Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Head Type",Head_Type)
+    
+    if Head_Type['HEX'][0].val:  
+        global Hex_Head_Height
+        Hex_Head_Height = Draw.Number('Head Height: ',No_Event,Head_Number_X ,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Head_Height.val, 0,100, '')
+        Head_Number_Y -= NUMBER_HEIGHT
+        global Hex_Head_Flat_Distance
+        Hex_Head_Flat_Distance = Draw.Number('Head Hex Flat Distance ',No_Event,Head_Number_X,Head_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Head_Flat_Distance.val, 0,MAX_INPUT_NUMBER, '')
+        Head_Number_Y -= NUMBER_HEIGHT
+  
+    elif Head_Type['CAP'][0].val:  
+        global Cap_Head_Height
+        Cap_Head_Height = Draw.Number('Head Height: ',No_Event, Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Cap_Head_Height.val, 0,100, '')
+        Head_Number_Y -= NUMBER_HEIGHT
+        global Cap_Head_Dia
+        Cap_Head_Dia = Draw.Number('Head Dia ',No_Event,Head_Number_X,Head_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Cap_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
+        Head_Number_Y -= NUMBER_HEIGHT
+  
+    elif Head_Type['DOME'][0].val:  
+        global Dome_Head_Dia
+        Dome_Head_Dia = Draw.Number(' Dome Head Dia ',No_Event,Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Dome_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
+        Head_Number_Y -= NUMBER_HEIGHT
+  
+    elif Head_Type['PAN'][0].val:  
+        global Pan_Head_Dia
+        Pan_Head_Dia = Draw.Number('Pan Head Dia ',No_Event,Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Pan_Head_Dia.val, 0,MAX_INPUT_NUMBER, '')
+        Head_Number_Y -= NUMBER_HEIGHT
+  
+    
+    
+    
+def Dispaly_Nut_Tab(Y_POS,CONTROL_HEIGHT):  
+    
+    CONTROL_WIDTH = 250
+    NUMBER_HEIGHT = 18
+    NUMBER_WIDTH = CONTROL_WIDTH  -3-3-3-3-3
+
+    Nut_Number_X = 3+3+3
+    Nut_Number_Y = Y_POS - 64
+   
+    Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Nut Type",Nut_Type)
+        
+    #if Nut_Type['HEX'][0].val:  
+    global Hex_Nut_Height
+    Hex_Nut_Height = Draw.Number('Nut Height: ',No_Event,Nut_Number_X ,Nut_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Nut_Height.val, 0,MAX_INPUT_NUMBER, '')
+    Nut_Number_Y -= NUMBER_HEIGHT
+    global Hex_Nut_Flat_Distance
+    Hex_Nut_Flat_Distance = Draw.Number('Nut Flat Distance ',No_Event,Nut_Number_X,Nut_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Nut_Flat_Distance.val, 0,MAX_INPUT_NUMBER, '')
+    Nut_Number_Y -= NUMBER_HEIGHT
+  
+
+def Dispaly_Bolt_Tab():    
+       
+    Dispaly_Shank_Tab(284,66)
+    Dispaly_Head_Tab(374,90)
+    Dispaly_Bit_Tab(464,90)
+    
+
+##########################################################################################
+
+def gui():              # the function to draw the screen
+    
+    CONTROL_WIDTH = 250
+
+    BGL.glClearColor(0.6, 0.6, 0.6, 1.0)
+    BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
+    
+    BGL.glColor3f(0.75, 0.75, 0.75)
+    BGL.glRecti(3,30,CONTROL_WIDTH,3)
+    
+    Dispaly_Title_Bar(514,50);
+    
+    if Model_Type['BOLT'][0].val:
+        Dispaly_Bolt_Tab();
+    
+    if Model_Type['NUT'][0].val:
+        Dispaly_Nut_Tab(464,246);
+
+    Dispaly_Thread_Tab(218,138)
+
+    Dispaly_Preset_Tab(80,50)
+    
+    Draw.PushButton("Create",On_Create_Click,6,8,55,18,"Create Bolt")
+    Draw.Button("Exit",On_Exit_Click,6+55+4,8,55,18)
+   
+#    Draw.Button("Test",On_Test_Click,150,10,55,20)
+
+Load_Preset()
+Draw.Register(gui, event, button_event)  # registering the 3 callbacks
diff --git a/release/scripts/wizard_landscape_ant.py b/release/scripts/wizard_landscape_ant.py
new file mode 100644 (file)
index 0000000..405c064
--- /dev/null
@@ -0,0 +1,2148 @@
+#!BPY
+"""
+Name: 'Landscape Generator (A.N.T)'
+Blender: 248
+Group: 'Wizards'
+Tip: 'Create landscape mesh.'
+"""
+
+__author__ = "Jimmy Hazevoet"
+__url__     = ('http://wiki.blender.org/index.php/Scripts/Manual/Wizards/ANTLandscape','elysiun')
+__version__ = "v.1.05 03-2007"
+__bpydoc__ = """\
+
+Another Noise Tool 'Landscape' v.1.05
+
+This script uses noise functions to create a terrain from a grid mesh.
+
+Usage:
+
+Make new terrain:  press the "Add New Grid" button, change some noise settings and press the "Update" button.
+
+Work on previous made grid:  select the grid/terrain in the 3D view, and press the "Assign" button.
+
+Tip: use a low resolution grid mesh and add some Multires levels for detail
+
+Note: when using Multires materials can get weird,
+only apply materials when your terrain is ready, or not use Multires.
+
+This Script creates a landscape mesh.
+Press the Auto button when you start the script.
+Then the Generate Button & read it's tooltip.
+The mesh created is average 16000 verts.
+To me the mesh appears quite small in the 3d view.
+Just Press S in the 3d view to scale it up.
+This saves overhead drawing the Mesh.
+
+Known Issues:
+If the mesh is not drawn in the 3d view first time, 
+Move your mouse to the 3d view, or press the button again.
+
+Not really an issue, more to be aware.
+Due to the complex nature & design of the script, it only creates one mesh at a time.
+When you press Generate or Reset, 
+Even if you have Closed then Opened the script or .blend file,
+The mesh Will be Overwritten.
+To create Multiple Landscapes you Must Re-Name or save the Mesh
+in Blender's F7 menu Links & Materials Panel.
+
+Readme:
+v.1.04:
+_ New G.U.I.
+_ New noise types like: 
+Double_Terrain, 
+StatsByAlt_Terrain, 
+slickRock, 
+ditorted_heteroTerrain, 
+vlNoise_turbulence, 
+and many more.
+
+New fractalized Effect functions.     
+Effect types such as: gradient,
+waves and bumps, dome, piramide, 
+squares, grid, shattered rocks, 
+lunar, and many more.
+     
+Bias types: Sin, Cos, Tri, Saw, 
+and Default(no bias).
+    
+For example the 'Rings' effect 
+with 'Sin Bias' makes 'Rings' 
+and 'Default Bias' makes 'Dome'.
+The Effect 'Mix factor' Slider gives control over how much of the Effect is vissible, 
+-1.0=noise, 0.0=average, 1.0=effect
+this slider controls also the 'Warp amount' if mix type 'Warp' is selected.
+
+Image effect: mix image with noise
+_ IPOCurve Filter: use Ipo curve to filter terrain height.
+I know it's a bit strange to use animation curves for landscape modelling, (actualy i want a curves panel in my G.U.I. but i dont know how to do that)
+the downside of this method is that you have this 'Empty' moving around in your scene, so put it on another layer and 'Pin' the Ipo block so that it stays visible.
+Usage:
+Add one 'Empty' Object to your scene, now add one Loc Key at Frame 1, go to Frame 101 (UpArrow ten times),
+move the 'Empty' +100 units in X+ direction and add another Loc Key, open the Ipo Curve Editor Window, rename this IpoBlock if you want,
+Copie the first curve to buffer and Paste it in the empty slots (from top to bottom), now you can edit the curves freely.
+(use the 'Pin' option to keep the curves visible while other objects are selected)
+Set the CurveLength and CurveHeight Button value's according to the length and height of the selected curve.
+A curve filter is very versatile when it comes to 'height' filtering.
+
+_ PreView in UV/Image Editor Window:
+The preview image is now rendered as Blender.Image and will be saved to file directory as 'ANTview_size.tga'
+you have to select 'ANTview_size.tga' in the UV/Image Editor Window
+now it's posible to render and save a large HeightMap image (you can also create nice texture images when the VertCol gradient is enabled),
+! If you Change the preview image Size a New Blender.Image object is created. (one for size 256, one for size 512 one for.....) !
+
+_ VertexColours: use any image as colour gradient.
+This function actualy uses one 'row' of pixels from a image to produce the color gradient,
+Make one or more custom gradient images with the Gimp or any other graphics software, the gradients must go from left to right (left is bottom and right is top.
+you only need one row of pixels so you can put 10 gradients in a 256*10 image.(higher resolutions like 512*n or 1024*n gives smoother result) 
+Set Window DrawMode 'Textured' , and set the 'VCol Paint' option in the Materials panel !
+
+_ Mesh Tiles: Create large scale terrains.
+
+_ Vertices Selection: select flat areas.
+
+_ Keyboard HotKeys:
+SPACE = Update mesh.
+R = Randomise.
+V = Redraw preview.
+
+_ and more...
+
+"""
+
+
+
+
+###
+#
+# Alt+P to start script.
+#
+###
+# scroll down to see info about updates
+##
+################################################################################################################
+# Another Noise Tool 'Landscape'
+# Jimmy Hazevoet
+# license: Do whatever you want with it.
+################################################################################################################
+
+################################################################################################################
+#   v.1.04:
+#
+# _ New G.U.I.
+# _ New noise types like: Double_Terrain, StatsByAlt_Terrain, slickRock, ditorted_heteroTerrain, vlNoise_turbulence, and many more.
+# _ New fractalized Effect functions.
+#      Effect types such as: gradient, waves and bumps, dome, piramide, squares, grid, shattered rocks, lunar, and many more.
+#      Bias types: Sin, Cos, Tri, Saw, and Default(no bias).
+#      For example the 'Rings' effect with 'Sin Bias' makes 'Rings' and 'Default Bias' makes 'Dome'.
+# _ The Effect 'Mix factor' Slider gives control over how much of the Effect is vissible, -1.0=noise, 0.0=average, 1.0=effect
+#      this slider controls also the 'Warp amount' if mix type 'Warp' is selected.
+# _ Image effect: mix image with noise
+# _ IPOCurve Filter: use Ipo curve to filter terrain height.
+#      I know it's a bit strange to use animation curves for landscape modelling, (actualy i want a curves panel in my G.U.I. but i dont know how to do that)
+#      the downside of this method is that you have this 'Empty' moving around in your scene, so put it on another layer and 'Pin' the Ipo block so that it stays visible.
+#     Usage:
+#      Add one 'Empty' Object to your scene, now add one Loc Key at Frame 1, go to Frame 101 (UpArrow ten times),
+#      move the 'Empty' +100 units in X+ direction and add another Loc Key, open the Ipo Curve Editor Window, rename this IpoBlock if you want,
+#      Copie the first curve to buffer and Paste it in the empty slots (from top to bottom), now you can edit the curves freely.
+#      (use the 'Pin' option to keep the curves visible while other objects are selected)
+#      Set the CurveLength and CurveHeight Button value's according to the length and height of the selected curve.
+#      A curve filter is very versatile when it comes to 'height' filtering.
+# _ PreView in UV/Image Editor Window:
+#      The preview image is now rendered as Blender.Image and will be saved to file directory as 'ANTview_size.tga'
+#      you have to select 'ANTview_size.tga' in the UV/Image Editor Window
+#      now it's posible to render and save a large HeightMap image (you can also create nice texture images when the VertCol gradient is enabled),
+#      ! If you Change the preview image Size a New Blender.Image object is created. (one for size 256, one for size 512 one for.....) !
+# _ VertexColours: use any image as colour gradient.
+#      This function actualy uses one 'row' of pixels from a image to produce the color gradient,
+#      Make one or more custom gradient images with the Gimp or any other graphics software, the gradients must go from left to right (left is bottom and right is top.
+#      you only need one row of pixels so you can put 10 gradients in a 256*10 image.(higher resolutions like 512*n or 1024*n gives smoother result) 
+#      Set Window DrawMode 'Textured' , and set the 'VCol Paint' option in the Materials panel !
+# _ Mesh Tiles: Create large scale terrains.
+# _ Vertices Selection: select flat areas.
+# _ Keyboard HotKeys:
+#      SPACE = Update mesh.
+#      R = Randomise.
+#      V = Redraw preview.
+# _ and more...
+################################################################################################################
+
+################################################################################################################
+# BugFix: Sept./2006  v.1.04a
+#-----------------------------
+# _Image Effect did not worked well with tiled mesh. Fixed (now use Freq. and Loc. buttons to scale and position image).
+#
+################################################################################################################
+
+
+################################################################################################################
+# UPDATE: v.1.05  03-2007
+#---------------------------------------------------------------------------------------------------------------
+#
+# _ New: Save and Load function, save your settings to a .ant file.
+# __NOTE: when saving/loading settings to/from a file,
+#         make sure the filename/path is not too long!
+# __HOTKEY__ Load from file: L
+# __HOTKEY__ Save to file  : S
+#
+# _ New mesh code, uses Mesh instead of NMesh,
+#        this gives a small speed improvement and alows you to use Multires.
+#
+#   Usage: Select a Grid/Terrain mesh and hit the Assign button, now you can work on it, when ready you assign another.
+#
+# _ New: 'Musgrave' noise types, 'Random noise' and 'Constant' in 'Effects' section.
+# _ New: 'Custom Effect', write custom formulae ( x,y, a,b, from math import *, from Blender.Noise import * )
+# _ New: 'Custom Height Filter', write custom formulae ( x,y, h, a,b, from math import *, from Blender.Noise import * )
+# _ New: 'Change Filter Order', Toggle: OFF = Noise+Effect+Falloff+FILTER / ON = Noise+FILTER+Effect+Falloff
+#
+# _ If you want to make a tiled terrain, you need to set the coordinates to "WorldSpace" or "Center at Cursor" (in G.U.I.Noise panel),
+#   create and place the grid meshes. now one by one select, assign and update, you may need to adjust the "EdgeFalloff" size.
+#
+# WARNING!: when using Multires, materials can get weird (?), so apply materials when your terrain is finnished.
+#
+###############################################################################################################
+
+
+###############################################################################################################
+#
+##  Execute Script: Alt P 
+#
+
+
+import Blender
+from Blender import * 
+from math import *
+from Blender.Noise import * 
+from Blender.Draw import *
+from Blender.BGL import *
+from Blender import Image
+import string
+from string import strip
+import BPyMathutils
+from BPyMathutils import genrand
+from random import choice
+scene = Scene.GetCurrent()
+
+###---------------------------------------------------------------------------
+
+CurVersion = 'A.N.T.Landscape v.1.05'
+
+##---------------------------------------------------------------------------
+# Customise default settings: ----------------------------------------------
+
+# Names:
+antfilename = 'Terrain'   # Default filename
+previewname = Create('')  # Default preview Image name
+DefaultIpoName  = ''      # Default Ipo DataBlock name (for height filter)
+# G.U.I.:
+FullScreen = Create( 0 )            # FullScreen on/off
+# gui colors:
+ledcolors = [ [1.0,0.498,0.498], [1.0,0.698,0.498], [1.0,0.898,0.498], [0.898,1.0,0.498], [0.698,1.0,0.498], [0.498,1.0,0.498], [0.498,1.0,0.698], [0.498,1.0,0.898], [0.600,0.918,1.0], [0.6,0.757,1.0], [0.6,0.6,1.0], [0.757,0.6,1.0], [0.898,0.498,1.0], [1.0,0.498,0.898] ]
+#ledcolor   = [ 1.0, 0.5, 0.0 ]
+lightgrey  = [ 0.76, 0.76, 0.76 ]   # gui col.
+grey       = [ 0.6, 0.6, 0.6 ]      # panel col.
+background = [ 0.7, 0.7, 0.7, 1.0 ] # background col.
+black      = [ 0.0, 0.0, 0.0 ]      # text col.
+white      = [ 1.0, 1.0, 1.0 ]
+# gui size
+size_x  = 320                       # gui x size
+size_y  = 280                       # gui y size
+# tabs
+guitabs = [ Create( 1 ), Create( 0 ), Create( 0 ), Create( 0 ), Create( 0 ) ]  # gui Tabs
+# How long does it take to generate a mesh or image ?
+print_time = 0 # 1 = Print time in console.
+
+# end customise. ----------------------------------------------------------
+##--------------------------------------------------------------------------
+###--------------------------------------------------------------------------
+####--------------------------------------------------------------------------
+##---------------------------------------------------------------------------
+
+dirpath=Blender.sys.dirname(Blender.Get('filename'))
+fname=dirpath.replace('\\','/')+'/' + antfilename + '.ant'
+txtFile = Create( fname )
+
+###---------------------------------------------------------------------------
+columns = 10 # gui columns
+rows    = 13 # gui rows
+actob = [] # active object
+actme = [] # active mesh
+ipoblockname=''
+thiscurve=[]
+selectedcurve=0
+phi=3.14159265359
+# events
+App_Evt = 144
+New_Evt = 166
+SelFile_Evt  = 71
+LoadFile_Evt = 72
+SaveFile_Evt = 73
+UseMe_Evt = 74
+No_Evt   = 1
+Btn_Evt  = 2
+Msh_Evt  = 12
+Upd_Evt  = 3
+Rndm_Evt = 4
+Load_Evt = 5
+Sel_Evt  = 6
+Save_Evt = 7
+Rend_Evt = 8
+End_Evt  = 9
+Scrn_Evt = 15
+Im_Evt   = 16
+gt0_Evt  = 20
+gt1_Evt  = 21
+gt2_Evt  = 22
+gt3_Evt  = 23
+gt4_Evt  = 24
+Ipo_Evt  = 17
+New_Ipo_Evt=700
+
+###---------------------------------------------------------------------------
+# menus
+noisetypemenu  = "Noise type: %t|multiFractal %x0|ridgedMFractal %x1|hybridMFractal %x2|heteroTerrain %x3|fBm %x4|turbulence %x5|Voronoi turb. %x6|vlNoise turb. %x7|noise %x8|cellNoise %x9|Marble %x10|lava_multiFractal %x11|slopey_noise %x12|duo_multiFractal %x13|distorted_heteroTerrain %x14|slickRock %x15|terra_turbulence %x16|rocky_fBm %x17|StatsByAlt_Terrain %x18|Double_Terrain %x19|Shattered_hTerrain %x20|vlhTerrain %x21"
+noisebasismenu = "Basis %t|Blender Original%x0|Original Perlin%x1|Improved Perlin%x2|Voronoi_F1%x3|Voronoi_F2%x4|Voronoi_F3%x5|Voronoi_F4%x6|Voronoi_F2-F1%x7|Voronoi Crackle%x8|CellNoise%x9"
+voronitypemenu = "Voronoi type %t|Distance %x0|Distance Squared %x1|Manhattan %x2|Chebychev %x3|Minkovsky 1/2 %x4|Minkovsky 4 %x5|Minkovsky %x6"
+tBasismodemenu = "Terrain basis mode: %t|noise %x0|ridged noise %x1|vlNoise %x2|ridged vlNoise %x3"
+effecttypemenu = ['Effect Type %t','No Effect %x0','Image %x1','Turbulence %x2','vlNoise %x3','Marble %x4', 'multiFractal %x5','ridgedMFractal %x6','hybridMFractal %x7','heteroTerrain %x8','fBm %x9', 'Gradient %x10','Waves and Bumps %x11','ZigZag %x12','Wavy %x13','Sine Bump %x14','Dots %x15','Rings / Dome %x16','Spiral %x17','Square / Piramide %x18','Blocks %x19','Grid %x20','Tech %x21','Crackle %x22','Sparse Cracks %x23','Shattered Rocks %x24','Lunar %x25','Cosine noise %x26','Spike noise %x27','Stone noise %x28','Flat Turb %x29','Flat Voroni %x30','Random noise %x31','Constant %x32','Custom Effect %x33' ]
+mixtypemenu    = ['Mix Type %t','Effect only %x0','%l','Mix %x1','Add %x2','Subtract %x3','Multiply %x4','Difference %x5','Screen %x6','addmodulo %x7','Minimum %x8','Maximum %x9','%l','Warp Effect %x10','Warp Noise %x11']
+biastypemenu   = "Bias %t|Sin bias %x0|Cos bias %x1|Tri bias %x2|Saw bias %x3|Default (no bias)%x4"
+sharptypemenu  = "Sharpen %t|Soft %x0|Sharp %x1|Sharper %x2"
+filtermodemenu = "Filter Mode %t|No Filter %x0| %l|Default Filters %x1|IPOCurve Filter %x2|Custom Filter %x3"
+filtertypemenu = "Filter Type %t|Default Terrace %x0|Sharper Terrace %x1|Rounded Terrace %x2|Posterise Mixed %x3|Posterise %x4|Layered Peaks %x5|Peaked %x6|Smooth-thing %x7|Sin bias %x8|Cos bias %x9|Tri bias %x10|Saw bias %x11|Clamp Max. %x12"
+falloftypemenu = "Edge Falloff %t|No Edge Falloff %x0| %l|Soft Falloff %x1|Default Falloff %x2|Hard Falloff %x3|Linear Falloff Y %x4|Linear Falloff X %x5|Diagonal Falloff + %x6|Diagonal Falloff - %x7|Square %x8|Round %x9"
+randomtypemenu = "Random type: %t|setRandomSeed() : Blender.Noise %x0|Rand() : Blender.Mathutils %x1|genrand() : BPyMathutils MersenneTwister %x2"
+
+##--------------------------------------------------
+def Set_ReSet_Values():
+       global fileinfo, filemessage
+       global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly, WorldSpaceCo
+       global NType, Basis, musgr, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, tBasismod, musgrTwo
+       global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
+       global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, AutoUpd, PreView, DefaultIpoName
+
+       filemessage = ''
+       fileinfo    = ''
+       effect_image = 'Load and Select image.'
+       AutoUpd  = Create( 0 )
+       PreView = [ Create( 0 ), Create( 1.0 ), Create( 0.0 ) ]
+       ## Coords controls:
+       WorldSpaceCo = Create(0)
+       iScale = [ Create( 1.0 ), Create( 1.0 ), Create( 0.25) ]
+       Offset = [ Create( 0.0 ), Create( 0.0), Create( 0.0) ]
+       Invert = [ Create( 0 ), Create( 0 ), Create( 0 ) ]
+       NSize = [ Create( 1.0 ), Create( 2.0 ) ]
+       Sx = [ Create( 1.0 ), Create( 1.0 ) ]
+       Sy = [ Create( 1.0 ), Create( 1.0 ) ]
+       Lx = [ Create( 0.0 ), Create( 0.0 ) ]
+       Ly = [ Create( 0.0 ), Create( 0.0 ) ]
+       ## Noise controls:
+       NType = Create( 3 )
+       Basis = [ Create( 0 ), Create( 0 ) ]
+       musgr = [ Create( 1.0 ), Create( 2.0 ), Create( 8 ), Create( 1.0 ), Create( 1.0 ), Create( 0.5 ) ]
+       vlnoi = [ Create( 1.0 ), Create( 0 ) ]
+       vlnoiTwo = [ Create( 1.0 ), Create( 0 ) ]
+       voron = [ Create( 0 ), Create( 2.5 ) ]
+       turbOne = [ Create( 6 ), Create( 0 ), Create( 0.5 ), Create( 2.0 ) ]
+       marbleOne = [ Create( 6 ), Create( 0 ), Create( 2.0 ), Create( 0 ), Create( 0 ), Create( 1.0 ) ]
+       tBasismod = Create(0)
+       ## Effect controls:
+       musgrTwo = [ Create( 1.0 ), Create( 2.0 ), Create( 8 ), Create( 1.0 ), Create( 1.0 ) ]
+       turbTwo = [ Create( 6 ), Create( 0 ), Create( 0.5 ), Create( 2.0 ) ]
+       marbleTwo = [ Create( 6 ), Create( 0 ), Create( 2.0 ), Create( 0 ), Create( 0 ), Create( 1.0 ) ]
+       Effect_Ctrl = [ Create( 0 ),Create( 2 ),Create( 0.0 ),Create( 0 ),Create( 0.0 ) ,Create( 0 ),Create( 2.0 ),Create( 0.5 ),Create( 0.5 ) ]
+       CustomFX = [ Create('sin(x*pi)'), Create('cos(y*pi)'), Create('abs(a*b)*0.5') ]
+       ## Filter controls:
+       Min = Create( 0.0 )
+       Max = Create( 1.0 )
+       Falloff = [ Create( 2 ), Create( 1.0 ), Create( 1.0 ), Create( 0 ) , Create( 0 ) ]
+       Filter_Mode = Create( 0 )
+       Def_Filter_Ctrl = [ Create( 0 ), Create( 3.0 ) ]
+       Ipo_Filter_Ctrl = [ Create( DefaultIpoName ), Create( 0 ), Create( 100.0 ), Create( 100.0 ) ]
+       Filter_Order =  Create( 0 )
+       CustomFilt = [ Create('sqrt(h*h)**2'), Create('0'), Create('a') ]
+       ## Randomise noise buttons:
+       RandMod = Create( 1 )
+       RSeed   = Create( 0 )
+       rand_I  = Create( 0 )
+       rand_H  = Create( 0 )
+       rand_S  = Create( 0 )
+       rand_L  = Create( 1 )
+
+##-------------------------
+Set_ReSet_Values()
+
+
+####----------------------------------------------------------------------------------------------------
+###----------------------------------------------------------------------------------------------------
+## G.U.I.: text,backpanel,panel
+#--------------------------------------------------
+def draw_Text( ( x, y ), text, color, size ):
+       glColor3f( color[0],color[1],color[2] )
+       glRasterPos2d(x,y)
+       txtsize = 'small', 'normal', 'large'
+       Text( text, txtsize[ size ] )
+def draw_BackPanel( text, x, y, w, h, colors ):
+       glColor3f( colors[0]*0.76, colors[1]*0.76, colors[2]*0.76 )
+       glRecti( x, h, w, h+20 )
+       glColor3f( colors[0], colors[1], colors[2] )
+       glRecti( x, y, w, h )
+       glColor3f( colors[0], colors[1], colors[2] )
+       glRasterPos2d( x+10, h+5 )
+       Text( text, 'small' )
+def draw_Panel( x, y, w, h, colors ):
+       glColor3f( colors[0], colors[1], colors[2] )
+       glRecti( x,y, w,h )
+def draw_Frame( text, x, y, w, h, color ):
+   glColor3f( color[0], color[1], color[2] )
+   glRasterPos2i(x+3,h-3)
+   Text(text ,'small')
+   stringwidth = GetStringWidth( text,'small' )
+   glColor3f( color[0], color[1], color[2]  )
+   glBegin(Blender.BGL.GL_LINE_STRIP)
+   glVertex2i(x,h)
+   glVertex2i(x,y)
+   glVertex2i(w,y)
+   glVertex2i(w,h)
+   glVertex2i(x+stringwidth+10,h)
+   glEnd()
+def draw_Led( x, y, colors ):
+       glColor3f( colors[0], colors[1], colors[2] )
+       glRecti( x,y, x+4,y+4 )
+
+
+###----------------------------------------------------------------------------------------------------
+## G.U.I. Buttons:
+#----------------------------------------------------------------------------------------------------
+
+###-------------------------
+## Main / Mesh Buttons:
+#
+def MeshButtons( col, row, width, height ):
+       global actme, actob, AutoUpd, txtFile, filemessage, fileinfo
+
+       PushButton("I", UseMe_Evt, col[8], row[3], width[0], height[1], "Info: Here you can write some text to save with the file." )
+       draw_Text( ( col[0], row[1]+5 ), 'Info: ' + fileinfo, black, 0 )
+       txtFile = String("",  No_Evt,      col[0], row[2], width[9], height[1],  txtFile.val, 256, "File: Full path and filename" )
+       PushButton( "Select", SelFile_Evt, col[1], row[3], width[0], height[1], "File: Open FileBrowser and select *.ant file" )
+       PushButton( "Load",   LoadFile_Evt,col[2], row[3], width[2], height[1], "File: Load settings from file ( HotKey: L )" )
+       PushButton( "Save",   SaveFile_Evt,col[5], row[3], width[2], height[1], "File: Save settings to file ( HotKey: S )" )
+
+       activeobname = ''
+       if actme !=[]:
+               activeobname = actob[0].name
+       draw_Text( ( col[5]+5, row[7]-5 ), 'OB: ' + activeobname, [0.0,0.0,1.0], 1 )
+       PushButton( "Add New Grid",    New_Evt, col[0], row[6], width[4], height[2] )
+       PushButton( "Assign Selected", App_Evt, col[5], row[6], width[4], height[2], 'Assign selected terrain')
+
+###-------------------------
+## Noise Buttons:
+#
+def NoiseButtons( col, row, width, height ):
+       global NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy, WorldSpaceCo
+       global Ha, La, Oc, Of, Ga, Basis, NType, musgr, vlnoi, voron, turbOne, tBasismod 
+       global Depth, Hard, Amp, Freq, vlBasis, Distort, VFunc, VExp, VDep, marbleOne
+       global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I
+
+       bth = height[1]/2+5
+       iScale[0] = Number("iScale:", Btn_Evt, col[5], row[2]+bth, width[3], height[1], iScale[0].val,   -10.0, 10.0 , "Noise: Intensity Scale." )
+       Invert[0] = Toggle("Inv.",    Btn_Evt, col[9], row[2]+bth, width[0], height[1], Invert[0].val, "Noise: Invert")
+       Offset[0] = Number("Offset:", Btn_Evt, col[5], row[3]+bth, width[4], height[1], Offset[0].val,   -10.0, 10.0 , "Noise: Offset " )
+       NSize[0] = Number("Noise Size:",Btn_Evt, col[5], row[5], width[4], height[2], NSize[0].val, 0.001, 10.0 , "Noise Size" )
+       Sx[0]     = Number("Size X:", Btn_Evt, col[5], row[6], width[4], height[1], Sx[0].val,    0.001, 10.0 , "Size X" )
+       Sy[0]     = Number("Size Y:", Btn_Evt, col[5], row[7], width[4], height[1], Sy[0].val,    0.001, 10.0 , "Size Y" )
+       Lx[0]     = Number("Loc X:",  Btn_Evt, col[5], row[8], width[4], height[1], Lx[0].val,  -10000.0, 10000.0 , "Loc X" )
+       Ly[0]     = Number("Loc Y:",  Btn_Evt, col[5], row[9],width[4], height[1], Ly[0].val,  -10000.0, 10000.0 , "Loc Y" )
+       WorldSpaceCo = Menu( "Coordinates %t|Local Space %x0|World Space %x1|Center at CursorPos %x2", Btn_Evt, col[5], row[10], width[4], height[1], WorldSpaceCo.val, "x,y,z coordinates for noise, effect and height falloff " )
+
+       NType = Menu( noisetypemenu,       Btn_Evt, col[0], row[2], width[4], height[2], NType.val, "Noise type" )
+       if NType.val == 6:
+               voron[0] = Menu( voronitypemenu, Btn_Evt, col[0], row[3], width[4], height[1], voron[0].val, "Voronoi type" )
+       else:
+               if NType.val != 9:
+                       Basis[0] = Menu( noisebasismenu, Btn_Evt, col[0], row[3], width[4], height[1], Basis[0].val, "Noise Basis" )
+
+       if NType.val in [0,1,2,3,4,11,12,13,14,15,17,18,19,20,21]:
+               musgr[0] = Slider( "H: ",          Btn_Evt, col[0], row[5], width[4], height[1], musgr[0].val,  0.0, 3.0, 0 ,  "H" )
+               musgr[1] = Slider( "Lacu: ",       Btn_Evt, col[0], row[6], width[4], height[1], musgr[1].val,  0.0, 6.0, 0 ,  "Lacunarity" )
+               musgr[2] = Slider( "Octs: ",       Btn_Evt, col[0], row[4], width[4], height[1], musgr[2].val,    0, 12,  0 , "Octaves" )
+       if NType.val in [1,2,3,13,14,15,18,19,20,21]:
+               musgr[3] = Slider( "Offst: ",      Btn_Evt, col[0], row[7], width[4], height[1], musgr[3].val,  0.0, 6.0, 0 ,  "Offset" )
+       if NType.val in [1,2,13,15,18]:
+               musgr[4] = Slider( "Gain: ",       Btn_Evt, col[0], row[8], width[4], height[1], musgr[4].val,  0.0, 6.0, 0 ,  "Gain" )
+       if NType.val == 19:
+               musgr[5] = Slider( "Thresh: ",     Btn_Evt, col[0], row[8], width[4], height[1], musgr[5].val,  0.001, 2.0, 0 ,  "Threshold" )
+       if NType.val in [5,6,7,16]:
+               turbOne[0] = Number( "Depth:",     Btn_Evt, col[0], row[4], width[4], height[1], turbOne[0].val, 0, 12, "Octaves")
+               turbOne[1] = Toggle( "Hard noise", Btn_Evt, col[0], row[5], width[4], height[1], turbOne[1].val,        "Soft noise / Hard noise")
+               turbOne[2] = Slider( "Amp:",       Btn_Evt, col[0], row[6], width[4], height[1], turbOne[2].val, 0.0, 3.0, 0, "Ampscale ")
+               turbOne[3] = Slider( "Freq:",      Btn_Evt, col[0], row[7], width[4], height[1], turbOne[3].val, 0.0, 6.0, 0, "Freqscale")
+       if NType.val in [18,19]:
+               tBasismod = Menu( tBasismodemenu,  Btn_Evt, col[0], row[9], width[4], height[1], tBasismod.val, "Terrain basis mode.")
+       if NType.val == 6:
+               if voron[0].val == 6:
+                       voron[1] = Slider( "Exp: ",      Btn_Evt, col[0], row[8], width[4], height[1], voron[1].val, 0.0,10.0, 0, "Minkovsky exponent")
+       if NType.val in [7,11,12,14,20,21]:
+               vlnoi[0] = Slider( "Dist: ",       Btn_Evt, col[0], row[8], width[4], height[1], vlnoi[0].val,  0.0, 10.0, 0 , "Distort" )
+       if NType.val in [7,13,14,15,21]:
+               vlnoi[1] = Menu(noisebasismenu,    Btn_Evt, col[0], row[9], width[4], height[1], vlnoi[1].val, "Distortion Noise")
+       if NType.val == 10:
+               marbleOne[0] = Number(  "Depth: ", Btn_Evt, col[0], row[6], width[4], height[1], marbleOne[0].val, 0, 12, "Octaves")
+               marbleOne[2] = Slider(  "Turb: ",  Btn_Evt, col[0], row[7], width[4], height[1], marbleOne[2].val,  0.0,20.0, 0, "Turbulence ")
+               marbleOne[3] = Menu( biastypemenu, Btn_Evt ,col[0], row[4], width[4], height[1], marbleOne[3].val, "Bias")
+               marbleOne[5] = Slider("ReScale: ", Btn_Evt, col[0], row[8], width[4], height[1], marbleOne[5].val,  0.0,20.0, 0, "ReScale")
+               if marbleOne[3].val != 4:
+                       marbleOne[4] = Menu(sharptypemenu, Btn_Evt ,col[0], row[5], width[4], height[1], marbleOne[4].val, "Sharpen")
+
+       RandMod = Menu( randomtypemenu, No_Evt, col[0], row[10], width[0], height[1], RandMod.val, "Random Type" )
+       rand_H = Toggle("TH",No_Evt ,col[1], row[10], width[0], height[1], rand_H.val, "Randomise Terrain Height ( in Height panel )")
+       rand_I = Toggle("NH",No_Evt ,col[2], row[10], width[0], height[1], rand_I.val, "Randomise Noise Height")
+       rand_S = Toggle("NS",No_Evt ,col[3], row[10], width[0], height[1], rand_S.val, "Randomise Noise Size")
+       rand_L = Toggle("NL",No_Evt ,col[4], row[10], width[0], height[1], rand_L.val, "Randomise Noise Location")
+
+###-------------------------
+## Effect Buttons:
+#
+def EffectButtons( col, row, width, height ):
+       global Effect_Type, Effect_Ctrl, Blend_Effect, CustomFX
+       global NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy
+       global BasisTwo, turbTwo, marbleTwo, vlnoiTwo, musgrTwo
+
+       Effect_Ctrl[0] = Menu( '|'.join( effecttypemenu ), Btn_Evt, col[0], row[2], width[4], height[2], Effect_Ctrl[0].val, "Effect: Type" )
+       if Effect_Ctrl[0].val != 0:
+               Effect_Ctrl[1] = Menu( '|'.join( mixtypemenu ),    Btn_Evt, col[5], row[2], width[4], height[2], Effect_Ctrl[1].val, "Mix: Type" )
+               if Effect_Ctrl[1].val in [10,11]:
+                       Effect_Ctrl[2] = Slider("Warp: ",   Btn_Evt, col[5], row[3], width[4], height[1], Effect_Ctrl[2].val, -1.0, 1.0, 0, "Mix factor / Warp amount" )
+               else: Effect_Ctrl[2] = Slider("Mix: ",Btn_Evt, col[5], row[3], width[4], height[1], Effect_Ctrl[2].val, -1.0, 1.0, 0, "Mix factor / Warp amount" )
+
+               iScale[1] = Number("iScale:",   Btn_Evt, col[5], row[4], width[3], height[1], iScale[1].val,   -20.0, 20.0 , "Effect: Intensity Scale " )
+               Invert[1] = Toggle("Inv.",      Btn_Evt, col[9], row[4], width[0], height[1], Invert[1].val, "Effect: Invert")
+               Offset[1] = Number("Offset:",   Btn_Evt, col[5], row[5], width[4], height[1], Offset[1].val,   -20.0, 20.0 , "Effect: Offset " )
+               NSize[1]  = Number("Frequency:",Btn_Evt, col[5], row[6], width[4], height[1], NSize[1].val, 0.001, 100.0, "Effect Frequency ( Scale )" )
+               Sx[1]     = Number("Freq X:",   Btn_Evt, col[5], row[7], width[4], height[1],  Sx[1].val,    -50.0, 50.0 , "Effect Frequency X ( ScaleX )" )
+               Sy[1]     = Number("Freq Y:",   Btn_Evt, col[5], row[8], width[4], height[1],  Sy[1].val,    -50.0, 50.0 , "Effect Frequency Y ( ScaleY )" )
+               Lx[1]     = Number("Loc X:",    Btn_Evt, col[5], row[9], width[4], height[1],  Lx[1].val, -1000.0, 1000.0 , "Effect Loc X" )
+               Ly[1]     = Number("Loc Y:",    Btn_Evt, col[5], row[10], width[4], height[1], Ly[1].val, -1000.0, 1000.0 , "Effect Loc Y" )
+
+               if Effect_Ctrl[0].val == 1:
+                       PushButton("Load Image",   Load_Evt, col[0], row[4], width[4], height[2] , "Load Image")
+                       PushButton("Select Image", Sel_Evt,  col[0], row[6], width[4], height[3] , "Select Image")
+                       draw_Text( ( col[0]+5, row[7] ), effect_image, black, 1 )
+
+               if Effect_Ctrl[0].val in [2,3,4,5,6,7,8,9]:
+                               Basis[1] = Menu( noisebasismenu,   Btn_Evt, col[0], row[3], width[4], height[1], Basis[1].val, "Basis" )
+
+               if Effect_Ctrl[0].val == 2:
+                               turbTwo[0] = Number(  "Depth:",    Btn_Evt, col[0], row[4], width[4], height[1], turbTwo[0].val, 1, 12, "Octaves")
+                               turbTwo[1] = Toggle("Hard noise",  Btn_Evt, col[0], row[5], width[4], height[1], turbTwo[1].val,        "Hard noise")
+                               turbTwo[2] = Slider(    "Amp:",    Btn_Evt, col[0], row[6], width[4], height[1], turbTwo[2].val, 0.0, 3.0, 0, "Ampscale ")
+                               turbTwo[3] = Slider(   "Freq:",    Btn_Evt, col[0], row[7], width[4], height[1], turbTwo[3].val, 0.0, 6.0, 0, "Freqscale")
+               if Effect_Ctrl[0].val == 3:
+                               vlnoiTwo[1] = Menu(noisebasismenu, Btn_Evt, col[0], row[4], width[4], height[1], vlnoiTwo[1].val, "Distortion Noise")
+                               vlnoiTwo[0] = Slider( "Dist: ",    Btn_Evt, col[0], row[5], width[4], height[1], vlnoiTwo[0].val,  0.0, 10.0, 0 , "Distort" )
+               if Effect_Ctrl[0].val == 4:
+                               marbleTwo[0] = Number(  "Depth: ", Btn_Evt, col[0], row[6], width[4], height[1], marbleTwo[0].val, 1, 12, "Octaves")
+                               marbleTwo[2] = Slider(  "Turb: ",  Btn_Evt, col[0], row[7], width[4], height[1], marbleTwo[2].val,  0.0,20.0, 0, "Turbulence")
+                               marbleTwo[3] = Menu( biastypemenu, Btn_Evt ,col[0], row[4], width[4], height[1], marbleTwo[3].val, "Bias")
+                               marbleTwo[5] = Slider("ReScale: ", Btn_Evt, col[0], row[8], width[4], height[1], marbleTwo[5].val,  0.0,20.0, 0, "ReScale")
+                               if marbleTwo[3].val != 4:
+                                       marbleTwo[4] = Menu(sharptypemenu,Btn_Evt ,col[0], row[5], width[4], height[1], marbleTwo[4].val, "Sharpen")
+
+               if Effect_Ctrl[0].val in [5,6,7,8,9]:
+                       musgrTwo[0] = Slider( "H: ",     Btn_Evt, col[0], row[5], width[4], height[1], musgrTwo[0].val,  0.0, 3.0, 0 ,  "H" )
+                       musgrTwo[1] = Slider( "Lacu: ",  Btn_Evt, col[0], row[6], width[4], height[1], musgrTwo[1].val,  0.0, 6.0, 0 ,  "Lacunarity" )
+                       musgrTwo[2] = Slider( "Octs: ",  Btn_Evt, col[0], row[4], width[4], height[1], musgrTwo[2].val,    0, 12,  0 , "Octaves" )
+               if Effect_Ctrl[0].val in [6,7,8]:
+                       musgrTwo[3] = Slider( "Offst: ", Btn_Evt, col[0], row[7], width[4], height[1], musgrTwo[3].val,  0.0, 6.0, 0 ,  "Offset" )
+               if Effect_Ctrl[0].val in [6,7]:
+                       musgrTwo[4] = Slider( "Gain: ",  Btn_Evt, col[0], row[8], width[4], height[1], musgrTwo[4].val,  0.0, 6.0, 0 ,  "Gain" )
+
+               if Effect_Ctrl[0].val > 9 and Effect_Ctrl[0].val < 31:
+                               Effect_Ctrl[5] = Number("Depth:",  Btn_Evt, col[0], row[4], width[4], height[1], Effect_Ctrl[5].val,   0, 12   ,  "Fractalize Effect: Octaves" )
+                               Effect_Ctrl[4] = Number("Distort:",Btn_Evt, col[0], row[7], width[4], height[1], Effect_Ctrl[4].val, 0.0, 50.0 ,  "Distort Effect: Amount" )
+                               Effect_Ctrl[6] = Slider("Freq:",   Btn_Evt, col[0], row[5], width[4], height[1], Effect_Ctrl[6].val, 0.0, 6.0, 0, "Fractalize Effect: Frequency" )
+                               Effect_Ctrl[7] = Slider("Amp:",    Btn_Evt, col[0], row[6], width[4], height[1], Effect_Ctrl[7].val, 0.0, 3.0, 0, "Fractalize Effect: Amplitude" )
+                               if Effect_Ctrl[0].val < 22:
+                                       Effect_Ctrl[3] = Menu(biastypemenu, Btn_Evt ,col[0], row[3], width[4], height[1], Effect_Ctrl[3].val, "Effect bias")
+               if Effect_Ctrl[0].val in [31,32]:
+                               Effect_Ctrl[8] = Number("Amount:", Btn_Evt, col[0], row[4], width[4], height[1], Effect_Ctrl[8].val, -20.0, 20.0, "Effect: Amount" )
+               if Effect_Ctrl[0].val == 33:
+                       draw_Text( ( col[0]+5, row[4] ), 'Custom math ( h, x,y, a,b )' , black, 0 )
+                       CustomFX[0] = String(      "a = ", Btn_Evt, col[0], row[5], width[4], height[1] ,CustomFX[0].val,96, "a" )
+                       CustomFX[1] = String(      "b = ", Btn_Evt, col[0], row[6], width[4], height[1] ,CustomFX[1].val,96, "b" )
+                       CustomFX[2] = String( "result = ", Btn_Evt, col[0], row[7], width[4], height[1] ,CustomFX[2].val,96, "result" )
+       
+###-------------------------
+## Filter / Height Buttons:
+#
+def FilterButtons( col, row, width, height ):
+       global iScale, Offset, Invert, Min, Max, Falloff, CustomFilt
+       global Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, DefaultIpoName, Filter_Order
+
+       iScale[2] = Number("Height:", Btn_Evt, col[5], row[2], width[3], height[2], iScale[2].val,   -10.0, 10.0 , "Terrain Height:  Scale" )
+       Invert[2] = Toggle("Inv.",    Btn_Evt, col[9], row[2], width[0], height[2], Invert[2].val, "Terrain Height:  Invert")
+       Offset[2] = Number("Offset:", Btn_Evt, col[5], row[3], width[4], height[1], Offset[2].val,   -10.0, 10.0 , "Terrain Height:  Offset" )
+       Max = Number(    "Plateau:",  Btn_Evt, col[5], row[5], width[4], height[1], Max.val, Min.val, 1.0 , "Terrain Height:  Clamp Max. ( Plateau )" )
+       Min = Number(    "Sealevel:", Btn_Evt, col[5], row[6], width[4], height[1], Min.val, -1.0, Max.val , "Terrain Height:  Clamp Min. ( Sealevel )" )
+       Falloff[0] = Menu( falloftypemenu, Btn_Evt ,col[5], row[9], width[4], height[2], Falloff[0].val, "Terrain Height:  Edge falloff")
+       if Falloff[0].val !=0:
+               Falloff[1] = Number("X:",   Btn_Evt, col[5], row[10], width[1], height[1], Falloff[1].val , 0.01, 100.0 , "Edge falloff:  X Size" )             
+               Falloff[2] = Number("Y:",   Btn_Evt, col[8], row[10], width[1], height[1], Falloff[2].val , 0.01, 100.0 , "Edge falloff:  Y Size" )
+               Falloff[4] = Toggle("Inv.", Btn_Evt, col[7], row[10], width[0], height[1], Falloff[4].val, "Edge falloff:  Invert")
+               Falloff[3] = Toggle("Edge At Sealevel", Btn_Evt, col[5], row[7], width[4], height[1], Falloff[3].val, "Edge falloff:  Edge at Sealevel")
+
+       Filter_Mode = Menu( filtermodemenu,               No_Evt, col[0], row[2], width[4], height[2], Filter_Mode.val, "Filter:  Mode")
+       if Filter_Mode.val ==1:
+               Def_Filter_Ctrl[0] = Menu( filtertypemenu,     Btn_Evt, col[0], row[5], width[4], height[2], Def_Filter_Ctrl[0].val, "Filter:  Type")
+               Def_Filter_Ctrl[1] = Number("Amount: ",        Btn_Evt, col[0], row[6], width[4], height[1], Def_Filter_Ctrl[1].val, 0.1, 100.0 , "Filter:  Amount" )
+
+       if Filter_Mode.val ==2:
+               Ipo_Filter_Ctrl[0] = String("IP:",              Ipo_Evt, col[0], row[5], width[4], height[2], Ipo_Filter_Ctrl[0].val,20, "Ipo datablock name" )
+               if Ipo_Filter_Ctrl[0].val !='':
+                       Ipo_Filter_Ctrl[1] = Number("Use This Curve:",Ipo_Evt, col[0], row[7], width[4], height[3], Ipo_Filter_Ctrl[1].val, 0, 29, "Select curve to use" )
+                       Ipo_Filter_Ctrl[2] = Number("Curve Length:",  Ipo_Evt, col[0], row[8], width[4], height[1], Ipo_Filter_Ctrl[2].val, 0.0, 1000.0, "X: Length (number of frames) of the selected curve." )
+                       Ipo_Filter_Ctrl[3] = Number("Curve Height:",  Ipo_Evt, col[0], row[9], width[4], height[1], Ipo_Filter_Ctrl[3].val, 0.0, 1000.0, "Y: Height (offset) of the selected curve." )
+               else:
+                       draw_Text( ( col[0]+5, row[6] ), 'Enter Ipo DataBlock name,' , black, 0 )
+                       draw_Text( ( col[0]+5, row[9] ), 'or else:' , black, 0 )
+               PushButton( "New IpoDataBlock/Object", New_Ipo_Evt, col[0], row[10], width[4], height[1], "Creates new Ipo Object(Empty), and Ipo DataBlock(curves)' to use as height filter")
+
+       if Filter_Mode.val ==3:
+               draw_Text( ( col[0]+5, row[4] ), 'Custom math ( h, x,y, a,b )' , black, 0 )
+               CustomFilt[0] = String(      "a = ", Btn_Evt, col[0], row[5], width[4], height[1] ,CustomFilt[0].val,96, "a" )
+               CustomFilt[1] = String(      "b = ", Btn_Evt, col[0], row[6], width[4], height[1] ,CustomFilt[1].val,96, "b" )
+               CustomFilt[2] = String( "result = ", Btn_Evt, col[0], row[7], width[4], height[1] ,CustomFilt[2].val,96, "result" )
+       if Filter_Mode.val !=0:
+               Filter_Order = Toggle("Change Filter Order",   Btn_Evt, col[0], row[3], width[4], height[1], Filter_Order.val, "Filter Order: OFF = Noise+Effect+Falloff+FILTER / ON = Noise+FILTER+Effect+Falloff.")
+
+###-------------------------
+## Option / Generate Image Buttons:
+#
+def OptionButtons( col, row, width, height ):
+       global PreView, previewname
+
+       PreView[0] = Toggle("Make Image", No_Evt, col[0], row[2], width[4], height[2], PreView[0].val, "Image: On/Off (Make a new Image in UV/ImageEditor Window, and give a name to it)")
+       if PreView[0].val !=0:
+               previewname = String( "IM:", No_Evt, col[0], row[3], width[4], height[1] ,previewname.val, 16, "IM:Name, Render terrain height to this image" )
+               PreView[1] = Number("",      Im_Evt, col[0], row[4], width[1], height[1], PreView[1].val, 0.0, 10.0, "Image: Intensity Scale")
+               PreView[2] = Number("",      Im_Evt, col[3], row[4], width[1], height[1], PreView[2].val,-10.0, 10.0, "Image: Offset")
+               PushButton(   "Draw Image",  Im_Evt, col[0], row[5], width[4], height[1] , "Image: Update image ( KEY: V )")
+               draw_Text( ( col[5], row[1] ), 'Create yourself a new image', black, 0 )
+               draw_Text( ( col[5], row[2] ), 'in UV/Image Editor Window,', black, 0 )
+               draw_Text( ( col[5], row[3] ), 'give it a name,', black, 0 )
+               draw_Text( ( col[5], row[4] ), 'and save it manualy.', black, 0 )
+
+####--------------------------------------------------------------------------
+###--------------------------------------------------------------------------
+## Draw G.U.I. -------------------------------------------------------------
+#--------------------------------------------------------------------------
+def drawgui():
+       global guitabs, ledcolor, FullScreen, AutoUpd, RandMod, RSeed, filemessage
+       global Effect_Ctrl, Filter_Mode, Falloff, PreView, rand_H, rand_S, rand_L, rand_I
+
+       glClearColor(background[0],background[1],background[2],background[3])
+       glClear(GL_COLOR_BUFFER_BIT)
+       scissorbox=Buffer(GL_FLOAT,4)
+       glGetFloatv(GL_SCISSOR_BOX,scissorbox)
+       scissbleft=int(scissorbox[0])
+       scissbbase=int(scissorbox[1])
+       scissbwidth=int(scissorbox[2])
+       scissbheight=int(scissorbox[3])
+       xstart = 5
+       ystart = 5
+       xgap = 5
+       ygap = 5
+       if FullScreen.val==1:
+               guiwidth  = scissbwidth-10
+               guiheight = scissbheight-25
+               if guiwidth < size_x/2:
+                       guiwidth = size_x/2
+               if guiheight < size_y/2:
+                       guiheight = size_y/2
+       else:
+               guiwidth = size_x
+               guiheight = size_y
+       col,row = [],[]
+       xpart = ( ( guiwidth-xstart ) / columns )
+       ypart = ( ( guiheight-ystart ) / rows )
+       width = []
+       for c in xrange( columns ):
+               col.append( xgap + xpart * c + xstart )
+               width.append( xpart*(c+1)-xgap )
+       height = [ (ypart-ygap)/2 , ypart-ygap, (ypart*3-ygap)/2, ypart*2-ygap, (ypart*5-ygap)/2  ]
+       for r in xrange( rows ):
+               row.append( ygap + ypart * r + ystart )
+       row.reverse()
+
+       ###-------------------------
+       ## Draw G.U.I.:
+       draw_BackPanel( 'Another Noise Tool 1.05', xstart, ystart, guiwidth, guiheight + ygap, lightgrey )
+
+       FullScreen = Toggle("", Scrn_Evt, guiwidth-32, guiheight+ygap+3, 15, 15, FullScreen.val ,"FullScreen" )
+       PushButton( "X",         End_Evt, guiwidth-16, guiheight+ygap+3, 15, 15, "Exit" )
+       draw_Text(( guiwidth-(guiwidth/2)-width[0], guiheight+ygap+5 ), filemessage, white, 0 )
+
+       # gui tabs
+       guitabs[0] = Toggle("Main",    gt0_Evt, col[0], row[0], width[1], height[1], guitabs[0].val ,"Main / Mesh settings" )
+       guitabs[1] = Toggle("Noise",   gt1_Evt, col[2], row[0], width[1], height[1], guitabs[1].val ,"Noise settings" )
+       guitabs[2] = Toggle("Effect",  gt2_Evt, col[4], row[0], width[1], height[1], guitabs[2].val ,"Add Effect" )
+       guitabs[3] = Toggle("Height",  gt3_Evt, col[6], row[0], width[1], height[1], guitabs[3].val ,"Height Filter" )
+       guitabs[4] = Toggle("Options", gt4_Evt, col[8], row[0], width[1], height[1], guitabs[4].val ,"Options" )
+
+       if   guitabs[0].val !=0: MeshButtons(   col, row, width, height )
+       elif guitabs[1].val !=0: NoiseButtons(  col, row, width, height )
+       elif guitabs[2].val !=0: EffectButtons( col, row, width, height )
+       elif guitabs[3].val !=0: FilterButtons( col, row, width, height )
+       elif guitabs[4].val !=0: OptionButtons( col, row, width, height )
+       else: # some info
+               draw_Panel(  col[0], row[0]-5, col[9]+width[0], row[10]-10, black )
+               draw_Text( ( col[0]+5, row[1] ), 'Another Noise Tool v.1.05',                     ledcolors[0], 2 )
+               draw_Text( ( col[0]+5, row[2] ), 'by: Jimmy Hazevoet, 01/2005-03/2007',           ledcolors[1], 2 )
+               draw_Text( ( col[0]+5, row[3] ), 'v.1.05: build/tested in: Blender 2.43 (Wndws)', ledcolors[2], 1 )
+               draw_Text( ( col[0]+5, row[4] ), 'HotKeys: ----------------------------',         ledcolors[3], 2 )
+               draw_Text( ( col[0]+5, row[5] ), 'Space = Update mesh',                           ledcolors[4], 2 )
+               draw_Text( ( col[0]+5, row[6] ), 'V = Update Image',                              ledcolors[5], 2 )
+               draw_Text( ( col[0]+5, row[7] ), 'R = Randomise',                                 ledcolors[6], 2 )
+               draw_Text( ( col[0]+5, row[8] ), 'L = Load from file',                            ledcolors[7], 2 )
+               draw_Text( ( col[0]+5, row[9] ), 'S = Save to file',                              ledcolors[8], 2 )
+               draw_Text( ( col[0]+5, row[10] ),'Q = Quit',                                      ledcolors[9], 2 )
+
+       # auto/generate/randomise buttons
+       rand_on_off = 0
+       if rand_H.val !=0:   rand_on_off = 1
+       elif rand_I.val !=0: rand_on_off = 1
+       elif rand_S.val !=0: rand_on_off = 1
+       elif rand_L.val !=0: rand_on_off = 1
+       else:                rand_on_off = 0
+       if rand_on_off != 0:
+               if RandMod.val in [1,2]:
+                       PushButton(     "Randomise", Rndm_Evt, col[2], row[12], width[2], height[2] , "Randomise Noise ( KEY: R )")
+               else: RSeed     = Number("Seed: ", Rndm_Evt, col[2], row[12], width[2], height[2], RSeed.val,  0, 255 , "Random Seed: If seed = 0, the current time will be used as seed." )
+               AutoUpd = Toggle("Auto", No_Evt, col[0], row[12], width[1], height[2], AutoUpd.val ,"Automatic update" )
+               PushButton("Update", Upd_Evt, col[5], row[12], width[4], height[2] , "Generate / Update. ( KEY: SPACE )")
+       else:
+               AutoUpd = Toggle("Auto", No_Evt, col[0], row[12], width[1], height[2], AutoUpd.val ,"Automatic update" )
+               PushButton("Update", Upd_Evt, col[2], row[12], width[7], height[2] , "Generate / Update. ( KEY: SPACE )")
+               ####---------------------------------------------------------------------------
+
+###---------------------------------------------------------------------------
+##---------------------------------------------------------------------------
+# Key Events:
+
+def events(evt, val):
+       global PreView, txtFile, AutoUpd, PreView
+
+       ## hotkey: Q = Quit
+       if (evt == QKEY and not val):
+               name = "Quit ?%t|No %x0|Yes %x1"
+               result = Blender.Draw.PupMenu(name)
+               if result==1:
+                       Exit()
+
+       ## hotkey: Space = Generate/Update terrain
+       if (evt == SPACEKEY and not val):
+               do_it()
+
+       ## hotkey: R = Randomise noise
+       if (evt in [ RKEY ] and not val):
+               if AutoUpd.val != 0:
+                       do_it_random()
+               else:
+                       randomiseNoise()
+                       Draw()
+
+       ## hotkey: V = Update image
+       if PreView[0].val != 0:
+               if (evt in [ VKEY, RKEY ] and not val):
+                       do_it_preview()
+
+       ## hotkey: L = Load from file
+       if (evt == LKEY and not val):
+               loadmenu = "Load file ?%t|" + txtFile.val
+               loadresult = Blender.Draw.PupMenu(loadmenu)
+               if loadresult==1:
+                       LoadPreset(txtFile.val)
+                       if AutoUpd.val != 0:
+                               do_it()
+                       else: Draw()
+
+       ## hotkey: S = Save to file
+       if (evt == SKEY and not val):
+               savemenu = "Save file ?%t|" + txtFile.val
+               saveresult = Blender.Draw.PupMenu(savemenu)
+               if saveresult==1:
+                       SavePreset(txtFile.val)
+                       Draw()
+
+###---------------------------------------------------------------------------
+##---------------------------------------------------------------------------
+# Button events:
+
+def bevents(evt):
+       global txtFile, effect_image, PreView, fileinfo, filemessage
+       global Filter_Mode, Ipo_Filter_Ctrl, iponame, thiscurve, selectedcurve
+       global antfilename, terrainname
+       global actob, actme
+
+       # quit/reset event
+       if (evt == End_Evt ):
+               name = "OK ?%t|Reset %x1|Quit %x2"
+               result = Blender.Draw.PupMenu(name)
+               if result==1:
+                       Set_ReSet_Values()
+                       Draw()
+               elif result==2:
+                       Exit()
+
+       ## file info string  event
+       if (evt == UseMe_Evt ):
+               result = Blender.Draw.PupStrInput("Info:  ", fileinfo, 96)
+               if result:
+                       fileinfo = result
+                       Draw()
+               else: return
+
+       ## none event
+       if (evt in [No_Evt, Scrn_Evt] ):
+               Draw()
+
+       ## image event
+       if (evt == Im_Evt ):
+               do_it_preview()
+
+       ## generate/update event
+       if (evt == Upd_Evt ):
+               if PreView[0].val != 0:
+                       do_it_preview()
+               do_it()
+
+       ## mesh button event
+       if (evt == Msh_Evt):
+               if AutoUpd.val != 0:
+                       do_it()
+               else: Draw()
+
+       ## button event
+       if (evt == Btn_Evt ):
+               if AutoUpd.val != 0:
+                       if PreView[0].val != 0:
+                               do_it_preview()
+                       do_it()
+               else: Draw()
+
+       ## randomise event
+       if (evt == Rndm_Evt ):
+               if AutoUpd.val != 0:
+                       do_it_random()
+               else:
+                       randomiseNoise()
+                       if PreView[0].val != 0:
+                               do_it_preview()
+                       Draw()
+
+       ###---------------------------------------------------------
+       ## Effect Image Load/Select:
+       if (evt == Load_Evt ):
+               Blender.Window.FileSelector ( load_image, 'LOAD IMAGE')
+       if (evt == Sel_Evt ):
+               try: effect_image = Image_Menu()
+               except: pass
+               if AutoUpd.val != 0:
+                       do_it()
+               else: Draw()
+
+       ###---------------------------------------------------------
+       ## Make New IPOCurve to use as Filter:
+       if (evt == New_Ipo_Evt ):
+               objname = Create("ANT_Ipo_Empty")
+               iponame = Create("ANT_IPO")
+               block = []
+               block.append("Enter new names")
+               block.append("and hit OK button")
+               block.append(("OB: ", objname, 0, 30, "New Ipo Object Name. (Object type = 'Empty')"))
+               block.append(("IP: ", iponame, 0, 30, "New Ipo DataBlock Name"))
+               block.append("Open IpoCurveEditor")
+               block.append("select Ipo DataBlock" )
+               block.append("'Pin' the view" )
+               block.append("and edit the curves." )
+               retval = PupBlock("Make A.N.T. IpoCurve Object", block)
+               if retval !=0:
+                       ANTAutoIpo(  objname.val, iponame.val )
+                       Ipo_Filter_Ctrl[0].val = iponame.val
+
+       ###---------------------------------------------------------
+       ## get IPOCurve to use as Filter:
+       if (evt in [Ipo_Evt, New_Ipo_Evt] ):
+               if Filter_Mode.val == 2:
+                       if AutoUpd.val != 0:                            
+                               try:
+                                       ipoblockname  = Ipo.Get( Ipo_Filter_Ctrl[0].val )
+                                       thiscurve     = ipoblockname.getCurves()
+                                       selectedcurve = thiscurve[ Ipo_Filter_Ctrl[1].val ]
+                                       if PreView[0].val != 0:
+                                               do_it_preview()
+                                       #if AutoUpd.val != 0:
+                                       do_it()
+                               except: pass
+                       else:
+                                       try:
+                                               ipoblockname  = Ipo.Get( Ipo_Filter_Ctrl[0].val )
+                                               thiscurve     = ipoblockname.getCurves()
+                                               selectedcurve = thiscurve[ Ipo_Filter_Ctrl[1].val ]
+                                               if PreView[0].val != 0:
+                                                       do_it_preview()
+                                               else:
+                                                       Draw()
+                                       except: pass
+
+       ###---------------------------------------------------------
+       ## gui tabs
+       if (evt == gt0_Evt ):
+               if guitabs[0].val == 1:
+                       guitabs[1].val = ( 0 )
+                       guitabs[2].val = ( 0 )
+                       guitabs[3].val = ( 0 )
+                       guitabs[4].val = ( 0 )
+               Draw()
+       if (evt == gt1_Evt ):
+               if guitabs[1].val == 1:
+                       guitabs[0].val = ( 0 )
+                       guitabs[2].val = ( 0 )
+                       guitabs[3].val = ( 0 )
+                       guitabs[4].val = ( 0 )
+               Draw()
+       if (evt == gt2_Evt ):
+               if guitabs[2].val == 1:
+                       guitabs[0].val = ( 0 )
+                       guitabs[1].val = ( 0 )
+                       guitabs[3].val = ( 0 )
+                       guitabs[4].val = ( 0 )
+               Draw()
+       if (evt == gt3_Evt ):
+               if guitabs[3].val == 1:
+                       guitabs[0].val = ( 0 )
+                       guitabs[1].val = ( 0 )
+                       guitabs[2].val = ( 0 )
+                       guitabs[4].val = ( 0 )
+               Draw()
+       if (evt == gt4_Evt ):
+               if guitabs[4].val == 1:
+                       guitabs[0].val = ( 0 )
+                       guitabs[1].val = ( 0 )
+                       guitabs[2].val = ( 0 )
+                       guitabs[3].val = ( 0 )
+               Draw()
+
+       ###---------------------------------------------------------
+       ## load and save all settings:
+       if (evt == SelFile_Evt ):
+               Blender.Window.FileSelector ( callback, "Select .ant File")
+       if (evt == LoadFile_Evt ):
+               loadmenu = "Load file ?%t|" + txtFile.val
+               loadresult = Blender.Draw.PupMenu(loadmenu)
+               if loadresult==1:
+                       LoadPreset(txtFile.val)
+                       Draw()
+                       if AutoUpd.val != 0:
+                               do_it()
+       if (evt == SaveFile_Evt ):
+               savemenu = "Save file ?%t|" + txtFile.val
+               saveresult = Blender.Draw.PupMenu(savemenu)
+               if saveresult==1:
+                       SavePreset(txtFile.val)
+                       Draw()
+
+       ###---------------------------------------------------------
+       # New Grid
+       ###-------------------------
+       if (evt == New_Evt):
+               scn = Blender.Scene.GetCurrent()
+               gridname = Create("Terrain")
+               gridres = Create(256)
+               curspos = Create(0)
+               block = []
+               block.append(("OB: ", gridname, 0, 30, "New Object Name."))
+               block.append(("Resol: ", gridres, 4, 1024, "New grid resolution"))
+               block.append(("At Cursor", curspos, "New grid at cursor position"))                     
+               retval = PupBlock("New Grid Mesh", block)
+               if retval !=0:
+                       MakeGridMesh( gridres.val, gridname.val, curspos.val, scn )
+                       obj = scn.objects.active
+                       if obj.type == 'Mesh':
+                               actob=[]
+                               actme=[]                
+                               actob.append( obj )
+                               actme.append( actob[0].getData(mesh=1) )
+                               Blender.Redraw()
+
+       ###---------------------------------------------------------
+       # Assign Grid
+       ###-------------------------
+       if (evt == App_Evt):
+               scn = Blender.Scene.GetCurrent()
+               obj = scn.objects.active
+               if obj:
+                       if obj.type == 'Mesh':
+                               actob=[]
+                               actme=[]                
+                               actob.append( obj )
+                               actme.append( actob[0].getData(mesh=1) )
+                               Draw()
+
+       ###-------------------------
+       if (evt not in [LoadFile_Evt,SaveFile_Evt] ):
+               filemessage = ''
+               #Draw()
+
+       ### end events. -------------------------
+
+####-------------------------------------------------------------------------------------
+###-------------------------------------------------------------------------------------
+##-------------------------------------------------------------------------------------
+#-------------------------------------------------------------------------------------
+
+##----------------------------------
+# A.N.T. Auto Ipo generator:
+def ANTAutoIpo( objname, iponame ):
+       scn=Scene.GetCurrent()
+       # Deselect all objects:
+       scn.objects.selected=[]
+       # Create new 'ANT_IPO_OBJECT':
+       obj = scn.objects.new('Empty', objname )
+       obj.setDrawMode(8)
+       obj.select(1)
+       obj.layers = Window.ViewLayers()
+       # Set current frame at 1:
+       frame = Get('curframe')
+       if frame !=1:
+               Set('curframe',1)
+               frame = Get('curframe')
+       # Insert IpoKeys:
+       obj.setLocation(0.0, 0.0, 0.0)
+       obj.insertIpoKey(0)
+       Set('curframe',101)
+       obj.setLocation(100.0, 100.0, 100.0)
+       obj.insertIpoKey(0)
+       Set('curframe',1)
+       # Set Ipo name:
+       ip = obj.getIpo()
+       ip.name = iponame
+       #-------------------------
+       print "New ANT_IPO: " + objname +" (Object) and " + iponame + " (Ipo DataBlock) Created!"
+       #-------------------------
+
+##-------------------------------------------------------------------------------------
+
+##-------------------------
+# Generate random numbers:
+def randnum(low,high):
+       global RandMod, RSeed
+       if RandMod.val == 0:
+               # Noise.random setRandomSeed
+               s = Noise.setRandomSeed( RSeed.val )
+               num = Noise.random()
+               num = num*(high-low)
+               num = num+low
+       elif RandMod.val == 1:
+               # Mathutils.Rand
+               num = Mathutils.Rand(low,high)
+       else:
+               # BPyMathutils  Mersenne Twister genrand
+               num = genrand()
+               num = num*(high-low)
+               num = num+low
+       return num
+
+##-------------------------
+# Randomise noise: height, size and location:
+def randomiseNoise():
+       global rand_I, rand_H, rand_S, rand_L, NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy
+
+       if rand_I.val !=0:
+               iScale[0] = Create( randnum( 0.2  , 3.0 ) )
+               Offset[0] = Create( randnum(-1.0 , 1.0 ) )
+       if rand_H.val !=0:
+               iScale[2] = Create( randnum( 0.10  , 1.0 ) )
+               Offset[2] = Create( randnum(-0.25 , 0.25 ) )
+       if rand_S.val !=0:
+               NSize[0]  = Create( randnum( 0.25 , 2.5 ) )
+               #Sx[0]     = Create( randnum( 0.5 , 1.5 ) )
+               #Sy[0]     = Create( randnum( 0.5 , 1.5 ) )
+       if rand_L.val !=0:
+               Lx[0]     = Create( randnum( -10000 , 10000 ) )
+               Ly[0]     = Create( randnum( -10000 , 10000 ) )
+
+##-------------------------------------------------------------------------------------
+
+###--------------------------
+# Load Image:
+def load_image( ImageFileName ):
+       Image.Load( ImageFileName )
+
+###--------------------------
+# Select Image Menu:
+def Image_Menu():
+       try:
+               names=[]
+               imagelist = Image.Get()
+               imagelist.reverse()
+               for numbers, obnames in enumerate( imagelist ):
+                       n = obnames.getName()
+                       names.append( n )
+               imlistText = string.join( [ '|' + str(names[key]) + '%x' + str(key)  for key in xrange(numbers+1) ], '' )
+               image_menu = Blender.Draw.PupMenu( "Images: %t" + imlistText )
+               if image_menu == -1:
+                       return ''
+               return imagelist[ image_menu ].getName()
+       except:
+               return 'No image found!'
+
+###--------------------------
+# Get Image Pixels:
+def Image_Func( x,y ):
+       try:
+               pic  = Image.Get( effect_image )
+       except:
+               return 0.0
+       w, h = pic.getSize()
+       x, y = x,-y
+       x = int(w * ((x + 1.0) % 2.0) / 2.0)
+       y = int((h-1) - h * ((y + 1.0) % 2.0) / 2.0)    
+       c = pic.getPixelF( x,y )
+       return ( c[0] + c[1] + c[2] ) / 3.0
+
+##-------------------------------------------------------------------------------------
+
+# Transpose noise coords:
+def Trans((x,y,z), size, loc  ):
+       x = ( x / size[1] / size[0] + loc[0] )
+       y = ( y / size[2] / size[0] + loc[1] )
+       z = 0.0 #( z / size[3] / size[0] + loc[2] )
+       return x,y,z
+
+# Transpose effect coords:
+def Trans_Effect((x,y,z), size, loc  ):
+       x = ( x * size[1] * size[0] + loc[0] )
+       y = ( y * size[2] * size[0] + loc[1] )
+       z = 0.0
+       return x,y,z
+
+# Height scale:
+def HeightScale( input, iscale, offset, invert ):
+       if invert !=0:
+               return (1.0-input) * iscale + offset
+       else:
+               return input * iscale + offset
+
+# dist.
+def Dist(x,y):
+       return sqrt( (x*x)+(y*y) )
+
+##-----------------------------------
+# bias types:
+def no_bias(a):
+       return a
+def sin_bias(a):
+       return 0.5 + 0.5 * sin(a)
+def cos_bias(a):
+       return 0.5 + 0.5 * cos(a)
+def tri_bias(a):
+       b = 2 * phi
+       a = 1 - 2 * abs(floor((a * (1/b))+0.5) - (a*(1/b)))
+       return a
+def saw_bias(a):
+       b = 2 * phi
+       n = int(a/b)
+       a -= n * b
+       if a < 0: a += b
+       return a / b
+# sharpen types:
+def soft(a):
+       return a
+def sharp(a):
+       return a**0.5
+def sharper(a):
+       return sharp(sharp(a))
+Bias_Types  = [ sin_bias, cos_bias, tri_bias, saw_bias, no_bias ]
+Sharp_Types = [ soft, sharp, sharper ]
+
+##-----------------------------------
+# clamp height
+def clamp( height, min, max ):
+       if ( height < min ): height = min
+       if ( height > max ): height = max
+       return height
+
+##-----------------------------------
+# Mix modes
+def maximum( a, b ):
+       if ( a > b ): b = a
+       return b
+def minimum( a, b ):
+       if ( a < b ): b = a
+       return b
+
+def Mix_Modes( (i,j),(x,y,z) , a,b, mixfactor, mode ):
+       a = a * ( 1.0 - mixfactor )
+       b = b * ( 1.0 + mixfactor )
+       if   mode == 0:  return  ( b )                     #0  effect only
+       elif mode == 1:  return  ( a*(1.0-0.5) + (b*0.5) ) #1  mix
+       elif mode == 2:  return  ( a + b )                 #2  add
+       elif mode == 3:  return  ( a - b )                 #3  sub.
+       elif mode == 4:  return  ( a * b )                 #4  mult.
+       elif mode == 5:  return  (abs( a - b ))            #5  abs diff.
+       elif mode == 6:  return  1.0-((1.0-a)*(1.0-b)/1.0) #6  screen
+       elif mode == 7:  return  ( a + b ) % 1.0           #7  addmodulo
+       elif mode == 8:  return  min( a, b )           #8  min.
+       elif mode == 9:  return  max( a, b )           #9  max.
+       elif mode == 10:                                   #10 warp: effect
+               noise =  mixfactor * Noise_Function(x,y,z)
+               return    Effects( (i,j),(x+noise,y+noise,z) )
+       elif mode == 11:                                   #11 warp: noise
+               effect = mixfactor * Effects( (i,j),(x,y,z) )
+               return   Noise_Function( x+effect, y+effect, z )
+       else: return a
+
+###----------------------------------------------------------------------
+# Effect functions:
+
+# Effect_Basis_Function:
+def Effect_Basis_Function((x,y), type, bias ):
+
+       iscale = 1.0
+       offset = 0.0
+       ## gradient:
+       if type == 0:
+               effect = offset + iscale * ( Bias_Types[ bias ]( x + y ) )
+       ## waves / bumps:
+       if type == 1:
+               effect = offset + iscale * 0.5 * ( Bias_Types[ bias ]( x*phi ) + Bias_Types[ bias ]( y*phi ) )
+       ## zigzag:
+       if type == 2:
+               effect = offset + iscale * Bias_Types[ bias ]( offset + iscale * sin( x*phi + sin( y*phi ) ) )
+       ## wavy:        
+       if type == 3:
+               effect = offset + iscale * ( Bias_Types[ bias ]( cos( x ) + sin( y ) + cos( x*2+y*2 ) - sin( -x*4+y*4) ) )
+       ## sine bump:   
+       if type == 4:
+               effect =   offset + iscale * 1-Bias_Types[ bias ](( sin( x*phi ) + sin( y*phi ) ))
+       ## dots:
+       if type == 5:
+               effect = offset + iscale * ( Bias_Types[ bias ](x*phi*2) * Bias_Types[ bias ](y*phi*2) )-0.5
+       ## rings / dome:
+       if type == 6:
+               effect = offset + iscale * ( Bias_Types[ bias ]( 1.0-(x*x+y*y) ) )
+       ## spiral:
+       if type == 7:
+               effect = offset + iscale * Bias_Types[ bias ](( x*sin( x*x+y*y ) + y*cos( x*x+y*y ) ))*0.5
+       ## square / piramide:
+       if type == 8:
+               effect = offset + iscale * Bias_Types[ bias ](1.0-sqrt( (x*x)**10 + (y*y)**10 )**0.1)
+       ## blocks:      
+       if type == 9:
+               effect = ( 0.5-max( Bias_Types[ bias ](x*phi) , Bias_Types[ bias ](y*phi) ))
+               if effect > 0.0: effect = 1.0
+               effect = offset + iscale * effect
+       ## grid:        
+       if type == 10:
+               effect = ( 0.025-min( Bias_Types[ bias ](x*phi) , Bias_Types[ bias ](y*phi) ))
+               if effect > 0.0: effect = 1.0
+               effect = offset + iscale * effect
+       ## tech:
+       if type == 11:
+               a = ( max( Bias_Types[ bias ](x*pi) , Bias_Types[ bias ](y*pi) ))
+               b = ( max( Bias_Types[ bias ](x*pi*2+2) , Bias_Types[ bias ](y*pi*2+2) ))
+               effect = ( min( Bias_Types[ bias ](a) , Bias_Types[ bias ](b) ))*3.0-2.0
+               if effect > 0.5: effect = 1.0
+               effect = offset + iscale * effect
+
+       ## crackle:     
+       if type == 12:
+               t = turbulence(( x, y, 0 ), 6, 0, 0 ) * 0.25
+               effect = vlNoise(( x, y, t ), 0.25, 0, 8 )
+               if effect > 0.5: effect = 0.5
+               effect = offset + iscale * ( effect )
+       ## sparse cracks noise:
+       if type == 13:
+               effect = 2.5 * abs( noise((x*0.5,y*0.5, 0 ), 1 ) )-0.1
+               if effect > 0.25: effect = 0.25
+               effect = offset + iscale * ( effect * 2.5 )
+       ## shattered rock noise:
+       if type == 14:
+               effect = 0.5 + noise((x,y,0), 7 )
+               if effect > 0.75: effect = 0.75
+               effect = offset + iscale * effect
+       ## lunar noise:
+       if type == 15:
+               effect = 0.25 + 1.5 * voronoi(( x+2, y+2, 0 ), 1 )[0][0]
+               if effect > 0.5: effect = 0.5
+               effect = offset + iscale * ( effect * 2.0 )
+       ## cosine noise:
+       if type == 16:
+               effect = cos( 5*noise(( x, y, 0 ), 0 ) )
+               effect = offset + iscale * ( effect*0.5 )
+       ## spikey noise:
+       if type == 17:
+               n = 0.5 + 0.5 * turbulence(( x*5, y*5, 0 ), 8, 0, 0 )
+               effect = ( ( n*n )**5 )
+               effect = offset + iscale * effect
+       ## stone noise:
+       if type == 18:
+               effect = offset + iscale *( noise((x*2,y*2, 0 ), 0 ) * 1.5 - 0.75)
+       ## Flat Turb:
+       if type == 19:
+               t = turbulence(( x, y, 0 ), 6, 0, 0 )
+               effect = t*2.0
+               if effect > 0.25: effect = 0.25
+               effect = offset + iscale * ( effect )
+       ## Flat Voroni:
+       if type == 20:
+               t = 1-noise(( x, y, 0 ), 3 )
+               effect = t*2-1.75
+               if effect > 0.25: effect = 0.25
+               effect = offset + iscale * ( effect )
+
+       if effect < 0.0: effect = 0.0
+       return effect
+
+# fractalize Effect_Basis_Function: ------------------------------ 
+def Effect_Function((x,y), type,bias, turb, depth,frequency,amplitude ):
+
+       ## effect distortion:
+       if turb != 0.0:
+               t =  vTurbulence(( x, y, 0 ), 6, 0, 0 )
+               x = x + ( 0.5 + 0.5 * t[0] ) * turb
+               y = y + ( 0.5 + 0.5 * t[1] ) * turb
+
+       result = Effect_Basis_Function((x,y), type, bias )
+       ## fractalize effect:
+       if depth != 0:
+               i=0
+               while i < depth:
+                       i+=1
+                       x *= frequency
+                       y *= frequency
+                       amplitude = amplitude / i
+                       result += Effect_Basis_Function( (x,y), type, bias ) * amplitude
+       return result
+
+###--------------------------------------------------
+# Custom effect:
+def CustomEffect( x,y,z,h ):
+       global CustomFX
+       try:
+               a = eval( CustomFX[0].val )
+               b = eval( CustomFX[1].val )
+               result = eval( CustomFX[2].val )
+               return result
+       except:
+               return 0.0
+
+###--------------------------------------------------
+## Effect Selector:
+
+def Effects( (i,j),(x,y,z), h=0.0 ):
+       global Effect_Type, Effect_Ctrl, iScale, Offset, Invert
+       global NSize, Lx, Ly, Lz, Sx, Sy, Sz, marbleTwo, turbTwo, vlnoiTwo, Basis, musgrTwo
+
+       x,y,z = Trans_Effect((x,y,z),( NSize[1].val, Sx[1].val, Sy[1].val, 0 ),( Lx[1].val, Ly[1].val, 0 )  )
+       basis = Basis[1].val
+       if basis == 9: basis = 14
+       vbasis = vlnoiTwo[1].val
+       if vbasis == 9: vbasis = 14
+       if Effect_Ctrl[0].val == 1:
+               try: effect  = Image_Func( x,y )
+               except: effect =        0.0
+       elif Effect_Ctrl[0].val == 2: effect = 0.5+0.5*turbulence(( x,y,z ),turbTwo[0].val, turbTwo[1].val, basis, turbTwo[2].val, turbTwo[3].val )
+       elif Effect_Ctrl[0].val == 3: effect = 0.5+0.5*vlNoise(( x,y,z ),vlnoiTwo[0].val, vbasis, basis )
+       elif Effect_Ctrl[0].val == 4: effect = 0.5*marbleNoise((x,y,z), marbleTwo[0].val, basis, marbleTwo[2].val, marbleTwo[3].val, marbleTwo[4].val, marbleTwo[5].val )
+       elif Effect_Ctrl[0].val == 5:   effect = 0.5*multiFractal((   x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, basis )
+       elif Effect_Ctrl[0].val == 6:   effect = 0.5*ridgedMFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, musgrTwo[4].val, basis )
+       elif Effect_Ctrl[0].val == 7:   effect = 0.5*hybridMFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, musgrTwo[4].val, basis )
+       elif Effect_Ctrl[0].val == 8:   effect = 0.5*heteroTerrain((  x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, basis )*0.5
+       elif Effect_Ctrl[0].val == 9:   effect = 0.5*fBm((            x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, basis )+0.5
+       elif Effect_Ctrl[0].val > 9 and Effect_Ctrl[0].val < 31:
+               effect = Effect_Function((x,y), Effect_Ctrl[0].val-10,  Effect_Ctrl[3].val,  Effect_Ctrl[4].val,  Effect_Ctrl[5].val,  Effect_Ctrl[6].val, Effect_Ctrl[7].val )
+       elif Effect_Ctrl[0].val == 31: effect = Effect_Ctrl[8].val * random()
+       elif Effect_Ctrl[0].val == 32: effect = Effect_Ctrl[8].val
+       elif Effect_Ctrl[0].val == 33: effect = CustomEffect( x,y,z, h )
+       effect = HeightScale( effect, iScale[1].val , Offset[1].val, Invert[1].val )
+       return  effect*2.0
+
+###----------------------------------------------------------------------
+# Noise:
+##-----------------------------------
+
+## voronoi_turbulence:
+def voroTurbMode((x,y,z), voro, mode ):
+       if mode == 0: # soft
+               return voronoi(( x,y,z ),voro[0], voro[1] )[0][0]
+       if mode == 1: # hard
+               return ( abs( 0.5-voronoi(( x,y,z ),voro[0], voro[1] )[0][0] ) )+0.5
+def voronoi_turbulence((x,y,z), voro, tur ):
+       result = voroTurbMode((x,y,z), voro, tur[1] )
+       depth  = tur[0]
+       amp    = tur[2]
+       freq   = tur[3]
+       i=0
+       for i in xrange( depth ):
+               i+=1
+               result += voroTurbMode( ( x*(freq*i), y*(freq*i), z ), voro, tur[1] )* ( amp*0.5/i )
+       return (result*4.0-2.0)
+
+## DistortedNoise / vlNoise_turbulence:
+def vlnTurbMode((x,y,z), vlno, basis, mode ):
+       if mode == 0: # soft
+               return vlNoise(( x,y,z ),vlno[0], vlno[1], basis )
+       if mode == 1: # hard
+               return ( abs( -vlNoise(( x,y,z ),vlno[0], vlno[1], basis ) ) )
+def vlNoise_turbulence((x,y,z), vlno, tur, basis ):
+       result = vlnTurbMode((x,y,z), vlno, basis, tur[1] )
+       depth  = tur[0]
+       amp    = tur[2]
+       freq   = tur[3]
+       i=0
+       for i in xrange( depth ):
+               i+=1
+               result += vlnTurbMode( ( x*(freq*i), y*(freq*i), z ), vlno, basis, tur[1] ) * ( amp*0.5/i )
+       return result*2.0+0.5
+
+## marbleNoise:
+def marbleNoise( (x,y,z), depth, basis, turb, bias, sharpnes, rescale ):
+       m = ( x * rescale + y * rescale + z ) * 5
+       height = m + turb * turbulence( ( x ,y ,z ), depth, 0, basis, 0.5, 2.0 )
+       height = Bias_Types[ bias ]( height )
+       if bias != 4:
+               height = Sharp_Types[ sharpnes ]( height )
+       return height*2.0
+
+## lava_multiFractal:
+def lava_multiFractal( ( x,y,z ),Ha, La, Oc, distort, Basis ):
+       m  = multiFractal( ( x,y,z ), Ha, La, Oc, Basis)
+       d = m * distort
+       m2 = 0.5 * multiFractal( ( x+d,y+d,d*0.5 ), Ha, La, Oc, Basis)
+       return (m * m2)**0.5
+
+## slopey_noise:
+def slopey_noise((x,y,z), H, lacunarity, octaves, distort, basis ):
+       x=x*2
+       y=y*2
+       turb = fBm((x,y,z), H, lacunarity, octaves, 2 ) * 0.5
+       map = 0.5 + noise( ( x+turb, y+turb, z ), basis )
+       result = map + turb * distort
+       return result
+
+## duo_multiFractal:
+def double_multiFractal((x,y,z), H, lacunarity, octaves, offset, gain, basis ):
+       n1 = multiFractal( (x*1.5+1,y*1.5+1,z), 1.0, 1.0, 1.0, basis[0] ) * offset
+       n2 = multiFractal( (x-1,y-1,z), H, lacunarity, octaves, basis[1] ) * gain
+       result = ( n1*n1 + n2*n2 )*0.5
+       return result
+
+## distorted_heteroTerrain:
+def distorted_heteroTerrain((x,y,z), H, lacunarity, octaves, offset, distort, basis ):
+       h1 = ( heteroTerrain((x,y,z), 1.0, 2.0, 1.0, 1.0, basis[0] ) * 0.5 )
+       h2 = ( heteroTerrain(( x, y, h1*distort ), H, lacunarity, octaves, offset, basis[1] ) * 0.25 )
+       result = ( h1*h1 + h2*h2 )
+       return  result
+
+## SlickRock:
+def SlickRock((x,y,z), H, lacunarity, octaves, offset, gain, basis ):
+       n = multiFractal( (x,y,z), 1.0, 2.0, 1.0, basis[0] )
+       r = ridgedMFractal((x,y,n*0.5), H, lacunarity, octaves, offset, gain, basis[1] )*0.5
+       return n+(n*r)
+
+## terra_turbulence:
+def terra_turbulence((x,y,z), depth, hard, basis, amp, freq ):
+       t2 = turbulence( ( x, y, z ), depth,  hard , basis, amp, freq )
+       return (t2*t2*t2)+0.5
+
+## rocky_fBm:
+def rocky_fBm((x,y,z), H, lacunarity, octaves, basis ):
+       turb = fBm((x,y,z), H, lacunarity, octaves, 2 ) * 0.25
+       coords = ( x+turb, y+turb, z )
+       map = noise( coords, 7 )
+       result = map + fBm( coords, H, lacunarity, octaves, basis ) + 1.0
+       return result
+
+## Shattered_hTerrain:
+def Shattered_hTerrain((x,y,z), H, lacunarity, octaves, offset, distort, basis ):
+       d = ( turbulence( ( x, y, z ), 6, 0, 0, 0.5, 2.0 ) * 0.5 + 0.5 )*distort*0.25
+       t0 = ( turbulence( ( x+d, y+d, z ), 0, 0, 7, 0.5, 2.0 ) + 0.5 )
+       t2 = ( heteroTerrain(( x*2, y*2, t0*0.5 ), H, lacunarity, octaves, offset, basis ) )
+       return (( t0*t2 )+t2*0.5)*0.75
+
+## vlhTerrain
+def vlhTerrain((x,y,z), H, lacunarity, octaves, offset, basis, vlbasis, distort ):
+       ht = heteroTerrain(( x, y, z ), H, lacunarity, octaves, offset, basis )*0.5
+       vl = ht * vlNoise((x,y,z), distort, basis, vlbasis )*0.5+0.5
+       return vl * ht
+
+####---------------------------------------.
+### StatsByAlt, double terrain  basis mode:
+def TerrainBasisMode((x,y,z), basis, mode ):
+       if mode == 0: # noise
+               return noise((x,y,z),basis)
+       if mode == 1: # noise ridged
+               return ( 1.0-abs( noise((x,y,z),basis) ) )-0.5
+       if mode == 2: # vlNoise
+               return vlNoise((x,y,z), 1.0, 0, basis )
+       else:         # vlNoise ridged
+               return ( 1.0-abs( vlNoise((x,y,z), 1.0, 0, basis ) ) )-0.5
+
+#### StatsByAlt terrain:
+def StatsByAltTerrain((x,y,z), exp, lacu, octs, offset, amp, basis, mode ):
+       result = 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) )
+       octs = int( octs )
+       i = 0
+       for i in xrange( 1, octs ):
+               i += 1
+               result += result * amp * 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) )
+               x *= lacu
+               y *= lacu
+               amp /= ( exp * 0.5 ) * i                
+       return result
+
+##### double terrain:
+def doubleTerrain((x,y,z), exp, lacu, octs, offset, threshold, basis, mode ):
+       result = amp = freq = 1.0
+       #octs = int( octs )
+       offset*=0.5
+       i = 1
+       signal = result = 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) )
+       for i in xrange( 1, octs ):
+               i += 1
+               x = x * lacu
+               y = y * lacu
+               freq *= lacu
+               amp = pow( freq, -exp )
+               amp *= i
+               weight = signal / threshold
+               if weight > 1.0: weight = 1.0
+               if weight < 0.0: weigth = 0.0
+               signal = weight * 0.5 * ( offset + TerrainBasisMode((x,y,z), basis, mode ) )
+               result += amp * signal
+       return result * 2.0
+
+##------------------------------------------------------------
+# Noise Functions:
+def Noise_Function(x,y,z):
+       global Basis, NType, musgr, vlnoi, voron, turbOne, marbleOne, tBasismod
+       global vlBasis, Distort, VFunc, VExp, VDep
+       global iScale, Offset, Invert, NSize, Lx, Ly, Sx, Sy
+
+       x,y,z = Trans((x,y,z),( NSize[0].val, Sx[0].val, Sy[0].val, 0 ),( Lx[0].val, Ly[0].val, 0 )  )
+       basis = Basis[0].val
+       if basis == 9: basis = 14
+       vbasis = vlnoi[1].val
+       if vbasis == 9: vbasis = 14
+       if   NType.val == 0:    z = multiFractal((   x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis )
+       elif NType.val == 1:    z = ridgedMFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, basis )
+       elif NType.val == 2:    z = hybridMFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, basis )
+       elif NType.val == 3:    z = heteroTerrain((  x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, basis )*0.5
+       elif NType.val == 4:    z = fBm((            x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis )+0.5
+       elif NType.val == 5:    z = turbulence((     x,y,z ),turbOne[0].val, turbOne[1].val, basis, turbOne[2].val, turbOne[3].val )+0.5
+       elif NType.val == 6:    z = voronoi_turbulence((x,y,z),(voron[0].val,voron[1].val),(turbOne[0].val,turbOne[1].val,turbOne[2].val,turbOne[3].val) )*0.5+0.5
+       elif NType.val == 7:    z = vlNoise_turbulence((x,y,z),(vlnoi[0].val,vbasis), (turbOne[0].val,turbOne[1].val,turbOne[2].val,turbOne[3].val), basis )*0.5+0.5
+       elif NType.val == 8:    z = noise((          x,y,z ),basis )+0.5
+       elif NType.val == 9:    z = cellNoise((      x,y,z ))+0.5
+       elif NType.val == 10: z = marbleNoise((         x,y,z), marbleOne[0].val, basis, marbleOne[2].val, marbleOne[3].val, marbleOne[4].val, marbleOne[5].val )
+       elif NType.val == 11: z = lava_multiFractal((  x,y,z ), musgr[0].val, musgr[1].val, musgr[2].val, vlnoi[0].val, basis )
+       elif NType.val == 12: z = slopey_noise((         x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, vlnoi[0].val, basis )+0.5
+       elif NType.val == 13: z = double_multiFractal(( x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, (vbasis,basis) )
+       elif NType.val == 14: z = distorted_heteroTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, vlnoi[0].val, (vbasis,basis) )
+       elif NType.val == 15: z = SlickRock((           x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, (vbasis,basis)  )
+       elif NType.val == 16: z = terra_turbulence((  x,y,z), turbOne[0].val, turbOne[1].val, basis, turbOne[2].val, turbOne[3].val )
+       elif NType.val == 17: z = rocky_fBm((           x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis )
+       elif NType.val == 18: z = StatsByAltTerrain(   (x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val*0.5, basis, tBasismod.val )
+       elif NType.val == 19: z = doubleTerrain(       (x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[5].val, basis, tBasismod.val )
+       elif NType.val == 20: z = Shattered_hTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, vlnoi[0].val, basis )
+       elif NType.val == 21: z = vlhTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, basis, vbasis, vlnoi[0].val )
+       else:   z = 0.0
+       return HeightScale( z, iScale[0].val , Offset[0].val, Invert[0].val )
+
+###----------------------------------------------------------------------
+##-----------------------------------
+# Filter functions:
+
+##-----------------------------------
+# Filter: Clamp height
+def Clamp_Max( height, max ):
+       if ( height > max ): height = max
+       return height
+def Clamp_Min( height, min ):
+       if ( height < min ): height = min
+       return height
+
+##-----------------------------------
+# Filters: terrace / posterise / peaked / bias:
+def Def_Filter((x,y,z), input, numb, type ):
+       if   type == 0:
+               s = ( sin( input*numb*phi ) * ( 0.1/numb*phi ) )
+               return ( input * (1.0-0.5) + s*0.5 ) * 2.0
+       elif type == 1:
+               s = -abs( sin( input*(numb*0.5)*phi ) * ( 0.1/(numb*0.5)*phi ) )
+               return ( input * (1.0-0.5) + s*0.5 ) * 2.0
+       elif type == 2:
+               s = abs( sin( input*(numb*0.5)*phi ) * ( 0.1/(numb*0.5)*phi ) )
+               return ( input * (1.0-0.5) + s*0.5 ) * 2.0
+       elif type == 3:
+               numb = numb*0.5
+               s = ( int( input*numb ) * 1.0/numb )
+               return ( input * (1.0-0.5) + s*0.5 ) * 2.0
+       elif type == 4:
+               numb = numb*0.5
+               s = ( int( input*numb ) * 1.0/numb )
+               return ( s ) * 2.0
+       elif type == 5:
+               s = ( sin( input*(2*numb)*phi ) * ( 0.1/(2*numb)*phi ) )
+               l = ( input * (1.0-0.5) + s*0.5 ) * 2.0
+               p = ( ( l*numb*0.25 ) * ( l*numb*0.25 ) )**2
+               return ( l * (1.0-0.5) + p*0.5 ) * 2.0
+       elif type == 6:
+               return ( input*numb*0.25 )**4
+       elif type == 7:
+               return 2.0-exp( 1.0-(input*numb/3.0) )
+       elif type == 8:
+               return sin_bias( input*numb )*2.0
+       elif type == 9:
+               return cos_bias( input*numb )*2.0
+       elif type == 10:
+               return tri_bias( input*numb )*2.0
+       elif type == 11:
+               return saw_bias( input*numb )*2.0
+       elif type == 12:
+               return Clamp_Max( input, numb )
+       else:
+               return input
+
+##-----------------------------------
+# Filter: Edge falloff
+def EdgeFalloff( (x,y,z), height, type ):
+       global Falloff, iScale, Offset
+
+       x = x / Falloff[1].val
+       y = y / Falloff[2].val
+
+       if Falloff[3].val != 0:
+               sealevel = (Min.val-Offset[2].val)*2.0/iScale[2].val
+       else:
+               sealevel = 0.0
+
+       falltypes = ( 0, sqrt(x*x+y*y), sqrt((x*x)**2+(y*y)**2), sqrt((x*x)**10+(y*y)**10), sqrt(y*y), sqrt(x*x), abs(x-y), abs(x+y), ((x*x)**10+(y*y)**10)**0.1, ((x*x)+(y*y)) )
+
+       dist = falltypes[ type ]
+       if Falloff[4].val != 0:
+               dist = 1.0 - dist
+       radius = 1.0
+       height = height - sealevel
+       if( dist < radius ):
+               dist = dist / radius
+               dist = ( (dist) * (dist) * ( 3-2*(dist) ) )
+               height = ( height - height * dist ) + sealevel
+       else:
+               height = sealevel
+
+       if Falloff[3].val != 0:
+               height = Clamp_Min( height, sealevel )
+       else:
+               height = Clamp_Min( height, Min.val )
+
+       return height
+
+##-----------------------------------
+# Filter: Custom height filter:
+def CustomFilter( x,y,z, h ):
+       global CustomFilt
+       try:
+               a = eval(CustomFilt[0].val)
+               b = eval(CustomFilt[1].val)
+               result = eval(CustomFilt[2].val)
+               return result
+       except:
+               return 0.0
+
+#####-------------------------------------------------------------------------------------#####
+####-------------------------------------------------------------------------------------####
+### Combine Functions: (get noise, Add effect, filter height and return result)         ###
+##-------------------------------------------------------------------------------------##
+
+def Combine_Functions( (i,j),(x,y,z) ):
+       global Effect_Ctrl, Blend_Effect, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
+       global iScale, Offset, Invert, Min, Max, Falloff
+
+       # get noise height:
+       height = Noise_Function(x,y,0.0)
+
+       ### Filter On
+       if Filter_Mode.val !=0:
+               ### 0= Default Filter Order: Noise>Effect>Filter ---------------------
+               if Filter_Order.val ==0:
+                       # mix noise with effect:
+                       if Effect_Ctrl[0].val !=0:
+                               height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val )
+                       # edge fallof:
+                       if Falloff[0].val !=0:
+                               height = EdgeFalloff( (x,y,z), height, Falloff[0].val )
+               #else: pass
+
+               if Filter_Mode.val !=0:
+                       # height Def_Filter (Terrace/peaked/bias):
+                       if Filter_Mode.val ==1:
+                               height = Def_Filter((x,y,z), height, Def_Filter_Ctrl[ 1 ].val, Def_Filter_Ctrl[ 0 ].val )
+
+                       ## 'IPOCurve' height filter:
+                       elif Filter_Mode.val ==2:
+                               try:
+                                       height = selectedcurve.evaluate( 1 + ( height*Ipo_Filter_Ctrl[2].val/2 ) )*2.0/Ipo_Filter_Ctrl[3].val
+                               except:
+                                       height = height
+
+                       ## Custom filter:
+                       elif Filter_Mode.val ==3:
+                                       height = CustomFilter( x,y,z, height )
+
+               ### 1= Changed Filter Order: Noise>Filter>Effect ---------------------
+               if Filter_Order.val !=0:
+                       # mix noise with effect:
+                       if Effect_Ctrl[0].val !=0:
+                               height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val )
+                       # edge fallof:
+                       if Falloff[0].val !=0:
+                               height = EdgeFalloff( (x,y,z), height, Falloff[0].val )
+               #else: pass
+
+       ### Filter Off ---------------------
+       else:
+               # mix noise with effect:
+               if Effect_Ctrl[0].val !=0:
+                       height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val )
+               # edge fallof:
+               if Falloff[0].val !=0:
+                       height = EdgeFalloff( (x,y,z), height, Falloff[0].val )
+
+       # height scale: 
+       height = HeightScale( height, 0.5*iScale[2].val , Offset[2].val, Invert[2].val )
+
+       # clamp height min. max.:
+       if Falloff[0].val !=1:
+               height = Clamp_Min( height, Min.val )
+       height = Clamp_Max( height, Max.val )
+
+       # return height:
+       return height
+
+
+#------------------------------------------------------------
+##------------------------------------------------------------
+###  Render Noise to a Image('NAME') (you must create one first)
+##------------------------------------------------------------
+#------------------------------------------------------------
+
+def HeightFieldImage():
+       global PreView, previewname
+
+       iname = previewname.val
+       try: 
+               pic = Image.Get( iname )
+       except:
+               #print iname, ' No Image with this name'
+               PupMenu( 'No Image with this name' )
+               return
+       res = pic.getMaxXY()
+       for i in xrange( res[0] ):
+               x = i - (res[0]) / 2.0
+               x = (x*2.0) / (res[0])
+               for j in xrange( res[1] ):
+                       y = j - (res[1]) / 2.0
+                       y = (y*2.0) / (res[1])
+                       height = PreView[2].val + PreView[1].val * Combine_Functions( (i,j),(x,y,0) )
+                       if height > 1.0: height = 1.0
+                       if height < 0.0: height = 0.0
+                       pic.setPixelF( i, j, ( height,height,height, 1.0 ) )
+
+
+#------------------------------------------------------------
+##------------------------------------------------------------
+###  Mesh
+##------------------------------------------------------------
+#------------------------------------------------------------
+
+#------------------------------------------------------------
+## Mesh: make new grid
+###------------------------------------------------------------
+
+def MakeGridMesh( RESOL=32, NAME='GridMesh', CURSORPOS=0, SCENE=None ):
+       # scene, object, mesh ---------------------------------------
+       if not SCENE:
+               SCENE = Blender.Scene.GetCurrent()
+       SCENE.objects.selected=[]
+       newme = Blender.Mesh.New( NAME )
+       newob = SCENE.objects.new( newme, NAME )
+       n = RESOL
+       # verts ---------------------------------------
+       v=[]
+       for i in xrange( n ):
+               x = i-(n-1)/2.0
+               x = x*2.0/(n-1)
+               for j in xrange( n ):
+                       y = j-(n-1)/2.0
+                       y = y*2.0/(n-1)
+                       v.append( [ x, y, 0 ] )
+       newme.verts.extend(v)
+       # faces ---------------------------------------
+       f=[]
+       for i in xrange( n-1 ):
+               for j in xrange( n-1 ):
+                       f.append( [     i*n+j,\
+                                               (i+1)*n+j,\
+                                               (i+1)*n+j+1,\
+                                               i*n+j+1 ] )
+       
+       newme.faces.extend(f, smooth=True)
+       #---------------------------------------
+       newme.calcNormals()
+       #---------------------------------------
+       if CURSORPOS !=0:
+               newob.loc = Window.GetCursorPos()
+       newob.select(1)
+
+#------------------------------------------------------------
+## Mesh: Grid vert displace / update terrain
+###------------------------------------------------------------
+
+def displace( OB, ME, WORLD=0  ):
+       if WORLD == 1:
+               wx,wy,wz = OB.getLocation( 'worldspace' )
+       elif WORLD ==2:
+               l = OB.getLocation( 'worldspace' )
+               w = Window.GetCursorPos()
+               wx,wy,wz = l[0]-w[0], l[1]-w[1], l[2]-w[2]
+       else:
+               wx,wy,wz = 0,0,0
+
+       for v in ME.verts:
+               co = v.co
+               co[2] = Combine_Functions( (co[0]+wx,co[1]+wy),(co[0]+wx, co[1]+wy, 0.0+wz) )
+       ME.update()
+       ME.calcNormals()        
+       #OB.makeDisplayList()
+
+
+#----------------------------------------------------------------------------------------------------
+##----------------------------------------------------------------------------------------------------
+###----------------------------------------------------------------------------------------------------
+####----------------------------------------------------------------------------------------------------
+###----------------------------------------------------------------------------------------------------
+## Do_it:
+#--------------------------------------
+
+#--------------------------------------
+def do_it():
+       global PreView, actme, actob, WorldSpaceCo
+       if actme !=[]:  
+               if print_time !=0:
+                       t= sys.time()
+               Window.WaitCursor(1)
+               in_editmode = Window.EditMode()
+               if in_editmode: Window.EditMode(0)
+               if PreView[0].val != 0:
+                       do_it_preview()
+                       displace( actob[0], actme[0], WorldSpaceCo.val  )
+                       Window.RedrawAll()
+               else:
+                       displace( actob[0], actme[0], WorldSpaceCo.val  )
+                       Window.RedrawAll()
+               if in_editmode: Window.EditMode(1)
+               Window.WaitCursor(0)                    
+               if print_time !=0:
+                       print 'Generate Mesh: done in %.6f' % (sys.time()-t)
+
+#--------------------------------------
+def do_it_random():
+       global PreView, actme, actob
+       if actme !=[]:  
+               if print_time !=0:
+                       t= sys.time()
+               Window.WaitCursor(1)
+               in_editmode = Window.EditMode()
+               if in_editmode: Window.EditMode(0)
+               randomiseNoise()
+               if PreView[0].val != 0:
+                       do_it_preview()
+                       displace( actob[0], actme[0], WorldSpaceCo.val  )
+                       Window.RedrawAll()
+               else:
+                       displace( actob[0], actme[0], WorldSpaceCo.val  )
+                       Window.RedrawAll()
+               if in_editmode: Window.EditMode(1)
+               Window.WaitCursor(0)
+               if print_time !=0:
+                       print 'Generate Mesh: done in %.6f' % (sys.time()-t)
+
+#--------------------------------------
+def do_it_preview():
+       if print_time !=0:
+               t= sys.time()
+       HeightFieldImage()
+       Window.RedrawAll()
+       if print_time !=0:
+               print 'Generate Image: done in %.6f' % (sys.time()-t)
+
+###---------------------------------------------------------
+###---------------------------------------------------------
+## load and save:
+#-------------------------
+
+def callback( filename ):
+       txtFile.val = filename
+       Register(drawgui, events, bevents)
+def writeln(f,x):
+  f.write(str(x))
+  f.write("\n")
+def readint(f):
+  return int(f.readline())
+def readfloat(f):
+  return float(f.readline())
+def readstr(f):
+  s = (f.readline())
+  return strip(s)
+
+#--------------------------------------------------
+# Save settings to .ant file
+def SavePreset(FName):
+       global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly
+       global NType, Basis, musgr, tBasismod, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, musgrTwo
+       global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
+       global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, filemessage, fileinfo
+
+       try:
+               f = open(FName,'w')
+               writeln(f,CurVersion)
+       except:
+               filemessage = "Unable to save file."
+               return
+
+       writeln(f,fileinfo)
+       writeln(f,iScale[0].val)
+       writeln(f,iScale[1].val)
+       writeln(f,iScale[2].val)
+       writeln(f,Offset[0].val)
+       writeln(f,Offset[1].val)
+       writeln(f,Offset[2].val)
+       writeln(f,Invert[0].val)
+       writeln(f,Invert[1].val)
+       writeln(f,Invert[2].val)
+       writeln(f,NSize[0].val)
+       writeln(f,NSize[1].val)
+       writeln(f,Sx[0].val)
+       writeln(f,Sx[1].val)
+       writeln(f,Sy[0].val)
+       writeln(f,Sy[1].val)
+       writeln(f,Lx[0].val)
+       writeln(f,Lx[1].val)
+       writeln(f,Ly[0].val)
+       writeln(f,Ly[1].val)
+       writeln(f,NType.val)
+       writeln(f,Basis[0].val)
+       writeln(f,Basis[1].val)
+       writeln(f,musgr[0].val)
+       writeln(f,musgr[1].val)
+       writeln(f,musgr[2].val)
+       writeln(f,musgr[3].val)
+       writeln(f,musgr[4].val)
+       writeln(f,musgr[5].val)
+       writeln(f,tBasismod.val)
+       writeln(f,vlnoi[0].val)
+       writeln(f,vlnoi[1].val)
+       writeln(f,vlnoiTwo[0].val)
+       writeln(f,vlnoiTwo[1].val)
+       writeln(f,voron[0].val)
+       writeln(f,voron[1].val)
+       writeln(f,turbOne[0].val)
+       writeln(f,turbOne[1].val)
+       writeln(f,turbOne[2].val)       
+       writeln(f,turbOne[3].val)
+       writeln(f,turbTwo[0].val)
+       writeln(f,turbTwo[1].val)       
+       writeln(f,turbTwo[2].val)       
+       writeln(f,turbTwo[3].val)       
+       writeln(f,marbleOne[0].val)
+       writeln(f,marbleOne[1].val)
+       writeln(f,marbleOne[2].val)
+       writeln(f,marbleOne[3].val)
+       writeln(f,marbleOne[4].val)
+       writeln(f,marbleOne[5].val)
+       writeln(f,marbleTwo[0].val)
+       writeln(f,marbleTwo[1].val)             
+       writeln(f,marbleTwo[2].val)
+       writeln(f,marbleTwo[3].val)
+       writeln(f,marbleTwo[4].val)
+       writeln(f,marbleTwo[5].val)
+       writeln(f,musgrTwo[0].val)
+       writeln(f,musgrTwo[1].val)
+       writeln(f,musgrTwo[2].val)
+       writeln(f,musgrTwo[3].val)
+       writeln(f,musgrTwo[4].val)
+       writeln(f,effect_image)
+       writeln(f,Effect_Ctrl[0].val)
+       writeln(f,Effect_Ctrl[1].val)
+       writeln(f,Effect_Ctrl[2].val)
+       writeln(f,Effect_Ctrl[3].val)
+       writeln(f,Effect_Ctrl[4].val)
+       writeln(f,Effect_Ctrl[5].val)
+       writeln(f,Effect_Ctrl[6].val)
+       writeln(f,Effect_Ctrl[7].val)
+       writeln(f,Effect_Ctrl[8].val)
+       writeln(f,CustomFX[0].val)
+       writeln(f,CustomFX[1].val)
+       writeln(f,CustomFX[2].val)
+       writeln(f,Min.val)
+       writeln(f,Max.val)
+       writeln(f,Falloff[0].val)
+       writeln(f,Falloff[1].val)
+       writeln(f,Falloff[2].val)
+       writeln(f,Falloff[3].val)
+       writeln(f,Falloff[4].val)
+       writeln(f,Filter_Mode.val)
+       writeln(f,Filter_Order.val)
+       writeln(f,CustomFilt[0].val)
+       writeln(f,CustomFilt[1].val)
+       writeln(f,CustomFilt[2].val)
+       writeln(f,Def_Filter_Ctrl[0].val)
+       writeln(f,Def_Filter_Ctrl[1].val)
+       writeln(f,Ipo_Filter_Ctrl[0].val)
+       writeln(f,Ipo_Filter_Ctrl[1].val)
+       writeln(f,Ipo_Filter_Ctrl[2].val)
+       writeln(f,Ipo_Filter_Ctrl[3].val)
+       writeln(f,RandMod.val)
+       writeln(f,RSeed.val)
+       writeln(f,rand_H.val)
+       writeln(f,rand_I.val)
+       writeln(f,rand_S.val)
+       writeln(f,rand_L.val)
+       filemessage = 'Settings saved to file.'
+       f.close()
+
+#--------------------------------------------------
+# load settings from .ant file
+def LoadPreset(FName):
+       global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly
+       global NType, Basis, musgr, tBasismod, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, musgrTwo
+       global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order
+       global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, filemessage, fileinfo
+
+       try:
+               f = open(FName,'r')
+               FVersion = readstr(f)
+       except:
+               filemessage = "Unable to open file."
+               return
+
+       fileinfo = readstr(f)
+       iScale[0].val = readfloat(f)
+       iScale[1].val = readfloat(f)
+       iScale[2].val = readfloat(f)
+       Offset[0].val = readfloat(f)
+       Offset[1].val = readfloat(f)
+       Offset[2].val = readfloat(f)
+       Invert[0].val = readint(f)
+       Invert[1].val = readint(f)
+       Invert[2].val = readint(f)
+       NSize[0].val = readfloat(f)
+       NSize[1].val = readfloat(f)
+       Sx[0].val = readfloat(f)
+       Sx[1].val = readfloat(f)
+       Sy[0].val = readfloat(f)
+       Sy[1].val = readfloat(f)
+       Lx[0].val = readfloat(f)
+       Lx[1].val = readfloat(f)
+       Ly[0].val = readfloat(f)
+       Ly[1].val = readfloat(f)
+       NType.val = readint(f)
+       Basis[0].val = readint(f)
+       Basis[1].val = readint(f)
+       musgr[0].val = readfloat(f)
+       musgr[1].val = readfloat(f)
+       musgr[2].val = readint(f)
+       musgr[3].val = readfloat(f)
+       musgr[4].val = readfloat(f)
+       musgr[5].val = readfloat(f)
+       tBasismod.val  = readint(f)
+       vlnoi[0].val = readfloat(f)
+       vlnoi[1].val = readint(f)
+       vlnoiTwo[0].val = readfloat(f)
+       vlnoiTwo[1].val = readint(f)
+       voron[0].val = readint(f)
+       voron[1].val = readfloat(f)
+       turbOne[0].val = readint(f)
+       turbOne[1].val = readint(f)
+       turbOne[2].val = readfloat(f)
+       turbOne[3].val = readfloat(f)
+       turbTwo[0].val = readint(f)
+       turbTwo[1].val = readint(f)
+       turbTwo[2].val = readfloat(f)
+       turbTwo[3].val = readfloat(f)
+       marbleOne[0].val = readint(f)
+       marbleOne[1].val = readint(f)
+       marbleOne[2].val = readfloat(f)
+       marbleOne[3].val = readint(f)
+       marbleOne[4].val = readint(f)
+       marbleOne[5].val = readfloat(f)
+       marbleTwo[0].val = readint(f)
+       marbleTwo[1].val = readint(f)
+       marbleTwo[2].val = readfloat(f)
+       marbleTwo[3].val = readint(f)
+       marbleTwo[4].val = readint(f)
+       marbleTwo[5].val = readfloat(f)
+       musgrTwo[0].val = readfloat(f)
+       musgrTwo[1].val = readfloat(f)
+       musgrTwo[2].val = readint(f)
+       musgrTwo[3].val = readfloat(f)
+       musgrTwo[4].val = readfloat(f)
+       effect_image = readstr(f)
+       Effect_Ctrl[0].val = readint(f)
+       Effect_Ctrl[1].val = readint(f)
+       Effect_Ctrl[2].val = readfloat(f)
+       Effect_Ctrl[3].val = readint(f)
+       Effect_Ctrl[4].val = readfloat(f)
+       Effect_Ctrl[5].val = readint(f)
+       Effect_Ctrl[6].val = readfloat(f)
+       Effect_Ctrl[7].val = readfloat(f)
+       Effect_Ctrl[8].val = readfloat(f)
+       CustomFX[0].val = readstr(f)
+       CustomFX[1].val = readstr(f)
+       CustomFX[2].val = readstr(f)
+       Min.val = readfloat(f)
+       Max.val = readfloat(f)
+       Falloff[0].val = readint(f)
+       Falloff[1].val = readfloat(f)
+       Falloff[2].val = readfloat(f)
+       Falloff[3].val = readint(f)
+       Falloff[4].val = readint(f)
+       Filter_Mode.val = readint(f)
+       Filter_Order.val = readint(f)
+       CustomFilt[0].val = readstr(f)
+       CustomFilt[1].val = readstr(f)
+       CustomFilt[2].val = readstr(f)
+       Def_Filter_Ctrl[0].val = readint(f)
+       Def_Filter_Ctrl[1].val = readfloat(f)
+       Ipo_Filter_Ctrl[0].val = readstr(f)
+       Ipo_Filter_Ctrl[1].val = readint(f)
+       Ipo_Filter_Ctrl[2].val = readfloat(f)
+       Ipo_Filter_Ctrl[3].val = readfloat(f)
+       RandMod.val = readint(f)
+       RSeed.val = readint(f)
+       rand_H.val = readint(f)
+       rand_I.val = readint(f) 
+       rand_S.val = readint(f)
+       rand_L.val = readint(f)
+       filemessage = 'Settings loaded from file.'
+       f.close()
+
+##---------------------------------------------------------------------------
+# Register:
+
+Register( drawgui, events, bevents )
+###--------------------------------------------------------------------------
+               
\ No newline at end of file
diff --git a/release/ui/space_sequencer.py b/release/ui/space_sequencer.py
new file mode 100644 (file)
index 0000000..b64e7d8
--- /dev/null
@@ -0,0 +1,559 @@
+
+import bpy
+
+def act_strip(context):
+       try:            return context.scene.sequence_editor.active_strip
+       except: return None
+
+# Header
+class SEQUENCER_HT_header(bpy.types.Header):
+       __space_type__ = "SEQUENCE_EDITOR"
+       __idname__ = "SEQUENCE_HT_header"
+
+       def draw(self, context):
+               
+               st = context.space_data
+               layout = self.layout
+
+               layout.template_header()
+               
+               if context.area.show_menus:
+                       row = layout.row()
+                       row.itemM("SEQUENCER_MT_view")
+                       
+                       row.itemR(st, "display_mode")
+                       
+                       layout.itemS()
+                       
+                       if st.display_mode == 'SEQUENCER':
+                               row.itemM("SEQUENCER_MT_select")
+                               row.itemM("SEQUENCER_MT_marker")
+                               row.itemM("SEQUENCER_MT_add")
+                               row.itemM("SEQUENCER_MT_strip")
+                               layout.itemS()
+                               row.itemO("SEQUENCER_OT_reload")
+                       else:
+                               row.itemR(st, "display_channel") # text="Chan"
+
+class SEQUENCER_MT_view(bpy.types.Menu):
+       __space_type__ = "SEQUENCE_EDITOR"
+       __label__ = "View (TODO)"
+       
+       def draw(self, context):
+               layout = self.layout
+               st = context.space_data
+               
+               layout.column()
+               
+               """
+       uiBlock *block= uiBeginBlock(C, ar, "seq_viewmenu", UI_EMBOSSP);
+       short yco= 0, menuwidth=120;
+
+       if (sseq->mainb == SEQ_DRAW_SEQUENCE) {
+               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+                                "Play Back Animation "
+                                "in all Sequence Areas|Alt A", 0, yco-=20,
+                                menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+       }
+       else {
+               uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL,
+                                "Grease Pencil...", 0, yco-=20,
+                                menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+               uiDefMenuSep(block);
+
+               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+                                "Play Back Animation "
+                                "in this window|Alt A", 0, yco-=20,
+                                menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+       }
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
+                        "Play Back Animation in all "
+                        "3D Views and Sequence Areas|Alt Shift A",
+                        0, yco-=20,
+                        menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+
+               """
+               layout.itemS()
+               layout.itemO("SEQUENCER_OT_view_all")
+               layout.itemO("SEQUENCER_OT_view_selected")
+               layout.itemS()
+               """
+       
+
+       /* Lock Time */
+       uiDefIconTextBut(block, BUTM, 1, (v2d->flag & V2D_VIEWSYNC_SCREEN_TIME)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
+                       "Lock Time to Other Windows|", 0, yco-=20,
+                       menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
+
+       /* Draw time or frames.*/
+       uiDefMenuSep(block);
+               """
+               
+               layout.itemR(st, "draw_frames")
+               
+               """
+       if(!sa->full) uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Maximize Window|Ctrl UpArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0,0, "");
+       else uiDefIconTextBut(block, BUTM, B_FULL, ICON_BLANK1, "Tile Window|Ctrl DownArrow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
+
+               """
+
+class SEQUENCER_MT_select(bpy.types.Menu):
+       __space_type__ = "SEQUENCE_EDITOR"
+       __label__ = "Select"
+
+       def draw(self, context):
+               layout = self.layout
+               st = context.space_data
+               
+               layout.column()
+               layout.item_enumO("SEQUENCER_OT_select_active_side", "side", 'LEFT', text="Strips to the Left")
+               layout.item_enumO("SEQUENCER_OT_select_active_side", "side", 'RIGHT', text="Strips to the Right")
+               layout.itemS()
+               layout.item_enumO("SEQUENCER_OT_select_handles", "side", 'BOTH', text="Surrounding Handles")
+               layout.item_enumO("SEQUENCER_OT_select_handles", "side", 'LEFT', text="Left Handle")
+               layout.item_enumO("SEQUENCER_OT_select_handles", "side", 'RIGHT', text="Right Handle")
+               layout.itemS()
+               layout.itemO("SEQUENCER_OT_select_linked")
+               layout.itemO("SEQUENCER_OT_select_all_toggle")
+               layout.itemO("SEQUENCER_OT_select_invert")
+
+class SEQUENCER_MT_marker(bpy.types.Menu):
+       __space_type__ = "SEQUENCE_EDITOR"
+       __label__ = "Marker (TODO)"
+
+       def draw(self, context):
+               layout = self.layout
+               st = context.space_data
+               
+               layout.column()
+               layout.itemO("SEQUENCER_OT_sound_strip_add", text="Add Marker|Ctrl Alt M")
+               layout.itemO("SEQUENCER_OT_sound_strip_add", text="Duplicate Marker|Ctrl Shift D")
+               layout.itemO("SEQUENCER_OT_sound_strip_add", text="Delete Marker|Shift X")
+               layout.itemS()
+               layout.itemO("SEQUENCER_OT_sound_strip_add", text="(Re)Name Marker|Ctrl M")
+               layout.itemO("SEQUENCER_OT_sound_strip_add", text="Grab/Move Marker|Ctrl G")
+               layout.itemS()
+               layout.itemO("SEQUENCER_OT_sound_strip_add", text="Transform Markers") # toggle, will be rna - (sseq->flag & SEQ_MARKER_TRANS)
+
+class SEQUENCER_MT_add(bpy.types.Menu):
+       __space_type__ = "SEQUENCE_EDITOR"
+       __label__ = "Add"
+
+       def draw(self, context):
+               layout = self.layout
+               st = context.space_data
+               
+               layout.column()
+               layout.itemO("SEQUENCER_OT_scene_strip_add", text="Scene")
+               layout.itemO("SEQUENCER_OT_movie_strip_add", text="Movie")
+               layout.item_booleanO("SEQUENCER_OT_movie_strip_add", "sound", True, text="Movie & Sound") # FFMPEG ONLY
+               layout.itemO("SEQUENCER_OT_image_strip_add", text="Image")
+               layout.itemO("SEQUENCER_OT_sound_strip_add", text="Sound (Ram)")
+               layout.item_booleanO("SEQUENCER_OT_sound_strip_add", "hd", True, text="Sound (Streaming)") # FFMPEG ONLY
+               
+               layout.itemM("SEQUENCER_MT_add_effect")
+
+
+class SEQUENCER_MT_add_effect(bpy.types.Menu):
+       __space_type__ = "SEQUENCE_EDITOR"
+       __label__ = "Effect Strip..."
+
+       def draw(self, context):
+               layout = self.layout
+               st = context.space_data
+               
+               self.layout.column()
+               self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'ADD')
+               self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'SUBTRACT')
+               self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'ALPHA_OVER')
+               self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'ALPHA_UNDER')
+               self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'GAMMA_CROSS')
+               self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'MULTIPLY')
+               self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'OVER_DROP')
+               self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'PLUGIN')
+               self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'WIPE')
+               self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'GLOW')
+               self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'TRANSFORM')
+               self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'COLOR')
+               self.layout.item_enumO("SEQUENCER_OT_effect_strip_add", 'type', 'SPEED')
+
+class SEQUENCER_MT_strip(bpy.types.Menu):
+       __space_type__ = "SEQUENCE_EDITOR"
+       __label__ = "Strip"
+
+       def draw(self, context):
+               layout = self.layout
+               st = context.space_data
+               
+               layout.operator_context = 'INVOKE_REGION_WIN'
+               
+               layout.column()
+               layout.item_enumO("TFM_OT_transform", "mode", 'TRANSLATION', text="Grab/Move")
+               layout.item_enumO("TFM_OT_transform", "mode", 'TIME_EXTEND', text="Grab/Extend from frame")
+               #  uiItemO(layout, NULL, 0, "SEQUENCER_OT_strip_snap"); // TODO - add this operator
+               layout.itemS()
+               
+               layout.item_enumO("SEQUENCER_OT_cut", "type", 'HARD', text="Cut (hard) at frame")
+               layout.item_enumO("SEQUENCER_OT_cut", "type", 'SOFT', text="Cut (soft) at frame")
+               layout.itemO("SEQUENCER_OT_images_separate")
+               layout.itemS()
+               
+               layout.itemO("SEQUENCER_OT_duplicate_add")
+               layout.itemO("SEQUENCER_OT_delete")
+               
+               strip = act_strip(context)
+               
+               if strip:
+                       stype = strip.type
+                       
+                       if      stype=='EFFECT':
+                               layout.itemS()
+                               layout.itemO("SEQUENCER_OT_effect_change")
+                               layout.itemO("SEQUENCER_OT_effect_reassign_inputs")
+                       elif stype=='IMAGE':
+                               layout.itemS()
+                               layout.itemO("SEQUENCER_OT_image_change")
+                       elif stype=='SCENE':
+                               layout.itemS()
+                               layout.itemO("SEQUENCER_OT_scene_change", text="Change Scene")
+                       elif stype=='MOVIE':
+                               layout.itemS()
+                               layout.itemO("SEQUENCER_OT_movie_change")
+                       
+               layout.itemS()
+               
+               layout.itemO("SEQUENCER_OT_meta_make")
+               layout.itemO("SEQUENCER_OT_meta_separate")
+               
+               #if (ed && (ed->metastack.first || (ed->act_seq && ed->act_seq->type == SEQ_META))) {
+               #       uiItemS(layout);
+               #       uiItemO(layout, NULL, 0, "SEQUENCER_OT_meta_toggle");
+               #}
+               
+               layout.itemS()
+               layout.itemO("SEQUENCER_OT_reload")
+               layout.itemS()
+               layout.itemO("SEQUENCER_OT_lock")
+               layout.itemO("SEQUENCER_OT_unlock")
+               layout.itemO("SEQUENCER_OT_mute")
+               layout.itemO("SEQUENCER_OT_unmute")
+               
+               layout.item_enumO("SEQUENCER_OT_mute", property="type", value='UNSELECTED', text="Mute Deselected Strips")
+
+               layout.itemO("SEQUENCER_OT_snap")
+
+# Panels
+class SequencerButtonsPanel(bpy.types.Panel):
+       __space_type__ = "SEQUENCE_EDITOR"
+       __region_type__ = "UI"
+
+       def poll(self, context):
+               return context.space_data.display_mode == 'SEQUENCER' and act_strip(context) != None
+               
+class SequencerButtonsPanel_Output(bpy.types.Panel):
+       __space_type__ = "SEQUENCE_EDITOR"
+       __region_type__ = "UI"
+
+       def poll(self, context):
+               return context.space_data.display_mode != 'SEQUENCER'
+
+class SEQUENCER_PT_edit(SequencerButtonsPanel):
+       __label__ = "Edit Strip"
+       __idname__ = "SEQUENCER_PT_edit"
+
+       def draw(self, context):
+               layout = self.layout
+               
+               strip = act_strip(context)
+               
+               layout.itemR(strip, "name")
+               
+               layout.itemR(strip, "type")
+               
+               layout.itemR(strip, "blend_mode")
+               
+               layout.itemR(strip, "blend_opacity", text="Opacity", slider=True)
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(strip, "mute")
+               col.itemR(strip, "lock")
+               col.itemR(strip, "frame_locked")
+               
+               col = split.column()
+               col.itemR(strip, "channel")
+               col.itemR(strip, "start_frame")
+               col.itemR(strip, "length")
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(strip, "start_offset")
+               col.itemR(strip, "start_still")
+               
+               col = split.column()
+               col.itemR(strip, "end_offset")
+               col.itemR(strip, "end_still")
+               
+class SEQUENCER_PT_effect(SequencerButtonsPanel):
+       __label__ = "Effect Strip"
+       __idname__ = "SEQUENCER_PT_effect"
+
+       def poll(self, context):
+               if context.space_data.display_mode != 'SEQUENCER':
+                       return False
+               
+               strip = act_strip(context)
+               if not strip:
+                       return False
+               
+               return strip.type in ('COLOR', 'WIPE', 'GLOW', 'SPEED', 'TRANSFORM')
+
+       def draw(self, context):
+               layout = self.layout
+               
+               strip = act_strip(context)
+               
+               if strip.type == 'COLOR':
+                       layout.itemR(strip, "color")
+                       
+               elif strip.type == 'WIPE':
+                       row = layout.row()
+                       row.itemL(text="Transition Type:")
+                       row.itemL(text="Direction:")
+                       
+                       row = layout.row()
+                       row.itemR(strip, "transition_type", text="")
+                       row.itemR(strip, "direction", text="")
+                       
+                       row = layout.row()
+                       row.itemR(strip, "blur_width")
+                       if strip.transition_type in ('SINGLE', 'DOUBLE'):
+                               row.itemR(strip, "angle")
+                               
+               elif strip.type == 'GLOW':
+                       flow = layout.column_flow()
+                       flow.itemR(strip, "threshold")
+                       flow.itemR(strip, "clamp")
+                       flow.itemR(strip, "boost_factor")
+                       flow.itemR(strip, "blur_distance")
+                       
+                       row = layout.row()
+                       row.itemR(strip, "quality", slider=True)
+                       row.itemR(strip, "only_boost")
+                       
+               elif strip.type == 'SPEED':
+                       layout.itemR(strip, "global_speed")
+                       
+                       flow = layout.column_flow()
+                       flow.itemR(strip, "curve_velocity")
+                       flow.itemR(strip, "curve_compress_y")
+                       flow.itemR(strip, "frame_blending")
+                       
+               elif strip.type == 'TRANSFORM':
+                       row = layout.row()
+                       row.itemL(text="Interpolation:")
+                       row.itemL(text="Translation Unit:")
+                       
+                       row = layout.row()
+                       row.itemR(strip, "interpolation", text="")
+                       row.itemR(strip, "translation_unit", text="")
+                       
+                       split = layout.split()
+                       
+                       col = split.column()
+                       sub = col.column(align=True) 
+                       sub.itemL(text="Position X:")
+                       sub.itemR(strip, "translate_start_x", text="Start")
+                       sub.itemR(strip, "translate_end_x", text="End")
+                       
+                       sub = col.column(align=True) 
+                       sub.itemL(text="Scale X:")
+                       sub.itemR(strip, "scale_start_x", text="Start")
+                       sub.itemR(strip, "scale_end_x", text="End")
+                       
+                       sub = col.column(align=True) 
+                       sub.itemL(text="Rotation:")
+                       sub.itemR(strip, "rotation_start", text="Start")
+                       sub.itemR(strip, "rotation_end", text="End")
+                       
+                       col = split.column()
+                       sub = col.column(align=True) 
+                       sub.itemL(text="Position Y:")
+                       sub.itemR(strip, "translate_start_y", text="Start")
+                       sub.itemR(strip, "translate_end_y", text="End")
+                       
+                       sub = col.column(align=True) 
+                       sub.itemL(text="Scale Y:")
+                       sub.itemR(strip, "scale_start_y", text="Start")
+                       sub.itemR(strip, "scale_end_y", text="End")
+
+class SEQUENCER_PT_input(SequencerButtonsPanel):
+       __label__ = "Strip Input"
+       __idname__ = "SEQUENCER_PT_input"
+       
+       def poll(self, context):
+               if context.space_data.display_mode != 'SEQUENCER':
+                       return False
+               
+               strip = act_strip(context)
+               if not strip:
+                       return False
+               
+               return strip.type in ('MOVIE', 'IMAGE', 'SOUND')
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               strip = act_strip(context)
+               
+               split = layout.split(percentage=0.3)
+               sub = split.column()
+               sub.itemL(text="Directory:")
+               sub = split.column() 
+               sub.itemR(strip, "directory", text="")
+               
+               # Current element for the filename
+               split = layout.split(percentage=0.3)
+               sub = split.column()
+               sub.itemL(text="File Name:")
+               sub = split.column()
+               
+               elem = strip.getStripElem(context.scene.current_frame)
+               if elem:
+                       sub.itemR(elem, "filename", text="") # strip.elements[0] could be a fallback
+               
+               layout.itemR(strip, "use_translation")
+               if strip.transform:
+                       flow = layout.column_flow()
+                       flow.active = strip.use_translation
+                       flow.itemR(strip.transform, "offset_x")
+                       flow.itemR(strip.transform, "offset_y")
+                       
+                       
+               layout.itemR(strip, "use_crop")
+               if strip.crop:
+                       flow = layout.column_flow()
+                       flow.active = strip.use_crop
+                       flow.itemR(strip.crop, "top")
+                       flow.itemR(strip.crop, "left")
+                       flow.itemR(strip.crop, "bottom")
+                       flow.itemR(strip.crop, "right")
+                       
+               layout.itemR(strip, "animation_start_offset")
+               layout.itemR(strip, "animation_end_offset")
+               
+
+class SEQUENCER_PT_filter(SequencerButtonsPanel):
+       __label__ = "Filter"
+       __idname__ = "SEQUENCER_PT_filter"
+       
+       def poll(self, context):
+               if context.space_data.display_mode != 'SEQUENCER':
+                       return False
+               
+               strip = act_strip(context)
+               if not strip:
+                       return False
+               
+               return strip.type in ('MOVIE', 'IMAGE', 'SCENE', 'META')
+       
+       def draw(self, context):
+               layout = self.layout
+               
+               strip = act_strip(context)
+               
+               split = layout.split()
+               
+               col = split.column()
+               col.itemR(strip, "premultiply")
+               col.itemR(strip, "convert_float")
+               col.itemR(strip, "de_interlace")
+               col.itemR(strip, "multiply_colors")
+               col.itemR(strip, "strobe")
+               
+               col = split.column()
+               col.itemL(text="Flip:")
+               col.itemR(strip, "flip_x", text="X")
+               col.itemR(strip, "flip_y", text="Y")
+               col.itemR(strip, "reverse_frames", text="Backwards")
+               
+               layout.itemR(strip, "use_color_balance")
+               if strip.color_balance: # TODO - need to add this somehow
+                       row = layout.row()
+                       row.active = strip.use_color_balance
+                       col = row.column()
+                       col.itemR(strip.color_balance, "lift")
+                       col.itemR(strip.color_balance, "inverse_lift")
+                       col = row.column()
+                       col.itemR(strip.color_balance, "gamma")
+                       col.itemR(strip.color_balance, "inverse_gamma")
+                       col = row.column()
+                       col.itemR(strip.color_balance, "gain")
+                       col.itemR(strip.color_balance, "inverse_gain")
+                       
+
+class SEQUENCER_PT_proxy(SequencerButtonsPanel):
+       __label__ = "Proxy"
+       __idname__ = "SEQUENCER_PT_proxy"
+       
+       def poll(self, context):
+               if context.space_data.display_mode != 'SEQUENCER':
+                       return False
+               
+               strip = act_strip(context)
+               if not strip:
+                       return False
+               
+               return strip.type in ('MOVIE', 'IMAGE', 'SCENE', 'META')
+       
+       def draw_header(self, context):
+               strip = act_strip(context)
+
+               layout = self.layout
+               
+               layout.itemR(strip, "use_proxy", text="")
+
+       def draw(self, context):
+               strip = act_strip(context)
+               
+               layout = self.layout
+               
+               flow = layout.column_flow()
+               flow.itemR(strip, "proxy_custom_directory")
+               if strip.proxy: # TODO - need to add this somehow
+                       flow.itemR(strip.proxy, "directory")
+                       flow.itemR(strip.proxy, "file")
+
+
+class SEQUENCER_PT_view(SequencerButtonsPanel_Output):
+       __label__ = "View Settings"
+       __idname__ = "SEQUENCER_PT_view"
+
+       def draw(self, context):
+               st = context.space_data
+
+               layout = self.layout
+
+               flow = layout.column_flow()
+               flow.itemR(st, "draw_overexposed") # text="Zebra"
+               flow.itemR(st, "draw_safe_margin")
+
+
+bpy.types.register(SEQUENCER_HT_header) # header/menu classes
+bpy.types.register(SEQUENCER_MT_view)
+bpy.types.register(SEQUENCER_MT_select)
+bpy.types.register(SEQUENCER_MT_marker)
+bpy.types.register(SEQUENCER_MT_add)
+bpy.types.register(SEQUENCER_MT_add_effect)
+bpy.types.register(SEQUENCER_MT_strip)
+
+bpy.types.register(SEQUENCER_PT_edit) # sequencer panels
+bpy.types.register(SEQUENCER_PT_effect)
+bpy.types.register(SEQUENCER_PT_input)
+bpy.types.register(SEQUENCER_PT_filter)
+bpy.types.register(SEQUENCER_PT_proxy)
+
+bpy.types.register(SEQUENCER_PT_view) # view panels
+
diff --git a/source/gameengine/Converter/BL_ModifierDeformer.cpp b/source/gameengine/Converter/BL_ModifierDeformer.cpp
new file mode 100644 (file)
index 0000000..eb27820
--- /dev/null
@@ -0,0 +1,183 @@
+/**
+ * $Id: BL_ModifierDeformer.cpp 20741 2009-06-08 20:08:19Z blendix $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#endif //WIN32
+
+#include "MEM_guardedalloc.h"
+#include "BL_ModifierDeformer.h"
+#include "GEN_Map.h"
+#include "STR_HashedString.h"
+#include "RAS_IPolygonMaterial.h"
+#include "BL_SkinMeshObject.h"
+#include "PHY_IGraphicController.h"
+
+//#include "BL_ArmatureController.h"
+#include "DNA_armature_types.h"
+#include "DNA_action_types.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_scene_types.h"
+#include "BKE_armature.h"
+#include "BKE_action.h"
+#include "BKE_key.h"
+#include "BKE_ipo.h"
+#include "MT_Point3.h"
+
+extern "C"{
+       #include "BKE_customdata.h"
+       #include "BKE_DerivedMesh.h"
+       #include "BKE_lattice.h"
+       #include "BKE_modifier.h"
+}
+ #include "BKE_utildefines.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#define __NLA_DEFNORMALS
+//#undef __NLA_DEFNORMALS
+
+
+BL_ModifierDeformer::~BL_ModifierDeformer()
+{
+       if (m_dm) {
+               // deformedOnly is used as a user counter
+               if (--m_dm->deformedOnly == 0) {
+                       m_dm->needsFree = 1;
+                       m_dm->release(m_dm);
+               }
+       }
+};
+
+RAS_Deformer *BL_ModifierDeformer::GetReplica()
+{
+       BL_ModifierDeformer *result;
+
+       result = new BL_ModifierDeformer(*this);
+       result->ProcessReplica();
+       return result;
+}
+
+void BL_ModifierDeformer::ProcessReplica()
+{
+       /* Note! - This is not inherited from PyObjectPlus */
+       BL_ShapeDeformer::ProcessReplica();
+       if (m_dm)
+               // by default try to reuse mesh, deformedOnly is used as a user count
+               m_dm->deformedOnly++;
+       // this will force an update and if the mesh cannot be reused, a new one will be created
+       m_lastModifierUpdate = -1;
+}
+
+bool BL_ModifierDeformer::HasCompatibleDeformer(Object *ob)
+{
+       if (!ob->modifiers.first)
+               return false;
+       // soft body cannot use mesh modifiers
+       if ((ob->gameflag & OB_SOFT_BODY) != 0)
+               return false;
+       ModifierData* md;
+       for (md = (ModifierData*)ob->modifiers.first; md; md = (ModifierData*)md->next) {
+               if (modifier_dependsOnTime(md))
+                       continue;
+               if (!(md->mode & eModifierMode_Realtime))
+                       continue;
+               return true;
+       }
+       return false;
+}
+
+bool BL_ModifierDeformer::Update(void)
+{
+       bool bShapeUpdate = BL_ShapeDeformer::Update();
+
+       if (bShapeUpdate || m_lastModifierUpdate != m_gameobj->GetLastFrame()) {
+               // static derived mesh are not updated
+               if (m_dm == NULL || m_bDynamic) {
+                       /* execute the modifiers */
+                       Object* blendobj = m_gameobj->GetBlendObject();
+                       /* hack: the modifiers require that the mesh is attached to the object
+                          It may not be the case here because of replace mesh actuator */
+                       Mesh *oldmesh = (Mesh*)blendobj->data;
+                       blendobj->data = m_bmesh;
+                       /* execute the modifiers */             
+                       DerivedMesh *dm = mesh_create_derived_no_virtual(m_scene, blendobj, m_transverts, CD_MASK_MESH);
+                       /* restore object data */
+                       blendobj->data = oldmesh;
+                       /* free the current derived mesh and replace, (dm should never be NULL) */
+                       if (m_dm != NULL) {
+                               // HACK! use deformedOnly as a user counter
+                               if (--m_dm->deformedOnly == 0) {
+                                       m_dm->needsFree = 1;
+                                       m_dm->release(m_dm);
+                               }
+                       }
+                       m_dm = dm;
+                       // get rid of temporary data
+                       m_dm->needsFree = 0;
+                       m_dm->release(m_dm);
+                       // HACK! use deformedOnly as a user counter
+                       m_dm->deformedOnly = 1;
+                       /* update the graphic controller */
+                       PHY_IGraphicController *ctrl = m_gameobj->GetGraphicController();
+                       if (ctrl) {
+                               float min_r[3], max_r[3];
+                               INIT_MINMAX(min_r, max_r);
+                               m_dm->getMinMax(m_dm, min_r, max_r);
+                               ctrl->setLocalAabb(min_r, max_r);
+                       }
+               }
+               m_lastModifierUpdate=m_gameobj->GetLastFrame();
+               bShapeUpdate = true;
+       }
+       return bShapeUpdate;
+}
+
+bool BL_ModifierDeformer::Apply(RAS_IPolyMaterial *mat)
+{
+       if (!Update())
+               return false;
+
+       // drawing is based on derived mesh, must set it in the mesh slots
+       int nmat = m_pMeshObject->NumMaterials();
+       for (int imat=0; imat<nmat; imat++) {
+               RAS_MeshMaterial *mmat = m_pMeshObject->GetMeshMaterial(imat);
+               RAS_MeshSlot **slot = mmat->m_slots[(void*)m_gameobj];
+               if(!slot || !*slot)
+                       continue;
+               (*slot)->m_pDerivedMesh = m_dm;
+       }
+       return true;
+}
diff --git a/source/gameengine/Converter/BL_ModifierDeformer.h b/source/gameengine/Converter/BL_ModifierDeformer.h
new file mode 100644 (file)
index 0000000..74de541
--- /dev/null
@@ -0,0 +1,107 @@
+/**
+ * $Id: BL_ModifierDeformer.h 20741 2009-06-08 20:08:19Z blendix $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BL_MODIFIERDEFORMER
+#define BL_MODIFIERDEFORMER
+
+#ifdef WIN32
+#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
+#endif //WIN32
+
+#include "BL_ShapeDeformer.h"
+#include "BL_DeformableGameObject.h"
+#include <vector>
+
+struct DerivedMesh;
+struct Object;
+
+class BL_ModifierDeformer : public BL_ShapeDeformer  
+{
+public:
+       static bool HasCompatibleDeformer(Object *ob);
+
+
+       BL_ModifierDeformer(BL_DeformableGameObject *gameobj,
+                                               Scene *scene,
+                                               Object *bmeshobj,
+                                               BL_SkinMeshObject *mesh)
+                                               :       
+                                               BL_ShapeDeformer(gameobj,bmeshobj, mesh),
+                                               m_lastModifierUpdate(-1),
+                                               m_scene(scene),
+                                               m_dm(NULL)
+       {
+               m_recalcNormal = false;
+       };
+
+       /* this second constructor is needed for making a mesh deformable on the fly. */
+       BL_ModifierDeformer(BL_DeformableGameObject *gameobj,
+                                               struct Scene *scene,
+                                               struct Object *bmeshobj_old,
+                                               struct Object *bmeshobj_new,
+                                               class BL_SkinMeshObject *mesh,
+                                               bool release_object,
+                                               BL_ArmatureObject* arma = NULL)
+                                               :
+                                               BL_ShapeDeformer(gameobj, bmeshobj_old, bmeshobj_new, mesh, release_object, false, arma),
+                                               m_lastModifierUpdate(-1),
+                                               m_scene(scene),
+                                               m_dm(NULL)
+       {
+       };
+
+       virtual void ProcessReplica();
+       virtual RAS_Deformer *GetReplica();
+       virtual ~BL_ModifierDeformer();
+       virtual bool UseVertexArray()
+       {
+               return false;
+       }
+
+       bool Update (void);
+       bool Apply(RAS_IPolyMaterial *mat);
+       void ForceUpdate()
+       {
+               m_lastModifierUpdate = -1.0;
+       };
+       virtual struct DerivedMesh* GetFinalMesh()
+       {
+               return m_dm;
+       }
+
+
+protected:
+       double                                   m_lastModifierUpdate;
+       Scene                                   *m_scene;
+       DerivedMesh                             *m_dm;
+
+};
+
+#endif
+
diff --git a/source/gameengine/Ketsji/KX_PythonSeq.cpp b/source/gameengine/Ketsji/KX_PythonSeq.cpp
new file mode 100644 (file)
index 0000000..cc8021f
--- /dev/null
@@ -0,0 +1,382 @@
+/**
+ * $Id: 
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: none of this file.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * Readonly sequence wrapper for lookups on logic bricks
+ */
+
+
+#include "KX_PythonSeq.h"
+#include "KX_GameObject.h"
+#include "SCA_ISensor.h"
+#include "SCA_IController.h"
+#include "SCA_IActuator.h"
+
+
+PyObject *KX_PythonSeq_CreatePyObject( PyObject *base, short type )
+{
+       KX_PythonSeq *seq = PyObject_NEW( KX_PythonSeq, &KX_PythonSeq_Type);
+       seq->base = base;
+       Py_INCREF(base); /* so we can always access to check if its valid */
+       seq->type = type;
+       seq->iter = -1; /* init */
+       return (PyObject *)seq;
+ }
+ static void KX_PythonSeq_dealloc( KX_PythonSeq * self )
+{
+       Py_DECREF(self->base);
+       PyObject_DEL( self );
+}
+
+static Py_ssize_t KX_PythonSeq_len( PyObject * self )
+{
+       PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
+        
+       if(self_plus==NULL) {
+               PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+               return -1;
+       }
+       
+       switch(((KX_PythonSeq *)self)->type) {
+       case KX_PYGENSEQ_CONT_TYPE_SENSORS:
+               return ((SCA_IController *)self_plus)->GetLinkedSensors().size();
+       case KX_PYGENSEQ_CONT_TYPE_ACTUATORS:
+               return ((SCA_IController *)self_plus)->GetLinkedActuators().size();
+       case KX_PYGENSEQ_OB_TYPE_SENSORS:
+               return ((KX_GameObject *)self_plus)->GetSensors().size();
+       case KX_PYGENSEQ_OB_TYPE_CONTROLLERS:
+               return ((KX_GameObject *)self_plus)->GetControllers().size();
+       case KX_PYGENSEQ_OB_TYPE_ACTUATORS:
+               return ((KX_GameObject *)self_plus)->GetActuators().size();
+       default:
+               /* Should never happen */
+               PyErr_SetString(PyExc_SystemError, "invalid type, internal error");
+               return -1;
+       }
+}
+
+static PyObject *KX_PythonSeq_getIndex(PyObject* self, int index)
+{
+       PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
+        
+       if(self_plus==NULL) {
+               PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+               return NULL;
+       }
+       
+       switch(((KX_PythonSeq *)self)->type) {
+               case KX_PYGENSEQ_CONT_TYPE_SENSORS:
+               {
+                       vector<SCA_ISensor*>& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors();
+                       if(index<0) index += linkedsensors.size();
+                       if(index<0 || index>= linkedsensors.size()) {
+                               PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
+                               return NULL;
+                       }
+                       return linkedsensors[index]->GetProxy();
+               }
+               case KX_PYGENSEQ_CONT_TYPE_ACTUATORS:
+               {
+                       vector<SCA_IActuator*>& linkedactuators = ((SCA_IController *)self_plus)->GetLinkedActuators();
+                       if(index<0) index += linkedactuators.size();
+                       if(index<0 || index>= linkedactuators.size()) {
+                               PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
+                               return NULL;
+                       }
+                       return linkedactuators[index]->GetProxy();
+               }
+               case KX_PYGENSEQ_OB_TYPE_SENSORS:
+               {
+                       SCA_SensorList& linkedsensors= ((KX_GameObject *)self_plus)->GetSensors();
+                       if(index<0) index += linkedsensors.size();
+                       if(index<0 || index>= linkedsensors.size()) {
+                               PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
+                               return NULL;
+                       }
+                       return linkedsensors[index]->GetProxy();
+               }
+               case KX_PYGENSEQ_OB_TYPE_CONTROLLERS:
+               {
+                       SCA_ControllerList& linkedcontrollers= ((KX_GameObject *)self_plus)->GetControllers();
+                       if(index<0) index += linkedcontrollers.size();
+                       if(index<0 || index>= linkedcontrollers.size()) {
+                               PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
+                               return NULL;
+                       }
+                       return linkedcontrollers[index]->GetProxy();
+               }
+               case KX_PYGENSEQ_OB_TYPE_ACTUATORS:
+               {
+                       SCA_ActuatorList& linkedactuators= ((KX_GameObject *)self_plus)->GetActuators();
+                       if(index<0) index += linkedactuators.size();
+                       if(index<0 || index>= linkedactuators.size()) {
+                               PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range");
+                               return NULL;
+                       }
+                       return linkedactuators[index]->GetProxy();
+               }
+       }
+       
+       PyErr_SetString(PyExc_SystemError, "invalid sequence type, this is a bug");
+       return NULL;
+}
+
+
+static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key)
+{
+       PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base);
+       char *name = NULL;
+       
+       if(self_plus==NULL) {
+               PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+               return NULL;
+       }
+       
+       if (PyInt_Check(key)) {
+               return KX_PythonSeq_getIndex(self, PyInt_AS_LONG( key ));
+       } else if ( PyString_Check(key) ) {
+               name = PyString_AsString( key );
+       } else {
+               PyErr_SetString( PyExc_TypeError, "expected a string or an index" );
+               return NULL;
+       }
+       
+       switch(((KX_PythonSeq *)self)->type) {
+               case KX_PYGENSEQ_CONT_TYPE_SENSORS:
+               {
+                       vector<SCA_ISensor*>& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors();
+                       SCA_ISensor* sensor;
+                       for (unsigned int index=0;index<linkedsensors.size();index++) {
+                               sensor = linkedsensors[index];
+                               if (sensor->GetName() == name)
+                                       return sensor->GetProxy();
+                       }
+                       break;
+               }
+               case KX_PYGENSEQ_CONT_TYPE_ACTUATORS:
+               {
+                       vector<SCA_IActuator*>& linkedactuators = ((SCA_IController *)self_plus)->GetLinkedActuators();
+                       SCA_IActuator* actuator;
+                       for (unsigned int index=0;index<linkedactuators.size();index++) {
+                               actuator = linkedactuators[index];
+                               if (actuator->GetName() == name)
+                                       return actuator->GetProxy();
+                       }
+                       break;
+               }
+               case KX_PYGENSEQ_OB_TYPE_SENSORS:
+               {
+                       SCA_SensorList& linkedsensors= ((KX_GameObject *)self_plus)->GetSensors();
+                       SCA_ISensor *sensor;
+                       for (unsigned int index=0;index<linkedsensors.size();index++) {
+                               sensor= linkedsensors[index];
+                               if (sensor->GetName() == name)
+                                       return sensor->GetProxy();
+                       }
+                       break;
+               }
+               case KX_PYGENSEQ_OB_TYPE_CONTROLLERS:
+               {
+                       SCA_ControllerList& linkedcontrollers= ((KX_GameObject *)self_plus)->GetControllers();
+                       SCA_IController *controller;
+                       for (unsigned int index=0;index<linkedcontrollers.size();index++) {
+                               controller= linkedcontrollers[index];
+                               if (controller->GetName() == name)
+                                       return controller->GetProxy();
+                       }
+                       break;
+               }
+               case KX_PYGENSEQ_OB_TYPE_ACTUATORS:
+               {
+                       SCA_ActuatorList& linkedactuators= ((KX_GameObject *)self_plus)->GetActuators();
+                       SCA_IActuator *actuator;
+                       for (unsigned int index=0;index<linkedactuators.size();index++) {
+                               actuator= linkedactuators[index];
+                               if (actuator->GetName() == name)
+                                       return actuator->GetProxy();
+                       }
+                       break;
+               }
+       }
+       
+       PyErr_Format( PyExc_KeyError, "requested item \"%s\" does not exist", name);
+       return NULL;
+}
+
+static PyMappingMethods KX_PythonSeq_as_mapping = {
+       KX_PythonSeq_len,       /* mp_length */
+       KX_PythonSeq_subscript, /* mp_subscript */
+       0,      /* mp_ass_subscript */
+};
+
+
+/*
+ * Initialize the interator index
+ */
+
+static PyObject *KX_PythonSeq_getIter(KX_PythonSeq *self)
+{
+       if(BGE_PROXY_REF(self->base)==NULL) {
+               PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+               return NULL;
+       }
+       
+       /* create a new iterator if were alredy using this one */
+       if (self->iter == -1) {
+               self->iter = 0;
+               Py_INCREF(self);
+               return (PyObject *)self;
+       } else {
+               return KX_PythonSeq_CreatePyObject(self->base, self->type);
+       }
+ }
+
+/*
+ * Return next KX_PythonSeq iter.
+ */
+static PyObject *KX_PythonSeq_nextIter(KX_PythonSeq *self)
+{
+       PyObject *object = KX_PythonSeq_getIndex((PyObject *)self, self->iter);
+       
+       self->iter++;
+       if( object==NULL ) {
+               self->iter= -1; /* for reuse */
+               PyErr_SetString(PyExc_StopIteration,    "iterator at end");
+       }
+       return object; /* can be NULL for end of iterator */
+}
+
+
+static int KX_PythonSeq_compare( KX_PythonSeq * a, KX_PythonSeq * b ) /* TODO - python3.x wants richcmp */
+{
+       return ( a->type == b->type && a->base == b->base) ? 0 : -1;    
+}
+
+/*
+ * repr function
+ * convert to a list and get its string value
+ */
+static PyObject *KX_PythonSeq_repr( KX_PythonSeq * self )
+{
+       PyObject *list = PySequence_List((PyObject *)self);
+       PyObject *repr = PyObject_Repr(list);
+       Py_DECREF(list);
+       return repr;
+}
+
+
+/*****************************************************************************/
+/* Python KX_PythonSeq_Type structure definition:                               */
+/*****************************************************************************/
+PyTypeObject KX_PythonSeq_Type = {
+#if (PY_VERSION_HEX >= 0x02060000)
+       PyVarObject_HEAD_INIT(NULL, 0)
+#else
+       /* python 2.5 and below */
+       PyObject_HEAD_INIT( NULL )  /* required py macro */
+       0,                          /* ob_size */
+#endif
+       /*  For printing, in format "<module>.<name>" */
+       "KX_PythonSeq",           /* char *tp_name; */
+       sizeof( KX_PythonSeq ),       /* int tp_basicsize; */
+       0,                          /* tp_itemsize;  For allocation */
+
+       /* Methods to implement standard operations */
+
+       ( destructor ) KX_PythonSeq_dealloc, /* destructor tp_dealloc; */
+       NULL,                       /* printfunc tp_print; */
+       NULL,                       /* getattrfunc tp_getattr; */
+       NULL,                       /* setattrfunc tp_setattr; */
+       ( cmpfunc ) KX_PythonSeq_compare, /* cmpfunc tp_compare; */
+       ( reprfunc ) KX_PythonSeq_repr,   /* reprfunc tp_repr; */
+
+       /* Method suites for standard classes */
+
+       NULL,                       /* PyNumberMethods *tp_as_number; */
+       NULL,       /* PySequenceMethods *tp_as_sequence; */
+       &KX_PythonSeq_as_mapping,                       /* PyMappingMethods *tp_as_mapping; */
+
+       /* More standard operations (here for binary compatibility) */
+
+       NULL,                       /* hashfunc tp_hash; */
+       NULL,                       /* ternaryfunc tp_call; */
+       NULL,                       /* reprfunc tp_str; */
+       NULL,                       /* getattrofunc tp_getattro; */
+       NULL,                       /* setattrofunc tp_setattro; */
+
+       /* Functions to access object as input/output buffer */
+       NULL,                       /* PyBufferProcs *tp_as_buffer; */
+
+  /*** Flags to define presence of optional/expanded features ***/
+       Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
+
+       NULL,                       /*  char *tp_doc;  Documentation string */
+  /*** Assigned meaning in release 2.0 ***/
+       /* call function for all accessible objects */
+       NULL,                       /* traverseproc tp_traverse; */
+
+       /* delete references to contained objects */
+       NULL,                       /* inquiry tp_clear; */
+
+  /***  Assigned meaning in release 2.1 ***/
+  /*** rich comparisons ***/
+       NULL,                       /* richcmpfunc tp_richcompare; */
+
+  /***  weak reference enabler ***/
+       0,                          /* long tp_weaklistoffset; */
+
+  /*** Added in release 2.2 ***/
+       /*   Iterators */
+       ( getiterfunc) KX_PythonSeq_getIter, /* getiterfunc tp_iter; */
+       ( iternextfunc ) KX_PythonSeq_nextIter, /* iternextfunc tp_iternext; */
+
+  /*** Attribute descriptor and subclassing stuff ***/
+       NULL,       /* struct PyMethodDef *tp_methods; */
+       NULL,                       /* struct PyMemberDef *tp_members; */
+       NULL,       /* struct PyGetSetDef *tp_getset; */
+       NULL,                       /* struct _typeobject *tp_base; */
+       NULL,                       /* PyObject *tp_dict; */
+       NULL,                       /* descrgetfunc tp_descr_get; */
+       NULL,                       /* descrsetfunc tp_descr_set; */
+       0,                          /* long tp_dictoffset; */
+       NULL,                       /* initproc tp_init; */
+       NULL,                       /* allocfunc tp_alloc; */
+       NULL,                       /* newfunc tp_new; */
+       /*  Low-level free-memory routine */
+       NULL,                       /* freefunc tp_free;  */
+       /* For PyObject_IS_GC */
+       NULL,                       /* inquiry tp_is_gc;  */
+       NULL,                       /* PyObject *tp_bases; */
+       /* method resolution order */
+       NULL,                       /* PyObject *tp_mro;  */
+       NULL,                       /* PyObject *tp_cache; */
+       NULL,                       /* PyObject *tp_subclasses; */
+       NULL,                       /* PyObject *tp_weaklist; */
+       NULL
+};
diff --git a/source/gameengine/Ketsji/KX_P