BPython:
authorWillian Padovani Germano <wpgermano@gmail.com>
Wed, 28 Jan 2004 19:16:50 +0000 (19:16 +0000)
committerWillian Padovani Germano <wpgermano@gmail.com>
Wed, 28 Jan 2004 19:16:50 +0000 (19:16 +0000)
-- fixing a last minute bug: scripts w/o guis that called the file selector were
   not being checked for errors, which could cause crash dumps upon exiting.
-- docs: updates for Draw (fixed example) and Material (added tex related methods docs)

Scripts:
-- added some more scripts, all I could get in shape in time (at least they export / import back).
   Only tested on linux.

13 files changed:
release/scripts/mod_flags.py [new file with mode: 0644]
release/scripts/mod_meshtools.py [new file with mode: 0644]
release/scripts/off_export.py [new file with mode: 0644]
release/scripts/off_import.py [new file with mode: 0644]
release/scripts/radiosity_export.py [new file with mode: 0644]
release/scripts/radiosity_import.py [new file with mode: 0644]
release/scripts/raw_export.py [new file with mode: 0644]
release/scripts/raw_import.py [new file with mode: 0644]
release/scripts/videoscape_export.py [new file with mode: 0644]
release/scripts/wrl2export.py [new file with mode: 0644]
source/blender/python/BPY_interface.c
source/blender/python/api2_2x/doc/Draw.py
source/blender/python/api2_2x/doc/Material.py

