def getShader(scriptName): """ Attempts to retrieve a L{Shader} object resource. @param scriptName: Should name a resource that is a python script. The script should, upon execution, create a global (to itself) object C{theShader}, which is expected to be an instance of L{Shader}. This object is what is retrieved and cached by this function. @type scriptName: C{str} @return: L{Shader} or C{None} """ # Return any cached copy of the desired shader object if (scriptName, 'theShader') in __resTable: return __resTable[(scriptName, 'theShader')] parole.info('Loading shader "%s"', scriptName) theShader = getObject(scriptName, 'theShader') if theShader and not isinstance(theShader, parole.Shader): parole.error( 'Shader definition script bound "theShader" to non-Shader') return None # The shader definition worked and we have a bona fide Shader object # getObject should have already cached it return theShader
def getSound(name): """ Attempts to retrieve the given sound resource as a PyGame C{Sound} object. The file can either be an uncompressed WAV or an OGG file. @return: C{pygame.mixer.Sound} or C{None} @param name: The path + filename of the sound resource to retrieve. @type name: C{str} """ # Return any cached copy of the texture surface object if name in __resTable: return __resTable[name] parole.info('Loading sound "%s"', name) # name should be a resource whose bytes are loadable by pygame's mixer # module bytes = getResource(name, binary=True) if not bytes: return None sound = None # Create a file-like object which pygame can use to read the bytes of # the sound soundf = cStringIO.StringIO(bytes) # Attempt to load the sound try: sound = pygame.mixer.Sound(soundf) except Exception, e: parole.error('Unable to load sound "%s": %s', name, e) return None
def __runScript(scriptName): # scriptName should be a resource whose bytes are python code bytes = getResource(scriptName) if not bytes: return None # compile the code, copy the current global namespace to execute it in scriptCode = compile(bytes, scriptName, 'exec') #modName = scriptName.replace('.py', '').replace('/', '.') modName = scriptName.split('/')[-1].replace('.py', '') scriptNamespace = { '__name__': modName, '__file__': scriptName, '__builtins__': globals()['__builtins__'], 'parole': globals()['parole'] } # Attempt to execute the code of the shader definition script. # It should create a global in its namespace called 'theShader', which # is the shader object we want to associate with this resource try: exec scriptCode in scriptNamespace except Exception, e: parole.error('Error executing "%s".\n%s', scriptName, e) return None
def getShader(scriptName): """ Attempts to retrieve a L{Shader} object resource. @param scriptName: Should name a resource that is a python script. The script should, upon execution, create a global (to itself) object C{theShader}, which is expected to be an instance of L{Shader}. This object is what is retrieved and cached by this function. @type scriptName: C{str} @return: L{Shader} or C{None} """ # Return any cached copy of the desired shader object if (scriptName, "theShader") in __resTable: return __resTable[(scriptName, "theShader")] parole.info('Loading shader "%s"', scriptName) theShader = getObject(scriptName, "theShader") if theShader and not isinstance(theShader, parole.Shader): parole.error('Shader definition script bound "theShader" to non-Shader') return None # The shader definition worked and we have a bona fide Shader object # getObject should have already cached it return theShader
def __init(): """ Initializes the resource module. Detects and loads all resource pakcages in the gamedir directory. Automatically called during engine startup -- user code shouldn't need to use this function. """ global __gameDir, __inInit __inInit = True __resTable.clear() parole.conf.notify(__onConfigChange, True) __gameDir = parole.conf.resource.gamedir # Score some packages while len(packages): packages.pop() suff = parole.conf.resource.packsuffix for root, dirs, files in os.walk(__gameDir): if root == __gameDir: if bool(parole.conf.resource.allowdirs): packages.extend([(dir, None, __getResourceFromDir) for dir in dirs if dir.endswith(suff)]) for arch in files: if not arch.endswith(suff): continue if not zipfile.is_zipfile(os.sep.join([__gameDir, arch])): parole.error("Ignoring bad archive resource package: %s: Not dir or zip.", arch) continue # archf = None try: archf = zipfile.ZipFile(os.sep.join([__gameDir, arch]), "r") parole.info("archf = %r", archf) except Exception, e: parole.error("Ignoring bad archive resource package: %s: %s", arch, e) continue packages.append((arch, archf, __getResourceFromArch))
def __runScript(scriptName): # scriptName should be a resource whose bytes are python code bytes = getResource(scriptName) if not bytes: return None # compile the code, copy the current global namespace to execute it in scriptCode = compile(bytes, scriptName, "exec") # modName = scriptName.replace('.py', '').replace('/', '.') modName = scriptName.split("/")[-1].replace(".py", "") scriptNamespace = { "__name__": modName, "__file__": scriptName, "__builtins__": globals()["__builtins__"], "parole": globals()["parole"], } # Attempt to execute the code of the shader definition script. # It should create a global in its namespace called 'theShader', which # is the shader object we want to associate with this resource try: exec scriptCode in scriptNamespace except Exception, e: parole.error('Error executing "%s".\n%s', scriptName, e) return None
def __getResourceFrom(path, package, binary=False): """ __getResourceFrom(path, package, binary=False) -> str or None Returns the bytes (as a string) of the resource at the given path in the given package, or None if an error is encountered. If binary is True, attempts to read the resource in binary mode. """ for (pkgname, archf, getter) in packages: if pkgname == package: return getter(path, archf or pkgname, binary) parole.error('__getResourceFrom(): unknown package: %s', package)
def __getResourceFrom(path, package, binary=False): """ __getResourceFrom(path, package, binary=False) -> str or None Returns the bytes (as a string) of the resource at the given path in the given package, or None if an error is encountered. If binary is True, attempts to read the resource in binary mode. """ for (pkgname, archf, getter) in packages: if pkgname == package: return getter(path, archf or pkgname, binary) parole.error("__getResourceFrom(): unknown package: %s", package)
def getFont(name, size): """ Attempts to retrieve the given font resource as a PyGame Font object. @return: C{pygame.font.Font} or C{None} @param name: The path + filename of the font resource to retrieve. Must name a font file in a format that PyGame can read (e.g., TrueType). @type name: C{str} """ # Return any cached copy of the font object if (name, size) in __resTable: return __resTable[(name, size)] parole.info('Loading font "%s" %spt', name, size) # name should be a resource whose bytes are loadable by pygame's font # module bytes = getResource(name, binary=True) if not bytes: parole.error('"%s" names an empty font resource.', name) return None parole.debug("Got font bytes. (len=%d)", len(bytes)) font = None # Create a file-like object which pygame can use to read the bytes of # the font file # pygame 1.9.1release segfaults when reading a font from cStringIO # fontf = cStringIO.StringIO(bytes) # Workaround: import tempfile tmpf = tempfile.NamedTemporaryFile(delete=False) tmpf.write(bytes) tmpf.close() fontf = tmpf.name # Attempt to load the font try: parole.debug("Parsing font bytes...") font = pygame.font.Font(fontf, size) except Exception, e: parole.error('Unable to load font "%s" %pt: %s', name, size, e) return None
def getFont(name, size): """ Attempts to retrieve the given font resource as a PyGame Font object. @return: C{pygame.font.Font} or C{None} @param name: The path + filename of the font resource to retrieve. Must name a font file in a format that PyGame can read (e.g., TrueType). @type name: C{str} """ # Return any cached copy of the font object if (name, size) in __resTable: return __resTable[(name, size)] parole.info('Loading font "%s" %spt', name, size) # name should be a resource whose bytes are loadable by pygame's font # module bytes = getResource(name, binary=True) if not bytes: parole.error('"%s" names an empty font resource.', name) return None parole.debug('Got font bytes. (len=%d)', len(bytes)) font = None # Create a file-like object which pygame can use to read the bytes of # the font file # pygame 1.9.1release segfaults when reading a font from cStringIO #fontf = cStringIO.StringIO(bytes) # Workaround: import tempfile tmpf = tempfile.NamedTemporaryFile(delete=False) tmpf.write(bytes) tmpf.close() fontf = tmpf.name # Attempt to load the font try: parole.debug('Parsing font bytes...') font = pygame.font.Font(fontf, size) except Exception, e: parole.error('Unable to load font "%s" %pt: %s', name, size, e) return None
def __init(): """ Initializes the resource module. Detects and loads all resource pakcages in the gamedir directory. Automatically called during engine startup -- user code shouldn't need to use this function. """ global __gameDir, __inInit __inInit = True __resTable.clear() parole.conf.notify(__onConfigChange, True) __gameDir = parole.conf.resource.gamedir # Score some packages while len(packages): packages.pop() suff = parole.conf.resource.packsuffix for root, dirs, files in os.walk(__gameDir): if root == __gameDir: if bool(parole.conf.resource.allowdirs): packages.extend([(dir, None, __getResourceFromDir) \ for dir in dirs if dir.endswith(suff)]) for arch in files: if not arch.endswith(suff): continue if not zipfile.is_zipfile(os.sep.join([__gameDir, arch])): parole.error( 'Ignoring bad archive resource package: %s: Not dir or zip.', arch) continue #archf = None try: archf = zipfile.ZipFile(os.sep.join([__gameDir, arch]), 'r') parole.info('archf = %r', archf) except Exception, e: parole.error( 'Ignoring bad archive resource package: %s: %s', arch, e) continue packages.append((arch, archf, __getResourceFromArch))
def exportResource(name, destination): """ Exports the named resource to the given destination on disk. C{destination} should be the full path plus filname to which the byte-contents of the named resource should be copied. This function can be useful for extracting a sound resource from a zip package and writing it to disk as a standalone file so that it can be used by C{pygame.mixer.music}, for instance. """ parole.info('Exporting resource "%s" to "%s".', name, destination) bytes = getResource(name, binary=True) if not bytes: parole.error('exportResource: resource "%s" not found.', name) destf = None try: destf = open(destination, "wb") destf.write(bytes) except IOError, e: parole.error('exportResource: IOError while writing resource "%s" to' ' "%s": %s', name, destination, e)
def getTexture(name): """ Attempts to retrieve the given texture resource as a PyGame C{Surface} object. @todo: Return a dummy texture if not found. @return: C{pygame.Surface} or C{None} @param name: The path + filename of the texture resource to retrieve. Must name an image file in a format that PyGame can read (png, jpeg, tiff, etc.). @type name: C{str} """ # Return any cached copy of the texture surface object if name in __resTable: return __resTable[name] parole.info('Loading texture "%s"', name) # name should be a resource whose bytes are loadable by pygame's image # module bytes = getResource(name, binary=True) if not bytes: return None tex = None # Create a file-like object which pygame can use to read the bytes of # the texture texf = cStringIO.StringIO(bytes) # Attempt to load the texture try: tex = pygame.image.load(texf, name).convert() except Exception, e: # TODO: return a dummy "not found" texture parole.error('Unable to load texture "%s": %s', name, e) return None
def getObject(scriptName, objName): """ Retrieves a python object defined in the given python script resource. @param scriptName: Should name a resource that is a python script. The script should, upon execution, create a global (to itself) object with the name C{objName}. @type scriptName: C{str} @param objName: The name of the object created in the script's global namespace to return. @return: C{object} """ # Return any cached copy of the desired object if (scriptName, objName) in __resTable: return __resTable[(scriptName, objName)] parole.info('Loading object "%s" from "%s"', objName, scriptName) scriptNamespace = __runScript(scriptName) if not scriptNamespace: parole.error('Failed to load object "%s" from "%s"', objName, scriptName) return None if objName not in scriptNamespace: parole.error('Script "%s" did not bind "s"', scriptName, objName) return None obj = scriptNamespace[objName] # The script worked and we have a bona fide object # Cache it and return it __resTable[(scriptName, objName)] = obj return obj
def exportResource(name, destination): """ Exports the named resource to the given destination on disk. C{destination} should be the full path plus filname to which the byte-contents of the named resource should be copied. This function can be useful for extracting a sound resource from a zip package and writing it to disk as a standalone file so that it can be used by C{pygame.mixer.music}, for instance. """ parole.info('Exporting resource "%s" to "%s".', name, destination) bytes = getResource(name, binary=True) if not bytes: parole.error('exportResource: resource "%s" not found.', name) destf = None try: destf = open(destination, 'wb') destf.write(bytes) except IOError, e: parole.error( 'exportResource: IOError while writing resource "%s" to' ' "%s": %s', name, destination, e)
# we need to load it parole.info('Loading resource: "%s"', name) bytes = None # go through all packages until we find one with the resource # we need. The packages list should already be in the proper order for (package, f, g) in packages: try: bytes = __getResourceFrom(name, package, binary) parole.debug('"%s" found in "%s"', name, package) break except __NotFound, e: parole.debug('"%s" not found in "%s"', name, package) if not bytes: parole.error("Unknown resource: %s", name) return None # store the resource's bytes in the resource table __resTable[name] = bytes return bytes # ============================================================================== def clearResource(name): """ Clears the cache of the given resource. Any future retrieval of the resource will result in an actual disk read. The resource may not actually be freed from memory if any user code still contains references to it.
# we need to load it parole.info('Loading resource: "%s"', name) bytes = None # go through all packages until we find one with the resource # we need. The packages list should already be in the proper order for (package, f, g) in packages: try: bytes = __getResourceFrom(name, package, binary) parole.debug('"%s" found in "%s"', name, package) break except __NotFound, e: parole.debug('"%s" not found in "%s"', name, package) if not bytes: parole.error('Unknown resource: %s', name) return None # store the resource's bytes in the resource table __resTable[name] = bytes return bytes #============================================================================== def clearResource(name): """ Clears the cache of the given resource. Any future retrieval of the resource will result in an actual disk read. The resource may not actually be freed from memory if any user code still contains references to it.