Index: tri_import_export.py
===================================================================
--- tri_import_export.py	(revision 1163)
+++ tri_import_export.py	(revision 1164)
@@ -0,0 +1,759 @@
+import bpy
+import os
+import time
+
+#bpy.data.meshes.remove(my_mesh)
+#bpy.ops.object.convert(target='MESH',keep_original=True)
+
+active_object=None
+selected_objects=[]
+active_object_mode=''
+temp_object=None
+all_scene=True
+
+#texture swap count
+texture_swap_count=0
+current_texture_list=[]
+exported_mesh_list=[]
+
+def save_state(context):
+    global active_object,selected_objects,active_object_mode
+    
+    print ("Saving State")
+    
+    active_object=context.active_object
+    if active_object!=None:
+        active_object_mode = context.object.mode
+        #Switch to object mode as default
+        bpy.ops.object.mode_set(mode='OBJECT')
+    
+    selected_objects = context.selected_objects
+    
+
+def restore_state(context):
+    global selected_objects,active_object,active_object_mode
+    
+    print ("Restoring State.")
+
+    #Switch to object mode
+    ob=context.object
+    if ob!=None:
+        if ob.mode=='EDIT':
+            bpy.ops.object.mode_set(mode='OBJECT')
+            
+    if active_object!=None:
+        bpy.ops.object.select_pattern(pattern=active_object.name)
+        bpy.context.scene.objects.active=active_object
+
+    bpy.ops.object.select_all(action='DESELECT')
+    for ob in selected_objects:
+        ob.select=True  
+
+    if active_object_mode=='EDIT':
+        bpy.ops.object.mode_set(mode='EDIT')        
+
+def convert_to_mesh(obj):
+    global temp_object
+    
+    print ("Creating temporary working Mesh for {}.".format(obj))
+    
+    if obj.type=='MESH':
+        bpy.ops.object.duplicate()
+    else:
+        bpy.ops.object.convert(target='MESH',keep_original=True)    
+        
+    if (len(bpy.context.selected_objects)>1):
+        raise ("Should never happen ")
+    temp_object=bpy.context.selected_objects[0]
+    bpy.context.scene.objects.active=temp_object
+    
+    for modifier in temp_object.modifiers:
+        print ("Applying modifier %s"%modifier.name)
+        bpy.ops.object.modifier_apply(modifier=modifier.name)
+    
+    return temp_object
+
+def convert_quad_to_tri(obj):
+    print ("Triangulate Faces with pattern")
+    bpy.ops.object.select_pattern(pattern=obj.name)
+    bpy.ops.object.mode_set(mode='EDIT')
+    bpy.ops.mesh.select_all(action='SELECT')
+    bpy.ops.mesh.quads_convert_to_tris()
+    bpy.ops.object.mode_set(mode='OBJECT')
+
+def export_vertice(vert,face,me,obj,f):    
+    global all_scene
+    
+    if all_scene:
+        rot = obj.matrix_world
+        pos = obj.location
+        vloc,qrot,vscale = rot.decompose()    
+    
+    v=me.vertices[vert].co.copy()
+    
+    if face.use_smooth:
+        n=me.vertices[vert].normal.copy()
+    else:
+        n=face.normal.copy()
+    
+    if all_scene:
+        v = (rot * v)
+        n = qrot * n
+
+    f.write("%+0f %+0f %+0f"%(v[0],v[1],v[2]))
+    f.write("  %+0f %+0f %+0f"%(n[0],n[1],n[2]))
+
+def build_vertex_color_list(i_vert,i_face,me):
+       
+    tex_list=[]
+    for vcol in me.vertex_colors:
+        if i_vert==0:
+            col = vcol.data[i_face].color1
+        if i_vert==1:
+            col = vcol.data[i_face].color2
+        if i_vert==2:
+            col = vcol.data[i_face].color3
+        r=col[0]
+        g=col[1]
+        b=col[2]
+        texture=("rgb(%3.2f,%3.2f,%3.2f)"%(r,g,b))
+        tex_list.append({'u':0.0,'v':0.0,'tex':texture})        
+
+    return tex_list
+
+def build_uv_texture_list(i_vert,i_face,me,obj):
+    global texture_swap_count,current_texture_list
+    
+    tex_list=[]
+    tex_name_list=[]
+    for uvt in me.uv_textures:            
+        if uvt.data[i_face].image!=None:
+            if i_vert==0:
+                uv=uvt.data[i_face].uv1
+            if i_vert==1:
+                uv=uvt.data[i_face].uv2
+            if i_vert==2:
+                uv=uvt.data[i_face].uv3
+            texture=os.path.basename(uvt.data[i_face].image.filepath)
+            
+            name=uvt.data[i_face].image.name
+            if (tex_name_list.count(name)==0):
+                tex_name_list.append(name)
+                
+            if not(os.path.isfile(texture)) or uvt.data[i_face].image.file_format!='TARGA':
+                image=uvt.data[i_face].image
+                image.file_format='TARGA'
+                image.filepath_raw=os.path.basename(image.filepath).rsplit('.',1)[0]+'.tga'
+                try:
+                    image.save()
+                except:
+                    pass
+                texture=os.path.basename(uvt.data[i_face].image.filepath)
+            map=uvt.data[i_face].image.mapping;
+                
+            tex_list.append({'u':uv[0],'v':uv[1],'tex':texture,'map':map});
+
+    for i in range(len(tex_name_list)):
+        try:
+            if (tex_name_list[i]!=current_texture_list[i]):
+                current_texture_list[i]=tex_name_list[i]
+                texture_swap_count+=1
+        except:
+            current_texture_list.append(tex_name_list[i])
+            texture_swap_count+=1
+    
+    return tex_list
+
+def selected(faces):
+
+    bpy.ops.object.mode_set(mode='OBJECT')
+    n=0
+    for face in faces:
+        if face.select:
+            n=n+1 
+    bpy.ops.object.mode_set(mode='EDIT')    
+    return n
+
+def unselect_unhide():
+    bpy.ops.object.mode_set(mode='EDIT')
+    bpy.ops.mesh.select_all(action='DESELECT')
+    bpy.ops.mesh.reveal()
+    bpy.ops.object.mode_set(mode='OBJECT')        
+    return
+
+def select_same_image():
+    bpy.ops.object.mode_set(mode='EDIT')            
+    bpy.ops.mesh.select_similar(type='IMAGE')   
+    bpy.ops.object.mode_set(mode='OBJECT')        
+    return   
+
+def hide_unselected():
+    bpy.ops.object.mode_set(mode='EDIT')                
+    bpy.ops.mesh.hide(unselected=True)
+    bpy.ops.object.mode_set(mode='OBJECT')         
+
+def export_mesh(obj,f):
+    
+    me=obj.data
+
+    #me=obj.to_mesh(scene=bpy.context.scene,apply_modifiers=True,settings='RENDER')
+    
+    nf=len(me.faces)
+    lper=-11
+    print ("Exporting mesh %s, %d faces, %d vertices"%(obj.data.name,len(me.faces),len(me.vertices)))
+
+    cpt=0 
+#    for i_tface,tface in enumerate(me.faces):
+    #depth, texture name, texture mode, indice
+    faces_array=[[0,'',i] for i in range(nf)]
+        
+
+    print ("Working on %d faces" % len(me.faces))
+    
+    print ("Building faces texture list")
+    for i,face in enumerate(me.faces):
+        for uvt in me.uv_textures:
+            if uvt.data[i].image!=None:
+                faces_array[face.index][1]+='|'+uvt.data[i].image.name
+                faces_array[face.index][0]=uvt.data[i].image.depth;
+    
+    print ("Sorting texture list")
+    faces_array.sort()
+        
+        #bpy.ops.object.mode_set(mode='OBJECT')        
+
+    print ("Exporting sorted list")
+    #for i_face,face in enumerate(me.faces):
+    for fa in faces_array:
+        
+        face = me.faces[fa[2]]
+        i_face = face.index
+
+        per=((cpt+1)*100)/nf
+        if per>lper+10:
+            print("%d%% (%d)"%(per,cpt))
+            lper=per
+        #print (i_face)
+        verts = face.vertices
+        
+        for i_vert,vert in enumerate(verts):
+            export_vertice(vert,face,me,obj,f)
+
+            tex_list=build_uv_texture_list(i_vert,i_face,me,obj)
+            if (len(tex_list)==0):
+                tex_list+=build_vertex_color_list(i_vert,i_face,me)
+
+            #print ("**"+tex_list)
+            
+            if len(tex_list)==0:
+                tex_list.append({'u':0.0,'v':0.0,'tex':'rgb(0.6,0.6,0.6)'})
+                
+            tex=tex_list[0]
+            f.write("  %f %f %s"%(tex['u'],tex['v'],tex['tex']))
+            ref_tex=tex_list[0] # used to find special multi texture without uv coordinates
+            tex_list.remove(tex)
+            for tex in tex_list:
+                #ugly way to specify a texture without inherited uv mapping
+                if (tex['map']=='UV'):
+                    if (abs(tex['u']-50.0*ref_tex['u'])<1e-5) and (abs(tex['v']-50.0*ref_tex['v'])<1e-5):
+                        f.write(";%s"%(tex['tex']))
+                    else:
+                        f.write(";%f|%f|%s"%(tex['u'],tex['v'],tex['tex']))
+                else:
+                    f.write("#%s"%(tex['tex']))
+
+            f.write("\n")
+        cpt+=1
+        
+                        
+    print ("%d%% (%d)"%(per,nf))
+    #bpy.data.meshes.remove(me)    
+
+def write_some_data(context, filepath, save_elements,save_position):
+    global all_scene,texture_swap_count
+    global exported_mesh_list
+
+    exported_mesh_list=[]
+    
+    pos_file_name = os.path.basename(filepath) + ".pos"
+
+    print ("Using file name: %s Working directory: %s"%(os.path.basename(filepath),os.path.dirname(filepath)))
+    
+    print ("Changing working directory to %s"%os.path.dirname(filepath))
+    os.chdir(os.path.dirname(filepath))
+   
+    if save_elements:
+        print ("Saving Each element in its own file according to mesh name.")
+        all_scene=False
+    else:
+        print ("Saving all scene in one file.")
+        print ("Opening %s for writing."%os.path.basename(filepath))
+        f =open(os.path.basename(filepath),'w')
+        print ("Version 1 tri file")
+        f.write("1\n")
+        all_scene=True
+    
+    if save_position:
+        print ("Saving elements positions in %s file."%pos_file_name)
+        f_pos=open(pos_file_name,'w')
+    
+    save_state(context)
+    
+    if len(context.selected_objects)==0:
+        bpy.ops.object.select_all(action='SELECT')
+        print ("No object selected, selecting all objects.")    
+
+    selected_objects = context.selected_objects
+    
+    texture_swap_count=0
+    print ("%d objects to export."%(len(selected_objects)))
+    
+    big_wobj=None    
+                           
+    for i_obj,obj in enumerate(selected_objects):
+        
+        try:
+            mesh_name=obj.data.name
+        except:
+            mesh_name=""
+
+        if save_position:
+            n1=obj.name.replace(" ","_")
+            n2=mesh_name.replace(" ","_")
+            f_pos.write("%32.32s %32.32s %f %f %f %f %f %f\n"%(n1,n2,obj.location[0],obj.location[1],obj.location[2],obj.rotation_euler[0],obj.rotation_euler[1],obj.rotation_euler[2]))
+ 
+        if obj.type=='LAMP' or obj.type=='CAMERA' or obj.type=='CURVE':
+            print ("Skipping object {}.".format(obj))
+            continue
+
+        mesh_name=obj.data.name
+        if mesh_name[0]=='.':
+            print ("Not exporting %s hidden mesh (begin with a . "%mesh_name)
+            continue
+        
+        if not (mesh_name in exported_mesh_list):
+            exported_mesh_list.append(mesh_name)
+        else:
+            print ("Skipping %s already exported"%mesh_name)
+            continue
+
+        bpy.ops.object.select_all(action='DESELECT')
+        #bpy.ops.object.select_name(name=obj.name)
+        bpy.ops.object.select_pattern(pattern=obj.name)
+        
+        print ("Exporting {} / {} Type:{}".format(obj,obj.name,obj.type))
+           
+        wobj = convert_to_mesh(obj)
+        convert_quad_to_tri(wobj)
+        
+        if all_scene:
+            if big_wobj==None:
+                print("Creating One big object/mesh for all scene.\n")
+                big_wobj=wobj
+            else:
+                print ("Joining %s and %s\n"%(big_wobj.name,wobj.name))
+                bpy.ops.object.select_all(action='DESELECT')
+                bpy.context.scene.objects.active=big_wobj
+                bpy.ops.object.select_pattern(pattern=big_wobj.name)
+                bpy.ops.object.select_pattern(pattern=wobj.name,extend=True)
+                bpy.ops.object.join()
+                
+            if i_obj < len(selected_objects)-1:
+                print ("Not last object, continue join.\n")
+                continue
+            else:
+                wobj=big_wobj
+                print ("Ok for exporting %s...\n"%wobj.name)
+                
+                
+                
+                
+        if not all_scene:
+            file_name=mesh_name
+            file_name+='.tri'
+            print ("Opening %s for writing."%file_name)
+            f =open(file_name,'w')
+            print ("Version 1 tri file")
+            f.write("1\n")               
+            
+
+        export_mesh(wobj,f)
+            
+        print ("Removing temporary object.")
+        bpy.ops.object.delete()
+
+        if not all_scene:
+            print("Closing %s file."%file_name)
+            f.close()
+
+    print ("Closing tri file.")
+    if all_scene:
+        f.close()
+        
+    if save_position:
+        print ("Closing position file.")
+        f_pos.close()
+        
+    restore_state(context)
+    print ("Texture swap count:%d."%texture_swap_count)
+    return {'FINISHED'}
+
+
+def read_some_data(context,filepath,clean_mesh):
+    
+    print ("Using file name: %s Working directory: %s"%(os.path.basename(filepath),os.path.dirname(filepath)))
+    
+    print ("Changing working directory to %s"%os.path.dirname(filepath))
+    os.chdir(os.path.dirname(filepath))
+    print ("importing %s."%filepath)
+    
+    finf=os.stat(filepath)
+    fsiz=finf.st_size
+    file=open(filepath,'r')
+    name=os.path.basename(filepath).split('.')[0]
+    ver = file.readline()
+    print (ver)
+    ver=int(ver)
+    if ver != 1 and ver!= 0 :
+        print ("Not a version 1 tri file. Not supported.")
+        return {'CANCELLED'}
+ 
+    print ('Creating Object')
+    bpy.ops.object.add(type='MESH')
+    #print ('Creating Mesh %s'%name)
+    #bpy.data.meshes.new(name)
+    #me=bpy.data.meshes[name]
+    #bpy.context.object.data=me
+    me=bpy.context.object.data
+    print ("Reading datas.")
+
+    nv=0
+    ne=0
+    nf=0
+
+    v=me.vertices
+    e=me.edges
+    f=me.faces
+    
+    n=0
+    while 1:
+        vert=file.readline() 
+        n=n+1
+        if not vert:
+            break
+        
+    file.seek(0)    #rewind file
+    file.readline() #skip first line (version)
+    
+    #allocate vertices,edges face, very very faster this way 
+    v.add(n)
+    f.add(n/3)
+    e.add(n)
+    
+    ltt=[] #last texture table, used to count texture changes
+    texture_change_count=0 
+    
+    image_not_found=[]
+
+    lper=-11    
+    while 1:
+        vert=file.readline() 
+        
+        if not vert:
+            break
+
+
+        per=(nv+2)*100/n;
+        if per>lper+10:
+            print ("%d%% (%d)"%(per,nf))
+            lper=per
+        
+        vs=vert.split()
+        ivs=0
+
+        v[nv].co=[float(vs[0]),float(vs[1]),float(vs[2])]
+        ivs=3
+
+        if ver==1:
+            v[nv].normal=[float(vs[3]),float(vs[4]),float(vs[5])]
+            ivs=6
+
+        #now compute texture information
+        tu=[]
+        tv=[]
+        tt=[]
+        tu.append(float(vs[ivs])) #remember it will be tu[0] 
+        tv.append(float(vs[ivs+1]))
+        
+        t=vs[ivs+2] #full texture name
+        
+        t=t.split(';') #split textures name, first name only, others u|v|name
+        temp=[];
+        for it in t:
+            ts=it.split('#');
+            if len(ts)==1:
+                temp.append([ts[0],0]);
+            else:
+                temp.append([ts[0],0]);
+                temp.append([ts[1],1]); # if we can split, the second is environnement texture.
+                
+        t=temp;
+        
+        tt.append(t[0]) #add first texture name to texture list
+        t.remove(t[0])
+        
+        for itt  in t:
+            it=itt[0]; # get texture string
+            map=itt[1]; 
+            #print (it)
+            iit=it.split('|')
+            #u and v coordinate and texture name
+            if len(iit)==3:
+                tu.append(float(iit[0]))
+                tv.append(float(iit[1]))
+                tt.append([iit[2],map])
+                
+            #only texture name using raydium hard coded scale factor of 50 from first texture coordinate
+            if len(iit)==1:
+                tu.append(tu[0]*50) #first texture it's ALWAYS in 0
+                tv.append(tv[0]*50)
+                tt.append([iit[0],map])
+        
+        ntt=0 # number of texture layers
+        ntc=0 # number of vertex color layers
+        
+        for i,ti in enumerate(tt): #for each texture
+            t=ti[0];
+            map=ti[1];
+            if t.find('rgb')==0:
+                ntc=ntc+1
+                if ntc > len(me.vertex_colors):
+                    print ("Adding RGB texture layer")
+                    me.vertex_colors.new()
+                l=t.split('(')
+                l=l[1]
+                l=l.split(',')
+                l[2]=l[2].split(')')[0]
+                if (nv%3)==0:
+                    me.vertex_colors[ntc-1].data[nf].color1=[float(l[0]),float(l[1]),float(l[2])]
+                if (nv%3)==1:
+                    me.vertex_colors[ntc-1].data[nf].color2=[float(l[0]),float(l[1]),float(l[2])]
+                if (nv%3)==2:
+                    me.vertex_colors[ntc-1].data[nf].color3=[float(l[0]),float(l[1]),float(l[2])]                                        
+            else:
+                ntt=ntt+1
+                #print (t)
+                if ntt > len (me.uv_textures):
+                    print ("Adding uv texture layer")
+                    me.uv_textures.new()
+                im=bpy.data.images.get(t)
+
+                if (image_not_found.count(t)==0):
+                    if not(isinstance(im,bpy.types.Image)):
+                        print ("Loading image %s."%t)
+                        try:
+                            print ("trying")
+                            bpy.data.images.load(t)
+                            print ("end trying")
+                        except:
+                            print ("except")
+                            image_not_found.append(t)
+                            print ("Not found image:%s."%t)
+                            pass
+                    
+                im=bpy.data.images.get(t)                        
+                me.uv_textures[ntt-1].data[nf].image=im
+                if map==0:
+                    me.uv_textures[ntt-1].data[nf].image.mapping='UV';
+                else:
+                    me.uv_textures[ntt-1].data[nf].image.mapping='REFLECTION';
+                #me.uv_textures[ntt-1].data[nf].use_image=True
+                if(nv%3)==0:
+                    me.uv_textures[ntt-1].data[nf].uv1=[tu[i],tv[i]]
+                if(nv%3)==1:
+                    me.uv_textures[ntt-1].data[nf].uv2=[tu[i],tv[i]]
+                if(nv%3)==2:
+                    me.uv_textures[ntt-1].data[nf].uv3=[tu[i],tv[i]]
+        
+        for i,t in enumerate(tt): #Count texture changes
+            try:
+                lt=ltt[i]
+            except:
+                ltt.append(t)
+                texture_change_count+=1
+                
+            if (t!=ltt[i]):
+                texture_change_count+=1
+                ltt[i]=t
+                           
+
+        nv=nv+1
+
+        if (nv%3)==0:
+            e[ne].vertices=[(nv-3),(nv-2)]
+            e[ne+1].vertices=[(nv-2),(nv-1)]
+            e[ne+2].vertices=[(nv-1),(nv-3)]
+            ne=ne+3
+            
+            f[nf].vertices=[(nv-3),(nv-2),(nv-1)]
+            
+            if v[nv-3].normal==v[nv-2].normal and v[nv-2].normal==v[nv-1].normal:
+                f[nf].use_smooth=False
+            else:
+                f[nf].use_smooth=True
+                
+            nf=nf+1                
+    
+    print ("%d%% (%d)"%(per,nf))
+    print (".tri file need %d textures swap"% texture_change_count)
+    
+    for t in image_not_found:
+        print ("Error image %s not found."%t)
+        
+    print ("Mesh Imported Vertices:%d Edges:%d Faces:%d."%(len(v),len(e),len(f)))
+    #me.from_pydata(v,e,f)
+    bpy.ops.object.mode_set(mode='EDIT')
+    print("close file.")
+    file.close()  
+    if clean_mesh:  
+        print("Clean Up Mesh")
+        bpy.ops.mesh.remove_doubles(limit=0.0001)
+        bpy.ops.mesh.tris_convert_to_quads()
+        
+    bpy.ops.object.mode_set(mode='OBJECT')
+    return {'FINISHED'} 
+
+# ExportHelper is a helper class, defines filename and
+# invoke() function which calls the file selector.
+from bpy_extras.io_utils import ExportHelper,ImportHelper
+from bpy.props import StringProperty, BoolProperty, EnumProperty
+
+
+class ExportSomeData(bpy.types.Operator, ExportHelper):
+    '''Export Raydium .tri file.'''
+    bl_idname = "export.raydium_tri"  # this is important since its how bpy.ops.export.some_data is constructed
+    bl_label = "Export Raydium Tri File"
+
+    # ExportHelper mixin class uses this
+    filename_ext = ".tri"
+
+    filter_glob = StringProperty(default="*.tri", options={'HIDDEN'})
+
+    # List of operator properties, the attributes will be assigned
+    # to the class instance from the operator settings before calling.
+    save_elements = BoolProperty(name="Save Each Element", description="Save each object as one file, using mesh name", default=False)
+    save_position = BoolProperty(name="Save Each Element Pos/Rot",description="Save Position and rotation of each element",default=False)
+
+#    type = EnumProperty(items=(('OPT_A', "First Option", "Description one"),
+#                               ('OPT_B', "Second Option", "Description two."),
+#                               ),
+#                        name="Example Enum",
+#                        description="Choose between two items",
+#                        default='OPT_A')
+#
+    @classmethod
+    def poll(cls, context):
+        #return context.active_object != None
+        return len(context.selectable_objects)>0
+
+    def execute(self, context):
+        now=time.time()
+        print ("----------------New Export------------------------")        
+        ret=write_some_data(context, self.filepath, self.save_elements,self.save_position)
+        print ("Elapsed: %f"%(time.time()-now))        
+        return ret
+    
+class ImportSomeData(bpy.types.Operator,ImportHelper):
+    '''Import Raydium .tri file.'''
+    bl_idname = "import_mesh.raydium_tri"  # this is important since its how bpy.ops.export.some_data is constructed
+    bl_label = "Import Raydium Tri File"
+
+    # ExportHelper mixin class uses this
+    filename_ext = ".tri"
+
+    filter_glob = StringProperty(default="*.tri", options={'HIDDEN'})
+
+    # List of operator properties, the attributes will be assigned
+    # to the class instance from the operator settings before calling.
+    clean_mesh = BoolProperty(name="Clean Up Mesh", description="Remove doubles vertices and try to make quads faces", default=False)
+
+#    type = EnumProperty(items=(('OPT_A', "First Option", "Description one"),
+#                               ('OPT_B', "Second Option", "Description two."),
+#                               ),
+#                        name="Example Enum",
+#                        description="Choose between two items",
+#                        default='OPT_A')
+#
+    @classmethod
+    def poll(cls, context):
+        return True
+        #return context.active_object != None
+        #return len(context.selectable_objects)>0
+
+    def execute(self, context):
+        now=time.time()
+        print ("----------------New Import------------------------")
+        ret=read_some_data(context,self.filepath,self.clean_mesh) 
+        print ("Elapsed: %f"%(time.time()-now))
+        return ret
+
+
+# Only needed if you want to add into a dynamic menu
+def menu_func_export(self, context):
+    self.layout.operator(ExportSomeData.bl_idname, text="Raydium (.tri)")
+
+def menu_func_import(self, context):
+    self.layout.operator(ImportSomeData.bl_idname, text="Raydium (.tri)")
+
+def register():
+    bpy.utils.register_class(ExportSomeData)
+    bpy.types.INFO_MT_file_export.append(menu_func_export)
+    bpy.utils.register_class(ImportSomeData)
+    bpy.types.INFO_MT_file_import.append(menu_func_import)    
+
+
+def unregister():
+    bpy.utils.unregister_class(ExportSomeData)
+    bpy.types.INFO_MT_file_export.remove(menu_func_export)
+    bpy.utils.unregister_class(ImportSomeData)
+    bpy.types.INFO_MT_file_export.remove(menu_func_Import)    
+
+
+if __name__ == "__main__":
+    #unregister()
+    try:
+        unregister()
+    except:
+        pass
+    register()
+
+    # test call
+    for i in range(20):
+        print ("\n")
+    
+    #bpy.ops.export.raydium_tri('INVOKE_DEFAULT')
+    #bpy.ops.import_mesh.raydium_tri('INVOKE_DEFAULT')
+    #write_some_data(bpy.context,"c:\\test.tri",True)
+    
+    if (0) :
+        try:
+            bpy.ops.object.mode_set(mode='OBJECT')
+        except:
+            pass
+        print ('remove object')
+        bpy.ops.object.select_all(action='SELECT')
+        bpy.ops.object.delete()
+        print ('removed')
+        
+        try:
+            while 1:
+                print ('remove mesh')
+                bpy.data.meshes.remove(bpy.data.meshes[0])
+                print ('removed')
+        except:
+            pass    
+        
+        #read_some_data(bpy.context,'C:\\raydium_win32_sdk_1041\\bin\\Cube.smooth.053.tri')
+        now=time.time()   
+        read_some_data(bpy.context,'C:\\raydium_win32_sdk_1041\\bin\\a.tri',True)
+        print ("Elapsed: %f."%(time.time()-now))
\ No newline at end of file
Index: triEXP-full.py
===================================================================
--- triEXP-full.py	(revision 1163)
+++ triEXP-full.py	(revision 1164)
@@ -0,0 +1,410 @@
+#!BPY 
+""" 
+Name: '-> Raydium Full export script' 
+Blender: 248 
+Group: 'Export' 
+Tooltip: 'Export object pose, mesh and texture as tga' 
+""" 
+
+try:
+	import nt
+	os=nt
+	os.sep='\\'
+except:
+	import posix
+	os=posix
+	os.sep='/'
+
+import Blender,bpy
+from Blender import Window,sys
+from Blender.sys import *
+import math 
+from math import *
+
+path=''
+
+allobj = 0
+multfile = 0
+autotri=1
+savetga = 0
+saveposrot=0
+genfilen=0
+pos_file_name=''
+exp_file_name=''
+selected_file_name=''
+
+
+def fileExists(f):
+	af = join(path,f)
+	try:
+		file = open(af)
+	except IOError:
+		exists = 0
+	else:
+		file.close()
+		exists = 1
+	return exists
+
+#Using blender feature
+#new image are tga
+#creating a new image / size is croped to power2
+#copy original image to new one
+#save image, updating original image with new one
+#TODO Unlink temp image file
+def conv_tga(image):
+	simg=image
+	dimg_name = simg.getName().split('.')[0]+'.tga'
+	print "Converting %s image to %s." % (simg.getName(),dimg_name)
+	
+	sz = simg.getSize()
+	isx=int(pow(2,int(log(sz[0])/log(2))))
+	isy=int(pow(2,int(log(sz[1])/log(2))))
+	dp=simg.getDepth()
+	dimg = Blender.Image.New(dimg_name.split('.')[0]+'.tmp',isx,isy,dp)
+	fxs=float(sz[0])/isx;fys=float(sz[1])/isy
+	xo=0;yo=0
+	#image rescale to have power of 2 texture
+	#x,y in result image,	 xo,yo in original image
+	
+	for y in range(isy):
+		yoi=int(yo);xo=0;dxf=1
+		Blender.Window.DrawProgressBar(float(y)/isy,"Converting to tga ...")
+		for x in range(isx):
+			xoi=int(xo)
+			pxy=simg.getPixelI(xoi,yoi)
+			dimg.setPixelI(x,y,pxy)
+			xo=xo+fxs
+		yo=yo+fys
+		
+	
+	dimg.setFilename(join(path,dimg_name))
+	dimg.save() 
+	
+	simg.setFilename(join(path,dimg_name))
+	simg.reload()
+	simg.setName(dimg_name)
+	print "Image converted to %d %d tga and updated(%s)." % (isx,isy,dimg_name)
+
+
+def valid_texture(image,texture_list):
+	#print "Valid texture %s" % image
+	file_name=basename(image.filename)
+	#already managed
+	if file_name in texture_list:
+		return  
+	texture_list.add(file_name)
+	if not(file_name.endswith('.tga')):
+		print "Find non .tga texture"
+		if savetga:
+			conv_tga(image)
+			file_name=basename(image.filename)
+			texture_list.add(file_name)
+	if not (fileExists(file_name)):
+		if savetga:
+			print "Creating %s " % (join(path,file_name))
+			image.setFilename(join(path,file_name))
+			image.save()
+		else:
+			print "Missing %s texture file." % file_name
+		
+#export object pos and rotation 
+def exp_pos_rot(ob,gfich):
+	chout = ob.getName()
+	pos = ob.getLocation('worldspace')
+	chout = chout + " %f,%f,%f" % (pos[0],pos[1],pos[2])
+	rot = ob.getEuler('worldspace')
+	chout = chout + ",%f,%f,%f" % (-rot[0],-rot[1],-rot[2])
+	#print chout
+	gfich.write(chout)
+	gfich.write("\n")
+	
+def quadToTri (object,scene):
+	object.sel=1
+	Blender.Object.Duplicate(mesh=1)
+	ob2=Blender.Object.GetSelected()[0]
+	m2=ob2.getData(mesh=1)
+	for f in m2.faces:
+		f.sel=1
+	m2.quadToTriangle()
+	#scn.unlink(ob2)
+	return ob2
+	
+def export(): 
+	global allobj
+
+	Window.WaitCursor(1) 
+	tinit = sys.time()
+		
+	print "Export begin"
+	Blender.Window.EditMode(0)
+	scene=Blender.Scene.GetCurrent()
+	
+	print "Path is %s" % path
+
+	if (not(allobj)):
+		objects = Blender.Object.GetSelected()
+		if len(objects)==0:
+			allobj=1
+			print "-- No object selected." 
+		else:
+			print "-- Exporting %d Selected Objects." % (len(objects))
+	if allobj:
+		objects = scene.objects
+		print "-- Exporting all %d objects" % (len(objects))
+
+	texture_list=set()
+	mesh_list=set()
+	
+	if (saveposrot):
+		gfich = open(pos_file_name,'w')
+		gfich.write('3\n')
+		print "-- Export pos/rot file : "+basename(pos_file_name)
+	
+	#Deselect all objects
+	for object in objects:
+		object.sel=0
+		
+	if not(multfile):
+		file = open (exp_file_name,'w')
+		file.write("1\n") #tri version	
+		print "-- Export all meshes file : "+basename(exp_file_name)
+	
+	for object in objects:
+		objtype=object.getType()
+		
+		if objtype =="Lamp":
+			if saveposrot:
+				exp_pos_rot(object,gfich)
+			
+		if objtype != "Mesh":
+			continue
+		
+		if (saveposrot):
+			exp_pos_rot(object,gfich)
+			
+		mesh=object.getData(mesh=1) 		
+		
+		#Hidden mesh can be used to save hinge pos and rot without needed
+		#to generate mesh .tri file
+		#need to be documented
+		#print mesh.name
+		if mesh.name[0]=='.':
+			#hidden mesh
+			print "%s is an hidden mesh" % (mesh.name)
+			continue
+			
+		if mesh.name in mesh_list:
+			#mesh already exported
+			continue
+		print "%s is a mesh(%d faces)" % (object.getName(),len(mesh.faces))	
+		
+		if (multfile):
+			filen= mesh.name + '.tri'
+			dirn=Blender.sys.dirname(exp_file_name)
+			filename=join(dirn,filen)
+			file = open (filename,"w")
+			file.write("1\n") #tri version	
+			print "--Export One mesh in file : "+basename(filename)
+				
+		mesh_list.add(mesh.name)
+		
+		if autotri:
+			#ob2 is a shadow object with all face as triangle
+			ob2=quadToTri(object,scene)
+			mesh = ob2.getData(mesh=1)
+		
+		l=len(mesh.faces)/10
+		li=0
+		lp=0
+		org=mesh.activeUVLayer
+		layers=mesh.getUVLayerNames()
+		if (len(layers)>0):
+			mesh.activeUVLayer=layers[0]
+		for face in mesh.faces:
+			if len(face)!=3:
+				print "ERROR: NOT A TRIANGLE ONLY MESH ! (select all vertices and use CTRL+T)"
+				if autotri:
+					print "This is normaly impossible "
+				#continue
+			li=li+1
+			if li>l:
+				lp+=10
+				print "%d" % lp
+				li=0
+				
+			for i in range(3): #triangles only ! (CTRL+T) 
+				indx=face.v[i].index
+				#writing vertex coordinate
+				file.write ("%f %f %f " % (mesh.verts[indx].co[0],mesh.verts[indx].co[1],mesh.verts[indx].co[2]))
+				if face.smooth:
+					nv=mesh.verts[indx].no
+				else:
+					nv=face.no
+				#writing vertex normal
+				file.write ("%f %f %f " % (nv[0],nv[1],nv[2]))
+				#if face is textured
+				if(mesh.faceUV):
+					mesh.activeUVLayer=layers[0]					
+					u=face.uv[i][0]
+					v=face.uv[i][1]
+					#get current texture image name
+					if (face.image):
+						valid_texture(face.image,texture_list)
+						texture=Blender.sys.basename(face.image.filename)
+					else:
+						texture="rgb(0.6,0.0,0.0)"
+					but=texture
+					cpt=0 # layers counter
+					if(len(layers)>1):
+						# texture=texture+';'
+						# loop on layers and append uv and name to a string
+						#print len(layers)
+						for layer in layers:
+							if (layer==layers[0]):
+								continue #already used first texture layer
+							mesh.activeUVLayer=layer
+							#Not textured layer skipping
+							# handle vertex with only one texture defined on a 
+							# mesh multitextured							
+							if not(face.image):
+								continue
+							#tex flag inactive, face is not textured, skipping
+							if not(face.mode and Blender.Mesh.FaceModes['TEX']):
+								continue
+							#Face image flagged as reflective
+							if (face.image.reflect):
+								#Found a face mapped on environnement using .tri file # syntax
+								valid_texture(face.image,texture_list)
+								t=Blender.sys.basename(face.image.filename)
+								texture=texture+"#"+t
+							else: #face image is not flagged as reflection so normal script behavior
+								uu=face.uv[i][0]
+								vv=face.uv[i][1]
+								valid_texture(face.image,texture_list)
+								t=Blender.sys.basename(face.image.filename)
+								texture=texture+';'+str(uu)+'|'+str(vv)+'|'+t
+						#end of layer multitexturing loop
+					file.write("%f %f %s\n" % (u,v,texture))
+				#face has no face UV informations
+				else:
+					#Face has vertex color assigned, using them.
+					if(mesh.vertexColors and len(face.col)>0):
+						file.write("0 0 rgb(%3.3f,%3.3f,%3.3f)\n" % (face.col[i].r/255.0,face.col[i].g/255.0,face.col[i].b/255.0))
+					else:
+					#No information, defaulting to gray face
+						file.write("0 0 rgb(0.6,0.6,0.6)\n")
+		if (org):
+			mesh.activeUVLayer=org
+		if multfile:
+			file.flush()
+			file.close()
+		if autotri:
+			scene.objects.unlink(ob2)
+		print "Mesh Exported."
+	if not(multfile):
+		file.flush()
+		file.close()
+	if(saveposrot):	
+		gfich.flush()
+		gfich.close()
+	
+	print 'Export Script finished in %.2f seconds\n' % (sys.time()-tinit)
+	print ' '
+	Window.WaitCursor(0) 
+	
+def gui():
+	global saveposrot,multfile,autotri,savetga,genfilen
+	
+	oallobj = Blender.Draw.Create(0)
+	omultfile = Blender.Draw.Create(0)
+	oautotri = Blender.Draw.Create(1)
+	osavetga = Blender.Draw.Create(0)
+	osaveposrot=Blender.Draw.Create(0)
+	ogenfilen=Blender.Draw.Create(0)
+	
+	conf = Blender.Registry.GetKey("raydium_full_export", True)
+	
+#	if not conf:
+#		return
+	
+	try:
+		oallobj.val = conf["allobj"]
+		omultfile.val = conf["multfile"]
+		oautotri.val = conf["autotri"]
+		osavetga.val = conf["savetga"]
+		osaveposrot.val = conf["saveposrot"]
+		ogenfilen.val = conf["genfile"]
+	except:
+		# If one of the key is not in the dict, don't worry, it'll use the defaults
+		pass
+
+	block = []
+	#block.append("Raydium tri export")#("Name: ", text, 0, 30, "this is some tool tip"))
+	dirs="Dir."+Blender.sys.makename()
+	#block.append("Export Mesh")
+	block.append(("Save All Objects",oallobj,"If Not Set Save only selected objects"))
+	block.append(("Separate Files",omultfile,"Each Mesh is saved in it's own file."))
+	block.append(("Auto Quad->Tri",oautotri,"Automaticaly convert quad to tri."))
+	block.append(("Create/Save tga",osavetga,"If needed create and save texture tga files"))
+	block.append(("Save Object Pose",osaveposrot,"Save each object position and rotation"))
+	block.append(("Auto. FileName",ogenfilen,"Automaticaly generate file name based on blender filename"))
+	block.append("")
+	block.append("")
+	block.append("")
+	
+	retval = Blender.Draw.PupBlock("Raydium_Export "+dirs, block)
+	if retval:
+		conf = {}	
+		conf["allobj"] = oallobj.val
+		conf["multfile"] = omultfile.val
+		conf["autotri"] = oautotri.val
+		conf["savetga"] = osavetga.val
+		conf["saveposrot"] = osaveposrot.val
+		conf["genfile"] = ogenfilen.val
+		Blender.Registry.SetKey("raydium_full_export", conf, True)
+	
+	
+	saveposrot = osaveposrot.val
+	multfile = omultfile.val
+	autotri = oautotri.val
+	savetga = osavetga.val
+	saveposrot = osaveposrot.val
+	genfilen = ogenfilen.val
+	
+def fs2(a):	
+	global exp_file_name
+
+	a=makename(a,'.tri')
+	exp_file_name=a
+	
+	export()
+
+def fs1(a):
+	a=makename(a,'.tri')
+	pos_file_name=a;
+
+	exp_file_name = makename (ext = '.tri')
+	if (not(multfile)):
+		if (not(genfilen)):
+			Blender.Window.FileSelector(fs2, ".tri Mesh Export", exp_file_name)
+	else:
+		fs2(exp_file_name)
+
+		
+def main(): 
+	global pos_file_name,exp_file_name,selected_file_name,path,genfilen
+	for i in range(20):
+		print 
+		
+	gui()
+	path = dirname(makename())
+	pos_file_name = makename (ext = '-pos.tri')
+	if (saveposrot):
+		if (not(genfilen)):
+			Blender.Window.FileSelector(fs1, ".tri Object Pos/Rot File", pos_file_name)
+	fs1(pos_file_name)	
+		
+	 
+# This lets you can import the script without running it 
+if __name__ == '__main__': 
+	main() 
\ No newline at end of file
Index: lampEXP-B2-28.py
===================================================================
--- lampEXP-B2-28.py	(revision 1163)
+++ lampEXP-B2-28.py	(revision 1164)
@@ -0,0 +1,60 @@
+#!BPY
+
+"""
+Name: 'FSrad lights export (.lamp format)'
+Blender: 2.28
+Group: 'Export'
+Tooltip: 'Export to .lamp format'
+"""
+
+import Blender
+from math import *
+from Blender.Mathutils import *
+from Blender import NMesh
+
+OUTPUTNAME="exported.tri.lamp"
+
+class source:
+	def __init__(self,filename):
+		self.file=open(filename,"w")
+
+	def writeLamps(self):
+		scene=Blender.Scene.getCurrent()
+		self.file.write("0\n")
+		
+		for object in scene.getChildren():
+		    objtype=object.getType()
+		    if objtype == "Lamp":
+			lamp=object.getData()
+			if lamp.type == Blender.Lamp.Types['Area']:
+			    print "lamp found"
+			    pos=object.loc
+			    col=lamp.col
+			    direc=euler2Vector(object.rot)
+			    ener=lamp.energy
+			    self.file.write("%f %f %f %f %f %f %f %f %f %f\n" % (pos[0],pos[1],pos[2],direc[0],direc[1],direc[2],col[0],col[1],col[2],ener))
+
+	def close(self):
+			self.file.flush()
+			self.file.close()
+
+
+def euler2Vector(rot):
+    vec = Vector([0,0,-1])
+    x,y,z = rot
+    mat = Euler([degs(x),degs(y),degs(z)]).toMatrix()
+    res = VecMultMat(vec,mat.rotationPart())
+    return res[0],res[1],res[2]
+	                                                                                  
+def radians(deg):
+  return deg * pi/180.0
+                                                                                  
+def degs(rad):
+    return rad * 180.0/pi
+        
+    
+
+obj=source(OUTPUTNAME)
+obj.writeLamps()
+obj.close
+print "Lamps exported to %s\n" % (OUTPUTNAME)
Index: triEXP-MD2-36.py
===================================================================
--- triEXP-MD2-36.py	(revision 1163)
+++ triEXP-MD2-36.py	(revision 1164)
@@ -0,0 +1,106 @@
+#!BPY
+
+"""
+Name: 'Raydium Export (.tri format)'
+Blender: 2.36"
+Group: 'Export'
+Tooltip: 'Export to .tri format'
+"""
+
+import Blender
+from Blender import NMesh
+
+class source:
+	def __init__(self,filename):
+		self.file=open(filename,"w")
+
+	def writeFaces(self):
+		scene=Blender.Scene.getCurrent()
+		allobj=scene.getChildren()
+		Blender.Set("curframe", 0)
+		mesh=NMesh.GetRawFromObject(allobj[0].name)
+		vlist=mesh.verts
+
+		# shame :)
+		nv=0
+		for nvi in mesh.faces:
+		    nv=nv+1
+		nv=nv*3
+
+		self.file.write("2\n") #tri version
+		self.file.write("20 %i\n" % nv) # number of anims
+		# anims
+		self.file.write("0 39 stand\n")
+		self.file.write("40 45 run\n")
+		self.file.write("46 53 attack\n")
+		self.file.write("54 57 pain1\n")
+		self.file.write("58 61 pain2\n")
+		self.file.write("62 65 pain3\n")
+		self.file.write("66 71 jump\n")
+		self.file.write("72 83 flip\n")
+		self.file.write("84 94 salute\n")
+		self.file.write("95 111 taunt\n")
+		self.file.write("112 122 wave\n")
+		self.file.write("123 134 point\n")
+		self.file.write("135 153 crstnd\n")
+		self.file.write("154 159 crwalk\n")
+		self.file.write("160 168 crattack\n")
+		self.file.write("169 172 crpain\n")
+		self.file.write("173 177 crdeath\n")
+		self.file.write("178 183 death1\n")
+		self.file.write("184 189 death2\n")
+		self.file.write("190 197 death3\n")
+		self.file.write("0\n") #sub-tri version
+				
+		for object in scene.getChildren():
+		    objtype=object.getType()
+		    if objtype == "Mesh":
+			print "ok, it's a mesh"
+			for frame in range(198):
+			    print "frame ", frame
+			    Blender.Set("curframe", frame)
+			    mesh=NMesh.GetRawFromObject(object.name)
+			    vlist=mesh.verts
+			    for face in mesh.faces:
+				if len(face)!=3:
+				    print "ERROR: NOT A TRIANGLE ONLY MESH ! (select all vertices and use CTRL+T)"
+		                for i in range(3): #triangles only ! (CTRL+T)
+		                    indx=vlist.index(face[i])
+				    if(face.image):
+					u=face.uv[i][0]
+					v=face.uv[i][1]
+					self.file.write("%f %f %f %f %f %s\n" % (vlist[indx][0],vlist[indx][1],vlist[indx][2],u,v,face.image.name))
+				    else:   
+					self.file.write("%f %f %f 0 0 rgb(0.5,0.5,0.5)\n" % (vlist[indx][0],vlist[indx][1],vlist[indx][2]))
+					
+
+
+# get the face normals
+#			self.file.write("GLfloat normals[%d][3] = {\n" % len(mesh.normals) )
+#			for normal in mesh.normals:
+#				self.file.write("{ %ff, %ff, %ff },\n" % (normal[0],normal[1],normal[2]))
+#			self.file.write("};\n\n")
+
+# get the mesh colors
+#			if mesh.colors:
+#				self.file.write("char OBJ_HAVE_COLORS=1;\n")
+#				self.file.write("GLfloat colors[%d][3] = {\n" % len(mesh.colors) )
+#				for color in mesh.colors:
+#					self.file.write("{ %ff, %ff, %ff },\n" % (color[0],color[1],color[2]))
+#				self.file.write("};\n\n")
+#			else:
+#				self.file.write("char OBJ_HAVE_COLORS=0;\nGLfloat *colors;\n")
+
+
+	def close(self):
+			self.file.flush()
+			self.file.close()
+
+def fs_callback(filename):
+	if filename.find('.tri', -4) <= 0: filename += '.tri'
+	obj=source(filename)
+	obj.writeFaces()
+	obj.close
+	print "Exported to %s. Textures must be .tga, uncompressed, origin NOT at lower-left.\n" % (filename)
+
+Blender.Window.FileSelector(fs_callback, "Export Raydium Tri")
Index: triEXP-B2-36.py
===================================================================
--- triEXP-B2-36.py	(revision 1163)
+++ triEXP-B2-36.py	(revision 1164)
@@ -0,0 +1,89 @@
+#!BPY
+
+"""
+Name: 'Raydium Export (.tri format)'
+Blender: 2.43"
+Group: 'Export'
+Tooltip: 'Export to .tri format'
+"""
+
+#import rpdb2;
+#rpdb2.start_embedded_debugger("test",True)
+
+import Blender
+
+from Blender import NMesh
+from Blender.sys import *
+
+class source:
+	def __init__(self,filename):
+		self.file=open(filename,"w")
+
+	def writeFaces(self):
+		Blender.Window.EditMode(0)
+		scene=Blender.Scene.GetCurrent()
+		self.file.write("1\n") #tri version
+		
+		objects = Blender.Object.GetSelected()
+
+		if len(objects) == 0:
+		    print "-- Exporting all objects"
+		    objects = scene.getChildren()
+		else:
+		    print "-- Exporting only selected objects"
+
+		for object in objects:
+		    objtype=object.getType()
+		    if objtype == "Mesh":
+			print "ok, it's a mesh"
+			mesh=object.getData(mesh=1) # let's get a Mesh, not a NMesh (faster, thin)
+			for face in mesh.faces:
+				if len(face)!=3:
+				    print "ERROR: NOT A TRIANGLE ONLY MESH ! (select all vertices and use CTRL+T)"
+		                for i in range(3): #triangles only ! (CTRL+T)
+		                    #indx=face.vlist.index(face[i])
+				    indx=face.v[i].index
+				    if(mesh.faceUV and face.image):
+					u=face.uv[i][0]
+					v=face.uv[i][1]
+					layers=mesh.getUVLayerNames()
+					texture=Blender.sys.basename(face.image.filename)
+					but=texture
+					cpt=0 # layers counter
+					if(len(layers)>1):
+					    org=mesh.activeUVLayer
+					    texture=texture+';'
+					    # loop on layers and append uv and name to a string
+					    for layer in layers:
+						mesh.activeUVLayer=layer
+						uu=face.uv[i][0]
+						vv=face.uv[i][1]
+						t=Blender.sys.basename(face.image.filename)
+						if(t!=but):
+						    if(cpt>0):
+							texture=texture+'|'
+						    cpt=cpt+1
+						    texture=texture+str(uu)+'|'+str(vv)+'|'+t
+					    mesh.activeUVLayer=org
+					self.file.write("%f %f %f %f %f %f %f %f %s\n" % (mesh.verts[indx].co[0],mesh.verts[indx].co[1],mesh.verts[indx].co[2],mesh.verts[indx].no[0],mesh.verts[indx].no[1],mesh.verts[indx].no[2],u,v,texture))
+				    else:
+						if(mesh.vertexColors and len(face.col)>0):
+							self.file.write("%f %f %f %f %f %f 0 0 rgb(%3.3f,%3.3f,%3.3f)\n" % (mesh.verts[indx].co[0],mesh.verts[indx].co[1],mesh.verts[indx].co[2],mesh.verts[indx].no[0],mesh.verts[indx].no[1],mesh.verts[indx].no[2],face.col[i].r/255.0,face.col[i].g/255.0,face.col[i].b/255.0))
+						else:
+							self.file.write("%f %f %f %f %f %f 0 0 rgb(0.6,0.6,0.6)\n" % (mesh.verts[indx].co[0],mesh.verts[indx].co[1],mesh.verts[indx].co[2],mesh.verts[indx].no[0],mesh.verts[indx].no[1],mesh.verts[indx].no[2]))
+					
+
+	def close(self):
+			self.file.flush()
+			self.file.close()
+
+def fs_callback(filename):
+	if filename.find('.tri', -4) <= 0: filename += '.tri'
+	obj=source(filename)
+	obj.writeFaces()
+	obj.close
+	print "Exported to %s. Textures must be .tga, uncompressed, origin NOT at lower-left.\n" % (filename)
+
+#fs_callback("tt.tri")
+nfile = makename (ext = '.tri')
+Blender.Window.FileSelector(fs_callback, "Export Raydium Tri", nfile)
Index: emptyEXP-B2-28.py
===================================================================
--- emptyEXP-B2-28.py	(revision 1163)
+++ emptyEXP-B2-28.py	(revision 1164)
@@ -0,0 +1,59 @@
+#!BPY
+
+"""
+Name: 'Empty entities export for Raydium'
+Blender: 2.28
+Group: 'Export'
+Tooltip: 'Raydium entities'
+"""
+
+import Blender
+from math import *
+from Blender.Mathutils import *
+from Blender import NMesh
+
+OUTPUTNAME="exported.ent"
+
+class source:
+	def __init__(self,filename):
+		self.file=open(filename,"w")
+
+	def writeLamps(self):
+		scene=Blender.Scene.getCurrent()
+		self.file.write("0\n")
+		
+		for object in scene.getChildren():
+		    objtype=object.getType()
+		    if objtype == "Empty":
+			    emp=object.getData()
+			    print "empty found"
+			    pos=object.loc
+			    name=object.name
+			    #direc=euler2Vector(object.rot)
+			    direc=object.rot
+			    self.file.write("%f %f %f %f %f %f %s\n" % (pos[0],pos[1],pos[2],-direc[0],-direc[1],-direc[2],name))
+
+	def close(self):
+			self.file.flush()
+			self.file.close()
+
+
+def euler2Vector(rot):
+    vec = Vector([0,0,-1])
+    x,y,z = rot
+    mat = Euler([degs(x),degs(y),degs(z)]).toMatrix()
+    res = VecMultMat(vec,mat.rotationPart())
+    return res[0],res[1],res[2]
+	                                                                                  
+def radians(deg):
+  return deg * pi/180.0
+                                                                                  
+def degs(rad):
+    return rad * 180.0/pi
+        
+    
+
+obj=source(OUTPUTNAME)
+obj.writeLamps()
+obj.close
+print "empty entities exported to %s\n" % (OUTPUTNAME)
Index: triIMP-B2-31.py
===================================================================
--- triIMP-B2-31.py	(revision 1163)
+++ triIMP-B2-31.py	(revision 1164)
@@ -0,0 +1,248 @@
+#!BPY
+
+"""
+Name: 'Raydium Import (.tri format)'
+blender: 2.31
+Group: 'Import'
+Tooltip: 'Import a .tri'
+"""
+#import rpdb2;
+#rpdb2.start_embedded_debugger("test",True)
+
+try:
+	import nt
+	os=nt
+	os.sep='\\'
+except:
+	import posix
+	os=posix
+	os.sep='/'
+
+import sys
+import Blender
+from Blender import sys
+from Blender.Mathutils import *
+
+# This script will include .tri files (Raydium mesh files)
+# Do not supports multitexturing yet.
+# Python puxxor :)
+
+
+def fileExists(f):
+	try:
+		file = open(f)
+	except IOError:
+		exists = 0
+	else:
+		exists = 1
+	return exists
+
+def selectUVLayer(mesh,k):
+	ntexname = "tex.%d" % (k)	
+	try:
+		mesh.activeUVLayer = ntexname
+	except:
+		print "Add UV Layer %s" % ntexname
+		mesh.addUVLayer(ntexname)
+		
+	mesh.activeUVLayer = ntexname
+	return
+
+class source:
+	def __init__(self,filename):
+		self.filename=filename
+		self.file=open(filename,"r")
+
+	def readFaces(self,meshname):
+		
+		lines = self.file.readlines();
+		p = Blender.sys.dirname(self.filename)
+		os.chdir(p)
+		print "CWD is now %s" % (p)
+		scene=Blender.Scene.GetCurrent()
+		
+		print "Creating %s Mesh" % meshname
+		mesh = Blender.Mesh.New(meshname)
+		
+		words = lines[0].split()
+		if len(words) <>1 :
+			print "Not a raydium .tri file (first line must be 0 or 1)"
+			return 0
+		version = float(words[0])
+		if version <0 or version >1:
+			print "Not a supported (0 or 1) file format"
+			return 0
+
+		n = 0
+		vi = 0
+		fi = 0
+		
+		ntot = len(lines)-1
+		naff = ntot /10
+		ncour = 0
+		
+		print "Reading Datas"
+		lfilename =[]
+		faces = []
+		verts =[]
+		lvertn=[]
+		
+		vbuv=[]
+		ltexname=[]
+	
+		for line in lines[1:]:
+			ncour=ncour+1
+			if (ncour % naff)==0:
+				print (ncour*100/ntot)+1
+
+			words = line.split()
+			
+			verts.append([float(words[0]),float(words[1]),float(words[2])])
+			vi=vi+1
+			
+			if version==1:
+				lvertn.append(Vector(float(words[3]),float(words[4]),float(words[5])))
+				vbuv.append(Vector(float(words[6]),float(words[7])))
+			
+			if version==0:
+				vbuv.append(Vector(float(words[3]),float(words[4])))
+				
+					
+			if (vi%3)==0:
+				faces.append([vi-3,vi-2,vi-1])
+				if version==1:
+					ltexname.append(words[8])
+				if version==0:
+					ltexname.append(words[5])
+				fi=fi+1
+				
+		print "Done Read %d vertices %d faces" % (vi,fi)
+		
+		print "Creating Mesh"	
+		mesh.verts.extend(verts)
+		mesh.faces.extend(faces)
+		print "Done"
+		
+		if version==1:
+			print "Updating %d Normals" % vi
+			for i in range(vi):
+				mesh.verts[i].no = lvertn[i]
+			print "Done."
+		
+		print "Updating %d Face UV" % fi
+		
+		limages=[]
+		nimages=[]
+		for i in range(fi):
+			if (i % (fi/10))==0:
+				print (i*100/fi)+1
+				
+			for j in range(3):
+				ij=i*3+j
+				face = mesh.faces[i]
+				texname=ltexname[i]
+				#rgb texture 
+				if texname[0:4] == "rgb(":
+					
+					try:
+						mesh.activeColorLayer = "rgb"
+					except:
+						print "Adding ColorLayer"
+						mesh.addColorLayer("rgb")
+						
+					mesh.activeColorLayer = "rgb"
+					
+					temp=texname[4:-1].split(")")
+					couls=temp[0].split(",")
+					face.col[j].r=int(float(couls[0])*255)
+					face.col[j].g=int(float(couls[1])*255)
+					face.col[j].b=int( float(couls[2])*255)
+					face.col[j].a=255
+				#image textured	
+				else:
+					filename = texname.split(";")
+					for k in range(len(filename)):
+						file=filename[k]
+						if (file.find("#")>=0): #Using special caracter for environnement mapping
+							lfile=file.split("#")
+							filename[k]=lfile[0] # first field for normal image file
+							filename.insert(k+1,"#"+lfile[1])	
+							
+					for k in range(len(filename)):
+						file = filename[k]				
+						param = file.split("|")
+						if (len(param)==1):
+							texname = param[0]
+							if (k==0):
+								buv = vbuv[ij]
+							else:
+								buv = []
+						if (len(param)==3):
+							texname = param[2]
+							buv = [float(param[0]),float(param[1])]
+						
+						selectUVLayer(mesh,k)
+						
+						if (texname[0]=="#"): #special texture
+							texname=texname[1:]
+							env_map=1
+						else:
+							env_map=0
+													
+						found =-1	
+						for l  in range(len(nimages)):
+							if texname == nimages[l]:
+								found=l
+								break
+							
+						if (found==-1):	
+							nimages.append(texname)							
+							if fileExists(texname) == 0:
+								print "Cannot access to %s" % (texname)	
+								limages.append('no_tex')
+							else:
+								limages.append(Blender.Image.Load(texname))
+								found = len(limages)-1
+								print "Loading texture %s" % texname
+								
+								
+						face.image = limages[found]
+						face.mode |= Blender.Mesh.FaceModes['TEX']
+						face.mode |= Blender.Mesh.FaceModes['TWOSIDE']
+						face.image.reflect=env_map
+
+						if (len(buv)>0):
+							face.uv[j][0] = buv[0];face.uv[j][1] = buv[1];
+
+		mesh.activeUVLayer = "tex.0"
+		print "Done"
+		
+		scn = Blender.Scene.GetCurrent()
+		ob = scn.objects.new(mesh)
+		ob.setLocation(0,0,0)
+		Blender.Redraw()
+		return vi		
+
+	def close(self):
+			#self.file.flush()
+			self.file.close()
+
+def importTRI(filename):
+	t=sys.time()
+	if filename.find('.tri', -4) <= 0: filename += '.tri'
+	obj=source(filename)
+	file = Blender.sys.basename(filename)
+	meshname = file.split('.')
+	ret = obj.readFaces(meshname[0])
+	obj.close
+	if ret>0:
+		print "Imported."
+	else:
+		Blender.Draw.PupMenu("Bad File type not imported See console.")
+	print "Imported %d vertices in %.2fs" % (ret,sys.time()-t)
+
+def filesel_callback(filename):
+	test = importTRI(filename)
+
+Blender.Window.FileSelector(filesel_callback, 'Import TRI','*.tri')
+#importTRI("cocorobix.tri")
\ No newline at end of file