#!BPY

"""
Name: 'Stl Batch (.stl)...'
Blender: 236
Group: 'Import'
Tooltip: 'Import Stereo Lithography (.stl) File Format'
"""

__author__ = "Mitch Hughes (lobo)"
__url__ = ("blender", "elysiun", "Author's homepage, http://blender.formworks.co.nz")
__version__ = "0.3"

__bpydoc__ = """\
This script batch imports binary Stereo Lithography files into Blender.

Usage:
    
Add the script to your blender/scripts directory
Execute this script from the "File->Import" menu and choose an STL Batch file,
select a file in the directory you would like to batch import .stl files from.
"""

# +---------------------------------------------------------+
# | Copyright (c) 2005 Mitch Hughes                         |
# | http://blender.formworks.co.nz                          |
# | blender@formworks.co.nz                                 |
# | Feb 19, 2005                                            |
# | Released under the Blender Artistic Licence (BAL)       |
# +---------------------------------------------------------+
# | Batch Import Directory of STL Binary Files (*.stl)      |
# +---------------------------------------------------------+

import Blender, mod_meshtools, os, struct, sys, string
from struct import *
from types import *

from Blender import NMesh, Scene, Object, Draw, Image, BGL
from Blender.Window import *

#Globals

#Detect OS
if (os.name == 'nt'):
    g_working_dir=Draw.Create("c:\\path\\to\\import\\from")
    g_os_separator = '\\'
else:
    g_working_dir=Draw.Create("/path/to/import/from")
    g_os_separator = '/'

#Default Scaling
g_scale=Draw.Create(0.01)

# Events
EVENT_NOEVENT=1
EVENT_LOAD_STL=2
EVENT_CHOOSE_FILENAME=3
EVENT_EXIT=100

######################################################
# Callbacks for Window functions
######################################################
def filename_callback(filename_in_dir):
    global g_working_dir
    # Get the target directory to batch import
    g_working_dir.val=os.path.dirname(filename_in_dir)
    
######################################################
# GUI Loader
# GUI Code taken from Bob Holcomb's ASCII stl_import script and modified
######################################################
def draw_gui():
    global g_scale
    global g_working_dir
    global g_scale_slider
    global EVENT_NOEVENT,EVENT_LOAD_STL,EVENT_CHOOSE_FILENAME,EVENT_EXIT

    ########## Titles
    BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
    BGL.glRasterPos2d(8, 190)
    Draw.Text("            Binary STL Batch Importer         ")
    BGL.glRasterPos2d(8, 170)
    Draw.Text("1) Select a file from the directory you")
    BGL.glRasterPos2d(8, 155)
    Draw.Text("    wish to Batch Import files from")
    
    ######### Parameters GUI Buttons
    g_working_dir = Draw.String("", EVENT_NOEVENT, 10, 130, 250, 18,
                            g_working_dir.val, 255, "Directory to Batch Import")
    ########## stl File Select Button
    Draw.Button("Select",EVENT_CHOOSE_FILENAME,95,110,80,18)
    
    BGL.glRasterPos2d(8, 85)
    Draw.Text("2) Set the desired Scaling Factor")
    
    ########## Scale slider-default is 0.1
    g_scale= Draw.Slider("Scale Factor: ", EVENT_NOEVENT, 10, 60, 250, 18,
                    g_scale.val, 0.001, 10.0, 1, "Scale factor for STL Models");
                    
    BGL.glRasterPos2d(8, 35)
    Draw.Text("3) Press Import")

    ######### Draw and Exit Buttons
    Draw.Button("Import",EVENT_LOAD_STL , 10, 10, 80, 18)
    Draw.Button("Exit",EVENT_EXIT , 180, 10, 80, 18)

def event(evt, val):
    if (evt == Draw.QKEY and not val):
        Draw.Exit()

def bevent(evt):
    global g_working_dir
    global g_material_filename
    global EVENT_NOEVENT,EVENT_LOAD_STL,EVENT_EXIT

    ######### Manages GUI events
    if (evt==EVENT_EXIT):
        Draw.Exit()
    elif (evt==EVENT_CHOOSE_FILENAME):
        FileSelector(filename_callback, "STL File Selection")

    #load the object and materials
    elif (evt==EVENT_LOAD_STL):
        if (g_working_dir.val == "/path/to/import/from"):
            Draw.Exit()
        else:
            iterate_directory(g_working_dir.val)
            Blender.Redraw()
            Draw.Exit()
            

######################################################
# Read STL Triangle Format
######################################################

def read_file(filename):
    global g_scale
    
    file = open(filename, "rb")
    
    #80 Any text such as the creator's name
    header = unpack("<80s", file.read(80))
    
    #4 int equal to the number of facets in file
    facets = unpack("i", file.read(4))
    
    # Collect vert data from RAW format
    faces = []
    for i in range(0, facets[0]):
        n_x = unpack("f", file.read(4))
        n_y = unpack("f", file.read(4))
        n_z = unpack("f", file.read(4))
        v1_x = unpack("f", file.read(4))
        v1_y = unpack("f", file.read(4))
        v1_z = unpack("f", file.read(4))
        v2_x = unpack("f", file.read(4))
        v2_y = unpack("f", file.read(4))
        v2_z = unpack("f", file.read(4))
        v3_x = unpack("f", file.read(4))
        v3_y = unpack("f", file.read(4))
        v3_z = unpack("f", file.read(4))
        unused = file.read(2)
        
        faces.append([(v1_x[0]*g_scale.val, v1_y[0]*g_scale.val, v1_z[0]*g_scale.val), (v2_x[0]*g_scale.val, v2_y[0]*g_scale.val, v2_z[0]*g_scale.val), (v3_x[0]*g_scale.val, v3_y[0]*g_scale.val, v3_z[0]*g_scale.val)])
    file.close()
    
    # The fine piece of code below for eliminating duplicate verts
    # and creating the object in blender was copied directly from
    # the slp import export script written by
    # Anthony D'Agostino (Scorpius)
    # Generate verts and faces lists, without duplicates
    verts = []
    coords = {}
    index = 0
    for i in range(len(faces)):
        for j in range(len(faces[i])):
            vertex = faces[i][j]
            if not coords.has_key(vertex):
                coords[vertex] = index
                index += 1
                verts.append(vertex)
            faces[i][j] = coords[vertex]

    objname = Blender.sys.splitext(Blender.sys.basename(filename))[0]

    mod_meshtools.create_mesh(verts, faces, objname)
    Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
    
    print "Successfully imported " + Blender.sys.basename(filename)

######################################################
# Read Files in Directory
######################################################

def iterate_directory(working_dir):
    #Check for stl extension so we dont try and 
    #import other files in the directory
    #stl_extension = re.compile('\.stl$', re.IGNORECASE)
    
    for file_name in os.listdir (working_dir):
        if string.rfind(string.lower(file_name), '.stl')>0:
            read_file(working_dir+g_os_separator+file_name)
        else:
            print "Omitting "+file_name

    
#def fs_callback(filename_in_dir):
#    iterate_directory(filename_in_dir)
#Blender.Window.FileSelector(fs_callback, "Batch STL")

Draw.Register(draw_gui, event, bevent)

