Merge from 2.5 rev 20515 through 20647.
authorArystanbek Dyussenov <arystan.d@gmail.com>
Fri, 5 Jun 2009 14:06:29 +0000 (14:06 +0000)
committerArystanbek Dyussenov <arystan.d@gmail.com>
Fri, 5 Jun 2009 14:06:29 +0000 (14:06 +0000)
release/scripts/export_obj-2.5.py [new file with mode: 0644]
release/ui/buttons_particle.py [deleted file]
source/blender/editors/space_buttons/buttons_context.c [deleted file]
source/blender/python/intern/bpy_interface.c
source/blender/python/intern/bpy_operator_wrap.c

diff --git a/release/scripts/export_obj-2.5.py b/release/scripts/export_obj-2.5.py
new file mode 100644 (file)
index 0000000..2effe75
--- /dev/null
@@ -0,0 +1,910 @@
+#!BPY
+
+"""
+Name: 'Wavefront (.obj)...'
+Blender: 248
+Group: 'Export'
+Tooltip: 'Save a Wavefront OBJ File'
+"""
+
+__author__ = "Campbell Barton, Jiri Hnidek"
+__url__ = ['http://wiki.blender.org/index.php/Scripts/Manual/Export/wavefront_obj', 'www.blender.org', 'blenderartists.org']
+__version__ = "1.2"
+
+__bpydoc__ = """\
+This script is an exporter to OBJ file format.
+
+Usage:
+
+Select the objects you wish to export and run this script from "File->Export" menu.
+Selecting the default options from the popup box will be good in most cases.
+All objects that can be represented as a mesh (mesh, curve, metaball, surface, text3d)
+will be exported as mesh data.
+"""
+
+
+# --------------------------------------------------------------------------
+# OBJ Export v1.1 by Campbell Barton (AKA Ideasman)
+# --------------------------------------------------------------------------
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA         02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+# --------------------------------------------------------------------------
+
+
+import bpy
+import BPySys
+
+# import Blender
+# from Blender import Mesh, Scene, Window, sys, Image, Draw
+# import BPyMesh
+# import BPyObject
+# import BPySys
+# import BPyMessages
+
+# Returns a tuple - path,extension.
+# 'hello.obj' >         ('hello', '.obj')
+def splitExt(path):
+       dotidx = path.rfind('.')
+       if dotidx == -1:
+               return path, ''
+       else:
+               return path[:dotidx], path[dotidx:] 
+
+def fixName(name):
+       if name == None:
+               return 'None'
+       else:
+               return name.replace(' ', '_')
+
+# A Dict of Materials
+# (material.name, image.name):matname_imagename # matname_imagename has gaps removed.
+MTL_DICT = {} 
+
+def write_mtl(filename):
+       
+       world = Blender.World.GetCurrent()
+       if world:
+               worldAmb = world.getAmb()
+       else:
+               worldAmb = (0,0,0) # Default value
+       
+       file = open(filename, "w")
+       file.write('# Blender3D MTL File: %s\n' % Blender.Get('filename').split('\\')[-1].split('/')[-1])
+       file.write('# Material Count: %i\n' % len(MTL_DICT))
+       # Write material/image combinations we have used.
+       for key, (mtl_mat_name, mat, img) in MTL_DICT.iteritems():
+               
+               # Get the Blender data for the material and the image.
+               # Having an image named None will make a bug, dont do it :)
+               
+               file.write('newmtl %s\n' % mtl_mat_name) # Define a new material: matname_imgname
+               
+               if mat:
+                       file.write('Ns %.6f\n' % ((mat.getHardness()-1) * 1.9607843137254901) ) # Hardness, convert blenders 1-511 to MTL's 
+                       file.write('Ka %.6f %.6f %.6f\n' %      tuple([c*mat.amb for c in worldAmb])  ) # Ambient, uses mirror colour,
+                       file.write('Kd %.6f %.6f %.6f\n' % tuple([c*mat.ref for c in mat.rgbCol]) ) # Diffuse
+                       file.write('Ks %.6f %.6f %.6f\n' % tuple([c*mat.spec for c in mat.specCol]) ) # Specular
+                       file.write('Ni %.6f\n' % mat.IOR) # Refraction index
+                       file.write('d %.6f\n' % mat.alpha) # Alpha (obj uses 'd' for dissolve)
+                       
+                       # 0 to disable lighting, 1 for ambient & diffuse only (specular color set to black), 2 for full lighting.
+                       if mat.getMode() & Blender.Material.Modes['SHADELESS']:
+                               file.write('illum 0\n') # ignore lighting
+                       elif mat.getSpec() == 0:
+                               file.write('illum 1\n') # no specular.
+                       else:
+                               file.write('illum 2\n') # light normaly 
+               
+               else:
+                       #write a dummy material here?
+                       file.write('Ns 0\n')
+                       file.write('Ka %.6f %.6f %.6f\n' %      tuple([c for c in worldAmb])  ) # Ambient, uses mirror colour,
+                       file.write('Kd 0.8 0.8 0.8\n')
+                       file.write('Ks 0.8 0.8 0.8\n')
+                       file.write('d 1\n') # No alpha
+                       file.write('illum 2\n') # light normaly
+               
+               # Write images!
+               if img:  # We have an image on the face!
+                       file.write('map_Kd %s\n' % img.filename.split('\\')[-1].split('/')[-1]) # Diffuse mapping image                 
+               
+               elif mat: # No face image. if we havea material search for MTex image.
+                       for mtex in mat.getTextures():
+                               if mtex and mtex.tex.type == Blender.Texture.Types.IMAGE:
+                                       try:
+                                               filename = mtex.tex.image.filename.split('\\')[-1].split('/')[-1]
+                                               file.write('map_Kd %s\n' % filename) # Diffuse mapping image
+                                               break
+                                       except:
+                                               # Texture has no image though its an image type, best ignore.
+                                               pass
+               
+               file.write('\n\n')
+       
+       file.close()
+
+def copy_file(source, dest):
+       file = open(source, 'rb')
+       data = file.read()
+       file.close()
+       
+       file = open(dest, 'wb')
+       file.write(data)
+       file.close()
+
+
+def copy_images(dest_dir):
+       if dest_dir[-1] != sys.sep:
+               dest_dir += sys.sep
+       
+       # Get unique image names
+       uniqueImages = {}
+       for matname, mat, image in MTL_DICT.itervalues(): # Only use image name
+               # Get Texface images
+               if image:
+                       uniqueImages[image] = image # Should use sets here. wait until Python 2.4 is default.
+               
+               # Get MTex images
+               if mat:
+                       for mtex in mat.getTextures():
+                               if mtex and mtex.tex.type == Blender.Texture.Types.IMAGE:
+                                       image_tex = mtex.tex.image
+                                       if image_tex:
+                                               try:
+                                                       uniqueImages[image_tex] = image_tex
+                                               except:
+                                                       pass
+       
+       # Now copy images
+       copyCount = 0
+       
+       for bImage in uniqueImages.itervalues():
+               image_path = sys.expandpath(bImage.filename)
+               if sys.exists(image_path):
+                       # Make a name for the target path.
+                       dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1]
+                       if not sys.exists(dest_image_path): # Image isnt alredy there
+                               print '\tCopying "%s" > "%s"' % (image_path, dest_image_path)
+                               copy_file(image_path, dest_image_path)
+                               copyCount+=1
+       print '\tCopied %d images' % copyCount
+
+def write(filename, objects,
+                 EXPORT_TRI=False,      EXPORT_EDGES=False,
+                 EXPORT_NORMALS=False,  EXPORT_NORMALS_HQ=False,
+                 EXPORT_UV=True,  EXPORT_MTL=True,      EXPORT_COPY_IMAGES=False,
+                 EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True, EXPORT_BLEN_OBS=True,
+                 EXPORT_GROUP_BY_OB=False,      EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=False):
+       '''
+       Basic write function. The context and options must be alredy set
+       This can be accessed externaly
+       eg.
+       write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options.
+       '''
+       
+       def veckey3d(v):
+               return round(v.x, 6), round(v.y, 6), round(v.z, 6)
+               
+       def veckey2d(v):
+               return round(v.x, 6), round(v.y, 6)
+       
+       print 'OBJ Export path: "%s"' % filename
+       temp_mesh_name = '~tmp-mesh'
+
+       time1 = sys.time()
+       scn = Scene.GetCurrent()
+
+       file = open(filename, "w")
+       
+       # Write Header
+       file.write('# Blender3D v%s OBJ File: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] ))
+       file.write('# www.blender3d.org\n')
+
+       # Tell the obj file what material file to use.
+       if EXPORT_MTL:
+               mtlfilename = '%s.mtl' % '.'.join(filename.split('.')[:-1])
+               file.write('mtllib %s\n' % ( mtlfilename.split('\\')[-1].split('/')[-1] ))
+       
+       # Get the container mesh. - used for applying modifiers and non mesh objects.
+       containerMesh = meshName = tempMesh = None
+       for meshName in Blender.NMesh.GetNames():
+               if meshName.startswith(temp_mesh_name):
+                       tempMesh = Mesh.Get(meshName)
+                       if not tempMesh.users:
+                               containerMesh = tempMesh
+       if not containerMesh:
+               containerMesh = Mesh.New(temp_mesh_name)
+       
+       if EXPORT_ROTX90:
+               mat_xrot90= Blender.Mathutils.RotationMatrix(-90, 4, 'x')
+               
+       del meshName
+       del tempMesh
+       
+       # Initialize totals, these are updated each object
+       totverts = totuvco = totno = 1
+       
+       face_vert_index = 1
+       
+       globalNormals = {}
+       
+       # Get all meshs
+       for ob_main in objects:
+               for ob, ob_mat in BPyObject.getDerivedObjects(ob_main):
+                       # Will work for non meshes now! :)
+                       # getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None)
+                       me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, False, scn)
+                       if not me:
+                               continue
+                       
+                       if EXPORT_UV:
+                               faceuv= me.faceUV
+                       else:
+                               faceuv = False
+                       
+                       # We have a valid mesh
+                       if EXPORT_TRI and me.faces:
+                               # Add a dummy object to it.
+                               has_quads = False
+                               for f in me.faces:
+                                       if len(f) == 4:
+                                               has_quads = True
+                                               break
+                               
+                               if has_quads:
+                                       oldmode = Mesh.Mode()
+                                       Mesh.Mode(Mesh.SelectModes['FACE'])
+                                       
+                                       me.sel = True
+                                       tempob = scn.objects.new(me)
+                                       me.quadToTriangle(0) # more=0 shortest length
+                                       oldmode = Mesh.Mode(oldmode)
+                                       scn.objects.unlink(tempob)
+                                       
+                                       Mesh.Mode(oldmode)
+                       
+                       # Make our own list so it can be sorted to reduce context switching
+                       faces = [ f for f in me.faces ]
+                       
+                       if EXPORT_EDGES:
+                               edges = me.edges
+                       else:
+                               edges = []
+                       
+                       if not (len(faces)+len(edges)+len(me.verts)): # Make sure there is somthing to write
+                               continue # dont bother with this mesh.
+                       
+                       if EXPORT_ROTX90:
+                               me.transform(ob_mat*mat_xrot90)
+                       else:
+                               me.transform(ob_mat)
+                       
+                       # High Quality Normals
+                       if EXPORT_NORMALS and faces:
+                               if EXPORT_NORMALS_HQ:
+                                       BPyMesh.meshCalcNormals(me)
+                               else:
+                                       # transforming normals is incorrect
+                                       # when the matrix is scaled,
+                                       # better to recalculate them
+                                       me.calcNormals()
+                       
+                       # # Crash Blender
+                       #materials = me.getMaterials(1) # 1 == will return None in the list.
+                       materials = me.materials
+                       
+                       materialNames = []
+                       materialItems = materials[:]
+                       if materials:
+                               for mat in materials:
+                                       if mat: # !=None
+                                               materialNames.append(mat.name)
+                                       else:
+                                               materialNames.append(None)
+                               # Cant use LC because some materials are None.
+                               # materialNames = map(lambda mat: mat.name, materials) # Bug Blender, dosent account for null materials, still broken.  
+                       
+                       # Possible there null materials, will mess up indicies
+                       # but at least it will export, wait until Blender gets fixed.
+                       materialNames.extend((16-len(materialNames)) * [None])
+                       materialItems.extend((16-len(materialItems)) * [None])
+                       
+                       # Sort by Material, then images
+                       # so we dont over context switch in the obj file.
+                       if EXPORT_KEEP_VERT_ORDER:
+                               pass
+                       elif faceuv:
+                               try:    faces.sort(key = lambda a: (a.mat, a.image, a.smooth))
+                               except: faces.sort(lambda a,b: cmp((a.mat, a.image, a.smooth), (b.mat, b.image, b.smooth)))
+                       elif len(materials) > 1:
+                               try:    faces.sort(key = lambda a: (a.mat, a.smooth))
+                               except: faces.sort(lambda a,b: cmp((a.mat, a.smooth), (b.mat, b.smooth)))
+                       else:
+                               # no materials
+                               try:    faces.sort(key = lambda a: a.smooth)
+                               except: faces.sort(lambda a,b: cmp(a.smooth, b.smooth))
+                       
+                       # Set the default mat to no material and no image.
+                       contextMat = (0, 0) # Can never be this, so we will label a new material teh first chance we get.
+                       contextSmooth = None # Will either be true or false,  set bad to force initialization switch.
+                       
+                       if EXPORT_BLEN_OBS or EXPORT_GROUP_BY_OB:
+                               name1 = ob.name
+                               name2 = ob.getData(1)
+                               if name1 == name2:
+                                       obnamestring = fixName(name1)
+                               else:
+                                       obnamestring = '%s_%s' % (fixName(name1), fixName(name2))
+                               
+                               if EXPORT_BLEN_OBS:
+                                       file.write('o %s\n' % obnamestring) # Write Object name
+                               else: # if EXPORT_GROUP_BY_OB:
+                                       file.write('g %s\n' % obnamestring)
+                       
+                       
+                       # Vert
+                       for v in me.verts:
+                               file.write('v %.6f %.6f %.6f\n' % tuple(v.co))
+                       
+                       # UV
+                       if faceuv:
+                               uv_face_mapping = [[0,0,0,0] for f in faces] # a bit of a waste for tri's :/
+                               
+                               uv_dict = {} # could use a set() here
+                               for f_index, f in enumerate(faces):
+                                       
+                                       for uv_index, uv in enumerate(f.uv):
+                                               uvkey = veckey2d(uv)
+                                               try:
+                                                       uv_face_mapping[f_index][uv_index] = uv_dict[uvkey]
+                                               except:
+                                                       uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] = len(uv_dict)
+                                                       file.write('vt %.6f %.6f\n' % tuple(uv))
+                               
+                               uv_unique_count = len(uv_dict)
+                               del uv, uvkey, uv_dict, f_index, uv_index
+                               # Only need uv_unique_count and uv_face_mapping
+                       
+                       # NORMAL, Smooth/Non smoothed.
+                       if EXPORT_NORMALS:
+                               for f in faces:
+                                       if f.smooth:
+                                               for v in f:
+                                                       noKey = veckey3d(v.no)
+                                                       if not globalNormals.has_key( noKey ):
+                                                               globalNormals[noKey] = totno
+                                                               totno +=1
+                                                               file.write('vn %.6f %.6f %.6f\n' % noKey)
+                                       else:
+                                               # Hard, 1 normal from the face.
+                                               noKey = veckey3d(f.no)
+                                               if not globalNormals.has_key( noKey ):
+                                                       globalNormals[noKey] = totno
+                                                       totno +=1
+                                                       file.write('vn %.6f %.6f %.6f\n' % noKey)
+                       
+                       if not faceuv:
+                               f_image = None
+                       
+                       for f_index, f in enumerate(faces):
+                               f_v= f.v
+                               f_smooth= f.smooth
+                               f_mat = min(f.mat, len(materialNames)-1)
+                               if faceuv:
+                                       f_image = f.image
+                                       f_uv= f.uv
+                               
+                               # MAKE KEY
+                               if faceuv and f_image: # Object is always true.
+                                       key = materialNames[f_mat],      f_image.name
+                               else:
+                                       key = materialNames[f_mat],      None # No image, use None instead.
+                               
+                               # CHECK FOR CONTEXT SWITCH
+                               if key == contextMat:
+                                       pass # Context alredy switched, dont do anythoing
+                               else:
+                                       if key[0] == None and key[1] == None:
+                                               # Write a null material, since we know the context has changed.
+                                               if EXPORT_GROUP_BY_MAT:
+                                                       file.write('g %s_%s\n' % (fixName(ob.name), fixName(ob.getData(1))) ) # can be mat_image or (null)
+                                               file.write('usemtl (null)\n') # mat, image
+                                               
+                                       else:
+                                               mat_data= MTL_DICT.get(key)
+                                               if not mat_data:
+                                                       # First add to global dict so we can export to mtl
+                                                       # Then write mtl
+                                                       
+                                                       # Make a new names from the mat and image name,
+                                                       # converting any spaces to underscores with fixName.
+                                                       
+                                                       # If none image dont bother adding it to the name
+                                                       if key[1] == None:
+                                                               mat_data = MTL_DICT[key] = ('%s'%fixName(key[0])), materialItems[f_mat], f_image
+                                                       else:
+                                                               mat_data = MTL_DICT[key] = ('%s_%s' % (fixName(key[0]), fixName(key[1]))), materialItems[f_mat], f_image
+                                               
+                                               if EXPORT_GROUP_BY_MAT:
+                                                       file.write('g %s_%s_%s\n' % (fixName(ob.name), fixName(ob.getData(1)), mat_data[0]) ) # can be mat_image or (null)
+                                               file.write('usemtl %s\n' % mat_data[0]) # can be mat_image or (null)
+                                       
+                               contextMat = key
+                               if f_smooth != contextSmooth:
+                                       if f_smooth: # on now off
+                                               file.write('s 1\n')
+                                               contextSmooth = f_smooth
+                                       else: # was off now on
+                                               file.write('s off\n')
+                                               contextSmooth = f_smooth
+                               
+                               file.write('f')
+                               if faceuv:
+                                       if EXPORT_NORMALS:
+                                               if f_smooth: # Smoothed, use vertex normals
+                                                       for vi, v in enumerate(f_v):
+                                                               file.write( ' %d/%d/%d' % (\
+                                                                 v.index+totverts,\
+                                                                 totuvco + uv_face_mapping[f_index][vi],\
+                                                                 globalNormals[ veckey3d(v.no) ])) # vert, uv, normal
+                                                       
+                                               else: # No smoothing, face normals
+                                                       no = globalNormals[ veckey3d(f.no) ]
+                                                       for vi, v in enumerate(f_v):
+                                                               file.write( ' %d/%d/%d' % (\
+                                                                 v.index+totverts,\
+                                                                 totuvco + uv_face_mapping[f_index][vi],\
+                                                                 no)) # vert, uv, normal
+                                       
+                                       else: # No Normals
+                                               for vi, v in enumerate(f_v):
+                                                       file.write( ' %d/%d' % (\
+                                                         v.index+totverts,\
+                                                         totuvco + uv_face_mapping[f_index][vi])) # vert, uv
+                                       
+                                       face_vert_index += len(f_v)
+                               
+                               else: # No UV's
+                                       if EXPORT_NORMALS:
+                                               if f_smooth: # Smoothed, use vertex normals
+                                                       for v in f_v:
+                                                               file.write( ' %d//%d' % (\
+                                                                 v.index+totverts,\
+                                                                 globalNormals[ veckey3d(v.no) ]))
+                                               else: # No smoothing, face normals
+                                                       no = globalNormals[ veckey3d(f.no) ]
+                                                       for v in f_v:
+                                                               file.write( ' %d//%d' % (\
+                                                                 v.index+totverts,\
+                                                                 no))
+                                       else: # No Normals
+                                               for v in f_v:
+                                                       file.write( ' %d' % (\
+                                                         v.index+totverts))
+                                               
+                               file.write('\n')
+                       
+                       # Write edges.
+                       if EXPORT_EDGES:
+                               LOOSE= Mesh.EdgeFlags.LOOSE
+                               for ed in edges:
+                                       if ed.flag & LOOSE:
+                                               file.write('f %d %d\n' % (ed.v1.index+totverts, ed.v2.index+totverts))
+                               
+                       # Make the indicies global rather then per mesh
+                       totverts += len(me.verts)
+                       if faceuv:
+                               totuvco += uv_unique_count
+                       me.verts= None
+       file.close()
+       
+       
+       # Now we have all our materials, save them
+       if EXPORT_MTL:
+               write_mtl(mtlfilename)
+       if EXPORT_COPY_IMAGES:
+               dest_dir = filename
+               # Remove chars until we are just the path.
+               while dest_dir and dest_dir[-1] not in '\\/':
+                       dest_dir = dest_dir[:-1]
+               if dest_dir:
+                       copy_images(dest_dir)
+               else:
+                       print '\tError: "%s" could not be used as a base for an image path.' % filename
+       
+       print "OBJ Export time: %.2f" % (sys.time() - time1)
+       
+
+# replaced by do_export
+def write_ui(filename):
+       
+       if not filename.lower().endswith('.obj'):
+               filename += '.obj'
+       
+       if not BPyMessages.Warning_SaveOver(filename):
+               return
+       
+       global EXPORT_APPLY_MODIFIERS, EXPORT_ROTX90, EXPORT_TRI, EXPORT_EDGES,\
+               EXPORT_NORMALS, EXPORT_NORMALS_HQ, EXPORT_UV,\
+               EXPORT_MTL, EXPORT_SEL_ONLY, EXPORT_ALL_SCENES,\
+               EXPORT_ANIMATION, EXPORT_COPY_IMAGES, EXPORT_BLEN_OBS,\
+               EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER
+       
+       EXPORT_APPLY_MODIFIERS = Draw.Create(0)
+       EXPORT_ROTX90 = Draw.Create(1)
+       EXPORT_TRI = Draw.Create(0)
+       EXPORT_EDGES = Draw.Create(1)
+       EXPORT_NORMALS = Draw.Create(0)
+       EXPORT_NORMALS_HQ = Draw.Create(0)
+       EXPORT_UV = Draw.Create(1)
+       EXPORT_MTL = Draw.Create(1)
+       EXPORT_SEL_ONLY = Draw.Create(1)
+       EXPORT_ALL_SCENES = Draw.Create(0)
+       EXPORT_ANIMATION = Draw.Create(0)
+       EXPORT_COPY_IMAGES = Draw.Create(0)
+       EXPORT_BLEN_OBS = Draw.Create(0)
+       EXPORT_GROUP_BY_OB = Draw.Create(0)
+       EXPORT_GROUP_BY_MAT = Draw.Create(0)
+       EXPORT_KEEP_VERT_ORDER = Draw.Create(1)
+       
+       # Old UI
+       '''
+       # removed too many options are bad!
+       
+       # Get USER Options
+       pup_block = [\
+       ('Context...'),\
+       ('Selection Only', EXPORT_SEL_ONLY, 'Only export objects in visible selection. Else export whole scene.'),\
+       ('All Scenes', EXPORT_ALL_SCENES, 'Each scene as a separate OBJ file.'),\
+       ('Animation', EXPORT_ANIMATION, 'Each frame as a numbered OBJ file.'),\
+       ('Object Prefs...'),\
+       ('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data from each object. May break vert order for morph targets.'),\
+       ('Rotate X90', EXPORT_ROTX90 , 'Rotate on export so Blenders UP is translated into OBJs UP'),\
+       ('Keep Vert Order', EXPORT_KEEP_VERT_ORDER, 'Keep vert and face order, disables some other options.'),\
+       ('Extra Data...'),\
+       ('Edges', EXPORT_EDGES, 'Edges not connected to faces.'),\
+       ('Normals', EXPORT_NORMALS, 'Export vertex normal data (Ignored on import).'),\
+       ('High Quality Normals', EXPORT_NORMALS_HQ, 'Calculate high quality normals for rendering.'),\
+       ('UVs', EXPORT_UV, 'Export texface UV coords.'),\
+       ('Materials', EXPORT_MTL, 'Write a separate MTL file with the OBJ.'),\
+       ('Copy Images', EXPORT_COPY_IMAGES, 'Copy image files to the export directory, never overwrite.'),\
+       ('Triangulate', EXPORT_TRI, 'Triangulate quads.'),\
+       ('Grouping...'),\
+       ('Objects', EXPORT_BLEN_OBS, 'Export blender objects as "OBJ objects".'),\
+       ('Object Groups', EXPORT_GROUP_BY_OB, 'Export blender objects as "OBJ Groups".'),\
+       ('Material Groups', EXPORT_GROUP_BY_MAT, 'Group by materials.'),\
+       ]
+       
+       if not Draw.PupBlock('Export...', pup_block):
+               return
+       '''
+       
+       # BEGIN ALTERNATIVE UI *******************
+       if True: 
+               
+               EVENT_NONE = 0
+               EVENT_EXIT = 1
+               EVENT_REDRAW = 2
+               EVENT_EXPORT = 3
+               
+               GLOBALS = {}
+               GLOBALS['EVENT'] = EVENT_REDRAW
+               #GLOBALS['MOUSE'] = Window.GetMouseCoords()
+               GLOBALS['MOUSE'] = [i/2 for i in Window.GetScreenSize()]
+               
+               def obj_ui_set_event(e,v):
+                       GLOBALS['EVENT'] = e
+               
+               def do_split(e,v):
+                       global EXPORT_BLEN_OBS, EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_APPLY_MODIFIERS, KEEP_VERT_ORDER
+                       if EXPORT_BLEN_OBS.val or EXPORT_GROUP_BY_OB.val or EXPORT_GROUP_BY_MAT.val or EXPORT_APPLY_MODIFIERS.val:
+                               EXPORT_KEEP_VERT_ORDER.val = 0
+                       else:
+                               EXPORT_KEEP_VERT_ORDER.val = 1
+                       
+               def do_vertorder(e,v):
+                       global EXPORT_BLEN_OBS, EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_APPLY_MODIFIERS, KEEP_VERT_ORDER
+                       if EXPORT_KEEP_VERT_ORDER.val:
+                               EXPORT_BLEN_OBS.val = EXPORT_GROUP_BY_OB.val = EXPORT_GROUP_BY_MAT.val = EXPORT_APPLY_MODIFIERS.val = 0
+                       else:
+                               if not (EXPORT_BLEN_OBS.val or EXPORT_GROUP_BY_OB.val or EXPORT_GROUP_BY_MAT.val or EXPORT_APPLY_MODIFIERS.val):
+                                       EXPORT_KEEP_VERT_ORDER.val = 1
+                       
+               def do_help(e,v):
+                       url = __url__[0]
+                       print 'Trying to open web browser with documentation at this address...'
+                       print '\t' + url
+                       
+                       try:
+                               import webbrowser
+                               webbrowser.open(url)
+                       except:
+                               print '...could not open a browser window.'
+               
+               def obj_ui():
+                       ui_x, ui_y = GLOBALS['MOUSE']
+                       
+                       # Center based on overall pup size
+                       ui_x -= 165
+                       ui_y -= 110
+                       
+                       global EXPORT_APPLY_MODIFIERS, EXPORT_ROTX90, EXPORT_TRI, EXPORT_EDGES,\
+                               EXPORT_NORMALS, EXPORT_NORMALS_HQ, EXPORT_UV,\
+                               EXPORT_MTL, EXPORT_SEL_ONLY, EXPORT_ALL_SCENES,\
+                               EXPORT_ANIMATION, EXPORT_COPY_IMAGES, EXPORT_BLEN_OBS,\
+                               EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER
+
+                       Draw.Label('Context...', ui_x+9, ui_y+209, 220, 20)
+                       Draw.BeginAlign()
+                       EXPORT_SEL_ONLY = Draw.Toggle('Selection Only', EVENT_NONE, ui_x+9, ui_y+189, 110, 20, EXPORT_SEL_ONLY.val, 'Only export objects in visible selection. Else export whole scene.')
+                       EXPORT_ALL_SCENES = Draw.Toggle('All Scenes', EVENT_NONE, ui_x+119, ui_y+189, 110, 20, EXPORT_ALL_SCENES.val, 'Each scene as a separate OBJ file.')
+                       EXPORT_ANIMATION = Draw.Toggle('Animation', EVENT_NONE, ui_x+229, ui_y+189, 110, 20, EXPORT_ANIMATION.val, 'Each frame as a numbered OBJ file.')
+                       Draw.EndAlign()
+                       
+                       
+                       Draw.Label('Output Options...', ui_x+9, ui_y+159, 220, 20)
+                       Draw.BeginAlign()
+                       EXPORT_APPLY_MODIFIERS = Draw.Toggle('Apply Modifiers', EVENT_REDRAW, ui_x+9, ui_y+140, 110, 20, EXPORT_APPLY_MODIFIERS.val, 'Use transformed mesh data from each object. May break vert order for morph targets.', do_split)
+                       EXPORT_ROTX90 = Draw.Toggle('Rotate X90', EVENT_NONE, ui_x+119, ui_y+140, 110, 20, EXPORT_ROTX90.val, 'Rotate on export so Blenders UP is translated into OBJs UP')
+                       EXPORT_COPY_IMAGES = Draw.Toggle('Copy Images', EVENT_NONE, ui_x+229, ui_y+140, 110, 20, EXPORT_COPY_IMAGES.val, 'Copy image files to the export directory, never overwrite.')
+                       Draw.EndAlign()
+                       
+                       
+                       Draw.Label('Export...', ui_x+9, ui_y+109, 220, 20)
+                       Draw.BeginAlign()
+                       EXPORT_EDGES = Draw.Toggle('Edges', EVENT_NONE, ui_x+9, ui_y+90, 50, 20, EXPORT_EDGES.val, 'Edges not connected to faces.')
+                       EXPORT_TRI = Draw.Toggle('Triangulate', EVENT_NONE, ui_x+59, ui_y+90, 70, 20, EXPORT_TRI.val, 'Triangulate quads.')
+                       Draw.EndAlign()
+                       Draw.BeginAlign()
+                       EXPORT_MTL = Draw.Toggle('Materials', EVENT_NONE, ui_x+139, ui_y+90, 70, 20, EXPORT_MTL.val, 'Write a separate MTL file with the OBJ.')
+                       EXPORT_UV = Draw.Toggle('UVs', EVENT_NONE, ui_x+209, ui_y+90, 31, 20, EXPORT_UV.val, 'Export texface UV coords.')
+                       Draw.EndAlign()
+                       Draw.BeginAlign()
+                       EXPORT_NORMALS = Draw.Toggle('Normals', EVENT_NONE, ui_x+250, ui_y+90, 59, 20, EXPORT_NORMALS.val, 'Export vertex normal data (Ignored on import).')
+                       EXPORT_NORMALS_HQ = Draw.Toggle('HQ', EVENT_NONE, ui_x+309, ui_y+90, 31, 20, EXPORT_NORMALS_HQ.val, 'Calculate high quality normals for rendering.')
+                       Draw.EndAlign()
+                       
+                       
+                       Draw.Label('Blender Objects as OBJ:', ui_x+9, ui_y+59, 220, 20)
+                       Draw.BeginAlign()
+                       EXPORT_BLEN_OBS = Draw.Toggle('Objects', EVENT_REDRAW, ui_x+9, ui_y+39, 60, 20, EXPORT_BLEN_OBS.val, 'Export blender objects as "OBJ objects".', do_split)
+                       EXPORT_GROUP_BY_OB = Draw.Toggle('Groups', EVENT_REDRAW, ui_x+69, ui_y+39, 60, 20, EXPORT_GROUP_BY_OB.val, 'Export blender objects as "OBJ Groups".', do_split)
+                       EXPORT_GROUP_BY_MAT = Draw.Toggle('Material Groups', EVENT_REDRAW, ui_x+129, ui_y+39, 100, 20, EXPORT_GROUP_BY_MAT.val, 'Group by materials.', do_split)
+                       Draw.EndAlign()
+                       
+                       EXPORT_KEEP_VERT_ORDER = Draw.Toggle('Keep Vert Order', EVENT_REDRAW, ui_x+239, ui_y+39, 100, 20, EXPORT_KEEP_VERT_ORDER.val, 'Keep vert and face order, disables some other options. Use for morph targets.', do_vertorder)
+                       
+                       Draw.BeginAlign()
+                       Draw.PushButton('Online Help', EVENT_REDRAW, ui_x+9, ui_y+9, 110, 20, 'Load the wiki page for this script', do_help)
+                       Draw.PushButton('Cancel', EVENT_EXIT, ui_x+119, ui_y+9, 110, 20, '', obj_ui_set_event)
+                       Draw.PushButton('Export', EVENT_EXPORT, ui_x+229, ui_y+9, 110, 20, 'Export with these settings', obj_ui_set_event)
+                       Draw.EndAlign()
+
+               
+               # hack so the toggle buttons redraw. this is not nice at all
+               while GLOBALS['EVENT'] not in (EVENT_EXIT, EVENT_EXPORT):
+                       Draw.UIBlock(obj_ui, 0)
+               
+               if GLOBALS['EVENT'] != EVENT_EXPORT:
+                       return
+               
+       # END ALTERNATIVE UI *********************
+       
+       
+       if EXPORT_KEEP_VERT_ORDER.val:
+               EXPORT_BLEN_OBS.val = False
+               EXPORT_GROUP_BY_OB.val = False
+               EXPORT_GROUP_BY_MAT.val = False
+               EXPORT_APPLY_MODIFIERS.val = False
+       
+       Window.EditMode(0)
+       Window.WaitCursor(1)
+       
+       EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val
+       EXPORT_ROTX90 = EXPORT_ROTX90.val
+       EXPORT_TRI = EXPORT_TRI.val
+       EXPORT_EDGES = EXPORT_EDGES.val
+       EXPORT_NORMALS = EXPORT_NORMALS.val
+       EXPORT_NORMALS_HQ = EXPORT_NORMALS_HQ.val
+       EXPORT_UV = EXPORT_UV.val
+       EXPORT_MTL = EXPORT_MTL.val
+       EXPORT_SEL_ONLY = EXPORT_SEL_ONLY.val
+       EXPORT_ALL_SCENES = EXPORT_ALL_SCENES.val
+       EXPORT_ANIMATION = EXPORT_ANIMATION.val
+       EXPORT_COPY_IMAGES = EXPORT_COPY_IMAGES.val
+       EXPORT_BLEN_OBS = EXPORT_BLEN_OBS.val
+       EXPORT_GROUP_BY_OB = EXPORT_GROUP_BY_OB.val
+       EXPORT_GROUP_BY_MAT = EXPORT_GROUP_BY_MAT.val
+       EXPORT_KEEP_VERT_ORDER = EXPORT_KEEP_VERT_ORDER.val
+       
+       
+       
+       base_name, ext = splitExt(filename)
+       context_name = [base_name, '', '', ext] # basename, scene_name, framenumber, extension
+       
+       # Use the options to export the data using write()
+       # def write(filename, objects, EXPORT_EDGES=False, EXPORT_NORMALS=False, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False, EXPORT_APPLY_MODIFIERS=True):
+       orig_scene = Scene.GetCurrent()
+       if EXPORT_ALL_SCENES:
+               export_scenes = Scene.Get()
+       else:
+               export_scenes = [orig_scene]
+       
+       # Export all scenes.
+       for scn in export_scenes:
+               scn.makeCurrent() # If alredy current, this is not slow.
+               context = scn.getRenderingContext()
+               orig_frame = Blender.Get('curframe')
+               
+               if EXPORT_ALL_SCENES: # Add scene name into the context_name
+                       context_name[1] = '_%s' % BPySys.cleanName(scn.name) # WARNING, its possible that this could cause a collision. we could fix if were feeling parranoied.
+               
+               # Export an animation?
+               if EXPORT_ANIMATION:
+                       scene_frames = xrange(context.startFrame(), context.endFrame()+1) # up to and including the end frame.
+               else:
+                       scene_frames = [orig_frame] # Dont export an animation.
+               
+               # Loop through all frames in the scene and export.
+               for frame in scene_frames:
+                       if EXPORT_ANIMATION: # Add frame to the filename.
+                               context_name[2] = '_%.6d' % frame
+                       
+                       Blender.Set('curframe', frame)
+                       if EXPORT_SEL_ONLY:
+                               export_objects = scn.objects.context
+                       else:   
+                               export_objects = scn.objects
+                       
+                       full_path= ''.join(context_name)
+                       
+                       # erm... bit of a problem here, this can overwrite files when exporting frames. not too bad.
+                       # EXPORT THE FILE.
+                       write(full_path, export_objects,\
+                       EXPORT_TRI, EXPORT_EDGES, EXPORT_NORMALS,\
+                       EXPORT_NORMALS_HQ, EXPORT_UV, EXPORT_MTL,\
+                       EXPORT_COPY_IMAGES, EXPORT_APPLY_MODIFIERS,\
+                       EXPORT_ROTX90, EXPORT_BLEN_OBS,\
+                       EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER)
+               
+               Blender.Set('curframe', orig_frame)
+       
+       # Restore old active scene.
+       orig_scene.makeCurrent()
+       Window.WaitCursor(0)
+
+
+def do_export(filename, context):
+#      Window.EditMode(0)
+#      Window.WaitCursor(1)
+       
+       EXPORT_APPLY_MODIFIERS = True
+       EXPORT_ROTX90 = True
+       EXPORT_TRI = False
+       EXPORT_EDGES = False
+       EXPORT_NORMALS = False
+       EXPORT_NORMALS_HQ = False
+       EXPORT_UV = True
+       EXPORT_MTL = True
+       EXPORT_SEL_ONLY = True
+       EXPORT_ALL_SCENES = False # XXX not working atm
+       EXPORT_ANIMATION = False
+       EXPORT_COPY_IMAGES = False
+       EXPORT_BLEN_OBS = True
+       EXPORT_GROUP_BY_OB = False
+       EXPORT_GROUP_BY_MAT = False
+       EXPORT_KEEP_VERT_ORDER = False
+
+       base_name, ext = splitExt(filename)
+       context_name = [base_name, '', '', ext] # Base name, scene name, frame number, extension
+       
+       orig_scene = context.scene
+
+#      if EXPORT_ALL_SCENES:
+#              export_scenes = bpy.data.scenes
+#      else:
+#              export_scenes = [orig_scene]
+
+       # XXX only exporting one scene atm since changing 
+       # current scene is not possible.
+       # Brecht says that ideally in 2.5 we won't need such a function,
+       # allowing multiple scenes open at once.
+       export_scenes = [orig_scene]
+
+       # Export all scenes.
+       for scn in export_scenes:
+#              scn.makeCurrent() # If already current, this is not slow.
+#              context = scn.getRenderingContext()
+               orig_frame = scn.current_frame
+               
+               if EXPORT_ALL_SCENES: # Add scene name into the context_name
+                       context_name[1] = '_%s' % BPySys.cleanName(scn.name) # WARNING, its possible that this could cause a collision. we could fix if were feeling parranoied.
+               
+               # Export an animation?
+               if EXPORT_ANIMATION:
+                       scene_frames = xrange(scn.start_frame, context.end_frame+1) # Up to and including the end frame.
+               else:
+                       scene_frames = [orig_frame] # Dont export an animation.
+               
+               # Loop through all frames in the scene and export.
+               for frame in scene_frames:
+                       if EXPORT_ANIMATION: # Add frame to the filename.
+                               context_name[2] = '_%.6d' % frame
+                       
+                       scn.current_frame = frame
+                       if EXPORT_SEL_ONLY:
+                               export_objects = context.selected_objects
+                       else:   
+                               export_objects = scn.objects
+                       
+                       full_path= ''.join(context_name)
+                       
+                       # erm... bit of a problem here, this can overwrite files when exporting frames. not too bad.
+                       # EXPORT THE FILE.
+#                      write(full_path, export_objects,
+#                                      EXPORT_TRI, EXPORT_EDGES, EXPORT_NORMALS,
+#                                      EXPORT_NORMALS_HQ, EXPORT_UV, EXPORT_MTL,
+#                                      EXPORT_COPY_IMAGES, EXPORT_APPLY_MODIFIERS,
+#                                      EXPORT_ROTX90, EXPORT_BLEN_OBS,
+#                                      EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER)
+               
+               scn.current_frame = orig_frame
+       
+       # Restore old active scene.
+#      orig_scene.makeCurrent()
+#      Window.WaitCursor(0)
+
+
+class SCRIPT_OT_export_obj(bpy.types.Operator):
+       '''
+       Operator documentatuon text, will be used for the operator tooltip and python docs.
+       '''
+       __label__ = 'My Operator'
+       
+       # List of operator properties, the attributes will be assigned
+       # to the class instance from the operator settings before calling.
+       __props__ = [
+               #               bpy.types.FloatProperty(attr="setting_1", name="Example 1",
+               #               default=10.0, min=0, max=10, description="Add info here"),
+               #               bpy.types.IntProperty(attr="setting_2", default=2),
+               #               bpy.types.BoolProperty(attr="toggle", default=True)
+               ]
+       
+       def execu(self, context):
+               print("Selected: " + context.active_object.name)
+
+               do_export("/tmp/test.obj", context)
+
+               return 'FINISHED'
+       
+       def invoke(self, event):
+               print("Invoke")
+               return 'FINISHED'
+       
+       def poll(self, context): # Poll isnt working yet
+               print("Poll")
+               return True
+
+if (hasattr(bpy.ops, "SCRIPT_OT_export_obj")):
+       bpy.ops.remove(bpy.ops.SCRIPT_OT_export_obj)
+
+bpy.ops.add(SCRIPT_OT_export_obj)
+
+bpy.ops.SCRIPT_OT_export_obj()
+
+bpy.ops.remove(bpy.ops.SCRIPT_OT_export_obj)
diff --git a/release/ui/buttons_particle.py b/release/ui/buttons_particle.py
deleted file mode 100644 (file)
index 737aa1a..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-
-import bpy
-
-class ParticleButtonsPanel(bpy.types.Panel):
-       __space_type__ = "BUTTONS_WINDOW"
-       __region_type__ = "WINDOW"
-       __context__ = "particle"
-
-       def poll(self, context):
-               return (context.particle_system != None)
-
-class PARTICLE_PT_particles(ParticleButtonsPanel):
-       __idname__= "PARTICLE_PT_particles"
-       __label__ = "Particles"
-
-       def draw(self, context):
-               layout = self.layout
-
-               psys = context.particle_system
-               part = psys.settings
-
-               layout.itemR(part, "amount")
-
-bpy.types.register(PARTICLE_PT_particles)
-
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
deleted file mode 100644 (file)
index 3e6fa9c..0000000
+++ /dev/null
@@ -1,536 +0,0 @@
-/**
- * $Id:
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. 
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2009 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_armature_types.h"
-#include "DNA_lamp_types.h"
-#include "DNA_material_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-#include "DNA_particle_types.h"
-#include "DNA_texture_types.h"
-#include "DNA_world_types.h"
-
-#include "BLI_listbase.h"
-
-#include "BKE_context.h"
-#include "BKE_material.h"
-#include "BKE_modifier.h"
-#include "BKE_particle.h"
-#include "BKE_screen.h"
-#include "BKE_utildefines.h"
-
-#include "RNA_access.h"
-
-#include "UI_interface.h"
-#include "UI_resources.h"
-
-#include "buttons_intern.h"    // own include
-
-typedef struct ButsContextPath {
-       PointerRNA ptr[8];
-       int len;
-} ButsContextPath;
-
-/************************* Creating the Path ************************/
-
-static int buttons_context_path_scene(ButsContextPath *path)
-{
-       PointerRNA *ptr= &path->ptr[path->len-1];
-
-       /* this one just verifies */
-       return RNA_struct_is_a(ptr->type, &RNA_Scene);
-}
-
-static int buttons_context_path_world(ButsContextPath *path)
-{
-       Scene *scene;
-       PointerRNA *ptr= &path->ptr[path->len-1];
-
-       /* if we already have a (pinned) world, we're done */
-       if(RNA_struct_is_a(ptr->type, &RNA_World)) {
-               return 1;
-       }
-       /* if we have a scene, use the scene's world */
-       else if(buttons_context_path_scene(path)) {
-               scene= path->ptr[path->len-1].data;
-
-               RNA_id_pointer_create(&scene->world->id, &path->ptr[path->len]);
-               path->len++;
-
-               return 1;
-       }
-
-       /* no path to a world possible */
-       return 0;
-}
-
-static int buttons_context_path_object(ButsContextPath *path)
-{
-       Scene *scene;
-       Object *ob;
-       PointerRNA *ptr= &path->ptr[path->len-1];
-
-       /* if we already have a (pinned) object, we're done */
-       if(RNA_struct_is_a(ptr->type, &RNA_Object)) {
-               return 1;
-       }
-       /* if we have a scene, use the scene's active object */
-       else if(buttons_context_path_scene(path)) {
-               scene= path->ptr[path->len-1].data;
-               ob= (scene->basact)? scene->basact->object: NULL;
-
-               if(ob) {
-                       RNA_id_pointer_create(&ob->id, &path->ptr[path->len]);
-                       path->len++;
-
-                       return 1;
-               }
-       }
-
-       /* no path to a object possible */
-       return 0;
-}
-
-static int buttons_context_path_data(ButsContextPath *path, int type)
-{
-       Object *ob;
-
-       /* try to get an object in the path, no pinning supported here */
-       if(buttons_context_path_object(path)) {
-               ob= path->ptr[path->len-1].data;
-
-               if(type == -1 || type == ob->type) {
-                       RNA_id_pointer_create(ob->data, &path->ptr[path->len]);
-                       path->len++;
-
-                       return 1;
-               }
-       }
-
-       /* no path to data possible */
-       return 0;
-}
-
-static int buttons_context_path_material(ButsContextPath *path)
-{
-       Object *ob;
-       PointerRNA *ptr= &path->ptr[path->len-1];
-
-       /* if we already have a (pinned) material, we're done */
-       if(RNA_struct_is_a(ptr->type, &RNA_Material)) {
-               return 1;
-       }
-       /* if we have an object, use the object material slot */
-       else if(buttons_context_path_object(path)) {
-               ob= path->ptr[path->len-1].data;
-
-               if(ob && ob->type && (ob->type<OB_LAMP)) {
-                       RNA_pointer_create(&ob->id, &RNA_MaterialSlot, ob->mat+ob->actcol-1, &path->ptr[path->len]);
-                       path->len++;
-                       return 1;
-               }
-       }
-
-       /* no path to a material possible */
-       return 0;
-}
-
-static Bone *find_active_bone(Bone *bone)
-{
-       Bone *active;
-
-       for(; bone; bone=bone->next) {
-               if(bone->flag & BONE_ACTIVE)
-                       return bone;
-
-               active= find_active_bone(bone->childbase.first);
-               if(active)
-                       return active;
-       }
-
-       return NULL;
-}
-
-static int buttons_context_path_bone(ButsContextPath *path)
-{
-       bArmature *arm;
-       Bone *bone;
-
-       /* if we have an armature, get the active bone */
-       if(buttons_context_path_data(path, OB_ARMATURE)) {
-               arm= path->ptr[path->len-1].data;
-               bone= find_active_bone(arm->bonebase.first);
-
-               if(bone) {
-                       RNA_pointer_create(&arm->id, &RNA_Bone, bone, &path->ptr[path->len]);
-                       path->len++;
-                       return 1;
-               }
-       }
-
-       /* no path to a bone possible */
-       return 0;
-}
-
-static int buttons_context_path_particle(ButsContextPath *path)
-{
-       Object *ob;
-       ParticleSystem *psys;
-
-       /* if we have an object, get the active particle system */
-       if(buttons_context_path_object(path)) {
-               ob= path->ptr[path->len-1].data;
-               psys= psys_get_current(ob);
-
-               RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &path->ptr[path->len]);
-               path->len++;
-               return 1;
-       }
-
-       /* no path to a particle system possible */
-       return 0;
-}
-
-static int buttons_context_path_texture(ButsContextPath *path)
-{
-       Object *ob;
-       Lamp *la;
-       Material *ma;
-       PointerRNA *ptr= &path->ptr[path->len-1];
-
-       /* if we already have a (pinned) texture, we're done */
-       if(RNA_struct_is_a(ptr->type, &RNA_Texture)) {
-               return 1;
-       }
-       /* try to get the active material */
-       else if(buttons_context_path_material(path)) {
-               ptr= &path->ptr[path->len-1];
-
-               if(RNA_struct_is_a(ptr->type, &RNA_Material)) {
-                       ma= ptr->data;
-               }
-               else if(RNA_struct_is_a(ptr->type, &RNA_MaterialSlot)) {
-                       ob= ptr->id.data;
-                       ma= give_current_material(ob, (Material**)ptr->data - ob->mat);
-               }
-               else
-                       ma= NULL;
-
-               if(ma) {
-                       RNA_pointer_create(&ma->id, &RNA_TextureSlot, ma->mtex[(int)ma->texact], &path->ptr[path->len]);
-                       path->len++;
-                       return 1;
-               }
-       }
-       /* try to get the active lamp */
-       else if(buttons_context_path_data(path, OB_LAMP)) {
-               la= path->ptr[path->len-1].data;
-
-               if(la) {
-                       RNA_pointer_create(&la->id, &RNA_TextureSlot, la->mtex[(int)la->texact], &path->ptr[path->len]);
-                       path->len++;
-                       return 1;
-               }
-       }
-       /* TODO: world, brush */
-
-       /* no path to a particle system possible */
-       return 0;
-}
-
-static int buttons_context_path(const bContext *C, ButsContextPath *path)
-{
-       SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
-       ID *id;
-       int found;
-
-       memset(path, 0, sizeof(*path));
-
-       /* if some ID datablock is pinned, set the root pointer */
-       if(sbuts->pinid) {
-               id= sbuts->pinid;
-
-               RNA_id_pointer_create(id, &path->ptr[0]);
-               path->len++;
-       }
-
-       /* no pinned root, use scene as root */
-       if(path->len == 0) {
-               id= (ID*)CTX_data_scene(C);
-               RNA_id_pointer_create(id, &path->ptr[0]);
-               path->len++;
-       }
-
-       /* now for each buttons context type, we try to construct a path,
-        * tracing back recursively */
-       switch(sbuts->mainb) {
-               case BCONTEXT_SCENE:
-                       found= buttons_context_path_scene(path);
-                       break;
-               case BCONTEXT_WORLD:
-                       found= buttons_context_path_world(path);
-                       break;
-               case BCONTEXT_OBJECT:
-               case BCONTEXT_PHYSICS:
-               case BCONTEXT_MODIFIER:
-                       found= buttons_context_path_object(path);
-                       break;
-               case BCONTEXT_DATA:
-                       found= buttons_context_path_data(path, -1);
-                       break;
-               case BCONTEXT_PARTICLE:
-                       found= buttons_context_path_particle(path);
-                       break;
-               case BCONTEXT_MATERIAL:
-                       found= buttons_context_path_material(path);
-                       break;
-               case BCONTEXT_TEXTURE:
-                       found= buttons_context_path_texture(path);
-                       break;
-               case BCONTEXT_BONE:
-                       found= buttons_context_path_bone(path);
-                       break;
-               default:
-                       found= 0;
-                       break;
-       }
-
-       return found;
-}
-
-void buttons_context_compute(const bContext *C, SpaceButs *sbuts)
-{
-       if(!sbuts->path)
-               sbuts->path= MEM_callocN(sizeof(ButsContextPath), "ButsContextPath");
-       
-       buttons_context_path(C, sbuts->path);
-}
-
-/************************* Context Callback ************************/
-
-static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, StructRNA *type)
-{
-       PointerRNA *ptr;
-       int a;
-
-       for(a=0; a<path->len; a++) {
-               ptr= &path->ptr[a];
-
-               if(RNA_struct_is_a(ptr->type, type)) {
-                       CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-
-static PointerRNA *get_pointer_type(ButsContextPath *path, StructRNA *type)
-{
-       PointerRNA *ptr;
-       int a;
-
-       for(a=0; a<path->len; a++) {
-               ptr= &path->ptr[a];
-
-               if(RNA_struct_is_a(ptr->type, type))
-                       return ptr;
-       }
-
-       return NULL;
-}
-
-int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
-{
-       SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
-       ButsContextPath *path= sbuts->path;
-
-       if(!path)
-               return 0;
-
-       /* here we handle context, getting data from precomputed path */
-
-       if(CTX_data_equals(member, "world")) {
-               set_pointer_type(path, result, &RNA_World);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "object")) {
-               set_pointer_type(path, result, &RNA_Object);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "mesh")) {
-               set_pointer_type(path, result, &RNA_Mesh);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "armature")) {
-               set_pointer_type(path, result, &RNA_Armature);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "lattice")) {
-               set_pointer_type(path, result, &RNA_Lattice);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "curve")) {
-               set_pointer_type(path, result, &RNA_Curve);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "meta_ball")) {
-               set_pointer_type(path, result, &RNA_MetaBall);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "lamp")) {
-               set_pointer_type(path, result, &RNA_Lamp);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "camera")) {
-               set_pointer_type(path, result, &RNA_Camera);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "material")) {
-               if(!set_pointer_type(path, result, &RNA_Material)) {
-                       PointerRNA *ptr= get_pointer_type(path, &RNA_MaterialSlot);
-
-                       if(ptr && ptr->data) {
-                               Object *ob= ptr->id.data;
-                               Material *ma= give_current_material(ob, (Material**)ptr->data - ob->mat);
-                               CTX_data_id_pointer_set(result, &ma->id);
-                       }
-               }
-
-               return 1;
-       }
-       else if(CTX_data_equals(member, "texture")) {
-               if(!set_pointer_type(path, result, &RNA_Texture)) {
-                       PointerRNA *ptr= get_pointer_type(path, &RNA_TextureSlot);
-
-                       if(ptr && ptr->data)
-                               CTX_data_id_pointer_set(result, &((MTex*)ptr->data)->tex->id);
-               }
-
-               return 1;
-       }
-       else if(CTX_data_equals(member, "material_slot")) {
-               set_pointer_type(path, result, &RNA_MaterialSlot);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "texture_slot")) {
-               set_pointer_type(path, result, &RNA_TextureSlot);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "bone")) {
-               set_pointer_type(path, result, &RNA_Bone);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "particle_system")) {
-               set_pointer_type(path, result, &RNA_ParticleSystem);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "cloth")) {
-               set_pointer_type(path, result, &RNA_ClothModifier);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "soft_body")) {
-               PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
-
-               if(ptr && ptr->data) {
-                       Object *ob= ptr->data;
-                       CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodySettings, ob->soft);
-                       return 1;
-               }
-       }
-       else if(CTX_data_equals(member, "fluid")) {
-               PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
-
-               if(ptr && ptr->data) {
-                       Object *ob= ptr->data;
-                       ModifierData *md= modifiers_findByType(ob, eModifierType_Fluidsim);
-                       CTX_data_pointer_set(result, &ob->id, &RNA_FluidSimulationModifier, md);
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-
-/************************* Drawing the Path ************************/
-
-static void buttons_panel_context(const bContext *C, Panel *pa)
-{
-       SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
-       ButsContextPath *path= sbuts->path;
-       uiLayout *row;
-       PointerRNA *ptr;
-       PropertyRNA *nameprop;
-       char namebuf[128], *name;
-       int a, icon;
-
-       if(!path)
-               return;
-
-       row= uiLayoutRow(pa->layout, 0);
-       uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
-
-       for(a=0; a<path->len; a++) {
-               ptr= &path->ptr[a];
-
-               if(ptr->data) {
-                       icon= RNA_struct_ui_icon(ptr->type);
-                       nameprop= RNA_struct_name_property(ptr->type);
-
-                       if(nameprop) {
-                               name= RNA_property_string_get_alloc(ptr, nameprop, namebuf, sizeof(namebuf));
-
-                               uiItemL(row, name, icon);
-
-                               if(name != namebuf)
-                                       MEM_freeN(name);
-                       }
-                       else
-                               uiItemL(row, "", icon);
-               }
-       }
-}
-
-void buttons_context_register(ARegionType *art)
-{
-       PanelType *pt;
-
-       pt= MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
-       strcpy(pt->idname, "BUTTONS_PT_context");
-       strcpy(pt->label, "Context");
-       pt->draw= buttons_panel_context;
-       BLI_addtail(&art->paneltypes, pt);
-}
-
index 999f6d8e9cb3083489f04acae1fc4847fe5a4563..d6e3b0c3dd561e81f32ce95a5caea4d0824d656d 100644 (file)
@@ -35,6 +35,8 @@
 
 #include "BPY_extern.h"
 
+static void bpy_init_syspath();
+
 void BPY_free_compiled_text( struct Text *text )
 {
        if( text->compiled ) {
@@ -126,14 +128,14 @@ void BPY_start_python( int argc, char **argv )
        /* Initialize thread support (also acquires lock) */
        PyEval_InitThreads();
        
-       
        /* bpy.* and lets us import it */
        bpy_init_modules(); 
 
+       /* init sys.path */
+       bpy_init_syspath();
        
        py_tstate = PyGILState_GetThisThreadState();
        PyEval_ReleaseThread(py_tstate);
-       
 }
 
 void BPY_end_python( void )
@@ -148,6 +150,56 @@ void BPY_end_python( void )
        return;
 }
 
+void syspath_append(char *dirname)
+{
+       PyObject *mod_sys= NULL, *dict= NULL, *path= NULL, *dir= NULL;
+       short ok=1;
+
+       mod_sys = PyImport_ImportModule( "sys" );       /* new ref */
+       
+       if (mod_sys) {
+               dict = PyModule_GetDict( mod_sys );     /* borrowed ref */
+               path = PyDict_GetItemString( dict, "path" );    /* borrowed ref */
+               if ( !PyList_Check( path ) ) {
+                       ok = 0;
+               }
+       } else {
+               /* cant get the sys module */
+               /* PyErr_Clear(); is called below */
+               ok = 0;
+       }
+       
+       dir = PyString_FromString( dirname );
+       
+       if (ok && PySequence_Contains(path, dir)==0) { /* Only add if we need to */
+               if (PyList_Append( path, dir ) != 0) /* decref below */
+                       ok = 0; /* append failed */
+       }
+       
+       if( (ok==0) || PyErr_Occurred(  ) )
+               fprintf(stderr, "Warning: could import or build sys.path\n" );
+       
+       PyErr_Clear();
+       Py_DECREF( dir );
+       Py_XDECREF( mod_sys );
+}
+
+/* Adds bpymodules to sys.path */
+static void bpy_init_syspath()
+{
+       char *dir;
+       char mod_dir[FILE_MAX];
+
+       // make path to [home]/scripts/bpymodules
+       dir = BLI_gethome_folder("scripts");
+       BLI_make_file_string("/", mod_dir, dir, "bpymodules");
+
+       if (BLI_exists(mod_dir)) {
+               syspath_append(mod_dir);
+               fprintf(stderr, "'%s' has been added to sys.path\n", mod_dir);
+       }
+}
+
 /* Can run a file or text block */
 int BPY_run_python_script( bContext *C, const char *fn, struct Text *text )
 {
index 43d62b3005fd84329503cae26dee1f870ada5afd..215e42dd95dfba78735fceb796f5b838cd8fa63a 100644 (file)
@@ -189,6 +189,8 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
        PyObject *args;
        PyObject *ret= NULL, *py_class_instance, *item= NULL;
        int ret_flag= (mode==PYOP_POLL ? 0:OPERATOR_CANCELLED);
+       PointerRNA ptr_context;
+       PyObject *py_context;
 
        PyGILState_STATE gilstate = PyGILState_Ensure();
        
@@ -232,8 +234,12 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
                        PyTuple_SET_ITEM(args, 1, pyop_dict_from_event(event));
                }
                else if (mode==PYOP_EXEC) {
-                       item= PyObject_GetAttrString(py_class, "exec");
-                       args = PyTuple_New(1);
+                       item= PyObject_GetAttrString(py_class, "execu");
+                       args = PyTuple_New(2);
+                       
+                       RNA_pointer_create(NULL, &RNA_Context, C, &ptr_context);
+                       py_context = pyrna_struct_CreatePyObject(&ptr_context);
+                       PyTuple_SET_ITEM(args, 1, py_context);
                }
                else if (mode==PYOP_POLL) {
                        item= PyObject_GetAttrString(py_class, "poll");
@@ -328,7 +334,7 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata)
        /* api callbacks, detailed checks dont on adding */ 
        if (PyObject_HasAttrString(py_class, "invoke"))
                ot->invoke= PYTHON_OT_invoke;
-       if (PyObject_HasAttrString(py_class, "exec"))
+       if (PyObject_HasAttrString(py_class, "execu"))
                ot->exec= PYTHON_OT_exec;
        if (PyObject_HasAttrString(py_class, "poll"))
                ot->poll= PYTHON_OT_poll;
@@ -391,7 +397,7 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
                {PYOP_ATTR_UINAME,              's', 0, BPY_CLASS_ATTR_OPTIONAL},
                {PYOP_ATTR_PROP,                'l', 0, BPY_CLASS_ATTR_OPTIONAL},
                {PYOP_ATTR_DESCRIPTION, 's', 0, BPY_CLASS_ATTR_NONE_OK},
-               {"exec",        'f', 1, BPY_CLASS_ATTR_OPTIONAL},
+               {"execu",       'f', 2, BPY_CLASS_ATTR_OPTIONAL},
                {"invoke",      'f', 2, BPY_CLASS_ATTR_OPTIONAL},
                {"poll",        'f', 2, BPY_CLASS_ATTR_OPTIONAL},
                {NULL, 0, 0, 0}