#
# $Id: alcresmanager.py 652 2006-09-28 22:25:35Z trylon $
#
#    Copyright (C) 2005-2006  Alcugs pyprp Project Team
#    See the file AUTHORS for more info about the team
#
#    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
#
#    Please see the file COPYING for the full license.
#    Please see the file DISCLAIMER for more details, before doing nothing.
#

try:
    import Blender
    try:
        from Blender import NMesh
    except Exception, detail:
        print detail
except ImportError:
    pass

import glob, dircache, os
from os.path import *
from binascii import *
import alcconfig
from alc_hsStream import *
from alcm5crypt import *
from alcspecialobjs import *
from alcprpfile import *
from alcurutypes import *
from alc_Classes import *
from alc_AbsClasses import *
from alcGObjects import *
from alcmfsgen import *

class alcUruPage:
    def __init__(self,parent,name="unnamed",num=0,hide=0,type=0x00):
        self.type="page"
        self.age=parent
        self.resmanager=parent.resmanager
        self.name=name
        self.num=num
        self.hide=hide
        self.type=type
        self.prp=None
        if self.resmanager.filesystem:
            self.ignore=[0x00,]
        else:
            self.ignore=[0x00,0x4C,]
            #self.ignore=[0x00,]
    
    
    def getPath(self,version=None):
        if version==None:
            version=self.age.version
        if version!=6:
            return self.age.base + "/" + self.age.name + "_District_" + self.name + ".prp"
        else:
            return self.age.base + "/" + self.age.name + "_" + self.name + ".prp"
    
    
    def preLoad(self):
        print " PreLoading %s" %(self.name)
        prpinfo=PrpFileInfo()
        try:
            #f=file(self.getPath(),"rb")
            f=hsStream(self.getPath(),"rb")
        except:
            print "Warning: Not found page %s for age %s" %(self.name,self.age.name)
            return
        prpinfo.read(f)
        f.close()
        #verify seq and num
        pid=xPageId()
        pid.setRaw(prpinfo.page_id,prpinfo.page_type)
        if self.age.getSeq()==0:
            self.age.setSeq(pid.getSeq())
        self.type=prpinfo.page_type
        pnum=self.num
        if prpinfo.name.name!=self.age.name:
            print "Error: Age name mismatch %s in manifest %s in page" %(self.age.name,prpinfo.name.name)
            print "Page %s in manifest %s in page" %(self.name,prpinfo.page.name)
            print "Debug: Age %s, Page: %s, path: %s, manifest contents:" %(self.age.name,self.name,self.getPath())
            for xpage in self.age.pages:
                print xpage.name, xpage.getPath()
            raise "Error: Age name mismatch %s in manifest %s in page" %(self.age.name,prpinfo.name.name)
        if prpinfo.page.name!=self.name:
            raise "Error: Page name mismatch %s in manifest %s in page" %(self.name,prpinfo.page.name)
        pid2=xPageId()
        pid2.setPage(self.age.getSeq(),pnum,None,prpinfo.page_type)
        if pid2.getRaw()!=pid.getRaw():
            raise "%s Page Id mismatch %08X in manifest, %08X in page" \
                  %(prpinfo.name.name + " " + prpinfo.page.name,pid2.getRaw(),pid.getRaw())

    
    def load(self):
        if self.prp==None:
            print "/\ Loading page %s %i" %(self.name,self.num)
            self.prp=PrpFile(self)
            try:
                f=hsStream(self.getPath(),"rb")
            except IOError:
                self.prp=None
                print "Warning: Not found page %s for age %s" %(self.name,self.age.name)
                return
            self.prp.read(f)
            #self.resmanager.addPrp(self.prp)
            f.close()

    
    def unload(self):
        if self.prp!=None:
            print "\/ Unloading page %s %i" %(self.name,self.num)
            #self.prp.resmanager.delPrp(self.prp)
            del self.prp

    
    def save(self):
        if self.prp==None:
            return
        print "@ Saving page %s %i" %(self.name,self.num)
        #f=file(self.getPath(),"wb")
        f=hsStream(self.getPath(),"wb")
        #self.update_page()
        self.prp.write(f)
        f.close()

    
    def update_page(self):
        thenum=self.num
        if self.type in (0x04,0x00):
            flags=KAgeData
        elif (self.type==0x08 and self.num==-2):
            #self.num=0
            thenum=0
            flags=KAgeSDLHook
        elif (self.type==0x08 and self.num==-1):
            #self.num=0
            thenum=0
            flags=KAgeTextures
        else:
            raise RuntimeError, "Cannot save, Incorrect type of page %i,%i" %(self.type,self.num)
        self.prp.setName(self.age.name)
        self.prp.setPageName(self.name)
        self.prp.setPage(self.age.getSeq(),thenum,flags,0)
        #removed update refs, you may want to turn it on
        ### self.prp.setPage(self.seq,thenum,flags,1) <--

    
    def import_all(self):
        print "-> Importing page %s %i" %(self.name,self.num)
        if not alcconfig.I_agree_that_I_am_NOT_going_to_use_CYAN_material_on_other_games_or_projects_without_written_permission_from_CYAN:
            if self.age.getSeq()<100:
                raise "Import is disabled by default, you must agree that you are not going to use Cyan protected material without their permission"
        if self.prp==None:
            self.load()
            if self.prp==None:
                return
        base=self.resmanager.getBasePath()
        agename=self.age.name
        pagename=self.name
        et = base + "/" + agename + "/" + pagename
        try:
            os.mkdir(et)
        except OSError:
            pass
        #import
        if self.type in (0x04,0x00):
            #find sceneNode and import all sceneobjects linked to it
            scn = self.prp.getSceneNode()
            if scn==None:
                raise RuntimeError, "This age does not have a Scene Node?"
            print "importing from scene node %s" %scn.data.Key.name
            #scn.dump()
            scn.data.import_all()
        elif self.num == -2:
            # Check for an AgeSDLHook
            scenobj = self.prp.find(0x01,"AgeSDLHook",0)
            if scenobj != None:
                # Check for the python file mod
                name = str("VeryVerySpecialPythonFileMod")
                pymod = self.prp.find(0xA2,"VeryVerySpecialPythonFileMod",0)
                if pymod != None:
                    print ">>> AgeSDLHook discovered"
                    try:
                        p = self.age.book.book.getProperty("AgeSDLHook")
                        # Note: Blender does not allow setting of
                        # existing Bool properties; it changes it to an int.  So, we
                        # must remove the existing property and replace it.
                        self.age.book.book.removeProperty(p)
                    except:
                        pass
                    self.age.book.book.addProperty("AgeSDLHook",True,'BOOL')
        #raw
        for i in self.prp.idx:
            if i.type in self.ignore:
                continue
            
            a=struct.pack(">H",i.type)
            b=hexlify(a).upper()
            cur = et + "/" + b
            try:
                os.mkdir(cur)
            except OSError:
                pass
            for o in i.objs:
                name = str(o.data.Key.name)
                name = stripIllegalChars(name)
                #f=file(cur + "/" + name + ".raw","wb")
                f=hsStream(cur + "/" + name + ".raw","wb")
                o.write(f)
                f.close()


    def export_all(self,selection=0):
        print "<- Exporting page %s %i" %(self.name,self.num)
        if self.prp==None:
            self.prp=PrpFile(self)
            #set version
            #self.prp.version=self.age.version
            #self.prp.vmin=alcconfig.ver2
            #self.prp.resmanager=self.resmanager
            #self.resmanager.addPrp(self.prp)
            self.update_page()
        out = self.age.base + "/" + self.age.name + "/" + self.name
        SceneNodeRef=UruObjectRef()
        #export
        if self.type in (0x04,0x00):
            #create void sceneNode
            self.prp.createSceneNode()
            self.prp.updateSceneNode()
            SceneNodeRef=self.prp.getSceneNode().data.getRef()
            pass
        elif self.num == -2:
            # Check if the AgeSDLHook property is set to true
            prop = None
            try:
                prop = self.age.book.book.getProperty("AgeSDLHook")
            except:
                # No property - don't do anything
                pass
            if prop != None and bool(prop.getData()) == True:
                # Form a plSceneObject for the hook
                name = str("AgeSDLHook")
                scnobj = self.prp.find(0x01,name,1)
                # Form a plPythonFileMod
                name = str("VeryVerySpecialPythonFileMod")
                pymod = self.prp.find(0xA2,name,1)
                pymod.data.PyFile = Ustr(self.age.name,self.age.version)
                # Give the scene object a ref to the python mod
                scnobj.data.data2.append(pymod.data.getRef())
                print ">>> Added AgeSDLHook scene object and python file mod"
        try:
            f=dircache.listdir(out)
        except OSError:
            f=[]
            pass
        for i in f:
            p=out + "/" + i
            if not isdir(p):
                continue
            b=unhexlify(i)
            a,=struct.unpack(">H",b)
            type=a
            if type in self.ignore:
                continue
            #idx = PrpIndex(prp.page_id,prp.page_type,type)
            idx = self.prp.findidx(type)
            k=dircache.listdir(p)
            for j in k:
                #print p,j
                if j[-4:]!=".raw":
                    continue
                # Get the file size
                f=file(p + "/" + j,"rb")
                stringBuf=StringIO.StringIO()
                stringBuf.write(f.read())
                f.close()
                size=stringBuf.tell()
                #print prp.page_type
                buf=hsStream(p + "/" + j,"rb")
                o = PrpObject(idx,0xFFFF)
                o.read(buf,0,size,0)
                r=idx.findobj(str(o.data.Key.name))
                buf.seek(0)
                r.read(buf,0,size,0)
                r.changePageRaw(o.data.Key.page_id,self.prp.page_id,o.data.Key.page_type,self.prp.page_type)
                #dirty
                ### update textures
                page1 = xPageId()
                page1.setRaw(o.data.Key.page_id,o.data.Key.page_type)
                page2 = xPageId()
                page2.setRaw(self.prp.page_id,self.prp.page_type)
                page1.setFlags(KAgeTextures)
                page2.setFlags(KAgeTextures)
                page1.setNum(-1)
                page2.setNum(-1)
                page1.setType(0x08)
                page2.setType(0x08)
                r.changePageRaw(page1.getRaw(),page2.getRaw(),0x08,0x08)
                ### update built-in
                page1 = xPageId()
                page1.setRaw(o.data.Key.page_id,o.data.Key.page_type)
                page2 = xPageId()
                page2.setRaw(self.prp.page_id,self.prp.page_type)
                page1.setFlags(KAgeSDLHook)
                page2.setFlags(KAgeSDLHook)
                page1.setNum(-2)
                page2.setNum(-2)
                page1.setType(0x08)
                page2.setType(0x08)
                r.changePageRaw(page1.getRaw(),page2.getRaw(),0x08,0x08)
                ### update all other pages
                # this code is a considerable big piece of shit
                # because it does not work with ages with mixed page types
                # well it works but is really ineficient
                for the_type in [0x00,0x10,0x04]:
                    for aaa in self.age.pages:
                        xid=aaa.num
                        if xid<0:
                            continue
                        page1 = xPageId()
                        page1.setRaw(o.data.Key.page_id,o.data.Key.page_type)
                        page2 = xPageId()
                        page2.setRaw(self.prp.page_id,self.prp.page_type)
                        page1.setNum(xid)
                        page2.setNum(xid)
                        r.changePageRaw(page1.getRaw(),page2.getRaw(),the_type,the_type)
                #other tweaks
                type=r.data.Key.object_type
                if type==0x01: #sceneObject
                    r.data.draw=UruObjectRef() #unset reference
                    r.data.scene=SceneNodeRef
                    pass
                elif type==0x16: #drawinterface
                    r.data.reset()
                    pass
                elif type==0x4C: #drawableSpans
                    r.data.scene=SceneNodeRef
                buf.close()
            #prp.idx.append(idx)
        #end raw part
        # First pass: export all lights and colliders, since the objects may 
        # reference them.  Put the other objects in a list.
        object_list=[]
        clickregion_list=[]
        camregion_list=[]
        if selection:
            l = Blender.Object.GetSelected()
        else:
            l = Blender.Object.Get()
        for obj in l:
            obj_type=obj.getType()
            if obj_type=="Lamp":
                try:
                    p=obj.getProperty("page_num")
                    if int(p.getData())!=int(self.num):
                        continue
                except AttributeError:
                    if self.num!=0:
                        continue
                #export the object
                try:
                    p=obj.getProperty("name")
                    name=str(p.getData())
                except AttributeError:
                    name=str(obj.name)
                #print name, obj.data.type, Blender.Lamp.Types["Spot"], Blender.Lamp.Types["Area"]
                if obj.data.type==Blender.Lamp.Types["Spot"]:
                    type=0x57 #spot
                elif obj.data.type==Blender.Lamp.Types["Lamp"]:
                    type=0x56 #omni
                else:
                    type=0x55 #directional
                #find the sceneobject or create it
                scnobj=self.prp.find(0x01,name,1)
                scnobj.data.scene=SceneNodeRef
                #create the lamp info
                for lampref in scnobj.data.data1.vector:
                    if lampref.Key.object_type in [0x55,0x56,0x57]: #SpawnModifier
                        scnobj.data.data1.remove(lampref)
                lamp=self.prp.find(type,name,1)
                lamp.data.parentref=scnobj.data.getRef()
                lamp.data.scenenode=SceneNodeRef
                lamp.data.export_object(obj)
                #print str(mod.data.Key)
                #print str(mod.data.getRef())
                scnobj.data.data1.append(lamp.data.getRef())
                # set the coordinate interface
                coordiface=self.prp.find(0x15,name,1)
                matrix=getMatrix(obj)
                matrix.transpose()
                coordiface.data.matrix.set(matrix)
                coordiface.data.matrix2.set(matrix)
                matrix.invert()
                coordiface.data.matrixinv.set(matrix)
                coordiface.data.matrix2inv.set(matrix)
                coordiface.data.parentref=scnobj.data.getRef()
                scnobj.data.coordinate=coordiface.data.getRef()

                # trylon addition for shadow (experimental)
                # now, see if it should master shadow
                try:
                    p=obj.getProperty("alcshadow")
                    alcshadow=str(p.getData())
                except AttributeError:
                    alcshadow=""
                if (alcshadow == "point"):
                    psmaster = self.prp.find(0xD5,name,1)
                    # set the sceneobject
                    psmaster.sceneobject = scnobj.data.getRef()
                    # now export the object
                    psmaster.export_obj(obj)
                # end shadow addition                        

            elif obj_type=="Mesh":
                try:
                    p=obj.getProperty("page_num")
                    if int(p.getData())!=int(self.num):
                        continue
                except AttributeError:
                    if self.num!=0:
                        continue
                try:
                    p=obj.getProperty("alctype")
                    alctype=str(p.getData())
                except AttributeError:
                    alctype="object"
                try:
                    p=obj.getProperty("alcspecial")
                    alcspecial=str(p.getData())
                except AttributeError:
                    alcspecial="none"

                if (alctype=="region"):
                    try:
                        p=obj.getProperty("prpregion")
                        prpregion=str(p.getData())
                    except AttributeError:
                        prpregion="unknown"
                        
                    if (prpregion == "clickregion"):
                        # click regions should be processed in the first pass
                        # so all click regions are known before we process clickable objects
                        try:
                            p=obj.getProperty("name")
                            name=str(p.getData())
                        except AttributeError:
                            name=str(obj.name)
                        #find the sceneobject or create it
                        scnobj=self.prp.find(0x01,name,1)
                        scnobj.data.scene=SceneNodeRef
                        
                        # Add it to the click region list
                        clickregion_list.append(scnobj)
                        # Determine the min/max extents of the region
                        bvertexs=obj.getBoundBox()
                        bmaxx=bvertexs[0][0]
                        bmaxy=bvertexs[0][1]
                        bmaxz=bvertexs[0][2]
                        bminx=bvertexs[0][0]
                        bminy=bvertexs[0][1]
                        bminz=bvertexs[0][2]
                        for vertex in bvertexs:
                            if vertex[0]>bmaxx:
                                bmaxx=vertex[0]
                            if vertex[0]<bminx:
                                bminx=vertex[0]
                            if vertex[1]>bmaxy:
                                bmaxy=vertex[1]
                            if vertex[1]<bminy:
                                bminy=vertex[1]
                            if vertex[2]>bmaxz:
                                bmaxz=vertex[2]
                            if vertex[2]<bminz:
                                bminz=vertex[2]
                        print "Click region extents (max X,Y,Z) (min X,Y,Z):"
                        print bmaxx,bmaxy,bmaxz,bminx,bminy,bminz
                        scnobj.vmin=Vertex(bminx,bminy,bminz)
                        scnobj.vmax=Vertex(bmaxx,bmaxy,bmaxz)

                        # col_type will default to 3
                        col_type = self.getStrIntPropertyOrDefault(obj,"col_type",3)

                        isdynamic=1 #clickregions are always dynamic (i.e. in need of coordinate interface)
                        
                        # set the simulation interface.
                        self.setSimInterface(scnobj,name,col_type,SceneNodeRef,obj,isdynamic)
    
                        #(re)Set default values, unless the values are defined
                        simi = simi=self.prp.findref(scnobj.data.simulation)
                        phys = simi=self.prp.findref(simi.data.physical)
                        
                        phys.data.mass  = self.getFloatPropertyOrDefault(obj,"mass",1.0)
                        phys.data.rc    = self.getFloatPropertyOrDefault(obj,"rc",0.0)
                        phys.data.el    = self.getFloatPropertyOrDefault(obj,"el",0.0)

                        phys.data.type      = self.getHexPropertyOrDefault(obj,"col_flags0",2,0x0400)
                        phys.data.flags1    = self.getHexPropertyOrDefault(obj,"col_flags1",4,0x08000000)
                        phys.data.flags2    = self.getHexPropertyOrDefault(obj,"col_flags2",4,0x00000000)
                        phys.data.flags3    = self.getHexPropertyOrDefault(obj,"col_flags3",2,0x0000)
                        phys.data.flags4    = self.getHexPropertyOrDefault(obj,"col_flags4",4,0x00000004)
                        phys.data.uk3       = self.getHexPropertyOrDefault(obj,"col_flags5",4,0x00000000)
    
                        # now set the coordinate interface
                        
                        self.setCoordInterface(scnobj,name,isdynamic,obj)
                    
                    elif(prpregion == "camerargn"):
                        # camera regions should also be processed in the first pass
                        # so all click regions are known before we process camera objects
                        try:
                            p=obj.getProperty("name")
                            name=str(p.getData())
                        except AttributeError:
                            name=str(obj.name)
                        #find the sceneobject or create it
                        scnobj=self.prp.find(0x01,name,1)
                        scnobj.data.scene=SceneNodeRef
                        
                        # col_type will default to 3
                        col_type = self.getStrIntPropertyOrDefault(obj,"col_type",3)

                        isdynamic=0 #here is a little problem with camera regions not getting
                                    #transformed, so set it to nondynamic for now
                        
                        # set the simulation interface.
                        self.setSimInterface(scnobj,name,col_type,SceneNodeRef,obj,isdynamic)
                        self.setCoordInterface(scnobj,name,isdynamic,obj)
    
                        #(re)Set default values, unless the values are defined
                        simi = simi=self.prp.findref(scnobj.data.simulation)
                        phys = simi=self.prp.findref(simi.data.physical)
                        
                        phys.data.mass  = self.getFloatPropertyOrDefault(obj,"mass",1.0)
                        phys.data.rc    = self.getFloatPropertyOrDefault(obj,"rc",0.0)
                        phys.data.el    = self.getFloatPropertyOrDefault(obj,"el",0.0)

                        phys.data.type      = self.getHexPropertyOrDefault(obj,"col_flags0",2,0x0400)
                        phys.data.flags1    = self.getHexPropertyOrDefault(obj,"col_flags1",4,0x08000000)
                        phys.data.flags2    = self.getHexPropertyOrDefault(obj,"col_flags2",4,0x00000000)
                        phys.data.flags3    = self.getHexPropertyOrDefault(obj,"col_flags3",2,0x0000)
                        phys.data.flags4    = self.getHexPropertyOrDefault(obj,"col_flags4",4,0x00000004)
                        phys.data.uk3       = self.getHexPropertyOrDefault(obj,"col_flags5",4,0x00000000)
    
                        # read in the camera
                        scnobj.cameralink = getTextPropertyOrDefault(obj,"camera",None)
                        scnobj.blendobj = obj
                        print "Found Camera Region '%s', Linking to Camera '%s'" % (name,scnobj.cameralink)
    
                        # Add it to the click region list
                        camregion_list.append(scnobj)
                        
    
                    else: # not a click or camera region
                        object_list.append(obj)
                else: # Not a click region - leave it for later
                    object_list.append(obj)
            else:
                object_list.append(obj)
        #Second pass: export the other objects
        for obj in object_list:
            obj_type=obj.getType()
            if obj_type=="Mesh":
                try:
                    p=obj.getProperty("page")
                    continue
                except AttributeError:
                    pass
                try:
                    p=obj.getProperty("book")
                    continue
                except AttributeError:
                    pass
                try:
                    p=obj.getProperty("page_num")
                    if int(p.getData())!=int(self.num):
                        continue
                except AttributeError:
                    if self.num!=0:
                        continue
                #export the object
                try:
                    p=obj.getProperty("name")
                    name=str(p.getData())
                except AttributeError:
                    name=str(obj.name)
                try:
                    p=obj.getProperty("alctype")
                    alctype=str(p.getData())
                except AttributeError:
                    alctype="object"
                try:
                    p=obj.getProperty("mass")
                    mass=float(p.getData())
                except AttributeError:
                    mass=0.0
                if mass!=0:
                    isdynamic=1
                else:
                    isdynamic=0
                if alctype=="object" or alctype=="sprite": #Object or sprite export
                    #find the sceneobject or create it
                    scnobj=self.prp.find(0x01,name,1)
                    scnobj.data.scene=SceneNodeRef

                    #Determine if we want to generate collision information for this object
                    #
                    col_type = self.getStrIntPropertyOrDefault(obj,"col_type",0)

                    #
                    # Check for sprite
                    #
                    
                    if(alctype == "sprite"):
                        isdynamic = 1 # viewfacemod objects are dynamic too!
                        vfm = self.prp.find(0x40,name + "_VFM",1)
                        vfm.data.export_obj(obj,self.prp)
                        scnobj.data.data2.append(vfm.data.getRef())

                    #
                    # Check for clickable objects
                    #

                    clickfile=self.getTextPropertyOrDefault(obj,"clickfile",None)
                    if(clickfile != None):
                        isdynamic = 1 # set the object to dynamic
                        
                        # if col_type is not set (0) set it to 4
                        if (col_type == 0):
                            col_type = 4
                        
                        # Locate a click region that encompasses this object
                        foundClickRegion = None
                        for clickregion in clickregion_list:
                            objX = obj.matrixWorld[3][0]
                            objY = obj.matrixWorld[3][1]
                            objZ = obj.matrixWorld[3][2]
                            print "Clickable object position: (%f,%f,%f)" %(objX,objY,objZ)
                            if objX >= clickregion.vmin.x and objX <= clickregion.vmax.x \
                              and objY >= clickregion.vmin.y and objY <= clickregion.vmax.y \
                              and objZ >= clickregion.vmin.z and objZ <= clickregion.vmax.z:
                                foundClickRegion = clickregion
                                break
                        if foundClickRegion == None:
                            raise RuntimeError, "Clickable object %s is not inside any click region" % name

                        # Create the plPythonFileMod
                        newname = str("cPyth") + name
                        pythMod = self.prp.find(0x00A2,newname,1)
                        pythMod.data.PyFile = Ustr(clickfile,self.age.version)
                        pyArg1 = plPyArg()
                        pyArg1.idx = 0x00000001
                        pyArg1.type = 0x00000007
                        pythMod.data.PyArgs.append(pyArg1)
                        pyArg2 = plPyArg()
                        pyArg2.idx = 0x00000002
                        pyArg2.type = 0x00000004
                        pyArg2.data = str32(name,0)
                        pythMod.data.PyArgs.append(pyArg2)
                        # Create the plPickingDetector
                        newname = str("cClk") + name
                        pickDetect = self.prp.find(0x002B,newname,1)
                        # Create the plObjectInBoxConditionalObject
                        objInBoxCO = self.prp.find(0x0037,newname,1)
                        objInBoxCO.data.i10 = 0x01
                        # Create the plActivatorConditionalObject
                        actCO = self.prp.find(0x0032,newname,1)
                        actCO.data.condobjs.append(pickDetect.data.getRef())
                        # Create the plFacingConditionalObject 
                        faceCO = self.prp.find(0x003E,newname,1)
                        faceCO.data.i10 = 0x01
                        # Create plLogicModifier
                        logicMod = self.prp.find(0x002D,newname,1)
                        logicMod.data.Notify.data.Modifiers.append(pythMod.data.getRef())
                        logicMod.data.DWords.append(0x00000001)
                        logicMod.data.Conditionals.append(objInBoxCO.data.getRef())
                        logicMod.data.Conditionals.append(actCO.data.getRef())
                        logicMod.data.Conditionals.append(faceCO.data.getRef())
                        logicMod.data.i98 = 0x00000005
                        # Create the plInterfaceInfoModifier (same name as object)
                        intInfoMod = self.prp.find(0x00CB,name,1)
                        # Add two references to the same logic modifier
                        intInfoMod.data.objects.append(logicMod.data.getRef())
                        intInfoMod.data.objects.append(logicMod.data.getRef())
                        # Create the plObjectInVolumeDetector 
                        objInVol = self.prp.find(0x007B,newname,1)
                        objInVol.data.logic.append(logicMod.data.getRef())
                        objInVol.data.c70 = 0x04
                        # Hook up the remaining references
                        pyArg1.data = logicMod.data.getRef()
                        pickDetect.data.logic.append(logicMod.data.getRef())
                        clickregion.data.data2.append(objInVol.data.getRef())
                        scnobj.data.data2.append(logicMod.data.getRef())
                        scnobj.data.data2.append(pythMod.data.getRef())
                        scnobj.data.data2.append(pickDetect.data.getRef())
                        scnobj.data.data2.append(intInfoMod.data.getRef())


                    #get the draw interface
                    drawiref=scnobj.data.draw
                    if drawiref.isNull():
                        drawi=self.prp.find(0x16,name,1)
                        scnobj.data.draw=drawi.data.getRef()
                    else:
                        drawi=self.prp.findref(drawiref)
                    if drawi==None:
                        raise "WARNING: %s - %s not found!" %(str(scnobj.data.Key),str(drawiref))
                        continue
                    # update draw interface
                    drawi.data.parentref=scnobj.data.getRef()
                    # Before exporting the spans, determine whether
                    # the material requires blending; this will affect
                    # the name of the spans
                    BlendFlags=0x00000000
                    ZBias=0
                    
                    # also count the number of texture layers
                    texLayerCount = 0
                    if len(obj.data.materials)>0:
                        materialName = obj.data.materials[0].name
                        pmat=self.prp.find(0x07,materialName,1)

                        # parse throug hte texture list, and see if we can obtain an Environment map
                        mtex_list = obj.data.materials[0].getTextures()
                        for mtex in mtex_list:
                            # see if the texture list is not empty
                            if(mtex != None): 
        
                                # get the associated texture
                                tex = mtex.tex
                                
                                #see if it's an image
                                if(tex.type == Blender.Texture.Types.IMAGE ):
                                    #add this texture
                                    layer = pmat.data.addTextureLayer(tex.getImage(),obj.data.materials[0],mtex)
                                    if (layer.data.hasAlpha() and BlendFlags == 0x00000000):
                                        # Not sure what these flags mean yet
                                        BlendFlags=0x20000000
                                    pass
                                    texLayerCount += 1
                                # now see if its a cubicenvironmap
                                elif(tex.type == Blender.Texture.Types.ENVMAP):
                                    print "    Found Environment map!"
                                    # now see if we gan retrieve the object
                                    envmap = tex.getImage()
                                    
                                    if(envmap != None):
                                        # we can probably make an environment map, try it....
                                        layer = pmat.data.addCubicMap(envmap,obj.data.materials[0],mtex) 
                                        texLayerCount += 1
                                        # CubicEnvironment maps are often in this span type:
                                        BlendFlags=0x40000000
                                        ZBias = 0xa
                                    else:
                                        # we have an environment map, but it is not a loaded file
                                        raise "PLEASE set your EnvironMap settings for %s to \"Load\" and select a file!" % obj.name

                                elif(tex.type == Blender.Texture.Types.NONE):
                                    # add this layer as a non-texture layer
                                    layer = pmat.data.addTextureLayer(None,obj.data.materials[0],mtex)
                       
                       
                        # if we have no viable texture layers set, try taking the UV texture layer
                        # (Compatibility with old-style materials)
                        if(pmat.data.layerCount() == 0):
                            meshName = obj.data.name
                            mesh = Blender.NMesh.GetRaw(meshName)
                            texture_img=None
                            for f in mesh.faces:
                                if f.image!=None:
                                    texture_img=f.image
                                    break
                            if(texture_img != None):
                                #add the texture if it is there
                                layer = pmat.data.addTextureLayer(texture_img,obj.data.materials[0],None)
                                # Check if the layer has the alpha blend flag set
                                if (layer.data.hasAlpha()):
                                    # Not sure what these flags mean yet
                                    BlendFlags=0x20000000

                                texLayerCount += 1
                        
                        
                        # ensure that there is a basic layer (this function adds one if it's not available)
                        pmat.data.ensureBasicMaterial(obj.data.materials[0])


                    ### export the span data
                    #find or create the drawablespans
                    ## set some flags
                    
                    if BlendFlags==0:
                        sfx="Spans"
                    else:
                        sfx="BlendSpans"
                    one="%08x" % BlendFlags
                    two="%x" % ZBias
                    thename=str(self.prp.name) + "_District_" + str(self.prp.page) + "_" + one + "_" + two + sfx
                    drawspans=self.prp.find(0x4C,thename,1)
                    drawspans.data.scene=SceneNodeRef
                    drawspans.data.dsiD=BlendFlags
                    drawspans.data.dsNumber=ZBias
                    #export the object
                    setnum=drawspans.data.export_object(obj,isdynamic,texLayerCount)
                    drawi.data.addSpanSet(setnum,drawspans.data.getRef())


                    # Set the Simulation interface
                    self.setSimInterface(scnobj,name,col_type,SceneNodeRef,obj,isdynamic)

                    if(clickfile != None):
                        # set the physical properties correct - but let them get overridden by any set properties

                        simi = simi=self.prp.findref(scnobj.data.simulation)
                        phys = simi=self.prp.findref(simi.data.physical)

                        phys.data.mass  = self.getFloatPropertyOrDefault(obj,"mass",1.0)
                        phys.data.rc    = self.getFloatPropertyOrDefault(obj,"rc",0.5)
                        phys.data.el    = self.getFloatPropertyOrDefault(obj,"el",0.0)

                        phys.data.type      = self.getHexPropertyOrDefault(obj,"col_flags0",2,0x0400)
                        phys.data.flags1    = self.getHexPropertyOrDefault(obj,"col_flags1",4,0x00000000)
                        phys.data.flags2    = self.getHexPropertyOrDefault(obj,"col_flags2",4,0x00020000)
                        phys.data.flags3    = self.getHexPropertyOrDefault(obj,"col_flags3",2,0x0000)
                        phys.data.flags4    = self.getHexPropertyOrDefault(obj,"col_flags4",4,0x00000004)
                        phys.data.uk3       = self.getHexPropertyOrDefault(obj,"col_flags5",4,0x00000002)

                    self.setCoordInterface(scnobj,name,isdynamic,obj)
                    
                elif alctype=="collider": #Physical export
                    print "Object %s is a Collider - Processing" % name
                    #find the sceneobject or create it
                    scnobj=self.prp.find(0x01,name,1)
                    scnobj.data.scene=SceneNodeRef
                    try:
                        p=obj.getProperty("col_type")
                        col_type=int(p.getData())
                    except AttributeError:
                        col_type=3

                    self.setSimInterface(scnobj,name,col_type,SceneNodeRef,obj)

                elif alctype=="region": #region export
                    print "Object %s is a Region - Processing" % name
                    prpregion=self.getTextPropertyOrDefault(obj,"prpregion","none")

                    #find the sceneobject or create it
                    scnobj=self.prp.find(0x01,name,1)
                    scnobj.data.scene=SceneNodeRef

                    # handle any special col_type settings here:
                    if(prpregion=="swimregion"):
                        col_type = self.getStrIntPropertyOrDefault(obj,"col_type",1)
                    elif (prpregion == "swimplainsfc") or (prpregion == "swimccursfc") or (prpregion == "swimscursfc"):
                        col_type = self.getStrIntPropertyOrDefault(obj,"col_type",4)
                    else:
                        col_type = self.getStrIntPropertyOrDefault(obj,"col_type",3)

                    isdynamic = 1   #regions are by default dynamic - except when explicitly defined not
                    if(prpregion == "footsteprgn"):

                        # find the "footstepsound" property
                        footstepsound = getHexPropertyOrDefault(obj,"footstepsound",2,int(0))
                        footstepsound = getIntPropertyOrDefault(obj,"footstepsound",footstepsound)
                        if(footstepsound > 255): # make sure that the calue doesn't rise out of maximum length
                            footstepsound = 255
                        print "Processing Footstep region %s - Footstep sound is %d" % (name,footstepsound)
                            
                                    # default to shallow water,
                                    # so they know something is amiss
                        
                        # find the respmodobject or create it
                        # use the objects name for it
                        ftresp=self.prp.find(0x007C,name,1)
                        print  "# On object ", name
                        # make the feetrespondergroup
                        ftgroup = respmodGroup()
                        ftresp.data.respmodGroup.append(ftgroup)
                        ftaction1 = respmodAction(ftresp.data.getRef())
                        ftgroup.actions.append(ftaction1)
                        ftaction1.flags = 0x00000850
                        ftmessage = PrpMessage(0x038E,self.age.version) # plArmatureEffectStateMsg()
                        ftaction1.message = ftmessage
                        ftaction1.ActionSubType = ftmessage.msgtype
                        ftmessage.data.groundtype = footstepsound
                        # # make the enter objects
                        # make the VolumeSensorConditionalObject
                        vsensor_enter = self.prp.find(0x00A6,name + "_Enter",1)
                        vsensor_enter.data.direction = vsensor_enter.data.enter
                        vsensor_enter.data.export_obj(obj,self.prp)
                        # make the LogicModifier
                        logicmod_enter = self.prp.find(0x002D,name + "_Enter",1)
                        logicmod_enter.data.DWords.append(0x00000040)
                        logicmod_enter.data.Notify.data.Modifiers.append(ftresp.data.getRef())
                        logicmod_enter.data.Conditionals.append(vsensor_enter.data.getRef())
                        objvdetect_enter = self.prp.find(0x007B,name + "_Enter",1)
                        objvdetect_enter.data.logic.append(vsensor_enter.data.getRef())
                        objvdetect_enter.data.logic.append(logicmod_enter.data.getRef())
                        # # make the exit objects
                        # make the VolumeSensorConditionalObject
                        vsensor_exit = self.prp.find(0x00A6,name + "_Exit",1)
                        vsensor_exit.data.direction = vsensor_exit.data.leave
                        vsensor_exit.data.export_obj(obj,self.prp)
                        # make the LogicModifier
                        logicmod_exit = self.prp.find(0x002D,name + "_Exit",1)
                        logicmod_exit.data.DWords.append(0x00000040)
                        logicmod_exit.data.Notify.data.Modifiers.append(ftresp.data.getRef())
                        logicmod_exit.data.Conditionals.append(vsensor_exit.data.getRef())
                        objvdetect_exit = self.prp.find(0x007B,name + "_Exit",1)
                        objvdetect_exit.data.logic.append(vsensor_exit.data.getRef())
                        objvdetect_exit.data.logic.append(logicmod_exit.data.getRef())
                        # # make the interfaceinfomodifier
                        iinfomod = self.prp.find(0x00CB,name,1)
                        iinfomod.data.objects.append(logicmod_enter.data.getRef())
                        iinfomod.data.objects.append(logicmod_exit.data.getRef())
                        # # finally link the
                        # - ResponderModifier 007C 
                        # - LogicModifier 002D "[Regionname]_Enter"       
                        # - LogicModifier 002D "[Regionname]_Exit
                        # - ObjectInVolumeDetector "[Regionname]_Enter"
                        # - ObjectInVolumeDetector "[Regionname]_Exit"
                        # - InterfaceInfoModifier "[Regionname]"
                        # # to the region sceneobject
                        scnobj.data.data2.append(ftresp.data.getRef())
                        scnobj.data.data2.append(logicmod_enter.data.getRef())
                        scnobj.data.data2.append(logicmod_exit.data.getRef())
                        scnobj.data.data2.append(objvdetect_enter.data.getRef())
                        scnobj.data.data2.append(objvdetect_exit.data.getRef())
                        scnobj.data.data2.append(iinfomod.data.getRef())
                    elif(prpregion == "paniclnkrgn"):
                        paniclink = self.prp.find(0x00FC,"PanicLinkReg",1)
                        scnobj.data.data2.append(paniclink.data.getRef())
                    elif(prpregion == "swimrgn"):
                        isdynamic = 0   # Swim Regions are NOT Dynamic
                        swimrgn = self.prp.find(0x012E,name + "_swimrgn",1)
                        swimrgn.parentref = scnobj.data.getRef()
                        swimrgn.parentref2 = scnobj.data.getRef()
                        swimrgn.myself = swimrgn.data.getRef()
                        swimrgn.myself2 = swimrgn.data.getRef()
                        scnobj.data.data2.append(swimrgn.data.getRef())
                    elif(prpregion == "swimplainsfc"):
                        isdynamic = 0   # Swim Surfaces are NOT Dynamic
                        swimsfcrgn = self.prp.find(0x0133,name + "_swimrgnif",1)
                        swimsfcrgn.data.parentref = scnobj.data.getRef()
                        swimsfcrgn.data.export_obj(obj)
                        scnobj.data.data1.append(swimsfcrgn.data.getRef())
                    elif(prpregion == "swimscursfc"): # straight Current // UNFINISHED
                                                 # needs Point object - probably for direction (coord intf only sceneobject)
                        isdynamic = 0   # Swim Surfaces are NOT Dynamic
                        swimsfcrgn = self.prp.find(0x0136,name + "_swimstrcrgn",1)
                        swimsfcrgn.data.parentref = scnobj.data.getRef()
                        swimsfcrgn.data.export_obj(obj,self.prp)
                        scnobj.data.data1.append(swimsfcrgn.data.getRef())
                    elif(prpregion == "swimccursfc"): # circular Current //UNFINISHED
                                                 # needs Point object - probably for direction (coord intf only sceneobject)
                        isdynamic = 0   # Swim Surfaces are NOT Dynamic
                        swimsfcrgn = self.prp.find(0x0134,name + "_swimcircrgn",1)
                        swimsfcrgn.data.parentref = scnobj.data.getRef()
                        swimsfcrgn.data.export_obj(obj,self.prp)
                        scnobj.data.data1.append(swimsfcrgn.data.getRef())
                    elif(prpregion == "climbregion"):
                        print "Exporting CLIMBREGION"
                        climbRegion = self.prp.find(0x00B2,name,1)
                        if climbRegion != None:
                            print "On object", name
                            climbRegion.data.parentref = scnobj.data.getRef()
                            climbRegion.data.export_obj(obj,self.prp)
                            scnobj.data.data2.append(climbRegion.data.getRef())
                        else:
                            print "Could not create a CLIMBREGION"
                        print "Finished with CLIMBREGION"
                    
                    self.setSimInterface(scnobj,name,col_type,SceneNodeRef,obj,isdynamic)

                    #Set default values, unless the values are defined
                    simi = simi=self.prp.findref(scnobj.data.simulation)
                    phys = simi=self.prp.findref(simi.data.physical)
            
                    if (prpregion == "swimrgn"):
                        phys.data.mass  = self.getFloatPropertyOrDefault(obj,"mass",0.0)
                        phys.data.rc    = self.getFloatPropertyOrDefault(obj,"rc",0.0)
                        phys.data.el    = self.getFloatPropertyOrDefault(obj,"el",0.0)

                        phys.data.type      = self.getHexPropertyOrDefault(obj,"col_flags0",2,0x0000)
                        phys.data.flags1    = self.getHexPropertyOrDefault(obj,"col_flags1",4,0x00020000)
                        phys.data.flags2    = self.getHexPropertyOrDefault(obj,"col_flags2",4,0x00000000)
                        phys.data.flags3    = self.getHexPropertyOrDefault(obj,"col_flags3",2,0x0000)
                        phys.data.flags4    = self.getHexPropertyOrDefault(obj,"col_flags4",4,0x00000000)
                        phys.data.uk3       = self.getHexPropertyOrDefault(obj,"col_flags5",4,0x00000000)
                    elif (prpregion == "swimplainsfc") or (prpregion == "swimccursfc") or (prpregion == "swimscursfc"):
                        phys.data.mass  = self.getFloatPropertyOrDefault(obj,"mass",0.0)
                        phys.data.rc    = self.getFloatPropertyOrDefault(obj,"rc",0.0)
                        phys.data.el    = self.getFloatPropertyOrDefault(obj,"el",0.0)

                        phys.data.type      = self.getHexPropertyOrDefault(obj,"col_flags0",2,0x0000)
                        phys.data.flags1    = self.getHexPropertyOrDefault(obj,"col_flags1",4,0x00000000)
                        phys.data.flags2    = self.getHexPropertyOrDefault(obj,"col_flags2",4,0x00000000)
                        phys.data.flags3    = self.getHexPropertyOrDefault(obj,"col_flags3",2,0x0000)
                        phys.data.flags4    = self.getHexPropertyOrDefault(obj,"col_flags4",4,0x00000000)
                        phys.data.uk3       = self.getHexPropertyOrDefault(obj,"col_flags5",4,0x00000080)
                    elif (prpregion != "unknown") and (prpregion):
                        phys.data.mass  = self.getFloatPropertyOrDefault(obj,"mass",1.0)
                        phys.data.rc    = self.getFloatPropertyOrDefault(obj,"rc",0.0)
                        phys.data.el    = self.getFloatPropertyOrDefault(obj,"el",0.0)

                        phys.data.type      = self.getHexPropertyOrDefault(obj,"col_flags0",2,0x0400)
                        phys.data.flags1    = self.getHexPropertyOrDefault(obj,"col_flags1",4,0x08000000)
                        phys.data.flags2    = self.getHexPropertyOrDefault(obj,"col_flags2",4,0x00000000)
                        phys.data.flags3    = self.getHexPropertyOrDefault(obj,"col_flags3",2,0x0000)
                        phys.data.flags4    = self.getHexPropertyOrDefault(obj,"col_flags4",4,0x00000004)
                        phys.data.uk3       = self.getHexPropertyOrDefault(obj,"col_flags5",4,0x00000000)
                
                                        
                    self.setCoordInterface(scnobj,name,isdynamic,obj)
                        
                ######################
                # Point type support
                ######################
                elif alctype=="point": 
                    print "Processing Mesh point object %s" % name
                    #find the sceneobject or create it
                    scnobj=self.prp.find(0x01,name,1)
                    scnobj.data.scene=SceneNodeRef
                    # get the coordinates
                    setCoordInterface(scnobj,name,1,obj)