diff --git a/release/scripts/mod_flags.py b/release/scripts/mod_flags.py
new file mode 100644 (file)
index 0000000..810a510
--- /dev/null
@@ -0,0 +1,19 @@
+# +---------------------------------------------------------+
+# | Copyright (c) 2002 Anthony D'Agostino                   |
+# | http://ourworld.compuserve.com/homepages/scorpius       |
+# | scorpius@compuserve.com                                 |
+# | October 25, 2002                                        |
+# | Released under the Blender Artistic Licence (BAL)       |
+# | Import Export Suite v0.5                                |
+# +---------------------------------------------------------+
+# | Share Global Variables Across Modules                   |
+# +---------------------------------------------------------+
+
+import Blender
+
+blender_version = Blender.Get('version')
+blender_version_str = `blender_version`[0] + '.' + `blender_version`[1:]
+
+show_progress = 1                      # Set to 0 for faster performance
+average_vcols = 1                      # Off for per-face, On for per-vertex
+overwrite_mesh_name = 0        # Set to 0 for safety
diff --git a/release/scripts/mod_meshtools.py b/release/scripts/mod_meshtools.py
new file mode 100644 (file)
index 0000000..dbcdab5
--- /dev/null
@@ -0,0 +1,178 @@
+# +---------------------------------------------------------+
+# | Copyright (c) 2001 Anthony D'Agostino                   |
+# | http://ourworld.compuserve.com/homepages/scorpius       |
+# | scorpius@compuserve.                                    |
+# | September 28, 2002                                      |
+# | Released under the Blender Artistic Licence (BAL)       |
+# | Import Export Suite v0.5                                |
+# +---------------------------------------------------------+
+# | Common Functions For All Modules                        |
+# +---------------------------------------------------------+
+
+import Blender
+import sys#, random, operator
+import mod_flags
+
+try:
+       import random, operator
+# ===================================
+# ==== Append Faces To Face List ====
+# ===================================
+       def append_faces(mesh, faces, facesuv, uvcoords):
+               r = random.randrange(200, 255, 50)
+               g = random.randrange(100, 200, 50)
+               b = random.randrange(0, 100, 50)
+               for i in range(len(faces)):
+                       if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(faces), "Generating Faces")
+                       numfaceverts=len(faces[i])
+                       if numfaceverts <= 4:                           # This face is a triangle or quad
+                               face = Blender.NMesh.Face()
+                               for j in range(numfaceverts):
+                                       index = faces[i][j]
+                                       face.v.append(mesh.verts[index])
+                                       if len(uvcoords) > 1:
+                                               uvidx = facesuv[i][j]
+                                               face.uv.append(uvcoords[uvidx])
+                                               face.mode = 0
+                                               #face.col = [Blender.NMesh.Col(r, g, b)]*4       # Random color
+                                               face.col = [Blender.NMesh.Col()]*4
+                               mesh.faces.append(face)
+                       else:                                                           # Triangulate n-sided convex polygon.
+                               a, b, c = 0, 1, 2                               # Indices of first triangle.
+                               for j in range(numfaceverts-2): # Number of triangles in polygon.
+                                       face = Blender.NMesh.Face()
+                                       face.v.append(mesh.verts[faces[i][a]])
+                                       face.v.append(mesh.verts[faces[i][b]])
+                                       face.v.append(mesh.verts[faces[i][c]])
+                                       b = c; c += 1
+                                       mesh.faces.append(face)
+                       #face.smooth = 1
+
+# =====================================
+# ==== Append Verts to Vertex List ====
+# =====================================
+       def append_verts(mesh, verts, normals):
+               #print "Number of normals:", len(normals)
+               #print "Number of verts  :", len(verts)
+               for i in range(len(verts)):
+                       if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(verts), "Generating Verts")
+                       x, y, z = verts[i]
+                       mesh.verts.append(Blender.NMesh.Vert(x, y, z))
+                       if normals:
+                               mesh.verts[i].no[0] = normals[i][0]
+                               mesh.verts[i].no[1] = normals[i][1]
+                               mesh.verts[i].no[2] = normals[i][2]
+
+# =============================
+# ==== Create Blender Mesh ====
+# =============================
+       def create_mesh(verts, faces, objname, facesuv=[], uvcoords=[], normals=[]):
+               if normals: normal_flag = 0
+               else: normal_flag = 1
+               mesh = Blender.NMesh.GetRaw()
+               append_verts(mesh, verts, normals)
+               append_faces(mesh, faces, facesuv, uvcoords)
+               if not mod_flags.overwrite_mesh_name:
+                       objname = versioned_name(objname)
+               Blender.NMesh.PutRaw(mesh, objname, normal_flag)        # Name the Mesh
+               Blender.Object.GetSelected()[0].name=objname            # Name the Object
+               Blender.Redraw()
+
+except ImportError: pass
+
+# ================================
+# ==== Increment Name Version ====
+# ================================
+def versioned_name(objname):
+       existing_names = []
+       for object in Blender.Object.Get():
+               existing_names.append(object.name)
+               existing_names.append(object.data.name)
+       if objname in existing_names: # don't over-write other names
+               try:
+                       name, ext = objname.split('.')
+               except ValueError:
+                       name, ext = objname, ''
+               try:
+                       num = int(ext)
+                       root = name
+               except ValueError:
+                       root = objname
+               for i in xrange(1, 1000):
+                       objname = "%s.%03d" % (root, i)
+                       if objname not in existing_names:
+                               break
+       return objname
+
+# =============================
+# ==== Print Text In A Box ====
+# =============================
+def print_boxed(text):
+       lines = text.splitlines()
+       maxlinelen = max(map(len, lines))
+       print '+-' + '-'*maxlinelen + '-+'
+       for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
+       print '+-' + '-'*maxlinelen + '-+'
+
+       print '\a\r', # beep when done
+
+# =================================================
+# ==== Get Euler Angles From A Rotation Matrix ====
+# =================================================
+#def mat2euler(mat):
+#      angle_y = -math.asin(mat[0][2])
+#      c = math.cos(angle_y)
+#      if math.fabs(c) > 0.005:
+#              angle_x = math.atan2(mat[1][2]/c, mat[2][2]/c)
+#              angle_z = math.atan2(mat[0][1]/c, mat[0][0]/c)
+#      else:
+#              angle_x = 0.0
+#              angle_z = -math.atan2(mat[1][0], mat[1][1])
+#      return (angle_x, angle_y, angle_z)
+
+# ============================
+# ==== Transpose A Matrix ====
+# ============================
+def transpose(A):
+       S = len(A)
+       T = len(A[0])
+       B = [[None]*S for i in range(T)]
+       for i in range(T):
+               for j in range(S):
+                       B[i][j] = A[j][i]
+       return B
+
+#def append_ntimes(Seq, N):
+#      Seq = reduce(operator.add, Seq)   # Flatten once
+#      if N == 1: return Seq
+#      return append_ntimes(Seq, N-1)
+
+
+
+#      print "mesh.has_col           ", mesh.has_col
+#      print "mesh.hasVertexColours()", mesh.hasVertexColours()
+#      print "mesh.hasFaceUV()       ", mesh.hasFaceUV()
+#      print "mesh.has_uvco          ", mesh.has_uvco
+
+# # =============================
+# # ==== Create Blender Mesh ====
+# # =============================
+# def create_mesh_old(verts, faces, objname):
+#      mesh = Blender.NMesh.GetRaw()
+#      # === Vertex List ===
+#      for i in range(len(verts)):
+#              x, y, z = verts[i]
+#              mesh.verts.append(Blender.NMesh.Vert(x, y ,z))
+#      # === Face List ===
+#      for i in range(len(faces)):
+#              face = Blender.NMesh.Face()
+#              for j in range(len(faces[i])):
+#                      index = faces[i][j]
+#                      face.v.append(mesh.verts[index])
+#              mesh.faces.append(face)
+#      # === Name the Object ===
+#      Blender.NMesh.PutRaw(mesh, objname)
+#      object = Blender.Object.GetSelected()
+#      object[0].name=objname
+#      Blender.Redraw()
+
diff --git a/release/scripts/off_export.py b/release/scripts/off_export.py
new file mode 100644 (file)
index 0000000..9648c1c
--- /dev/null
@@ -0,0 +1,72 @@
+#!BPY
+
+"""
+Name: 'OFF...'
+Blender: 232
+Group: 'Export'
+Tooltip: 'Export selected mesh to Object File Format (*.off)'
+"""
+
+# +---------------------------------------------------------+
+# | Copyright (c) 2002 Anthony D'Agostino                   |
+# | http://ourworld.compuserve.com/homepages/scorpius       |
+# | scorpius@compuserve.com                                 |
+# | February 3, 2001                                        |
+# | Released under the Blender Artistic Licence (BAL)       |
+# | Import Export Suite v0.5                                |
+# +---------------------------------------------------------+
+# | Read and write Object File Format (*.off)               |
+# +---------------------------------------------------------+
+
+import Blender
+#import time
+import mod_flags, mod_meshtools
+
+# ==============================
+# ====== Write OFF Format ======
+# ==============================
+def write(filename):
+       #start = time.clock()
+       file = open(filename, "wb")
+
+       objects = Blender.Object.GetSelected()
+       objname = objects[0].name
+       meshname = objects[0].data.name
+       mesh = Blender.NMesh.GetRaw(meshname)
+       #mesh = Blender.NMesh.GetRawFromObject(meshname)        # for SubSurf
+       obj = Blender.Object.Get(objname)
+
+       # === OFF Header ===
+       file.write("OFF\n")
+       file.write("%d %d %d\n" % (len(mesh.verts), len(mesh.faces), 0))
+
+       # === Vertex List ===
+       for i in range(len(mesh.verts)):
+               if not i%100 and mod_flags.show_progress:
+                       Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts")
+               x, y, z = mesh.verts[i].co
+               file.write("%f %f %f\n" % (x, y, z))
+
+       # === Face List ===
+       for i in range(len(mesh.faces)):
+               if not i%100 and mod_flags.show_progress:
+                       Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces")
+               file.write(`len(mesh.faces[i].v)`+' ')
+               mesh.faces[i].v.reverse()
+               for j in range(len(mesh.faces[i].v)):
+                       file.write(`mesh.faces[i].v[j].index`+' ')
+               file.write("\n")
+
+
+       Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
+       file.close()
+       #end = time.clock()
+       #seconds = " in %.2f %s" % (end-start, "seconds")
+       message = "Successfully exported " + Blender.sys.basename(filename)# + seconds
+       mod_meshtools.print_boxed(message)
+
+def fs_callback(filename):
+       if filename.find('.off', -4) <= 0: filename += '.off'
+       write(filename)
+
+Blender.Window.FileSelector(fs_callback, "OFF Export")
diff --git a/release/scripts/off_import.py b/release/scripts/off_import.py
new file mode 100644 (file)
index 0000000..9f7fd5e
--- /dev/null
@@ -0,0 +1,75 @@
+#!BPY
+
+"""
+Name: 'OFF...'
+Blender: 232
+Group: 'Import'
+Tooltip: 'Import Object File Format (*.off)'
+"""
+
+# +---------------------------------------------------------+
+# | Copyright (c) 2002 Anthony D'Agostino                   |
+# | http://ourworld.compuserve.com/homepages/scorpius       |
+# | scorpius@compuserve.com                                 |
+# | February 3, 2001                                        |
+# | Released under the Blender Artistic Licence (BAL)       |
+# | Import Export Suite v0.5                                |
+# +---------------------------------------------------------+
+# | Read and write Object File Format (*.off)               |
+# +---------------------------------------------------------+
+
+import Blender
+#import time
+import mod_flags, mod_meshtools
+
+# =============================
+# ====== Read OFF Format ======
+# =============================
+def read(filename):
+       #start = time.clock()
+       file = open(filename, "rb")
+
+       verts = []
+       faces = []
+
+       # === OFF Header ===
+       offheader = file.readline()
+       numverts, numfaces, null = file.readline().split()
+       numverts = int(numverts)
+       numfaces = int(numfaces)
+
+       # === Vertex List ===
+       for i in range(numverts):
+               if not i%100 and mod_flags.show_progress:
+                       Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts")
+               x, y, z = file.readline().split()
+               x, y, z = float(x), float(y), float(z)
+               verts.append((x, y, z))
+
+       # === Face List ===
+       for i in range(numfaces):
+               if not i%100 and mod_flags.show_progress:
+                       Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces")
+               line = file.readline().split()
+               numfaceverts = len(line)-1
+               facev = []
+               for j in range(numfaceverts):
+                       index = int(line[j+1])
+                       facev.append(index)
+               facev.reverse()
+               faces.append(facev)
+
+       objname = Blender.sys.splitext(Blender.sys.basename(filename))[0]
+
+       mod_meshtools.create_mesh(verts, faces, objname)
+       Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
+       file.close()
+       #end = time.clock()
+       #seconds = " in %.2f %s" % (end-start, "seconds")
+       message = "Successfully imported " + Blender.sys.basename(filename)# + seconds
+       mod_meshtools.print_boxed(message)
+
+def fs_callback(filename):
+       read(filename)
+
+Blender.Window.FileSelector(fs_callback, "OFF Import")
diff --git a/release/scripts/radiosity_export.py b/release/scripts/radiosity_export.py
new file mode 100644 (file)
index 0000000..f87f8a1
--- /dev/null
@@ -0,0 +1,89 @@
+#!BPY
+
+"""
+Name: 'Radiosity...'
+Blender: 232
+Group: 'Export'
+Tooltip: 'Export selected mesh (with vertex colors) to Radiosity File Format (*.radio)'
+"""
+
+# +---------------------------------------------------------+
+# | Copyright (c) 2002 Anthony D'Agostino                   |
+# | http://ourworld.compuserve.com/homepages/scorpius       |
+# | scorpius@compuserve.com                                 |
+# | April 11, 2002                                          |
+# | Released under the Blender Artistic Licence (BAL)       |
+# | Import Export Suite v0.5                                |
+# +---------------------------------------------------------+
+# | Read and write Radiosity File Format (*.radio)          |
+# +---------------------------------------------------------+
+
+import Blender
+#import time
+import mod_flags, mod_meshtools
+try:
+       import struct
+except:
+       msg = "Error: you need a full Python install to run this script."
+       mod_meshtools.print_boxed(msg)
+
+# ================================
+# ====== Write Radio Format ======
+# ================================
+def write(filename):
+       #start = time.clock()
+       file = open(filename, "wb")
+
+       objects = Blender.Object.GetSelected()
+       objname = objects[0].name
+       meshname = objects[0].data.name
+       mesh = Blender.NMesh.GetRaw(meshname)
+       obj = Blender.Object.Get(objname)
+
+       if not mesh.hasVertexColours():
+               message = "Please assign vertex colors before exporting.\n"
+               message += objname + " object was not saved."
+               mod_meshtools.print_boxed(message)
+               return
+
+       # === Object Name ===
+       file.write(struct.pack("<h", len(objname)))
+       file.write(struct.pack("<"+`len(objname)`+"s", objname))
+
+       # === Vertex List ===
+       file.write(struct.pack("<l", len(mesh.verts)))
+       for i in range(len(mesh.verts)):
+               if not i%100 and mod_flags.show_progress:
+                       Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts")
+
+               x, y, z = mesh.verts[i].co
+               file.write(struct.pack("<fff", x, y, z))
+
+       # === Face List ===
+       file.write(struct.pack("<l", len(mesh.faces)))
+       for i in range(len(mesh.faces)):
+               if not i%100 and mod_flags.show_progress:
+                       Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces")
+
+               file.write(struct.pack("<b", len(mesh.faces[i].v)))
+               for j in range(len(mesh.faces[i].v)):
+                       file.write(struct.pack("<h", mesh.faces[i].v[j].index))
+
+               for j in range(4): # .col always has a length of 4
+                       file.write(struct.pack("<BBBB", mesh.faces[i].col[j].r,
+                                                                                       mesh.faces[i].col[j].g,
+                                                                                       mesh.faces[i].col[j].b,
+                                                                                       mesh.faces[i].col[j].a))
+
+       Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
+       file.close()
+       #end = time.clock()
+       #seconds = " in %.2f %s" % (end-start, "seconds")
+       message = "Successfully exported " + Blender.sys.basename(filename)# + seconds
+       mod_meshtools.print_boxed(message)
+
+def fs_callback(filename):
+       if filename.find('.radio', -6) <= 0: filename += '.radio'
+       write(filename)
+
+Blender.Window.FileSelector(fs_callback, "Radio Export")
diff --git a/release/scripts/radiosity_import.py b/release/scripts/radiosity_import.py
new file mode 100644 (file)
index 0000000..d2e784b
--- /dev/null
@@ -0,0 +1,93 @@
+#!BPY
+
+"""
+Name: 'Radiosity...'
+Blender: 232
+Group: 'Import'
+Tooltip: 'Import Radiosity File Format (*.radio) with vertex colors'
+"""
+
+# +---------------------------------------------------------+
+# | Copyright (c) 2002 Anthony D'Agostino                   |
+# | http://ourworld.compuserve.com/homepages/scorpius       |
+# | scorpius@compuserve.com                                 |
+# | April 11, 2002                                          |
+# | Released under the Blender Artistic Licence (BAL)       |
+# | Import Export Suite v0.5                                |
+# +---------------------------------------------------------+
+# | Read and write Radiosity File Format (*.radio)          |
+# +---------------------------------------------------------+
+
+import Blender
+#import time
+import mod_flags, mod_meshtools
+try:
+       import struct
+except:
+       msg = "Error: you need a full Python install to run this script."
+       mod_meshtools.print_boxed(msg)
+
+# ===============================
+# ====== Read Radio Format ======
+# ===============================
+def read(filename):
+       #start = time.clock()
+       file = open(filename, "rb")
+       mesh = Blender.NMesh.GetRaw()
+       mesh.addMaterial(Blender.Material.New())
+
+       # === Object Name ===
+       namelen, = struct.unpack("<h",  file.read(2))
+       objname, = struct.unpack("<"+`namelen`+"s", file.read(namelen))
+
+       # === Vertex List ===
+       numverts, = struct.unpack("<l", file.read(4))
+       for i in range(numverts):
+               if not i%100 and mod_flags.show_progress:
+                       Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts")
+               x, y, z = struct.unpack("<fff", file.read(12))
+               mesh.verts.append(Blender.NMesh.Vert(x, y, z))
+
+       # === Face List ===
+       numfaces, = struct.unpack("<l", file.read(4))
+       for i in range(numfaces):
+               if not i%100 and mod_flags.show_progress:
+                       Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces")
+
+               face = Blender.NMesh.Face()
+               numfaceverts, = struct.unpack("<b", file.read(1))
+
+               for j in range(numfaceverts):
+                       index, = struct.unpack("<h", file.read(2))
+                       face.v.append(mesh.verts[index])
+
+               for j in range(4):
+                       r, g, b, a = struct.unpack("<BBBB", file.read(4))
+                       vertexcolor = Blender.NMesh.Col(r, g, b, a)
+                       face.col.append(vertexcolor)
+
+               if len(face.v) == 3:
+                       face.uv = [ (0,0), (0,1), (1,1) ]
+               else:
+                       face.uv = [ (0,0), (0,1), (1,1), (1,0) ]
+
+               face.mode = 0
+               mesh.faces.append(face)
+
+       # ->tools.create_mesh(verts, faces, objname):
+       Blender.NMesh.PutRaw(mesh, objname)
+       object = Blender.Object.GetSelected()
+       object[0].name=objname
+       # ->tools.create_mesh(verts, faces, objname):
+
+       Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
+       file.close()
+       #end = time.clock()
+       #seconds = " in %.2f %s" % (end-start, "seconds")
+       message = "Successfully imported " + Blender.sys.basename(filename)# + seconds
+       mod_meshtools.print_boxed(message)
+
+def fs_callback(filename):
+       read(filename)
+
+Blender.Window.FileSelector(fs_callback, "Radio Import")
diff --git a/release/scripts/raw_export.py b/release/scripts/raw_export.py
new file mode 100644 (file)
index 0000000..809f6e2
--- /dev/null
@@ -0,0 +1,66 @@
+#!BPY
+
+"""
+Name: 'Raw Triangle...'
+Blender: 232
+Group: 'Export'
+Tooltip: 'Export selected mesh to Raw Triangle Format (*.raw)'
+"""
+
+# +---------------------------------------------------------+
+# | Copyright (c) 2002 Anthony D'Agostino                   |
+# | http://ourworld.compuserve.com/homepages/scorpius       |
+# | scorpius@compuserve.com                                 |
+# | April 28, 2002                                          |
+# | Released under the Blender Artistic Licence (BAL)       |
+# | Import Export Suite v0.5                                |
+# +---------------------------------------------------------+
+# | Read and write RAW Triangle File Format (*.raw)         |
+# +---------------------------------------------------------+
+
+import Blender, sys
+#import time
+import mod_flags, mod_meshtools
+
+# ===================================
+# ==== Write RAW Triangle Format ====
+# ===================================
+def write(filename):
+       #start = time.clock()
+       file = open(filename, "wb")
+
+       objects = Blender.Object.GetSelected()
+       objname = objects[0].name
+       meshname = objects[0].data.name
+       mesh = Blender.NMesh.GetRaw(meshname)
+       obj = Blender.Object.Get(objname)
+
+
+       std=sys.stdout
+       sys.stdout=file
+       for face in mesh.faces:
+               if len(face.v) == 3:            # triangle
+                       v1, v2, v3 = face.v
+                       faceverts = tuple(v1.co) + tuple(v2.co) + tuple(v3.co)
+                       print "% f % f % f % f % f % f % f % f % f" % faceverts
+               else:                                           # quadrilateral
+                       v1, v2, v3, v4 = face.v
+                       faceverts1 = tuple(v1.co) + tuple(v2.co) + tuple(v3.co)
+                       faceverts2 = tuple(v3.co) + tuple(v4.co) + tuple(v1.co)
+                       print "% f % f % f % f % f % f % f % f % f" % faceverts1
+                       print "% f % f % f % f % f % f % f % f % f" % faceverts2
+       sys.stdout=std
+
+
+       Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
+       file.close()
+       #end = time.clock()
+       #seconds = " in %.2f %s" % (end-start, "seconds")
+       message = "Successfully exported " + Blender.sys.basename(filename)# + seconds
+       mod_meshtools.print_boxed(message)
+
+def fs_callback(filename):
+       if filename.find('.raw', -4) <= 0: filename += '.raw'
+       write(filename)
+
+Blender.Window.FileSelector(fs_callback, "Raw Export")
diff --git a/release/scripts/raw_import.py b/release/scripts/raw_import.py
new file mode 100644 (file)
index 0000000..c080d02
--- /dev/null
@@ -0,0 +1,68 @@
+#!BPY
+
+"""
+Name: 'Raw Triangle...'
+Blender: 232
+Group: 'Import'
+Tooltip: 'Import Raw Triangle File Format (*.raw)'
+"""
+
+# +---------------------------------------------------------+
+# | Copyright (c) 2002 Anthony D'Agostino                   |
+# | http://ourworld.compuserve.com/homepages/scorpius       |
+# | scorpius@compuserve.com                                 |
+# | April 28, 2002                                          |
+# | Released under the Blender Artistic Licence (BAL)       |
+# | Import Export Suite v0.5                                |
+# +---------------------------------------------------------+
+# | Read and write RAW Triangle File Format (*.raw)         |
+# +---------------------------------------------------------+
+
+import Blender
+#import time
+import mod_flags, mod_meshtools
+
+# ==================================
+# ==== Read RAW Triangle Format ====
+# ==================================
+def read(filename):
+       #start = time.clock()
+       file = open(filename, "rb")
+
+       # Collect data from RAW format
+       faces = []
+       for line in file.readlines():
+               try:
+                       f1, f2, f3, f4, f5, f6, f7, f8, f9 = map(float, line.split())
+                       faces.append([(f1, f2, f3), (f4, f5, f6), (f7, f8, f9)])
+               except: # Quad
+                       f1, f2, f3, f4, f5, f6, f7, f8, f9, A, B, C = map(float, line.split())
+                       faces.append([(f1, f2, f3), (f4, f5, f6), (f7, f8, f9), (A, B, C)])
+
+       # 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
+       file.close()
+       #end = time.clock()
+       #seconds = " in %.2f %s" % (end-start, "seconds")
+       message = "Successfully imported " + Blender.sys.basename(filename)# + seconds
+       mod_meshtools.print_boxed(message)
+
+def fs_callback(filename):
+       read(filename)
+
+Blender.Window.FileSelector(fs_callback, "Raw Import")
diff --git a/release/scripts/videoscape_export.py b/release/scripts/videoscape_export.py
new file mode 100644 (file)
index 0000000..6f7b084
--- /dev/null
@@ -0,0 +1,232 @@
+#!BPY
+
+"""
+Name: 'Videoscape (with Vertex Colors)...'
+Blender: 232
+Group: 'Export'
+Tooltip: 'Export selected mesh to VideoScape File Format (*.obj)'
+"""
+
+# +---------------------------------------------------------+
+# | Copyright (c) 2001 Anthony D'Agostino                   |
+# | http://ourworld.compuserve.com/homepages/scorpius       |
+# | scorpius@compuserve.com                                 |
+# | June 5, 2001                                            |
+# | Released under the Blender Artistic Licence (BAL)       |
+# | Import Export Suite v0.5                                |
+# +---------------------------------------------------------+
+# | Write Videoscape File Format (*.obj NOT WAVEFRONT OBJ)  |
+# | Includes a *fast* algorithm for averaging vertex colors |
+# | Blender's a|w doesn't export proper vertex colors       |
+# +---------------------------------------------------------+
+
+import Blender, mod_meshtools
+#import time
+import mod_flags
+
+# =====================================
+# ====== Write VideoScape Format ======
+# =====================================
+def write(filename):
+       #start = time.clock()
+       file = open(filename, "wb")
+
+       objects = Blender.Object.GetSelected()
+       objname = objects[0].name
+       meshname = objects[0].data.name
+       mesh = Blender.NMesh.GetRaw(meshname)
+       obj = Blender.Object.Get(objname)
+
+       if not mesh.hasVertexColours():
+               message = "Please assign vertex colors before exporting.\n"
+               message += objname + " object was not saved."
+               mod_meshtools.print_boxed(message)
+               return
+
+       vcols = average_vertexcolors(mesh)
+
+       # === Write Videoscape Header ===
+       file.write("GOUR\n")
+       file.write("%d\n" % len(mesh.verts))
+
+       # === Write Vertex List & Vertex Colors ===
+       for i in range(len(mesh.verts)):
+               if not i%100 and mod_flags.show_progress:
+                       Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts")
+               file.write("% f % f % f 0x" % tuple(mesh.verts[i].co))
+               for j in range(len(vcols[i])):
+                       file.write("%02X" % vcols[i][j])
+               file.write("\n")
+
+       # === Write Face List ===
+       for i in range(len(mesh.faces)):
+               if not i%100 and mod_flags.show_progress:
+                       Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces")
+               file.write("%d " % len(mesh.faces[i].v)) # numfaceverts
+               for j in range(len(mesh.faces[i].v)):
+                       file.write("%d " % mesh.faces[i].v[j].index)
+               file.write("\n")
+
+       Blender.Window.DrawProgressBar(1.0, '')    # clear progressbar
+       file.close()
+       #end = time.clock()
+       #seconds = " in %.2f %s" % (end-start, "seconds")
+       message = "Successfully exported " + Blender.sys.basename(filename)# + seconds
+       mod_meshtools.print_boxed(message)
+
+# ===========================================
+# === Vector Operations for Vertex Colors ===
+# ===========================================
+vcolor_add = lambda u, v: [u[0]+v[0], u[1]+v[1], u[2]+v[2], u[3]+v[3]]
+vcolor_div = lambda u, s: [u[0]/s, u[1]/s, u[2]/s, u[3]/s]
+
+# ========================================
+# === Average All Vertex Colors (Fast) ===
+# ========================================
+def average_vertexcolors(mesh, debug=0):
+       vertexcolors = {}
+       for i in range(len(mesh.faces)):        # get all vcolors that share this vertex
+               if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Finding Shared VColors")
+               for j in range(len(mesh.faces[i].v)):
+                       index = mesh.faces[i].v[j].index
+                       color = mesh.faces[i].col[j]
+                       r,g,b,a = color.r, color.g, color.b, color.a
+                       vertexcolors.setdefault(index, []).append([r,g,b,a])
+       if debug: print 'before'; vcprint(vertexcolors)
+
+       for i in range(len(vertexcolors)):      # average them
+               if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors")
+               vcolor = [0,0,0,0]      # rgba
+               for j in range(len(vertexcolors[i])):
+                       vcolor = vcolor_add(vcolor, vertexcolors[i][j])
+               shared = len(vertexcolors[i])
+               vertexcolors[i] = vcolor_div(vcolor, shared)
+       if debug: print 'after'; vcprint(vertexcolors)
+       return vertexcolors
+
+# ========================================
+# === Average all Vertex Colors Slow 1 ===
+# ========================================
+def average_vertexcolors_slow_1(mesh, debug=0):
+       vertexcolors = []
+       i = 0
+       for vertex in mesh.verts:
+               if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors")
+               i += 1
+               vcolor = [0,0,0,0]      # rgba
+               shared = 0
+               for face in mesh.faces:
+                       if vertex in face.v:
+                               index = face.v.index(vertex)
+                               color = face.col[index]
+                               r,g,b,a = color.r, color.g, color.b, color.a
+                               vcolor = vcolor_add(vcolor, [r,g,b,a])
+                               shared += 1
+               if not shared: print "Error, vertex %d is not shared." % i; shared += 1
+               vertexcolors.append(vcolor_div(vcolor, shared))
+       if debug: print 'after'; vcprint(vertexcolors)
+       return vertexcolors
+
+# ========================================
+# === Average all Vertex Colors Slow 2 ===
+# ========================================
+def average_vertexcolors_slow_2(mesh, debug=0):
+       vertexcolors = []
+       for i in range(len(mesh.verts)):
+               if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors")
+               vcolor = [0,0,0,0]      # rgba
+               shared = 0
+               for j in range(len(mesh.faces)):
+                       if mesh.verts[i] in mesh.faces[j].v:
+                               index = mesh.faces[j].v.index(mesh.verts[i])
+                               color = mesh.faces[j].col[index]
+                               r,g,b,a = color.r, color.g, color.b, color.a
+                               vcolor = vcolor_add(vcolor, [r,g,b,a])
+                               shared += 1
+               vertexcolors.append(vcolor_div(vcolor, shared))
+       if debug: print 'after'; vcprint(vertexcolors)
+       return vertexcolors
+
+# ========================================
+# === Average all Vertex Colors Slow 3 ===
+# ========================================
+def average_vertexcolors_slow_3(mesh, debug=0):
+       vertexcolors = []
+       for i in range(len(mesh.verts)):
+               if not i%100 and mod_flags.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors")
+               vcolor = [0,0,0,0]      # rgba
+               shared = 0
+               for j in range(len(mesh.faces)):
+                       if len(mesh.faces[j].v) == 4:
+                               v1,v2,v3,v4 = mesh.faces[j].v
+                               faceverts = v1.index, v2.index, v3.index, v4.index
+                       else:
+                               v1,v2,v3 = mesh.faces[j].v
+                               faceverts = v1.index, v2.index, v3.index
+
+                       if i in faceverts:
+                               index = mesh.faces[j].v.index(mesh.verts[i])
+                               color = mesh.faces[j].col[index]
+                               r,g,b,a = color.r, color.g, color.b, color.a
+                               vcolor = vcolor_add(vcolor, [r,g,b,a])
+                               shared += 1
+               vertexcolors.append(vcolor_div(vcolor, shared))
+       if debug: print 'after'; vcprint(vertexcolors)
+       return vertexcolors
+
+def fs_callback(filename):
+       if filename.find('.obj', -4) <= 0: filename += '.VIDEOSCAPE.obj'
+       write(filename)
+
+Blender.Window.FileSelector(fs_callback, "Videoscape Export")
+
+
+# filename = "VIDEOSCAPE_" + objname + ".obj"
+# filename = 'nul'
+# file = open(filename, "wb")
+# debug = 0
+# time_functions = 1
+# time_loop = 0
+#
+# if time_functions:
+#        funcs = [ average_vertexcolors,
+#                              average_vertexcolors_slow_1,
+#                              average_vertexcolors_slow_2,
+#                              average_vertexcolors_slow_3 ]
+#
+#        print
+#        for func in funcs:
+#                start = time.clock()
+#                vcols = func(mesh, debug)
+#                end = time.clock()
+#                seconds = "in %.2f %s" % (end-start, "seconds")
+#                print func.__name__, "finished in", seconds
+#
+# elif time_loop:
+#        total = 0
+#        loops = 6
+#        for i in range(loops):
+#                start = time.clock()
+#                vcols = average_vertexcolors(mesh, debug)
+#                end = time.clock()
+#                total += (end-start)
+#        print "Total: %5.2f Avg: %.2f " % (total, total/loops)
+# else:
+#        start = time.clock()
+#        vcols = average_vertexcolors(mesh, debug)
+
+# # =====================================
+# # === Print Vertex Colors for Debug ===
+# # =====================================
+# def vcprint(data):
+#        print type(data)
+#        for i in range(len(data)):
+#                print "%2d" % i,
+#                for j in range(len(data[i])):
+#                        try:
+#                                print "[%3d %3d %3d %3d]" % tuple(data[i][j]),  # before
+#                        except:
+#                                print "[%3d]" % data[i][j],                     # after
+#                print
+#        print
+#
diff --git a/release/scripts/wrl2export.py b/release/scripts/wrl2export.py
new file mode 100644 (file)
index 0000000..b45f8e3
--- /dev/null
@@ -0,0 +1,984 @@
+#!BPY
+""" Registration info for Blender menus:
+Name: 'VRML 2.0'
+Blender: 232
+Group: 'Export'
+Submenu: 'All objects...' all
+Submenu: 'Only selected objects...' selected
+Tooltip: 'Export to VRML2 (.wrl) file.'
+"""
+#------------------------------------------------------------------------
+# VRML2 exporter for blender 2.28a or above
+#
+# Source: http://blender.kimballsoftware.com/
+#
+# $Id$
+#
+# Authors: Rick Kimball with much inspiration
+#         from the forum at www.elysiun.com
+#         and irc://irc.freenode.net/blenderchat
+#         Ken Miller and Steve Matthews (Added Camera Support)
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# Copyright (C) 2003,2004: Rick Kimball rick@vrmlworld.net
+#
+# 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 *****
+#
+# To use script:
+# 1.) load this file in the text window.
+#     (press SHIFT+F11, Open New via Datablock button)
+# 2.) make sure your mouse is over the text edit window and
+#     run this script. (press ALT+P)
+# Or:
+#   copy to the scripts directory and it will appear in the
+#   export list. (Needs 2.32 or higher)
+#
+# Notes:
+#  a.) output filename is same as current blender file with .wrl extension
+#  b.) error messages go to the Blender DOS console window
+#
+# The latest version of this python export script:
+#   http://blender.kimballsoftware.com/
+#
+# If you like this script, try using http://vrmlworld.net/
+# to show off your VRML world.
+#
+# 2004-01-19 by Rick Kimball <rick@vrmlworld.net>
+#  o added sub menus and file selector dialog
+#
+# 2004-01-17 by Rick Kimball <rick@vrmlworld.net>
+#  o add meta comments so script will appear in export menu list
+#
+# 2003-11-01 by Rick Kimball <rick@vrmlworld.net>
+#  o fixed issues related to Lamp object and 2.28a API.
+#
+# 2003-07-19 by Rick Kimball <rick@vrmlworld.net>
+#  o made compatible with new Python API in 2.28
+#
+# 2003-01-16 by Ken Miller - with math help from Steve Matthews :)
+#   o Added support for exporting cameras out of Blender
+#   o Sets the name of the camera as the object name
+#   o sets the description of the camera as the object name,
+#     which should be modified to something meaningful
+#   o sets the position and orientation
+#
+# 2003-01-19 Rick Kimball <rick@vrmlworld.net>
+#   o Added Support For PointLight, SpotLight and DirectionalLight using Lamps
+#   o Creates multi singlesided or doublesided IFS
+#   o Creates IndexedLineSets if DrawTypes is WIRE instead of Shaded
+#
+# 2003-02-03 Rick Kimball <rick@vrmlworld.net>
+#   o attempts to catch exceptions for empty objects
+#
+# 2003-02-04 Rick Kimball <rick@vrmlworld.net>
+#   o fixed file overwrite problem when blender filename is all uppercase
+#
+# 2003-02-08 Rick Kimball <rick@vrmlworld.net>
+#   o cleanStr() creates valid VRML DEF names even if object.name
+#     is zero length or uses VRML reserved names or characters
+#
+#------------------------------------------------------------------------
+# Known Issue:
+#  o doesn't handle multiple materials (don't use material indices)
+#  o doesn't handle multiple UV textures on a single mesh. (create a mesh for each texture)
+#  o material colors need work
+#  o spotlight softness needs work
+#  o can't get the texture array associated with material * not the UV ones
+#  o can't set smoothing, crease angle and mesh smoothing * setting not accesible
+#
+# Still Todo:
+#
+#  - Support for material indexes
+#  - Automatically Split IFS when multiple UV textures found * warning only now
+#  - Automatically Split IFS when combination of single vs double sided
+#  - Automatically Split IFS when face with only 2 vertices is found should be an ILS
+#  - Export common coordinate map for split IFS
+#  - Intelligent color array vs color index
+#  - Support more blender objects: World
+#  - Figure out how to output Animation
+#  - Add GUI to control the following:
+#    o All/Layer/Object output radio button
+#    o Color per vertex toggle yes/no
+#    o Complex/Simple VRML output radio button
+#    o Compressed/Uncompressed output radio button
+#    o Decimal precision dropdown 1,2,3,4,5,6
+#    o IFS/Elevation Grid output radio button
+#    o Normals output toggle yes/no
+#    o Proto output toggle yes/no
+#    o Verbose console progress
+
+import Blender
+from Blender import NMesh, Lamp
+import math
+
+
+#-- module constants
+radD=math.pi/180.0
+rad90=90.0*radD      # for rotation
+rad30=30.0*radD      # default crease angle
+ARG=''
+
+#------------------------------------------------------------------------
+#-- utility functions and classes --
+#------------------------------------------------------------------------
+def rad2deg(v):
+    return round(v*180.0/math.pi,4)
+
+def deg2rad(v):
+    return (v*math.pi)/180.0;
+
+class DrawTypes:
+    """Object DrawTypes enum values
+    BOUNDS - draw only the bounding box of the object
+    WIRE - draw object as a wire frame
+    SOLID - draw object with flat shading
+    SHADED - draw object with OpenGL shading
+"""
+    BOUNDBOX  = 1
+    WIRE      = 2
+    SOLID     = 3
+    SHADED    = 4
+    TEXTURE   = 5
+
+#------------------------------------------------------
+# the Blender.Object class seems to be missing this...
+#------------------------------------------------------
+if not hasattr(Blender.Object,'DrawTypes'):
+    Blender.Object.DrawTypes = DrawTypes()
+
+#------------------------------------------------------------------------
+#-- VRML2Export --
+#------------------------------------------------------------------------
+class VRML2Export:
+    #------------------------------------------------------------------------
+    def __init__(self, filename):
+        #--- public you can change these ---
+        self.verbose=1     # level of verbosity in console 0-none, 1-some, 2-most
+        self.cp=3          # decimals for material color values     0.000 - 1.000
+        self.vp=3          # decimals for vertex coordinate values  0.000 - n.000
+        self.tp=3          # decimals for texture coordinate values 0.000 - 1.000
+        self.ambientIntensity=.2
+        self.defCreaseAngle=rad30
+        self.smooth=0
+        
+        #--- class private don't touch ---
+        self.texNames={}   # dictionary of textureNames
+        self.matNames={}   # dictionary of materiaNames
+        self.indentLevel=0 # keeps track of current indenting
+        self.filename=filename
+        self.file = open(filename, "w")
+        self.bNav=0
+        self.nNodeID=0
+        self.VRMLReserved=[ "Anchor","Appearance","Anchor","AudioClip","Background",
+                            "Billboard", "Box", "Collision", "Color", "ColorInterpolator",
+                            "Cone", "Coordinate", "CoordinateInterpolator", "Cylinder",
+                            "CylinderSensor", "DirectionalLight", "ElevationGrid",
+                            "Extrustion", "Fog", "FontStyle", "Group", "ImageTexture",
+                            "IndexedFaceSet", "IndexedLineSet", "Inline", "LOD",
+                            "Material", "MovieTexture", "NavigationInfo", "Normal",
+                            "NormalInterpolator","OrientationInterpolator", "PixelTexture",
+                            "PlaneSensor", "PointLight", "PointSet", "PositionInterpolator",
+                            "ProxmimitySensor", "ScalarInterpolator", "Script", "Shape",
+                            "Sound", "Sphere", "SphereSensor", "SpotLight", "Switch",
+                            "Text", "TextureCoordinate", "TextureTransform", "TimeSensor",
+                            "TouchSensor", "Transform", "Viewpoint", "VisibilitySensor",
+                            "WorldInfo"
+                            ]
+
+    #------------------------------------------------------------------------
+    # writeHeader, export file, cleanup
+    #------------------------------------------------------------------------
+    def writeHeader(self):
+        self.file.write("#VRML V2.0 utf8\n")
+        self.file.write("# modeled using blender3d http://blender.org/$\n")
+        self.file.write("# exported using wrl2export.py version $Revision$\n")
+        self.file.write("# get latest exporter at http://kimballsoftware.com/blender/\n\n")
+    
+    def export(self, scene):
+        print "Info: starting VRML2 export to " + self.filename + "..."
+    
+        self.writeHeader()
+        theObjects = []
+        if ARG == 'selected':
+            theObjects = Blender.Object.GetSelected()
+        else:
+            theObjects = scene.getChildren()
+            
+        for object in theObjects:
+            try:
+                objType=object.getType()
+
+                if objType == "Mesh":
+                    self.writeIndexedFaceSet(object, normals = 0)
+                elif objType == "Camera":
+                    self.writeCameraInfo(object)
+                elif objType == "Lamp":
+                    # if there is a lamp then we probably want to turn off the headlight
+                    if self.bNav == 0:
+                        self.writeNavigationInfo()
+                        self.bNav=1
+                    #endif
+                
+                    lamp=Lamp.Get(object.data.getName())
+                    try:
+                        lampType=lamp.getType()
+
+                        if lampType == Lamp.Types.Lamp:
+                            self.writePointLight(object, lamp)
+                        elif lampType == Lamp.Types.Spot:
+                            self.writeSpotLight(object, lamp)
+                        elif lampType == Lamp.Types.Sun:
+                            self.writeDirectionalLight(object, lamp)
+                        else:
+                            self.writeDirectionalLight(object, lamp)
+                        #endif
+                    except AttributeError:
+                        print "Error: Unable to get type info for %s" % object.name
+                else:
+                    print "Info: Ignoring [%s], object type [%s] not handle yet" % \
+                          (object.name,object.getType())
+                #endif
+            except ValueError:
+                print "Error: object named %s has problem with accessing an attribute" % object.name
+            #end try
+        #endfor
+        self.cleanup()
+
+    def cleanup(self):
+        self.file.close()
+        self.texNames={}
+        self.matNames={}
+        self.indentLevel=0
+        print "Info: finished VRML2 export to %s\n" % self.filename
+
+    #------------------------------------------------------------------------
+    # Writes out camera info as a viewpoint
+    # Handles orientation, position
+    # Use camera object name to set description
+    #------------------------------------------------------------------------
+    def writeCameraInfo(self, object):
+        if self.verbose > 0:
+            print "Info: exporting camera named="+object.name
+        #endif
+        
+        self.writeIndented("DEF %s Viewpoint {\n" % (self.cleanStr(object.name)), 1)
+        
+        self.writeIndented("description \"%s\" \n" % (object.name))
+        
+        # get the camera location, subtract 90 degress from X to orient like VRML does
+        loc = self.rotatePointForVRML(object.loc)
+        rot = [object.RotX - 1.57, object.RotY, object.RotZ]
+        nRot = self.rotatePointForVRML(rot)
+        
+        # convert to Quaternion and to Angle Axis
+        Q  = self.eulerToQuaternions(nRot[0], nRot[1], nRot[2])
+        Q1 = self.multiplyQuaternions(Q[0], Q[1])
+        Qf = self.multiplyQuaternions(Q1, Q[2])
+        angleAxis = self.quaternionToAngleAxis(Qf)
+        
+        # write orientation statement
+        self.writeIndented("orientation %3.2f %3.2f %3.2f %3.2f\n" %
+                           (angleAxis[0], angleAxis[1], -angleAxis[2], angleAxis[3]))
+        
+        # write position statement
+        self.writeIndented("position %3.2f %3.2f %3.2f\n" %
+                           (loc[0], loc[1], loc[2]))
+        
+        self.writeIndented("} # Viewpoint\n", -1)
+        
+        self.writeIndented("\n")
+
+    #------------------------------------------------------------------------
+    def writeIndexedFaceSet(self, object, normals = 0):
+        if self.verbose > 0:
+            print "Info: exporting mesh named=["+object.name+"]"
+        #endif
+
+        imageMap={}   # set of used images
+        sided={}      # 'one':cnt , 'two':cnt
+        vColors={}    # 'multi':1
+
+        mesh=object.getData()
+
+        nIFSCnt=self.countIFSSetsNeeded(mesh, imageMap, sided, vColors)
+
+        meshName = self.cleanStr(object.name)
+        
+        if nIFSCnt > 1:
+            self.writeIndented("DEF %s%s Group {\n" % ("G_", meshName),1)
+            self.writeIndented("children [\n",1)
+        #endif
+        
+        if self.verbose > 0:
+            print "Debug: [%s] has %d UV Textures" % (object.name, nIFSCnt)
+        #endif
+
+        if sided.has_key('two') and sided['two'] > 0:
+            bTwoSided=1
+        else:
+            bTwoSided=0
+
+        self.writeIndented("DEF %s Shape {\n" % meshName,1)
+    
+        # show script debugging info
+        if self.verbose > 1:
+            self.meshToString(mesh)
+            print "Debug: mesh.faces["
+            for face in mesh.faces:
+                self.faceToString(face)
+            #endfor
+            print "Debug: ]"
+        #endif
+        
+        maters=mesh.materials
+        hasImageTexture=0
+
+        if len(maters) > 0 or mesh.hasFaceUV():
+            self.writeIndented("appearance Appearance {\n", 1)
+            
+            # right now this script can only handle a single material per mesh.
+            if len(maters) >= 1:
+                mat=Blender.Material.Get(maters[0].name)
+                self.writeMaterial(mat, self.cleanStr(maters[0].name,'mat_'))
+                if len(maters) > 1:
+                    print "Warning: mesh named %s has multiple materials" % meshName
+                    print "Warning: only one material per object handled"
+                #endif
+            else:
+                self.writeIndented("material NULL\n")
+            #endif
+        
+            #-- textures
+            if mesh.hasFaceUV():
+                for face in mesh.faces:
+                    if (hasImageTexture == 0) and (face.image):
+                        self.writeImageTexture(face.image.name)
+                        hasImageTexture=1  # keep track of face texture
+                    #endif
+                #endfor
+            #endif
+
+            self.writeIndented("} # Appearance\n", -1)
+        #endif
+
+        #-------------------------------------------------------------------
+        #--
+        #-- IndexedFaceSet or IndexedLineSet
+        #
+
+        # check if object is wireframe only
+        if object.drawType == Blender.Object.DrawTypes.WIRE:
+            # user selected WIRE=2 on the Drawtype=Wire on (F9) Edit page
+            ifStyle="IndexedLineSet"
+        else:
+            # user selected BOUNDS=1, SOLID=3, SHARED=4, or TEXTURE=5
+            ifStyle="IndexedFaceSet"
+        #endif
+        
+        self.writeIndented("geometry %s {\n" % ifStyle, 1)
+        if object.drawType != Blender.Object.DrawTypes.WIRE:
+            if bTwoSided == 1:
+                self.writeIndented("solid FALSE # two sided\n")
+            else:
+                self.writeIndented("solid TRUE # one sided\n")
+            #endif
+        #endif
+        
+        #---
+        #--- output coordinates
+        self.writeCoordinates(object, mesh, meshName)
+        
+        if object.drawType != Blender.Object.DrawTypes.WIRE:
+            #---
+            #--- output textureCoordinates if UV texture used
+            if mesh.hasFaceUV():
+                if hasImageTexture == 1:
+                    self.writeTextureCoordinates(mesh)
+                    if vColors.has_key('multi'):
+                        self.writeVertexColors(mesh) # experiment
+                    #endif
+                else:
+                    self.writeFaceColors(mesh)
+                #endif hasImageTexture
+            #endif hasFaceUV
+
+            # TBD: figure out how to get this properly
+            if self.smooth:
+                creaseAngle=self.defCreaseAngle;
+                self.writeIndented("creaseAngle %s\n" % creaseAngle)
+            else:
+                self.writeIndented("creaseAngle 0.0 # in radians\n")
+            #endif mesh.smooth
+        #endif WIRE
+
+        #--- output vertexColors
+        if mesh.hasVertexColours() and vColors.has_key('multi'):
+            self.writeVertexColors(mesh)
+        #endif
+
+        #--- output closing braces
+        self.writeIndented("} # %s\n" % ifStyle, -1)
+        self.writeIndented("} # Shape\n", -1)
+
+        if nIFSCnt > 1:
+            self.writeIndented("] # children\n", -1)
+            self.writeIndented("} # Group\n", -1)
+        #endif
+
+        self.writeIndented("\n")
+
+    #------------------------------------------------------------------------
+    def writeCoordinates(self, object, mesh, meshName):
+        #-- vertices
+        self.writeIndented("coord DEF %s%s Coordinate {\n" % ("coord_",meshName), 1)
+        self.writeIndented("point [\n", 1)
+        meshVertexList = mesh.verts
+
+        # create vertex list and pre rotate -90 degrees X for VRML
+        mm=object.getMatrix()
+        for vertex in meshVertexList:
+            v=self.rotVertex(mm, vertex);
+            self.writeIndented("%s %s %s,\n" %
+                               (round(v[0],self.vp),
+                                round(v[1],self.vp),
+                                round(v[2],self.vp) ))
+        #endfor
+        self.writeIndented("] # point\n", -1)
+        self.writeIndented("} # Coordinate\n", -1)
+
+        self.writeIndented("coordIndex [\n", 1)
+        coordIndexList=[]  
+        for face in mesh.faces:
+            cordStr=""
+            for i in range(len(face)):
+                indx=meshVertexList.index(face[i])
+                cordStr = cordStr + "%s, " % indx
+            #endfor
+            self.writeIndented(cordStr + "-1,\n")
+        #endfor
+        self.writeIndented("] # coordIndex\n", -1)
+
+    #------------------------------------------------------------------------
+    def writeTextureCoordinates(self, mesh):
+        texCoordList=[] 
+        texIndexList=[]
+        j=0
+
+        for face in mesh.faces:
+            for i in range(len(face)):
+                texIndexList.append(j)
+                texCoordList.append(face.uv[i])
+                j=j+1
+            #endfor
+            texIndexList.append(-1)
+        #endfor
+
+        self.writeIndented("texCoord TextureCoordinate {\n", 1)
+        self.writeIndented("point [\n", 1)
+        for i in range(len(texCoordList)):
+            self.writeIndented("%s %s," %
+                               (round(texCoordList[i][0],self.tp), 
+                                round(texCoordList[i][1],self.tp))+"\n")
+        #endfor
+        self.writeIndented("] # point\n", -1)
+        self.writeIndented("} # texCoord\n", -1)
+
+        self.writeIndented("texCoordIndex [\n", 1)
+        texIndxStr=""
+        for i in range(len(texIndexList)):
+            texIndxStr = texIndxStr + "%d, " % texIndexList[i]
+            if texIndexList[i]==-1:
+                self.writeIndented(texIndxStr + "\n")
+                texIndxStr=""
+            #endif
+        #endfor
+        self.writeIndented("] # texCoordIndex\n", -1)
+
+    #------------------------------------------------------------------------
+    def writeFaceColors(self, mesh):
+        self.writeIndented("colorPerVertex FALSE\n")
+        self.writeIndented("color Color {\n",1)
+        self.writeIndented("color [\n",1)
+
+        for face in mesh.faces:
+            if face.col:
+                c=face.col[0]
+                if self.verbose > 1:
+                    print "Debug: face.col r=%d g=%d b=%d" % (c.r, c.g, c.b)
+                #endif
+
+                aColor = self.rgbToFS(c)
+                self.writeIndented("%s,\n" % aColor)
+        #endfor
+
+        self.writeIndented("] # color\n",-1)
+        self.writeIndented("} # Color\n",-1)
+
+    #------------------------------------------------------------------------
+    def writeVertexColors(self, mesh):
+        self.writeIndented("colorPerVertex TRUE\n")
+        self.writeIndented("color Color {\n",1)
+        self.writeIndented("color [\n",1)
+
+        for i in range(len(mesh.verts)):
+            c=self.getVertexColorByIndx(mesh,i)
+            if self.verbose > 1:
+                print "Debug: vertex[%d].col r=%d g=%d b=%d" % (i, c.r, c.g, c.b)
+            #endif
+
+            aColor = self.rgbToFS(c)
+            self.writeIndented("%s,\n" % aColor)
+        #endfor
+
+        self.writeIndented("] # color\n",-1)
+        self.writeIndented("} # Color\n",-1)
+
+    #------------------------------------------------------------------------
+    def writeMaterial(self, mat, matName):
+        # look up material name, use it if available
+        if self.matNames.has_key(matName):
+            self.writeIndented("material USE %s\n" % matName)
+            self.matNames[matName]+=1
+            return;
+        #endif
+
+        self.matNames[matName]=1
+
+        ambient = mat.amb
+        diffuseR, diffuseG, diffuseB = mat.rgbCol[0], mat.rgbCol[1],mat.rgbCol[2]
+        emisR, emisG, emisB = diffuseR*mat.emit, diffuseG*mat.emit, diffuseB*mat.emit
+        shininess = mat.hard/255.0
+        specR = mat.specCol[0]
+        specG = mat.specCol[1]
+        specB = mat.specCol[2]
+        transp = 1-mat.alpha
+
+        self.writeIndented("material DEF %s Material {\n" % matName, 1)
+        self.writeIndented("diffuseColor %s %s %s" %
+                           (round(diffuseR,self.cp), round(diffuseG,self.cp), round(diffuseB,self.cp)) +
+                           "\n")
+        self.writeIndented("ambientIntensity %s" %
+                           (round(ambient,self.cp))+
+                           "\n")
+        self.writeIndented("specularColor %s %s %s" %
+                           (round(specR,self.cp), round(specG,self.cp), round(specB,self.cp)) +
+                           "\n" )
+        self.writeIndented("emissiveColor  %s %s %s" %
+                           (round(emisR,self.cp), round(emisG,self.cp), round(emisB,self.cp)) +
+                           "\n" )
+        self.writeIndented("shininess %s" %
+                           (round(shininess,self.cp)) +
+                           "\n" )
+        self.writeIndented("transparency %s" %
+                           (round(transp,self.cp)) +
+                           "\n")
+        self.writeIndented("} # Material\n",-1)
+
+    #------------------------------------------------------------------------
+    def writeImageTexture(self, name):
+        if self.texNames.has_key(name):
+            self.writeIndented("texture USE %s\n" % self.cleanStr(name))
+            self.texNames[name] += 1
+            return
+        else:
+            self.writeIndented("texture DEF %s ImageTexture {\n" % self.cleanStr(name), 1)
+            self.writeIndented("url \"%s\"\n" % name)
+            self.writeIndented("} # ImageTexture \n",-1)
+            self.texNames[name] = 1
+        #endif
+
+    #------------------------------------------------------------------------
+    def writeSpotLight(self, object, lamp):
+        safeName = self.cleanStr(object.name)
+
+        # compute cutoff and beamwidth
+        intensity=min(lamp.energy/1.5,1.0) # TBD: figure out the right value
+
+        beamWidth=deg2rad(lamp.spotSize)*.5;
+        cutOffAngle=beamWidth*.99
+
+        (dx,dy,dz)=self.computeDirection(object)
+        # note -dx seems to equal om[3][0]
+        # note -dz seems to equal om[3][1]
+        # note  dy seems to equal om[3][2]
+        om = object.getMatrix()
+            
+        location=self.rotVertex(om, (0,0,0));
+        radius = lamp.dist*math.cos(beamWidth)
+        self.writeIndented("DEF %s SpotLight {\n" % safeName,1)
+        self.writeIndented("radius %s\n" % radius )
+        self.writeIndented("intensity %s\n" % intensity )
+        self.writeIndented("beamWidth %s # lamp.spotSize %s\n" % (beamWidth, lamp.spotSize) )
+        self.writeIndented("cutOffAngle %s # lamp.spotBlend %s\n" % (cutOffAngle, lamp.spotBlend))
+        self.writeIndented("direction %s %s %s # lamp.RotX=%s RotY=%s RotZ=%s\n" % \
+                           (round(dx,3),round(dy,3),round(dz,3),
+                            round(rad2deg(object.RotX),3),
+                            round(rad2deg(object.RotY),3),
+                            round(rad2deg(object.RotZ),3)))
+        self.writeIndented("location %s %s %s\n" % (round(location[0],3),
+                                                    round(location[1],3),
+                                                    round(location[2],3)))
+        self.writeIndented("} # SpotLight\n",-1)
+
+        # export a cone that matches the spotlight in verbose mode
+        if self.verbose > 1:
+            self.writeIndented("#generated visible spotlight cone\n")
+            self.writeIndented("Transform { # Spotlight Cone\n",1)
+            self.writeIndented("translation %s %s %s\n" % (round(location[0],3),
+                                                           round(location[1],3),
+                                                           round(location[2],3)))
+            rot = [object.RotX, object.RotY, object.RotZ]
+            nRot = self.rotatePointForVRML(rot)
+            
+            # convert to Quaternion and to Angle Axis
+            Q  = self.eulerToQuaternions(nRot[0], nRot[1], nRot[2])
+            Q1 = self.multiplyQuaternions(Q[0], Q[1])
+            Qf = self.multiplyQuaternions(Q1, Q[2])
+            angleAxis = self.quaternionToAngleAxis(Qf)
+            
+            # write orientation statement
+            self.writeIndented("rotation %3.2f %3.2f %3.2f %3.2f\n" %
+                               (angleAxis[0], angleAxis[1], -angleAxis[2], angleAxis[3]))
+            
+            self.writeIndented("children [\n",1)
+            
+            ch=radius
+            br=ch*math.sin(beamWidth)
+            self.writeIndented("Transform {\n",1)
+            self.writeIndented("translation 0 -%s 0\n" % (ch/2))
+            self.writeIndented("children ")
+            self.writeIndented("Collision {\n",1)
+            self.writeIndented("collide FALSE children Shape {\n",1)
+            self.writeIndented("geometry Cone { height %s bottomRadius %s }\n" % (ch, br))
+            self.writeIndented("appearance Appearance{\n",1)
+            self.writeIndented("material Material { diffuseColor 1 1 1 transparency .8 }\n")
+            self.writeIndented("} # Appearance\n",-1)
+            self.writeIndented("} # Shape\n",-1)
+            self.writeIndented("} # Collision\n",-1)
+            self.writeIndented("} # Transform visible cone \n",-1)
+            self.writeIndented("] # Spot children\n",-1)
+            self.writeIndented("} # SpotLight Cone Transform\n",-1)
+        #endif debug cone
+        self.writeIndented("\n")
+        
+    #------------------------------------------------------------------------
+    def writeDirectionalLight(self, object, lamp):
+        safeName = self.cleanStr(object.name)
+
+        intensity=min(lamp.energy/1.5, 1.0) # TBD: figure out the right value
+        (dx,dy,dz)=self.computeDirection(object)
+
+        self.writeIndented("DEF %s DirectionalLight {\n" % safeName,1)
+        self.writeIndented("ambientIntensity %s\n" % self.ambientIntensity )
+        self.writeIndented("intensity %s\n" % intensity )
+        self.writeIndented("direction %s %s %s\n" % (round(dx,4),round(dy,4),round(dz,4)))
+        self.writeIndented("} # DirectionalLight\n",-1)
+        self.writeIndented("\n")
+
+    #------------------------------------------------------------------------
+    def writePointLight(self, object, lamp):
+        safeName = self.cleanStr(object.name)
+
+        om = object.getMatrix()
+        location=self.rotVertex(om, (0,0,0));
+        intensity=min(lamp.energy/1.5,1.0) # TBD: figure out the right value
+
+        radius = lamp.dist
+        self.writeIndented("DEF %s PointLight {\n" % safeName,1)
+        self.writeIndented("ambientIntensity %s\n" % self.ambientIntensity )
+        self.writeIndented("intensity %s\n" % intensity )
+        self.writeIndented("location %s %s %s\n" % (round(location[0],3),
+                                                    round(location[1],3),
+                                                    round(location[2],3)))
+        self.writeIndented("radius %s\n" % radius )
+        self.writeIndented("} # PointLight\n",-1)
+        self.writeIndented("\n")
+
+    #------------------------------------------------------------------------
+    def writeNavigationInfo(self):
+        self.writeIndented("NavigationInfo {\n",1)
+        self.writeIndented("headlight FALSE\n")
+        self.writeIndented("avatarSize [0.25, 1.75, 0.75]\n")
+        self.writeIndented("} # NavigationInfo\n",-1)
+        self.writeIndented("\n")
+
+    #------------------------------------------------------------------------
+    #--- Utility methods
+    #------------------------------------------------------------------------
+
+    def cleanStr(self, name, prefix='rsvd_'):
+        """cleanStr(name,prefix) - try to create a valid VRML DEF name from object name"""
+
+        newName=name[:]
+        if len(newName) == 0:
+            self.nNodeID+=1
+            return "%s%d" % (prefix, self.nNodeID)
+        
+        if newName in self.VRMLReserved:
+            newName='%s%s' % (prefix,newName)
+        #endif
+        
+        if newName[0] in ['0','1','2','3','4','5','6','7','8','9']:
+            newName='%s%s' % ('_',newName)
+        #endif
+
+        for bad in [' ','"','#',"'",',','.','[','\\',']','{','}']:
+            newName=newName.replace(bad,'_')
+        return newName
+
+    def countIFSSetsNeeded(self, mesh, imageMap, sided, vColors):
+        """
+        countIFFSetsNeeded() - should look at a blender mesh to determine
+        how many VRML IndexFaceSets or IndexLineSets are needed.  A
+        new mesh created under the following conditions:
+        
+         o - split by UV Textures / one per mesh
+         o - split by face, one sided and two sided
+         o - split by smooth and flat faces
+         o - split when faces only have 2 vertices * needs to be an IndexLineSet
+        """
+        
+        imageNameMap={}
+        faceMap={}
+        nFaceIndx=0
+        
+        for face in mesh.faces:
+            sidename='';
+            if (face.mode & NMesh.FaceModes.TWOSIDE) == NMesh.FaceModes.TWOSIDE:
+                sidename='two'
+            else:
+                sidename='one'
+            #endif
+
+            if not vColors.has_key('multi'):
+                for face in mesh.faces:
+                    if face.col:
+                        c=face.col[0]
+                        if c.r != 255 and c.g != 255 and c.b !=255:
+                            vColors['multi']=1
+                        #endif
+                    #endif
+                #endfor
+            #endif
+
+            if sided.has_key(sidename):
+                sided[sidename]+=1
+            else:
+                sided[sidename]=1
+            #endif
+
+            if face.image:
+                faceName="%s_%s" % (face.image.name, sidename);
+
+                if imageMap.has_key(faceName):
+                    imageMap[faceName].append(face)
+                else:
+                    imageMap[faceName]=[face.image.name,sidename,face]
+                #endif
+            #endif
+        #endfor
+
+        if self.verbose > 0:
+            for faceName in imageMap.keys():
+                ifs=imageMap[faceName]
+                print "Debug: faceName=%s image=%s, solid=%s facecnt=%d" % \
+                      (faceName, ifs[0], ifs[1], len(ifs)-2)
+            #endif
+        #endif
+
+        return len(imageMap.keys())
+    
+    def faceToString(self,face):
+        print "Debug: face.flag=0x%x (bitflags)" % face.flag
+        if face.flag & NMesh.FaceFlags.SELECT == NMesh.FaceFlags.SELECT:
+            print "Debug: face.flag.SELECT=true"
+        #endif
+
+        print "Debug: face.mode=0x%x (bitflags)" % face.mode
+        if (face.mode & NMesh.FaceModes.TWOSIDE) == NMesh.FaceModes.TWOSIDE:
+            print "Debug: face.mode twosided"
+        #endif
+
+        print "Debug: face.transp=0x%x (enum)" % face.transp
+        if face.transp == NMesh.FaceTranspModes.SOLID:
+            print "Debug: face.transp.SOLID"
+        #
+
+        if face.image:
+            print "Debug: face.image=%s" % face.image.name
+        #endif
+        print "Debug: face.materialIndex=%d" % face.materialIndex
+
+    def getVertexColorByIndx(self, mesh, indx):
+        for face in mesh.faces:
+            j=0
+            for vertex in face.v:
+                if vertex.index == indx:
+                    c=face.col[j]
+                #endif
+                j=j+1
+            #endfor
+        #endfor
+        return c
+
+    def meshToString(self,mesh):
+        print "Debug: mesh.hasVertexUV=%d" % mesh.hasVertexUV()
+        print "Debug: mesh.hasFaceUV=%d" % mesh.hasFaceUV()
+        print "Debug: mesh.hasVertexColours=%d" % mesh.hasVertexColours()
+        print "Debug: mesh.verts=%d" % len(mesh.verts)
+        print "Debug: mesh.faces=%d" % len(mesh.faces)
+        print "Debug: mesh.materials=%d" % len(mesh.materials)
+
+    def rgbToFS(self, c):
+        s="%s %s %s" % (
+            round(c.r/255.0,self.cp),
+            round(c.g/255.0,self.cp),
+            round(c.b/255.0,self.cp))
+        return s
+
+    def computeDirection(self, object):
+        x,y,z=(0,-1.0,0) # point down
+        ax,ay,az = (object.RotX,object.RotZ,object.RotY)
+
+        # rot X
+        x1=x
+        y1=y*math.cos(ax)-z*math.sin(ax)
+        z1=y*math.sin(ax)+z*math.cos(ax)
+
+        # rot Y
+        x2=x1*math.cos(ay)+z1*math.sin(ay)
+        y2=y1
+        z2=z1*math.cos(ay)-x1*math.sin(ay)
+
+        # rot Z
+        x3=x2*math.cos(az)-y2*math.sin(az)
+        y3=x2*math.sin(az)+y2*math.cos(az)
+        z3=z2
+
+        return [x3,y3,z3]
+        
+
+    # swap Y and Z to handle axis difference between Blender and VRML
+    #------------------------------------------------------------------------
+    def rotatePointForVRML(self, v):
+        x = v[0]
+        y = v[2]
+        z = -v[1]
+        
+        vrmlPoint=[x, y, z]
+        return vrmlPoint
+    
+    def rotVertex(self, mm, v):
+        lx,ly,lz=v[0],v[1],v[2]
+        gx=(mm[0][0]*lx + mm[1][0]*ly + mm[2][0]*lz) + mm[3][0]
+        gy=((mm[0][2]*lx + mm[1][2]*ly+ mm[2][2]*lz) + mm[3][2])
+        gz=-((mm[0][1]*lx + mm[1][1]*ly + mm[2][1]*lz) + mm[3][1])
+        rotatedv=[gx,gy,gz]
+        return rotatedv
+
+    def writeIndented(self, s, inc=0):
+        if inc < 1:
+            self.indentLevel = self.indentLevel + inc
+        #endif
+
+        spaces=""
+        for x in xrange(self.indentLevel):
+            spaces = spaces + "   "
+        #endfor
+        self.file.write(spaces + s)
+
+        if inc > 0:
+            self.indentLevel = self.indentLevel + inc
+        #endif
+
+    # Converts a Euler to three new Quaternions
+    # Angles of Euler are passed in as radians
+    #------------------------------------------------------------------------
+    def eulerToQuaternions(self, x, y, z):
+        Qx = [math.cos(x/2), math.sin(x/2), 0, 0]
+        Qy = [math.cos(y/2), 0, math.sin(y/2), 0]
+        Qz = [math.cos(z/2), 0, 0, math.sin(z/2)]
+        
+        quaternionVec=[Qx,Qy,Qz]
+        return quaternionVec
+    
+    # Multiply two Quaternions together to get a new Quaternion
+    #------------------------------------------------------------------------
+    def multiplyQuaternions(self, Q1, Q2):
+        result = [((Q1[0] * Q2[0]) - (Q1[1] * Q2[1]) - (Q1[2] * Q2[2]) - (Q1[3] * Q2[3])),
+                  ((Q1[0] * Q2[1]) + (Q1[1] * Q2[0]) + (Q1[2] * Q2[3]) - (Q1[3] * Q2[2])),
+                  ((Q1[0] * Q2[2]) + (Q1[2] * Q2[0]) + (Q1[3] * Q2[1]) - (Q1[1] * Q2[3])),
+                  ((Q1[0] * Q2[3]) + (Q1[3] * Q2[0]) + (Q1[1] * Q2[2]) - (Q1[2] * Q2[1]))]
+        
+        return result
+    
+    # Convert a Quaternion to an Angle Axis (ax, ay, az, angle)
+    # angle is in radians
+    #------------------------------------------------------------------------
+    def quaternionToAngleAxis(self, Qf):
+        scale = math.pow(Qf[1],2) + math.pow(Qf[2],2) + math.pow(Qf[3],2)
+        ax = Qf[1]
+        ay = Qf[2]
+        az = Qf[3]
+
+        if scale > .0001:
+            ax/=scale
+            ay/=scale
+            az/=scale
+        #endif
+        
+        angle = 2 * math.acos(Qf[0])
+        
+        result = [ax, ay, az, angle]
+        return result
+
+def file_callback(filename):
+    if filename.find('.wrl', -4) < 0: filename += '.wrl'
+    wrlexport=VRML2Export(filename)
+    scene = Blender.Scene.getCurrent()
+    wrlexport.export(scene)
+#enddef
+    
+#------------------------------------------------------------------------
+# main routine
+#------------------------------------------------------------------------
+try:
+    ARG = __script__['arg'] # user selected argument
+except:
+    print "older version"
+
+if Blender.Get('version') < 225:
+    print "Warning: VRML2 export failed, wrong blender version!"
+    print " You aren't running blender version 2.25 or greater"
+    print " download a newer version from http://blender.org/"
+else:
+    if ARG == 'all' or ARG == 'selected':
+        Blender.Window.FileSelector(file_callback,"Save VRML 2.0")
+    else:
+        baseFileName=Blender.Get('filename')
+        if baseFileName.find('.') != -1:
+            dots=Blender.Get('filename').split('.')[0:-1]
+        else:
+            dots=[baseFileName]
+        #endif
+        dots+=["wrl"]
+        vrmlFile=".".join(dots)
+
+        file_callback(vrmlFile)
+    #endif
+#endif
index ba826ace4bc60b138c1a9bf4411ae651ad57fd7e..2e9cbd7b3f208eaf3ba5fafd78da15c3ceb217ce 100644 (file)
@@ -396,8 +396,6 @@ int BPY_txt_do_python(struct SpaceText* st)
 
   if (!st->text) return 0;
 
