Merge from 2.5 rev 20647 through 20776.
authorChingiz Dyussenov <chingiz.ds@gmail.com>
Wed, 10 Jun 2009 11:21:17 +0000 (11:21 +0000)
committerChingiz Dyussenov <chingiz.ds@gmail.com>
Wed, 10 Jun 2009 11:21:17 +0000 (11:21 +0000)
release/scripts/export_obj-2.5.py [new file with mode: 0644]
release/ui/buttons_particle.py [deleted file]
source/blender/editors/mesh/editmesh.c
source/blender/editors/space_buttons/buttons_context.c [deleted file]
source/blender/makesrna/intern/rna_internal.h
source/blender/makesrna/intern/rna_main.c
source/blender/makesrna/intern/rna_mesh.c
source/blender/python/intern/bpy_interface.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 571cafb..0000000
+++ /dev/null
@@ -1,630 +0,0 @@
-
-import bpy
-
-def particle_panel_enabled(psys):
-       return psys.point_cache.baked==False and psys.editable==False
-       
-def particle_panel_poll(context):
-       psys = context.particle_system
-       if psys==None:  return False
-       return psys.settings.type in ('EMITTER', 'REACTOR', 'HAIR')
-
-class ParticleButtonsPanel(bpy.types.Panel):
-       __space_type__ = "BUTTONS_WINDOW"
-       __region_type__ = "WINDOW"
-       __context__ = "particle"
-
-       def poll(self, context):
-               return particle_panel_poll(context)
-
-class PARTICLE_PT_particles(ParticleButtonsPanel):
-       __idname__= "PARTICLE_PT_particles"
-       __label__ = "Particle System"
-
-       def poll(self, context):
-               return (context.particle_system or context.object)
-
-       def draw(self, context):
-               layout = self.layout
-               ob = context.object
-               psys = context.particle_system
-
-               split = layout.split(percentage=0.65)
-
-               if psys:
-                       split.template_ID(context, psys, "settings")
-
-                       #if ob:
-                       #       split.itemR(ob, "active_particle_system_index", text="Active")
-
-               if psys:
-                       #row = layout.row()
-                       #row.itemL(text="Particle system datablock")
-                       #row.itemL(text="Viewport")
-                       #row.itemL(text="Render")
-                       
-                       part = psys.settings
-                       ptype = psys.settings.type
-                       
-                       if ptype not in ('EMITTER', 'REACTOR', 'HAIR'):
-                               layout.itemL(text="No settings for fluid particles")
-                               return
-                       
-                       row = layout.row()
-                       row.enabled = particle_panel_enabled(psys)
-                       row.itemR(part, "type")
-                       row.itemR(psys, "seed")
-                       
-                       row = layout.row()
-                       if part.type=='HAIR':
-                               if psys.editable==True:
-                                       row.itemO("PARTICLE_OT_editable_set", text="Free Edit")
-                               else:
-                                       row.itemO("PARTICLE_OT_editable_set", text="Make Editable")
-                               subrow = row.row()
-                               subrow.enabled = particle_panel_enabled(psys)
-                               subrow.itemR(part, "hair_step")
-                       elif part.type=='REACTOR':
-                               row.itemR(psys, "reactor_target_object")
-                               row.itemR(psys, "reactor_target_particle_system", text="Particle System")
-               
-               if psys:
-                       #row = layout.row()
-                       #row.itemL(text="Particle system datablock")
-                       #row.itemL(text="Viewport")
-                       #row.itemL(text="Render")
-                       
-                       part = psys.settings
-                       ptype = psys.settings.type
-                       
-                       if ptype not in ('EMITTER', 'REACTOR', 'HAIR'):
-                               layout.itemL(text="No settings for fluid particles")
-                               return
-                       
-                       row = layout.row()
-                       row.enabled = particle_panel_enabled(psys)
-                       row.itemR(part, "type", expand=True)
-                       
-                       
-                       row = layout.row()
-                       if part.type=='HAIR':
-                               if psys.editable==True:
-                                       row.itemO("PARTICLE_OT_editable_set", text="Free Edit")
-                               else:
-                                       row.itemO("PARTICLE_OT_editable_set", text="Make Editable")
-                               subrow = row.row()
-                               subrow.enabled = particle_panel_enabled(psys)
-                               subrow.itemR(part, "hair_step")
-                       elif part.type=='REACTOR':
-                               row.itemR(psys, "reactor_target_object")
-                               row.itemR(psys, "reactor_target_particle_system", text="Particle System")
-               
-class PARTICLE_PT_emission(ParticleButtonsPanel):
-       __idname__= "PARTICLE_PT_emission"
-       __label__ = "Emission"
-       
-       def draw(self, context):
-               layout = self.layout
-
-               psys = context.particle_system
-               part = psys.settings
-               
-               layout.enabled = particle_panel_enabled(psys)
-               
-               row = layout.row()
-               #col.itemL(text="TODO: Rate instead of amount")
-               row.itemR(part, "amount")
-               row.itemR(psys, "seed")
-               
-               split = layout.split()
-               
-               col = split.column(align=True)
-               col.itemR(part, "start")
-               col.itemR(part, "end")
-
-               col = split.column(align=True)
-               col.itemR(part, "lifetime")
-               col.itemR(part, "random_lifetime", slider=True)
-               
-               layout.row().itemL(text="Emit From:")
-               
-               row = layout.row()
-               row.itemR(part, "emit_from", expand=True)
-               row = layout.row()
-               row.itemR(part, "trand")
-               if part.distribution!='GRID':
-                       row.itemR(part, "even_distribution")
-               
-               if part.emit_from=='FACE' or part.emit_from=='VOLUME':
-                       row = layout.row()
-                       row.itemR(part, "distribution", expand=True)
-                       
-                       row = layout.row()
-
-                       if part.distribution=='JIT':
-                               row.itemR(part, "userjit", text="Particles/Face")
-                               row.itemR(part, "jitter_factor", text="Jittering Amount", slider=True)
-                       elif part.distribution=='GRID':
-                               row.itemR(part, "grid_resolution")
-
-class PARTICLE_PT_cache(ParticleButtonsPanel):
-       __idname__= "PARTICLE_PT_cache"
-       __label__ = "Cache"
-       
-       def poll(self, context):
-               psys = context.particle_system
-               if psys==None:  return False
-               return psys.settings.type in ('EMITTER', 'REACTOR')
-
-       def draw(self, context):
-               layout = self.layout
-
-               psys = context.particle_system
-               part = psys.settings
-               cache = psys.point_cache
-               
-               #if cache.baked==True:
-                       #layout.itemO("PARTICLE_OT_free_bake", text="BAKE")
-               #else:
-               row = layout.row()
-                       #row.itemO("PARTICLE_OT_bake", text="BAKE")
-               row.itemR(cache, "start_frame")
-               row.itemR(cache, "end_frame")
-                       
-                       #layout.row().itemL(text="No simulation frames in disk cache.")
-
-class PARTICLE_PT_initial(ParticleButtonsPanel):
-       __idname__= "PARTICLE_PT_initial"
-       __label__ = "Velocity"
-
-       def draw(self, context):
-               layout = self.layout
-
-               psys = context.particle_system
-               part = psys.settings
-               
-               layout.enabled = particle_panel_enabled(psys)
-               
-               #layout.row().itemL(text="")
-                               
-               layout.row().itemL(text="Direction:")
-       
-               split = layout.split()
-                       
-               sub = split.column()
-               sub.itemR(part, "normal_factor")
-               if part.emit_from=='PARTICLE':
-                       sub.itemR(part, "particle_factor")
-               else:
-                       sub.itemR(part, "object_factor", slider=True)
-               sub.itemR(part, "random_factor")
-               sub.itemR(part, "tangent_factor")
-               sub.itemR(part, "tangent_phase", slider=True)
-               
-               sub = split.column()
-               sub.itemL(text="TODO:")
-               sub.itemL(text="Object aligned")
-               sub.itemL(text="direction: X, Y, Z")
-               
-               if part.type=='REACTOR':
-                       sub.itemR(part, "reactor_factor")
-                       sub.itemR(part, "reaction_shape", slider=True)
-               else:
-                       sub.itemL(text="")
-               
-               layout.row().itemL(text="Rotation:")
-               split = layout.split()
-                       
-               sub = split.column()
-               
-               sub.itemR(part, "rotation_mode", text="Axis")
-               split = layout.split()
-                       
-               sub = split.column()
-               sub.itemR(part, "rotation_dynamic")
-               sub.itemR(part, "random_rotation_factor", slider=True)
-               sub = split.column()
-               sub.itemR(part, "phase_factor", slider=True)
-               sub.itemR(part, "random_phase_factor", text="Random", slider=True)
-
-               layout.row().itemL(text="Angular velocity:")
-               layout.row().itemR(part, "angular_velocity_mode", expand=True)
-               split = layout.split()
-                       
-               sub = split.column()
-               
-               sub.itemR(part, "angular_velocity_factor", text="")
-               
-class PARTICLE_PT_physics(ParticleButtonsPanel):
-       __idname__= "PARTICLE_PT_physics"
-       __label__ = "Physics"
-
-       def draw(self, context):
-               layout = self.layout
-
-               psys = context.particle_system
-               part = psys.settings
-               
-               layout.enabled = layout.enabled = particle_panel_enabled(psys)
-
-               row = layout.row()
-               row.itemR(part, "physics_type", expand=True)
-               if part.physics_type != 'NO':
-                       layout.itemR(part, "effector_group")
-               
-                       row = layout.row()
-                       col = row.column(align=True)
-                       col.itemR(part, "particle_size")
-                       col.itemR(part, "random_size", slider=True)
-                       col = row.column(align=True)
-                       col.itemR(part, "mass")
-                       col.itemR(part, "sizemass", text="Multiply mass with size")
-                                                       
-                       split = layout.split()
-                       
-                       sub = split.column()
-                       
-               if part.physics_type == 'NEWTON':
-                       
-                       sub.itemL(text="Forces:")
-                       sub.itemR(part, "brownian_factor")
-                       sub.itemR(part, "drag_factor", slider=True)
-                       sub.itemR(part, "damp_factor", slider=True)
-                       sub.itemR(part, "integrator")
-                       sub = split.column()
-                       sub.itemR(part, "acceleration")
-                       
-               elif part.physics_type == 'KEYED':
-                       sub.itemR(psys, "keyed_first")
-                       if psys.keyed_first==True:
-                               sub.itemR(psys, "timed_keys", text="Key timing")
-                       else:
-                               sub.itemR(part, "keyed_time")
-                       sub = split.column()
-                       sub.itemL(text="Next key from object:")
-                       sub.itemR(psys, "keyed_object", text="")
-                       sub.itemR(psys, "keyed_particle_system")
-               
-               if part.physics_type=='NEWTON' or part.physics_type=='BOIDS':
-
-                       sub.itemR(part, "size_deflect")
-                       sub.itemR(part, "die_on_collision")
-                       sub.itemR(part, "sticky")
-
-class PARTICLE_PT_render(ParticleButtonsPanel):
-       __idname__= "PARTICLE_PT_render"
-       __label__ = "Render"
-       
-       def poll(self, context):
-               return (context.particle_system != None)
-               
-       def draw(self, context):
-               layout = self.layout
-
-               psys = context.particle_system
-               part = psys.settings
-               
-               layout.itemR(part, "material")
-               
-               split = layout.split()
-                       
-               sub = split.column()
-               sub.itemR(part, "emitter");
-               sub.itemR(part, "parent");
-               sub = split.column()
-               sub.itemR(part, "unborn");
-               sub.itemR(part, "died");
-               
-               row = layout.row()
-               row.itemR(part, "ren_as", expand=True)
-               
-               split = layout.split()
-                       
-               sub = split.column()
-               
-               if part.ren_as == 'LINE':
-                       sub.itemR(part, "line_length_tail")
-                       sub.itemR(part, "line_length_head")
-                       sub = split.column()
-                       sub.itemR(part, "velocity_length")
-               elif part.ren_as == 'PATH':
-               
-                       if (part.type!='HAIR' and psys.point_cache.baked==False):
-                               box = layout.box()
-                               box.itemL(text="Baked or keyed particles needed for correct rendering.")
-                               return
-                               
-                       sub.itemR(part, "render_strand")
-                       colsub = sub.column()
-                       colsub.active = part.render_strand == False
-                       colsub.itemR(part, "render_adaptive")
-                       colsub = sub.column()
-                       colsub.active = part.render_adaptive or part.render_strand == True
-                       colsub.itemR(part, "adaptive_angle")
-                       colsub = sub.column()
-                       colsub.active = part.render_adaptive == True and part.render_strand == False
-                       colsub.itemR(part, "adaptive_pix")
-                       sub.itemR(part, "hair_bspline")
-                       sub.itemR(part, "render_step", text="Steps")
-                       sub = split.column()
-                       sub.itemL(text="Length:")
-                       sub.itemR(part, "abs_length", text="Absolute")
-                       sub.itemR(part, "absolute_length", text="Maximum")
-                       sub.itemR(part, "random_length", text="Random", slider=True)
-                       
-                       #row = layout.row()
-                       #row.itemR(part, "timed_path")
-                       #col = row.column(align=True)
-                       #col.active = part.timed_path == True
-                       #col.itemR(part, "line_length_tail", text="Start")
-                       #col.itemR(part, "line_length_head", text="End")
-                       
-                       row = layout.row()
-                       col = row.column()
-                       
-                       
-#                      subrow = col.row()
-#                      subrow.active = part.render_strand == False
-#                      subrow.itemR(part, "render_adaptive")
-#                      col = row.column(align=True)
-#                      subrow = col.row()
-#                      subrow.active = part.render_adaptive or part.render_strand == True
-#                      subrow.itemR(part, "adaptive_angle")
-#                      subrow = col.row()
-#                      subrow.active = part.render_adaptive == True and part.render_strand == False
-#                      subrow.itemR(part, "adaptive_pix")
-                       
-                       if part.type=='HAIR' and part.render_strand==True and part.child_type=='FACES':
-                               layout.itemR(part, "enable_simplify")
-                               if part.enable_simplify==True:
-                                       box = layout.box()
-                                       row = box.row()
-                                       row.itemR(part, "simplify_refsize")
-                                       row.itemR(part, "simplify_rate")
-                                       row.itemR(part, "simplify_transition")
-                                       row = box.row()
-                                       row.itemR(part, "viewport")
-                                       subrow = row.row()
-                                       subrow.active = part.viewport==True
-                                       subrow.itemR(part, "simplify_viewport")
-                       
-
-               elif part.ren_as == 'OBJECT':
-                       #sub = split.column()
-                       sub.itemR(part, "dupli_object")
-               elif part.ren_as == 'GROUP':
-                       sub.itemR(part, "dupli_group")
-                       split = layout.split()
-                       sub = split.column()
-                       sub.itemR(part, "whole_group")
-                       sub = split.column()
-                       colsub = sub.column()
-                       colsub.active = part.whole_group == False
-                       colsub.itemR(part, "rand_group")
-                       
-               elif part.ren_as == 'BILLBOARD':
-                       sub.itemL(text="Align:")
-                       
-                       row = layout.row()
-                       row.itemR(part, "billboard_align", expand=True)
-                       row.itemR(part, "billboard_lock", text="Lock")
-                       row = layout.row()
-                       row.itemR(part, "billboard_object")
-               
-                       row = layout.row()
-                       col = row.column(align=True)
-                       col.itemL(text="Tilt:")
-                       col.itemR(part, "billboard_tilt", text="Angle", slider=True)
-                       col.itemR(part, "billboard_random_tilt", slider=True)
-                       col = row.column()
-                       col.itemR(part, "billboard_offset")
-                       
-                       row = layout.row()
-                       row.itemR(psys, "billboard_normal_uv")
-                       row = layout.row()
-                       row.itemR(psys, "billboard_time_index_uv")
-                       
-                       row = layout.row()
-                       row.itemL(text="Split uv's:")
-                       row.itemR(part, "billboard_uv_split", text="Number of splits")
-                       row = layout.row()
-                       row.itemR(psys, "billboard_split_uv")
-                       row = layout.row()
-                       row.itemL(text="Animate:")
-                       row.itemR(part, "billboard_animation", expand=True)
-                       row.itemL(text="Offset:")
-                       row.itemR(part, "billboard_split_offset", expand=True)
-               
-class PARTICLE_PT_draw(ParticleButtonsPanel):
-       __idname__= "PARTICLE_PT_draw"
-       __label__ = "Display"
-       
-       def poll(self, context):
-               return (context.particle_system != None)
-       
-       def draw(self, context):
-               layout = self.layout
-
-               psys = context.particle_system
-               part = psys.settings
-               
-               row = layout.row()
-               row.itemR(part, "draw_as", expand=True)
-               
-               if part.draw_as=='NONE' or (part.ren_as=='NONE' and part.draw_as=='RENDER'):
-                       return
-                       
-               path = (part.ren_as=='PATH' and part.draw_as=='RENDER') or part.draw_as=='PATH'
-                       
-               if path and part.type!='HAIR' and psys.point_cache.baked==False:
-                       box = layout.box()
-                       box.itemL(text="Baked or keyed particles needed for correct drawing.")
-                       return
-               
-               row = layout.row()
-               row.itemR(part, "display", slider=True)
-               if part.draw_as!='RENDER' or part.ren_as=='HALO':
-                       row.itemR(part, "draw_size")
-               else:
-                       row.itemL(text="")
-               
-               row = layout.row()
-               col = row.column()
-               col.itemR(part, "show_size")
-               col.itemR(part, "velocity")
-               col.itemR(part, "num")
-               if part.physics_type == 'BOIDS':
-                       col.itemR(part, "draw_health")
-               
-               col = row.column()
-               if (path):
-                       box = col.box()                         
-                       box.itemR(part, "draw_step")
-               else:
-                       col.itemR(part, "material_color", text="Use material color")
-                       subcol = col.column()
-                       subcol.active = part.material_color==False
-                       #subcol.itemL(text="color")
-                       #subcol.itemL(text="Override material color")
-
-class PARTICLE_PT_children(ParticleButtonsPanel):
-       __idname__= "PARTICLE_PT_children"
-       __label__ = "Children"
-
-       def draw(self, context):
-               layout = self.layout
-
-               psys = context.particle_system
-               part = psys.settings
-               
-               layout.row().itemR(part, "child_type", expand=True)
-               
-               if part.child_type=='NONE':
-                       return
-               
-               row = layout.row()
-               
-               col = row.column(align=True)
-               col.itemR(part, "child_nbr", text="Display")
-               col.itemR(part, "rendered_child_nbr", text="Render")
-               
-               col = row.column(align=True)
-               
-               if part.child_type=='FACES':
-                       col.itemR(part, "virtual_parents", slider=True)
-               else:
-                       col.itemR(part, "child_radius", text="Radius")
-                       col.itemR(part, "child_roundness", text="Roundness", slider=True)
-               
-                       col = row.column(align=True)
-                       col.itemR(part, "child_size", text="Size")
-                       col.itemR(part, "child_random_size", text="Random")
-               
-               layout.row().itemL(text="Effects:")
-               
-               row = layout.row()
-               
-               col = row.column(align=True)
-               col.itemR(part, "clump_factor", slider=True)
-               col.itemR(part, "clumppow", slider=True)
-               
-               col = row.column(align=True)
-               col.itemR(part, "rough_endpoint")
-               col.itemR(part, "rough_end_shape")
-
-               row = layout.row()
-               
-               col = row.column(align=True)
-               col.itemR(part, "rough1")
-               col.itemR(part, "rough1_size")
-
-               col = row.column(align=True)
-               col.itemR(part, "rough2")
-               col.itemR(part, "rough2_size")
-               col.itemR(part, "rough2_thres", slider=True)
-               
-               layout.row().itemL(text="Kink:")
-               layout.row().itemR(part, "kink", expand=True)
-               
-               split = layout.split()
-               
-               sub = split.column()
-               sub.itemR(part, "kink_amplitude")
-               sub.itemR(part, "kink_frequency")
-               sub = split.column()
-               sub.itemR(part, "kink_shape", slider=True)
-
-class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
-       __idname__= "PARTICLE_PT_vertexgroups"
-       __label__ = "Vertexgroups"
-
-       def draw(self, context):
-               layout = self.layout
-
-               psys = context.particle_system
-               part = psys.settings
-               
-               layout.itemL(text="Nothing here yet.")
-
-               #row = layout.row()
-               #row.itemL(text="Vertex Group")
-               #row.itemL(text="Negate")
-
-               
-               #row = layout.row()
-               #row.itemR(psys, "vertex_group_density")
-               #row.itemR(psys, "vertex_group_density_negate", text="")
-               
-               #row = layout.row()
-               #row.itemR(psys, "vertex_group_velocity")
-               #row.itemR(psys, "vertex_group_velocity_negate", text="")
-               
-               #row = layout.row()
-               #row.itemR(psys, "vertex_group_length")
-               #row.itemR(psys, "vertex_group_length_negate", text="")
-               
-               #row = layout.row()
-               #row.itemR(psys, "vertex_group_clump")
-               #row.itemR(psys, "vertex_group_clump_negate", text="")
-               
-               #row = layout.row()
-               #row.itemR(psys, "vertex_group_kink")
-               #row.itemR(psys, "vertex_group_kink_negate", text="")
-               
-               #row = layout.row()
-               #row.itemR(psys, "vertex_group_roughness1")
-               #row.itemR(psys, "vertex_group_roughness1_negate", text="")
-               
-               #row = layout.row()
-               #row.itemR(psys, "vertex_group_roughness2")
-               #row.itemR(psys, "vertex_group_roughness2_negate", text="")
-               
-               #row = layout.row()
-               #row.itemR(psys, "vertex_group_roughness_end")
-               #row.itemR(psys, "vertex_group_roughness_end_negate", text="")
-
-               #row = layout.row()
-               #row.itemR(psys, "vertex_group_size")
-               #row.itemR(psys, "vertex_group_size_negate", text="")
-               
-               #row = layout.row()
-               #row.itemR(psys, "vertex_group_tangent")
-               #row.itemR(psys, "vertex_group_tangent_negate", text="")
-               
-               #row = layout.row()
-               #row.itemR(psys, "vertex_group_rotation")
-               #row.itemR(psys, "vertex_group_rotation_negate", text="")
-               
-               #row = layout.row()
-               #row.itemR(psys, "vertex_group_field")
-               #row.itemR(psys, "vertex_group_field_negate", text="")
-               
-bpy.types.register(PARTICLE_PT_particles)
-bpy.types.register(PARTICLE_PT_cache)
-bpy.types.register(PARTICLE_PT_emission)
-bpy.types.register(PARTICLE_PT_initial)
-bpy.types.register(PARTICLE_PT_physics)
-bpy.types.register(PARTICLE_PT_render)
-bpy.types.register(PARTICLE_PT_draw)
-bpy.types.register(PARTICLE_PT_children)
-bpy.types.register(PARTICLE_PT_vertexgroups)
index 40373c9f32793cc3eed5af7345aef770cc408824..a1b6bc567425415909039d703751d860e02edc64 100644 (file)
@@ -2027,3 +2027,98 @@ void em_setup_viewcontext(bContext *C, ViewContext *vc)
                vc->em= me->edit_mesh;
        }
 }