#                    coori=self.prp.findref(scnobj.data.coordinate)
#                    if coori==None:
#                        coori=self.prp.find(0x15,name,1)
#                    scnobj.data.coordinate=coori.data.getRef()
#                    coori.data.parentref=scnobj.data.getRef()
#                    coori.data.export_matrices(obj)
            elif obj_type=="Camera":
                try:
                    p=obj.getProperty("page")
                    continue
                except AttributeError:
                    pass
                try:
                    p=obj.getProperty("book")
                    continue
                except AttributeError:
                    pass
                try:
                    p=obj.getProperty("page_num")
                    if int(p.getData())!=int(self.num):
                        continue
                except AttributeError:
                    if self.num!=0:
                        continue
                #export the object
                try:
                    p=obj.getProperty("name")
                    name=str(p.getData())
                except AttributeError:
                    name=str(obj.name)
                try:
                    p=obj.getProperty("alctype")
                    alctype=str(p.getData())
                except AttributeError:
                    alctype="camera"

                if(alctype == "camera"):
                    print "Handling Camera %s"% name
                    #find the sceneobject or create it
                    scnobj=self.prp.find(0x01,name,1)
                    scnobj.data.scene=SceneNodeRef
                    # get the coordinates
                    coori=self.prp.findref(scnobj.data.coordinate)
                    if coori==None:
                        coori=self.prp.find(0x15,name,1)
                    scnobj.data.coordinate=coori.data.getRef()
                    coori.data.parentref=scnobj.data.getRef()
                    coori.data.export_matrices(obj)

                    # find or create the camera modifier
                    cameramod = self.prp.find(0x009B,name,1)
                    cambraintype = getTextPropertyOrDefault(obj,"cambrain","fixed")

                    # determine the camera brain
                    if(cambraintype == "fixed"):
                        # fixed camera brain
                        cambrain = self.prp.find(0x009F,name,1)
                    elif(cambraintype == "circle"):
                        # Circle camera brain
                        cambrain = self.prp.find(0x00C2,name,1)
                    elif(cambraintype == "avatar"):
                        # Avatar camera brain
                        cambrain = self.prp.find(0x009E,name,1)
                    elif(cambraintype == "firstperson"):
                        # First Person Camera Brain
                        cambrain = self.prp.find(0x00B3,name,1)
                    elif(cambraintype == "pinned"):
                        # 23 sep 06: support for pinned camera's is not yet working correctly
                        # they act like normal fixed cameras
                        
                        # first set the camera brian to fixed
                        cambrain = self.prp.find(0x009F,name,1)
                        
                        # we must pin the camera's rotation by making an object
                        # We should pin at iat the camera's maximum clip_end
                        # get the matrices
                        camLocalToWorld=hsMatrix44()
                        m=getMatrix(obj)
                        m.transpose()
                        camLocalToWorld.set(m)
                
                        camWorldToLocal=hsMatrix44()
                        m=getMatrix(obj)
                        m.invert() 
                        m.transpose()
                        camWorldToLocal.set(m)
                
                        clip_end = obj.data.getClipEnd()
                        
                        # make an object that is at the specified coordinates
                        
                        vtrack = Vertex(0,0,0 - clip_end) # camera points to local -Z
                        vtrack.transform(camLocalToWorld)
                        trackpoint = Blender.Object.New("Empty",name+".target")
                        trackpoint.setLocation(vtrack.x,vtrack.y,vtrack.z)
                        
                        
                        # make a copy of the tracked objects location, and assign a simple camera brain to it
                        trackscnobj=self.prp.find(0x01,name + ".target",1)
                        trackscnobj.data.scene=SceneNodeRef
                        trackcoori=self.prp.findref(trackscnobj.data.coordinate)
                        if trackcoori==None:
                            trackcoori=self.prp.find(0x15,name + ".target",1)

                        trackscnobj.data.coordinate=trackcoori.data.getRef()
                        trackcoori.data.parentref=trackscnobj.data.getRef()
                        trackcoori.data.export_matrices(trackpoint)
                        
                        trackcammod = self.prp.find(0x009B,name + ".target",1)
                        trackcambrain = self.prp.find(0x0099,name + ".target",1)
                        
                        trackcammod.data.cambrain = trackcambrain.data.getRef()
                        trackcambrain.data.X1 = 0
                        trackcambrain.data.Y1 = 0
                        trackcambrain.data.Z1 = 0
                        trackcambrain.data.DWords = []
                        
                        trackscnobj.data.data2.append(trackcammod.data.getRef())
                        
                        # link the camera modifier to the brain.
                        cambrain.data.target = trackcammod.data.getRef()
                    else:
                        # simple and default camera brain
                        cambrain = self.prp.find(0x0099,name,1)
                   
                    # now export the camera modifier
                    cameramod.data.cambrain = cambrain.data.getRef()
                    cameramod.data.export_obj(obj,self.prp)
                    cambrain.data.export_obj(obj,self.prp)
                    
                    # now link the camera modifier to the object (twice, since that appears to be what cyan does
                    scnobj.data.data2.append(cameramod.data.getRef())
                    scnobj.data.data2.append(cameramod.data.getRef())
                    
                    # Now locate a cameraregion that links to this camera
                    foundCamRegion = 0
                    for camregion in camregion_list:
                        # see what camera regions link to this camera
                        if(camregion.cameralink == name):
                            print "Linking Region %s to Camera %s" % (str(camregion.data.Key.name),name)
                            # now create the camera Region Detector
                            camregdetect = self.prp.find(0x006F,name,1)
                            camregdetect.data.camera = scnobj.data.getRef()
                            # find or create the parent object
                            #find the sceneobject or create it
                            camregdetect.data.export_obj(camregion.blendobj,self.prp)
                            camregion.data.scene=SceneNodeRef
                            camregion.data.data2.append(camregdetect.data.getRef())
                            foundCamRegion += 1
                    if(foundCamRegion == 0):
                        print "WARNING: Camera has NO regions associated"
                    else:
                        print "Camera has %d regions associated" % foundCamRegion

            elif obj_type=="Empty":
                try:
                    p=obj.getProperty("page_num")
                    if int(p.getData())!=int(self.num):
                        continue
                except AttributeError:
                    if self.num!=0:
                        continue
                #export the object
                name = getTextPropertyOrDefault(obj,"name",str(obj.name))
                alctype = getTextPropertyOrDefault(obj,"alctype","point")

                if alctype=="swpoint": #A spawnPoint
                    #find the sceneobject or create it
                    scnobj=self.prp.find(0x01,name,1)
                    scnobj.data.scene=SceneNodeRef
                    #create the spawn modifier
                    found=0
                    for mod in scnobj.data.data2.vector:
                        if mod.Key.object_type==0x3D: #SpawnModifier
                            found=1
                            break
                    if not found:
                        mod=self.prp.find(0x3D,name,1)
                        #print str(mod.data.Key)
                        #print str(mod.data.getRef())
                        scnobj.data.data2.append(mod.data.getRef())
                    # set the coordinate interface
                    coordiface=self.prp.find(0x15,name,1)
                    matrix=getMatrix(obj)
                    matrix.transpose()
                    coordiface.data.matrix.set(matrix)
                    coordiface.data.matrix2.set(matrix)
                    matrix.invert()
                    coordiface.data.matrixinv.set(matrix)
                    coordiface.data.matrix2inv.set(matrix)
                    coordiface.data.parentref=scnobj.data.getRef() 
                    scnobj.data.coordinate=coordiface.data.getRef()
                elif alctype=="point":
                    print "Processing Empty point object %s" % name
                    #find the sceneobject or create it
                    scnobj=self.prp.find(0x01,name,1)
                    scnobj.data.scene=SceneNodeRef
                    # get the coordinates
                    self.setCoordInterface(scnobj,name,1,obj)
                    
