# -*- test-case-name: mv3d.test.test_asset -*- # Copyright (C) 2006-2012 Mortal Coil Games # See LICENSE for details. """ """ import os import ctypes from urlparse import urlparse from twisted.internet import defer from mv3d.resource.asset import MaterialAsset, MeshAsset from mv3d.resource.url import URLMeshAsset, URLMaterialAsset, URLShaderAsset from mv3d.util.classgen import ClassGenerator from mv3d.util.iservice import IPlayerClient from mv3d.net.ha import withSlaveUpdate from mv3d.util.persist import Text from mv3d.client.ui.irenderer import Ogre3D try: from ogre.renderer import OGRE as Ogre from mv3d.client.ui.ogre3d import ogreVersion #@UnusedImport noOgre = False except ImportError: noOgre = True class LocalOgreMaterialAsset(MaterialAsset): """ An asset that is a local file and is an ogre material """ _schemaVersion = 2 filename = Text(default="", autoSave=True, partialSave=True, transmit=True) classModifiers = dict(web=[ ClassGenerator("mv3d.server.editor.LocalOgreMaterialAssetEditor"), ClassGenerator("mv3d.server.editor.DeleteAsset"), ]) def __init__(self, filename=None, server=None, datastore=None): MaterialAsset.__init__(self) self.filename = filename self.datastore = datastore self.server = server def getFilename(self): """ Returns the filename of the material """ return self.filename @withSlaveUpdate def setFilename(self, f): """ Sets the file name of the material """ self.filename = f observe_setFilename = setFilename def getMaterialName(self): """ Returns the name of the material """ return self.filename def getCompatibleRenderers(self): """ Returns a list of compatible renderers. """ return [Ogre3D] def newURLOgreMeshAsset(conductor, assetgroup, url, localfile="", name="", depends=[]): """ Factory to create a new ogre mesh asset """ d = assetgroup.newAsset(conductor, ClassGenerator( classname="URLOgreObjectAsset", modulename="mv3d.resource.ogre3d")) for dd in depends: assert not isinstance(dd, defer.Deferred) def finishUp(tm, _u, localfile, name, depends): """ Actually set the attributes of the mesh """ tm.url = url if localfile != "": tm.localfile = localfile if name != "": tm.name = name for d in depends: if isinstance(d, tuple): tm.addDependency(d) else: tm.addDependency(d.getID()) tm.grantPermission("read", "all") tm.grantPermission("reference", "all") tm.queueSave(selectAttributes=["url", "localfile", "name"]) return tm d.addCallback(finishUp, url, localfile, name, depends) return d class URLOgreObjectAsset(URLMeshAsset): """ An ogre object that can be downoaded from a url """ _schemaVersion = 2 meshname = Text(default="", autoSave=True, partialSave=True, transmit=True) materialname = "" readied = None classModifiers = dict(web=[ ClassGenerator("mv3d.server.editor.URLAssetEditor"), ClassGenerator("mv3d.server.editor.DeleteAsset"), ]) def __init__(self, datastore=None, url=None, localfile=None, basedir=u"Extern", server=None, meshname=None): URLMeshAsset.__init__(self, datastore, url, localfile, server, basedir) self.meshname = meshname def setURL(self, u): """ Sets the url. """ p = urlparse(u) path = p[2] pp = path.split("/") self.localfile = pp[ -1] self.meshname = pp[ -1] URLMeshAsset.setURL(self, u) def setFilename(self, f): """ Sets the filename """ self.meshname = os.path.split(f)[1] URLMeshAsset.setFilename(self, f) observe_setURL = setURL observe_setFilename = setFilename def getCompatibleRenderers(self): """ Returns a list of compatible renderers. """ return [Ogre3D] def create(self, name): """ Creates the asset """ #print "Calling create for",self.meshname assert self.parent, "got no parent!" i = self.parent.parent.getLocalService(IPlayerClient).getRenderer() if not Ogre.ResourceGroupManager.getSingleton().resourceExists( "General", self.meshname): # register the resource group if not Ogre.ResourceGroupManager.getSingleton( ).resourceLocationExists(self.getFullPath(), "General"): Ogre.ResourceGroupManager.getSingleton().addResourceLocation( self.getFullPath(), "FileSystem", "General") if not Ogre.ResourceGroupManager.getSingleton().resourceExists( "General", self.meshname): raise KeyError("Couldn't find resource! %s " % self.meshname) return i.createEntity(str(name), self.meshname) def newURLOgreMaterialAsset(conductor, assetgroup, url, materialname, localfile="", name="", depends=[]): tm = assetgroup.newAsset(conductor, ClassGenerator( "mv3d.resource.ogre3d.URLOgreMaterialAsset")) def finishUp(tm, _u, _m, _l, _n, _dp): tm.url = url tm.materialname = materialname if localfile != "": tm.localfile = localfile if name != "": tm.name = name else: tm.name = materialname for d in depends: if isinstance(d, tuple): tm.addDependency(d) else: tm.addDependency(d.getID()) tm.grantPermission("read", "all") tm.grantPermission("reference", "all") tm.queueSave(selectAttributes=["materialname", "url", "localfile", "name"]) return tm if isinstance(tm, defer.Deferred): tm.addCallback(finishUp, url, materialname, localfile, name, depends) return tm return finishUp(tm, url, materialname, localfile, name, depends) class URLOgreMaterialAsset(URLMaterialAsset): """ An asset that is downloadable by URL and represents a material script """ _schemaVersion = 2 materialname = Text(default="", autoSave=True, partialSave=True, transmit=True) readied = False classModifiers = dict(web=[ ClassGenerator("mv3d.server.editor.URLOgreMaterialAssetEditor"), ClassGenerator("mv3d.server.editor.DeleteAsset"), ]) def __init__(self, datastore=None, url=None, localfile=None, basedir=u"Extern", server=None, materialname=None): URLMaterialAsset.__init__(self, datastore, url, localfile, server, basedir) self.materialname = materialname self.server = server def setURL(self, u): URLMaterialAsset.setURL(self, u) p = urlparse(u) path = p[2] pp = path.split("/") self.localfile = pp[ -1] def getMaterialName(self): return self.materialname @withSlaveUpdate def setMaterialName(self, m): self.materialname = m observe_setMaterialName = setMaterialName def getCompatibleRenderers(self): """ Returns a list of compatible renderers. """ return [Ogre3D] def acquireAsset(self, downloadList=None, **kw): """ After acquiring the asset, we have to ready it. """ d = URLMaterialAsset.acquireAsset(self, downloadList=downloadList, **kw) def done(r): self.readyAsset() return r d.addCallback(done) return d def urlHaveAsset(self): """ After checking if the asset is local, we have to ready it. """ if not URLMaterialAsset.urlHaveAsset(self): return False self.readyAsset() return True def readyAsset(self): """ Load the material into Ogre with a file stream. """ if not self.readied: if noOgre: return if Ogre.MaterialManager.getSingleton() is None: return if Ogre.ResourceGroupManager.getSingleton().resourceExists( "General", self.materialname): return # if ogreVersion < 1.6: fil = open(self.getFullFile()) data = fil.read() fil.close() sctyp = ctypes.c_char * len(data) cpy = sctyp(" ") for pos in range(len(data)): cpy[pos] = data[pos] if ogreVersion >= 1.7: dst = Ogre.MemoryDataStream(os.path.basename( self.getFullFile()), Ogre.castAsVoidPtr( ctypes.addressof(cpy)), len(data)) else: dst = Ogre.MemoryDataStream(os.path.basename( self.getFullFile()), Ogre.CastVoidPtr( ctypes.addressof(cpy)), len(data)) Ogre.MaterialManager.getSingleton().parseScript(dst, "General") self.readied = 1 class URLOgreShaderAsset(URLShaderAsset): """ An asset that is downloadable by URL and represents a shader script or program """ _schemaVersion = 2 readied = False classModifiers = dict(web=[ ClassGenerator("mv3d.server.editor.DeleteAsset"), ]) def __init__(self, url=None, localfile=None, basedir=u"Extern", server=None): URLShaderAsset.__init__(self, url, localfile, server, basedir) self.server = server def setURL(self, u): URLShaderAsset.setURL(self, u) p = urlparse(u) path = p[2] pp = path.split("/") self.localfile = pp[ -1] def getCompatibleRenderers(self): """ Returns a list of compatible renderers. """ return [Ogre3D] def acquireAsset(self, downloadList=None, **kw): """ After acquiring the asset, we have to ready it. """ d = URLShaderAsset.acquireAsset(self, downloadList=downloadList, **kw) def done(r): self.readyAsset() return r d.addCallback(done) return d def urlHaveAsset(self): """ After checking if the asset is local, we have to ready it. """ if not URLShaderAsset.urlHaveAsset(self): return False self.readyAsset() return True def readyAsset(self): """ Load the material into Ogre with a file stream. """ if not self.readied: if noOgre: return if Ogre.ScriptCompilerManager.getSingleton() is None: return if not Ogre.ResourceGroupManager.getSingleton( ).resourceLocationExists(self.getFullPath(), "General"): Ogre.ResourceGroupManager.getSingleton().addResourceLocation( self.getFullPath(), "FileSystem", "General") fil = open(self.getFullFile()) data = fil.read() fil.close() sctyp = ctypes.c_char * len(data) cpy = sctyp(" ") for pos in range(len(data)): cpy[pos] = data[pos] if ogreVersion >= 1.7: dst = Ogre.MemoryDataStream(Ogre.castAsVoidPtr(ctypes.addressof( cpy)), len(data)) else: dst = Ogre.MemoryDataStream(Ogre.CastVoidPtr(ctypes.addressof( cpy)), len(data)) Ogre.ScriptCompilerManager.getSingleton().parseScript(dst, "General") self.readied = 1 class LocalOgreObjectAsset(MeshAsset): """ An asset that represents an ogre object """ _schemaVersion = 2 Types = ("Mesh", "Light", "Particles") filename = Text(default="", autoSave=True, partialSave=True, transmit=True) type = Text(default="", autoSave=True, partialSave=True, transmit=True) def __init__(self, filename=None, datastore=None, server=None, ype=None): MeshAsset.__init__(self) self.filename = filename self.type = type self.datastore = datastore self.server = server def getFilename(self): """ Returns the filename """ return self.filename @withSlaveUpdate def setFilename(self, f): """ Sets the filename """ self.filename = f def getType(self): """ Returns the type of mesh """ return self.type @withSlaveUpdate def setType(self, t): """ Sets the type of mesh """ self.type = t observe_setFilename = setFilename observe_setType = setType def getCompatibleRenderers(self): """ Returns a list of compatible renderers. """ return [Ogre3D] def create(self, name): """ Creates the mesh """ if self.server == 0: return 0 i = self.server.GetRenderer() if self.type == "Mesh": return i.createEntity(str(name), self.filename) if self.type == "Particles": return i.createParticles(str(name), self.filename) return 0 class LocalOgreMeshAsset(MeshAsset): """ An asset that is an ogre mesh existing on our local filesystem """ _schemaVersion = 2 filename = Text(default="", autoSave=True, partialSave=True, transmit=True) def __init__(self, filename=None, datastore=None): MeshAsset.__init__(self) self.filename = filename self.datastore = datastore def getFilename(self): """ Returns the filename """ return self.filename @withSlaveUpdate def setFilename(self, f): """ Sets the filename """ self.filename = f observe_setFilename = setFilename def getCompatibleRenderers(self): """ Returns a list of compatible renderers. """ return [Ogre3D] def create(self, name): """ Creates the asset """ assert self.server, "got no server!" i = self.server.GetRenderer() return i.createEntity(str(name), self.filename)