+
+/* Python API */
+void copy_mesh_data(Mesh *dest, Mesh *src);
+
+Mesh *RNA_api_add_mesh(Main *main, char *name)
+{
+       return add_mesh(name);
+}
+
+void RNA_api_mesh_copy(Mesh *me, Mesh *from)
+{
+       copy_mesh_data(me, from);
+}
+
+void RNA_api_mesh_copy_transformed()
+{
+}
+
+/*
+ * This version of copy_mesh doesn't allocate a new mesh,
+ * instead it copies data between two existing meshes.
+ */
+void copy_mesh_data(Mesh *dest, Mesh *src)
+{
+       int totvert, totedge, totface;
+       int has_layer;
+
+       CustomData_free(&dest->vdata, dest->totvert);
+       CustomData_free(&dest->edata, dest->totedge);
+       CustomData_free(&dest->fdata, dest->totface);
+
+       memset(&dest->vdata, 0, sizeof(dest->vdata));
+       memset(&dest->edata, 0, sizeof(dest->edata));
+       memset(&dest->fdata, 0, sizeof(dest->fdata));
+
+       totvert = dest->totvert = src->totvert;
+       totedge = dest->totedge = src->totedge;
+       totface = dest->totface = src->totface;
+
+       CustomData_copy(&src->vdata, &dest->vdata, CD_MASK_MESH, CD_DUPLICATE, totvert);
+       CustomData_copy(&src->edata, &dest->edata, CD_MASK_MESH, CD_DUPLICATE, totedge);
+       CustomData_copy(&src->fdata, &dest->fdata, CD_MASK_MESH, CD_DUPLICATE, totface);
+
+       CustomData_has_layer(&dest->vdata, CD_MVERT);
+
+       CustomData_add_layer(&dest->vdata, CD_MVERT, CD_ASSIGN, src->mvert, totvert);
+       CustomData_add_layer(&dest->edata, CD_MEDGE, CD_ASSIGN, src->medge, totedge);
+       CustomData_add_layer(&dest->fdata, CD_MFACE, CD_ASSIGN, src->mface, totface);
+
+       mesh_update_customdata_pointers(dest);
+}
+
+/*
+void RNA_api_mesh_apply_transform(Mesh *me)
+{
+       
+}
+*/
+
+/*
+void RNA_api_mesh_copy_(Mesh *me, Object *ob, int apply_transform)
+{
+       if (ob->type != OB_MESH) {
+               return;
+       }
+
+       Mesh *src= (Mesh*)ob->data;
+
+       CustomData_free(&me->vdata, me->totvert);
+       CustomData_free(&me->edata, me->totedge);
+       CustomData_free(&me->fdata, me->totface);
+
+       CustomData_copy(&src->vdata, &me->vdata, CD_MASK_MESH, CD_DUPLICATE, me->totvert);
+       CustomData_copy(&src->edata, &me->edata, CD_MASK_MESH, CD_DUPLICATE, me->totedge);
+       CustomData_copy(&src->fdata, &me->fdata, CD_MASK_MESH, CD_DUPLICATE, me->totface);
+       mesh_update_customdata_pointers(me);
+
+       // ensure indirect linked data becomes lib-extern
+       for(i=0; i<src->fdata.totlayer; i++) {
+               if(src->fdata.layers[i].type == CD_MTFACE) {
+                       tface= (MTFace*)src->fdata.layers[i].data;
+
+                       for(a=0; a<src->totface; a++, tface++)
+                               if(tface->tpage)
+                                       id_lib_extern((ID*)tface->tpage);
+               }
+       }
+       
+       me->mselect= NULL;
+       me->bb= src->bb;
+
+       //men->key= copy_key(me->key);
+       //if(men->key) men->key->from= (ID *)men;
+}
+*/
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 255bee1..0000000
+++ /dev/null
@@ -1,695 +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 "BKE_world.h"
-
-#include "RNA_access.h"
-
-#include "ED_screen.h"
-
-#include "UI_interface.h"
-#include "UI_resources.h"
-
-#include "buttons_intern.h"    // own include
-
-typedef struct ButsContextPath {
-       PointerRNA ptr[8];
-       int len;
-       int worldtex;
-} ButsContextPath;
-
-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;
-}
-
-/************************* 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;
-       PointerRNA *ptr= &path->ptr[path->len-1];
-
-       /* if we already have a data, we're done */
-       if(RNA_struct_is_a(ptr->type, &RNA_Mesh) && (type == -1 || type == OB_MESH)) return 1;
-       else if(RNA_struct_is_a(ptr->type, &RNA_Curve) && (type == -1 || ELEM3(type, OB_CURVE, OB_SURF, OB_FONT))) return 1;
-       else if(RNA_struct_is_a(ptr->type, &RNA_Armature) && (type == -1 || type == OB_ARMATURE)) return 1;
-       else if(RNA_struct_is_a(ptr->type, &RNA_MetaBall) && (type == -1 || type == OB_MBALL)) return 1;
-       else if(RNA_struct_is_a(ptr->type, &RNA_Lattice) && (type == -1 || type == OB_LATTICE)) return 1;
-       else if(RNA_struct_is_a(ptr->type, &RNA_Camera) && (type == -1 || type == OB_CAMERA)) return 1;
-       else if(RNA_struct_is_a(ptr->type, &RNA_Lamp) && (type == -1 || type == OB_LAMP)) return 1;
-       /* try to get an object in the path, no pinning supported here */
-       else if(buttons_context_path_object(path)) {
-               ob= path->ptr[path->len-1].data;
-
-               if(ob && (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_modifier(ButsContextPath *path)
-{
-       Object *ob;
-
-       if(buttons_context_path_object(path)) {
-               ob= path->ptr[path->len-1].data;
-
-               if(ob && ELEM4(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF))
-                       return 1;
-       }
-
-       return 0;
-}
-
-static int buttons_context_path_material(ButsContextPath *path)
-{
-       Object *ob;
-       PointerRNA *ptr= &path->ptr[path->len-1];
-       Material *ma;
-
-       /* 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)) {
-                       ma= give_current_material(ob, ob->actcol);
-                       RNA_id_pointer_create(&ma->id, &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;
-
-               if(ob && ob->type == OB_MESH) {
-                       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)
-{
-       Material *ma;
-       Lamp *la;
-       World *wo;
-       MTex *mtex;
-       Tex *tex;
-       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 world */
-       else if(path->worldtex && buttons_context_path_world(path)) {
-               wo= path->ptr[path->len-1].data;
-
-               if(wo) {
-                       mtex= wo->mtex[(int)wo->texact];
-                       tex= (mtex)? mtex->tex: NULL;
-
-                       RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
-                       path->len++;
-                       return 1;
-               }
-       }
-       /* try material */
-       else if(buttons_context_path_material(path)) {
-               ma= path->ptr[path->len-1].data;
-
-               if(ma) {
-                       mtex= ma->mtex[(int)ma->texact];
-                       tex= (mtex)? mtex->tex: NULL;
-
-                       RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
-                       path->len++;
-                       return 1;
-               }
-       }
-       /* try lamp */
-       else if(buttons_context_path_data(path, OB_LAMP)) {
-               la= path->ptr[path->len-1].data;
-
-               if(la) {
-                       mtex= la->mtex[(int)la->texact];
-                       tex= (mtex)? mtex->tex: NULL;
-
-                       RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
-                       path->len++;
-                       return 1;
-               }
-       }
-       /* TODO: material nodes, brush */
-
-       /* no path to a particle system possible */
-       return 0;
-}
-
-static int buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int worldtex)
-{
-       SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
-       ID *id;
-       int found;
-
-       memset(path, 0, sizeof(*path));
-       path->worldtex= worldtex;
-
-       /* 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(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_CONSTRAINT:
-                       found= buttons_context_path_object(path);
-                       break;
-               case BCONTEXT_MODIFIER:
-                       found= buttons_context_path_modifier(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)
-{
-       ButsContextPath *path;
-       PointerRNA *ptr;
-       int a, worldtex, flag= 0;
-
-       if(!sbuts->path)
-               sbuts->path= MEM_callocN(sizeof(ButsContextPath), "ButsContextPath");
-       
-       path= sbuts->path;
-       worldtex= (sbuts->flag & SB_WORLD_TEX);
-       
-       /* for each context, see if we can compute a valid path to it, if
-        * this is the case, we know we have to display the button */
-       for(a=0; a<BCONTEXT_TOT; a++) {
-               if(buttons_context_path(C, path, a, worldtex)) {
-                       flag |= (1<<a);
-
-                       /* setting icon for data context */
-                       if(a == BCONTEXT_DATA) {
-                               ptr= &path->ptr[path->len-1];
-
-                               if(ptr->type)
-                                       sbuts->dataicon= RNA_struct_ui_icon(ptr->type);
-                               else
-                                       sbuts->dataicon= ICON_EMPTY_DATA;
-                       }
-               }
-       }
-
-       /* in case something becomes invalid, change */
-       if((flag & (1 << sbuts->mainb)) == 0) {
-               if(flag & BCONTEXT_OBJECT) {
-                       sbuts->mainb= BCONTEXT_OBJECT;
-               }
-               else {
-                       for(a=0; a<BCONTEXT_TOT; a++) {
-                               if(flag & (1 << a)) {
-                                       sbuts->mainb= a;
-                                       break;
-                               }
-                       }
-               }
-       }
-
-       buttons_context_path(C, path, sbuts->mainb, worldtex);
-
-       if(!(flag & (1 << sbuts->mainb))) {
-               if(flag & (1 << BCONTEXT_OBJECT))
-                       sbuts->mainb= BCONTEXT_OBJECT;
-               else
-                       sbuts->mainb= BCONTEXT_SCENE;
-       }
-
-       sbuts->pathflag= flag;
-}
-
-/************************* Context Callback ************************/
-
-int buttons_context(const bContext *C, const char *member, bContextDataResult *result)
-{
-       SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
-       ButsContextPath *path= sbuts?sbuts->path:NULL;
-
-       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")) {
-               set_pointer_type(path, result, &RNA_Material);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "texture")) {
-               set_pointer_type(path, result, &RNA_Texture);
-               return 1;
-       }
-       else if(CTX_data_equals(member, "material_slot")) {
-               PointerRNA *ptr= get_pointer_type(path, &RNA_Object);
-
-               if(ptr) {
-                       Object *ob= ptr->data;
-
-                       if(ob && ob->type && (ob->type<OB_LAMP))
-                               CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, ob->mat+ob->actcol-1);
-               }
-
-               return 1;
-       }
-       else if(CTX_data_equals(member, "texture_slot")) {
-               PointerRNA *ptr;
-
-               if((ptr=get_pointer_type(path, &RNA_Material))) {
-                       Material *ma= ptr->data;
-
-                       if(ma)
-                               CTX_data_pointer_set(result, &ma->id, &RNA_MaterialTextureSlot, ma->mtex[(int)ma->texact]);
-               }
-               else if((ptr=get_pointer_type(path, &RNA_Lamp))) {
-                       Lamp *la= ptr->data;
-
-                       if(la)
-                               CTX_data_pointer_set(result, &la->id, &RNA_LampTextureSlot, la->mtex[(int)la->texact]);
-               }
-               else if((ptr=get_pointer_type(path, &RNA_World))) {
-                       World *wo= ptr->data;
-
-                       if(wo)
-                               CTX_data_pointer_set(result, &wo->id, &RNA_WorldTextureSlot, wo->mtex[(int)wo->texact]);
-               }
-               else if((ptr=get_pointer_type(path, &RNA_Brush))) { /* how to get this into context? */
-                       Brush *br= ptr->data;
-
-                       if(br)
-                               CTX_data_pointer_set(result, &br->id, &RNA_TextureSlot, br->mtex[(int)br->texact]);
-               }
-
-               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 pin_cb(bContext *C, void *arg1, void *arg2)
-{
-       SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
-       ButsContextPath *path= sbuts->path;
-       PointerRNA *ptr;
-       int a;
-
-       if(sbuts->flag & SB_PIN_CONTEXT) {
-               if(path->len) {
-                       for(a=path->len-1; a>=0; a--) {
-                               ptr= &path->ptr[a];
-
-                               if(ptr->id.data) {
-                                       sbuts->pinid= ptr->id.data;
-                                       break;
-                               }
-                       }
-               }
-       }
-       else
-               sbuts->pinid= NULL;
-       
-       ED_area_tag_redraw(CTX_wm_area(C));
-}
-
-void buttons_context_draw(const bContext *C, uiLayout *layout)
-{
-       SpaceButs *sbuts= (SpaceButs*)CTX_wm_space_data(C);
-       ButsContextPath *path= sbuts->path;
-       uiLayout *row;
-       uiBlock *block;
-       uiBut *but;
-       PointerRNA *ptr;
-       PropertyRNA *nameprop;
-       char namebuf[128], *name;
-       int a, icon;
-
-       if(!path)
-               return;
-
-       row= uiLayoutRow(layout, 0);
-       uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
-
-       block= uiLayoutGetBlock(row);
-       uiBlockSetEmboss(block, UI_EMBOSSN);
-       but= uiDefIconButBitC(block, ICONTOG, SB_PIN_CONTEXT, 0, (sbuts->flag & SB_PIN_CONTEXT)? ICON_PINNED: ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag, 0, 0, 0, 0, "Follow context or keep fixed datablock displayed.");
-       uiButSetFunc(but, pin_cb, NULL, NULL);
-
-       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 0
-                       if(sbuts->mainb != BCONTEXT_SCENE && ptr->type == &RNA_Scene) {
-                               uiItemL(row, "", icon); /* save some space */
-                       }
-                       else
-#endif
-                       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);
-               }
-       }
-}
-
-static void buttons_panel_context(const bContext *C, Panel *pa)
-{
-       buttons_context_draw(C, pa->layout);
-}
-
-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 9071efe71f791f08fc8aa69f6a43b38a950d6de5..d93c296ca934201194b75e92e64f2d96c1ee5ba7 100644 (file)
@@ -189,6 +189,8 @@ void rna_object_vcollayer_name_set(struct PointerRNA *ptr, const char *value, ch
 /* API functions */
 
 void RNA_api_ui_layout(struct StructRNA *srna);
+struct Mesh *RNA_api_add_mesh(struct Main *main, char *name);
+void RNA_api_mesh_copy(struct Mesh *me, struct Mesh *from);
 
 /* ID Properties */
 
index fdd0349b25e43dbb844db41ed3589cea22093a00..347aef69a76808571cc651d9c5f03c9be8307fda 100644 (file)
@@ -218,6 +218,8 @@ void RNA_def_main(BlenderRNA *brna)
 {
        StructRNA *srna;
        PropertyRNA *prop;
+       FunctionRNA *func;
+
        const char *lists[][5]= {
                {"cameras", "Camera", "rna_Main_camera_begin", "Cameras", "Camera datablocks."},
                {"scenes", "Scene", "rna_Main_scene_begin", "Scenes", "Scene datablocks."},
@@ -265,6 +267,13 @@ void RNA_def_main(BlenderRNA *brna)
                RNA_def_property_collection_funcs(prop, lists[i][2], "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0);
                RNA_def_property_ui_text(prop, lists[i][3], lists[i][4]);
        }
+
+       func= RNA_def_function(srna, "add_mesh", "RNA_api_add_mesh");
+       RNA_def_function_ui_description(func, "Add a new mesh.");
+       prop= RNA_def_string(func, "name", "", 0, "", "New name for the datablock.");
+       RNA_def_property_flag(prop, PROP_REQUIRED);
+       prop= RNA_def_pointer(func, "mesh", "Mesh", "", "A new mesh.");
+       RNA_def_function_return(func, prop);
 }
 
 #endif
index e58b3c51fec473699dbc64c4814abb1803b409af..a071a79230ec9e9250e416b6ac73be51e255acc7 100644 (file)
@@ -1044,6 +1044,7 @@ static void rna_def_mesh(BlenderRNA *brna)
 {
        StructRNA *srna;
        PropertyRNA *prop;
+       FunctionRNA *func;
 
        srna= RNA_def_struct(brna, "Mesh", "ID");
        RNA_def_struct_ui_text(srna, "Mesh", "Mesh datablock to define geometric surfaces.");
@@ -1126,6 +1127,15 @@ static void rna_def_mesh(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Shape Keys", "");
 
        rna_def_texmat_common(srna, "rna_Mesh_texspace_editable");
+
+       func= RNA_def_function(srna, "copy", "RNA_api_mesh_copy");
+       RNA_def_function_ui_description(func, "Copy mesh data.");
+       prop= RNA_def_pointer(func, "src", "Mesh", "", "A mesh to copy data from.");
+       RNA_def_property_flag(prop, PROP_REQUIRED);
+       /*
+       prop= RNA_def_pointer(func, "mesh", "Mesh", "", "A new mesh.");
+       RNA_def_function_return(func, prop);
+       */
 }
 
 void RNA_def_mesh(BlenderRNA *brna)
index 7b3a67ebff5a570b410b4ed4071ee2ab74d18c4f..49cc4d678e55d5b62f2a10255c96274bec1b2622 100644 (file)
@@ -36,6 +36,8 @@
 
 #include "BPY_extern.h"
 
+static void bpy_init_syspath();
+
 void BPY_free_compiled_text( struct Text *text )
 {
        if( text->compiled ) {
@@ -127,14 +129,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 )
@@ -149,6 +151,60 @@ 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;
+       }
+
+#if PY_MAJOR_VERSION >= 3
+       dir = PyUnicode_FromString( dirname );
+#else
+       dir = PyString_FromString( dirname );
+#endif
+       
+       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 )
 {