#                    coori=self.prp.findref(scnobj.data.coordinate)
#                    if coori==None:
#                        coori=self.prp.find(0x15,name,1)
#                    scnobj.data.coordinate=coori.data.getRef()
#                    coori.data.parentref=scnobj.data.getRef()
#                    coori.data.export_matrices(obj)
                    
                elif alctype=="pymod": #A PythonFileMod
                    try:
                        p = obj.getData("PyFile")
                        name = str(p.getData())
                    except:
                        raise "You have an unnamed PyMod. Please look into it."
                    found=0
                    for mod in scnobj.data.data2.vector:
                        if mod.Key.object_type==0xA2: #PythonFileMod
                            found=1
                            break
                    if not found:
                        mod=self.prp.find(0xA2,name,1)
                        #print str(mod.data.Key)
                        #print str(mod.data.getRef())
                    for i in range(999): #You can have 999 args perfile... Not too shabby
                        try:
                            p = obj.getProperty("PyArg" + i)
                            d = p.getData()
                        except:
                            break #We're done here!
                        mod.data.addArg(i,d)
                ### End export code
        if self.type in (0x04,0x00):
            #update sceneNode
            self.prp.updateSceneNode()
            pass
        #end

    def getFloatPropertyOrDefault(self,obj,propertyname,defaultvalue):
        try:
            p=obj.getProperty(propertyname)
            var=float(p.getData())
        except AttributeError:
            var=defaultvalue
        return var

    def getHexPropertyOrDefault(self,obj,propertyname,bytesize,defaultvalue):
        try:
            p=obj.getProperty(propertyname)
            var=alcAscii2Hex(str(p.getData()),bytesize)
        except AttributeError:
            var=defaultvalue
            pass
        return var

    def getTextPropertyOrDefault(self,obj,propertyname,defaultvalue):
        try:
            p=obj.getProperty(propertyname)
            var=str(p.getData())
        except AttributeError:
            var=defaultvalue
            pass
        return var

    def getStrIntPropertyOrDefault(self,obj,propertyname,defaultvalue):
        try:
            p=obj.getProperty(propertyname)
            var=int(p.getData())
        except AttributeError:
            var=defaultvalue
            pass
        return var
        

    def setSimInterface(self,scnobj,name,col_type,SceneNodeRef,obj,isdynamic=0):
        if col_type == 0:
            return
        #set the simulation interface
        simiref=scnobj.data.simulation
        simi=self.prp.findref(simiref)
        if simi==None:
            simi=self.prp.find(0x1C,name,1)
        scnobj.data.simulation=simi.data.getRef()
        simi.data.parentref=scnobj.data.getRef()
        physical=self.prp.findref(simi.data.physical)
        if physical==None:
            physical=self.prp.find(0x3F,name,1)
        simi.data.physical=physical.data.getRef()
        physical.data.scene=SceneNodeRef
        physical.data.sceneobject=scnobj.data.getRef()
        physical.data.format=int(col_type)
        
        physical.data.export_object(obj,isdynamic)

    def setCoordInterface(self,scnobj,name,isdynamic,obj):
        if isdynamic==1:
            #set the coordinate interface
            coori=self.prp.findref(scnobj.data.coordinate)
            if coori==None:
                coori=self.prp.find(0x15,name,1)
            scnobj.data.coordinate=coori.data.getRef()
            coori.data.parentref=scnobj.data.getRef()
            coori.data.export_matrices(obj)
        else:
            scnobj.data.coordinate=UruObjectRef()