-       PyErr_Clear();
-
        /* check if this text is already running */
        while (script) {
                if (!strcmp(script->id.name+2, st->text->id.name+2)) {
@@ -488,8 +486,6 @@ int BPY_menu_do_python(short menutype, int event)
 
        if (!pym) return 0;
 
-       PyErr_Clear();
-
        if (pym->version > G.version)
                notice ("Version mismatch: script was written for Blender %d. "
                                                "It may fail with yours: %d.", pym->version, G.version);
@@ -632,6 +628,11 @@ void BPY_free_finished_script(Script *script)
 {
        if (!script) return;
 
+       if (PyErr_Occurred()) { /* if script ended after filesel */
+               PyErr_Print(); /* eventual errors are handled now */
+               error ("Python script error: check console");
+       }
+
        free_libblock(&G.main->script, script);
        return;
 }
index 01c126a274e0784bfdcedafd8e4259a0a1655624..4a0185cd389b8da5eb39be905934cac1bf769ec3 100644 (file)
@@ -12,63 +12,66 @@ scrollbar, plus support for text drawing.  It also includes keyboard keys and
 mouse button code values in its dictionary (print dir(Blender.Draw)).
 
 Example::
-  import Blender
-  from Blender import Draw, BGL
-  #
-  mystring = ""
-  mymsg = ""
-  toggle = 0
-  #
-  def event(evt, val):    # the function to handle input events
-    global mystring, mymsg
-
-    if not val:  # val = 0: it's a key/mbutton release
-      if evt in [Draw.LEFTMOUSE, Draw.MIDDLEMOUSE, Draw.RIGHTMOUSE]:
-        mymsg = "You released a mouse button."
-        Draw.Redraw(1)
-      return
-
-    if evt == Draw.ESCKEY:
-      Draw.Exit()                 # exit when user presses ESC
-      return
-
-    elif Draw.AKEY <= evt <= Draw.ZKEY: mystring += chr(evt)
-    elif evt == Draw.SPACEKEY: mystring += ' '
-    elif evt == Draw.BACKSPACEKEY and len(mystring):
-      mystring = mystring[:-1]
-    else: return # this is important: only re-register if an event was caught
-
-    Draw.Register(gui, event, button_event)  # re-register to stay in the loop
-  #
-  def button_event(evt):  # the function to handle Draw Button events
-    global mymsg, toggle
-    if evt == 1:
-      mymsg = "You pressed the toggle button."
-      toggle = 1 - toggle
-      Draw.Redraw(1)
-    else:
-      Draw.Register(gui, event, button_event)
-  #
-  def gui():              # the function to draw the screen
-    global mystring, mymsg, toggle
-    if len(mystring) > 90: mystring = ""
-    BGL.glClearColor(0,0,1,1)
-    BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
-    BGL.glColor3f(1,1,1)
-    Draw.Toggle("Toggle", 1, 10, 10, 55, 20, toggle,"A toggle button")
-    BGL.glRasterPos2i(72, 16)
-    if toggle: toggle_state = "down"
-    else: toggle_state = "up"
-    Draw.Text("The toggle button is %s." % toggle_state, "small")
-    BGL.glRasterPos2i(10, 230)
-    Draw.Text("Type letters from a to z, ESC to leave.")
-    BGL.glRasterPos2i(20, 200)
-    Draw.Text(mystring)
-    BGL.glColor3f(1,0.4,0.3)
-    BGL.glRasterPos2i(340, 70)
-    Draw.Text(mymsg, "tiny")
-  #
-  Draw.Register(gui, event, button_event)  # registering the 3 callbacks
+ import Blender
+ from Blender import Draw, BGL
+
+ mystring = ""
+ mymsg = ""
+ toggle = 0
+
+ def event(evt, val):    # the function to handle input events
+   global mystring, mymsg
+
+   if not val:  # val = 0: it's a key/mbutton release
+     if evt in [Draw.LEFTMOUSE, Draw.MIDDLEMOUSE, Draw.RIGHTMOUSE]:
+       mymsg = "You released a mouse button."
+       Draw.Redraw(1)
+     return
+
+   if evt == Draw.ESCKEY:
+     Draw.Exit()                 # exit when user presses ESC
+     return
+
+   elif Draw.AKEY <= evt <= Draw.ZKEY: mystring += chr(evt)
+   elif evt == Draw.SPACEKEY: mystring += ' '
+   elif evt == Draw.BACKSPACEKEY and len(mystring):
+     mystring = mystring[:-1]
+   else: return # no need to redraw if nothing changed
+
+   Draw.Redraw(1)
+
+ def button_event(evt):  # the function to handle Draw Button events
+   global mymsg, toggle
+   if evt == 1:
+     mymsg = "You pressed the toggle button."
+     toggle = 1 - toggle
+     Draw.Redraw(1)
+
+ def gui():              # the function to draw the screen
+   global mystring, mymsg, toggle
+   if len(mystring) > 90: mystring = ""
+   BGL.glClearColor(0,0,1,1)
+   BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
+   BGL.glColor3f(1,1,1)
+   Draw.Toggle("Toggle", 1, 10, 10, 55, 20, toggle,"A toggle button")
+   BGL.glRasterPos2i(72, 16)
+   if toggle: toggle_state = "down"
+   else: toggle_state = "up"
+   Draw.Text("The toggle button is %s." % toggle_state, "small")
+   BGL.glRasterPos2i(10, 230)
+   Draw.Text("Type letters from a to z, ESC to leave.")
+   BGL.glRasterPos2i(20, 200)
+   Draw.Text(mystring)
+   BGL.glColor3f(1,0.4,0.3)
+   BGL.glRasterPos2i(340, 70)
+   Draw.Text(mymsg, "tiny")
+
+ Draw.Register(gui, event, button_event)  # registering the 3 callbacks
+
+@note: The example above was fixed to call Draw.Register only once.  It's
+not necessary to re-register the callbacks, they will stay until Draw.Exit
+is called.  It's enough to redraw the screen when a relevant event is caught.
+Apologies for the confusion.
 
 @warn: Inside the windowing loop (after Draw.Register() has been executed and
 before Draw.Exit() is called), don't use the redraw functions from other
index ea85f841f091a8fec2aac09357553c87b2ce0be3..85d336a0599ff50808831ef6e7e299094cb90b70 100644 (file)
@@ -117,6 +117,8 @@ class Material:
    that range: if val < Min, then val = Min, if val > Max, then val = Max.
   """
 
+  import Texture
+
   def getName():
     """
     Get the name of this Material object.
@@ -471,3 +473,30 @@ class Material:
     @type nrings: int
     @param nrings: The new value in [0, 24].
     """
+
+  def setTexture(index, texture, texco, mapto):
+    """
+    Assign a Blender Texture object to slot number 'number'.
+    @type index: int
+    @param index: material's texture index in [0, 7].
+    @type texture: Blender Texture
+    @param texture: a Blender Texture object.
+    @type texco: int
+    @param texco: optional or'ed bitflag -- defaults to TexCo.ORCO.  See TexCo var in L{Texture}.
+    @type mapto: int
+    @param mapto: optional or'ed bitflag -- defaults to MapTo.COL.  See MapTo var in L{Texture}.
+    """
+
+  def clearTexture(index):
+    """
+    Clear the ith (given by 'index') texture channel of this material.
+    @type index: int
+    @param index: material's texture channel index in [0, 7].
+    """
+
+  def getTextures ():
+    """
+    Get this Material's Texture list.
+    @rtype: list
+    @return: a list of Blender Textures.  None is returned for each empty texture slot.
+    """