class alcUruAge:
    def __init__(self,parent,name="test",basename="./",prefix=0,version=5):
        self.type="age"
        self.resmanager=parent
        self.base=basename
        self.name=name
        self.book=None
        self.version=version
        self.setDefaults(prefix)
        self.mfs=mfs(prefix)
        self.mfs.addFile(self.base + "/" + self.name + ".age")
    
    
    def setDefaults(self,prefix=None):
        self.options=[]
        self.pages=[]
        if prefix==None:
            prefix=self.getOpt("SequencePrefix")
            if prefix==None:
                prefix=0
        self.mfs=mfs(prefix)
        self.mfs.addFile(self.base + "/" + self.name + ".age")
        self.addOpt("StartDateTime","0000000000")
        self.addOpt("DayLength",24.0)
        self.addOpt("MaxCapacity",150)
        self.addOpt("LingerTime",180)
        self.addOpt("SequencePrefix",prefix)
    
    
    def addOpt(self,name,value):
        if name=="SequencePrefix":
            self.mfs.seq=int(value)
        for me in self.options:
            if me[0].lower()==name.lower():
                me[1]=value
                return
        w=[]
        w.append(name)
        w.append(str(value))
        self.options.append(w)
    
    
    def getOpt(self,name):
        for me in self.options:
            if me[0].lower()==name.lower():
                return me[1]
        return None
    
    
    def findPage(self,name,agename=None):
        for page in self.pages:
            if page.name==name:
                return page
        return None
    
    
    def findPageByNum(self,num):
        for page in self.pages:
            if page.num==num:
                return page
        return None
    
    
    def addPage(self,name,num,hide,type=0x00):
        page=self.findPageByNum(num)
        self.mfs.addFile(self.base + "/" + self.name + "_District_" + name + ".prp")
        if page!=None:
            page.name=name
            page.hide=int(hide)
            page.type=int(type)
            return
        page=alcUruPage(self,name,num,hide,type)
        self.pages.append(page)
    
    
    def getInit(self):
        fpath=self.base + "/" + self.name + ".fni"
        if self.version==6:
            f=M5Crypt()
        else:
            f=Wdys()
        try:
            f.open(fpath,"rb")
            txt=f.read()
            f.close()
        except IOError:
            txt=""
        return txt
    
    
    def setInit(self,txt):
        fpath=self.base + "/" + self.name + ".fni"
        if self.version==6:
            f=M5Crypt()
        else:
            f=Wdys()
        f.open(fpath,"wb")
        f.write(txt)
        f.close()
    
    
    def read(self):
        fpath=self.base + "/" + self.name + ".age"
        f=Wdys()
        try:
            f.open(fpath)
            self.version=5
        except NotWdys:
            try:
                f=M5Crypt()
                f.open(fpath)
                self.version=6
            except NotM5Crypt:
                f=file(fpath,"rb")
                self.version=5
        buf = cStringIO.StringIO()
        buf.write(f.read())
        f.close()
        buf.seek(0)
        IAddedBuiltInPages=0
        for line in buf.readlines():
            w = line.strip().split("=")
            if w[0].lower()!="page":
                self.addOpt(w[0],w[1])
            else:
                if not IAddedBuiltInPages:
                    IAddedBuiltInPages=1
                    self.addBuiltInPages()
                x = w[1].split(",")
                try:
                    flag=int(x[2])
                except IndexError:
                    flag=0
                self.addPage(x[0],int(x[1]),flag)
        #print self.options
        #print self.pages
        buf.close()
        self.preLoadAllPages()
    
    
    def preLoadAllPages(self):
        for page in self.pages:
            page.preLoad()
    
    
    def write(self):
        if self.resmanager.prp_version==6:
            self.f=M5Crypt()
        else:
            self.f=Wdys()
        self.f.open(self.base + "/" + self.name + ".age","wb")
        for opt in self.options:
            self.f.write(opt[0] + "=" + opt[1] + "\r\n")
        for page in self.pages:
            if page.type in (0x04,0x00):
                if page.hide==1:
                    self.f.write("Page=%s,%i,%i\r\n" %(page.name,page.num,page.hide))
                else:
                    self.f.write("Page=%s,%i\r\n" %(page.name,page.num))
        self.f.close()
    
    
    def setSeq(self,val):
        self.addOpt("SequencePrefix",str(val))
    
    
    def getSeq(self):
        return(int(self.getOpt("SequencePrefix")))
    
    
    def addBuiltInPages(self):
        seq=self.getSeq()
        if seq<0:
            return
        else:
            self.addPage("Textures",-1,0,0x08)
            if self.version!=6:
                self.addPage("BuiltIn",-2,0,0x08)

    
    def import_book(self):
        self.book=alcBook(self)
        if self.resmanager.filesystem:
            self.book.save2xml()
        else:
            self.book.find()
            self.book.setAge()
    
    
    def export_book(self,selection):
        self.book=alcBook(self)
        self.book.find(selection)
        self.book.getAge()
    
    
    def import_page(self,name):
        for page in self.pages:
            if page.name==name:
                page.import_all()
                return
        raise "The page %s is not in the %s manifest" %(name,self.name)
    
    
    def find(self,type,name,agename=None):
        for page in self.book.pages:
            if page.prp!=None:
                res=page.prp.find(type,name,0)
                if res!=None:
                    return res
        return None
    
    
    def findref(self,ref):
        if ref.flag==0x01:
            seq=self.getSeq()
            for page in self.pages:
                pid=xPageId()
                pid.setPage(seq,page.num,None,page.type)
                if pid.getRaw()==ref.Key.page_id:
                    if page.prp!=None:
                        return page.prp.findref(ref)
        return None


class alcResManager:
    def __init__(self,datadir="./",version=5,min_ver=12):
        self.type="rmgr"
        self.prp_version=version
        self.prp_min_ver=min_ver
        self.datadir=datadir
        self.ages=[]
        self.filesystem=0
    
    
    def setFilesystem(self):
        self.filesystem=1
    
    
    def getPRPVersion(self):
        return self.prp_version
    
    
    def getBasePath(self):
        return self.datadir
    
    
    def preload(self,datadir=None,age=None):
        if datadir==None:
            datadir=self.datadir
        ages=glob.glob(datadir + "/*.age")
        #print datadir
        #print ages
        for a in ages:
            a=basename(a)[:-4]
            if(age == None or age == a or a[0:6] == 'Global' or a == 'GUI'):
                self.preLoadAge(a,datadir)
            
    
    
    def findAge(self,age,create=0,datadir=None,version=None):
        if version==None:
            version=self.prp_version
        for a in self.ages:
            if a.name==age:
                return a
        if not create:
            return None
        if datadir==None:
            datadir=self.datadir
        a=alcUruAge(self,age,datadir,None,version)
        self.ages.append(a)
        return a
    
    
    def preLoadAge(self,age,datadir=None):
        print "PreLoading %s" %age
        a=self.findAge(age,create=1,datadir=datadir)
        a.read()
    
    
    def import_book(self,agename):
        age=self.findAge(agename)
        if age==None:
            raise "Age %s does not exists!" %(agename)
        age.import_book()
    
    
    def export_book(self,agename,selection):
        age=self.findAge(agename,1)
        age.export_book(selection)

    
    def find(self,type,name,agename=None):
        if agename==None:
            for a in self.ages:
                out=a.find(type,name)
                if out!=None:
                    return out
            return None
        for a in self.ages:
            if a.name==agename:
                return a.find(type,name)
        return None
    
    
    def findref(self,ref):
        if ref.flag==0x01:
            for a in self.ages:
                ret=a.findref(ref)
                if ret!=None:
                    return ret
        return None

    
    def xfindPage(self,pagename,agename=None):
        if agename==None:
            for age in self.ages:
                ret=age.findPage(pagename)
                if ret!=None:
                    return ret
        else:
            age=self.findAge(agename)
            if age==None:
                return None
            return age.findPage(pagename)
        return None

    
    def findPrp(self,name,agename=None):
        for age in self.ages:
            for page in age.pages:
                if page.name==name and page.prp!=None:
                    return page.prp
